letta-nightly 0.7.9.dev20250505104245__py3-none-any.whl → 0.7.10.dev20250506042051__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.
letta/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.7.9"
1
+ __version__ = "0.7.10"
2
2
 
3
3
  # import clients
4
4
  from letta.client.client import LocalClient, RESTClient, create_client
@@ -66,7 +66,7 @@ class _ResumeContext:
66
66
  request_status_updates: List[RequestStatusUpdateInfo]
67
67
 
68
68
 
69
- async def execute_tool_wrapper(params: ToolExecutionParams):
69
+ async def execute_tool_wrapper(params: ToolExecutionParams) -> Tuple[str, Tuple[str, bool]]:
70
70
  """
71
71
  Executes the tool in an out‑of‑process worker and returns:
72
72
  (agent_id, (tool_result:str, success_flag:bool))
@@ -324,8 +324,13 @@ class LettaAgentBatch:
324
324
  @trace_method
325
325
  async def _execute_tools(self, ctx: _ResumeContext) -> Sequence[Tuple[str, Tuple[str, bool]]]:
326
326
  sbx_cfg, sbx_env = self._build_sandbox()
327
- params = [
328
- ToolExecutionParams(
327
+ rethink_memory_tool_name = "rethink_memory"
328
+ tool_params = []
329
+ # TODO: This is a special case - we need to think about how to generalize this
330
+ # TODO: Rethink memory is a common op that is easily batchable, so we pull this logic out
331
+ rethink_memory_params = []
332
+ for aid in ctx.agent_ids:
333
+ param = ToolExecutionParams(
329
334
  agent_id=aid,
330
335
  tool_call_name=ctx.tool_call_name_map[aid],
331
336
  tool_args=ctx.tool_call_args_map[aid],
@@ -334,10 +339,44 @@ class LettaAgentBatch:
334
339
  sbx_config=sbx_cfg,
335
340
  sbx_env_vars=sbx_env,
336
341
  )
337
- for aid in ctx.agent_ids
338
- ]
339
- async with Pool() as pool:
340
- return await pool.map(execute_tool_wrapper, params)
342
+
343
+ if ctx.tool_call_name_map[aid] == rethink_memory_tool_name:
344
+ rethink_memory_params.append(param)
345
+ else:
346
+ tool_params.append(param)
347
+
348
+ if rethink_memory_params:
349
+ return self._bulk_rethink_memory(rethink_memory_params)
350
+
351
+ if tool_params:
352
+ async with Pool() as pool:
353
+ return await pool.map(execute_tool_wrapper, tool_params)
354
+
355
+ @trace_method
356
+ def _bulk_rethink_memory(self, params: List[ToolExecutionParams]) -> Sequence[Tuple[str, Tuple[str, bool]]]:
357
+ updates = {}
358
+ result = []
359
+ for param in params:
360
+ # Sanity check
361
+ # TODO: This is very brittle and done quickly for performance
362
+ # TODO: If the end tool is changed, this will break
363
+ # TODO: Move 'rethink_memory' to a native Letta tool that we control
364
+ if "new_memory" not in param.tool_args or "target_block_label" not in param.tool_args:
365
+ raise ValueError(f"Missing either `new_memory` or `target_block_label` in the tool args: {param.tool_args}")
366
+
367
+ # Find the block id/update
368
+ block_id = param.agent_state.memory.get_block(label=param.tool_args.get("target_block_label")).id
369
+ new_value = param.tool_args.get("new_memory")
370
+
371
+ # This is sensitive to multiple agents overwriting the same memory block
372
+ updates[block_id] = new_value
373
+
374
+ # TODO: This is quite ugly and confusing - this is mostly to align with the returns of other tools
375
+ result.append((param.agent_id, ("", True)))
376
+
377
+ self.block_manager.bulk_update_block_values(updates=updates, actor=self.actor)
378
+
379
+ return result
341
380
 
342
381
  def _persist_tool_messages(
343
382
  self,
@@ -46,6 +46,7 @@ from letta.services.message_manager import MessageManager
46
46
  from letta.services.passage_manager import PassageManager
47
47
  from letta.services.summarizer.enums import SummarizationMode
48
48
  from letta.services.summarizer.summarizer import Summarizer
49
+ from letta.settings import model_settings
49
50
  from letta.utils import united_diff
50
51
 
51
52
  logger = get_logger(__name__)
@@ -125,6 +126,14 @@ class VoiceAgent(BaseAgent):
125
126
 
126
127
  agent_state = self.agent_manager.get_agent_by_id(self.agent_id, actor=self.actor)
127
128
 
129
+ # TODO: Refactor this so it uses our in-house clients
130
+ # TODO: For now, piggyback off of OpenAI client for ease
131
+ if agent_state.llm_config.model_endpoint_type == "anthropic":
132
+ self.openai_client.api_key = model_settings.anthropic_api_key
133
+ self.openai_client.base_url = "https://api.anthropic.com/v1/"
134
+ elif agent_state.llm_config.model_endpoint_type != "openai":
135
+ raise ValueError("Letta voice agents are only compatible with OpenAI or Anthropic.")
136
+
128
137
  # Safety check
129
138
  if agent_state.agent_type != AgentType.voice_convo_agent:
130
139
  raise IncompatibleAgentType(expected_type=AgentType.voice_convo_agent, actual_type=agent_state.agent_type)
@@ -35,18 +35,19 @@ class OpenAIChatCompletionsStreamingInterface:
35
35
  """
36
36
  async with stream:
37
37
  async for chunk in stream:
38
- choice = chunk.choices[0]
39
- delta = choice.delta
40
- finish_reason = choice.finish_reason
38
+ if chunk.choices:
39
+ choice = chunk.choices[0]
40
+ delta = choice.delta
41
+ finish_reason = choice.finish_reason
41
42
 
42
- async for sse_chunk in self._process_content(delta, chunk):
43
- yield sse_chunk
43
+ async for sse_chunk in self._process_content(delta, chunk):
44
+ yield sse_chunk
44
45
 
45
- async for sse_chunk in self._process_tool_calls(delta, chunk):
46
- yield sse_chunk
46
+ async for sse_chunk in self._process_tool_calls(delta, chunk):
47
+ yield sse_chunk
47
48
 
48
- if self._handle_finish_reason(finish_reason):
49
- break
49
+ if self._handle_finish_reason(finish_reason):
50
+ break
50
51
 
51
52
  async def _process_content(self, delta: ChoiceDelta, chunk: ChatCompletionChunk) -> AsyncGenerator[str, None]:
52
53
  """Processes regular content tokens and streams them."""
@@ -115,6 +115,8 @@ MODEL_LIST = [
115
115
 
116
116
  DUMMY_FIRST_USER_MESSAGE = "User initializing bootup sequence."
117
117
 
118
+ VALID_EVENT_TYPES = {"content_block_stop", "message_stop"}
119
+
118
120
 
119
121
  def antropic_get_model_context_window(url: str, api_key: Union[str, None], model: str) -> int:
120
122
  for model_dict in anthropic_get_model_list(url=url, api_key=api_key):
@@ -596,7 +598,8 @@ def convert_anthropic_stream_event_to_chatcompletion(
596
598
  redacted_reasoning_content = event.content_block.data
597
599
  else:
598
600
  warnings.warn("Unexpected content start type: " + str(type(event.content_block)))
599
-
601
+ elif event.type in VALID_EVENT_TYPES:
602
+ pass
600
603
  else:
601
604
  warnings.warn("Unexpected event type: " + event.type)
602
605
 
@@ -1,5 +1,6 @@
1
1
  GOOGLE_MODEL_TO_CONTEXT_LENGTH = {
2
2
  "gemini-2.5-pro-exp-03-25": 1048576,
3
+ "gemini-2.5-flash-preview-04-17": 1048576,
3
4
  "gemini-2.0-flash-001": 1048576,
4
5
  "gemini-2.0-pro-exp-02-05": 2097152,
5
6
  "gemini-2.0-flash-lite-preview-02-05": 1048576,
@@ -110,12 +110,12 @@ class GoogleVertexClient(GoogleAIClient):
110
110
  for candidate in response.candidates:
111
111
  content = candidate.content
112
112
 
113
- if "role" not in content or not content["role"]:
114
- # This means the response is malformed like MALFORMED_FUNCTION_CALL
115
- # NOTE: must be a ValueError to trigger a retry
116
- raise ValueError(f"Error in response data from LLM: {response_data}")
117
- role = content["role"]
118
- assert role == "model", f"Unknown role in response: {role}"
113
+ # if "role" not in content or not content["role"]:
114
+ # # This means the response is malformed like MALFORMED_FUNCTION_CALL
115
+ # # NOTE: must be a ValueError to trigger a retry
116
+ # raise ValueError(f"Error in response data from LLM: {response_data}")
117
+ # role = content["role"]
118
+ # assert role == "model", f"Unknown role in response: {role}"
119
119
 
120
120
  parts = content.parts
121
121
 
@@ -181,17 +181,6 @@ def create_application() -> "FastAPI":
181
181
  },
182
182
  )
183
183
 
184
- @app.exception_handler(IncompatibleAgentType)
185
- async def handle_incompatible_agent_type(request: Request, exc: IncompatibleAgentType):
186
- return JSONResponse(
187
- status_code=400,
188
- content={
189
- "detail": str(exc),
190
- "expected_type": exc.expected_type,
191
- "actual_type": exc.actual_type,
192
- },
193
- )
194
-
195
184
  @app.exception_handler(Exception)
196
185
  async def generic_error_handler(request: Request, exc: Exception):
197
186
  # Log the actual error for debugging
@@ -31,11 +31,22 @@ def list_blocks(
31
31
  )
32
32
 
33
33
 
34
+ @router.get("/count", response_model=int, operation_id="count_blocks")
35
+ def count_blocks(
36
+ server: SyncServer = Depends(get_letta_server),
37
+ actor_id: Optional[str] = Header(None, alias="user_id"),
38
+ ):
39
+ """
40
+ Count all blocks created by a user.
41
+ """
42
+ return server.block_manager.size(actor=server.user_manager.get_user_or_default(user_id=actor_id))
43
+
44
+
34
45
  @router.post("/", response_model=Block, operation_id="create_block")
35
46
  def create_block(
36
47
  create_block: CreateBlock = Body(...),
37
48
  server: SyncServer = Depends(get_letta_server),
38
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
49
+ actor_id: Optional[str] = Header(None, alias="user_id"),
39
50
  ):
40
51
  actor = server.user_manager.get_user_or_default(user_id=actor_id)
41
52
  block = Block(**create_block.model_dump())
@@ -40,11 +40,22 @@ def list_groups(
40
40
  )
41
41
 
42
42
 
43
+ @router.get("/count", response_model=int, operation_id="count_groups")
44
+ def count_groups(
45
+ server: SyncServer = Depends(get_letta_server),
46
+ actor_id: Optional[str] = Header(None, alias="user_id"),
47
+ ):
48
+ """
49
+ Get the count of all groups associated with a given user.
50
+ """
51
+ return server.group_manager.size(actor=server.user_manager.get_user_or_default(user_id=actor_id))
52
+
53
+
43
54
  @router.get("/{group_id}", response_model=Group, operation_id="retrieve_group")
44
55
  def retrieve_group(
45
56
  group_id: str,
46
57
  server: "SyncServer" = Depends(get_letta_server),
47
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
58
+ actor_id: Optional[str] = Header(None, alias="user_id"),
48
59
  ):
49
60
  """
50
61
  Retrieve the group by id.
@@ -61,7 +72,7 @@ def retrieve_group(
61
72
  def create_group(
62
73
  group: GroupCreate = Body(...),
63
74
  server: "SyncServer" = Depends(get_letta_server),
64
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
75
+ actor_id: Optional[str] = Header(None, alias="user_id"),
65
76
  x_project: Optional[str] = Header(None, alias="X-Project"), # Only handled by next js middleware
66
77
  ):
67
78
  """
@@ -79,7 +90,7 @@ def modify_group(
79
90
  group_id: str,
80
91
  group: GroupUpdate = Body(...),
81
92
  server: "SyncServer" = Depends(get_letta_server),
82
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
93
+ actor_id: Optional[str] = Header(None, alias="user_id"),
83
94
  x_project: Optional[str] = Header(None, alias="X-Project"), # Only handled by next js middleware
84
95
  ):
85
96
  """
@@ -96,7 +107,7 @@ def modify_group(
96
107
  def delete_group(
97
108
  group_id: str,
98
109
  server: "SyncServer" = Depends(get_letta_server),
99
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
110
+ actor_id: Optional[str] = Header(None, alias="user_id"),
100
111
  ):
101
112
  """
102
113
  Delete a multi-agent group.
@@ -118,7 +129,7 @@ async def send_group_message(
118
129
  group_id: str,
119
130
  server: SyncServer = Depends(get_letta_server),
120
131
  request: LettaRequest = Body(...),
121
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
132
+ actor_id: Optional[str] = Header(None, alias="user_id"),
122
133
  ):
123
134
  """
124
135
  Process a user message and return the group's response.
@@ -156,7 +167,7 @@ async def send_group_message_streaming(
156
167
  group_id: str,
157
168
  server: SyncServer = Depends(get_letta_server),
158
169
  request: LettaStreamingRequest = Body(...),
159
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
170
+ actor_id: Optional[str] = Header(None, alias="user_id"),
160
171
  ):
161
172
  """
162
173
  Process a user message and return the group's responses.
@@ -189,7 +200,7 @@ def modify_group_message(
189
200
  message_id: str,
190
201
  request: LettaMessageUpdateUnion = Body(...),
191
202
  server: "SyncServer" = Depends(get_letta_server),
192
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
203
+ actor_id: Optional[str] = Header(None, alias="user_id"),
193
204
  ):
194
205
  """
195
206
  Update the details of a message associated with an agent.
@@ -209,7 +220,7 @@ def list_group_messages(
209
220
  use_assistant_message: bool = Query(True, description="Whether to use assistant messages"),
210
221
  assistant_message_tool_name: str = Query(DEFAULT_MESSAGE_TOOL, description="The name of the designated message tool."),
211
222
  assistant_message_tool_kwarg: str = Query(DEFAULT_MESSAGE_TOOL_KWARG, description="The name of the message argument."),
212
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
223
+ actor_id: Optional[str] = Header(None, alias="user_id"),
213
224
  ):
214
225
  """
215
226
  Retrieve message history for an agent.
@@ -247,7 +258,7 @@ def list_group_messages(
247
258
  def reset_group_messages(
248
259
  group_id: str,
249
260
  server: "SyncServer" = Depends(get_letta_server),
250
- actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
261
+ actor_id: Optional[str] = Header(None, alias="user_id"),
251
262
  ):
252
263
  """
253
264
  Delete the group messages for all agents that are part of the multi-agent group.
@@ -20,6 +20,7 @@ from letta.helpers.message_helper import convert_message_creates_to_messages
20
20
  from letta.log import get_logger
21
21
  from letta.schemas.enums import MessageRole
22
22
  from letta.schemas.letta_message_content import OmittedReasoningContent, ReasoningContent, RedactedReasoningContent, TextContent
23
+ from letta.schemas.llm_config import LLMConfig
23
24
  from letta.schemas.message import Message, MessageCreate
24
25
  from letta.schemas.usage import LettaUsageStatistics
25
26
  from letta.schemas.user import User
@@ -53,6 +54,7 @@ async def sse_async_generator(
53
54
  usage_task: Optional[asyncio.Task] = None,
54
55
  finish_message=True,
55
56
  request_start_timestamp_ns: Optional[int] = None,
57
+ llm_config: Optional[LLMConfig] = None,
56
58
  ):
57
59
  """
58
60
  Wraps a generator for use in Server-Sent Events (SSE), handling errors and ensuring a completion message.
@@ -70,6 +72,7 @@ async def sse_async_generator(
70
72
  ttft_span = None
71
73
  if request_start_timestamp_ns is not None:
72
74
  ttft_span = tracer.start_span("time_to_first_token", start_time=request_start_timestamp_ns)
75
+ ttft_span.set_attributes({f"llm_config.{k}": v for k, v in llm_config.model_dump().items()})
73
76
 
74
77
  try:
75
78
  async for chunk in generator:
letta/server/server.py CHANGED
@@ -1725,6 +1725,7 @@ class SyncServer(Server):
1725
1725
  usage_task=task,
1726
1726
  finish_message=include_final_message,
1727
1727
  request_start_timestamp_ns=request_start_timestamp_ns,
1728
+ llm_config=llm_config,
1728
1729
  ),
1729
1730
  media_type="text/event-stream",
1730
1731
  )
@@ -866,8 +866,9 @@ class AgentManager:
866
866
  @enforce_types
867
867
  def trim_older_in_context_messages(self, num: int, agent_id: str, actor: PydanticUser) -> PydanticAgentState:
868
868
  message_ids = self.get_agent_by_id(agent_id=agent_id, actor=actor).message_ids
869
- new_messages = [message_ids[0]] + message_ids[num:] # 0 is system message
870
- return self.set_in_context_messages(agent_id=agent_id, message_ids=new_messages, actor=actor)
869
+ newer_messages = self._trim_tool_response(agent_id=agent_id, actor=actor, message_ids=message_ids[num:])
870
+ trimmed_messages = [message_ids[0]] + newer_messages # 0 is system message
871
+ return self.set_in_context_messages(agent_id=agent_id, message_ids=trimmed_messages, actor=actor)
871
872
 
872
873
  @enforce_types
873
874
  def trim_all_in_context_messages_except_system(self, agent_id: str, actor: PydanticUser) -> PydanticAgentState:
@@ -876,6 +877,16 @@ class AgentManager:
876
877
  new_messages = [message_ids[0]] # 0 is system message
877
878
  return self.set_in_context_messages(agent_id=agent_id, message_ids=new_messages, actor=actor)
878
879
 
880
+ def _trim_tool_response(self, agent_id: str, actor: PydanticUser, message_ids: list[str]) -> PydanticAgentState:
881
+ """
882
+ Trims the tool response from the in-context messages if there is no tool call present in trimmed messages.
883
+ """
884
+ if message_ids:
885
+ messages = self.message_manager.get_messages_by_ids(message_ids=[message_ids[0]], actor=actor)
886
+ if messages and messages[0].role == "tool":
887
+ return message_ids[1:]
888
+ return message_ids
889
+
879
890
  @enforce_types
880
891
  def prepend_to_in_context_messages(self, messages: List[PydanticMessage], agent_id: str, actor: PydanticUser) -> PydanticAgentState:
881
892
  message_ids = self.get_agent_by_id(agent_id=agent_id, actor=actor).message_ids
@@ -1,8 +1,9 @@
1
1
  import os
2
- from typing import List, Optional
2
+ from typing import Dict, List, Optional
3
3
 
4
4
  from sqlalchemy.orm import Session
5
5
 
6
+ from letta.log import get_logger
6
7
  from letta.orm.block import Block as BlockModel
7
8
  from letta.orm.block_history import BlockHistory
8
9
  from letta.orm.enums import ActorType
@@ -13,6 +14,8 @@ from letta.schemas.block import BlockUpdate, Human, Persona
13
14
  from letta.schemas.user import User as PydanticUser
14
15
  from letta.utils import enforce_types, list_human_files, list_persona_files
15
16
 
17
+ logger = get_logger(__name__)
18
+
16
19
 
17
20
  class BlockManager:
18
21
  """Manager class to handle business logic related to Blocks."""
@@ -165,6 +168,17 @@ class BlockManager:
165
168
 
166
169
  return agents_pydantic
167
170
 
171
+ @enforce_types
172
+ def size(
173
+ self,
174
+ actor: PydanticUser,
175
+ ) -> int:
176
+ """
177
+ Get the total count of blocks for the given user.
178
+ """
179
+ with self.session_maker() as session:
180
+ return BlockModel.size(db_session=session, actor=actor)
181
+
168
182
  # Block History Functions
169
183
 
170
184
  @enforce_types
@@ -349,3 +363,44 @@ class BlockManager:
349
363
 
350
364
  session.commit()
351
365
  return block.to_pydantic()
366
+
367
+ @enforce_types
368
+ def bulk_update_block_values(
369
+ self, updates: Dict[str, str], actor: PydanticUser, return_hydrated: bool = False
370
+ ) -> Optional[List[PydanticBlock]]:
371
+ """
372
+ Bulk-update the `value` field for multiple blocks in one transaction.
373
+
374
+ Args:
375
+ updates: mapping of block_id -> new value
376
+ actor: the user performing the update (for org scoping, permissions, audit)
377
+ return_hydrated: whether to return the pydantic Block objects that were updated
378
+
379
+ Returns:
380
+ the updated Block objects as Pydantic schemas
381
+
382
+ Raises:
383
+ NoResultFound if any block_id doesn’t exist or isn’t visible to this actor
384
+ ValueError if any new value exceeds its block’s limit
385
+ """
386
+ with self.session_maker() as session:
387
+ q = session.query(BlockModel).filter(BlockModel.id.in_(updates.keys()), BlockModel.organization_id == actor.organization_id)
388
+ blocks = q.all()
389
+
390
+ found_ids = {b.id for b in blocks}
391
+ missing = set(updates.keys()) - found_ids
392
+ if missing:
393
+ logger.warning(f"Block IDs not found or inaccessible, skipping during bulk update: {missing!r}")
394
+
395
+ for block in blocks:
396
+ new_val = updates[block.id]
397
+ if len(new_val) > block.limit:
398
+ logger.warning(f"Value length ({len(new_val)}) exceeds limit " f"({block.limit}) for block {block.id!r}, truncating...")
399
+ new_val = new_val[: block.limit]
400
+ block.value = new_val
401
+
402
+ session.commit()
403
+
404
+ if return_hydrated:
405
+ return [b.to_pydantic() for b in blocks]
406
+ return None
@@ -239,6 +239,17 @@ class GroupManager:
239
239
 
240
240
  return prev_last_processed_message_id
241
241
 
242
+ @enforce_types
243
+ def size(
244
+ self,
245
+ actor: PydanticUser,
246
+ ) -> int:
247
+ """
248
+ Get the total count of groups for the given user.
249
+ """
250
+ with self.session_maker() as session:
251
+ return GroupModel.size(db_session=session, actor=actor)
252
+
242
253
  def _process_agent_relationship(self, session: Session, group: GroupModel, agent_ids: List[str], allow_partial=False, replace=True):
243
254
  if not agent_ids:
244
255
  if replace:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: letta-nightly
3
- Version: 0.7.9.dev20250505104245
3
+ Version: 0.7.10.dev20250506042051
4
4
  Summary: Create LLM agents with long-term memory and custom tools
5
5
  License: Apache License
6
6
  Author: Letta Team
@@ -1,4 +1,4 @@
1
- letta/__init__.py,sha256=ayPB5d7EYFS2iOGqVFQHqzmVac71mnSp-Q7mCHuXEBU,915
1
+ letta/__init__.py,sha256=FH6FPDkIXVSTJcnUS-h2PWhPA0APeYBKnvFICoi2NhE,916
2
2
  letta/__main__.py,sha256=6Hs2PV7EYc5Tid4g4OtcLXhqVHiNYTGzSBdoOnW2HXA,29
3
3
  letta/agent.py,sha256=6WNvO40ob6YFGvn2yeCnMJ_XdvoNKBJUKmf4bgIYrYY,72093
4
4
  letta/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -7,8 +7,8 @@ letta/agents/ephemeral_agent.py,sha256=el-SUF_16vv_7OouIR-6z0pAE9Yc0PLibygvfCKwq
7
7
  letta/agents/exceptions.py,sha256=BQY4D4w32OYHM63CM19ko7dPwZiAzUs3NbKvzmCTcJg,318
8
8
  letta/agents/helpers.py,sha256=yAiRTS0sanXmI6fsoQ6LXXDteNaxZ8fY_K66rsGEFT4,4007
9
9
  letta/agents/letta_agent.py,sha256=oY3fa2-r7YM9Xssd_DYFcwyAJFbwWvHMrooJFrmeFK8,19531
10
- letta/agents/letta_agent_batch.py,sha256=abAJIFFi2V_fsmoXeMikBHj815QjKjgq6mc09hK-2bk,24070
11
- letta/agents/voice_agent.py,sha256=w2OtpfNtjDBs_uJ4uHgOXUwp7g_ymP4e6V94ApkfWiE,22614
10
+ letta/agents/letta_agent_batch.py,sha256=0qqjIOJcB6Gf75tmQ3cNxs0ExzQ3JWArY48NRDQzddY,25988
11
+ letta/agents/voice_agent.py,sha256=YHaGCy3A35lB3bxXMXldIHUsXt76kC88Ti34EDs3zzA,23168
12
12
  letta/agents/voice_sleeptime_agent.py,sha256=Joi3-8emTpV7v86OR_HGYXblkulrNaHhudCvPmMyXz0,7274
13
13
  letta/benchmark/benchmark.py,sha256=ebvnwfp3yezaXOQyGXkYCDYpsmre-b9hvNtnyx4xkG0,3701
14
14
  letta/benchmark/constants.py,sha256=aXc5gdpMGJT327VuxsT5FngbCK2J41PQYeICBO7g_RE,536
@@ -62,7 +62,7 @@ letta/humans/examples/cs_phd.txt,sha256=9C9ZAV_VuG7GB31ksy3-_NAyk8rjE6YtVOkhp08k
62
62
  letta/interface.py,sha256=6GKasvJMASu-kcZch6Hffz1vnHuPA_ryI6cLH2bMArc,13023
63
63
  letta/interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
64
  letta/interfaces/anthropic_streaming_interface.py,sha256=OU5Q8OwazIQ6z6AQKGWe6yEHcafnfBiCc3iaMOkbVW4,17038
65
- letta/interfaces/openai_chat_completions_streaming_interface.py,sha256=-YdOcLElW0E8YzFGMT3b4mWHjLgxGxPh6pAkzRnj4AY,4841
65
+ letta/interfaces/openai_chat_completions_streaming_interface.py,sha256=LANdVBA8UNWscBvsFbWTT8cxNg5fHA_woWU2jkTf6TQ,4911
66
66
  letta/interfaces/utils.py,sha256=c6jvO0dBYHh8DQnlN-B0qeNC64d3CSunhfqlFA4pJTY,278
67
67
  letta/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
68
  letta/jobs/helpers.py,sha256=kO4aj954xsQ1RAmkjY6LQQ7JEIGuhaxB1e9pzrYKHAY,914
@@ -70,7 +70,7 @@ letta/jobs/llm_batch_job_polling.py,sha256=qy1-rkm9ehS_DaSz7pvcUmsueW8gug_kubnz8
70
70
  letta/jobs/scheduler.py,sha256=VpRyO2vuETNrarHOIWYctAkrD4WFtV57buUSHaLE89Y,10240
71
71
  letta/jobs/types.py,sha256=K8GKEnqEgAT6Kq4F2hUrBC4ZAFM9OkfOjVMStzxKuXQ,742
72
72
  letta/llm_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- letta/llm_api/anthropic.py,sha256=B-O2nS0WkvvgDS_hBQM_lVe33MNsBNeGZWwsll4H5cU,44721
73
+ letta/llm_api/anthropic.py,sha256=AS8ybffjJkS-4GchKG5emhPHlnlGccML_-4ay_ZASyI,44835
74
74
  letta/llm_api/anthropic_client.py,sha256=Be3LupDrXBqgYSy8vpxwR896lL0Tlo3VhaJ5DZTLGl4,24590
75
75
  letta/llm_api/aws_bedrock.py,sha256=kAPpKPRe4ZUa6fkxFbo8xwQgq4fJf3QoZEAP1LOCfaw,4168
76
76
  letta/llm_api/azure_openai.py,sha256=YAkXwKyfnJFNhB45pkJVFsoxUNB_M74rQYchtw_CN6I,5099
@@ -78,8 +78,8 @@ letta/llm_api/azure_openai_constants.py,sha256=ZaR2IasJThijG0uhLKJThrixdAxLPD2Io
78
78
  letta/llm_api/cohere.py,sha256=IZ6LXyOFMYjWHTeNG9lvFxCdV_NIl0hY2q9SPFYXNkQ,14849
79
79
  letta/llm_api/deepseek.py,sha256=b1mSW8gnBrpAI8d2GcBpDyLYDnuC-P1UP6xJPalfQS4,12456
80
80
  letta/llm_api/google_ai_client.py,sha256=iBHOD64_xAh9NHfioCJSNm-yMpHJkqB8bn2OfQWR9sI,23446
81
- letta/llm_api/google_constants.py,sha256=1dqwt-YwdYGnAHV5rIPfGHfE3ybPzSn_48vlNYfd-bk,588
82
- letta/llm_api/google_vertex_client.py,sha256=dbU9o7lQiyGEZV7cToJH5ON0hemYJxUQQM_SBUY0ytw,11949
81
+ letta/llm_api/google_constants.py,sha256=jgVwBDndE0cTA8S5wHUDFH-x_ZB1W9ekY-S_bNO1u00,635
82
+ letta/llm_api/google_vertex_client.py,sha256=cjyqHtGK0CmAMYOncU530oMMefSwB1Mvr2F_DBJLM9I,11958
83
83
  letta/llm_api/helpers.py,sha256=sLYv30UnKBRVPuhU_KDXfKFdbkUONiDAyVEwGr86l3A,16780
84
84
  letta/llm_api/llm_api_tools.py,sha256=GEpmPbjBjFl4ztlS5eaNHGwkAOysSVEvidTwlpLHIhg,28070
85
85
  letta/llm_api/llm_client.py,sha256=H8JwcKgz6XyooP751R3dNJ9Cf8sVT8v0KQkhjh4KNqA,2274
@@ -254,7 +254,7 @@ letta/server/constants.py,sha256=yAdGbLkzlOU_dLTx0lKDmAnj0ZgRXCEaIcPJWO69eaE,92
254
254
  letta/server/db.py,sha256=Jt_lWUvqTWFHfgsWUuXcDlGD3yejNBjY1P4J2vI3kL0,4935
255
255
  letta/server/generate_openapi_schema.sh,sha256=0OtBhkC1g6CobVmNEd_m2B6sTdppjbJLXaM95icejvE,371
256
256
  letta/server/rest_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
257
- letta/server/rest_api/app.py,sha256=8gXmSguStBXtILPN61KmK1R6dA39OlANntaIbvk_Z84,15053
257
+ letta/server/rest_api/app.py,sha256=ZLtTm2HZwctfM69ujF433xK2Bx9ZILHyYSBnxdRQtcY,14669
258
258
  letta/server/rest_api/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
259
259
  letta/server/rest_api/auth/index.py,sha256=fQBGyVylGSRfEMLQ17cZzrHd5Y1xiVylvPqH5Rl-lXQ,1378
260
260
  letta/server/rest_api/auth_token.py,sha256=725EFEIiNj4dh70hrSd94UysmFD8vcJLrTRfNHkzxDo,774
@@ -266,9 +266,9 @@ letta/server/rest_api/routers/openai/chat_completions/__init__.py,sha256=47DEQpj
266
266
  letta/server/rest_api/routers/openai/chat_completions/chat_completions.py,sha256=QBWab1fn2LXVDMtc6li3gOzmrNzDiUw5WUJsMeeMZII,5076
267
267
  letta/server/rest_api/routers/v1/__init__.py,sha256=_skmAcDOK9ovHKfywRaBgigo3IvPmnUSQSR2hGVCOhY,1664
268
268
  letta/server/rest_api/routers/v1/agents.py,sha256=M-ANOePUfPITB753PfCvmW95P-1KNcTjQLxdLea7AXY,34827
269
- letta/server/rest_api/routers/v1/blocks.py,sha256=Sefvon0jLvlNh0oAzntUcDZptnutuJOf-2Wcad_45Dg,4169
269
+ letta/server/rest_api/routers/v1/blocks.py,sha256=jrDpSYrEgHaGvlnUCn6wczgWnCZa3ZyHVL5NQv2KJNE,4471
270
270
  letta/server/rest_api/routers/v1/embeddings.py,sha256=P-Dvt_HNKoTyjRwkScAMg1hlB3cNxMeAQwV7bSatsKI,957
271
- letta/server/rest_api/routers/v1/groups.py,sha256=sLXkw8kgf9fhaQwb-n0SVbyzH6-e1kdzNuqGbdvPPgo,10890
271
+ letta/server/rest_api/routers/v1/groups.py,sha256=JI9ShKewoE8lB58OP02NuAT7eUzPfqSG7y44a6tBh9s,10710
272
272
  letta/server/rest_api/routers/v1/health.py,sha256=MoOjkydhGcJXTiuJrKIB0etVXiRMdTa51S8RQ8-50DQ,399
273
273
  letta/server/rest_api/routers/v1/identities.py,sha256=fvp-0cwvb4iX1fUGPkL--9nq8YD3tIE47kYRxUgOlp4,7462
274
274
  letta/server/rest_api/routers/v1/jobs.py,sha256=4oeJfI2odNGubU_g7WSORJhn_usFsbRaD-qm86rve1E,2746
@@ -285,8 +285,8 @@ letta/server/rest_api/routers/v1/tools.py,sha256=FXFx8J4Zs-pZ1H8andFzI5Pyv-PJkY8
285
285
  letta/server/rest_api/routers/v1/users.py,sha256=G5DBHSkPfBgVHN2Wkm-rVYiLQAudwQczIq2Z3YLdbVo,2277
286
286
  letta/server/rest_api/routers/v1/voice.py,sha256=nSwjoW5Hi9EdScGyRWXpGVooAS0X2G-mOrpLUz0NqNs,1935
287
287
  letta/server/rest_api/static_files.py,sha256=NG8sN4Z5EJ8JVQdj19tkFa9iQ1kBPTab9f_CUxd_u4Q,3143
288
- letta/server/rest_api/utils.py,sha256=PmWbPH6Z0ZDZ8YpdzxpfxN8yupWW5PJp_DvjgQt0TMk,16307
289
- letta/server/server.py,sha256=6Mwmvx267Pwyva3WWiLNMnQWIF_ng3-6oQIseXBghlE,85186
288
+ letta/server/rest_api/utils.py,sha256=sUHtcmbs9yl7__jvtUHzfhiZV1mzU7r5SzrGTJhRIC4,16499
289
+ letta/server/server.py,sha256=2ytjZt6sj8ooMZMYKA7HUyWbcfrW-1AwbxGsUEbyVt8,85233
290
290
  letta/server/startup.sh,sha256=MRXh1RKbS5lyA7XAsk7O6Q4LEKOqnv5B-dwe0SnTHeQ,2514
291
291
  letta/server/static_files/assets/index-048c9598.js,sha256=mR16XppvselwKCcNgONs4L7kZEVa4OEERm4lNZYtLSk,146819
292
292
  letta/server/static_files/assets/index-0e31b727.css,sha256=SBbja96uiQVLDhDOroHgM6NSl7tS4lpJRCREgSS_hA8,7672
@@ -300,9 +300,9 @@ letta/server/ws_api/interface.py,sha256=TWl9vkcMCnLsUtgsuENZ-ku2oMDA-OUTzLh_yNRo
300
300
  letta/server/ws_api/protocol.py,sha256=5mDgpfNZn_kNwHnpt5Dsuw8gdNH298sgxTGed3etzYg,1836
301
301
  letta/server/ws_api/server.py,sha256=cBSzf-V4zT1bL_0i54OTI3cMXhTIIxqjSRF8pYjk7fg,5835
302
302
  letta/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
303
- letta/services/agent_manager.py,sha256=FfMRz0Ewebn0OGhb9adBxga06-da3YmQ2qlh1BHOXUI,72037
304
- letta/services/block_manager.py,sha256=rphbpGBIEDFvCJ5GJt6A1OfbURGFQZ3WardljELQyAc,15225
305
- letta/services/group_manager.py,sha256=kAj0uq4vmeHfI9YREvZGdZFmfQRyuPsLXk-_UcyUQ24,15609
303
+ letta/services/agent_manager.py,sha256=AB4yV70NNCzeKR7tR1CD4lqxlJUgPvKLBXOCdsZ6Rik,72665
304
+ letta/services/block_manager.py,sha256=rAwOX9MYGSWYlzQsUtS_UXJwoh7jD-5O6aL8VWnA7fw,17327
305
+ letta/services/group_manager.py,sha256=EKYeD3MyJknpZBsH850pqIPZJmsphgEfI8hL-uOZbvU,15896
306
306
  letta/services/helpers/agent_manager_helper.py,sha256=2W9DpxGOx3rK2LnpGDtQmBJh9u9sKZ_xwAUAYzAMyS0,20350
307
307
  letta/services/helpers/tool_execution_helper.py,sha256=JdH6VTWFrXfwPWsWNSZFKuRFhhXp8qiDYWjbPc8PLLI,7649
308
308
  letta/services/identity_manager.py,sha256=sjHTCPbLYRDyWCJ3qjcuKZqWqzDoEuslRsDVKQtBraE,9683
@@ -340,8 +340,8 @@ letta/streaming_utils.py,sha256=jLqFTVhUL76FeOuYk8TaRQHmPTf3HSRc2EoJwxJNK6U,1194
340
340
  letta/system.py,sha256=mKxmvvekuP8mdgsebRINGBoFbUdJhxLJ260crPBNVyk,8386
341
341
  letta/tracing.py,sha256=j9uyBbx02erQZ307XmZmZSNyzQt-d7ZDB7vhFhjDlsU,8448
342
342
  letta/utils.py,sha256=IZFvtj9WYcrxUbkoUUYGDxMYQYdn5SgfqsvnARGsAzc,32245
343
- letta_nightly-0.7.9.dev20250505104245.dist-info/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
344
- letta_nightly-0.7.9.dev20250505104245.dist-info/METADATA,sha256=0m8PdWDTImpZ_xZIs7yr4uFF5hK1u-nTmTg6hmdIJEo,22231
345
- letta_nightly-0.7.9.dev20250505104245.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
346
- letta_nightly-0.7.9.dev20250505104245.dist-info/entry_points.txt,sha256=2zdiyGNEZGV5oYBuS-y2nAAgjDgcC9yM_mHJBFSRt5U,40
347
- letta_nightly-0.7.9.dev20250505104245.dist-info/RECORD,,
343
+ letta_nightly-0.7.10.dev20250506042051.dist-info/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
344
+ letta_nightly-0.7.10.dev20250506042051.dist-info/METADATA,sha256=oLX3DkT3SOHPEVjaZfES1NSRjdXW-4SwwSDiNUEu4hI,22232
345
+ letta_nightly-0.7.10.dev20250506042051.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
346
+ letta_nightly-0.7.10.dev20250506042051.dist-info/entry_points.txt,sha256=2zdiyGNEZGV5oYBuS-y2nAAgjDgcC9yM_mHJBFSRt5U,40
347
+ letta_nightly-0.7.10.dev20250506042051.dist-info/RECORD,,