agent-framework-github-copilot 2.0.0__tar.gz → 2.0.1__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-2.0.0 → agent_framework_github_copilot-2.0.1}/PKG-INFO +1 -1
- {agent_framework_github_copilot-2.0.0 → agent_framework_github_copilot-2.0.1}/agent_framework_github_copilot/_agent.py +227 -37
- agent_framework_github_copilot-2.0.1/agent_framework_github_copilot/py.typed +0 -0
- {agent_framework_github_copilot-2.0.0 → agent_framework_github_copilot-2.0.1}/pyproject.toml +1 -1
- {agent_framework_github_copilot-2.0.0 → agent_framework_github_copilot-2.0.1}/LICENSE +0 -0
- {agent_framework_github_copilot-2.0.0 → agent_framework_github_copilot-2.0.1}/README.md +0 -0
- {agent_framework_github_copilot-2.0.0 → agent_framework_github_copilot-2.0.1}/agent_framework_github_copilot/__init__.py +0 -0
- {agent_framework_github_copilot-2.0.0 → agent_framework_github_copilot-2.0.1}/agent_framework_github_copilot/_feature_usage.py +0 -0
|
@@ -9,7 +9,8 @@ import json
|
|
|
9
9
|
import logging
|
|
10
10
|
import sys
|
|
11
11
|
import warnings
|
|
12
|
-
|
|
12
|
+
import weakref
|
|
13
|
+
from collections.abc import AsyncGenerator, AsyncIterable, Awaitable, Callable, Mapping, MutableMapping, Sequence
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
from typing import Any, ClassVar, Generic, Literal, TypedDict, cast, overload
|
|
15
16
|
from urllib.parse import urlparse
|
|
@@ -23,6 +24,7 @@ from agent_framework import (
|
|
|
23
24
|
BaseAgent,
|
|
24
25
|
Content,
|
|
25
26
|
ContextProvider,
|
|
27
|
+
FunctionInvocationContext,
|
|
26
28
|
HistoryProvider,
|
|
27
29
|
Message,
|
|
28
30
|
ResponseStream,
|
|
@@ -181,6 +183,10 @@ async def _resolve_function_approval(
|
|
|
181
183
|
|
|
182
184
|
logger = logging.getLogger("agent_framework.github_copilot")
|
|
183
185
|
|
|
186
|
+
# One lock per (CopilotClient, service session ID), shared across agents that share a client.
|
|
187
|
+
# Entries disappear once no run holds or awaits the lock.
|
|
188
|
+
_SESSION_RUN_LOCKS: weakref.WeakValueDictionary[tuple[int, str], asyncio.Lock] = weakref.WeakValueDictionary()
|
|
189
|
+
|
|
184
190
|
_MCP_TOOL_MESSAGE = (
|
|
185
191
|
"MCP server '{name}' cannot be passed to GitHubCopilotAgent as a tool: the Copilot SDK "
|
|
186
192
|
"connects to MCP servers itself, so a framework-managed MCPTool would keep none of its "
|
|
@@ -813,6 +819,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
813
819
|
session: AgentSession | None = None,
|
|
814
820
|
middleware: Sequence[AgentMiddlewareTypes] | None = None,
|
|
815
821
|
options: OptionsT | None = None,
|
|
822
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
816
823
|
**kwargs: Any,
|
|
817
824
|
) -> Awaitable[AgentResponse]: ...
|
|
818
825
|
|
|
@@ -825,6 +832,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
825
832
|
session: AgentSession | None = None,
|
|
826
833
|
middleware: Sequence[AgentMiddlewareTypes] | None = None,
|
|
827
834
|
options: OptionsT | None = None,
|
|
835
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
828
836
|
**kwargs: Any,
|
|
829
837
|
) -> ResponseStream[AgentResponseUpdate, AgentResponse]: ...
|
|
830
838
|
|
|
@@ -836,6 +844,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
836
844
|
session: AgentSession | None = None,
|
|
837
845
|
middleware: Sequence[AgentMiddlewareTypes] | None = None,
|
|
838
846
|
options: OptionsT | None = None,
|
|
847
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
839
848
|
**kwargs: Any,
|
|
840
849
|
) -> Awaitable[AgentResponse] | ResponseStream[AgentResponseUpdate, AgentResponse]:
|
|
841
850
|
"""Get a response from the agent.
|
|
@@ -854,6 +863,9 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
854
863
|
compatibility; pass middleware via :class:`GitHubCopilotAgent` which
|
|
855
864
|
forwards it through :class:`AgentTelemetryLayer`.
|
|
856
865
|
options: Runtime options (model, timeout, etc.).
|
|
866
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
867
|
+
Tools receive them through ``FunctionInvocationContext.kwargs`` when they
|
|
868
|
+
declare a ``FunctionInvocationContext`` parameter.
|
|
857
869
|
kwargs: Additional keyword arguments for compatibility with the shared agent
|
|
858
870
|
interface (e.g. compaction_strategy, tokenizer). Not used by this agent.
|
|
859
871
|
|
|
@@ -887,11 +899,22 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
887
899
|
return AgentResponse.from_updates(updates)
|
|
888
900
|
|
|
889
901
|
return ResponseStream(
|
|
890
|
-
self._stream_updates(
|
|
902
|
+
self._stream_updates(
|
|
903
|
+
messages=messages,
|
|
904
|
+
session=session,
|
|
905
|
+
options=options,
|
|
906
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
907
|
+
_ctx_holder=ctx_holder,
|
|
908
|
+
),
|
|
891
909
|
finalizer=_finalize,
|
|
892
910
|
result_hooks=[_after_run_hook],
|
|
893
911
|
)
|
|
894
|
-
return self._run_impl(
|
|
912
|
+
return self._run_impl(
|
|
913
|
+
messages=messages,
|
|
914
|
+
session=session,
|
|
915
|
+
options=options,
|
|
916
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
917
|
+
)
|
|
895
918
|
|
|
896
919
|
@staticmethod
|
|
897
920
|
def _parse_usage_details_from_copilot(data: AssistantUsageData) -> UsageDetails | None:
|
|
@@ -920,6 +943,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
920
943
|
*,
|
|
921
944
|
session: AgentSession | None = None,
|
|
922
945
|
options: OptionsT | None = None,
|
|
946
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
923
947
|
) -> AgentResponse:
|
|
924
948
|
"""Non-streaming implementation of run."""
|
|
925
949
|
if not self._started:
|
|
@@ -952,7 +976,6 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
952
976
|
existing = list(opts.get("tools") or [])
|
|
953
977
|
opts["tools"] = existing + list(session_context.tools)
|
|
954
978
|
|
|
955
|
-
copilot_session = await self._get_or_create_session(session, streaming=False, runtime_options=opts)
|
|
956
979
|
usage_details: UsageDetails | None = None
|
|
957
980
|
finish_reason: str | None = None
|
|
958
981
|
model: str | None = None
|
|
@@ -986,14 +1009,20 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
986
1009
|
prompt = "\n".join(session_context.instructions) + "\n" + prompt
|
|
987
1010
|
attachments = self._prepare_attachments_for_copilot(context_messages)
|
|
988
1011
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1012
|
+
async with self._session_run_scope(
|
|
1013
|
+
session,
|
|
1014
|
+
streaming=False,
|
|
1015
|
+
runtime_options=opts,
|
|
1016
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1017
|
+
) as copilot_session:
|
|
1018
|
+
unsubscribe = copilot_session.on(usage_event_handler)
|
|
1019
|
+
try:
|
|
1020
|
+
mark_feature_used(FeatureIndex.GITHUB_COPILOT)
|
|
1021
|
+
response_event = await copilot_session.send_and_wait(prompt, attachments=attachments, timeout=timeout)
|
|
1022
|
+
except Exception as ex:
|
|
1023
|
+
raise AgentException(f"GitHub Copilot request failed: {ex}") from ex
|
|
1024
|
+
finally:
|
|
1025
|
+
unsubscribe()
|
|
997
1026
|
|
|
998
1027
|
response_messages: list[Message] = []
|
|
999
1028
|
response_id: str | None = None
|
|
@@ -1032,6 +1061,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1032
1061
|
*,
|
|
1033
1062
|
session: AgentSession | None = None,
|
|
1034
1063
|
options: OptionsT | None = None,
|
|
1064
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
1035
1065
|
_ctx_holder: dict[str, Any] | None = None,
|
|
1036
1066
|
) -> AsyncIterable[AgentResponseUpdate]:
|
|
1037
1067
|
"""Internal method to stream updates from GitHub Copilot.
|
|
@@ -1042,6 +1072,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1042
1072
|
Keyword Args:
|
|
1043
1073
|
session: The conversation session associated with the message(s).
|
|
1044
1074
|
options: Runtime options (model, timeout, etc.).
|
|
1075
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
1045
1076
|
_ctx_holder: Internal dict populated with session_context and session
|
|
1046
1077
|
so that the caller (via a ResponseStream result_hook) can run
|
|
1047
1078
|
after_run providers without duplicating the updates buffer.
|
|
@@ -1081,12 +1112,6 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1081
1112
|
existing = list(opts.get("tools") or [])
|
|
1082
1113
|
opts["tools"] = existing + list(session_context.tools)
|
|
1083
1114
|
|
|
1084
|
-
copilot_session = await self._get_or_create_session(session, streaming=True, runtime_options=opts)
|
|
1085
|
-
|
|
1086
|
-
if _ctx_holder is not None:
|
|
1087
|
-
_ctx_holder["session_context"] = session_context
|
|
1088
|
-
_ctx_holder["session"] = session
|
|
1089
|
-
|
|
1090
1115
|
# Build the prompt from the full session context so provider-injected messages are included.
|
|
1091
1116
|
context_messages = session_context.get_messages(include_input=True)
|
|
1092
1117
|
prompt = "\n".join([message.text for message in context_messages])
|
|
@@ -1172,18 +1197,28 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1172
1197
|
error_msg = error_data.message or "Unknown error"
|
|
1173
1198
|
queue.put_nowait(AgentException(f"GitHub Copilot session error: {error_msg}"))
|
|
1174
1199
|
|
|
1175
|
-
|
|
1200
|
+
async with self._session_run_scope(
|
|
1201
|
+
session,
|
|
1202
|
+
streaming=True,
|
|
1203
|
+
runtime_options=opts,
|
|
1204
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1205
|
+
) as copilot_session:
|
|
1206
|
+
if _ctx_holder is not None:
|
|
1207
|
+
_ctx_holder["session_context"] = session_context
|
|
1208
|
+
_ctx_holder["session"] = session
|
|
1176
1209
|
|
|
1177
|
-
|
|
1178
|
-
mark_feature_used(FeatureIndex.GITHUB_COPILOT)
|
|
1179
|
-
await copilot_session.send(prompt, attachments=attachments)
|
|
1210
|
+
unsubscribe = copilot_session.on(event_handler)
|
|
1180
1211
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1212
|
+
try:
|
|
1213
|
+
mark_feature_used(FeatureIndex.GITHUB_COPILOT)
|
|
1214
|
+
await copilot_session.send(prompt, attachments=attachments)
|
|
1215
|
+
|
|
1216
|
+
while (item := await queue.get()) is not None:
|
|
1217
|
+
if isinstance(item, Exception):
|
|
1218
|
+
raise item
|
|
1219
|
+
yield item
|
|
1220
|
+
finally:
|
|
1221
|
+
unsubscribe()
|
|
1187
1222
|
|
|
1188
1223
|
async def _run_before_providers(
|
|
1189
1224
|
self,
|
|
@@ -1301,12 +1336,20 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1301
1336
|
def _prepare_tools(
|
|
1302
1337
|
self,
|
|
1303
1338
|
tools: Sequence[ToolTypes | CopilotTool],
|
|
1339
|
+
*,
|
|
1340
|
+
agent_session: AgentSession | None = None,
|
|
1341
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
1304
1342
|
) -> list[CopilotTool]:
|
|
1305
1343
|
"""Convert Agent Framework tools to Copilot SDK tools.
|
|
1306
1344
|
|
|
1307
1345
|
Args:
|
|
1308
1346
|
tools: List of Agent Framework tools.
|
|
1309
1347
|
|
|
1348
|
+
Keyword Args:
|
|
1349
|
+
agent_session: The conversation session, exposed to tools through their
|
|
1350
|
+
``FunctionInvocationContext``.
|
|
1351
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
1352
|
+
|
|
1310
1353
|
Returns:
|
|
1311
1354
|
List of Copilot SDK tools.
|
|
1312
1355
|
"""
|
|
@@ -1316,16 +1359,33 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1316
1359
|
if isinstance(tool, CopilotTool):
|
|
1317
1360
|
copilot_tools.append(tool)
|
|
1318
1361
|
elif isinstance(tool, FunctionTool):
|
|
1319
|
-
copilot_tools.append(
|
|
1362
|
+
copilot_tools.append(
|
|
1363
|
+
self._tool_to_copilot_tool(
|
|
1364
|
+
tool,
|
|
1365
|
+
agent_session=agent_session,
|
|
1366
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1367
|
+
)
|
|
1368
|
+
)
|
|
1320
1369
|
elif isinstance(tool, MutableMapping):
|
|
1321
1370
|
copilot_tools.append(tool) # type: ignore[arg-type]
|
|
1322
1371
|
# Note: Other tool types (e.g., dict-based hosted tools) are skipped
|
|
1323
1372
|
|
|
1324
1373
|
return copilot_tools
|
|
1325
1374
|
|
|
1326
|
-
def _tool_to_copilot_tool(
|
|
1375
|
+
def _tool_to_copilot_tool(
|
|
1376
|
+
self,
|
|
1377
|
+
ai_func: FunctionTool,
|
|
1378
|
+
*,
|
|
1379
|
+
agent_session: AgentSession | None = None,
|
|
1380
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
1381
|
+
) -> CopilotTool:
|
|
1327
1382
|
"""Convert an FunctionTool to a Copilot SDK tool.
|
|
1328
1383
|
|
|
1384
|
+
Each invocation receives a ``FunctionInvocationContext`` carrying the run's
|
|
1385
|
+
``function_invocation_kwargs`` and ``agent_session``, so tools that declare a
|
|
1386
|
+
``FunctionInvocationContext`` parameter can read them the same way they do
|
|
1387
|
+
with a chat-client-backed agent.
|
|
1388
|
+
|
|
1329
1389
|
Approval for tools declared with ``approval_mode="always_require"`` is normally
|
|
1330
1390
|
enforced by the Copilot SDK's native ``on_pre_tool_use`` hook (see
|
|
1331
1391
|
:meth:`_build_session_hooks`). When the deprecated ``on_function_approval``
|
|
@@ -1335,6 +1395,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1335
1395
|
"""
|
|
1336
1396
|
approval_handler = self._function_approval_handler
|
|
1337
1397
|
enforce = approval_handler is not None and ai_func.approval_mode == "always_require"
|
|
1398
|
+
runtime_kwargs = dict(function_invocation_kwargs) if function_invocation_kwargs is not None else {}
|
|
1338
1399
|
|
|
1339
1400
|
async def handler(invocation: ToolInvocation) -> ToolResult:
|
|
1340
1401
|
args: dict[str, Any] = invocation.arguments or {}
|
|
@@ -1353,11 +1414,21 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1353
1414
|
result_type="failure",
|
|
1354
1415
|
error="approval_denied",
|
|
1355
1416
|
)
|
|
1417
|
+
context = FunctionInvocationContext(
|
|
1418
|
+
function=ai_func,
|
|
1419
|
+
arguments=args,
|
|
1420
|
+
session=agent_session,
|
|
1421
|
+
kwargs=runtime_kwargs,
|
|
1422
|
+
)
|
|
1356
1423
|
if ai_func.input_model:
|
|
1357
1424
|
args_instance = ai_func.input_model(**args)
|
|
1358
|
-
result = await ai_func.invoke(
|
|
1425
|
+
result = await ai_func.invoke(
|
|
1426
|
+
arguments=args_instance, context=context, tool_call_id=invocation.tool_call_id or None
|
|
1427
|
+
)
|
|
1359
1428
|
else:
|
|
1360
|
-
result = await ai_func.invoke(
|
|
1429
|
+
result = await ai_func.invoke(
|
|
1430
|
+
arguments=args, context=context, tool_call_id=invocation.tool_call_id or None
|
|
1431
|
+
)
|
|
1361
1432
|
rich = [c for c in result if c.type in ("data", "uri")]
|
|
1362
1433
|
if rich:
|
|
1363
1434
|
logger.warning(
|
|
@@ -1471,11 +1542,73 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1471
1542
|
|
|
1472
1543
|
return {"on_pre_tool_use": default_pre_tool_use}
|
|
1473
1544
|
|
|
1545
|
+
def _session_run_lock(self, service_session_id: str) -> asyncio.Lock:
|
|
1546
|
+
"""Return the lock that serializes runs on one Copilot service session."""
|
|
1547
|
+
key = (id(self._client), service_session_id)
|
|
1548
|
+
lock = _SESSION_RUN_LOCKS.get(key)
|
|
1549
|
+
if lock is None:
|
|
1550
|
+
lock = asyncio.Lock()
|
|
1551
|
+
_SESSION_RUN_LOCKS[key] = lock
|
|
1552
|
+
return lock
|
|
1553
|
+
|
|
1554
|
+
@contextlib.asynccontextmanager
|
|
1555
|
+
async def _session_run_scope(
|
|
1556
|
+
self,
|
|
1557
|
+
agent_session: AgentSession,
|
|
1558
|
+
*,
|
|
1559
|
+
streaming: bool,
|
|
1560
|
+
runtime_options: dict[str, Any],
|
|
1561
|
+
function_invocation_kwargs: Mapping[str, Any] | None,
|
|
1562
|
+
) -> AsyncGenerator[CopilotSession]:
|
|
1563
|
+
"""Open the Copilot session for one run and hold it exclusively until the run ends.
|
|
1564
|
+
|
|
1565
|
+
The Copilot SDK keeps a single session object per service session ID and
|
|
1566
|
+
re-registers tools on it on every resume, dispatching tool calls by session ID.
|
|
1567
|
+
Tool handlers capture the run's ``function_invocation_kwargs`` and session, so
|
|
1568
|
+
an overlapping resume would let one run's tool calls execute with another run's
|
|
1569
|
+
context. Runs on the same service session are therefore serialized.
|
|
1570
|
+
|
|
1571
|
+
Args:
|
|
1572
|
+
agent_session: The conversation session.
|
|
1573
|
+
|
|
1574
|
+
Keyword Args:
|
|
1575
|
+
streaming: Whether to enable streaming for the session.
|
|
1576
|
+
runtime_options: Runtime options from run that take precedence.
|
|
1577
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
1578
|
+
|
|
1579
|
+
Yields:
|
|
1580
|
+
The created or resumed CopilotSession.
|
|
1581
|
+
"""
|
|
1582
|
+
lock: asyncio.Lock | None = None
|
|
1583
|
+
service_session_id = agent_session.service_session_id
|
|
1584
|
+
if isinstance(service_session_id, str):
|
|
1585
|
+
resume_lock = self._session_run_lock(service_session_id)
|
|
1586
|
+
await resume_lock.acquire()
|
|
1587
|
+
lock = resume_lock
|
|
1588
|
+
try:
|
|
1589
|
+
copilot_session = await self._get_or_create_session(
|
|
1590
|
+
agent_session,
|
|
1591
|
+
streaming=streaming,
|
|
1592
|
+
runtime_options=runtime_options,
|
|
1593
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1594
|
+
)
|
|
1595
|
+
if lock is None:
|
|
1596
|
+
# A newly created service session ID is not known to any other run yet,
|
|
1597
|
+
# so this acquire never waits.
|
|
1598
|
+
create_lock = self._session_run_lock(copilot_session.session_id)
|
|
1599
|
+
await create_lock.acquire()
|
|
1600
|
+
lock = create_lock
|
|
1601
|
+
yield copilot_session
|
|
1602
|
+
finally:
|
|
1603
|
+
if lock is not None:
|
|
1604
|
+
lock.release()
|
|
1605
|
+
|
|
1474
1606
|
async def _get_or_create_session(
|
|
1475
1607
|
self,
|
|
1476
1608
|
agent_session: AgentSession,
|
|
1477
1609
|
streaming: bool = False,
|
|
1478
1610
|
runtime_options: dict[str, Any] | None = None,
|
|
1611
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
1479
1612
|
) -> CopilotSession:
|
|
1480
1613
|
"""Get an existing session or create a new one for the session.
|
|
1481
1614
|
|
|
@@ -1483,6 +1616,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1483
1616
|
agent_session: The conversation session.
|
|
1484
1617
|
streaming: Whether to enable streaming for the session.
|
|
1485
1618
|
runtime_options: Runtime options from run that take precedence.
|
|
1619
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
1486
1620
|
|
|
1487
1621
|
Returns:
|
|
1488
1622
|
A CopilotSession instance.
|
|
@@ -1500,9 +1634,20 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1500
1634
|
raise AgentException(
|
|
1501
1635
|
"GitHubCopilotAgent expects a string service_session_id for session resumption."
|
|
1502
1636
|
)
|
|
1503
|
-
return await self._resume_session(
|
|
1637
|
+
return await self._resume_session(
|
|
1638
|
+
service_session_id,
|
|
1639
|
+
streaming,
|
|
1640
|
+
runtime_options,
|
|
1641
|
+
agent_session=agent_session,
|
|
1642
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1643
|
+
)
|
|
1504
1644
|
|
|
1505
|
-
session = await self._create_session(
|
|
1645
|
+
session = await self._create_session(
|
|
1646
|
+
streaming,
|
|
1647
|
+
runtime_options,
|
|
1648
|
+
agent_session=agent_session,
|
|
1649
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1650
|
+
)
|
|
1506
1651
|
agent_session.service_session_id = session.session_id
|
|
1507
1652
|
return session
|
|
1508
1653
|
except Exception as ex:
|
|
@@ -1533,6 +1678,9 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1533
1678
|
self,
|
|
1534
1679
|
streaming: bool,
|
|
1535
1680
|
runtime_options: dict[str, Any] | None,
|
|
1681
|
+
*,
|
|
1682
|
+
agent_session: AgentSession | None = None,
|
|
1683
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
1536
1684
|
) -> dict[str, Any]:
|
|
1537
1685
|
"""Assemble keyword arguments for ``create_session`` / ``resume_session``.
|
|
1538
1686
|
|
|
@@ -1551,6 +1699,11 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1551
1699
|
streaming: Whether to enable streaming for the session.
|
|
1552
1700
|
runtime_options: Runtime options that take precedence over default_options.
|
|
1553
1701
|
|
|
1702
|
+
Keyword Args:
|
|
1703
|
+
agent_session: The conversation session, exposed to tools through their
|
|
1704
|
+
``FunctionInvocationContext``.
|
|
1705
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
1706
|
+
|
|
1554
1707
|
Returns:
|
|
1555
1708
|
The keyword arguments to splat into the SDK session factory.
|
|
1556
1709
|
"""
|
|
@@ -1565,7 +1718,15 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1565
1718
|
# and flattens tool-collection wrappers, which can otherwise hide an MCPTool.
|
|
1566
1719
|
all_tools = normalize_tools(list(self._tools or []) + list(kwargs.get("tools") or []))
|
|
1567
1720
|
_reject_mcp_tools(all_tools)
|
|
1568
|
-
kwargs["tools"] =
|
|
1721
|
+
kwargs["tools"] = (
|
|
1722
|
+
self._prepare_tools(
|
|
1723
|
+
all_tools,
|
|
1724
|
+
agent_session=agent_session,
|
|
1725
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1726
|
+
)
|
|
1727
|
+
if all_tools
|
|
1728
|
+
else None
|
|
1729
|
+
)
|
|
1569
1730
|
|
|
1570
1731
|
kwargs["streaming"] = streaming
|
|
1571
1732
|
# model may already be present from per-run options (merged above); otherwise fall
|
|
@@ -1606,23 +1767,40 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1606
1767
|
self,
|
|
1607
1768
|
streaming: bool,
|
|
1608
1769
|
runtime_options: dict[str, Any] | None = None,
|
|
1770
|
+
*,
|
|
1771
|
+
agent_session: AgentSession | None = None,
|
|
1772
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
1609
1773
|
) -> CopilotSession:
|
|
1610
1774
|
"""Create a new Copilot session.
|
|
1611
1775
|
|
|
1612
1776
|
Args:
|
|
1613
1777
|
streaming: Whether to enable streaming for the session.
|
|
1614
1778
|
runtime_options: Runtime options that take precedence over default_options.
|
|
1779
|
+
|
|
1780
|
+
Keyword Args:
|
|
1781
|
+
agent_session: The conversation session, exposed to tools.
|
|
1782
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
1615
1783
|
"""
|
|
1616
1784
|
if not self._client:
|
|
1617
1785
|
raise RuntimeError("GitHub Copilot client not initialized. Call start() first.")
|
|
1618
1786
|
|
|
1619
|
-
return await self._client.create_session(
|
|
1787
|
+
return await self._client.create_session(
|
|
1788
|
+
**self._build_session_kwargs(
|
|
1789
|
+
streaming,
|
|
1790
|
+
runtime_options,
|
|
1791
|
+
agent_session=agent_session,
|
|
1792
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1793
|
+
)
|
|
1794
|
+
)
|
|
1620
1795
|
|
|
1621
1796
|
async def _resume_session(
|
|
1622
1797
|
self,
|
|
1623
1798
|
session_id: str,
|
|
1624
1799
|
streaming: bool,
|
|
1625
1800
|
runtime_options: dict[str, Any] | None = None,
|
|
1801
|
+
*,
|
|
1802
|
+
agent_session: AgentSession | None = None,
|
|
1803
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
1626
1804
|
) -> CopilotSession:
|
|
1627
1805
|
"""Resume an existing Copilot session by ID.
|
|
1628
1806
|
|
|
@@ -1630,11 +1808,23 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1630
1808
|
session_id: The session ID to resume.
|
|
1631
1809
|
streaming: Whether to enable streaming for the session.
|
|
1632
1810
|
runtime_options: Runtime options that take precedence over default_options.
|
|
1811
|
+
|
|
1812
|
+
Keyword Args:
|
|
1813
|
+
agent_session: The conversation session, exposed to tools.
|
|
1814
|
+
function_invocation_kwargs: Keyword arguments forwarded to tool invocations.
|
|
1633
1815
|
"""
|
|
1634
1816
|
if not self._client:
|
|
1635
1817
|
raise RuntimeError("GitHub Copilot client not initialized. Call start() first.")
|
|
1636
1818
|
|
|
1637
|
-
return await self._client.resume_session(
|
|
1819
|
+
return await self._client.resume_session(
|
|
1820
|
+
session_id,
|
|
1821
|
+
**self._build_session_kwargs(
|
|
1822
|
+
streaming,
|
|
1823
|
+
runtime_options,
|
|
1824
|
+
agent_session=agent_session,
|
|
1825
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
1826
|
+
),
|
|
1827
|
+
)
|
|
1638
1828
|
|
|
1639
1829
|
|
|
1640
1830
|
class GitHubCopilotAgent( # type: ignore[misc]
|
|
File without changes
|
{agent_framework_github_copilot-2.0.0 → agent_framework_github_copilot-2.0.1}/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 = "2.0.
|
|
7
|
+
version = "2.0.1"
|
|
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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|