letta-nightly 0.6.2.dev20241210104242__py3-none-any.whl → 0.6.2.dev20241211031658__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/agent.py +32 -43
- letta/agent_store/db.py +12 -54
- letta/agent_store/storage.py +10 -9
- letta/cli/cli.py +1 -0
- letta/client/client.py +3 -2
- letta/config.py +2 -2
- letta/data_sources/connectors.py +4 -3
- letta/embeddings.py +29 -9
- letta/functions/function_sets/base.py +36 -11
- letta/metadata.py +13 -2
- letta/o1_agent.py +2 -3
- letta/offline_memory_agent.py +2 -1
- letta/orm/__init__.py +1 -0
- letta/orm/file.py +1 -0
- letta/orm/mixins.py +12 -2
- letta/orm/organization.py +3 -0
- letta/orm/passage.py +72 -0
- letta/orm/sqlalchemy_base.py +36 -7
- letta/orm/sqlite_functions.py +140 -0
- letta/orm/user.py +1 -1
- letta/schemas/agent.py +4 -3
- letta/schemas/letta_message.py +5 -1
- letta/schemas/letta_request.py +3 -3
- letta/schemas/passage.py +6 -4
- letta/schemas/sandbox_config.py +1 -0
- letta/schemas/tool_rule.py +0 -3
- letta/server/rest_api/app.py +34 -12
- letta/server/rest_api/routers/v1/agents.py +19 -6
- letta/server/server.py +118 -44
- letta/server/static_files/assets/{index-4848e3d7.js → index-048c9598.js} +1 -1
- letta/server/static_files/assets/{index-43ab4d62.css → index-0e31b727.css} +1 -1
- letta/server/static_files/index.html +2 -2
- letta/services/passage_manager.py +225 -0
- letta/services/source_manager.py +2 -1
- letta/services/tool_execution_sandbox.py +18 -6
- letta/settings.py +2 -0
- {letta_nightly-0.6.2.dev20241210104242.dist-info → letta_nightly-0.6.2.dev20241211031658.dist-info}/METADATA +10 -15
- {letta_nightly-0.6.2.dev20241210104242.dist-info → letta_nightly-0.6.2.dev20241211031658.dist-info}/RECORD +41 -39
- letta/agent_store/chroma.py +0 -297
- {letta_nightly-0.6.2.dev20241210104242.dist-info → letta_nightly-0.6.2.dev20241211031658.dist-info}/LICENSE +0 -0
- {letta_nightly-0.6.2.dev20241210104242.dist-info → letta_nightly-0.6.2.dev20241211031658.dist-info}/WHEEL +0 -0
- {letta_nightly-0.6.2.dev20241210104242.dist-info → letta_nightly-0.6.2.dev20241211031658.dist-info}/entry_points.txt +0 -0
letta/server/server.py
CHANGED
|
@@ -16,7 +16,6 @@ import letta.constants as constants
|
|
|
16
16
|
import letta.server.utils as server_utils
|
|
17
17
|
import letta.system as system
|
|
18
18
|
from letta.agent import Agent, save_agent
|
|
19
|
-
from letta.agent_store.db import attach_base
|
|
20
19
|
from letta.agent_store.storage import StorageConnector, TableType
|
|
21
20
|
from letta.chat_only_agent import ChatOnlyAgent
|
|
22
21
|
from letta.credentials import LettaCredentials
|
|
@@ -70,17 +69,18 @@ from letta.schemas.memory import (
|
|
|
70
69
|
)
|
|
71
70
|
from letta.schemas.message import Message, MessageCreate, MessageRole, MessageUpdate
|
|
72
71
|
from letta.schemas.organization import Organization
|
|
73
|
-
from letta.schemas.passage import Passage
|
|
72
|
+
from letta.schemas.passage import Passage as PydanticPassage
|
|
74
73
|
from letta.schemas.source import Source
|
|
75
74
|
from letta.schemas.tool import Tool, ToolCreate
|
|
76
75
|
from letta.schemas.usage import LettaUsageStatistics
|
|
77
|
-
from letta.schemas.user import User
|
|
76
|
+
from letta.schemas.user import User as PydanticUser
|
|
78
77
|
from letta.services.agents_tags_manager import AgentsTagsManager
|
|
79
78
|
from letta.services.block_manager import BlockManager
|
|
80
79
|
from letta.services.blocks_agents_manager import BlocksAgentsManager
|
|
81
80
|
from letta.services.job_manager import JobManager
|
|
82
81
|
from letta.services.message_manager import MessageManager
|
|
83
82
|
from letta.services.organization_manager import OrganizationManager
|
|
83
|
+
from letta.services.passage_manager import PassageManager
|
|
84
84
|
from letta.services.per_agent_lock_manager import PerAgentLockManager
|
|
85
85
|
from letta.services.sandbox_config_manager import SandboxConfigManager
|
|
86
86
|
from letta.services.source_manager import SourceManager
|
|
@@ -125,7 +125,7 @@ class Server(object):
|
|
|
125
125
|
def create_agent(
|
|
126
126
|
self,
|
|
127
127
|
request: CreateAgent,
|
|
128
|
-
actor:
|
|
128
|
+
actor: PydanticUser,
|
|
129
129
|
# interface
|
|
130
130
|
interface: Union[AgentInterface, None] = None,
|
|
131
131
|
) -> AgentState:
|
|
@@ -166,8 +166,6 @@ from letta.settings import model_settings, settings, tool_settings
|
|
|
166
166
|
|
|
167
167
|
config = LettaConfig.load()
|
|
168
168
|
|
|
169
|
-
attach_base()
|
|
170
|
-
|
|
171
169
|
if settings.letta_pg_uri_no_default:
|
|
172
170
|
config.recall_storage_type = "postgres"
|
|
173
171
|
config.recall_storage_uri = settings.letta_pg_uri_no_default
|
|
@@ -245,6 +243,7 @@ class SyncServer(Server):
|
|
|
245
243
|
|
|
246
244
|
# Managers that interface with data models
|
|
247
245
|
self.organization_manager = OrganizationManager()
|
|
246
|
+
self.passage_manager = PassageManager()
|
|
248
247
|
self.user_manager = UserManager()
|
|
249
248
|
self.tool_manager = ToolManager()
|
|
250
249
|
self.block_manager = BlockManager()
|
|
@@ -379,6 +378,8 @@ class SyncServer(Server):
|
|
|
379
378
|
interface = interface or self.default_interface_factory()
|
|
380
379
|
if agent_state.agent_type == AgentType.memgpt_agent:
|
|
381
380
|
agent = Agent(agent_state=agent_state, interface=interface, user=actor, initial_message_sequence=initial_message_sequence)
|
|
381
|
+
elif agent_state.agent_type == AgentType.offline_memory_agent:
|
|
382
|
+
agent = OfflineMemoryAgent(agent_state=agent_state, interface=interface, user=actor, initial_message_sequence=initial_message_sequence)
|
|
382
383
|
else:
|
|
383
384
|
assert initial_message_sequence is None, f"Initial message sequence is not supported for O1Agents"
|
|
384
385
|
agent = O1Agent(agent_state=agent_state, interface=interface, user=actor)
|
|
@@ -496,7 +497,12 @@ class SyncServer(Server):
|
|
|
496
497
|
|
|
497
498
|
# attach data to agent from source
|
|
498
499
|
source_connector = StorageConnector.get_storage_connector(TableType.PASSAGES, self.config, user_id=user_id)
|
|
499
|
-
letta_agent.attach_source(
|
|
500
|
+
letta_agent.attach_source(
|
|
501
|
+
user=self.user_manager.get_user_by_id(user_id=user_id),
|
|
502
|
+
source_id=data_source,
|
|
503
|
+
source_manager=letta_agent.source_manager,
|
|
504
|
+
ms=self.ms
|
|
505
|
+
)
|
|
500
506
|
|
|
501
507
|
elif command.lower() == "dump" or command.lower().startswith("dump "):
|
|
502
508
|
# Check if there's an additional argument that's an integer
|
|
@@ -511,7 +517,7 @@ class SyncServer(Server):
|
|
|
511
517
|
letta_agent.interface.print_messages_raw(letta_agent.messages)
|
|
512
518
|
|
|
513
519
|
elif command.lower() == "memory":
|
|
514
|
-
ret_str = f"\nDumping memory contents:\n" + f"\n{str(letta_agent.agent_state.memory)}" + f"\n{str(letta_agent.
|
|
520
|
+
ret_str = f"\nDumping memory contents:\n" + f"\n{str(letta_agent.agent_state.memory)}" + f"\n{str(letta_agent.passage_manager)}"
|
|
515
521
|
return ret_str
|
|
516
522
|
|
|
517
523
|
elif command.lower() == "pop" or command.lower().startswith("pop "):
|
|
@@ -767,7 +773,7 @@ class SyncServer(Server):
|
|
|
767
773
|
def create_agent(
|
|
768
774
|
self,
|
|
769
775
|
request: CreateAgent,
|
|
770
|
-
actor:
|
|
776
|
+
actor: PydanticUser,
|
|
771
777
|
# interface
|
|
772
778
|
interface: Union[AgentInterface, None] = None,
|
|
773
779
|
) -> AgentState:
|
|
@@ -824,6 +830,12 @@ class SyncServer(Server):
|
|
|
824
830
|
if not user:
|
|
825
831
|
raise ValueError(f"cannot find user with associated client id: {user_id}")
|
|
826
832
|
|
|
833
|
+
if request.llm_config is None:
|
|
834
|
+
raise ValueError("llm_config is required")
|
|
835
|
+
|
|
836
|
+
if request.embedding_config is None:
|
|
837
|
+
raise ValueError("embedding_config is required")
|
|
838
|
+
|
|
827
839
|
# created and persist the agent state in the DB
|
|
828
840
|
agent_state = PersistedAgentState(
|
|
829
841
|
name=request.name,
|
|
@@ -843,7 +855,7 @@ class SyncServer(Server):
|
|
|
843
855
|
self.ms.create_agent(agent_state)
|
|
844
856
|
|
|
845
857
|
# create the agent object
|
|
846
|
-
if request.initial_message_sequence:
|
|
858
|
+
if request.initial_message_sequence is not None:
|
|
847
859
|
# init_messages = [Message(user_id=user_id, agent_id=agent_state.id, role=message.role, text=message.text) for message in request.initial_message_sequence]
|
|
848
860
|
init_messages = []
|
|
849
861
|
for message in request.initial_message_sequence:
|
|
@@ -913,6 +925,7 @@ class SyncServer(Server):
|
|
|
913
925
|
|
|
914
926
|
# get `Tool` objects
|
|
915
927
|
tools = [self.tool_manager.get_tool_by_name(tool_name=tool_name, actor=user) for tool_name in agent_state.tool_names]
|
|
928
|
+
tools = [tool for tool in tools if tool is not None]
|
|
916
929
|
|
|
917
930
|
# get `Source` objects
|
|
918
931
|
sources = self.list_attached_sources(agent_id=agent_id)
|
|
@@ -926,7 +939,7 @@ class SyncServer(Server):
|
|
|
926
939
|
def update_agent(
|
|
927
940
|
self,
|
|
928
941
|
request: UpdateAgentState,
|
|
929
|
-
actor:
|
|
942
|
+
actor: PydanticUser,
|
|
930
943
|
) -> AgentState:
|
|
931
944
|
"""Update the agents core memory block, return the new state"""
|
|
932
945
|
try:
|
|
@@ -1143,7 +1156,7 @@ class SyncServer(Server):
|
|
|
1143
1156
|
|
|
1144
1157
|
def get_archival_memory_summary(self, agent_id: str) -> ArchivalMemorySummary:
|
|
1145
1158
|
agent = self.load_agent(agent_id=agent_id)
|
|
1146
|
-
return ArchivalMemorySummary(size=
|
|
1159
|
+
return ArchivalMemorySummary(size=agent.passage_manager.size(actor=self.default_user))
|
|
1147
1160
|
|
|
1148
1161
|
def get_recall_memory_summary(self, agent_id: str) -> RecallMemorySummary:
|
|
1149
1162
|
agent = self.load_agent(agent_id=agent_id)
|
|
@@ -1168,7 +1181,56 @@ class SyncServer(Server):
|
|
|
1168
1181
|
message = agent.message_manager.get_message_by_id(id=message_id, actor=self.default_user)
|
|
1169
1182
|
return message
|
|
1170
1183
|
|
|
1171
|
-
def
|
|
1184
|
+
def get_agent_messages(
|
|
1185
|
+
self,
|
|
1186
|
+
agent_id: str,
|
|
1187
|
+
start: int,
|
|
1188
|
+
count: int,
|
|
1189
|
+
) -> Union[List[Message], List[LettaMessage]]:
|
|
1190
|
+
"""Paginated query of all messages in agent message queue"""
|
|
1191
|
+
# Get the agent object (loaded in memory)
|
|
1192
|
+
letta_agent = self.load_agent(agent_id=agent_id)
|
|
1193
|
+
|
|
1194
|
+
if start < 0 or count < 0:
|
|
1195
|
+
raise ValueError("Start and count values should be non-negative")
|
|
1196
|
+
|
|
1197
|
+
if start + count < len(letta_agent._messages): # messages can be returned from whats in memory
|
|
1198
|
+
# Reverse the list to make it in reverse chronological order
|
|
1199
|
+
reversed_messages = letta_agent._messages[::-1]
|
|
1200
|
+
# Check if start is within the range of the list
|
|
1201
|
+
if start >= len(reversed_messages):
|
|
1202
|
+
raise IndexError("Start index is out of range")
|
|
1203
|
+
|
|
1204
|
+
# Calculate the end index, ensuring it does not exceed the list length
|
|
1205
|
+
end_index = min(start + count, len(reversed_messages))
|
|
1206
|
+
|
|
1207
|
+
# Slice the list for pagination
|
|
1208
|
+
messages = reversed_messages[start:end_index]
|
|
1209
|
+
|
|
1210
|
+
else:
|
|
1211
|
+
# need to access persistence manager for additional messages
|
|
1212
|
+
|
|
1213
|
+
# get messages using message manager
|
|
1214
|
+
page = letta_agent.message_manager.list_user_messages_for_agent(
|
|
1215
|
+
agent_id=agent_id,
|
|
1216
|
+
actor=self.default_user,
|
|
1217
|
+
cursor=start,
|
|
1218
|
+
limit=count,
|
|
1219
|
+
)
|
|
1220
|
+
|
|
1221
|
+
messages = page
|
|
1222
|
+
assert all(isinstance(m, Message) for m in messages)
|
|
1223
|
+
|
|
1224
|
+
## Convert to json
|
|
1225
|
+
## Add a tag indicating in-context or not
|
|
1226
|
+
# json_messages = [record.to_json() for record in messages]
|
|
1227
|
+
# in_context_message_ids = [str(m.id) for m in letta_agent._messages]
|
|
1228
|
+
# for d in json_messages:
|
|
1229
|
+
# d["in_context"] = True if str(d["id"]) in in_context_message_ids else False
|
|
1230
|
+
|
|
1231
|
+
return messages
|
|
1232
|
+
|
|
1233
|
+
def get_agent_archival(self, user_id: str, agent_id: str, cursor: Optional[str] = None, limit: int = 50) -> List[PydanticPassage]:
|
|
1172
1234
|
"""Paginated query of all messages in agent archival memory"""
|
|
1173
1235
|
if self.user_manager.get_user_by_id(user_id=user_id) is None:
|
|
1174
1236
|
raise ValueError(f"User user_id={user_id} does not exist")
|
|
@@ -1179,22 +1241,22 @@ class SyncServer(Server):
|
|
|
1179
1241
|
letta_agent = self.load_agent(agent_id=agent_id)
|
|
1180
1242
|
|
|
1181
1243
|
# iterate over records
|
|
1182
|
-
|
|
1244
|
+
records = letta_agent.passage_manager.list_passages(
|
|
1245
|
+
actor=self.default_user,
|
|
1246
|
+
agent_id=agent_id,
|
|
1247
|
+
cursor=cursor,
|
|
1248
|
+
limit=limit,
|
|
1249
|
+
)
|
|
1183
1250
|
|
|
1184
|
-
|
|
1185
|
-
page = next(db_iterator, [])
|
|
1186
|
-
return page
|
|
1251
|
+
return records
|
|
1187
1252
|
|
|
1188
1253
|
def get_agent_archival_cursor(
|
|
1189
1254
|
self,
|
|
1190
1255
|
user_id: str,
|
|
1191
1256
|
agent_id: str,
|
|
1192
|
-
|
|
1193
|
-
before: Optional[str] = None,
|
|
1257
|
+
cursor: Optional[str] = None,
|
|
1194
1258
|
limit: Optional[int] = 100,
|
|
1195
|
-
|
|
1196
|
-
reverse: Optional[bool] = False,
|
|
1197
|
-
) -> List[Passage]:
|
|
1259
|
+
) -> List[PydanticPassage]:
|
|
1198
1260
|
if self.user_manager.get_user_by_id(user_id=user_id) is None:
|
|
1199
1261
|
raise LettaUserNotFoundError(f"User user_id={user_id} does not exist")
|
|
1200
1262
|
if self.ms.get_agent(agent_id=agent_id, user_id=user_id) is None:
|
|
@@ -1203,14 +1265,15 @@ class SyncServer(Server):
|
|
|
1203
1265
|
# Get the agent object (loaded in memory)
|
|
1204
1266
|
letta_agent = self.load_agent(agent_id=agent_id)
|
|
1205
1267
|
|
|
1206
|
-
# iterate over
|
|
1207
|
-
|
|
1208
|
-
|
|
1268
|
+
# iterate over records
|
|
1269
|
+
records = letta_agent.passage_manager.list_passages(
|
|
1270
|
+
actor=self.default_user, agent_id=agent_id, cursor=cursor, limit=limit,
|
|
1209
1271
|
)
|
|
1210
1272
|
return records
|
|
1211
1273
|
|
|
1212
|
-
def insert_archival_memory(self, user_id: str, agent_id: str, memory_contents: str) -> List[
|
|
1213
|
-
|
|
1274
|
+
def insert_archival_memory(self, user_id: str, agent_id: str, memory_contents: str) -> List[PydanticPassage]:
|
|
1275
|
+
actor = self.user_manager.get_user_by_id(user_id=user_id)
|
|
1276
|
+
if actor is None:
|
|
1214
1277
|
raise ValueError(f"User user_id={user_id} does not exist")
|
|
1215
1278
|
if self.ms.get_agent(agent_id=agent_id, user_id=user_id) is None:
|
|
1216
1279
|
raise ValueError(f"Agent agent_id={agent_id} does not exist")
|
|
@@ -1219,17 +1282,20 @@ class SyncServer(Server):
|
|
|
1219
1282
|
letta_agent = self.load_agent(agent_id=agent_id)
|
|
1220
1283
|
|
|
1221
1284
|
# Insert into archival memory
|
|
1222
|
-
passage_ids =
|
|
1285
|
+
passage_ids = self.passage_manager.insert_passage(
|
|
1286
|
+
agent_state=letta_agent.agent_state, agent_id=agent_id, text=memory_contents, actor=actor, return_ids=True
|
|
1287
|
+
)
|
|
1223
1288
|
|
|
1224
1289
|
# Update the agent
|
|
1225
1290
|
# TODO: should this update the system prompt?
|
|
1226
1291
|
save_agent(letta_agent, self.ms)
|
|
1227
1292
|
|
|
1228
1293
|
# TODO: this is gross, fix
|
|
1229
|
-
return [
|
|
1294
|
+
return [self.passage_manager.get_passage_by_id(passage_id=passage_id, actor=actor) for passage_id in passage_ids]
|
|
1230
1295
|
|
|
1231
1296
|
def delete_archival_memory(self, user_id: str, agent_id: str, memory_id: str):
|
|
1232
|
-
|
|
1297
|
+
actor = self.user_manager.get_user_by_id(user_id=user_id)
|
|
1298
|
+
if actor is None:
|
|
1233
1299
|
raise ValueError(f"User user_id={user_id} does not exist")
|
|
1234
1300
|
if self.ms.get_agent(agent_id=agent_id, user_id=user_id) is None:
|
|
1235
1301
|
raise ValueError(f"Agent agent_id={agent_id} does not exist")
|
|
@@ -1241,7 +1307,7 @@ class SyncServer(Server):
|
|
|
1241
1307
|
|
|
1242
1308
|
# Delete by ID
|
|
1243
1309
|
# TODO check if it exists first, and throw error if not
|
|
1244
|
-
letta_agent.
|
|
1310
|
+
letta_agent.passage_manager.delete_passage_by_id(passage_id=memory_id, actor=actor)
|
|
1245
1311
|
|
|
1246
1312
|
# TODO: return archival memory
|
|
1247
1313
|
|
|
@@ -1387,6 +1453,12 @@ class SyncServer(Server):
|
|
|
1387
1453
|
except NoResultFound:
|
|
1388
1454
|
logger.error(f"Agent with id {agent_state.id} has nonexistent user {agent_state.user_id}")
|
|
1389
1455
|
|
|
1456
|
+
# delete all passages associated with this agent
|
|
1457
|
+
# TODO: REMOVE THIS ONCE WE MIGRATE AGENTMODEL TO ORM
|
|
1458
|
+
passages = self.passage_manager.list_passages(actor=actor, agent_id=agent_state.id)
|
|
1459
|
+
for passage in passages:
|
|
1460
|
+
self.passage_manager.delete_passage_by_id(passage.id, actor=actor)
|
|
1461
|
+
|
|
1390
1462
|
# First, if the agent is in the in-memory cache we should remove it
|
|
1391
1463
|
# List of {'user_id': user_id, 'agent_id': agent_id, 'agent': agent_obj} dicts
|
|
1392
1464
|
try:
|
|
@@ -1429,7 +1501,7 @@ class SyncServer(Server):
|
|
|
1429
1501
|
self.ms.delete_api_key(api_key=api_key)
|
|
1430
1502
|
return api_key_obj
|
|
1431
1503
|
|
|
1432
|
-
def delete_source(self, source_id: str, actor:
|
|
1504
|
+
def delete_source(self, source_id: str, actor: PydanticUser):
|
|
1433
1505
|
"""Delete a data source"""
|
|
1434
1506
|
self.source_manager.delete_source(source_id=source_id, actor=actor)
|
|
1435
1507
|
|
|
@@ -1439,7 +1511,7 @@ class SyncServer(Server):
|
|
|
1439
1511
|
|
|
1440
1512
|
# TODO: delete data from agent passage stores (?)
|
|
1441
1513
|
|
|
1442
|
-
def load_file_to_source(self, source_id: str, file_path: str, job_id: str, actor:
|
|
1514
|
+
def load_file_to_source(self, source_id: str, file_path: str, job_id: str, actor: PydanticUser) -> Job:
|
|
1443
1515
|
|
|
1444
1516
|
# update job
|
|
1445
1517
|
job = self.job_manager.get_job_by_id(job_id, actor=actor)
|
|
@@ -1466,6 +1538,7 @@ class SyncServer(Server):
|
|
|
1466
1538
|
user_id: str,
|
|
1467
1539
|
connector: DataConnector,
|
|
1468
1540
|
source_name: str,
|
|
1541
|
+
agent_id: Optional[str] = None,
|
|
1469
1542
|
) -> Tuple[int, int]:
|
|
1470
1543
|
"""Load data from a DataConnector into a source for a specified user_id"""
|
|
1471
1544
|
# TODO: this should be implemented as a batch job or at least async, since it may take a long time
|
|
@@ -1480,14 +1553,13 @@ class SyncServer(Server):
|
|
|
1480
1553
|
passage_store = StorageConnector.get_storage_connector(TableType.PASSAGES, self.config, user_id=user_id)
|
|
1481
1554
|
|
|
1482
1555
|
# load data into the document store
|
|
1483
|
-
passage_count, document_count = load_data(connector, source, passage_store, self.source_manager, actor=user)
|
|
1556
|
+
passage_count, document_count = load_data(connector, source, passage_store, self.source_manager, actor=user, agent_id=agent_id)
|
|
1484
1557
|
return passage_count, document_count
|
|
1485
1558
|
|
|
1486
1559
|
def attach_source_to_agent(
|
|
1487
1560
|
self,
|
|
1488
1561
|
user_id: str,
|
|
1489
1562
|
agent_id: str,
|
|
1490
|
-
# source_id: str,
|
|
1491
1563
|
source_id: Optional[str] = None,
|
|
1492
1564
|
source_name: Optional[str] = None,
|
|
1493
1565
|
) -> Source:
|
|
@@ -1499,15 +1571,14 @@ class SyncServer(Server):
|
|
|
1499
1571
|
data_source = self.source_manager.get_source_by_name(source_name=source_name, actor=user)
|
|
1500
1572
|
else:
|
|
1501
1573
|
raise ValueError(f"Need to provide at least source_id or source_name to find the source.")
|
|
1502
|
-
|
|
1503
|
-
source_connector = StorageConnector.get_storage_connector(TableType.PASSAGES, self.config, user_id=user_id)
|
|
1574
|
+
|
|
1504
1575
|
assert data_source, f"Data source with id={source_id} or name={source_name} does not exist"
|
|
1505
1576
|
|
|
1506
1577
|
# load agent
|
|
1507
1578
|
agent = self.load_agent(agent_id=agent_id)
|
|
1508
1579
|
|
|
1509
1580
|
# attach source to agent
|
|
1510
|
-
agent.attach_source(data_source.id,
|
|
1581
|
+
agent.attach_source(user=user, source_id=data_source.id, source_manager=self.source_manager, ms=self.ms)
|
|
1511
1582
|
|
|
1512
1583
|
return data_source
|
|
1513
1584
|
|
|
@@ -1530,8 +1601,7 @@ class SyncServer(Server):
|
|
|
1530
1601
|
|
|
1531
1602
|
# delete all Passage objects with source_id==source_id from agent's archival memory
|
|
1532
1603
|
agent = self.load_agent(agent_id=agent_id)
|
|
1533
|
-
|
|
1534
|
-
archival_memory.storage.delete({"source_id": source_id})
|
|
1604
|
+
agent.passage_manager.delete_passages(actor=user, limit=100, source_id=source_id)
|
|
1535
1605
|
|
|
1536
1606
|
# delete agent-source mapping
|
|
1537
1607
|
self.ms.detach_source(agent_id=agent_id, source_id=source_id)
|
|
@@ -1545,11 +1615,11 @@ class SyncServer(Server):
|
|
|
1545
1615
|
|
|
1546
1616
|
return [self.source_manager.get_source_by_id(source_id=id) for id in source_ids]
|
|
1547
1617
|
|
|
1548
|
-
def list_data_source_passages(self, user_id: str, source_id: str) -> List[
|
|
1618
|
+
def list_data_source_passages(self, user_id: str, source_id: str) -> List[PydanticPassage]:
|
|
1549
1619
|
warnings.warn("list_data_source_passages is not yet implemented, returning empty list.", category=UserWarning)
|
|
1550
1620
|
return []
|
|
1551
1621
|
|
|
1552
|
-
def list_all_sources(self, actor:
|
|
1622
|
+
def list_all_sources(self, actor: PydanticUser) -> List[Source]:
|
|
1553
1623
|
"""List all sources (w/ extra metadata) belonging to a user"""
|
|
1554
1624
|
|
|
1555
1625
|
sources = self.source_manager.list_sources(actor=actor)
|
|
@@ -1589,7 +1659,7 @@ class SyncServer(Server):
|
|
|
1589
1659
|
|
|
1590
1660
|
return sources_with_metadata
|
|
1591
1661
|
|
|
1592
|
-
def add_default_external_tools(self, actor:
|
|
1662
|
+
def add_default_external_tools(self, actor: PydanticUser) -> bool:
|
|
1593
1663
|
"""Add default langchain tools. Return true if successful, false otherwise."""
|
|
1594
1664
|
success = True
|
|
1595
1665
|
tool_creates = ToolCreate.load_default_langchain_tools()
|
|
@@ -1646,7 +1716,7 @@ class SyncServer(Server):
|
|
|
1646
1716
|
save_agent(letta_agent, self.ms)
|
|
1647
1717
|
return response
|
|
1648
1718
|
|
|
1649
|
-
def get_user_or_default(self, user_id: Optional[str]) ->
|
|
1719
|
+
def get_user_or_default(self, user_id: Optional[str]) -> PydanticUser:
|
|
1650
1720
|
"""Get the user object for user_id if it exists, otherwise return the default user object"""
|
|
1651
1721
|
if user_id is None:
|
|
1652
1722
|
user_id = self.user_manager.DEFAULT_USER_ID
|
|
@@ -1827,6 +1897,8 @@ class SyncServer(Server):
|
|
|
1827
1897
|
date=get_utc_time(),
|
|
1828
1898
|
status="success",
|
|
1829
1899
|
function_return=function_response,
|
|
1900
|
+
stdout=sandbox_run_result.stdout,
|
|
1901
|
+
stderr=sandbox_run_result.stderr,
|
|
1830
1902
|
)
|
|
1831
1903
|
except Exception as e:
|
|
1832
1904
|
# same as agent.py
|
|
@@ -1842,6 +1914,8 @@ class SyncServer(Server):
|
|
|
1842
1914
|
date=get_utc_time(),
|
|
1843
1915
|
status="error",
|
|
1844
1916
|
function_return=error_msg,
|
|
1917
|
+
stdout=[''],
|
|
1918
|
+
stderr=[traceback.format_exc()],
|
|
1845
1919
|
)
|
|
1846
1920
|
|
|
1847
1921
|
# Composio wrappers
|