jvserve 2.1.15__py3-none-any.whl → 2.1.17__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.
- jvserve/cli.py +2 -0
- jvserve/lib/agent_interface.py +6 -3
- jvserve/lib/agent_pulse.py +63 -0
- jvserve/lib/jac_interface.py +9 -3
- {jvserve-2.1.15.dist-info → jvserve-2.1.17.dist-info}/METADATA +1 -1
- jvserve-2.1.17.dist-info/RECORD +14 -0
- jvserve-2.1.15.dist-info/RECORD +0 -13
- {jvserve-2.1.15.dist-info → jvserve-2.1.17.dist-info}/WHEEL +0 -0
- {jvserve-2.1.15.dist-info → jvserve-2.1.17.dist-info}/entry_points.txt +0 -0
- {jvserve-2.1.15.dist-info → jvserve-2.1.17.dist-info}/licenses/LICENSE +0 -0
- {jvserve-2.1.15.dist-info → jvserve-2.1.17.dist-info}/top_level.txt +0 -0
jvserve/cli.py
CHANGED
|
@@ -33,6 +33,7 @@ from typing_extensions import Any
|
|
|
33
33
|
from watchfiles import Change, watch
|
|
34
34
|
|
|
35
35
|
from jvserve.lib.agent_interface import AgentInterface
|
|
36
|
+
from jvserve.lib.agent_pulse import AgentPulse
|
|
36
37
|
from jvserve.lib.file_interface import (
|
|
37
38
|
DEFAULT_FILES_ROOT,
|
|
38
39
|
FILE_INTERFACE,
|
|
@@ -220,6 +221,7 @@ def run_jivas(filename: str, host: str = "localhost", port: int = 8000) -> None:
|
|
|
220
221
|
|
|
221
222
|
async def on_shutdown() -> None:
|
|
222
223
|
jvlogger.info("JIVAS is shutting down...")
|
|
224
|
+
AgentPulse.stop()
|
|
223
225
|
|
|
224
226
|
app = JaseciFastAPI.get()
|
|
225
227
|
app_lifespan = app.router.lifespan_context
|
jvserve/lib/agent_interface.py
CHANGED
|
@@ -15,6 +15,7 @@ class AgentInterface:
|
|
|
15
15
|
|
|
16
16
|
_instance = None
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
18
|
+
timeout = int(os.environ.get("JIVAS_REQUEST_TIMEOUT", 30))
|
|
18
19
|
|
|
19
20
|
def __init__(self, host: str = "localhost", port: int = 8000) -> None:
|
|
20
21
|
"""Initialize the AgentInterface with JacInterface."""
|
|
@@ -49,8 +50,10 @@ class AgentInterface:
|
|
|
49
50
|
def api_pulse(self, action_label: str, agent_id: str) -> dict:
|
|
50
51
|
"""Synchronous pulse API call"""
|
|
51
52
|
if not self._jac.is_valid():
|
|
52
|
-
self.logger.warning(
|
|
53
|
-
|
|
53
|
+
self.logger.warning(
|
|
54
|
+
"Invalid API state for pulse, attempting to reinstate it..."
|
|
55
|
+
)
|
|
56
|
+
self._jac._authenticate()
|
|
54
57
|
|
|
55
58
|
# Clean parameters
|
|
56
59
|
action_label = action_label.replace("action_label=", "")
|
|
@@ -62,7 +65,7 @@ class AgentInterface:
|
|
|
62
65
|
|
|
63
66
|
try:
|
|
64
67
|
response = requests.post(
|
|
65
|
-
endpoint, json=payload, headers=headers, timeout=
|
|
68
|
+
endpoint, json=payload, headers=headers, timeout=self.timeout
|
|
66
69
|
)
|
|
67
70
|
if response.status_code == 200:
|
|
68
71
|
return response.json().get("reports", {})
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Agent Pulse class for scheduling and running agent jobs."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import threading
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
import schedule
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AgentPulse:
|
|
11
|
+
"""Agent Pulse class for scheduling and running agent jobs."""
|
|
12
|
+
|
|
13
|
+
EVENT = None
|
|
14
|
+
THREAD = None
|
|
15
|
+
LOGGER = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def start(interval: int = 1) -> threading.Event:
|
|
19
|
+
"""Starts the agent pulse in a separate thread that executes
|
|
20
|
+
pending jobs at each elapsed time interval.
|
|
21
|
+
|
|
22
|
+
This method ensures that only one thread is running at a time
|
|
23
|
+
to prevent duplication. If a thread is already running, it logs
|
|
24
|
+
a message and returns without starting a new thread.
|
|
25
|
+
|
|
26
|
+
@param interval: Time in seconds between each execution cycle of
|
|
27
|
+
scheduled jobs.
|
|
28
|
+
@return: threading.Event which can be set to stop the running
|
|
29
|
+
thread.
|
|
30
|
+
|
|
31
|
+
Note: It is intended behavior that run_continuously() does not
|
|
32
|
+
run missed jobs. For instance, a job scheduled to run every
|
|
33
|
+
minute with a run interval of one hour will only run once per
|
|
34
|
+
hour, not 60 times at once.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
if AgentPulse.THREAD and AgentPulse.THREAD.is_alive():
|
|
38
|
+
AgentPulse.LOGGER.info("agent pulse is already running.")
|
|
39
|
+
return AgentPulse.EVENT
|
|
40
|
+
|
|
41
|
+
AgentPulse.EVENT = threading.Event()
|
|
42
|
+
|
|
43
|
+
class ScheduleThread(threading.Thread):
|
|
44
|
+
def run(self) -> None:
|
|
45
|
+
while AgentPulse.EVENT and not AgentPulse.EVENT.is_set():
|
|
46
|
+
schedule.run_pending()
|
|
47
|
+
time.sleep(interval)
|
|
48
|
+
|
|
49
|
+
AgentPulse.THREAD = ScheduleThread()
|
|
50
|
+
AgentPulse.THREAD.start()
|
|
51
|
+
|
|
52
|
+
AgentPulse.LOGGER.info("agent pulse started.")
|
|
53
|
+
|
|
54
|
+
return AgentPulse.EVENT
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def stop() -> None:
|
|
58
|
+
"""Stops the agent pulse."""
|
|
59
|
+
if AgentPulse.EVENT and not AgentPulse.EVENT.is_set():
|
|
60
|
+
AgentPulse.LOGGER.info("agent pulse stopped.")
|
|
61
|
+
AgentPulse.EVENT.set()
|
|
62
|
+
if AgentPulse.THREAD:
|
|
63
|
+
AgentPulse.THREAD.join()
|
jvserve/lib/jac_interface.py
CHANGED
|
@@ -25,6 +25,8 @@ from jaclang.runtimelib.machine import JacMachine
|
|
|
25
25
|
class JacInterface:
|
|
26
26
|
"""Thread-safe connection and context state provider for Jac Runtime with auto-authentication."""
|
|
27
27
|
|
|
28
|
+
timeout = int(os.environ.get("JIVAS_REQUEST_TIMEOUT", 30))
|
|
29
|
+
|
|
28
30
|
def __init__(self, host: str = "localhost", port: int = 8000) -> None:
|
|
29
31
|
"""Initialize JacInterface with host and port."""
|
|
30
32
|
self.host = host
|
|
@@ -155,7 +157,9 @@ class JacInterface:
|
|
|
155
157
|
try:
|
|
156
158
|
# Try login first
|
|
157
159
|
response = requests.post(
|
|
158
|
-
login_url,
|
|
160
|
+
login_url,
|
|
161
|
+
json={"email": user, "password": password},
|
|
162
|
+
timeout=self.timeout,
|
|
159
163
|
)
|
|
160
164
|
self.logger.info(f"Login response status: {response.status_code}")
|
|
161
165
|
if response.status_code == 200:
|
|
@@ -164,7 +168,9 @@ class JacInterface:
|
|
|
164
168
|
|
|
165
169
|
# Register if login fails
|
|
166
170
|
reg_response = requests.post(
|
|
167
|
-
register_url,
|
|
171
|
+
register_url,
|
|
172
|
+
json={"email": user, "password": password},
|
|
173
|
+
timeout=self.timeout,
|
|
168
174
|
)
|
|
169
175
|
self.logger.info(
|
|
170
176
|
f"Register response status: {reg_response.status_code}"
|
|
@@ -174,7 +180,7 @@ class JacInterface:
|
|
|
174
180
|
login_response = requests.post(
|
|
175
181
|
login_url,
|
|
176
182
|
json={"email": user, "password": password},
|
|
177
|
-
timeout=
|
|
183
|
+
timeout=self.timeout,
|
|
178
184
|
)
|
|
179
185
|
self.logger.info(
|
|
180
186
|
f"Retry login response status: {login_response.status_code}"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
jvserve/__init__.py,sha256=Jd0pamSDn2wGTZkNk8I9qNYTFBHp7rasdYO0_Dvad_k,245
|
|
2
|
+
jvserve/cli.py,sha256=b1AHsiJUsMVHZ7ZOKhrOJSvISPh5O5O020aoDJQJ0Rk,13910
|
|
3
|
+
jvserve/lib/__init__.py,sha256=cnzfSHLoTWG9Ygut2nOpDys5aPlQz-m0BSkB-nd7OMs,31
|
|
4
|
+
jvserve/lib/agent_interface.py,sha256=p7Fofd5q6Fk-Q900qbvPu2gB4TemPJFkOPgSq1w-oyk,3628
|
|
5
|
+
jvserve/lib/agent_pulse.py,sha256=6hBF6KQYr6Z9Mi_yoWKGfdnW7gg84kK20Slu-bLR_m8,2067
|
|
6
|
+
jvserve/lib/file_interface.py,sha256=VO9RBCtJwaBxu5eZjc57-uRbsVXXZt86wVRVq9R3KXY,6079
|
|
7
|
+
jvserve/lib/jac_interface.py,sha256=7LuY_ddG9qANgRWk7i7Oum6cX_EzB_mYAH7YYRH7ytQ,8149
|
|
8
|
+
jvserve/lib/jvlogger.py,sha256=RNiB9PHuBzTvNIQWhxoDgrDlNYA0PYm1SVpvzlqu8mE,4180
|
|
9
|
+
jvserve-2.1.17.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
10
|
+
jvserve-2.1.17.dist-info/METADATA,sha256=03dypxwccncxgYacVU4cPQ53ncrkMd4Gc9g425UmTNs,4821
|
|
11
|
+
jvserve-2.1.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
+
jvserve-2.1.17.dist-info/entry_points.txt,sha256=HYyg1QXoLs0JRb004L300VeLOZyDLY27ynD1tnTnEN4,35
|
|
13
|
+
jvserve-2.1.17.dist-info/top_level.txt,sha256=afoCXZv-zXNBuhVIvfJGjafXKEiJl_ooy4BtgQwAG4Q,8
|
|
14
|
+
jvserve-2.1.17.dist-info/RECORD,,
|
jvserve-2.1.15.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
jvserve/__init__.py,sha256=Jd0pamSDn2wGTZkNk8I9qNYTFBHp7rasdYO0_Dvad_k,245
|
|
2
|
-
jvserve/cli.py,sha256=LR6PbEWStL3eSErplA_K7U8ZY_5pDYGYJbZLV1oTlkw,13837
|
|
3
|
-
jvserve/lib/__init__.py,sha256=cnzfSHLoTWG9Ygut2nOpDys5aPlQz-m0BSkB-nd7OMs,31
|
|
4
|
-
jvserve/lib/agent_interface.py,sha256=Igv5Jb7i9Aq_7IbLDZ6jnldGKssAWKeb6iXoolX8u4k,3478
|
|
5
|
-
jvserve/lib/file_interface.py,sha256=VO9RBCtJwaBxu5eZjc57-uRbsVXXZt86wVRVq9R3KXY,6079
|
|
6
|
-
jvserve/lib/jac_interface.py,sha256=ydhXfYTsrhdvMXBTAd_vnAXJSSVBydQ3qavPU1-oodU,7973
|
|
7
|
-
jvserve/lib/jvlogger.py,sha256=RNiB9PHuBzTvNIQWhxoDgrDlNYA0PYm1SVpvzlqu8mE,4180
|
|
8
|
-
jvserve-2.1.15.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
9
|
-
jvserve-2.1.15.dist-info/METADATA,sha256=IxIo1aY9pcqIiLIPd3UQbZZN58fNVTtyX1bHOZEiQAc,4821
|
|
10
|
-
jvserve-2.1.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
jvserve-2.1.15.dist-info/entry_points.txt,sha256=HYyg1QXoLs0JRb004L300VeLOZyDLY27ynD1tnTnEN4,35
|
|
12
|
-
jvserve-2.1.15.dist-info/top_level.txt,sha256=afoCXZv-zXNBuhVIvfJGjafXKEiJl_ooy4BtgQwAG4Q,8
|
|
13
|
-
jvserve-2.1.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|