Skip to content
Merged
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
8 changes: 4 additions & 4 deletions kittycad.py.patch.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
"op": "add",
"path": "/paths/~1file~1conversion/post/x-python",
"value": {
"example": "from kittycad.models.conversion_params import ConversionParams\nfrom kittycad.models.output_format3d import OptionGltf\nfrom kittycad.models.gltf_presentation import GltfPresentation\nfrom kittycad.models.gltf_storage import GltfStorage\nfrom kittycad.models.output_format3d import OutputFormat3d\nfrom kittycad.models.input_format3d import OptionFbx\nfrom kittycad.models.input_format3d import InputFormat3d\nfrom pathlib import Path\nfrom typing import Dict\nfrom kittycad._io_types import SyncUpload\nfrom kittycad.models import FileConversion\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_create_file_conversion_options():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n result: FileConversion = client.file.create_file_conversion_options(body=ConversionParams(\n output_format=OutputFormat3d(OptionGltf(\n presentation=GltfPresentation.COMPACT,\n storage=GltfStorage.BINARY,\n )),\n src_format=InputFormat3d(OptionFbx()),\n ),\n file_attachments={\n \"main.kcl\": Path(\"path/to/main.kcl\"),\n \"helper.kcl\": Path(\"path/to/helper.kcl\"),\n })\n\n\n body: FileConversion = result\n print(body)\n\n",
"example": "from kittycad.models.conversion_params import ConversionParams\nfrom kittycad.models.output_format3d import OptionPly\nfrom kittycad.models.system import System\nfrom kittycad.models.axis_direction_pair import AxisDirectionPair\nfrom kittycad.models.axis import Axis\nfrom kittycad.models.direction import Direction\nfrom kittycad.models.axis_direction_pair import AxisDirectionPair\nfrom kittycad.models.axis import Axis\nfrom kittycad.models.direction import Direction\nfrom kittycad.models.selection import OptionSceneByIndex\nfrom kittycad.models.selection import Selection\nfrom kittycad.models.ply_storage import PlyStorage\nfrom kittycad.models.unit_length import UnitLength\nfrom kittycad.models.output_format3d import OutputFormat3d\nfrom kittycad.models.input_format3d import OptionStl\nfrom kittycad.models.system import System\nfrom kittycad.models.axis_direction_pair import AxisDirectionPair\nfrom kittycad.models.axis import Axis\nfrom kittycad.models.direction import Direction\nfrom kittycad.models.axis_direction_pair import AxisDirectionPair\nfrom kittycad.models.axis import Axis\nfrom kittycad.models.direction import Direction\nfrom kittycad.models.unit_length import UnitLength\nfrom kittycad.models.input_format3d import InputFormat3d\nfrom pathlib import Path\nfrom typing import Dict\nfrom kittycad._io_types import SyncUpload\nfrom kittycad.models import FileConversion\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_create_file_conversion_options():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n result: FileConversion = client.file.create_file_conversion_options(body=ConversionParams(\n output_format=OutputFormat3d(OptionPly(\n coords=System(\n forward=AxisDirectionPair(\n axis=Axis.Y,\n direction=Direction.POSITIVE,\n ),\n up=AxisDirectionPair(\n axis=Axis.Y,\n direction=Direction.POSITIVE,\n ),\n ),\n selection=Selection(OptionSceneByIndex(\n index=10,\n )),\n storage=PlyStorage.ASCII,\n units=UnitLength.CM,\n )),\n src_format=InputFormat3d(OptionStl(\n coords=System(\n forward=AxisDirectionPair(\n axis=Axis.Y,\n direction=Direction.POSITIVE,\n ),\n up=AxisDirectionPair(\n axis=Axis.Y,\n direction=Direction.POSITIVE,\n ),\n ),\n units=UnitLength.CM,\n )),\n ),\n file_attachments={\n \"main.kcl\": Path(\"path/to/main.kcl\"),\n \"helper.kcl\": Path(\"path/to/helper.kcl\"),\n })\n\n\n body: FileConversion = result\n print(body)\n\n",
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.file"
}
},
Expand Down Expand Up @@ -1691,23 +1691,23 @@
"op": "add",
"path": "/paths/~1ws~1ml~1copilot/get/x-python",
"value": {
"example": "from kittycad.models import MlCopilotClientMessage\nfrom kittycad.models.ml_copilot_client_message import OptionProjectContext\nfrom kittycad.models import MlCopilotServerMessage\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_ml_copilot_ws():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n # Connect to the websocket.\n with client.ml.ml_copilot_ws(replay=None,\n conversation_id=None,\n pr=None) as websocket:\n\n # Send a message.\n websocket.send(MlCopilotClientMessage(OptionProjectContext(\ncurrent_files={\"<string>\": b\"<bytes>\"},\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
"example": "from kittycad.models import MlCopilotClientMessage\nfrom kittycad.models.ml_copilot_client_message import OptionPing\nfrom kittycad.models import MlCopilotServerMessage\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_ml_copilot_ws():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n # Connect to the websocket.\n with client.ml.ml_copilot_ws(replay=None,\n conversation_id=None,\n pr=None) as websocket:\n\n # Send a message.\n websocket.send(MlCopilotClientMessage(OptionPing()))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.ml"
}
},
{
"op": "add",
"path": "/paths/~1ws~1ml~1reasoning~1{id}/get/x-python",
"value": {
"example": "from kittycad.models import MlCopilotClientMessage\nfrom kittycad.models.ml_copilot_client_message import OptionListModes\nfrom kittycad.models import MlCopilotServerMessage\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_ml_reasoning_ws():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n # Connect to the websocket.\n with client.ml.ml_reasoning_ws(id=\"<string>\") as websocket:\n\n # Send a message.\n websocket.send(MlCopilotClientMessage(OptionListModes()))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
"example": "from kittycad.models import MlCopilotClientMessage\nfrom kittycad.models.ml_copilot_client_message import OptionProjectContext\nfrom kittycad.models import MlCopilotServerMessage\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_ml_reasoning_ws():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n # Connect to the websocket.\n with client.ml.ml_reasoning_ws(id=\"<string>\") as websocket:\n\n # Send a message.\n websocket.send(MlCopilotClientMessage(OptionProjectContext(\ncurrent_files={\"<string>\": b\"<bytes>\"},\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.ml"
}
},
{
"op": "add",
"path": "/paths/~1ws~1modeling~1commands/get/x-python",
"value": {
"example": "from kittycad.models.post_effect_type import PostEffectType\nfrom kittycad.models import WebSocketRequest\nfrom kittycad.models.web_socket_request import OptionDebug\nfrom kittycad.models import WebSocketResponse\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_modeling_commands_ws():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n # Connect to the websocket.\n with client.modeling.modeling_commands_ws(video_res_width=10,\n video_res_height=10,\n fps=10,\n unlocked_framerate=False,\n post_effect=PostEffectType.PHOSPHOR,\n webrtc=False,\n show_grid=False,\n order_independent_transparency=False,\n pool=None,\n replay=None,\n api_call_id=None,\n pr=None) as websocket:\n\n # Send a message.\n websocket.send(WebSocketRequest(OptionDebug()))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
"example": "from kittycad.models.post_effect_type import PostEffectType\nfrom kittycad.models import WebSocketRequest\nfrom kittycad.models.web_socket_request import OptionModelingCmdBatchReq\nfrom kittycad.models.modeling_cmd_id import ModelingCmdId\nfrom kittycad.models.modeling_cmd_id import ModelingCmdId\nfrom kittycad.models.modeling_cmd_req import ModelingCmdReq\nfrom kittycad.models.modeling_cmd import OptionProjectPointsToPlane\nfrom kittycad.models.point3d import Point3d\nfrom typing import List\nfrom kittycad.models.modeling_cmd import ModelingCmd\nfrom kittycad.models.modeling_cmd_id import ModelingCmdId\nfrom kittycad.models.modeling_cmd_id import ModelingCmdId\nfrom typing import List\nfrom kittycad.models import WebSocketResponse\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_modeling_commands_ws():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n # Connect to the websocket.\n with client.modeling.modeling_commands_ws(video_res_width=10,\n video_res_height=10,\n fps=10,\n unlocked_framerate=False,\n post_effect=PostEffectType.PHOSPHOR,\n webrtc=False,\n show_grid=False,\n order_independent_transparency=False,\n pool=None,\n replay=None,\n api_call_id=None,\n pr=None) as websocket:\n\n # Send a message.\n websocket.send(WebSocketRequest(OptionModelingCmdBatchReq(\nbatch_id=ModelingCmdId(\"<string>\"),\n\nrequests=[ModelingCmdReq(\ncmd=ModelingCmd(OptionProjectPointsToPlane(\nplane_id=\"<string>\",\n\npoints=[Point3d(\nx=3.14,\n\ny=3.14,\n\nz=3.14,\n)],\n\nuse_plane_coords=False,\n)),\n\ncmd_id=ModelingCmdId(\"<string>\"),\n)],\n\nresponses=False,\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.modeling"
}
}
Expand Down
29 changes: 28 additions & 1 deletion kittycad/models/ml_copilot_server_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,32 @@ class ZookeeperAutoRouterMetadata(KittyCadBaseModel):
zookeeper_auto_router_metadata: ZookeeperAutoRouterMetadataModel


class ZookeeperOpenAiResponseCheckpoint(KittyCadBaseModel):
"""Backend-only completed OpenAI response checkpoint.

API persists this on the active prompt and includes the latest completed checkpoint only in replay sent to the text-to-CAD backend. It is never forwarded to browser clients."""

response_id: str

@model_validator(mode="before")
@classmethod
def _unwrap(cls, data):
if (
isinstance(data, dict)
and "zookeeper_open_ai_response_checkpoint" in data
and isinstance(data["zookeeper_open_ai_response_checkpoint"], dict)
):
return data["zookeeper_open_ai_response_checkpoint"]

return data

@model_serializer(mode="wrap")
def _wrap(self, handler, info):
payload = handler(self, info)

return {"zookeeper_open_ai_response_checkpoint": payload}


class ZookeeperTurnUsage(KittyCadBaseModel):
"""Backend-only token usage and cost for one completed Zookeeper turn.

Expand Down Expand Up @@ -354,7 +380,7 @@ def _wrap(self, handler, info):
class Replay(KittyCadBaseModel):
"""Replay containing raw bytes for previously-saved messages for a conversation. Includes server messages and client `User` messages.

Invariants: - Client replay includes server messages: `Info`, `Error`, `Reasoning(..)`, `ToolOutput { .. }`, `Files { .. }`, `ProjectUpdated { .. }`, and `EndOfStream { .. }`. - Client replay also includes client `User` messages. - Backend replay includes client `User` messages plus selected reasoning, edit metadata, recovery output, and final responses. - The following are NEVER included: `SessionData`, `ConversationId`, `Delta`, `BackendShutdown`, `ZookeeperAutoRouterMetadata`, or `ZookeeperTurnUsage`. - `ZookeeperRecoveryToolOutput` is included only in replay sent to the text-to-CAD backend and is filtered from client replay. - Ordering is stable: messages are ordered by prompt creation time within the conversation, then by the per-prompt `seq` value (monotonically increasing as seen in the original stream).
Invariants: - Client replay includes server messages: `Info`, `Error`, `Reasoning(..)`, `ToolOutput { .. }`, `Files { .. }`, `ProjectUpdated { .. }`, and `EndOfStream { .. }`. - Client replay also includes client `User` messages. - Backend replay includes client `User` messages plus selected reasoning, edit metadata, recovery output, and final responses. - The following are NEVER included from persisted chat rows: `SessionData`, `ConversationId`, `Delta`, `BackendShutdown`, `ZookeeperAutoRouterMetadata`, `ZookeeperOpenAiResponseCheckpoint`, or `ZookeeperTurnUsage`. - `ZookeeperRecoveryToolOutput` is included only in replay sent to the text-to-CAD backend and is filtered from client replay. - The latest completed `ZookeeperOpenAiResponseCheckpoint` is synthesized from prompt metadata only for replay sent to the text-to-CAD backend. - Ordering is stable: messages are ordered by prompt creation time within the conversation, then by the per-prompt `seq` value (monotonically increasing as seen in the original stream).

Wire format: - Each element is canonical serialized bytes (typically JSON) for either a `MlCopilotServerMessage` or a `MlCopilotClientMessage::User`. - When delivered as an initial replay over the websocket (upon `?replay=true&conversation_id=<uuid>`), the server sends a single WebSocket Binary frame containing a MsgPack-encoded document of this enum: `Replay { messages }`."""

Expand Down Expand Up @@ -451,6 +477,7 @@ def _wrap(self, handler, info):
RequestAttachments,
AttachmentsLoaded,
ZookeeperAutoRouterMetadata,
ZookeeperOpenAiResponseCheckpoint,
ZookeeperTurnUsage,
ZookeeperRecoveryToolOutput,
Replay,
Expand Down
Loading
Loading