@elizaos/python 2.0.0-alpha.10 → 2.0.0-alpha.11
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/actions/schedule_follow_up.py +70 -15
- package/elizaos/advanced_capabilities/actions/send_message.py +9 -184
- package/elizaos/advanced_memory/memory_service.py +15 -17
- package/elizaos/advanced_planning/planning_service.py +26 -14
- package/elizaos/basic_capabilities/providers/actions.py +118 -29
- package/elizaos/basic_capabilities/providers/character.py +19 -21
- package/elizaos/basic_capabilities/providers/current_time.py +7 -4
- 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/service.py +230 -28
- 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 +1 -0
- 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/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 +152 -39
- package/elizaos/services/message_service.py +2 -6
- 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 +161 -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 +3 -0
- package/elizaos/types/runtime.py +1 -1
- package/package.json +3 -2
- package/tests/test_action_parameters.py +2 -3
- 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_autonomy.py +11 -1
- 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/uv.lock +1565 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from types import SimpleNamespace
|
|
5
|
+
from typing import Protocol
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from elizaos.advanced_capabilities.actions.schedule_follow_up import (
|
|
10
|
+
schedule_follow_up_action as advanced_schedule_follow_up_action,
|
|
11
|
+
)
|
|
12
|
+
from elizaos.bootstrap.actions.schedule_follow_up import (
|
|
13
|
+
schedule_follow_up_action as bootstrap_schedule_follow_up_action,
|
|
14
|
+
)
|
|
15
|
+
from elizaos.bootstrap.services.follow_up import FollowUpService
|
|
16
|
+
from elizaos.bootstrap.services.rolodex import RolodexService
|
|
17
|
+
from elizaos.types import Content, Memory, as_uuid
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class RolodexLike(Protocol):
|
|
21
|
+
async def search_contacts(
|
|
22
|
+
self,
|
|
23
|
+
categories: list[str] | None = None,
|
|
24
|
+
tags: list[str] | None = None,
|
|
25
|
+
search_term: str | None = None,
|
|
26
|
+
) -> list[SimpleNamespace]: ...
|
|
27
|
+
|
|
28
|
+
async def get_contact(self, entity_id: object) -> SimpleNamespace | None: ...
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ActionLike(Protocol):
|
|
32
|
+
async def handler(
|
|
33
|
+
self,
|
|
34
|
+
runtime: object,
|
|
35
|
+
message: Memory,
|
|
36
|
+
state: object | None,
|
|
37
|
+
options: object | None,
|
|
38
|
+
callback: object | None,
|
|
39
|
+
responses: list[Memory] | None,
|
|
40
|
+
) -> object: ...
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class FakeFollowUpCall:
|
|
45
|
+
entity_id: object
|
|
46
|
+
priority: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class FakeFollowUpService(FollowUpService):
|
|
50
|
+
def __init__(self) -> None:
|
|
51
|
+
self.calls: list[FakeFollowUpCall] = []
|
|
52
|
+
|
|
53
|
+
async def schedule_follow_up(
|
|
54
|
+
self,
|
|
55
|
+
entity_id: object,
|
|
56
|
+
scheduled_at: object,
|
|
57
|
+
reason: str,
|
|
58
|
+
priority: str = "medium",
|
|
59
|
+
message: str | None = None,
|
|
60
|
+
) -> SimpleNamespace:
|
|
61
|
+
self.calls.append(FakeFollowUpCall(entity_id=entity_id, priority=priority))
|
|
62
|
+
return SimpleNamespace(
|
|
63
|
+
entity_id=entity_id,
|
|
64
|
+
scheduled_at=str(scheduled_at),
|
|
65
|
+
reason=reason,
|
|
66
|
+
priority=priority,
|
|
67
|
+
message=message,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class FakeRolodexService(RolodexService):
|
|
72
|
+
def __init__(self, contacts: list[SimpleNamespace]) -> None:
|
|
73
|
+
self._contacts = contacts
|
|
74
|
+
|
|
75
|
+
async def search_contacts(
|
|
76
|
+
self,
|
|
77
|
+
categories: list[str] | None = None,
|
|
78
|
+
tags: list[str] | None = None,
|
|
79
|
+
search_term: str | None = None,
|
|
80
|
+
) -> list[SimpleNamespace]:
|
|
81
|
+
if not search_term:
|
|
82
|
+
return self._contacts
|
|
83
|
+
lowered = search_term.lower()
|
|
84
|
+
return [
|
|
85
|
+
contact
|
|
86
|
+
for contact in self._contacts
|
|
87
|
+
if lowered in str(contact.entity_id).lower()
|
|
88
|
+
or lowered in str(getattr(contact, "name", "")).lower()
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
async def get_contact(self, entity_id: object) -> SimpleNamespace | None:
|
|
92
|
+
for contact in self._contacts:
|
|
93
|
+
if contact.entity_id == entity_id:
|
|
94
|
+
return contact
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class FakeRuntime:
|
|
99
|
+
def __init__(self, rolodex: RolodexLike, follow_up: FakeFollowUpService, response: str) -> None:
|
|
100
|
+
self._rolodex = rolodex
|
|
101
|
+
self._follow_up = follow_up
|
|
102
|
+
self._response = response
|
|
103
|
+
|
|
104
|
+
def get_service(self, name: str) -> object | None:
|
|
105
|
+
if name == "rolodex":
|
|
106
|
+
return self._rolodex
|
|
107
|
+
if name == "follow_up":
|
|
108
|
+
return self._follow_up
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
async def compose_state(self, _message: Memory, _providers: list[str]) -> SimpleNamespace:
|
|
112
|
+
return SimpleNamespace(values={}, data={}, text="")
|
|
113
|
+
|
|
114
|
+
def get_setting(self, _key: str) -> object | None:
|
|
115
|
+
return None
|
|
116
|
+
|
|
117
|
+
def compose_prompt_from_state(self, state: object, template: str) -> str:
|
|
118
|
+
return f"{template}\n{state}"
|
|
119
|
+
|
|
120
|
+
async def use_model(self, _model_type: object, _params: dict[str, object]) -> str:
|
|
121
|
+
return self._response
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@pytest.mark.asyncio
|
|
125
|
+
@pytest.mark.parametrize(
|
|
126
|
+
"action_under_test",
|
|
127
|
+
[bootstrap_schedule_follow_up_action, advanced_schedule_follow_up_action],
|
|
128
|
+
)
|
|
129
|
+
async def test_schedule_follow_up_fails_when_contact_unresolved(
|
|
130
|
+
action_under_test: ActionLike,
|
|
131
|
+
) -> None:
|
|
132
|
+
follow_up_service = FakeFollowUpService()
|
|
133
|
+
rolodex_service = FakeRolodexService(contacts=[])
|
|
134
|
+
runtime = FakeRuntime(
|
|
135
|
+
rolodex=rolodex_service,
|
|
136
|
+
follow_up=follow_up_service,
|
|
137
|
+
response=(
|
|
138
|
+
"<response>"
|
|
139
|
+
"<contactName>missing-contact</contactName>"
|
|
140
|
+
"<scheduledAt>2026-01-02T12:00:00Z</scheduledAt>"
|
|
141
|
+
"<reason>Check-in</reason>"
|
|
142
|
+
"<priority>high</priority>"
|
|
143
|
+
"</response>"
|
|
144
|
+
),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
message = Memory(
|
|
148
|
+
id=as_uuid("70000000-0000-0000-0000-000000000001"),
|
|
149
|
+
room_id=as_uuid("70000000-0000-0000-0000-000000000002"),
|
|
150
|
+
entity_id=None,
|
|
151
|
+
content=Content(text="follow up with missing-contact next week"),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
result = await action_under_test.handler(
|
|
155
|
+
runtime,
|
|
156
|
+
message,
|
|
157
|
+
None,
|
|
158
|
+
None,
|
|
159
|
+
None,
|
|
160
|
+
None,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
assert result is not None
|
|
164
|
+
assert result.success is False
|
|
165
|
+
assert len(follow_up_service.calls) == 0
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@pytest.mark.asyncio
|
|
169
|
+
@pytest.mark.parametrize(
|
|
170
|
+
"action_under_test",
|
|
171
|
+
[bootstrap_schedule_follow_up_action, advanced_schedule_follow_up_action],
|
|
172
|
+
)
|
|
173
|
+
async def test_schedule_follow_up_normalizes_priority_and_schedules(
|
|
174
|
+
action_under_test: ActionLike,
|
|
175
|
+
) -> None:
|
|
176
|
+
follow_up_service = FakeFollowUpService()
|
|
177
|
+
contact_id = as_uuid("80000000-0000-0000-0000-000000000001")
|
|
178
|
+
rolodex_service = FakeRolodexService(
|
|
179
|
+
contacts=[SimpleNamespace(entity_id=contact_id, name="known-contact")]
|
|
180
|
+
)
|
|
181
|
+
runtime = FakeRuntime(
|
|
182
|
+
rolodex=rolodex_service,
|
|
183
|
+
follow_up=follow_up_service,
|
|
184
|
+
response=(
|
|
185
|
+
"<response>"
|
|
186
|
+
"<contactName>known-contact</contactName>"
|
|
187
|
+
"<scheduledAt>2026-01-03T09:30:00Z</scheduledAt>"
|
|
188
|
+
"<reason>Status update</reason>"
|
|
189
|
+
"<priority>urgent</priority>"
|
|
190
|
+
"</response>"
|
|
191
|
+
),
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
message = Memory(
|
|
195
|
+
id=as_uuid("80000000-0000-0000-0000-000000000002"),
|
|
196
|
+
room_id=as_uuid("80000000-0000-0000-0000-000000000003"),
|
|
197
|
+
entity_id=None,
|
|
198
|
+
content=Content(text="schedule follow-up with known-contact"),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
result = await action_under_test.handler(
|
|
202
|
+
runtime,
|
|
203
|
+
message,
|
|
204
|
+
None,
|
|
205
|
+
None,
|
|
206
|
+
None,
|
|
207
|
+
None,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
assert result is not None
|
|
211
|
+
assert result.success is True
|
|
212
|
+
assert len(follow_up_service.calls) == 1
|
|
213
|
+
assert follow_up_service.calls[0].priority == "medium"
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@pytest.mark.asyncio
|
|
217
|
+
@pytest.mark.parametrize(
|
|
218
|
+
"action_under_test",
|
|
219
|
+
[bootstrap_schedule_follow_up_action, advanced_schedule_follow_up_action],
|
|
220
|
+
)
|
|
221
|
+
async def test_schedule_follow_up_rejects_invalid_scheduled_at(
|
|
222
|
+
action_under_test: ActionLike,
|
|
223
|
+
) -> None:
|
|
224
|
+
follow_up_service = FakeFollowUpService()
|
|
225
|
+
contact_id = as_uuid("90000000-0000-0000-0000-000000000001")
|
|
226
|
+
rolodex_service = FakeRolodexService(
|
|
227
|
+
contacts=[SimpleNamespace(entity_id=contact_id, name="known-contact")]
|
|
228
|
+
)
|
|
229
|
+
runtime = FakeRuntime(
|
|
230
|
+
rolodex=rolodex_service,
|
|
231
|
+
follow_up=follow_up_service,
|
|
232
|
+
response=(
|
|
233
|
+
"<response>"
|
|
234
|
+
"<contactName>known-contact</contactName>"
|
|
235
|
+
"<scheduledAt>not-a-date</scheduledAt>"
|
|
236
|
+
"<reason>Status update</reason>"
|
|
237
|
+
"<priority>high</priority>"
|
|
238
|
+
"</response>"
|
|
239
|
+
),
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
message = Memory(
|
|
243
|
+
id=as_uuid("90000000-0000-0000-0000-000000000002"),
|
|
244
|
+
room_id=as_uuid("90000000-0000-0000-0000-000000000003"),
|
|
245
|
+
entity_id=None,
|
|
246
|
+
content=Content(text="schedule follow-up with known-contact"),
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
result = await action_under_test.handler(
|
|
250
|
+
runtime,
|
|
251
|
+
message,
|
|
252
|
+
None,
|
|
253
|
+
None,
|
|
254
|
+
None,
|
|
255
|
+
None,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
assert result is not None
|
|
259
|
+
assert result.success is False
|
|
260
|
+
assert len(follow_up_service.calls) == 0
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import SimpleNamespace
|
|
4
|
+
from unittest.mock import AsyncMock, MagicMock
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from elizaos.advanced_capabilities.actions.send_message import (
|
|
9
|
+
send_message_action as advanced_send_message_action,
|
|
10
|
+
)
|
|
11
|
+
from elizaos.bootstrap.actions.send_message import (
|
|
12
|
+
send_message_action as bootstrap_send_message_action,
|
|
13
|
+
)
|
|
14
|
+
from elizaos.types.memory import Memory
|
|
15
|
+
from elizaos.types.primitives import Content, as_uuid
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _make_runtime() -> MagicMock:
|
|
19
|
+
runtime = MagicMock()
|
|
20
|
+
runtime.agent_id = as_uuid("42345678-1234-1234-1234-123456789001")
|
|
21
|
+
runtime.create_memory = AsyncMock()
|
|
22
|
+
runtime.emit_event = AsyncMock()
|
|
23
|
+
runtime.send_message_to_target = AsyncMock()
|
|
24
|
+
runtime.get_room = AsyncMock(return_value=None)
|
|
25
|
+
runtime.get_rooms = AsyncMock(return_value=[])
|
|
26
|
+
runtime.get_entities_for_room = AsyncMock(return_value=[])
|
|
27
|
+
return runtime
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _make_message() -> Memory:
|
|
31
|
+
return Memory(
|
|
32
|
+
id=as_uuid("42345678-1234-1234-1234-123456789010"),
|
|
33
|
+
entity_id=as_uuid("42345678-1234-1234-1234-123456789011"),
|
|
34
|
+
room_id=as_uuid("42345678-1234-1234-1234-123456789012"),
|
|
35
|
+
content=Content(text="fallback", source="telegram"),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@pytest.mark.asyncio
|
|
40
|
+
@pytest.mark.parametrize(
|
|
41
|
+
"action_under_test",
|
|
42
|
+
[bootstrap_send_message_action, advanced_send_message_action],
|
|
43
|
+
)
|
|
44
|
+
async def test_send_message_uses_room_target_parameters(action_under_test: object) -> None:
|
|
45
|
+
runtime = _make_runtime()
|
|
46
|
+
message = _make_message()
|
|
47
|
+
target_room_id = "42345678-1234-1234-1234-123456789099"
|
|
48
|
+
|
|
49
|
+
result = await action_under_test.handler(
|
|
50
|
+
runtime,
|
|
51
|
+
message,
|
|
52
|
+
None,
|
|
53
|
+
SimpleNamespace(
|
|
54
|
+
parameters={
|
|
55
|
+
"targetType": "room",
|
|
56
|
+
"target": target_room_id,
|
|
57
|
+
"source": "discord",
|
|
58
|
+
"text": "ship it",
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
None,
|
|
62
|
+
None,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
assert result.success is True
|
|
66
|
+
assert result.values["targetType"] == "room"
|
|
67
|
+
assert result.values["targetRoomId"] == target_room_id
|
|
68
|
+
runtime.create_memory.assert_awaited_once()
|
|
69
|
+
create_kwargs = runtime.create_memory.await_args.kwargs
|
|
70
|
+
assert create_kwargs["room_id"] == as_uuid(target_room_id)
|
|
71
|
+
|
|
72
|
+
runtime.send_message_to_target.assert_awaited_once()
|
|
73
|
+
send_target = runtime.send_message_to_target.await_args.args[0]
|
|
74
|
+
assert str(send_target.room_id) == target_room_id
|
|
75
|
+
assert send_target.source == "discord"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@pytest.mark.asyncio
|
|
79
|
+
@pytest.mark.parametrize(
|
|
80
|
+
"action_under_test",
|
|
81
|
+
[bootstrap_send_message_action, advanced_send_message_action],
|
|
82
|
+
)
|
|
83
|
+
async def test_send_message_resolves_user_target_from_room_entities(
|
|
84
|
+
action_under_test: object,
|
|
85
|
+
) -> None:
|
|
86
|
+
runtime = _make_runtime()
|
|
87
|
+
message = _make_message()
|
|
88
|
+
target_entity_id = as_uuid("42345678-1234-1234-1234-123456789088")
|
|
89
|
+
runtime.get_entities_for_room = AsyncMock(
|
|
90
|
+
return_value=[SimpleNamespace(id=target_entity_id, names=["Alice"])]
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
result = await action_under_test.handler(
|
|
94
|
+
runtime,
|
|
95
|
+
message,
|
|
96
|
+
None,
|
|
97
|
+
SimpleNamespace(
|
|
98
|
+
parameters={
|
|
99
|
+
"targetType": "user",
|
|
100
|
+
"target": "alice",
|
|
101
|
+
"source": "discord",
|
|
102
|
+
"text": "hello",
|
|
103
|
+
}
|
|
104
|
+
),
|
|
105
|
+
None,
|
|
106
|
+
None,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
assert result.success is True
|
|
110
|
+
assert result.values["targetType"] == "user"
|
|
111
|
+
assert result.values["targetEntityId"] == target_entity_id
|
|
112
|
+
runtime.send_message_to_target.assert_awaited_once()
|
|
113
|
+
send_target = runtime.send_message_to_target.await_args.args[0]
|
|
114
|
+
assert str(send_target.entity_id) == target_entity_id
|
|
@@ -78,7 +78,6 @@ class TestSettingsCrypto:
|
|
|
78
78
|
assert migrated.startswith("v2:")
|
|
79
79
|
assert decrypt_string_value(migrated, salt) == plaintext
|
|
80
80
|
|
|
81
|
-
@pytest.mark.skip(reason="Runtime get_setting from secrets not yet implemented")
|
|
82
81
|
def test_runtime_get_setting_decrypts_secret_strings(
|
|
83
82
|
self, monkeypatch: pytest.MonkeyPatch
|
|
84
83
|
) -> None:
|
|
@@ -96,7 +95,6 @@ class TestSettingsCrypto:
|
|
|
96
95
|
runtime = AgentRuntime(character=character)
|
|
97
96
|
assert runtime.get_setting("API_KEY") == "super-secret"
|
|
98
97
|
|
|
99
|
-
@pytest.mark.skip(reason="Runtime get_setting from secrets not yet implemented")
|
|
100
98
|
def test_runtime_get_setting_coerces_true_false_strings(
|
|
101
99
|
self, monkeypatch: pytest.MonkeyPatch
|
|
102
100
|
) -> None:
|