letta-nightly 0.7.22.dev20250523081403__py3-none-any.whl → 0.7.23.dev20250523164139__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/__init__.py +1 -1
- letta/llm_api/google_ai_client.py +15 -0
- letta/llm_api/google_vertex_client.py +4 -5
- letta/schemas/providers.py +1 -1
- letta/server/db.py +0 -2
- letta/server/rest_api/routers/v1/blocks.py +12 -13
- letta/server/rest_api/routers/v1/sources.py +0 -11
- letta/server/server.py +115 -4
- letta/services/agent_manager.py +0 -209
- letta/services/block_manager.py +51 -0
- {letta_nightly-0.7.22.dev20250523081403.dist-info → letta_nightly-0.7.23.dev20250523164139.dist-info}/METADATA +1 -1
- {letta_nightly-0.7.22.dev20250523081403.dist-info → letta_nightly-0.7.23.dev20250523164139.dist-info}/RECORD +15 -15
- {letta_nightly-0.7.22.dev20250523081403.dist-info → letta_nightly-0.7.23.dev20250523164139.dist-info}/LICENSE +0 -0
- {letta_nightly-0.7.22.dev20250523081403.dist-info → letta_nightly-0.7.23.dev20250523164139.dist-info}/WHEEL +0 -0
- {letta_nightly-0.7.22.dev20250523081403.dist-info → letta_nightly-0.7.23.dev20250523164139.dist-info}/entry_points.txt +0 -0
letta/__init__.py
CHANGED
@@ -7,7 +7,10 @@ from letta.errors import ErrorCode, LLMAuthenticationError, LLMError
|
|
7
7
|
from letta.llm_api.google_constants import GOOGLE_MODEL_FOR_API_KEY_CHECK
|
8
8
|
from letta.llm_api.google_vertex_client import GoogleVertexClient
|
9
9
|
from letta.log import get_logger
|
10
|
+
from letta.schemas.llm_config import LLMConfig
|
11
|
+
from letta.schemas.message import Message as PydanticMessage
|
10
12
|
from letta.settings import model_settings
|
13
|
+
from letta.tracing import trace_method
|
11
14
|
|
12
15
|
logger = get_logger(__name__)
|
13
16
|
|
@@ -17,6 +20,18 @@ class GoogleAIClient(GoogleVertexClient):
|
|
17
20
|
def _get_client(self):
|
18
21
|
return genai.Client(api_key=model_settings.gemini_api_key)
|
19
22
|
|
23
|
+
@trace_method
|
24
|
+
def build_request_data(
|
25
|
+
self,
|
26
|
+
messages: List[PydanticMessage],
|
27
|
+
llm_config: LLMConfig,
|
28
|
+
tools: List[dict],
|
29
|
+
force_tool_call: Optional[str] = None,
|
30
|
+
) -> dict:
|
31
|
+
request = super().build_request_data(messages, llm_config, tools, force_tool_call)
|
32
|
+
del request["config"]["thinking_config"]
|
33
|
+
return request
|
34
|
+
|
20
35
|
|
21
36
|
def get_gemini_endpoint_and_headers(
|
22
37
|
base_url: str, model: Optional[str], api_key: str, key_in_header: bool = True, generate_content: bool = False
|
@@ -244,11 +244,10 @@ class GoogleVertexClient(LLMClientBase):
|
|
244
244
|
# Add thinking_config
|
245
245
|
# If enable_reasoner is False, set thinking_budget to 0
|
246
246
|
# Otherwise, use the value from max_reasoning_tokens
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
request_data["config"]["thinking_config"] = thinking_config.model_dump()
|
247
|
+
thinking_config = ThinkingConfig(
|
248
|
+
thinking_budget=llm_config.max_reasoning_tokens if llm_config.enable_reasoner else 0,
|
249
|
+
)
|
250
|
+
request_data["config"]["thinking_config"] = thinking_config.model_dump()
|
252
251
|
|
253
252
|
return request_data
|
254
253
|
|
letta/schemas/providers.py
CHANGED
@@ -54,7 +54,7 @@ class Provider(ProviderBase):
|
|
54
54
|
return []
|
55
55
|
|
56
56
|
async def list_embedding_models_async(self) -> List[EmbeddingConfig]:
|
57
|
-
return
|
57
|
+
return self.list_embedding_models()
|
58
58
|
|
59
59
|
def get_model_context_window(self, model_name: str) -> Optional[int]:
|
60
60
|
raise NotImplementedError
|
letta/server/db.py
CHANGED
@@ -50,47 +50,46 @@ def count_blocks(
|
|
50
50
|
|
51
51
|
|
52
52
|
@router.post("/", response_model=Block, operation_id="create_block")
|
53
|
-
def create_block(
|
53
|
+
async def create_block(
|
54
54
|
create_block: CreateBlock = Body(...),
|
55
55
|
server: SyncServer = Depends(get_letta_server),
|
56
56
|
actor_id: Optional[str] = Header(None, alias="user_id"),
|
57
57
|
):
|
58
|
-
actor = server.user_manager.
|
58
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
59
59
|
block = Block(**create_block.model_dump())
|
60
|
-
return server.block_manager.
|
60
|
+
return await server.block_manager.create_or_update_block_async(actor=actor, block=block)
|
61
61
|
|
62
62
|
|
63
63
|
@router.patch("/{block_id}", response_model=Block, operation_id="modify_block")
|
64
|
-
def modify_block(
|
64
|
+
async def modify_block(
|
65
65
|
block_id: str,
|
66
66
|
block_update: BlockUpdate = Body(...),
|
67
67
|
server: SyncServer = Depends(get_letta_server),
|
68
68
|
actor_id: Optional[str] = Header(None, alias="user_id"),
|
69
69
|
):
|
70
|
-
actor = server.user_manager.
|
71
|
-
return server.block_manager.
|
70
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
71
|
+
return await server.block_manager.update_block_async(block_id=block_id, block_update=block_update, actor=actor)
|
72
72
|
|
73
73
|
|
74
74
|
@router.delete("/{block_id}", response_model=Block, operation_id="delete_block")
|
75
|
-
def delete_block(
|
75
|
+
async def delete_block(
|
76
76
|
block_id: str,
|
77
77
|
server: SyncServer = Depends(get_letta_server),
|
78
78
|
actor_id: Optional[str] = Header(None, alias="user_id"),
|
79
79
|
):
|
80
|
-
actor = server.user_manager.
|
81
|
-
return server.block_manager.
|
80
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
81
|
+
return await server.block_manager.delete_block_async(block_id=block_id, actor=actor)
|
82
82
|
|
83
83
|
|
84
84
|
@router.get("/{block_id}", response_model=Block, operation_id="retrieve_block")
|
85
|
-
def retrieve_block(
|
85
|
+
async def retrieve_block(
|
86
86
|
block_id: str,
|
87
87
|
server: SyncServer = Depends(get_letta_server),
|
88
88
|
actor_id: Optional[str] = Header(None, alias="user_id"),
|
89
89
|
):
|
90
|
-
|
91
|
-
actor = server.user_manager.get_user_or_default(user_id=actor_id)
|
90
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
92
91
|
try:
|
93
|
-
block = server.block_manager.
|
92
|
+
block = await server.block_manager.get_block_by_id_async(block_id=block_id, actor=actor)
|
94
93
|
if block is None:
|
95
94
|
raise HTTPException(status_code=404, detail="Block not found")
|
96
95
|
return block
|
@@ -78,17 +78,6 @@ async def list_sources(
|
|
78
78
|
return await server.source_manager.list_sources(actor=actor)
|
79
79
|
|
80
80
|
|
81
|
-
@router.get("/count", response_model=int, operation_id="count_sources")
|
82
|
-
def count_sources(
|
83
|
-
server: "SyncServer" = Depends(get_letta_server),
|
84
|
-
actor_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present
|
85
|
-
):
|
86
|
-
"""
|
87
|
-
Count all data sources created by a user.
|
88
|
-
"""
|
89
|
-
return server.source_manager.size(actor=server.user_manager.get_user_or_default(user_id=actor_id))
|
90
|
-
|
91
|
-
|
92
81
|
@router.post("/", response_model=Source, operation_id="create_source")
|
93
82
|
async def create_source(
|
94
83
|
source_create: SourceCreate,
|
letta/server/server.py
CHANGED
@@ -741,6 +741,13 @@ class SyncServer(Server):
|
|
741
741
|
self._llm_config_cache[key] = self.get_llm_config_from_handle(actor=actor, **kwargs)
|
742
742
|
return self._llm_config_cache[key]
|
743
743
|
|
744
|
+
@trace_method
|
745
|
+
async def get_cached_llm_config_async(self, actor: User, **kwargs):
|
746
|
+
key = make_key(**kwargs)
|
747
|
+
if key not in self._llm_config_cache:
|
748
|
+
self._llm_config_cache[key] = await self.get_llm_config_from_handle_async(actor=actor, **kwargs)
|
749
|
+
return self._llm_config_cache[key]
|
750
|
+
|
744
751
|
@trace_method
|
745
752
|
def get_cached_embedding_config(self, actor: User, **kwargs):
|
746
753
|
key = make_key(**kwargs)
|
@@ -748,6 +755,13 @@ class SyncServer(Server):
|
|
748
755
|
self._embedding_config_cache[key] = self.get_embedding_config_from_handle(actor=actor, **kwargs)
|
749
756
|
return self._embedding_config_cache[key]
|
750
757
|
|
758
|
+
@trace_method
|
759
|
+
async def get_cached_embedding_config_async(self, actor: User, **kwargs):
|
760
|
+
key = make_key(**kwargs)
|
761
|
+
if key not in self._embedding_config_cache:
|
762
|
+
self._embedding_config_cache[key] = await self.get_embedding_config_from_handle_async(actor=actor, **kwargs)
|
763
|
+
return self._embedding_config_cache[key]
|
764
|
+
|
751
765
|
@trace_method
|
752
766
|
def create_agent(
|
753
767
|
self,
|
@@ -815,7 +829,7 @@ class SyncServer(Server):
|
|
815
829
|
"enable_reasoner": request.enable_reasoner,
|
816
830
|
}
|
817
831
|
log_event(name="start get_cached_llm_config", attributes=config_params)
|
818
|
-
request.llm_config = self.
|
832
|
+
request.llm_config = await self.get_cached_llm_config_async(actor=actor, **config_params)
|
819
833
|
log_event(name="end get_cached_llm_config", attributes=config_params)
|
820
834
|
|
821
835
|
if request.embedding_config is None:
|
@@ -826,7 +840,7 @@ class SyncServer(Server):
|
|
826
840
|
"embedding_chunk_size": request.embedding_chunk_size or constants.DEFAULT_EMBEDDING_CHUNK_SIZE,
|
827
841
|
}
|
828
842
|
log_event(name="start get_cached_embedding_config", attributes=embedding_config_params)
|
829
|
-
request.embedding_config = self.
|
843
|
+
request.embedding_config = await self.get_cached_embedding_config_async(actor=actor, **embedding_config_params)
|
830
844
|
log_event(name="end get_cached_embedding_config", attributes=embedding_config_params)
|
831
845
|
|
832
846
|
log_event(name="start create_agent db")
|
@@ -877,10 +891,10 @@ class SyncServer(Server):
|
|
877
891
|
actor: User,
|
878
892
|
) -> AgentState:
|
879
893
|
if request.model is not None:
|
880
|
-
request.llm_config = self.
|
894
|
+
request.llm_config = await self.get_llm_config_from_handle_async(handle=request.model, actor=actor)
|
881
895
|
|
882
896
|
if request.embedding is not None:
|
883
|
-
request.embedding_config = self.
|
897
|
+
request.embedding_config = await self.get_embedding_config_from_handle_async(handle=request.embedding, actor=actor)
|
884
898
|
|
885
899
|
if request.enable_sleeptime:
|
886
900
|
agent = self.agent_manager.get_agent_by_id(agent_id=agent_id, actor=actor)
|
@@ -1568,6 +1582,61 @@ class SyncServer(Server):
|
|
1568
1582
|
|
1569
1583
|
return llm_config
|
1570
1584
|
|
1585
|
+
@trace_method
|
1586
|
+
async def get_llm_config_from_handle_async(
|
1587
|
+
self,
|
1588
|
+
actor: User,
|
1589
|
+
handle: str,
|
1590
|
+
context_window_limit: Optional[int] = None,
|
1591
|
+
max_tokens: Optional[int] = None,
|
1592
|
+
max_reasoning_tokens: Optional[int] = None,
|
1593
|
+
enable_reasoner: Optional[bool] = None,
|
1594
|
+
) -> LLMConfig:
|
1595
|
+
try:
|
1596
|
+
provider_name, model_name = handle.split("/", 1)
|
1597
|
+
provider = await self.get_provider_from_name_async(provider_name, actor)
|
1598
|
+
|
1599
|
+
all_llm_configs = await provider.list_llm_models_async()
|
1600
|
+
llm_configs = [config for config in all_llm_configs if config.handle == handle]
|
1601
|
+
if not llm_configs:
|
1602
|
+
llm_configs = [config for config in all_llm_configs if config.model == model_name]
|
1603
|
+
if not llm_configs:
|
1604
|
+
available_handles = [config.handle for config in all_llm_configs]
|
1605
|
+
raise HandleNotFoundError(handle, available_handles)
|
1606
|
+
except ValueError as e:
|
1607
|
+
llm_configs = [config for config in self.get_local_llm_configs() if config.handle == handle]
|
1608
|
+
if not llm_configs:
|
1609
|
+
llm_configs = [config for config in self.get_local_llm_configs() if config.model == model_name]
|
1610
|
+
if not llm_configs:
|
1611
|
+
raise e
|
1612
|
+
|
1613
|
+
if len(llm_configs) == 1:
|
1614
|
+
llm_config = llm_configs[0]
|
1615
|
+
elif len(llm_configs) > 1:
|
1616
|
+
raise ValueError(f"Multiple LLM models with name {model_name} supported by {provider_name}")
|
1617
|
+
else:
|
1618
|
+
llm_config = llm_configs[0]
|
1619
|
+
|
1620
|
+
if context_window_limit is not None:
|
1621
|
+
if context_window_limit > llm_config.context_window:
|
1622
|
+
raise ValueError(f"Context window limit ({context_window_limit}) is greater than maximum of ({llm_config.context_window})")
|
1623
|
+
llm_config.context_window = context_window_limit
|
1624
|
+
else:
|
1625
|
+
llm_config.context_window = min(llm_config.context_window, model_settings.global_max_context_window_limit)
|
1626
|
+
|
1627
|
+
if max_tokens is not None:
|
1628
|
+
llm_config.max_tokens = max_tokens
|
1629
|
+
if max_reasoning_tokens is not None:
|
1630
|
+
if not max_tokens or max_reasoning_tokens > max_tokens:
|
1631
|
+
raise ValueError(f"Max reasoning tokens ({max_reasoning_tokens}) must be less than max tokens ({max_tokens})")
|
1632
|
+
llm_config.max_reasoning_tokens = max_reasoning_tokens
|
1633
|
+
if enable_reasoner is not None:
|
1634
|
+
llm_config.enable_reasoner = enable_reasoner
|
1635
|
+
if enable_reasoner and llm_config.model_endpoint_type == "anthropic":
|
1636
|
+
llm_config.put_inner_thoughts_in_kwargs = False
|
1637
|
+
|
1638
|
+
return llm_config
|
1639
|
+
|
1571
1640
|
@trace_method
|
1572
1641
|
def get_embedding_config_from_handle(
|
1573
1642
|
self, actor: User, handle: str, embedding_chunk_size: int = constants.DEFAULT_EMBEDDING_CHUNK_SIZE
|
@@ -1597,6 +1666,36 @@ class SyncServer(Server):
|
|
1597
1666
|
|
1598
1667
|
return embedding_config
|
1599
1668
|
|
1669
|
+
@trace_method
|
1670
|
+
async def get_embedding_config_from_handle_async(
|
1671
|
+
self, actor: User, handle: str, embedding_chunk_size: int = constants.DEFAULT_EMBEDDING_CHUNK_SIZE
|
1672
|
+
) -> EmbeddingConfig:
|
1673
|
+
try:
|
1674
|
+
provider_name, model_name = handle.split("/", 1)
|
1675
|
+
provider = await self.get_provider_from_name_async(provider_name, actor)
|
1676
|
+
|
1677
|
+
all_embedding_configs = await provider.list_embedding_models_async()
|
1678
|
+
embedding_configs = [config for config in all_embedding_configs if config.handle == handle]
|
1679
|
+
if not embedding_configs:
|
1680
|
+
raise ValueError(f"Embedding model {model_name} is not supported by {provider_name}")
|
1681
|
+
except ValueError as e:
|
1682
|
+
# search local configs
|
1683
|
+
embedding_configs = [config for config in self.get_local_embedding_configs() if config.handle == handle]
|
1684
|
+
if not embedding_configs:
|
1685
|
+
raise e
|
1686
|
+
|
1687
|
+
if len(embedding_configs) == 1:
|
1688
|
+
embedding_config = embedding_configs[0]
|
1689
|
+
elif len(embedding_configs) > 1:
|
1690
|
+
raise ValueError(f"Multiple embedding models with name {model_name} supported by {provider_name}")
|
1691
|
+
else:
|
1692
|
+
embedding_config = embedding_configs[0]
|
1693
|
+
|
1694
|
+
if embedding_chunk_size:
|
1695
|
+
embedding_config.embedding_chunk_size = embedding_chunk_size
|
1696
|
+
|
1697
|
+
return embedding_config
|
1698
|
+
|
1600
1699
|
def get_provider_from_name(self, provider_name: str, actor: User) -> Provider:
|
1601
1700
|
providers = [provider for provider in self.get_enabled_providers(actor) if provider.name == provider_name]
|
1602
1701
|
if not providers:
|
@@ -1608,6 +1707,18 @@ class SyncServer(Server):
|
|
1608
1707
|
|
1609
1708
|
return provider
|
1610
1709
|
|
1710
|
+
async def get_provider_from_name_async(self, provider_name: str, actor: User) -> Provider:
|
1711
|
+
all_providers = await self.get_enabled_providers_async(actor)
|
1712
|
+
providers = [provider for provider in all_providers if provider.name == provider_name]
|
1713
|
+
if not providers:
|
1714
|
+
raise ValueError(f"Provider {provider_name} is not supported")
|
1715
|
+
elif len(providers) > 1:
|
1716
|
+
raise ValueError(f"Multiple providers with name {provider_name} supported")
|
1717
|
+
else:
|
1718
|
+
provider = providers[0]
|
1719
|
+
|
1720
|
+
return provider
|
1721
|
+
|
1611
1722
|
def get_local_llm_configs(self):
|
1612
1723
|
llm_models = []
|
1613
1724
|
try:
|
letta/services/agent_manager.py
CHANGED
@@ -1023,34 +1023,6 @@ class AgentManager:
|
|
1023
1023
|
return await asyncio.gather(*[agent.to_pydantic_async(include_relationships=include_relationships) for agent in agents])
|
1024
1024
|
|
1025
1025
|
@trace_method
|
1026
|
-
@enforce_types
|
1027
|
-
async def get_agent_by_id_async(
|
1028
|
-
self,
|
1029
|
-
agent_id: str,
|
1030
|
-
actor: PydanticUser,
|
1031
|
-
include_relationships: Optional[List[str]] = None,
|
1032
|
-
) -> PydanticAgentState:
|
1033
|
-
"""Fetch an agent by its ID."""
|
1034
|
-
async with db_registry.async_session() as session:
|
1035
|
-
agent = await AgentModel.read_async(db_session=session, identifier=agent_id, actor=actor)
|
1036
|
-
return await agent.to_pydantic_async(include_relationships=include_relationships)
|
1037
|
-
|
1038
|
-
@enforce_types
|
1039
|
-
async def get_agents_by_ids_async(
|
1040
|
-
self,
|
1041
|
-
agent_ids: list[str],
|
1042
|
-
actor: PydanticUser,
|
1043
|
-
include_relationships: Optional[List[str]] = None,
|
1044
|
-
) -> list[PydanticAgentState]:
|
1045
|
-
"""Fetch a list of agents by their IDs."""
|
1046
|
-
async with db_registry.async_session() as session:
|
1047
|
-
agents = await AgentModel.read_multiple_async(
|
1048
|
-
db_session=session,
|
1049
|
-
identifiers=agent_ids,
|
1050
|
-
actor=actor,
|
1051
|
-
)
|
1052
|
-
return await asyncio.gather(*[agent.to_pydantic_async(include_relationships=include_relationships) for agent in agents])
|
1053
|
-
|
1054
1026
|
@enforce_types
|
1055
1027
|
def get_agent_by_name(self, agent_name: str, actor: PydanticUser) -> PydanticAgentState:
|
1056
1028
|
"""Fetch an agent by its ID."""
|
@@ -1321,11 +1293,6 @@ class AgentManager:
|
|
1321
1293
|
return await self.message_manager.get_messages_by_ids_async(message_ids=agent.message_ids, actor=actor)
|
1322
1294
|
|
1323
1295
|
@trace_method
|
1324
|
-
@enforce_types
|
1325
|
-
async def get_in_context_messages_async(self, agent_id: str, actor: PydanticUser) -> List[PydanticMessage]:
|
1326
|
-
agent = await self.get_agent_by_id_async(agent_id=agent_id, include_relationships=[], actor=actor)
|
1327
|
-
return await self.message_manager.get_messages_by_ids_async(message_ids=agent.message_ids, actor=actor)
|
1328
|
-
|
1329
1296
|
@enforce_types
|
1330
1297
|
def get_system_message(self, agent_id: str, actor: PydanticUser) -> PydanticMessage:
|
1331
1298
|
message_ids = self.get_agent_by_id(agent_id=agent_id, actor=actor).message_ids
|
@@ -1475,73 +1442,6 @@ class AgentManager:
|
|
1475
1442
|
return agent_state
|
1476
1443
|
|
1477
1444
|
@trace_method
|
1478
|
-
@enforce_types
|
1479
|
-
async def rebuild_system_prompt_async(
|
1480
|
-
self, agent_id: str, actor: PydanticUser, force=False, update_timestamp=True
|
1481
|
-
) -> PydanticAgentState:
|
1482
|
-
"""Rebuilds the system message with the latest memory object and any shared memory block updates
|
1483
|
-
|
1484
|
-
Updates to core memory blocks should trigger a "rebuild", which itself will create a new message object
|
1485
|
-
|
1486
|
-
Updates to the memory header should *not* trigger a rebuild, since that will simply flood recall storage with excess messages
|
1487
|
-
"""
|
1488
|
-
agent_state = await self.get_agent_by_id_async(agent_id=agent_id, include_relationships=["memory"], actor=actor)
|
1489
|
-
|
1490
|
-
curr_system_message = await self.get_system_message_async(
|
1491
|
-
agent_id=agent_id, actor=actor
|
1492
|
-
) # this is the system + memory bank, not just the system prompt
|
1493
|
-
curr_system_message_openai = curr_system_message.to_openai_dict()
|
1494
|
-
|
1495
|
-
# note: we only update the system prompt if the core memory is changed
|
1496
|
-
# this means that the archival/recall memory statistics may be someout out of date
|
1497
|
-
curr_memory_str = agent_state.memory.compile()
|
1498
|
-
if curr_memory_str in curr_system_message_openai["content"] and not force:
|
1499
|
-
# NOTE: could this cause issues if a block is removed? (substring match would still work)
|
1500
|
-
logger.debug(
|
1501
|
-
f"Memory hasn't changed for agent id={agent_id} and actor=({actor.id}, {actor.name}), skipping system prompt rebuild"
|
1502
|
-
)
|
1503
|
-
return agent_state
|
1504
|
-
|
1505
|
-
# If the memory didn't update, we probably don't want to update the timestamp inside
|
1506
|
-
# For example, if we're doing a system prompt swap, this should probably be False
|
1507
|
-
if update_timestamp:
|
1508
|
-
memory_edit_timestamp = get_utc_time()
|
1509
|
-
else:
|
1510
|
-
# NOTE: a bit of a hack - we pull the timestamp from the message created_by
|
1511
|
-
memory_edit_timestamp = curr_system_message.created_at
|
1512
|
-
|
1513
|
-
num_messages = await self.message_manager.size_async(actor=actor, agent_id=agent_id)
|
1514
|
-
num_archival_memories = await self.passage_manager.size_async(actor=actor, agent_id=agent_id)
|
1515
|
-
|
1516
|
-
# update memory (TODO: potentially update recall/archival stats separately)
|
1517
|
-
new_system_message_str = compile_system_message(
|
1518
|
-
system_prompt=agent_state.system,
|
1519
|
-
in_context_memory=agent_state.memory,
|
1520
|
-
in_context_memory_last_edit=memory_edit_timestamp,
|
1521
|
-
recent_passages=self.list_passages(actor=actor, agent_id=agent_id, ascending=False, limit=10),
|
1522
|
-
previous_message_count=num_messages,
|
1523
|
-
archival_memory_size=num_archival_memories,
|
1524
|
-
)
|
1525
|
-
|
1526
|
-
diff = united_diff(curr_system_message_openai["content"], new_system_message_str)
|
1527
|
-
if len(diff) > 0: # there was a diff
|
1528
|
-
logger.debug(f"Rebuilding system with new memory...\nDiff:\n{diff}")
|
1529
|
-
|
1530
|
-
# Swap the system message out (only if there is a diff)
|
1531
|
-
message = PydanticMessage.dict_to_message(
|
1532
|
-
agent_id=agent_id,
|
1533
|
-
model=agent_state.llm_config.model,
|
1534
|
-
openai_message_dict={"role": "system", "content": new_system_message_str},
|
1535
|
-
)
|
1536
|
-
message = await self.message_manager.update_message_by_id_async(
|
1537
|
-
message_id=curr_system_message.id,
|
1538
|
-
message_update=MessageUpdate(**message.model_dump()),
|
1539
|
-
actor=actor,
|
1540
|
-
)
|
1541
|
-
return await self.set_in_context_messages_async(agent_id=agent_id, message_ids=agent_state.message_ids, actor=actor)
|
1542
|
-
else:
|
1543
|
-
return agent_state
|
1544
|
-
|
1545
1445
|
@enforce_types
|
1546
1446
|
def set_in_context_messages(self, agent_id: str, message_ids: List[str], actor: PydanticUser) -> PydanticAgentState:
|
1547
1447
|
return self.update_agent(agent_id=agent_id, agent_update=UpdateAgent(message_ids=message_ids), actor=actor)
|
@@ -1552,10 +1452,6 @@ class AgentManager:
|
|
1552
1452
|
return await self.update_agent_async(agent_id=agent_id, agent_update=UpdateAgent(message_ids=message_ids), actor=actor)
|
1553
1453
|
|
1554
1454
|
@trace_method
|
1555
|
-
@enforce_types
|
1556
|
-
async def set_in_context_messages_async(self, agent_id: str, message_ids: List[str], actor: PydanticUser) -> PydanticAgentState:
|
1557
|
-
return await self.update_agent_async(agent_id=agent_id, agent_update=UpdateAgent(message_ids=message_ids), actor=actor)
|
1558
|
-
|
1559
1455
|
@enforce_types
|
1560
1456
|
def trim_older_in_context_messages(self, num: int, agent_id: str, actor: PydanticUser) -> PydanticAgentState:
|
1561
1457
|
message_ids = self.get_agent_by_id(agent_id=agent_id, actor=actor).message_ids
|
@@ -1786,25 +1682,6 @@ class AgentManager:
|
|
1786
1682
|
return [source.to_pydantic() for source in agent.sources]
|
1787
1683
|
|
1788
1684
|
@trace_method
|
1789
|
-
@enforce_types
|
1790
|
-
async def list_attached_sources_async(self, agent_id: str, actor: PydanticUser) -> List[PydanticSource]:
|
1791
|
-
"""
|
1792
|
-
Lists all sources attached to an agent.
|
1793
|
-
|
1794
|
-
Args:
|
1795
|
-
agent_id: ID of the agent to list sources for
|
1796
|
-
actor: User performing the action
|
1797
|
-
|
1798
|
-
Returns:
|
1799
|
-
List[str]: List of source IDs attached to the agent
|
1800
|
-
"""
|
1801
|
-
async with db_registry.async_session() as session:
|
1802
|
-
# Verify agent exists and user has permission to access it
|
1803
|
-
agent = await AgentModel.read_async(db_session=session, identifier=agent_id, actor=actor)
|
1804
|
-
|
1805
|
-
# Use the lazy-loaded relationship to get sources
|
1806
|
-
return [source.to_pydantic() for source in agent.sources]
|
1807
|
-
|
1808
1685
|
@enforce_types
|
1809
1686
|
def detach_source(self, agent_id: str, source_id: str, actor: PydanticUser) -> PydanticAgentState:
|
1810
1687
|
"""
|
@@ -1896,33 +1773,6 @@ class AgentManager:
|
|
1896
1773
|
return block.to_pydantic()
|
1897
1774
|
|
1898
1775
|
@trace_method
|
1899
|
-
@enforce_types
|
1900
|
-
async def modify_block_by_label_async(
|
1901
|
-
self,
|
1902
|
-
agent_id: str,
|
1903
|
-
block_label: str,
|
1904
|
-
block_update: BlockUpdate,
|
1905
|
-
actor: PydanticUser,
|
1906
|
-
) -> PydanticBlock:
|
1907
|
-
"""Gets a block attached to an agent by its label."""
|
1908
|
-
async with db_registry.async_session() as session:
|
1909
|
-
block = None
|
1910
|
-
agent = await AgentModel.read_async(db_session=session, identifier=agent_id, actor=actor)
|
1911
|
-
for block in agent.core_memory:
|
1912
|
-
if block.label == block_label:
|
1913
|
-
block = block
|
1914
|
-
break
|
1915
|
-
if not block:
|
1916
|
-
raise NoResultFound(f"No block with label '{block_label}' found for agent '{agent_id}'")
|
1917
|
-
|
1918
|
-
update_data = block_update.model_dump(to_orm=True, exclude_unset=True, exclude_none=True)
|
1919
|
-
|
1920
|
-
for key, value in update_data.items():
|
1921
|
-
setattr(block, key, value)
|
1922
|
-
|
1923
|
-
await block.update_async(session, actor=actor)
|
1924
|
-
return block.to_pydantic()
|
1925
|
-
|
1926
1776
|
@enforce_types
|
1927
1777
|
def update_block_with_label(
|
1928
1778
|
self,
|
@@ -2337,65 +2187,6 @@ class AgentManager:
|
|
2337
2187
|
return [p.to_pydantic() for p in passages]
|
2338
2188
|
|
2339
2189
|
@trace_method
|
2340
|
-
@enforce_types
|
2341
|
-
async def list_passages_async(
|
2342
|
-
self,
|
2343
|
-
actor: PydanticUser,
|
2344
|
-
agent_id: Optional[str] = None,
|
2345
|
-
file_id: Optional[str] = None,
|
2346
|
-
limit: Optional[int] = 50,
|
2347
|
-
query_text: Optional[str] = None,
|
2348
|
-
start_date: Optional[datetime] = None,
|
2349
|
-
end_date: Optional[datetime] = None,
|
2350
|
-
before: Optional[str] = None,
|
2351
|
-
after: Optional[str] = None,
|
2352
|
-
source_id: Optional[str] = None,
|
2353
|
-
embed_query: bool = False,
|
2354
|
-
ascending: bool = True,
|
2355
|
-
embedding_config: Optional[EmbeddingConfig] = None,
|
2356
|
-
agent_only: bool = False,
|
2357
|
-
) -> List[PydanticPassage]:
|
2358
|
-
"""Lists all passages attached to an agent."""
|
2359
|
-
async with db_registry.async_session() as session:
|
2360
|
-
main_query = self._build_passage_query(
|
2361
|
-
actor=actor,
|
2362
|
-
agent_id=agent_id,
|
2363
|
-
file_id=file_id,
|
2364
|
-
query_text=query_text,
|
2365
|
-
start_date=start_date,
|
2366
|
-
end_date=end_date,
|
2367
|
-
before=before,
|
2368
|
-
after=after,
|
2369
|
-
source_id=source_id,
|
2370
|
-
embed_query=embed_query,
|
2371
|
-
ascending=ascending,
|
2372
|
-
embedding_config=embedding_config,
|
2373
|
-
agent_only=agent_only,
|
2374
|
-
)
|
2375
|
-
|
2376
|
-
# Add limit
|
2377
|
-
if limit:
|
2378
|
-
main_query = main_query.limit(limit)
|
2379
|
-
|
2380
|
-
# Execute query
|
2381
|
-
result = await session.execute(main_query)
|
2382
|
-
|
2383
|
-
passages = []
|
2384
|
-
for row in result:
|
2385
|
-
data = dict(row._mapping)
|
2386
|
-
if data["agent_id"] is not None:
|
2387
|
-
# This is an AgentPassage - remove source fields
|
2388
|
-
data.pop("source_id", None)
|
2389
|
-
data.pop("file_id", None)
|
2390
|
-
passage = AgentPassage(**data)
|
2391
|
-
else:
|
2392
|
-
# This is a SourcePassage - remove agent field
|
2393
|
-
data.pop("agent_id", None)
|
2394
|
-
passage = SourcePassage(**data)
|
2395
|
-
passages.append(passage)
|
2396
|
-
|
2397
|
-
return [p.to_pydantic() for p in passages]
|
2398
|
-
|
2399
2190
|
@enforce_types
|
2400
2191
|
def passage_size(
|
2401
2192
|
self,
|
letta/services/block_manager.py
CHANGED
@@ -38,6 +38,21 @@ class BlockManager:
|
|
38
38
|
block.create(session, actor=actor)
|
39
39
|
return block.to_pydantic()
|
40
40
|
|
41
|
+
@trace_method
|
42
|
+
@enforce_types
|
43
|
+
async def create_or_update_block_async(self, block: PydanticBlock, actor: PydanticUser) -> PydanticBlock:
|
44
|
+
"""Create a new block based on the Block schema."""
|
45
|
+
db_block = await self.get_block_by_id_async(block.id, actor)
|
46
|
+
if db_block:
|
47
|
+
update_data = BlockUpdate(**block.model_dump(to_orm=True, exclude_none=True))
|
48
|
+
return await self.update_block_async(block.id, update_data, actor)
|
49
|
+
else:
|
50
|
+
async with db_registry.async_session() as session:
|
51
|
+
data = block.model_dump(to_orm=True, exclude_none=True)
|
52
|
+
block = BlockModel(**data, organization_id=actor.organization_id)
|
53
|
+
await block.create_async(session, actor=actor)
|
54
|
+
return block.to_pydantic()
|
55
|
+
|
41
56
|
@trace_method
|
42
57
|
@enforce_types
|
43
58
|
def batch_create_blocks(self, blocks: List[PydanticBlock], actor: PydanticUser) -> List[PydanticBlock]:
|
@@ -78,6 +93,22 @@ class BlockManager:
|
|
78
93
|
block.update(db_session=session, actor=actor)
|
79
94
|
return block.to_pydantic()
|
80
95
|
|
96
|
+
@trace_method
|
97
|
+
@enforce_types
|
98
|
+
async def update_block_async(self, block_id: str, block_update: BlockUpdate, actor: PydanticUser) -> PydanticBlock:
|
99
|
+
"""Update a block by its ID with the given BlockUpdate object."""
|
100
|
+
# Safety check for block
|
101
|
+
|
102
|
+
async with db_registry.async_session() as session:
|
103
|
+
block = await BlockModel.read_async(db_session=session, identifier=block_id, actor=actor)
|
104
|
+
update_data = block_update.model_dump(to_orm=True, exclude_unset=True, exclude_none=True)
|
105
|
+
|
106
|
+
for key, value in update_data.items():
|
107
|
+
setattr(block, key, value)
|
108
|
+
|
109
|
+
await block.update_async(db_session=session, actor=actor)
|
110
|
+
return block.to_pydantic()
|
111
|
+
|
81
112
|
@trace_method
|
82
113
|
@enforce_types
|
83
114
|
def delete_block(self, block_id: str, actor: PydanticUser) -> PydanticBlock:
|
@@ -87,6 +118,15 @@ class BlockManager:
|
|
87
118
|
block.hard_delete(db_session=session, actor=actor)
|
88
119
|
return block.to_pydantic()
|
89
120
|
|
121
|
+
@trace_method
|
122
|
+
@enforce_types
|
123
|
+
async def delete_block_async(self, block_id: str, actor: PydanticUser) -> PydanticBlock:
|
124
|
+
"""Delete a block by its ID."""
|
125
|
+
async with db_registry.async_session() as session:
|
126
|
+
block = await BlockModel.read_async(db_session=session, identifier=block_id, actor=actor)
|
127
|
+
await block.hard_delete_async(db_session=session, actor=actor)
|
128
|
+
return block.to_pydantic()
|
129
|
+
|
90
130
|
@trace_method
|
91
131
|
@enforce_types
|
92
132
|
async def get_blocks_async(
|
@@ -161,6 +201,17 @@ class BlockManager:
|
|
161
201
|
except NoResultFound:
|
162
202
|
return None
|
163
203
|
|
204
|
+
@trace_method
|
205
|
+
@enforce_types
|
206
|
+
async def get_block_by_id_async(self, block_id: str, actor: Optional[PydanticUser] = None) -> Optional[PydanticBlock]:
|
207
|
+
"""Retrieve a block by its name."""
|
208
|
+
async with db_registry.async_session() as session:
|
209
|
+
try:
|
210
|
+
block = await BlockModel.read_async(db_session=session, identifier=block_id, actor=actor)
|
211
|
+
return block.to_pydantic()
|
212
|
+
except NoResultFound:
|
213
|
+
return None
|
214
|
+
|
164
215
|
@trace_method
|
165
216
|
@enforce_types
|
166
217
|
async def get_all_blocks_by_ids_async(self, block_ids: List[str], actor: Optional[PydanticUser] = None) -> List[PydanticBlock]:
|
@@ -1,4 +1,4 @@
|
|
1
|
-
letta/__init__.py,sha256=
|
1
|
+
letta/__init__.py,sha256=vzj6HtecPrKm7mPJweZmynwWQsIiHIWSopQMTD3u96E,888
|
2
2
|
letta/agent.py,sha256=2r6xovRHeUnmWZ6WJoIP217ryse5Q3Bkco1JXiV599w,87459
|
3
3
|
letta/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
letta/agents/base_agent.py,sha256=mdFEpYBVyFjmt6BzO9YrpJnH99RkBWZ9gnP3Q_bnbBI,5505
|
@@ -76,9 +76,9 @@ letta/llm_api/azure_openai.py,sha256=YAkXwKyfnJFNhB45pkJVFsoxUNB_M74rQYchtw_CN6I
|
|
76
76
|
letta/llm_api/azure_openai_constants.py,sha256=ZaR2IasJThijG0uhLKJThrixdAxLPD2IojfeaJ-KQMQ,294
|
77
77
|
letta/llm_api/cohere.py,sha256=IZ6LXyOFMYjWHTeNG9lvFxCdV_NIl0hY2q9SPFYXNkQ,14849
|
78
78
|
letta/llm_api/deepseek.py,sha256=b1mSW8gnBrpAI8d2GcBpDyLYDnuC-P1UP6xJPalfQS4,12456
|
79
|
-
letta/llm_api/google_ai_client.py,sha256=
|
79
|
+
letta/llm_api/google_ai_client.py,sha256=WSLTayAd7FQPilIZ7MxJnSCgw4JCl2vY_KE2aorvr5Q,9933
|
80
80
|
letta/llm_api/google_constants.py,sha256=4PKWUNNbBHgHi4K5u9YaHr_8UC3fokfI6Qb6Dfpt4mU,693
|
81
|
-
letta/llm_api/google_vertex_client.py,sha256=
|
81
|
+
letta/llm_api/google_vertex_client.py,sha256=XoGDmX_kbaRayHZMjiQuo96VpvisDikg8vYfez_rsNc,22796
|
82
82
|
letta/llm_api/helpers.py,sha256=rpZInutKVKgoywreclisNSi2zVxwFinAzJIuxF6ll4I,17041
|
83
83
|
letta/llm_api/llm_api_tools.py,sha256=gMYoEvs5vSyvjos2eYJN6_BpQ2aNpt3zvyF7D2phbqY,30044
|
84
84
|
letta/llm_api/llm_client.py,sha256=sO9MwiSOJ_ycOFnYrQP0_g6cFkMSnrZqFDz1sUeBHD8,2098
|
@@ -229,7 +229,7 @@ letta/schemas/openai/openai.py,sha256=Hilo5BiLAGabzxCwnwfzK5QrWqwYD8epaEKFa4Pwnd
|
|
229
229
|
letta/schemas/organization.py,sha256=TXrHN4IBQnX-mWvRuCOH57XZSLYCVOY0wWm2_UzDQIA,1279
|
230
230
|
letta/schemas/passage.py,sha256=RG0vkaewEu4a_NAZM-FVyMammHjqpPP0RDYAdu27g6A,3723
|
231
231
|
letta/schemas/provider_trace.py,sha256=gsgo1CdfTUFSnm1ep1tSZ0fZfGSx45EdPaVyVJREt_U,1958
|
232
|
-
letta/schemas/providers.py,sha256=
|
232
|
+
letta/schemas/providers.py,sha256=p9k2lTNT0qdFGgYAiNLYJpyfdrZrDBeWeU7v112WDl4,63063
|
233
233
|
letta/schemas/response_format.py,sha256=pXNsjbtpA3Tf8HsDyIa40CSmoUbVR_7n2WOfQaX4aFs,2204
|
234
234
|
letta/schemas/run.py,sha256=SRqPRziINIiPunjOhE_NlbnQYgxTvqmbauni_yfBQRA,2085
|
235
235
|
letta/schemas/sandbox_config.py,sha256=Qfkzw422HCQUsE3GKry94oecQGziAzGXIyd6ke8W06M,5985
|
@@ -252,7 +252,7 @@ letta/serialize_schemas/marshmallow_tool.py,sha256=jwU69BDCakPlYPSk-ta21kuvsURKO
|
|
252
252
|
letta/serialize_schemas/pydantic_agent_schema.py,sha256=NKq70niUVMI3_lxMKc3u3rOBUhm77bIFaPRj9aidMUQ,3006
|
253
253
|
letta/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
254
254
|
letta/server/constants.py,sha256=yAdGbLkzlOU_dLTx0lKDmAnj0ZgRXCEaIcPJWO69eaE,92
|
255
|
-
letta/server/db.py,sha256=
|
255
|
+
letta/server/db.py,sha256=Hj4DDGXu7J1t6Q4oJwvhpIB3IXgNCvU1cQbW6f1osWM,9954
|
256
256
|
letta/server/generate_openapi_schema.sh,sha256=0OtBhkC1g6CobVmNEd_m2B6sTdppjbJLXaM95icejvE,371
|
257
257
|
letta/server/rest_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
258
258
|
letta/server/rest_api/app.py,sha256=8Y5R_t_s4IAG7wRfdbmCeF5YT9pfGG4h6_kpUAaUwoQ,14771
|
@@ -267,7 +267,7 @@ letta/server/rest_api/routers/openai/chat_completions/__init__.py,sha256=47DEQpj
|
|
267
267
|
letta/server/rest_api/routers/openai/chat_completions/chat_completions.py,sha256=QBWab1fn2LXVDMtc6li3gOzmrNzDiUw5WUJsMeeMZII,5076
|
268
268
|
letta/server/rest_api/routers/v1/__init__.py,sha256=JfSSttkEWu0W18NVVDxl8AGnd8Qhj0BXJNxntOB7070,1768
|
269
269
|
letta/server/rest_api/routers/v1/agents.py,sha256=evL3IHe5PR2Jmo3edT6hGv2BkHd7hB1EfC4Y4z3qOVc,38631
|
270
|
-
letta/server/rest_api/routers/v1/blocks.py,sha256=
|
270
|
+
letta/server/rest_api/routers/v1/blocks.py,sha256=2uCUK91hFFmiAJt0Mrj0wn0Q6UC6J7xcV1dbDLU44r0,4767
|
271
271
|
letta/server/rest_api/routers/v1/embeddings.py,sha256=P-Dvt_HNKoTyjRwkScAMg1hlB3cNxMeAQwV7bSatsKI,957
|
272
272
|
letta/server/rest_api/routers/v1/groups.py,sha256=DT2tc4wwiq_gzmxefltEIrFSoqOntzhvmgqQy23varA,10738
|
273
273
|
letta/server/rest_api/routers/v1/health.py,sha256=MoOjkydhGcJXTiuJrKIB0etVXiRMdTa51S8RQ8-50DQ,399
|
@@ -279,7 +279,7 @@ letta/server/rest_api/routers/v1/organizations.py,sha256=r7rj-cA3shgAgM0b2JCMqjY
|
|
279
279
|
letta/server/rest_api/routers/v1/providers.py,sha256=qp6XT20tcZac64XDGF2QUyLhselnShrRcTDQBHExEbQ,4322
|
280
280
|
letta/server/rest_api/routers/v1/runs.py,sha256=rq-k5kYN0On7VBNSzoPJxZcBf13hZFaDx0IUJJ04_K8,8875
|
281
281
|
letta/server/rest_api/routers/v1/sandbox_configs.py,sha256=g6JE1Xcl4vQPRduPdKZL04FexHttK0ZPJuTGds_Heig,8782
|
282
|
-
letta/server/rest_api/routers/v1/sources.py,sha256=
|
282
|
+
letta/server/rest_api/routers/v1/sources.py,sha256=ccdCdgCvdd1g81IPrnpoiQwqhh3eP5b7HuLfhrVYZhw,11457
|
283
283
|
letta/server/rest_api/routers/v1/steps.py,sha256=ra7ttm7HDs3N52M6s80XdpwiSMTLyf776_SmEILWDvo,3276
|
284
284
|
letta/server/rest_api/routers/v1/tags.py,sha256=ef94QitUSJ3NQVffWF1ZqANUZ2b2jRyGHp_I3UUjhno,912
|
285
285
|
letta/server/rest_api/routers/v1/telemetry.py,sha256=z53BW3Pefi3eWy47FPJyGhFWbZicX9jPJUi5LC5c3sk,790
|
@@ -289,7 +289,7 @@ letta/server/rest_api/routers/v1/voice.py,sha256=NZa7ksEqXTWSqh7CqmbVMClO7wOmrql
|
|
289
289
|
letta/server/rest_api/static_files.py,sha256=NG8sN4Z5EJ8JVQdj19tkFa9iQ1kBPTab9f_CUxd_u4Q,3143
|
290
290
|
letta/server/rest_api/streaming_response.py,sha256=yYTuZHfuZ-DYYbA1Ta6axkBn5MvC6OHuVRHSiBqRNUk,3939
|
291
291
|
letta/server/rest_api/utils.py,sha256=UVWlJI026oBB3uWxjhnA9DRlUiYtCoqBzmekI2JhvOQ,16612
|
292
|
-
letta/server/server.py,sha256=
|
292
|
+
letta/server/server.py,sha256=iIt6AhxsSHoUEZylUci0-D5MUikIC0mA6NSTu2ky1dw,101509
|
293
293
|
letta/server/startup.sh,sha256=MRXh1RKbS5lyA7XAsk7O6Q4LEKOqnv5B-dwe0SnTHeQ,2514
|
294
294
|
letta/server/static_files/assets/index-048c9598.js,sha256=mR16XppvselwKCcNgONs4L7kZEVa4OEERm4lNZYtLSk,146819
|
295
295
|
letta/server/static_files/assets/index-0e31b727.css,sha256=SBbja96uiQVLDhDOroHgM6NSl7tS4lpJRCREgSS_hA8,7672
|
@@ -303,8 +303,8 @@ letta/server/ws_api/interface.py,sha256=TWl9vkcMCnLsUtgsuENZ-ku2oMDA-OUTzLh_yNRo
|
|
303
303
|
letta/server/ws_api/protocol.py,sha256=5mDgpfNZn_kNwHnpt5Dsuw8gdNH298sgxTGed3etzYg,1836
|
304
304
|
letta/server/ws_api/server.py,sha256=cBSzf-V4zT1bL_0i54OTI3cMXhTIIxqjSRF8pYjk7fg,5835
|
305
305
|
letta/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
306
|
-
letta/services/agent_manager.py,sha256=
|
307
|
-
letta/services/block_manager.py,sha256=
|
306
|
+
letta/services/agent_manager.py,sha256=N2Wsi0zrwuhRjQyofSvC1aOPwiP3MUSamYSdJFyaslc,122236
|
307
|
+
letta/services/block_manager.py,sha256=e4_VAHA5XzOLOdIE3uLqtnxykjEvfTgSJSRqNKDUsWM,21716
|
308
308
|
letta/services/group_manager.py,sha256=zzxrPlk3FTUfiOMPwdjuVr9loxInjtXlJsO_TKReJqk,17267
|
309
309
|
letta/services/helpers/agent_manager_helper.py,sha256=q7GfVgKI-e8k0BZS-V_PuUCjK-PYciZDoig_sYHi_Go,21334
|
310
310
|
letta/services/helpers/noop_helper.py,sha256=OZ6wZLsdNEAg9Q2t5oFTOMK6jp-YUMBPdoyiR8M3T1c,272
|
@@ -346,8 +346,8 @@ letta/system.py,sha256=mKxmvvekuP8mdgsebRINGBoFbUdJhxLJ260crPBNVyk,8386
|
|
346
346
|
letta/tracing.py,sha256=YMb9KgoBVz7nwCPwnErk2EJEKMiQ_ohctW1nOwhHd1Y,8458
|
347
347
|
letta/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
348
348
|
letta/utils.py,sha256=W8J1FfhRADFqoyx3J8-Z1_aWyG433PBoEh_b5wdOZIg,32262
|
349
|
-
letta_nightly-0.7.
|
350
|
-
letta_nightly-0.7.
|
351
|
-
letta_nightly-0.7.
|
352
|
-
letta_nightly-0.7.
|
353
|
-
letta_nightly-0.7.
|
349
|
+
letta_nightly-0.7.23.dev20250523164139.dist-info/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
|
350
|
+
letta_nightly-0.7.23.dev20250523164139.dist-info/METADATA,sha256=Ojwp8JmVzsZWA7ibbGOtjEWmOgEP6YMBToiSCgQcTww,22321
|
351
|
+
letta_nightly-0.7.23.dev20250523164139.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
352
|
+
letta_nightly-0.7.23.dev20250523164139.dist-info/entry_points.txt,sha256=2zdiyGNEZGV5oYBuS-y2nAAgjDgcC9yM_mHJBFSRt5U,40
|
353
|
+
letta_nightly-0.7.23.dev20250523164139.dist-info/RECORD,,
|
File without changes
|
File without changes
|