@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
|
@@ -10,7 +10,7 @@ from uuid import UUID, uuid4
|
|
|
10
10
|
from google.protobuf.json_format import MessageToDict
|
|
11
11
|
|
|
12
12
|
from elizaos.logger import Logger
|
|
13
|
-
from elizaos.types.components import ActionContext, ActionResult, HandlerCallback
|
|
13
|
+
from elizaos.types.components import ActionContext, ActionResult, HandlerCallback
|
|
14
14
|
from elizaos.types.memory import Memory
|
|
15
15
|
from elizaos.types.primitives import Content
|
|
16
16
|
from elizaos.types.service import Service
|
|
@@ -538,6 +538,8 @@ Focus on:
|
|
|
538
538
|
]
|
|
539
539
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
540
540
|
for r in results:
|
|
541
|
+
if isinstance(r, Exception):
|
|
542
|
+
raise RuntimeError(f"Plan step failed during parallel execution: {r}") from r
|
|
541
543
|
if isinstance(r, ActionResult):
|
|
542
544
|
execution.results.append(r)
|
|
543
545
|
|
|
@@ -586,6 +588,10 @@ Focus on:
|
|
|
586
588
|
|
|
587
589
|
for step, r in zip(ready_batch, results, strict=False):
|
|
588
590
|
completed_count += 1
|
|
591
|
+
if isinstance(r, Exception):
|
|
592
|
+
raise RuntimeError(
|
|
593
|
+
f"Plan step '{step.action_name}' failed during DAG execution: {r}"
|
|
594
|
+
) from r
|
|
589
595
|
if isinstance(r, ActionResult):
|
|
590
596
|
execution.results.append(r)
|
|
591
597
|
|
|
@@ -622,13 +628,16 @@ Focus on:
|
|
|
622
628
|
if execution.abort_event.is_set():
|
|
623
629
|
raise RuntimeError("Plan execution aborted")
|
|
624
630
|
try:
|
|
625
|
-
options =
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
631
|
+
options = type(
|
|
632
|
+
"_PlanningHandlerOptions",
|
|
633
|
+
(),
|
|
634
|
+
{
|
|
635
|
+
"action_context": action_context,
|
|
636
|
+
"parameters": step.parameters,
|
|
637
|
+
"previous_results": previous_results,
|
|
638
|
+
"context": {"workingMemory": execution.working_memory},
|
|
639
|
+
},
|
|
640
|
+
)()
|
|
632
641
|
|
|
633
642
|
validate_fn = getattr(action, "validate", None) or getattr(
|
|
634
643
|
action, "validate_fn", None
|
|
@@ -641,12 +650,15 @@ Focus on:
|
|
|
641
650
|
if result is None:
|
|
642
651
|
return None
|
|
643
652
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
653
|
+
step_metadata = {
|
|
654
|
+
"stepId": str(step.id),
|
|
655
|
+
"actionName": step.action_name,
|
|
656
|
+
"executedAt": int(time.time() * 1000),
|
|
657
|
+
}
|
|
658
|
+
if isinstance(result.data, dict) or hasattr(result.data, "update"):
|
|
659
|
+
result.data.update(step_metadata)
|
|
660
|
+
else:
|
|
661
|
+
result.data = step_metadata
|
|
650
662
|
return result
|
|
651
663
|
except Exception as e:
|
|
652
664
|
retries += 1
|
|
@@ -18,7 +18,6 @@ from .providers import (
|
|
|
18
18
|
actions_provider,
|
|
19
19
|
attachments_provider,
|
|
20
20
|
basic_providers,
|
|
21
|
-
capabilities_provider,
|
|
22
21
|
character_provider,
|
|
23
22
|
choice_provider,
|
|
24
23
|
context_bench_provider,
|
|
@@ -48,7 +47,6 @@ __all__ = [
|
|
|
48
47
|
"action_state_provider",
|
|
49
48
|
"actions_provider",
|
|
50
49
|
"attachments_provider",
|
|
51
|
-
"capabilities_provider",
|
|
52
50
|
"character_provider",
|
|
53
51
|
"choice_provider",
|
|
54
52
|
"context_bench_provider",
|
|
@@ -6,7 +6,6 @@ Fundamental providers included by default in the bootstrap plugin.
|
|
|
6
6
|
from .action_state import action_state_provider
|
|
7
7
|
from .actions import actions_provider
|
|
8
8
|
from .attachments import attachments_provider
|
|
9
|
-
from .capabilities import capabilities_provider
|
|
10
9
|
from .character import character_provider
|
|
11
10
|
from .choice import choice_provider
|
|
12
11
|
from .context_bench import context_bench_provider
|
|
@@ -22,7 +21,6 @@ __all__ = [
|
|
|
22
21
|
"action_state_provider",
|
|
23
22
|
"actions_provider",
|
|
24
23
|
"attachments_provider",
|
|
25
|
-
"capabilities_provider",
|
|
26
24
|
"character_provider",
|
|
27
25
|
"choice_provider",
|
|
28
26
|
"context_bench_provider",
|
|
@@ -40,7 +38,6 @@ basic_providers = [
|
|
|
40
38
|
actions_provider,
|
|
41
39
|
action_state_provider,
|
|
42
40
|
attachments_provider,
|
|
43
|
-
capabilities_provider,
|
|
44
41
|
character_provider,
|
|
45
42
|
choice_provider,
|
|
46
43
|
context_bench_provider,
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import contextlib
|
|
4
|
+
from typing import TYPE_CHECKING, TypeVar, cast
|
|
4
5
|
|
|
5
6
|
from google.protobuf.json_format import MessageToDict
|
|
6
7
|
|
|
7
8
|
from elizaos.action_docs import get_canonical_action_example_calls
|
|
9
|
+
from elizaos.deterministic import (
|
|
10
|
+
build_conversation_seed,
|
|
11
|
+
build_deterministic_seed,
|
|
12
|
+
deterministic_int,
|
|
13
|
+
)
|
|
8
14
|
from elizaos.generated.spec_helpers import require_provider_spec
|
|
9
15
|
from elizaos.types import Provider, ProviderResult
|
|
10
16
|
from elizaos.types.components import ActionExample
|
|
@@ -23,10 +29,6 @@ if TYPE_CHECKING:
|
|
|
23
29
|
_spec = require_provider_spec("ACTIONS")
|
|
24
30
|
|
|
25
31
|
|
|
26
|
-
def format_action_names(actions: list[Action]) -> str:
|
|
27
|
-
return ", ".join(action.name for action in actions)
|
|
28
|
-
|
|
29
|
-
|
|
30
32
|
def _format_parameter_type(schema: ActionParameterSchema) -> str:
|
|
31
33
|
if schema.type == "number" and (schema.minimum is not None or schema.maximum is not None):
|
|
32
34
|
min_val = schema.minimum if schema.minimum is not None else "∞"
|
|
@@ -35,9 +37,10 @@ def _format_parameter_type(schema: ActionParameterSchema) -> str:
|
|
|
35
37
|
return schema.type
|
|
36
38
|
|
|
37
39
|
|
|
38
|
-
def _get_param_schema(param: ActionParameter) ->
|
|
40
|
+
def _get_param_schema(param: ActionParameter) -> ActionParameterSchema | None:
|
|
39
41
|
"""Get schema from ActionParameter, handling both Pydantic and protobuf variants."""
|
|
40
|
-
|
|
42
|
+
schema = getattr(param, "schema_def", None) or getattr(param, "schema", None)
|
|
43
|
+
return cast("ActionParameterSchema | None", schema)
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
def _format_action_parameters(parameters: list[ActionParameter]) -> str:
|
|
@@ -64,9 +67,23 @@ def _format_action_parameters(parameters: list[ActionParameter]) -> str:
|
|
|
64
67
|
return "\n".join(lines)
|
|
65
68
|
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
T = TypeVar("T")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _deterministic_shuffle(items: list[T], seed: str, surface: str = "shuffle") -> list[T]:
|
|
74
|
+
shuffled = list(items)
|
|
75
|
+
for i in range(len(shuffled) - 1, 0, -1):
|
|
76
|
+
j = deterministic_int(seed, f"{surface}:{i}", i + 1)
|
|
77
|
+
shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
|
|
78
|
+
return shuffled
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def format_actions(actions: list[Action], seed: str | None = None) -> str:
|
|
82
|
+
deterministic_seed = seed or build_deterministic_seed(
|
|
83
|
+
["actions-format", ",".join(action.name for action in actions)]
|
|
84
|
+
)
|
|
68
85
|
lines: list[str] = []
|
|
69
|
-
for action in actions:
|
|
86
|
+
for action in _deterministic_shuffle(actions, deterministic_seed, "actions"):
|
|
70
87
|
line = f"- **{action.name}**: {action.description or 'No description'}"
|
|
71
88
|
if action.parameters:
|
|
72
89
|
params_text = _format_action_parameters(action.parameters)
|
|
@@ -83,7 +100,24 @@ def _replace_name_placeholders(text: str) -> str:
|
|
|
83
100
|
return text
|
|
84
101
|
|
|
85
102
|
|
|
86
|
-
def
|
|
103
|
+
def _replace_name_placeholders_seeded(text: str, seed: str, example_index: int) -> str:
|
|
104
|
+
names = ["Alex", "Jordan", "Sam", "Taylor", "Riley"]
|
|
105
|
+
output = text
|
|
106
|
+
for placeholder_index in range(1, 6):
|
|
107
|
+
name_index = deterministic_int(
|
|
108
|
+
seed,
|
|
109
|
+
f"example:{example_index}:name:{placeholder_index}",
|
|
110
|
+
len(names),
|
|
111
|
+
)
|
|
112
|
+
output = output.replace(f"{{{{name{placeholder_index}}}}}", names[name_index])
|
|
113
|
+
return output
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def format_action_examples(
|
|
117
|
+
actions: list[Action],
|
|
118
|
+
max_examples: int = 10,
|
|
119
|
+
seed: str | None = None,
|
|
120
|
+
) -> str:
|
|
87
121
|
"""
|
|
88
122
|
Format a deterministic subset of action examples for prompt context.
|
|
89
123
|
|
|
@@ -92,27 +126,60 @@ def format_action_examples(actions: list[Action], max_examples: int = 10) -> str
|
|
|
92
126
|
if max_examples <= 0:
|
|
93
127
|
return ""
|
|
94
128
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
examples.append(ex)
|
|
102
|
-
if len(examples) >= max_examples:
|
|
103
|
-
break
|
|
104
|
-
if len(examples) >= max_examples:
|
|
105
|
-
break
|
|
106
|
-
|
|
107
|
-
if not examples:
|
|
129
|
+
actions_with_examples = [
|
|
130
|
+
action
|
|
131
|
+
for action in actions
|
|
132
|
+
if action.examples and isinstance(action.examples, list) and len(action.examples) > 0
|
|
133
|
+
]
|
|
134
|
+
if not actions_with_examples:
|
|
108
135
|
return ""
|
|
109
136
|
|
|
137
|
+
examples_copy: list[list[list[ActionExample]]] = [
|
|
138
|
+
[example for example in (action.examples or []) if isinstance(example, list) and example]
|
|
139
|
+
for action in actions_with_examples
|
|
140
|
+
]
|
|
141
|
+
available_action_indices = [
|
|
142
|
+
idx for idx, action_examples in enumerate(examples_copy) if action_examples
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
selection_seed = seed or build_deterministic_seed(
|
|
146
|
+
[
|
|
147
|
+
"action-examples",
|
|
148
|
+
",".join(action.name for action in actions_with_examples),
|
|
149
|
+
max_examples,
|
|
150
|
+
]
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
selected_examples: list[list[ActionExample]] = []
|
|
154
|
+
iteration = 0
|
|
155
|
+
while len(selected_examples) < max_examples and available_action_indices:
|
|
156
|
+
random_index = deterministic_int(
|
|
157
|
+
selection_seed,
|
|
158
|
+
f"action-index:{iteration}",
|
|
159
|
+
len(available_action_indices),
|
|
160
|
+
)
|
|
161
|
+
action_index = available_action_indices[random_index]
|
|
162
|
+
action_examples = examples_copy[action_index]
|
|
163
|
+
|
|
164
|
+
example_index = deterministic_int(
|
|
165
|
+
selection_seed,
|
|
166
|
+
f"example-index:{iteration}",
|
|
167
|
+
len(action_examples),
|
|
168
|
+
)
|
|
169
|
+
selected_examples.append(action_examples.pop(example_index))
|
|
170
|
+
iteration += 1
|
|
171
|
+
|
|
172
|
+
if not action_examples:
|
|
173
|
+
available_action_indices.pop(random_index)
|
|
174
|
+
|
|
110
175
|
blocks: list[str] = []
|
|
111
|
-
for ex in
|
|
176
|
+
for example_index, ex in enumerate(selected_examples):
|
|
112
177
|
lines: list[str] = []
|
|
113
178
|
for msg in ex:
|
|
114
179
|
msg_text = msg.content.text if msg.content and msg.content.text else ""
|
|
115
|
-
lines.append(
|
|
180
|
+
lines.append(
|
|
181
|
+
f"{msg.name}: {_replace_name_placeholders_seeded(msg_text, selection_seed, example_index)}"
|
|
182
|
+
)
|
|
116
183
|
blocks.append("\n".join(lines))
|
|
117
184
|
|
|
118
185
|
return "\n\n".join(blocks)
|
|
@@ -182,6 +249,17 @@ def format_action_call_examples(actions: list[Action], max_examples: int = 5) ->
|
|
|
182
249
|
return "\n\n".join(blocks)
|
|
183
250
|
|
|
184
251
|
|
|
252
|
+
def format_action_names(actions: list[Action], seed: str | None = None) -> str:
|
|
253
|
+
if not actions:
|
|
254
|
+
return ""
|
|
255
|
+
|
|
256
|
+
deterministic_seed = seed or build_deterministic_seed(
|
|
257
|
+
["action-names", ",".join(action.name for action in actions)]
|
|
258
|
+
)
|
|
259
|
+
shuffled = _deterministic_shuffle(actions, deterministic_seed, "actions")
|
|
260
|
+
return ", ".join(action.name for action in shuffled)
|
|
261
|
+
|
|
262
|
+
|
|
185
263
|
async def get_actions(
|
|
186
264
|
runtime: IAgentRuntime,
|
|
187
265
|
message: Memory,
|
|
@@ -193,16 +271,27 @@ async def get_actions(
|
|
|
193
271
|
# Support both validate and validate_fn for backwards compatibility
|
|
194
272
|
validate_fn = getattr(action, "validate", None) or getattr(action, "validate_fn", None)
|
|
195
273
|
if validate_fn:
|
|
196
|
-
|
|
274
|
+
try:
|
|
275
|
+
is_valid = await validate_fn(runtime, message, state)
|
|
276
|
+
except Exception:
|
|
277
|
+
if hasattr(runtime, "logger"):
|
|
278
|
+
with contextlib.suppress(Exception):
|
|
279
|
+
runtime.logger.warning(
|
|
280
|
+
f"Action validation failed for {action.name}; excluding from prompt"
|
|
281
|
+
)
|
|
282
|
+
is_valid = False
|
|
197
283
|
if is_valid:
|
|
198
284
|
validated_actions.append(action)
|
|
199
285
|
else:
|
|
200
286
|
# If no validation function, include the action
|
|
201
287
|
validated_actions.append(action)
|
|
202
288
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
289
|
+
action_seed = build_conversation_seed(runtime, message, state, "provider:actions")
|
|
290
|
+
action_names = format_action_names(validated_actions, seed=f"{action_seed}:names")
|
|
291
|
+
actions_text = format_actions(validated_actions, seed=f"{action_seed}:descriptions")
|
|
292
|
+
examples_text = format_action_examples(
|
|
293
|
+
validated_actions, max_examples=10, seed=f"{action_seed}:examples"
|
|
294
|
+
)
|
|
206
295
|
call_examples_text = format_action_call_examples(validated_actions, max_examples=5)
|
|
207
296
|
|
|
208
297
|
text_parts: list[str] = [f"Possible response actions: {action_names}"]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from elizaos.generated.spec_helpers import require_provider_spec
|
|
6
|
+
from elizaos.types import Provider, ProviderResult
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from elizaos.types import IAgentRuntime, Memory, State
|
|
10
|
+
|
|
11
|
+
# Get text content from centralized specs
|
|
12
|
+
_spec = require_provider_spec("AGENT_SETTINGS")
|
|
13
|
+
|
|
14
|
+
SENSITIVE_KEY_PATTERNS = (
|
|
15
|
+
"key",
|
|
16
|
+
"secret",
|
|
17
|
+
"password",
|
|
18
|
+
"token",
|
|
19
|
+
"credential",
|
|
20
|
+
"auth",
|
|
21
|
+
"private",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def get_agent_settings_context(
|
|
26
|
+
runtime: IAgentRuntime,
|
|
27
|
+
message: Memory,
|
|
28
|
+
state: State | None = None,
|
|
29
|
+
) -> ProviderResult:
|
|
30
|
+
all_settings = runtime.get_all_settings()
|
|
31
|
+
|
|
32
|
+
safe_settings: dict[str, str] = {}
|
|
33
|
+
for key, value in all_settings.items():
|
|
34
|
+
if not any(pattern in key.lower() for pattern in SENSITIVE_KEY_PATTERNS):
|
|
35
|
+
safe_settings[key] = str(value)
|
|
36
|
+
|
|
37
|
+
sections: list[str] = []
|
|
38
|
+
if safe_settings:
|
|
39
|
+
sections.append("# Agent Settings")
|
|
40
|
+
for key, value in safe_settings.items():
|
|
41
|
+
display_value = value if len(value) <= 50 else value[:50] + "..."
|
|
42
|
+
sections.append(f"- {key}: {display_value}")
|
|
43
|
+
|
|
44
|
+
context_text = "\n".join(sections) if sections else ""
|
|
45
|
+
|
|
46
|
+
return ProviderResult(
|
|
47
|
+
text=context_text,
|
|
48
|
+
values={
|
|
49
|
+
"settingsCount": len(safe_settings),
|
|
50
|
+
"hasSettings": len(safe_settings) > 0,
|
|
51
|
+
},
|
|
52
|
+
data={
|
|
53
|
+
"settings": safe_settings,
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
agent_settings_provider = Provider(
|
|
59
|
+
name=_spec["name"],
|
|
60
|
+
description=_spec["description"],
|
|
61
|
+
get=get_agent_settings_context,
|
|
62
|
+
dynamic=_spec.get("dynamic", True),
|
|
63
|
+
position=_spec.get("position"),
|
|
64
|
+
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import Iterable
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from elizaos.generated.spec_helpers import require_provider_spec
|
|
@@ -27,6 +28,19 @@ def _resolve_name_list(items: list[str], name: str) -> list[str]:
|
|
|
27
28
|
return [_resolve_name(s, name) for s in items]
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
def _coerce_text_list(value: object) -> list[str]:
|
|
32
|
+
"""Normalize protobuf repeated fields and plain Python values to list[str]."""
|
|
33
|
+
if value is None:
|
|
34
|
+
return []
|
|
35
|
+
if isinstance(value, str):
|
|
36
|
+
return [value]
|
|
37
|
+
if isinstance(value, (list, tuple)):
|
|
38
|
+
return [str(item) for item in value]
|
|
39
|
+
if isinstance(value, Iterable):
|
|
40
|
+
return [str(item) for item in value]
|
|
41
|
+
return [str(value)]
|
|
42
|
+
|
|
43
|
+
|
|
30
44
|
async def get_character_context(
|
|
31
45
|
runtime: IAgentRuntime,
|
|
32
46
|
message: Memory,
|
|
@@ -47,11 +61,7 @@ async def get_character_context(
|
|
|
47
61
|
sections.append(f"\n## Bio\n{bio_text}")
|
|
48
62
|
|
|
49
63
|
if character.adjectives:
|
|
50
|
-
adjectives = (
|
|
51
|
-
character.adjectives
|
|
52
|
-
if isinstance(character.adjectives, list)
|
|
53
|
-
else [character.adjectives]
|
|
54
|
-
)
|
|
64
|
+
adjectives = _coerce_text_list(character.adjectives)
|
|
55
65
|
resolved_adjectives = _resolve_name_list(adjectives, agent_name)
|
|
56
66
|
sections.append(f"\n## Personality Traits\n{', '.join(resolved_adjectives)}")
|
|
57
67
|
|
|
@@ -65,34 +75,22 @@ async def get_character_context(
|
|
|
65
75
|
sections.append(f"\n## Background\n{lore_text}")
|
|
66
76
|
|
|
67
77
|
if character.topics:
|
|
68
|
-
topics =
|
|
78
|
+
topics = _coerce_text_list(character.topics)
|
|
69
79
|
resolved_topics = _resolve_name_list(topics, agent_name)
|
|
70
80
|
sections.append(f"\n## Knowledge Areas\n{', '.join(resolved_topics)}")
|
|
71
81
|
|
|
72
82
|
if character.style:
|
|
73
83
|
style_sections: list[str] = []
|
|
74
84
|
if character.style.all:
|
|
75
|
-
all_style = (
|
|
76
|
-
character.style.all
|
|
77
|
-
if isinstance(character.style.all, list)
|
|
78
|
-
else [character.style.all]
|
|
79
|
-
)
|
|
85
|
+
all_style = _coerce_text_list(character.style.all)
|
|
80
86
|
resolved_all = _resolve_name_list(all_style, agent_name)
|
|
81
87
|
style_sections.append(f"General: {', '.join(resolved_all)}")
|
|
82
88
|
if character.style.chat:
|
|
83
|
-
chat_style = (
|
|
84
|
-
character.style.chat
|
|
85
|
-
if isinstance(character.style.chat, list)
|
|
86
|
-
else [character.style.chat]
|
|
87
|
-
)
|
|
89
|
+
chat_style = _coerce_text_list(character.style.chat)
|
|
88
90
|
resolved_chat = _resolve_name_list(chat_style, agent_name)
|
|
89
91
|
style_sections.append(f"Chat: {', '.join(resolved_chat)}")
|
|
90
92
|
if character.style.post:
|
|
91
|
-
post_style = (
|
|
92
|
-
character.style.post
|
|
93
|
-
if isinstance(character.style.post, list)
|
|
94
|
-
else [character.style.post]
|
|
95
|
-
)
|
|
93
|
+
post_style = _coerce_text_list(character.style.post)
|
|
96
94
|
resolved_post = _resolve_name_list(post_style, agent_name)
|
|
97
95
|
style_sections.append(f"Posts: {', '.join(resolved_post)}")
|
|
98
96
|
if style_sections:
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from elizaos.generated.spec_helpers import require_provider_spec
|
|
6
|
+
from elizaos.types import Provider, ProviderResult
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from elizaos.types import IAgentRuntime, Memory, State
|
|
10
|
+
|
|
11
|
+
# Get text content from centralized specs
|
|
12
|
+
_spec = require_provider_spec("CONTACTS")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def get_contacts_context(
|
|
16
|
+
runtime: IAgentRuntime,
|
|
17
|
+
message: Memory,
|
|
18
|
+
state: State | None = None,
|
|
19
|
+
) -> ProviderResult:
|
|
20
|
+
from elizaos.bootstrap.services.rolodex import RolodexService
|
|
21
|
+
|
|
22
|
+
rolodex_service = runtime.get_service("rolodex")
|
|
23
|
+
if not rolodex_service or not isinstance(rolodex_service, RolodexService):
|
|
24
|
+
return ProviderResult(text="", values={}, data={})
|
|
25
|
+
|
|
26
|
+
contacts = await rolodex_service.get_all_contacts()
|
|
27
|
+
|
|
28
|
+
if not contacts:
|
|
29
|
+
return ProviderResult(text="No contacts in rolodex.", values={"contactCount": 0}, data={})
|
|
30
|
+
|
|
31
|
+
contact_details: list[dict[str, str]] = []
|
|
32
|
+
for contact in contacts:
|
|
33
|
+
entity = await runtime.get_entity(contact.entity_id)
|
|
34
|
+
name = entity.name if entity and entity.name else "Unknown"
|
|
35
|
+
contact_details.append(
|
|
36
|
+
{
|
|
37
|
+
"id": str(contact.entity_id),
|
|
38
|
+
"name": name,
|
|
39
|
+
"categories": ",".join(contact.categories),
|
|
40
|
+
"tags": ",".join(contact.tags),
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
grouped: dict[str, list[dict[str, str]]] = {}
|
|
45
|
+
for detail in contact_details:
|
|
46
|
+
for cat in detail["categories"].split(","):
|
|
47
|
+
cat = cat.strip()
|
|
48
|
+
if cat:
|
|
49
|
+
grouped.setdefault(cat, []).append(detail)
|
|
50
|
+
|
|
51
|
+
text_summary = f"You have {len(contacts)} contacts in your rolodex:\n"
|
|
52
|
+
|
|
53
|
+
for category, items in grouped.items():
|
|
54
|
+
text_summary += f"\n{category.capitalize()}s ({len(items)}):\n"
|
|
55
|
+
for item in items:
|
|
56
|
+
text_summary += f"- {item['name']}"
|
|
57
|
+
if item["tags"]:
|
|
58
|
+
text_summary += f" [{item['tags']}]"
|
|
59
|
+
text_summary += "\n"
|
|
60
|
+
|
|
61
|
+
category_counts = {cat: len(items) for cat, items in grouped.items()}
|
|
62
|
+
|
|
63
|
+
return ProviderResult(
|
|
64
|
+
text=text_summary.strip(),
|
|
65
|
+
values={
|
|
66
|
+
"contactCount": len(contacts),
|
|
67
|
+
**category_counts,
|
|
68
|
+
},
|
|
69
|
+
data=category_counts,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
contacts_provider = Provider(
|
|
74
|
+
name=_spec["name"],
|
|
75
|
+
description=_spec["description"],
|
|
76
|
+
get=get_contacts_context,
|
|
77
|
+
dynamic=_spec.get("dynamic", True),
|
|
78
|
+
position=_spec.get("position"),
|
|
79
|
+
)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from datetime import UTC, datetime
|
|
4
3
|
from typing import TYPE_CHECKING
|
|
5
4
|
|
|
5
|
+
from elizaos.deterministic import get_prompt_reference_datetime
|
|
6
6
|
from elizaos.generated.spec_helpers import require_provider_spec
|
|
7
7
|
from elizaos.types import Provider, ProviderResult
|
|
8
8
|
|
|
@@ -18,9 +18,12 @@ async def get_current_time_context(
|
|
|
18
18
|
message: Memory,
|
|
19
19
|
state: State | None = None,
|
|
20
20
|
) -> ProviderResult:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
now = get_prompt_reference_datetime(
|
|
22
|
+
runtime,
|
|
23
|
+
message,
|
|
24
|
+
state,
|
|
25
|
+
"provider:current_time",
|
|
26
|
+
)
|
|
24
27
|
|
|
25
28
|
iso_timestamp = now.isoformat()
|
|
26
29
|
human_readable = now.strftime("%A, %B %d, %Y at %H:%M:%S UTC")
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from elizaos.generated.spec_helpers import require_provider_spec
|
|
6
|
+
from elizaos.types import Provider, ProviderResult
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from elizaos.types import IAgentRuntime, Memory, State
|
|
10
|
+
|
|
11
|
+
# Get text content from centralized specs
|
|
12
|
+
_spec = require_provider_spec("FACTS")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def get_facts_context(
|
|
16
|
+
runtime: IAgentRuntime,
|
|
17
|
+
message: Memory,
|
|
18
|
+
state: State | None = None,
|
|
19
|
+
) -> ProviderResult:
|
|
20
|
+
sections: list[str] = []
|
|
21
|
+
facts_list: list[dict[str, str]] = []
|
|
22
|
+
|
|
23
|
+
entity_id = message.entity_id
|
|
24
|
+
room_id = message.room_id
|
|
25
|
+
|
|
26
|
+
if entity_id:
|
|
27
|
+
sender_facts = await runtime.get_memories(
|
|
28
|
+
entity_id=entity_id,
|
|
29
|
+
memory_type="fact",
|
|
30
|
+
limit=10,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
if sender_facts:
|
|
34
|
+
sender = await runtime.get_entity(entity_id)
|
|
35
|
+
sender_name = sender.name if sender and sender.name else "User"
|
|
36
|
+
sections.append(f"\n## Facts about {sender_name}")
|
|
37
|
+
|
|
38
|
+
for fact in sender_facts:
|
|
39
|
+
if fact.content and fact.content.text:
|
|
40
|
+
fact_text = fact.content.text
|
|
41
|
+
if len(fact_text) > 200:
|
|
42
|
+
fact_text = fact_text[:200] + "..."
|
|
43
|
+
facts_list.append(
|
|
44
|
+
{"entityId": str(entity_id), "entityName": sender_name, "fact": fact_text}
|
|
45
|
+
)
|
|
46
|
+
sections.append(f"- {fact_text}")
|
|
47
|
+
|
|
48
|
+
if room_id:
|
|
49
|
+
room_facts = await runtime.get_memories(
|
|
50
|
+
room_id=room_id,
|
|
51
|
+
memory_type="fact",
|
|
52
|
+
limit=5,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if room_facts:
|
|
56
|
+
sections.append("\n## Room Context Facts")
|
|
57
|
+
for fact in room_facts:
|
|
58
|
+
if fact.content and fact.content.text:
|
|
59
|
+
fact_text = fact.content.text
|
|
60
|
+
if len(fact_text) > 200:
|
|
61
|
+
fact_text = fact_text[:200] + "..."
|
|
62
|
+
facts_list.append({"roomId": str(room_id), "fact": fact_text})
|
|
63
|
+
sections.append(f"- {fact_text}")
|
|
64
|
+
|
|
65
|
+
context_text = ""
|
|
66
|
+
if sections:
|
|
67
|
+
context_text = "# Known Facts" + "\n".join(sections)
|
|
68
|
+
|
|
69
|
+
return ProviderResult(
|
|
70
|
+
text=context_text,
|
|
71
|
+
values={
|
|
72
|
+
"factCount": len(facts_list),
|
|
73
|
+
"hasFacts": len(facts_list) > 0,
|
|
74
|
+
},
|
|
75
|
+
data={
|
|
76
|
+
"facts": facts_list,
|
|
77
|
+
},
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
facts_provider = Provider(
|
|
82
|
+
name=_spec["name"],
|
|
83
|
+
description=_spec["description"],
|
|
84
|
+
get=get_facts_context,
|
|
85
|
+
dynamic=_spec.get("dynamic", True),
|
|
86
|
+
position=_spec.get("position"),
|
|
87
|
+
)
|