letta-nightly 0.11.7.dev20250914103918__py3-none-any.whl → 0.11.7.dev20250915104130__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.
@@ -162,8 +162,8 @@ class IndentedORJSONResponse(Response):
162
162
  return orjson.dumps(content, option=orjson.OPT_INDENT_2)
163
163
 
164
164
 
165
- @router.get("/{agent_id}/export", response_class=IndentedORJSONResponse, operation_id="export_agent_serialized")
166
- async def export_agent_serialized(
165
+ @router.get("/{agent_id}/export", response_class=IndentedORJSONResponse, operation_id="export_agent")
166
+ async def export_agent(
167
167
  agent_id: str,
168
168
  max_steps: int = 100,
169
169
  server: "SyncServer" = Depends(get_letta_server),
@@ -256,7 +256,7 @@ def import_agent_legacy(
256
256
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred while uploading the agent: {e!s}")
257
257
 
258
258
 
259
- async def import_agent(
259
+ async def _import_agent(
260
260
  agent_file_json: dict,
261
261
  server: "SyncServer",
262
262
  actor: User,
@@ -313,8 +313,8 @@ async def import_agent(
313
313
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred while importing agents: {e!s}")
314
314
 
315
315
 
316
- @router.post("/import", response_model=ImportedAgentsResponse, operation_id="import_agent_serialized")
317
- async def import_agent_serialized(
316
+ @router.post("/import", response_model=ImportedAgentsResponse, operation_id="import_agent")
317
+ async def import_agent(
318
318
  file: UploadFile = File(...),
319
319
  server: "SyncServer" = Depends(get_letta_server),
320
320
  actor_id: str | None = Header(None, alias="user_id"),
@@ -367,7 +367,7 @@ async def import_agent_serialized(
367
367
  # TODO: This is kind of hacky, but should work as long as dont' change the schema
368
368
  if "agents" in agent_json and isinstance(agent_json.get("agents"), list):
369
369
  # This is an AgentFileSchema
370
- agent_ids = await import_agent(
370
+ agent_ids = await _import_agent(
371
371
  agent_file_json=agent_json,
372
372
  server=server,
373
373
  actor=actor,
@@ -12,8 +12,8 @@ router = APIRouter(prefix="/health", tags=["health"])
12
12
 
13
13
 
14
14
  # Health check
15
- @router.get("/", response_model=Health, operation_id="health_check")
16
- def health_check():
15
+ @router.get("/", response_model=Health, operation_id="check_health")
16
+ def check_health():
17
17
  return Health(
18
18
  version=__version__,
19
19
  status="ok",
@@ -19,23 +19,22 @@ router = APIRouter(prefix="/messages", tags=["messages"])
19
19
  logger = get_logger(__name__)
20
20
 
21
21
 
22
- # Batch APIs
23
-
24
-
25
22
  @router.post(
26
23
  "/batches",
27
24
  response_model=BatchJob,
28
- operation_id="create_batch_run",
25
+ operation_id="create_batch",
29
26
  )
30
- async def create_batch_run(
27
+ async def create_batch(
31
28
  request: Request,
32
29
  payload: CreateBatch = Body(..., description="Messages and config for all agents"),
33
30
  server: SyncServer = Depends(get_letta_server),
34
31
  actor_id: Optional[str] = Header(None, alias="user_id"),
35
32
  ):
36
33
  """
37
- Submit a batch of agent messages for asynchronous processing.
34
+ Submit a batch of agent runs for asynchronous processing.
35
+
38
36
  Creates a job that will fan out messages to all listed agents and process them in parallel.
37
+ The request will be rejected if it exceeds 256MB.
39
38
  """
40
39
  # Reject requests greater than 256Mbs
41
40
  max_bytes = 256 * 1024 * 1024
@@ -76,10 +75,7 @@ async def create_batch_run(
76
75
 
77
76
  # TODO: update run metadata
78
77
  except Exception as e:
79
- import traceback
80
-
81
- print("Error creating batch job", e)
82
- traceback.print_exc()
78
+ logger.error(f"Error creating batch job: {e}")
83
79
 
84
80
  # mark job as failed
85
81
  await server.job_manager.update_job_by_id_async(job_id=batch_job.id, job_update=JobUpdate(status=JobStatus.failed), actor=actor)
@@ -87,14 +83,14 @@ async def create_batch_run(
87
83
  return batch_job
88
84
 
89
85
 
90
- @router.get("/batches/{batch_id}", response_model=BatchJob, operation_id="retrieve_batch_run")
91
- async def retrieve_batch_run(
86
+ @router.get("/batches/{batch_id}", response_model=BatchJob, operation_id="retrieve_batch")
87
+ async def retrieve_batch(
92
88
  batch_id: str,
93
89
  actor_id: Optional[str] = Header(None, alias="user_id"),
94
90
  server: "SyncServer" = Depends(get_letta_server),
95
91
  ):
96
92
  """
97
- Get the status of a batch run.
93
+ Retrieve the status and details of a batch run.
98
94
  """
99
95
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
100
96
 
@@ -105,18 +101,36 @@ async def retrieve_batch_run(
105
101
  raise HTTPException(status_code=404, detail="Batch not found")
106
102
 
107
103
 
108
- @router.get("/batches", response_model=List[BatchJob], operation_id="list_batch_runs")
109
- async def list_batch_runs(
104
+ @router.get("/batches", response_model=List[BatchJob], operation_id="list_batches")
105
+ async def list_batches(
106
+ before: Optional[str] = Query(
107
+ None, description="Job ID cursor for pagination. Returns jobs that come before this job ID in the specified sort order"
108
+ ),
109
+ after: Optional[str] = Query(
110
+ None, description="Job ID cursor for pagination. Returns jobs that come after this job ID in the specified sort order"
111
+ ),
112
+ limit: Optional[int] = Query(100, description="Maximum number of jobs to return"),
113
+ order: Literal["asc", "desc"] = Query(
114
+ "desc", description="Sort order for jobs by creation time. 'asc' for oldest first, 'desc' for newest first"
115
+ ),
116
+ order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
110
117
  actor_id: Optional[str] = Header(None, alias="user_id"),
111
118
  server: "SyncServer" = Depends(get_letta_server),
112
119
  ):
113
120
  """
114
121
  List all batch runs.
115
122
  """
116
- # TODO: filter
117
123
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
118
124
 
119
- jobs = server.job_manager.list_jobs(actor=actor, statuses=[JobStatus.created, JobStatus.running], job_type=JobType.BATCH)
125
+ jobs = server.job_manager.list_jobs(
126
+ actor=actor,
127
+ statuses=[JobStatus.created, JobStatus.running],
128
+ job_type=JobType.BATCH,
129
+ before=before,
130
+ after=after,
131
+ limit=limit,
132
+ ascending=(order == "asc"),
133
+ )
120
134
  return [BatchJob.from_job(job) for job in jobs]
121
135
 
122
136
 
@@ -137,14 +151,17 @@ async def list_batch_messages(
137
151
  order: Literal["asc", "desc"] = Query(
138
152
  "desc", description="Sort order for messages by creation time. 'asc' for oldest first, 'desc' for newest first"
139
153
  ),
154
+ order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
140
155
  agent_id: Optional[str] = Query(None, description="Filter messages by agent ID"),
141
156
  actor_id: Optional[str] = Header(None, alias="user_id"),
142
157
  server: SyncServer = Depends(get_letta_server),
143
158
  ):
144
- """Get response messages for a specific batch job."""
159
+ """
160
+ Get response messages for a specific batch job.
161
+ """
145
162
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
146
163
 
147
- # First, verify the batch job exists and the user has access to it
164
+ # Verify the batch job exists and the user has access to it
148
165
  try:
149
166
  job = await server.job_manager.get_job_by_id_async(job_id=batch_id, actor=actor)
150
167
  BatchJob.from_job(job)
@@ -159,8 +176,8 @@ async def list_batch_messages(
159
176
  return LettaBatchMessages(messages=messages)
160
177
 
161
178
 
162
- @router.patch("/batches/{batch_id}/cancel", operation_id="cancel_batch_run")
163
- async def cancel_batch_run(
179
+ @router.patch("/batches/{batch_id}/cancel", operation_id="cancel_batch")
180
+ async def cancel_batch(
164
181
  batch_id: str,
165
182
  server: "SyncServer" = Depends(get_letta_server),
166
183
  actor_id: Optional[str] = Header(None, alias="user_id"),
@@ -25,7 +25,7 @@ async def list_providers(
25
25
  server: "SyncServer" = Depends(get_letta_server),
26
26
  ):
27
27
  """
28
- Get a list of all custom providers in the database
28
+ Get a list of all custom providers.
29
29
  """
30
30
  try:
31
31
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
@@ -46,7 +46,7 @@ async def create_provider(
46
46
  server: "SyncServer" = Depends(get_letta_server),
47
47
  ):
48
48
  """
49
- Create a new custom provider
49
+ Create a new custom provider.
50
50
  """
51
51
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
52
52
  for field_name in request.model_fields:
@@ -68,7 +68,7 @@ async def modify_provider(
68
68
  server: "SyncServer" = Depends(get_letta_server),
69
69
  ):
70
70
  """
71
- Update an existing custom provider
71
+ Update an existing custom provider.
72
72
  """
73
73
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
74
74
  return await server.provider_manager.update_provider_async(provider_id=provider_id, provider_update=request, actor=actor)
@@ -79,6 +79,9 @@ async def check_provider(
79
79
  request: ProviderCheck = Body(...),
80
80
  server: "SyncServer" = Depends(get_letta_server),
81
81
  ):
82
+ """
83
+ Verify the API key and additional parameters for a provider.
84
+ """
82
85
  try:
83
86
  if request.base_url and len(request.base_url) == 0:
84
87
  # set to null if empty string
@@ -100,7 +103,7 @@ async def delete_provider(
100
103
  server: "SyncServer" = Depends(get_letta_server),
101
104
  ):
102
105
  """
103
- Delete an existing custom provider
106
+ Delete an existing custom provider.
104
107
  """
105
108
  try:
106
109
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
@@ -1,14 +1,17 @@
1
1
  from datetime import datetime
2
2
  from typing import List, Literal, Optional
3
3
 
4
- from fastapi import APIRouter, Depends, Header, HTTPException, Query
4
+ from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query
5
+ from pydantic import BaseModel, Field
5
6
 
6
7
  from letta.orm.errors import NoResultFound
8
+ from letta.schemas.provider_trace import ProviderTrace
7
9
  from letta.schemas.step import Step
8
10
  from letta.schemas.step_metrics import StepMetrics
9
11
  from letta.server.rest_api.utils import get_letta_server
10
12
  from letta.server.server import SyncServer
11
13
  from letta.services.step_manager import FeedbackType
14
+ from letta.settings import settings
12
15
 
13
16
  router = APIRouter(prefix="/steps", tags=["steps"])
14
17
 
@@ -93,10 +96,33 @@ async def retrieve_step_metrics(
93
96
  raise HTTPException(status_code=404, detail="Step metrics not found")
94
97
 
95
98
 
99
+ @router.get("/{step_id}/trace", response_model=Optional[ProviderTrace], operation_id="retrieve_step_trace")
100
+ async def retrieve_step_trace(
101
+ step_id: str,
102
+ server: SyncServer = Depends(get_letta_server),
103
+ actor_id: str | None = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
104
+ ):
105
+ provider_trace = None
106
+ if settings.track_provider_trace:
107
+ try:
108
+ provider_trace = await server.telemetry_manager.get_provider_trace_by_step_id_async(
109
+ step_id=step_id, actor=await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
110
+ )
111
+ except:
112
+ pass
113
+
114
+ return provider_trace
115
+
116
+
117
+ class AddFeedbackRequest(BaseModel):
118
+ feedback: FeedbackType | None = Field(None, description="Whether this feedback is positive or negative")
119
+ tags: list[str] | None = Field(None, description="Feedback tags to add to the step")
120
+
121
+
96
122
  @router.patch("/{step_id}/feedback", response_model=Step, operation_id="add_feedback")
97
123
  async def add_feedback(
98
124
  step_id: str,
99
- feedback: Optional[FeedbackType],
125
+ request: AddFeedbackRequest = Body(...),
100
126
  actor_id: Optional[str] = Header(None, alias="user_id"),
101
127
  server: SyncServer = Depends(get_letta_server),
102
128
  ):
@@ -105,7 +131,7 @@ async def add_feedback(
105
131
  """
106
132
  try:
107
133
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
108
- return await server.step_manager.add_feedback_async(step_id=step_id, feedback=feedback, actor=actor)
134
+ return await server.step_manager.add_feedback_async(step_id=step_id, feedback=request.feedback, tags=request.tags, actor=actor)
109
135
  except NoResultFound:
110
136
  raise HTTPException(status_code=404, detail="Step not found")
111
137
 
@@ -1,4 +1,4 @@
1
- from typing import TYPE_CHECKING, List, Optional
1
+ from typing import TYPE_CHECKING, List, Literal, Optional
2
2
 
3
3
  from fastapi import APIRouter, Depends, Header, Query
4
4
 
@@ -13,15 +13,26 @@ router = APIRouter(prefix="/tags", tags=["tag", "admin"])
13
13
 
14
14
  @router.get("/", tags=["admin"], response_model=List[str], operation_id="list_tags")
15
15
  async def list_tags(
16
- after: Optional[str] = Query(None),
17
- limit: Optional[int] = Query(50),
16
+ before: Optional[str] = Query(
17
+ None, description="Tag cursor for pagination. Returns tags that come before this tag in the specified sort order"
18
+ ),
19
+ after: Optional[str] = Query(
20
+ None, description="Tag cursor for pagination. Returns tags that come after this tag in the specified sort order"
21
+ ),
22
+ limit: Optional[int] = Query(50, description="Maximum number of tags to return"),
23
+ order: Literal["asc", "desc"] = Query(
24
+ "asc", description="Sort order for tags. 'asc' for alphabetical order, 'desc' for reverse alphabetical order"
25
+ ),
26
+ order_by: Literal["name"] = Query("name", description="Field to sort by"),
27
+ query_text: Optional[str] = Query(None, description="Filter tags by text search"),
18
28
  server: "SyncServer" = Depends(get_letta_server),
19
- query_text: Optional[str] = Query(None),
20
29
  actor_id: Optional[str] = Header(None, alias="user_id"),
21
30
  ):
22
31
  """
23
- Get a list of all tags in the database
32
+ Get a list of all agent tags in the database.
24
33
  """
25
34
  actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
26
- tags = await server.agent_manager.list_tags_async(actor=actor, after=after, limit=limit, query_text=query_text)
35
+ tags = await server.agent_manager.list_tags_async(
36
+ actor=actor, before=before, after=after, limit=limit, query_text=query_text, ascending=(order == "asc")
37
+ )
27
38
  return tags
@@ -3542,19 +3542,27 @@ class AgentManager:
3542
3542
  @enforce_types
3543
3543
  @trace_method
3544
3544
  async def list_tags_async(
3545
- self, actor: PydanticUser, after: Optional[str] = None, limit: Optional[int] = 50, query_text: Optional[str] = None
3545
+ self,
3546
+ actor: PydanticUser,
3547
+ before: Optional[str] = None,
3548
+ after: Optional[str] = None,
3549
+ limit: Optional[int] = 50,
3550
+ query_text: Optional[str] = None,
3551
+ ascending: bool = True,
3546
3552
  ) -> List[str]:
3547
3553
  """
3548
3554
  Get all tags a user has created, ordered alphabetically.
3549
3555
 
3550
3556
  Args:
3551
3557
  actor: User performing the action.
3552
- after: Cursor for forward pagination.
3553
- limit: Maximum number of tags to return.
3554
- query text to filter tags by.
3558
+ before: Cursor for backward pagination (tags before this tag).
3559
+ after: Cursor for forward pagination (tags after this tag).
3560
+ limit: Maximum number of tags to return (default: 50).
3561
+ query_text: Filter tags by text search.
3562
+ ascending: Sort order - True for alphabetical, False for reverse (default: True).
3555
3563
 
3556
3564
  Returns:
3557
- List[str]: List of all tags.
3565
+ List[str]: List of all tags matching the criteria.
3558
3566
  """
3559
3567
  async with db_registry.async_session() as session:
3560
3568
  # Build the query using select() for async SQLAlchemy
@@ -3573,10 +3581,26 @@ class AgentManager:
3573
3581
  # SQLite: Use LIKE with LOWER for case-insensitive search
3574
3582
  query = query.where(func.lower(AgentsTags.tag).like(func.lower(f"%{query_text}%")))
3575
3583
 
3584
+ # Handle pagination cursors
3576
3585
  if after:
3577
- query = query.where(AgentsTags.tag > after)
3586
+ if ascending:
3587
+ query = query.where(AgentsTags.tag > after)
3588
+ else:
3589
+ query = query.where(AgentsTags.tag < after)
3578
3590
 
3579
- query = query.order_by(AgentsTags.tag).limit(limit)
3591
+ if before:
3592
+ if ascending:
3593
+ query = query.where(AgentsTags.tag < before)
3594
+ else:
3595
+ query = query.where(AgentsTags.tag > before)
3596
+
3597
+ # Apply ordering based on ascending parameter
3598
+ if ascending:
3599
+ query = query.order_by(AgentsTags.tag.asc())
3600
+ else:
3601
+ query = query.order_by(AgentsTags.tag.desc())
3602
+
3603
+ query = query.limit(limit)
3580
3604
 
3581
3605
  # Execute the query asynchronously
3582
3606
  result = await session.execute(query)
@@ -197,12 +197,16 @@ class StepManager:
197
197
 
198
198
  @enforce_types
199
199
  @trace_method
200
- async def add_feedback_async(self, step_id: str, feedback: Optional[FeedbackType], actor: PydanticUser) -> PydanticStep:
200
+ async def add_feedback_async(
201
+ self, step_id: str, feedback: FeedbackType | None, actor: PydanticUser, tags: list[str] | None = None
202
+ ) -> PydanticStep:
201
203
  async with db_registry.async_session() as session:
202
204
  step = await StepModel.read_async(db_session=session, identifier=step_id, actor=actor)
203
205
  if not step:
204
206
  raise NoResultFound(f"Step with id {step_id} does not exist")
205
207
  step.feedback = feedback
208
+ if tags:
209
+ step.tags = tags
206
210
  step = await step.update_async(session)
207
211
  return step.to_pydantic()
208
212
 
letta/utils.py CHANGED
@@ -536,6 +536,8 @@ def enforce_types(func):
536
536
 
537
537
  if origin is Union: # Handle Union types (including Optional)
538
538
  return any(matches_type(value, arg) for arg in args)
539
+ elif hasattr(hint, "__class__") and hint.__class__.__name__ == "UnionType": # Handle Python 3.10+ X | Y syntax
540
+ return any(matches_type(value, arg) for arg in args)
539
541
  elif origin is list and isinstance(value, list): # Handle List[T]
540
542
  element_type = args[0] if args else None
541
543
  return all(isinstance(v, element_type) for v in value) if element_type else True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: letta-nightly
3
- Version: 0.11.7.dev20250914103918
3
+ Version: 0.11.7.dev20250915104130
4
4
  Summary: Create LLM agents with long-term memory and custom tools
5
5
  Author-email: Letta Team <contact@letta.com>
6
6
  License: Apache License
@@ -13,7 +13,7 @@ letta/settings.py,sha256=QEjNUwRXGBgsQpQAs2kksQmGN5CbxKlxPPydrklx_Ms,15011
13
13
  letta/streaming_interface.py,sha256=rPMfwUcjqITWk2tVqFQm1hmP99tU2IOHg9gU2dgPSo8,16400
14
14
  letta/streaming_utils.py,sha256=ZRFGFpQqn9ujCEbgZdLM7yTjiuNNvqQ47sNhV8ix-yQ,16553
15
15
  letta/system.py,sha256=kHF7n3Viq7gV5UIUEXixod2gWa2jroUgztpEzMC1Sew,8925
16
- letta/utils.py,sha256=bSq3St7MUw9gN1g0ICdOhNNaUFYBC3EfJLG6qsRLSFA,43290
16
+ letta/utils.py,sha256=TwSAZKw3uCWAzmmEA156W4CYRDaEOiZmAO-zvzFdK6Q,43483
17
17
  letta/adapters/letta_llm_adapter.py,sha256=11wkOkEQfPXUuJoJxbK22wCa-8gnWiDAb3UOXOxLt5U,3427
18
18
  letta/adapters/letta_llm_request_adapter.py,sha256=wJhK5M_qOhRPAhgMmYI7EJcM8Op19tClnXe0kJ29a3Q,4831
19
19
  letta/adapters/letta_llm_stream_adapter.py,sha256=G8IqtXor0LUuW-dKtGJWsUt6DfJreVCn5h6W2lHEPBg,7658
@@ -355,24 +355,24 @@ letta/server/rest_api/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
355
355
  letta/server/rest_api/routers/openai/chat_completions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
356
356
  letta/server/rest_api/routers/openai/chat_completions/chat_completions.py,sha256=ohM1i8BsNxTiw8duuRT5X_0tSUzBwctQM4fJ5DXURic,5157
357
357
  letta/server/rest_api/routers/v1/__init__.py,sha256=9MnEA7CgtIxyU_dDNG0jm-Ziqu1somBml-e5gKjgd9I,1997
358
- letta/server/rest_api/routers/v1/agents.py,sha256=2lGLtfgB2ZtAa0EgaiaDlNV0GJhAi_kQQy7XqXB2DG0,77771
358
+ letta/server/rest_api/routers/v1/agents.py,sha256=rYCTQqlWHp0YgahElG1XOznD3OKT7zRr4R7mBo_ln8o,77729
359
359
  letta/server/rest_api/routers/v1/blocks.py,sha256=ykI77xnmIxPLqdAy5kzGyGw0w0ZRyVXn-O5Xcdj6-70,7690
360
360
  letta/server/rest_api/routers/v1/embeddings.py,sha256=PRaQlrmEXPiIdWsTbadrFsv3Afyv5oEFUdhgHA8FTi8,989
361
361
  letta/server/rest_api/routers/v1/folders.py,sha256=8Yb-bw2JdXBxMfrJNIZQk9_FKN2fet9Ccp8T83_c2sc,23539
362
362
  letta/server/rest_api/routers/v1/groups.py,sha256=PlCKfG1ZUubg-bNVRBmqJNBMvvZtHDvT50LUKKd0w9I,11466
363
- letta/server/rest_api/routers/v1/health.py,sha256=MoOjkydhGcJXTiuJrKIB0etVXiRMdTa51S8RQ8-50DQ,399
363
+ letta/server/rest_api/routers/v1/health.py,sha256=j43UoGJ7Yh5WzdwvqbKTEdWzlcKJBF6ZI5I1kslWim0,399
364
364
  letta/server/rest_api/routers/v1/identities.py,sha256=KUfw6avQIVHNw2lWz4pXOyTOPVy1g19CJGG-zayORl8,7858
365
365
  letta/server/rest_api/routers/v1/internal_templates.py,sha256=wY7tUmF7kZEVnjBVsw3_Tez4U2c8SABDJ2vplsKxhzM,11211
366
366
  letta/server/rest_api/routers/v1/jobs.py,sha256=ZcP_cqxgixCEYNtKVMqN1FwErNY-945h7XZhQV4vcEE,4933
367
367
  letta/server/rest_api/routers/v1/llms.py,sha256=0VJuuGW9_ta0cBnSDtXd3Ngw7GjsqEN2NBf5U3b6M3I,1920
368
- letta/server/rest_api/routers/v1/messages.py,sha256=J4Sbn8oMX24_OoBpHFLpcJi7vgJxeihmu36EgcPmfjk,7662
368
+ letta/server/rest_api/routers/v1/messages.py,sha256=iXw59JTqpXs_I6JTxE5bNCh72EUExBOo2dewv68Lb94,8528
369
369
  letta/server/rest_api/routers/v1/organizations.py,sha256=OnG2vMDZEmN4eEvj24CPwiV76ImHQuHi2ojrgwJnw7I,2925
370
- letta/server/rest_api/routers/v1/providers.py,sha256=rypNWQ1VMjmZJYd48uvNGJsE2N22jDTxn89qvbDaOMs,4765
370
+ letta/server/rest_api/routers/v1/providers.py,sha256=T3xvtiJO89p_a0wJ1fFmqPOc--kGbmOXI9eWdDW260c,4834
371
371
  letta/server/rest_api/routers/v1/runs.py,sha256=WnYwoFNjHNZicTnCkvoXCxl0XiyVAEvF70TTaMCBhPw,12982
372
372
  letta/server/rest_api/routers/v1/sandbox_configs.py,sha256=f0xEOwR3PXqCS2HOjEv7UKfMWTwEaTHx105HW_X-LI4,8852
373
373
  letta/server/rest_api/routers/v1/sources.py,sha256=nXZxtHi40281VltWmx1RwGBbau_00UpzDS6teTLvt2w,22679
374
- letta/server/rest_api/routers/v1/steps.py,sha256=bTzfz1GR3VEZdJRYUGiSr6ZLd12i5faPsf3oAqu1eMk,5570
375
- letta/server/rest_api/routers/v1/tags.py,sha256=ef94QitUSJ3NQVffWF1ZqANUZ2b2jRyGHp_I3UUjhno,912
374
+ letta/server/rest_api/routers/v1/steps.py,sha256=t_RnOQR_dwthpPeE8Bko6hSXbW3GtMvJj-9wQYvDh6A,6670
375
+ letta/server/rest_api/routers/v1/tags.py,sha256=9VCZUc0YBZD07PvLPJl7iOaj2-foLaBJ5s5rZ8xzNHA,1608
376
376
  letta/server/rest_api/routers/v1/telemetry.py,sha256=eSTg7mWbuwPb2OTHQxwRM0EUEl49wHzNB6i1xJtH8BQ,1036
377
377
  letta/server/rest_api/routers/v1/tools.py,sha256=UMtJj3bX8fVe0VuuU5JS0TeaFimEzZ4YRyphSO2tQMU,51085
378
378
  letta/server/rest_api/routers/v1/users.py,sha256=J1vaTbS1UrBMgnPya7GdZ2wr3L9XHmkm6qdGY6pWaOI,2366
@@ -389,7 +389,7 @@ letta/server/ws_api/protocol.py,sha256=5mDgpfNZn_kNwHnpt5Dsuw8gdNH298sgxTGed3etz
389
389
  letta/server/ws_api/server.py,sha256=_16TQafm509rqRztZYqo0HKKZoe8ccBrNftd_kbIJTE,5833
390
390
  letta/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
391
391
  letta/services/agent_file_manager.py,sha256=bgYTyQA90Iqo3W-LprPtyyOKf2itoqivcRhh4EOUXss,30847
392
- letta/services/agent_manager.py,sha256=KaJRTWwvA1SpfKQFPPVCeYxIOKwpKmLMioeyHuGw63Y,168884
392
+ letta/services/agent_manager.py,sha256=C-k9S8_TwLRDSdCqu0YZXbwgSRn4_hPOpP2O62NkaMM,169791
393
393
  letta/services/agent_serialization_manager.py,sha256=lWXTzYItqVxJMyy9ZYlcCDQwC3ZKk9XPCHvBkoVuszA,46388
394
394
  letta/services/archive_manager.py,sha256=P10BjZ2PxLoIkCwJ8rx7qLzchNVBsqNG3_KzxTanCLQ,14060
395
395
  letta/services/block_manager.py,sha256=mohj12QqHenSBbBx0Xmry1Rw25Gy5DSljOITzAwqMtw,33683
@@ -407,7 +407,7 @@ letta/services/per_agent_lock_manager.py,sha256=cMaW8r-qhucQbiK27jVqz8wzhlr2yuRN
407
407
  letta/services/provider_manager.py,sha256=vysp_SgJDezn6YymOfTiNVKOF93EK_dLhsM7upzSjrM,10727
408
408
  letta/services/sandbox_config_manager.py,sha256=BwN3bebiFvcliTJpRkbOwGxmV5dUJ8B64kFfXAgAqDw,25989
409
409
  letta/services/source_manager.py,sha256=mH9l2KJ9R7yG1vdqhltOIVsAajQP4KbueKcB7ZgN0QA,18624
410
- letta/services/step_manager.py,sha256=RLDdxyPI0bxlp2CWr1zzGuNbyR6CAttw4wThpOQAQyE,20891
410
+ letta/services/step_manager.py,sha256=vfXhE-cuE40dv2Uv6pICrpleJeXMjYeEOrkvGcY_sqI,20987
411
411
  letta/services/telemetry_manager.py,sha256=zDdSsRrBYunmlemtUUL1Qh3bcKu5-nhL2n7AlAmVrgs,3297
412
412
  letta/services/tool_manager.py,sha256=zh52n6StaFF5-v6nu0kdNSzJq4du5ACv5iGw5_Y9EDM,43192
413
413
  letta/services/user_manager.py,sha256=XuG9eFrvax69sONx7t_D5kgpt5zNwyER-MhqLSDs8L4,9949
@@ -470,8 +470,8 @@ letta/templates/sandbox_code_file_async.py.j2,sha256=lb7nh_P2W9VZHzU_9TxSCEMUod7
470
470
  letta/templates/summary_request_text.j2,sha256=ZttQwXonW2lk4pJLYzLK0pmo4EO4EtUUIXjgXKiizuc,842
471
471
  letta/templates/template_helper.py,sha256=HkG3zwRc5NVGmSTQu5PUTpz7LevK43bzXVaQuN8urf0,1634
472
472
  letta/types/__init__.py,sha256=hokKjCVFGEfR7SLMrtZsRsBfsC7yTIbgKPLdGg4K1eY,147
473
- letta_nightly-0.11.7.dev20250914103918.dist-info/METADATA,sha256=znAgbibaDvvLthC_McJ-W-HokPJdRIUijKN7KtgqoE0,24424
474
- letta_nightly-0.11.7.dev20250914103918.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
475
- letta_nightly-0.11.7.dev20250914103918.dist-info/entry_points.txt,sha256=m-94Paj-kxiR6Ktu0us0_2qfhn29DzF2oVzqBE6cu8w,41
476
- letta_nightly-0.11.7.dev20250914103918.dist-info/licenses/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
477
- letta_nightly-0.11.7.dev20250914103918.dist-info/RECORD,,
473
+ letta_nightly-0.11.7.dev20250915104130.dist-info/METADATA,sha256=mpHuQ8T7Dn58hWBd4OBq_IJhl-GIqXOmD1T4jt4SwSY,24424
474
+ letta_nightly-0.11.7.dev20250915104130.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
475
+ letta_nightly-0.11.7.dev20250915104130.dist-info/entry_points.txt,sha256=m-94Paj-kxiR6Ktu0us0_2qfhn29DzF2oVzqBE6cu8w,41
476
+ letta_nightly-0.11.7.dev20250915104130.dist-info/licenses/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
477
+ letta_nightly-0.11.7.dev20250915104130.dist-info/RECORD,,