letta-nightly 0.8.7.dev20250629104239__py3-none-any.whl → 0.8.8.dev20250630104345__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/__init__.py +1 -1
- letta/agents/helpers.py +13 -9
- letta/agents/letta_agent.py +8 -4
- letta/helpers/tool_rule_solver.py +5 -4
- letta/orm/sqlalchemy_base.py +1 -0
- letta/services/agent_manager.py +6 -1
- letta/services/file_processor/file_types.py +2 -0
- letta/utils.py +4 -0
- {letta_nightly-0.8.7.dev20250629104239.dist-info → letta_nightly-0.8.8.dev20250630104345.dist-info}/METADATA +1 -1
- {letta_nightly-0.8.7.dev20250629104239.dist-info → letta_nightly-0.8.8.dev20250630104345.dist-info}/RECORD +13 -13
- {letta_nightly-0.8.7.dev20250629104239.dist-info → letta_nightly-0.8.8.dev20250630104345.dist-info}/LICENSE +0 -0
- {letta_nightly-0.8.7.dev20250629104239.dist-info → letta_nightly-0.8.8.dev20250630104345.dist-info}/WHEEL +0 -0
- {letta_nightly-0.8.7.dev20250629104239.dist-info → letta_nightly-0.8.8.dev20250630104345.dist-info}/entry_points.txt +0 -0
letta/__init__.py
CHANGED
letta/agents/helpers.py
CHANGED
|
@@ -210,17 +210,21 @@ def generate_step_id():
|
|
|
210
210
|
return f"step-{uuid.uuid4()}"
|
|
211
211
|
|
|
212
212
|
|
|
213
|
-
def
|
|
213
|
+
def _safe_load_tool_call_str(tool_call_args_str: str) -> dict:
|
|
214
214
|
"""Lenient JSON → dict with fallback to eval on assertion failure."""
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
# Temp hack to gracefully handle parallel tool calling attempt, only take first one
|
|
216
|
+
if "}{" in tool_call_args_str:
|
|
217
|
+
tool_call_args_str = tool_call_args_str.split("}{", 1)[0] + "}"
|
|
218
|
+
|
|
217
219
|
try:
|
|
218
|
-
|
|
219
|
-
if not isinstance(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
except
|
|
223
|
-
|
|
220
|
+
tool_args = json.loads(tool_call_args_str)
|
|
221
|
+
if not isinstance(tool_args, dict):
|
|
222
|
+
# Load it again - this is due to sometimes Anthropic returning weird json @caren
|
|
223
|
+
tool_args = json.loads(tool_args)
|
|
224
|
+
except json.JSONDecodeError:
|
|
225
|
+
tool_args = {}
|
|
226
|
+
|
|
227
|
+
return tool_args
|
|
224
228
|
|
|
225
229
|
|
|
226
230
|
def _pop_heartbeat(tool_args: dict) -> bool:
|
letta/agents/letta_agent.py
CHANGED
|
@@ -15,7 +15,7 @@ from letta.agents.helpers import (
|
|
|
15
15
|
_create_letta_response,
|
|
16
16
|
_pop_heartbeat,
|
|
17
17
|
_prepare_in_context_messages_no_persist_async,
|
|
18
|
-
|
|
18
|
+
_safe_load_tool_call_str,
|
|
19
19
|
generate_step_id,
|
|
20
20
|
)
|
|
21
21
|
from letta.constants import DEFAULT_MAX_STEPS, NON_USER_MSG_PREFIX
|
|
@@ -944,7 +944,7 @@ class LettaAgent(BaseAgent):
|
|
|
944
944
|
# 1. Parse and validate the tool-call envelope
|
|
945
945
|
tool_call_name: str = tool_call.function.name
|
|
946
946
|
tool_call_id: str = tool_call.id or f"call_{uuid.uuid4().hex[:8]}"
|
|
947
|
-
tool_args =
|
|
947
|
+
tool_args = _safe_load_tool_call_str(tool_call.function.arguments)
|
|
948
948
|
request_heartbeat: bool = _pop_heartbeat(tool_args)
|
|
949
949
|
tool_args.pop(INNER_THOUGHTS_KWARG, None)
|
|
950
950
|
|
|
@@ -993,6 +993,7 @@ class LettaAgent(BaseAgent):
|
|
|
993
993
|
|
|
994
994
|
# 4. Decide whether to keep stepping (<<< focal section simplified)
|
|
995
995
|
continue_stepping, heartbeat_reason, stop_reason = self._decide_continuation(
|
|
996
|
+
agent_state=agent_state,
|
|
996
997
|
request_heartbeat=request_heartbeat,
|
|
997
998
|
tool_call_name=tool_call_name,
|
|
998
999
|
tool_rule_violated=tool_rule_violated,
|
|
@@ -1048,6 +1049,7 @@ class LettaAgent(BaseAgent):
|
|
|
1048
1049
|
|
|
1049
1050
|
def _decide_continuation(
|
|
1050
1051
|
self,
|
|
1052
|
+
agent_state: AgentState,
|
|
1051
1053
|
request_heartbeat: bool,
|
|
1052
1054
|
tool_call_name: str,
|
|
1053
1055
|
tool_rule_violated: bool,
|
|
@@ -1083,10 +1085,12 @@ class LettaAgent(BaseAgent):
|
|
|
1083
1085
|
continue_stepping = False
|
|
1084
1086
|
stop_reason = LettaStopReason(stop_reason=StopReasonType.max_steps.value)
|
|
1085
1087
|
else:
|
|
1086
|
-
uncalled = tool_rules_solver.get_uncalled_required_tools()
|
|
1088
|
+
uncalled = tool_rules_solver.get_uncalled_required_tools(available_tools=set([t.name for t in agent_state.tools]))
|
|
1087
1089
|
if not continue_stepping and uncalled:
|
|
1088
1090
|
continue_stepping = True
|
|
1089
|
-
heartbeat_reason =
|
|
1091
|
+
heartbeat_reason = (
|
|
1092
|
+
f"{NON_USER_MSG_PREFIX}Continuing, user expects these tools: [" f"{', '.join(uncalled)}] to be called still."
|
|
1093
|
+
)
|
|
1090
1094
|
|
|
1091
1095
|
stop_reason = None # reset – we’re still going
|
|
1092
1096
|
|
|
@@ -151,11 +151,11 @@ class ToolRulesSolver(BaseModel):
|
|
|
151
151
|
"""Check if the tool is defined as a continue tool in the tool rules."""
|
|
152
152
|
return any(rule.tool_name == tool_name for rule in self.continue_tool_rules)
|
|
153
153
|
|
|
154
|
-
def has_required_tools_been_called(self) -> bool:
|
|
154
|
+
def has_required_tools_been_called(self, available_tools: Set[str]) -> bool:
|
|
155
155
|
"""Check if all required-before-exit tools have been called."""
|
|
156
|
-
return len(self.get_uncalled_required_tools()) == 0
|
|
156
|
+
return len(self.get_uncalled_required_tools(available_tools=available_tools)) == 0
|
|
157
157
|
|
|
158
|
-
def get_uncalled_required_tools(self) -> List[str]:
|
|
158
|
+
def get_uncalled_required_tools(self, available_tools: Set[str]) -> List[str]:
|
|
159
159
|
"""Get the list of required-before-exit tools that have not been called yet."""
|
|
160
160
|
if not self.required_before_exit_tool_rules:
|
|
161
161
|
return [] # No required tools means no uncalled tools
|
|
@@ -163,7 +163,8 @@ class ToolRulesSolver(BaseModel):
|
|
|
163
163
|
required_tool_names = {rule.tool_name for rule in self.required_before_exit_tool_rules}
|
|
164
164
|
called_tool_names = set(self.tool_call_history)
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
# Get required tools that are uncalled AND available
|
|
167
|
+
return list((required_tool_names & available_tools) - called_tool_names)
|
|
167
168
|
|
|
168
169
|
def get_ending_tool_names(self) -> List[str]:
|
|
169
170
|
"""Get the names of tools that are required before exit."""
|
letta/orm/sqlalchemy_base.py
CHANGED
letta/services/agent_manager.py
CHANGED
|
@@ -779,6 +779,7 @@ class AgentManager:
|
|
|
779
779
|
"response_format": agent_update.response_format,
|
|
780
780
|
"last_run_completion": agent_update.last_run_completion,
|
|
781
781
|
"last_run_duration_ms": agent_update.last_run_duration_ms,
|
|
782
|
+
"timezone": agent_update.timezone,
|
|
782
783
|
}
|
|
783
784
|
for col, val in scalar_updates.items():
|
|
784
785
|
if val is not None:
|
|
@@ -2051,7 +2052,11 @@ class AgentManager:
|
|
|
2051
2052
|
except NoResultFound:
|
|
2052
2053
|
# Agent might not exist anymore, skip
|
|
2053
2054
|
continue
|
|
2054
|
-
|
|
2055
|
+
|
|
2056
|
+
# TODO: @andy/caren
|
|
2057
|
+
# TODO: Ideally we do two no commits on the update_async calls, and then commit here - but that errors for some reason?
|
|
2058
|
+
# TODO: I have too many things rn so lets look at this later
|
|
2059
|
+
# await session.commit()
|
|
2055
2060
|
|
|
2056
2061
|
return await agent.to_pydantic_async()
|
|
2057
2062
|
|
|
@@ -49,6 +49,7 @@ class FileTypeRegistry:
|
|
|
49
49
|
self.register(".markdown", "text/markdown", True, "Markdown document", ChunkingStrategy.DOCUMENTATION)
|
|
50
50
|
self.register(".json", "application/json", True, "JSON data file", ChunkingStrategy.STRUCTURED_DATA)
|
|
51
51
|
self.register(".jsonl", "application/jsonl", True, "JSON Lines file", ChunkingStrategy.STRUCTURED_DATA)
|
|
52
|
+
self.register(".csv", "text/csv", True, "CSV data file", ChunkingStrategy.STRUCTURED_DATA)
|
|
52
53
|
|
|
53
54
|
# Programming languages
|
|
54
55
|
self.register(".py", "text/x-python", True, "Python source code", ChunkingStrategy.CODE)
|
|
@@ -137,6 +138,7 @@ class FileTypeRegistry:
|
|
|
137
138
|
mimetypes.add_type("text/x-markdown", ".md")
|
|
138
139
|
mimetypes.add_type("application/x-jsonlines", ".jsonl")
|
|
139
140
|
mimetypes.add_type("text/xml", ".xml")
|
|
141
|
+
mimetypes.add_type("text/csv", ".csv")
|
|
140
142
|
|
|
141
143
|
def get_allowed_media_types(self) -> Set[str]:
|
|
142
144
|
"""
|
letta/utils.py
CHANGED
|
@@ -531,6 +531,10 @@ def enforce_types(func):
|
|
|
531
531
|
elif origin is list and isinstance(value, list): # Handle List[T]
|
|
532
532
|
element_type = args[0] if args else None
|
|
533
533
|
return all(isinstance(v, element_type) for v in value) if element_type else True
|
|
534
|
+
elif origin is not None and (
|
|
535
|
+
str(origin).endswith("Literal") or getattr(origin, "_name", None) == "Literal"
|
|
536
|
+
): # Handle Literal types
|
|
537
|
+
return value in args
|
|
534
538
|
elif origin: # Handle other generics like Dict, Tuple, etc.
|
|
535
539
|
return isinstance(value, origin)
|
|
536
540
|
else: # Handle non-generic types
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
letta/__init__.py,sha256=
|
|
1
|
+
letta/__init__.py,sha256=qFQJGPrcmwxPDtXS2lrVBj_uI4R-ANeKxnygFadRNWg,1043
|
|
2
2
|
letta/agent.py,sha256=PLTHwDvgl4Nffi_NBm3Jn40H39t7Z6_kZWJ8sswNlpk,89097
|
|
3
3
|
letta/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
letta/agents/base_agent.py,sha256=ymn0Uq9VcImoHmmnP0DyXQ-D3trmpcYVCdi7S9p0fKs,6571
|
|
5
5
|
letta/agents/ephemeral_agent.py,sha256=el-SUF_16vv_7OouIR-6z0pAE9Yc0PLibygvfCKwqfo,2736
|
|
6
6
|
letta/agents/ephemeral_summary_agent.py,sha256=MgJZxmlMU8ZKOKfqMAH7t2WMlf7zW0ZliVuCxxeHehk,4101
|
|
7
7
|
letta/agents/exceptions.py,sha256=BQY4D4w32OYHM63CM19ko7dPwZiAzUs3NbKvzmCTcJg,318
|
|
8
|
-
letta/agents/helpers.py,sha256=
|
|
9
|
-
letta/agents/letta_agent.py,sha256=
|
|
8
|
+
letta/agents/helpers.py,sha256=reSrQCEgIz8wE2FKIr-Gm6jsJeihS607BPqFVs_jaK0,10025
|
|
9
|
+
letta/agents/letta_agent.py,sha256=5DtcSAfY3zprbk27TA1DlscttIwCgZoN8FrnKwMKllI,53664
|
|
10
10
|
letta/agents/letta_agent_batch.py,sha256=cl9_nZYflIZWR23D_x_fUpmMHYITDWu0FUfPW1ivDuw,28031
|
|
11
11
|
letta/agents/prompts/summary_system_prompt.txt,sha256=ftc-aEhfJYN6FlQF4I-I5me-BAh_T2nsTwitPZpZisE,2313
|
|
12
12
|
letta/agents/voice_agent.py,sha256=FE9F1PN4nCUnNQhgoJssAFiJKZz1DiThyRDE3Xcf14Y,23420
|
|
@@ -62,7 +62,7 @@ letta/helpers/json_helpers.py,sha256=PWZ5HhSqGXO4e563dM_8M72q7ScirjXQ4Rv1ckohaV8
|
|
|
62
62
|
letta/helpers/message_helper.py,sha256=Xzf_VCMAXT0Ys8LVUh1ySVtgJwabSQYksOdPr7P4EJU,3549
|
|
63
63
|
letta/helpers/singleton.py,sha256=Y4dG_ZBCcrogvl9iZ69bSLq-QltrdP8wHqKkhef8OBI,370
|
|
64
64
|
letta/helpers/tool_execution_helper.py,sha256=BgBgVLZzbc-JTdOGwyU9miV_-zM3A30jkMpwH1otxaU,7599
|
|
65
|
-
letta/helpers/tool_rule_solver.py,sha256=
|
|
65
|
+
letta/helpers/tool_rule_solver.py,sha256=avRMQzqxE2r6gRvw7oTImYmkSvuoMHlADPND0__feBw,11620
|
|
66
66
|
letta/humans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
letta/humans/examples/basic.txt,sha256=Lcp8YESTWvOJgO4Yf_yyQmgo5bKakeB1nIVrwEGG6PA,17
|
|
68
68
|
letta/humans/examples/cs_phd.txt,sha256=9C9ZAV_VuG7GB31ksy3-_NAyk8rjE6YtVOkhp08k1xw,297
|
|
@@ -171,7 +171,7 @@ letta/orm/provider_trace.py,sha256=CJMGz-rLqagJ-yXh9SJRbiGr5nAYdxY524hmiTgDFx4,1
|
|
|
171
171
|
letta/orm/sandbox_config.py,sha256=zOCvORexDBt16mc6A3U65EI6_2Xe3Roh7k2asLeFMps,4242
|
|
172
172
|
letta/orm/source.py,sha256=rtehzez80rRrJigXeRBgTlfTZEUy6cVqDizWEN2tvuY,2224
|
|
173
173
|
letta/orm/sources_agents.py,sha256=Ik_PokCBrXRd9wXWomeNeb8EtLUwjb9VMZ8LWXqpK5A,473
|
|
174
|
-
letta/orm/sqlalchemy_base.py,sha256=
|
|
174
|
+
letta/orm/sqlalchemy_base.py,sha256=N90RIye2ubLRklJAPEVrLkh7sV30DKLcFmAKHrCgXcY,44438
|
|
175
175
|
letta/orm/sqlite_functions.py,sha256=JCScKiRlYCKxy9hChQ8wsk4GMKknZE24MunnG3fM1Gw,4255
|
|
176
176
|
letta/orm/step.py,sha256=SLsLY1g4nuUeI47q9rlXPBCSVUNX3lxYAYAIqxy-YK4,3517
|
|
177
177
|
letta/orm/tool.py,sha256=oTDbvSNNW_jHjYbJqqsLLuXf9uFRTZTZh33TXAcZ898,2839
|
|
@@ -333,7 +333,7 @@ letta/server/ws_api/interface.py,sha256=TWl9vkcMCnLsUtgsuENZ-ku2oMDA-OUTzLh_yNRo
|
|
|
333
333
|
letta/server/ws_api/protocol.py,sha256=5mDgpfNZn_kNwHnpt5Dsuw8gdNH298sgxTGed3etzYg,1836
|
|
334
334
|
letta/server/ws_api/server.py,sha256=cBSzf-V4zT1bL_0i54OTI3cMXhTIIxqjSRF8pYjk7fg,5835
|
|
335
335
|
letta/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
336
|
-
letta/services/agent_manager.py,sha256=
|
|
336
|
+
letta/services/agent_manager.py,sha256=J7eOEFoJuaCDo9kG3l7J7FKGPtzdxRDm9eqNxGN344k,121338
|
|
337
337
|
letta/services/block_manager.py,sha256=YwDGdy6f6MNXVXVOxIMOOP6IEWT8h-k5uQlveof0pyE,22744
|
|
338
338
|
letta/services/context_window_calculator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
339
339
|
letta/services/context_window_calculator/context_window_calculator.py,sha256=H0-Ello1DHV28MnzMseWrg--jarDc6YwCcgwPlWjtZk,6527
|
|
@@ -346,7 +346,7 @@ letta/services/file_processor/chunker/llama_index_chunker.py,sha256=dEBf33TifD_B
|
|
|
346
346
|
letta/services/file_processor/embedder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
347
347
|
letta/services/file_processor/embedder/openai_embedder.py,sha256=BjKsNqh_nfNIDVWkCR2noFX7E6Mr68FQtj79F2xeCpM,3545
|
|
348
348
|
letta/services/file_processor/file_processor.py,sha256=xOcoQRgekcZo4JrrXMNYKSiuN4vPKxc81HuS2G3sFPs,4803
|
|
349
|
-
letta/services/file_processor/file_types.py,sha256=
|
|
349
|
+
letta/services/file_processor/file_types.py,sha256=9k3Lt_bquQjJ7T6L12fPS9IS5wldhJ2puSkH6rhfCaE,13128
|
|
350
350
|
letta/services/file_processor/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
351
351
|
letta/services/file_processor/parser/base_parser.py,sha256=WfnXP6fL-xQz4eIHEWa6-ZNEAARbF_alowqH4BAUzJo,238
|
|
352
352
|
letta/services/file_processor/parser/mistral_parser.py,sha256=Hzsrm36HbKQ7CWljTZT1RgbvxE4gvSBq76Ucj80jjeQ,2322
|
|
@@ -404,9 +404,9 @@ letta/templates/sandbox_code_file.py.j2,sha256=zgzaboDZVtM15XkxILnhiKisF7DSUoI2Y
|
|
|
404
404
|
letta/templates/sandbox_code_file_async.py.j2,sha256=hL6UWt4L16o79OPOBq1_Cw7gR5-gpaR_esbmU8bSp8w,1805
|
|
405
405
|
letta/templates/template_helper.py,sha256=uHWO1PukgMoIIvgqQdPyHq3o3CQ6mcjUjTGvx9VLGkk,409
|
|
406
406
|
letta/types/__init__.py,sha256=hokKjCVFGEfR7SLMrtZsRsBfsC7yTIbgKPLdGg4K1eY,147
|
|
407
|
-
letta/utils.py,sha256=
|
|
408
|
-
letta_nightly-0.8.
|
|
409
|
-
letta_nightly-0.8.
|
|
410
|
-
letta_nightly-0.8.
|
|
411
|
-
letta_nightly-0.8.
|
|
412
|
-
letta_nightly-0.8.
|
|
407
|
+
letta/utils.py,sha256=tpJIzZetCfkCPI2YixMp_6tul7QgjdO6_G6Yg2_nYa4,33437
|
|
408
|
+
letta_nightly-0.8.8.dev20250630104345.dist-info/LICENSE,sha256=mExtuZ_GYJgDEI38GWdiEYZizZS4KkVt2SF1g_GPNhI,10759
|
|
409
|
+
letta_nightly-0.8.8.dev20250630104345.dist-info/METADATA,sha256=gPHo8DKY7FGcBfQxX-BOy0kqon3Tmdi0QRbVPPR59Lk,22841
|
|
410
|
+
letta_nightly-0.8.8.dev20250630104345.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
411
|
+
letta_nightly-0.8.8.dev20250630104345.dist-info/entry_points.txt,sha256=2zdiyGNEZGV5oYBuS-y2nAAgjDgcC9yM_mHJBFSRt5U,40
|
|
412
|
+
letta_nightly-0.8.8.dev20250630104345.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|