letta-nightly 0.13.0.dev20251031104146__py3-none-any.whl → 0.13.1.dev20251101010313__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/__init__.py +1 -1
- letta/adapters/simple_llm_stream_adapter.py +1 -0
- letta/agents/letta_agent_v2.py +8 -0
- letta/agents/letta_agent_v3.py +127 -27
- letta/agents/temporal/activities/__init__.py +25 -0
- letta/agents/temporal/activities/create_messages.py +26 -0
- letta/agents/temporal/activities/create_step.py +57 -0
- letta/agents/temporal/activities/example_activity.py +9 -0
- letta/agents/temporal/activities/execute_tool.py +130 -0
- letta/agents/temporal/activities/llm_request.py +114 -0
- letta/agents/temporal/activities/prepare_messages.py +27 -0
- letta/agents/temporal/activities/refresh_context.py +160 -0
- letta/agents/temporal/activities/summarize_conversation_history.py +77 -0
- letta/agents/temporal/activities/update_message_ids.py +25 -0
- letta/agents/temporal/activities/update_run.py +43 -0
- letta/agents/temporal/constants.py +59 -0
- letta/agents/temporal/temporal_agent_workflow.py +704 -0
- letta/agents/temporal/types.py +275 -0
- letta/constants.py +11 -0
- letta/errors.py +4 -0
- letta/functions/function_sets/base.py +0 -11
- letta/groups/helpers.py +7 -1
- letta/groups/sleeptime_multi_agent_v4.py +4 -3
- letta/interfaces/anthropic_streaming_interface.py +0 -1
- letta/interfaces/openai_streaming_interface.py +103 -100
- letta/llm_api/anthropic_client.py +57 -12
- letta/llm_api/bedrock_client.py +1 -0
- letta/llm_api/deepseek_client.py +3 -2
- letta/llm_api/google_vertex_client.py +5 -4
- letta/llm_api/groq_client.py +1 -0
- letta/llm_api/llm_client_base.py +15 -1
- letta/llm_api/openai.py +2 -2
- letta/llm_api/openai_client.py +17 -3
- letta/llm_api/xai_client.py +1 -0
- letta/orm/agent.py +3 -0
- letta/orm/organization.py +4 -0
- letta/orm/sqlalchemy_base.py +7 -0
- letta/otel/tracing.py +131 -4
- letta/schemas/agent.py +108 -40
- letta/schemas/agent_file.py +10 -10
- letta/schemas/block.py +22 -3
- letta/schemas/enums.py +21 -0
- letta/schemas/environment_variables.py +3 -2
- letta/schemas/group.py +3 -3
- letta/schemas/letta_response.py +36 -4
- letta/schemas/llm_batch_job.py +3 -3
- letta/schemas/llm_config.py +123 -4
- letta/schemas/mcp.py +3 -2
- letta/schemas/mcp_server.py +3 -2
- letta/schemas/message.py +167 -49
- letta/schemas/model.py +265 -0
- letta/schemas/organization.py +2 -1
- letta/schemas/passage.py +2 -1
- letta/schemas/provider_trace.py +2 -1
- letta/schemas/providers/openrouter.py +1 -2
- letta/schemas/run_metrics.py +2 -1
- letta/schemas/sandbox_config.py +3 -1
- letta/schemas/step_metrics.py +2 -1
- letta/schemas/tool_rule.py +2 -2
- letta/schemas/user.py +2 -1
- letta/server/rest_api/app.py +5 -1
- letta/server/rest_api/routers/v1/__init__.py +4 -0
- letta/server/rest_api/routers/v1/agents.py +71 -9
- letta/server/rest_api/routers/v1/blocks.py +7 -7
- letta/server/rest_api/routers/v1/groups.py +40 -0
- letta/server/rest_api/routers/v1/identities.py +2 -2
- letta/server/rest_api/routers/v1/internal_agents.py +31 -0
- letta/server/rest_api/routers/v1/internal_blocks.py +177 -0
- letta/server/rest_api/routers/v1/internal_runs.py +25 -1
- letta/server/rest_api/routers/v1/runs.py +2 -22
- letta/server/rest_api/routers/v1/tools.py +12 -1
- letta/server/server.py +20 -4
- letta/services/agent_manager.py +4 -4
- letta/services/archive_manager.py +16 -0
- letta/services/group_manager.py +44 -0
- letta/services/helpers/run_manager_helper.py +2 -2
- letta/services/lettuce/lettuce_client.py +148 -0
- letta/services/mcp/base_client.py +9 -3
- letta/services/run_manager.py +148 -37
- letta/services/source_manager.py +91 -3
- letta/services/step_manager.py +2 -3
- letta/services/streaming_service.py +52 -13
- letta/services/summarizer/summarizer.py +28 -2
- letta/services/tool_executor/builtin_tool_executor.py +1 -1
- letta/services/tool_executor/core_tool_executor.py +2 -117
- letta/services/tool_sandbox/e2b_sandbox.py +4 -1
- letta/services/tool_schema_generator.py +2 -2
- letta/validators.py +21 -0
- {letta_nightly-0.13.0.dev20251031104146.dist-info → letta_nightly-0.13.1.dev20251101010313.dist-info}/METADATA +1 -1
- {letta_nightly-0.13.0.dev20251031104146.dist-info → letta_nightly-0.13.1.dev20251101010313.dist-info}/RECORD +93 -87
- letta/agent.py +0 -1758
- letta/cli/cli_load.py +0 -16
- letta/client/__init__.py +0 -0
- letta/client/streaming.py +0 -95
- letta/client/utils.py +0 -78
- letta/functions/async_composio_toolset.py +0 -109
- letta/functions/composio_helpers.py +0 -96
- letta/helpers/composio_helpers.py +0 -38
- letta/orm/job_messages.py +0 -33
- letta/schemas/providers.py +0 -1617
- letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +0 -132
- letta/services/tool_executor/composio_tool_executor.py +0 -57
- {letta_nightly-0.13.0.dev20251031104146.dist-info → letta_nightly-0.13.1.dev20251101010313.dist-info}/WHEEL +0 -0
- {letta_nightly-0.13.0.dev20251031104146.dist-info → letta_nightly-0.13.1.dev20251101010313.dist-info}/entry_points.txt +0 -0
- {letta_nightly-0.13.0.dev20251031104146.dist-info → letta_nightly-0.13.1.dev20251101010313.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,7 +4,13 @@ import traceback
|
|
|
4
4
|
from typing import List, Optional, Tuple, Union
|
|
5
5
|
|
|
6
6
|
from letta.agents.ephemeral_summary_agent import EphemeralSummaryAgent
|
|
7
|
-
from letta.constants import
|
|
7
|
+
from letta.constants import (
|
|
8
|
+
DEFAULT_MESSAGE_TOOL,
|
|
9
|
+
DEFAULT_MESSAGE_TOOL_KWARG,
|
|
10
|
+
MESSAGE_SUMMARY_REQUEST_ACK,
|
|
11
|
+
TOOL_RETURN_TRUNCATION_CHARS,
|
|
12
|
+
)
|
|
13
|
+
from letta.errors import ContextWindowExceededError
|
|
8
14
|
from letta.helpers.message_helper import convert_message_creates_to_messages
|
|
9
15
|
from letta.llm_api.llm_client import LLMClient
|
|
10
16
|
from letta.log import get_logger
|
|
@@ -394,7 +400,27 @@ async def simple_summary(messages: List[Message], llm_config: LLMConfig, actor:
|
|
|
394
400
|
response_data = await llm_client.request_async(request_data, summarizer_llm_config)
|
|
395
401
|
except Exception as e:
|
|
396
402
|
# handle LLM error (likely a context window exceeded error)
|
|
397
|
-
|
|
403
|
+
try:
|
|
404
|
+
raise llm_client.handle_llm_error(e)
|
|
405
|
+
except ContextWindowExceededError as context_error:
|
|
406
|
+
logger.warning(
|
|
407
|
+
f"Context window exceeded during summarization, falling back to truncated tool returns. Original error: {context_error}"
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Fallback: rebuild request with truncated tool returns
|
|
411
|
+
request_data = llm_client.build_request_data(
|
|
412
|
+
AgentType.letta_v1_agent,
|
|
413
|
+
input_messages_obj,
|
|
414
|
+
summarizer_llm_config,
|
|
415
|
+
tools=[],
|
|
416
|
+
tool_return_truncation_chars=TOOL_RETURN_TRUNCATION_CHARS,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
try:
|
|
420
|
+
response_data = await llm_client.request_async(request_data, summarizer_llm_config)
|
|
421
|
+
except Exception as fallback_error:
|
|
422
|
+
logger.error(f"Fallback summarization also failed: {fallback_error}")
|
|
423
|
+
raise llm_client.handle_llm_error(fallback_error)
|
|
398
424
|
response = llm_client.convert_response_to_chat_completion(response_data, input_messages_obj, summarizer_llm_config)
|
|
399
425
|
if response.choices[0].message.content is None:
|
|
400
426
|
logger.warning("No content returned from summarizer")
|
|
@@ -189,7 +189,7 @@ class LettaBuiltinToolExecutor(ToolExecutor):
|
|
|
189
189
|
return json.dumps(response, indent=2, ensure_ascii=False)
|
|
190
190
|
|
|
191
191
|
except Exception as e:
|
|
192
|
-
logger.
|
|
192
|
+
logger.info(f"Exa search failed for query '{query}': {str(e)}")
|
|
193
193
|
return json.dumps({"query": query, "error": f"Search failed: {str(e)}"})
|
|
194
194
|
|
|
195
195
|
async def fetch_webpage(self, agent_state: "AgentState", url: str) -> str:
|
|
@@ -688,115 +688,6 @@ class LettaCoreToolExecutor(ToolExecutor):
|
|
|
688
688
|
except Exception as e:
|
|
689
689
|
raise Exception(f"Error performing rename: {str(e)}")
|
|
690
690
|
|
|
691
|
-
async def memory_view(self, agent_state: AgentState, actor: User, path: str, view_range: Optional[int] = None) -> str:
|
|
692
|
-
"""View the content of a memory block with optional line range."""
|
|
693
|
-
try:
|
|
694
|
-
# Special case: if path is "/memories", list all blocks
|
|
695
|
-
if path == "/memories":
|
|
696
|
-
blocks = agent_state.memory.get_blocks()
|
|
697
|
-
|
|
698
|
-
if not blocks:
|
|
699
|
-
raise ValueError("No memory blocks found.")
|
|
700
|
-
|
|
701
|
-
result_lines = [f"Found {len(blocks)} memory block(s):\n"]
|
|
702
|
-
|
|
703
|
-
for i, block in enumerate(blocks, 1):
|
|
704
|
-
content = str(block.value)
|
|
705
|
-
content_length = len(content)
|
|
706
|
-
line_count = len(content.split("\n")) if content else 0
|
|
707
|
-
|
|
708
|
-
# Basic info
|
|
709
|
-
block_info = [f"{i}. {block.label}"]
|
|
710
|
-
|
|
711
|
-
# Add description if available
|
|
712
|
-
if block.description:
|
|
713
|
-
block_info.append(f" Description: {block.description}")
|
|
714
|
-
|
|
715
|
-
# Add read-only status
|
|
716
|
-
if block.read_only:
|
|
717
|
-
block_info.append(" Read-only: true")
|
|
718
|
-
|
|
719
|
-
# Add content stats
|
|
720
|
-
block_info.append(f" Character limit: {block.limit}")
|
|
721
|
-
block_info.append(f" Current length: {content_length} characters")
|
|
722
|
-
block_info.append(f" Lines: {line_count}")
|
|
723
|
-
|
|
724
|
-
# Add content preview (first 100 characters)
|
|
725
|
-
if content:
|
|
726
|
-
preview = content[:100].replace("\n", "\\n")
|
|
727
|
-
if len(content) > 100:
|
|
728
|
-
preview += "..."
|
|
729
|
-
block_info.append(f" Preview: {preview}")
|
|
730
|
-
else:
|
|
731
|
-
block_info.append(" Preview: (empty)")
|
|
732
|
-
|
|
733
|
-
result_lines.append("\n".join(block_info))
|
|
734
|
-
if i < len(blocks): # Add separator between blocks
|
|
735
|
-
result_lines.append("")
|
|
736
|
-
|
|
737
|
-
return "\n".join(result_lines)
|
|
738
|
-
|
|
739
|
-
# Extract memory block label from path (e.g., "/memories/preferences.txt" -> "preferences.txt")
|
|
740
|
-
if path.startswith("/memories/"):
|
|
741
|
-
label = path[10:] # Remove "/memories/" prefix
|
|
742
|
-
else:
|
|
743
|
-
label = path
|
|
744
|
-
|
|
745
|
-
# Get the memory block
|
|
746
|
-
memory_block = agent_state.memory.get_block(label)
|
|
747
|
-
if memory_block is None:
|
|
748
|
-
raise ValueError(f"Error: Memory block '{label}' does not exist")
|
|
749
|
-
|
|
750
|
-
# Get the content
|
|
751
|
-
content = str(memory_block.value)
|
|
752
|
-
if not content:
|
|
753
|
-
raise ValueError(f"Memory block '{label}' is empty")
|
|
754
|
-
|
|
755
|
-
# Split content into lines
|
|
756
|
-
lines = content.split("\n")
|
|
757
|
-
total_lines = len(lines)
|
|
758
|
-
|
|
759
|
-
# Handle view_range parameter
|
|
760
|
-
if view_range is not None:
|
|
761
|
-
if view_range <= 0:
|
|
762
|
-
raise ValueError(f"Error: view_range must be positive, got {view_range}")
|
|
763
|
-
|
|
764
|
-
# Show only the first view_range lines
|
|
765
|
-
lines_to_show = lines[:view_range]
|
|
766
|
-
range_info = f" (showing first {view_range} of {total_lines} lines)"
|
|
767
|
-
else:
|
|
768
|
-
lines_to_show = lines
|
|
769
|
-
range_info = f" ({total_lines} lines total)"
|
|
770
|
-
|
|
771
|
-
# Format output with line numbers
|
|
772
|
-
numbered_lines = []
|
|
773
|
-
for i, line in enumerate(lines_to_show, start=1):
|
|
774
|
-
numbered_lines.append(f"Line {i}: {line}")
|
|
775
|
-
|
|
776
|
-
numbered_content = "\n".join(numbered_lines)
|
|
777
|
-
|
|
778
|
-
# Add metadata information
|
|
779
|
-
metadata_info = []
|
|
780
|
-
if memory_block.description:
|
|
781
|
-
metadata_info.append(f"Description: {memory_block.description}")
|
|
782
|
-
if memory_block.read_only:
|
|
783
|
-
metadata_info.append("Read-only: true")
|
|
784
|
-
metadata_info.append(f"Character limit: {memory_block.limit}")
|
|
785
|
-
metadata_info.append(f"Current length: {len(content)} characters")
|
|
786
|
-
|
|
787
|
-
metadata_str = "\n".join(metadata_info)
|
|
788
|
-
|
|
789
|
-
result = f"Memory block: {label}{range_info}\n"
|
|
790
|
-
result += f"Metadata:\n{metadata_str}\n\n"
|
|
791
|
-
result += f"Content:\n{numbered_content}"
|
|
792
|
-
|
|
793
|
-
return result
|
|
794
|
-
|
|
795
|
-
except KeyError:
|
|
796
|
-
raise ValueError(f"Error: Memory block '{label}' does not exist")
|
|
797
|
-
except Exception as e:
|
|
798
|
-
raise Exception(f"Error viewing memory block: {str(e)}")
|
|
799
|
-
|
|
800
691
|
async def memory_create(
|
|
801
692
|
self, agent_state: AgentState, actor: User, path: str, description: str, file_text: Optional[str] = None
|
|
802
693
|
) -> str:
|
|
@@ -961,14 +852,8 @@ class LettaCoreToolExecutor(ToolExecutor):
|
|
|
961
852
|
insert_text: Optional[str] = None,
|
|
962
853
|
old_path: Optional[str] = None,
|
|
963
854
|
new_path: Optional[str] = None,
|
|
964
|
-
view_range: Optional[int] = None,
|
|
965
855
|
) -> Optional[str]:
|
|
966
|
-
if command == "
|
|
967
|
-
if path is None:
|
|
968
|
-
raise ValueError("Error: path is required for view command")
|
|
969
|
-
return await self.memory_view(agent_state, actor, path, view_range)
|
|
970
|
-
|
|
971
|
-
elif command == "create":
|
|
856
|
+
if command == "create":
|
|
972
857
|
if path is None:
|
|
973
858
|
raise ValueError("Error: path is required for create command")
|
|
974
859
|
if description is None:
|
|
@@ -1007,4 +892,4 @@ class LettaCoreToolExecutor(ToolExecutor):
|
|
|
1007
892
|
)
|
|
1008
893
|
|
|
1009
894
|
else:
|
|
1010
|
-
raise ValueError(f"Error: Unknown command '{command}'. Supported commands:
|
|
895
|
+
raise ValueError(f"Error: Unknown command '{command}'. Supported commands: create, str_replace, insert, delete, rename")
|
|
@@ -102,7 +102,10 @@ class AsyncToolSandboxE2B(AsyncToolSandboxBase):
|
|
|
102
102
|
function_name=self.tool_name, exception_name=execution.error.name, exception_message=execution.error.value
|
|
103
103
|
)
|
|
104
104
|
execution.logs.stderr.append(execution.error.traceback)
|
|
105
|
-
logger.info(
|
|
105
|
+
logger.info(
|
|
106
|
+
f"E2B execution failed for ID {e2b_sandbox.sandbox_id}: {self.tool_name} - {execution.error.name}: {execution.error.value}"
|
|
107
|
+
)
|
|
108
|
+
logger.info(f"Traceback from e2b sandbox: \n{execution.error.traceback}")
|
|
106
109
|
log_event(
|
|
107
110
|
"e2b_execution_failed",
|
|
108
111
|
{
|
|
@@ -45,7 +45,7 @@ def generate_schema_for_tool_creation(
|
|
|
45
45
|
|
|
46
46
|
return derive_typescript_json_schema(source_code=tool.source_code)
|
|
47
47
|
except Exception as e:
|
|
48
|
-
logger.
|
|
48
|
+
logger.warning(f"Failed to derive TypeScript json schema: {e}")
|
|
49
49
|
raise ValueError(f"Failed to derive TypeScript json schema: {e}")
|
|
50
50
|
|
|
51
51
|
# Python tools (default if not specified for backwards compatibility)
|
|
@@ -65,7 +65,7 @@ def generate_schema_for_tool_creation(
|
|
|
65
65
|
try:
|
|
66
66
|
return derive_openai_json_schema(source_code=tool.source_code)
|
|
67
67
|
except Exception as e:
|
|
68
|
-
logger.
|
|
68
|
+
logger.warning(f"Failed to derive json schema: {e}")
|
|
69
69
|
raise ValueError(f"Failed to derive json schema: {e}")
|
|
70
70
|
else:
|
|
71
71
|
# TODO: convert to explicit error
|
letta/validators.py
CHANGED
|
@@ -63,6 +63,27 @@ SandboxConfigId = Annotated[str, PATH_VALIDATORS[PrimitiveType.SANDBOX_CONFIG.va
|
|
|
63
63
|
StepId = Annotated[str, PATH_VALIDATORS[PrimitiveType.STEP.value]()]
|
|
64
64
|
IdentityId = Annotated[str, PATH_VALIDATORS[PrimitiveType.IDENTITY.value]()]
|
|
65
65
|
|
|
66
|
+
# Infrastructure types
|
|
67
|
+
McpServerId = Annotated[str, PATH_VALIDATORS[PrimitiveType.MCP_SERVER.value]()]
|
|
68
|
+
McpOAuthId = Annotated[str, PATH_VALIDATORS[PrimitiveType.MCP_OAUTH.value]()]
|
|
69
|
+
FileAgentId = Annotated[str, PATH_VALIDATORS[PrimitiveType.FILE_AGENT.value]()]
|
|
70
|
+
|
|
71
|
+
# Configuration types
|
|
72
|
+
SandboxEnvId = Annotated[str, PATH_VALIDATORS[PrimitiveType.SANDBOX_ENV.value]()]
|
|
73
|
+
AgentEnvId = Annotated[str, PATH_VALIDATORS[PrimitiveType.AGENT_ENV.value]()]
|
|
74
|
+
|
|
75
|
+
# Core entity types
|
|
76
|
+
UserId = Annotated[str, PATH_VALIDATORS[PrimitiveType.USER.value]()]
|
|
77
|
+
OrganizationId = Annotated[str, PATH_VALIDATORS[PrimitiveType.ORGANIZATION.value]()]
|
|
78
|
+
ToolRuleId = Annotated[str, PATH_VALIDATORS[PrimitiveType.TOOL_RULE.value]()]
|
|
79
|
+
|
|
80
|
+
# Batch processing types
|
|
81
|
+
BatchItemId = Annotated[str, PATH_VALIDATORS[PrimitiveType.BATCH_ITEM.value]()]
|
|
82
|
+
BatchRequestId = Annotated[str, PATH_VALIDATORS[PrimitiveType.BATCH_REQUEST.value]()]
|
|
83
|
+
|
|
84
|
+
# Telemetry types
|
|
85
|
+
ProviderTraceId = Annotated[str, PATH_VALIDATORS[PrimitiveType.PROVIDER_TRACE.value]()]
|
|
86
|
+
|
|
66
87
|
|
|
67
88
|
def raise_on_invalid_id(param_name: str, expected_prefix: PrimitiveType):
|
|
68
89
|
"""
|