@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,90 @@
1
+ from __future__ import annotations
2
+
3
+ from elizaos.types import Provider, ProviderResult
4
+
5
+
6
+ async def long_term_memory_get(runtime, message, _state=None) -> ProviderResult:
7
+ svc = runtime.get_service("memory")
8
+ if svc is None:
9
+ return ProviderResult(text="", values={"longTermMemories": ""}, data={"memoryCount": 0})
10
+
11
+ entity_id = message.entity_id
12
+ if entity_id == runtime.agent_id:
13
+ return ProviderResult(text="", values={"longTermMemories": ""}, data={"memoryCount": 0})
14
+
15
+ memories = await svc.get_long_term_memories(entity_id, None, 25)
16
+ if not memories:
17
+ return ProviderResult(text="", values={"longTermMemories": ""}, data={"memoryCount": 0})
18
+
19
+ formatted = await svc.get_formatted_long_term_memories(entity_id)
20
+ text = f"# What I Know About You\n\n{formatted}"
21
+
22
+ category_counts: dict[str, int] = {}
23
+ for m in memories:
24
+ category_counts[m.category.value] = category_counts.get(m.category.value, 0) + 1
25
+ category_list = ", ".join(f"{k}: {v}" for k, v in category_counts.items())
26
+
27
+ return ProviderResult(
28
+ text=text,
29
+ values={"longTermMemories": text, "memoryCategories": category_list},
30
+ data={"memoryCount": len(memories), "categories": category_list},
31
+ )
32
+
33
+
34
+ async def context_summary_get(runtime, message, _state=None) -> ProviderResult:
35
+ svc = runtime.get_service("memory")
36
+ if svc is None:
37
+ return ProviderResult(
38
+ text="",
39
+ values={"sessionSummaries": "", "sessionSummariesWithTopics": ""},
40
+ data={},
41
+ )
42
+
43
+ current = await svc.get_current_session_summary(message.room_id)
44
+ if current is None:
45
+ return ProviderResult(
46
+ text="",
47
+ values={"sessionSummaries": "", "sessionSummariesWithTopics": ""},
48
+ data={},
49
+ )
50
+
51
+ summary_only = (
52
+ f"**Previous Conversation** ({current.message_count} messages)\n{current.summary}"
53
+ )
54
+ summary_with_topics = (
55
+ summary_only + f"\n*Topics: {', '.join(current.topics)}*"
56
+ if current.topics
57
+ else summary_only
58
+ )
59
+ session_summaries = f"# Conversation Summary\n\n{summary_only}" if summary_only else ""
60
+ session_summaries_with_topics = (
61
+ f"# Conversation Summary\n\n{summary_with_topics}" if summary_with_topics else ""
62
+ )
63
+
64
+ return ProviderResult(
65
+ text=session_summaries_with_topics,
66
+ values={
67
+ "sessionSummaries": session_summaries,
68
+ "sessionSummariesWithTopics": session_summaries_with_topics,
69
+ },
70
+ data={
71
+ "summaryText": current.summary,
72
+ "messageCount": current.message_count,
73
+ "topics": ", ".join(current.topics),
74
+ },
75
+ )
76
+
77
+
78
+ long_term_memory_provider = Provider(
79
+ name="LONG_TERM_MEMORY",
80
+ description="Persistent facts and preferences about the user",
81
+ position=50,
82
+ get=long_term_memory_get,
83
+ )
84
+
85
+ context_summary_provider = Provider(
86
+ name="SUMMARIZED_CONTEXT",
87
+ description="Provides summarized context from previous conversations",
88
+ position=96,
89
+ get=context_summary_get,
90
+ )
@@ -0,0 +1,65 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from enum import Enum
5
+ from uuid import UUID
6
+
7
+
8
+ class LongTermMemoryCategory(str, Enum):
9
+ EPISODIC = "episodic"
10
+ SEMANTIC = "semantic"
11
+ PROCEDURAL = "procedural"
12
+
13
+
14
+ @dataclass
15
+ class MemoryConfig:
16
+ short_term_summarization_threshold: int = 16
17
+ short_term_retain_recent: int = 6
18
+ short_term_summarization_interval: int = 10
19
+ long_term_extraction_enabled: bool = True
20
+ long_term_vector_search_enabled: bool = False
21
+ long_term_confidence_threshold: float = 0.85
22
+ long_term_extraction_threshold: int = 30
23
+ long_term_extraction_interval: int = 10
24
+ summary_model_type: str = "TEXT_LARGE"
25
+ summary_max_tokens: int = 2500
26
+ summary_max_new_messages: int = 20
27
+
28
+
29
+ @dataclass
30
+ class LongTermMemory:
31
+ id: UUID
32
+ agent_id: UUID
33
+ entity_id: UUID
34
+ category: LongTermMemoryCategory
35
+ content: str
36
+ confidence: float = 1.0
37
+ source: str | None = None
38
+ metadata: dict[str, object] = field(default_factory=dict)
39
+
40
+
41
+ @dataclass
42
+ class SessionSummary:
43
+ id: UUID
44
+ agent_id: UUID
45
+ room_id: UUID
46
+ entity_id: UUID | None
47
+ summary: str
48
+ message_count: int
49
+ last_message_offset: int
50
+ topics: list[str] = field(default_factory=list)
51
+ metadata: dict[str, object] = field(default_factory=dict)
52
+
53
+
54
+ @dataclass
55
+ class SummaryResult:
56
+ summary: str
57
+ topics: list[str]
58
+ key_points: list[str]
59
+
60
+
61
+ @dataclass
62
+ class MemoryExtraction:
63
+ category: LongTermMemoryCategory
64
+ content: str
65
+ confidence: float
@@ -0,0 +1,10 @@
1
+ """Built-in advanced planning (gated by Character.advancedPlanning)."""
2
+
3
+ from .planning_service import PlanningService
4
+ from .plugin import advanced_planning_plugin, create_advanced_planning_plugin
5
+
6
+ __all__ = [
7
+ "advanced_planning_plugin",
8
+ "create_advanced_planning_plugin",
9
+ "PlanningService",
10
+ ]
@@ -0,0 +1,145 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ import time
5
+ from uuid import uuid4
6
+
7
+ from elizaos.types import Action, ActionResult
8
+
9
+
10
+ async def _always_validate(_runtime, _message, _state=None) -> bool:
11
+ return True
12
+
13
+
14
+ async def analyze_input_handler(
15
+ _runtime, message, _state=None, options=None, _callback=None, _responses=None
16
+ ):
17
+ abort_signal = getattr(options, "abort_signal", None)
18
+ if abort_signal is not None and getattr(abort_signal, "aborted", False):
19
+ raise RuntimeError("Analysis aborted")
20
+
21
+ text = message.content.text or ""
22
+ words = text.split() if text.strip() else []
23
+ sentiment = "neutral"
24
+ lower = text.lower()
25
+ if any(w in lower for w in ["urgent", "emergency", "critical"]):
26
+ sentiment = "urgent"
27
+ elif "good" in lower:
28
+ sentiment = "positive"
29
+ elif "bad" in lower:
30
+ sentiment = "negative"
31
+
32
+ return ActionResult(
33
+ success=True,
34
+ text=f"Analyzed {len(words)} words with {sentiment} sentiment",
35
+ data={
36
+ "wordCount": len(words),
37
+ "hasNumbers": bool(re.search(r"\d", text)),
38
+ "sentiment": sentiment,
39
+ "topics": [w.lower() for w in words if len(w) >= 5],
40
+ "timestamp": int(time.time() * 1000),
41
+ },
42
+ )
43
+
44
+
45
+ async def process_analysis_handler(
46
+ _runtime, _message, _state=None, options=None, _callback=None, _responses=None
47
+ ):
48
+ previous = getattr(options, "previous_results", None) or []
49
+ prev0 = previous[0] if previous else None
50
+ analysis = getattr(prev0, "data", None) or {}
51
+ word_count = int(analysis.get("wordCount") or 0)
52
+ sentiment = str(analysis.get("sentiment") or "neutral")
53
+
54
+ decisions = {
55
+ "needsMoreInfo": word_count < 5,
56
+ "isComplex": word_count > 20,
57
+ "requiresAction": sentiment != "neutral" or word_count > 8,
58
+ "suggestedResponse": (
59
+ "Thank you for the positive feedback!"
60
+ if sentiment == "positive"
61
+ else "I understand your concerns and will help address them."
62
+ if sentiment == "negative"
63
+ else "I can help you with that."
64
+ ),
65
+ }
66
+
67
+ return ActionResult(
68
+ success=True,
69
+ text=str(decisions["suggestedResponse"]),
70
+ data={
71
+ "analysis": analysis,
72
+ "decisions": decisions,
73
+ "processedAt": int(time.time() * 1000),
74
+ "shouldContinue": not decisions["needsMoreInfo"],
75
+ },
76
+ )
77
+
78
+
79
+ async def execute_final_handler(
80
+ _runtime, _message, _state=None, options=None, callback=None, _responses=None
81
+ ):
82
+ previous = getattr(options, "previous_results", None) or []
83
+ decisions = None
84
+ for r in previous:
85
+ data = getattr(r, "data", None) or {}
86
+ if "decisions" in data:
87
+ decisions = data.get("decisions")
88
+ break
89
+ if not isinstance(decisions, dict):
90
+ raise RuntimeError("No processing results available")
91
+
92
+ msg = str(decisions.get("suggestedResponse") or "Done")
93
+ if callback is not None:
94
+ await callback({"text": msg, "source": "chain_example"})
95
+
96
+ return ActionResult(success=True, text=msg, data={"action": "RESPOND", "message": msg})
97
+
98
+
99
+ async def create_plan_validate(_runtime, message, _state=None) -> bool:
100
+ text = (message.content.text or "").lower()
101
+ return any(k in text for k in ["plan", "project", "comprehensive", "organize", "strategy"])
102
+
103
+
104
+ async def create_plan_handler(
105
+ _runtime, _message, _state=None, _options=None, callback=None, _responses=None
106
+ ):
107
+ plan_id = str(uuid4())
108
+ if callback is not None:
109
+ await callback(
110
+ {
111
+ "text": "I've created a comprehensive project plan.",
112
+ "actions": ["CREATE_PLAN"],
113
+ "source": "planning",
114
+ }
115
+ )
116
+ return ActionResult(success=True, text="Created plan", data={"planId": plan_id})
117
+
118
+
119
+ analyze_input_action = Action(
120
+ name="ANALYZE_INPUT",
121
+ description="Analyzes user input and extracts key information",
122
+ validate=_always_validate,
123
+ handler=analyze_input_handler,
124
+ )
125
+
126
+ process_analysis_action = Action(
127
+ name="PROCESS_ANALYSIS",
128
+ description="Processes the analysis results and makes decisions",
129
+ validate=_always_validate,
130
+ handler=process_analysis_handler,
131
+ )
132
+
133
+ execute_final_action = Action(
134
+ name="EXECUTE_FINAL",
135
+ description="Executes the final action based on processing results",
136
+ validate=_always_validate,
137
+ handler=execute_final_handler,
138
+ )
139
+
140
+ create_plan_action = Action(
141
+ name="CREATE_PLAN",
142
+ description="Creates a comprehensive project plan",
143
+ validate=create_plan_validate,
144
+ handler=create_plan_handler,
145
+ )
@@ -0,0 +1,127 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+
5
+ from elizaos.types import Provider, ProviderResult
6
+ from elizaos.types.model import ModelType
7
+
8
+ from .prompts import MESSAGE_CLASSIFIER_TEMPLATE
9
+
10
+
11
+ async def get_message_classification(runtime, message, _state=None) -> ProviderResult:
12
+ text = message.content.text or ""
13
+
14
+ if not text.strip():
15
+ return ProviderResult(
16
+ text="Message classified as: general (empty message)",
17
+ data={
18
+ "classification": "general",
19
+ "confidence": 0.1,
20
+ "complexity": "simple",
21
+ "planningRequired": False,
22
+ "stakeholders": [],
23
+ "constraints": [],
24
+ },
25
+ )
26
+
27
+ try:
28
+ prompt = MESSAGE_CLASSIFIER_TEMPLATE.format(text=text)
29
+ response = await runtime.use_model(
30
+ ModelType.TEXT_SMALL,
31
+ {
32
+ "prompt": prompt,
33
+ "temperature": 0.3,
34
+ "maxTokens": 300,
35
+ },
36
+ )
37
+
38
+ response_text = str(response)
39
+ lines = response_text.splitlines()
40
+
41
+ def _parse_list(prefix: str) -> list[str]:
42
+ line = next((ln for ln in lines if ln.startswith(prefix)), "")
43
+ if not line:
44
+ return []
45
+ raw = line[len(prefix) :].strip()
46
+ if not raw:
47
+ return []
48
+ return [s.strip() for s in raw.split(",") if s.strip()]
49
+
50
+ complexity = next(
51
+ (ln[len("COMPLEXITY:") :].strip() for ln in lines if ln.startswith("COMPLEXITY:")),
52
+ "simple",
53
+ )
54
+ planning_type = next(
55
+ (ln[len("PLANNING:") :].strip() for ln in lines if ln.startswith("PLANNING:")),
56
+ "direct_action",
57
+ )
58
+ confidence_str = next(
59
+ (ln[len("CONFIDENCE:") :].strip() for ln in lines if ln.startswith("CONFIDENCE:")),
60
+ "0.5",
61
+ )
62
+ try:
63
+ confidence = float(confidence_str)
64
+ except Exception:
65
+ confidence = 0.5
66
+ confidence = max(0.0, min(1.0, confidence))
67
+
68
+ capabilities = _parse_list("CAPABILITIES:")
69
+ stakeholders = _parse_list("STAKEHOLDERS:")
70
+ constraints = _parse_list("CONSTRAINTS:")
71
+ dependencies = _parse_list("DEPENDENCIES:")
72
+
73
+ planning_required = planning_type != "direct_action" and complexity != "simple"
74
+
75
+ classification = "general"
76
+ lower = text.lower()
77
+ if "strategic" in lower or planning_type == "strategic_planning":
78
+ classification = "strategic"
79
+ elif "analyz" in lower:
80
+ classification = "analysis"
81
+ elif "process" in lower:
82
+ classification = "processing"
83
+ elif "execute" in lower:
84
+ classification = "execution"
85
+
86
+ return ProviderResult(
87
+ text=f"Message classified as: {classification} ({complexity} complexity, {planning_type}) with confidence: {confidence}",
88
+ data={
89
+ "classification": classification,
90
+ "confidence": confidence,
91
+ "originalText": text,
92
+ "complexity": complexity,
93
+ "planningType": planning_type,
94
+ "planningRequired": planning_required,
95
+ "capabilities": capabilities,
96
+ "stakeholders": stakeholders,
97
+ "constraints": constraints,
98
+ "dependencies": dependencies,
99
+ "analyzedAt": int(time.time() * 1000),
100
+ "modelUsed": "TEXT_SMALL",
101
+ },
102
+ )
103
+ except Exception as e:
104
+ return ProviderResult(
105
+ text="Message classified as: general with confidence: 0.5 (fallback)",
106
+ data={
107
+ "classification": "general",
108
+ "confidence": 0.5,
109
+ "originalText": text,
110
+ "complexity": "simple",
111
+ "planningRequired": False,
112
+ "planningType": "direct_action",
113
+ "capabilities": [],
114
+ "stakeholders": [],
115
+ "constraints": [],
116
+ "dependencies": [],
117
+ "error": str(e),
118
+ "fallback": True,
119
+ },
120
+ )
121
+
122
+
123
+ message_classifier_provider = Provider(
124
+ name="messageClassifier",
125
+ description="Classifies messages by complexity and planning requirements",
126
+ get=get_message_classification,
127
+ )