letta-nightly 0.8.0.dev20250606195656__py3-none-any.whl → 0.8.3.dev20250607000559__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 (105) hide show
  1. letta/__init__.py +1 -1
  2. letta/agent.py +16 -12
  3. letta/agents/base_agent.py +1 -1
  4. letta/agents/helpers.py +13 -2
  5. letta/agents/letta_agent.py +72 -34
  6. letta/agents/letta_agent_batch.py +1 -2
  7. letta/agents/voice_agent.py +19 -13
  8. letta/agents/voice_sleeptime_agent.py +23 -6
  9. letta/constants.py +18 -0
  10. letta/data_sources/__init__.py +0 -0
  11. letta/data_sources/redis_client.py +282 -0
  12. letta/errors.py +0 -4
  13. letta/functions/function_sets/files.py +58 -0
  14. letta/functions/schema_generator.py +18 -1
  15. letta/groups/sleeptime_multi_agent_v2.py +13 -3
  16. letta/helpers/datetime_helpers.py +47 -3
  17. letta/helpers/decorators.py +69 -0
  18. letta/{services/helpers/noop_helper.py → helpers/singleton.py} +5 -0
  19. letta/interfaces/anthropic_streaming_interface.py +43 -24
  20. letta/interfaces/openai_streaming_interface.py +21 -19
  21. letta/llm_api/anthropic.py +1 -1
  22. letta/llm_api/anthropic_client.py +30 -16
  23. letta/llm_api/google_vertex_client.py +1 -1
  24. letta/llm_api/helpers.py +36 -30
  25. letta/llm_api/llm_api_tools.py +1 -1
  26. letta/llm_api/llm_client_base.py +29 -1
  27. letta/llm_api/openai.py +1 -1
  28. letta/llm_api/openai_client.py +6 -8
  29. letta/local_llm/chat_completion_proxy.py +1 -1
  30. letta/memory.py +1 -1
  31. letta/orm/enums.py +1 -0
  32. letta/orm/file.py +80 -3
  33. letta/orm/files_agents.py +13 -0
  34. letta/orm/passage.py +2 -0
  35. letta/orm/sqlalchemy_base.py +34 -11
  36. letta/otel/__init__.py +0 -0
  37. letta/otel/context.py +25 -0
  38. letta/otel/events.py +0 -0
  39. letta/otel/metric_registry.py +122 -0
  40. letta/otel/metrics.py +66 -0
  41. letta/otel/resource.py +26 -0
  42. letta/{tracing.py → otel/tracing.py} +55 -78
  43. letta/plugins/README.md +22 -0
  44. letta/plugins/__init__.py +0 -0
  45. letta/plugins/defaults.py +11 -0
  46. letta/plugins/plugins.py +72 -0
  47. letta/schemas/enums.py +8 -0
  48. letta/schemas/file.py +12 -0
  49. letta/schemas/letta_request.py +6 -0
  50. letta/schemas/passage.py +1 -0
  51. letta/schemas/tool.py +4 -0
  52. letta/server/db.py +7 -7
  53. letta/server/rest_api/app.py +8 -6
  54. letta/server/rest_api/routers/v1/agents.py +46 -37
  55. letta/server/rest_api/routers/v1/groups.py +3 -3
  56. letta/server/rest_api/routers/v1/sources.py +26 -3
  57. letta/server/rest_api/routers/v1/tools.py +7 -2
  58. letta/server/rest_api/utils.py +9 -6
  59. letta/server/server.py +25 -13
  60. letta/services/agent_manager.py +186 -194
  61. letta/services/block_manager.py +1 -1
  62. letta/services/context_window_calculator/context_window_calculator.py +1 -1
  63. letta/services/context_window_calculator/token_counter.py +3 -2
  64. letta/services/file_processor/chunker/line_chunker.py +34 -0
  65. letta/services/file_processor/file_processor.py +43 -12
  66. letta/services/file_processor/parser/mistral_parser.py +11 -1
  67. letta/services/files_agents_manager.py +96 -7
  68. letta/services/group_manager.py +6 -6
  69. letta/services/helpers/agent_manager_helper.py +404 -3
  70. letta/services/identity_manager.py +1 -1
  71. letta/services/job_manager.py +1 -1
  72. letta/services/llm_batch_manager.py +1 -1
  73. letta/services/mcp/stdio_client.py +5 -1
  74. letta/services/mcp_manager.py +4 -4
  75. letta/services/message_manager.py +1 -1
  76. letta/services/organization_manager.py +1 -1
  77. letta/services/passage_manager.py +604 -19
  78. letta/services/per_agent_lock_manager.py +1 -1
  79. letta/services/provider_manager.py +1 -1
  80. letta/services/sandbox_config_manager.py +1 -1
  81. letta/services/source_manager.py +178 -19
  82. letta/services/step_manager.py +2 -2
  83. letta/services/summarizer/summarizer.py +1 -1
  84. letta/services/telemetry_manager.py +1 -1
  85. letta/services/tool_executor/builtin_tool_executor.py +117 -0
  86. letta/services/tool_executor/composio_tool_executor.py +53 -0
  87. letta/services/tool_executor/core_tool_executor.py +474 -0
  88. letta/services/tool_executor/files_tool_executor.py +138 -0
  89. letta/services/tool_executor/mcp_tool_executor.py +45 -0
  90. letta/services/tool_executor/multi_agent_tool_executor.py +123 -0
  91. letta/services/tool_executor/tool_execution_manager.py +34 -14
  92. letta/services/tool_executor/tool_execution_sandbox.py +1 -1
  93. letta/services/tool_executor/tool_executor.py +3 -802
  94. letta/services/tool_executor/tool_executor_base.py +43 -0
  95. letta/services/tool_manager.py +55 -59
  96. letta/services/tool_sandbox/e2b_sandbox.py +1 -1
  97. letta/services/tool_sandbox/local_sandbox.py +6 -3
  98. letta/services/user_manager.py +6 -3
  99. letta/settings.py +23 -2
  100. letta/utils.py +7 -2
  101. {letta_nightly-0.8.0.dev20250606195656.dist-info → letta_nightly-0.8.3.dev20250607000559.dist-info}/METADATA +4 -2
  102. {letta_nightly-0.8.0.dev20250606195656.dist-info → letta_nightly-0.8.3.dev20250607000559.dist-info}/RECORD +105 -83
  103. {letta_nightly-0.8.0.dev20250606195656.dist-info → letta_nightly-0.8.3.dev20250607000559.dist-info}/LICENSE +0 -0
  104. {letta_nightly-0.8.0.dev20250606195656.dist-info → letta_nightly-0.8.3.dev20250607000559.dist-info}/WHEEL +0 -0
  105. {letta_nightly-0.8.0.dev20250606195656.dist-info → letta_nightly-0.8.3.dev20250607000559.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,43 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict, Optional
3
+
4
+ from letta.schemas.agent import AgentState
5
+ from letta.schemas.sandbox_config import SandboxConfig
6
+ from letta.schemas.tool import Tool
7
+ from letta.schemas.tool_execution_result import ToolExecutionResult
8
+ from letta.schemas.user import User
9
+ from letta.services.agent_manager import AgentManager
10
+ from letta.services.block_manager import BlockManager
11
+ from letta.services.message_manager import MessageManager
12
+ from letta.services.passage_manager import PassageManager
13
+
14
+
15
+ class ToolExecutor(ABC):
16
+ """Abstract base class for tool executors."""
17
+
18
+ def __init__(
19
+ self,
20
+ message_manager: MessageManager,
21
+ agent_manager: AgentManager,
22
+ block_manager: BlockManager,
23
+ passage_manager: PassageManager,
24
+ actor: User,
25
+ ):
26
+ self.message_manager = message_manager
27
+ self.agent_manager = agent_manager
28
+ self.block_manager = block_manager
29
+ self.passage_manager = passage_manager
30
+ self.actor = actor
31
+
32
+ @abstractmethod
33
+ async def execute(
34
+ self,
35
+ function_name: str,
36
+ function_args: dict,
37
+ tool: Tool,
38
+ actor: User,
39
+ agent_state: Optional[AgentState] = None,
40
+ sandbox_config: Optional[SandboxConfig] = None,
41
+ sandbox_env_vars: Optional[Dict[str, Any]] = None,
42
+ ) -> ToolExecutionResult:
43
+ """Execute the tool and return the result."""
@@ -1,7 +1,7 @@
1
1
  import asyncio
2
2
  import importlib
3
3
  import warnings
4
- from typing import List, Optional, Union
4
+ from typing import List, Optional, Set, Union
5
5
 
6
6
  from letta.constants import (
7
7
  BASE_FUNCTION_RETURN_CHAR_LIMIT,
@@ -11,6 +11,8 @@ from letta.constants import (
11
11
  BASE_VOICE_SLEEPTIME_CHAT_TOOLS,
12
12
  BASE_VOICE_SLEEPTIME_TOOLS,
13
13
  BUILTIN_TOOLS,
14
+ FILES_TOOLS,
15
+ LETTA_TOOL_MODULE_NAMES,
14
16
  LETTA_TOOL_SET,
15
17
  MCP_TOOL_TAG_NAME_PREFIX,
16
18
  MULTI_AGENT_TOOLS,
@@ -22,12 +24,12 @@ from letta.orm.enums import ToolType
22
24
  # TODO: Remove this once we translate all of these to the ORM
23
25
  from letta.orm.errors import NoResultFound
24
26
  from letta.orm.tool import Tool as ToolModel
27
+ from letta.otel.tracing import trace_method
25
28
  from letta.schemas.tool import Tool as PydanticTool
26
29
  from letta.schemas.tool import ToolCreate, ToolUpdate
27
30
  from letta.schemas.user import User as PydanticUser
28
31
  from letta.server.db import db_registry
29
32
  from letta.services.mcp.types import SSEServerConfig, StdioServerConfig
30
- from letta.tracing import trace_method
31
33
  from letta.utils import enforce_types, printd
32
34
 
33
35
  logger = get_logger(__name__)
@@ -368,12 +370,10 @@ class ToolManager:
368
370
  def upsert_base_tools(self, actor: PydanticUser) -> List[PydanticTool]:
369
371
  """Add default tools in base.py and multi_agent.py"""
370
372
  functions_to_schema = {}
371
- module_names = ["base", "multi_agent", "voice", "builtin"]
372
373
 
373
- for module_name in module_names:
374
- full_module_name = f"letta.functions.function_sets.{module_name}"
374
+ for module_name in LETTA_TOOL_MODULE_NAMES:
375
375
  try:
376
- module = importlib.import_module(full_module_name)
376
+ module = importlib.import_module(module_name)
377
377
  except Exception as e:
378
378
  # Handle other general exceptions
379
379
  raise e
@@ -407,6 +407,9 @@ class ToolManager:
407
407
  elif name in BUILTIN_TOOLS:
408
408
  tool_type = ToolType.LETTA_BUILTIN
409
409
  tags = [tool_type.value]
410
+ elif name in FILES_TOOLS:
411
+ tool_type = ToolType.LETTA_FILES_CORE
412
+ tags = [tool_type.value]
410
413
  else:
411
414
  raise ValueError(
412
415
  f"Tool name {name} is not in the list of base tool names: {BASE_TOOLS + BASE_MEMORY_TOOLS + MULTI_AGENT_TOOLS + BASE_SLEEPTIME_TOOLS + BASE_VOICE_SLEEPTIME_TOOLS + BASE_VOICE_SLEEPTIME_CHAT_TOOLS}"
@@ -431,66 +434,59 @@ class ToolManager:
431
434
 
432
435
  @enforce_types
433
436
  @trace_method
434
- async def upsert_base_tools_async(self, actor: PydanticUser) -> List[PydanticTool]:
435
- """Add default tools in base.py and multi_agent.py"""
436
- functions_to_schema = {}
437
- module_names = ["base", "multi_agent", "voice", "builtin"]
438
-
439
- for module_name in module_names:
440
- full_module_name = f"letta.functions.function_sets.{module_name}"
441
- try:
442
- module = importlib.import_module(full_module_name)
443
- except Exception as e:
444
- # Handle other general exceptions
445
- raise e
437
+ async def upsert_base_tools_async(
438
+ self,
439
+ actor: PydanticUser,
440
+ allowed_types: Optional[Set[ToolType]] = None,
441
+ ) -> List[PydanticTool]:
442
+ """Add default tools defined in the various function_sets modules, optionally filtered by ToolType."""
446
443
 
444
+ functions_to_schema = {}
445
+ for module_name in LETTA_TOOL_MODULE_NAMES:
447
446
  try:
448
- # Load the function set
447
+ module = importlib.import_module(module_name)
449
448
  functions_to_schema.update(load_function_set(module))
450
449
  except ValueError as e:
451
- err = f"Error loading function set '{module_name}': {e}"
452
- warnings.warn(err)
450
+ warnings.warn(f"Error loading function set '{module_name}': {e}")
451
+ except Exception as e:
452
+ raise e
453
453
 
454
- # create tool in db
455
454
  tools = []
456
455
  for name, schema in functions_to_schema.items():
457
- if name in LETTA_TOOL_SET:
458
- if name in BASE_TOOLS:
459
- tool_type = ToolType.LETTA_CORE
460
- tags = [tool_type.value]
461
- elif name in BASE_MEMORY_TOOLS:
462
- tool_type = ToolType.LETTA_MEMORY_CORE
463
- tags = [tool_type.value]
464
- elif name in MULTI_AGENT_TOOLS:
465
- tool_type = ToolType.LETTA_MULTI_AGENT_CORE
466
- tags = [tool_type.value]
467
- elif name in BASE_SLEEPTIME_TOOLS:
468
- tool_type = ToolType.LETTA_SLEEPTIME_CORE
469
- tags = [tool_type.value]
470
- elif name in BASE_VOICE_SLEEPTIME_TOOLS or name in BASE_VOICE_SLEEPTIME_CHAT_TOOLS:
471
- tool_type = ToolType.LETTA_VOICE_SLEEPTIME_CORE
472
- tags = [tool_type.value]
473
- elif name in BUILTIN_TOOLS:
474
- tool_type = ToolType.LETTA_BUILTIN
475
- tags = [tool_type.value]
476
- else:
477
- raise ValueError(
478
- f"Tool name {name} is not in the list of base tool names: {BASE_TOOLS + BASE_MEMORY_TOOLS + MULTI_AGENT_TOOLS + BASE_SLEEPTIME_TOOLS + BASE_VOICE_SLEEPTIME_TOOLS + BASE_VOICE_SLEEPTIME_CHAT_TOOLS}"
479
- )
480
-
481
- # create to tool
482
- tools.append(
483
- self.create_or_update_tool_async(
484
- PydanticTool(
485
- name=name,
486
- tags=tags,
487
- source_type="python",
488
- tool_type=tool_type,
489
- return_char_limit=BASE_FUNCTION_RETURN_CHAR_LIMIT,
490
- ),
491
- actor=actor,
492
- )
456
+ if name not in LETTA_TOOL_SET:
457
+ continue
458
+
459
+ if name in BASE_TOOLS:
460
+ tool_type = ToolType.LETTA_CORE
461
+ elif name in BASE_MEMORY_TOOLS:
462
+ tool_type = ToolType.LETTA_MEMORY_CORE
463
+ elif name in BASE_SLEEPTIME_TOOLS:
464
+ tool_type = ToolType.LETTA_SLEEPTIME_CORE
465
+ elif name in MULTI_AGENT_TOOLS:
466
+ tool_type = ToolType.LETTA_MULTI_AGENT_CORE
467
+ elif name in BASE_VOICE_SLEEPTIME_TOOLS or name in BASE_VOICE_SLEEPTIME_CHAT_TOOLS:
468
+ tool_type = ToolType.LETTA_VOICE_SLEEPTIME_CORE
469
+ elif name in BUILTIN_TOOLS:
470
+ tool_type = ToolType.LETTA_BUILTIN
471
+ elif name in FILES_TOOLS:
472
+ tool_type = ToolType.LETTA_FILES_CORE
473
+ else:
474
+ raise ValueError(f"Tool name {name} is not recognized in any known base tool set.")
475
+
476
+ if allowed_types is not None and tool_type not in allowed_types:
477
+ continue
478
+
479
+ tools.append(
480
+ self.create_or_update_tool_async(
481
+ PydanticTool(
482
+ name=name,
483
+ tags=[tool_type.value],
484
+ source_type="python",
485
+ tool_type=tool_type,
486
+ return_char_limit=BASE_FUNCTION_RETURN_CHAR_LIMIT,
487
+ ),
488
+ actor=actor,
493
489
  )
490
+ )
494
491
 
495
- # TODO: Delete any base tools that are stale
496
492
  return await asyncio.gather(*tools)
@@ -3,13 +3,13 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
3
3
  from e2b_code_interpreter import AsyncSandbox
4
4
 
5
5
  from letta.log import get_logger
6
+ from letta.otel.tracing import log_event, trace_method
6
7
  from letta.schemas.agent import AgentState
7
8
  from letta.schemas.sandbox_config import SandboxConfig, SandboxType
8
9
  from letta.schemas.tool import Tool
9
10
  from letta.schemas.tool_execution_result import ToolExecutionResult
10
11
  from letta.services.helpers.tool_parser_helper import parse_stdout_best_effort
11
12
  from letta.services.tool_sandbox.base import AsyncToolSandboxBase
12
- from letta.tracing import log_event, trace_method
13
13
  from letta.types import JsonDict
14
14
  from letta.utils import get_friendly_error_msg
15
15
 
@@ -8,6 +8,7 @@ from typing import Any, Dict, Optional
8
8
 
9
9
  from pydantic.config import JsonDict
10
10
 
11
+ from letta.otel.tracing import log_event, trace_method
11
12
  from letta.schemas.agent import AgentState
12
13
  from letta.schemas.sandbox_config import SandboxConfig, SandboxType
13
14
  from letta.schemas.tool import Tool
@@ -20,7 +21,6 @@ from letta.services.helpers.tool_execution_helper import (
20
21
  from letta.services.helpers.tool_parser_helper import parse_stdout_best_effort
21
22
  from letta.services.tool_sandbox.base import AsyncToolSandboxBase
22
23
  from letta.settings import tool_settings
23
- from letta.tracing import log_event, trace_method
24
24
  from letta.utils import get_friendly_error_msg, parse_stderr_error_msg
25
25
 
26
26
 
@@ -152,8 +152,11 @@ class AsyncToolSandboxLocal(AsyncToolSandboxBase):
152
152
  print(f"Auto-generated code for debugging:\n\n{code}")
153
153
  raise e
154
154
  finally:
155
- # Clean up the temp file
156
- os.remove(temp_file_path)
155
+ # Clean up the temp file if not debugging
156
+ from letta.settings import settings
157
+
158
+ if not settings.debug:
159
+ os.remove(temp_file_path)
157
160
 
158
161
  async def _prepare_venv(self, local_configs, venv_path: str, env: Dict[str, str]):
159
162
  """
@@ -5,12 +5,13 @@ from sqlalchemy import select, text
5
5
  from letta.orm.errors import NoResultFound
6
6
  from letta.orm.organization import Organization as OrganizationModel
7
7
  from letta.orm.user import User as UserModel
8
+ from letta.otel.tracing import trace_method
8
9
  from letta.schemas.user import User as PydanticUser
9
10
  from letta.schemas.user import UserUpdate
10
11
  from letta.server.db import db_registry
11
12
  from letta.services.organization_manager import OrganizationManager
12
- from letta.tracing import trace_method
13
13
  from letta.utils import enforce_types
14
+ from letta.settings import settings
14
15
 
15
16
 
16
17
  class UserManager:
@@ -147,13 +148,15 @@ class UserManager:
147
148
  """Fetch a user by ID asynchronously."""
148
149
  async with db_registry.async_session() as session:
149
150
  # Turn off seqscan to force use pk index
150
- await session.execute(text("SET LOCAL enable_seqscan = OFF"))
151
+ if settings.letta_pg_uri_no_default:
152
+ await session.execute(text("SET LOCAL enable_seqscan = OFF"))
151
153
  try:
152
154
  stmt = select(UserModel).where(UserModel.id == actor_id)
153
155
  result = await session.execute(stmt)
154
156
  user = result.scalar_one_or_none()
155
157
  finally:
156
- await session.execute(text("SET LOCAL enable_seqscan = ON"))
158
+ if settings.letta_pg_uri_no_default:
159
+ await session.execute(text("SET LOCAL enable_seqscan = ON"))
157
160
 
158
161
  if not user:
159
162
  raise NoResultFound(f"User not found with id={actor_id}")
letta/settings.py CHANGED
@@ -28,7 +28,8 @@ class ToolSettings(BaseSettings):
28
28
  mcp_connect_to_server_timeout: float = 30.0
29
29
  mcp_list_tools_timeout: float = 30.0
30
30
  mcp_execute_tool_timeout: float = 60.0
31
- mcp_read_from_config: bool = True # if False, will throw if attempting to read/write from file
31
+ mcp_read_from_config: bool = False # if False, will throw if attempting to read/write from file
32
+ mcp_disable_stdio: bool = False
32
33
 
33
34
 
34
35
  class SummarizerSettings(BaseSettings):
@@ -192,13 +193,17 @@ class Settings(BaseSettings):
192
193
  pool_use_lifo: bool = True
193
194
  disable_sqlalchemy_pooling: bool = False
194
195
 
196
+ redis_host: Optional[str] = None
197
+ redis_port: Optional[int] = None
198
+
199
+ plugin_register: Optional[str] = None
200
+
195
201
  # multi agent settings
196
202
  multi_agent_send_message_max_retries: int = 3
197
203
  multi_agent_send_message_timeout: int = 20 * 60
198
204
  multi_agent_concurrent_sends: int = 50
199
205
 
200
206
  # telemetry logging
201
- verbose_telemetry_logging: bool = False
202
207
  otel_exporter_otlp_endpoint: Optional[str] = None # otel default: "http://localhost:4317"
203
208
  disable_tracing: bool = False
204
209
  llm_api_logging: bool = True
@@ -210,6 +215,7 @@ class Settings(BaseSettings):
210
215
 
211
216
  use_uvloop: bool = False
212
217
  use_granian: bool = False
218
+ sqlalchemy_tracing: bool = False
213
219
 
214
220
  # event loop parallelism
215
221
  event_loop_threadpool_max_workers: int = 43
@@ -258,6 +264,15 @@ class Settings(BaseSettings):
258
264
  else:
259
265
  return None
260
266
 
267
+ @property
268
+ def plugin_register_dict(self) -> dict:
269
+ plugins = {}
270
+ if self.plugin_register:
271
+ for plugin in self.plugin_register.split(";"):
272
+ name, target = plugin.split("=")
273
+ plugins[name] = {"target": target}
274
+ return plugins
275
+
261
276
 
262
277
  class TestSettings(Settings):
263
278
  model_config = SettingsConfigDict(env_prefix="letta_test_", extra="ignore")
@@ -265,9 +280,15 @@ class TestSettings(Settings):
265
280
  letta_dir: Optional[Path] = Field(Path.home() / ".letta/test", env="LETTA_TEST_DIR")
266
281
 
267
282
 
283
+ class LogSettings(BaseSettings):
284
+ model_config = SettingsConfigDict(env_prefix="letta_logging_", extra="ignore")
285
+ verbose_telemetry_logging: bool = False
286
+
287
+
268
288
  # singleton
269
289
  settings = Settings(_env_parse_none_str="None")
270
290
  test_settings = TestSettings()
271
291
  model_settings = ModelSettings()
272
292
  tool_settings = ToolSettings()
273
293
  summarizer_settings = SummarizerSettings()
294
+ log_settings = LogSettings()
letta/utils.py CHANGED
@@ -515,6 +515,11 @@ def is_optional_type(hint):
515
515
 
516
516
 
517
517
  def enforce_types(func):
518
+ """Enforces that values passed in match the expected types.
519
+
520
+ Technically will handle coroutines as well.
521
+ """
522
+
518
523
  @wraps(func)
519
524
  def wrapper(*args, **kwargs):
520
525
  # Get type hints, excluding the return type hint
@@ -1078,9 +1083,9 @@ def log_telemetry(logger: Logger, event: str, **kwargs):
1078
1083
  :param event: A string describing the event.
1079
1084
  :param kwargs: Additional key-value pairs for logging metadata.
1080
1085
  """
1081
- from letta.settings import settings
1086
+ from letta.settings import log_settings
1082
1087
 
1083
- if settings.verbose_telemetry_logging:
1088
+ if log_settings.verbose_telemetry_logging:
1084
1089
  timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S,%f UTC") # More readable timestamp
1085
1090
  extra_data = " | ".join(f"{key}={value}" for key, value in kwargs.items() if value is not None)
1086
1091
  logger.info(f"[{timestamp}] EVENT: {event} | {extra_data}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: letta-nightly
3
- Version: 0.8.0.dev20250606195656
3
+ Version: 0.8.3.dev20250607000559
4
4
  Summary: Create LLM agents with long-term memory and custom tools
5
5
  License: Apache License
6
6
  Author: Letta Team
@@ -21,6 +21,7 @@ Provides-Extra: external-tools
21
21
  Provides-Extra: google
22
22
  Provides-Extra: postgres
23
23
  Provides-Extra: qdrant
24
+ Provides-Extra: redis
24
25
  Provides-Extra: server
25
26
  Provides-Extra: tests
26
27
  Requires-Dist: aiomultiprocess (>=0.9.1,<0.10.0)
@@ -55,7 +56,7 @@ Requires-Dist: isort (>=5.13.2,<6.0.0) ; extra == "dev" or extra == "all"
55
56
  Requires-Dist: jinja2 (>=3.1.5,<4.0.0)
56
57
  Requires-Dist: langchain (>=0.3.7,<0.4.0) ; extra == "external-tools" or extra == "desktop" or extra == "all"
57
58
  Requires-Dist: langchain-community (>=0.3.7,<0.4.0) ; extra == "external-tools" or extra == "desktop" or extra == "all"
58
- Requires-Dist: letta_client (>=0.1.143,<0.2.0)
59
+ Requires-Dist: letta_client (>=0.1.147,<0.2.0)
59
60
  Requires-Dist: llama-index (>=0.12.2,<0.13.0)
60
61
  Requires-Dist: llama-index-embeddings-openai (>=0.3.1,<0.4.0)
61
62
  Requires-Dist: locust (>=2.31.5,<3.0.0) ; extra == "dev" or extra == "desktop" or extra == "all"
@@ -90,6 +91,7 @@ Requires-Dist: pytz (>=2023.3.post1,<2024.0)
90
91
  Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
91
92
  Requires-Dist: qdrant-client (>=1.9.1,<2.0.0) ; extra == "qdrant"
92
93
  Requires-Dist: questionary (>=2.0.1,<3.0.0)
94
+ Requires-Dist: redis (>=6.2.0,<7.0.0) ; extra == "redis" or extra == "all"
93
95
  Requires-Dist: rich (>=13.9.4,<14.0.0)
94
96
  Requires-Dist: sentry-sdk[fastapi] (==2.19.1)
95
97
  Requires-Dist: setuptools (>=70,<71)