jl-ecms-client 0.2.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jl-ecms-client might be problematic. Click here for more details.

Files changed (53) hide show
  1. jl_ecms_client-0.2.8.dist-info/METADATA +295 -0
  2. jl_ecms_client-0.2.8.dist-info/RECORD +53 -0
  3. jl_ecms_client-0.2.8.dist-info/WHEEL +5 -0
  4. jl_ecms_client-0.2.8.dist-info/licenses/LICENSE +190 -0
  5. jl_ecms_client-0.2.8.dist-info/top_level.txt +1 -0
  6. mirix/client/__init__.py +14 -0
  7. mirix/client/client.py +405 -0
  8. mirix/client/constants.py +60 -0
  9. mirix/client/remote_client.py +1136 -0
  10. mirix/client/utils.py +34 -0
  11. mirix/helpers/__init__.py +1 -0
  12. mirix/helpers/converters.py +429 -0
  13. mirix/helpers/datetime_helpers.py +90 -0
  14. mirix/helpers/json_helpers.py +47 -0
  15. mirix/helpers/message_helpers.py +74 -0
  16. mirix/helpers/tool_rule_solver.py +166 -0
  17. mirix/schemas/__init__.py +1 -0
  18. mirix/schemas/agent.py +401 -0
  19. mirix/schemas/block.py +188 -0
  20. mirix/schemas/cloud_file_mapping.py +29 -0
  21. mirix/schemas/embedding_config.py +114 -0
  22. mirix/schemas/enums.py +69 -0
  23. mirix/schemas/environment_variables.py +82 -0
  24. mirix/schemas/episodic_memory.py +170 -0
  25. mirix/schemas/file.py +57 -0
  26. mirix/schemas/health.py +10 -0
  27. mirix/schemas/knowledge_vault.py +181 -0
  28. mirix/schemas/llm_config.py +187 -0
  29. mirix/schemas/memory.py +318 -0
  30. mirix/schemas/message.py +1315 -0
  31. mirix/schemas/mirix_base.py +107 -0
  32. mirix/schemas/mirix_message.py +411 -0
  33. mirix/schemas/mirix_message_content.py +230 -0
  34. mirix/schemas/mirix_request.py +39 -0
  35. mirix/schemas/mirix_response.py +183 -0
  36. mirix/schemas/openai/__init__.py +1 -0
  37. mirix/schemas/openai/chat_completion_request.py +122 -0
  38. mirix/schemas/openai/chat_completion_response.py +144 -0
  39. mirix/schemas/openai/chat_completions.py +127 -0
  40. mirix/schemas/openai/embedding_response.py +11 -0
  41. mirix/schemas/openai/openai.py +229 -0
  42. mirix/schemas/organization.py +38 -0
  43. mirix/schemas/procedural_memory.py +151 -0
  44. mirix/schemas/providers.py +816 -0
  45. mirix/schemas/resource_memory.py +134 -0
  46. mirix/schemas/sandbox_config.py +132 -0
  47. mirix/schemas/semantic_memory.py +162 -0
  48. mirix/schemas/source.py +96 -0
  49. mirix/schemas/step.py +53 -0
  50. mirix/schemas/tool.py +241 -0
  51. mirix/schemas/tool_rule.py +209 -0
  52. mirix/schemas/usage.py +31 -0
  53. mirix/schemas/user.py +67 -0
@@ -0,0 +1,107 @@
1
+ import uuid
2
+ from datetime import datetime
3
+ from logging import getLogger
4
+ from typing import Optional
5
+ from uuid import UUID
6
+
7
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
8
+
9
+ # from: https://gist.github.com/norton120/22242eadb80bf2cf1dd54a961b151c61
10
+
11
+
12
+ logger = getLogger(__name__)
13
+
14
+
15
+ class MirixBase(BaseModel):
16
+ """Base schema for Mirix schemas (does not include model provider schemas, e.g. OpenAI)"""
17
+
18
+ model_config = ConfigDict(
19
+ # allows you to use the snake or camelcase names in your code (ie user_id or userId)
20
+ populate_by_name=True,
21
+ # allows you do dump a sqlalchemy object directly (ie PersistedAddress.model_validate(SQLAdress)
22
+ from_attributes=True,
23
+ # throw errors if attributes are given that don't belong
24
+ extra="forbid",
25
+ # handle datetime serialization consistently across all models
26
+ # json_encoders={datetime: lambda dt: (dt.replace(tzinfo=timezone.utc) if dt.tzinfo is None else dt).isoformat()},
27
+ )
28
+
29
+ # def __id_prefix__(self):
30
+ # raise NotImplementedError("All schemas must have an __id_prefix__ attribute!")
31
+
32
+ @classmethod
33
+ def generate_id_field(cls, prefix: Optional[str] = None) -> "Field":
34
+ prefix = prefix or cls.__id_prefix__
35
+
36
+ return Field(
37
+ ...,
38
+ description=cls._id_description(prefix),
39
+ pattern=cls._id_regex_pattern(prefix),
40
+ examples=[cls._id_example(prefix)],
41
+ default_factory=cls._generate_id,
42
+ )
43
+
44
+ @classmethod
45
+ def _generate_id(cls, prefix: Optional[str] = None) -> str:
46
+ prefix = prefix or cls.__id_prefix__
47
+ return f"{prefix}-{uuid.uuid4()}"
48
+
49
+ # def _generate_id(self) -> str:
50
+ # return f"{self.__id_prefix__}-{uuid.uuid4()}"
51
+
52
+ @classmethod
53
+ def _id_regex_pattern(cls, prefix: str):
54
+ """generates the regex pattern for a given id"""
55
+ if cls.__name__ in ("JobBase", "Job", "Run", "RunBase"):
56
+ prefix_pattern = "(job|run)"
57
+ else:
58
+ prefix_pattern = prefix
59
+
60
+ return (
61
+ r"^" + prefix_pattern + r"-" # prefix string
62
+ r"[a-fA-F0-9]{8}" # 8 hexadecimal characters
63
+ # r"[a-fA-F0-9]{4}-" # 4 hexadecimal characters
64
+ # r"[a-fA-F0-9]{4}-" # 4 hexadecimal characters
65
+ # r"[a-fA-F0-9]{4}-" # 4 hexadecimal characters
66
+ # r"[a-fA-F0-9]{12}$" # 12 hexadecimal characters
67
+ )
68
+
69
+ @classmethod
70
+ def _id_example(cls, prefix: str):
71
+ """generates an example id for a given prefix"""
72
+ return f"{prefix}-123e4567-e89b-12d3-a456-426614174000"
73
+
74
+ @classmethod
75
+ def _id_description(cls, prefix: str):
76
+ """generates a factory function for a given prefix"""
77
+ return f"The human-friendly ID of the {prefix.capitalize()}"
78
+
79
+ @field_validator("id", check_fields=False, mode="before")
80
+ @classmethod
81
+ def allow_bare_uuids(cls, v, values):
82
+ """to ease the transition to stripe ids,
83
+ we allow bare uuids and convert them with a warning
84
+ """
85
+ _ = values # for SCA
86
+ if isinstance(v, UUID):
87
+ logger.debug(
88
+ f"Bare UUIDs are deprecated, please use the full prefixed id ({cls.__id_prefix__})!"
89
+ )
90
+ return f"{cls.__id_prefix__}-{v}"
91
+ return v
92
+
93
+
94
+ class OrmMetadataBase(MirixBase):
95
+ # metadata fields
96
+ created_by_id: Optional[str] = Field(
97
+ None, description="The id of the user that made this object."
98
+ )
99
+ last_updated_by_id: Optional[str] = Field(
100
+ None, description="The id of the user that made this object."
101
+ )
102
+ created_at: Optional[datetime] = Field(
103
+ None, description="The timestamp when the object was created."
104
+ )
105
+ updated_at: Optional[datetime] = Field(
106
+ None, description="The timestamp when the object was last updated."
107
+ )
@@ -0,0 +1,411 @@
1
+ import json
2
+ from datetime import datetime, timezone
3
+ from enum import Enum
4
+ from typing import Annotated, List, Literal, Optional, Union
5
+
6
+ from pydantic import BaseModel, Field, field_serializer, field_validator
7
+
8
+ from mirix.schemas.mirix_message_content import (
9
+ MirixAssistantMessageContentUnion,
10
+ MirixUserMessageContentUnion,
11
+ get_mirix_assistant_message_content_union_str_json_schema,
12
+ get_mirix_user_message_content_union_str_json_schema,
13
+ )
14
+
15
+ # ---------------------------
16
+ # Mirix API Messaging Schemas
17
+ # ---------------------------
18
+
19
+
20
+ class MessageType(str, Enum):
21
+ system_message = "system_message"
22
+ user_message = "user_message"
23
+ assistant_message = "assistant_message"
24
+ reasoning_message = "reasoning_message"
25
+ hidden_reasoning_message = "hidden_reasoning_message"
26
+ tool_call_message = "tool_call_message"
27
+ tool_return_message = "tool_return_message"
28
+
29
+
30
+ class MirixMessage(BaseModel):
31
+ """
32
+ Base class for simplified Mirix message response type. This is intended to be used for developers
33
+ who want the internal monologue, tool calls, and tool returns in a simplified format that does not
34
+ include additional information other than the content and timestamp.
35
+
36
+ Args:
37
+ id (str): The ID of the message
38
+ date (datetime): The date the message was created in ISO format
39
+ name (Optional[str]): The name of the sender of the message
40
+ message_type (MessageType): The type of the message
41
+ otid (Optional[str]): The offline threading id associated with this message
42
+ sender_id (Optional[str]): The id of the sender of the message, can be an identity id or agent id
43
+ """
44
+
45
+ id: str
46
+ date: datetime
47
+ name: Optional[str] = None
48
+ message_type: MessageType = Field(..., description="The type of the message.")
49
+ otid: Optional[str] = None
50
+ sender_id: Optional[str] = None
51
+
52
+ @field_serializer("date")
53
+ def serialize_datetime(self, dt: datetime, _info):
54
+ """
55
+ Remove microseconds since it seems like we're inconsistent with getting them
56
+ TODO: figure out why we don't always get microseconds (get_utc_time() does)
57
+ """
58
+ if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None:
59
+ dt = dt.replace(tzinfo=timezone.utc)
60
+ return dt.isoformat(timespec="seconds")
61
+
62
+
63
+ class SystemMessage(MirixMessage):
64
+ """
65
+ A message generated by the system. Never streamed back on a response, only used for cursor pagination.
66
+
67
+ Args:
68
+ id (str): The ID of the message
69
+ date (datetime): The date the message was created in ISO format
70
+ name (Optional[str]): The name of the sender of the message
71
+ content (str): The message content sent by the system
72
+ """
73
+
74
+ message_type: Literal[MessageType.system_message] = Field(
75
+ MessageType.system_message, description="The type of the message."
76
+ )
77
+ content: str = Field(..., description="The message content sent by the system")
78
+
79
+
80
+ class UserMessage(MirixMessage):
81
+ """
82
+ A message sent by the user. Never streamed back on a response, only used for cursor pagination.
83
+
84
+ Args:
85
+ id (str): The ID of the message
86
+ date (datetime): The date the message was created in ISO format
87
+ name (Optional[str]): The name of the sender of the message
88
+ content (Union[str, List[MirixUserMessageContentUnion]]): The message content sent by the user (can be a string or an array of multi-modal content parts)
89
+ """
90
+
91
+ message_type: Literal[MessageType.user_message] = Field(
92
+ MessageType.user_message, description="The type of the message."
93
+ )
94
+ content: Union[str, List[MirixUserMessageContentUnion]] = Field(
95
+ ...,
96
+ description="The message content sent by the user (can be a string or an array of multi-modal content parts)",
97
+ json_schema_extra=get_mirix_user_message_content_union_str_json_schema(),
98
+ )
99
+
100
+
101
+ class ReasoningMessage(MirixMessage):
102
+ """
103
+ Representation of an agent's internal reasoning.
104
+
105
+ Args:
106
+ id (str): The ID of the message
107
+ date (datetime): The date the message was created in ISO format
108
+ name (Optional[str]): The name of the sender of the message
109
+ source (Literal["reasoner_model", "non_reasoner_model"]): Whether the reasoning
110
+ content was generated natively by a reasoner model or derived via prompting
111
+ reasoning (str): The internal reasoning of the agent
112
+ signature (Optional[str]): The model-generated signature of the reasoning step
113
+ """
114
+
115
+ message_type: Literal[MessageType.reasoning_message] = Field(
116
+ MessageType.reasoning_message, description="The type of the message."
117
+ )
118
+ source: Literal["reasoner_model", "non_reasoner_model"] = "non_reasoner_model"
119
+ reasoning: str
120
+ signature: Optional[str] = None
121
+
122
+
123
+ class HiddenReasoningMessage(MirixMessage):
124
+ """
125
+ Representation of an agent's internal reasoning where reasoning content
126
+ has been hidden from the response.
127
+
128
+ Args:
129
+ id (str): The ID of the message
130
+ date (datetime): The date the message was created in ISO format
131
+ name (Optional[str]): The name of the sender of the message
132
+ state (Literal["redacted", "omitted"]): Whether the reasoning
133
+ content was redacted by the provider or simply omitted by the API
134
+ hidden_reasoning (Optional[str]): The internal reasoning of the agent
135
+ """
136
+
137
+ message_type: Literal[MessageType.hidden_reasoning_message] = Field(
138
+ MessageType.hidden_reasoning_message, description="The type of the message."
139
+ )
140
+ state: Literal["redacted", "omitted"]
141
+ hidden_reasoning: Optional[str] = None
142
+
143
+
144
+ class ToolCall(BaseModel):
145
+ name: str
146
+ arguments: str
147
+ tool_call_id: str
148
+
149
+
150
+ class ToolCallDelta(BaseModel):
151
+ name: Optional[str] = None
152
+ arguments: Optional[str] = None
153
+ tool_call_id: Optional[str] = None
154
+
155
+ def model_dump(self, *args, **kwargs):
156
+ """
157
+ This is a workaround to exclude None values from the JSON dump since the
158
+ OpenAI style of returning chunks doesn't include keys with null values.
159
+ """
160
+ kwargs["exclude_none"] = True
161
+ return super().model_dump(*args, **kwargs)
162
+
163
+ def json(self, *args, **kwargs):
164
+ return json.dumps(self.model_dump(exclude_none=True), *args, **kwargs)
165
+
166
+
167
+ class ToolCallMessage(MirixMessage):
168
+ """
169
+ A message representing a request to call a tool (generated by the LLM to trigger tool execution).
170
+
171
+ Args:
172
+ id (str): The ID of the message
173
+ date (datetime): The date the message was created in ISO format
174
+ name (Optional[str]): The name of the sender of the message
175
+ tool_call (Union[ToolCall, ToolCallDelta]): The tool call
176
+ """
177
+
178
+ message_type: Literal[MessageType.tool_call_message] = Field(
179
+ MessageType.tool_call_message, description="The type of the message."
180
+ )
181
+ tool_call: Union[ToolCall, ToolCallDelta]
182
+
183
+ def model_dump(self, *args, **kwargs):
184
+ """
185
+ Handling for the ToolCallDelta exclude_none to work correctly
186
+ """
187
+ kwargs["exclude_none"] = True
188
+ data = super().model_dump(*args, **kwargs)
189
+ if isinstance(data["tool_call"], dict):
190
+ data["tool_call"] = {
191
+ k: v for k, v in data["tool_call"].items() if v is not None
192
+ }
193
+ return data
194
+
195
+ class Config:
196
+ json_encoders = {
197
+ ToolCallDelta: lambda v: v.model_dump(exclude_none=True),
198
+ ToolCall: lambda v: v.model_dump(exclude_none=True),
199
+ }
200
+
201
+ @field_validator("tool_call", mode="before")
202
+ @classmethod
203
+ def validate_tool_call(cls, v):
204
+ """
205
+ Casts dicts into ToolCallMessage objects. Without this extra validator, Pydantic will throw
206
+ an error if 'name' or 'arguments' are None instead of properly casting to ToolCallDelta
207
+ instead of ToolCall.
208
+ """
209
+ if isinstance(v, dict):
210
+ if "name" in v and "arguments" in v and "tool_call_id" in v:
211
+ return ToolCall(
212
+ name=v["name"],
213
+ arguments=v["arguments"],
214
+ tool_call_id=v["tool_call_id"],
215
+ )
216
+ elif "name" in v or "arguments" in v or "tool_call_id" in v:
217
+ return ToolCallDelta(
218
+ name=v.get("name"),
219
+ arguments=v.get("arguments"),
220
+ tool_call_id=v.get("tool_call_id"),
221
+ )
222
+ else:
223
+ raise ValueError("tool_call must contain either 'name' or 'arguments'")
224
+ return v
225
+
226
+
227
+ class ToolReturnMessage(MirixMessage):
228
+ """
229
+ A message representing the return value of a tool call (generated by Mirix executing the requested tool).
230
+
231
+ Args:
232
+ id (str): The ID of the message
233
+ date (datetime): The date the message was created in ISO format
234
+ name (Optional[str]): The name of the sender of the message
235
+ tool_return (str): The return value of the tool
236
+ status (Literal["success", "error"]): The status of the tool call
237
+ tool_call_id (str): A unique identifier for the tool call that generated this message
238
+ stdout (Optional[List(str)]): Captured stdout (e.g. prints, logs) from the tool invocation
239
+ stderr (Optional[List(str)]): Captured stderr from the tool invocation
240
+ """
241
+
242
+ message_type: Literal[MessageType.tool_return_message] = Field(
243
+ MessageType.tool_return_message, description="The type of the message."
244
+ )
245
+ tool_return: str
246
+ status: Literal["success", "error"]
247
+ tool_call_id: str
248
+ stdout: Optional[List[str]] = None
249
+ stderr: Optional[List[str]] = None
250
+
251
+
252
+ class AssistantMessage(MirixMessage):
253
+ """
254
+ A message sent by the LLM in response to user input. Used in the LLM context.
255
+
256
+ Args:
257
+ id (str): The ID of the message
258
+ date (datetime): The date the message was created in ISO format
259
+ name (Optional[str]): The name of the sender of the message
260
+ content (Union[str, List[MirixAssistantMessageContentUnion]]): The message content sent by the agent (can be a string or an array of content parts)
261
+ """
262
+
263
+ message_type: Literal[MessageType.assistant_message] = Field(
264
+ MessageType.assistant_message, description="The type of the message."
265
+ )
266
+ content: Union[str, List[MirixAssistantMessageContentUnion]] = Field(
267
+ ...,
268
+ description="The message content sent by the agent (can be a string or an array of content parts)",
269
+ json_schema_extra=get_mirix_assistant_message_content_union_str_json_schema(),
270
+ )
271
+
272
+
273
+ # NOTE: use Pydantic's discriminated unions feature: https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions
274
+ MirixMessageUnion = Annotated[
275
+ Union[
276
+ SystemMessage,
277
+ UserMessage,
278
+ ReasoningMessage,
279
+ HiddenReasoningMessage,
280
+ ToolCallMessage,
281
+ ToolReturnMessage,
282
+ AssistantMessage,
283
+ ],
284
+ Field(discriminator="message_type"),
285
+ ]
286
+
287
+
288
+ def create_mirix_message_union_schema():
289
+ return {
290
+ "oneOf": [
291
+ {"$ref": "#/components/schemas/SystemMessage"},
292
+ {"$ref": "#/components/schemas/UserMessage"},
293
+ {"$ref": "#/components/schemas/ReasoningMessage"},
294
+ {"$ref": "#/components/schemas/HiddenReasoningMessage"},
295
+ {"$ref": "#/components/schemas/ToolCallMessage"},
296
+ {"$ref": "#/components/schemas/ToolReturnMessage"},
297
+ {"$ref": "#/components/schemas/AssistantMessage"},
298
+ ],
299
+ "discriminator": {
300
+ "propertyName": "message_type",
301
+ "mapping": {
302
+ "system_message": "#/components/schemas/SystemMessage",
303
+ "user_message": "#/components/schemas/UserMessage",
304
+ "reasoning_message": "#/components/schemas/ReasoningMessage",
305
+ "hidden_reasoning_message": "#/components/schemas/HiddenReasoningMessage",
306
+ "tool_call_message": "#/components/schemas/ToolCallMessage",
307
+ "tool_return_message": "#/components/schemas/ToolReturnMessage",
308
+ "assistant_message": "#/components/schemas/AssistantMessage",
309
+ },
310
+ },
311
+ }
312
+
313
+
314
+ # --------------------------
315
+ # Message Update API Schemas
316
+ # --------------------------
317
+
318
+
319
+ class UpdateSystemMessage(BaseModel):
320
+ message_type: Literal["system_message"] = "system_message"
321
+ content: str = Field(
322
+ ...,
323
+ description="The message content sent by the system (can be a string or an array of multi-modal content parts)",
324
+ )
325
+
326
+
327
+ class UpdateUserMessage(BaseModel):
328
+ message_type: Literal["user_message"] = "user_message"
329
+ content: Union[str, List[MirixUserMessageContentUnion]] = Field(
330
+ ...,
331
+ description="The message content sent by the user (can be a string or an array of multi-modal content parts)",
332
+ json_schema_extra=get_mirix_user_message_content_union_str_json_schema(),
333
+ )
334
+
335
+
336
+ class UpdateReasoningMessage(BaseModel):
337
+ reasoning: str
338
+ message_type: Literal["reasoning_message"] = "reasoning_message"
339
+
340
+
341
+ class UpdateAssistantMessage(BaseModel):
342
+ message_type: Literal["assistant_message"] = "assistant_message"
343
+ content: Union[str, List[MirixAssistantMessageContentUnion]] = Field(
344
+ ...,
345
+ description="The message content sent by the assistant (can be a string or an array of content parts)",
346
+ json_schema_extra=get_mirix_assistant_message_content_union_str_json_schema(),
347
+ )
348
+
349
+
350
+ MirixMessageUpdateUnion = Annotated[
351
+ Union[
352
+ UpdateSystemMessage,
353
+ UpdateUserMessage,
354
+ UpdateReasoningMessage,
355
+ UpdateAssistantMessage,
356
+ ],
357
+ Field(discriminator="message_type"),
358
+ ]
359
+
360
+
361
+ # --------------------------
362
+ # Deprecated Message Schemas
363
+ # --------------------------
364
+
365
+
366
+ class LegacyFunctionCallMessage(MirixMessage):
367
+ function_call: str
368
+
369
+
370
+ class LegacyFunctionReturn(MirixMessage):
371
+ """
372
+ A message representing the return value of a function call (generated by Mirix executing the requested function).
373
+
374
+ Args:
375
+ function_return (str): The return value of the function
376
+ status (Literal["success", "error"]): The status of the function call
377
+ id (str): The ID of the message
378
+ date (datetime): The date the message was created in ISO format
379
+ function_call_id (str): A unique identifier for the function call that generated this message
380
+ stdout (Optional[List(str)]): Captured stdout (e.g. prints, logs) from the function invocation
381
+ stderr (Optional[List(str)]): Captured stderr from the function invocation
382
+ """
383
+
384
+ message_type: Literal["function_return"] = "function_return"
385
+ function_return: str
386
+ status: Literal["success", "error"]
387
+ function_call_id: str
388
+ stdout: Optional[List[str]] = None
389
+ stderr: Optional[List[str]] = None
390
+
391
+
392
+ class LegacyInternalMonologue(MirixMessage):
393
+ """
394
+ Representation of an agent's internal monologue.
395
+
396
+ Args:
397
+ internal_monologue (str): The internal monologue of the agent
398
+ id (str): The ID of the message
399
+ date (datetime): The date the message was created in ISO format
400
+ """
401
+
402
+ message_type: Literal["internal_monologue"] = "internal_monologue"
403
+ internal_monologue: str
404
+
405
+
406
+ LegacyMirixMessage = Union[
407
+ LegacyInternalMonologue,
408
+ AssistantMessage,
409
+ LegacyFunctionCallMessage,
410
+ LegacyFunctionReturn,
411
+ ]