mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Upgrade github-copilot-sdk to v1.0.0 (stable) (#6292)
* Python: Upgrade github-copilot-sdk to v1.0.0 (stable) Upgrade agent-framework-github-copilot from github-copilot-sdk 1.0.0b2 to the stable 1.0.0 release, adapting to all breaking API changes. Source changes (_agent.py): - SubprocessConfig removed: use RuntimeConnection.for_stdio(path=...) + CopilotClient kwargs (connection, log_level, base_directory) - Import paths: copilot.generated.session_events -> copilot.session_events - Settings: copilot_home -> base_directory (env GITHUB_COPILOT_BASE_DIRECTORY) - Default deny handler: PermissionDecisionUserNotAvailable() (from copilot.generated.rpc) Test changes: - Updated imports and client-construction assertions (kwargs-based) - Permission handler tests use concrete decision types (PermissionDecisionApproveOnce, PermissionDecisionDeniedInteractivelyByUser) Sample changes: - Permission handlers use PermissionHandler.approve_all or sync approve_and_log pattern (v1.0.0 protocol v3 dispatch is incompatible with blocking input() in permission handlers) - Function approval sample uses asyncio.to_thread for interactive prompts - Simplified imports across all samples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: scope permission handlers, widen type, add test - Shell sample: only approve kind='shell', deny others - URL sample: only approve kind='url', deny others - Use getattr() for kind-specific attributes to satisfy pyright - Widen PermissionHandlerType to accept async handlers (matches SDK) - Add test for _deny_all_permissions return value Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix validation script and strengthen test assertion - Update scripts/sample_validation/create_dynamic_workflow_executor.py to use copilot.session_events imports and PermissionHandler.approve_all - Assert isinstance(result, PermissionDecisionUserNotAvailable) instead of stringly-typed kind check Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add integration tests for GitHubCopilotAgent Add 6 integration tests mirroring .NET coverage: - Basic non-streaming response - Streaming response - Function tool invocation - Session context (multi-turn) - Session resume by ID - Shell command execution Tests require COPILOT_GITHUB_TOKEN env var (skipped otherwise). Each test cleans up its Copilot session via delete_session. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
f970a699d8
commit
fe08574a7c
@@ -23,7 +23,7 @@ The following environment variables can be configured:
|
||||
| `GITHUB_COPILOT_MODEL` | Model to use (e.g., "gpt-5", "claude-sonnet-4") | Server default |
|
||||
| `GITHUB_COPILOT_TIMEOUT` | Request timeout in seconds | `60` |
|
||||
| `GITHUB_COPILOT_LOG_LEVEL` | CLI log level | `info` |
|
||||
| `GITHUB_COPILOT_COPILOT_HOME` | Directory for CLI session state and config | `~/.copilot` |
|
||||
| `GITHUB_COPILOT_BASE_DIRECTORY` | Directory for CLI session state and config | `~/.copilot` |
|
||||
|
||||
## Observability
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@ from typing import Annotated
|
||||
|
||||
from agent_framework import tool
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import PermissionRequestResult
|
||||
from copilot.session import PermissionHandler
|
||||
from dotenv import load_dotenv
|
||||
from pydantic import Field
|
||||
|
||||
@@ -28,19 +27,6 @@ from pydantic import Field
|
||||
load_dotenv()
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
if request.full_command_text is not None:
|
||||
print(f" Command: {request.full_command_text}")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
|
||||
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
|
||||
# see samples/02-agents/tools/function_tool_with_approval.py
|
||||
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
|
||||
@@ -60,7 +46,7 @@ async def non_streaming_example() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=[get_weather],
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
@@ -77,7 +63,7 @@ async def streaming_example() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=[get_weather],
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
@@ -97,7 +83,7 @@ async def runtime_options_example() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="Always respond in exactly 3 words.",
|
||||
tools=[get_weather],
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
|
||||
+8
-12
@@ -4,8 +4,7 @@
|
||||
GitHub Copilot Agent with File Operation Permissions
|
||||
|
||||
This sample demonstrates how to enable file read and write operations with GitHubCopilotAgent.
|
||||
By providing a permission handler that approves "read" and/or "write" requests, the agent can
|
||||
read from and write to files on the filesystem.
|
||||
By providing a permission handler, the agent can read from and write to files on the filesystem.
|
||||
|
||||
SECURITY NOTE: Only enable file permissions when you trust the agent's actions.
|
||||
- "read" allows the agent to read any accessible file
|
||||
@@ -15,21 +14,18 @@ SECURITY NOTE: Only enable file permissions when you trust the agent's actions.
|
||||
import asyncio
|
||||
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import PermissionRequestResult
|
||||
from copilot.generated.rpc import PermissionDecisionDeniedInteractivelyByUser
|
||||
from copilot.session import PermissionHandler, PermissionRequestResult
|
||||
from copilot.session_events import PermissionRequest
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
async def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
if request.path is not None:
|
||||
print(f" Path: {request.path}")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
response = (await asyncio.to_thread(input, "Approve? (y/n): ")).strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
return PermissionHandler.approve_all(request, context)
|
||||
return PermissionDecisionDeniedInteractivelyByUser()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
|
||||
+31
-20
@@ -32,6 +32,7 @@ from typing import Annotated
|
||||
|
||||
from agent_framework import Content, tool
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.session import PermissionHandler
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
@@ -48,37 +49,42 @@ def get_weather_detail(location: Annotated[str, "The city and state, e.g. San Fr
|
||||
)
|
||||
|
||||
|
||||
def prompt_for_approval(call: Content) -> bool:
|
||||
"""Synchronous approval prompt.
|
||||
async def prompt_for_approval(call: Content) -> bool:
|
||||
"""Async approval callback that prompts the user interactively.
|
||||
|
||||
The callback receives a ``FunctionCallContent`` so the operator can review
|
||||
the tool name and arguments before deciding. Returning ``True`` allows the
|
||||
call; returning ``False`` denies it and a tool-error is returned to the
|
||||
model.
|
||||
|
||||
Uses ``asyncio.to_thread`` so the event loop is not blocked by ``input()``.
|
||||
"""
|
||||
print(f"\n[Function Approval Request]\n Tool: {call.name}\n Arguments: {call.arguments}")
|
||||
response = input("Approve this tool call? (y/n): ").strip().lower()
|
||||
print(f"\n [Function Approval Request]\n Tool: {call.name}\n Arguments: {call.arguments}")
|
||||
response = (await asyncio.to_thread(input, " Approve this tool call? (y/n): ")).strip().lower()
|
||||
return response in ("y", "yes")
|
||||
|
||||
|
||||
async def prompt_for_approval_async(call: Content) -> bool:
|
||||
"""Async approval prompt.
|
||||
def auto_approve(call: Content) -> bool:
|
||||
"""Synchronous approval callback that always approves.
|
||||
|
||||
Use an async callback when approval requires I/O (e.g. an HTTP call to a
|
||||
review service or queueing the request to a UI). ``input()`` is wrapped
|
||||
with ``asyncio.to_thread`` so the event loop is not blocked.
|
||||
Use a sync callback for simple, non-blocking decisions that don't require
|
||||
I/O (e.g. checking an allow-list of tool names).
|
||||
"""
|
||||
print(f"\n[Function Approval Request - async]\n Tool: {call.name}\n Arguments: {call.arguments}")
|
||||
response = await asyncio.to_thread(input, "Approve this tool call? (y/n): ")
|
||||
return response.strip().lower() in ("y", "yes")
|
||||
print(f"\n [Function Approval Request]\n Tool: {call.name}\n Arguments: {call.arguments}")
|
||||
print(" -> Auto-approved")
|
||||
return True
|
||||
|
||||
|
||||
async def run_with_sync_callback() -> None:
|
||||
print("\n=== GitHub Copilot Agent: synchronous approval callback ===")
|
||||
async def run_with_interactive_callback() -> None:
|
||||
"""Demonstrates an interactive approval prompt before tool execution."""
|
||||
print("\n=== GitHub Copilot Agent: interactive approval callback ===")
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather assistant.",
|
||||
tools=[get_weather_detail],
|
||||
default_options={"on_function_approval": prompt_for_approval},
|
||||
default_options={
|
||||
"on_function_approval": prompt_for_approval,
|
||||
"on_permission_request": PermissionHandler.approve_all,
|
||||
},
|
||||
)
|
||||
async with agent:
|
||||
query = "Give me the detailed weather for Seattle."
|
||||
@@ -87,12 +93,16 @@ async def run_with_sync_callback() -> None:
|
||||
print(f"Agent: {result}")
|
||||
|
||||
|
||||
async def run_with_async_callback() -> None:
|
||||
print("\n=== GitHub Copilot Agent: asynchronous approval callback ===")
|
||||
async def run_with_auto_approve_callback() -> None:
|
||||
"""Demonstrates a synchronous callback that always approves."""
|
||||
print("\n=== GitHub Copilot Agent: synchronous auto-approve callback ===")
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather assistant.",
|
||||
tools=[get_weather_detail],
|
||||
default_options={"on_function_approval": prompt_for_approval_async},
|
||||
default_options={
|
||||
"on_function_approval": auto_approve,
|
||||
"on_permission_request": PermissionHandler.approve_all,
|
||||
},
|
||||
)
|
||||
async with agent:
|
||||
query = "Give me the detailed weather for Tokyo."
|
||||
@@ -112,6 +122,7 @@ async def run_without_callback() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather assistant.",
|
||||
tools=[get_weather_detail],
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
async with agent:
|
||||
query = "Give me the detailed weather for Paris."
|
||||
@@ -122,8 +133,8 @@ async def run_without_callback() -> None:
|
||||
|
||||
async def main() -> None:
|
||||
print("=== GitHub Copilot Agent: Function approval enforcement ===")
|
||||
await run_with_sync_callback()
|
||||
await run_with_async_callback()
|
||||
await run_with_interactive_callback()
|
||||
await run_with_auto_approve_callback()
|
||||
await run_without_callback()
|
||||
|
||||
|
||||
|
||||
+3
-14
@@ -22,24 +22,13 @@ import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import PermissionRequestResult
|
||||
from copilot.session import PermissionHandler
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
|
||||
|
||||
async def default_instructions_example() -> None:
|
||||
"""Example of pointing the agent at project-specific instruction directories."""
|
||||
print("=== Instruction Directories (Default) ===\n")
|
||||
@@ -58,7 +47,7 @@ async def default_instructions_example() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful coding assistant.",
|
||||
default_options={
|
||||
"on_permission_request": prompt_permission,
|
||||
"on_permission_request": PermissionHandler.approve_all,
|
||||
"instruction_directories": instruction_dirs,
|
||||
},
|
||||
)
|
||||
@@ -79,7 +68,7 @@ async def runtime_override_example() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful assistant.",
|
||||
default_options={
|
||||
"on_permission_request": prompt_permission,
|
||||
"on_permission_request": PermissionHandler.approve_all,
|
||||
"instruction_directories": ["/team/shared/instructions"],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -15,24 +15,13 @@ of MCP-related actions.
|
||||
import asyncio
|
||||
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import MCPServerConfig, PermissionRequestResult
|
||||
from copilot.session import MCPServerConfig, PermissionHandler
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== GitHub Copilot Agent with MCP Servers ===\n")
|
||||
|
||||
@@ -56,7 +45,7 @@ async def main() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful assistant with access to the local filesystem and Microsoft Learn.",
|
||||
default_options={
|
||||
"on_permission_request": prompt_permission,
|
||||
"on_permission_request": PermissionHandler.approve_all,
|
||||
"mcp_servers": mcp_servers,
|
||||
},
|
||||
)
|
||||
|
||||
+11
-21
@@ -3,9 +3,8 @@
|
||||
"""
|
||||
GitHub Copilot Agent with Multiple Permissions
|
||||
|
||||
This sample demonstrates how to enable multiple permission types with GitHubCopilotAgent.
|
||||
By combining different permission kinds in the handler, the agent can perform complex tasks
|
||||
that require multiple capabilities.
|
||||
This sample demonstrates how multiple permission types are requested when GitHubCopilotAgent
|
||||
performs complex tasks that require different capabilities.
|
||||
|
||||
Available permission kinds:
|
||||
- "shell": Execute shell commands
|
||||
@@ -21,23 +20,14 @@ More permissions mean more potential for unintended actions.
|
||||
import asyncio
|
||||
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import PermissionRequestResult
|
||||
from copilot.session import PermissionHandler, PermissionRequestResult
|
||||
from copilot.session_events import PermissionRequest
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
if request.full_command_text is not None:
|
||||
print(f" Command: {request.full_command_text}")
|
||||
if request.path is not None:
|
||||
print(f" Path: {request.path}")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
def approve_and_log(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that auto-approves and logs each permission kind."""
|
||||
print(f" [Permission: {request.kind}]", flush=True)
|
||||
return PermissionHandler.approve_all(request, context)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
@@ -45,14 +35,14 @@ async def main() -> None:
|
||||
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful development assistant that can read, write files and run commands.",
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": approve_and_log},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
query = "List the first 3 Python files, then read the first one and create a summary in summary.txt"
|
||||
print(f"User: {query}")
|
||||
print(f"User: {query}\n")
|
||||
result = await agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
print(f"\nAgent: {result}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -14,24 +14,10 @@ from typing import Annotated
|
||||
|
||||
from agent_framework import tool
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import PermissionRequestResult
|
||||
from copilot.session import PermissionHandler
|
||||
from pydantic import Field
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
if request.full_command_text is not None:
|
||||
print(f" Command: {request.full_command_text}")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
|
||||
|
||||
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production;
|
||||
# see samples/02-agents/tools/function_tool_with_approval.py
|
||||
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
|
||||
@@ -51,7 +37,7 @@ async def example_with_automatic_session_creation() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=[get_weather],
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
@@ -76,7 +62,7 @@ async def example_with_session_persistence() -> None:
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=[get_weather],
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
@@ -113,7 +99,7 @@ async def example_with_existing_session_id() -> None:
|
||||
agent1 = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=[get_weather],
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
|
||||
async with agent1:
|
||||
@@ -135,7 +121,7 @@ async def example_with_existing_session_id() -> None:
|
||||
agent2 = GitHubCopilotAgent(
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=[get_weather],
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": PermissionHandler.approve_all},
|
||||
)
|
||||
|
||||
async with agent2:
|
||||
|
||||
@@ -14,21 +14,20 @@ Shell commands have full access to your system within the permissions of the run
|
||||
import asyncio
|
||||
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import PermissionRequestResult
|
||||
from copilot.generated.rpc import PermissionDecisionUserNotAvailable
|
||||
from copilot.session import PermissionHandler, PermissionRequestResult
|
||||
from copilot.session_events import PermissionRequest
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
if request.full_command_text is not None:
|
||||
print(f" Command: {request.full_command_text}")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
def approve_and_log(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that approves only shell commands and logs them."""
|
||||
if request.kind == "shell":
|
||||
print(f"\n [Permission: {request.kind}]", flush=True)
|
||||
command = getattr(request, "full_command_text", None)
|
||||
if command is not None:
|
||||
print(f" Command: {command}", flush=True)
|
||||
return PermissionHandler.approve_all(request, context)
|
||||
return PermissionDecisionUserNotAvailable()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
@@ -36,14 +35,14 @@ async def main() -> None:
|
||||
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful assistant that can execute shell commands.",
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": approve_and_log},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
query = "List the first 3 Python files in the current directory"
|
||||
print(f"User: {query}")
|
||||
result = await agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
print(f"\nAgent: {result}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -14,21 +14,20 @@ URL fetching allows the agent to access any URL accessible from your network.
|
||||
import asyncio
|
||||
|
||||
from agent_framework.github import GitHubCopilotAgent
|
||||
from copilot.generated.session_events import PermissionRequest
|
||||
from copilot.session import PermissionRequestResult
|
||||
from copilot.generated.rpc import PermissionDecisionUserNotAvailable
|
||||
from copilot.session import PermissionHandler, PermissionRequestResult
|
||||
from copilot.session_events import PermissionRequest
|
||||
|
||||
|
||||
def prompt_permission(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that prompts the user for approval."""
|
||||
print(f"\n[Permission Request: {request.kind}]")
|
||||
|
||||
if request.url is not None:
|
||||
print(f" URL: {request.url}")
|
||||
|
||||
response = input("Approve? (y/n): ").strip().lower()
|
||||
if response in ("y", "yes"):
|
||||
return PermissionRequestResult(kind="approved")
|
||||
return PermissionRequestResult(kind="denied-interactively-by-user")
|
||||
def approve_and_log(request: PermissionRequest, context: dict[str, str]) -> PermissionRequestResult:
|
||||
"""Permission handler that approves only URL requests and logs them."""
|
||||
if request.kind == "url":
|
||||
print(f"\n [Permission: {request.kind}]", flush=True)
|
||||
url = getattr(request, "url", None)
|
||||
if url is not None:
|
||||
print(f" URL: {url}", flush=True)
|
||||
return PermissionHandler.approve_all(request, context)
|
||||
return PermissionDecisionUserNotAvailable()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
@@ -36,14 +35,14 @@ async def main() -> None:
|
||||
|
||||
agent = GitHubCopilotAgent(
|
||||
instructions="You are a helpful assistant that can fetch and summarize web content.",
|
||||
default_options={"on_permission_request": prompt_permission},
|
||||
default_options={"on_permission_request": approve_and_log},
|
||||
)
|
||||
|
||||
async with agent:
|
||||
query = "Fetch https://learn.microsoft.com/agent-framework/tutorials/quick-start and summarize its contents"
|
||||
print(f"User: {query}")
|
||||
result = await agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
print(f"\nAgent: {result}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user