letta-nightly 0.11.7.dev20251007104119__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.
Files changed (145) hide show
  1. letta/adapters/letta_llm_adapter.py +1 -0
  2. letta/adapters/letta_llm_request_adapter.py +0 -1
  3. letta/adapters/letta_llm_stream_adapter.py +7 -2
  4. letta/adapters/simple_llm_request_adapter.py +88 -0
  5. letta/adapters/simple_llm_stream_adapter.py +192 -0
  6. letta/agents/agent_loop.py +6 -0
  7. letta/agents/ephemeral_summary_agent.py +2 -1
  8. letta/agents/helpers.py +142 -6
  9. letta/agents/letta_agent.py +13 -33
  10. letta/agents/letta_agent_batch.py +2 -4
  11. letta/agents/letta_agent_v2.py +87 -77
  12. letta/agents/letta_agent_v3.py +899 -0
  13. letta/agents/voice_agent.py +2 -6
  14. letta/constants.py +8 -4
  15. letta/errors.py +40 -0
  16. letta/functions/function_sets/base.py +84 -4
  17. letta/functions/function_sets/multi_agent.py +0 -3
  18. letta/functions/schema_generator.py +113 -71
  19. letta/groups/dynamic_multi_agent.py +3 -2
  20. letta/groups/helpers.py +1 -2
  21. letta/groups/round_robin_multi_agent.py +3 -2
  22. letta/groups/sleeptime_multi_agent.py +3 -2
  23. letta/groups/sleeptime_multi_agent_v2.py +1 -1
  24. letta/groups/sleeptime_multi_agent_v3.py +17 -17
  25. letta/groups/supervisor_multi_agent.py +84 -80
  26. letta/helpers/converters.py +3 -0
  27. letta/helpers/message_helper.py +4 -0
  28. letta/helpers/tool_rule_solver.py +92 -5
  29. letta/interfaces/anthropic_streaming_interface.py +409 -0
  30. letta/interfaces/gemini_streaming_interface.py +296 -0
  31. letta/interfaces/openai_streaming_interface.py +752 -1
  32. letta/llm_api/anthropic_client.py +126 -16
  33. letta/llm_api/bedrock_client.py +4 -2
  34. letta/llm_api/deepseek_client.py +4 -1
  35. letta/llm_api/google_vertex_client.py +123 -42
  36. letta/llm_api/groq_client.py +4 -1
  37. letta/llm_api/llm_api_tools.py +11 -4
  38. letta/llm_api/llm_client_base.py +6 -2
  39. letta/llm_api/openai.py +32 -2
  40. letta/llm_api/openai_client.py +423 -18
  41. letta/llm_api/xai_client.py +4 -1
  42. letta/main.py +9 -5
  43. letta/memory.py +1 -0
  44. letta/orm/__init__.py +1 -1
  45. letta/orm/agent.py +10 -0
  46. letta/orm/block.py +7 -16
  47. letta/orm/blocks_agents.py +8 -2
  48. letta/orm/files_agents.py +2 -0
  49. letta/orm/job.py +7 -5
  50. letta/orm/mcp_oauth.py +1 -0
  51. letta/orm/message.py +21 -6
  52. letta/orm/organization.py +2 -0
  53. letta/orm/provider.py +6 -2
  54. letta/orm/run.py +71 -0
  55. letta/orm/sandbox_config.py +7 -1
  56. letta/orm/sqlalchemy_base.py +0 -306
  57. letta/orm/step.py +6 -5
  58. letta/orm/step_metrics.py +5 -5
  59. letta/otel/tracing.py +28 -3
  60. letta/plugins/defaults.py +4 -4
  61. letta/prompts/system_prompts/__init__.py +2 -0
  62. letta/prompts/system_prompts/letta_v1.py +25 -0
  63. letta/schemas/agent.py +3 -2
  64. letta/schemas/agent_file.py +9 -3
  65. letta/schemas/block.py +23 -10
  66. letta/schemas/enums.py +21 -2
  67. letta/schemas/job.py +17 -4
  68. letta/schemas/letta_message_content.py +71 -2
  69. letta/schemas/letta_stop_reason.py +5 -5
  70. letta/schemas/llm_config.py +53 -3
  71. letta/schemas/memory.py +1 -1
  72. letta/schemas/message.py +504 -117
  73. letta/schemas/openai/responses_request.py +64 -0
  74. letta/schemas/providers/__init__.py +2 -0
  75. letta/schemas/providers/anthropic.py +16 -0
  76. letta/schemas/providers/ollama.py +115 -33
  77. letta/schemas/providers/openrouter.py +52 -0
  78. letta/schemas/providers/vllm.py +2 -1
  79. letta/schemas/run.py +48 -42
  80. letta/schemas/step.py +2 -2
  81. letta/schemas/step_metrics.py +1 -1
  82. letta/schemas/tool.py +15 -107
  83. letta/schemas/tool_rule.py +88 -5
  84. letta/serialize_schemas/marshmallow_agent.py +1 -0
  85. letta/server/db.py +86 -408
  86. letta/server/rest_api/app.py +61 -10
  87. letta/server/rest_api/dependencies.py +14 -0
  88. letta/server/rest_api/redis_stream_manager.py +19 -8
  89. letta/server/rest_api/routers/v1/agents.py +364 -292
  90. letta/server/rest_api/routers/v1/blocks.py +14 -20
  91. letta/server/rest_api/routers/v1/identities.py +45 -110
  92. letta/server/rest_api/routers/v1/internal_templates.py +21 -0
  93. letta/server/rest_api/routers/v1/jobs.py +23 -6
  94. letta/server/rest_api/routers/v1/messages.py +1 -1
  95. letta/server/rest_api/routers/v1/runs.py +126 -85
  96. letta/server/rest_api/routers/v1/sandbox_configs.py +10 -19
  97. letta/server/rest_api/routers/v1/tools.py +281 -594
  98. letta/server/rest_api/routers/v1/voice.py +1 -1
  99. letta/server/rest_api/streaming_response.py +29 -29
  100. letta/server/rest_api/utils.py +122 -64
  101. letta/server/server.py +160 -887
  102. letta/services/agent_manager.py +236 -919
  103. letta/services/agent_serialization_manager.py +16 -0
  104. letta/services/archive_manager.py +0 -100
  105. letta/services/block_manager.py +211 -168
  106. letta/services/file_manager.py +1 -1
  107. letta/services/files_agents_manager.py +24 -33
  108. letta/services/group_manager.py +0 -142
  109. letta/services/helpers/agent_manager_helper.py +7 -2
  110. letta/services/helpers/run_manager_helper.py +85 -0
  111. letta/services/job_manager.py +96 -411
  112. letta/services/lettuce/__init__.py +6 -0
  113. letta/services/lettuce/lettuce_client_base.py +86 -0
  114. letta/services/mcp_manager.py +38 -6
  115. letta/services/message_manager.py +165 -362
  116. letta/services/organization_manager.py +0 -36
  117. letta/services/passage_manager.py +0 -345
  118. letta/services/provider_manager.py +0 -80
  119. letta/services/run_manager.py +301 -0
  120. letta/services/sandbox_config_manager.py +0 -234
  121. letta/services/step_manager.py +62 -39
  122. letta/services/summarizer/summarizer.py +9 -7
  123. letta/services/telemetry_manager.py +0 -16
  124. letta/services/tool_executor/builtin_tool_executor.py +35 -0
  125. letta/services/tool_executor/core_tool_executor.py +397 -2
  126. letta/services/tool_executor/files_tool_executor.py +3 -3
  127. letta/services/tool_executor/multi_agent_tool_executor.py +30 -15
  128. letta/services/tool_executor/tool_execution_manager.py +6 -8
  129. letta/services/tool_executor/tool_executor_base.py +3 -3
  130. letta/services/tool_manager.py +85 -339
  131. letta/services/tool_sandbox/base.py +24 -13
  132. letta/services/tool_sandbox/e2b_sandbox.py +16 -1
  133. letta/services/tool_schema_generator.py +123 -0
  134. letta/services/user_manager.py +0 -99
  135. letta/settings.py +20 -4
  136. {letta_nightly-0.11.7.dev20251007104119.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/METADATA +3 -5
  137. {letta_nightly-0.11.7.dev20251007104119.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/RECORD +140 -132
  138. letta/agents/temporal/activities/__init__.py +0 -4
  139. letta/agents/temporal/activities/example_activity.py +0 -7
  140. letta/agents/temporal/activities/prepare_messages.py +0 -10
  141. letta/agents/temporal/temporal_agent_workflow.py +0 -56
  142. letta/agents/temporal/types.py +0 -25
  143. {letta_nightly-0.11.7.dev20251007104119.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/WHEEL +0 -0
  144. {letta_nightly-0.11.7.dev20251007104119.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/entry_points.txt +0 -0
  145. {letta_nightly-0.11.7.dev20251007104119.dist-info → letta_nightly-0.11.7.dev20251008104128.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,86 @@
1
+ from letta.constants import DEFAULT_MAX_STEPS
2
+ from letta.schemas.agent import AgentState
3
+ from letta.schemas.letta_message import MessageType
4
+ from letta.schemas.message import MessageCreate
5
+ from letta.schemas.user import User
6
+
7
+
8
+ class LettuceClient:
9
+ """Base class for LettuceClient."""
10
+
11
+ def __init__(self):
12
+ """Initialize the LettuceClient."""
13
+ self.client: None = None
14
+
15
+ @classmethod
16
+ async def create(cls) -> "LettuceClient":
17
+ """
18
+ Asynchronously creates the client.
19
+
20
+ Returns:
21
+ LettuceClient: The created LettuceClient instance.
22
+ """
23
+ instance = cls()
24
+ return instance
25
+
26
+ def get_client(self) -> None:
27
+ """
28
+ Get the inner client.
29
+
30
+ Returns:
31
+ None: The inner client.
32
+ """
33
+ return self.client
34
+
35
+ async def get_status(self, run_id: str) -> str | None:
36
+ """
37
+ Get the status of a run.
38
+
39
+ Args:
40
+ run_id (str): The ID of the run.
41
+
42
+ Returns:
43
+ str | None: The status of the run or None if not available.
44
+ """
45
+ return None
46
+
47
+ async def cancel(self, run_id: str) -> str | None:
48
+ """
49
+ Cancel a run.
50
+
51
+ Args:
52
+ run_id (str): The ID of the run to cancel.
53
+
54
+ Returns:
55
+ str | None: The ID of the canceled run or None if not available.
56
+ """
57
+ return None
58
+
59
+ async def step(
60
+ self,
61
+ agent_state: AgentState,
62
+ actor: User,
63
+ input_messages: list[MessageCreate],
64
+ max_steps: int = DEFAULT_MAX_STEPS,
65
+ run_id: str | None = None,
66
+ use_assistant_message: bool = True,
67
+ include_return_message_types: list[MessageType] | None = None,
68
+ request_start_timestamp_ns: int | None = None,
69
+ ) -> str | None:
70
+ """
71
+ Execute the agent loop on Lettuce service.
72
+
73
+ Args:
74
+ agent_state (AgentState): The state of the agent.
75
+ actor (User): The actor.
76
+ input_messages (list[MessageCreate]): The input messages.
77
+ max_steps (int, optional): The maximum number of steps. Defaults to DEFAULT_MAX_STEPS.
78
+ run_id (str | None, optional): The ID of the run. Defaults to None.
79
+ use_assistant_message (bool, optional): Whether to use the assistant message. Defaults to True.
80
+ include_return_message_types (list[MessageType] | None, optional): The message types to include in the return. Defaults to None.
81
+ request_start_timestamp_ns (int | None, optional): The start timestamp of the request. Defaults to None.
82
+
83
+ Returns:
84
+ str | None: The ID of the run or None if client is not available.
85
+ """
86
+ return None
@@ -18,6 +18,7 @@ from letta.functions.mcp_client.types import (
18
18
  StdioServerConfig,
19
19
  StreamableHTTPServerConfig,
20
20
  )
21
+ from letta.functions.schema_generator import normalize_mcp_schema
21
22
  from letta.functions.schema_validator import validate_complete_json_schema
22
23
  from letta.log import get_logger
23
24
  from letta.orm.errors import NoResultFound
@@ -72,7 +73,9 @@ class MCPManager:
72
73
  tools = await mcp_client.list_tools()
73
74
  # Add health information to each tool
74
75
  for tool in tools:
76
+ # Try to normalize the schema and re-validate\
75
77
  if tool.inputSchema:
78
+ tool.inputSchema = normalize_mcp_schema(tool.inputSchema)
76
79
  health_status, reasons = validate_complete_json_schema(tool.inputSchema)
77
80
  tool.health = MCPToolHealth(status=health_status.value, reasons=reasons)
78
81
 
@@ -140,12 +143,41 @@ class MCPManager:
140
143
  for mcp_tool in mcp_tools:
141
144
  # TODO: @jnjpng move health check to tool class
142
145
  if mcp_tool.name == mcp_tool_name:
143
- # Check tool health - reject only INVALID tools
144
- if mcp_tool.health:
145
- if mcp_tool.health.status == "INVALID":
146
- raise ValueError(
147
- f"Tool {mcp_tool_name} cannot be attached, JSON schema is invalid.Reasons: {', '.join(mcp_tool.health.reasons)}"
148
- )
146
+ # Check tool health - but try normalization first for INVALID schemas
147
+ if mcp_tool.health and mcp_tool.health.status == "INVALID":
148
+ logger.info(f"Attempting to normalize INVALID schema for tool {mcp_tool_name}")
149
+ logger.info(f"Original health reasons: {mcp_tool.health.reasons}")
150
+
151
+ # Try to normalize the schema and re-validate
152
+ try:
153
+ # Normalize the schema to fix common issues
154
+ logger.debug(f"Normalizing schema for {mcp_tool_name}")
155
+ normalized_schema = normalize_mcp_schema(mcp_tool.inputSchema)
156
+
157
+ # Re-validate after normalization
158
+ logger.debug(f"Re-validating schema for {mcp_tool_name}")
159
+ health_status, health_reasons = validate_complete_json_schema(normalized_schema)
160
+ logger.info(f"After normalization: status={health_status.value}, reasons={health_reasons}")
161
+
162
+ # Update the tool's schema and health (use inputSchema, not input_schema)
163
+ mcp_tool.inputSchema = normalized_schema
164
+ mcp_tool.health.status = health_status.value
165
+ mcp_tool.health.reasons = health_reasons
166
+
167
+ # Log the normalization result
168
+ if health_status.value != "INVALID":
169
+ logger.info(f"✓ MCP tool {mcp_tool_name} schema normalized successfully: {health_status.value}")
170
+ else:
171
+ logger.warning(f"MCP tool {mcp_tool_name} still INVALID after normalization. Reasons: {health_reasons}")
172
+ except Exception as e:
173
+ logger.error(f"Failed to normalize schema for tool {mcp_tool_name}: {e}", exc_info=True)
174
+
175
+ # After normalization attempt, check if still INVALID
176
+ if mcp_tool.health and mcp_tool.health.status == "INVALID":
177
+ raise ValueError(
178
+ f"Tool {mcp_tool_name} cannot be attached, JSON schema is invalid even after normalization. "
179
+ f"Reasons: {', '.join(mcp_tool.health.reasons)}"
180
+ )
149
181
 
150
182
  tool_create = ToolCreate.from_mcp(mcp_server_name=mcp_server_name, mcp_tool=mcp_tool)
151
183
  return await self.tool_manager.create_mcp_tool_async(