@elizaos/python 2.0.0-alpha.11 → 2.0.0-alpha.26

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 (57) hide show
  1. package/elizaos/advanced_capabilities/__init__.py +6 -41
  2. package/elizaos/advanced_capabilities/actions/__init__.py +1 -21
  3. package/elizaos/advanced_capabilities/actions/add_contact.py +21 -11
  4. package/elizaos/advanced_capabilities/actions/follow_room.py +28 -28
  5. package/elizaos/advanced_capabilities/actions/image_generation.py +13 -26
  6. package/elizaos/advanced_capabilities/actions/mute_room.py +13 -26
  7. package/elizaos/advanced_capabilities/actions/remove_contact.py +16 -2
  8. package/elizaos/advanced_capabilities/actions/roles.py +13 -27
  9. package/elizaos/advanced_capabilities/actions/search_contacts.py +17 -3
  10. package/elizaos/advanced_capabilities/actions/send_message.py +317 -9
  11. package/elizaos/advanced_capabilities/actions/settings.py +16 -2
  12. package/elizaos/advanced_capabilities/actions/unfollow_room.py +13 -26
  13. package/elizaos/advanced_capabilities/actions/unmute_room.py +13 -26
  14. package/elizaos/advanced_capabilities/actions/update_contact.py +16 -2
  15. package/elizaos/advanced_capabilities/actions/update_entity.py +16 -2
  16. package/elizaos/advanced_capabilities/evaluators/__init__.py +2 -9
  17. package/elizaos/advanced_capabilities/evaluators/reflection.py +3 -132
  18. package/elizaos/advanced_capabilities/evaluators/relationship_extraction.py +5 -201
  19. package/elizaos/advanced_capabilities/providers/__init__.py +1 -12
  20. package/elizaos/advanced_capabilities/providers/knowledge.py +24 -3
  21. package/elizaos/advanced_capabilities/services/__init__.py +2 -9
  22. package/elizaos/advanced_memory/actions/reset_session.py +11 -0
  23. package/elizaos/advanced_memory/evaluators/reflection.py +134 -0
  24. package/elizaos/advanced_memory/evaluators/relationship_extraction.py +203 -0
  25. package/elizaos/advanced_memory/test_advanced_memory.py +357 -0
  26. package/elizaos/advanced_planning/actions/schedule_follow_up.py +222 -0
  27. package/elizaos/basic_capabilities/__init__.py +0 -2
  28. package/elizaos/basic_capabilities/providers/__init__.py +0 -3
  29. package/elizaos/basic_capabilities/providers/agent_settings.py +64 -0
  30. package/elizaos/basic_capabilities/providers/contacts.py +79 -0
  31. package/elizaos/basic_capabilities/providers/facts.py +87 -0
  32. package/elizaos/basic_capabilities/providers/follow_ups.py +117 -0
  33. package/elizaos/basic_capabilities/providers/knowledge.py +97 -0
  34. package/elizaos/basic_capabilities/providers/relationships.py +107 -0
  35. package/elizaos/basic_capabilities/providers/roles.py +96 -0
  36. package/elizaos/basic_capabilities/providers/settings.py +56 -0
  37. package/elizaos/bootstrap/autonomy/__init__.py +5 -1
  38. package/elizaos/bootstrap/autonomy/action.py +161 -0
  39. package/elizaos/bootstrap/autonomy/evaluators.py +217 -0
  40. package/elizaos/bootstrap/autonomy/service.py +8 -0
  41. package/elizaos/bootstrap/plugin.py +7 -0
  42. package/elizaos/bootstrap/providers/knowledge.py +26 -3
  43. package/elizaos/bootstrap/services/embedding.py +156 -1
  44. package/elizaos/runtime.py +63 -18
  45. package/elizaos/services/message_service.py +173 -23
  46. package/elizaos/types/generated/eliza/v1/agent_pb2.py +16 -16
  47. package/elizaos/types/generated/eliza/v1/agent_pb2.pyi +2 -4
  48. package/elizaos/types/model.py +27 -0
  49. package/elizaos/types/runtime.py +5 -1
  50. package/elizaos/utils/validation.py +76 -0
  51. package/package.json +2 -2
  52. package/tests/test_actions_provider_examples.py +58 -1
  53. package/tests/test_async_embedding.py +124 -0
  54. package/tests/test_autonomy.py +13 -2
  55. package/tests/test_validation.py +141 -0
  56. package/tests/verify_memory_architecture.py +192 -0
  57. package/elizaos/basic_capabilities/providers/capabilities.py +0 -62
@@ -0,0 +1,79 @@
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
+ position=_spec.get("position"),
79
+ )
@@ -0,0 +1,87 @@
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
+ position=_spec.get("position"),
87
+ )
@@ -0,0 +1,117 @@
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
+ position=_spec.get("position"),
117
+ )
@@ -0,0 +1,97 @@
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
+ from elizaos.types.database import MemorySearchOptions
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("KNOWLEDGE")
14
+
15
+
16
+ async def get_knowledge_context(
17
+ runtime: IAgentRuntime,
18
+ message: Memory,
19
+ state: State | None = None,
20
+ ) -> ProviderResult:
21
+ sections: list[str] = []
22
+ knowledge_entries: list[dict[str, str]] = []
23
+
24
+ query_text = ""
25
+ if message.content and message.content.text:
26
+ query_text = message.content.text
27
+
28
+ if not query_text:
29
+ return ProviderResult(
30
+ text="", values={"knowledgeCount": 0, "hasKnowledge": False}, data={"entries": []}
31
+ )
32
+
33
+ # 1. Fetch recent messages to get embeddings
34
+ recent_messages = await runtime.get_memories(
35
+ room_id=message.room_id, limit=5, table_name="messages"
36
+ )
37
+
38
+ # 2. Extract valid embeddings
39
+ embeddings = [m.embedding for m in recent_messages if m and m.embedding]
40
+
41
+ relevant_knowledge = []
42
+ # 3. Search using the most recent embedding if available
43
+ if embeddings:
44
+ primary_embedding = embeddings[0]
45
+ params = MemorySearchOptions(
46
+ table_name="knowledge",
47
+ room_id=message.room_id,
48
+ embedding=primary_embedding,
49
+ match_threshold=0.75,
50
+ match_count=5,
51
+ unique=True,
52
+ )
53
+ relevant_knowledge = await runtime.search_memories(params)
54
+ elif query_text:
55
+ # Fallback to search_knowledge if no embeddings found?
56
+ # TS implementation might rely on search_memories logic handling missing embedding?
57
+ # No, TS skips if no embedding.
58
+ pass
59
+
60
+ for entry in relevant_knowledge:
61
+ if entry.content and entry.content.text:
62
+ knowledge_text = entry.content.text
63
+ if len(knowledge_text) > 500:
64
+ knowledge_text = knowledge_text[:500] + "..."
65
+
66
+ entry_dict = {
67
+ "id": str(entry.id) if entry.id else "",
68
+ "text": knowledge_text,
69
+ "source": str(entry.metadata.get("source", "unknown"))
70
+ if entry.metadata
71
+ else "unknown",
72
+ }
73
+ knowledge_entries.append(entry_dict)
74
+ sections.append(f"- {knowledge_text}")
75
+
76
+ context_text = "# Relevant Knowledge\n" + "\n".join(sections) if sections else ""
77
+
78
+ return ProviderResult(
79
+ text=context_text,
80
+ values={
81
+ "knowledgeCount": len(knowledge_entries),
82
+ "hasKnowledge": len(knowledge_entries) > 0,
83
+ },
84
+ data={
85
+ "entries": knowledge_entries,
86
+ "query": query_text,
87
+ },
88
+ )
89
+
90
+
91
+ knowledge_provider = Provider(
92
+ name=_spec["name"],
93
+ description=_spec["description"],
94
+ get=get_knowledge_context,
95
+ dynamic=_spec.get("dynamic", True),
96
+ position=_spec.get("position"),
97
+ )
@@ -0,0 +1,107 @@
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("RELATIONSHIPS")
13
+
14
+
15
+ def format_relationship(
16
+ relationship: dict[str, str | int | list[str] | dict[str, str]],
17
+ target_name: str,
18
+ ) -> str:
19
+ tags = relationship.get("tags", [])
20
+ tags_str = (", ".join(tags) if tags else "none") if isinstance(tags, list) else str(tags)
21
+
22
+ interactions = relationship.get("metadata", {})
23
+ interaction_count = interactions.get("interactions", 0) if isinstance(interactions, dict) else 0
24
+
25
+ return f"- {target_name}: tags=[{tags_str}], interactions={interaction_count}"
26
+
27
+
28
+ async def get_relationships(
29
+ runtime: IAgentRuntime,
30
+ message: Memory,
31
+ state: State | None = None,
32
+ ) -> ProviderResult:
33
+ entity_id = message.entity_id
34
+ if not entity_id:
35
+ return ProviderResult(
36
+ text="No relationships found.",
37
+ values={"relationshipCount": 0},
38
+ data={"relationships": []},
39
+ )
40
+
41
+ try:
42
+ relationships = await runtime.get_relationships(entity_id=entity_id)
43
+ except Exception as e:
44
+ runtime.logger.debug(
45
+ {"src": "provider:relationships", "agentId": runtime.agent_id, "error": str(e)},
46
+ "Failed to get relationships",
47
+ )
48
+ relationships = []
49
+
50
+ if not relationships:
51
+ return ProviderResult(
52
+ text="No relationships found.",
53
+ values={"relationshipCount": 0},
54
+ data={"relationships": []},
55
+ )
56
+
57
+ sorted_relationships = sorted(
58
+ relationships,
59
+ key=lambda r: (r.get("metadata", {}) or {}).get("interactions", 0),
60
+ reverse=True,
61
+ )[:30]
62
+
63
+ formatted_relationships: list[str] = []
64
+ entity_cache: dict[object, str] = {}
65
+ for rel in sorted_relationships:
66
+ target_id = rel.get("targetEntityId")
67
+ if not target_id:
68
+ continue
69
+
70
+ target_name = entity_cache.get(target_id)
71
+ if target_name is None:
72
+ target_entity = await runtime.get_entity(target_id)
73
+ target_name = target_entity.name if target_entity else str(target_id)[:8]
74
+ entity_cache[target_id] = target_name
75
+
76
+ formatted_relationships.append(format_relationship(rel, target_name))
77
+
78
+ if not formatted_relationships:
79
+ return ProviderResult(
80
+ text="No relationships found.",
81
+ values={"relationshipCount": 0},
82
+ data={"relationships": []},
83
+ )
84
+
85
+ sender_name = message.content.sender_name if message.content else "Unknown"
86
+ text = f"# {runtime.character.name} has observed {sender_name} interacting with:\n" + "\n".join(
87
+ formatted_relationships
88
+ )
89
+
90
+ return ProviderResult(
91
+ text=text,
92
+ values={
93
+ "relationshipCount": len(sorted_relationships),
94
+ },
95
+ data={
96
+ "relationships": sorted_relationships,
97
+ },
98
+ )
99
+
100
+
101
+ relationships_provider = Provider(
102
+ name=_spec["name"],
103
+ description=_spec["description"],
104
+ get=get_relationships,
105
+ dynamic=_spec.get("dynamic", True),
106
+ position=_spec.get("position"),
107
+ )
@@ -0,0 +1,96 @@
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("ROLES")
13
+
14
+
15
+ def format_role_info(entity_name: str, role: str) -> str:
16
+ return f"- {entity_name}: {role}"
17
+
18
+
19
+ async def get_roles(
20
+ runtime: IAgentRuntime,
21
+ message: Memory,
22
+ state: State | None = None,
23
+ ) -> ProviderResult:
24
+ role_info: list[dict[str, str]] = []
25
+
26
+ world_id = None
27
+ if state and hasattr(state, "world"):
28
+ world = state.world
29
+ if world and hasattr(world, "id"):
30
+ world_id = world.id
31
+
32
+ if not world_id and message.room_id:
33
+ room = await runtime.get_room(message.room_id)
34
+ if room and hasattr(room, "world_id"):
35
+ world_id = room.world_id
36
+
37
+ if world_id:
38
+ world = await runtime.get_world(world_id)
39
+ if world and hasattr(world, "metadata"):
40
+ roles = world.metadata.get("roles", {})
41
+ if isinstance(roles, dict):
42
+ for entity_id, role in roles.items():
43
+ entity = await runtime.get_entity(entity_id)
44
+ entity_name = entity.name if entity else str(entity_id)[:8]
45
+
46
+ role_info.append(
47
+ {
48
+ "entityId": str(entity_id),
49
+ "entityName": entity_name,
50
+ "role": str(role),
51
+ }
52
+ )
53
+
54
+ if message.entity_id:
55
+ entity = await runtime.get_entity(message.entity_id)
56
+ if entity and hasattr(entity, "metadata"):
57
+ sender_role = entity.metadata.get("role")
58
+ if sender_role:
59
+ existing = next(
60
+ (r for r in role_info if r["entityId"] == str(message.entity_id)), None
61
+ )
62
+ if not existing:
63
+ role_info.append(
64
+ {
65
+ "entityId": str(message.entity_id),
66
+ "entityName": entity.name or "Unknown",
67
+ "role": str(sender_role),
68
+ }
69
+ )
70
+
71
+ if not role_info:
72
+ return ProviderResult(text="", values={"roleCount": 0}, data={"roles": []})
73
+
74
+ formatted_roles = "\n".join(format_role_info(r["entityName"], r["role"]) for r in role_info)
75
+
76
+ text = f"# Entity Roles\n{formatted_roles}"
77
+
78
+ return ProviderResult(
79
+ text=text,
80
+ values={
81
+ "roleCount": len(role_info),
82
+ "roles": {r["entityName"]: r["role"] for r in role_info},
83
+ },
84
+ data={
85
+ "roles": role_info,
86
+ },
87
+ )
88
+
89
+
90
+ roles_provider = Provider(
91
+ name=_spec["name"],
92
+ description=_spec["description"],
93
+ get=get_roles,
94
+ dynamic=_spec.get("dynamic", True),
95
+ position=_spec.get("position"),
96
+ )
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from elizaos.bootstrap.providers.agent_settings import SENSITIVE_KEY_PATTERNS
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("SETTINGS")
14
+
15
+
16
+ async def get_settings_context(
17
+ runtime: IAgentRuntime,
18
+ message: Memory,
19
+ state: State | None = None,
20
+ ) -> ProviderResult:
21
+ _ = message, state
22
+
23
+ all_settings = runtime.get_all_settings()
24
+
25
+ safe_settings: dict[str, str] = {}
26
+ for key, value in all_settings.items():
27
+ if not any(pattern in key.lower() for pattern in SENSITIVE_KEY_PATTERNS):
28
+ safe_settings[key] = str(value)
29
+
30
+ lines: list[str] = []
31
+ if safe_settings:
32
+ lines.append("## Current Configuration")
33
+ for key, value in safe_settings.items():
34
+ display_value = value if len(value) <= 50 else value[:50] + "..."
35
+ lines.append(f"- {key}: {display_value}")
36
+
37
+ context_text = "\n".join(lines) if lines else ""
38
+
39
+ return ProviderResult(
40
+ text=context_text,
41
+ values={
42
+ "settings": context_text,
43
+ "settingsCount": len(safe_settings),
44
+ "hasSettings": len(safe_settings) > 0,
45
+ },
46
+ data={"settings": safe_settings},
47
+ )
48
+
49
+
50
+ settings_provider = Provider(
51
+ name=_spec["name"],
52
+ description=_spec["description"],
53
+ get=get_settings_context,
54
+ dynamic=_spec.get("dynamic", True),
55
+ position=_spec.get("position"),
56
+ )
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from .action import send_to_admin_action
3
+ from .action import disable_autonomy_action, enable_autonomy_action, send_to_admin_action
4
+ from .evaluators import post_action_evaluator
4
5
  from .providers import admin_chat_provider, autonomy_status_provider
5
6
  from .routes import autonomy_routes
6
7
  from .service import AUTONOMY_SERVICE_TYPE, AutonomyService
@@ -12,6 +13,9 @@ __all__ = [
12
13
  "AutonomyService",
13
14
  "AUTONOMY_SERVICE_TYPE",
14
15
  "send_to_admin_action",
16
+ "enable_autonomy_action",
17
+ "disable_autonomy_action",
18
+ "post_action_evaluator",
15
19
  "admin_chat_provider",
16
20
  "autonomy_status_provider",
17
21
  "autonomy_routes",