letta-nightly 0.11.7.dev20250914103918__py3-none-any.whl → 0.11.7.dev20250916104104__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/functions/function_sets/multi_agent.py +1 -1
- letta/functions/helpers.py +1 -1
- letta/prompts/gpt_system.py +13 -15
- letta/prompts/system_prompts/__init__.py +27 -0
- letta/prompts/{system/memgpt_chat.txt → system_prompts/memgpt_chat.py} +2 -0
- letta/prompts/{system/memgpt_generate_tool.txt → system_prompts/memgpt_generate_tool.py} +4 -2
- letta/prompts/{system/memgpt_v2_chat.txt → system_prompts/memgpt_v2_chat.py} +2 -0
- letta/prompts/{system/react.txt → system_prompts/react.py} +2 -0
- letta/prompts/{system/sleeptime_doc_ingest.txt → system_prompts/sleeptime_doc_ingest.py} +2 -0
- letta/prompts/{system/sleeptime_v2.txt → system_prompts/sleeptime_v2.py} +2 -0
- letta/prompts/{system/summary_system_prompt.txt → system_prompts/summary_system_prompt.py} +2 -0
- letta/prompts/{system/voice_chat.txt → system_prompts/voice_chat.py} +2 -0
- letta/prompts/{system/voice_sleeptime.txt → system_prompts/voice_sleeptime.py} +2 -0
- letta/prompts/{system/workflow.txt → system_prompts/workflow.py} +2 -0
- letta/server/rest_api/dependencies.py +37 -0
- letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +4 -3
- letta/server/rest_api/routers/v1/agents.py +112 -109
- letta/server/rest_api/routers/v1/blocks.py +44 -20
- letta/server/rest_api/routers/v1/embeddings.py +3 -3
- letta/server/rest_api/routers/v1/folders.py +107 -47
- letta/server/rest_api/routers/v1/groups.py +52 -32
- letta/server/rest_api/routers/v1/health.py +2 -2
- letta/server/rest_api/routers/v1/identities.py +110 -21
- letta/server/rest_api/routers/v1/internal_templates.py +28 -13
- letta/server/rest_api/routers/v1/jobs.py +12 -12
- letta/server/rest_api/routers/v1/llms.py +6 -8
- letta/server/rest_api/routers/v1/messages.py +53 -36
- letta/server/rest_api/routers/v1/organizations.py +1 -1
- letta/server/rest_api/routers/v1/providers.py +47 -20
- letta/server/rest_api/routers/v1/runs.py +19 -19
- letta/server/rest_api/routers/v1/sandbox_configs.py +25 -25
- letta/server/rest_api/routers/v1/sources.py +44 -45
- letta/server/rest_api/routers/v1/steps.py +50 -22
- letta/server/rest_api/routers/v1/tags.py +25 -10
- letta/server/rest_api/routers/v1/telemetry.py +11 -6
- letta/server/rest_api/routers/v1/tools.py +71 -54
- letta/server/rest_api/routers/v1/users.py +1 -1
- letta/server/rest_api/routers/v1/voice.py +6 -5
- letta/server/rest_api/utils.py +1 -18
- letta/services/agent_manager.py +31 -7
- letta/services/file_manager.py +6 -0
- letta/services/group_manager.py +2 -1
- letta/services/identity_manager.py +67 -0
- letta/services/provider_manager.py +14 -1
- letta/services/source_manager.py +11 -1
- letta/services/step_manager.py +5 -1
- letta/services/tool_manager.py +46 -9
- letta/utils.py +6 -2
- {letta_nightly-0.11.7.dev20250914103918.dist-info → letta_nightly-0.11.7.dev20250916104104.dist-info}/METADATA +1 -1
- {letta_nightly-0.11.7.dev20250914103918.dist-info → letta_nightly-0.11.7.dev20250916104104.dist-info}/RECORD +53 -65
- letta/prompts/system/memgpt_base.txt +0 -54
- letta/prompts/system/memgpt_chat_compressed.txt +0 -13
- letta/prompts/system/memgpt_chat_fstring.txt +0 -51
- letta/prompts/system/memgpt_convo_only.txt +0 -12
- letta/prompts/system/memgpt_doc.txt +0 -50
- letta/prompts/system/memgpt_gpt35_extralong.txt +0 -53
- letta/prompts/system/memgpt_intuitive_knowledge.txt +0 -31
- letta/prompts/system/memgpt_memory_only.txt +0 -29
- letta/prompts/system/memgpt_modified_chat.txt +0 -23
- letta/prompts/system/memgpt_modified_o1.txt +0 -31
- letta/prompts/system/memgpt_offline_memory.txt +0 -23
- letta/prompts/system/memgpt_offline_memory_chat.txt +0 -35
- letta/prompts/system/memgpt_sleeptime_chat.txt +0 -52
- letta/prompts/system/sleeptime.txt +0 -37
- {letta_nightly-0.11.7.dev20250914103918.dist-info → letta_nightly-0.11.7.dev20250916104104.dist-info}/WHEEL +0 -0
- {letta_nightly-0.11.7.dev20250914103918.dist-info → letta_nightly-0.11.7.dev20250916104104.dist-info}/entry_points.txt +0 -0
- {letta_nightly-0.11.7.dev20250914103918.dist-info → letta_nightly-0.11.7.dev20250916104104.dist-info}/licenses/LICENSE +0 -0
@@ -1,11 +1,11 @@
|
|
1
|
-
from typing import TYPE_CHECKING, List, Optional
|
1
|
+
from typing import TYPE_CHECKING, List, Literal, Optional
|
2
2
|
|
3
|
-
from fastapi import APIRouter, Body, Depends,
|
3
|
+
from fastapi import APIRouter, Body, Depends, HTTPException, Query
|
4
4
|
|
5
5
|
from letta.orm.errors import NoResultFound
|
6
6
|
from letta.schemas.agent import AgentState
|
7
7
|
from letta.schemas.block import Block, BlockUpdate, CreateBlock
|
8
|
-
from letta.server.rest_api.
|
8
|
+
from letta.server.rest_api.dependencies import HeaderParams, get_headers, get_letta_server
|
9
9
|
from letta.server.server import SyncServer
|
10
10
|
|
11
11
|
if TYPE_CHECKING:
|
@@ -26,12 +26,16 @@ async def list_blocks(
|
|
26
26
|
limit: Optional[int] = Query(50, description="Number of blocks to return"),
|
27
27
|
before: Optional[str] = Query(
|
28
28
|
None,
|
29
|
-
description="
|
29
|
+
description="Block ID cursor for pagination. Returns blocks that come before this block ID in the specified sort order",
|
30
30
|
),
|
31
31
|
after: Optional[str] = Query(
|
32
32
|
None,
|
33
|
-
description="
|
33
|
+
description="Block ID cursor for pagination. Returns blocks that come after this block ID in the specified sort order",
|
34
34
|
),
|
35
|
+
order: Literal["asc", "desc"] = Query(
|
36
|
+
"asc", description="Sort order for blocks by creation time. 'asc' for oldest first, 'desc' for newest first"
|
37
|
+
),
|
38
|
+
order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
|
35
39
|
label_search: Optional[str] = Query(
|
36
40
|
None,
|
37
41
|
description=("Search blocks by label. If provided, returns blocks that match this label. This is a full-text search on labels."),
|
@@ -74,9 +78,9 @@ async def list_blocks(
|
|
74
78
|
description="If set to True, include blocks marked as hidden in the results.",
|
75
79
|
),
|
76
80
|
server: SyncServer = Depends(get_letta_server),
|
77
|
-
|
81
|
+
headers: HeaderParams = Depends(get_headers),
|
78
82
|
):
|
79
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
83
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
80
84
|
return await server.block_manager.get_blocks_async(
|
81
85
|
actor=actor,
|
82
86
|
label=label,
|
@@ -94,6 +98,7 @@ async def list_blocks(
|
|
94
98
|
connected_to_agents_count_eq=connected_to_agents_count_eq,
|
95
99
|
limit=limit,
|
96
100
|
after=after,
|
101
|
+
ascending=(order == "asc"),
|
97
102
|
show_hidden_blocks=show_hidden_blocks,
|
98
103
|
)
|
99
104
|
|
@@ -101,12 +106,12 @@ async def list_blocks(
|
|
101
106
|
@router.get("/count", response_model=int, operation_id="count_blocks")
|
102
107
|
async def count_blocks(
|
103
108
|
server: SyncServer = Depends(get_letta_server),
|
104
|
-
|
109
|
+
headers: HeaderParams = Depends(get_headers),
|
105
110
|
):
|
106
111
|
"""
|
107
112
|
Count all blocks created by a user.
|
108
113
|
"""
|
109
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
114
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
110
115
|
return await server.block_manager.size_async(actor=actor)
|
111
116
|
|
112
117
|
|
@@ -114,9 +119,9 @@ async def count_blocks(
|
|
114
119
|
async def create_block(
|
115
120
|
create_block: CreateBlock = Body(...),
|
116
121
|
server: SyncServer = Depends(get_letta_server),
|
117
|
-
|
122
|
+
headers: HeaderParams = Depends(get_headers),
|
118
123
|
):
|
119
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
124
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
120
125
|
block = Block(**create_block.model_dump())
|
121
126
|
return await server.block_manager.create_or_update_block_async(actor=actor, block=block)
|
122
127
|
|
@@ -126,9 +131,9 @@ async def modify_block(
|
|
126
131
|
block_id: str,
|
127
132
|
block_update: BlockUpdate = Body(...),
|
128
133
|
server: SyncServer = Depends(get_letta_server),
|
129
|
-
|
134
|
+
headers: HeaderParams = Depends(get_headers),
|
130
135
|
):
|
131
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
136
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
132
137
|
return await server.block_manager.update_block_async(block_id=block_id, block_update=block_update, actor=actor)
|
133
138
|
|
134
139
|
|
@@ -136,9 +141,9 @@ async def modify_block(
|
|
136
141
|
async def delete_block(
|
137
142
|
block_id: str,
|
138
143
|
server: SyncServer = Depends(get_letta_server),
|
139
|
-
|
144
|
+
headers: HeaderParams = Depends(get_headers),
|
140
145
|
):
|
141
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
146
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
142
147
|
await server.block_manager.delete_block_async(block_id=block_id, actor=actor)
|
143
148
|
|
144
149
|
|
@@ -146,9 +151,9 @@ async def delete_block(
|
|
146
151
|
async def retrieve_block(
|
147
152
|
block_id: str,
|
148
153
|
server: SyncServer = Depends(get_letta_server),
|
149
|
-
|
154
|
+
headers: HeaderParams = Depends(get_headers),
|
150
155
|
):
|
151
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
156
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
152
157
|
try:
|
153
158
|
block = await server.block_manager.get_block_by_id_async(block_id=block_id, actor=actor)
|
154
159
|
if block is None:
|
@@ -161,6 +166,19 @@ async def retrieve_block(
|
|
161
166
|
@router.get("/{block_id}/agents", response_model=List[AgentState], operation_id="list_agents_for_block")
|
162
167
|
async def list_agents_for_block(
|
163
168
|
block_id: str,
|
169
|
+
before: Optional[str] = Query(
|
170
|
+
None,
|
171
|
+
description="Agent ID cursor for pagination. Returns agents that come before this agent ID in the specified sort order",
|
172
|
+
),
|
173
|
+
after: Optional[str] = Query(
|
174
|
+
None,
|
175
|
+
description="Agent ID cursor for pagination. Returns agents that come after this agent ID in the specified sort order",
|
176
|
+
),
|
177
|
+
limit: Optional[int] = Query(50, description="Maximum number of agents to return"),
|
178
|
+
order: Literal["asc", "desc"] = Query(
|
179
|
+
"desc", description="Sort order for agents by creation time. 'asc' for oldest first, 'desc' for newest first"
|
180
|
+
),
|
181
|
+
order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
|
164
182
|
include_relationships: list[str] | None = Query(
|
165
183
|
None,
|
166
184
|
description=(
|
@@ -170,16 +188,22 @@ async def list_agents_for_block(
|
|
170
188
|
),
|
171
189
|
),
|
172
190
|
server: SyncServer = Depends(get_letta_server),
|
173
|
-
|
191
|
+
headers: HeaderParams = Depends(get_headers),
|
174
192
|
):
|
175
193
|
"""
|
176
194
|
Retrieves all agents associated with the specified block.
|
177
195
|
Raises a 404 if the block does not exist.
|
178
196
|
"""
|
179
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
197
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
180
198
|
try:
|
181
199
|
agents = await server.block_manager.get_agents_for_block_async(
|
182
|
-
block_id=block_id,
|
200
|
+
block_id=block_id,
|
201
|
+
before=before,
|
202
|
+
after=after,
|
203
|
+
limit=limit,
|
204
|
+
ascending=(order == "asc"),
|
205
|
+
include_relationships=include_relationships,
|
206
|
+
actor=actor,
|
183
207
|
)
|
184
208
|
return agents
|
185
209
|
except NoResultFound:
|
@@ -2,7 +2,7 @@ from typing import Optional
|
|
2
2
|
|
3
3
|
from fastapi import APIRouter, Depends, Header
|
4
4
|
|
5
|
-
from letta.server.rest_api.
|
5
|
+
from letta.server.rest_api.dependencies import HeaderParams, get_headers, get_letta_server
|
6
6
|
from letta.server.server import SyncServer
|
7
7
|
|
8
8
|
router = APIRouter(prefix="/embeddings", tags=["embeddings"])
|
@@ -11,11 +11,11 @@ router = APIRouter(prefix="/embeddings", tags=["embeddings"])
|
|
11
11
|
@router.get("/total_storage_size", response_model=float, operation_id="get_total_storage_size")
|
12
12
|
async def get_embeddings_total_storage_size(
|
13
13
|
server: SyncServer = Depends(get_letta_server),
|
14
|
-
|
14
|
+
headers: HeaderParams = Depends(get_headers),
|
15
15
|
storage_unit: Optional[str] = Header("GB", alias="storage_unit"), # Extract storage unit from header, default to GB
|
16
16
|
):
|
17
17
|
"""
|
18
18
|
Get the total size of all embeddings in the database for a user in the storage unit given.
|
19
19
|
"""
|
20
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
20
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
21
21
|
return await server.passage_manager.estimate_embeddings_size_async(actor=actor, storage_unit=storage_unit)
|
@@ -1,11 +1,10 @@
|
|
1
|
-
import asyncio
|
2
1
|
import mimetypes
|
3
2
|
import os
|
4
3
|
import tempfile
|
5
4
|
from pathlib import Path
|
6
|
-
from typing import List, Optional
|
5
|
+
from typing import List, Literal, Optional
|
7
6
|
|
8
|
-
from fastapi import APIRouter, Depends,
|
7
|
+
from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile
|
9
8
|
from starlette import status
|
10
9
|
from starlette.responses import Response
|
11
10
|
|
@@ -27,7 +26,7 @@ from letta.schemas.passage import Passage
|
|
27
26
|
from letta.schemas.source import Source, SourceCreate, SourceUpdate
|
28
27
|
from letta.schemas.source_metadata import OrganizationSourcesStats
|
29
28
|
from letta.schemas.user import User
|
30
|
-
from letta.server.rest_api.
|
29
|
+
from letta.server.rest_api.dependencies import HeaderParams, get_headers, get_letta_server
|
31
30
|
from letta.server.server import SyncServer
|
32
31
|
from letta.services.file_processor.embedder.openai_embedder import OpenAIEmbedder
|
33
32
|
from letta.services.file_processor.embedder.pinecone_embedder import PineconeEmbedder
|
@@ -50,12 +49,12 @@ router = APIRouter(prefix="/folders", tags=["folders"])
|
|
50
49
|
@router.get("/count", response_model=int, operation_id="count_folders")
|
51
50
|
async def count_folders(
|
52
51
|
server: "SyncServer" = Depends(get_letta_server),
|
53
|
-
|
52
|
+
headers: HeaderParams = Depends(get_headers),
|
54
53
|
):
|
55
54
|
"""
|
56
55
|
Count all data folders created by a user.
|
57
56
|
"""
|
58
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
57
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
59
58
|
return await server.source_manager.size_async(actor=actor)
|
60
59
|
|
61
60
|
|
@@ -63,12 +62,12 @@ async def count_folders(
|
|
63
62
|
async def retrieve_folder(
|
64
63
|
folder_id: str,
|
65
64
|
server: "SyncServer" = Depends(get_letta_server),
|
66
|
-
|
65
|
+
headers: HeaderParams = Depends(get_headers),
|
67
66
|
):
|
68
67
|
"""
|
69
68
|
Get a folder by ID
|
70
69
|
"""
|
71
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
70
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
72
71
|
|
73
72
|
folder = await server.source_manager.get_source_by_id(source_id=folder_id, actor=actor)
|
74
73
|
if not folder:
|
@@ -76,16 +75,19 @@ async def retrieve_folder(
|
|
76
75
|
return folder
|
77
76
|
|
78
77
|
|
79
|
-
@router.get("/name/{folder_name}", response_model=str, operation_id="
|
80
|
-
async def
|
78
|
+
@router.get("/name/{folder_name}", response_model=str, operation_id="get_folder_by_name", deprecated=True)
|
79
|
+
async def get_folder_by_name(
|
81
80
|
folder_name: str,
|
82
81
|
server: "SyncServer" = Depends(get_letta_server),
|
83
|
-
|
82
|
+
headers: HeaderParams = Depends(get_headers),
|
84
83
|
):
|
85
84
|
"""
|
86
|
-
|
85
|
+
**Deprecated**: Please use the list endpoint `GET /v1/folders?name=` instead.
|
86
|
+
|
87
|
+
|
88
|
+
Get a folder by name.
|
87
89
|
"""
|
88
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
90
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
89
91
|
|
90
92
|
folder = await server.source_manager.get_source_by_name(source_name=folder_name, actor=actor)
|
91
93
|
if not folder:
|
@@ -93,10 +95,10 @@ async def get_folder_id_by_name(
|
|
93
95
|
return folder.id
|
94
96
|
|
95
97
|
|
96
|
-
@router.get("/metadata", response_model=OrganizationSourcesStats, operation_id="
|
97
|
-
async def
|
98
|
+
@router.get("/metadata", response_model=OrganizationSourcesStats, operation_id="retrieve_metadata")
|
99
|
+
async def retrieve_metadata(
|
98
100
|
server: "SyncServer" = Depends(get_letta_server),
|
99
|
-
|
101
|
+
headers: HeaderParams = Depends(get_headers),
|
100
102
|
include_detailed_per_source_metadata: bool = False,
|
101
103
|
):
|
102
104
|
"""
|
@@ -108,7 +110,7 @@ async def get_folders_metadata(
|
|
108
110
|
- Total size of all files
|
109
111
|
- Per-source breakdown with file details (file_name, file_size per file) if include_detailed_per_source_metadata is True
|
110
112
|
"""
|
111
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
113
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
112
114
|
return await server.file_manager.get_organization_sources_metadata(
|
113
115
|
actor=actor, include_detailed_per_source_metadata=include_detailed_per_source_metadata
|
114
116
|
)
|
@@ -116,26 +118,40 @@ async def get_folders_metadata(
|
|
116
118
|
|
117
119
|
@router.get("/", response_model=List[Folder], operation_id="list_folders")
|
118
120
|
async def list_folders(
|
121
|
+
before: Optional[str] = Query(
|
122
|
+
None, description="Folder ID cursor for pagination. Returns folders that come before this folder ID in the specified sort order"
|
123
|
+
),
|
124
|
+
after: Optional[str] = Query(
|
125
|
+
None, description="Folder ID cursor for pagination. Returns folders that come after this folder ID in the specified sort order"
|
126
|
+
),
|
127
|
+
limit: Optional[int] = Query(50, description="Maximum number of folders to return"),
|
128
|
+
order: Literal["asc", "desc"] = Query(
|
129
|
+
"asc", description="Sort order for folders by creation time. 'asc' for oldest first, 'desc' for newest first"
|
130
|
+
),
|
131
|
+
order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
|
132
|
+
name: Optional[str] = Query(None, description="Folder name to filter by"),
|
119
133
|
server: "SyncServer" = Depends(get_letta_server),
|
120
|
-
|
134
|
+
headers: HeaderParams = Depends(get_headers),
|
121
135
|
):
|
122
136
|
"""
|
123
137
|
List all data folders created by a user.
|
124
138
|
"""
|
125
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
126
|
-
return await server.source_manager.list_sources(
|
139
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
140
|
+
return await server.source_manager.list_sources(
|
141
|
+
actor=actor, before=before, after=after, limit=limit, ascending=(order == "asc"), name=name
|
142
|
+
)
|
127
143
|
|
128
144
|
|
129
145
|
@router.post("/", response_model=Folder, operation_id="create_folder")
|
130
146
|
async def create_folder(
|
131
147
|
folder_create: SourceCreate,
|
132
148
|
server: "SyncServer" = Depends(get_letta_server),
|
133
|
-
|
149
|
+
headers: HeaderParams = Depends(get_headers),
|
134
150
|
):
|
135
151
|
"""
|
136
152
|
Create a new data folder.
|
137
153
|
"""
|
138
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
154
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
139
155
|
|
140
156
|
# TODO: need to asyncify this
|
141
157
|
if not folder_create.embedding_config:
|
@@ -165,13 +181,13 @@ async def modify_folder(
|
|
165
181
|
folder_id: str,
|
166
182
|
folder: SourceUpdate,
|
167
183
|
server: "SyncServer" = Depends(get_letta_server),
|
168
|
-
|
184
|
+
headers: HeaderParams = Depends(get_headers),
|
169
185
|
):
|
170
186
|
"""
|
171
187
|
Update the name or documentation of an existing data folder.
|
172
188
|
"""
|
173
189
|
# TODO: allow updating the handle/embedding config
|
174
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
190
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
175
191
|
if not await server.source_manager.get_source_by_id(source_id=folder_id, actor=actor):
|
176
192
|
raise HTTPException(status_code=404, detail=f"Folder with id={folder_id} does not exist.")
|
177
193
|
return await server.source_manager.update_source(source_id=folder_id, source_update=folder, actor=actor)
|
@@ -181,12 +197,12 @@ async def modify_folder(
|
|
181
197
|
async def delete_folder(
|
182
198
|
folder_id: str,
|
183
199
|
server: "SyncServer" = Depends(get_letta_server),
|
184
|
-
|
200
|
+
headers: HeaderParams = Depends(get_headers),
|
185
201
|
):
|
186
202
|
"""
|
187
203
|
Delete a data folder.
|
188
204
|
"""
|
189
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
205
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
190
206
|
folder = await server.source_manager.get_source_by_id(source_id=folder_id, actor=actor)
|
191
207
|
agent_states = await server.source_manager.list_attached_agents(source_id=folder_id, actor=actor)
|
192
208
|
files = await server.file_manager.list_files(folder_id, actor)
|
@@ -221,7 +237,7 @@ async def upload_file_to_folder(
|
|
221
237
|
duplicate_handling: DuplicateFileHandling = Query(DuplicateFileHandling.SUFFIX, description="How to handle duplicate filenames"),
|
222
238
|
name: Optional[str] = Query(None, description="Optional custom name to override the uploaded file's name"),
|
223
239
|
server: "SyncServer" = Depends(get_letta_server),
|
224
|
-
|
240
|
+
headers: HeaderParams = Depends(get_headers),
|
225
241
|
):
|
226
242
|
"""
|
227
243
|
Upload a file to a data folder.
|
@@ -258,7 +274,7 @@ async def upload_file_to_folder(
|
|
258
274
|
),
|
259
275
|
)
|
260
276
|
|
261
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
277
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
262
278
|
|
263
279
|
folder = await server.source_manager.get_source_by_id(source_id=folder_id, actor=actor)
|
264
280
|
if folder is None:
|
@@ -332,58 +348,102 @@ async def upload_file_to_folder(
|
|
332
348
|
return file_metadata
|
333
349
|
|
334
350
|
|
335
|
-
@router.get("/{folder_id}/agents", response_model=List[str], operation_id="
|
336
|
-
async def
|
351
|
+
@router.get("/{folder_id}/agents", response_model=List[str], operation_id="list_agents_for_folder")
|
352
|
+
async def list_agents_for_folder(
|
337
353
|
folder_id: str,
|
354
|
+
before: Optional[str] = Query(
|
355
|
+
None,
|
356
|
+
description="Agent ID cursor for pagination. Returns agents that come before this agent ID in the specified sort order",
|
357
|
+
),
|
358
|
+
after: Optional[str] = Query(
|
359
|
+
None,
|
360
|
+
description="Agent ID cursor for pagination. Returns agents that come after this agent ID in the specified sort order",
|
361
|
+
),
|
362
|
+
limit: Optional[int] = Query(50, description="Maximum number of agents to return"),
|
363
|
+
order: Literal["asc", "desc"] = Query(
|
364
|
+
"desc", description="Sort order for agents by creation time. 'asc' for oldest first, 'desc' for newest first"
|
365
|
+
),
|
366
|
+
order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
|
338
367
|
server: SyncServer = Depends(get_letta_server),
|
339
|
-
|
368
|
+
headers: HeaderParams = Depends(get_headers),
|
340
369
|
):
|
341
370
|
"""
|
342
371
|
Get all agent IDs that have the specified folder attached.
|
343
372
|
"""
|
344
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
345
|
-
return await server.source_manager.get_agents_for_source_id(
|
373
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
374
|
+
return await server.source_manager.get_agents_for_source_id(
|
375
|
+
source_id=folder_id,
|
376
|
+
before=before,
|
377
|
+
after=after,
|
378
|
+
limit=limit,
|
379
|
+
ascending=(order == "asc"),
|
380
|
+
actor=actor,
|
381
|
+
)
|
346
382
|
|
347
383
|
|
348
384
|
@router.get("/{folder_id}/passages", response_model=List[Passage], operation_id="list_folder_passages")
|
349
385
|
async def list_folder_passages(
|
350
386
|
folder_id: str,
|
351
|
-
|
352
|
-
|
353
|
-
|
387
|
+
before: Optional[str] = Query(
|
388
|
+
None,
|
389
|
+
description="Passage ID cursor for pagination. Returns passages that come before this passage ID in the specified sort order",
|
390
|
+
),
|
391
|
+
after: Optional[str] = Query(
|
392
|
+
None,
|
393
|
+
description="Passage ID cursor for pagination. Returns passages that come after this passage ID in the specified sort order",
|
394
|
+
),
|
395
|
+
limit: Optional[int] = Query(100, description="Maximum number of passages to return"),
|
396
|
+
order: Literal["asc", "desc"] = Query(
|
397
|
+
"desc", description="Sort order for passages by creation time. 'asc' for oldest first, 'desc' for newest first"
|
398
|
+
),
|
399
|
+
order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
|
354
400
|
server: SyncServer = Depends(get_letta_server),
|
355
|
-
|
401
|
+
headers: HeaderParams = Depends(get_headers),
|
356
402
|
):
|
357
403
|
"""
|
358
404
|
List all passages associated with a data folder.
|
359
405
|
"""
|
360
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
406
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
361
407
|
return await server.agent_manager.query_source_passages_async(
|
362
408
|
actor=actor,
|
363
409
|
source_id=folder_id,
|
364
410
|
after=after,
|
365
411
|
before=before,
|
366
412
|
limit=limit,
|
413
|
+
ascending=(order == "asc"),
|
367
414
|
)
|
368
415
|
|
369
416
|
|
370
417
|
@router.get("/{folder_id}/files", response_model=List[FileMetadata], operation_id="list_folder_files")
|
371
418
|
async def list_folder_files(
|
372
419
|
folder_id: str,
|
373
|
-
|
374
|
-
|
420
|
+
before: Optional[str] = Query(
|
421
|
+
None,
|
422
|
+
description="File ID cursor for pagination. Returns files that come before this file ID in the specified sort order",
|
423
|
+
),
|
424
|
+
after: Optional[str] = Query(
|
425
|
+
None,
|
426
|
+
description="File ID cursor for pagination. Returns files that come after this file ID in the specified sort order",
|
427
|
+
),
|
428
|
+
limit: Optional[int] = Query(1000, description="Maximum number of files to return"),
|
429
|
+
order: Literal["asc", "desc"] = Query(
|
430
|
+
"desc", description="Sort order for files by creation time. 'asc' for oldest first, 'desc' for newest first"
|
431
|
+
),
|
432
|
+
order_by: Literal["created_at"] = Query("created_at", description="Field to sort by"),
|
375
433
|
include_content: bool = Query(False, description="Whether to include full file content"),
|
376
434
|
server: "SyncServer" = Depends(get_letta_server),
|
377
|
-
|
435
|
+
headers: HeaderParams = Depends(get_headers),
|
378
436
|
):
|
379
437
|
"""
|
380
438
|
List paginated files associated with a data folder.
|
381
439
|
"""
|
382
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
440
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
383
441
|
return await server.file_manager.list_files(
|
384
442
|
source_id=folder_id,
|
385
|
-
|
443
|
+
before=before,
|
386
444
|
after=after,
|
445
|
+
limit=limit,
|
446
|
+
ascending=(order == "asc"),
|
387
447
|
actor=actor,
|
388
448
|
include_content=include_content,
|
389
449
|
strip_directory_prefix=True, # TODO: Reconsider this. This is purely for aesthetics.
|
@@ -396,12 +456,12 @@ async def list_folder_files(
|
|
396
456
|
# file_id: str,
|
397
457
|
# include_content: bool = Query(False, description="Whether to include full file content"),
|
398
458
|
# server: "SyncServer" = Depends(get_letta_server),
|
399
|
-
#
|
459
|
+
# headers: HeaderParams = Depends(get_headers),
|
400
460
|
# ):
|
401
461
|
# """
|
402
462
|
# Retrieve metadata for a specific file by its ID.
|
403
463
|
# """
|
404
|
-
# actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
464
|
+
# actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
405
465
|
#
|
406
466
|
# # Get file metadata using the file manager
|
407
467
|
# file_metadata = await server.file_manager.get_file_by_id(
|
@@ -446,12 +506,12 @@ async def delete_file_from_folder(
|
|
446
506
|
folder_id: str,
|
447
507
|
file_id: str,
|
448
508
|
server: "SyncServer" = Depends(get_letta_server),
|
449
|
-
|
509
|
+
headers: HeaderParams = Depends(get_headers),
|
450
510
|
):
|
451
511
|
"""
|
452
512
|
Delete a file from a folder.
|
453
513
|
"""
|
454
|
-
actor = await server.user_manager.get_actor_or_default_async(actor_id=actor_id)
|
514
|
+
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
|
455
515
|
|
456
516
|
deleted_file = await server.file_manager.delete_file(file_id=file_id, actor=actor)
|
457
517
|
|