letta-nightly 0.6.39.dev20250314104053__py3-none-any.whl → 0.6.40.dev20250314173529__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 letta-nightly might be problematic. Click here for more details.
- letta/agent.py +13 -3
- letta/agents/ephemeral_agent.py +2 -1
- letta/agents/low_latency_agent.py +8 -0
- letta/dynamic_multi_agent.py +274 -0
- letta/functions/function_sets/base.py +1 -0
- letta/functions/function_sets/extras.py +2 -1
- letta/functions/function_sets/multi_agent.py +17 -0
- letta/functions/helpers.py +41 -0
- letta/helpers/converters.py +67 -0
- letta/helpers/mcp_helpers.py +26 -5
- letta/llm_api/openai.py +1 -1
- letta/memory.py +2 -1
- letta/orm/__init__.py +2 -0
- letta/orm/agent.py +69 -20
- letta/orm/custom_columns.py +15 -0
- letta/orm/group.py +33 -0
- letta/orm/groups_agents.py +13 -0
- letta/orm/message.py +7 -4
- letta/orm/organization.py +1 -0
- letta/orm/sqlalchemy_base.py +3 -3
- letta/round_robin_multi_agent.py +152 -0
- letta/schemas/agent.py +3 -0
- letta/schemas/enums.py +0 -4
- letta/schemas/group.py +65 -0
- letta/schemas/letta_message.py +167 -106
- letta/schemas/letta_message_content.py +192 -0
- letta/schemas/message.py +28 -36
- letta/serialize_schemas/__init__.py +1 -1
- letta/serialize_schemas/marshmallow_agent.py +108 -0
- letta/serialize_schemas/{agent_environment_variable.py → marshmallow_agent_environment_variable.py} +1 -1
- letta/serialize_schemas/marshmallow_base.py +52 -0
- letta/serialize_schemas/{block.py → marshmallow_block.py} +1 -1
- letta/serialize_schemas/{custom_fields.py → marshmallow_custom_fields.py} +12 -0
- letta/serialize_schemas/marshmallow_message.py +42 -0
- letta/serialize_schemas/{tag.py → marshmallow_tag.py} +12 -2
- letta/serialize_schemas/{tool.py → marshmallow_tool.py} +1 -1
- letta/serialize_schemas/pydantic_agent_schema.py +111 -0
- letta/server/rest_api/app.py +15 -0
- letta/server/rest_api/routers/v1/__init__.py +2 -0
- letta/server/rest_api/routers/v1/agents.py +46 -40
- letta/server/rest_api/routers/v1/groups.py +233 -0
- letta/server/rest_api/routers/v1/tools.py +31 -3
- letta/server/rest_api/utils.py +1 -1
- letta/server/server.py +267 -12
- letta/services/agent_manager.py +65 -28
- letta/services/group_manager.py +147 -0
- letta/services/helpers/agent_manager_helper.py +151 -1
- letta/services/message_manager.py +11 -3
- letta/services/passage_manager.py +15 -0
- letta/settings.py +5 -0
- letta/supervisor_multi_agent.py +103 -0
- {letta_nightly-0.6.39.dev20250314104053.dist-info → letta_nightly-0.6.40.dev20250314173529.dist-info}/METADATA +1 -2
- {letta_nightly-0.6.39.dev20250314104053.dist-info → letta_nightly-0.6.40.dev20250314173529.dist-info}/RECORD +56 -46
- letta/serialize_schemas/agent.py +0 -80
- letta/serialize_schemas/base.py +0 -64
- letta/serialize_schemas/message.py +0 -29
- {letta_nightly-0.6.39.dev20250314104053.dist-info → letta_nightly-0.6.40.dev20250314173529.dist-info}/LICENSE +0 -0
- {letta_nightly-0.6.39.dev20250314104053.dist-info → letta_nightly-0.6.40.dev20250314173529.dist-info}/WHEEL +0 -0
- {letta_nightly-0.6.39.dev20250314104053.dist-info → letta_nightly-0.6.40.dev20250314173529.dist-info}/entry_points.txt +0 -0
letta/schemas/letta_message.py
CHANGED
|
@@ -4,109 +4,132 @@ from typing import Annotated, List, Literal, Optional, Union
|
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel, Field, field_serializer, field_validator
|
|
6
6
|
|
|
7
|
-
from letta.schemas.
|
|
7
|
+
from letta.schemas.letta_message_content import (
|
|
8
|
+
LettaAssistantMessageContentUnion,
|
|
9
|
+
LettaUserMessageContentUnion,
|
|
10
|
+
get_letta_assistant_message_content_union_str_json_schema,
|
|
11
|
+
get_letta_user_message_content_union_str_json_schema,
|
|
12
|
+
)
|
|
8
13
|
|
|
9
|
-
#
|
|
14
|
+
# ---------------------------
|
|
15
|
+
# Letta API Messaging Schemas
|
|
16
|
+
# ---------------------------
|
|
10
17
|
|
|
11
18
|
|
|
12
19
|
class LettaMessage(BaseModel):
|
|
13
20
|
"""
|
|
14
|
-
Base class for simplified Letta message response type. This is intended to be used for developers
|
|
21
|
+
Base class for simplified Letta message response type. This is intended to be used for developers
|
|
22
|
+
who want the internal monologue, tool calls, and tool returns in a simplified format that does not
|
|
23
|
+
include additional information other than the content and timestamp.
|
|
15
24
|
|
|
16
|
-
|
|
25
|
+
Args:
|
|
17
26
|
id (str): The ID of the message
|
|
18
27
|
date (datetime): The date the message was created in ISO format
|
|
19
|
-
|
|
28
|
+
name (Optional[str]): The name of the sender of the message
|
|
20
29
|
"""
|
|
21
30
|
|
|
22
|
-
# NOTE: use Pydantic's discriminated unions feature: https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions
|
|
23
|
-
# see `message_type` attribute
|
|
24
|
-
|
|
25
31
|
id: str
|
|
26
32
|
date: datetime
|
|
33
|
+
name: Optional[str] = None
|
|
27
34
|
|
|
28
35
|
@field_serializer("date")
|
|
29
36
|
def serialize_datetime(self, dt: datetime, _info):
|
|
37
|
+
"""
|
|
38
|
+
Remove microseconds since it seems like we're inconsistent with getting them
|
|
39
|
+
TODO: figure out why we don't always get microseconds (get_utc_time() does)
|
|
40
|
+
"""
|
|
30
41
|
if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None:
|
|
31
42
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
32
|
-
# Remove microseconds since it seems like we're inconsistent with getting them
|
|
33
|
-
# TODO figure out why we don't always get microseconds (get_utc_time() does)
|
|
34
43
|
return dt.isoformat(timespec="seconds")
|
|
35
44
|
|
|
36
45
|
|
|
37
|
-
class MessageContent(BaseModel):
|
|
38
|
-
type: MessageContentType = Field(..., description="The type of the message.")
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class TextContent(MessageContent):
|
|
42
|
-
type: Literal[MessageContentType.text] = Field(MessageContentType.text, description="The type of the message.")
|
|
43
|
-
text: str = Field(..., description="The text content of the message.")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
MessageContentUnion = Annotated[
|
|
47
|
-
Union[TextContent],
|
|
48
|
-
Field(discriminator="type"),
|
|
49
|
-
]
|
|
50
|
-
|
|
51
|
-
|
|
52
46
|
class SystemMessage(LettaMessage):
|
|
53
47
|
"""
|
|
54
48
|
A message generated by the system. Never streamed back on a response, only used for cursor pagination.
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
content (Union[str, List[MessageContentUnion]]): The message content sent by the user (can be a string or an array of content parts)
|
|
50
|
+
Args:
|
|
58
51
|
id (str): The ID of the message
|
|
59
52
|
date (datetime): The date the message was created in ISO format
|
|
53
|
+
name (Optional[str]): The name of the sender of the message
|
|
54
|
+
content (str): The message content sent by the system
|
|
60
55
|
"""
|
|
61
56
|
|
|
62
57
|
message_type: Literal["system_message"] = "system_message"
|
|
63
|
-
content:
|
|
58
|
+
content: str = Field(..., description="The message content sent by the system")
|
|
64
59
|
|
|
65
60
|
|
|
66
61
|
class UserMessage(LettaMessage):
|
|
67
62
|
"""
|
|
68
63
|
A message sent by the user. Never streamed back on a response, only used for cursor pagination.
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
content (Union[str, List[MessageContentUnion]]): The message content sent by the user (can be a string or an array of content parts)
|
|
65
|
+
Args:
|
|
72
66
|
id (str): The ID of the message
|
|
73
67
|
date (datetime): The date the message was created in ISO format
|
|
68
|
+
name (Optional[str]): The name of the sender of the message
|
|
69
|
+
content (Union[str, List[LettaUserMessageContentUnion]]): The message content sent by the user (can be a string or an array of multi-modal content parts)
|
|
74
70
|
"""
|
|
75
71
|
|
|
76
72
|
message_type: Literal["user_message"] = "user_message"
|
|
77
|
-
content: Union[str, List[
|
|
73
|
+
content: Union[str, List[LettaUserMessageContentUnion]] = Field(
|
|
74
|
+
...,
|
|
75
|
+
description="The message content sent by the user (can be a string or an array of multi-modal content parts)",
|
|
76
|
+
json_schema_extra=get_letta_user_message_content_union_str_json_schema(),
|
|
77
|
+
)
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
class ReasoningMessage(LettaMessage):
|
|
81
81
|
"""
|
|
82
82
|
Representation of an agent's internal reasoning.
|
|
83
83
|
|
|
84
|
-
|
|
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
|
+
source (Literal["reasoner_model", "non_reasoner_model"]): Whether the reasoning
|
|
89
|
+
content was generated natively by a reasoner model or derived via prompting
|
|
85
90
|
reasoning (str): The internal reasoning of the agent
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
message_type: Literal["reasoning_message"] = "reasoning_message"
|
|
94
|
+
source: Literal["reasoner_model", "non_reasoner_model"] = "non_reasoner_model"
|
|
95
|
+
reasoning: str
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class HiddenReasoningMessage(LettaMessage):
|
|
99
|
+
"""
|
|
100
|
+
Representation of an agent's internal reasoning where reasoning content
|
|
101
|
+
has been hidden from the response.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
86
104
|
id (str): The ID of the message
|
|
87
105
|
date (datetime): The date the message was created in ISO format
|
|
106
|
+
name (Optional[str]): The name of the sender of the message
|
|
107
|
+
state (Literal["redacted", "omitted"]): Whether the reasoning
|
|
108
|
+
content was redacted by the provider or simply omitted by the API
|
|
109
|
+
reasoning (str): The internal reasoning of the agent
|
|
88
110
|
"""
|
|
89
111
|
|
|
90
112
|
message_type: Literal["reasoning_message"] = "reasoning_message"
|
|
113
|
+
state: Literal["redacted", "omitted"]
|
|
91
114
|
reasoning: str
|
|
92
115
|
|
|
93
116
|
|
|
94
117
|
class ToolCall(BaseModel):
|
|
95
|
-
|
|
96
118
|
name: str
|
|
97
119
|
arguments: str
|
|
98
120
|
tool_call_id: str
|
|
99
121
|
|
|
100
122
|
|
|
101
123
|
class ToolCallDelta(BaseModel):
|
|
102
|
-
|
|
103
124
|
name: Optional[str]
|
|
104
125
|
arguments: Optional[str]
|
|
105
126
|
tool_call_id: Optional[str]
|
|
106
127
|
|
|
107
|
-
# NOTE: this is a workaround to exclude None values from the JSON dump,
|
|
108
|
-
# since the OpenAI style of returning chunks doesn't include keys with null values
|
|
109
128
|
def model_dump(self, *args, **kwargs):
|
|
129
|
+
"""
|
|
130
|
+
This is a workaround to exclude None values from the JSON dump since the
|
|
131
|
+
OpenAI style of returning chunks doesn't include keys with null values.
|
|
132
|
+
"""
|
|
110
133
|
kwargs["exclude_none"] = True
|
|
111
134
|
return super().model_dump(*args, **kwargs)
|
|
112
135
|
|
|
@@ -118,17 +141,20 @@ class ToolCallMessage(LettaMessage):
|
|
|
118
141
|
"""
|
|
119
142
|
A message representing a request to call a tool (generated by the LLM to trigger tool execution).
|
|
120
143
|
|
|
121
|
-
|
|
122
|
-
tool_call (Union[ToolCall, ToolCallDelta]): The tool call
|
|
144
|
+
Args:
|
|
123
145
|
id (str): The ID of the message
|
|
124
146
|
date (datetime): The date the message was created in ISO format
|
|
147
|
+
name (Optional[str]): The name of the sender of the message
|
|
148
|
+
tool_call (Union[ToolCall, ToolCallDelta]): The tool call
|
|
125
149
|
"""
|
|
126
150
|
|
|
127
151
|
message_type: Literal["tool_call_message"] = "tool_call_message"
|
|
128
152
|
tool_call: Union[ToolCall, ToolCallDelta]
|
|
129
153
|
|
|
130
|
-
# NOTE: this is required for the ToolCallDelta exclude_none to work correctly
|
|
131
154
|
def model_dump(self, *args, **kwargs):
|
|
155
|
+
"""
|
|
156
|
+
Handling for the ToolCallDelta exclude_none to work correctly
|
|
157
|
+
"""
|
|
132
158
|
kwargs["exclude_none"] = True
|
|
133
159
|
data = super().model_dump(*args, **kwargs)
|
|
134
160
|
if isinstance(data["tool_call"], dict):
|
|
@@ -141,12 +167,14 @@ class ToolCallMessage(LettaMessage):
|
|
|
141
167
|
ToolCall: lambda v: v.model_dump(exclude_none=True),
|
|
142
168
|
}
|
|
143
169
|
|
|
144
|
-
# NOTE: this is required to cast dicts into ToolCallMessage objects
|
|
145
|
-
# Without this extra validator, Pydantic will throw an error if 'name' or 'arguments' are None
|
|
146
|
-
# (instead of properly casting to ToolCallDelta instead of ToolCall)
|
|
147
170
|
@field_validator("tool_call", mode="before")
|
|
148
171
|
@classmethod
|
|
149
172
|
def validate_tool_call(cls, v):
|
|
173
|
+
"""
|
|
174
|
+
Casts dicts into ToolCallMessage objects. Without this extra validator, Pydantic will throw
|
|
175
|
+
an error if 'name' or 'arguments' are None instead of properly casting to ToolCallDelta
|
|
176
|
+
instead of ToolCall.
|
|
177
|
+
"""
|
|
150
178
|
if isinstance(v, dict):
|
|
151
179
|
if "name" in v and "arguments" in v and "tool_call_id" in v:
|
|
152
180
|
return ToolCall(name=v["name"], arguments=v["arguments"], tool_call_id=v["tool_call_id"])
|
|
@@ -161,11 +189,12 @@ class ToolReturnMessage(LettaMessage):
|
|
|
161
189
|
"""
|
|
162
190
|
A message representing the return value of a tool call (generated by Letta executing the requested tool).
|
|
163
191
|
|
|
164
|
-
|
|
165
|
-
tool_return (str): The return value of the tool
|
|
166
|
-
status (Literal["success", "error"]): The status of the tool call
|
|
192
|
+
Args:
|
|
167
193
|
id (str): The ID of the message
|
|
168
194
|
date (datetime): The date the message was created in ISO format
|
|
195
|
+
name (Optional[str]): The name of the sender of the message
|
|
196
|
+
tool_return (str): The return value of the tool
|
|
197
|
+
status (Literal["success", "error"]): The status of the tool call
|
|
169
198
|
tool_call_id (str): A unique identifier for the tool call that generated this message
|
|
170
199
|
stdout (Optional[List(str)]): Captured stdout (e.g. prints, logs) from the tool invocation
|
|
171
200
|
stderr (Optional[List(str)]): Captured stderr from the tool invocation
|
|
@@ -179,12 +208,100 @@ class ToolReturnMessage(LettaMessage):
|
|
|
179
208
|
stderr: Optional[List[str]] = None
|
|
180
209
|
|
|
181
210
|
|
|
182
|
-
|
|
211
|
+
class AssistantMessage(LettaMessage):
|
|
212
|
+
"""
|
|
213
|
+
A message sent by the LLM in response to user input. Used in the LLM context.
|
|
183
214
|
|
|
215
|
+
Args:
|
|
216
|
+
id (str): The ID of the message
|
|
217
|
+
date (datetime): The date the message was created in ISO format
|
|
218
|
+
name (Optional[str]): The name of the sender of the message
|
|
219
|
+
content (Union[str, List[LettaAssistantMessageContentUnion]]): The message content sent by the agent (can be a string or an array of content parts)
|
|
220
|
+
"""
|
|
184
221
|
|
|
185
|
-
class AssistantMessage(LettaMessage):
|
|
186
222
|
message_type: Literal["assistant_message"] = "assistant_message"
|
|
187
|
-
content: Union[str, List[
|
|
223
|
+
content: Union[str, List[LettaAssistantMessageContentUnion]] = Field(
|
|
224
|
+
...,
|
|
225
|
+
description="The message content sent by the agent (can be a string or an array of content parts)",
|
|
226
|
+
json_schema_extra=get_letta_assistant_message_content_union_str_json_schema(),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# NOTE: use Pydantic's discriminated unions feature: https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions
|
|
231
|
+
LettaMessageUnion = Annotated[
|
|
232
|
+
Union[SystemMessage, UserMessage, ReasoningMessage, ToolCallMessage, ToolReturnMessage, AssistantMessage],
|
|
233
|
+
Field(discriminator="message_type"),
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def create_letta_message_union_schema():
|
|
238
|
+
return {
|
|
239
|
+
"oneOf": [
|
|
240
|
+
{"$ref": "#/components/schemas/SystemMessage"},
|
|
241
|
+
{"$ref": "#/components/schemas/UserMessage"},
|
|
242
|
+
{"$ref": "#/components/schemas/ReasoningMessage"},
|
|
243
|
+
{"$ref": "#/components/schemas/ToolCallMessage"},
|
|
244
|
+
{"$ref": "#/components/schemas/ToolReturnMessage"},
|
|
245
|
+
{"$ref": "#/components/schemas/AssistantMessage"},
|
|
246
|
+
],
|
|
247
|
+
"discriminator": {
|
|
248
|
+
"propertyName": "message_type",
|
|
249
|
+
"mapping": {
|
|
250
|
+
"system_message": "#/components/schemas/SystemMessage",
|
|
251
|
+
"user_message": "#/components/schemas/UserMessage",
|
|
252
|
+
"reasoning_message": "#/components/schemas/ReasoningMessage",
|
|
253
|
+
"tool_call_message": "#/components/schemas/ToolCallMessage",
|
|
254
|
+
"tool_return_message": "#/components/schemas/ToolReturnMessage",
|
|
255
|
+
"assistant_message": "#/components/schemas/AssistantMessage",
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
# --------------------------
|
|
262
|
+
# Message Update API Schemas
|
|
263
|
+
# --------------------------
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class UpdateSystemMessage(BaseModel):
|
|
267
|
+
message_type: Literal["system_message"] = "system_message"
|
|
268
|
+
content: str = Field(
|
|
269
|
+
..., description="The message content sent by the system (can be a string or an array of multi-modal content parts)"
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class UpdateUserMessage(BaseModel):
|
|
274
|
+
message_type: Literal["user_message"] = "user_message"
|
|
275
|
+
content: Union[str, List[LettaUserMessageContentUnion]] = Field(
|
|
276
|
+
...,
|
|
277
|
+
description="The message content sent by the user (can be a string or an array of multi-modal content parts)",
|
|
278
|
+
json_schema_extra=get_letta_user_message_content_union_str_json_schema(),
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
class UpdateReasoningMessage(BaseModel):
|
|
283
|
+
reasoning: str
|
|
284
|
+
message_type: Literal["reasoning_message"] = "reasoning_message"
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class UpdateAssistantMessage(BaseModel):
|
|
288
|
+
message_type: Literal["assistant_message"] = "assistant_message"
|
|
289
|
+
content: Union[str, List[LettaAssistantMessageContentUnion]] = Field(
|
|
290
|
+
...,
|
|
291
|
+
description="The message content sent by the assistant (can be a string or an array of content parts)",
|
|
292
|
+
json_schema_extra=get_letta_assistant_message_content_union_str_json_schema(),
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
LettaMessageUpdateUnion = Annotated[
|
|
297
|
+
Union[UpdateSystemMessage, UpdateUserMessage, UpdateReasoningMessage, UpdateAssistantMessage],
|
|
298
|
+
Field(discriminator="message_type"),
|
|
299
|
+
]
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
# --------------------------
|
|
303
|
+
# Deprecated Message Schemas
|
|
304
|
+
# --------------------------
|
|
188
305
|
|
|
189
306
|
|
|
190
307
|
class LegacyFunctionCallMessage(LettaMessage):
|
|
@@ -195,7 +312,7 @@ class LegacyFunctionReturn(LettaMessage):
|
|
|
195
312
|
"""
|
|
196
313
|
A message representing the return value of a function call (generated by Letta executing the requested function).
|
|
197
314
|
|
|
198
|
-
|
|
315
|
+
Args:
|
|
199
316
|
function_return (str): The return value of the function
|
|
200
317
|
status (Literal["success", "error"]): The status of the function call
|
|
201
318
|
id (str): The ID of the message
|
|
@@ -217,7 +334,7 @@ class LegacyInternalMonologue(LettaMessage):
|
|
|
217
334
|
"""
|
|
218
335
|
Representation of an agent's internal monologue.
|
|
219
336
|
|
|
220
|
-
|
|
337
|
+
Args:
|
|
221
338
|
internal_monologue (str): The internal monologue of the agent
|
|
222
339
|
id (str): The ID of the message
|
|
223
340
|
date (datetime): The date the message was created in ISO format
|
|
@@ -228,59 +345,3 @@ class LegacyInternalMonologue(LettaMessage):
|
|
|
228
345
|
|
|
229
346
|
|
|
230
347
|
LegacyLettaMessage = Union[LegacyInternalMonologue, AssistantMessage, LegacyFunctionCallMessage, LegacyFunctionReturn]
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
LettaMessageUnion = Annotated[
|
|
234
|
-
Union[SystemMessage, UserMessage, ReasoningMessage, ToolCallMessage, ToolReturnMessage, AssistantMessage],
|
|
235
|
-
Field(discriminator="message_type"),
|
|
236
|
-
]
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
class UpdateSystemMessage(BaseModel):
|
|
240
|
-
content: Union[str, List[MessageContentUnion]]
|
|
241
|
-
message_type: Literal["system_message"] = "system_message"
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
class UpdateUserMessage(BaseModel):
|
|
245
|
-
content: Union[str, List[MessageContentUnion]]
|
|
246
|
-
message_type: Literal["user_message"] = "user_message"
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
class UpdateReasoningMessage(BaseModel):
|
|
250
|
-
reasoning: Union[str, List[MessageContentUnion]]
|
|
251
|
-
message_type: Literal["reasoning_message"] = "reasoning_message"
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
class UpdateAssistantMessage(BaseModel):
|
|
255
|
-
content: Union[str, List[MessageContentUnion]]
|
|
256
|
-
message_type: Literal["assistant_message"] = "assistant_message"
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
LettaMessageUpdateUnion = Annotated[
|
|
260
|
-
Union[UpdateSystemMessage, UpdateUserMessage, UpdateReasoningMessage, UpdateAssistantMessage],
|
|
261
|
-
Field(discriminator="message_type"),
|
|
262
|
-
]
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
def create_letta_message_union_schema():
|
|
266
|
-
return {
|
|
267
|
-
"oneOf": [
|
|
268
|
-
{"$ref": "#/components/schemas/SystemMessage"},
|
|
269
|
-
{"$ref": "#/components/schemas/UserMessage"},
|
|
270
|
-
{"$ref": "#/components/schemas/ReasoningMessage"},
|
|
271
|
-
{"$ref": "#/components/schemas/ToolCallMessage"},
|
|
272
|
-
{"$ref": "#/components/schemas/ToolReturnMessage"},
|
|
273
|
-
{"$ref": "#/components/schemas/AssistantMessage"},
|
|
274
|
-
],
|
|
275
|
-
"discriminator": {
|
|
276
|
-
"propertyName": "message_type",
|
|
277
|
-
"mapping": {
|
|
278
|
-
"system_message": "#/components/schemas/SystemMessage",
|
|
279
|
-
"user_message": "#/components/schemas/UserMessage",
|
|
280
|
-
"reasoning_message": "#/components/schemas/ReasoningMessage",
|
|
281
|
-
"tool_call_message": "#/components/schemas/ToolCallMessage",
|
|
282
|
-
"tool_return_message": "#/components/schemas/ToolReturnMessage",
|
|
283
|
-
"assistant_message": "#/components/schemas/AssistantMessage",
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Annotated, Literal, Optional, Union
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MessageContentType(str, Enum):
|
|
8
|
+
text = "text"
|
|
9
|
+
tool_call = "tool_call"
|
|
10
|
+
tool_return = "tool_return"
|
|
11
|
+
reasoning = "reasoning"
|
|
12
|
+
redacted_reasoning = "redacted_reasoning"
|
|
13
|
+
omitted_reasoning = "omitted_reasoning"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MessageContent(BaseModel):
|
|
17
|
+
type: MessageContentType = Field(..., description="The type of the message.")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# -------------------------------
|
|
21
|
+
# User Content Types
|
|
22
|
+
# -------------------------------
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TextContent(MessageContent):
|
|
26
|
+
type: Literal[MessageContentType.text] = Field(MessageContentType.text, description="The type of the message.")
|
|
27
|
+
text: str = Field(..., description="The text content of the message.")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
LettaUserMessageContentUnion = Annotated[
|
|
31
|
+
Union[TextContent],
|
|
32
|
+
Field(discriminator="type"),
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def create_letta_user_message_content_union_schema():
|
|
37
|
+
return {
|
|
38
|
+
"oneOf": [
|
|
39
|
+
{"$ref": "#/components/schemas/TextContent"},
|
|
40
|
+
],
|
|
41
|
+
"discriminator": {
|
|
42
|
+
"propertyName": "type",
|
|
43
|
+
"mapping": {
|
|
44
|
+
"text": "#/components/schemas/TextContent",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_letta_user_message_content_union_str_json_schema():
|
|
51
|
+
return {
|
|
52
|
+
"anyOf": [
|
|
53
|
+
{
|
|
54
|
+
"type": "array",
|
|
55
|
+
"items": {
|
|
56
|
+
"$ref": "#/components/schemas/LettaUserMessageContentUnion",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{"type": "string"},
|
|
60
|
+
],
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# -------------------------------
|
|
65
|
+
# Assistant Content Types
|
|
66
|
+
# -------------------------------
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
LettaAssistantMessageContentUnion = Annotated[
|
|
70
|
+
Union[TextContent],
|
|
71
|
+
Field(discriminator="type"),
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def create_letta_assistant_message_content_union_schema():
|
|
76
|
+
return {
|
|
77
|
+
"oneOf": [
|
|
78
|
+
{"$ref": "#/components/schemas/TextContent"},
|
|
79
|
+
],
|
|
80
|
+
"discriminator": {
|
|
81
|
+
"propertyName": "type",
|
|
82
|
+
"mapping": {
|
|
83
|
+
"text": "#/components/schemas/TextContent",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def get_letta_assistant_message_content_union_str_json_schema():
|
|
90
|
+
return {
|
|
91
|
+
"anyOf": [
|
|
92
|
+
{
|
|
93
|
+
"type": "array",
|
|
94
|
+
"items": {
|
|
95
|
+
"$ref": "#/components/schemas/LettaAssistantMessageContentUnion",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{"type": "string"},
|
|
99
|
+
],
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# -------------------------------
|
|
104
|
+
# Intermediate Step Content Types
|
|
105
|
+
# -------------------------------
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class ToolCallContent(MessageContent):
|
|
109
|
+
type: Literal[MessageContentType.tool_call] = Field(
|
|
110
|
+
MessageContentType.tool_call, description="Indicates this content represents a tool call event."
|
|
111
|
+
)
|
|
112
|
+
id: str = Field(..., description="A unique identifier for this specific tool call instance.")
|
|
113
|
+
name: str = Field(..., description="The name of the tool being called.")
|
|
114
|
+
input: dict = Field(
|
|
115
|
+
..., description="The parameters being passed to the tool, structured as a dictionary of parameter names to values."
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ToolReturnContent(MessageContent):
|
|
120
|
+
type: Literal[MessageContentType.tool_return] = Field(
|
|
121
|
+
MessageContentType.tool_return, description="Indicates this content represents a tool return event."
|
|
122
|
+
)
|
|
123
|
+
tool_call_id: str = Field(..., description="References the ID of the ToolCallContent that initiated this tool call.")
|
|
124
|
+
content: str = Field(..., description="The content returned by the tool execution.")
|
|
125
|
+
is_error: bool = Field(..., description="Indicates whether the tool execution resulted in an error.")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class ReasoningContent(MessageContent):
|
|
129
|
+
type: Literal[MessageContentType.reasoning] = Field(
|
|
130
|
+
MessageContentType.reasoning, description="Indicates this is a reasoning/intermediate step."
|
|
131
|
+
)
|
|
132
|
+
is_native: bool = Field(..., description="Whether the reasoning content was generated by a reasoner model that processed this step.")
|
|
133
|
+
reasoning: str = Field(..., description="The intermediate reasoning or thought process content.")
|
|
134
|
+
signature: Optional[str] = Field(None, description="A unique identifier for this reasoning step.")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class RedactedReasoningContent(MessageContent):
|
|
138
|
+
type: Literal[MessageContentType.redacted_reasoning] = Field(
|
|
139
|
+
MessageContentType.redacted_reasoning, description="Indicates this is a redacted thinking step."
|
|
140
|
+
)
|
|
141
|
+
data: str = Field(..., description="The redacted or filtered intermediate reasoning content.")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class OmittedReasoningContent(MessageContent):
|
|
145
|
+
type: Literal[MessageContentType.omitted_reasoning] = Field(
|
|
146
|
+
MessageContentType.omitted_reasoning, description="Indicates this is an omitted reasoning step."
|
|
147
|
+
)
|
|
148
|
+
tokens: int = Field(..., description="The reasoning token count for intermediate reasoning content.")
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
LettaMessageContentUnion = Annotated[
|
|
152
|
+
Union[TextContent, ToolCallContent, ToolReturnContent, ReasoningContent, RedactedReasoningContent, OmittedReasoningContent],
|
|
153
|
+
Field(discriminator="type"),
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def create_letta_message_content_union_schema():
|
|
158
|
+
return {
|
|
159
|
+
"oneOf": [
|
|
160
|
+
{"$ref": "#/components/schemas/TextContent"},
|
|
161
|
+
{"$ref": "#/components/schemas/ToolCallContent"},
|
|
162
|
+
{"$ref": "#/components/schemas/ToolReturnContent"},
|
|
163
|
+
{"$ref": "#/components/schemas/ReasoningContent"},
|
|
164
|
+
{"$ref": "#/components/schemas/RedactedReasoningContent"},
|
|
165
|
+
{"$ref": "#/components/schemas/OmittedReasoningContent"},
|
|
166
|
+
],
|
|
167
|
+
"discriminator": {
|
|
168
|
+
"propertyName": "type",
|
|
169
|
+
"mapping": {
|
|
170
|
+
"text": "#/components/schemas/TextContent",
|
|
171
|
+
"tool_call": "#/components/schemas/ToolCallContent",
|
|
172
|
+
"tool_return": "#/components/schemas/ToolCallContent",
|
|
173
|
+
"reasoning": "#/components/schemas/ReasoningContent",
|
|
174
|
+
"redacted_reasoning": "#/components/schemas/RedactedReasoningContent",
|
|
175
|
+
"omitted_reasoning": "#/components/schemas/OmittedReasoningContent",
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def get_letta_message_content_union_str_json_schema():
|
|
182
|
+
return {
|
|
183
|
+
"anyOf": [
|
|
184
|
+
{
|
|
185
|
+
"type": "array",
|
|
186
|
+
"items": {
|
|
187
|
+
"$ref": "#/components/schemas/LettaMessageContentUnion",
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{"type": "string"},
|
|
191
|
+
],
|
|
192
|
+
}
|