letta-nightly 0.6.3.dev20241213104231__py3-none-any.whl → 0.6.4.dev20241214104034__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 +2 -2
- letta/agent.py +54 -45
- letta/chat_only_agent.py +6 -8
- letta/cli/cli.py +2 -10
- letta/client/client.py +121 -138
- letta/config.py +0 -161
- letta/main.py +3 -8
- letta/memory.py +3 -14
- letta/o1_agent.py +1 -5
- letta/offline_memory_agent.py +2 -6
- letta/orm/__init__.py +2 -0
- letta/orm/agent.py +109 -0
- letta/orm/agents_tags.py +10 -18
- letta/orm/block.py +29 -4
- letta/orm/blocks_agents.py +5 -11
- letta/orm/custom_columns.py +152 -0
- letta/orm/message.py +3 -38
- letta/orm/organization.py +2 -7
- letta/orm/passage.py +10 -32
- letta/orm/source.py +5 -25
- letta/orm/sources_agents.py +13 -0
- letta/orm/sqlalchemy_base.py +54 -30
- letta/orm/tool.py +1 -19
- letta/orm/tools_agents.py +7 -24
- letta/orm/user.py +3 -4
- letta/schemas/agent.py +48 -65
- letta/schemas/memory.py +2 -1
- letta/schemas/sandbox_config.py +12 -1
- letta/server/rest_api/app.py +0 -5
- letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +1 -1
- letta/server/rest_api/routers/v1/agents.py +99 -78
- letta/server/rest_api/routers/v1/blocks.py +22 -25
- letta/server/rest_api/routers/v1/jobs.py +4 -4
- letta/server/rest_api/routers/v1/sandbox_configs.py +10 -10
- letta/server/rest_api/routers/v1/sources.py +12 -12
- letta/server/rest_api/routers/v1/tools.py +35 -15
- letta/server/rest_api/routers/v1/users.py +0 -46
- letta/server/server.py +172 -718
- letta/server/ws_api/server.py +0 -5
- letta/services/agent_manager.py +405 -0
- letta/services/block_manager.py +13 -21
- letta/services/helpers/agent_manager_helper.py +90 -0
- letta/services/organization_manager.py +0 -1
- letta/services/passage_manager.py +62 -62
- letta/services/sandbox_config_manager.py +3 -3
- letta/services/source_manager.py +22 -1
- letta/services/tool_execution_sandbox.py +4 -4
- letta/services/user_manager.py +11 -6
- letta/utils.py +2 -2
- {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/METADATA +1 -1
- {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/RECORD +54 -58
- letta/metadata.py +0 -407
- letta/schemas/agents_tags.py +0 -33
- letta/schemas/api_key.py +0 -21
- letta/schemas/blocks_agents.py +0 -32
- letta/schemas/tools_agents.py +0 -32
- letta/server/rest_api/routers/openai/assistants/threads.py +0 -338
- letta/services/agents_tags_manager.py +0 -64
- letta/services/blocks_agents_manager.py +0 -106
- letta/services/tools_agents_manager.py +0 -94
- {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/LICENSE +0 -0
- {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/WHEEL +0 -0
- {letta_nightly-0.6.3.dev20241213104231.dist-info → letta_nightly-0.6.4.dev20241214104034.dist-info}/entry_points.txt +0 -0
letta/client/client.py
CHANGED
|
@@ -15,7 +15,8 @@ from letta.constants import (
|
|
|
15
15
|
)
|
|
16
16
|
from letta.data_sources.connectors import DataConnector
|
|
17
17
|
from letta.functions.functions import parse_source_code
|
|
18
|
-
from letta.
|
|
18
|
+
from letta.orm.errors import NoResultFound
|
|
19
|
+
from letta.schemas.agent import AgentState, AgentType, CreateAgent, UpdateAgent
|
|
19
20
|
from letta.schemas.block import Block, BlockUpdate, CreateBlock, Human, Persona
|
|
20
21
|
from letta.schemas.embedding_config import EmbeddingConfig
|
|
21
22
|
|
|
@@ -65,10 +66,8 @@ def create_client(base_url: Optional[str] = None, token: Optional[str] = None):
|
|
|
65
66
|
class AbstractClient(object):
|
|
66
67
|
def __init__(
|
|
67
68
|
self,
|
|
68
|
-
auto_save: bool = False,
|
|
69
69
|
debug: bool = False,
|
|
70
70
|
):
|
|
71
|
-
self.auto_save = auto_save
|
|
72
71
|
self.debug = debug
|
|
73
72
|
|
|
74
73
|
def agent_exists(self, agent_id: Optional[str] = None, agent_name: Optional[str] = None) -> bool:
|
|
@@ -81,8 +80,9 @@ class AbstractClient(object):
|
|
|
81
80
|
embedding_config: Optional[EmbeddingConfig] = None,
|
|
82
81
|
llm_config: Optional[LLMConfig] = None,
|
|
83
82
|
memory=None,
|
|
83
|
+
block_ids: Optional[List[str]] = None,
|
|
84
84
|
system: Optional[str] = None,
|
|
85
|
-
|
|
85
|
+
tool_ids: Optional[List[str]] = None,
|
|
86
86
|
tool_rules: Optional[List[BaseToolRule]] = None,
|
|
87
87
|
include_base_tools: Optional[bool] = True,
|
|
88
88
|
metadata: Optional[Dict] = {"human:": DEFAULT_HUMAN, "persona": DEFAULT_PERSONA},
|
|
@@ -97,7 +97,7 @@ class AbstractClient(object):
|
|
|
97
97
|
name: Optional[str] = None,
|
|
98
98
|
description: Optional[str] = None,
|
|
99
99
|
system: Optional[str] = None,
|
|
100
|
-
|
|
100
|
+
tool_ids: Optional[List[str]] = None,
|
|
101
101
|
metadata: Optional[Dict] = None,
|
|
102
102
|
llm_config: Optional[LLMConfig] = None,
|
|
103
103
|
embedding_config: Optional[EmbeddingConfig] = None,
|
|
@@ -436,7 +436,6 @@ class RESTClient(AbstractClient):
|
|
|
436
436
|
Initializes a new instance of Client class.
|
|
437
437
|
|
|
438
438
|
Args:
|
|
439
|
-
auto_save (bool): Whether to automatically save changes.
|
|
440
439
|
user_id (str): The user ID.
|
|
441
440
|
debug (bool): Whether to print debug information.
|
|
442
441
|
default_llm_config (Optional[LLMConfig]): The default LLM configuration.
|
|
@@ -456,6 +455,7 @@ class RESTClient(AbstractClient):
|
|
|
456
455
|
params = {}
|
|
457
456
|
if tags:
|
|
458
457
|
params["tags"] = tags
|
|
458
|
+
params["match_all_tags"] = False
|
|
459
459
|
|
|
460
460
|
response = requests.get(f"{self.base_url}/{self.api_prefix}/agents", headers=self.headers, params=params)
|
|
461
461
|
return [AgentState(**agent) for agent in response.json()]
|
|
@@ -491,10 +491,12 @@ class RESTClient(AbstractClient):
|
|
|
491
491
|
llm_config: LLMConfig = None,
|
|
492
492
|
# memory
|
|
493
493
|
memory: Memory = ChatMemory(human=get_human_text(DEFAULT_HUMAN), persona=get_persona_text(DEFAULT_PERSONA)),
|
|
494
|
+
# Existing blocks
|
|
495
|
+
block_ids: Optional[List[str]] = None,
|
|
494
496
|
# system
|
|
495
497
|
system: Optional[str] = None,
|
|
496
498
|
# tools
|
|
497
|
-
|
|
499
|
+
tool_ids: Optional[List[str]] = None,
|
|
498
500
|
tool_rules: Optional[List[BaseToolRule]] = None,
|
|
499
501
|
include_base_tools: Optional[bool] = True,
|
|
500
502
|
# metadata
|
|
@@ -511,7 +513,7 @@ class RESTClient(AbstractClient):
|
|
|
511
513
|
llm_config (LLMConfig): LLM configuration
|
|
512
514
|
memory (Memory): Memory configuration
|
|
513
515
|
system (str): System configuration
|
|
514
|
-
|
|
516
|
+
tool_ids (List[str]): List of tool ids
|
|
515
517
|
include_base_tools (bool): Include base tools
|
|
516
518
|
metadata (Dict): Metadata
|
|
517
519
|
description (str): Description
|
|
@@ -520,31 +522,54 @@ class RESTClient(AbstractClient):
|
|
|
520
522
|
Returns:
|
|
521
523
|
agent_state (AgentState): State of the created agent
|
|
522
524
|
"""
|
|
525
|
+
tool_ids = tool_ids or []
|
|
523
526
|
tool_names = []
|
|
524
|
-
if tools:
|
|
525
|
-
tool_names += tools
|
|
526
527
|
if include_base_tools:
|
|
527
528
|
tool_names += BASE_TOOLS
|
|
528
529
|
tool_names += BASE_MEMORY_TOOLS
|
|
530
|
+
tool_ids += [self.get_tool_id(tool_name=name) for name in tool_names]
|
|
529
531
|
|
|
530
532
|
assert embedding_config or self._default_embedding_config, f"Embedding config must be provided"
|
|
531
533
|
assert llm_config or self._default_llm_config, f"LLM config must be provided"
|
|
532
534
|
|
|
535
|
+
# TODO: This should not happen here, we need to have clear separation between create/add blocks
|
|
536
|
+
# TODO: This is insanely hacky and a result of allowing free-floating blocks
|
|
537
|
+
# TODO: When we create the block, it gets it's own block ID
|
|
538
|
+
blocks = []
|
|
539
|
+
for block in memory.get_blocks():
|
|
540
|
+
blocks.append(
|
|
541
|
+
self.create_block(
|
|
542
|
+
label=block.label,
|
|
543
|
+
value=block.value,
|
|
544
|
+
limit=block.limit,
|
|
545
|
+
template_name=block.template_name,
|
|
546
|
+
is_template=block.is_template,
|
|
547
|
+
)
|
|
548
|
+
)
|
|
549
|
+
memory.blocks = blocks
|
|
550
|
+
block_ids = block_ids or []
|
|
551
|
+
|
|
533
552
|
# create agent
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
tool_rules
|
|
541
|
-
system
|
|
542
|
-
agent_type
|
|
543
|
-
llm_config
|
|
544
|
-
embedding_config
|
|
545
|
-
initial_message_sequence
|
|
546
|
-
tags
|
|
547
|
-
|
|
553
|
+
create_params = {
|
|
554
|
+
"description": description,
|
|
555
|
+
"metadata_": metadata,
|
|
556
|
+
"memory_blocks": [],
|
|
557
|
+
"block_ids": [b.id for b in memory.get_blocks()] + block_ids,
|
|
558
|
+
"tool_ids": tool_ids,
|
|
559
|
+
"tool_rules": tool_rules,
|
|
560
|
+
"system": system,
|
|
561
|
+
"agent_type": agent_type,
|
|
562
|
+
"llm_config": llm_config if llm_config else self._default_llm_config,
|
|
563
|
+
"embedding_config": embedding_config if embedding_config else self._default_embedding_config,
|
|
564
|
+
"initial_message_sequence": initial_message_sequence,
|
|
565
|
+
"tags": tags,
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
# Only add name if it's not None
|
|
569
|
+
if name is not None:
|
|
570
|
+
create_params["name"] = name
|
|
571
|
+
|
|
572
|
+
request = CreateAgent(**create_params)
|
|
548
573
|
|
|
549
574
|
# Use model_dump_json() instead of model_dump()
|
|
550
575
|
# If we use model_dump(), the datetime objects will not be serialized correctly
|
|
@@ -561,14 +586,6 @@ class RESTClient(AbstractClient):
|
|
|
561
586
|
# gather agent state
|
|
562
587
|
agent_state = AgentState(**response.json())
|
|
563
588
|
|
|
564
|
-
# create and link blocks
|
|
565
|
-
for block in memory.get_blocks():
|
|
566
|
-
if not self.get_block(block.id):
|
|
567
|
-
# note: this does not update existing blocks
|
|
568
|
-
# WARNING: this resets the block ID - this method is a hack for backwards compat, should eventually use CreateBlock not Memory
|
|
569
|
-
block = self.create_block(label=block.label, value=block.value, limit=block.limit)
|
|
570
|
-
self.link_agent_memory_block(agent_id=agent_state.id, block_id=block.id)
|
|
571
|
-
|
|
572
589
|
# refresh and return agent
|
|
573
590
|
return self.get_agent(agent_state.id)
|
|
574
591
|
|
|
@@ -602,7 +619,7 @@ class RESTClient(AbstractClient):
|
|
|
602
619
|
name: Optional[str] = None,
|
|
603
620
|
description: Optional[str] = None,
|
|
604
621
|
system: Optional[str] = None,
|
|
605
|
-
|
|
622
|
+
tool_ids: Optional[List[str]] = None,
|
|
606
623
|
metadata: Optional[Dict] = None,
|
|
607
624
|
llm_config: Optional[LLMConfig] = None,
|
|
608
625
|
embedding_config: Optional[EmbeddingConfig] = None,
|
|
@@ -617,7 +634,7 @@ class RESTClient(AbstractClient):
|
|
|
617
634
|
name (str): Name of the agent
|
|
618
635
|
description (str): Description of the agent
|
|
619
636
|
system (str): System configuration
|
|
620
|
-
|
|
637
|
+
tool_ids (List[str]): List of tools
|
|
621
638
|
metadata (Dict): Metadata
|
|
622
639
|
llm_config (LLMConfig): LLM configuration
|
|
623
640
|
embedding_config (EmbeddingConfig): Embedding configuration
|
|
@@ -627,11 +644,10 @@ class RESTClient(AbstractClient):
|
|
|
627
644
|
Returns:
|
|
628
645
|
agent_state (AgentState): State of the updated agent
|
|
629
646
|
"""
|
|
630
|
-
request =
|
|
631
|
-
id=agent_id,
|
|
647
|
+
request = UpdateAgent(
|
|
632
648
|
name=name,
|
|
633
649
|
system=system,
|
|
634
|
-
|
|
650
|
+
tool_ids=tool_ids,
|
|
635
651
|
tags=tags,
|
|
636
652
|
description=description,
|
|
637
653
|
metadata_=metadata,
|
|
@@ -742,7 +758,7 @@ class RESTClient(AbstractClient):
|
|
|
742
758
|
agents = [AgentState(**agent) for agent in response.json()]
|
|
743
759
|
if len(agents) == 0:
|
|
744
760
|
return None
|
|
745
|
-
agents = [agents[0]]
|
|
761
|
+
agents = [agents[0]] # TODO: @matt monkeypatched
|
|
746
762
|
assert len(agents) == 1, f"Multiple agents with the same name: {[(agents.name, agents.id) for agents in agents]}"
|
|
747
763
|
return agents[0].id
|
|
748
764
|
|
|
@@ -1052,7 +1068,7 @@ class RESTClient(AbstractClient):
|
|
|
1052
1068
|
raise ValueError(f"Failed to update block: {response.text}")
|
|
1053
1069
|
return Block(**response.json())
|
|
1054
1070
|
|
|
1055
|
-
def get_block(self, block_id: str) -> Block:
|
|
1071
|
+
def get_block(self, block_id: str) -> Optional[Block]:
|
|
1056
1072
|
response = requests.get(f"{self.base_url}/{self.api_prefix}/blocks/{block_id}", headers=self.headers)
|
|
1057
1073
|
if response.status_code == 404:
|
|
1058
1074
|
return None
|
|
@@ -1607,23 +1623,6 @@ class RESTClient(AbstractClient):
|
|
|
1607
1623
|
raise ValueError(f"Failed to get tool: {response.text}")
|
|
1608
1624
|
return Tool(**response.json())
|
|
1609
1625
|
|
|
1610
|
-
def get_tool_id(self, name: str) -> Optional[str]:
|
|
1611
|
-
"""
|
|
1612
|
-
Get a tool ID by its name.
|
|
1613
|
-
|
|
1614
|
-
Args:
|
|
1615
|
-
id (str): ID of the tool
|
|
1616
|
-
|
|
1617
|
-
Returns:
|
|
1618
|
-
tool (Tool): Tool
|
|
1619
|
-
"""
|
|
1620
|
-
response = requests.get(f"{self.base_url}/{self.api_prefix}/tools/name/{name}", headers=self.headers)
|
|
1621
|
-
if response.status_code == 404:
|
|
1622
|
-
return None
|
|
1623
|
-
elif response.status_code != 200:
|
|
1624
|
-
raise ValueError(f"Failed to get tool: {response.text}")
|
|
1625
|
-
return response.json()
|
|
1626
|
-
|
|
1627
1626
|
def set_default_llm_config(self, llm_config: LLMConfig):
|
|
1628
1627
|
"""
|
|
1629
1628
|
Set the default LLM configuration
|
|
@@ -2006,7 +2005,6 @@ class LocalClient(AbstractClient):
|
|
|
2006
2005
|
A local client for Letta, which corresponds to a single user.
|
|
2007
2006
|
|
|
2008
2007
|
Attributes:
|
|
2009
|
-
auto_save (bool): Whether to automatically save changes.
|
|
2010
2008
|
user_id (str): The user ID.
|
|
2011
2009
|
debug (bool): Whether to print debug information.
|
|
2012
2010
|
interface (QueuingInterface): The interface for the client.
|
|
@@ -2015,7 +2013,6 @@ class LocalClient(AbstractClient):
|
|
|
2015
2013
|
|
|
2016
2014
|
def __init__(
|
|
2017
2015
|
self,
|
|
2018
|
-
auto_save: bool = False,
|
|
2019
2016
|
user_id: Optional[str] = None,
|
|
2020
2017
|
org_id: Optional[str] = None,
|
|
2021
2018
|
debug: bool = False,
|
|
@@ -2026,11 +2023,9 @@ class LocalClient(AbstractClient):
|
|
|
2026
2023
|
Initializes a new instance of Client class.
|
|
2027
2024
|
|
|
2028
2025
|
Args:
|
|
2029
|
-
auto_save (bool): Whether to automatically save changes.
|
|
2030
2026
|
user_id (str): The user ID.
|
|
2031
2027
|
debug (bool): Whether to print debug information.
|
|
2032
2028
|
"""
|
|
2033
|
-
self.auto_save = auto_save
|
|
2034
2029
|
|
|
2035
2030
|
# set logging levels
|
|
2036
2031
|
letta.utils.DEBUG = debug
|
|
@@ -2056,14 +2051,14 @@ class LocalClient(AbstractClient):
|
|
|
2056
2051
|
# get default user
|
|
2057
2052
|
self.user_id = self.server.user_manager.DEFAULT_USER_ID
|
|
2058
2053
|
|
|
2059
|
-
self.user = self.server.get_user_or_default(self.user_id)
|
|
2054
|
+
self.user = self.server.user_manager.get_user_or_default(self.user_id)
|
|
2060
2055
|
self.organization = self.server.get_organization_or_default(self.org_id)
|
|
2061
2056
|
|
|
2062
2057
|
# agents
|
|
2063
2058
|
def list_agents(self, tags: Optional[List[str]] = None) -> List[AgentState]:
|
|
2064
2059
|
self.interface.clear()
|
|
2065
2060
|
|
|
2066
|
-
return self.server.list_agents(
|
|
2061
|
+
return self.server.agent_manager.list_agents(actor=self.user, tags=tags)
|
|
2067
2062
|
|
|
2068
2063
|
def agent_exists(self, agent_id: Optional[str] = None, agent_name: Optional[str] = None) -> bool:
|
|
2069
2064
|
"""
|
|
@@ -2097,6 +2092,7 @@ class LocalClient(AbstractClient):
|
|
|
2097
2092
|
llm_config: LLMConfig = None,
|
|
2098
2093
|
# memory
|
|
2099
2094
|
memory: Memory = ChatMemory(human=get_human_text(DEFAULT_HUMAN), persona=get_persona_text(DEFAULT_PERSONA)),
|
|
2095
|
+
block_ids: Optional[List[str]] = None,
|
|
2100
2096
|
# TODO: change to this when we are ready to migrate all the tests/examples (matches the REST API)
|
|
2101
2097
|
# memory_blocks=[
|
|
2102
2098
|
# {"label": "human", "value": get_human_text(DEFAULT_HUMAN), "limit": 5000},
|
|
@@ -2105,7 +2101,7 @@ class LocalClient(AbstractClient):
|
|
|
2105
2101
|
# system
|
|
2106
2102
|
system: Optional[str] = None,
|
|
2107
2103
|
# tools
|
|
2108
|
-
|
|
2104
|
+
tool_ids: Optional[List[str]] = None,
|
|
2109
2105
|
tool_rules: Optional[List[BaseToolRule]] = None,
|
|
2110
2106
|
include_base_tools: Optional[bool] = True,
|
|
2111
2107
|
# metadata
|
|
@@ -2132,55 +2128,53 @@ class LocalClient(AbstractClient):
|
|
|
2132
2128
|
Returns:
|
|
2133
2129
|
agent_state (AgentState): State of the created agent
|
|
2134
2130
|
"""
|
|
2135
|
-
|
|
2136
|
-
if name and self.agent_exists(agent_name=name):
|
|
2137
|
-
raise ValueError(f"Agent with name {name} already exists (user_id={self.user_id})")
|
|
2138
|
-
|
|
2139
2131
|
# construct list of tools
|
|
2132
|
+
tool_ids = tool_ids or []
|
|
2140
2133
|
tool_names = []
|
|
2141
|
-
if tools:
|
|
2142
|
-
tool_names += tools
|
|
2143
2134
|
if include_base_tools:
|
|
2144
2135
|
tool_names += BASE_TOOLS
|
|
2145
2136
|
tool_names += BASE_MEMORY_TOOLS
|
|
2137
|
+
tool_ids += [self.server.tool_manager.get_tool_by_name(tool_name=name, actor=self.user).id for name in tool_names]
|
|
2146
2138
|
|
|
2147
2139
|
# check if default configs are provided
|
|
2148
2140
|
assert embedding_config or self._default_embedding_config, f"Embedding config must be provided"
|
|
2149
2141
|
assert llm_config or self._default_llm_config, f"LLM config must be provided"
|
|
2150
2142
|
|
|
2143
|
+
# TODO: This should not happen here, we need to have clear separation between create/add blocks
|
|
2144
|
+
for block in memory.get_blocks():
|
|
2145
|
+
self.server.block_manager.create_or_update_block(block, actor=self.user)
|
|
2146
|
+
|
|
2147
|
+
# Also get any existing block_ids passed in
|
|
2148
|
+
block_ids = block_ids or []
|
|
2149
|
+
|
|
2151
2150
|
# create agent
|
|
2151
|
+
# Create the base parameters
|
|
2152
|
+
create_params = {
|
|
2153
|
+
"description": description,
|
|
2154
|
+
"metadata_": metadata,
|
|
2155
|
+
"memory_blocks": [],
|
|
2156
|
+
"block_ids": [b.id for b in memory.get_blocks()] + block_ids,
|
|
2157
|
+
"tool_ids": tool_ids,
|
|
2158
|
+
"tool_rules": tool_rules,
|
|
2159
|
+
"system": system,
|
|
2160
|
+
"agent_type": agent_type,
|
|
2161
|
+
"llm_config": llm_config if llm_config else self._default_llm_config,
|
|
2162
|
+
"embedding_config": embedding_config if embedding_config else self._default_embedding_config,
|
|
2163
|
+
"initial_message_sequence": initial_message_sequence,
|
|
2164
|
+
"tags": tags,
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
# Only add name if it's not None
|
|
2168
|
+
if name is not None:
|
|
2169
|
+
create_params["name"] = name
|
|
2170
|
+
|
|
2152
2171
|
agent_state = self.server.create_agent(
|
|
2153
|
-
CreateAgent(
|
|
2154
|
-
name=name,
|
|
2155
|
-
description=description,
|
|
2156
|
-
metadata_=metadata,
|
|
2157
|
-
# memory=memory,
|
|
2158
|
-
memory_blocks=[],
|
|
2159
|
-
# memory_blocks = memory.get_blocks(),
|
|
2160
|
-
# memory_tools=memory_tools,
|
|
2161
|
-
tools=tool_names,
|
|
2162
|
-
tool_rules=tool_rules,
|
|
2163
|
-
system=system,
|
|
2164
|
-
agent_type=agent_type,
|
|
2165
|
-
llm_config=llm_config if llm_config else self._default_llm_config,
|
|
2166
|
-
embedding_config=embedding_config if embedding_config else self._default_embedding_config,
|
|
2167
|
-
initial_message_sequence=initial_message_sequence,
|
|
2168
|
-
tags=tags,
|
|
2169
|
-
),
|
|
2172
|
+
CreateAgent(**create_params),
|
|
2170
2173
|
actor=self.user,
|
|
2171
2174
|
)
|
|
2172
2175
|
|
|
2173
|
-
# TODO: remove when we fully migrate to block creation CreateAgent model
|
|
2174
|
-
# Link additional blocks to the agent (block ids created on the client)
|
|
2175
|
-
# This needs to happen since the create agent does not allow passing in blocks which have already been persisted and have an ID
|
|
2176
|
-
# So we create the agent and then link the blocks afterwards
|
|
2177
|
-
user = self.server.get_user_or_default(self.user_id)
|
|
2178
|
-
for block in memory.get_blocks():
|
|
2179
|
-
self.server.block_manager.create_or_update_block(block, actor=user)
|
|
2180
|
-
self.server.link_block_to_agent_memory(user_id=self.user_id, agent_id=agent_state.id, block_id=block.id)
|
|
2181
|
-
|
|
2182
2176
|
# TODO: get full agent state
|
|
2183
|
-
return self.server.
|
|
2177
|
+
return self.server.agent_manager.get_agent_by_id(agent_state.id, actor=self.user)
|
|
2184
2178
|
|
|
2185
2179
|
def update_message(
|
|
2186
2180
|
self,
|
|
@@ -2202,6 +2196,7 @@ class LocalClient(AbstractClient):
|
|
|
2202
2196
|
tool_calls=tool_calls,
|
|
2203
2197
|
tool_call_id=tool_call_id,
|
|
2204
2198
|
),
|
|
2199
|
+
actor=self.user,
|
|
2205
2200
|
)
|
|
2206
2201
|
return message
|
|
2207
2202
|
|
|
@@ -2211,7 +2206,7 @@ class LocalClient(AbstractClient):
|
|
|
2211
2206
|
name: Optional[str] = None,
|
|
2212
2207
|
description: Optional[str] = None,
|
|
2213
2208
|
system: Optional[str] = None,
|
|
2214
|
-
|
|
2209
|
+
tool_ids: Optional[List[str]] = None,
|
|
2215
2210
|
tags: Optional[List[str]] = None,
|
|
2216
2211
|
metadata: Optional[Dict] = None,
|
|
2217
2212
|
llm_config: Optional[LLMConfig] = None,
|
|
@@ -2239,11 +2234,11 @@ class LocalClient(AbstractClient):
|
|
|
2239
2234
|
# TODO: add the abilitty to reset linked block_ids
|
|
2240
2235
|
self.interface.clear()
|
|
2241
2236
|
agent_state = self.server.update_agent(
|
|
2242
|
-
|
|
2243
|
-
|
|
2237
|
+
agent_id,
|
|
2238
|
+
UpdateAgent(
|
|
2244
2239
|
name=name,
|
|
2245
2240
|
system=system,
|
|
2246
|
-
|
|
2241
|
+
tool_ids=tool_ids,
|
|
2247
2242
|
tags=tags,
|
|
2248
2243
|
description=description,
|
|
2249
2244
|
metadata_=metadata,
|
|
@@ -2315,7 +2310,7 @@ class LocalClient(AbstractClient):
|
|
|
2315
2310
|
Args:
|
|
2316
2311
|
agent_id (str): ID of the agent to delete
|
|
2317
2312
|
"""
|
|
2318
|
-
self.server.delete_agent(
|
|
2313
|
+
self.server.agent_manager.delete_agent(agent_id=agent_id, actor=self.user)
|
|
2319
2314
|
|
|
2320
2315
|
def get_agent_by_name(self, agent_name: str) -> AgentState:
|
|
2321
2316
|
"""
|
|
@@ -2328,7 +2323,7 @@ class LocalClient(AbstractClient):
|
|
|
2328
2323
|
agent_state (AgentState): State of the agent
|
|
2329
2324
|
"""
|
|
2330
2325
|
self.interface.clear()
|
|
2331
|
-
return self.server.
|
|
2326
|
+
return self.server.agent_manager.get_agent_by_name(agent_name=agent_name, actor=self.user)
|
|
2332
2327
|
|
|
2333
2328
|
def get_agent(self, agent_id: str) -> AgentState:
|
|
2334
2329
|
"""
|
|
@@ -2340,9 +2335,8 @@ class LocalClient(AbstractClient):
|
|
|
2340
2335
|
Returns:
|
|
2341
2336
|
agent_state (AgentState): State representation of the agent
|
|
2342
2337
|
"""
|
|
2343
|
-
# TODO: include agent_name
|
|
2344
2338
|
self.interface.clear()
|
|
2345
|
-
return self.server.
|
|
2339
|
+
return self.server.agent_manager.get_agent_by_id(agent_id=agent_id, actor=self.user)
|
|
2346
2340
|
|
|
2347
2341
|
def get_agent_id(self, agent_name: str) -> Optional[str]:
|
|
2348
2342
|
"""
|
|
@@ -2357,7 +2351,12 @@ class LocalClient(AbstractClient):
|
|
|
2357
2351
|
|
|
2358
2352
|
self.interface.clear()
|
|
2359
2353
|
assert agent_name, f"Agent name must be provided"
|
|
2360
|
-
|
|
2354
|
+
|
|
2355
|
+
# TODO: Refactor this futher to not have downstream users expect Optionals - this should just error
|
|
2356
|
+
try:
|
|
2357
|
+
return self.server.agent_manager.get_agent_by_name(agent_name=agent_name, actor=self.user).id
|
|
2358
|
+
except NoResultFound:
|
|
2359
|
+
return None
|
|
2361
2360
|
|
|
2362
2361
|
# memory
|
|
2363
2362
|
def get_in_context_memory(self, agent_id: str) -> Memory:
|
|
@@ -2370,7 +2369,7 @@ class LocalClient(AbstractClient):
|
|
|
2370
2369
|
Returns:
|
|
2371
2370
|
memory (Memory): In-context memory of the agent
|
|
2372
2371
|
"""
|
|
2373
|
-
memory = self.server.get_agent_memory(agent_id=agent_id)
|
|
2372
|
+
memory = self.server.get_agent_memory(agent_id=agent_id, actor=self.user)
|
|
2374
2373
|
return memory
|
|
2375
2374
|
|
|
2376
2375
|
def get_core_memory(self, agent_id: str) -> Memory:
|
|
@@ -2388,7 +2387,7 @@ class LocalClient(AbstractClient):
|
|
|
2388
2387
|
|
|
2389
2388
|
"""
|
|
2390
2389
|
# TODO: implement this (not sure what it should look like)
|
|
2391
|
-
memory = self.server.update_agent_core_memory(
|
|
2390
|
+
memory = self.server.update_agent_core_memory(agent_id=agent_id, label=section, value=value, actor=self.user)
|
|
2392
2391
|
return memory
|
|
2393
2392
|
|
|
2394
2393
|
def get_archival_memory_summary(self, agent_id: str) -> ArchivalMemorySummary:
|
|
@@ -2402,7 +2401,7 @@ class LocalClient(AbstractClient):
|
|
|
2402
2401
|
summary (ArchivalMemorySummary): Summary of the archival memory
|
|
2403
2402
|
|
|
2404
2403
|
"""
|
|
2405
|
-
return self.server.get_archival_memory_summary(agent_id=agent_id)
|
|
2404
|
+
return self.server.get_archival_memory_summary(agent_id=agent_id, actor=self.user)
|
|
2406
2405
|
|
|
2407
2406
|
def get_recall_memory_summary(self, agent_id: str) -> RecallMemorySummary:
|
|
2408
2407
|
"""
|
|
@@ -2414,7 +2413,7 @@ class LocalClient(AbstractClient):
|
|
|
2414
2413
|
Returns:
|
|
2415
2414
|
summary (RecallMemorySummary): Summary of the recall memory
|
|
2416
2415
|
"""
|
|
2417
|
-
return self.server.get_recall_memory_summary(agent_id=agent_id)
|
|
2416
|
+
return self.server.get_recall_memory_summary(agent_id=agent_id, actor=self.user)
|
|
2418
2417
|
|
|
2419
2418
|
def get_in_context_messages(self, agent_id: str) -> List[Message]:
|
|
2420
2419
|
"""
|
|
@@ -2426,7 +2425,7 @@ class LocalClient(AbstractClient):
|
|
|
2426
2425
|
Returns:
|
|
2427
2426
|
messages (List[Message]): List of in-context messages
|
|
2428
2427
|
"""
|
|
2429
|
-
return self.server.get_in_context_messages(agent_id=agent_id)
|
|
2428
|
+
return self.server.get_in_context_messages(agent_id=agent_id, actor=self.user)
|
|
2430
2429
|
|
|
2431
2430
|
# agent interactions
|
|
2432
2431
|
|
|
@@ -2446,11 +2445,7 @@ class LocalClient(AbstractClient):
|
|
|
2446
2445
|
response (LettaResponse): Response from the agent
|
|
2447
2446
|
"""
|
|
2448
2447
|
self.interface.clear()
|
|
2449
|
-
usage = self.server.send_messages(
|
|
2450
|
-
|
|
2451
|
-
# auto-save
|
|
2452
|
-
if self.auto_save:
|
|
2453
|
-
self.save()
|
|
2448
|
+
usage = self.server.send_messages(actor=self.user, agent_id=agent_id, messages=messages)
|
|
2454
2449
|
|
|
2455
2450
|
# format messages
|
|
2456
2451
|
return LettaResponse(messages=messages, usage=usage)
|
|
@@ -2490,15 +2485,11 @@ class LocalClient(AbstractClient):
|
|
|
2490
2485
|
self.interface.clear()
|
|
2491
2486
|
|
|
2492
2487
|
usage = self.server.send_messages(
|
|
2493
|
-
|
|
2488
|
+
actor=self.user,
|
|
2494
2489
|
agent_id=agent_id,
|
|
2495
2490
|
messages=[MessageCreate(role=MessageRole(role), text=message, name=name)],
|
|
2496
2491
|
)
|
|
2497
2492
|
|
|
2498
|
-
# auto-save
|
|
2499
|
-
if self.auto_save:
|
|
2500
|
-
self.save()
|
|
2501
|
-
|
|
2502
2493
|
## TODO: need to make sure date/timestamp is propely passed
|
|
2503
2494
|
## TODO: update self.interface.to_list() to return actual Message objects
|
|
2504
2495
|
## here, the message objects will have faulty created_by timestamps
|
|
@@ -2547,16 +2538,9 @@ class LocalClient(AbstractClient):
|
|
|
2547
2538
|
self.interface.clear()
|
|
2548
2539
|
usage = self.server.run_command(user_id=self.user_id, agent_id=agent_id, command=command)
|
|
2549
2540
|
|
|
2550
|
-
# auto-save
|
|
2551
|
-
if self.auto_save:
|
|
2552
|
-
self.save()
|
|
2553
|
-
|
|
2554
2541
|
# NOTE: messages/usage may be empty, depending on the command
|
|
2555
2542
|
return LettaResponse(messages=self.interface.to_list(), usage=usage)
|
|
2556
2543
|
|
|
2557
|
-
def save(self):
|
|
2558
|
-
self.server.save_agents()
|
|
2559
|
-
|
|
2560
2544
|
# archival memory
|
|
2561
2545
|
|
|
2562
2546
|
# humans / personas
|
|
@@ -3036,7 +3020,7 @@ class LocalClient(AbstractClient):
|
|
|
3036
3020
|
Returns:
|
|
3037
3021
|
sources (List[Source]): List of sources
|
|
3038
3022
|
"""
|
|
3039
|
-
return self.server.list_attached_sources(agent_id=agent_id)
|
|
3023
|
+
return self.server.agent_manager.list_attached_sources(agent_id=agent_id, actor=self.user)
|
|
3040
3024
|
|
|
3041
3025
|
def list_files_from_source(self, source_id: str, limit: int = 1000, cursor: Optional[str] = None) -> List[FileMetadata]:
|
|
3042
3026
|
"""
|
|
@@ -3080,7 +3064,7 @@ class LocalClient(AbstractClient):
|
|
|
3080
3064
|
Returns:
|
|
3081
3065
|
passages (List[Passage]): List of inserted passages
|
|
3082
3066
|
"""
|
|
3083
|
-
return self.server.insert_archival_memory(
|
|
3067
|
+
return self.server.insert_archival_memory(agent_id=agent_id, memory_contents=memory, actor=self.user)
|
|
3084
3068
|
|
|
3085
3069
|
def delete_archival_memory(self, agent_id: str, memory_id: str):
|
|
3086
3070
|
"""
|
|
@@ -3090,7 +3074,7 @@ class LocalClient(AbstractClient):
|
|
|
3090
3074
|
agent_id (str): ID of the agent
|
|
3091
3075
|
memory_id (str): ID of the memory
|
|
3092
3076
|
"""
|
|
3093
|
-
self.server.delete_archival_memory(
|
|
3077
|
+
self.server.delete_archival_memory(agent_id=agent_id, memory_id=memory_id, actor=self.user)
|
|
3094
3078
|
|
|
3095
3079
|
def get_archival_memory(
|
|
3096
3080
|
self, agent_id: str, before: Optional[str] = None, after: Optional[str] = None, limit: Optional[int] = 1000
|
|
@@ -3349,8 +3333,8 @@ class LocalClient(AbstractClient):
|
|
|
3349
3333
|
block_req = Block(**create_block.model_dump())
|
|
3350
3334
|
block = self.server.block_manager.create_or_update_block(actor=self.user, block=block_req)
|
|
3351
3335
|
# Link the block to the agent
|
|
3352
|
-
|
|
3353
|
-
return
|
|
3336
|
+
agent = self.server.agent_manager.attach_block(agent_id=agent_id, block_id=block.id, actor=self.user)
|
|
3337
|
+
return agent.memory
|
|
3354
3338
|
|
|
3355
3339
|
def link_agent_memory_block(self, agent_id: str, block_id: str) -> Memory:
|
|
3356
3340
|
"""
|
|
@@ -3363,7 +3347,7 @@ class LocalClient(AbstractClient):
|
|
|
3363
3347
|
Returns:
|
|
3364
3348
|
memory (Memory): The updated memory
|
|
3365
3349
|
"""
|
|
3366
|
-
return self.server.
|
|
3350
|
+
return self.server.agent_manager.attach_block(agent_id=agent_id, block_id=block_id, actor=self.user)
|
|
3367
3351
|
|
|
3368
3352
|
def remove_agent_memory_block(self, agent_id: str, block_label: str) -> Memory:
|
|
3369
3353
|
"""
|
|
@@ -3376,7 +3360,7 @@ class LocalClient(AbstractClient):
|
|
|
3376
3360
|
Returns:
|
|
3377
3361
|
memory (Memory): The updated memory
|
|
3378
3362
|
"""
|
|
3379
|
-
return self.server.
|
|
3363
|
+
return self.server.agent_manager.detach_block_with_label(agent_id=agent_id, block_label=block_label, actor=self.user)
|
|
3380
3364
|
|
|
3381
3365
|
def get_agent_memory_blocks(self, agent_id: str) -> List[Block]:
|
|
3382
3366
|
"""
|
|
@@ -3388,8 +3372,8 @@ class LocalClient(AbstractClient):
|
|
|
3388
3372
|
Returns:
|
|
3389
3373
|
blocks (List[Block]): The blocks in the agent's core memory
|
|
3390
3374
|
"""
|
|
3391
|
-
|
|
3392
|
-
return
|
|
3375
|
+
agent = self.server.agent_manager.get_agent_by_id(agent_id=agent_id, actor=self.user)
|
|
3376
|
+
return agent.memory.blocks
|
|
3393
3377
|
|
|
3394
3378
|
def get_agent_memory_block(self, agent_id: str, label: str) -> Block:
|
|
3395
3379
|
"""
|
|
@@ -3402,8 +3386,7 @@ class LocalClient(AbstractClient):
|
|
|
3402
3386
|
Returns:
|
|
3403
3387
|
block (Block): The block corresponding to the label
|
|
3404
3388
|
"""
|
|
3405
|
-
|
|
3406
|
-
return self.server.block_manager.get_block_by_id(block_id, actor=self.user)
|
|
3389
|
+
return self.server.agent_manager.get_block_with_label(agent_id=agent_id, block_label=label, actor=self.user)
|
|
3407
3390
|
|
|
3408
3391
|
def update_agent_memory_block(
|
|
3409
3392
|
self,
|