letta-nightly 0.6.3.dev20241213104231__py3-none-any.whl → 0.6.4.dev20241214104034__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.

Files changed (63) hide show
  1. letta/__init__.py +2 -2
  2. letta/agent.py +54 -45
  3. letta/chat_only_agent.py +6 -8
  4. letta/cli/cli.py +2 -10
  5. letta/client/client.py +121 -138
  6. letta/config.py +0 -161
  7. letta/main.py +3 -8
  8. letta/memory.py +3 -14
  9. letta/o1_agent.py +1 -5
  10. letta/offline_memory_agent.py +2 -6
  11. letta/orm/__init__.py +2 -0
  12. letta/orm/agent.py +109 -0
  13. letta/orm/agents_tags.py +10 -18
  14. letta/orm/block.py +29 -4
  15. letta/orm/blocks_agents.py +5 -11
  16. letta/orm/custom_columns.py +152 -0
  17. letta/orm/message.py +3 -38
  18. letta/orm/organization.py +2 -7
  19. letta/orm/passage.py +10 -32
  20. letta/orm/source.py +5 -25
  21. letta/orm/sources_agents.py +13 -0
  22. letta/orm/sqlalchemy_base.py +54 -30
  23. letta/orm/tool.py +1 -19
  24. letta/orm/tools_agents.py +7 -24
  25. letta/orm/user.py +3 -4
  26. letta/schemas/agent.py +48 -65
  27. letta/schemas/memory.py +2 -1
  28. letta/schemas/sandbox_config.py +12 -1
  29. letta/server/rest_api/app.py +0 -5
  30. letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +1 -1
  31. letta/server/rest_api/routers/v1/agents.py +99 -78
  32. letta/server/rest_api/routers/v1/blocks.py +22 -25
  33. letta/server/rest_api/routers/v1/jobs.py +4 -4
  34. letta/server/rest_api/routers/v1/sandbox_configs.py +10 -10
  35. letta/server/rest_api/routers/v1/sources.py +12 -12
  36. letta/server/rest_api/routers/v1/tools.py +35 -15
  37. letta/server/rest_api/routers/v1/users.py +0 -46
  38. letta/server/server.py +172 -718
  39. letta/server/ws_api/server.py +0 -5
  40. letta/services/agent_manager.py +405 -0
  41. letta/services/block_manager.py +13 -21
  42. letta/services/helpers/agent_manager_helper.py +90 -0
  43. letta/services/organization_manager.py +0 -1
  44. letta/services/passage_manager.py +62 -62
  45. letta/services/sandbox_config_manager.py +3 -3
  46. letta/services/source_manager.py +22 -1
  47. letta/services/tool_execution_sandbox.py +4 -4
  48. letta/services/user_manager.py +11 -6
  49. letta/utils.py +2 -2
  50. {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/METADATA +1 -1
  51. {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/RECORD +54 -58
  52. letta/metadata.py +0 -407
  53. letta/schemas/agents_tags.py +0 -33
  54. letta/schemas/api_key.py +0 -21
  55. letta/schemas/blocks_agents.py +0 -32
  56. letta/schemas/tools_agents.py +0 -32
  57. letta/server/rest_api/routers/openai/assistants/threads.py +0 -338
  58. letta/services/agents_tags_manager.py +0 -64
  59. letta/services/blocks_agents_manager.py +0 -106
  60. letta/services/tools_agents_manager.py +0 -94
  61. {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/LICENSE +0 -0
  62. {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/WHEEL +0 -0
  63. {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/entry_points.txt +0 -0
@@ -25,7 +25,7 @@ def create_sandbox_config(
25
25
  server: SyncServer = Depends(get_letta_server),
26
26
  user_id: str = Depends(get_user_id),
27
27
  ):
28
- actor = server.get_user_or_default(user_id=user_id)
28
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
29
29
 
30
30
  return server.sandbox_config_manager.create_or_update_sandbox_config(config_create, actor)
31
31
 
@@ -35,7 +35,7 @@ def create_default_e2b_sandbox_config(
35
35
  server: SyncServer = Depends(get_letta_server),
36
36
  user_id: str = Depends(get_user_id),
37
37
  ):
38
- actor = server.get_user_or_default(user_id=user_id)
38
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
39
39
  return server.sandbox_config_manager.get_or_create_default_sandbox_config(sandbox_type=SandboxType.E2B, actor=actor)
40
40
 
41
41
 
@@ -44,7 +44,7 @@ def create_default_local_sandbox_config(
44
44
  server: SyncServer = Depends(get_letta_server),
45
45
  user_id: str = Depends(get_user_id),
46
46
  ):
47
- actor = server.get_user_or_default(user_id=user_id)
47
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
48
48
  return server.sandbox_config_manager.get_or_create_default_sandbox_config(sandbox_type=SandboxType.LOCAL, actor=actor)
49
49
 
50
50
 
@@ -55,7 +55,7 @@ def update_sandbox_config(
55
55
  server: SyncServer = Depends(get_letta_server),
56
56
  user_id: str = Depends(get_user_id),
57
57
  ):
58
- actor = server.get_user_or_default(user_id=user_id)
58
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
59
59
  return server.sandbox_config_manager.update_sandbox_config(sandbox_config_id, config_update, actor)
60
60
 
61
61
 
@@ -65,7 +65,7 @@ def delete_sandbox_config(
65
65
  server: SyncServer = Depends(get_letta_server),
66
66
  user_id: str = Depends(get_user_id),
67
67
  ):
68
- actor = server.get_user_or_default(user_id=user_id)
68
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
69
69
  server.sandbox_config_manager.delete_sandbox_config(sandbox_config_id, actor)
70
70
 
71
71
 
@@ -76,7 +76,7 @@ def list_sandbox_configs(
76
76
  server: SyncServer = Depends(get_letta_server),
77
77
  user_id: str = Depends(get_user_id),
78
78
  ):
79
- actor = server.get_user_or_default(user_id=user_id)
79
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
80
80
  return server.sandbox_config_manager.list_sandbox_configs(actor, limit=limit, cursor=cursor)
81
81
 
82
82
 
@@ -90,7 +90,7 @@ def create_sandbox_env_var(
90
90
  server: SyncServer = Depends(get_letta_server),
91
91
  user_id: str = Depends(get_user_id),
92
92
  ):
93
- actor = server.get_user_or_default(user_id=user_id)
93
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
94
94
  return server.sandbox_config_manager.create_sandbox_env_var(env_var_create, sandbox_config_id, actor)
95
95
 
96
96
 
@@ -101,7 +101,7 @@ def update_sandbox_env_var(
101
101
  server: SyncServer = Depends(get_letta_server),
102
102
  user_id: str = Depends(get_user_id),
103
103
  ):
104
- actor = server.get_user_or_default(user_id=user_id)
104
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
105
105
  return server.sandbox_config_manager.update_sandbox_env_var(env_var_id, env_var_update, actor)
106
106
 
107
107
 
@@ -111,7 +111,7 @@ def delete_sandbox_env_var(
111
111
  server: SyncServer = Depends(get_letta_server),
112
112
  user_id: str = Depends(get_user_id),
113
113
  ):
114
- actor = server.get_user_or_default(user_id=user_id)
114
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
115
115
  server.sandbox_config_manager.delete_sandbox_env_var(env_var_id, actor)
116
116
 
117
117
 
@@ -123,5 +123,5 @@ def list_sandbox_env_vars(
123
123
  server: SyncServer = Depends(get_letta_server),
124
124
  user_id: str = Depends(get_user_id),
125
125
  ):
126
- actor = server.get_user_or_default(user_id=user_id)
126
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
127
127
  return server.sandbox_config_manager.list_sandbox_env_vars(sandbox_config_id, actor, limit=limit, cursor=cursor)
@@ -36,7 +36,7 @@ def get_source(
36
36
  """
37
37
  Get all sources
38
38
  """
39
- actor = server.get_user_or_default(user_id=user_id)
39
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
40
40
 
41
41
  source = server.source_manager.get_source_by_id(source_id=source_id, actor=actor)
42
42
  if not source:
@@ -53,7 +53,7 @@ def get_source_id_by_name(
53
53
  """
54
54
  Get a source by name
55
55
  """
56
- actor = server.get_user_or_default(user_id=user_id)
56
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
57
57
 
58
58
  source = server.source_manager.get_source_by_name(source_name=source_name, actor=actor)
59
59
  if not source:
@@ -69,7 +69,7 @@ def list_sources(
69
69
  """
70
70
  List all data sources created by a user.
71
71
  """
72
- actor = server.get_user_or_default(user_id=user_id)
72
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
73
73
 
74
74
  return server.list_all_sources(actor=actor)
75
75
 
@@ -83,7 +83,7 @@ def create_source(
83
83
  """
84
84
  Create a new data source.
85
85
  """
86
- actor = server.get_user_or_default(user_id=user_id)
86
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
87
87
  source = Source(**source_create.model_dump())
88
88
 
89
89
  return server.source_manager.create_source(source=source, actor=actor)
@@ -99,7 +99,7 @@ def update_source(
99
99
  """
100
100
  Update the name or documentation of an existing data source.
101
101
  """
102
- actor = server.get_user_or_default(user_id=user_id)
102
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
103
103
  if not server.source_manager.get_source_by_id(source_id=source_id, actor=actor):
104
104
  raise HTTPException(status_code=404, detail=f"Source with id={source_id} does not exist.")
105
105
  return server.source_manager.update_source(source_id=source_id, source_update=source, actor=actor)
@@ -114,7 +114,7 @@ def delete_source(
114
114
  """
115
115
  Delete a data source.
116
116
  """
117
- actor = server.get_user_or_default(user_id=user_id)
117
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
118
118
 
119
119
  server.delete_source(source_id=source_id, actor=actor)
120
120
 
@@ -129,7 +129,7 @@ def attach_source_to_agent(
129
129
  """
130
130
  Attach a data source to an existing agent.
131
131
  """
132
- actor = server.get_user_or_default(user_id=user_id)
132
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
133
133
 
134
134
  source = server.source_manager.get_source_by_id(source_id=source_id, actor=actor)
135
135
  assert source is not None, f"Source with id={source_id} not found."
@@ -147,7 +147,7 @@ def detach_source_from_agent(
147
147
  """
148
148
  Detach a data source from an existing agent.
149
149
  """
150
- actor = server.get_user_or_default(user_id=user_id)
150
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
151
151
 
152
152
  return server.detach_source_from_agent(source_id=source_id, agent_id=agent_id, user_id=actor.id)
153
153
 
@@ -163,7 +163,7 @@ def upload_file_to_source(
163
163
  """
164
164
  Upload a file to a data source.
165
165
  """
166
- actor = server.get_user_or_default(user_id=user_id)
166
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
167
167
 
168
168
  source = server.source_manager.get_source_by_id(source_id=source_id, actor=actor)
169
169
  assert source is not None, f"Source with id={source_id} not found."
@@ -197,7 +197,7 @@ def list_passages(
197
197
  """
198
198
  List all passages associated with a data source.
199
199
  """
200
- actor = server.get_user_or_default(user_id=user_id)
200
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
201
201
  passages = server.list_data_source_passages(user_id=actor.id, source_id=source_id)
202
202
  return passages
203
203
 
@@ -213,7 +213,7 @@ def list_files_from_source(
213
213
  """
214
214
  List paginated files associated with a data source.
215
215
  """
216
- actor = server.get_user_or_default(user_id=user_id)
216
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
217
217
  return server.source_manager.list_files(source_id=source_id, limit=limit, cursor=cursor, actor=actor)
218
218
 
219
219
 
@@ -229,7 +229,7 @@ def delete_file_from_source(
229
229
  """
230
230
  Delete a data source.
231
231
  """
232
- actor = server.get_user_or_default(user_id=user_id)
232
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
233
233
 
234
234
  deleted_file = server.source_manager.delete_file(file_id=file_id, actor=actor)
235
235
  if deleted_file is None:
@@ -1,6 +1,8 @@
1
1
  from typing import List, Optional
2
2
 
3
3
  from composio.client.collections import ActionModel, AppModel
4
+ from composio.client.enums.base import EnumStringNotFound
5
+ from composio.exceptions import ComposioSDKError
4
6
  from fastapi import APIRouter, Body, Depends, Header, HTTPException
5
7
 
6
8
  from letta.errors import LettaToolCreateError
@@ -23,7 +25,7 @@ def delete_tool(
23
25
  """
24
26
  Delete a tool by name
25
27
  """
26
- actor = server.get_user_or_default(user_id=user_id)
28
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
27
29
  server.tool_manager.delete_tool_by_id(tool_id=tool_id, actor=actor)
28
30
 
29
31
 
@@ -36,7 +38,7 @@ def get_tool(
36
38
  """
37
39
  Get a tool by ID
38
40
  """
39
- actor = server.get_user_or_default(user_id=user_id)
41
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
40
42
  tool = server.tool_manager.get_tool_by_id(tool_id=tool_id, actor=actor)
41
43
  if tool is None:
42
44
  # return 404 error
@@ -53,7 +55,7 @@ def get_tool_id(
53
55
  """
54
56
  Get a tool ID by name
55
57
  """
56
- actor = server.get_user_or_default(user_id=user_id)
58
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
57
59
  tool = server.tool_manager.get_tool_by_name(tool_name=tool_name, actor=actor)
58
60
  if tool:
59
61
  return tool.id
@@ -72,7 +74,7 @@ def list_tools(
72
74
  Get a list of all tools available to agents belonging to the org of the user
73
75
  """
74
76
  try:
75
- actor = server.get_user_or_default(user_id=user_id)
77
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
76
78
  return server.tool_manager.list_tools(actor=actor, cursor=cursor, limit=limit)
77
79
  except Exception as e:
78
80
  # Log or print the full exception here for debugging
@@ -90,7 +92,7 @@ def create_tool(
90
92
  Create a new tool
91
93
  """
92
94
  try:
93
- actor = server.get_user_or_default(user_id=user_id)
95
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
94
96
  tool = Tool(**request.model_dump())
95
97
  return server.tool_manager.create_tool(pydantic_tool=tool, actor=actor)
96
98
  except UniqueConstraintViolationError as e:
@@ -122,7 +124,7 @@ def upsert_tool(
122
124
  Create or update a tool
123
125
  """
124
126
  try:
125
- actor = server.get_user_or_default(user_id=user_id)
127
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
126
128
  tool = server.tool_manager.create_or_update_tool(pydantic_tool=Tool(**request.model_dump()), actor=actor)
127
129
  return tool
128
130
  except UniqueConstraintViolationError as e:
@@ -145,7 +147,7 @@ def update_tool(
145
147
  """
146
148
  Update an existing tool
147
149
  """
148
- actor = server.get_user_or_default(user_id=user_id)
150
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
149
151
  return server.tool_manager.update_tool_by_id(tool_id=tool_id, tool_update=request, actor=actor)
150
152
 
151
153
 
@@ -157,7 +159,7 @@ def add_base_tools(
157
159
  """
158
160
  Add base tools
159
161
  """
160
- actor = server.get_user_or_default(user_id=user_id)
162
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
161
163
  return server.tool_manager.add_base_tools(actor=actor)
162
164
 
163
165
 
@@ -171,7 +173,7 @@ def add_base_tools(
171
173
  # """
172
174
  # Run an existing tool on provided arguments
173
175
  # """
174
- # actor = server.get_user_or_default(user_id=user_id)
176
+ # actor = server.user_manager.get_user_or_default(user_id=user_id)
175
177
 
176
178
  # return server.run_tool(tool_id=request.tool_id, tool_args=request.tool_args, user_id=actor.id)
177
179
 
@@ -185,7 +187,7 @@ def run_tool_from_source(
185
187
  """
186
188
  Attempt to build a tool from source, then run it on the provided arguments
187
189
  """
188
- actor = server.get_user_or_default(user_id=user_id)
190
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
189
191
 
190
192
  try:
191
193
  return server.run_tool_from_source(
@@ -218,7 +220,7 @@ def list_composio_apps(server: SyncServer = Depends(get_letta_server), user_id:
218
220
  """
219
221
  Get a list of all Composio apps
220
222
  """
221
- actor = server.get_user_or_default(user_id=user_id)
223
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
222
224
  composio_api_key = get_composio_key(server, actor=actor)
223
225
  return server.get_composio_apps(api_key=composio_api_key)
224
226
 
@@ -232,7 +234,7 @@ def list_composio_actions_by_app(
232
234
  """
233
235
  Get a list of all Composio actions for a specific app
234
236
  """
235
- actor = server.get_user_or_default(user_id=user_id)
237
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
236
238
  composio_api_key = get_composio_key(server, actor=actor)
237
239
  return server.get_composio_actions_from_app_name(composio_app_name=composio_app_name, api_key=composio_api_key)
238
240
 
@@ -246,10 +248,28 @@ def add_composio_tool(
246
248
  """
247
249
  Add a new Composio tool by action name (Composio refers to each tool as an `Action`)
248
250
  """
249
- actor = server.get_user_or_default(user_id=user_id)
251
+ actor = server.user_manager.get_user_or_default(user_id=user_id)
250
252
  composio_api_key = get_composio_key(server, actor=actor)
251
- tool_create = ToolCreate.from_composio(action_name=composio_action_name, api_key=composio_api_key)
252
- return server.tool_manager.create_or_update_tool(pydantic_tool=Tool(**tool_create.model_dump()), actor=actor)
253
+
254
+ try:
255
+ tool_create = ToolCreate.from_composio(action_name=composio_action_name, api_key=composio_api_key)
256
+ return server.tool_manager.create_or_update_tool(pydantic_tool=Tool(**tool_create.model_dump()), actor=actor)
257
+ except EnumStringNotFound:
258
+ raise HTTPException(
259
+ status_code=400, # Bad Request
260
+ detail={
261
+ "message": f"Cannot find composio action with name `{composio_action_name}`.",
262
+ "composio_action_name": composio_action_name,
263
+ },
264
+ )
265
+ except ComposioSDKError:
266
+ raise HTTPException(
267
+ status_code=400, # Bad Request
268
+ detail={
269
+ "message": f"No connected account found for tool `{composio_action_name}`. You need to connect the relevant app in Composio order to use the tool.",
270
+ "composio_action_name": composio_action_name,
271
+ },
272
+ )
253
273
 
254
274
 
255
275
  # TODO: Factor this out to somewhere else
@@ -2,21 +2,9 @@ from typing import TYPE_CHECKING, List, Optional
2
2
 
3
3
  from fastapi import APIRouter, Body, Depends, HTTPException, Query
4
4
 
5
- from letta.schemas.api_key import APIKey, APIKeyCreate
6
5
  from letta.schemas.user import User, UserCreate, UserUpdate
7
6
  from letta.server.rest_api.utils import get_letta_server
8
7
 
9
- # from letta.server.schemas.users import (
10
- # CreateAPIKeyRequest,
11
- # CreateAPIKeyResponse,
12
- # CreateUserRequest,
13
- # CreateUserResponse,
14
- # DeleteAPIKeyResponse,
15
- # DeleteUserResponse,
16
- # GetAllUsersResponse,
17
- # GetAPIKeysResponse,
18
- # )
19
-
20
8
  if TYPE_CHECKING:
21
9
  from letta.schemas.user import User
22
10
  from letta.server.server import SyncServer
@@ -84,37 +72,3 @@ def delete_user(
84
72
  except Exception as e:
85
73
  raise HTTPException(status_code=500, detail=f"{e}")
86
74
  return user
87
-
88
-
89
- @router.post("/keys", response_model=APIKey, operation_id="create_api_key")
90
- def create_new_api_key(
91
- create_key: APIKeyCreate = Body(...),
92
- server: "SyncServer" = Depends(get_letta_server),
93
- ):
94
- """
95
- Create a new API key for a user
96
- """
97
- api_key = server.create_api_key(create_key)
98
- return api_key
99
-
100
-
101
- @router.get("/keys", response_model=List[APIKey], operation_id="list_api_keys")
102
- def get_api_keys(
103
- user_id: str = Query(..., description="The unique identifier of the user."),
104
- server: "SyncServer" = Depends(get_letta_server),
105
- ):
106
- """
107
- Get a list of all API keys for a user
108
- """
109
- if server.user_manager.get_user_by_id(user_id=user_id) is None:
110
- raise HTTPException(status_code=404, detail=f"User does not exist")
111
- api_keys = server.ms.get_all_api_keys_for_user(user_id=user_id)
112
- return api_keys
113
-
114
-
115
- @router.delete("/keys", response_model=APIKey, operation_id="delete_api_key")
116
- def delete_api_key(
117
- api_key: str = Query(..., description="The API key to be deleted."),
118
- server: "SyncServer" = Depends(get_letta_server),
119
- ):
120
- return server.delete_api_key(api_key)