feat: modal tool execution - NO FEATURE FLAGS USES MODAL [LET-4357] (#5120)
* initial commit * add delay to deploy * fix tests * add tests * passing tests * cleanup * and use modal * working on modal * gate on tool metadata * agent state * cleanup --------- Co-authored-by: Letta Bot <noreply@letta.com>
This commit is contained in:
committed by
Caren Thomas
parent
2a8523aa01
commit
5730f69ecf
69
letta/helpers/tool_helpers.py
Normal file
69
letta/helpers/tool_helpers.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import hashlib
|
||||
|
||||
from letta.constants import MODAL_VERSION_HASH_LENGTH
|
||||
from letta.schemas.tool import Tool
|
||||
|
||||
|
||||
def _serialize_dependencies(tool: Tool) -> str:
|
||||
"""
|
||||
Serialize dependencies in a consistent way for hashing.
|
||||
TODO: This should be improved per LET-3770 to ensure consistent ordering.
|
||||
For now, we convert to string representation.
|
||||
"""
|
||||
parts = []
|
||||
|
||||
if tool.pip_requirements:
|
||||
# TODO: Sort these consistently
|
||||
parts.append(f"pip:{str(tool.pip_requirements)}")
|
||||
|
||||
if tool.npm_requirements:
|
||||
# TODO: Sort these consistently
|
||||
parts.append(f"npm:{str(tool.npm_requirements)}")
|
||||
|
||||
return ";".join(parts)
|
||||
|
||||
|
||||
def compute_tool_hash(tool: Tool):
|
||||
"""
|
||||
Calculate a hash representing the current version of the tool and configuration.
|
||||
This hash changes when:
|
||||
- Tool source code changes
|
||||
- Tool dependencies change
|
||||
- Sandbox configuration changes
|
||||
- Language/runtime changes
|
||||
"""
|
||||
components = [
|
||||
tool.source_code if tool.source_code else "",
|
||||
tool.source_type if tool.source_type else "",
|
||||
_serialize_dependencies(tool),
|
||||
]
|
||||
|
||||
combined = "|".join(components)
|
||||
return hashlib.sha256(combined.encode()).hexdigest()[:MODAL_VERSION_HASH_LENGTH]
|
||||
|
||||
|
||||
def generate_modal_function_name(tool_name: str, organization_id: str, project_id: str = "default") -> str:
|
||||
"""
|
||||
Generate a Modal function name from tool name and project ID.
|
||||
Shortens the project ID to just the prefix and first UUID segment.
|
||||
|
||||
Args:
|
||||
tool_name: Name of the tool
|
||||
organization_id: Full organization ID (not used in function name, but kept for future use)
|
||||
project_id: Project ID (e.g., project-12345678-90ab-cdef-1234-567890abcdef or "default")
|
||||
|
||||
Returns:
|
||||
Modal function name (e.g., tool_name_project-12345678 or tool_name_default)
|
||||
"""
|
||||
from letta.constants import MAX_TOOL_NAME_LENGTH
|
||||
|
||||
max_tool_name_length = 64
|
||||
|
||||
# Shorten the organization_id to just the first segment (e.g., project-12345678)
|
||||
short_organization_id = organization_id[: (max_tool_name_length - MAX_TOOL_NAME_LENGTH - 1)]
|
||||
|
||||
# make extra sure the tool name is not too long
|
||||
name = f"{tool_name[:MAX_TOOL_NAME_LENGTH]}_{short_organization_id}"
|
||||
|
||||
# safe fallback
|
||||
return name
|
||||
Reference in New Issue
Block a user