pycityagent 2.0.0a1__py3-none-any.whl → 2.0.0a3__py3-none-any.whl
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.
- pycityagent/agent.py +1 -1
- pycityagent/environment/sim/__init__.py +2 -0
- pycityagent/environment/sim/sim_env.py +145 -0
- pycityagent/environment/simulator.py +110 -159
- pycityagent/environment/utils/__init__.py +3 -1
- pycityagent/environment/utils/base64.py +16 -0
- pycityagent/environment/utils/const.py +242 -0
- pycityagent/environment/utils/port.py +11 -0
- pycityagent/simulation/simulation.py +153 -87
- pycityagent/workflow/__init__.py +5 -3
- pycityagent/workflow/block.py +31 -4
- pycityagent/workflow/trigger.py +108 -24
- {pycityagent-2.0.0a1.dist-info → pycityagent-2.0.0a3.dist-info}/METADATA +1 -1
- {pycityagent-2.0.0a1.dist-info → pycityagent-2.0.0a3.dist-info}/RECORD +15 -11
- {pycityagent-2.0.0a1.dist-info → pycityagent-2.0.0a3.dist-info}/WHEEL +0 -0
pycityagent/workflow/trigger.py
CHANGED
@@ -1,10 +1,38 @@
|
|
1
1
|
import asyncio
|
2
|
-
from typing import Any, Callable, Dict, List, Optional, Union
|
2
|
+
from typing import Any, Callable, Dict, List, Optional, Union, Type
|
3
3
|
import socket
|
4
4
|
from ..memory import Memory
|
5
|
+
from ..environment import Simulator
|
6
|
+
|
7
|
+
KEY_TRIGGER_COMPONENTS = [Memory, Simulator]
|
5
8
|
|
6
9
|
class EventTrigger:
|
7
10
|
"""Base class for event triggers that wait for specific conditions to be met."""
|
11
|
+
# 定义该trigger需要的组件类型
|
12
|
+
required_components: List[Type] = []
|
13
|
+
|
14
|
+
def __init__(self, block=None):
|
15
|
+
self.block = block
|
16
|
+
if block is not None:
|
17
|
+
self.initialize()
|
18
|
+
|
19
|
+
def initialize(self) -> None:
|
20
|
+
"""Initialize the trigger with necessary dependencies."""
|
21
|
+
if not self.block:
|
22
|
+
raise RuntimeError("Block not set for trigger")
|
23
|
+
|
24
|
+
# 检查所需组件是否都存在
|
25
|
+
missing_components = []
|
26
|
+
for component_type in self.required_components:
|
27
|
+
component_name = component_type.__name__.lower()
|
28
|
+
if not hasattr(self.block, component_name):
|
29
|
+
missing_components.append(component_type.__name__)
|
30
|
+
|
31
|
+
if missing_components:
|
32
|
+
raise RuntimeError(
|
33
|
+
f"Block is missing required components for {self.__class__.__name__}: "
|
34
|
+
f"{', '.join(missing_components)}"
|
35
|
+
)
|
8
36
|
|
9
37
|
async def wait_for_trigger(self) -> None:
|
10
38
|
"""Wait for the event trigger to be activated.
|
@@ -16,51 +44,107 @@ class EventTrigger:
|
|
16
44
|
|
17
45
|
class MemoryChangeTrigger(EventTrigger):
|
18
46
|
"""Event trigger that activates when a specific key in memory changes."""
|
47
|
+
required_components = [Memory]
|
19
48
|
|
20
|
-
def __init__(self,
|
49
|
+
def __init__(self, key: str) -> None:
|
21
50
|
"""Initialize the memory change trigger.
|
22
51
|
|
23
52
|
Args:
|
24
|
-
memory (Memory): The memory object to watch.
|
25
53
|
key (str): The key in memory to monitor for changes.
|
26
54
|
"""
|
27
|
-
self.memory = memory
|
28
55
|
self.key = key
|
29
56
|
self.trigger_event = asyncio.Event()
|
30
|
-
|
57
|
+
self._initialized = False
|
58
|
+
super().__init__()
|
59
|
+
|
60
|
+
def initialize(self) -> None:
|
61
|
+
"""Initialize the trigger with memory from block."""
|
62
|
+
super().initialize() # 首先检查必需组件
|
63
|
+
self.memory = self.block.memory
|
64
|
+
asyncio.create_task(self.memory.add_watcher(self.key, self.trigger_event.set))
|
65
|
+
self._initialized = True
|
31
66
|
|
32
67
|
async def wait_for_trigger(self) -> None:
|
33
68
|
"""Wait for the memory change trigger to be activated."""
|
69
|
+
if not self._initialized:
|
70
|
+
raise RuntimeError("Trigger not properly initialized")
|
34
71
|
await self.trigger_event.wait()
|
35
72
|
self.trigger_event.clear()
|
36
73
|
|
37
|
-
|
38
|
-
|
74
|
+
|
75
|
+
class TimeTrigger(EventTrigger):
|
76
|
+
"""Event trigger that activates periodically based on time intervals."""
|
77
|
+
required_components = [Simulator]
|
39
78
|
|
40
|
-
def __init__(self,
|
41
|
-
|
79
|
+
def __init__(self,
|
80
|
+
days: Optional[int] = None,
|
81
|
+
hours: Optional[int] = None,
|
82
|
+
minutes: Optional[int] = None) -> None:
|
83
|
+
"""Initialize the time trigger with interval settings.
|
42
84
|
|
43
85
|
Args:
|
44
|
-
|
86
|
+
days (Optional[int]): Execute every N days
|
87
|
+
hours (Optional[int]): Execute every N hours
|
88
|
+
minutes (Optional[int]): Execute every N minutes
|
89
|
+
|
90
|
+
Raises:
|
91
|
+
ValueError: If all interval parameters are None or negative
|
45
92
|
"""
|
46
|
-
|
93
|
+
if all(param is None for param in (days, hours, minutes)):
|
94
|
+
raise ValueError("At least one time interval must be specified")
|
95
|
+
|
96
|
+
# 验证参数有效性
|
97
|
+
for param_name, param_value in [('days', days), ('hours', hours), ('minutes', minutes)]:
|
98
|
+
if param_value is not None and param_value < 0:
|
99
|
+
raise ValueError(f"{param_name} cannot be negative")
|
100
|
+
|
101
|
+
# 将所有时间间隔转换为秒
|
102
|
+
self.interval = 0
|
103
|
+
if days is not None:
|
104
|
+
self.interval += days * 24 * 60 * 60
|
105
|
+
if hours is not None:
|
106
|
+
self.interval += hours * 60 * 60
|
107
|
+
if minutes is not None:
|
108
|
+
self.interval += minutes * 60
|
109
|
+
|
47
110
|
self.trigger_event = asyncio.Event()
|
48
|
-
self.
|
49
|
-
|
111
|
+
self._initialized = False
|
112
|
+
self._monitoring_task = None
|
113
|
+
self._last_trigger_time = None
|
114
|
+
super().__init__()
|
50
115
|
|
51
|
-
|
52
|
-
"""
|
116
|
+
def initialize(self) -> None:
|
117
|
+
"""Initialize the trigger with necessary dependencies."""
|
118
|
+
super().initialize() # 首先检查必需组件
|
119
|
+
self.memory = self.block.memory
|
120
|
+
self.simulator = self.block.simulator
|
121
|
+
# 启动时间监控任务
|
122
|
+
self._monitoring_task = asyncio.create_task(self._monitor_time())
|
123
|
+
self._initialized = True
|
53
124
|
|
54
|
-
|
55
|
-
"""
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
self.
|
125
|
+
async def _monitor_time(self):
|
126
|
+
"""持续监控时间并在达到间隔时触发事件"""
|
127
|
+
# 第一次调用时直接触发
|
128
|
+
self.trigger_event.set()
|
129
|
+
|
130
|
+
while True:
|
131
|
+
try:
|
132
|
+
current_time = await self.simulator.GetTime()
|
133
|
+
|
134
|
+
# 如果是第一次或者已经过了指定的时间间隔
|
135
|
+
if (self._last_trigger_time is None or
|
136
|
+
current_time - self._last_trigger_time >= self.interval):
|
137
|
+
self._last_trigger_time = current_time
|
138
|
+
self.trigger_event.set()
|
139
|
+
|
140
|
+
await asyncio.sleep(5) # 避免过于频繁的检查
|
141
|
+
except Exception as e:
|
142
|
+
print(f"Error in time monitoring: {e}")
|
143
|
+
await asyncio.sleep(10) # 发生错误时等待较长时间
|
62
144
|
|
63
145
|
async def wait_for_trigger(self) -> None:
|
64
|
-
"""Wait for the
|
146
|
+
"""Wait for the time trigger to be activated."""
|
147
|
+
if not self._initialized:
|
148
|
+
raise RuntimeError("Trigger not properly initialized")
|
65
149
|
await self.trigger_event.wait()
|
66
150
|
self.trigger_event.clear()
|
@@ -1,5 +1,5 @@
|
|
1
1
|
pycityagent/__init__.py,sha256=n56bWkAUEcvjDsb7LcJpaGjlrriSKPnR0yBhwRfEYBA,212
|
2
|
-
pycityagent/agent.py,sha256=
|
2
|
+
pycityagent/agent.py,sha256=QzVBgTdlwZEY0pQQB9nTruWiIc3t8mZxLzv5cId1IbY,5951
|
3
3
|
pycityagent/config.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
pycityagent/economy/__init__.py,sha256=aonY4WHnx-6EGJ4WKrx4S-2jAkYNLtqUA04jp6q8B7w,75
|
5
5
|
pycityagent/economy/econ_client.py,sha256=qQb_kZneEXGBRaS_y5Jdoi95I8GyjKEsDSC4s6V6R7w,10829
|
@@ -11,7 +11,7 @@ pycityagent/environment/sence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
11
11
|
pycityagent/environment/sence/static.py,sha256=fdBjHKacNiDCKhvQkc9WgEYYSO0peMC5lb8CcXl9iNc,29101
|
12
12
|
pycityagent/environment/sidecar/__init__.py,sha256=RFbOf40aYBP4WwRpFkua5tlRE_OtMcMNyp1Lew_aaAU,235
|
13
13
|
pycityagent/environment/sidecar/sidecarv2.py,sha256=beKlYZgt38EQbV1x6NWQo7xVXyB-5QHfbwJexyXu7Tg,3252
|
14
|
-
pycityagent/environment/sim/__init__.py,sha256=
|
14
|
+
pycityagent/environment/sim/__init__.py,sha256=JVG6sSD2Hbohl1TtKjuQi7_M7tKMrFh9vl3QV3VA5O0,724
|
15
15
|
pycityagent/environment/sim/aoi_service.py,sha256=pYSsqdGBpfQvp0-umNJir_7Yph75OJqhLjFQ2QWhSP8,1211
|
16
16
|
pycityagent/environment/sim/client.py,sha256=MHR7Hhu-Cr7B61d3K_QDpSJh4HrUU9JQf6Cu7_8pdsE,3493
|
17
17
|
pycityagent/environment/sim/clock_service.py,sha256=YG_A_IA7iJp9rOQE3bCPgppzuzzUwWMCzlxSUdOy088,1326
|
@@ -20,12 +20,16 @@ pycityagent/environment/sim/lane_service.py,sha256=6ljWiX_GbZd-a-fEcktDZncxBkraL
|
|
20
20
|
pycityagent/environment/sim/light_service.py,sha256=ezYGcV_PkZ6I-yv48LNEjsytwwwQx-1Qp2QCWXWIhdQ,4215
|
21
21
|
pycityagent/environment/sim/person_service.py,sha256=nIvOsoBoqOTDYtsiThg07-4ZBgkTUDEbb3dHyOjzyb8,10652
|
22
22
|
pycityagent/environment/sim/road_service.py,sha256=Pab182YRcrjLw3UcfoD1Hdd6O8XEdi6Q2hJKzFcpSWE,1272
|
23
|
+
pycityagent/environment/sim/sim_env.py,sha256=HI1LcS_FotDKQ6vBnx0e49prXSABOfA20aU9KM-ZkCY,4625
|
23
24
|
pycityagent/environment/sim/social_service.py,sha256=a9mGZm95EFUIKQJUwQi9f8anmtf2SK4XqGfE2W9IXSQ,2001
|
24
|
-
pycityagent/environment/simulator.py,sha256=
|
25
|
-
pycityagent/environment/utils/__init__.py,sha256=
|
25
|
+
pycityagent/environment/simulator.py,sha256=lw6-T6HFeE6lOtbTQdKZLre2cX7PZkXftRt7wC4mE-8,11858
|
26
|
+
pycityagent/environment/utils/__init__.py,sha256=PUx8etr2p_AA7F50ZR7g27odkgv-nOqFZa61ER8-DLg,221
|
27
|
+
pycityagent/environment/utils/base64.py,sha256=hoREzQo3FXMN79pqQLO2jgsDEvudciomyKii7MWljAM,374
|
28
|
+
pycityagent/environment/utils/const.py,sha256=3RMNy7_bE7-23K90j9DFW_tWEzu8s7hSTgKbV-3BFl4,5327
|
26
29
|
pycityagent/environment/utils/geojson.py,sha256=Ieg8Bzw63kKhJlhDIOVDoh-wQO4Sbtoe47FtIOy5wWg,686
|
27
30
|
pycityagent/environment/utils/grpc.py,sha256=6EJwKXXktIWb1NcUiJzIRmfrY0S03QAXXGcCDHqAT00,1998
|
28
31
|
pycityagent/environment/utils/map_utils.py,sha256=oqrRgQICC3SYw6gwjjPe_MAif7_t6dlrQpY8E32Fexs,5777
|
32
|
+
pycityagent/environment/utils/port.py,sha256=3OM6kSUt3PxvDUOlgyiendBtETaWU8Mzk_8H0TzTmYg,295
|
29
33
|
pycityagent/environment/utils/protobuf.py,sha256=0jBvK_s96y_n7tuMbG22TOtQmg71SGV4ONDy2IGsU9o,1148
|
30
34
|
pycityagent/llm/__init__.py,sha256=0-_q-StY0g4p9mdUNve_kqzHNXwVxedNsvxGXSQYq6o,144
|
31
35
|
pycityagent/llm/embedding.py,sha256=vtjMUuInrtn0WRPXp3cmYEhwHXJ0q6zszdXsjTsgNeQ,4499
|
@@ -43,7 +47,7 @@ pycityagent/memory/utils.py,sha256=97lkenn-36wgt7uWb3Z39BXdJ5zlEQTQnQBFpoND1gg,8
|
|
43
47
|
pycityagent/message/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
48
|
pycityagent/simulation/__init__.py,sha256=SZQzjcGR-zkTDrE81bQuEdKn7yjk4BcZ9m7o1wTc7EE,111
|
45
49
|
pycityagent/simulation/interview.py,sha256=mY4Vpz0vgJo4rrMy3TZnwwM-iVDL6J0LgjOxbEuV27E,1173
|
46
|
-
pycityagent/simulation/simulation.py,sha256
|
50
|
+
pycityagent/simulation/simulation.py,sha256=-vm0Yhl_k4_CbGYScg-V4dD2KEyLiarN27u0ccaX8ao,12680
|
47
51
|
pycityagent/simulation/survey/__init__.py,sha256=hFJ0Q1yo4jwKAIXP17sznBSWwm2Lyh3F3W3Lly40wr8,172
|
48
52
|
pycityagent/simulation/survey/manager.py,sha256=DkNrb12Ay7TiGURoyJTFFeUdV1zh6TgRpTmpZOblADw,2158
|
49
53
|
pycityagent/simulation/survey/models.py,sha256=-3EKe-qvkUJ2TH24ow0A_Lc4teGet7pueN2T5mOR_Qc,1308
|
@@ -55,11 +59,11 @@ pycityagent/utils/parsers/__init__.py,sha256=p5RZ4azJIpMgmKIU2evIp2moNzFabIR9X1L
|
|
55
59
|
pycityagent/utils/parsers/code_block_parser.py,sha256=Cs2Z_hm9VfNCpPPll1TwteaJF-HAQPs-3RApsOekFm4,1173
|
56
60
|
pycityagent/utils/parsers/json_parser.py,sha256=FZ3XN1g8z4Dr2TFraUOoah1oQcze4fPd2m01hHoX0Mo,2917
|
57
61
|
pycityagent/utils/parsers/parser_base.py,sha256=k6DVqwAMK3jJdOP4IeLE-aFPm3V2F-St5qRBuRdx4aU,1742
|
58
|
-
pycityagent/workflow/__init__.py,sha256=
|
59
|
-
pycityagent/workflow/block.py,sha256=
|
62
|
+
pycityagent/workflow/__init__.py,sha256=EyCcjB6LyBim-5iAOPe4m2qfvghEPqu1ZdGfy4KPeZ8,551
|
63
|
+
pycityagent/workflow/block.py,sha256=IXfarqIax6yVP_DniU6ZsPTT8QA4aIDnvZbwP_MtRaw,6054
|
60
64
|
pycityagent/workflow/prompt.py,sha256=cmzKEmlzjdwg50uwfnTnN_6xNJA8OVjo5fdmcsaTbdU,2886
|
61
65
|
pycityagent/workflow/tool.py,sha256=4sYbH-OVNffXbK3m58f8ap6WrS_uMzhK1c_Rl2er1B0,8981
|
62
|
-
pycityagent/workflow/trigger.py,sha256=
|
63
|
-
pycityagent-2.0.
|
64
|
-
pycityagent-2.0.
|
65
|
-
pycityagent-2.0.
|
66
|
+
pycityagent/workflow/trigger.py,sha256=u2aPBOzTWvdYKb45nUsQfA_uRunsmbLzB7ztSU2mlrQ,5736
|
67
|
+
pycityagent-2.0.0a3.dist-info/METADATA,sha256=C5Mcssb-bkqMJEBYu3MsqGTqfjgH__gFo_3w9wItFAA,7537
|
68
|
+
pycityagent-2.0.0a3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
69
|
+
pycityagent-2.0.0a3.dist-info/RECORD,,
|
File without changes
|