letta-nightly 0.6.15.dev20250125103914__py3-none-any.whl → 0.6.16.dev20250127040412__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 -2
- letta/agent.py +5 -1
- letta/cli/cli_config.py +1 -1
- letta/client/client.py +4 -20
- letta/functions/schema_generator.py +24 -11
- letta/llm_api/anthropic.py +485 -7
- letta/llm_api/llm_api_tools.py +28 -13
- letta/llm_api/openai.py +8 -3
- letta/local_llm/constants.py +1 -0
- letta/schemas/message.py +6 -5
- letta/schemas/providers.py +125 -0
- letta/schemas/tool.py +0 -4
- letta/server/rest_api/interface.py +15 -3
- letta/server/rest_api/routers/v1/agents.py +2 -0
- letta/server/rest_api/routers/v1/tools.py +1 -1
- letta/server/server.py +23 -5
- letta/services/helpers/agent_manager_helper.py +22 -1
- letta/services/tool_manager.py +1 -0
- letta/settings.py +3 -0
- letta/streaming_utils.py +5 -1
- {letta_nightly-0.6.15.dev20250125103914.dist-info → letta_nightly-0.6.16.dev20250127040412.dist-info}/METADATA +1 -1
- {letta_nightly-0.6.15.dev20250125103914.dist-info → letta_nightly-0.6.16.dev20250127040412.dist-info}/RECORD +25 -25
- {letta_nightly-0.6.15.dev20250125103914.dist-info → letta_nightly-0.6.16.dev20250127040412.dist-info}/LICENSE +0 -0
- {letta_nightly-0.6.15.dev20250125103914.dist-info → letta_nightly-0.6.16.dev20250127040412.dist-info}/WHEEL +0 -0
- {letta_nightly-0.6.15.dev20250125103914.dist-info → letta_nightly-0.6.16.dev20250127040412.dist-info}/entry_points.txt +0 -0
letta/__init__.py
CHANGED
letta/agent.py
CHANGED
|
@@ -466,7 +466,10 @@ class Agent(BaseAgent):
|
|
|
466
466
|
if isinstance(heartbeat_request, str) and heartbeat_request.lower().strip() == "true":
|
|
467
467
|
heartbeat_request = True
|
|
468
468
|
|
|
469
|
-
if
|
|
469
|
+
if heartbeat_request is None:
|
|
470
|
+
heartbeat_request = False
|
|
471
|
+
|
|
472
|
+
if not isinstance(heartbeat_request, bool):
|
|
470
473
|
self.logger.warning(
|
|
471
474
|
f"{CLI_WARNING_PREFIX}'request_heartbeat' arg parsed was not a bool or None, type={type(heartbeat_request)}, value={heartbeat_request}"
|
|
472
475
|
)
|
|
@@ -728,6 +731,7 @@ class Agent(BaseAgent):
|
|
|
728
731
|
# (if yes) Step 4: call the function
|
|
729
732
|
# (if yes) Step 5: send the info on the function call and function response to LLM
|
|
730
733
|
response_message = response.choices[0].message
|
|
734
|
+
|
|
731
735
|
response_message.model_copy() # TODO why are we copying here?
|
|
732
736
|
all_response_messages, heartbeat_request, function_failed = self._handle_ai_response(
|
|
733
737
|
response_message,
|
letta/cli/cli_config.py
CHANGED
|
@@ -135,7 +135,7 @@ def add_tool(
|
|
|
135
135
|
func = eval(func_def.name)
|
|
136
136
|
|
|
137
137
|
# 4. Add or update the tool
|
|
138
|
-
tool = client.create_or_update_tool(func=func,
|
|
138
|
+
tool = client.create_or_update_tool(func=func, tags=tags, update=update)
|
|
139
139
|
print(f"Tool {tool.name} added successfully")
|
|
140
140
|
|
|
141
141
|
|
letta/client/client.py
CHANGED
|
@@ -185,20 +185,15 @@ class AbstractClient(object):
|
|
|
185
185
|
def load_composio_tool(self, action: "ActionType") -> Tool:
|
|
186
186
|
raise NotImplementedError
|
|
187
187
|
|
|
188
|
-
def create_tool(
|
|
189
|
-
self, func, name: Optional[str] = None, tags: Optional[List[str]] = None, return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT
|
|
190
|
-
) -> Tool:
|
|
188
|
+
def create_tool(self, func, tags: Optional[List[str]] = None, return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT) -> Tool:
|
|
191
189
|
raise NotImplementedError
|
|
192
190
|
|
|
193
|
-
def create_or_update_tool(
|
|
194
|
-
self, func, name: Optional[str] = None, tags: Optional[List[str]] = None, return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT
|
|
195
|
-
) -> Tool:
|
|
191
|
+
def create_or_update_tool(self, func, tags: Optional[List[str]] = None, return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT) -> Tool:
|
|
196
192
|
raise NotImplementedError
|
|
197
193
|
|
|
198
194
|
def update_tool(
|
|
199
195
|
self,
|
|
200
196
|
id: str,
|
|
201
|
-
name: Optional[str] = None,
|
|
202
197
|
description: Optional[str] = None,
|
|
203
198
|
func: Optional[Callable] = None,
|
|
204
199
|
tags: Optional[List[str]] = None,
|
|
@@ -1546,7 +1541,6 @@ class RESTClient(AbstractClient):
|
|
|
1546
1541
|
def create_tool(
|
|
1547
1542
|
self,
|
|
1548
1543
|
func: Callable,
|
|
1549
|
-
name: Optional[str] = None,
|
|
1550
1544
|
tags: Optional[List[str]] = None,
|
|
1551
1545
|
return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
|
|
1552
1546
|
) -> Tool:
|
|
@@ -1566,7 +1560,7 @@ class RESTClient(AbstractClient):
|
|
|
1566
1560
|
source_type = "python"
|
|
1567
1561
|
|
|
1568
1562
|
# call server function
|
|
1569
|
-
request = ToolCreate(source_type=source_type, source_code=source_code,
|
|
1563
|
+
request = ToolCreate(source_type=source_type, source_code=source_code, return_char_limit=return_char_limit)
|
|
1570
1564
|
if tags:
|
|
1571
1565
|
request.tags = tags
|
|
1572
1566
|
response = requests.post(f"{self.base_url}/{self.api_prefix}/tools", json=request.model_dump(), headers=self.headers)
|
|
@@ -1577,7 +1571,6 @@ class RESTClient(AbstractClient):
|
|
|
1577
1571
|
def create_or_update_tool(
|
|
1578
1572
|
self,
|
|
1579
1573
|
func: Callable,
|
|
1580
|
-
name: Optional[str] = None,
|
|
1581
1574
|
tags: Optional[List[str]] = None,
|
|
1582
1575
|
return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
|
|
1583
1576
|
) -> Tool:
|
|
@@ -1597,7 +1590,7 @@ class RESTClient(AbstractClient):
|
|
|
1597
1590
|
source_type = "python"
|
|
1598
1591
|
|
|
1599
1592
|
# call server function
|
|
1600
|
-
request = ToolCreate(source_type=source_type, source_code=source_code,
|
|
1593
|
+
request = ToolCreate(source_type=source_type, source_code=source_code, return_char_limit=return_char_limit)
|
|
1601
1594
|
if tags:
|
|
1602
1595
|
request.tags = tags
|
|
1603
1596
|
response = requests.put(f"{self.base_url}/{self.api_prefix}/tools", json=request.model_dump(), headers=self.headers)
|
|
@@ -1608,7 +1601,6 @@ class RESTClient(AbstractClient):
|
|
|
1608
1601
|
def update_tool(
|
|
1609
1602
|
self,
|
|
1610
1603
|
id: str,
|
|
1611
|
-
name: Optional[str] = None,
|
|
1612
1604
|
description: Optional[str] = None,
|
|
1613
1605
|
func: Optional[Callable] = None,
|
|
1614
1606
|
tags: Optional[List[str]] = None,
|
|
@@ -1639,7 +1631,6 @@ class RESTClient(AbstractClient):
|
|
|
1639
1631
|
source_type=source_type,
|
|
1640
1632
|
source_code=source_code,
|
|
1641
1633
|
tags=tags,
|
|
1642
|
-
name=name,
|
|
1643
1634
|
return_char_limit=return_char_limit,
|
|
1644
1635
|
)
|
|
1645
1636
|
response = requests.patch(f"{self.base_url}/{self.api_prefix}/tools/{id}", json=request.model_dump(), headers=self.headers)
|
|
@@ -2976,7 +2967,6 @@ class LocalClient(AbstractClient):
|
|
|
2976
2967
|
def create_tool(
|
|
2977
2968
|
self,
|
|
2978
2969
|
func,
|
|
2979
|
-
name: Optional[str] = None,
|
|
2980
2970
|
tags: Optional[List[str]] = None,
|
|
2981
2971
|
description: Optional[str] = None,
|
|
2982
2972
|
return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
|
|
@@ -3018,7 +3008,6 @@ class LocalClient(AbstractClient):
|
|
|
3018
3008
|
def create_or_update_tool(
|
|
3019
3009
|
self,
|
|
3020
3010
|
func,
|
|
3021
|
-
name: Optional[str] = None,
|
|
3022
3011
|
tags: Optional[List[str]] = None,
|
|
3023
3012
|
description: Optional[str] = None,
|
|
3024
3013
|
return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
|
|
@@ -3028,7 +3017,6 @@ class LocalClient(AbstractClient):
|
|
|
3028
3017
|
|
|
3029
3018
|
Args:
|
|
3030
3019
|
func (callable): The function to create a tool for.
|
|
3031
|
-
name: (str): Name of the tool (must be unique per-user.)
|
|
3032
3020
|
tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
|
|
3033
3021
|
description (str, optional): The description.
|
|
3034
3022
|
return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
|
|
@@ -3046,7 +3034,6 @@ class LocalClient(AbstractClient):
|
|
|
3046
3034
|
Tool(
|
|
3047
3035
|
source_type=source_type,
|
|
3048
3036
|
source_code=source_code,
|
|
3049
|
-
name=name,
|
|
3050
3037
|
tags=tags,
|
|
3051
3038
|
description=description,
|
|
3052
3039
|
return_char_limit=return_char_limit,
|
|
@@ -3057,7 +3044,6 @@ class LocalClient(AbstractClient):
|
|
|
3057
3044
|
def update_tool(
|
|
3058
3045
|
self,
|
|
3059
3046
|
id: str,
|
|
3060
|
-
name: Optional[str] = None,
|
|
3061
3047
|
description: Optional[str] = None,
|
|
3062
3048
|
func: Optional[Callable] = None,
|
|
3063
3049
|
tags: Optional[List[str]] = None,
|
|
@@ -3068,7 +3054,6 @@ class LocalClient(AbstractClient):
|
|
|
3068
3054
|
|
|
3069
3055
|
Args:
|
|
3070
3056
|
id (str): ID of the tool
|
|
3071
|
-
name (str): Name of the tool
|
|
3072
3057
|
func (callable): Function to wrap in a tool
|
|
3073
3058
|
tags (List[str]): Tags for the tool
|
|
3074
3059
|
return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
|
|
@@ -3080,7 +3065,6 @@ class LocalClient(AbstractClient):
|
|
|
3080
3065
|
"source_type": "python", # Always include source_type
|
|
3081
3066
|
"source_code": parse_source_code(func) if func else None,
|
|
3082
3067
|
"tags": tags,
|
|
3083
|
-
"name": name,
|
|
3084
3068
|
"description": description,
|
|
3085
3069
|
"return_char_limit": return_char_limit,
|
|
3086
3070
|
}
|
|
@@ -437,6 +437,7 @@ def generate_tool_schema_for_composio(
|
|
|
437
437
|
name: str,
|
|
438
438
|
description: str,
|
|
439
439
|
append_heartbeat: bool = True,
|
|
440
|
+
strict: bool = False,
|
|
440
441
|
) -> Dict[str, Any]:
|
|
441
442
|
properties_json = {}
|
|
442
443
|
required_fields = parameters_model.required or []
|
|
@@ -473,14 +474,26 @@ def generate_tool_schema_for_composio(
|
|
|
473
474
|
required_fields.append("request_heartbeat")
|
|
474
475
|
|
|
475
476
|
# Return the final schema
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
"
|
|
482
|
-
"
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
477
|
+
if strict:
|
|
478
|
+
# https://platform.openai.com/docs/guides/function-calling#strict-mode
|
|
479
|
+
return {
|
|
480
|
+
"name": name,
|
|
481
|
+
"description": description,
|
|
482
|
+
"strict": True, # NOTE
|
|
483
|
+
"parameters": {
|
|
484
|
+
"type": "object",
|
|
485
|
+
"properties": properties_json,
|
|
486
|
+
"additionalProperties": False, # NOTE
|
|
487
|
+
"required": required_fields,
|
|
488
|
+
},
|
|
489
|
+
}
|
|
490
|
+
else:
|
|
491
|
+
return {
|
|
492
|
+
"name": name,
|
|
493
|
+
"description": description,
|
|
494
|
+
"parameters": {
|
|
495
|
+
"type": "object",
|
|
496
|
+
"properties": properties_json,
|
|
497
|
+
"required": required_fields,
|
|
498
|
+
},
|
|
499
|
+
}
|