agent-framework-github-copilot 1.0.3__tar.gz → 2.0.0__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.3 → agent_framework_github_copilot-2.0.0}/PKG-INFO +31 -2
- {agent_framework_github_copilot-1.0.3 → agent_framework_github_copilot-2.0.0}/README.md +29 -0
- {agent_framework_github_copilot-1.0.3 → agent_framework_github_copilot-2.0.0}/agent_framework_github_copilot/_agent.py +127 -13
- {agent_framework_github_copilot-1.0.3 → agent_framework_github_copilot-2.0.0}/pyproject.toml +3 -3
- {agent_framework_github_copilot-1.0.3 → agent_framework_github_copilot-2.0.0}/LICENSE +0 -0
- {agent_framework_github_copilot-1.0.3 → agent_framework_github_copilot-2.0.0}/agent_framework_github_copilot/__init__.py +0 -0
- {agent_framework_github_copilot-1.0.3 → agent_framework_github_copilot-2.0.0}/agent_framework_github_copilot/_feature_usage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-framework-github-copilot
|
|
3
|
-
Version:
|
|
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
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
16
16
|
Classifier: Typing :: Typed
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: agent-framework-core>=1.15.0,<2
|
|
19
|
-
Requires-Dist: github-copilot-sdk==1.0.
|
|
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
|
|
|
@@ -87,3 +87,32 @@ model described above. When `on_function_approval` is set, it gates `always_requ
|
|
|
87
87
|
the default ask-hook is not installed. It is **mutually exclusive** with `on_pre_tool_use` —
|
|
88
88
|
setting both (whether at construction or per run) raises `ValueError`.
|
|
89
89
|
|
|
90
|
+
## Workspace-driven session options
|
|
91
|
+
|
|
92
|
+
`on_permission_request` and `on_pre_tool_use` gate **tool calls**. They do not cover
|
|
93
|
+
configuration the CLI picks up from the working directory it runs in, which is a separate
|
|
94
|
+
mechanism with its own switches.
|
|
95
|
+
|
|
96
|
+
So that a session behaves the same way in every checkout, `GitHubCopilotAgent` leaves the
|
|
97
|
+
following off by default:
|
|
98
|
+
|
|
99
|
+
| Option | Default | Effect when enabled |
|
|
100
|
+
| --- | --- | --- |
|
|
101
|
+
| `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. |
|
|
102
|
+
|
|
103
|
+
Opt in per agent or per run when your workflow needs the checkout to drive the session:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
agent = GitHubCopilotAgent(
|
|
107
|
+
default_options=GitHubCopilotOptions(enable_file_hooks=True),
|
|
108
|
+
)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Only enable these for a working directory whose contents you trust to act on the host.
|
|
112
|
+
|
|
113
|
+
To make the default visible rather than silent, the agent logs a warning through the
|
|
114
|
+
`agent_framework.github_copilot` logger the first time it starts a session in a working
|
|
115
|
+
directory that defines hooks it is not loading. See
|
|
116
|
+
[`github_copilot_with_file_hooks.py`](../../samples/02-agents/providers/github_copilot/github_copilot_with_file_hooks.py)
|
|
117
|
+
for a runnable example.
|
|
118
|
+
|
|
@@ -10,6 +10,7 @@ import logging
|
|
|
10
10
|
import sys
|
|
11
11
|
import warnings
|
|
12
12
|
from collections.abc import AsyncIterable, Awaitable, Callable, Mapping, MutableMapping, Sequence
|
|
13
|
+
from pathlib import Path
|
|
13
14
|
from typing import Any, ClassVar, Generic, Literal, TypedDict, cast, overload
|
|
14
15
|
from urllib.parse import urlparse
|
|
15
16
|
|
|
@@ -30,6 +31,7 @@ from agent_framework import (
|
|
|
30
31
|
add_usage_details,
|
|
31
32
|
normalize_messages,
|
|
32
33
|
)
|
|
34
|
+
from agent_framework._mcp import MCPTool
|
|
33
35
|
from agent_framework._settings import load_settings
|
|
34
36
|
from agent_framework._telemetry import mark_feature_used
|
|
35
37
|
from agent_framework._tools import FunctionTool, ToolTypes
|
|
@@ -77,6 +79,7 @@ try:
|
|
|
77
79
|
Attachment,
|
|
78
80
|
BlobAttachment,
|
|
79
81
|
MCPServerConfig,
|
|
82
|
+
PermissionInvocation,
|
|
80
83
|
PermissionRequestResult,
|
|
81
84
|
PreToolUseHandler,
|
|
82
85
|
PreToolUseHookOutput,
|
|
@@ -110,14 +113,24 @@ except ImportError as _copilot_import_error:
|
|
|
110
113
|
DEFAULT_TIMEOUT_SECONDS: float = 60.0
|
|
111
114
|
"""Default timeout in seconds for Copilot requests."""
|
|
112
115
|
|
|
116
|
+
_PermissionHandlerContext = Any
|
|
117
|
+
"""Compatibility context accepted by permission handlers across SDK versions."""
|
|
118
|
+
|
|
113
119
|
PermissionHandlerType = Callable[
|
|
114
|
-
[PermissionRequest,
|
|
120
|
+
[PermissionRequest, _PermissionHandlerContext],
|
|
121
|
+
"PermissionRequestResult | Awaitable[PermissionRequestResult]",
|
|
115
122
|
]
|
|
116
123
|
"""Type for permission request handlers. Supports both sync and async callbacks."""
|
|
117
124
|
|
|
118
|
-
AsyncPermissionHandlerType = Callable[
|
|
125
|
+
AsyncPermissionHandlerType = Callable[
|
|
126
|
+
[PermissionRequest, _PermissionHandlerContext], "Awaitable[PermissionRequestResult]"
|
|
127
|
+
]
|
|
119
128
|
"""Type for permission request handlers that are always asynchronous."""
|
|
120
129
|
|
|
130
|
+
_SdkAsyncPermissionHandlerType = Callable[
|
|
131
|
+
[PermissionRequest, PermissionInvocation], "Awaitable[PermissionRequestResult]"
|
|
132
|
+
]
|
|
133
|
+
|
|
121
134
|
|
|
122
135
|
FunctionApprovalCallback = Callable[[Content], "bool | Awaitable[bool]"]
|
|
123
136
|
"""Deprecated approval callback for ``FunctionTool`` instances declared with
|
|
@@ -168,10 +181,26 @@ async def _resolve_function_approval(
|
|
|
168
181
|
|
|
169
182
|
logger = logging.getLogger("agent_framework.github_copilot")
|
|
170
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
|
+
|
|
171
200
|
|
|
172
201
|
def _deny_all_permissions(
|
|
173
202
|
_request: PermissionRequest,
|
|
174
|
-
_invocation:
|
|
203
|
+
_invocation: _PermissionHandlerContext,
|
|
175
204
|
) -> PermissionRequestResult:
|
|
176
205
|
"""Default permission handler that denies all requests."""
|
|
177
206
|
return PermissionDecisionUserNotAvailable()
|
|
@@ -322,7 +351,7 @@ def _normalize_permission_decision(
|
|
|
322
351
|
return PermissionDecisionApproveForSession(approval=approval)
|
|
323
352
|
|
|
324
353
|
|
|
325
|
-
def _with_normalized_permission_decisions(handler: PermissionHandlerType) ->
|
|
354
|
+
def _with_normalized_permission_decisions(handler: PermissionHandlerType) -> _SdkAsyncPermissionHandlerType:
|
|
326
355
|
"""Wrap a permission handler so its decisions are normalized before reaching the SDK.
|
|
327
356
|
|
|
328
357
|
Exceptions raised by ``handler`` deliberately propagate: the SDK already catches them
|
|
@@ -335,8 +364,10 @@ def _with_normalized_permission_decisions(handler: PermissionHandlerType) -> Asy
|
|
|
335
364
|
An async handler delegating to ``handler`` and normalizing its result.
|
|
336
365
|
"""
|
|
337
366
|
|
|
338
|
-
async def normalized_handler(
|
|
339
|
-
|
|
367
|
+
async def normalized_handler(
|
|
368
|
+
request: PermissionRequest, invocation: PermissionInvocation
|
|
369
|
+
) -> PermissionRequestResult:
|
|
370
|
+
result = handler(request, cast(PermissionInvocation, dict(invocation)))
|
|
340
371
|
if inspect.isawaitable(result):
|
|
341
372
|
result = await result
|
|
342
373
|
return _normalize_permission_decision(result, request)
|
|
@@ -364,6 +395,45 @@ def _parse_telemetry_config(raw: str) -> TelemetryConfig | None:
|
|
|
364
395
|
return cast(TelemetryConfig, parsed)
|
|
365
396
|
|
|
366
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
|
+
|
|
367
437
|
class GitHubCopilotSettings(TypedDict, total=False):
|
|
368
438
|
"""GitHub Copilot model settings.
|
|
369
439
|
|
|
@@ -468,6 +538,14 @@ class GitHubCopilotOptions(TypedDict, total=False):
|
|
|
468
538
|
base_directory: str
|
|
469
539
|
"""Directory where the CLI stores session state, configuration, and other persistent data."""
|
|
470
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
|
+
|
|
471
549
|
telemetry: TelemetryConfig
|
|
472
550
|
"""OpenTelemetry configuration for the Copilot CLI process."""
|
|
473
551
|
|
|
@@ -641,6 +719,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
641
719
|
)
|
|
642
720
|
|
|
643
721
|
self._tools = normalize_tools(tools)
|
|
722
|
+
_reject_mcp_tools(self._tools)
|
|
644
723
|
self._permission_handler = on_permission_request
|
|
645
724
|
self._on_pre_tool_use: PreToolUseHandler | None = on_pre_tool_use
|
|
646
725
|
self._function_approval_handler: FunctionApprovalCallback | None = on_function_approval
|
|
@@ -649,6 +728,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
649
728
|
# are forwarded verbatim to the Copilot SDK by _build_session_kwargs.
|
|
650
729
|
self._default_options = opts
|
|
651
730
|
self._started = False
|
|
731
|
+
self._file_hooks_warning_emitted = False
|
|
652
732
|
|
|
653
733
|
async def __aenter__(self) -> Self:
|
|
654
734
|
"""Start the agent when entering async context."""
|
|
@@ -1428,6 +1508,27 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1428
1508
|
except Exception as ex:
|
|
1429
1509
|
raise AgentException(f"Failed to create GitHub Copilot session: {ex}") from ex
|
|
1430
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
|
+
|
|
1431
1532
|
def _build_session_kwargs(
|
|
1432
1533
|
self,
|
|
1433
1534
|
streaming: bool,
|
|
@@ -1439,11 +1540,12 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1439
1540
|
``runtime_options`` which override them. Every key is forwarded verbatim to
|
|
1440
1541
|
the Copilot SDK, so any ``create_session`` parameter is supported without a
|
|
1441
1542
|
dedicated mapping here (an unknown name surfaces as a ``TypeError`` from the
|
|
1442
|
-
SDK). A few keys are handled specially because they need a
|
|
1443
|
-
|
|
1444
|
-
under-specified ``approve-for-session`` decisions are scoped to the
|
|
1445
|
-
triggered them
|
|
1446
|
-
converted to SDK tools, and approval callbacks
|
|
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``.
|
|
1447
1549
|
|
|
1448
1550
|
Args:
|
|
1449
1551
|
streaming: Whether to enable streaming for the session.
|
|
@@ -1459,7 +1561,10 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1459
1561
|
|
|
1460
1562
|
# Merge agent-level tools with any caller-supplied tools (from default_options
|
|
1461
1563
|
# or per-run options, the latter winning) and convert to SDK tools.
|
|
1462
|
-
|
|
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)
|
|
1463
1568
|
kwargs["tools"] = self._prepare_tools(all_tools) if all_tools else None
|
|
1464
1569
|
|
|
1465
1570
|
kwargs["streaming"] = streaming
|
|
@@ -1468,8 +1573,17 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1468
1573
|
if not kwargs.get("model"):
|
|
1469
1574
|
kwargs["model"] = self._settings.get("model") or None
|
|
1470
1575
|
kwargs["on_permission_request"] = _with_normalized_permission_decisions(
|
|
1471
|
-
|
|
1576
|
+
cast(
|
|
1577
|
+
PermissionHandlerType,
|
|
1578
|
+
opts.get("on_permission_request") or self._permission_handler or _deny_all_permissions,
|
|
1579
|
+
)
|
|
1472
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"))
|
|
1473
1587
|
kwargs["hooks"] = self._build_session_hooks(all_tools, kwargs)
|
|
1474
1588
|
|
|
1475
1589
|
# Strip agent-internal and client-level keys that are consumed here or in the
|
{agent_framework_github_copilot-1.0.3 → agent_framework_github_copilot-2.0.0}/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.11"
|
|
7
|
-
version = "
|
|
7
|
+
version = "2.0.0"
|
|
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,11 +23,11 @@ classifiers = [
|
|
|
23
23
|
]
|
|
24
24
|
dependencies = [
|
|
25
25
|
"agent-framework-core>=1.15.0,<2",
|
|
26
|
-
"github-copilot-sdk==1.0.
|
|
26
|
+
"github-copilot-sdk==1.0.11; python_version >= '3.11'",
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
[tool.uv]
|
|
30
|
-
prerelease = "if-necessary
|
|
30
|
+
prerelease = "if-necessary"
|
|
31
31
|
environments = [
|
|
32
32
|
"sys_platform == 'darwin'",
|
|
33
33
|
"sys_platform == 'linux'",
|
|
File without changes
|
|
File without changes
|