@elizaos/python 2.0.0-alpha.10
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.
- package/LICENSE +26 -0
- package/README.md +239 -0
- package/elizaos/__init__.py +280 -0
- package/elizaos/action_docs.py +149 -0
- package/elizaos/advanced_capabilities/__init__.py +85 -0
- package/elizaos/advanced_capabilities/actions/__init__.py +54 -0
- package/elizaos/advanced_capabilities/actions/add_contact.py +139 -0
- package/elizaos/advanced_capabilities/actions/follow_room.py +151 -0
- package/elizaos/advanced_capabilities/actions/image_generation.py +148 -0
- package/elizaos/advanced_capabilities/actions/mute_room.py +164 -0
- package/elizaos/advanced_capabilities/actions/remove_contact.py +145 -0
- package/elizaos/advanced_capabilities/actions/roles.py +207 -0
- package/elizaos/advanced_capabilities/actions/schedule_follow_up.py +154 -0
- package/elizaos/advanced_capabilities/actions/search_contacts.py +145 -0
- package/elizaos/advanced_capabilities/actions/send_message.py +187 -0
- package/elizaos/advanced_capabilities/actions/settings.py +151 -0
- package/elizaos/advanced_capabilities/actions/unfollow_room.py +164 -0
- package/elizaos/advanced_capabilities/actions/unmute_room.py +164 -0
- package/elizaos/advanced_capabilities/actions/update_contact.py +164 -0
- package/elizaos/advanced_capabilities/actions/update_entity.py +161 -0
- package/elizaos/advanced_capabilities/evaluators/__init__.py +18 -0
- package/elizaos/advanced_capabilities/evaluators/reflection.py +134 -0
- package/elizaos/advanced_capabilities/evaluators/relationship_extraction.py +203 -0
- package/elizaos/advanced_capabilities/providers/__init__.py +36 -0
- package/elizaos/advanced_capabilities/providers/agent_settings.py +60 -0
- package/elizaos/advanced_capabilities/providers/contacts.py +77 -0
- package/elizaos/advanced_capabilities/providers/facts.py +82 -0
- package/elizaos/advanced_capabilities/providers/follow_ups.py +113 -0
- package/elizaos/advanced_capabilities/providers/knowledge.py +83 -0
- package/elizaos/advanced_capabilities/providers/relationships.py +112 -0
- package/elizaos/advanced_capabilities/providers/roles.py +97 -0
- package/elizaos/advanced_capabilities/providers/settings.py +51 -0
- package/elizaos/advanced_capabilities/services/__init__.py +18 -0
- package/elizaos/advanced_capabilities/services/follow_up.py +138 -0
- package/elizaos/advanced_capabilities/services/rolodex.py +244 -0
- package/elizaos/advanced_memory/__init__.py +3 -0
- package/elizaos/advanced_memory/evaluators.py +97 -0
- package/elizaos/advanced_memory/memory_service.py +556 -0
- package/elizaos/advanced_memory/plugin.py +30 -0
- package/elizaos/advanced_memory/prompts.py +12 -0
- package/elizaos/advanced_memory/providers.py +90 -0
- package/elizaos/advanced_memory/types.py +65 -0
- package/elizaos/advanced_planning/__init__.py +10 -0
- package/elizaos/advanced_planning/actions.py +145 -0
- package/elizaos/advanced_planning/message_classifier.py +127 -0
- package/elizaos/advanced_planning/planning_service.py +712 -0
- package/elizaos/advanced_planning/plugin.py +40 -0
- package/elizaos/advanced_planning/prompts.py +4 -0
- package/elizaos/basic_capabilities/__init__.py +66 -0
- package/elizaos/basic_capabilities/actions/__init__.py +24 -0
- package/elizaos/basic_capabilities/actions/choice.py +140 -0
- package/elizaos/basic_capabilities/actions/ignore.py +66 -0
- package/elizaos/basic_capabilities/actions/none.py +56 -0
- package/elizaos/basic_capabilities/actions/reply.py +120 -0
- package/elizaos/basic_capabilities/providers/__init__.py +54 -0
- package/elizaos/basic_capabilities/providers/action_state.py +113 -0
- package/elizaos/basic_capabilities/providers/actions.py +263 -0
- package/elizaos/basic_capabilities/providers/attachments.py +76 -0
- package/elizaos/basic_capabilities/providers/capabilities.py +62 -0
- package/elizaos/basic_capabilities/providers/character.py +113 -0
- package/elizaos/basic_capabilities/providers/choice.py +73 -0
- package/elizaos/basic_capabilities/providers/context_bench.py +44 -0
- package/elizaos/basic_capabilities/providers/current_time.py +58 -0
- package/elizaos/basic_capabilities/providers/entities.py +99 -0
- package/elizaos/basic_capabilities/providers/evaluators.py +54 -0
- package/elizaos/basic_capabilities/providers/providers_list.py +55 -0
- package/elizaos/basic_capabilities/providers/recent_messages.py +85 -0
- package/elizaos/basic_capabilities/providers/time.py +45 -0
- package/elizaos/basic_capabilities/providers/world.py +93 -0
- package/elizaos/basic_capabilities/services/__init__.py +18 -0
- package/elizaos/basic_capabilities/services/embedding.py +122 -0
- package/elizaos/basic_capabilities/services/task.py +178 -0
- package/elizaos/bootstrap/__init__.py +12 -0
- package/elizaos/bootstrap/actions/__init__.py +68 -0
- package/elizaos/bootstrap/actions/add_contact.py +149 -0
- package/elizaos/bootstrap/actions/choice.py +147 -0
- package/elizaos/bootstrap/actions/follow_room.py +151 -0
- package/elizaos/bootstrap/actions/ignore.py +80 -0
- package/elizaos/bootstrap/actions/image_generation.py +135 -0
- package/elizaos/bootstrap/actions/mute_room.py +151 -0
- package/elizaos/bootstrap/actions/none.py +71 -0
- package/elizaos/bootstrap/actions/remove_contact.py +159 -0
- package/elizaos/bootstrap/actions/reply.py +140 -0
- package/elizaos/bootstrap/actions/roles.py +193 -0
- package/elizaos/bootstrap/actions/schedule_follow_up.py +164 -0
- package/elizaos/bootstrap/actions/search_contacts.py +159 -0
- package/elizaos/bootstrap/actions/send_message.py +173 -0
- package/elizaos/bootstrap/actions/settings.py +165 -0
- package/elizaos/bootstrap/actions/unfollow_room.py +151 -0
- package/elizaos/bootstrap/actions/unmute_room.py +151 -0
- package/elizaos/bootstrap/actions/update_contact.py +178 -0
- package/elizaos/bootstrap/actions/update_entity.py +175 -0
- package/elizaos/bootstrap/autonomy/__init__.py +18 -0
- package/elizaos/bootstrap/autonomy/action.py +197 -0
- package/elizaos/bootstrap/autonomy/providers.py +165 -0
- package/elizaos/bootstrap/autonomy/routes.py +171 -0
- package/elizaos/bootstrap/autonomy/service.py +562 -0
- package/elizaos/bootstrap/autonomy/types.py +18 -0
- package/elizaos/bootstrap/evaluators/__init__.py +19 -0
- package/elizaos/bootstrap/evaluators/reflection.py +118 -0
- package/elizaos/bootstrap/evaluators/relationship_extraction.py +192 -0
- package/elizaos/bootstrap/plugin.py +140 -0
- package/elizaos/bootstrap/providers/__init__.py +80 -0
- package/elizaos/bootstrap/providers/action_state.py +71 -0
- package/elizaos/bootstrap/providers/actions.py +256 -0
- package/elizaos/bootstrap/providers/agent_settings.py +63 -0
- package/elizaos/bootstrap/providers/attachments.py +76 -0
- package/elizaos/bootstrap/providers/capabilities.py +66 -0
- package/elizaos/bootstrap/providers/character.py +128 -0
- package/elizaos/bootstrap/providers/choice.py +77 -0
- package/elizaos/bootstrap/providers/contacts.py +78 -0
- package/elizaos/bootstrap/providers/context_bench.py +49 -0
- package/elizaos/bootstrap/providers/current_time.py +56 -0
- package/elizaos/bootstrap/providers/entities.py +99 -0
- package/elizaos/bootstrap/providers/evaluators.py +58 -0
- package/elizaos/bootstrap/providers/facts.py +86 -0
- package/elizaos/bootstrap/providers/follow_ups.py +116 -0
- package/elizaos/bootstrap/providers/knowledge.py +73 -0
- package/elizaos/bootstrap/providers/providers_list.py +59 -0
- package/elizaos/bootstrap/providers/recent_messages.py +85 -0
- package/elizaos/bootstrap/providers/relationships.py +106 -0
- package/elizaos/bootstrap/providers/roles.py +95 -0
- package/elizaos/bootstrap/providers/settings.py +55 -0
- package/elizaos/bootstrap/providers/time.py +45 -0
- package/elizaos/bootstrap/providers/world.py +97 -0
- package/elizaos/bootstrap/services/__init__.py +26 -0
- package/elizaos/bootstrap/services/embedding.py +122 -0
- package/elizaos/bootstrap/services/follow_up.py +138 -0
- package/elizaos/bootstrap/services/rolodex.py +244 -0
- package/elizaos/bootstrap/services/task.py +585 -0
- package/elizaos/bootstrap/types.py +54 -0
- package/elizaos/bootstrap/utils/__init__.py +7 -0
- package/elizaos/bootstrap/utils/xml.py +69 -0
- package/elizaos/character.py +149 -0
- package/elizaos/logger.py +179 -0
- package/elizaos/media/__init__.py +45 -0
- package/elizaos/media/mime.py +315 -0
- package/elizaos/media/search.py +161 -0
- package/elizaos/media/tests/__init__.py +1 -0
- package/elizaos/media/tests/test_mime.py +117 -0
- package/elizaos/media/tests/test_search.py +156 -0
- package/elizaos/plugin.py +191 -0
- package/elizaos/prompts.py +1071 -0
- package/elizaos/py.typed +0 -0
- package/elizaos/runtime.py +2572 -0
- package/elizaos/services/__init__.py +49 -0
- package/elizaos/services/hook_service.py +511 -0
- package/elizaos/services/message_service.py +1248 -0
- package/elizaos/settings.py +182 -0
- package/elizaos/streaming_context.py +159 -0
- package/elizaos/trajectory_context.py +18 -0
- package/elizaos/types/__init__.py +512 -0
- package/elizaos/types/agent.py +31 -0
- package/elizaos/types/components.py +208 -0
- package/elizaos/types/database.py +64 -0
- package/elizaos/types/environment.py +46 -0
- package/elizaos/types/events.py +47 -0
- package/elizaos/types/memory.py +45 -0
- package/elizaos/types/model.py +393 -0
- package/elizaos/types/plugin.py +188 -0
- package/elizaos/types/primitives.py +100 -0
- package/elizaos/types/runtime.py +460 -0
- package/elizaos/types/service.py +113 -0
- package/elizaos/types/service_interfaces.py +244 -0
- package/elizaos/types/state.py +188 -0
- package/elizaos/types/task.py +29 -0
- package/elizaos/utils/__init__.py +108 -0
- package/elizaos/utils/spec_examples.py +48 -0
- package/elizaos/utils/streaming.py +426 -0
- package/elizaos_atropos_shared/__init__.py +1 -0
- package/elizaos_atropos_shared/canonical_eliza.py +282 -0
- package/package.json +19 -0
- package/pyproject.toml +143 -0
- package/requirements-dev.in +11 -0
- package/requirements-dev.lock +134 -0
- package/requirements.in +9 -0
- package/requirements.lock +64 -0
- package/tests/__init__.py +0 -0
- package/tests/test_action_parameters.py +154 -0
- package/tests/test_actions_provider_examples.py +39 -0
- package/tests/test_advanced_memory_behavior.py +96 -0
- package/tests/test_advanced_memory_flag.py +30 -0
- package/tests/test_advanced_planning_behavior.py +225 -0
- package/tests/test_advanced_planning_flag.py +26 -0
- package/tests/test_autonomy.py +445 -0
- package/tests/test_bootstrap_initialize.py +37 -0
- package/tests/test_character.py +163 -0
- package/tests/test_character_provider.py +231 -0
- package/tests/test_dynamic_prompt_exec.py +561 -0
- package/tests/test_logger_redaction.py +43 -0
- package/tests/test_plugin.py +117 -0
- package/tests/test_runtime.py +422 -0
- package/tests/test_salt_production_enforcement.py +22 -0
- package/tests/test_settings_crypto.py +118 -0
- package/tests/test_streaming.py +295 -0
- package/tests/test_types.py +221 -0
- package/tests/test_uuid_parity.py +46 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
from uuid import UUID
|
|
7
|
+
|
|
8
|
+
from elizaos.generated.spec_helpers import require_action_spec
|
|
9
|
+
from elizaos.types import Action, ActionExample, ActionResult, Content
|
|
10
|
+
from elizaos.types.memory import Memory as MemoryType
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from elizaos.types import HandlerCallback, HandlerOptions, IAgentRuntime, Memory, State
|
|
14
|
+
|
|
15
|
+
# Get text content from centralized specs
|
|
16
|
+
_spec = require_action_spec("SEND_MESSAGE")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _convert_spec_examples() -> list[list[ActionExample]]:
|
|
20
|
+
"""Convert spec examples to ActionExample format."""
|
|
21
|
+
spec_examples = _spec.get("examples", [])
|
|
22
|
+
if spec_examples:
|
|
23
|
+
return [
|
|
24
|
+
[
|
|
25
|
+
ActionExample(
|
|
26
|
+
name=msg.get("name", ""),
|
|
27
|
+
content=Content(
|
|
28
|
+
text=msg.get("content", {}).get("text", ""),
|
|
29
|
+
actions=msg.get("content", {}).get("actions"),
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
for msg in example
|
|
33
|
+
]
|
|
34
|
+
for example in spec_examples
|
|
35
|
+
]
|
|
36
|
+
return []
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class SendMessageAction:
|
|
41
|
+
name: str = _spec["name"]
|
|
42
|
+
similes: list[str] = field(default_factory=lambda: list(_spec.get("similes", [])))
|
|
43
|
+
description: str = _spec["description"]
|
|
44
|
+
|
|
45
|
+
async def validate(
|
|
46
|
+
self, runtime: IAgentRuntime, message: Memory, _state: State | None = None
|
|
47
|
+
) -> bool:
|
|
48
|
+
if message.content and message.content.target:
|
|
49
|
+
return True
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
async def handler(
|
|
53
|
+
self,
|
|
54
|
+
runtime: IAgentRuntime,
|
|
55
|
+
message: Memory,
|
|
56
|
+
state: State | None = None,
|
|
57
|
+
options: HandlerOptions | None = None,
|
|
58
|
+
callback: HandlerCallback | None = None,
|
|
59
|
+
responses: list[Memory] | None = None,
|
|
60
|
+
) -> ActionResult:
|
|
61
|
+
message_text = ""
|
|
62
|
+
if responses and responses[0].content:
|
|
63
|
+
message_text = str(responses[0].content.text or "")
|
|
64
|
+
|
|
65
|
+
if not message_text:
|
|
66
|
+
return ActionResult(
|
|
67
|
+
text="No message content to send",
|
|
68
|
+
values={"success": False, "error": "no_content"},
|
|
69
|
+
data={"actionName": "SEND_MESSAGE"},
|
|
70
|
+
success=False,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
target_room_id = message.room_id
|
|
74
|
+
target_entity_id: UUID | None = None
|
|
75
|
+
|
|
76
|
+
if message.content and message.content.target:
|
|
77
|
+
target = message.content.target
|
|
78
|
+
if isinstance(target, dict):
|
|
79
|
+
room_str = target.get("roomId")
|
|
80
|
+
entity_str = target.get("entityId")
|
|
81
|
+
if room_str:
|
|
82
|
+
with contextlib.suppress(ValueError):
|
|
83
|
+
target_room_id = UUID(room_str)
|
|
84
|
+
if entity_str:
|
|
85
|
+
with contextlib.suppress(ValueError):
|
|
86
|
+
target_entity_id = UUID(entity_str)
|
|
87
|
+
|
|
88
|
+
if not target_room_id:
|
|
89
|
+
return ActionResult(
|
|
90
|
+
text="No target room specified",
|
|
91
|
+
values={"success": False, "error": "no_target"},
|
|
92
|
+
data={"actionName": "SEND_MESSAGE"},
|
|
93
|
+
success=False,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
message_content = Content(
|
|
97
|
+
text=message_text,
|
|
98
|
+
source="agent",
|
|
99
|
+
actions=["SEND_MESSAGE"],
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Create the message memory
|
|
103
|
+
import time
|
|
104
|
+
import uuid as uuid_module
|
|
105
|
+
|
|
106
|
+
from elizaos.types.primitives import as_uuid
|
|
107
|
+
|
|
108
|
+
message_memory = MemoryType(
|
|
109
|
+
id=as_uuid(str(uuid_module.uuid4())),
|
|
110
|
+
entity_id=runtime.agent_id,
|
|
111
|
+
room_id=target_room_id,
|
|
112
|
+
content=message_content,
|
|
113
|
+
created_at=int(time.time() * 1000),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
await runtime.create_memory(
|
|
117
|
+
content=message_content,
|
|
118
|
+
room_id=target_room_id,
|
|
119
|
+
entity_id=runtime.agent_id,
|
|
120
|
+
memory_type="message",
|
|
121
|
+
metadata={
|
|
122
|
+
"type": "SEND_MESSAGE",
|
|
123
|
+
"targetEntityId": str(target_entity_id) if target_entity_id else None,
|
|
124
|
+
},
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Emit MESSAGE_SENT event
|
|
128
|
+
await runtime.emit_event(
|
|
129
|
+
"MESSAGE_SENT",
|
|
130
|
+
{
|
|
131
|
+
"runtime": runtime,
|
|
132
|
+
"source": "send-message-action",
|
|
133
|
+
"message": message_memory,
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
response_content = Content(
|
|
138
|
+
text=f"Message sent: {message_text[:50]}...",
|
|
139
|
+
actions=["SEND_MESSAGE"],
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if callback:
|
|
143
|
+
await callback(response_content)
|
|
144
|
+
|
|
145
|
+
return ActionResult(
|
|
146
|
+
text="Message sent to room",
|
|
147
|
+
values={
|
|
148
|
+
"success": True,
|
|
149
|
+
"messageSent": True,
|
|
150
|
+
"targetRoomId": str(target_room_id),
|
|
151
|
+
"targetEntityId": str(target_entity_id) if target_entity_id else None,
|
|
152
|
+
},
|
|
153
|
+
data={
|
|
154
|
+
"actionName": "SEND_MESSAGE",
|
|
155
|
+
"targetRoomId": str(target_room_id),
|
|
156
|
+
"messagePreview": message_text[:100],
|
|
157
|
+
},
|
|
158
|
+
success=True,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def examples(self) -> list[list[ActionExample]]:
|
|
163
|
+
return _convert_spec_examples()
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
send_message_action = Action(
|
|
167
|
+
name=SendMessageAction.name,
|
|
168
|
+
similes=SendMessageAction().similes,
|
|
169
|
+
description=SendMessageAction.description,
|
|
170
|
+
validate=SendMessageAction().validate,
|
|
171
|
+
handler=SendMessageAction().handler,
|
|
172
|
+
examples=SendMessageAction().examples,
|
|
173
|
+
)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from elizaos.bootstrap.utils.xml import parse_key_value_xml
|
|
7
|
+
from elizaos.generated.spec_helpers import require_action_spec
|
|
8
|
+
from elizaos.prompts import UPDATE_SETTINGS_TEMPLATE
|
|
9
|
+
from elizaos.types import Action, ActionExample, ActionResult, Content, ModelType
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from elizaos.types import HandlerCallback, HandlerOptions, IAgentRuntime, Memory, State
|
|
13
|
+
|
|
14
|
+
# Get text content from centralized specs
|
|
15
|
+
_spec = require_action_spec("UPDATE_SETTINGS")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _convert_spec_examples() -> list[list[ActionExample]]:
|
|
19
|
+
"""Convert spec examples to ActionExample format."""
|
|
20
|
+
spec_examples = _spec.get("examples", [])
|
|
21
|
+
if spec_examples:
|
|
22
|
+
return [
|
|
23
|
+
[
|
|
24
|
+
ActionExample(
|
|
25
|
+
name=msg.get("name", ""),
|
|
26
|
+
content=Content(
|
|
27
|
+
text=msg.get("content", {}).get("text", ""),
|
|
28
|
+
actions=msg.get("content", {}).get("actions"),
|
|
29
|
+
),
|
|
30
|
+
)
|
|
31
|
+
for msg in example
|
|
32
|
+
]
|
|
33
|
+
for example in spec_examples
|
|
34
|
+
]
|
|
35
|
+
return []
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class SettingUpdate:
|
|
40
|
+
key: str
|
|
41
|
+
value: str
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class UpdateSettingsAction:
|
|
46
|
+
name: str = _spec["name"]
|
|
47
|
+
similes: list[str] = field(default_factory=lambda: list(_spec.get("similes", [])))
|
|
48
|
+
description: str = _spec["description"]
|
|
49
|
+
|
|
50
|
+
async def validate(
|
|
51
|
+
self, runtime: IAgentRuntime, _message: Memory, _state: State | None = None
|
|
52
|
+
) -> bool:
|
|
53
|
+
return True
|
|
54
|
+
|
|
55
|
+
async def handler(
|
|
56
|
+
self,
|
|
57
|
+
runtime: IAgentRuntime,
|
|
58
|
+
message: Memory,
|
|
59
|
+
state: State | None = None,
|
|
60
|
+
options: HandlerOptions | None = None,
|
|
61
|
+
callback: HandlerCallback | None = None,
|
|
62
|
+
responses: list[Memory] | None = None,
|
|
63
|
+
) -> ActionResult:
|
|
64
|
+
if state is None:
|
|
65
|
+
raise ValueError("State is required for UPDATE_SETTINGS action")
|
|
66
|
+
|
|
67
|
+
state = await runtime.compose_state(
|
|
68
|
+
message, ["RECENT_MESSAGES", "ACTION_STATE", "AGENT_SETTINGS"]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
current_settings = runtime.get_all_settings()
|
|
72
|
+
settings_context = "\n".join(
|
|
73
|
+
f"- {key}: {value}"
|
|
74
|
+
for key, value in current_settings.items()
|
|
75
|
+
if not key.lower().endswith(("key", "secret", "password", "token"))
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
template = (
|
|
79
|
+
runtime.character.templates.get("updateSettingsTemplate")
|
|
80
|
+
if runtime.character.templates
|
|
81
|
+
and "updateSettingsTemplate" in runtime.character.templates
|
|
82
|
+
else UPDATE_SETTINGS_TEMPLATE
|
|
83
|
+
)
|
|
84
|
+
prompt = runtime.compose_prompt(state=state, template=template)
|
|
85
|
+
prompt = prompt.replace("{{settings}}", settings_context)
|
|
86
|
+
|
|
87
|
+
response_text = await runtime.use_model(ModelType.TEXT_LARGE, prompt=prompt)
|
|
88
|
+
parsed_xml = parse_key_value_xml(response_text)
|
|
89
|
+
|
|
90
|
+
if parsed_xml is None:
|
|
91
|
+
raise ValueError("Failed to parse XML response")
|
|
92
|
+
|
|
93
|
+
thought = str(parsed_xml.get("thought", ""))
|
|
94
|
+
updates_raw = parsed_xml.get("updates", [])
|
|
95
|
+
|
|
96
|
+
updated_settings: list[SettingUpdate] = []
|
|
97
|
+
|
|
98
|
+
if isinstance(updates_raw, list):
|
|
99
|
+
for update in updates_raw:
|
|
100
|
+
if isinstance(update, dict):
|
|
101
|
+
key = str(update.get("key", ""))
|
|
102
|
+
value = str(update.get("value", ""))
|
|
103
|
+
if key and value:
|
|
104
|
+
updated_settings.append(SettingUpdate(key=key, value=value))
|
|
105
|
+
elif isinstance(updates_raw, dict):
|
|
106
|
+
update_list = updates_raw.get("update", [])
|
|
107
|
+
if isinstance(update_list, dict):
|
|
108
|
+
update_list = [update_list]
|
|
109
|
+
for update in update_list:
|
|
110
|
+
if isinstance(update, dict):
|
|
111
|
+
key = str(update.get("key", ""))
|
|
112
|
+
value = str(update.get("value", ""))
|
|
113
|
+
if key and value:
|
|
114
|
+
updated_settings.append(SettingUpdate(key=key, value=value))
|
|
115
|
+
|
|
116
|
+
if not updated_settings:
|
|
117
|
+
return ActionResult(
|
|
118
|
+
text="No settings to update",
|
|
119
|
+
values={"success": True, "noChanges": True},
|
|
120
|
+
data={"actionName": "UPDATE_SETTINGS", "thought": thought},
|
|
121
|
+
success=True,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
for setting in updated_settings:
|
|
125
|
+
runtime.set_setting(setting.key, setting.value)
|
|
126
|
+
|
|
127
|
+
updated_keys = [s.key for s in updated_settings]
|
|
128
|
+
|
|
129
|
+
response_content = Content(
|
|
130
|
+
text=f"Updated {len(updated_settings)} setting(s): {', '.join(updated_keys)}",
|
|
131
|
+
actions=["UPDATE_SETTINGS"],
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if callback:
|
|
135
|
+
await callback(response_content)
|
|
136
|
+
|
|
137
|
+
return ActionResult(
|
|
138
|
+
text=f"Updated settings: {', '.join(updated_keys)}",
|
|
139
|
+
values={
|
|
140
|
+
"success": True,
|
|
141
|
+
"settingsUpdated": True,
|
|
142
|
+
"updatedCount": len(updated_settings),
|
|
143
|
+
"updatedKeys": ", ".join(updated_keys),
|
|
144
|
+
},
|
|
145
|
+
data={
|
|
146
|
+
"actionName": "UPDATE_SETTINGS",
|
|
147
|
+
"updatedSettings": updated_keys,
|
|
148
|
+
"thought": thought,
|
|
149
|
+
},
|
|
150
|
+
success=True,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def examples(self) -> list[list[ActionExample]]:
|
|
155
|
+
return _convert_spec_examples()
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
update_settings_action = Action(
|
|
159
|
+
name=UpdateSettingsAction.name,
|
|
160
|
+
similes=UpdateSettingsAction().similes,
|
|
161
|
+
description=UpdateSettingsAction.description,
|
|
162
|
+
validate=UpdateSettingsAction().validate,
|
|
163
|
+
handler=UpdateSettingsAction().handler,
|
|
164
|
+
examples=UpdateSettingsAction().examples,
|
|
165
|
+
)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from elizaos.generated.spec_helpers import require_action_spec
|
|
7
|
+
from elizaos.types import Action, ActionExample, ActionResult, Content
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from elizaos.types import HandlerCallback, HandlerOptions, IAgentRuntime, Memory, State
|
|
11
|
+
|
|
12
|
+
# Get text content from centralized specs
|
|
13
|
+
_spec = require_action_spec("UNFOLLOW_ROOM")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _convert_spec_examples() -> list[list[ActionExample]]:
|
|
17
|
+
"""Convert spec examples to ActionExample format."""
|
|
18
|
+
spec_examples = _spec.get("examples", [])
|
|
19
|
+
if spec_examples:
|
|
20
|
+
return [
|
|
21
|
+
[
|
|
22
|
+
ActionExample(
|
|
23
|
+
name=msg.get("name", ""),
|
|
24
|
+
content=Content(
|
|
25
|
+
text=msg.get("content", {}).get("text", ""),
|
|
26
|
+
actions=msg.get("content", {}).get("actions"),
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
for msg in example
|
|
30
|
+
]
|
|
31
|
+
for example in spec_examples
|
|
32
|
+
]
|
|
33
|
+
return []
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class UnfollowRoomAction:
|
|
38
|
+
name: str = _spec["name"]
|
|
39
|
+
similes: list[str] = field(default_factory=lambda: list(_spec.get("similes", [])))
|
|
40
|
+
description: str = _spec["description"]
|
|
41
|
+
|
|
42
|
+
async def validate(
|
|
43
|
+
self, runtime: IAgentRuntime, message: Memory, _state: State | None = None
|
|
44
|
+
) -> bool:
|
|
45
|
+
room_id = message.room_id
|
|
46
|
+
if not room_id:
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
room = await runtime.get_room(room_id)
|
|
50
|
+
if room is None:
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
world_id = room.world_id
|
|
54
|
+
if world_id:
|
|
55
|
+
world = await runtime.get_world(world_id)
|
|
56
|
+
if world and world.metadata:
|
|
57
|
+
followed_rooms = world.metadata.get("followedRooms", [])
|
|
58
|
+
if str(room_id) in followed_rooms:
|
|
59
|
+
return True
|
|
60
|
+
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
async def handler(
|
|
64
|
+
self,
|
|
65
|
+
runtime: IAgentRuntime,
|
|
66
|
+
message: Memory,
|
|
67
|
+
state: State | None = None,
|
|
68
|
+
options: HandlerOptions | None = None,
|
|
69
|
+
callback: HandlerCallback | None = None,
|
|
70
|
+
responses: list[Memory] | None = None,
|
|
71
|
+
) -> ActionResult:
|
|
72
|
+
room_id = message.room_id
|
|
73
|
+
if not room_id:
|
|
74
|
+
return ActionResult(
|
|
75
|
+
text="No room specified to unfollow",
|
|
76
|
+
values={"success": False, "error": "no_room_id"},
|
|
77
|
+
data={"actionName": "UNFOLLOW_ROOM"},
|
|
78
|
+
success=False,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
room = await runtime.get_room(room_id)
|
|
82
|
+
if room is None:
|
|
83
|
+
return ActionResult(
|
|
84
|
+
text="Room not found",
|
|
85
|
+
values={"success": False, "error": "room_not_found"},
|
|
86
|
+
data={"actionName": "UNFOLLOW_ROOM"},
|
|
87
|
+
success=False,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
room_name = str(room.name) if room.name else "Unknown Room"
|
|
91
|
+
|
|
92
|
+
world_id = room.world_id
|
|
93
|
+
if world_id:
|
|
94
|
+
world = await runtime.get_world(world_id)
|
|
95
|
+
if world and world.metadata:
|
|
96
|
+
followed_rooms = list(world.metadata.get("followedRooms", []))
|
|
97
|
+
room_id_str = str(room_id)
|
|
98
|
+
|
|
99
|
+
if room_id_str in followed_rooms:
|
|
100
|
+
followed_rooms.remove(room_id_str)
|
|
101
|
+
world.metadata["followedRooms"] = followed_rooms
|
|
102
|
+
await runtime.update_world(world)
|
|
103
|
+
|
|
104
|
+
await runtime.create_memory(
|
|
105
|
+
content=Content(
|
|
106
|
+
text=f"Stopped following room: {room_name}",
|
|
107
|
+
actions=["UNFOLLOW_ROOM"],
|
|
108
|
+
),
|
|
109
|
+
room_id=room_id,
|
|
110
|
+
entity_id=runtime.agent_id,
|
|
111
|
+
memory_type="action",
|
|
112
|
+
metadata={"type": "UNFOLLOW_ROOM", "roomName": room_name},
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
response_content = Content(
|
|
116
|
+
text=f"I am no longer following {room_name}.",
|
|
117
|
+
actions=["UNFOLLOW_ROOM"],
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if callback:
|
|
121
|
+
await callback(response_content)
|
|
122
|
+
|
|
123
|
+
return ActionResult(
|
|
124
|
+
text=f"Stopped following room: {room_name}",
|
|
125
|
+
values={
|
|
126
|
+
"success": True,
|
|
127
|
+
"unfollowed": True,
|
|
128
|
+
"roomId": str(room_id),
|
|
129
|
+
"roomName": room_name,
|
|
130
|
+
},
|
|
131
|
+
data={
|
|
132
|
+
"actionName": "UNFOLLOW_ROOM",
|
|
133
|
+
"roomId": str(room_id),
|
|
134
|
+
"roomName": room_name,
|
|
135
|
+
},
|
|
136
|
+
success=True,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def examples(self) -> list[list[ActionExample]]:
|
|
141
|
+
return _convert_spec_examples()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
unfollow_room_action = Action(
|
|
145
|
+
name=UnfollowRoomAction.name,
|
|
146
|
+
similes=UnfollowRoomAction().similes,
|
|
147
|
+
description=UnfollowRoomAction.description,
|
|
148
|
+
validate=UnfollowRoomAction().validate,
|
|
149
|
+
handler=UnfollowRoomAction().handler,
|
|
150
|
+
examples=UnfollowRoomAction().examples,
|
|
151
|
+
)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from elizaos.generated.spec_helpers import require_action_spec
|
|
7
|
+
from elizaos.types import Action, ActionExample, ActionResult, Content
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from elizaos.types import HandlerCallback, HandlerOptions, IAgentRuntime, Memory, State
|
|
11
|
+
|
|
12
|
+
# Get text content from centralized specs
|
|
13
|
+
_spec = require_action_spec("UNMUTE_ROOM")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _convert_spec_examples() -> list[list[ActionExample]]:
|
|
17
|
+
"""Convert spec examples to ActionExample format."""
|
|
18
|
+
spec_examples = _spec.get("examples", [])
|
|
19
|
+
if spec_examples:
|
|
20
|
+
return [
|
|
21
|
+
[
|
|
22
|
+
ActionExample(
|
|
23
|
+
name=msg.get("name", ""),
|
|
24
|
+
content=Content(
|
|
25
|
+
text=msg.get("content", {}).get("text", ""),
|
|
26
|
+
actions=msg.get("content", {}).get("actions"),
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
for msg in example
|
|
30
|
+
]
|
|
31
|
+
for example in spec_examples
|
|
32
|
+
]
|
|
33
|
+
return []
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class UnmuteRoomAction:
|
|
38
|
+
name: str = _spec["name"]
|
|
39
|
+
similes: list[str] = field(default_factory=lambda: list(_spec.get("similes", [])))
|
|
40
|
+
description: str = _spec["description"]
|
|
41
|
+
|
|
42
|
+
async def validate(
|
|
43
|
+
self, runtime: IAgentRuntime, message: Memory, _state: State | None = None
|
|
44
|
+
) -> bool:
|
|
45
|
+
room_id = message.room_id
|
|
46
|
+
if not room_id:
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
room = await runtime.get_room(room_id)
|
|
50
|
+
if room is None:
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
world_id = room.world_id
|
|
54
|
+
if world_id:
|
|
55
|
+
world = await runtime.get_world(world_id)
|
|
56
|
+
if world and world.metadata:
|
|
57
|
+
muted_rooms = world.metadata.get("mutedRooms", [])
|
|
58
|
+
if str(room_id) in muted_rooms:
|
|
59
|
+
return True
|
|
60
|
+
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
async def handler(
|
|
64
|
+
self,
|
|
65
|
+
runtime: IAgentRuntime,
|
|
66
|
+
message: Memory,
|
|
67
|
+
state: State | None = None,
|
|
68
|
+
options: HandlerOptions | None = None,
|
|
69
|
+
callback: HandlerCallback | None = None,
|
|
70
|
+
responses: list[Memory] | None = None,
|
|
71
|
+
) -> ActionResult:
|
|
72
|
+
room_id = message.room_id
|
|
73
|
+
if not room_id:
|
|
74
|
+
return ActionResult(
|
|
75
|
+
text="No room specified to unmute",
|
|
76
|
+
values={"success": False, "error": "no_room_id"},
|
|
77
|
+
data={"actionName": "UNMUTE_ROOM"},
|
|
78
|
+
success=False,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
room = await runtime.get_room(room_id)
|
|
82
|
+
if room is None:
|
|
83
|
+
return ActionResult(
|
|
84
|
+
text="Room not found",
|
|
85
|
+
values={"success": False, "error": "room_not_found"},
|
|
86
|
+
data={"actionName": "UNMUTE_ROOM"},
|
|
87
|
+
success=False,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
room_name = str(room.name) if room.name else "Unknown Room"
|
|
91
|
+
|
|
92
|
+
world_id = room.world_id
|
|
93
|
+
if world_id:
|
|
94
|
+
world = await runtime.get_world(world_id)
|
|
95
|
+
if world and world.metadata:
|
|
96
|
+
muted_rooms = list(world.metadata.get("mutedRooms", []))
|
|
97
|
+
room_id_str = str(room_id)
|
|
98
|
+
|
|
99
|
+
if room_id_str in muted_rooms:
|
|
100
|
+
muted_rooms.remove(room_id_str)
|
|
101
|
+
world.metadata["mutedRooms"] = muted_rooms
|
|
102
|
+
await runtime.update_world(world)
|
|
103
|
+
|
|
104
|
+
await runtime.create_memory(
|
|
105
|
+
content=Content(
|
|
106
|
+
text=f"Unmuted room: {room_name}",
|
|
107
|
+
actions=["UNMUTE_ROOM"],
|
|
108
|
+
),
|
|
109
|
+
room_id=room_id,
|
|
110
|
+
entity_id=runtime.agent_id,
|
|
111
|
+
memory_type="action",
|
|
112
|
+
metadata={"type": "UNMUTE_ROOM", "roomName": room_name},
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
response_content = Content(
|
|
116
|
+
text=f"I have unmuted {room_name}. I will now respond to messages there.",
|
|
117
|
+
actions=["UNMUTE_ROOM"],
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if callback:
|
|
121
|
+
await callback(response_content)
|
|
122
|
+
|
|
123
|
+
return ActionResult(
|
|
124
|
+
text=f"Unmuted room: {room_name}",
|
|
125
|
+
values={
|
|
126
|
+
"success": True,
|
|
127
|
+
"unmuted": True,
|
|
128
|
+
"roomId": str(room_id),
|
|
129
|
+
"roomName": room_name,
|
|
130
|
+
},
|
|
131
|
+
data={
|
|
132
|
+
"actionName": "UNMUTE_ROOM",
|
|
133
|
+
"roomId": str(room_id),
|
|
134
|
+
"roomName": room_name,
|
|
135
|
+
},
|
|
136
|
+
success=True,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def examples(self) -> list[list[ActionExample]]:
|
|
141
|
+
return _convert_spec_examples()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
unmute_room_action = Action(
|
|
145
|
+
name=UnmuteRoomAction.name,
|
|
146
|
+
similes=UnmuteRoomAction().similes,
|
|
147
|
+
description=UnmuteRoomAction.description,
|
|
148
|
+
validate=UnmuteRoomAction().validate,
|
|
149
|
+
handler=UnmuteRoomAction().handler,
|
|
150
|
+
examples=UnmuteRoomAction().examples,
|
|
151
|
+
)
|