letta-nightly 0.11.7.dev20251006104136__py3-none-any.whl → 0.11.7.dev20251008104128__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/adapters/letta_llm_adapter.py +1 -0
- letta/adapters/letta_llm_request_adapter.py +0 -1
- letta/adapters/letta_llm_stream_adapter.py +7 -2
- letta/adapters/simple_llm_request_adapter.py +88 -0
- letta/adapters/simple_llm_stream_adapter.py +192 -0
- letta/agents/agent_loop.py +6 -0
- letta/agents/ephemeral_summary_agent.py +2 -1
- letta/agents/helpers.py +142 -6
- letta/agents/letta_agent.py +13 -33
- letta/agents/letta_agent_batch.py +2 -4
- letta/agents/letta_agent_v2.py +87 -77
- letta/agents/letta_agent_v3.py +899 -0
- letta/agents/voice_agent.py +2 -6
- letta/constants.py +8 -4
- letta/errors.py +40 -0
- letta/functions/function_sets/base.py +84 -4
- letta/functions/function_sets/multi_agent.py +0 -3
- letta/functions/schema_generator.py +113 -71
- letta/groups/dynamic_multi_agent.py +3 -2
- letta/groups/helpers.py +1 -2
- letta/groups/round_robin_multi_agent.py +3 -2
- letta/groups/sleeptime_multi_agent.py +3 -2
- letta/groups/sleeptime_multi_agent_v2.py +1 -1
- letta/groups/sleeptime_multi_agent_v3.py +17 -17
- letta/groups/supervisor_multi_agent.py +84 -80
- letta/helpers/converters.py +3 -0
- letta/helpers/message_helper.py +4 -0
- letta/helpers/tool_rule_solver.py +92 -5
- letta/interfaces/anthropic_streaming_interface.py +409 -0
- letta/interfaces/gemini_streaming_interface.py +296 -0
- letta/interfaces/openai_streaming_interface.py +752 -1
- letta/llm_api/anthropic_client.py +126 -16
- letta/llm_api/bedrock_client.py +4 -2
- letta/llm_api/deepseek_client.py +4 -1
- letta/llm_api/google_vertex_client.py +123 -42
- letta/llm_api/groq_client.py +4 -1
- letta/llm_api/llm_api_tools.py +11 -4
- letta/llm_api/llm_client_base.py +6 -2
- letta/llm_api/openai.py +32 -2
- letta/llm_api/openai_client.py +423 -18
- letta/llm_api/xai_client.py +4 -1
- letta/main.py +9 -5
- letta/memory.py +1 -0
- letta/orm/__init__.py +1 -1
- letta/orm/agent.py +10 -0
- letta/orm/block.py +7 -16
- letta/orm/blocks_agents.py +8 -2
- letta/orm/files_agents.py +2 -0
- letta/orm/job.py +7 -5
- letta/orm/mcp_oauth.py +1 -0
- letta/orm/message.py +21 -6
- letta/orm/organization.py +2 -0
- letta/orm/provider.py +6 -2
- letta/orm/run.py +71 -0
- letta/orm/sandbox_config.py +7 -1
- letta/orm/sqlalchemy_base.py +0 -306
- letta/orm/step.py +6 -5
- letta/orm/step_metrics.py +5 -5
- letta/otel/tracing.py +28 -3
- letta/plugins/defaults.py +4 -4
- letta/prompts/system_prompts/__init__.py +2 -0
- letta/prompts/system_prompts/letta_v1.py +25 -0
- letta/schemas/agent.py +3 -2
- letta/schemas/agent_file.py +9 -3
- letta/schemas/block.py +23 -10
- letta/schemas/enums.py +21 -2
- letta/schemas/job.py +17 -4
- letta/schemas/letta_message_content.py +71 -2
- letta/schemas/letta_stop_reason.py +5 -5
- letta/schemas/llm_config.py +53 -3
- letta/schemas/memory.py +1 -1
- letta/schemas/message.py +504 -117
- letta/schemas/openai/responses_request.py +64 -0
- letta/schemas/providers/__init__.py +2 -0
- letta/schemas/providers/anthropic.py +16 -0
- letta/schemas/providers/ollama.py +115 -33
- letta/schemas/providers/openrouter.py +52 -0
- letta/schemas/providers/vllm.py +2 -1
- letta/schemas/run.py +48 -42
- letta/schemas/step.py +2 -2
- letta/schemas/step_metrics.py +1 -1
- letta/schemas/tool.py +15 -107
- letta/schemas/tool_rule.py +88 -5
- letta/serialize_schemas/marshmallow_agent.py +1 -0
- letta/server/db.py +86 -408
- letta/server/rest_api/app.py +61 -10
- letta/server/rest_api/dependencies.py +14 -0
- letta/server/rest_api/redis_stream_manager.py +19 -8
- letta/server/rest_api/routers/v1/agents.py +364 -292
- letta/server/rest_api/routers/v1/blocks.py +14 -20
- letta/server/rest_api/routers/v1/identities.py +45 -110
- letta/server/rest_api/routers/v1/internal_templates.py +21 -0
- letta/server/rest_api/routers/v1/jobs.py +23 -6
- letta/server/rest_api/routers/v1/messages.py +1 -1
- letta/server/rest_api/routers/v1/runs.py +126 -85
- letta/server/rest_api/routers/v1/sandbox_configs.py +10 -19
- letta/server/rest_api/routers/v1/tools.py +281 -594
- letta/server/rest_api/routers/v1/voice.py +1 -1
- letta/server/rest_api/streaming_response.py +29 -29
- letta/server/rest_api/utils.py +122 -64
- letta/server/server.py +160 -887
- letta/services/agent_manager.py +236 -919
- letta/services/agent_serialization_manager.py +16 -0
- letta/services/archive_manager.py +0 -100
- letta/services/block_manager.py +211 -168
- letta/services/file_manager.py +1 -1
- letta/services/files_agents_manager.py +24 -33
- letta/services/group_manager.py +0 -142
- letta/services/helpers/agent_manager_helper.py +7 -2
- letta/services/helpers/run_manager_helper.py +85 -0
- letta/services/job_manager.py +96 -411
- letta/services/lettuce/__init__.py +6 -0
- letta/services/lettuce/lettuce_client_base.py +86 -0
- letta/services/mcp_manager.py +38 -6
- letta/services/message_manager.py +165 -362
- letta/services/organization_manager.py +0 -36
- letta/services/passage_manager.py +0 -345
- letta/services/provider_manager.py +0 -80
- letta/services/run_manager.py +301 -0
- letta/services/sandbox_config_manager.py +0 -234
- letta/services/step_manager.py +62 -39
- letta/services/summarizer/summarizer.py +9 -7
- letta/services/telemetry_manager.py +0 -16
- letta/services/tool_executor/builtin_tool_executor.py +35 -0
- letta/services/tool_executor/core_tool_executor.py +397 -2
- letta/services/tool_executor/files_tool_executor.py +3 -3
- letta/services/tool_executor/multi_agent_tool_executor.py +30 -15
- letta/services/tool_executor/tool_execution_manager.py +6 -8
- letta/services/tool_executor/tool_executor_base.py +3 -3
- letta/services/tool_manager.py +85 -339
- letta/services/tool_sandbox/base.py +24 -13
- letta/services/tool_sandbox/e2b_sandbox.py +16 -1
- letta/services/tool_schema_generator.py +123 -0
- letta/services/user_manager.py +0 -99
- letta/settings.py +20 -4
- {letta_nightly-0.11.7.dev20251006104136.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/METADATA +3 -5
- {letta_nightly-0.11.7.dev20251006104136.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/RECORD +140 -132
- letta/agents/temporal/activities/__init__.py +0 -4
- letta/agents/temporal/activities/example_activity.py +0 -7
- letta/agents/temporal/activities/prepare_messages.py +0 -10
- letta/agents/temporal/temporal_agent_workflow.py +0 -56
- letta/agents/temporal/types.py +0 -25
- {letta_nightly-0.11.7.dev20251006104136.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/WHEEL +0 -0
- {letta_nightly-0.11.7.dev20251006104136.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/entry_points.txt +0 -0
- {letta_nightly-0.11.7.dev20251006104136.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/licenses/LICENSE +0 -0
@@ -208,6 +208,22 @@ class AgentSerializationManager:
|
|
208
208
|
)
|
209
209
|
agent_schema.id = agent_file_id
|
210
210
|
|
211
|
+
# Ensure all in-context messages are present before ID remapping.
|
212
|
+
# AgentSchema.from_agent_state fetches a limited slice (~50) and may exclude messages still
|
213
|
+
# referenced by in_context_message_ids. Fetch any missing in-context messages by ID so remapping succeeds.
|
214
|
+
existing_msg_ids = {m.id for m in (agent_schema.messages or [])}
|
215
|
+
in_context_ids = agent_schema.in_context_message_ids or []
|
216
|
+
missing_in_context_ids = [mid for mid in in_context_ids if mid not in existing_msg_ids]
|
217
|
+
if missing_in_context_ids:
|
218
|
+
missing_msgs = await self.message_manager.get_messages_by_ids_async(message_ids=missing_in_context_ids, actor=actor)
|
219
|
+
fetched_ids = {m.id for m in missing_msgs}
|
220
|
+
not_found = [mid for mid in missing_in_context_ids if mid not in fetched_ids]
|
221
|
+
if not_found:
|
222
|
+
# Surface a clear mapping error; handled upstream by the route/export wrapper.
|
223
|
+
raise AgentExportIdMappingError(db_id=not_found[0], entity_type=MessageSchema.__id_prefix__)
|
224
|
+
for msg in missing_msgs:
|
225
|
+
agent_schema.messages.append(MessageSchema.from_message(msg))
|
226
|
+
|
211
227
|
# wipe the values of tool_exec_environment_variables (they contain secrets)
|
212
228
|
agent_secrets = agent_schema.secrets or agent_schema.tool_exec_environment_variables
|
213
229
|
if agent_secrets:
|
@@ -19,32 +19,6 @@ logger = get_logger(__name__)
|
|
19
19
|
class ArchiveManager:
|
20
20
|
"""Manager class to handle business logic related to Archives."""
|
21
21
|
|
22
|
-
@enforce_types
|
23
|
-
@trace_method
|
24
|
-
def create_archive(
|
25
|
-
self,
|
26
|
-
name: str,
|
27
|
-
description: Optional[str] = None,
|
28
|
-
actor: PydanticUser = None,
|
29
|
-
) -> PydanticArchive:
|
30
|
-
"""Create a new archive."""
|
31
|
-
try:
|
32
|
-
with db_registry.session() as session:
|
33
|
-
# determine vector db provider based on settings
|
34
|
-
vector_db_provider = VectorDBProvider.TPUF if should_use_tpuf() else VectorDBProvider.NATIVE
|
35
|
-
|
36
|
-
archive = ArchiveModel(
|
37
|
-
name=name,
|
38
|
-
description=description,
|
39
|
-
organization_id=actor.organization_id,
|
40
|
-
vector_db_provider=vector_db_provider,
|
41
|
-
)
|
42
|
-
archive.create(session, actor=actor)
|
43
|
-
return archive.to_pydantic()
|
44
|
-
except Exception as e:
|
45
|
-
logger.exception(f"Failed to create archive {name}. error={e}")
|
46
|
-
raise
|
47
|
-
|
48
22
|
@enforce_types
|
49
23
|
@trace_method
|
50
24
|
async def create_archive_async(
|
@@ -160,36 +134,6 @@ class ArchiveManager:
|
|
160
134
|
)
|
161
135
|
return [a.to_pydantic() for a in archives]
|
162
136
|
|
163
|
-
@enforce_types
|
164
|
-
@trace_method
|
165
|
-
def attach_agent_to_archive(
|
166
|
-
self,
|
167
|
-
agent_id: str,
|
168
|
-
archive_id: str,
|
169
|
-
is_owner: bool,
|
170
|
-
actor: PydanticUser,
|
171
|
-
) -> None:
|
172
|
-
"""Attach an agent to an archive."""
|
173
|
-
with db_registry.session() as session:
|
174
|
-
# Check if already attached
|
175
|
-
existing = session.query(ArchivesAgents).filter_by(agent_id=agent_id, archive_id=archive_id).first()
|
176
|
-
|
177
|
-
if existing:
|
178
|
-
# Update ownership if needed
|
179
|
-
if existing.is_owner != is_owner:
|
180
|
-
existing.is_owner = is_owner
|
181
|
-
session.commit()
|
182
|
-
return
|
183
|
-
|
184
|
-
# Create new relationship
|
185
|
-
archives_agents = ArchivesAgents(
|
186
|
-
agent_id=agent_id,
|
187
|
-
archive_id=archive_id,
|
188
|
-
is_owner=is_owner,
|
189
|
-
)
|
190
|
-
session.add(archives_agents)
|
191
|
-
session.commit()
|
192
|
-
|
193
137
|
@enforce_types
|
194
138
|
@trace_method
|
195
139
|
async def attach_agent_to_archive_async(
|
@@ -345,50 +289,6 @@ class ArchiveManager:
|
|
345
289
|
# this shouldn't happen, but if it does, re-raise
|
346
290
|
raise
|
347
291
|
|
348
|
-
@enforce_types
|
349
|
-
@trace_method
|
350
|
-
def get_or_create_default_archive_for_agent(
|
351
|
-
self,
|
352
|
-
agent_id: str,
|
353
|
-
agent_name: Optional[str] = None,
|
354
|
-
actor: PydanticUser = None,
|
355
|
-
) -> PydanticArchive:
|
356
|
-
"""Get the agent's default archive, creating one if it doesn't exist."""
|
357
|
-
with db_registry.session() as session:
|
358
|
-
# First check if agent has any archives
|
359
|
-
query = select(ArchivesAgents.archive_id).where(ArchivesAgents.agent_id == agent_id)
|
360
|
-
result = session.execute(query)
|
361
|
-
archive_ids = [row[0] for row in result.fetchall()]
|
362
|
-
|
363
|
-
if archive_ids:
|
364
|
-
# TODO: Remove this check once we support multiple archives per agent
|
365
|
-
if len(archive_ids) > 1:
|
366
|
-
raise ValueError(f"Agent {agent_id} has multiple archives, which is not yet supported")
|
367
|
-
# Get the archive
|
368
|
-
archive = ArchiveModel.read(db_session=session, identifier=archive_ids[0], actor=actor)
|
369
|
-
return archive.to_pydantic()
|
370
|
-
|
371
|
-
# Create a default archive for this agent
|
372
|
-
archive_name = f"{agent_name or f'Agent {agent_id}'}'s Archive"
|
373
|
-
|
374
|
-
# Create the archive
|
375
|
-
archive_model = ArchiveModel(
|
376
|
-
name=archive_name,
|
377
|
-
description="Default archive created automatically",
|
378
|
-
organization_id=actor.organization_id,
|
379
|
-
)
|
380
|
-
archive_model.create(session, actor=actor)
|
381
|
-
|
382
|
-
# Attach the agent to the archive as owner
|
383
|
-
self.attach_agent_to_archive(
|
384
|
-
agent_id=agent_id,
|
385
|
-
archive_id=archive_model.id,
|
386
|
-
is_owner=True,
|
387
|
-
actor=actor,
|
388
|
-
)
|
389
|
-
|
390
|
-
return archive_model.to_pydantic()
|
391
|
-
|
392
292
|
@enforce_types
|
393
293
|
@trace_method
|
394
294
|
async def get_agents_for_archive_async(
|