@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.
- package/elizaos/__init__.py +0 -1
- package/elizaos/advanced_capabilities/__init__.py +6 -41
- package/elizaos/advanced_capabilities/actions/__init__.py +1 -21
- package/elizaos/advanced_capabilities/actions/add_contact.py +21 -11
- package/elizaos/advanced_capabilities/actions/follow_room.py +28 -28
- package/elizaos/advanced_capabilities/actions/image_generation.py +13 -26
- package/elizaos/advanced_capabilities/actions/mute_room.py +13 -26
- package/elizaos/advanced_capabilities/actions/remove_contact.py +16 -2
- package/elizaos/advanced_capabilities/actions/roles.py +13 -27
- package/elizaos/advanced_capabilities/actions/schedule_follow_up.py +70 -15
- package/elizaos/advanced_capabilities/actions/search_contacts.py +17 -3
- package/elizaos/advanced_capabilities/actions/send_message.py +183 -50
- package/elizaos/advanced_capabilities/actions/settings.py +16 -2
- package/elizaos/advanced_capabilities/actions/unfollow_room.py +13 -26
- package/elizaos/advanced_capabilities/actions/unmute_room.py +13 -26
- package/elizaos/advanced_capabilities/actions/update_contact.py +16 -2
- package/elizaos/advanced_capabilities/actions/update_entity.py +16 -2
- package/elizaos/advanced_capabilities/evaluators/__init__.py +2 -9
- package/elizaos/advanced_capabilities/evaluators/reflection.py +3 -132
- package/elizaos/advanced_capabilities/evaluators/relationship_extraction.py +5 -201
- package/elizaos/advanced_capabilities/providers/__init__.py +1 -12
- package/elizaos/advanced_capabilities/providers/knowledge.py +24 -3
- package/elizaos/advanced_capabilities/services/__init__.py +2 -9
- package/elizaos/advanced_memory/actions/reset_session.py +11 -0
- package/elizaos/advanced_memory/evaluators/reflection.py +134 -0
- package/elizaos/advanced_memory/evaluators/relationship_extraction.py +203 -0
- package/elizaos/advanced_memory/memory_service.py +15 -17
- package/elizaos/advanced_memory/test_advanced_memory.py +357 -0
- package/elizaos/advanced_planning/actions/schedule_follow_up.py +222 -0
- package/elizaos/advanced_planning/planning_service.py +26 -14
- package/elizaos/basic_capabilities/__init__.py +0 -2
- package/elizaos/basic_capabilities/providers/__init__.py +0 -3
- package/elizaos/basic_capabilities/providers/actions.py +118 -29
- package/elizaos/basic_capabilities/providers/agent_settings.py +64 -0
- package/elizaos/basic_capabilities/providers/character.py +19 -21
- package/elizaos/basic_capabilities/providers/contacts.py +79 -0
- package/elizaos/basic_capabilities/providers/current_time.py +7 -4
- package/elizaos/basic_capabilities/providers/facts.py +87 -0
- package/elizaos/basic_capabilities/providers/follow_ups.py +117 -0
- package/elizaos/basic_capabilities/providers/knowledge.py +97 -0
- package/elizaos/basic_capabilities/providers/relationships.py +107 -0
- package/elizaos/basic_capabilities/providers/roles.py +96 -0
- package/elizaos/basic_capabilities/providers/settings.py +56 -0
- package/elizaos/basic_capabilities/providers/time.py +7 -4
- package/elizaos/bootstrap/__init__.py +21 -2
- package/elizaos/bootstrap/actions/schedule_follow_up.py +65 -7
- package/elizaos/bootstrap/actions/send_message.py +162 -15
- package/elizaos/bootstrap/autonomy/__init__.py +5 -1
- package/elizaos/bootstrap/autonomy/action.py +161 -0
- package/elizaos/bootstrap/autonomy/evaluators.py +217 -0
- package/elizaos/bootstrap/autonomy/service.py +238 -28
- package/elizaos/bootstrap/plugin.py +7 -0
- package/elizaos/bootstrap/providers/actions.py +118 -27
- package/elizaos/bootstrap/providers/agent_settings.py +1 -0
- package/elizaos/bootstrap/providers/attachments.py +1 -0
- package/elizaos/bootstrap/providers/capabilities.py +1 -0
- package/elizaos/bootstrap/providers/character.py +1 -0
- package/elizaos/bootstrap/providers/choice.py +1 -0
- package/elizaos/bootstrap/providers/contacts.py +1 -0
- package/elizaos/bootstrap/providers/current_time.py +8 -2
- package/elizaos/bootstrap/providers/entities.py +1 -0
- package/elizaos/bootstrap/providers/evaluators.py +1 -0
- package/elizaos/bootstrap/providers/facts.py +1 -0
- package/elizaos/bootstrap/providers/follow_ups.py +1 -0
- package/elizaos/bootstrap/providers/knowledge.py +27 -3
- package/elizaos/bootstrap/providers/providers_list.py +1 -0
- package/elizaos/bootstrap/providers/relationships.py +1 -0
- package/elizaos/bootstrap/providers/roles.py +1 -0
- package/elizaos/bootstrap/providers/settings.py +1 -0
- package/elizaos/bootstrap/providers/time.py +8 -4
- package/elizaos/bootstrap/providers/world.py +1 -0
- package/elizaos/bootstrap/services/embedding.py +156 -1
- package/elizaos/deterministic.py +193 -0
- package/elizaos/generated/__init__.py +1 -0
- package/elizaos/generated/action_docs.py +3181 -0
- package/elizaos/generated/spec_helpers.py +175 -0
- package/elizaos/media/mime.py +2 -2
- package/elizaos/media/search.py +23 -23
- package/elizaos/runtime.py +215 -57
- package/elizaos/services/message_service.py +175 -29
- package/elizaos/types/components.py +2 -2
- package/elizaos/types/generated/__init__.py +12 -0
- package/elizaos/types/generated/eliza/v1/agent_pb2.py +63 -0
- package/elizaos/types/generated/eliza/v1/agent_pb2.pyi +159 -0
- package/elizaos/types/generated/eliza/v1/components_pb2.py +65 -0
- package/elizaos/types/generated/eliza/v1/components_pb2.pyi +160 -0
- package/elizaos/types/generated/eliza/v1/database_pb2.py +78 -0
- package/elizaos/types/generated/eliza/v1/database_pb2.pyi +305 -0
- package/elizaos/types/generated/eliza/v1/environment_pb2.py +58 -0
- package/elizaos/types/generated/eliza/v1/environment_pb2.pyi +135 -0
- package/elizaos/types/generated/eliza/v1/events_pb2.py +82 -0
- package/elizaos/types/generated/eliza/v1/events_pb2.pyi +322 -0
- package/elizaos/types/generated/eliza/v1/ipc_pb2.py +113 -0
- package/elizaos/types/generated/eliza/v1/ipc_pb2.pyi +367 -0
- package/elizaos/types/generated/eliza/v1/knowledge_pb2.py +41 -0
- package/elizaos/types/generated/eliza/v1/knowledge_pb2.pyi +26 -0
- package/elizaos/types/generated/eliza/v1/memory_pb2.py +55 -0
- package/elizaos/types/generated/eliza/v1/memory_pb2.pyi +111 -0
- package/elizaos/types/generated/eliza/v1/message_service_pb2.py +48 -0
- package/elizaos/types/generated/eliza/v1/message_service_pb2.pyi +69 -0
- package/elizaos/types/generated/eliza/v1/messaging_pb2.py +51 -0
- package/elizaos/types/generated/eliza/v1/messaging_pb2.pyi +97 -0
- package/elizaos/types/generated/eliza/v1/model_pb2.py +84 -0
- package/elizaos/types/generated/eliza/v1/model_pb2.pyi +280 -0
- package/elizaos/types/generated/eliza/v1/payment_pb2.py +44 -0
- package/elizaos/types/generated/eliza/v1/payment_pb2.pyi +70 -0
- package/elizaos/types/generated/eliza/v1/plugin_pb2.py +68 -0
- package/elizaos/types/generated/eliza/v1/plugin_pb2.pyi +145 -0
- package/elizaos/types/generated/eliza/v1/primitives_pb2.py +48 -0
- package/elizaos/types/generated/eliza/v1/primitives_pb2.pyi +92 -0
- package/elizaos/types/generated/eliza/v1/prompts_pb2.py +52 -0
- package/elizaos/types/generated/eliza/v1/prompts_pb2.pyi +74 -0
- package/elizaos/types/generated/eliza/v1/service_interfaces_pb2.py +211 -0
- package/elizaos/types/generated/eliza/v1/service_interfaces_pb2.pyi +1296 -0
- package/elizaos/types/generated/eliza/v1/service_pb2.py +42 -0
- package/elizaos/types/generated/eliza/v1/service_pb2.pyi +69 -0
- package/elizaos/types/generated/eliza/v1/settings_pb2.py +58 -0
- package/elizaos/types/generated/eliza/v1/settings_pb2.pyi +85 -0
- package/elizaos/types/generated/eliza/v1/state_pb2.py +60 -0
- package/elizaos/types/generated/eliza/v1/state_pb2.pyi +114 -0
- package/elizaos/types/generated/eliza/v1/task_pb2.py +42 -0
- package/elizaos/types/generated/eliza/v1/task_pb2.pyi +58 -0
- package/elizaos/types/generated/eliza/v1/tee_pb2.py +52 -0
- package/elizaos/types/generated/eliza/v1/tee_pb2.pyi +90 -0
- package/elizaos/types/generated/eliza/v1/testing_pb2.py +39 -0
- package/elizaos/types/generated/eliza/v1/testing_pb2.pyi +23 -0
- package/elizaos/types/model.py +30 -0
- package/elizaos/types/runtime.py +6 -2
- package/elizaos/utils/validation.py +76 -0
- package/package.json +3 -2
- package/tests/test_action_parameters.py +2 -3
- package/tests/test_actions_provider_examples.py +58 -1
- package/tests/test_advanced_memory_behavior.py +0 -2
- package/tests/test_advanced_memory_flag.py +0 -2
- package/tests/test_advanced_planning_behavior.py +11 -5
- package/tests/test_async_embedding.py +124 -0
- package/tests/test_autonomy.py +24 -3
- package/tests/test_runtime.py +8 -17
- package/tests/test_schedule_follow_up_action.py +260 -0
- package/tests/test_send_message_action_targets.py +114 -0
- package/tests/test_settings_crypto.py +0 -2
- package/tests/test_validation.py +141 -0
- package/tests/verify_memory_architecture.py +192 -0
- package/uv.lock +1565 -0
- package/elizaos/basic_capabilities/providers/capabilities.py +0 -62
package/elizaos/runtime.py
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import contextlib
|
|
4
5
|
import re
|
|
5
6
|
import uuid
|
|
6
7
|
import xml.etree.ElementTree as ET
|
|
7
|
-
from collections.abc import AsyncIterator, Awaitable, Callable
|
|
8
|
+
from collections.abc import AsyncIterator, Awaitable, Callable, Mapping, MutableMapping
|
|
8
9
|
from dataclasses import dataclass
|
|
9
10
|
from typing import Any
|
|
10
11
|
|
|
12
|
+
from google.protobuf.struct_pb2 import Value as StructValue
|
|
13
|
+
|
|
11
14
|
from elizaos.action_docs import with_canonical_action_docs, with_canonical_evaluator_docs
|
|
15
|
+
from elizaos.deterministic import (
|
|
16
|
+
build_conversation_seed,
|
|
17
|
+
deterministic_hex,
|
|
18
|
+
deterministic_uuid,
|
|
19
|
+
)
|
|
12
20
|
from elizaos.logger import Logger, create_logger
|
|
13
21
|
from elizaos.settings import decrypt_secret, get_salt
|
|
14
22
|
from elizaos.types.agent import Character, TemplateType
|
|
@@ -18,9 +26,10 @@ from elizaos.types.components import (
|
|
|
18
26
|
Evaluator,
|
|
19
27
|
HandlerCallback,
|
|
20
28
|
HandlerOptions,
|
|
29
|
+
PreEvaluatorResult,
|
|
21
30
|
Provider,
|
|
22
31
|
)
|
|
23
|
-
from elizaos.types.database import AgentRunSummaryResult, IDatabaseAdapter, Log
|
|
32
|
+
from elizaos.types.database import AgentRunSummaryResult, IDatabaseAdapter, Log, MemorySearchOptions
|
|
24
33
|
from elizaos.types.environment import Entity, Room, World
|
|
25
34
|
from elizaos.types.events import EventType
|
|
26
35
|
from elizaos.types.memory import Memory
|
|
@@ -81,6 +90,48 @@ class StreamingModelHandlerWrapper:
|
|
|
81
90
|
|
|
82
91
|
_anonymous_agent_counter = 0
|
|
83
92
|
|
|
93
|
+
_MISSING = object()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _struct_value_to_python(value: StructValue) -> object | None:
|
|
97
|
+
kind = value.WhichOneof("kind")
|
|
98
|
+
if kind == "null_value":
|
|
99
|
+
return None
|
|
100
|
+
if kind == "number_value":
|
|
101
|
+
return value.number_value
|
|
102
|
+
if kind == "string_value":
|
|
103
|
+
return value.string_value
|
|
104
|
+
if kind == "bool_value":
|
|
105
|
+
return value.bool_value
|
|
106
|
+
if kind == "struct_value":
|
|
107
|
+
return {
|
|
108
|
+
key: _struct_value_to_python(item) for key, item in value.struct_value.fields.items()
|
|
109
|
+
}
|
|
110
|
+
if kind == "list_value":
|
|
111
|
+
return [_struct_value_to_python(item) for item in value.list_value.values]
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _is_struct_compatible(value: object) -> bool:
|
|
116
|
+
if value is None:
|
|
117
|
+
return True
|
|
118
|
+
if isinstance(value, (str, int, float, bool)):
|
|
119
|
+
return True
|
|
120
|
+
if isinstance(value, list):
|
|
121
|
+
return all(_is_struct_compatible(item) for item in value)
|
|
122
|
+
if isinstance(value, Mapping):
|
|
123
|
+
return all(
|
|
124
|
+
isinstance(map_key, str) and _is_struct_compatible(map_value)
|
|
125
|
+
for map_key, map_value in value.items()
|
|
126
|
+
)
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _to_runtime_setting_value(value: object | None) -> str | bool | int | float | None:
|
|
131
|
+
if value is None or isinstance(value, (str, bool, int, float)):
|
|
132
|
+
return value
|
|
133
|
+
return str(value)
|
|
134
|
+
|
|
84
135
|
|
|
85
136
|
class AgentRuntime(IAgentRuntime):
|
|
86
137
|
def __init__(
|
|
@@ -93,7 +144,7 @@ class AgentRuntime(IAgentRuntime):
|
|
|
93
144
|
conversation_length: int = 32,
|
|
94
145
|
log_level: str = "ERROR",
|
|
95
146
|
disable_basic_capabilities: bool = False,
|
|
96
|
-
|
|
147
|
+
advanced_capabilities: bool = False,
|
|
97
148
|
action_planning: bool | None = None,
|
|
98
149
|
llm_mode: LLMMode | None = None,
|
|
99
150
|
check_should_respond: bool | None = None,
|
|
@@ -112,7 +163,7 @@ class AgentRuntime(IAgentRuntime):
|
|
|
112
163
|
is_anonymous = True
|
|
113
164
|
|
|
114
165
|
self._capability_disable_basic = disable_basic_capabilities
|
|
115
|
-
self.
|
|
166
|
+
self._capability_advanced = advanced_capabilities
|
|
116
167
|
self._capability_enable_autonomy = enable_autonomy
|
|
117
168
|
self._is_anonymous_character = is_anonymous
|
|
118
169
|
self._action_planning_option = action_planning
|
|
@@ -289,8 +340,8 @@ class AgentRuntime(IAgentRuntime):
|
|
|
289
340
|
disable_basic = self._capability_disable_basic or (
|
|
290
341
|
char_settings.get("DISABLE_BASIC_CAPABILITIES") in (True, "true")
|
|
291
342
|
)
|
|
292
|
-
|
|
293
|
-
char_settings.get("
|
|
343
|
+
advanced_capabilities = self._capability_advanced or (
|
|
344
|
+
char_settings.get("ADVANCED_CAPABILITIES") in (True, "true")
|
|
294
345
|
)
|
|
295
346
|
skip_character_provider = self._is_anonymous_character
|
|
296
347
|
|
|
@@ -298,12 +349,12 @@ class AgentRuntime(IAgentRuntime):
|
|
|
298
349
|
char_settings.get("ENABLE_AUTONOMY") in (True, "true")
|
|
299
350
|
)
|
|
300
351
|
|
|
301
|
-
if disable_basic or
|
|
352
|
+
if disable_basic or advanced_capabilities or skip_character_provider or enable_autonomy:
|
|
302
353
|
from elizaos.bootstrap import CapabilityConfig, create_bootstrap_plugin
|
|
303
354
|
|
|
304
355
|
config = CapabilityConfig(
|
|
305
356
|
disable_basic=disable_basic,
|
|
306
|
-
|
|
357
|
+
advanced_capabilities=advanced_capabilities,
|
|
307
358
|
skip_character_provider=skip_character_provider,
|
|
308
359
|
enable_autonomy=enable_autonomy,
|
|
309
360
|
)
|
|
@@ -354,37 +405,58 @@ class AgentRuntime(IAgentRuntime):
|
|
|
354
405
|
if secret:
|
|
355
406
|
if self._character.secrets is None:
|
|
356
407
|
self._character.secrets = {}
|
|
357
|
-
if isinstance(self._character.secrets,
|
|
408
|
+
if isinstance(self._character.secrets, MutableMapping):
|
|
358
409
|
self._character.secrets[key] = value # type: ignore[assignment]
|
|
359
410
|
else:
|
|
360
411
|
# Fall back to internal settings dict for protobuf objects
|
|
361
|
-
self._settings[key] = value
|
|
412
|
+
self._settings[key] = _to_runtime_setting_value(value)
|
|
362
413
|
return
|
|
363
414
|
|
|
364
415
|
# Try to set on character.settings if it's a dict
|
|
365
|
-
if isinstance(self._character.settings,
|
|
416
|
+
if isinstance(self._character.settings, MutableMapping):
|
|
366
417
|
self._character.settings[key] = value # type: ignore[assignment]
|
|
418
|
+
return
|
|
419
|
+
|
|
420
|
+
settings_extra = getattr(self._character.settings, "extra", None)
|
|
421
|
+
if (
|
|
422
|
+
settings_extra is not None
|
|
423
|
+
and hasattr(settings_extra, "update")
|
|
424
|
+
and _is_struct_compatible(value)
|
|
425
|
+
):
|
|
426
|
+
settings_extra.update({key: value})
|
|
367
427
|
else:
|
|
368
428
|
# Fall back to internal settings dict for protobuf objects
|
|
369
|
-
self._settings[key] = value
|
|
429
|
+
self._settings[key] = _to_runtime_setting_value(value)
|
|
370
430
|
|
|
371
431
|
def get_setting(self, key: str) -> object | None:
|
|
372
432
|
settings = self._character.settings
|
|
373
433
|
secrets = self._character.secrets
|
|
374
434
|
|
|
375
|
-
nested_secrets:
|
|
376
|
-
|
|
435
|
+
nested_secrets: Mapping[str, object] | None = None
|
|
436
|
+
extra_value: object = _MISSING
|
|
437
|
+
if isinstance(settings, Mapping):
|
|
377
438
|
nested = settings.get("secrets")
|
|
378
|
-
if isinstance(nested,
|
|
439
|
+
if isinstance(nested, Mapping):
|
|
379
440
|
nested_secrets = nested
|
|
441
|
+
else:
|
|
442
|
+
settings_extra = getattr(settings, "extra", None)
|
|
443
|
+
settings_fields = getattr(settings_extra, "fields", None)
|
|
444
|
+
if isinstance(settings_fields, Mapping) and key in settings_fields:
|
|
445
|
+
struct_candidate = settings_fields[key]
|
|
446
|
+
if isinstance(struct_candidate, StructValue):
|
|
447
|
+
extra_value = _struct_value_to_python(struct_candidate)
|
|
448
|
+
else:
|
|
449
|
+
extra_value = struct_candidate
|
|
380
450
|
|
|
381
451
|
value: object | None
|
|
382
|
-
if isinstance(secrets,
|
|
452
|
+
if isinstance(secrets, Mapping) and key in secrets:
|
|
383
453
|
value = secrets.get(key)
|
|
384
|
-
elif isinstance(settings,
|
|
454
|
+
elif isinstance(settings, Mapping) and key in settings:
|
|
385
455
|
value = settings.get(key)
|
|
386
|
-
elif isinstance(nested_secrets,
|
|
456
|
+
elif isinstance(nested_secrets, Mapping) and key in nested_secrets:
|
|
387
457
|
value = nested_secrets.get(key)
|
|
458
|
+
elif extra_value is not _MISSING:
|
|
459
|
+
value = extra_value
|
|
388
460
|
else:
|
|
389
461
|
value = self._settings.get(key)
|
|
390
462
|
|
|
@@ -409,12 +481,17 @@ class AgentRuntime(IAgentRuntime):
|
|
|
409
481
|
|
|
410
482
|
def get_all_settings(self) -> dict[str, object | None]:
|
|
411
483
|
keys: set[str] = set(self._settings.keys())
|
|
412
|
-
if isinstance(self._character.settings,
|
|
484
|
+
if isinstance(self._character.settings, Mapping):
|
|
413
485
|
keys.update(self._character.settings.keys())
|
|
414
486
|
nested = self._character.settings.get("secrets")
|
|
415
|
-
if isinstance(nested,
|
|
487
|
+
if isinstance(nested, Mapping):
|
|
416
488
|
keys.update(nested.keys())
|
|
417
|
-
|
|
489
|
+
else:
|
|
490
|
+
settings_extra = getattr(self._character.settings, "extra", None)
|
|
491
|
+
settings_fields = getattr(settings_extra, "fields", None)
|
|
492
|
+
if isinstance(settings_fields, Mapping):
|
|
493
|
+
keys.update(settings_fields.keys())
|
|
494
|
+
if isinstance(self._character.secrets, Mapping):
|
|
418
495
|
keys.update(self._character.secrets.keys())
|
|
419
496
|
|
|
420
497
|
return {k: self.get_setting(k) for k in keys}
|
|
@@ -608,8 +685,14 @@ class AgentRuntime(IAgentRuntime):
|
|
|
608
685
|
errors.append(
|
|
609
686
|
f"Required parameter '{param_def.name}' was not provided for action {action.name}"
|
|
610
687
|
)
|
|
611
|
-
|
|
612
|
-
|
|
688
|
+
else:
|
|
689
|
+
default_value = getattr(param_def.schema, "default_value", None)
|
|
690
|
+
if isinstance(default_value, StructValue):
|
|
691
|
+
parsed_default = _struct_value_to_python(default_value)
|
|
692
|
+
if parsed_default is not None:
|
|
693
|
+
validated[param_def.name] = parsed_default
|
|
694
|
+
elif default_value is not None:
|
|
695
|
+
validated[param_def.name] = default_value
|
|
613
696
|
continue
|
|
614
697
|
|
|
615
698
|
schema_type = param_def.schema.type
|
|
@@ -770,6 +853,7 @@ class AgentRuntime(IAgentRuntime):
|
|
|
770
853
|
if data_params is not None:
|
|
771
854
|
# Convert protobuf Struct to dict for _parse_action_params
|
|
772
855
|
from google.protobuf.json_format import MessageToDict
|
|
856
|
+
|
|
773
857
|
if hasattr(data_params, "DESCRIPTOR"):
|
|
774
858
|
params_raw = MessageToDict(data_params)
|
|
775
859
|
else:
|
|
@@ -802,11 +886,8 @@ class AgentRuntime(IAgentRuntime):
|
|
|
802
886
|
actionName=action.name,
|
|
803
887
|
errors=errors,
|
|
804
888
|
)
|
|
805
|
-
|
|
889
|
+
with contextlib.suppress(AttributeError, ValueError):
|
|
806
890
|
options_obj.parameter_errors = errors
|
|
807
|
-
except (AttributeError, ValueError):
|
|
808
|
-
# Protobuf HandlerOptions may not have parameter_errors field
|
|
809
|
-
pass
|
|
810
891
|
|
|
811
892
|
if validated_params:
|
|
812
893
|
from google.protobuf import struct_pb2
|
|
@@ -891,7 +972,7 @@ class AgentRuntime(IAgentRuntime):
|
|
|
891
972
|
self,
|
|
892
973
|
message: Memory,
|
|
893
974
|
state: State | None = None,
|
|
894
|
-
) ->
|
|
975
|
+
) -> PreEvaluatorResult:
|
|
895
976
|
"""Run phase='pre' evaluators as middleware before memory storage.
|
|
896
977
|
|
|
897
978
|
Pre-evaluators can inspect, rewrite, or block a message before it
|
|
@@ -902,8 +983,6 @@ class AgentRuntime(IAgentRuntime):
|
|
|
902
983
|
Returns:
|
|
903
984
|
A merged PreEvaluatorResult.
|
|
904
985
|
"""
|
|
905
|
-
from elizaos.types.components import PreEvaluatorResult
|
|
906
|
-
|
|
907
986
|
pre_evaluators = [e for e in self._evaluators if getattr(e, "phase", "post") == "pre"]
|
|
908
987
|
if not pre_evaluators:
|
|
909
988
|
return PreEvaluatorResult(blocked=False)
|
|
@@ -1057,12 +1136,17 @@ class AgentRuntime(IAgentRuntime):
|
|
|
1057
1136
|
include_list: list[str] | None = None,
|
|
1058
1137
|
only_include: bool = False,
|
|
1059
1138
|
skip_cache: bool = False,
|
|
1139
|
+
trajectory_phase: str | None = None,
|
|
1060
1140
|
) -> State:
|
|
1061
1141
|
# If we're running inside a trajectory step, always bypass the state cache
|
|
1062
1142
|
# so providers are executed and logged for training/benchmark traces.
|
|
1063
1143
|
traj_step_id: str | None = None
|
|
1064
1144
|
if message.metadata is not None:
|
|
1065
1145
|
maybe_step = getattr(message.metadata, "trajectoryStepId", None)
|
|
1146
|
+
if not maybe_step and hasattr(message.metadata, "message"):
|
|
1147
|
+
# Check nested MessageMetadata for parsing parity
|
|
1148
|
+
maybe_step = message.metadata.message.trajectory_step_id
|
|
1149
|
+
|
|
1066
1150
|
if isinstance(maybe_step, str) and maybe_step:
|
|
1067
1151
|
traj_step_id = maybe_step
|
|
1068
1152
|
skip_cache = True
|
|
@@ -1133,6 +1217,9 @@ class AgentRuntime(IAgentRuntime):
|
|
|
1133
1217
|
out[k] = _as_json_scalar(v)
|
|
1134
1218
|
return out
|
|
1135
1219
|
|
|
1220
|
+
# Resolve the purpose label for trajectory provider accesses
|
|
1221
|
+
traj_purpose = f"compose_state:{trajectory_phase}" if trajectory_phase else "compose_state"
|
|
1222
|
+
|
|
1136
1223
|
text_parts: list[str] = []
|
|
1137
1224
|
for provider in providers_to_run:
|
|
1138
1225
|
if provider.private:
|
|
@@ -1155,18 +1242,18 @@ class AgentRuntime(IAgentRuntime):
|
|
|
1155
1242
|
|
|
1156
1243
|
# Log provider access to trajectory service (if available)
|
|
1157
1244
|
if traj_step_id and traj_logger is not None:
|
|
1158
|
-
|
|
1159
|
-
|
|
1245
|
+
# Trajectory logging must never break core message flow.
|
|
1246
|
+
with contextlib.suppress(Exception):
|
|
1160
1247
|
traj_logger.log_provider_access(
|
|
1161
1248
|
step_id=traj_step_id,
|
|
1162
1249
|
provider_name=provider.name,
|
|
1163
|
-
data=
|
|
1164
|
-
|
|
1165
|
-
|
|
1250
|
+
data={
|
|
1251
|
+
"textLength": len(result.text) if result.text else 0,
|
|
1252
|
+
"hasValues": bool(result.values),
|
|
1253
|
+
"hasData": bool(result.data),
|
|
1254
|
+
},
|
|
1255
|
+
purpose=traj_purpose,
|
|
1166
1256
|
)
|
|
1167
|
-
except Exception:
|
|
1168
|
-
# Trajectory logging must never break core message flow.
|
|
1169
|
-
pass
|
|
1170
1257
|
|
|
1171
1258
|
state.text = "\n".join(text_parts)
|
|
1172
1259
|
# Match TypeScript behavior: expose providers text under {{providers}}.
|
|
@@ -1260,16 +1347,25 @@ class AgentRuntime(IAgentRuntime):
|
|
|
1260
1347
|
max_tokens_raw = params.get("maxTokens") if isinstance(params, dict) else None
|
|
1261
1348
|
max_tokens = int(max_tokens_raw) if isinstance(max_tokens_raw, int) else 0
|
|
1262
1349
|
|
|
1350
|
+
# Truncate embedding vectors to avoid bloating trajectory files
|
|
1351
|
+
result_str = str(result)
|
|
1352
|
+
is_embedding = "EMBEDDING" in str(effective_model_type).upper()
|
|
1353
|
+
if is_embedding and len(result_str) > 200:
|
|
1354
|
+
dim = result_str.count(",") + 1
|
|
1355
|
+
result_str = f"[embedding vector dim={dim}]"
|
|
1356
|
+
elif len(result_str) > 2000:
|
|
1357
|
+
result_str = result_str[:2000]
|
|
1358
|
+
|
|
1263
1359
|
traj_svc.log_llm_call( # type: ignore[call-arg]
|
|
1264
1360
|
step_id=step_id,
|
|
1265
1361
|
model=str(effective_model_type),
|
|
1266
1362
|
system_prompt=system_prompt,
|
|
1267
|
-
user_prompt=prompt,
|
|
1268
|
-
response=
|
|
1363
|
+
user_prompt=prompt[:2000] if prompt else "",
|
|
1364
|
+
response=result_str,
|
|
1269
1365
|
temperature=temperature,
|
|
1270
1366
|
max_tokens=max_tokens,
|
|
1271
1367
|
purpose="action",
|
|
1272
|
-
action_type="runtime.
|
|
1368
|
+
action_type="runtime.useModel",
|
|
1273
1369
|
latency_ms=max(0, end_ms - start_ms),
|
|
1274
1370
|
)
|
|
1275
1371
|
except Exception:
|
|
@@ -1648,6 +1744,12 @@ class AgentRuntime(IAgentRuntime):
|
|
|
1648
1744
|
if self._adapter:
|
|
1649
1745
|
await self._adapter.delete_component(component_id)
|
|
1650
1746
|
|
|
1747
|
+
async def search_memories(self, params: MemorySearchOptions) -> list[Memory]:
|
|
1748
|
+
"""Search memories by embedding."""
|
|
1749
|
+
if not self._adapter:
|
|
1750
|
+
raise RuntimeError("Database adapter not set")
|
|
1751
|
+
return await self._adapter.search_memories(params)
|
|
1752
|
+
|
|
1651
1753
|
async def get_memories(
|
|
1652
1754
|
self,
|
|
1653
1755
|
params: dict[str, Any] | None = None,
|
|
@@ -1982,6 +2084,12 @@ class AgentRuntime(IAgentRuntime):
|
|
|
1982
2084
|
|
|
1983
2085
|
schema_key = ",".join(s.field for s in schema)
|
|
1984
2086
|
model_schema_key = f"{model_type_str}:{schema_key}"
|
|
2087
|
+
deterministic_seed = build_conversation_seed(
|
|
2088
|
+
self,
|
|
2089
|
+
None,
|
|
2090
|
+
state,
|
|
2091
|
+
f"dynamic-prompt:{model_schema_key}",
|
|
2092
|
+
)
|
|
1985
2093
|
|
|
1986
2094
|
# Get validation level from settings or options (mirrors TypeScript behavior)
|
|
1987
2095
|
default_context_level = 2
|
|
@@ -2023,7 +2131,11 @@ class AgentRuntime(IAgentRuntime):
|
|
|
2023
2131
|
row.validate_field if row.validate_field is not None else default_validate
|
|
2024
2132
|
)
|
|
2025
2133
|
if needs_validation:
|
|
2026
|
-
per_field_codes[row.field] =
|
|
2134
|
+
per_field_codes[row.field] = deterministic_hex(
|
|
2135
|
+
deterministic_seed,
|
|
2136
|
+
f"field-code:{row.field}",
|
|
2137
|
+
8,
|
|
2138
|
+
)
|
|
2027
2139
|
|
|
2028
2140
|
# Streaming extractor (created on first iteration if streaming enabled)
|
|
2029
2141
|
extractor: ValidationStreamExtractor | None = None
|
|
@@ -2147,9 +2259,18 @@ class AgentRuntime(IAgentRuntime):
|
|
|
2147
2259
|
example_lines.append(container_end)
|
|
2148
2260
|
example = "\n".join(example_lines)
|
|
2149
2261
|
|
|
2150
|
-
init_code =
|
|
2151
|
-
|
|
2152
|
-
|
|
2262
|
+
init_code = deterministic_uuid(
|
|
2263
|
+
deterministic_seed,
|
|
2264
|
+
f"init-code:{current_retry}",
|
|
2265
|
+
)
|
|
2266
|
+
mid_code = deterministic_uuid(
|
|
2267
|
+
deterministic_seed,
|
|
2268
|
+
f"mid-code:{current_retry}",
|
|
2269
|
+
)
|
|
2270
|
+
final_code = deterministic_uuid(
|
|
2271
|
+
deterministic_seed,
|
|
2272
|
+
f"final-code:{current_retry}",
|
|
2273
|
+
)
|
|
2153
2274
|
|
|
2154
2275
|
section_start = "<output>" if is_xml else "# Strict Output instructions"
|
|
2155
2276
|
section_end = "</output>" if is_xml else ""
|
|
@@ -2223,25 +2344,40 @@ end code: {final_code}
|
|
|
2223
2344
|
if not stream_fields and any(row.field == "text" for row in schema):
|
|
2224
2345
|
stream_fields = ["text"]
|
|
2225
2346
|
|
|
2226
|
-
stream_message_id =
|
|
2347
|
+
stream_message_id = "stream-" + deterministic_hex(
|
|
2348
|
+
deterministic_seed,
|
|
2349
|
+
f"stream-message-id:{current_retry}",
|
|
2350
|
+
20,
|
|
2351
|
+
)
|
|
2352
|
+
|
|
2353
|
+
on_stream_chunk = options.on_stream_chunk
|
|
2354
|
+
on_stream_event = options.on_stream_event
|
|
2355
|
+
|
|
2356
|
+
def _emit_chunk(
|
|
2357
|
+
chunk: str,
|
|
2358
|
+
_field: str | None,
|
|
2359
|
+
cb=on_stream_chunk,
|
|
2360
|
+
msg_id=stream_message_id,
|
|
2361
|
+
) -> None:
|
|
2362
|
+
if cb is not None:
|
|
2363
|
+
cb(chunk, msg_id)
|
|
2364
|
+
|
|
2365
|
+
def _emit_event(
|
|
2366
|
+
event: StreamEvent,
|
|
2367
|
+
cb=on_stream_event,
|
|
2368
|
+
msg_id=stream_message_id,
|
|
2369
|
+
) -> None:
|
|
2370
|
+
if cb is not None:
|
|
2371
|
+
cb(event, msg_id)
|
|
2227
2372
|
|
|
2228
|
-
# Capture stream_message_id in default parameter to avoid late binding
|
|
2229
2373
|
extractor = ValidationStreamExtractor(
|
|
2230
2374
|
ValidationStreamExtractorConfig(
|
|
2231
2375
|
level=validation_level,
|
|
2232
2376
|
schema=schema,
|
|
2233
2377
|
stream_fields=stream_fields,
|
|
2234
2378
|
expected_codes=per_field_codes,
|
|
2235
|
-
on_chunk=
|
|
2236
|
-
|
|
2237
|
-
msg_id=stream_message_id: options.on_stream_chunk(chunk, msg_id)
|
|
2238
|
-
if options.on_stream_chunk
|
|
2239
|
-
else None,
|
|
2240
|
-
on_event=lambda event, msg_id=stream_message_id: options.on_stream_event(
|
|
2241
|
-
event, msg_id
|
|
2242
|
-
)
|
|
2243
|
-
if options.on_stream_event
|
|
2244
|
-
else None,
|
|
2379
|
+
on_chunk=_emit_chunk,
|
|
2380
|
+
on_event=_emit_event if on_stream_event is not None else None,
|
|
2245
2381
|
abort_signal=options.abort_signal,
|
|
2246
2382
|
has_rich_consumer=has_rich_consumer,
|
|
2247
2383
|
)
|
|
@@ -2268,6 +2404,28 @@ end code: {final_code}
|
|
|
2268
2404
|
# Flush extractor and get final state
|
|
2269
2405
|
extractor.flush()
|
|
2270
2406
|
response_str = "".join(response_parts)
|
|
2407
|
+
|
|
2408
|
+
# Log streaming response to trajectory (streaming bypasses use_model hook)
|
|
2409
|
+
try:
|
|
2410
|
+
from elizaos.trajectory_context import CURRENT_TRAJECTORY_STEP_ID
|
|
2411
|
+
|
|
2412
|
+
step_id = CURRENT_TRAJECTORY_STEP_ID.get()
|
|
2413
|
+
traj_svc = self.get_service("trajectory_logger")
|
|
2414
|
+
if step_id and traj_svc is not None and hasattr(traj_svc, "log_llm_call"):
|
|
2415
|
+
traj_svc.log_llm_call( # type: ignore[call-arg]
|
|
2416
|
+
step_id=step_id,
|
|
2417
|
+
model=stream_model_type,
|
|
2418
|
+
system_prompt="",
|
|
2419
|
+
user_prompt=str(params.get("prompt", ""))[:2000],
|
|
2420
|
+
response=response_str[:2000],
|
|
2421
|
+
temperature=0.0,
|
|
2422
|
+
max_tokens=int(params.get("maxTokens", 0)),
|
|
2423
|
+
purpose="action",
|
|
2424
|
+
action_type="dynamic_prompt_exec.stream",
|
|
2425
|
+
latency_ms=0,
|
|
2426
|
+
)
|
|
2427
|
+
except Exception:
|
|
2428
|
+
pass
|
|
2271
2429
|
else:
|
|
2272
2430
|
# Non-streaming mode: use use_model
|
|
2273
2431
|
response = await self.use_model(model_type_str, params)
|