agent-framework-github-copilot 1.0.0rc3__tar.gz → 1.0.0rc4__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 → agent_framework_github_copilot-1.0.0rc4}/PKG-INFO +1 -1
- {agent_framework_github_copilot-1.0.0rc3 → agent_framework_github_copilot-1.0.0rc4}/agent_framework_github_copilot/_agent.py +98 -83
- {agent_framework_github_copilot-1.0.0rc3 → agent_framework_github_copilot-1.0.0rc4}/pyproject.toml +1 -1
- {agent_framework_github_copilot-1.0.0rc3 → agent_framework_github_copilot-1.0.0rc4}/LICENSE +0 -0
- {agent_framework_github_copilot-1.0.0rc3 → agent_framework_github_copilot-1.0.0rc4}/README.md +0 -0
- {agent_framework_github_copilot-1.0.0rc3 → agent_framework_github_copilot-1.0.0rc4}/agent_framework_github_copilot/__init__.py +0 -0
|
@@ -162,7 +162,16 @@ class GitHubCopilotSettings(TypedDict, total=False):
|
|
|
162
162
|
|
|
163
163
|
|
|
164
164
|
class GitHubCopilotOptions(TypedDict, total=False):
|
|
165
|
-
"""GitHub Copilot-specific options.
|
|
165
|
+
"""GitHub Copilot-specific options.
|
|
166
|
+
|
|
167
|
+
The keys below have first-class typing and inline documentation because they are
|
|
168
|
+
the commonly used options. They are **not** an exhaustive list: any other
|
|
169
|
+
parameter accepted by the Copilot SDK's ``create_session`` (for example
|
|
170
|
+
``reasoning_effort``, ``context_tier``, ``enable_citations``, ``available_tools``,
|
|
171
|
+
``memory``, ...) may also be supplied and is forwarded verbatim to the SDK. An
|
|
172
|
+
unrecognized parameter name surfaces as a ``TypeError`` from the SDK, so typos are
|
|
173
|
+
caught rather than silently ignored.
|
|
174
|
+
"""
|
|
166
175
|
|
|
167
176
|
system_message: SystemMessageConfig
|
|
168
177
|
"""System message configuration for the session. Use mode 'append' to add to the default
|
|
@@ -355,11 +364,6 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
355
364
|
timeout = opts.pop("timeout", None)
|
|
356
365
|
log_level = opts.pop("log_level", None)
|
|
357
366
|
on_permission_request: PermissionHandlerType | None = opts.pop("on_permission_request", None)
|
|
358
|
-
mcp_servers: dict[str, MCPServerConfig] | None = opts.pop("mcp_servers", None)
|
|
359
|
-
provider: ProviderConfig | None = opts.pop("provider", None)
|
|
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
367
|
on_pre_tool_use: PreToolUseHandler | None = opts.pop("on_pre_tool_use", None)
|
|
364
368
|
on_function_approval: FunctionApprovalCallback | None = opts.pop("on_function_approval", None)
|
|
365
369
|
base_directory = opts.pop("base_directory", None)
|
|
@@ -397,11 +401,9 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
397
401
|
self._permission_handler = on_permission_request
|
|
398
402
|
self._on_pre_tool_use: PreToolUseHandler | None = on_pre_tool_use
|
|
399
403
|
self._function_approval_handler: FunctionApprovalCallback | None = on_function_approval
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
self._skill_directories = skill_directories
|
|
404
|
-
self._disabled_skills = disabled_skills
|
|
404
|
+
# Remaining options (e.g. mcp_servers, provider, instruction_directories,
|
|
405
|
+
# skill_directories, disabled_skills, and any other create_session parameter)
|
|
406
|
+
# are forwarded verbatim to the Copilot SDK by _build_session_kwargs.
|
|
405
407
|
self._default_options = opts
|
|
406
408
|
self._started = False
|
|
407
409
|
|
|
@@ -635,8 +637,11 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
635
637
|
parsed_usage_details = self._parse_usage_details_from_copilot(event.data)
|
|
636
638
|
if parsed_usage_details:
|
|
637
639
|
usage_details = add_usage_details(usage_details, parsed_usage_details)
|
|
638
|
-
|
|
639
|
-
|
|
640
|
+
event_finish_reason = (
|
|
641
|
+
"content_filter" if event.data.content_filter_triggered else event.data.finish_reason
|
|
642
|
+
)
|
|
643
|
+
if event_finish_reason:
|
|
644
|
+
finish_reason = event_finish_reason
|
|
640
645
|
if event.data.model:
|
|
641
646
|
model = event.data.model
|
|
642
647
|
else:
|
|
@@ -780,7 +785,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
780
785
|
)
|
|
781
786
|
return
|
|
782
787
|
usage_details = self._parse_usage_details_from_copilot(event.data)
|
|
783
|
-
finish_reason = event.data.
|
|
788
|
+
finish_reason = "content_filter" if event.data.content_filter_triggered else event.data.finish_reason
|
|
784
789
|
model = event.data.model or None
|
|
785
790
|
if usage_details or finish_reason or model:
|
|
786
791
|
update = AgentResponseUpdate(
|
|
@@ -999,7 +1004,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
999
1004
|
def _build_session_hooks(
|
|
1000
1005
|
self,
|
|
1001
1006
|
all_tools: Sequence[ToolTypes | CopilotTool],
|
|
1002
|
-
|
|
1007
|
+
options: Mapping[str, Any],
|
|
1003
1008
|
) -> SessionHooks | None:
|
|
1004
1009
|
"""Build the ``SessionHooks`` to pass to the Copilot SDK for this session.
|
|
1005
1010
|
|
|
@@ -1007,11 +1012,14 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1007
1012
|
``approval_mode="always_require"`` is delegated to the Copilot SDK's native
|
|
1008
1013
|
``on_pre_tool_use`` hook:
|
|
1009
1014
|
|
|
1010
|
-
- If the caller supplies their own
|
|
1011
|
-
|
|
1015
|
+
- If the caller supplies their own session hooks -- either the SDK-native
|
|
1016
|
+
``hooks`` dict or the convenience ``on_pre_tool_use`` handler (via per-run
|
|
1017
|
+
``options`` or ``default_options``) -- those take precedence and are used
|
|
1018
|
+
as-is. When both are given, the explicit ``hooks`` dict wins for any key it
|
|
1019
|
+
defines and the ``on_pre_tool_use`` shortcut fills in that key otherwise. A
|
|
1012
1020
|
warning is logged naming any approval-required tool that will therefore not
|
|
1013
|
-
be automatically gated, since the caller's
|
|
1014
|
-
approval.
|
|
1021
|
+
be automatically gated, since the caller's hooks are responsible for
|
|
1022
|
+
enforcing approval.
|
|
1015
1023
|
- Otherwise, when any approval-required tool is present, a default hook is
|
|
1016
1024
|
installed that returns ``"ask"`` for those tools (routing the decision to
|
|
1017
1025
|
``on_permission_request``) and defers (``None``) for all other tools.
|
|
@@ -1019,32 +1027,43 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1019
1027
|
``on_function_approval`` callback is configured: in that case approval is
|
|
1020
1028
|
enforced inside the tool handler (see :meth:`_tool_to_copilot_tool`) to
|
|
1021
1029
|
preserve backward-compatible behavior.
|
|
1022
|
-
- When there are no approval-required tools and no caller
|
|
1030
|
+
- When there are no approval-required tools and no caller hooks, ``None`` is
|
|
1023
1031
|
returned so no hooks are registered.
|
|
1024
1032
|
|
|
1025
1033
|
Args:
|
|
1026
1034
|
all_tools: The full set of tools resolved for the session.
|
|
1027
|
-
|
|
1035
|
+
options: The merged session options (``default_options`` overlaid with
|
|
1036
|
+
per-run ``options``).
|
|
1028
1037
|
|
|
1029
1038
|
Returns:
|
|
1030
1039
|
The hooks to register for the session, or ``None`` if none are needed.
|
|
1031
1040
|
"""
|
|
1032
|
-
user_hook: PreToolUseHandler | None =
|
|
1041
|
+
user_hook: PreToolUseHandler | None = options.get("on_pre_tool_use") or self._on_pre_tool_use
|
|
1042
|
+
caller_hooks: Mapping[str, Any] | None = options.get("hooks")
|
|
1043
|
+
|
|
1044
|
+
# Combine caller-provided hooks: the SDK-native ``hooks`` dict plus the
|
|
1045
|
+
# convenience ``on_pre_tool_use`` shortcut. The explicit dict wins for the
|
|
1046
|
+
# keys it defines; the shortcut only fills in ``on_pre_tool_use`` otherwise.
|
|
1047
|
+
combined: dict[str, Any] = {}
|
|
1048
|
+
if user_hook is not None:
|
|
1049
|
+
combined["on_pre_tool_use"] = user_hook
|
|
1050
|
+
if caller_hooks:
|
|
1051
|
+
combined.update(caller_hooks)
|
|
1033
1052
|
|
|
1034
1053
|
approval_required_names = {
|
|
1035
1054
|
tool.name for tool in all_tools if isinstance(tool, FunctionTool) and tool.approval_mode == "always_require"
|
|
1036
1055
|
}
|
|
1037
1056
|
|
|
1038
|
-
if
|
|
1057
|
+
if combined:
|
|
1039
1058
|
if approval_required_names:
|
|
1040
1059
|
logger.warning(
|
|
1041
|
-
"
|
|
1042
|
-
"will not be automatically gated by GitHubCopilotAgent. The custom
|
|
1060
|
+
"Custom session hooks are configured, so %d approval-required tool(s) (%s) "
|
|
1061
|
+
"will not be automatically gated by GitHubCopilotAgent. The custom hooks are responsible "
|
|
1043
1062
|
"for enforcing approval (for example, by returning a 'deny' or 'ask' decision).",
|
|
1044
1063
|
len(approval_required_names),
|
|
1045
1064
|
", ".join(sorted(approval_required_names)),
|
|
1046
1065
|
)
|
|
1047
|
-
return
|
|
1066
|
+
return cast("SessionHooks", combined)
|
|
1048
1067
|
|
|
1049
1068
|
if not approval_required_names:
|
|
1050
1069
|
return None
|
|
@@ -1107,6 +1126,57 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1107
1126
|
except Exception as ex:
|
|
1108
1127
|
raise AgentException(f"Failed to create GitHub Copilot session: {ex}") from ex
|
|
1109
1128
|
|
|
1129
|
+
def _build_session_kwargs(
|
|
1130
|
+
self,
|
|
1131
|
+
streaming: bool,
|
|
1132
|
+
runtime_options: dict[str, Any] | None,
|
|
1133
|
+
) -> dict[str, Any]:
|
|
1134
|
+
"""Assemble keyword arguments for ``create_session`` / ``resume_session``.
|
|
1135
|
+
|
|
1136
|
+
Options are layered: the agent's ``default_options`` first, then per-run
|
|
1137
|
+
``runtime_options`` which override them. Every key is forwarded verbatim to
|
|
1138
|
+
the Copilot SDK, so any ``create_session`` parameter is supported without a
|
|
1139
|
+
dedicated mapping here (an unknown name surfaces as a ``TypeError`` from the
|
|
1140
|
+
SDK). A few keys are handled specially because they need a secure default
|
|
1141
|
+
(``on_permission_request`` defaults to denying all requests) or transforming:
|
|
1142
|
+
``tools`` are merged with the agent's tools and converted to SDK tools, and
|
|
1143
|
+
approval callbacks are turned into ``hooks``.
|
|
1144
|
+
|
|
1145
|
+
Args:
|
|
1146
|
+
streaming: Whether to enable streaming for the session.
|
|
1147
|
+
runtime_options: Runtime options that take precedence over default_options.
|
|
1148
|
+
|
|
1149
|
+
Returns:
|
|
1150
|
+
The keyword arguments to splat into the SDK session factory.
|
|
1151
|
+
"""
|
|
1152
|
+
opts = runtime_options or {}
|
|
1153
|
+
|
|
1154
|
+
# Passthrough layer: agent defaults first, per-run options override.
|
|
1155
|
+
kwargs: dict[str, Any] = {**self._default_options, **opts}
|
|
1156
|
+
|
|
1157
|
+
# Merge agent-level tools with any caller-supplied tools (from default_options
|
|
1158
|
+
# or per-run options, the latter winning) and convert to SDK tools.
|
|
1159
|
+
all_tools = list(self._tools or []) + list(kwargs.get("tools") or [])
|
|
1160
|
+
kwargs["tools"] = self._prepare_tools(all_tools) if all_tools else None
|
|
1161
|
+
|
|
1162
|
+
kwargs["streaming"] = streaming
|
|
1163
|
+
# model may already be present from per-run options (merged above); otherwise fall
|
|
1164
|
+
# back to the resolved setting (which carries the default_options / env model).
|
|
1165
|
+
if not kwargs.get("model"):
|
|
1166
|
+
kwargs["model"] = self._settings.get("model") or None
|
|
1167
|
+
kwargs["on_permission_request"] = (
|
|
1168
|
+
opts.get("on_permission_request") or self._permission_handler or _deny_all_permissions
|
|
1169
|
+
)
|
|
1170
|
+
kwargs["hooks"] = self._build_session_hooks(all_tools, kwargs)
|
|
1171
|
+
|
|
1172
|
+
# Strip agent-internal and client-level keys that are consumed here or in the
|
|
1173
|
+
# run methods (and settings) but are NOT valid create_session parameters, so
|
|
1174
|
+
# they don't leak through the passthrough layer and raise TypeError.
|
|
1175
|
+
for key in ("on_pre_tool_use", "on_function_approval", "timeout", "cli_path", "log_level", "base_directory"):
|
|
1176
|
+
kwargs.pop(key, None)
|
|
1177
|
+
|
|
1178
|
+
return kwargs
|
|
1179
|
+
|
|
1110
1180
|
async def _create_session(
|
|
1111
1181
|
self,
|
|
1112
1182
|
streaming: bool,
|
|
@@ -1121,34 +1191,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1121
1191
|
if not self._client:
|
|
1122
1192
|
raise RuntimeError("GitHub Copilot client not initialized. Call start() first.")
|
|
1123
1193
|
|
|
1124
|
-
|
|
1125
|
-
model = opts.get("model") or self._settings.get("model") or None
|
|
1126
|
-
system_message = opts.get("system_message") or self._default_options.get("system_message") or None
|
|
1127
|
-
permission_handler: PermissionHandlerType = (
|
|
1128
|
-
opts.get("on_permission_request") or self._permission_handler or _deny_all_permissions
|
|
1129
|
-
)
|
|
1130
|
-
mcp_servers = opts.get("mcp_servers") or self._mcp_servers or None
|
|
1131
|
-
provider = opts.get("provider") or self._provider or None
|
|
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)
|
|
1135
|
-
all_tools = list(self._tools or []) + list(opts.get("tools") or [])
|
|
1136
|
-
tools = self._prepare_tools(all_tools) if all_tools else None
|
|
1137
|
-
hooks = self._build_session_hooks(all_tools, opts)
|
|
1138
|
-
|
|
1139
|
-
return await self._client.create_session(
|
|
1140
|
-
on_permission_request=permission_handler,
|
|
1141
|
-
streaming=streaming,
|
|
1142
|
-
model=model or None,
|
|
1143
|
-
system_message=system_message or None,
|
|
1144
|
-
tools=tools or None,
|
|
1145
|
-
mcp_servers=mcp_servers or None,
|
|
1146
|
-
provider=provider or None,
|
|
1147
|
-
instruction_directories=instruction_directories,
|
|
1148
|
-
skill_directories=skill_directories,
|
|
1149
|
-
disabled_skills=disabled_skills,
|
|
1150
|
-
hooks=hooks,
|
|
1151
|
-
)
|
|
1194
|
+
return await self._client.create_session(**self._build_session_kwargs(streaming, runtime_options))
|
|
1152
1195
|
|
|
1153
1196
|
async def _resume_session(
|
|
1154
1197
|
self,
|
|
@@ -1166,35 +1209,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
|
|
|
1166
1209
|
if not self._client:
|
|
1167
1210
|
raise RuntimeError("GitHub Copilot client not initialized. Call start() first.")
|
|
1168
1211
|
|
|
1169
|
-
|
|
1170
|
-
model = opts.get("model") or self._settings.get("model") or None
|
|
1171
|
-
system_message = opts.get("system_message") or self._default_options.get("system_message") or None
|
|
1172
|
-
permission_handler: PermissionHandlerType = (
|
|
1173
|
-
opts.get("on_permission_request") or self._permission_handler or _deny_all_permissions
|
|
1174
|
-
)
|
|
1175
|
-
mcp_servers = opts.get("mcp_servers") or self._mcp_servers or None
|
|
1176
|
-
provider = opts.get("provider") or self._provider or None
|
|
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)
|
|
1180
|
-
all_tools = list(self._tools or []) + list(opts.get("tools") or [])
|
|
1181
|
-
tools = self._prepare_tools(all_tools) if all_tools else None
|
|
1182
|
-
hooks = self._build_session_hooks(all_tools, opts)
|
|
1183
|
-
|
|
1184
|
-
return await self._client.resume_session(
|
|
1185
|
-
session_id,
|
|
1186
|
-
on_permission_request=permission_handler,
|
|
1187
|
-
streaming=streaming,
|
|
1188
|
-
model=model or None,
|
|
1189
|
-
system_message=system_message or None,
|
|
1190
|
-
tools=tools or None,
|
|
1191
|
-
mcp_servers=mcp_servers or None,
|
|
1192
|
-
provider=provider or None,
|
|
1193
|
-
instruction_directories=instruction_directories,
|
|
1194
|
-
skill_directories=skill_directories,
|
|
1195
|
-
disabled_skills=disabled_skills,
|
|
1196
|
-
hooks=hooks,
|
|
1197
|
-
)
|
|
1212
|
+
return await self._client.resume_session(session_id, **self._build_session_kwargs(streaming, runtime_options))
|
|
1198
1213
|
|
|
1199
1214
|
|
|
1200
1215
|
class GitHubCopilotAgent( # type: ignore[misc]
|
{agent_framework_github_copilot-1.0.0rc3 → agent_framework_github_copilot-1.0.0rc4}/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.0rc4"
|
|
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
|
{agent_framework_github_copilot-1.0.0rc3 → agent_framework_github_copilot-1.0.0rc4}/README.md
RENAMED
|
File without changes
|