letta-nightly 0.5.0.dev20241021104213__py3-none-any.whl → 0.5.0.dev20241023104105__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 (33) hide show
  1. letta/__init__.py +7 -2
  2. letta/agent_store/db.py +4 -2
  3. letta/cli/cli_config.py +2 -2
  4. letta/client/client.py +13 -0
  5. letta/constants.py +4 -1
  6. letta/embeddings.py +34 -16
  7. letta/llm_api/azure_openai.py +44 -4
  8. letta/llm_api/helpers.py +45 -19
  9. letta/llm_api/openai.py +24 -5
  10. letta/metadata.py +1 -59
  11. letta/orm/__all__.py +0 -0
  12. letta/orm/__init__.py +0 -0
  13. letta/orm/base.py +75 -0
  14. letta/orm/enums.py +8 -0
  15. letta/orm/errors.py +2 -0
  16. letta/orm/mixins.py +40 -0
  17. letta/orm/organization.py +35 -0
  18. letta/orm/sqlalchemy_base.py +214 -0
  19. letta/schemas/organization.py +3 -3
  20. letta/server/rest_api/interface.py +245 -98
  21. letta/server/rest_api/routers/v1/agents.py +11 -3
  22. letta/server/rest_api/routers/v1/organizations.py +4 -5
  23. letta/server/server.py +10 -25
  24. letta/services/__init__.py +0 -0
  25. letta/services/organization_manager.py +66 -0
  26. letta/streaming_utils.py +270 -0
  27. {letta_nightly-0.5.0.dev20241021104213.dist-info → letta_nightly-0.5.0.dev20241023104105.dist-info}/METADATA +2 -1
  28. {letta_nightly-0.5.0.dev20241021104213.dist-info → letta_nightly-0.5.0.dev20241023104105.dist-info}/RECORD +31 -22
  29. letta/base.py +0 -3
  30. letta/client/admin.py +0 -171
  31. {letta_nightly-0.5.0.dev20241021104213.dist-info → letta_nightly-0.5.0.dev20241023104105.dist-info}/LICENSE +0 -0
  32. {letta_nightly-0.5.0.dev20241021104213.dist-info → letta_nightly-0.5.0.dev20241023104105.dist-info}/WHEEL +0 -0
  33. {letta_nightly-0.5.0.dev20241021104213.dist-info → letta_nightly-0.5.0.dev20241023104105.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,270 @@
1
+ from typing import Optional
2
+
3
+ from letta.constants import DEFAULT_MESSAGE_TOOL_KWARG
4
+
5
+
6
+ class JSONInnerThoughtsExtractor:
7
+ """
8
+ A class to process incoming JSON fragments and extract 'inner_thoughts' separately from the main JSON.
9
+
10
+ This handler processes JSON fragments incrementally, parsing out the value associated with a specified key (default is 'inner_thoughts'). It maintains two separate buffers:
11
+
12
+ - `main_json`: Accumulates the JSON data excluding the 'inner_thoughts' key-value pair.
13
+ - `inner_thoughts`: Accumulates the value associated with the 'inner_thoughts' key.
14
+
15
+ **Parameters:**
16
+
17
+ - `inner_thoughts_key` (str): The key to extract from the JSON (default is 'inner_thoughts').
18
+ - `wait_for_first_key` (bool): If `True`, holds back main JSON output until after the 'inner_thoughts' value is processed.
19
+
20
+ **Functionality:**
21
+
22
+ - **Stateful Parsing:** Maintains parsing state across fragments.
23
+ - **String Handling:** Correctly processes strings, escape sequences, and quotation marks.
24
+ - **Selective Extraction:** Identifies and extracts the value of the specified key.
25
+ - **Fragment Processing:** Handles data that arrives in chunks.
26
+
27
+ **Usage:**
28
+
29
+ ```python
30
+ extractor = JSONInnerThoughtsExtractor(wait_for_first_key=True)
31
+ for fragment in fragments:
32
+ updates_main_json, updates_inner_thoughts = extractor.process_fragment(fragment)
33
+ ```
34
+
35
+ """
36
+
37
+ def __init__(self, inner_thoughts_key="inner_thoughts", wait_for_first_key=False):
38
+ self.inner_thoughts_key = inner_thoughts_key
39
+ self.wait_for_first_key = wait_for_first_key
40
+ self.main_buffer = ""
41
+ self.inner_thoughts_buffer = ""
42
+ self.state = "start" # Possible states: start, key, colon, value, comma_or_end, end
43
+ self.in_string = False
44
+ self.escaped = False
45
+ self.current_key = ""
46
+ self.is_inner_thoughts_value = False
47
+ self.inner_thoughts_processed = False
48
+ self.hold_main_json = wait_for_first_key
49
+ self.main_json_held_buffer = ""
50
+
51
+ def process_fragment(self, fragment):
52
+ updates_main_json = ""
53
+ updates_inner_thoughts = ""
54
+ i = 0
55
+ while i < len(fragment):
56
+ c = fragment[i]
57
+ if self.escaped:
58
+ self.escaped = False
59
+ if self.in_string:
60
+ if self.state == "key":
61
+ self.current_key += c
62
+ elif self.state == "value":
63
+ if self.is_inner_thoughts_value:
64
+ updates_inner_thoughts += c
65
+ self.inner_thoughts_buffer += c
66
+ else:
67
+ if self.hold_main_json:
68
+ self.main_json_held_buffer += c
69
+ else:
70
+ updates_main_json += c
71
+ self.main_buffer += c
72
+ else:
73
+ if not self.is_inner_thoughts_value:
74
+ if self.hold_main_json:
75
+ self.main_json_held_buffer += c
76
+ else:
77
+ updates_main_json += c
78
+ self.main_buffer += c
79
+ elif c == "\\":
80
+ self.escaped = True
81
+ if self.in_string:
82
+ if self.state == "key":
83
+ self.current_key += c
84
+ elif self.state == "value":
85
+ if self.is_inner_thoughts_value:
86
+ updates_inner_thoughts += c
87
+ self.inner_thoughts_buffer += c
88
+ else:
89
+ if self.hold_main_json:
90
+ self.main_json_held_buffer += c
91
+ else:
92
+ updates_main_json += c
93
+ self.main_buffer += c
94
+ else:
95
+ if not self.is_inner_thoughts_value:
96
+ if self.hold_main_json:
97
+ self.main_json_held_buffer += c
98
+ else:
99
+ updates_main_json += c
100
+ self.main_buffer += c
101
+ elif c == '"':
102
+ if not self.escaped:
103
+ self.in_string = not self.in_string
104
+ if self.in_string:
105
+ if self.state in ["start", "comma_or_end"]:
106
+ self.state = "key"
107
+ self.current_key = ""
108
+ # Release held main_json when starting to process the next key
109
+ if self.wait_for_first_key and self.hold_main_json and self.inner_thoughts_processed:
110
+ updates_main_json += self.main_json_held_buffer
111
+ self.main_buffer += self.main_json_held_buffer
112
+ self.main_json_held_buffer = ""
113
+ self.hold_main_json = False
114
+ else:
115
+ if self.state == "key":
116
+ self.state = "colon"
117
+ elif self.state == "value":
118
+ # End of value
119
+ if self.is_inner_thoughts_value:
120
+ self.inner_thoughts_processed = True
121
+ # Do not release held main_json here
122
+ else:
123
+ if self.hold_main_json:
124
+ self.main_json_held_buffer += '"'
125
+ else:
126
+ updates_main_json += '"'
127
+ self.main_buffer += '"'
128
+ self.state = "comma_or_end"
129
+ else:
130
+ self.escaped = False
131
+ if self.in_string:
132
+ if self.state == "key":
133
+ self.current_key += '"'
134
+ elif self.state == "value":
135
+ if self.is_inner_thoughts_value:
136
+ updates_inner_thoughts += '"'
137
+ self.inner_thoughts_buffer += '"'
138
+ else:
139
+ if self.hold_main_json:
140
+ self.main_json_held_buffer += '"'
141
+ else:
142
+ updates_main_json += '"'
143
+ self.main_buffer += '"'
144
+ elif self.in_string:
145
+ if self.state == "key":
146
+ self.current_key += c
147
+ elif self.state == "value":
148
+ if self.is_inner_thoughts_value:
149
+ updates_inner_thoughts += c
150
+ self.inner_thoughts_buffer += c
151
+ else:
152
+ if self.hold_main_json:
153
+ self.main_json_held_buffer += c
154
+ else:
155
+ updates_main_json += c
156
+ self.main_buffer += c
157
+ else:
158
+ if c == ":" and self.state == "colon":
159
+ self.state = "value"
160
+ self.is_inner_thoughts_value = self.current_key == self.inner_thoughts_key
161
+ if self.is_inner_thoughts_value:
162
+ pass # Do not include 'inner_thoughts' key in main_json
163
+ else:
164
+ key_colon = f'"{self.current_key}":'
165
+ if self.hold_main_json:
166
+ self.main_json_held_buffer += key_colon + '"'
167
+ else:
168
+ updates_main_json += key_colon + '"'
169
+ self.main_buffer += key_colon + '"'
170
+ elif c == "," and self.state == "comma_or_end":
171
+ if self.is_inner_thoughts_value:
172
+ # Inner thoughts value ended
173
+ self.is_inner_thoughts_value = False
174
+ self.state = "start"
175
+ # Do not release held main_json here
176
+ else:
177
+ if self.hold_main_json:
178
+ self.main_json_held_buffer += c
179
+ else:
180
+ updates_main_json += c
181
+ self.main_buffer += c
182
+ self.state = "start"
183
+ elif c == "{":
184
+ if not self.is_inner_thoughts_value:
185
+ if self.hold_main_json:
186
+ self.main_json_held_buffer += c
187
+ else:
188
+ updates_main_json += c
189
+ self.main_buffer += c
190
+ elif c == "}":
191
+ self.state = "end"
192
+ if self.hold_main_json:
193
+ self.main_json_held_buffer += c
194
+ else:
195
+ updates_main_json += c
196
+ self.main_buffer += c
197
+ else:
198
+ if self.state == "value":
199
+ if self.is_inner_thoughts_value:
200
+ updates_inner_thoughts += c
201
+ self.inner_thoughts_buffer += c
202
+ else:
203
+ if self.hold_main_json:
204
+ self.main_json_held_buffer += c
205
+ else:
206
+ updates_main_json += c
207
+ self.main_buffer += c
208
+ i += 1
209
+
210
+ return updates_main_json, updates_inner_thoughts
211
+
212
+ @property
213
+ def main_json(self):
214
+ return self.main_buffer
215
+
216
+ @property
217
+ def inner_thoughts(self):
218
+ return self.inner_thoughts_buffer
219
+
220
+
221
+ class FunctionArgumentsStreamHandler:
222
+ """State machine that can process a stream of"""
223
+
224
+ def __init__(self, json_key=DEFAULT_MESSAGE_TOOL_KWARG):
225
+ self.json_key = json_key
226
+ self.reset()
227
+
228
+ def reset(self):
229
+ self.in_message = False
230
+ self.key_buffer = ""
231
+ self.accumulating = False
232
+ self.message_started = False
233
+
234
+ def process_json_chunk(self, chunk: str) -> Optional[str]:
235
+ """Process a chunk from the function arguments and return the plaintext version"""
236
+
237
+ # Use strip to handle only leading and trailing whitespace in control structures
238
+ if self.accumulating:
239
+ clean_chunk = chunk.strip()
240
+ if self.json_key in self.key_buffer:
241
+ if ":" in clean_chunk:
242
+ self.in_message = True
243
+ self.accumulating = False
244
+ return None
245
+ self.key_buffer += clean_chunk
246
+ return None
247
+
248
+ if self.in_message:
249
+ if chunk.strip() == '"' and self.message_started:
250
+ self.in_message = False
251
+ self.message_started = False
252
+ return None
253
+ if not self.message_started and chunk.strip() == '"':
254
+ self.message_started = True
255
+ return None
256
+ if self.message_started:
257
+ if chunk.strip().endswith('"'):
258
+ self.in_message = False
259
+ return chunk.rstrip('"\n')
260
+ return chunk
261
+
262
+ if chunk.strip() == "{":
263
+ self.key_buffer = ""
264
+ self.accumulating = True
265
+ return None
266
+ if chunk.strip() == "}":
267
+ self.in_message = False
268
+ self.message_started = False
269
+ return None
270
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: letta-nightly
3
- Version: 0.5.0.dev20241021104213
3
+ Version: 0.5.0.dev20241023104105
4
4
  Summary: Create LLM agents with long-term memory and custom tools
5
5
  License: Apache License
6
6
  Author: Letta Team
@@ -55,6 +55,7 @@ Requires-Dist: prettytable (>=3.9.0,<4.0.0)
55
55
  Requires-Dist: pyautogen (==0.2.22) ; extra == "autogen"
56
56
  Requires-Dist: pydantic (>=2.7.4,<3.0.0)
57
57
  Requires-Dist: pydantic-settings (>=2.2.1,<3.0.0)
58
+ Requires-Dist: pyhumps (>=3.8.0,<4.0.0)
58
59
  Requires-Dist: pymilvus (>=2.4.3,<3.0.0) ; extra == "milvus"
59
60
  Requires-Dist: pyright (>=1.1.347,<2.0.0) ; extra == "dev"
60
61
  Requires-Dist: pytest-asyncio (>=0.23.2,<0.24.0) ; extra == "dev"
@@ -1,29 +1,27 @@
1
- letta/__init__.py,sha256=cwav47GUQB8F9w0sHIDPe1nZMf_WL00KovBa9dZvSj4,996
1
+ letta/__init__.py,sha256=kRTa2BzRf4EWmx6MkOXUyaisXDj7-6NkmY22gd7h_xs,1014
2
2
  letta/__main__.py,sha256=6Hs2PV7EYc5Tid4g4OtcLXhqVHiNYTGzSBdoOnW2HXA,29
3
3
  letta/agent.py,sha256=PRMDj0vZu5TGj-k2apeWcWYzJnBR36prdMXTKWnRYc8,72997
4
4
  letta/agent_store/chroma.py,sha256=upR5zGnGs6I6btulEYbiZdGG87BgKjxUJOQZ4Y-RQ_M,12492
5
- letta/agent_store/db.py,sha256=54EpxQYX0lAWxrsO0iUKw2vibF8-62Khczns2vxIK-0,23307
5
+ letta/agent_store/db.py,sha256=mTY3YWUs5n17479GMeTmxN8DAyzbBweVcypyNsK_slg,23435
6
6
  letta/agent_store/lancedb.py,sha256=i63d4VZwj9UIOTNs5f0JZ_r5yZD-jKWz4FAH4RMpXOE,5104
7
7
  letta/agent_store/milvus.py,sha256=xUu-D9a6N10MuGJ-R-QWR2IHX77ueqAp88tV4gg9B4M,8470
8
8
  letta/agent_store/qdrant.py,sha256=6_33V-FEDpT9LG5zmr6-3y9slw1YFLswxpahiyMkvHA,7880
9
9
  letta/agent_store/storage.py,sha256=4gKvMRYBGm9cwyaDOzljxDKgqr4MxGXcC4yGhAdKcAA,6693
10
- letta/base.py,sha256=Ba-wt8p59bLmeUONkYSo5MhrkH-_HdT4zE1Y9MVGrSQ,83
11
10
  letta/benchmark/benchmark.py,sha256=ebvnwfp3yezaXOQyGXkYCDYpsmre-b9hvNtnyx4xkG0,3701
12
11
  letta/benchmark/constants.py,sha256=aXc5gdpMGJT327VuxsT5FngbCK2J41PQYeICBO7g_RE,536
13
12
  letta/cli/cli.py,sha256=A5u87nx6g7n_KfIfU2nmjWd2Wq8f5YnCvSBH86bOk28,16149
14
- letta/cli/cli_config.py,sha256=G7QqPNTtlQ4TdrXZrrFFGblZEhnkyrqN1Cl5z415C-g,8689
13
+ letta/cli/cli_config.py,sha256=ynsezKawQ0l95rymlv-AJ3QjbqiyaXZyuzsDfBYwMwg,8537
15
14
  letta/cli/cli_load.py,sha256=x4L8s15GwIW13xrhKYFWHo_y-IVGtoPDHWWKcHDRP10,4587
16
15
  letta/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- letta/client/admin.py,sha256=itdH1dGL143Je5tkZl8dQ1PavjepClar3QasxpbX1cI,7397
18
- letta/client/client.py,sha256=Alx_m9b4ZX_A3G7XtOa5Lgbxtf9PmDhCkUf3QDK0jS0,93065
16
+ letta/client/client.py,sha256=CLOdsr3rVfWHQBPG-NN4sHKKn0Cn0VqIcjtHGxYaix4,93462
19
17
  letta/client/streaming.py,sha256=bfWlUu7z7EoPfKxBqIarYxGKyrL7Pj79BlliToqcCgI,4592
20
18
  letta/client/utils.py,sha256=OJlAKWrldc4I6M1WpcTWNtPJ4wfxlzlZqWLfCozkFtI,2872
21
19
  letta/config.py,sha256=j2I90fOh9d9__kOYObwTDLbvVwYR50rIql5nzrvREKg,19161
22
- letta/constants.py,sha256=8-ep8znrhMLFrfnK63G0Lq8FEyI5M9dXNApCkFfB3iI,6574
20
+ letta/constants.py,sha256=Y7MNpkAZfQ1Mo-AhgFiA_dFQLDCiZT6ebCG_n0R_0FQ,6784
23
21
  letta/credentials.py,sha256=D9mlcPsdDWlIIXQQD8wSPE9M_QvsRrb0p3LB5i9OF5Q,5806
24
22
  letta/data_sources/connectors.py,sha256=qO81ASB6V-vDPthfHYtZiyqcQDQPTT0NuD8hVwC6xI0,9907
25
23
  letta/data_sources/connectors_helper.py,sha256=2TQjCt74fCgT5sw1AP8PalDEk06jPBbhrPG4HVr-WLs,3371
26
- letta/embeddings.py,sha256=ayAMxW6RUK1RUpLsDiJCG1oY2H6fgricaoqMa4GBjRE,8170
24
+ letta/embeddings.py,sha256=qPt8kB-wmuRIg1py7DHnQGJpw3DmQHJ505FJvc0K6Yk,8873
27
25
  letta/errors.py,sha256=cDOo4cSYL-LA0w0b0GdsxXd5k2I1LLOY8nhtXk9YqYs,2875
28
26
  letta/functions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
27
  letta/functions/function_sets/base.py,sha256=N4QmOjL6gDEyOg67ocF6zVKM-NquTo-yXG_T8r18buA,6440
@@ -37,14 +35,14 @@ letta/humans/examples/cs_phd.txt,sha256=9C9ZAV_VuG7GB31ksy3-_NAyk8rjE6YtVOkhp08k
37
35
  letta/interface.py,sha256=QI4hFP0WrNsgM5qX6TbnhH1ZZxsLYr5DaccuxpEQ8S4,12768
38
36
  letta/llm_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
37
  letta/llm_api/anthropic.py,sha256=DTBYPvByj-mfbrkZeAa4PjVEI8gg0p_v15a2h_I-Rqo,12883
40
- letta/llm_api/azure_openai.py,sha256=C-fuuholudcLJDWjqnXJwpXsfmGWfNugEVWyj6YCrpg,4572
38
+ letta/llm_api/azure_openai.py,sha256=Y1HKPog1XzM_f7ujUK_Gv2zQkoy5pU-1bKiUnvSxSrs,6297
41
39
  letta/llm_api/azure_openai_constants.py,sha256=oXtKrgBFHf744gyt5l1thILXgyi8NDNUrKEa2GGGpjw,278
42
40
  letta/llm_api/cohere.py,sha256=vDRd-SUGp1t_JUIdwC3RkIhwMl0OY7n-tAU9uPORYkY,14826
43
41
  letta/llm_api/google_ai.py,sha256=3xZ074nSOCC22c15yerA5ngWzh0ex4wxeI-6faNbHPE,17708
44
- letta/llm_api/helpers.py,sha256=8aG6LzB0T3NFlnab-RR2tj0ARUTMBHSd0icCur5-RCk,8813
42
+ letta/llm_api/helpers.py,sha256=sGCmNA1U_7-AhRFgvT668jdp_xyzSliKQYbTvRR6O7c,9812
45
43
  letta/llm_api/llm_api_tools.py,sha256=GEBO7Dlt7xtAQud1sVsigKZKPpLOZOt2IWL8LwcNV4o,14869
46
44
  letta/llm_api/mistral.py,sha256=fHdfD9ug-rQIk2qn8tRKay1U6w9maF11ryhKi91FfXM,1593
47
- letta/llm_api/openai.py,sha256=faJLzgx94cxz32VSeSxLDHeeSiKkb5WCM3BA_MNylkI,22821
45
+ letta/llm_api/openai.py,sha256=0hwAZhpjrmubYy549hvjzhw6zK_aBhSVuIQN0OsTq-w,23705
48
46
  letta/local_llm/README.md,sha256=hFJyw5B0TU2jrh9nb0zGZMgdH-Ei1dSRfhvPQG_NSoU,168
49
47
  letta/local_llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
48
  letta/local_llm/chat_completion_proxy.py,sha256=SiohxsjGTku4vOryOZx7I0t0xoO_sUuhXgoe62fKq3c,12995
@@ -85,10 +83,18 @@ letta/local_llm/webui/settings.py,sha256=gmLHfiOl1u4JmlAZU2d2O8YKF9lafdakyjwR_ft
85
83
  letta/log.py,sha256=QHquDnL7oUAvdKlAwUlCK9zXKDMUjrU9WA0bxnMsP0Y,2101
86
84
  letta/main.py,sha256=yHgM1lltQZvbE8k0QDQMmVyJiWEj07ZTOYIBHDxE_DQ,18709
87
85
  letta/memory.py,sha256=6q1x3-PY-PeXzAt6hvP-UF1ajvroPZ7XW-5nLy-JhMo,17657
88
- letta/metadata.py,sha256=HIzNn9A28iD3d5Utrey8Z8CQ4KHmaD1iib2a_blLvds,37174
86
+ letta/metadata.py,sha256=dcQk1dx5ugO73I6bcOMpNapbFtphSiaG_80yL3rIU-U,34811
89
87
  letta/o1_agent.py,sha256=0jospImZUKhuQZ0cop0INj8xI6cxhxNffGA8iloHyfU,3114
90
88
  letta/openai_backcompat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
89
  letta/openai_backcompat/openai_object.py,sha256=Y1ZS1sATP60qxJiOsjOP3NbwSzuzvkNAvb3DeuhM5Uk,13490
90
+ letta/orm/__all__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
+ letta/orm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
+ letta/orm/base.py,sha256=9k7mwKDApJNpbrk6oXosQ7amlpeYhDzArdYTZ6BhfpQ,2405
93
+ letta/orm/enums.py,sha256=KfHcFt_fR6GUmSlmfsa-TetvmuRxGESNve8MStRYW64,145
94
+ letta/orm/errors.py,sha256=dYyFwsBuEOS11Wjdz3AAoR4OhejSXNBdQhU71pxymd0,111
95
+ letta/orm/mixins.py,sha256=nOG8Bt4cP75dPPOnI35efFrBZ2OSa6bVRuEFrUuJfBw,1224
96
+ letta/orm/organization.py,sha256=JykIMHJ_g3JVgBaRliBVlqe9iMoahHqSlfwWZv_LDxA,1695
97
+ letta/orm/sqlalchemy_base.py,sha256=YJJBqZ3S6Gp7fr_nBTXBtOt_5rKk-zBBuBUMTAgyRWk,9337
92
98
  letta/persistence_manager.py,sha256=LlLgEDpSafCPAiyKmuq0NvVAnfBkZo6TWbGIKYQjQBs,5200
93
99
  letta/personas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
100
  letta/personas/examples/anna_pa.txt,sha256=zgiNdSNhy1HQy58cF_6RFPzcg2i37F9v38YuL1CW40A,1849
@@ -134,7 +140,7 @@ letta/schemas/openai/chat_completion_response.py,sha256=05FRfm1EsVivyeWo2aoJk34h
134
140
  letta/schemas/openai/chat_completions.py,sha256=V0ZPIIk-ds3O6MAkNHMz8zh1hqMFSPrTcYr88WDYzWE,3588
135
141
  letta/schemas/openai/embedding_response.py,sha256=WKIZpXab1Av7v6sxKG8feW3ZtpQUNosmLVSuhXYa_xU,357
136
142
  letta/schemas/openai/openai.py,sha256=Hilo5BiLAGabzxCwnwfzK5QrWqwYD8epaEKFa4Pwndk,7970
137
- letta/schemas/organization.py,sha256=JSc3hLl0IO_c9iOqf367sU5tJ0Dx_kPzbokCEg0eS4g,601
143
+ letta/schemas/organization.py,sha256=0MOUbaiDGTXkzTjaALLI2wj4E1bL5V_0jjI6jEgFKlA,635
138
144
  letta/schemas/passage.py,sha256=eYQMxD_XjHAi72jmqcGBU4wM4VZtSU0XK8uhQxxN3Ug,3563
139
145
  letta/schemas/source.py,sha256=hB4Ai6Nj8dFdbxv5_Qaf4uN_cmdGmnzgc-4QnHXcV3o,2562
140
146
  letta/schemas/tool.py,sha256=m8jWIsPUhekoQcjX7U_Y5vwhhQqSKn748RcXNXRiLGg,10329
@@ -151,7 +157,7 @@ letta/server/rest_api/app.py,sha256=JNmDnvp9fP--hJPtPpEWgQT-14O1YOceZbWELr2vedA,
151
157
  letta/server/rest_api/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
152
158
  letta/server/rest_api/auth/index.py,sha256=fQBGyVylGSRfEMLQ17cZzrHd5Y1xiVylvPqH5Rl-lXQ,1378
153
159
  letta/server/rest_api/auth_token.py,sha256=725EFEIiNj4dh70hrSd94UysmFD8vcJLrTRfNHkzxDo,774
154
- letta/server/rest_api/interface.py,sha256=Mub9iOQFJh9HSwbc5X6OwHCdtwJYCBzhOjpSx9c5Lss,36181
160
+ letta/server/rest_api/interface.py,sha256=BX0Wa4yO_6KiDzU6GNkW7C_zL10xPgsn0kpId7Z3OJ8,46276
155
161
  letta/server/rest_api/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
162
  letta/server/rest_api/routers/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
163
  letta/server/rest_api/routers/openai/assistants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -161,18 +167,18 @@ letta/server/rest_api/routers/openai/assistants/threads.py,sha256=WXVGBaBvSNPB7Z
161
167
  letta/server/rest_api/routers/openai/chat_completions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
168
  letta/server/rest_api/routers/openai/chat_completions/chat_completions.py,sha256=-uye6cm4SnoQGwxhr1N1FrSXOlnO2Hvbfj6k8JSc45k,4918
163
169
  letta/server/rest_api/routers/v1/__init__.py,sha256=sqlVZa-u9DJwdRsp0_8YUGrac9DHguIB4wETlEDRylA,666
164
- letta/server/rest_api/routers/v1/agents.py,sha256=Yoktva6_pSCRztUdZNZXdbnrp9L5OKnP5E1mZkbUAGw,25066
170
+ letta/server/rest_api/routers/v1/agents.py,sha256=BY4rQOcwsi_WiWh6DwrO8Vz6Nu2JgMBKSHxiBqlaaYY,25397
165
171
  letta/server/rest_api/routers/v1/blocks.py,sha256=0WekE_yBD2U3jYgPxI0DCFjACWavCAlvm_Ybw5SZBnw,2583
166
172
  letta/server/rest_api/routers/v1/health.py,sha256=pKCuVESlVOhGIb4VC4K-H82eZqfghmT6kvj2iOkkKuc,401
167
173
  letta/server/rest_api/routers/v1/jobs.py,sha256=a-j0v-5A0un0pVCOHpfeWnzpOWkVDQO6ti42k_qAlZY,2272
168
174
  letta/server/rest_api/routers/v1/llms.py,sha256=TcyvSx6MEM3je5F4DysL7ligmssL_pFlJaaO4uL95VY,877
169
- letta/server/rest_api/routers/v1/organizations.py,sha256=i3S9E1hu2Zj9g0pRv6wnQhz1VJ_RMIHCrGzgwY-Wj3Y,1945
175
+ letta/server/rest_api/routers/v1/organizations.py,sha256=yIni1i1Yurcbu0SwURm01IEEmlTgiWQ7ci6BefNZT_I,2025
170
176
  letta/server/rest_api/routers/v1/sources.py,sha256=eY_pk9jRL2Y9yIZdsTjH6EuKsfH1neaTU15MKNL0dvw,8749
171
177
  letta/server/rest_api/routers/v1/tools.py,sha256=vxE4b5juoiBiNWmplktuv6GEgenCkKBRov-t6usUJ9A,3665
172
178
  letta/server/rest_api/routers/v1/users.py,sha256=Y2rDvHOG1B5FLSOjutY3R22vt48IngbZ-9h8CohG5rc,3378
173
179
  letta/server/rest_api/static_files.py,sha256=NG8sN4Z5EJ8JVQdj19tkFa9iQ1kBPTab9f_CUxd_u4Q,3143
174
180
  letta/server/rest_api/utils.py,sha256=Fc2ZGKzLaBa2sEtSTVjJ8D5M0xIwsWC0CVAOIJaD3rY,2176
175
- letta/server/server.py,sha256=fEPkRE1R1jBu6S_pMYi2NmoTOkDwa6NjOnNnJVmm5Cw,91491
181
+ letta/server/server.py,sha256=TI9VItwqQ0M-zBHQJwdSKlx5aDMDGczK6vOzagy2zeA,91063
176
182
  letta/server/startup.sh,sha256=jeGV7B_PS0hS-tT6o6GpACrUbV9WV1NI2L9aLoUDDtc,311
177
183
  letta/server/static_files/assets/index-3ab03d5b.css,sha256=OrA9W4iKJ5h2Wlr7GwdAT4wow0CM8hVit1yOxEL49Qw,54295
178
184
  letta/server/static_files/assets/index-d6b3669a.js,sha256=i1nHReU0RPnj-a5W0nNPV4Y9bQ0FOW0ztjMz8a2AE-Y,1821560
@@ -185,12 +191,15 @@ letta/server/ws_api/example_client.py,sha256=95AA5UFgTlNJ0FUQkLxli8dKNx48MNm3eWG
185
191
  letta/server/ws_api/interface.py,sha256=TWl9vkcMCnLsUtgsuENZ-ku2oMDA-OUTzLh_yNRoMa4,4120
186
192
  letta/server/ws_api/protocol.py,sha256=M_-gM5iuDBwa1cuN2IGNCG5GxMJwU2d3XW93XALv9s8,1821
187
193
  letta/server/ws_api/server.py,sha256=C2Kv48PCwl46DQFb0ZP30s86KJLQ6dZk2AhWQEZn9pY,6004
194
+ letta/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
195
+ letta/services/organization_manager.py,sha256=834mNQDVaf6TKx-icAMeOgiYaq1NXtuM7je3SjULlYI,3036
188
196
  letta/settings.py,sha256=gNdH-Ty6f-Nfz2j9ZMZFRQHac2KzgsxLZNt5l_TiAyo,3301
189
197
  letta/streaming_interface.py,sha256=_FPUWy58j50evHcpXyd7zB1wWqeCc71NCFeWh_TBvnw,15736
198
+ letta/streaming_utils.py,sha256=329fsvj1ZN0r0LpQtmMPZ2vSxkDBIUUwvGHZFkjm2I8,11745
190
199
  letta/system.py,sha256=buKYPqG5n2x41hVmWpu6JUpyd7vTWED9Km2_M7dLrvk,6960
191
200
  letta/utils.py,sha256=SXLEYhyp3gHyIjrxNIKNZZ5ittKo3KOj6zxgC_Trex0,31012
192
- letta_nightly-0.5.0.dev20241021104213.dist-info/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
193
- letta_nightly-0.5.0.dev20241021104213.dist-info/METADATA,sha256=HzdXSUkW_tN8xukhNa0g1wcCtIoZAlc9S4vaAHbmdDs,10620
194
- letta_nightly-0.5.0.dev20241021104213.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
195
- letta_nightly-0.5.0.dev20241021104213.dist-info/entry_points.txt,sha256=2zdiyGNEZGV5oYBuS-y2nAAgjDgcC9yM_mHJBFSRt5U,40
196
- letta_nightly-0.5.0.dev20241021104213.dist-info/RECORD,,
201
+ letta_nightly-0.5.0.dev20241023104105.dist-info/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
202
+ letta_nightly-0.5.0.dev20241023104105.dist-info/METADATA,sha256=n2RNxyAEkgg6neEBHsFKxoUpeu9o4qlPSIdJ3ynWx0M,10660
203
+ letta_nightly-0.5.0.dev20241023104105.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
204
+ letta_nightly-0.5.0.dev20241023104105.dist-info/entry_points.txt,sha256=2zdiyGNEZGV5oYBuS-y2nAAgjDgcC9yM_mHJBFSRt5U,40
205
+ letta_nightly-0.5.0.dev20241023104105.dist-info/RECORD,,
letta/base.py DELETED
@@ -1,3 +0,0 @@
1
- from sqlalchemy.ext.declarative import declarative_base
2
-
3
- Base = declarative_base()
letta/client/admin.py DELETED
@@ -1,171 +0,0 @@
1
- from typing import List, Optional
2
-
3
- import requests
4
- from requests import HTTPError
5
-
6
- from letta.functions.functions import parse_source_code
7
- from letta.functions.schema_generator import generate_schema
8
- from letta.schemas.api_key import APIKey, APIKeyCreate
9
- from letta.schemas.organization import Organization, OrganizationCreate
10
- from letta.schemas.user import User, UserCreate
11
-
12
-
13
- class Admin:
14
- """
15
- Admin client allows admin-level operations on the Letta server.
16
- - Creating users
17
- - Generating user keys
18
- """
19
-
20
- def __init__(
21
- self,
22
- base_url: str,
23
- token: str,
24
- api_prefix: str = "v1",
25
- ):
26
- self.base_url = base_url
27
- self.api_prefix = api_prefix
28
- self.token = token
29
- self.headers = {"accept": "application/json", "content-type": "application/json", "authorization": f"Bearer {token}"}
30
-
31
- def get_users(self, cursor: Optional[str] = None, limit: Optional[int] = 50) -> List[User]:
32
- params = {}
33
- if cursor:
34
- params["cursor"] = str(cursor)
35
- if limit:
36
- params["limit"] = limit
37
- response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/users", params=params, headers=self.headers)
38
- if response.status_code != 200:
39
- raise HTTPError(response.json())
40
- return [User(**user) for user in response.json()]
41
-
42
- def create_key(self, user_id: str, key_name: Optional[str] = None) -> APIKey:
43
- request = APIKeyCreate(user_id=user_id, name=key_name)
44
- response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/users/keys", headers=self.headers, json=request.model_dump())
45
- if response.status_code != 200:
46
- raise HTTPError(response.json())
47
- return APIKey(**response.json())
48
-
49
- def get_keys(self, user_id: str) -> List[APIKey]:
50
- params = {"user_id": str(user_id)}
51
- response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/users/keys", params=params, headers=self.headers)
52
- if response.status_code != 200:
53
- raise HTTPError(response.json())
54
- return [APIKey(**key) for key in response.json()]
55
-
56
- def delete_key(self, api_key: str) -> APIKey:
57
- params = {"api_key": api_key}
58
- response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/users/keys", params=params, headers=self.headers)
59
- if response.status_code != 200:
60
- raise HTTPError(response.json())
61
- return APIKey(**response.json())
62
-
63
- def create_user(self, name: Optional[str] = None, org_id: Optional[str] = None) -> User:
64
- request = UserCreate(name=name, org_id=org_id)
65
- response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/users", headers=self.headers, json=request.model_dump())
66
- if response.status_code != 200:
67
- raise HTTPError(response.json())
68
- response_json = response.json()
69
- return User(**response_json)
70
-
71
- def delete_user(self, user_id: str) -> User:
72
- params = {"user_id": str(user_id)}
73
- response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/users", params=params, headers=self.headers)
74
- if response.status_code != 200:
75
- raise HTTPError(response.json())
76
- return User(**response.json())
77
-
78
- def create_organization(self, name: Optional[str] = None) -> Organization:
79
- request = OrganizationCreate(name=name)
80
- response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/orgs", headers=self.headers, json=request.model_dump())
81
- if response.status_code != 200:
82
- raise HTTPError(response.json())
83
- response_json = response.json()
84
- return Organization(**response_json)
85
-
86
- def delete_organization(self, org_id: str) -> Organization:
87
- params = {"org_id": str(org_id)}
88
- response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/orgs", params=params, headers=self.headers)
89
- if response.status_code != 200:
90
- raise HTTPError(response.json())
91
- return Organization(**response.json())
92
-
93
- def get_organizations(self, cursor: Optional[str] = None, limit: Optional[int] = 50) -> List[Organization]:
94
- params = {}
95
- if cursor:
96
- params["cursor"] = str(cursor)
97
- if limit:
98
- params["limit"] = limit
99
- response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/orgs", params=params, headers=self.headers)
100
- if response.status_code != 200:
101
- raise HTTPError(response.json())
102
- return [Organization(**org) for org in response.json()]
103
-
104
- def _reset_server(self):
105
- # DANGER: this will delete all users and keys
106
- # clear all state associated with users
107
- # TODO: clear out all agents, presets, etc.
108
- users = self.get_users()
109
- for user in users:
110
- keys = self.get_keys(user.id)
111
- for key in keys:
112
- self.delete_key(key.key)
113
- self.delete_user(user.id)
114
-
115
- # tools
116
- def create_tool(
117
- self,
118
- func,
119
- name: Optional[str] = None,
120
- update: Optional[bool] = True, # TODO: actually use this
121
- tags: Optional[List[str]] = None,
122
- ):
123
- """Create a tool
124
- Args:
125
- func (callable): The function to create a tool for.
126
- tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
127
- update (bool, optional): Update the tool if it already exists. Defaults to True.
128
- Returns:
129
- Tool object
130
- """
131
-
132
- # TODO: check if tool already exists
133
- # TODO: how to load modules?
134
- # parse source code/schema
135
- source_code = parse_source_code(func)
136
- json_schema = generate_schema(func, name)
137
- source_type = "python"
138
- json_schema["name"]
139
-
140
- if "memory" in tags:
141
- # special modifications to memory functions
142
- # self.memory -> self.memory.memory, since Agent.memory.memory needs to be modified (not BaseMemory.memory)
143
- source_code = source_code.replace("self.memory", "self.memory.memory")
144
-
145
- # create data
146
- data = {"source_code": source_code, "source_type": source_type, "tags": tags, "json_schema": json_schema}
147
- CreateToolRequest(**data) # validate
148
-
149
- # make REST request
150
- response = requests.post(f"{self.base_url}/{self.api_prefix}/admin/tools", json=data, headers=self.headers)
151
- if response.status_code != 200:
152
- raise ValueError(f"Failed to create tool: {response.text}")
153
- return ToolModel(**response.json())
154
-
155
- def list_tools(self):
156
- response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/tools", headers=self.headers)
157
- return ListToolsResponse(**response.json()).tools
158
-
159
- def delete_tool(self, name: str):
160
- response = requests.delete(f"{self.base_url}/{self.api_prefix}/admin/tools/{name}", headers=self.headers)
161
- if response.status_code != 200:
162
- raise ValueError(f"Failed to delete tool: {response.text}")
163
- return response.json()
164
-
165
- def get_tool(self, name: str):
166
- response = requests.get(f"{self.base_url}/{self.api_prefix}/admin/tools/{name}", headers=self.headers)
167
- if response.status_code == 404:
168
- return None
169
- elif response.status_code != 200:
170
- raise ValueError(f"Failed to get tool: {response.text}")
171
- return ToolModel(**response.json())