@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,393 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Awaitable, Callable
4
+ from enum import Enum
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class LLMMode(str, Enum):
11
+ DEFAULT = "DEFAULT"
12
+ SMALL = "SMALL"
13
+ LARGE = "LARGE"
14
+
15
+
16
+ class ModelType(str, Enum):
17
+ # Text generation models
18
+ TEXT_SMALL = "TEXT_SMALL"
19
+ TEXT_LARGE = "TEXT_LARGE"
20
+ TEXT_COMPLETION = "TEXT_COMPLETION"
21
+
22
+ # Streaming text generation models
23
+ TEXT_SMALL_STREAM = "TEXT_SMALL_STREAM"
24
+ TEXT_LARGE_STREAM = "TEXT_LARGE_STREAM"
25
+
26
+ # Reasoning models (note: values are REASONING_*, not TEXT_REASONING_*)
27
+ TEXT_REASONING_SMALL = "REASONING_SMALL"
28
+ TEXT_REASONING_LARGE = "REASONING_LARGE"
29
+
30
+ # Tokenization models
31
+ TEXT_TOKENIZER_ENCODE = "TEXT_TOKENIZER_ENCODE"
32
+ TEXT_TOKENIZER_DECODE = "TEXT_TOKENIZER_DECODE"
33
+
34
+ # Embedding models
35
+ TEXT_EMBEDDING = "TEXT_EMBEDDING"
36
+
37
+ # Image models
38
+ IMAGE = "IMAGE"
39
+ IMAGE_DESCRIPTION = "IMAGE_DESCRIPTION"
40
+
41
+ # Audio models
42
+ TRANSCRIPTION = "TRANSCRIPTION"
43
+ TEXT_TO_SPEECH = "TEXT_TO_SPEECH"
44
+ AUDIO = "AUDIO"
45
+
46
+ # Video models
47
+ VIDEO = "VIDEO"
48
+
49
+ # Object generation models
50
+ OBJECT_SMALL = "OBJECT_SMALL"
51
+ OBJECT_LARGE = "OBJECT_LARGE"
52
+
53
+ # Research models (deep research)
54
+ RESEARCH = "RESEARCH"
55
+
56
+
57
+ # Type for model type names - allows string for extensibility
58
+ ModelTypeName = str
59
+
60
+ # Union type of text generation model types
61
+ TextGenerationModelType = str # TEXT_SMALL, TEXT_LARGE, REASONING_*, TEXT_COMPLETION
62
+
63
+ # ModelHandler uses Any at runtime to avoid circular imports.
64
+ # Type checkers will see the proper type from the TYPE_CHECKING block.
65
+ if TYPE_CHECKING:
66
+ ModelHandler = Callable[["IAgentRuntime", object], Awaitable[object]]
67
+ else:
68
+ ModelHandler = Callable[[Any, object], Awaitable[object]]
69
+
70
+
71
+ class ModelSettings(BaseModel):
72
+ """Settings for a specific model type."""
73
+
74
+ model: str | None = Field(default=None, description="Model identifier")
75
+ max_tokens: int | None = Field(default=None, alias="maxTokens", description="Maximum tokens")
76
+ temperature: float | None = Field(default=None, description="Temperature setting")
77
+ top_p: float | None = Field(default=None, alias="topP", description="Top P setting")
78
+ top_k: int | None = Field(default=None, alias="topK", description="Top K setting")
79
+ min_p: float | None = Field(default=None, alias="minP", description="Minimum P setting")
80
+ seed: int | None = Field(default=None, description="Random seed for reproducibility")
81
+ repetition_penalty: float | None = Field(
82
+ default=None, alias="repetitionPenalty", description="Repetition penalty"
83
+ )
84
+ frequency_penalty: float | None = Field(
85
+ default=None, alias="frequencyPenalty", description="Frequency penalty"
86
+ )
87
+ presence_penalty: float | None = Field(
88
+ default=None, alias="presencePenalty", description="Presence penalty"
89
+ )
90
+ stop_sequences: list[str] | None = Field(
91
+ default=None, alias="stopSequences", description="Stop sequences"
92
+ )
93
+
94
+ model_config = {"populate_by_name": True, "extra": "allow"}
95
+
96
+
97
+ # Model parameters map type - maps model types to their parameter types
98
+ ModelParamsMap = dict[ModelType, dict[str, Any]]
99
+
100
+ # Model result map type - maps model types to their result types
101
+ ModelResultMap = dict[ModelType, Any]
102
+
103
+ # Stream chunk callback type
104
+ StreamChunkCallback = Callable[[str, str | None], Awaitable[None] | None]
105
+
106
+
107
+ class GenerateTextParams(BaseModel):
108
+ prompt: str = Field(..., description="The input prompt for text generation")
109
+ max_tokens: int | None = Field(
110
+ default=None, alias="maxTokens", description="Maximum tokens to generate"
111
+ )
112
+ min_tokens: int | None = Field(
113
+ default=None, alias="minTokens", description="Minimum tokens to generate"
114
+ )
115
+ temperature: float | None = Field(default=None, description="Controls randomness (0.0-1.0)")
116
+ top_p: float | None = Field(
117
+ default=None, alias="topP", description="Nucleus sampling parameter (0.0-1.0)"
118
+ )
119
+ top_k: int | None = Field(
120
+ default=None, alias="topK", description="Limits highest-probability tokens considered"
121
+ )
122
+ min_p: float | None = Field(
123
+ default=None, alias="minP", description="Minimum probability threshold (0.0-1.0)"
124
+ )
125
+ seed: int | None = Field(default=None, description="Random seed for reproducible outputs")
126
+ repetition_penalty: float | None = Field(
127
+ default=None, alias="repetitionPenalty", description="Repetition penalty (1.0 = no penalty)"
128
+ )
129
+ frequency_penalty: float | None = Field(
130
+ default=None, alias="frequencyPenalty", description="Penalizes based on frequency"
131
+ )
132
+ presence_penalty: float | None = Field(
133
+ default=None, alias="presencePenalty", description="Penalizes based on presence"
134
+ )
135
+ stop_sequences: list[str] | None = Field(
136
+ default=None, alias="stopSequences", description="Sequences to stop generation"
137
+ )
138
+ user: str | None = Field(default=None, description="User identifier for tracking/analytics")
139
+ response_format: dict[str, str] | str | None = Field(
140
+ default=None, alias="responseFormat", description="Response format specification"
141
+ )
142
+ stream: bool | None = Field(default=None, description="Enable streaming mode")
143
+
144
+ model_config = {"populate_by_name": True, "extra": "allow"}
145
+
146
+
147
+ class GenerateTextOptions(BaseModel):
148
+ """Options for the simplified generateText API."""
149
+
150
+ include_character: bool | None = Field(
151
+ default=None, alias="includeCharacter", description="Include character personality"
152
+ )
153
+ model_type: str | None = Field(default=None, alias="modelType", description="Model type to use")
154
+ max_tokens: int | None = Field(default=None, alias="maxTokens", description="Maximum tokens")
155
+ temperature: float | None = Field(default=None, description="Temperature")
156
+ top_p: float | None = Field(default=None, alias="topP", description="Top P setting")
157
+ frequency_penalty: float | None = Field(
158
+ default=None, alias="frequencyPenalty", description="Frequency penalty"
159
+ )
160
+ presence_penalty: float | None = Field(
161
+ default=None, alias="presencePenalty", description="Presence penalty"
162
+ )
163
+ stop_sequences: list[str] | None = Field(
164
+ default=None, alias="stopSequences", description="Stop sequences"
165
+ )
166
+
167
+ model_config = {"populate_by_name": True, "extra": "allow"}
168
+
169
+
170
+ class GenerateTextResult(BaseModel):
171
+ text: str = Field(..., description="Generated text")
172
+
173
+ model_config = {"populate_by_name": True}
174
+
175
+
176
+ class TokenUsage(BaseModel):
177
+ """Token usage information from a model response."""
178
+
179
+ prompt_tokens: int = Field(..., alias="promptTokens", description="Tokens in input prompt")
180
+ completion_tokens: int = Field(
181
+ ..., alias="completionTokens", description="Tokens in generated response"
182
+ )
183
+ total_tokens: int = Field(..., alias="totalTokens", description="Total tokens used")
184
+
185
+ model_config = {"populate_by_name": True}
186
+
187
+
188
+ class TextStreamChunk(BaseModel):
189
+ text: str = Field(..., description="Text chunk")
190
+ done: bool = Field(default=False, description="Whether this is the final chunk")
191
+
192
+ model_config = {"populate_by_name": True}
193
+
194
+
195
+ class TokenizeTextParams(BaseModel):
196
+ prompt: str = Field(..., description="Text to tokenize")
197
+ model_type: str = Field(..., alias="modelType", description="Model type for tokenization")
198
+
199
+ model_config = {"populate_by_name": True}
200
+
201
+
202
+ class DetokenizeTextParams(BaseModel):
203
+ tokens: list[int] = Field(..., description="Tokens to convert to text")
204
+ model_type: str = Field(..., alias="modelType", description="Model type for detokenization")
205
+
206
+ model_config = {"populate_by_name": True}
207
+
208
+
209
+ class TextEmbeddingParams(BaseModel):
210
+ """Parameters for text embedding."""
211
+
212
+ text: str = Field(..., description="Text to create embeddings for")
213
+
214
+ model_config = {"populate_by_name": True}
215
+
216
+
217
+ class ImageGenerationParams(BaseModel):
218
+ """Parameters for image generation."""
219
+
220
+ prompt: str = Field(..., description="Prompt describing the image")
221
+ size: str | None = Field(default=None, description="Image dimensions")
222
+ count: int | None = Field(default=None, description="Number of images to generate")
223
+
224
+ model_config = {"populate_by_name": True}
225
+
226
+
227
+ class ImageDescriptionParams(BaseModel):
228
+ image_url: str = Field(..., alias="imageUrl", description="URL of the image")
229
+ prompt: str | None = Field(default=None, description="Optional guiding prompt")
230
+
231
+ model_config = {"populate_by_name": True}
232
+
233
+
234
+ class ImageDescriptionResult(BaseModel):
235
+ title: str = Field(..., description="Image title")
236
+ description: str = Field(..., description="Image description")
237
+
238
+ model_config = {"populate_by_name": True}
239
+
240
+
241
+ class TranscriptionParams(BaseModel):
242
+ """Parameters for audio transcription."""
243
+
244
+ audio_url: str = Field(..., alias="audioUrl", description="URL of audio file")
245
+ prompt: str | None = Field(default=None, description="Optional guiding prompt")
246
+
247
+ model_config = {"populate_by_name": True}
248
+
249
+
250
+ class TextToSpeechParams(BaseModel):
251
+ text: str = Field(..., description="Text to convert to speech")
252
+ voice: str | None = Field(default=None, description="Voice to use")
253
+ speed: float | None = Field(default=None, description="Speaking speed")
254
+
255
+ model_config = {"populate_by_name": True}
256
+
257
+
258
+ class ObjectGenerationParams(BaseModel):
259
+ """Parameters for object generation models."""
260
+
261
+ prompt: str = Field(..., description="Prompt describing the object")
262
+ schema_def: dict[str, Any] | None = Field(
263
+ default=None, alias="schema", description="JSON schema for validation"
264
+ )
265
+ output: str | None = Field(
266
+ default=None, description="Output type: 'object', 'array', or 'enum'"
267
+ )
268
+ enum_values: list[str] | None = Field(
269
+ default=None, alias="enumValues", description="Allowed values for enum type"
270
+ )
271
+ model_type: str | None = Field(default=None, alias="modelType", description="Model type")
272
+ temperature: float | None = Field(default=None, description="Temperature")
273
+ max_tokens: int | None = Field(default=None, alias="maxTokens", description="Maximum tokens")
274
+ stop_sequences: list[str] | None = Field(
275
+ default=None, alias="stopSequences", description="Stop sequences"
276
+ )
277
+
278
+ model_config = {"populate_by_name": True, "extra": "allow"}
279
+
280
+
281
+ # ============================================================================
282
+ # Research Model Types (Deep Research)
283
+ # ============================================================================
284
+
285
+
286
+ class ResearchWebSearchTool(BaseModel):
287
+ """Research tool configuration for web search."""
288
+
289
+ type: str = Field(default="web_search_preview", description="Tool type")
290
+
291
+ model_config = {"populate_by_name": True}
292
+
293
+
294
+ class ResearchFileSearchTool(BaseModel):
295
+ """Research tool configuration for file search over vector stores."""
296
+
297
+ type: str = Field(default="file_search", description="Tool type")
298
+ vector_store_ids: list[str] = Field(
299
+ ..., alias="vectorStoreIds", description="Vector store IDs (max 2)"
300
+ )
301
+
302
+ model_config = {"populate_by_name": True}
303
+
304
+
305
+ class ResearchCodeInterpreterTool(BaseModel):
306
+ """Research tool configuration for code interpreter."""
307
+
308
+ type: str = Field(default="code_interpreter", description="Tool type")
309
+ container: dict[str, str] | None = Field(default=None, description="Container configuration")
310
+
311
+ model_config = {"populate_by_name": True}
312
+
313
+
314
+ class ResearchMcpTool(BaseModel):
315
+ """Research tool configuration for remote MCP servers."""
316
+
317
+ type: str = Field(default="mcp", description="Tool type")
318
+ server_label: str = Field(..., alias="serverLabel", description="MCP server label")
319
+ server_url: str = Field(..., alias="serverUrl", description="MCP server URL")
320
+ require_approval: str | None = Field(
321
+ default="never", alias="requireApproval", description="Approval mode"
322
+ )
323
+
324
+ model_config = {"populate_by_name": True}
325
+
326
+
327
+ # Union type for research tools
328
+ ResearchTool = (
329
+ ResearchWebSearchTool | ResearchFileSearchTool | ResearchCodeInterpreterTool | ResearchMcpTool
330
+ )
331
+
332
+
333
+ class ResearchParams(BaseModel):
334
+ """
335
+ Parameters for deep research models (o3-deep-research, o4-mini-deep-research).
336
+
337
+ Deep research models can find, analyze, and synthesize hundreds of sources
338
+ to create comprehensive reports.
339
+ """
340
+
341
+ input: str = Field(..., description="The research input/question")
342
+ instructions: str | None = Field(
343
+ default=None, description="Optional instructions to guide research"
344
+ )
345
+ background: bool | None = Field(
346
+ default=None, description="Run in background mode for long tasks"
347
+ )
348
+ tools: list[ResearchTool] | None = Field(
349
+ default=None,
350
+ description="Research tools (web_search_preview, file_search, mcp, code_interpreter)",
351
+ )
352
+ max_tool_calls: int | None = Field(
353
+ default=None, alias="maxToolCalls", description="Maximum number of tool calls"
354
+ )
355
+ reasoning_summary: str | None = Field(
356
+ default=None,
357
+ alias="reasoningSummary",
358
+ description="Include reasoning summary ('auto' or 'none')",
359
+ )
360
+ model: str | None = Field(
361
+ default=None, description="Model variant (o3-deep-research or o4-mini-deep-research)"
362
+ )
363
+
364
+ model_config = {"populate_by_name": True, "extra": "allow"}
365
+
366
+
367
+ class ResearchAnnotation(BaseModel):
368
+ """Annotation in research results, linking text to sources."""
369
+
370
+ url: str = Field(..., description="URL of the source")
371
+ title: str = Field(..., description="Title of the source")
372
+ start_index: int = Field(..., alias="startIndex", description="Start index in text")
373
+ end_index: int = Field(..., alias="endIndex", description="End index in text")
374
+
375
+ model_config = {"populate_by_name": True}
376
+
377
+
378
+ class ResearchResult(BaseModel):
379
+ """Result from a deep research model request."""
380
+
381
+ id: str = Field(..., description="Unique response identifier")
382
+ text: str = Field(..., description="Final research report with inline citations")
383
+ annotations: list[ResearchAnnotation] = Field(
384
+ default_factory=list, description="Annotations linking text to sources"
385
+ )
386
+ output_items: list[dict[str, Any]] = Field(
387
+ default_factory=list,
388
+ alias="outputItems",
389
+ description="Output items showing research process",
390
+ )
391
+ status: str | None = Field(default=None, description="Status for background requests")
392
+
393
+ model_config = {"populate_by_name": True}
@@ -0,0 +1,188 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncIterator, Awaitable, Callable
4
+ from typing import TYPE_CHECKING, Any, Literal
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ if TYPE_CHECKING:
9
+ from elizaos.types.agent import Character
10
+ from elizaos.types.components import Action, Evaluator, Provider
11
+ from elizaos.types.database import IDatabaseAdapter
12
+ from elizaos.types.runtime import IAgentRuntime
13
+ from elizaos.types.service import Service
14
+
15
+ # Type for streaming model handlers
16
+ StreamingModelHandler = Callable[["IAgentRuntime", dict[str, Any]], AsyncIterator[str]]
17
+
18
+
19
+ class RouteRequest(BaseModel):
20
+ body: Any | None = Field(default=None, description="Request body")
21
+ params: dict[str, str] | None = Field(default=None, description="Route parameters")
22
+ query: dict[str, Any] | None = Field(default=None, description="Query parameters")
23
+ headers: dict[str, str | list[str] | None] | None = Field(
24
+ default=None, description="Request headers"
25
+ )
26
+ method: str | None = Field(default=None, description="HTTP method")
27
+ path: str | None = Field(default=None, description="Request path")
28
+ url: str | None = Field(default=None, description="Full URL")
29
+
30
+ model_config = {"extra": "allow"}
31
+
32
+
33
+ class RouteResponse:
34
+ def __init__(self) -> None:
35
+ self._status_code: int = 200
36
+ self._headers: dict[str, str | list[str]] = {}
37
+ self._body: Any = None
38
+ self.headers_sent: bool = False
39
+
40
+ def status(self, code: int) -> RouteResponse:
41
+ self._status_code = code
42
+ return self
43
+
44
+ def json(self, data: Any) -> RouteResponse:
45
+ self._body = data
46
+ return self
47
+
48
+ def send(self, data: Any) -> RouteResponse:
49
+ self._body = data
50
+ return self
51
+
52
+ def end(self) -> RouteResponse:
53
+ self.headers_sent = True
54
+ return self
55
+
56
+ def set_header(self, name: str, value: str | list[str]) -> RouteResponse:
57
+ self._headers[name] = value
58
+ return self
59
+
60
+
61
+ # Route handler type
62
+ RouteHandler = Callable[
63
+ [RouteRequest, RouteResponse, "IAgentRuntime"],
64
+ Awaitable[None],
65
+ ]
66
+
67
+
68
+ class Route(BaseModel):
69
+ """Route definition for plugin HTTP routes."""
70
+
71
+ type: Literal["GET", "POST", "PUT", "PATCH", "DELETE", "STATIC"] = Field(
72
+ ..., description="HTTP method"
73
+ )
74
+ path: str = Field(..., description="Route path")
75
+ file_path: str | None = Field(default=None, alias="filePath", description="Static file path")
76
+ public: bool | None = Field(default=None, description="Whether route is public")
77
+ name: str | None = Field(default=None, description="Route name for tab display")
78
+ handler: RouteHandler | None = Field(default=None, description="Route handler")
79
+ is_multipart: bool | None = Field(
80
+ default=None,
81
+ alias="isMultipart",
82
+ description="Whether route expects multipart/form-data",
83
+ )
84
+
85
+ model_config = {"populate_by_name": True, "arbitrary_types_allowed": True}
86
+
87
+
88
+ # Plugin events type - maps event names to lists of event handlers
89
+ PluginEvents = dict[str, list[Callable[[Any], Awaitable[None]]]]
90
+
91
+
92
+ class TestCase(BaseModel):
93
+ name: str = Field(..., description="Test case name")
94
+ fn: Callable[[IAgentRuntime], Awaitable[None]] = Field(..., description="Test function")
95
+
96
+ model_config = {"arbitrary_types_allowed": True}
97
+
98
+
99
+ class TestSuite(BaseModel):
100
+ """Test suite definition for plugin tests."""
101
+
102
+ name: str = Field(..., description="Test suite name")
103
+ tests: list[TestCase] = Field(..., description="Test cases")
104
+
105
+ model_config = {"arbitrary_types_allowed": True}
106
+
107
+
108
+ class ComponentTypeDefinition(BaseModel):
109
+ name: str = Field(..., description="Component type name")
110
+ schema_def: dict[str, Any] = Field(..., alias="schema", description="Component schema")
111
+ validator: Callable[[Any], bool] | None = Field(
112
+ default=None, description="Optional validator function"
113
+ )
114
+
115
+ model_config = {"arbitrary_types_allowed": True, "populate_by_name": True}
116
+
117
+
118
+ class Plugin(BaseModel):
119
+ name: str = Field(..., description="Unique name for the plugin")
120
+ description: str = Field(..., description="Human-readable description")
121
+
122
+ # Initialize plugin with runtime services
123
+ init: (
124
+ Callable[[dict[str, str | int | float | bool | None], IAgentRuntime], Awaitable[None]]
125
+ | None
126
+ ) = Field(default=None, description="Plugin initialization function")
127
+
128
+ # Configuration
129
+ config: dict[str, str | int | float | bool | None] | None = Field(
130
+ default=None, description="Plugin configuration"
131
+ )
132
+
133
+ # Services
134
+ services: list[type[Service]] | None = Field(
135
+ default=None, description="Service classes to register"
136
+ )
137
+
138
+ # Component type definitions
139
+ component_types: list[ComponentTypeDefinition] | None = Field(
140
+ default=None, alias="componentTypes", description="Entity component definitions"
141
+ )
142
+
143
+ # Optional plugin features
144
+ actions: list[Action] | None = Field(default=None, description="Actions to register")
145
+ providers: list[Provider] | None = Field(default=None, description="Providers to register")
146
+ evaluators: list[Evaluator] | None = Field(default=None, description="Evaluators to register")
147
+ adapter: IDatabaseAdapter | None = Field(default=None, description="Database adapter")
148
+ models: dict[str, Callable[[IAgentRuntime, dict[str, Any]], Awaitable[Any]]] | None = Field(
149
+ default=None, description="Model handlers by model type"
150
+ )
151
+ streaming_models: dict[str, StreamingModelHandler] | None = Field(
152
+ default=None,
153
+ alias="streamingModels",
154
+ description="Streaming model handlers by model type",
155
+ )
156
+ events: PluginEvents | None = Field(default=None, description="Event handlers by event type")
157
+ routes: list[Route] | None = Field(default=None, description="HTTP routes to register")
158
+ tests: list[TestSuite] | None = Field(default=None, description="Test suites")
159
+
160
+ dependencies: list[str] | None = Field(default=None, description="Plugin dependencies")
161
+ test_dependencies: list[str] | None = Field(
162
+ default=None, alias="testDependencies", description="Test dependencies"
163
+ )
164
+ priority: int | None = Field(default=None, description="Plugin priority")
165
+ schema_def: dict[str, Any] | None = Field(
166
+ default=None, alias="schema", description="Plugin schema"
167
+ )
168
+
169
+ model_config = {"populate_by_name": True, "arbitrary_types_allowed": True}
170
+
171
+
172
+ class ProjectAgent(BaseModel):
173
+ """Agent configuration within a project."""
174
+
175
+ character: Character = Field(..., description="Agent character")
176
+ init: Callable[[IAgentRuntime], Awaitable[None]] | None = Field(
177
+ default=None, description="Agent initialization function"
178
+ )
179
+ plugins: list[Plugin] | None = Field(default=None, description="Agent-specific plugins")
180
+ tests: TestSuite | list[TestSuite] | None = Field(default=None, description="Agent tests")
181
+
182
+ model_config = {"arbitrary_types_allowed": True}
183
+
184
+
185
+ class Project(BaseModel):
186
+ agents: list[ProjectAgent] = Field(..., description="Project agents")
187
+
188
+ model_config = {"arbitrary_types_allowed": True}
@@ -0,0 +1,100 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import re
5
+ import urllib.parse
6
+ import uuid as uuid_module
7
+ from enum import Enum
8
+
9
+ from elizaos.types.generated.eliza.v1 import primitives_pb2
10
+
11
+ # UUID validation pattern
12
+ UUID_PATTERN = re.compile(
13
+ r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
14
+ re.IGNORECASE,
15
+ )
16
+
17
+ # UUID type - stored as string values in proto messages
18
+ UUID = str
19
+
20
+ # The default UUID used when no room or world is specified.
21
+ DEFAULT_UUID: str = "00000000-0000-0000-0000-000000000000"
22
+
23
+ # Proto-backed message types
24
+ Content = primitives_pb2.Content
25
+ Media = primitives_pb2.Media
26
+ MentionContext = primitives_pb2.MentionContext
27
+ Metadata = primitives_pb2.Metadata
28
+ UUIDMessage = primitives_pb2.UUID
29
+ DefaultUUID = primitives_pb2.DefaultUUID
30
+
31
+
32
+ def as_uuid(id_str: str | uuid_module.UUID) -> str:
33
+ if isinstance(id_str, uuid_module.UUID):
34
+ return str(id_str)
35
+ if isinstance(id_str, str):
36
+ if not UUID_PATTERN.match(id_str):
37
+ raise ValueError(f"Invalid UUID format: {id_str}")
38
+ return id_str
39
+ raise TypeError(f"Expected str or UUID, got {type(id_str).__name__}")
40
+
41
+
42
+ def string_to_uuid(target: str | int | uuid_module.UUID) -> str:
43
+ if isinstance(target, uuid_module.UUID):
44
+ return str(target)
45
+
46
+ if isinstance(target, int):
47
+ target_str = str(target)
48
+ elif isinstance(target, str):
49
+ target_str = target
50
+ else:
51
+ raise TypeError("Value must be string")
52
+
53
+ if UUID_PATTERN.match(target_str):
54
+ return target_str
55
+
56
+ escaped = urllib.parse.quote(target_str, safe="-_.!~*'()")
57
+ digest = hashlib.sha1(escaped.encode("utf-8")).digest() # noqa: S324 (required for parity)
58
+
59
+ b = bytearray(digest[:16])
60
+ b[8] = (b[8] & 0x3F) | 0x80
61
+ b[6] &= 0x0F
62
+
63
+ return str(uuid_module.UUID(bytes=bytes(b)))
64
+
65
+
66
+ class ChannelType(str, Enum):
67
+ SELF = "SELF"
68
+ DM = "DM"
69
+ GROUP = "GROUP"
70
+ VOICE_DM = "VOICE_DM"
71
+ VOICE_GROUP = "VOICE_GROUP"
72
+ FEED = "FEED"
73
+ THREAD = "THREAD"
74
+ WORLD = "WORLD"
75
+ FORUM = "FORUM"
76
+ API = "API"
77
+
78
+
79
+ class ContentType(str, Enum):
80
+ IMAGE = "image"
81
+ VIDEO = "video"
82
+ AUDIO = "audio"
83
+ DOCUMENT = "document"
84
+ LINK = "link"
85
+
86
+
87
+ __all__ = [
88
+ "UUID",
89
+ "DEFAULT_UUID",
90
+ "UUIDMessage",
91
+ "DefaultUUID",
92
+ "ChannelType",
93
+ "ContentType",
94
+ "Content",
95
+ "Media",
96
+ "MentionContext",
97
+ "Metadata",
98
+ "as_uuid",
99
+ "string_to_uuid",
100
+ ]