Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 30 additions & 19 deletions cookbook/python/recipe/error_handling.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
#!/usr/bin/env python3

import asyncio
from copilot import CopilotClient
from copilot.generated.session_events import SessionEventType

client = CopilotClient()
async def main():
client = CopilotClient()

try:
client.start()
session = client.create_session(model="gpt-5")
try:
await client.start()
# Ensure model is passed as part of a dict
session = await client.create_session({"model": "gpt-5"})

response = None
def handle_message(event):
nonlocal response
if event["type"] == "assistant.message":
response = event["data"]["content"]
# Using a list to allow modification inside inner function (closure workaround)
# or nonlocal would work if defined inside main
response_data = {"content": None}

session.on(handle_message)
session.send(prompt="Hello!")
session.wait_for_idle()
def handle_message(event):
if event.type == SessionEventType.ASSISTANT_MESSAGE:
response_data["content"] = event.data.content

if response:
print(response)
session.on(handle_message)

session.destroy()
except Exception as e:
print(f"Error: {e}")
finally:
client.stop()
# Use send_and_wait with timeout
await session.send_and_wait({"prompt": "Hello!"}, timeout=30)

if response_data["content"]:
print(f"Copilot: {response_data['content']}")

await session.destroy()

except Exception as e:
print(f"Error: {e}")
finally:
await client.stop()

if __name__ == "__main__":
asyncio.run(main())
79 changes: 50 additions & 29 deletions cookbook/python/recipe/managing_local_files.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,63 @@
#!/usr/bin/env python3

from copilot import CopilotClient
import asyncio
import os
from copilot import CopilotClient
from copilot.generated.session_events import SessionEventType

async def main():
# Create and start client
client = CopilotClient()
await client.start()

try:
# Create session
session = await client.create_session({"model": "gpt-5"})

# Event handler
def handle_event(event):
if event.type == SessionEventType.ASSISTANT_MESSAGE:
print(f"\nCopilot: {event.data.content}")
elif event.type == SessionEventType.TOOL_EXECUTION_START:
print(f" → Running: {event.data.tool_name}")
elif event.type == SessionEventType.TOOL_EXECUTION_COMPLETE:
# Check if tool_call_id exists in data
call_id = getattr(event.data, "tool_call_id", "unknown")
print(f" ✓ Completed: {call_id}")

session.on(handle_event)

# Create and start client
client = CopilotClient()
client.start()
# Ask Copilot to organize files
# Change this to your target folder
target_folder = os.path.expanduser("~/Downloads")

# Create session
session = client.create_session(model="gpt-5")
print(f"📂 Organizing files in: {target_folder}\n")

# 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']}")
await session.send_and_wait({
"prompt": f"""
Analyze the files in "{target_folder}" and organize them into subfolders.

session.on(handle_event)
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

# Ask Copilot to organize files
# Change this to your target folder
target_folder = os.path.expanduser("~/Downloads")
Please confirm before moving any files.
"""
}, timeout=300)

session.send(prompt=f"""
Analyze the files in "{target_folder}" and organize them into subfolders.
# Allow user to respond if Copilot asks for confirmation
while True:
user_input = await asyncio.get_event_loop().run_in_executor(None, input, "\nYou: ")
if user_input.lower() in ["exit", "quit", "no", "n"]:
break

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
await session.send_and_wait({"prompt": user_input}, timeout=300)

Please confirm before moving any files.
""")
await session.destroy()

session.wait_for_idle()
finally:
await client.stop()

session.destroy()
client.stop()
if __name__ == "__main__":
asyncio.run(main())
57 changes: 34 additions & 23 deletions cookbook/python/recipe/multiple_sessions.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,46 @@
#!/usr/bin/env python3

import asyncio
from copilot import CopilotClient

client = CopilotClient()
client.start()
async def main():
client = CopilotClient()
await 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")
try:
# Create multiple independent sessions with config dicts
# Use gpt-5 for the first two sessions, per the SDK's SessionConfig valid models.
session1 = await client.create_session({"model": "gpt-5"})
session2 = await client.create_session({"model": "gpt-5"})
# Use a valid Claude Sonnet model identifier as per SessionConfig type definition.
session3 = await client.create_session({"model": "claude-sonnet-4.5"})

print("Created 3 independent sessions")
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")
# Each session maintains its own conversation history
# We can run these in parallel or sequence. Sequence is easier to follow in logs.
await session1.send_and_wait({"prompt": "You are helping with a Python project"})
await session2.send_and_wait({"prompt": "You are helping with a TypeScript project"})
await session3.send_and_wait({"prompt": "You are helping with a Go project"})

print("Sent initial context to all sessions")
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?")
# Follow-up messages stay in their respective contexts
await session1.send_and_wait({"prompt": "How do I create a virtual environment?"})
await session2.send_and_wait({"prompt": "How do I set up tsconfig?"})
await session3.send_and_wait({"prompt": "How do I initialize a module?"})

print("Sent follow-up questions to each session")
print("Sent follow-up questions to each session")

# Clean up all sessions
session1.destroy()
session2.destroy()
session3.destroy()
client.stop()
# Clean up all sessions
await session1.destroy()
await session2.destroy()
await session3.destroy()

print("All sessions destroyed successfully")
print("All sessions destroyed successfully")

finally:
await client.stop()

if __name__ == "__main__":
asyncio.run(main())
62 changes: 38 additions & 24 deletions cookbook/python/recipe/persisting_sessions.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
#!/usr/bin/env python3

import asyncio
from copilot import CopilotClient

client = CopilotClient()
client.start()
async def main():
client = CopilotClient()
await client.start()

# Create session with a memorable ID
session = client.create_session(
session_id="user-123-conversation",
model="gpt-5",
)
try:
# Create session with a memorable ID
# Note: the SDK might generate the ID, or we pass it in config if supported
# Looking at client.py, create_session takes config which can have session_id
session = await 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}")
await session.send_and_wait({"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)")
# Destroy session but keep data on disk?
# Actually session.destroy() releases resources in the client but also sends 'session.destroy' to the server.
# If the server persists sessions, we can resume.
await session.destroy()
print("Session destroyed (client side resources released)")

# Resume the previous session
resumed = client.resume_session("user-123-conversation")
print(f"Resumed: {resumed.session_id}")
# Resume the previous session
resumed = await client.resume_session("user-123-conversation")
print(f"Resumed: {resumed.session_id}")

resumed.send(prompt="What were we discussing?")
await resumed.send_and_wait({"prompt": "What were we discussing?"})

# List sessions
sessions = client.list_sessions()
print("Sessions:", [s["sessionId"] for s in sessions])
# Listen for the response to verify
# (In a real app we'd set up handlers before sending)

# Delete session permanently
client.delete_session("user-123-conversation")
print("Session deleted")
# list_sessions and delete_session are not currently available in the Python SDK Client
# sessions = await client.list_sessions()
# print("Sessions:", [s["sessionId"] for s in sessions])

resumed.destroy()
client.stop()
# client.delete_session("user-123-conversation")
# print("Session deleted")

await resumed.destroy()

finally:
await client.stop()

if __name__ == "__main__":
asyncio.run(main())
Loading
Loading