@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,78 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.generated.spec_helpers import require_provider_spec
6
+ from elizaos.types import Provider, ProviderResult
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types import IAgentRuntime, Memory, State
10
+
11
+ # Get text content from centralized specs
12
+ _spec = require_provider_spec("CONTACTS")
13
+
14
+
15
+ async def get_contacts_context(
16
+ runtime: IAgentRuntime,
17
+ message: Memory,
18
+ state: State | None = None,
19
+ ) -> ProviderResult:
20
+ from elizaos.bootstrap.services.rolodex import RolodexService
21
+
22
+ rolodex_service = runtime.get_service("rolodex")
23
+ if not rolodex_service or not isinstance(rolodex_service, RolodexService):
24
+ return ProviderResult(text="", values={}, data={})
25
+
26
+ contacts = await rolodex_service.get_all_contacts()
27
+
28
+ if not contacts:
29
+ return ProviderResult(text="No contacts in rolodex.", values={"contactCount": 0}, data={})
30
+
31
+ contact_details: list[dict[str, str]] = []
32
+ for contact in contacts:
33
+ entity = await runtime.get_entity(contact.entity_id)
34
+ name = entity.name if entity and entity.name else "Unknown"
35
+ contact_details.append(
36
+ {
37
+ "id": str(contact.entity_id),
38
+ "name": name,
39
+ "categories": ",".join(contact.categories),
40
+ "tags": ",".join(contact.tags),
41
+ }
42
+ )
43
+
44
+ grouped: dict[str, list[dict[str, str]]] = {}
45
+ for detail in contact_details:
46
+ for cat in detail["categories"].split(","):
47
+ cat = cat.strip()
48
+ if cat:
49
+ grouped.setdefault(cat, []).append(detail)
50
+
51
+ text_summary = f"You have {len(contacts)} contacts in your rolodex:\n"
52
+
53
+ for category, items in grouped.items():
54
+ text_summary += f"\n{category.capitalize()}s ({len(items)}):\n"
55
+ for item in items:
56
+ text_summary += f"- {item['name']}"
57
+ if item["tags"]:
58
+ text_summary += f" [{item['tags']}]"
59
+ text_summary += "\n"
60
+
61
+ category_counts = {cat: len(items) for cat, items in grouped.items()}
62
+
63
+ return ProviderResult(
64
+ text=text_summary.strip(),
65
+ values={
66
+ "contactCount": len(contacts),
67
+ **category_counts,
68
+ },
69
+ data=category_counts,
70
+ )
71
+
72
+
73
+ contacts_provider = Provider(
74
+ name=_spec["name"],
75
+ description=_spec["description"],
76
+ get=get_contacts_context,
77
+ dynamic=_spec.get("dynamic", True),
78
+ )
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.generated.spec_helpers import require_provider_spec
6
+ from elizaos.types import Provider, ProviderResult
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types import IAgentRuntime, Memory, State
10
+
11
+ # Get text content from centralized specs
12
+ _spec = require_provider_spec("CONTEXT_BENCH")
13
+
14
+
15
+ async def get_context_bench(
16
+ runtime: IAgentRuntime,
17
+ message: Memory,
18
+ state: State | None = None,
19
+ ) -> ProviderResult:
20
+ _ = runtime
21
+ _ = state
22
+ meta = getattr(message, "metadata", None)
23
+ bench_ctx = None
24
+ if meta is not None:
25
+ maybe = getattr(meta, "benchmarkContext", None)
26
+ if isinstance(maybe, str) and maybe.strip():
27
+ bench_ctx = maybe.strip()
28
+
29
+ if not bench_ctx:
30
+ return ProviderResult(
31
+ text="",
32
+ values={"benchmark_has_context": False},
33
+ data={},
34
+ )
35
+
36
+ return ProviderResult(
37
+ text=f"# Benchmark Context\n{bench_ctx}",
38
+ values={"benchmark_has_context": True},
39
+ data={"benchmarkContext": bench_ctx},
40
+ )
41
+
42
+
43
+ context_bench_provider = Provider(
44
+ name=_spec["name"],
45
+ description=_spec["description"],
46
+ get=get_context_bench,
47
+ position=_spec.get("position"),
48
+ dynamic=_spec.get("dynamic", True),
49
+ )
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import UTC, datetime
4
+ from typing import TYPE_CHECKING
5
+
6
+ from elizaos.generated.spec_helpers import require_provider_spec
7
+ from elizaos.types import Provider, ProviderResult
8
+
9
+ if TYPE_CHECKING:
10
+ from elizaos.types import IAgentRuntime, Memory, State
11
+
12
+ # Get text content from centralized specs
13
+ _spec = require_provider_spec("CURRENT_TIME")
14
+
15
+
16
+ async def get_current_time_context(
17
+ runtime: IAgentRuntime,
18
+ message: Memory,
19
+ state: State | None = None,
20
+ ) -> ProviderResult:
21
+ now = datetime.now(UTC)
22
+
23
+ iso_timestamp = now.isoformat()
24
+ human_readable = now.strftime("%A, %B %d, %Y at %H:%M:%S UTC")
25
+ date_only = now.strftime("%Y-%m-%d")
26
+ time_only = now.strftime("%H:%M:%S")
27
+ day_of_week = now.strftime("%A")
28
+ unix_timestamp = int(now.timestamp())
29
+
30
+ context_text = f"# Current Time\n- Date: {date_only}\n- Time: {time_only} UTC\n- Day: {day_of_week}\n- Full: {human_readable}\n- ISO: {iso_timestamp}"
31
+
32
+ return ProviderResult(
33
+ text=context_text,
34
+ values={
35
+ "currentTime": iso_timestamp,
36
+ "currentDate": date_only,
37
+ "dayOfWeek": day_of_week,
38
+ "unixTimestamp": unix_timestamp,
39
+ },
40
+ data={
41
+ "iso": iso_timestamp,
42
+ "date": date_only,
43
+ "time": time_only,
44
+ "dayOfWeek": day_of_week,
45
+ "humanReadable": human_readable,
46
+ "unixTimestamp": unix_timestamp,
47
+ },
48
+ )
49
+
50
+
51
+ current_time_provider = Provider(
52
+ name=_spec["name"],
53
+ description=_spec["description"],
54
+ get=get_current_time_context,
55
+ dynamic=_spec.get("dynamic", True),
56
+ )
@@ -0,0 +1,99 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.generated.spec_helpers import require_provider_spec
6
+ from elizaos.types import Provider, ProviderResult
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types import IAgentRuntime, Memory, State
10
+
11
+ # Get text content from centralized specs
12
+ _spec = require_provider_spec("ENTITIES")
13
+
14
+
15
+ async def get_entities_context(
16
+ runtime: IAgentRuntime,
17
+ message: Memory,
18
+ state: State | None = None,
19
+ ) -> ProviderResult:
20
+ room_id = message.room_id
21
+ sender_id = message.entity_id
22
+
23
+ sections: list[str] = []
24
+ entity_list: list[dict[str, str]] = []
25
+
26
+ if sender_id:
27
+ sender = await runtime.get_entity(sender_id)
28
+ if sender:
29
+ sender_info = {
30
+ "id": str(sender.id),
31
+ "name": sender.name or "Unknown",
32
+ "type": sender.entity_type or "user",
33
+ "role": "sender",
34
+ }
35
+ entity_list.append(sender_info)
36
+ sections.append(
37
+ f"- **{sender.name or 'Unknown'}** (sender): {sender.entity_type or 'user'}"
38
+ )
39
+
40
+ if room_id:
41
+ room = await runtime.get_room(room_id)
42
+ if room and room.world_id:
43
+ world = await runtime.get_world(room.world_id)
44
+ if world and world.metadata:
45
+ member_ids = world.metadata.get("members", [])
46
+ roles = world.metadata.get("roles", {})
47
+
48
+ for member_id in member_ids:
49
+ if str(member_id) == str(sender_id):
50
+ continue
51
+
52
+ entity = await runtime.get_entity(member_id)
53
+ if entity:
54
+ role = roles.get(str(member_id), "member")
55
+ entity_info = {
56
+ "id": str(entity.id),
57
+ "name": entity.name or "Unknown",
58
+ "type": entity.entity_type or "user",
59
+ "role": role,
60
+ }
61
+ entity_list.append(entity_info)
62
+ sections.append(
63
+ f"- **{entity.name or 'Unknown'}** ({role}): {entity.entity_type or 'user'}"
64
+ )
65
+
66
+ agent_entity = await runtime.get_entity(runtime.agent_id)
67
+ if agent_entity:
68
+ agent_info = {
69
+ "id": str(agent_entity.id),
70
+ "name": agent_entity.name or runtime.character.name,
71
+ "type": "agent",
72
+ "role": "self",
73
+ }
74
+ entity_list.append(agent_info)
75
+ sections.append(f"- **{agent_entity.name or runtime.character.name}** (self): agent")
76
+
77
+ context_text = "# Entities in Context\n" + "\n".join(sections) if sections else ""
78
+
79
+ return ProviderResult(
80
+ text=context_text,
81
+ values={
82
+ "entityCount": len(entity_list),
83
+ "hasSender": sender_id is not None,
84
+ "agentId": str(runtime.agent_id),
85
+ },
86
+ data={
87
+ "entities": entity_list,
88
+ "senderId": str(sender_id) if sender_id else None,
89
+ "agentId": str(runtime.agent_id),
90
+ },
91
+ )
92
+
93
+
94
+ entities_provider = Provider(
95
+ name=_spec["name"],
96
+ description=_spec["description"],
97
+ get=get_entities_context,
98
+ dynamic=_spec.get("dynamic", True),
99
+ )
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.generated.spec_helpers import require_provider_spec
6
+ from elizaos.types import Provider, ProviderResult
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types import IAgentRuntime, Memory, State
10
+
11
+ # Get text content from centralized specs
12
+ _spec = require_provider_spec("EVALUATORS")
13
+
14
+
15
+ async def get_evaluators(
16
+ runtime: IAgentRuntime,
17
+ message: Memory,
18
+ state: State | None = None,
19
+ ) -> ProviderResult:
20
+ evaluator_info: list[dict[str, str]] = []
21
+
22
+ for evaluator in runtime.evaluators:
23
+ evaluator_info.append(
24
+ {
25
+ "name": evaluator.name,
26
+ "description": getattr(evaluator, "description", "No description"),
27
+ }
28
+ )
29
+
30
+ if not evaluator_info:
31
+ return ProviderResult(
32
+ text="No evaluators available.",
33
+ values={"evaluatorCount": 0},
34
+ data={"evaluators": []},
35
+ )
36
+
37
+ formatted_evaluators = "\n".join(f"- {e['name']}: {e['description']}" for e in evaluator_info)
38
+
39
+ text = f"# Available Evaluators\n{formatted_evaluators}"
40
+
41
+ return ProviderResult(
42
+ text=text,
43
+ values={
44
+ "evaluatorCount": len(evaluator_info),
45
+ "evaluatorNames": [e["name"] for e in evaluator_info],
46
+ },
47
+ data={
48
+ "evaluators": evaluator_info,
49
+ },
50
+ )
51
+
52
+
53
+ evaluators_provider = Provider(
54
+ name=_spec["name"],
55
+ description=_spec["description"],
56
+ get=get_evaluators,
57
+ dynamic=_spec.get("dynamic", False),
58
+ )
@@ -0,0 +1,86 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.generated.spec_helpers import require_provider_spec
6
+ from elizaos.types import Provider, ProviderResult
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types import IAgentRuntime, Memory, State
10
+
11
+ # Get text content from centralized specs
12
+ _spec = require_provider_spec("FACTS")
13
+
14
+
15
+ async def get_facts_context(
16
+ runtime: IAgentRuntime,
17
+ message: Memory,
18
+ state: State | None = None,
19
+ ) -> ProviderResult:
20
+ sections: list[str] = []
21
+ facts_list: list[dict[str, str]] = []
22
+
23
+ entity_id = message.entity_id
24
+ room_id = message.room_id
25
+
26
+ if entity_id:
27
+ sender_facts = await runtime.get_memories(
28
+ entity_id=entity_id,
29
+ memory_type="fact",
30
+ limit=10,
31
+ )
32
+
33
+ if sender_facts:
34
+ sender = await runtime.get_entity(entity_id)
35
+ sender_name = sender.name if sender and sender.name else "User"
36
+ sections.append(f"\n## Facts about {sender_name}")
37
+
38
+ for fact in sender_facts:
39
+ if fact.content and fact.content.text:
40
+ fact_text = fact.content.text
41
+ if len(fact_text) > 200:
42
+ fact_text = fact_text[:200] + "..."
43
+ facts_list.append(
44
+ {"entityId": str(entity_id), "entityName": sender_name, "fact": fact_text}
45
+ )
46
+ sections.append(f"- {fact_text}")
47
+
48
+ if room_id:
49
+ room_facts = await runtime.get_memories(
50
+ room_id=room_id,
51
+ memory_type="fact",
52
+ limit=5,
53
+ )
54
+
55
+ if room_facts:
56
+ sections.append("\n## Room Context Facts")
57
+ for fact in room_facts:
58
+ if fact.content and fact.content.text:
59
+ fact_text = fact.content.text
60
+ if len(fact_text) > 200:
61
+ fact_text = fact_text[:200] + "..."
62
+ facts_list.append({"roomId": str(room_id), "fact": fact_text})
63
+ sections.append(f"- {fact_text}")
64
+
65
+ context_text = ""
66
+ if sections:
67
+ context_text = "# Known Facts" + "\n".join(sections)
68
+
69
+ return ProviderResult(
70
+ text=context_text,
71
+ values={
72
+ "factCount": len(facts_list),
73
+ "hasFacts": len(facts_list) > 0,
74
+ },
75
+ data={
76
+ "facts": facts_list,
77
+ },
78
+ )
79
+
80
+
81
+ facts_provider = Provider(
82
+ name=_spec["name"],
83
+ description=_spec["description"],
84
+ get=get_facts_context,
85
+ dynamic=_spec.get("dynamic", True),
86
+ )
@@ -0,0 +1,116 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import UTC, datetime
4
+ from typing import TYPE_CHECKING
5
+
6
+ from elizaos.generated.spec_helpers import require_provider_spec
7
+ from elizaos.types import Provider, ProviderResult
8
+
9
+ if TYPE_CHECKING:
10
+ from elizaos.types import IAgentRuntime, Memory, State
11
+
12
+ # Get text content from centralized specs
13
+ _spec = require_provider_spec("FOLLOW_UPS")
14
+
15
+
16
+ async def get_follow_ups_context(
17
+ runtime: IAgentRuntime,
18
+ message: Memory,
19
+ state: State | None = None,
20
+ ) -> ProviderResult:
21
+ from elizaos.bootstrap.services.follow_up import FollowUpService
22
+
23
+ follow_up_service = runtime.get_service("follow_up")
24
+ if not follow_up_service or not isinstance(follow_up_service, FollowUpService):
25
+ return ProviderResult(text="", values={}, data={})
26
+
27
+ upcoming = await follow_up_service.get_upcoming_follow_ups(days_ahead=7, include_overdue=True)
28
+
29
+ if not upcoming:
30
+ return ProviderResult(
31
+ text="No upcoming follow-ups scheduled.", values={"followUpCount": 0}, data={}
32
+ )
33
+
34
+ now = datetime.now(UTC)
35
+
36
+ overdue_items: list[dict[str, str]] = []
37
+ upcoming_items: list[dict[str, str]] = []
38
+
39
+ for task in upcoming:
40
+ scheduled = datetime.fromisoformat(task.scheduled_at.replace("Z", "+00:00"))
41
+ entity = await runtime.get_entity(task.entity_id)
42
+ name = entity.name if entity and entity.name else "Unknown"
43
+
44
+ item = {
45
+ "entityId": str(task.entity_id),
46
+ "name": name,
47
+ "scheduledAt": task.scheduled_at,
48
+ "reason": task.reason,
49
+ "priority": task.priority,
50
+ }
51
+
52
+ if scheduled < now:
53
+ days_overdue = (now - scheduled).days
54
+ item["daysOverdue"] = str(days_overdue)
55
+ overdue_items.append(item)
56
+ else:
57
+ days_until = (scheduled - now).days
58
+ item["daysUntil"] = str(days_until)
59
+ upcoming_items.append(item)
60
+
61
+ text_summary = f"You have {len(upcoming)} follow-up(s) scheduled:\n"
62
+
63
+ if overdue_items:
64
+ text_summary += f"\nOverdue ({len(overdue_items)}):\n"
65
+ for item in overdue_items:
66
+ text_summary += f"- {item['name']} ({item['daysOverdue']} days overdue)"
67
+ if item.get("reason"):
68
+ text_summary += f" - {item['reason']}"
69
+ text_summary += "\n"
70
+
71
+ if upcoming_items:
72
+ text_summary += f"\nUpcoming ({len(upcoming_items)}):\n"
73
+ for item in upcoming_items:
74
+ days = int(item["daysUntil"])
75
+ if days == 0:
76
+ time_str = "today"
77
+ elif days == 1:
78
+ time_str = "tomorrow"
79
+ else:
80
+ time_str = f"in {days} days"
81
+ text_summary += f"- {item['name']} ({time_str})"
82
+ if item.get("reason"):
83
+ text_summary += f" - {item['reason']}"
84
+ text_summary += "\n"
85
+
86
+ suggestions = await follow_up_service.get_follow_up_suggestions()
87
+ if suggestions:
88
+ text_summary += "\nSuggested follow-ups:\n"
89
+ for s in suggestions[:3]:
90
+ text_summary += (
91
+ f"- {s.entity_name} ({s.days_since_last_contact} days since last contact)\n"
92
+ )
93
+
94
+ return ProviderResult(
95
+ text=text_summary.strip(),
96
+ values={
97
+ "followUpCount": len(upcoming),
98
+ "overdueCount": len(overdue_items),
99
+ "upcomingCount": len(upcoming_items),
100
+ "suggestionsCount": len(suggestions),
101
+ },
102
+ data={
103
+ "followUpCount": len(upcoming),
104
+ "overdueCount": len(overdue_items),
105
+ "upcomingCount": len(upcoming_items),
106
+ "suggestionsCount": len(suggestions),
107
+ },
108
+ )
109
+
110
+
111
+ follow_ups_provider = Provider(
112
+ name=_spec["name"],
113
+ description=_spec["description"],
114
+ get=get_follow_ups_context,
115
+ dynamic=_spec.get("dynamic", True),
116
+ )
@@ -0,0 +1,73 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.generated.spec_helpers import require_provider_spec
6
+ from elizaos.types import Provider, ProviderResult
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types import IAgentRuntime, Memory, State
10
+
11
+ # Get text content from centralized specs
12
+ _spec = require_provider_spec("KNOWLEDGE")
13
+
14
+
15
+ async def get_knowledge_context(
16
+ runtime: IAgentRuntime,
17
+ message: Memory,
18
+ state: State | None = None,
19
+ ) -> ProviderResult:
20
+ sections: list[str] = []
21
+ knowledge_entries: list[dict[str, str]] = []
22
+
23
+ query_text = ""
24
+ if message.content and message.content.text:
25
+ query_text = message.content.text
26
+
27
+ if not query_text:
28
+ return ProviderResult(
29
+ text="", values={"knowledgeCount": 0, "hasKnowledge": False}, data={"entries": []}
30
+ )
31
+
32
+ relevant_knowledge = await runtime.search_knowledge(
33
+ query=query_text,
34
+ limit=5,
35
+ )
36
+
37
+ for entry in relevant_knowledge:
38
+ if entry.content and entry.content.text:
39
+ knowledge_text = entry.content.text
40
+ if len(knowledge_text) > 500:
41
+ knowledge_text = knowledge_text[:500] + "..."
42
+
43
+ entry_dict = {
44
+ "id": str(entry.id) if entry.id else "",
45
+ "text": knowledge_text,
46
+ "source": str(entry.metadata.get("source", "unknown"))
47
+ if entry.metadata
48
+ else "unknown",
49
+ }
50
+ knowledge_entries.append(entry_dict)
51
+ sections.append(f"- {knowledge_text}")
52
+
53
+ context_text = "# Relevant Knowledge\n" + "\n".join(sections) if sections else ""
54
+
55
+ return ProviderResult(
56
+ text=context_text,
57
+ values={
58
+ "knowledgeCount": len(knowledge_entries),
59
+ "hasKnowledge": len(knowledge_entries) > 0,
60
+ },
61
+ data={
62
+ "entries": knowledge_entries,
63
+ "query": query_text,
64
+ },
65
+ )
66
+
67
+
68
+ knowledge_provider = Provider(
69
+ name=_spec["name"],
70
+ description=_spec["description"],
71
+ get=get_knowledge_context,
72
+ dynamic=_spec.get("dynamic", True),
73
+ )
@@ -0,0 +1,59 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.generated.spec_helpers import require_provider_spec
6
+ from elizaos.types import Provider, ProviderResult
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types import IAgentRuntime, Memory, State
10
+
11
+ # Get text content from centralized specs
12
+ _spec = require_provider_spec("PROVIDERS")
13
+
14
+
15
+ async def get_providers_list(
16
+ runtime: IAgentRuntime,
17
+ message: Memory,
18
+ state: State | None = None,
19
+ ) -> ProviderResult:
20
+ provider_info: list[dict[str, str | bool]] = []
21
+
22
+ for provider in runtime.providers:
23
+ provider_info.append(
24
+ {
25
+ "name": provider.name,
26
+ "description": getattr(provider, "description", "No description"),
27
+ "dynamic": getattr(provider, "dynamic", True),
28
+ }
29
+ )
30
+
31
+ if not provider_info:
32
+ return ProviderResult(
33
+ text="No providers available.",
34
+ values={"providerCount": 0},
35
+ data={"providers": []},
36
+ )
37
+
38
+ formatted_providers = "\n".join(f"- {p['name']}: {p['description']}" for p in provider_info)
39
+
40
+ text = f"# Available Providers\n{formatted_providers}"
41
+
42
+ return ProviderResult(
43
+ text=text,
44
+ values={
45
+ "providerCount": len(provider_info),
46
+ "providerNames": [p["name"] for p in provider_info],
47
+ },
48
+ data={
49
+ "providers": provider_info,
50
+ },
51
+ )
52
+
53
+
54
+ providers_list_provider = Provider(
55
+ name=_spec["name"],
56
+ description=_spec["description"],
57
+ get=get_providers_list,
58
+ dynamic=_spec.get("dynamic", False),
59
+ )