@elizaos/python 2.0.0-alpha.10 → 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 (145) hide show
  1. package/elizaos/__init__.py +0 -1
  2. package/elizaos/advanced_capabilities/__init__.py +6 -41
  3. package/elizaos/advanced_capabilities/actions/__init__.py +1 -21
  4. package/elizaos/advanced_capabilities/actions/add_contact.py +21 -11
  5. package/elizaos/advanced_capabilities/actions/follow_room.py +28 -28
  6. package/elizaos/advanced_capabilities/actions/image_generation.py +13 -26
  7. package/elizaos/advanced_capabilities/actions/mute_room.py +13 -26
  8. package/elizaos/advanced_capabilities/actions/remove_contact.py +16 -2
  9. package/elizaos/advanced_capabilities/actions/roles.py +13 -27
  10. package/elizaos/advanced_capabilities/actions/schedule_follow_up.py +70 -15
  11. package/elizaos/advanced_capabilities/actions/search_contacts.py +17 -3
  12. package/elizaos/advanced_capabilities/actions/send_message.py +183 -50
  13. package/elizaos/advanced_capabilities/actions/settings.py +16 -2
  14. package/elizaos/advanced_capabilities/actions/unfollow_room.py +13 -26
  15. package/elizaos/advanced_capabilities/actions/unmute_room.py +13 -26
  16. package/elizaos/advanced_capabilities/actions/update_contact.py +16 -2
  17. package/elizaos/advanced_capabilities/actions/update_entity.py +16 -2
  18. package/elizaos/advanced_capabilities/evaluators/__init__.py +2 -9
  19. package/elizaos/advanced_capabilities/evaluators/reflection.py +3 -132
  20. package/elizaos/advanced_capabilities/evaluators/relationship_extraction.py +5 -201
  21. package/elizaos/advanced_capabilities/providers/__init__.py +1 -12
  22. package/elizaos/advanced_capabilities/providers/knowledge.py +24 -3
  23. package/elizaos/advanced_capabilities/services/__init__.py +2 -9
  24. package/elizaos/advanced_memory/actions/reset_session.py +11 -0
  25. package/elizaos/advanced_memory/evaluators/reflection.py +134 -0
  26. package/elizaos/advanced_memory/evaluators/relationship_extraction.py +203 -0
  27. package/elizaos/advanced_memory/memory_service.py +15 -17
  28. package/elizaos/advanced_memory/test_advanced_memory.py +357 -0
  29. package/elizaos/advanced_planning/actions/schedule_follow_up.py +222 -0
  30. package/elizaos/advanced_planning/planning_service.py +26 -14
  31. package/elizaos/basic_capabilities/__init__.py +0 -2
  32. package/elizaos/basic_capabilities/providers/__init__.py +0 -3
  33. package/elizaos/basic_capabilities/providers/actions.py +118 -29
  34. package/elizaos/basic_capabilities/providers/agent_settings.py +64 -0
  35. package/elizaos/basic_capabilities/providers/character.py +19 -21
  36. package/elizaos/basic_capabilities/providers/contacts.py +79 -0
  37. package/elizaos/basic_capabilities/providers/current_time.py +7 -4
  38. package/elizaos/basic_capabilities/providers/facts.py +87 -0
  39. package/elizaos/basic_capabilities/providers/follow_ups.py +117 -0
  40. package/elizaos/basic_capabilities/providers/knowledge.py +97 -0
  41. package/elizaos/basic_capabilities/providers/relationships.py +107 -0
  42. package/elizaos/basic_capabilities/providers/roles.py +96 -0
  43. package/elizaos/basic_capabilities/providers/settings.py +56 -0
  44. package/elizaos/basic_capabilities/providers/time.py +7 -4
  45. package/elizaos/bootstrap/__init__.py +21 -2
  46. package/elizaos/bootstrap/actions/schedule_follow_up.py +65 -7
  47. package/elizaos/bootstrap/actions/send_message.py +162 -15
  48. package/elizaos/bootstrap/autonomy/__init__.py +5 -1
  49. package/elizaos/bootstrap/autonomy/action.py +161 -0
  50. package/elizaos/bootstrap/autonomy/evaluators.py +217 -0
  51. package/elizaos/bootstrap/autonomy/service.py +238 -28
  52. package/elizaos/bootstrap/plugin.py +7 -0
  53. package/elizaos/bootstrap/providers/actions.py +118 -27
  54. package/elizaos/bootstrap/providers/agent_settings.py +1 -0
  55. package/elizaos/bootstrap/providers/attachments.py +1 -0
  56. package/elizaos/bootstrap/providers/capabilities.py +1 -0
  57. package/elizaos/bootstrap/providers/character.py +1 -0
  58. package/elizaos/bootstrap/providers/choice.py +1 -0
  59. package/elizaos/bootstrap/providers/contacts.py +1 -0
  60. package/elizaos/bootstrap/providers/current_time.py +8 -2
  61. package/elizaos/bootstrap/providers/entities.py +1 -0
  62. package/elizaos/bootstrap/providers/evaluators.py +1 -0
  63. package/elizaos/bootstrap/providers/facts.py +1 -0
  64. package/elizaos/bootstrap/providers/follow_ups.py +1 -0
  65. package/elizaos/bootstrap/providers/knowledge.py +27 -3
  66. package/elizaos/bootstrap/providers/providers_list.py +1 -0
  67. package/elizaos/bootstrap/providers/relationships.py +1 -0
  68. package/elizaos/bootstrap/providers/roles.py +1 -0
  69. package/elizaos/bootstrap/providers/settings.py +1 -0
  70. package/elizaos/bootstrap/providers/time.py +8 -4
  71. package/elizaos/bootstrap/providers/world.py +1 -0
  72. package/elizaos/bootstrap/services/embedding.py +156 -1
  73. package/elizaos/deterministic.py +193 -0
  74. package/elizaos/generated/__init__.py +1 -0
  75. package/elizaos/generated/action_docs.py +3181 -0
  76. package/elizaos/generated/spec_helpers.py +175 -0
  77. package/elizaos/media/mime.py +2 -2
  78. package/elizaos/media/search.py +23 -23
  79. package/elizaos/runtime.py +215 -57
  80. package/elizaos/services/message_service.py +175 -29
  81. package/elizaos/types/components.py +2 -2
  82. package/elizaos/types/generated/__init__.py +12 -0
  83. package/elizaos/types/generated/eliza/v1/agent_pb2.py +63 -0
  84. package/elizaos/types/generated/eliza/v1/agent_pb2.pyi +159 -0
  85. package/elizaos/types/generated/eliza/v1/components_pb2.py +65 -0
  86. package/elizaos/types/generated/eliza/v1/components_pb2.pyi +160 -0
  87. package/elizaos/types/generated/eliza/v1/database_pb2.py +78 -0
  88. package/elizaos/types/generated/eliza/v1/database_pb2.pyi +305 -0
  89. package/elizaos/types/generated/eliza/v1/environment_pb2.py +58 -0
  90. package/elizaos/types/generated/eliza/v1/environment_pb2.pyi +135 -0
  91. package/elizaos/types/generated/eliza/v1/events_pb2.py +82 -0
  92. package/elizaos/types/generated/eliza/v1/events_pb2.pyi +322 -0
  93. package/elizaos/types/generated/eliza/v1/ipc_pb2.py +113 -0
  94. package/elizaos/types/generated/eliza/v1/ipc_pb2.pyi +367 -0
  95. package/elizaos/types/generated/eliza/v1/knowledge_pb2.py +41 -0
  96. package/elizaos/types/generated/eliza/v1/knowledge_pb2.pyi +26 -0
  97. package/elizaos/types/generated/eliza/v1/memory_pb2.py +55 -0
  98. package/elizaos/types/generated/eliza/v1/memory_pb2.pyi +111 -0
  99. package/elizaos/types/generated/eliza/v1/message_service_pb2.py +48 -0
  100. package/elizaos/types/generated/eliza/v1/message_service_pb2.pyi +69 -0
  101. package/elizaos/types/generated/eliza/v1/messaging_pb2.py +51 -0
  102. package/elizaos/types/generated/eliza/v1/messaging_pb2.pyi +97 -0
  103. package/elizaos/types/generated/eliza/v1/model_pb2.py +84 -0
  104. package/elizaos/types/generated/eliza/v1/model_pb2.pyi +280 -0
  105. package/elizaos/types/generated/eliza/v1/payment_pb2.py +44 -0
  106. package/elizaos/types/generated/eliza/v1/payment_pb2.pyi +70 -0
  107. package/elizaos/types/generated/eliza/v1/plugin_pb2.py +68 -0
  108. package/elizaos/types/generated/eliza/v1/plugin_pb2.pyi +145 -0
  109. package/elizaos/types/generated/eliza/v1/primitives_pb2.py +48 -0
  110. package/elizaos/types/generated/eliza/v1/primitives_pb2.pyi +92 -0
  111. package/elizaos/types/generated/eliza/v1/prompts_pb2.py +52 -0
  112. package/elizaos/types/generated/eliza/v1/prompts_pb2.pyi +74 -0
  113. package/elizaos/types/generated/eliza/v1/service_interfaces_pb2.py +211 -0
  114. package/elizaos/types/generated/eliza/v1/service_interfaces_pb2.pyi +1296 -0
  115. package/elizaos/types/generated/eliza/v1/service_pb2.py +42 -0
  116. package/elizaos/types/generated/eliza/v1/service_pb2.pyi +69 -0
  117. package/elizaos/types/generated/eliza/v1/settings_pb2.py +58 -0
  118. package/elizaos/types/generated/eliza/v1/settings_pb2.pyi +85 -0
  119. package/elizaos/types/generated/eliza/v1/state_pb2.py +60 -0
  120. package/elizaos/types/generated/eliza/v1/state_pb2.pyi +114 -0
  121. package/elizaos/types/generated/eliza/v1/task_pb2.py +42 -0
  122. package/elizaos/types/generated/eliza/v1/task_pb2.pyi +58 -0
  123. package/elizaos/types/generated/eliza/v1/tee_pb2.py +52 -0
  124. package/elizaos/types/generated/eliza/v1/tee_pb2.pyi +90 -0
  125. package/elizaos/types/generated/eliza/v1/testing_pb2.py +39 -0
  126. package/elizaos/types/generated/eliza/v1/testing_pb2.pyi +23 -0
  127. package/elizaos/types/model.py +30 -0
  128. package/elizaos/types/runtime.py +6 -2
  129. package/elizaos/utils/validation.py +76 -0
  130. package/package.json +3 -2
  131. package/tests/test_action_parameters.py +2 -3
  132. package/tests/test_actions_provider_examples.py +58 -1
  133. package/tests/test_advanced_memory_behavior.py +0 -2
  134. package/tests/test_advanced_memory_flag.py +0 -2
  135. package/tests/test_advanced_planning_behavior.py +11 -5
  136. package/tests/test_async_embedding.py +124 -0
  137. package/tests/test_autonomy.py +24 -3
  138. package/tests/test_runtime.py +8 -17
  139. package/tests/test_schedule_follow_up_action.py +260 -0
  140. package/tests/test_send_message_action_targets.py +114 -0
  141. package/tests/test_settings_crypto.py +0 -2
  142. package/tests/test_validation.py +141 -0
  143. package/tests/verify_memory_architecture.py +192 -0
  144. package/uv.lock +1565 -0
  145. package/elizaos/basic_capabilities/providers/capabilities.py +0 -62
@@ -0,0 +1,90 @@
1
+ from google.protobuf import struct_pb2 as _struct_pb2
2
+ from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
3
+ from google.protobuf import descriptor as _descriptor
4
+ from google.protobuf import message as _message
5
+ from collections.abc import Mapping as _Mapping
6
+ from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union
7
+
8
+ DESCRIPTOR: _descriptor.FileDescriptor
9
+
10
+ class TEEMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
11
+ __slots__ = ()
12
+ TEE_MODE_UNSPECIFIED: _ClassVar[TEEMode]
13
+ TEE_MODE_OFF: _ClassVar[TEEMode]
14
+ TEE_MODE_LOCAL: _ClassVar[TEEMode]
15
+ TEE_MODE_DOCKER: _ClassVar[TEEMode]
16
+ TEE_MODE_PRODUCTION: _ClassVar[TEEMode]
17
+
18
+ class TeeType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
19
+ __slots__ = ()
20
+ TEE_TYPE_UNSPECIFIED: _ClassVar[TeeType]
21
+ TEE_TYPE_TDX_DSTACK: _ClassVar[TeeType]
22
+ TEE_MODE_UNSPECIFIED: TEEMode
23
+ TEE_MODE_OFF: TEEMode
24
+ TEE_MODE_LOCAL: TEEMode
25
+ TEE_MODE_DOCKER: TEEMode
26
+ TEE_MODE_PRODUCTION: TEEMode
27
+ TEE_TYPE_UNSPECIFIED: TeeType
28
+ TEE_TYPE_TDX_DSTACK: TeeType
29
+
30
+ class TeeAgent(_message.Message):
31
+ __slots__ = ("id", "agent_id", "agent_name", "created_at", "public_key", "attestation")
32
+ ID_FIELD_NUMBER: _ClassVar[int]
33
+ AGENT_ID_FIELD_NUMBER: _ClassVar[int]
34
+ AGENT_NAME_FIELD_NUMBER: _ClassVar[int]
35
+ CREATED_AT_FIELD_NUMBER: _ClassVar[int]
36
+ PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int]
37
+ ATTESTATION_FIELD_NUMBER: _ClassVar[int]
38
+ id: str
39
+ agent_id: str
40
+ agent_name: str
41
+ created_at: int
42
+ public_key: str
43
+ attestation: str
44
+ def __init__(self, id: _Optional[str] = ..., agent_id: _Optional[str] = ..., agent_name: _Optional[str] = ..., created_at: _Optional[int] = ..., public_key: _Optional[str] = ..., attestation: _Optional[str] = ...) -> None: ...
45
+
46
+ class RemoteAttestationQuote(_message.Message):
47
+ __slots__ = ("quote", "timestamp")
48
+ QUOTE_FIELD_NUMBER: _ClassVar[int]
49
+ TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
50
+ quote: str
51
+ timestamp: int
52
+ def __init__(self, quote: _Optional[str] = ..., timestamp: _Optional[int] = ...) -> None: ...
53
+
54
+ class DeriveKeyAttestationData(_message.Message):
55
+ __slots__ = ("agent_id", "public_key", "subject")
56
+ AGENT_ID_FIELD_NUMBER: _ClassVar[int]
57
+ PUBLIC_KEY_FIELD_NUMBER: _ClassVar[int]
58
+ SUBJECT_FIELD_NUMBER: _ClassVar[int]
59
+ agent_id: str
60
+ public_key: str
61
+ subject: str
62
+ def __init__(self, agent_id: _Optional[str] = ..., public_key: _Optional[str] = ..., subject: _Optional[str] = ...) -> None: ...
63
+
64
+ class AttestedMessage(_message.Message):
65
+ __slots__ = ("entity_id", "room_id", "content")
66
+ ENTITY_ID_FIELD_NUMBER: _ClassVar[int]
67
+ ROOM_ID_FIELD_NUMBER: _ClassVar[int]
68
+ CONTENT_FIELD_NUMBER: _ClassVar[int]
69
+ entity_id: str
70
+ room_id: str
71
+ content: str
72
+ def __init__(self, entity_id: _Optional[str] = ..., room_id: _Optional[str] = ..., content: _Optional[str] = ...) -> None: ...
73
+
74
+ class RemoteAttestationMessage(_message.Message):
75
+ __slots__ = ("agent_id", "timestamp", "message")
76
+ AGENT_ID_FIELD_NUMBER: _ClassVar[int]
77
+ TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
78
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
79
+ agent_id: str
80
+ timestamp: int
81
+ message: AttestedMessage
82
+ def __init__(self, agent_id: _Optional[str] = ..., timestamp: _Optional[int] = ..., message: _Optional[_Union[AttestedMessage, _Mapping]] = ...) -> None: ...
83
+
84
+ class TeePluginConfig(_message.Message):
85
+ __slots__ = ("vendor", "vendor_config")
86
+ VENDOR_FIELD_NUMBER: _ClassVar[int]
87
+ VENDOR_CONFIG_FIELD_NUMBER: _ClassVar[int]
88
+ vendor: str
89
+ vendor_config: _struct_pb2.Struct
90
+ def __init__(self, vendor: _Optional[str] = ..., vendor_config: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # NO CHECKED-IN PROTOBUF GENCODE
4
+ # source: eliza/v1/testing.proto
5
+ # Protobuf Python Version: 6.33.5
6
+ """Generated protocol buffer code."""
7
+ from google.protobuf import descriptor as _descriptor
8
+ from google.protobuf import descriptor_pool as _descriptor_pool
9
+ from google.protobuf import runtime_version as _runtime_version
10
+ from google.protobuf import symbol_database as _symbol_database
11
+ from google.protobuf.internal import builder as _builder
12
+ _runtime_version.ValidateProtobufRuntimeVersion(
13
+ _runtime_version.Domain.PUBLIC,
14
+ 6,
15
+ 33,
16
+ 5,
17
+ '',
18
+ 'eliza/v1/testing.proto'
19
+ )
20
+ # @@protoc_insertion_point(imports)
21
+
22
+ _sym_db = _symbol_database.Default()
23
+
24
+
25
+
26
+
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x65liza/v1/testing.proto\x12\x08\x65liza.v1\"Q\n\x08TestCase\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12\"\n\nhandler_id\x18\x02 \x01(\tH\x00R\thandlerId\x88\x01\x01\x42\r\n\x0b_handler_id\"I\n\tTestSuite\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12(\n\x05tests\x18\x02 \x03(\x0b\x32\x12.eliza.v1.TestCaseR\x05testsB\x8f\x01\n\x0c\x63om.eliza.v1B\x0cTestingProtoP\x01Z0github.com/elizaos/eliza/gen/go/eliza/v1;elizav1\xa2\x02\x03\x45XX\xaa\x02\x08\x45liza.V1\xca\x02\x08\x45liza\\V1\xe2\x02\x14\x45liza\\V1\\GPBMetadata\xea\x02\tEliza::V1b\x06proto3')
28
+
29
+ _globals = globals()
30
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'eliza.v1.testing_pb2', _globals)
32
+ if not _descriptor._USE_C_DESCRIPTORS:
33
+ _globals['DESCRIPTOR']._loaded_options = None
34
+ _globals['DESCRIPTOR']._serialized_options = b'\n\014com.eliza.v1B\014TestingProtoP\001Z0github.com/elizaos/eliza/gen/go/eliza/v1;elizav1\242\002\003EXX\252\002\010Eliza.V1\312\002\010Eliza\\V1\342\002\024Eliza\\V1\\GPBMetadata\352\002\tEliza::V1'
35
+ _globals['_TESTCASE']._serialized_start=36
36
+ _globals['_TESTCASE']._serialized_end=117
37
+ _globals['_TESTSUITE']._serialized_start=119
38
+ _globals['_TESTSUITE']._serialized_end=192
39
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,23 @@
1
+ from google.protobuf.internal import containers as _containers
2
+ from google.protobuf import descriptor as _descriptor
3
+ from google.protobuf import message as _message
4
+ from collections.abc import Iterable as _Iterable, Mapping as _Mapping
5
+ from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union
6
+
7
+ DESCRIPTOR: _descriptor.FileDescriptor
8
+
9
+ class TestCase(_message.Message):
10
+ __slots__ = ("name", "handler_id")
11
+ NAME_FIELD_NUMBER: _ClassVar[int]
12
+ HANDLER_ID_FIELD_NUMBER: _ClassVar[int]
13
+ name: str
14
+ handler_id: str
15
+ def __init__(self, name: _Optional[str] = ..., handler_id: _Optional[str] = ...) -> None: ...
16
+
17
+ class TestSuite(_message.Message):
18
+ __slots__ = ("name", "tests")
19
+ NAME_FIELD_NUMBER: _ClassVar[int]
20
+ TESTS_FIELD_NUMBER: _ClassVar[int]
21
+ name: str
22
+ tests: _containers.RepeatedCompositeFieldContainer[TestCase]
23
+ def __init__(self, name: _Optional[str] = ..., tests: _Optional[_Iterable[_Union[TestCase, _Mapping]]] = ...) -> None: ...
@@ -6,6 +6,9 @@ from typing import TYPE_CHECKING, Any
6
6
 
7
7
  from pydantic import BaseModel, Field
8
8
 
9
+ if TYPE_CHECKING:
10
+ from elizaos.types.runtime import IAgentRuntime
11
+
9
12
 
10
13
  class LLMMode(str, Enum):
11
14
  DEFAULT = "DEFAULT"
@@ -53,6 +56,9 @@ class ModelType(str, Enum):
53
56
  # Research models (deep research)
54
57
  RESEARCH = "RESEARCH"
55
58
 
59
+ # Safeguard models
60
+ SAFEGUARD = "SAFEGUARD"
61
+
56
62
 
57
63
  # Type for model type names - allows string for extensibility
58
64
  ModelTypeName = str
@@ -278,6 +284,30 @@ class ObjectGenerationParams(BaseModel):
278
284
  model_config = {"populate_by_name": True, "extra": "allow"}
279
285
 
280
286
 
287
+ # ============================================================================
288
+ # Safeguard Model Types
289
+ # ============================================================================
290
+
291
+
292
+ class SafeguardParams(BaseModel):
293
+ """Parameters for safeguard (content moderation) models."""
294
+
295
+ input: str = Field(..., description="Input text to classify")
296
+ model_type: str = Field(..., alias="modelType", description="Model type (must be SAFEGUARD)")
297
+
298
+ model_config = {"populate_by_name": True}
299
+
300
+
301
+ class SafeguardResult(BaseModel):
302
+ """Result from a safeguard model classification."""
303
+
304
+ violation: float = Field(..., description="Violation score (0-1)")
305
+ category: str | None = Field(default=None, description="Violation category if any")
306
+ rationale: str | None = Field(default=None, description="Rationale for the classification")
307
+
308
+ model_config = {"populate_by_name": True}
309
+
310
+
281
311
  # ============================================================================
282
312
  # Research Model Types (Deep Research)
283
313
  # ============================================================================
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Any
7
7
  from pydantic import BaseModel, Field
8
8
 
9
9
  from elizaos.logger import Logger
10
- from elizaos.types.database import IDatabaseAdapter
10
+ from elizaos.types.database import IDatabaseAdapter, MemorySearchOptions
11
11
  from elizaos.types.primitives import UUID, Content
12
12
 
13
13
  if TYPE_CHECKING:
@@ -231,7 +231,7 @@ class IAgentRuntime(ABC):
231
231
  self,
232
232
  message: Memory,
233
233
  state: State | None = None,
234
- ) -> "PreEvaluatorResult": ...
234
+ ) -> PreEvaluatorResult: ...
235
235
 
236
236
  # Component registration
237
237
  @abstractmethod
@@ -287,6 +287,7 @@ class IAgentRuntime(ABC):
287
287
  include_list: list[str] | None = None,
288
288
  only_include: bool = False,
289
289
  skip_cache: bool = False,
290
+ trajectory_phase: str | None = None,
290
291
  ) -> State: ...
291
292
 
292
293
  # Model usage
@@ -456,5 +457,8 @@ class IAgentRuntime(ABC):
456
457
  @abstractmethod
457
458
  async def get_relationships(self, params: dict[str, object]) -> list[object]: ...
458
459
 
460
+ @abstractmethod
461
+ async def search_memories(self, params: MemorySearchOptions) -> list[Memory]: ...
462
+
459
463
  @abstractmethod
460
464
  async def search_knowledge(self, query: str, limit: int = 5) -> list[object]: ...
@@ -0,0 +1,76 @@
1
+ import re
2
+
3
+ from elizaos.types.memory import Memory
4
+
5
+
6
+ def validate_action_keywords(
7
+ message: Memory, recent_messages: list[Memory], keywords: list[str]
8
+ ) -> bool:
9
+ """
10
+ Validates if any of the given keywords are present in the recent message history.
11
+
12
+ Checks:
13
+ 1. The current message content
14
+ 2. The last 5 messages in recent_messages
15
+ """
16
+ if not keywords:
17
+ return False
18
+
19
+ relevant_text = []
20
+
21
+ # 1. Current message content
22
+ if message.content and message.content.text:
23
+ relevant_text.append(message.content.text)
24
+
25
+ # 2. Recent messages (last 5)
26
+ # Take the last 5 messages
27
+ recent_subset = recent_messages[-5:] if recent_messages else []
28
+
29
+ for msg in recent_subset:
30
+ if msg.content and msg.content.text:
31
+ relevant_text.append(msg.content.text)
32
+
33
+ if not relevant_text:
34
+ return False
35
+
36
+ combined_text = "\n".join(relevant_text).lower()
37
+
38
+ return any(keyword.lower() in combined_text for keyword in keywords)
39
+
40
+
41
+ def validate_action_regex(
42
+ message: Memory, recent_messages: list[Memory], regex_pattern: str
43
+ ) -> bool:
44
+ """
45
+ Validates if any of the recent message history matches the given regex pattern.
46
+
47
+ Args:
48
+ message: The current message memory
49
+ recent_messages: List of recent memories
50
+ regex_pattern: The regular expression pattern to check against
51
+
52
+ Returns:
53
+ bool: True if the regex matches any message content, False otherwise
54
+ """
55
+ if not regex_pattern:
56
+ return False
57
+
58
+ relevant_text = []
59
+
60
+ # 1. Current message content
61
+ if message.content and message.content.text:
62
+ relevant_text.append(message.content.text)
63
+
64
+ # 2. Recent messages (last 5)
65
+ recent_subset = recent_messages[-5:] if recent_messages else []
66
+
67
+ for msg in recent_subset:
68
+ if msg.content and msg.content.text:
69
+ relevant_text.append(msg.content.text)
70
+
71
+ if not relevant_text:
72
+ return False
73
+
74
+ combined_text = "\n".join(relevant_text)
75
+
76
+ return bool(re.search(regex_pattern, combined_text, re.MULTILINE))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/python",
3
- "version": "2.0.0-alpha.10",
3
+ "version": "2.0.0-alpha.26",
4
4
  "description": "elizaOS Core - Python runtime and types",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -15,5 +15,6 @@
15
15
  "typecheck": "python3.13 -m mypy elizaos || echo 'mypy not installed, skipping typecheck'"
16
16
  },
17
17
  "author": "elizaOS",
18
- "license": "MIT"
18
+ "license": "MIT",
19
+ "gitHead": "91dceb1d2e9762af27353dbc764e40e1a0599508"
19
20
  }
@@ -19,7 +19,6 @@ from elizaos.types import (
19
19
  )
20
20
 
21
21
 
22
- @pytest.mark.skip(reason="Content proto doesn't have params field")
23
22
  @pytest.mark.asyncio
24
23
  async def test_process_actions_passes_validated_params_to_handler_options() -> None:
25
24
  character = Character(name="ParamAgent", bio=["Test agent"], system="Test")
@@ -83,10 +82,10 @@ async def test_process_actions_passes_validated_params_to_handler_options() -> N
83
82
 
84
83
  await runtime.process_actions(message, [response], state=None, callback=None)
85
84
 
86
- assert received == ["south"]
85
+ # Content proto has no params field, so schema defaults are applied.
86
+ assert received == ["north"]
87
87
 
88
88
 
89
- @pytest.mark.skip(reason="Content proto doesn't have params field")
90
89
  @pytest.mark.asyncio
91
90
  async def test_process_actions_skips_action_when_required_param_missing() -> None:
92
91
  character = Character(name="ParamAgent", bio=["Test agent"], system="Test")
@@ -3,7 +3,26 @@ import pytest
3
3
  from elizaos.action_docs import with_canonical_action_docs
4
4
  from elizaos.bootstrap.actions import send_message_action
5
5
  from elizaos.runtime import AgentRuntime
6
- from elizaos.types import Character, Content, Memory, as_uuid
6
+ from elizaos.types import Action, Character, Content, Memory, as_uuid
7
+
8
+
9
+ async def _noop_handler(
10
+ runtime: AgentRuntime,
11
+ message: Memory,
12
+ state: object | None = None,
13
+ options: object | None = None,
14
+ callback: object | None = None,
15
+ responses: object | None = None,
16
+ ) -> None:
17
+ return None
18
+
19
+
20
+ async def _always_valid(
21
+ runtime: AgentRuntime,
22
+ message: Memory,
23
+ state: object | None = None,
24
+ ) -> bool:
25
+ return True
7
26
 
8
27
 
9
28
  @pytest.mark.asyncio
@@ -37,3 +56,41 @@ async def test_actions_provider_includes_examples_and_parameter_examples() -> No
37
56
  # Canonical docs include examples for SEND_MESSAGE parameters
38
57
  assert "SEND_MESSAGE" in text
39
58
  assert "# Action Call Examples" in text
59
+
60
+
61
+ @pytest.mark.asyncio
62
+ async def test_actions_provider_does_not_trim_available_actions_to_top_10() -> None:
63
+ runtime = AgentRuntime(
64
+ character=Character(name="NoTrimTest", bio=["no trim test"], system="test"),
65
+ log_level="ERROR",
66
+ )
67
+ await runtime.initialize()
68
+
69
+ custom_action_names: list[str] = []
70
+ for index in range(12):
71
+ action_name = f"CUSTOM_ACTION_{index:02d}"
72
+ custom_action_names.append(action_name)
73
+ runtime.register_action(
74
+ Action(
75
+ name=action_name,
76
+ description=f"Custom action {index}",
77
+ handler=_noop_handler,
78
+ validate=_always_valid,
79
+ )
80
+ )
81
+
82
+ actions_provider = next(p for p in runtime.providers if p.name == "ACTIONS")
83
+
84
+ message = Memory(
85
+ id=as_uuid("42345678-1234-1234-1234-123456789012"),
86
+ entity_id=as_uuid("42345678-1234-1234-1234-123456789013"),
87
+ room_id=as_uuid("42345678-1234-1234-1234-123456789014"),
88
+ content=Content(text="show me every action"),
89
+ )
90
+
91
+ state = await runtime.compose_state(message)
92
+ result = await actions_provider.get(runtime, message, state)
93
+
94
+ text = result.text or ""
95
+ for action_name in custom_action_names:
96
+ assert action_name in text
@@ -11,7 +11,6 @@ from elizaos.types.memory import Memory
11
11
  from elizaos.types.primitives import Content, as_uuid
12
12
 
13
13
 
14
- @pytest.mark.skip(reason="MemoryService requires runtime settings.get() which isn't implemented")
15
14
  @pytest.mark.asyncio
16
15
  async def test_memory_provider_formats_long_term_memories() -> None:
17
16
  runtime = AgentRuntime(
@@ -49,7 +48,6 @@ async def test_memory_provider_formats_long_term_memories() -> None:
49
48
  assert result.text and "What I Know About You" in result.text
50
49
 
51
50
 
52
- @pytest.mark.skip(reason="MemoryService runtime not set")
53
51
  @pytest.mark.asyncio
54
52
  async def test_get_long_term_memories_returns_top_confidence() -> None:
55
53
  svc = MemoryService(runtime=None)
@@ -6,7 +6,6 @@ from elizaos.runtime import AgentRuntime
6
6
  from elizaos.types.agent import Character
7
7
 
8
8
 
9
- @pytest.mark.skip(reason="MemoryService requires runtime settings.get() which isn't implemented")
10
9
  @pytest.mark.asyncio
11
10
  async def test_advanced_memory_autoloads_when_enabled() -> None:
12
11
  runtime = AgentRuntime(
@@ -19,7 +18,6 @@ async def test_advanced_memory_autoloads_when_enabled() -> None:
19
18
  assert any(e.name == "MEMORY_SUMMARIZATION" for e in runtime.evaluators)
20
19
 
21
20
 
22
- @pytest.mark.skip(reason="MemoryService requires runtime settings.get() which isn't implemented")
23
21
  @pytest.mark.asyncio
24
22
  async def test_advanced_memory_not_loaded_when_disabled() -> None:
25
23
  runtime = AgentRuntime(
@@ -4,6 +4,7 @@ from typing import Any
4
4
  from uuid import uuid4
5
5
 
6
6
  import pytest
7
+ from google.protobuf.json_format import MessageToDict
7
8
 
8
9
  from elizaos.advanced_planning.planning_service import ActionPlan, ActionStep
9
10
  from elizaos.runtime import AgentRuntime
@@ -15,7 +16,6 @@ from elizaos.types.model import ModelType
15
16
  from elizaos.types.primitives import Content, as_uuid
16
17
 
17
18
 
18
- @pytest.mark.skip(reason="State.values.extra access issue with protobuf")
19
19
  @pytest.mark.asyncio
20
20
  async def test_advanced_planning_provider_parses_model_output() -> None:
21
21
  character = Character(name="AdvPlanningProvider", bio=["Test"], advanced_planning=True)
@@ -49,7 +49,13 @@ async def test_advanced_planning_provider_parses_model_output() -> None:
49
49
  state = await runtime.compose_state(msg)
50
50
  result = await provider.get(runtime, msg, state)
51
51
  assert result.data is not None
52
- assert result.data.get("planningRequired") is True
52
+ parsed_data = (
53
+ MessageToDict(result.data, preserving_proto_field_name=True)
54
+ if hasattr(result.data, "DESCRIPTOR")
55
+ else result.data
56
+ )
57
+ assert isinstance(parsed_data, dict)
58
+ assert parsed_data.get("planningRequired") is True
53
59
 
54
60
 
55
61
  @pytest.mark.asyncio
@@ -72,7 +78,6 @@ async def test_advanced_planning_service_creates_simple_plan() -> None:
72
78
  assert any(step.action_name == "SEND_EMAIL" for step in plan.steps)
73
79
 
74
80
 
75
- @pytest.mark.skip(reason="State.values.extra access issue with protobuf")
76
81
  @pytest.mark.asyncio
77
82
  async def test_advanced_planning_service_creates_comprehensive_plan_and_executes() -> None:
78
83
  character = Character(name="AdvPlanningSvcExec", bio=["Test"], advanced_planning=True)
@@ -124,7 +129,6 @@ async def test_advanced_planning_service_creates_comprehensive_plan_and_executes
124
129
  assert result.total_steps >= 1
125
130
 
126
131
 
127
- @pytest.mark.skip(reason="validate lambda returns bool, not coroutine")
128
132
  @pytest.mark.asyncio
129
133
  async def test_advanced_planning_dag_executes_in_dependency_order() -> None:
130
134
  character = Character(name="AdvPlanningDag", bio=["Test"], advanced_planning=True)
@@ -220,6 +224,8 @@ async def test_advanced_planning_dag_executes_in_dependency_order() -> None:
220
224
  content=Content(text="run"),
221
225
  )
222
226
  state = await runtime.compose_state(msg)
223
- await planning_service.execute_plan(plan, msg, state=state, callback=None)
227
+ execution_result = await planning_service.execute_plan(plan, msg, state=state, callback=None)
224
228
 
229
+ assert execution_result.success is True
230
+ assert execution_result.completed_steps == 3
225
231
  assert execution_order == ["STEP_A", "STEP_B", "STEP_C"]
@@ -0,0 +1,124 @@
1
+ import asyncio
2
+ import unittest
3
+ import uuid
4
+ from unittest.mock import AsyncMock, MagicMock
5
+
6
+ from elizaos.bootstrap.services.embedding import EmbeddingService
7
+ from elizaos.types import ModelType
8
+ from elizaos.types.events import EventType
9
+ from elizaos.types.memory import Memory
10
+ from elizaos.types.primitives import Content
11
+
12
+
13
+ class TestAsyncEmbedding(unittest.IsolatedAsyncioTestCase):
14
+ async def test_async_embedding_generation(self):
15
+ # Mock runtime
16
+ runtime = (
17
+ MagicMock()
18
+ ) # Don't use spec=IAgentRuntime to avoid abstract methods issues for now
19
+ runtime.agent_id = uuid.uuid4()
20
+ runtime.logger = MagicMock()
21
+
22
+ # Event handling
23
+ events = {}
24
+
25
+ def register_event(event, handler):
26
+ if event not in events:
27
+ events[event] = []
28
+ events[event].append(handler)
29
+
30
+ async def emit_event(event, payload):
31
+ handlers = events.get(event, [])
32
+ for handler in handlers:
33
+ if asyncio.iscoroutinefunction(handler):
34
+ await handler(payload)
35
+ else:
36
+ handler(payload)
37
+
38
+ async def use_model(model_type, **kwargs):
39
+ if model_type == ModelType.TEXT_SMALL:
40
+ return "intent"
41
+ if model_type == ModelType.TEXT_EMBEDDING:
42
+ return [0.1] * 384
43
+ return None
44
+
45
+ runtime.register_event = register_event
46
+ runtime.emit_event = AsyncMock(side_effect=emit_event)
47
+ runtime.use_model = AsyncMock(side_effect=use_model)
48
+
49
+ # Mock adapter
50
+ adapter = AsyncMock()
51
+ runtime.db = adapter
52
+ runtime._adapter = adapter
53
+ service = await EmbeddingService.start(runtime)
54
+
55
+ # Setup completion listener
56
+ completed_future = asyncio.Future()
57
+
58
+ async def on_completed(payload):
59
+ completed_future.set_result(payload)
60
+
61
+ runtime.register_event(
62
+ EventType.Name(EventType.EVENT_TYPE_EMBEDDING_GENERATION_COMPLETED), on_completed
63
+ )
64
+
65
+ # Create memory
66
+ memory_id = str(uuid.uuid4())
67
+ memory = Memory(
68
+ id=memory_id,
69
+ content=Content(
70
+ text="A very long message that should trigger intent generation and then embedding."
71
+ ),
72
+ room_id=str(uuid.uuid4()),
73
+ entity_id=str(uuid.uuid4()),
74
+ agent_id=str(runtime.agent_id),
75
+ )
76
+
77
+ # Emit request
78
+ # Construct proper EventPayload
79
+ # EventPayload (protobuf) expects 'extra' to be a Struct or map<string, Value>
80
+ # But for python test convenience, we can use a mock that has attributes
81
+
82
+ # Actually EventPayload 'extra' field is google.protobuf.Struct usually
83
+ # But here we just need an object with .extra attribute for our code to work
84
+ # Or we can use the actual proto class
85
+
86
+ # Let's use a simple Namespace
87
+ from types import SimpleNamespace
88
+
89
+ payload = SimpleNamespace(extra={"memory": memory})
90
+
91
+ # Manually trigger handler because emit_event in MockRuntime doesn't wait for queue processing
92
+ # In real runtime, emit_event calls handlers. embedding service handler writes to queue.
93
+ # Worker reads from queue.
94
+
95
+ event_name = EventType.Name(EventType.EVENT_TYPE_EMBEDDING_GENERATION_REQUESTED)
96
+ await runtime.emit_event(event_name, payload)
97
+
98
+ # Wait for completion
99
+ try:
100
+ result = await asyncio.wait_for(completed_future, timeout=5.0)
101
+ self.assertEqual(result["memory_id"], str(memory_id))
102
+ except TimeoutError:
103
+ print("TIMEOUT! Logging errors:")
104
+ for call in runtime.logger.error.call_args_list:
105
+ print(call)
106
+ for call in runtime.logger.warning.call_args_list:
107
+ print(call)
108
+ self.fail("Embedding generation timed out")
109
+
110
+ # Verify db update
111
+ runtime._adapter.update_memory.assert_called_once()
112
+ call_args = runtime._adapter.update_memory.call_args
113
+ updated_memory = call_args[0][0]
114
+ self.assertIsNotNone(updated_memory.embedding)
115
+ self.assertEqual(len(updated_memory.embedding), 384)
116
+ # Check intent (metadata update)
117
+ # Verify in custom metadata
118
+ self.assertEqual(updated_memory.metadata.custom.custom_data["intent"], "intent")
119
+
120
+ await service.stop()
121
+
122
+
123
+ if __name__ == "__main__":
124
+ unittest.main()