Skip to content

Commit 0d10712

Browse files
authored
fix bug with None in copilot ws messages (#530)
updates Signed-off-by: Jessie Frazelle <github@jessfraz.com>
1 parent 7a631ef commit 0d10712

File tree

5 files changed

+63
-10
lines changed

5 files changed

+63
-10
lines changed

generate/templates/__init__.py.jinja2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,15 @@ class WebSocket{{ func_name|to_pascal_case }}:
147147
{% if func_info.ws_request_is_dict %}
148148
self.ws.send(json.dumps(data))
149149
{% else %}
150-
self.ws.send(json.dumps(data.model_dump()))
150+
self.ws.send(json.dumps(data.model_dump(exclude_none=True)))
151151
{% endif %}
152152

153153
def send_binary(self, data: {{ func_info.ws_request_type }}):
154154
"""Send data as bson to the websocket."""
155155
{% if func_info.ws_request_is_dict %}
156156
self.ws.send(bson.encode(data))
157157
{% else %}
158-
self.ws.send(bson.encode(data.model_dump()))
158+
self.ws.send(bson.encode(data.model_dump(exclude_none=True)))
159159
{% endif %}
160160

161161
def recv(self) -> {{ func_info.ws_response_type }}:

kittycad/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12247,12 +12247,12 @@ def __iter__(self):
1224712247
def send(self, data: MlCopilotClientMessage):
1224812248
"""Send data to the websocket."""
1224912249

12250-
self.ws.send(json.dumps(data.model_dump()))
12250+
self.ws.send(json.dumps(data.model_dump(exclude_none=True)))
1225112251

1225212252
def send_binary(self, data: MlCopilotClientMessage):
1225312253
"""Send data as bson to the websocket."""
1225412254

12255-
self.ws.send(bson.encode(data.model_dump()))
12255+
self.ws.send(bson.encode(data.model_dump(exclude_none=True)))
1225612256

1225712257
def recv(self) -> MlCopilotServerMessage:
1225812258
"""Receive data from the websocket."""
@@ -12317,12 +12317,12 @@ def __iter__(self):
1231712317
def send(self, data: MlCopilotClientMessage):
1231812318
"""Send data to the websocket."""
1231912319

12320-
self.ws.send(json.dumps(data.model_dump()))
12320+
self.ws.send(json.dumps(data.model_dump(exclude_none=True)))
1232112321

1232212322
def send_binary(self, data: MlCopilotClientMessage):
1232312323
"""Send data as bson to the websocket."""
1232412324

12325-
self.ws.send(bson.encode(data.model_dump()))
12325+
self.ws.send(bson.encode(data.model_dump(exclude_none=True)))
1232612326

1232712327
def recv(self) -> MlCopilotServerMessage:
1232812328
"""Receive data from the websocket."""
@@ -12525,12 +12525,12 @@ def __iter__(self):
1252512525
def send(self, data: WebSocketRequest):
1252612526
"""Send data to the websocket."""
1252712527

12528-
self.ws.send(json.dumps(data.model_dump()))
12528+
self.ws.send(json.dumps(data.model_dump(exclude_none=True)))
1252912529

1253012530
def send_binary(self, data: WebSocketRequest):
1253112531
"""Send data as bson to the websocket."""
1253212532

12533-
self.ws.send(bson.encode(data.model_dump()))
12533+
self.ws.send(bson.encode(data.model_dump(exclude_none=True)))
1253412534

1253512535
def recv(self) -> WebSocketResponse:
1253612536
"""Receive data from the websocket."""
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import os
2+
3+
import pytest
4+
5+
from kittycad import KittyCAD
6+
from kittycad.models import MlCopilotClientMessage
7+
from kittycad.models.ml_copilot_client_message import OptionUser
8+
from kittycad.models.ml_copilot_server_message import (
9+
ConversationId,
10+
Delta,
11+
EndOfStream,
12+
Error,
13+
)
14+
15+
16+
def test_ml_copilot_ws_round_trip() -> None:
17+
token = os.getenv("KITTYCAD_API_TOKEN")
18+
if not token:
19+
pytest.skip("requires KITTYCAD_API_TOKEN")
20+
21+
client = KittyCAD()
22+
client.headers["Cache-Control"] = "no-cache"
23+
24+
prompt = "Explain why reliable CAD tooling matters in one sentence."
25+
26+
with client.ml.ml_copilot_ws(conversation_id=None, replay=None) as websocket:
27+
websocket.send(MlCopilotClientMessage(OptionUser(content=prompt)))
28+
29+
deltas: list[str] = []
30+
conversation_id: str | None = None
31+
end_of_stream = False
32+
33+
for _ in range(200):
34+
message = websocket.recv()
35+
root = message.root
36+
37+
if isinstance(root, ConversationId):
38+
conversation_id = root.conversation_id
39+
elif isinstance(root, Delta):
40+
deltas.append(root.delta)
41+
elif isinstance(root, EndOfStream):
42+
end_of_stream = True
43+
break
44+
elif isinstance(root, Error):
45+
pytest.fail(f"ml_copilot_ws returned error: {root.detail}")
46+
else:
47+
pytest.fail("ml_copilot_ws did not emit EndOfStream within 200 messages")
48+
49+
response_text = "".join(deltas).strip()
50+
51+
assert conversation_id, "Expected ConversationId message from ml_copilot_ws"
52+
assert end_of_stream, "Expected EndOfStream message from ml_copilot_ws"
53+
assert response_text, "Expected non-empty streamed response from ml_copilot_ws"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "kittycad"
7-
version = "1.2.6"
7+
version = "1.2.7"
88
description = "A client library for accessing KittyCAD"
99
authors = []
1010
readme = "README.md"

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)