agent-framework-github-copilot 1.0.2__py3-none-any.whl → 2.0.0__py3-none-any.whl

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.
@@ -5,10 +5,12 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import contextlib
7
7
  import inspect
8
+ import json
8
9
  import logging
9
10
  import sys
10
11
  import warnings
11
12
  from collections.abc import AsyncIterable, Awaitable, Callable, Mapping, MutableMapping, Sequence
13
+ from pathlib import Path
12
14
  from typing import Any, ClassVar, Generic, Literal, TypedDict, cast, overload
13
15
  from urllib.parse import urlparse
14
16
 
@@ -29,6 +31,7 @@ from agent_framework import (
29
31
  add_usage_details,
30
32
  normalize_messages,
31
33
  )
34
+ from agent_framework._mcp import MCPTool
32
35
  from agent_framework._settings import load_settings
33
36
  from agent_framework._telemetry import mark_feature_used
34
37
  from agent_framework._tools import FunctionTool, ToolTypes
@@ -52,7 +55,12 @@ else:
52
55
  from typing_extensions import TypeVar # pragma: no cover
53
56
 
54
57
  try:
55
- from copilot import CopilotClient, CopilotSession, RuntimeConnection
58
+ from copilot import (
59
+ CopilotClient,
60
+ CopilotSession,
61
+ RuntimeConnection,
62
+ TelemetryConfig,
63
+ )
56
64
  from copilot.generated.rpc import (
57
65
  PermissionDecisionApproveForSession,
58
66
  PermissionDecisionApproveForSessionApproval,
@@ -71,6 +79,7 @@ try:
71
79
  Attachment,
72
80
  BlobAttachment,
73
81
  MCPServerConfig,
82
+ PermissionInvocation,
74
83
  PermissionRequestResult,
75
84
  PreToolUseHandler,
76
85
  PreToolUseHookOutput,
@@ -104,14 +113,24 @@ except ImportError as _copilot_import_error:
104
113
  DEFAULT_TIMEOUT_SECONDS: float = 60.0
105
114
  """Default timeout in seconds for Copilot requests."""
106
115
 
116
+ _PermissionHandlerContext = Any
117
+ """Compatibility context accepted by permission handlers across SDK versions."""
118
+
107
119
  PermissionHandlerType = Callable[
108
- [PermissionRequest, dict[str, str]], "PermissionRequestResult | Awaitable[PermissionRequestResult]"
120
+ [PermissionRequest, _PermissionHandlerContext],
121
+ "PermissionRequestResult | Awaitable[PermissionRequestResult]",
109
122
  ]
110
123
  """Type for permission request handlers. Supports both sync and async callbacks."""
111
124
 
112
- AsyncPermissionHandlerType = Callable[[PermissionRequest, dict[str, str]], "Awaitable[PermissionRequestResult]"]
125
+ AsyncPermissionHandlerType = Callable[
126
+ [PermissionRequest, _PermissionHandlerContext], "Awaitable[PermissionRequestResult]"
127
+ ]
113
128
  """Type for permission request handlers that are always asynchronous."""
114
129
 
130
+ _SdkAsyncPermissionHandlerType = Callable[
131
+ [PermissionRequest, PermissionInvocation], "Awaitable[PermissionRequestResult]"
132
+ ]
133
+
115
134
 
116
135
  FunctionApprovalCallback = Callable[[Content], "bool | Awaitable[bool]"]
117
136
  """Deprecated approval callback for ``FunctionTool`` instances declared with
@@ -162,10 +181,26 @@ async def _resolve_function_approval(
162
181
 
163
182
  logger = logging.getLogger("agent_framework.github_copilot")
164
183
 
184
+ _MCP_TOOL_MESSAGE = (
185
+ "MCP server '{name}' cannot be passed to GitHubCopilotAgent as a tool: the Copilot SDK "
186
+ "connects to MCP servers itself, so a framework-managed MCPTool would keep none of its "
187
+ "framework behavior. Configure the server natively instead, for example "
188
+ "default_options={{'mcp_servers': {{'{name}': {{'type': 'stdio', 'command': 'python', "
189
+ "'args': ['server.py'], 'tools': ['*']}}}}}}, or use a ChatAgent, where the framework owns "
190
+ "the connection."
191
+ )
192
+
193
+
194
+ def _reject_mcp_tools(tools: Sequence[Any]) -> None:
195
+ """Refuse MCP servers handed in as tools, from whichever option carried them."""
196
+ for tool in tools:
197
+ if isinstance(tool, MCPTool):
198
+ raise TypeError(_MCP_TOOL_MESSAGE.format(name=tool.name))
199
+
165
200
 
166
201
  def _deny_all_permissions(
167
202
  _request: PermissionRequest,
168
- _invocation: dict[str, str],
203
+ _invocation: _PermissionHandlerContext,
169
204
  ) -> PermissionRequestResult:
170
205
  """Default permission handler that denies all requests."""
171
206
  return PermissionDecisionUserNotAvailable()
@@ -316,7 +351,7 @@ def _normalize_permission_decision(
316
351
  return PermissionDecisionApproveForSession(approval=approval)
317
352
 
318
353
 
319
- def _with_normalized_permission_decisions(handler: PermissionHandlerType) -> AsyncPermissionHandlerType:
354
+ def _with_normalized_permission_decisions(handler: PermissionHandlerType) -> _SdkAsyncPermissionHandlerType:
320
355
  """Wrap a permission handler so its decisions are normalized before reaching the SDK.
321
356
 
322
357
  Exceptions raised by ``handler`` deliberately propagate: the SDK already catches them
@@ -329,8 +364,10 @@ def _with_normalized_permission_decisions(handler: PermissionHandlerType) -> Asy
329
364
  An async handler delegating to ``handler`` and normalizing its result.
330
365
  """
331
366
 
332
- async def normalized_handler(request: PermissionRequest, invocation: dict[str, str]) -> PermissionRequestResult:
333
- result = handler(request, invocation)
367
+ async def normalized_handler(
368
+ request: PermissionRequest, invocation: PermissionInvocation
369
+ ) -> PermissionRequestResult:
370
+ result = handler(request, cast(PermissionInvocation, dict(invocation)))
334
371
  if inspect.isawaitable(result):
335
372
  result = await result
336
373
  return _normalize_permission_decision(result, request)
@@ -338,6 +375,65 @@ def _with_normalized_permission_decisions(handler: PermissionHandlerType) -> Asy
338
375
  return normalized_handler
339
376
 
340
377
 
378
+ def _parse_telemetry_config(raw: str) -> TelemetryConfig | None:
379
+ # GITHUB_COPILOT_TELEMETRY and matching .env values are read as plain strings while the
380
+ # Copilot SDK expects a mapping, so parse here before the value reaches CopilotClient.
381
+ # Malformed values are logged and ignored so a bad telemetry setting cannot prevent the
382
+ # agent from starting.
383
+ try:
384
+ parsed = json.loads(raw)
385
+ except json.JSONDecodeError:
386
+ logger.warning(
387
+ "Ignoring malformed GITHUB_COPILOT_TELEMETRY value; expected a JSON object with TelemetryConfig keys."
388
+ )
389
+ return None
390
+ if not isinstance(parsed, dict):
391
+ logger.warning(
392
+ "Ignoring invalid GITHUB_COPILOT_TELEMETRY value; expected a JSON object with TelemetryConfig keys."
393
+ )
394
+ return None
395
+ return cast(TelemetryConfig, parsed)
396
+
397
+
398
+ def _client_working_directory(client: CopilotClient | None) -> str | None:
399
+ """Best-effort read of the working directory an injected client configured.
400
+
401
+ A client created with ``CopilotClient(working_directory=...)`` spawns the CLI process
402
+ in that directory, so the CLI resolves ``.github/hooks/`` relative to it rather than to
403
+ this process. The SDK keeps the value on a private options object, so this is read
404
+ defensively: if the attribute ever moves, hook detection falls back to the process
405
+ working directory instead of failing.
406
+ """
407
+ options = getattr(client, "_options", None)
408
+ working_directory = getattr(options, "working_directory", None)
409
+ return working_directory if isinstance(working_directory, str) else None
410
+
411
+
412
+ def _resolve_effective_working_directory(session_working_directory: str | None, client: CopilotClient | None) -> Path:
413
+ """Resolve the directory the CLI will treat as the workspace, mirroring the SDK.
414
+
415
+ The SDK resolves in this order: the session's ``working_directory`` when supplied,
416
+ otherwise the CLI process's own directory, which is the injected client's configured
417
+ ``working_directory`` when it set one and this process's directory otherwise.
418
+ """
419
+ if session_working_directory:
420
+ return Path(session_working_directory)
421
+ client_working_directory = _client_working_directory(client)
422
+ if client_working_directory:
423
+ return Path(client_working_directory)
424
+ return Path.cwd()
425
+
426
+
427
+ def _has_file_hooks(working_directory: Path) -> bool:
428
+ """Return whether ``.github/hooks/`` holds hook definitions the CLI would otherwise load."""
429
+ try:
430
+ return any((working_directory / ".github" / "hooks").iterdir())
431
+ except OSError:
432
+ # Missing directory, unreadable path, or a file where the directory would be:
433
+ # there is nothing the caller needs to know about.
434
+ return False
435
+
436
+
341
437
  class GitHubCopilotSettings(TypedDict, total=False):
342
438
  """GitHub Copilot model settings.
343
439
 
@@ -359,6 +455,10 @@ class GitHubCopilotSettings(TypedDict, total=False):
359
455
  GITHUB_COPILOT_BASE_DIRECTORY. Defaults to ~/.copilot when not set.
360
456
  Only applicable when the SDK spawns the CLI process (ignored when
361
457
  connecting to an external server via a pre-configured client).
458
+ telemetry: OpenTelemetry configuration for the Copilot CLI process. This is
459
+ passed to the SDK client when it is created by the agent. Values coming
460
+ from GITHUB_COPILOT_TELEMETRY or a .env file arrive as a JSON string and
461
+ are parsed into a mapping before they reach the SDK.
362
462
  """
363
463
 
364
464
  cli_path: str | None
@@ -366,6 +466,7 @@ class GitHubCopilotSettings(TypedDict, total=False):
366
466
  timeout: float | None
367
467
  log_level: str | None
368
468
  base_directory: str | None
469
+ telemetry: dict[str, Any] | str | None
369
470
 
370
471
 
371
472
  class GitHubCopilotOptions(TypedDict, total=False):
@@ -437,6 +538,17 @@ class GitHubCopilotOptions(TypedDict, total=False):
437
538
  base_directory: str
438
539
  """Directory where the CLI stores session state, configuration, and other persistent data."""
439
540
 
541
+ enable_file_hooks: bool
542
+ """Whether the CLI loads file hooks from the working directory's ``.github/hooks/``.
543
+
544
+ Defaults to ``False``: hook definitions checked into the working directory are ignored
545
+ unless you opt in, so a session behaves the same way regardless of which checkout it
546
+ runs in. Unrelated to the SDK callback hooks configured through ``on_pre_tool_use``.
547
+ """
548
+
549
+ telemetry: TelemetryConfig
550
+ """OpenTelemetry configuration for the Copilot CLI process."""
551
+
440
552
  on_pre_tool_use: PreToolUseHandler
441
553
  """Pre-tool-use hook handler for the Copilot SDK.
442
554
 
@@ -574,6 +686,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
574
686
  on_pre_tool_use: PreToolUseHandler | None = opts.pop("on_pre_tool_use", None)
575
687
  on_function_approval: FunctionApprovalCallback | None = opts.pop("on_function_approval", None)
576
688
  base_directory = opts.pop("base_directory", None)
689
+ telemetry = opts.pop("telemetry", None)
577
690
 
578
691
  if on_function_approval is not None and on_pre_tool_use is not None:
579
692
  raise ValueError(
@@ -600,11 +713,13 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
600
713
  timeout=timeout,
601
714
  log_level=log_level,
602
715
  base_directory=base_directory,
716
+ telemetry=telemetry,
603
717
  env_file_path=env_file_path,
604
718
  env_file_encoding=env_file_encoding,
605
719
  )
606
720
 
607
721
  self._tools = normalize_tools(tools)
722
+ _reject_mcp_tools(self._tools)
608
723
  self._permission_handler = on_permission_request
609
724
  self._on_pre_tool_use: PreToolUseHandler | None = on_pre_tool_use
610
725
  self._function_approval_handler: FunctionApprovalCallback | None = on_function_approval
@@ -613,6 +728,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
613
728
  # are forwarded verbatim to the Copilot SDK by _build_session_kwargs.
614
729
  self._default_options = opts
615
730
  self._started = False
731
+ self._file_hooks_warning_emitted = False
616
732
 
617
733
  async def __aenter__(self) -> Self:
618
734
  """Start the agent when entering async context."""
@@ -640,6 +756,9 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
640
756
  cli_path = self._settings.get("cli_path") or None
641
757
  log_level = self._settings.get("log_level") or None
642
758
  base_directory = self._settings.get("base_directory") or None
759
+ telemetry = self._settings.get("telemetry") or None
760
+ if isinstance(telemetry, str):
761
+ telemetry = _parse_telemetry_config(telemetry)
643
762
 
644
763
  client_kwargs: dict[str, Any] = {}
645
764
  if cli_path:
@@ -648,6 +767,8 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
648
767
  client_kwargs["log_level"] = log_level
649
768
  if base_directory:
650
769
  client_kwargs["base_directory"] = base_directory
770
+ if telemetry:
771
+ client_kwargs["telemetry"] = telemetry
651
772
  self._client = CopilotClient(**client_kwargs)
652
773
 
653
774
  try:
@@ -1387,6 +1508,27 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
1387
1508
  except Exception as ex:
1388
1509
  raise AgentException(f"Failed to create GitHub Copilot session: {ex}") from ex
1389
1510
 
1511
+ def _warn_once_about_unloaded_file_hooks(self, session_working_directory: str | None) -> None:
1512
+ """Warn once when the effective working directory defines file hooks that will not run.
1513
+
1514
+ Without this the default is silent: hooks simply stop running, with nothing to
1515
+ point at the cause. The warning fires at most once per agent so a long-lived agent
1516
+ does not repeat it on every run.
1517
+ """
1518
+ if self._file_hooks_warning_emitted:
1519
+ return
1520
+ working_directory = _resolve_effective_working_directory(session_working_directory, self._client)
1521
+ if not _has_file_hooks(working_directory):
1522
+ return
1523
+ self._file_hooks_warning_emitted = True
1524
+ logger.warning(
1525
+ "Not loading the file hooks defined in '%s': GitHubCopilotAgent leaves "
1526
+ "enable_file_hooks off so a session behaves the same way in every working "
1527
+ "directory. Set enable_file_hooks=True in default_options (or in per-run "
1528
+ "options) to run them.",
1529
+ working_directory / ".github" / "hooks",
1530
+ )
1531
+
1390
1532
  def _build_session_kwargs(
1391
1533
  self,
1392
1534
  streaming: bool,
@@ -1398,11 +1540,12 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
1398
1540
  ``runtime_options`` which override them. Every key is forwarded verbatim to
1399
1541
  the Copilot SDK, so any ``create_session`` parameter is supported without a
1400
1542
  dedicated mapping here (an unknown name surfaces as a ``TypeError`` from the
1401
- SDK). A few keys are handled specially because they need a secure default
1402
- (``on_permission_request`` defaults to denying all requests, and is wrapped so
1403
- under-specified ``approve-for-session`` decisions are scoped to the request that
1404
- triggered them) or transforming: ``tools`` are merged with the agent's tools and
1405
- converted to SDK tools, and approval callbacks are turned into ``hooks``.
1543
+ SDK). A few keys are handled specially because they need a specific default or
1544
+ transforming: ``on_permission_request`` defaults to denying all requests and is
1545
+ wrapped so under-specified ``approve-for-session`` decisions are scoped to the
1546
+ request that triggered them, ``enable_file_hooks`` defaults to off, ``tools`` are
1547
+ merged with the agent's tools and converted to SDK tools, and approval callbacks
1548
+ are turned into ``hooks``.
1406
1549
 
1407
1550
  Args:
1408
1551
  streaming: Whether to enable streaming for the session.
@@ -1418,7 +1561,10 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
1418
1561
 
1419
1562
  # Merge agent-level tools with any caller-supplied tools (from default_options
1420
1563
  # or per-run options, the latter winning) and convert to SDK tools.
1421
- all_tools = list(self._tools or []) + list(kwargs.get("tools") or [])
1564
+ # Normalize the option-supplied tools the way the constructor does: it converts callables
1565
+ # and flattens tool-collection wrappers, which can otherwise hide an MCPTool.
1566
+ all_tools = normalize_tools(list(self._tools or []) + list(kwargs.get("tools") or []))
1567
+ _reject_mcp_tools(all_tools)
1422
1568
  kwargs["tools"] = self._prepare_tools(all_tools) if all_tools else None
1423
1569
 
1424
1570
  kwargs["streaming"] = streaming
@@ -1427,14 +1573,31 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
1427
1573
  if not kwargs.get("model"):
1428
1574
  kwargs["model"] = self._settings.get("model") or None
1429
1575
  kwargs["on_permission_request"] = _with_normalized_permission_decisions(
1430
- opts.get("on_permission_request") or self._permission_handler or _deny_all_permissions
1576
+ cast(
1577
+ PermissionHandlerType,
1578
+ opts.get("on_permission_request") or self._permission_handler or _deny_all_permissions,
1579
+ )
1431
1580
  )
1581
+ # File hooks let the working directory's checked-in configuration influence what the
1582
+ # CLI does on the host, so the agent leaves them off for a consistent session in every
1583
+ # checkout. Callers opt in through ``default_options`` or per-run options.
1584
+ if kwargs.get("enable_file_hooks") is None:
1585
+ kwargs["enable_file_hooks"] = False
1586
+ self._warn_once_about_unloaded_file_hooks(kwargs.get("working_directory"))
1432
1587
  kwargs["hooks"] = self._build_session_hooks(all_tools, kwargs)
1433
1588
 
1434
1589
  # Strip agent-internal and client-level keys that are consumed here or in the
1435
1590
  # run methods (and settings) but are NOT valid create_session parameters, so
1436
1591
  # they don't leak through the passthrough layer and raise TypeError.
1437
- for key in ("on_pre_tool_use", "on_function_approval", "timeout", "cli_path", "log_level", "base_directory"):
1592
+ for key in (
1593
+ "on_pre_tool_use",
1594
+ "on_function_approval",
1595
+ "timeout",
1596
+ "cli_path",
1597
+ "log_level",
1598
+ "base_directory",
1599
+ "telemetry",
1600
+ ):
1438
1601
  kwargs.pop(key, None)
1439
1602
 
1440
1603
  return kwargs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-framework-github-copilot
3
- Version: 1.0.2
3
+ Version: 2.0.0
4
4
  Summary: GitHub Copilot integration for Microsoft Agent Framework.
5
5
  Author-email: Microsoft <af-support@microsoft.com>
6
6
  Requires-Python: >=3.11
@@ -15,8 +15,8 @@ Classifier: Programming Language :: Python :: 3.13
15
15
  Classifier: Programming Language :: Python :: 3.14
16
16
  Classifier: Typing :: Typed
17
17
  License-File: LICENSE
18
- Requires-Dist: agent-framework-core>=1.13.0,<2
19
- Requires-Dist: github-copilot-sdk==1.0.2; python_version >= '3.11'
18
+ Requires-Dist: agent-framework-core>=1.15.0,<2
19
+ Requires-Dist: github-copilot-sdk==1.0.11; python_version >= '3.11'
20
20
  Project-URL: homepage, https://aka.ms/agent-framework
21
21
  Project-URL: issues, https://github.com/microsoft/agent-framework/issues
22
22
  Project-URL: release_notes, https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true
@@ -111,4 +111,33 @@ model described above. When `on_function_approval` is set, it gates `always_requ
111
111
  the default ask-hook is not installed. It is **mutually exclusive** with `on_pre_tool_use` —
112
112
  setting both (whether at construction or per run) raises `ValueError`.
113
113
 
114
+ ## Workspace-driven session options
115
+
116
+ `on_permission_request` and `on_pre_tool_use` gate **tool calls**. They do not cover
117
+ configuration the CLI picks up from the working directory it runs in, which is a separate
118
+ mechanism with its own switches.
119
+
120
+ So that a session behaves the same way in every checkout, `GitHubCopilotAgent` leaves the
121
+ following off by default:
122
+
123
+ | Option | Default | Effect when enabled |
124
+ | --- | --- | --- |
125
+ | `enable_file_hooks` | `False` | The CLI loads file hooks from the working directory's `.github/hooks/` and runs the commands they define, independently of the tool-approval path. |
126
+
127
+ Opt in per agent or per run when your workflow needs the checkout to drive the session:
128
+
129
+ ```python
130
+ agent = GitHubCopilotAgent(
131
+ default_options=GitHubCopilotOptions(enable_file_hooks=True),
132
+ )
133
+ ```
134
+
135
+ Only enable these for a working directory whose contents you trust to act on the host.
136
+
137
+ To make the default visible rather than silent, the agent logs a warning through the
138
+ `agent_framework.github_copilot` logger the first time it starts a session in a working
139
+ directory that defines hooks it is not loading. See
140
+ [`github_copilot_with_file_hooks.py`](../../samples/02-agents/providers/github_copilot/github_copilot_with_file_hooks.py)
141
+ for a runnable example.
142
+
114
143
 
@@ -0,0 +1,7 @@
1
+ agent_framework_github_copilot/__init__.py,sha256=A8xc4tEW9aFASMSwBmiWIn6MWnOU1rXGyN3HMzEOZxw,464
2
+ agent_framework_github_copilot/_agent.py,sha256=aR9nKRDa_1L9QAyfgh74qyvRVm6f-0NgVNYW7MVEOus,75345
3
+ agent_framework_github_copilot/_feature_usage.py,sha256=UfIdQLxq6ppR2zrjHZTo5kptX7PPR4Be_N2Wd7DSV4U,184
4
+ agent_framework_github_copilot-2.0.0.dist-info/licenses/LICENSE,sha256=ws_MuBL-SCEBqPBFl9_FqZkaaydIJmxHrJG2parhU4M,1141
5
+ agent_framework_github_copilot-2.0.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
6
+ agent_framework_github_copilot-2.0.0.dist-info/METADATA,sha256=JrePbSIdKKpIMChvVH0n7KKh-k7Qp8voz30Mb8IjVWw,6447
7
+ agent_framework_github_copilot-2.0.0.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- agent_framework_github_copilot/__init__.py,sha256=A8xc4tEW9aFASMSwBmiWIn6MWnOU1rXGyN3HMzEOZxw,464
2
- agent_framework_github_copilot/_agent.py,sha256=M96Xy1whwgDTcvCuUOoyBbpi4hoUepCm3gbgX4iv22M,68004
3
- agent_framework_github_copilot/_feature_usage.py,sha256=UfIdQLxq6ppR2zrjHZTo5kptX7PPR4Be_N2Wd7DSV4U,184
4
- agent_framework_github_copilot-1.0.2.dist-info/licenses/LICENSE,sha256=ws_MuBL-SCEBqPBFl9_FqZkaaydIJmxHrJG2parhU4M,1141
5
- agent_framework_github_copilot-1.0.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
6
- agent_framework_github_copilot-1.0.2.dist-info/METADATA,sha256=DIAjemb3jP20Ck5l0y5BlJFrXWSU3cOICZ2o_e3pfP4,5176
7
- agent_framework_github_copilot-1.0.2.dist-info/RECORD,,