@elizaos/python 2.0.0-alpha.3 → 2.0.0-alpha.30
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 +24 -13
- package/elizaos/advanced_capabilities/actions/follow_room.py +29 -29
- package/elizaos/advanced_capabilities/actions/image_generation.py +15 -28
- package/elizaos/advanced_capabilities/actions/mute_room.py +15 -28
- package/elizaos/advanced_capabilities/actions/remove_contact.py +17 -3
- package/elizaos/advanced_capabilities/actions/roles.py +17 -30
- 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 +184 -51
- package/elizaos/advanced_capabilities/actions/settings.py +17 -3
- package/elizaos/advanced_capabilities/actions/unfollow_room.py +15 -28
- package/elizaos/advanced_capabilities/actions/unmute_room.py +15 -28
- package/elizaos/advanced_capabilities/actions/update_contact.py +17 -3
- package/elizaos/advanced_capabilities/actions/update_entity.py +17 -3
- 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 +23 -3
- package/elizaos/advanced_capabilities/services/__init__.py +2 -9
- package/elizaos/advanced_capabilities/services/rolodex.py +2 -2
- package/elizaos/advanced_memory/actions/reset_session.py +143 -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 +69 -27
- package/elizaos/advanced_memory/plugin.py +2 -1
- package/elizaos/advanced_memory/test_advanced_memory.py +357 -0
- package/elizaos/advanced_memory/types.py +2 -2
- 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 +96 -0
- package/elizaos/basic_capabilities/providers/recent_messages.py +5 -0
- package/elizaos/basic_capabilities/providers/relationships.py +113 -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/basic_capabilities/services/embedding.py +10 -7
- package/elizaos/basic_capabilities/services/task.py +3 -3
- package/elizaos/bootstrap/__init__.py +21 -2
- package/elizaos/bootstrap/actions/__init__.py +3 -0
- package/elizaos/bootstrap/actions/reset_session.py +3 -0
- package/elizaos/bootstrap/actions/roles.py +5 -4
- 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 +26 -3
- package/elizaos/bootstrap/providers/providers_list.py +1 -0
- package/elizaos/bootstrap/providers/recent_messages.py +5 -0
- package/elizaos/bootstrap/providers/relationships.py +20 -13
- 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 +206 -8
- package/elizaos/bootstrap/services/rolodex.py +2 -2
- package/elizaos/bootstrap/services/task.py +3 -3
- 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 +4 -4
- package/elizaos/media/search.py +23 -23
- package/elizaos/runtime.py +223 -64
- package/elizaos/services/hook_service.py +3 -3
- 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 +33 -3
- package/elizaos/types/primitives.py +3 -3
- package/elizaos/types/runtime.py +17 -3
- package/elizaos/types/state.py +2 -2
- package/elizaos/utils/streaming.py +3 -3
- package/elizaos/utils/validation.py +76 -0
- package/package.json +4 -3
- package/pyproject.toml +1 -2
- package/requirements-dev.lock +2 -2
- package/requirements.in +1 -2
- package/requirements.lock +2 -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_history_compaction.py +104 -0
- package/tests/test_memory_bounds.py +115 -0
- 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
|
@@ -1,134 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
"""Compatibility wrapper for reflection evaluator."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from elizaos.bootstrap.evaluators.reflection import reflection_evaluator
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
from elizaos.bootstrap.utils.xml import parse_key_value_xml
|
|
8
|
-
from elizaos.generated.spec_helpers import require_evaluator_spec
|
|
9
|
-
from elizaos.prompts import REFLECTION_TEMPLATE
|
|
10
|
-
from elizaos.types import ActionResult, Evaluator, HandlerOptions, ModelType
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from elizaos.types import Content, IAgentRuntime, Memory, State
|
|
14
|
-
|
|
15
|
-
# Get text content from centralized specs
|
|
16
|
-
_spec = require_evaluator_spec("REFLECTION")
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
async def evaluate_reflection(
|
|
20
|
-
runtime: IAgentRuntime,
|
|
21
|
-
message: Memory,
|
|
22
|
-
state: State | None = None,
|
|
23
|
-
) -> EvaluatorResult:
|
|
24
|
-
if state is None:
|
|
25
|
-
return EvaluatorResult(
|
|
26
|
-
score=50,
|
|
27
|
-
passed=True,
|
|
28
|
-
reason="No state for reflection",
|
|
29
|
-
details={},
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
recent_interactions: list[str] = []
|
|
33
|
-
room_id = message.room_id
|
|
34
|
-
|
|
35
|
-
if room_id:
|
|
36
|
-
recent_messages = await runtime.get_memories(
|
|
37
|
-
room_id=room_id,
|
|
38
|
-
limit=10,
|
|
39
|
-
order_by="created_at",
|
|
40
|
-
order_direction="desc",
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
for msg in recent_messages:
|
|
44
|
-
if msg.content and msg.content.text:
|
|
45
|
-
sender = "Unknown"
|
|
46
|
-
if msg.entity_id:
|
|
47
|
-
if str(msg.entity_id) == str(runtime.agent_id):
|
|
48
|
-
sender = runtime.character.name
|
|
49
|
-
else:
|
|
50
|
-
entity = await runtime.get_entity(msg.entity_id)
|
|
51
|
-
if entity and entity.name:
|
|
52
|
-
sender = entity.name
|
|
53
|
-
recent_interactions.append(f"{sender}: {msg.content.text}")
|
|
54
|
-
|
|
55
|
-
if not recent_interactions:
|
|
56
|
-
return EvaluatorResult(
|
|
57
|
-
score=50,
|
|
58
|
-
passed=True,
|
|
59
|
-
reason="No recent interactions to reflect on",
|
|
60
|
-
details={"noInteractions": True},
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
interactions_text = "\n".join(recent_interactions)
|
|
64
|
-
|
|
65
|
-
template = (
|
|
66
|
-
runtime.character.templates.get("reflectionTemplate")
|
|
67
|
-
if runtime.character.templates and "reflectionTemplate" in runtime.character.templates
|
|
68
|
-
else REFLECTION_TEMPLATE
|
|
69
|
-
)
|
|
70
|
-
prompt = runtime.compose_prompt(state=state, template=template)
|
|
71
|
-
prompt = prompt.replace("{{recentInteractions}}", interactions_text)
|
|
72
|
-
|
|
73
|
-
response_text = await runtime.use_model(ModelType.TEXT_LARGE, prompt=prompt)
|
|
74
|
-
parsed_xml = parse_key_value_xml(response_text)
|
|
75
|
-
|
|
76
|
-
if parsed_xml is None:
|
|
77
|
-
raise ValueError("Failed to parse reflection response")
|
|
78
|
-
|
|
79
|
-
quality_str = str(parsed_xml.get("quality_score", "50"))
|
|
80
|
-
quality_score = max(0, min(100, int(quality_str)))
|
|
81
|
-
|
|
82
|
-
thought = str(parsed_xml.get("thought", ""))
|
|
83
|
-
strengths = str(parsed_xml.get("strengths", ""))
|
|
84
|
-
improvements = str(parsed_xml.get("improvements", ""))
|
|
85
|
-
learnings = str(parsed_xml.get("learnings", ""))
|
|
86
|
-
|
|
87
|
-
passed = quality_score >= 50
|
|
88
|
-
|
|
89
|
-
return EvaluatorResult(
|
|
90
|
-
score=quality_score,
|
|
91
|
-
passed=passed,
|
|
92
|
-
reason=f"Strengths: {strengths}\nImprovements: {improvements}",
|
|
93
|
-
details={
|
|
94
|
-
"thought": thought,
|
|
95
|
-
"strengths": strengths,
|
|
96
|
-
"improvements": improvements,
|
|
97
|
-
"learnings": learnings,
|
|
98
|
-
"interactionCount": len(recent_interactions),
|
|
99
|
-
},
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
async def validate_reflection(
|
|
104
|
-
runtime: IAgentRuntime,
|
|
105
|
-
message: Memory,
|
|
106
|
-
_state: State | None = None,
|
|
107
|
-
) -> bool:
|
|
108
|
-
return True
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
async def _reflection_handler(
|
|
112
|
-
runtime: IAgentRuntime,
|
|
113
|
-
message: Memory,
|
|
114
|
-
state: State | None = None,
|
|
115
|
-
options: HandlerOptions | None = None,
|
|
116
|
-
callback: Callable[[Content], Awaitable[list[Memory]]] | None = None,
|
|
117
|
-
responses: list[Memory] | None = None,
|
|
118
|
-
) -> ActionResult | None:
|
|
119
|
-
"""Wrapper handler that matches the expected signature."""
|
|
120
|
-
_ = options, callback, responses # Unused parameters
|
|
121
|
-
result = await evaluate_reflection(runtime, message, state)
|
|
122
|
-
# Return ActionResult - evaluators don't typically return action results
|
|
123
|
-
return ActionResult(text=result.reason, success=result.passed, values={}, data={})
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
reflection_evaluator = Evaluator(
|
|
127
|
-
name=str(_spec["name"]),
|
|
128
|
-
description=str(_spec["description"]),
|
|
129
|
-
similes=list(_spec.get("similes", [])) if _spec.get("similes") else [],
|
|
130
|
-
validate=validate_reflection,
|
|
131
|
-
handler=_reflection_handler,
|
|
132
|
-
always_run=bool(_spec.get("alwaysRun", False)),
|
|
133
|
-
examples=[],
|
|
134
|
-
)
|
|
5
|
+
__all__ = ["reflection_evaluator"]
|
|
@@ -1,203 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"""Compatibility wrapper for relationship extraction evaluator."""
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
|
-
|
|
7
|
-
from elizaos.bootstrap.types import EvaluatorResult
|
|
8
|
-
from elizaos.generated.spec_helpers import require_evaluator_spec
|
|
9
|
-
from elizaos.types import ActionResult, Evaluator, HandlerOptions
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from elizaos.types import Content, IAgentRuntime, Memory, State
|
|
13
|
-
|
|
14
|
-
# Get text content from centralized specs
|
|
15
|
-
_spec = require_evaluator_spec("RELATIONSHIP_EXTRACTION")
|
|
16
|
-
|
|
17
|
-
X_HANDLE_PATTERN = re.compile(r"@[\w]+")
|
|
18
|
-
EMAIL_PATTERN = re.compile(r"[\w.+-]+@[\w.-]+\.\w+")
|
|
19
|
-
PHONE_PATTERN = re.compile(r"\+?[\d\s\-()]{10,}")
|
|
20
|
-
DISCORD_PATTERN = re.compile(r"[\w]+#\d{4}")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def extract_platform_identities(text: str) -> list[dict[str, str | bool | float]]:
|
|
24
|
-
identities: list[dict[str, str | bool | float]] = []
|
|
25
|
-
|
|
26
|
-
for match in X_HANDLE_PATTERN.finditer(text):
|
|
27
|
-
handle = match.group()
|
|
28
|
-
if handle.lower() not in ("@here", "@everyone", "@channel"):
|
|
29
|
-
identities.append(
|
|
30
|
-
{
|
|
31
|
-
"platform": "x",
|
|
32
|
-
"handle": handle,
|
|
33
|
-
"verified": False,
|
|
34
|
-
"confidence": 0.7,
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
for match in EMAIL_PATTERN.finditer(text):
|
|
39
|
-
identities.append(
|
|
40
|
-
{
|
|
41
|
-
"platform": "email",
|
|
42
|
-
"handle": match.group(),
|
|
43
|
-
"verified": False,
|
|
44
|
-
"confidence": 0.9,
|
|
45
|
-
}
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
for match in DISCORD_PATTERN.finditer(text):
|
|
49
|
-
identities.append(
|
|
50
|
-
{
|
|
51
|
-
"platform": "discord",
|
|
52
|
-
"handle": match.group(),
|
|
53
|
-
"verified": False,
|
|
54
|
-
"confidence": 0.8,
|
|
55
|
-
}
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
return identities
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def detect_relationship_indicators(text: str) -> list[dict[str, str | float]]:
|
|
62
|
-
indicators: list[dict[str, str | float]] = []
|
|
63
|
-
|
|
64
|
-
friend_patterns = [
|
|
65
|
-
r"my friend",
|
|
66
|
-
r"good friend",
|
|
67
|
-
r"best friend",
|
|
68
|
-
r"close friend",
|
|
69
|
-
r"we're friends",
|
|
70
|
-
]
|
|
71
|
-
for pattern in friend_patterns:
|
|
72
|
-
if re.search(pattern, text, re.IGNORECASE):
|
|
73
|
-
indicators.append(
|
|
74
|
-
{
|
|
75
|
-
"type": "friend",
|
|
76
|
-
"sentiment": "positive",
|
|
77
|
-
"confidence": 0.8,
|
|
78
|
-
}
|
|
79
|
-
)
|
|
80
|
-
break
|
|
81
|
-
|
|
82
|
-
colleague_patterns = [
|
|
83
|
-
r"my colleague",
|
|
84
|
-
r"coworker",
|
|
85
|
-
r"co-worker",
|
|
86
|
-
r"work together",
|
|
87
|
-
r"at work",
|
|
88
|
-
]
|
|
89
|
-
for pattern in colleague_patterns:
|
|
90
|
-
if re.search(pattern, text, re.IGNORECASE):
|
|
91
|
-
indicators.append(
|
|
92
|
-
{
|
|
93
|
-
"type": "colleague",
|
|
94
|
-
"sentiment": "neutral",
|
|
95
|
-
"confidence": 0.8,
|
|
96
|
-
}
|
|
97
|
-
)
|
|
98
|
-
break
|
|
99
|
-
|
|
100
|
-
family_patterns = [
|
|
101
|
-
r"my (brother|sister|mom|dad|mother|father|parent|son|daughter|child)",
|
|
102
|
-
r"my family",
|
|
103
|
-
r"family member",
|
|
104
|
-
]
|
|
105
|
-
for pattern in family_patterns:
|
|
106
|
-
if re.search(pattern, text, re.IGNORECASE):
|
|
107
|
-
indicators.append(
|
|
108
|
-
{
|
|
109
|
-
"type": "family",
|
|
110
|
-
"sentiment": "positive",
|
|
111
|
-
"confidence": 0.9,
|
|
112
|
-
}
|
|
113
|
-
)
|
|
114
|
-
break
|
|
115
|
-
|
|
116
|
-
return indicators
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
async def evaluate_relationship_extraction(
|
|
120
|
-
runtime: IAgentRuntime,
|
|
121
|
-
message: Memory,
|
|
122
|
-
state: State | None = None,
|
|
123
|
-
) -> EvaluatorResult:
|
|
124
|
-
text = message.content.text if message.content else ""
|
|
125
|
-
|
|
126
|
-
if not text:
|
|
127
|
-
return EvaluatorResult(
|
|
128
|
-
score=50,
|
|
129
|
-
passed=True,
|
|
130
|
-
reason="No text to analyze",
|
|
131
|
-
details={"noText": True},
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
identities = extract_platform_identities(text)
|
|
135
|
-
|
|
136
|
-
indicators = detect_relationship_indicators(text)
|
|
137
|
-
|
|
138
|
-
if identities and message.entity_id:
|
|
139
|
-
entity = await runtime.get_entity(str(message.entity_id))
|
|
140
|
-
if entity:
|
|
141
|
-
metadata = entity.metadata or {}
|
|
142
|
-
existing_identities = metadata.get("platformIdentities", [])
|
|
143
|
-
if isinstance(existing_identities, list):
|
|
144
|
-
for identity in identities:
|
|
145
|
-
exists = any(
|
|
146
|
-
i.get("platform") == identity["platform"]
|
|
147
|
-
and i.get("handle") == identity["handle"]
|
|
148
|
-
for i in existing_identities
|
|
149
|
-
if isinstance(i, dict)
|
|
150
|
-
)
|
|
151
|
-
if not exists:
|
|
152
|
-
existing_identities.append(identity)
|
|
153
|
-
metadata["platformIdentities"] = existing_identities
|
|
154
|
-
entity.metadata = metadata
|
|
155
|
-
await runtime.update_entity(entity)
|
|
156
|
-
|
|
157
|
-
runtime.logger.info(
|
|
158
|
-
f"Completed extraction: src=evaluator:relationship_extraction agentId={runtime.agent_id} identitiesFound={len(identities)} indicatorsFound={len(indicators)}"
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
return EvaluatorResult(
|
|
162
|
-
score=70,
|
|
163
|
-
passed=True,
|
|
164
|
-
reason=f"Found {len(identities)} identities and {len(indicators)} relationship indicators",
|
|
165
|
-
details={
|
|
166
|
-
"identitiesCount": len(identities),
|
|
167
|
-
"indicatorsCount": len(indicators),
|
|
168
|
-
},
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
async def validate_relationship_extraction(
|
|
173
|
-
runtime: IAgentRuntime,
|
|
174
|
-
message: Memory,
|
|
175
|
-
_state: State | None = None,
|
|
176
|
-
) -> bool:
|
|
177
|
-
return message.content is not None and bool(message.content.text)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
async def _relationship_extraction_handler(
|
|
181
|
-
runtime: IAgentRuntime,
|
|
182
|
-
message: Memory,
|
|
183
|
-
state: State | None = None,
|
|
184
|
-
options: HandlerOptions | None = None,
|
|
185
|
-
callback: Callable[[Content], Awaitable[list[Memory]]] | None = None,
|
|
186
|
-
responses: list[Memory] | None = None,
|
|
187
|
-
) -> ActionResult | None:
|
|
188
|
-
"""Wrapper handler that matches the expected signature."""
|
|
189
|
-
_ = options, callback, responses # Unused parameters
|
|
190
|
-
result = await evaluate_relationship_extraction(runtime, message, state)
|
|
191
|
-
# Return None as ActionResult - evaluators don't typically return action results
|
|
192
|
-
return ActionResult(text=result.reason, success=result.passed, values={}, data={})
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
relationship_extraction_evaluator = Evaluator(
|
|
196
|
-
name=str(_spec["name"]),
|
|
197
|
-
description=str(_spec["description"]),
|
|
198
|
-
similes=list(_spec.get("similes", [])) if _spec.get("similes") else [],
|
|
199
|
-
validate=validate_relationship_extraction,
|
|
200
|
-
handler=_relationship_extraction_handler,
|
|
201
|
-
always_run=bool(_spec.get("alwaysRun", False)),
|
|
202
|
-
examples=[],
|
|
3
|
+
from elizaos.bootstrap.evaluators.relationship_extraction import (
|
|
4
|
+
relationship_extraction_evaluator,
|
|
203
5
|
)
|
|
6
|
+
|
|
7
|
+
__all__ = ["relationship_extraction_evaluator"]
|
|
@@ -4,32 +4,21 @@ Extended providers that can be enabled with `advanced_capabilities=True`.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from .agent_settings import agent_settings_provider
|
|
7
|
-
from .contacts import contacts_provider
|
|
8
|
-
from .facts import facts_provider
|
|
9
|
-
from .follow_ups import follow_ups_provider
|
|
10
7
|
from .knowledge import knowledge_provider
|
|
11
|
-
from .relationships import relationships_provider
|
|
12
8
|
from .roles import roles_provider
|
|
13
9
|
from .settings import settings_provider
|
|
14
10
|
|
|
15
11
|
__all__ = [
|
|
16
12
|
"agent_settings_provider",
|
|
17
|
-
"contacts_provider",
|
|
18
|
-
"facts_provider",
|
|
19
|
-
"follow_ups_provider",
|
|
20
13
|
"knowledge_provider",
|
|
21
|
-
"relationships_provider",
|
|
22
14
|
"roles_provider",
|
|
23
15
|
"settings_provider",
|
|
24
16
|
"advanced_providers",
|
|
25
17
|
]
|
|
26
18
|
|
|
19
|
+
# Rolodex/contact providers are provided by plugin-rolodex.
|
|
27
20
|
advanced_providers = [
|
|
28
|
-
contacts_provider,
|
|
29
|
-
facts_provider,
|
|
30
|
-
follow_ups_provider,
|
|
31
21
|
knowledge_provider,
|
|
32
|
-
relationships_provider,
|
|
33
22
|
roles_provider,
|
|
34
23
|
agent_settings_provider,
|
|
35
24
|
settings_provider,
|
|
@@ -25,11 +25,31 @@ async def get_knowledge_context(
|
|
|
25
25
|
text="", values={"knowledgeCount": 0, "hasKnowledge": False}, data={"entries": []}
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
limit=5,
|
|
28
|
+
# 1. Fetch recent messages to get embeddings
|
|
29
|
+
recent_messages = await runtime.get_memories(
|
|
30
|
+
room_id=message.room_id, limit=5, table_name="messages"
|
|
31
31
|
)
|
|
32
32
|
|
|
33
|
+
# 2. Extract valid embeddings
|
|
34
|
+
embeddings = [m.embedding for m in recent_messages if m and m.embedding]
|
|
35
|
+
|
|
36
|
+
relevant_knowledge = []
|
|
37
|
+
# 3. Search using the most recent embedding if available
|
|
38
|
+
if embeddings:
|
|
39
|
+
primary_embedding = embeddings[0]
|
|
40
|
+
params = {
|
|
41
|
+
"tableName": "knowledge",
|
|
42
|
+
"roomId": str(message.room_id),
|
|
43
|
+
"embedding": primary_embedding,
|
|
44
|
+
"matchThreshold": 0.75,
|
|
45
|
+
"matchCount": 5,
|
|
46
|
+
"unique": True,
|
|
47
|
+
}
|
|
48
|
+
relevant_knowledge = await runtime.search_memories(params)
|
|
49
|
+
elif query_text:
|
|
50
|
+
# Fallback skipped for parity with TS/Bootstrap
|
|
51
|
+
pass
|
|
52
|
+
|
|
33
53
|
for entry in relevant_knowledge:
|
|
34
54
|
# Handle both dict and object entries
|
|
35
55
|
if isinstance(entry, dict):
|
|
@@ -3,16 +3,9 @@
|
|
|
3
3
|
Services that can be enabled with `advanced_capabilities=True`.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from .follow_up import FollowUpService
|
|
7
|
-
from .rolodex import RolodexService
|
|
8
|
-
|
|
9
6
|
__all__ = [
|
|
10
|
-
"FollowUpService",
|
|
11
|
-
"RolodexService",
|
|
12
7
|
"advanced_services",
|
|
13
8
|
]
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
FollowUpService,
|
|
18
|
-
]
|
|
10
|
+
# Rolodex/follow-up services are owned by plugin-rolodex.
|
|
11
|
+
advanced_services: list[type] = []
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
4
|
from datetime import datetime
|
|
5
|
-
from enum import
|
|
5
|
+
from enum import StrEnum
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
from uuid import UUID
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|
|
12
12
|
from elizaos.types import IAgentRuntime
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class ContactCategory(
|
|
15
|
+
class ContactCategory(StrEnum):
|
|
16
16
|
FRIEND = "friend"
|
|
17
17
|
FAMILY = "family"
|
|
18
18
|
COLLEAGUE = "colleague"
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from elizaos.types import Action, ActionExample, ActionResult, Content
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from elizaos.types import HandlerCallback, HandlerOptions, IAgentRuntime, Memory, State
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class ResetSessionAction:
|
|
15
|
+
name: str = "RESET_SESSION"
|
|
16
|
+
similes: list[str] = field(
|
|
17
|
+
default_factory=lambda: ["CLEAR_HISTORY", "NEW_SESSION", "FORGET", "START_OVER", "RESET"]
|
|
18
|
+
)
|
|
19
|
+
description: str = (
|
|
20
|
+
"Resets the conversation session by creating a compaction point. "
|
|
21
|
+
"Messages before this point will not be included in future context."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
async def validate(
|
|
25
|
+
self, runtime: IAgentRuntime, message: Memory, state: State | None = None
|
|
26
|
+
) -> bool:
|
|
27
|
+
room = None
|
|
28
|
+
if state and getattr(state, "data", None) and getattr(state.data, "room", None):
|
|
29
|
+
room = state.data.room
|
|
30
|
+
elif message.room_id:
|
|
31
|
+
room = await runtime.get_room(message.room_id)
|
|
32
|
+
|
|
33
|
+
if not room or not getattr(room, "world_id", None):
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
world = await runtime.get_world(room.world_id)
|
|
37
|
+
if not world or not getattr(world, "metadata", None):
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
roles = world.metadata.get("roles", {})
|
|
41
|
+
user_role = roles.get(str(message.entity_id), "NONE")
|
|
42
|
+
return user_role in ("OWNER", "ADMIN")
|
|
43
|
+
|
|
44
|
+
async def handler(
|
|
45
|
+
self,
|
|
46
|
+
runtime: IAgentRuntime,
|
|
47
|
+
message: Memory,
|
|
48
|
+
state: State | None = None,
|
|
49
|
+
options: HandlerOptions | None = None,
|
|
50
|
+
callback: HandlerCallback | None = None,
|
|
51
|
+
responses: list[Memory] | None = None,
|
|
52
|
+
) -> ActionResult:
|
|
53
|
+
del options, responses
|
|
54
|
+
|
|
55
|
+
room = None
|
|
56
|
+
if state and getattr(state, "data", None) and getattr(state.data, "room", None):
|
|
57
|
+
room = state.data.room
|
|
58
|
+
elif message.room_id:
|
|
59
|
+
room = await runtime.get_room(message.room_id)
|
|
60
|
+
|
|
61
|
+
if room is None:
|
|
62
|
+
if callback:
|
|
63
|
+
await callback(
|
|
64
|
+
Content(
|
|
65
|
+
text="Unable to reset session - room not found.",
|
|
66
|
+
actions=["RESET_SESSION_FAILED"],
|
|
67
|
+
source=getattr(message.content, "source", None),
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
return ActionResult(
|
|
71
|
+
text="Room not found",
|
|
72
|
+
values={"error": "room_not_found"},
|
|
73
|
+
data={"actionName": "RESET_SESSION"},
|
|
74
|
+
success=False,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
metadata = dict(getattr(room, "metadata", {}) or {})
|
|
78
|
+
previous_compaction = metadata.get("lastCompactionAt")
|
|
79
|
+
compaction_history = list(metadata.get("compactionHistory", []))
|
|
80
|
+
now = int(time.time() * 1000)
|
|
81
|
+
|
|
82
|
+
compaction_history.append(
|
|
83
|
+
{
|
|
84
|
+
"timestamp": now,
|
|
85
|
+
"triggeredBy": str(message.entity_id),
|
|
86
|
+
"reason": "manual_reset",
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
metadata["lastCompactionAt"] = now
|
|
90
|
+
metadata["compactionHistory"] = compaction_history[-10:]
|
|
91
|
+
|
|
92
|
+
if (
|
|
93
|
+
hasattr(room, "metadata")
|
|
94
|
+
and hasattr(room.metadata, "clear")
|
|
95
|
+
and hasattr(room.metadata, "update")
|
|
96
|
+
):
|
|
97
|
+
room.metadata.clear()
|
|
98
|
+
room.metadata.update(metadata)
|
|
99
|
+
else:
|
|
100
|
+
room.metadata = metadata
|
|
101
|
+
|
|
102
|
+
await runtime.update_room(room)
|
|
103
|
+
|
|
104
|
+
if callback:
|
|
105
|
+
await callback(
|
|
106
|
+
Content(
|
|
107
|
+
text="Session has been reset. I'll start fresh from here.",
|
|
108
|
+
actions=["RESET_SESSION"],
|
|
109
|
+
source=getattr(message.content, "source", None),
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
result = ActionResult(
|
|
114
|
+
text="Session reset successfully",
|
|
115
|
+
values={
|
|
116
|
+
"success": True,
|
|
117
|
+
"compactionAt": now,
|
|
118
|
+
"roomId": str(room.id),
|
|
119
|
+
},
|
|
120
|
+
data={
|
|
121
|
+
"actionName": "RESET_SESSION",
|
|
122
|
+
"compactionAt": now,
|
|
123
|
+
"roomId": str(room.id),
|
|
124
|
+
},
|
|
125
|
+
success=True,
|
|
126
|
+
)
|
|
127
|
+
if previous_compaction is not None:
|
|
128
|
+
result.values["previousCompactionAt"] = previous_compaction
|
|
129
|
+
return result
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def examples(self) -> list[list[ActionExample]]:
|
|
133
|
+
return []
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
reset_session_action = Action(
|
|
137
|
+
name=ResetSessionAction.name,
|
|
138
|
+
similes=ResetSessionAction().similes,
|
|
139
|
+
description=ResetSessionAction.description,
|
|
140
|
+
validate=ResetSessionAction().validate,
|
|
141
|
+
handler=ResetSessionAction().handler,
|
|
142
|
+
examples=ResetSessionAction().examples,
|
|
143
|
+
)
|