-
Notifications
You must be signed in to change notification settings - Fork 850
Closed
Labels
Description
Summary
The SDK throws a ValueError when the Copilot server sends session.usage_info events, because this event type is not defined in the SessionEventType enum. The error is printed to stderr as an unhandled exception in the asyncio event loop callback, which creates noisy output even though the request completes successfully.
Reproduction
import asyncio
from copilot import CopilotClient
from copilot.generated.session_events import SessionEventType
async def repro():
client = CopilotClient()
await client.start()
try:
session = await client.create_session({
"model": "claude-sonnet-4.5",
"streaming": False,
"available_tools": [],
})
done = asyncio.Event()
def handle_event(event):
if event.type == SessionEventType.ASSISTANT_TURN_END:
done.set()
unsubscribe = session.on(handle_event)
try:
await session.send({"prompt": "Say hello"})
await asyncio.wait_for(done.wait(), timeout=30)
finally:
unsubscribe()
await session.destroy()
finally:
await client.stop()
# Run with GH_TOKEN set
asyncio.run(repro())Output:
Exception in callback CopilotClient._connect_via_stdio.<locals>.handle_notification(...)
Traceback (most recent call last):
...
File ".../copilot/generated/session_events.py", line 618, in from_dict
type = SessionEventType(obj.get("type"))
ValueError: 'session.usage_info' is not a valid SessionEventType
Root Cause
In copilot/generated/session_events.py, the SessionEventType enum does not include session.usage_info:
class SessionEventType(Enum):
ASSISTANT_MESSAGE = "session.assistant.message"
ASSISTANT_MESSAGE_DELTA = "session.assistant.message.delta"
ASSISTANT_TURN_END = "session.assistant.turn.end"
# ... other types
# Missing: SESSION_USAGE_INFO = "session.usage_info"When SessionEvent.from_dict() tries to parse an event with type: "session.usage_info", it fails:
type = SessionEventType(obj.get("type")) # ValueError!Suggested Fix
Option 1: Add the missing event type to the enum:
class SessionEventType(Enum):
# ... existing types ...
SESSION_USAGE_INFO = "session.usage_info"Option 2: Handle unknown event types gracefully in session_event_from_dict():
def session_event_from_dict(s: dict) -> Optional[SessionEvent]:
try:
return SessionEvent.from_dict(s)
except ValueError:
# Unknown event type - ignore gracefully
return NoneAnd update handle_notification() to handle None:
def handle_notification(method: str, params: dict):
if method == "session.event":
event = session_event_from_dict(event_dict)
if event is not None: # Skip unknown event types
session._dispatch_event(event)Environment
- OS: macOS 14.x
- Python: 3.11
- SDK version: Latest from pip
Impact
- Severity: Low (does not break functionality, but creates noisy stderr output)
- Workaround: Suppress the exception via custom asyncio exception handler
Reactions are currently unavailable