@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.
Files changed (197) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +239 -0
  3. package/elizaos/__init__.py +280 -0
  4. package/elizaos/action_docs.py +149 -0
  5. package/elizaos/advanced_capabilities/__init__.py +85 -0
  6. package/elizaos/advanced_capabilities/actions/__init__.py +54 -0
  7. package/elizaos/advanced_capabilities/actions/add_contact.py +139 -0
  8. package/elizaos/advanced_capabilities/actions/follow_room.py +151 -0
  9. package/elizaos/advanced_capabilities/actions/image_generation.py +148 -0
  10. package/elizaos/advanced_capabilities/actions/mute_room.py +164 -0
  11. package/elizaos/advanced_capabilities/actions/remove_contact.py +145 -0
  12. package/elizaos/advanced_capabilities/actions/roles.py +207 -0
  13. package/elizaos/advanced_capabilities/actions/schedule_follow_up.py +154 -0
  14. package/elizaos/advanced_capabilities/actions/search_contacts.py +145 -0
  15. package/elizaos/advanced_capabilities/actions/send_message.py +187 -0
  16. package/elizaos/advanced_capabilities/actions/settings.py +151 -0
  17. package/elizaos/advanced_capabilities/actions/unfollow_room.py +164 -0
  18. package/elizaos/advanced_capabilities/actions/unmute_room.py +164 -0
  19. package/elizaos/advanced_capabilities/actions/update_contact.py +164 -0
  20. package/elizaos/advanced_capabilities/actions/update_entity.py +161 -0
  21. package/elizaos/advanced_capabilities/evaluators/__init__.py +18 -0
  22. package/elizaos/advanced_capabilities/evaluators/reflection.py +134 -0
  23. package/elizaos/advanced_capabilities/evaluators/relationship_extraction.py +203 -0
  24. package/elizaos/advanced_capabilities/providers/__init__.py +36 -0
  25. package/elizaos/advanced_capabilities/providers/agent_settings.py +60 -0
  26. package/elizaos/advanced_capabilities/providers/contacts.py +77 -0
  27. package/elizaos/advanced_capabilities/providers/facts.py +82 -0
  28. package/elizaos/advanced_capabilities/providers/follow_ups.py +113 -0
  29. package/elizaos/advanced_capabilities/providers/knowledge.py +83 -0
  30. package/elizaos/advanced_capabilities/providers/relationships.py +112 -0
  31. package/elizaos/advanced_capabilities/providers/roles.py +97 -0
  32. package/elizaos/advanced_capabilities/providers/settings.py +51 -0
  33. package/elizaos/advanced_capabilities/services/__init__.py +18 -0
  34. package/elizaos/advanced_capabilities/services/follow_up.py +138 -0
  35. package/elizaos/advanced_capabilities/services/rolodex.py +244 -0
  36. package/elizaos/advanced_memory/__init__.py +3 -0
  37. package/elizaos/advanced_memory/evaluators.py +97 -0
  38. package/elizaos/advanced_memory/memory_service.py +556 -0
  39. package/elizaos/advanced_memory/plugin.py +30 -0
  40. package/elizaos/advanced_memory/prompts.py +12 -0
  41. package/elizaos/advanced_memory/providers.py +90 -0
  42. package/elizaos/advanced_memory/types.py +65 -0
  43. package/elizaos/advanced_planning/__init__.py +10 -0
  44. package/elizaos/advanced_planning/actions.py +145 -0
  45. package/elizaos/advanced_planning/message_classifier.py +127 -0
  46. package/elizaos/advanced_planning/planning_service.py +712 -0
  47. package/elizaos/advanced_planning/plugin.py +40 -0
  48. package/elizaos/advanced_planning/prompts.py +4 -0
  49. package/elizaos/basic_capabilities/__init__.py +66 -0
  50. package/elizaos/basic_capabilities/actions/__init__.py +24 -0
  51. package/elizaos/basic_capabilities/actions/choice.py +140 -0
  52. package/elizaos/basic_capabilities/actions/ignore.py +66 -0
  53. package/elizaos/basic_capabilities/actions/none.py +56 -0
  54. package/elizaos/basic_capabilities/actions/reply.py +120 -0
  55. package/elizaos/basic_capabilities/providers/__init__.py +54 -0
  56. package/elizaos/basic_capabilities/providers/action_state.py +113 -0
  57. package/elizaos/basic_capabilities/providers/actions.py +263 -0
  58. package/elizaos/basic_capabilities/providers/attachments.py +76 -0
  59. package/elizaos/basic_capabilities/providers/capabilities.py +62 -0
  60. package/elizaos/basic_capabilities/providers/character.py +113 -0
  61. package/elizaos/basic_capabilities/providers/choice.py +73 -0
  62. package/elizaos/basic_capabilities/providers/context_bench.py +44 -0
  63. package/elizaos/basic_capabilities/providers/current_time.py +58 -0
  64. package/elizaos/basic_capabilities/providers/entities.py +99 -0
  65. package/elizaos/basic_capabilities/providers/evaluators.py +54 -0
  66. package/elizaos/basic_capabilities/providers/providers_list.py +55 -0
  67. package/elizaos/basic_capabilities/providers/recent_messages.py +85 -0
  68. package/elizaos/basic_capabilities/providers/time.py +45 -0
  69. package/elizaos/basic_capabilities/providers/world.py +93 -0
  70. package/elizaos/basic_capabilities/services/__init__.py +18 -0
  71. package/elizaos/basic_capabilities/services/embedding.py +122 -0
  72. package/elizaos/basic_capabilities/services/task.py +178 -0
  73. package/elizaos/bootstrap/__init__.py +12 -0
  74. package/elizaos/bootstrap/actions/__init__.py +68 -0
  75. package/elizaos/bootstrap/actions/add_contact.py +149 -0
  76. package/elizaos/bootstrap/actions/choice.py +147 -0
  77. package/elizaos/bootstrap/actions/follow_room.py +151 -0
  78. package/elizaos/bootstrap/actions/ignore.py +80 -0
  79. package/elizaos/bootstrap/actions/image_generation.py +135 -0
  80. package/elizaos/bootstrap/actions/mute_room.py +151 -0
  81. package/elizaos/bootstrap/actions/none.py +71 -0
  82. package/elizaos/bootstrap/actions/remove_contact.py +159 -0
  83. package/elizaos/bootstrap/actions/reply.py +140 -0
  84. package/elizaos/bootstrap/actions/roles.py +193 -0
  85. package/elizaos/bootstrap/actions/schedule_follow_up.py +164 -0
  86. package/elizaos/bootstrap/actions/search_contacts.py +159 -0
  87. package/elizaos/bootstrap/actions/send_message.py +173 -0
  88. package/elizaos/bootstrap/actions/settings.py +165 -0
  89. package/elizaos/bootstrap/actions/unfollow_room.py +151 -0
  90. package/elizaos/bootstrap/actions/unmute_room.py +151 -0
  91. package/elizaos/bootstrap/actions/update_contact.py +178 -0
  92. package/elizaos/bootstrap/actions/update_entity.py +175 -0
  93. package/elizaos/bootstrap/autonomy/__init__.py +18 -0
  94. package/elizaos/bootstrap/autonomy/action.py +197 -0
  95. package/elizaos/bootstrap/autonomy/providers.py +165 -0
  96. package/elizaos/bootstrap/autonomy/routes.py +171 -0
  97. package/elizaos/bootstrap/autonomy/service.py +562 -0
  98. package/elizaos/bootstrap/autonomy/types.py +18 -0
  99. package/elizaos/bootstrap/evaluators/__init__.py +19 -0
  100. package/elizaos/bootstrap/evaluators/reflection.py +118 -0
  101. package/elizaos/bootstrap/evaluators/relationship_extraction.py +192 -0
  102. package/elizaos/bootstrap/plugin.py +140 -0
  103. package/elizaos/bootstrap/providers/__init__.py +80 -0
  104. package/elizaos/bootstrap/providers/action_state.py +71 -0
  105. package/elizaos/bootstrap/providers/actions.py +256 -0
  106. package/elizaos/bootstrap/providers/agent_settings.py +63 -0
  107. package/elizaos/bootstrap/providers/attachments.py +76 -0
  108. package/elizaos/bootstrap/providers/capabilities.py +66 -0
  109. package/elizaos/bootstrap/providers/character.py +128 -0
  110. package/elizaos/bootstrap/providers/choice.py +77 -0
  111. package/elizaos/bootstrap/providers/contacts.py +78 -0
  112. package/elizaos/bootstrap/providers/context_bench.py +49 -0
  113. package/elizaos/bootstrap/providers/current_time.py +56 -0
  114. package/elizaos/bootstrap/providers/entities.py +99 -0
  115. package/elizaos/bootstrap/providers/evaluators.py +58 -0
  116. package/elizaos/bootstrap/providers/facts.py +86 -0
  117. package/elizaos/bootstrap/providers/follow_ups.py +116 -0
  118. package/elizaos/bootstrap/providers/knowledge.py +73 -0
  119. package/elizaos/bootstrap/providers/providers_list.py +59 -0
  120. package/elizaos/bootstrap/providers/recent_messages.py +85 -0
  121. package/elizaos/bootstrap/providers/relationships.py +106 -0
  122. package/elizaos/bootstrap/providers/roles.py +95 -0
  123. package/elizaos/bootstrap/providers/settings.py +55 -0
  124. package/elizaos/bootstrap/providers/time.py +45 -0
  125. package/elizaos/bootstrap/providers/world.py +97 -0
  126. package/elizaos/bootstrap/services/__init__.py +26 -0
  127. package/elizaos/bootstrap/services/embedding.py +122 -0
  128. package/elizaos/bootstrap/services/follow_up.py +138 -0
  129. package/elizaos/bootstrap/services/rolodex.py +244 -0
  130. package/elizaos/bootstrap/services/task.py +585 -0
  131. package/elizaos/bootstrap/types.py +54 -0
  132. package/elizaos/bootstrap/utils/__init__.py +7 -0
  133. package/elizaos/bootstrap/utils/xml.py +69 -0
  134. package/elizaos/character.py +149 -0
  135. package/elizaos/logger.py +179 -0
  136. package/elizaos/media/__init__.py +45 -0
  137. package/elizaos/media/mime.py +315 -0
  138. package/elizaos/media/search.py +161 -0
  139. package/elizaos/media/tests/__init__.py +1 -0
  140. package/elizaos/media/tests/test_mime.py +117 -0
  141. package/elizaos/media/tests/test_search.py +156 -0
  142. package/elizaos/plugin.py +191 -0
  143. package/elizaos/prompts.py +1071 -0
  144. package/elizaos/py.typed +0 -0
  145. package/elizaos/runtime.py +2572 -0
  146. package/elizaos/services/__init__.py +49 -0
  147. package/elizaos/services/hook_service.py +511 -0
  148. package/elizaos/services/message_service.py +1248 -0
  149. package/elizaos/settings.py +182 -0
  150. package/elizaos/streaming_context.py +159 -0
  151. package/elizaos/trajectory_context.py +18 -0
  152. package/elizaos/types/__init__.py +512 -0
  153. package/elizaos/types/agent.py +31 -0
  154. package/elizaos/types/components.py +208 -0
  155. package/elizaos/types/database.py +64 -0
  156. package/elizaos/types/environment.py +46 -0
  157. package/elizaos/types/events.py +47 -0
  158. package/elizaos/types/memory.py +45 -0
  159. package/elizaos/types/model.py +393 -0
  160. package/elizaos/types/plugin.py +188 -0
  161. package/elizaos/types/primitives.py +100 -0
  162. package/elizaos/types/runtime.py +460 -0
  163. package/elizaos/types/service.py +113 -0
  164. package/elizaos/types/service_interfaces.py +244 -0
  165. package/elizaos/types/state.py +188 -0
  166. package/elizaos/types/task.py +29 -0
  167. package/elizaos/utils/__init__.py +108 -0
  168. package/elizaos/utils/spec_examples.py +48 -0
  169. package/elizaos/utils/streaming.py +426 -0
  170. package/elizaos_atropos_shared/__init__.py +1 -0
  171. package/elizaos_atropos_shared/canonical_eliza.py +282 -0
  172. package/package.json +19 -0
  173. package/pyproject.toml +143 -0
  174. package/requirements-dev.in +11 -0
  175. package/requirements-dev.lock +134 -0
  176. package/requirements.in +9 -0
  177. package/requirements.lock +64 -0
  178. package/tests/__init__.py +0 -0
  179. package/tests/test_action_parameters.py +154 -0
  180. package/tests/test_actions_provider_examples.py +39 -0
  181. package/tests/test_advanced_memory_behavior.py +96 -0
  182. package/tests/test_advanced_memory_flag.py +30 -0
  183. package/tests/test_advanced_planning_behavior.py +225 -0
  184. package/tests/test_advanced_planning_flag.py +26 -0
  185. package/tests/test_autonomy.py +445 -0
  186. package/tests/test_bootstrap_initialize.py +37 -0
  187. package/tests/test_character.py +163 -0
  188. package/tests/test_character_provider.py +231 -0
  189. package/tests/test_dynamic_prompt_exec.py +561 -0
  190. package/tests/test_logger_redaction.py +43 -0
  191. package/tests/test_plugin.py +117 -0
  192. package/tests/test_runtime.py +422 -0
  193. package/tests/test_salt_production_enforcement.py +22 -0
  194. package/tests/test_settings_crypto.py +118 -0
  195. package/tests/test_streaming.py +295 -0
  196. package/tests/test_types.py +221 -0
  197. package/tests/test_uuid_parity.py +46 -0
@@ -0,0 +1,80 @@
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("IGNORE")
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 IgnoreAction:
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
+ return True
46
+
47
+ async def handler(
48
+ self,
49
+ runtime: IAgentRuntime,
50
+ message: Memory,
51
+ state: State | None = None,
52
+ options: HandlerOptions | None = None,
53
+ callback: HandlerCallback | None = None,
54
+ responses: list[Memory] | None = None,
55
+ ) -> ActionResult:
56
+ if callback and responses and len(responses) > 0:
57
+ first_response = responses[0]
58
+ if first_response.content:
59
+ await callback(first_response.content)
60
+
61
+ return ActionResult(
62
+ text="Ignoring message",
63
+ values={"success": True, "ignored": True},
64
+ data={"actionName": "IGNORE"},
65
+ success=True,
66
+ )
67
+
68
+ @property
69
+ def examples(self) -> list[list[ActionExample]]:
70
+ return _convert_spec_examples()
71
+
72
+
73
+ ignore_action = Action(
74
+ name=IgnoreAction.name,
75
+ similes=IgnoreAction().similes,
76
+ description=IgnoreAction.description,
77
+ validate=IgnoreAction().validate,
78
+ handler=IgnoreAction().handler,
79
+ examples=IgnoreAction().examples,
80
+ )
@@ -0,0 +1,135 @@
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 IMAGE_GENERATION_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("GENERATE_IMAGE")
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 GenerateImageAction:
40
+ name: str = _spec["name"]
41
+ similes: list[str] = field(default_factory=lambda: list(_spec.get("similes", [])))
42
+ description: str = _spec["description"]
43
+
44
+ async def validate(
45
+ self, runtime: IAgentRuntime, message: Memory, _state: State | None = None
46
+ ) -> bool:
47
+ return runtime.has_model(ModelType.IMAGE)
48
+
49
+ async def handler(
50
+ self,
51
+ runtime: IAgentRuntime,
52
+ message: Memory,
53
+ state: State | None = None,
54
+ options: HandlerOptions | None = None,
55
+ callback: HandlerCallback | None = None,
56
+ responses: list[Memory] | None = None,
57
+ ) -> ActionResult:
58
+ if state is None:
59
+ raise ValueError("State is required for GENERATE_IMAGE action")
60
+
61
+ state = await runtime.compose_state(message, ["RECENT_MESSAGES", "ACTION_STATE"])
62
+
63
+ template = (
64
+ runtime.character.templates.get("imageGenerationTemplate")
65
+ if runtime.character.templates
66
+ and "imageGenerationTemplate" in runtime.character.templates
67
+ else IMAGE_GENERATION_TEMPLATE
68
+ )
69
+ prompt = runtime.compose_prompt(state=state, template=template)
70
+
71
+ prompt_response = await runtime.use_model(ModelType.TEXT_LARGE, prompt=prompt)
72
+ parsed_xml = parse_key_value_xml(prompt_response)
73
+
74
+ if parsed_xml is None:
75
+ raise ValueError("Failed to parse XML response for image prompt")
76
+
77
+ thought = str(parsed_xml.get("thought", ""))
78
+ image_prompt = str(parsed_xml.get("prompt", ""))
79
+
80
+ if not image_prompt:
81
+ raise ValueError("No image prompt generated")
82
+
83
+ image_result = await runtime.use_model(
84
+ ModelType.IMAGE,
85
+ prompt=image_prompt,
86
+ )
87
+
88
+ image_url: str | None = None
89
+ if isinstance(image_result, str):
90
+ image_url = image_result
91
+ elif isinstance(image_result, dict):
92
+ image_url = image_result.get("url") or image_result.get("data")
93
+
94
+ if not image_url:
95
+ raise ValueError("No image URL returned from generation")
96
+
97
+ response_content = Content(
98
+ text=f"Generated image with prompt: {image_prompt}",
99
+ attachments=[{"type": "image", "url": image_url}],
100
+ actions=["GENERATE_IMAGE"],
101
+ )
102
+
103
+ if callback:
104
+ await callback(response_content)
105
+
106
+ return ActionResult(
107
+ text=f"Generated image: {image_prompt}",
108
+ values={
109
+ "success": True,
110
+ "imageGenerated": True,
111
+ "imageUrl": image_url,
112
+ "imagePrompt": image_prompt,
113
+ },
114
+ data={
115
+ "actionName": "GENERATE_IMAGE",
116
+ "prompt": image_prompt,
117
+ "thought": thought,
118
+ "imageUrl": image_url,
119
+ },
120
+ success=True,
121
+ )
122
+
123
+ @property
124
+ def examples(self) -> list[list[ActionExample]]:
125
+ return _convert_spec_examples()
126
+
127
+
128
+ generate_image_action = Action(
129
+ name=GenerateImageAction.name,
130
+ similes=GenerateImageAction().similes,
131
+ description=GenerateImageAction.description,
132
+ validate=GenerateImageAction().validate,
133
+ handler=GenerateImageAction().handler,
134
+ examples=GenerateImageAction().examples,
135
+ )
@@ -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("MUTE_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 MuteRoomAction:
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 False
60
+
61
+ return True
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 mute",
76
+ values={"success": False, "error": "no_room_id"},
77
+ data={"actionName": "MUTE_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": "MUTE_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 not in muted_rooms:
100
+ muted_rooms.append(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"Muted room: {room_name}",
107
+ actions=["MUTE_ROOM"],
108
+ ),
109
+ room_id=room_id,
110
+ entity_id=runtime.agent_id,
111
+ memory_type="action",
112
+ metadata={"type": "MUTE_ROOM", "roomName": room_name},
113
+ )
114
+
115
+ response_content = Content(
116
+ text=f"I have muted {room_name}. I won't respond to messages there.",
117
+ actions=["MUTE_ROOM"],
118
+ )
119
+
120
+ if callback:
121
+ await callback(response_content)
122
+
123
+ return ActionResult(
124
+ text=f"Muted room: {room_name}",
125
+ values={
126
+ "success": True,
127
+ "muted": True,
128
+ "roomId": str(room_id),
129
+ "roomName": room_name,
130
+ },
131
+ data={
132
+ "actionName": "MUTE_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
+ mute_room_action = Action(
145
+ name=MuteRoomAction.name,
146
+ similes=MuteRoomAction().similes,
147
+ description=MuteRoomAction.description,
148
+ validate=MuteRoomAction().validate,
149
+ handler=MuteRoomAction().handler,
150
+ examples=MuteRoomAction().examples,
151
+ )
@@ -0,0 +1,71 @@
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("NONE")
14
+
15
+
16
+ @dataclass
17
+ class NoneAction:
18
+ name: str = _spec["name"]
19
+ similes: list[str] = field(default_factory=lambda: list(_spec.get("similes", [])))
20
+ description: str = _spec["description"]
21
+
22
+ async def validate(
23
+ self, runtime: IAgentRuntime, _message: Memory, _state: State | None = None
24
+ ) -> bool:
25
+ return True
26
+
27
+ async def handler(
28
+ self,
29
+ runtime: IAgentRuntime,
30
+ message: Memory,
31
+ state: State | None = None,
32
+ options: HandlerOptions | None = None,
33
+ callback: HandlerCallback | None = None,
34
+ responses: list[Memory] | None = None,
35
+ ) -> ActionResult:
36
+ return ActionResult(
37
+ text="No action taken",
38
+ values={"success": True, "noAction": True},
39
+ data={"actionName": "NONE"},
40
+ success=True,
41
+ )
42
+
43
+ @property
44
+ def examples(self) -> list[list[ActionExample]]:
45
+ # Convert spec examples to ActionExample format
46
+ spec_examples = _spec.get("examples", [])
47
+ if spec_examples:
48
+ return [
49
+ [
50
+ ActionExample(
51
+ name=msg.get("name", ""),
52
+ content=Content(
53
+ text=msg.get("content", {}).get("text", ""),
54
+ actions=msg.get("content", {}).get("actions"),
55
+ ),
56
+ )
57
+ for msg in example
58
+ ]
59
+ for example in spec_examples
60
+ ]
61
+ return []
62
+
63
+
64
+ none_action = Action(
65
+ name=NoneAction.name,
66
+ similes=NoneAction().similes,
67
+ description=NoneAction.description,
68
+ validate=NoneAction().validate,
69
+ handler=NoneAction().handler,
70
+ examples=NoneAction().examples,
71
+ )
@@ -0,0 +1,159 @@
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 REMOVE_CONTACT_TEMPLATE
9
+ from elizaos.types import (
10
+ Action,
11
+ ActionExample,
12
+ ActionResult,
13
+ Content,
14
+ ModelType,
15
+ )
16
+
17
+ if TYPE_CHECKING:
18
+ from elizaos.types import (
19
+ HandlerCallback,
20
+ HandlerOptions,
21
+ IAgentRuntime,
22
+ Memory,
23
+ State,
24
+ )
25
+
26
+ # Get text content from centralized specs
27
+ _spec = require_action_spec("REMOVE_CONTACT")
28
+
29
+
30
+ def _convert_spec_examples() -> list[list[ActionExample]]:
31
+ """Convert spec examples to ActionExample format."""
32
+ spec_examples = _spec.get("examples", [])
33
+ if spec_examples:
34
+ return [
35
+ [
36
+ ActionExample(
37
+ name=msg.get("name", ""),
38
+ content=Content(
39
+ text=msg.get("content", {}).get("text", ""),
40
+ actions=msg.get("content", {}).get("actions"),
41
+ ),
42
+ )
43
+ for msg in example
44
+ ]
45
+ for example in spec_examples
46
+ ]
47
+ return []
48
+
49
+
50
+ @dataclass
51
+ class RemoveContactAction:
52
+ name: str = _spec["name"]
53
+ similes: list[str] = field(default_factory=lambda: list(_spec.get("similes", [])))
54
+ description: str = _spec["description"]
55
+
56
+ async def validate(
57
+ self, runtime: IAgentRuntime, _message: Memory, _state: State | None = None
58
+ ) -> bool:
59
+ rolodex_service = runtime.get_service("rolodex")
60
+ return rolodex_service is not None
61
+
62
+ async def handler(
63
+ self,
64
+ runtime: IAgentRuntime,
65
+ message: Memory,
66
+ state: State | None = None,
67
+ options: HandlerOptions | None = None,
68
+ callback: HandlerCallback | None = None,
69
+ responses: list[Memory] | None = None,
70
+ ) -> ActionResult:
71
+ from elizaos.bootstrap.services.rolodex import RolodexService
72
+
73
+ rolodex_service = runtime.get_service("rolodex")
74
+ if not rolodex_service or not isinstance(rolodex_service, RolodexService):
75
+ return ActionResult(
76
+ text="Rolodex service not available",
77
+ success=False,
78
+ values={"error": True},
79
+ data={"error": "RolodexService not available"},
80
+ )
81
+
82
+ state = await runtime.compose_state(message, ["RECENT_MESSAGES", "ENTITIES"])
83
+
84
+ prompt = runtime.compose_prompt_from_state(
85
+ state=state,
86
+ template=REMOVE_CONTACT_TEMPLATE,
87
+ )
88
+
89
+ response = await runtime.use_model(ModelType.TEXT_SMALL, {"prompt": prompt})
90
+ parsed = parse_key_value_xml(response)
91
+
92
+ if not parsed or not parsed.get("contactName"):
93
+ return ActionResult(
94
+ text="Could not determine which contact to remove",
95
+ success=False,
96
+ values={"error": True},
97
+ data={"error": "No contact name provided"},
98
+ )
99
+
100
+ contact_name = str(parsed.get("contactName", ""))
101
+ confirmed = str(parsed.get("confirmed", "no")).lower() == "yes"
102
+
103
+ if not confirmed:
104
+ response_text = (
105
+ f'To remove {contact_name}, please confirm by saying "yes, remove {contact_name}".'
106
+ )
107
+ if callback:
108
+ await callback(Content(text=response_text, actions=["REMOVE_CONTACT"]))
109
+ return ActionResult(
110
+ text=response_text,
111
+ success=True,
112
+ values={"needsConfirmation": True},
113
+ data={"contactName": contact_name},
114
+ )
115
+
116
+ contacts = await rolodex_service.search_contacts(search_term=contact_name)
117
+
118
+ if not contacts:
119
+ return ActionResult(
120
+ text=f"Could not find a contact named '{contact_name}'",
121
+ success=False,
122
+ values={"error": True},
123
+ data={"error": "Contact not found"},
124
+ )
125
+
126
+ contact = contacts[0]
127
+ removed = await rolodex_service.remove_contact(contact.entity_id)
128
+
129
+ if removed:
130
+ response_text = f"I've removed {contact_name} from your contacts."
131
+ if callback:
132
+ await callback(Content(text=response_text, actions=["REMOVE_CONTACT"]))
133
+ return ActionResult(
134
+ text=response_text,
135
+ success=True,
136
+ values={"contactId": str(contact.entity_id)},
137
+ data={"success": True},
138
+ )
139
+ else:
140
+ return ActionResult(
141
+ text="Failed to remove contact",
142
+ success=False,
143
+ values={"error": True},
144
+ data={"error": "Remove operation failed"},
145
+ )
146
+
147
+ @property
148
+ def examples(self) -> list[list[ActionExample]]:
149
+ return _convert_spec_examples()
150
+
151
+
152
+ remove_contact_action = Action(
153
+ name=RemoveContactAction.name,
154
+ similes=RemoveContactAction().similes,
155
+ description=RemoveContactAction.description,
156
+ validate=RemoveContactAction().validate,
157
+ handler=RemoveContactAction().handler,
158
+ examples=RemoveContactAction().examples,
159
+ )