Moving the copilot-sdk cookbook content in here

This commit is contained in:
Aaron Powell
2026-01-29 14:29:36 +11:00
parent ccdfd66cc2
commit f59e0b4080
53 changed files with 5385 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
# Runnable Recipe Examples
This folder contains standalone, executable Python examples for each cookbook recipe. Each file can be run directly as a Python script.
## Prerequisites
- Python 3.8 or later
- Install dependencies (this installs the local SDK in editable mode):
```bash
pip install -r requirements.txt
```
## Running Examples
Each `.py` file is a complete, runnable program with executable permissions:
```bash
python <filename>.py
# or on Unix-like systems:
./<filename>.py
```
### Available Recipes
| Recipe | Command | Description |
| -------------------- | -------------------------------- | ------------------------------------------ |
| Error Handling | `python error_handling.py` | Demonstrates error handling patterns |
| Multiple Sessions | `python multiple_sessions.py` | Manages multiple independent conversations |
| Managing Local Files | `python managing_local_files.py` | Organizes files using AI grouping |
| PR Visualization | `python pr_visualization.py` | Generates PR age charts |
| Persisting Sessions | `python persisting_sessions.py` | Save and resume sessions across restarts |
### Examples with Arguments
**PR Visualization with specific repo:**
```bash
python pr_visualization.py --repo github/copilot-sdk
```
**Managing Local Files (edit the file to change target folder):**
```bash
# Edit the target_folder variable in managing_local_files.py first
python managing_local_files.py
```
## Local SDK Development
The `requirements.txt` installs the local Copilot SDK using `-e ../..` (editable install). This means:
- Changes to the SDK source are immediately available
- No need to publish or install from PyPI
- Perfect for testing and development
If you modify the SDK source, Python will automatically use the updated code (no rebuild needed).
## Python Best Practices
These examples follow Python conventions:
- PEP 8 naming (snake_case for functions and variables)
- Shebang line for direct execution
- Proper exception handling
- Type hints where appropriate
- Standard library usage
## Virtual Environment (Recommended)
For isolated development:
```bash
# Create virtual environment
python -m venv venv
# Activate it
# Windows:
venv\Scripts\activate
# Unix/macOS:
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
```
## Learning Resources
- [Python Documentation](https://docs.python.org/3/)
- [PEP 8 Style Guide](https://pep8.org/)
- [GitHub Copilot SDK for Python](https://github.com/github/copilot-sdk/blob/main/python/README.md)
- [Parent Cookbook](../README.md)

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env python3
from copilot import CopilotClient
client = CopilotClient()
try:
client.start()
session = client.create_session(model="gpt-5")
response = None
def handle_message(event):
nonlocal response
if event["type"] == "assistant.message":
response = event["data"]["content"]
session.on(handle_message)
session.send(prompt="Hello!")
session.wait_for_idle()
if response:
print(response)
session.destroy()
except Exception as e:
print(f"Error: {e}")
finally:
client.stop()

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env python3
from copilot import CopilotClient
import os
# Create and start client
client = CopilotClient()
client.start()
# Create session
session = client.create_session(model="gpt-5")
# Event handler
def handle_event(event):
if event["type"] == "assistant.message":
print(f"\nCopilot: {event['data']['content']}")
elif event["type"] == "tool.execution_start":
print(f" → Running: {event['data']['toolName']}")
elif event["type"] == "tool.execution_complete":
print(f" ✓ Completed: {event['data']['toolCallId']}")
session.on(handle_event)
# Ask Copilot to organize files
# Change this to your target folder
target_folder = os.path.expanduser("~/Downloads")
session.send(prompt=f"""
Analyze the files in "{target_folder}" and organize them into subfolders.
1. First, list all files and their metadata
2. Preview grouping by file extension
3. Create appropriate subfolders (e.g., "images", "documents", "videos")
4. Move each file to its appropriate subfolder
Please confirm before moving any files.
""")
session.wait_for_idle()
session.destroy()
client.stop()

View File

@@ -0,0 +1,35 @@
#!/usr/bin/env python3
from copilot import CopilotClient
client = CopilotClient()
client.start()
# Create multiple independent sessions
session1 = client.create_session(model="gpt-5")
session2 = client.create_session(model="gpt-5")
session3 = client.create_session(model="claude-sonnet-4.5")
print("Created 3 independent sessions")
# Each session maintains its own conversation history
session1.send(prompt="You are helping with a Python project")
session2.send(prompt="You are helping with a TypeScript project")
session3.send(prompt="You are helping with a Go project")
print("Sent initial context to all sessions")
# Follow-up messages stay in their respective contexts
session1.send(prompt="How do I create a virtual environment?")
session2.send(prompt="How do I set up tsconfig?")
session3.send(prompt="How do I initialize a module?")
print("Sent follow-up questions to each session")
# Clean up all sessions
session1.destroy()
session2.destroy()
session3.destroy()
client.stop()
print("All sessions destroyed successfully")

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env python3
from copilot import CopilotClient
client = CopilotClient()
client.start()
# Create session with a memorable ID
session = client.create_session(
session_id="user-123-conversation",
model="gpt-5",
)
session.send(prompt="Let's discuss TypeScript generics")
print(f"Session created: {session.session_id}")
# Destroy session but keep data on disk
session.destroy()
print("Session destroyed (state persisted)")
# Resume the previous session
resumed = client.resume_session("user-123-conversation")
print(f"Resumed: {resumed.session_id}")
resumed.send(prompt="What were we discussing?")
# List sessions
sessions = client.list_sessions()
print("Sessions:", [s["sessionId"] for s in sessions])
# Delete session permanently
client.delete_session("user-123-conversation")
print("Session deleted")
resumed.destroy()
client.stop()

View File

@@ -0,0 +1,161 @@
#!/usr/bin/env python3
import subprocess
import sys
import os
import re
from copilot import CopilotClient
# ============================================================================
# Git & GitHub Detection
# ============================================================================
def is_git_repo():
try:
subprocess.run(
["git", "rev-parse", "--git-dir"],
check=True,
capture_output=True
)
return True
except (subprocess.CalledProcessError, FileNotFoundError):
return False
def get_github_remote():
try:
result = subprocess.run(
["git", "remote", "get-url", "origin"],
check=True,
capture_output=True,
text=True
)
remote_url = result.stdout.strip()
# Handle SSH: git@github.com:owner/repo.git
ssh_match = re.search(r"git@github\.com:(.+/.+?)(?:\.git)?$", remote_url)
if ssh_match:
return ssh_match.group(1)
# Handle HTTPS: https://github.com/owner/repo.git
https_match = re.search(r"https://github\.com/(.+/.+?)(?:\.git)?$", remote_url)
if https_match:
return https_match.group(1)
return None
except (subprocess.CalledProcessError, FileNotFoundError):
return None
def parse_args():
args = sys.argv[1:]
if "--repo" in args:
idx = args.index("--repo")
if idx + 1 < len(args):
return {"repo": args[idx + 1]}
return {}
def prompt_for_repo():
return input("Enter GitHub repo (owner/repo): ").strip()
# ============================================================================
# Main Application
# ============================================================================
def main():
print("🔍 PR Age Chart Generator\n")
# Determine the repository
args = parse_args()
repo = None
if "repo" in args:
repo = args["repo"]
print(f"📦 Using specified repo: {repo}")
elif is_git_repo():
detected = get_github_remote()
if detected:
repo = detected
print(f"📦 Detected GitHub repo: {repo}")
else:
print("⚠️ Git repo found but no GitHub remote detected.")
repo = prompt_for_repo()
else:
print("📁 Not in a git repository.")
repo = prompt_for_repo()
if not repo or "/" not in repo:
print("❌ Invalid repo format. Expected: owner/repo")
sys.exit(1)
owner, repo_name = repo.split("/", 1)
# Create Copilot client - no custom tools needed!
client = CopilotClient(log_level="error")
client.start()
session = client.create_session(
model="gpt-5",
system_message={
"content": f"""
<context>
You are analyzing pull requests for the GitHub repository: {owner}/{repo_name}
The current working directory is: {os.getcwd()}
</context>
<instructions>
- Use the GitHub MCP Server tools to fetch PR data
- Use your file and code execution tools to generate charts
- Save any generated images to the current working directory
- Be concise in your responses
</instructions>
"""
}
)
# Set up event handling
def handle_event(event):
if event["type"] == "assistant.message":
print(f"\n🤖 {event['data']['content']}\n")
elif event["type"] == "tool.execution_start":
print(f" ⚙️ {event['data']['toolName']}")
session.on(handle_event)
# Initial prompt - let Copilot figure out the details
print("\n📊 Starting analysis...\n")
session.send(prompt=f"""
Fetch the open pull requests for {owner}/{repo_name} from the last week.
Calculate the age of each PR in days.
Then generate a bar chart image showing the distribution of PR ages
(group them into sensible buckets like <1 day, 1-3 days, etc.).
Save the chart as "pr-age-chart.png" in the current directory.
Finally, summarize the PR health - average age, oldest PR, and how many might be considered stale.
""")
session.wait_for_idle()
# Interactive loop
print("\n💡 Ask follow-up questions or type \"exit\" to quit.\n")
print("Examples:")
print(" - \"Expand to the last month\"")
print(" - \"Show me the 5 oldest PRs\"")
print(" - \"Generate a pie chart instead\"")
print(" - \"Group by author instead of age\"")
print()
while True:
user_input = input("You: ").strip()
if user_input.lower() in ["exit", "quit"]:
print("👋 Goodbye!")
break
if user_input:
session.send(prompt=user_input)
session.wait_for_idle()
session.destroy()
client.stop()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,2 @@
# Install the local Copilot SDK package in editable mode
github-copilot-sdk