Skip to content

Commit 8735cc4

Browse files
Update api spec (#677)
* YOYO NEW API SPEC! * I have generated the latest API! --------- Co-authored-by: zoo-github-actions-auth[bot] <zoo-github-actions-auth[bot]@users.noreply.github.com>
1 parent 64df18e commit 8735cc4

5 files changed

Lines changed: 240 additions & 55 deletions

File tree

kittycad.py.patch.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@
147147
"op": "add",
148148
"path": "/paths/~1file~1conversion/post/x-python",
149149
"value": {
150-
"example": "from kittycad.models.conversion_params import ConversionParams\nfrom kittycad.models.output_format3d import OptionStep\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.step_presentation import StepPresentation\nfrom kittycad.models.unit_length import UnitLength\nfrom kittycad.models.output_format3d import OutputFormat3d\nfrom kittycad.models.input_format3d import OptionStep\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.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(OptionStep(\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 presentation=StepPresentation.COMPACT,\n units=UnitLength.CM,\n )),\n src_format=InputFormat3d(OptionStep(\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 split_closed_faces=False,\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",
150+
"example": "from kittycad.models.conversion_params import ConversionParams\nfrom kittycad.models.output_format3d import OptionStep\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.step_presentation import StepPresentation\nfrom kittycad.models.unit_length import UnitLength\nfrom kittycad.models.output_format3d import OutputFormat3d\nfrom kittycad.models.input_format3d import OptionGltf\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(OptionStep(\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 presentation=StepPresentation.COMPACT,\n units=UnitLength.CM,\n )),\n src_format=InputFormat3d(OptionGltf()),\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",
151151
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.file"
152152
}
153153
},
@@ -747,7 +747,7 @@
747747
"op": "add",
748748
"path": "/paths/~1org~1saml~1idp/post/x-python",
749749
"value": {
750-
"example": "from kittycad.models.saml_identity_provider_create import SamlIdentityProviderCreate\nfrom kittycad.models.idp_metadata_source import OptionBase64EncodedXml\nfrom kittycad.models.base64data import Base64Data\nfrom kittycad.models.idp_metadata_source import IdpMetadataSource\nfrom kittycad.models import SamlIdentityProvider\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_create_org_saml_idp():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n result: SamlIdentityProvider = client.orgs.create_org_saml_idp(body=SamlIdentityProviderCreate(\n idp_entity_id=\"<string>\",\n idp_metadata_source=IdpMetadataSource(OptionBase64EncodedXml(\n data=Base64Data(b\"<bytes>\"),\n )),\n technical_contact_email=\"<string>\",\n ))\n\n\n body: SamlIdentityProvider = result\n print(body)\n\n",
750+
"example": "from kittycad.models.saml_identity_provider_create import SamlIdentityProviderCreate\nfrom kittycad.models.idp_metadata_source import OptionUrl\nfrom kittycad.models.idp_metadata_source import IdpMetadataSource\nfrom kittycad.models import SamlIdentityProvider\nfrom typing import Union, Any, Optional, List, Tuple\nfrom kittycad.types import Response\ndef example_create_org_saml_idp():\n client = KittyCAD() # Uses KITTYCAD_API_TOKEN environment variable\n\n result: SamlIdentityProvider = client.orgs.create_org_saml_idp(body=SamlIdentityProviderCreate(\n idp_entity_id=\"<string>\",\n idp_metadata_source=IdpMetadataSource(OptionUrl(\n url=\"<string>\",\n )),\n technical_contact_email=\"<string>\",\n ))\n\n\n body: SamlIdentityProvider = result\n print(body)\n\n",
751751
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.orgs"
752752
}
753753
},
@@ -1611,23 +1611,23 @@
16111611
"op": "add",
16121612
"path": "/paths/~1ws~1ml~1copilot/get/x-python",
16131613
"value": {
1614-
"example": "from kittycad.models import MlCopilotClientMessage\nfrom kittycad.models.ml_copilot_client_message import OptionHeaders\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(OptionHeaders(\nheaders={\"<string>\": \"<string>\"},\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
1614+
"example": "from kittycad.models import MlCopilotClientMessage\nfrom kittycad.models.ml_copilot_client_message import OptionSystem\nfrom kittycad.models.ml_copilot_system_command import MlCopilotSystemCommand\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(OptionSystem(\ncommand=MlCopilotSystemCommand.NEW,\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
16151615
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.ml"
16161616
}
16171617
},
16181618
{
16191619
"op": "add",
16201620
"path": "/paths/~1ws~1ml~1reasoning~1{id}/get/x-python",
16211621
"value": {
1622-
"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_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(OptionPing()))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
1622+
"example": "from kittycad.models import MlCopilotClientMessage\nfrom kittycad.models.ml_copilot_client_message import OptionSystem\nfrom kittycad.models.ml_copilot_system_command import MlCopilotSystemCommand\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(OptionSystem(\ncommand=MlCopilotSystemCommand.NEW,\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
16231623
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.ml"
16241624
}
16251625
},
16261626
{
16271627
"op": "add",
16281628
"path": "/paths/~1ws~1modeling~1commands/get/x-python",
16291629
"value": {
1630-
"example": "from kittycad.models.post_effect_type import PostEffectType\nfrom kittycad.models import WebSocketRequest\nfrom kittycad.models.web_socket_request import OptionHeaders\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(OptionHeaders(\nheaders={\"<string>\": \"<string>\"},\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
1630+
"example": "from kittycad.models.post_effect_type import PostEffectType\nfrom kittycad.models import WebSocketRequest\nfrom kittycad.models.web_socket_request import OptionModelingCmdReq\nfrom kittycad.models.modeling_cmd import OptionObjectBringToFront\nfrom kittycad.models.modeling_cmd import ModelingCmd\nfrom kittycad.models.modeling_cmd_id import ModelingCmdId\nfrom kittycad.models.modeling_cmd_id import ModelingCmdId\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(OptionModelingCmdReq(\ncmd=ModelingCmd(OptionObjectBringToFront(\nobject_id=\"<string>\",\n)),\n\ncmd_id=ModelingCmdId(\"<string>\"),\n)))\n\n # Get a message.\n message = websocket.recv()\n print(message)\n\n ",
16311631
"libDocsLink": "https://python.api.docs.zoo.dev/_autosummary/kittycad.KittyCAD.html#kittycad.KittyCAD.modeling"
16321632
}
16331633
}

kittycad/models/ml_copilot_client_message.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from ..models.ml_copilot_tool import MlCopilotTool
1111
from ..models.ml_reasoning_effort import MlReasoningEffort
1212
from ..models.source_range_prompt import SourceRangePrompt
13+
from ..models.uuid import Uuid
1314
from .base import KittyCadBaseModel
1415

1516

@@ -75,6 +76,22 @@ class OptionSystem(KittyCadBaseModel):
7576
type: Literal["system"] = "system"
7677

7778

79+
class OptionAttachmentResponse(KittyCadBaseModel):
80+
"""Attachments returned by API in response to a backend `RequestAttachments` message."""
81+
82+
error: Optional[str] = None
83+
84+
files: Optional[List[MlCopilotFile]] = None
85+
86+
prompt_id: Optional[Uuid] = None
87+
88+
request_id: Optional[str] = None
89+
90+
seq: Optional[int] = None
91+
92+
type: Literal["attachment_response"] = "attachment_response"
93+
94+
7895
MlCopilotClientMessage = RootModel[
7996
Annotated[
8097
Union[
@@ -84,6 +101,7 @@ class OptionSystem(KittyCadBaseModel):
84101
OptionProjectContext,
85102
OptionUser,
86103
OptionSystem,
104+
OptionAttachmentResponse,
87105
],
88106
Field(discriminator="type"),
89107
]

kittycad/models/ml_copilot_server_message.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,66 @@ class Reasoning(KittyCadBaseModel):
239239
reasoning: ReasoningMessage
240240

241241

242+
class RequestAttachments(KittyCadBaseModel):
243+
"""Backend-only request for API to reload client attachments from storage.
244+
245+
API handles this message internally and responds upstream with `MlCopilotClientMessage::AttachmentResponse`; it is not forwarded to the browser."""
246+
247+
conversation_id: Optional[Uuid] = None
248+
249+
names: Optional[List[str]] = None
250+
251+
only_metadata: Optional[bool] = False
252+
253+
prompt_id: Optional[Uuid] = None
254+
255+
request_id: Optional[str] = None
256+
257+
seq: Optional[int] = None
258+
259+
@model_validator(mode="before")
260+
@classmethod
261+
def _unwrap(cls, data):
262+
if (
263+
isinstance(data, dict)
264+
and "request_attachments" in data
265+
and isinstance(data["request_attachments"], dict)
266+
):
267+
return data["request_attachments"]
268+
269+
return data
270+
271+
@model_serializer(mode="wrap")
272+
def _wrap(self, handler, info):
273+
payload = handler(self, info)
274+
275+
return {"request_attachments": payload}
276+
277+
278+
class AttachmentsLoaded(KittyCadBaseModel):
279+
"""Notification that API finished loading all attachments for the conversation."""
280+
281+
request_id: Optional[str] = None
282+
283+
@model_validator(mode="before")
284+
@classmethod
285+
def _unwrap(cls, data):
286+
if (
287+
isinstance(data, dict)
288+
and "attachments_loaded" in data
289+
and isinstance(data["attachments_loaded"], dict)
290+
):
291+
return data["attachments_loaded"]
292+
293+
return data
294+
295+
@model_serializer(mode="wrap")
296+
def _wrap(self, handler, info):
297+
payload = handler(self, info)
298+
299+
return {"attachments_loaded": payload}
300+
301+
242302
class Replay(KittyCadBaseModel):
243303
"""Replay containing raw bytes for previously-saved messages for a conversation. Includes server messages and client `User` messages.
244304
@@ -336,6 +396,8 @@ def _wrap(self, handler, info):
336396
BackendShutdown,
337397
ProjectUpdated,
338398
Reasoning,
399+
RequestAttachments,
400+
AttachmentsLoaded,
339401
Replay,
340402
EndOfStream,
341403
Files,

0 commit comments

Comments
 (0)