Skip to content

Commit 1c180c3

Browse files
authored
Merge pull request #697 from tonybaloney/fix/python-cookbook-api
Fix Python cookbook recipes to use correct async SDK API
2 parents 39d80e1 + c65e8ab commit 1c180c3

File tree

10 files changed

+321
-301
lines changed

10 files changed

+321
-301
lines changed

cookbook/copilot-sdk/python/error-handling.md

Lines changed: 37 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,36 @@ You need to handle various error conditions like connection failures, timeouts,
1616
## Basic try-except
1717
1818
```python
19-
from copilot import CopilotClient
19+
import asyncio
20+
from copilot import CopilotClient, SessionConfig, MessageOptions
2021
21-
client = CopilotClient()
22+
async def main():
23+
client = CopilotClient()
2224
23-
try:
24-
client.start()
25-
session = client.create_session(model="gpt-5")
25+
try:
26+
await client.start()
27+
session = await client.create_session(SessionConfig(model="gpt-5"))
2628
27-
response = None
28-
def handle_message(event):
29-
nonlocal response
30-
if event["type"] == "assistant.message":
31-
response = event["data"]["content"]
29+
response = await session.send_and_wait(MessageOptions(prompt="Hello!"))
3230
33-
session.on(handle_message)
34-
session.send(prompt="Hello!")
35-
session.wait_for_idle()
31+
if response:
32+
print(response.data.content)
3633
37-
if response:
38-
print(response)
34+
await session.destroy()
35+
except Exception as e:
36+
print(f"Error: {e}")
37+
finally:
38+
await client.stop()
3939
40-
session.destroy()
41-
except Exception as e:
42-
print(f"Error: {e}")
43-
finally:
44-
client.stop()
40+
if __name__ == "__main__":
41+
asyncio.run(main())
4542
```
4643
4744
## Handling specific error types
4845
4946
```python
50-
import subprocess
51-
5247
try:
53-
client.start()
48+
await client.start()
5449
except FileNotFoundError:
5550
print("Copilot CLI not found. Please install it first.")
5651
except ConnectionError:
@@ -62,31 +57,14 @@ except Exception as e:
6257
## Timeout handling
6358
6459
```python
65-
import signal
66-
from contextlib import contextmanager
67-
68-
@contextmanager
69-
def timeout(seconds):
70-
def timeout_handler(signum, frame):
71-
raise TimeoutError("Request timed out")
72-
73-
old_handler = signal.signal(signal.SIGALRM, timeout_handler)
74-
signal.alarm(seconds)
75-
try:
76-
yield
77-
finally:
78-
signal.alarm(0)
79-
signal.signal(signal.SIGALRM, old_handler)
80-
81-
session = client.create_session(model="gpt-5")
60+
session = await client.create_session(SessionConfig(model="gpt-5"))
8261
8362
try:
84-
session.send(prompt="Complex question...")
85-
86-
# Wait with timeout (30 seconds)
87-
with timeout(30):
88-
session.wait_for_idle()
89-
63+
# send_and_wait accepts an optional timeout in seconds
64+
response = await session.send_and_wait(
65+
MessageOptions(prompt="Complex question..."),
66+
timeout=30.0
67+
)
9068
print("Response received")
9169
except TimeoutError:
9270
print("Request timed out")
@@ -95,21 +73,15 @@ except TimeoutError:
9573
## Aborting a request
9674
9775
```python
98-
import threading
99-
100-
session = client.create_session(model="gpt-5")
76+
session = await client.create_session(SessionConfig(model="gpt-5"))
10177
102-
# Start a request
103-
session.send(prompt="Write a very long story...")
78+
# Start a request (non-blocking send)
79+
await session.send(MessageOptions(prompt="Write a very long story..."))
10480
10581
# Abort it after some condition
106-
def abort_later():
107-
import time
108-
time.sleep(5)
109-
session.abort()
110-
print("Request aborted")
111-
112-
threading.Thread(target=abort_later).start()
82+
await asyncio.sleep(5)
83+
await session.abort()
84+
print("Request aborted")
11385
```
11486
11587
## Graceful shutdown
@@ -120,31 +92,19 @@ import sys
12092
12193
def signal_handler(sig, frame):
12294
print("\nShutting down...")
123-
errors = client.stop()
124-
if errors:
125-
print(f"Cleanup errors: {errors}")
95+
try:
96+
loop = asyncio.get_running_loop()
97+
loop.create_task(client.stop())
98+
except RuntimeError:
99+
asyncio.run(client.stop())
126100
sys.exit(0)
127101
128102
signal.signal(signal.SIGINT, signal_handler)
129103
```
130104
131-
## Context manager for automatic cleanup
132-
133-
```python
134-
from copilot import CopilotClient
135-
136-
with CopilotClient() as client:
137-
client.start()
138-
session = client.create_session(model="gpt-5")
139-
140-
# ... do work ...
141-
142-
# client.stop() is automatically called when exiting context
143-
```
144-
145105
## Best practices
146106
147-
1. **Always clean up**: Use try-finally or context managers to ensure `stop()` is called
107+
1. **Always clean up**: Use try-finally to ensure `await client.stop()` is called
148108
2. **Handle connection errors**: The CLI might not be installed or running
149-
3. **Set appropriate timeouts**: Long-running requests should have timeouts
109+
3. **Set appropriate timeouts**: Use the `timeout` parameter on `send_and_wait()`
150110
4. **Log errors**: Capture error details for debugging

cookbook/copilot-sdk/python/managing-local-files.md

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,40 @@ You have a folder with many files and want to organize them into subfolders base
1616
## Example code
1717
1818
```python
19-
from copilot import CopilotClient
19+
import asyncio
2020
import os
21-
22-
# Create and start client
23-
client = CopilotClient()
24-
client.start()
25-
26-
# Create session
27-
session = client.create_session(model="gpt-5")
28-
29-
# Event handler
30-
def handle_event(event):
31-
if event["type"] == "assistant.message":
32-
print(f"\nCopilot: {event['data']['content']}")
33-
elif event["type"] == "tool.execution_start":
34-
print(f" → Running: {event['data']['toolName']}")
35-
elif event["type"] == "tool.execution_complete":
36-
print(f" ✓ Completed: {event['data']['toolCallId']}")
37-
38-
session.on(handle_event)
39-
40-
# Ask Copilot to organize files
41-
target_folder = os.path.expanduser("~/Downloads")
42-
43-
session.send(prompt=f"""
21+
from copilot import (
22+
CopilotClient, SessionConfig, MessageOptions,
23+
SessionEvent, SessionEventType,
24+
)
25+
26+
async def main():
27+
# Create and start client
28+
client = CopilotClient()
29+
await client.start()
30+
31+
# Create session
32+
session = await client.create_session(SessionConfig(model="gpt-5"))
33+
34+
done = asyncio.Event()
35+
36+
# Event handler
37+
def handle_event(event: SessionEvent):
38+
if event.type == SessionEventType.ASSISTANT_MESSAGE:
39+
print(f"\nCopilot: {event.data.content}")
40+
elif event.type == SessionEventType.TOOL_EXECUTION_START:
41+
print(f" → Running: {event.data.tool_name}")
42+
elif event.type == SessionEventType.TOOL_EXECUTION_COMPLETE:
43+
print(f" ✓ Completed: {event.data.tool_call_id}")
44+
elif event.type.value == "session.idle":
45+
done.set()
46+
47+
session.on(handle_event)
48+
49+
# Ask Copilot to organize files
50+
target_folder = os.path.expanduser("~/Downloads")
51+
52+
await session.send(MessageOptions(prompt=f"""
4453
Analyze the files in "{target_folder}" and organize them into subfolders.
4554
4655
1. First, list all files and their metadata
@@ -49,11 +58,15 @@ Analyze the files in "{target_folder}" and organize them into subfolders.
4958
4. Move each file to its appropriate subfolder
5059
5160
Please confirm before moving any files.
52-
""")
61+
"""))
62+
63+
await done.wait()
5364
54-
session.wait_for_idle()
65+
await session.destroy()
66+
await client.stop()
5567
56-
client.stop()
68+
if __name__ == "__main__":
69+
asyncio.run(main())
5770
```
5871
5972
## Grouping strategies
@@ -90,26 +103,26 @@ client.stop()
90103
For safety, you can ask Copilot to only preview changes:
91104
92105
```python
93-
session.send(prompt=f"""
106+
await session.send(MessageOptions(prompt=f"""
94107
Analyze files in "{target_folder}" and show me how you would organize them
95108
by file type. DO NOT move any files - just show me the plan.
96-
""")
109+
"""))
97110
```
98111
99112
## Custom grouping with AI analysis
100113
101114
Let Copilot determine the best grouping based on file content:
102115
103116
```python
104-
session.send(prompt=f"""
117+
await session.send(MessageOptions(prompt=f"""
105118
Look at the files in "{target_folder}" and suggest a logical organization.
106119
Consider:
107120
- File names and what they might contain
108121
- File types and their typical uses
109122
- Date patterns that might indicate projects or events
110123
111124
Propose folder names that are descriptive and useful.
112-
""")
125+
"""))
113126
```
114127
115128
## Safety considerations

cookbook/copilot-sdk/python/multiple-sessions.md

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,59 +16,64 @@ You need to run multiple conversations in parallel, each with its own context an
1616
## Python
1717
1818
```python
19-
from copilot import CopilotClient
20-
21-
client = CopilotClient()
22-
client.start()
23-
24-
# Create multiple independent sessions
25-
session1 = client.create_session(model="gpt-5")
26-
session2 = client.create_session(model="gpt-5")
27-
session3 = client.create_session(model="claude-sonnet-4.5")
28-
29-
# Each session maintains its own conversation history
30-
session1.send(prompt="You are helping with a Python project")
31-
session2.send(prompt="You are helping with a TypeScript project")
32-
session3.send(prompt="You are helping with a Go project")
33-
34-
# Follow-up messages stay in their respective contexts
35-
session1.send(prompt="How do I create a virtual environment?")
36-
session2.send(prompt="How do I set up tsconfig?")
37-
session3.send(prompt="How do I initialize a module?")
38-
39-
# Clean up all sessions
40-
session1.destroy()
41-
session2.destroy()
42-
session3.destroy()
43-
client.stop()
19+
import asyncio
20+
from copilot import CopilotClient, SessionConfig, MessageOptions
21+
22+
async def main():
23+
client = CopilotClient()
24+
await client.start()
25+
26+
# Create multiple independent sessions
27+
session1 = await client.create_session(SessionConfig(model="gpt-5"))
28+
session2 = await client.create_session(SessionConfig(model="gpt-5"))
29+
session3 = await client.create_session(SessionConfig(model="claude-sonnet-4.5"))
30+
31+
# Each session maintains its own conversation history
32+
await session1.send(MessageOptions(prompt="You are helping with a Python project"))
33+
await session2.send(MessageOptions(prompt="You are helping with a TypeScript project"))
34+
await session3.send(MessageOptions(prompt="You are helping with a Go project"))
35+
36+
# Follow-up messages stay in their respective contexts
37+
await session1.send(MessageOptions(prompt="How do I create a virtual environment?"))
38+
await session2.send(MessageOptions(prompt="How do I set up tsconfig?"))
39+
await session3.send(MessageOptions(prompt="How do I initialize a module?"))
40+
41+
# Clean up all sessions
42+
await session1.destroy()
43+
await session2.destroy()
44+
await session3.destroy()
45+
await client.stop()
46+
47+
if __name__ == "__main__":
48+
asyncio.run(main())
4449
```
4550
4651
## Custom session IDs
4752
4853
Use custom IDs for easier tracking:
4954
5055
```python
51-
session = client.create_session(
56+
session = await client.create_session(SessionConfig(
5257
session_id="user-123-chat",
5358
model="gpt-5"
54-
)
59+
))
5560
5661
print(session.session_id) # "user-123-chat"
5762
```
5863
5964
## Listing sessions
6065
6166
```python
62-
sessions = client.list_sessions()
67+
sessions = await client.list_sessions()
6368
for session_info in sessions:
64-
print(f"Session: {session_info['sessionId']}")
69+
print(f"Session: {session_info.session_id}")
6570
```
6671
6772
## Deleting sessions
6873
6974
```python
7075
# Delete a specific session
71-
client.delete_session("user-123-chat")
76+
await client.delete_session("user-123-chat")
7277
```
7378
7479
## Use cases

0 commit comments

Comments
 (0)