supervaizer 0.10.13__py3-none-any.whl → 0.10.14__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.
- supervaizer/__version__.py +1 -1
- supervaizer/account.py +7 -1
- supervaizer/admin/routes.py +33 -33
- supervaizer/admin/templates/index.html +1 -0
- supervaizer/server.py +32 -35
- {supervaizer-0.10.13.dist-info → supervaizer-0.10.14.dist-info}/METADATA +1 -1
- {supervaizer-0.10.13.dist-info → supervaizer-0.10.14.dist-info}/RECORD +10 -10
- {supervaizer-0.10.13.dist-info → supervaizer-0.10.14.dist-info}/WHEEL +0 -0
- {supervaizer-0.10.13.dist-info → supervaizer-0.10.14.dist-info}/entry_points.txt +0 -0
- {supervaizer-0.10.13.dist-info → supervaizer-0.10.14.dist-info}/licenses/LICENSE.md +0 -0
supervaizer/__version__.py
CHANGED
supervaizer/account.py
CHANGED
|
@@ -199,7 +199,13 @@ class Account(AccountAbstract):
|
|
|
199
199
|
from supervaizer.event import ServerRegisterEvent
|
|
200
200
|
|
|
201
201
|
event = ServerRegisterEvent(server=server, account=self)
|
|
202
|
-
|
|
202
|
+
result = self.send_event(sender=server, event=event)
|
|
203
|
+
if isinstance(result, ApiSuccess):
|
|
204
|
+
log.success(result.message)
|
|
205
|
+
# TODO: Update server with the server ID from the response. store this ID in env variable.
|
|
206
|
+
else:
|
|
207
|
+
log.error(result.message)
|
|
208
|
+
return result
|
|
203
209
|
|
|
204
210
|
def _create_api_result(
|
|
205
211
|
self,
|
supervaizer/admin/routes.py
CHANGED
|
@@ -445,7 +445,11 @@ def create_admin_routes() -> APIRouter:
|
|
|
445
445
|
if isinstance(result, ApiSuccess):
|
|
446
446
|
return JSONResponse(
|
|
447
447
|
status_code=200,
|
|
448
|
-
content={
|
|
448
|
+
content={
|
|
449
|
+
"success": True,
|
|
450
|
+
"message": result.message,
|
|
451
|
+
"detail": result.detail,
|
|
452
|
+
},
|
|
449
453
|
)
|
|
450
454
|
# ApiError
|
|
451
455
|
return JSONResponse(
|
|
@@ -921,28 +925,24 @@ def create_admin_routes() -> APIRouter:
|
|
|
921
925
|
# Combine and sort by created_at
|
|
922
926
|
activities = []
|
|
923
927
|
for job in recent_jobs:
|
|
924
|
-
activities.append(
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
}
|
|
933
|
-
)
|
|
928
|
+
activities.append({
|
|
929
|
+
"type": "job",
|
|
930
|
+
"id": job.get("id"),
|
|
931
|
+
"name": job.get("name"),
|
|
932
|
+
"status": job.get("status"),
|
|
933
|
+
"created_at": job.get("created_at"),
|
|
934
|
+
"agent_name": job.get("agent_name"),
|
|
935
|
+
})
|
|
934
936
|
|
|
935
937
|
for case in recent_cases:
|
|
936
|
-
activities.append(
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
}
|
|
945
|
-
)
|
|
938
|
+
activities.append({
|
|
939
|
+
"type": "case",
|
|
940
|
+
"id": case.get("id"),
|
|
941
|
+
"name": case.get("name"),
|
|
942
|
+
"status": case.get("status"),
|
|
943
|
+
"created_at": case.get("created_at"),
|
|
944
|
+
"job_id": case.get("job_id"),
|
|
945
|
+
})
|
|
946
946
|
|
|
947
947
|
# Sort by created_at descending
|
|
948
948
|
activities.sort(key=lambda x: str(x.get("created_at", "")), reverse=True)
|
|
@@ -1199,23 +1199,23 @@ def get_dashboard_stats(storage: StorageManager) -> AdminStats:
|
|
|
1199
1199
|
|
|
1200
1200
|
# Calculate job stats
|
|
1201
1201
|
job_total = len(all_jobs)
|
|
1202
|
-
job_running = len(
|
|
1203
|
-
|
|
1204
|
-
)
|
|
1202
|
+
job_running = len([
|
|
1203
|
+
j for j in all_jobs if j.get("status") in ["in_progress", "awaiting"]
|
|
1204
|
+
])
|
|
1205
1205
|
job_completed = len([j for j in all_jobs if j.get("status") == "completed"])
|
|
1206
|
-
job_failed = len(
|
|
1207
|
-
|
|
1208
|
-
)
|
|
1206
|
+
job_failed = len([
|
|
1207
|
+
j for j in all_jobs if j.get("status") in ["failed", "cancelled"]
|
|
1208
|
+
])
|
|
1209
1209
|
|
|
1210
1210
|
# Calculate case stats
|
|
1211
1211
|
case_total = len(all_cases)
|
|
1212
|
-
case_running = len(
|
|
1213
|
-
|
|
1214
|
-
)
|
|
1212
|
+
case_running = len([
|
|
1213
|
+
c for c in all_cases if c.get("status") in ["in_progress", "awaiting"]
|
|
1214
|
+
])
|
|
1215
1215
|
case_completed = len([c for c in all_cases if c.get("status") == "completed"])
|
|
1216
|
-
case_failed = len(
|
|
1217
|
-
|
|
1218
|
-
)
|
|
1216
|
+
case_failed = len([
|
|
1217
|
+
c for c in all_cases if c.get("status") in ["failed", "cancelled"]
|
|
1218
|
+
])
|
|
1219
1219
|
|
|
1220
1220
|
# TinyDB collections count (tables)
|
|
1221
1221
|
collections_count = len(storage._db.tables())
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
<p class="mt-2 text-sm text-gray-500">
|
|
17
17
|
Controller version {{ version }} · API version {{ api_version }}
|
|
18
18
|
</p>
|
|
19
|
+
<p class="mt-1 text-xs text-gray-400 font-mono">Server ID: {{ server_id }}</p>
|
|
19
20
|
|
|
20
21
|
<div class="mt-8">
|
|
21
22
|
<h2 class="text-lg font-medium text-gray-900 mb-4">Links</h2>
|
supervaizer/server.py
CHANGED
|
@@ -20,7 +20,7 @@ from cryptography.hazmat.primitives.asymmetric import rsa
|
|
|
20
20
|
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey
|
|
21
21
|
from fastapi import FastAPI, HTTPException, Request, Security, status
|
|
22
22
|
from fastapi.exceptions import RequestValidationError
|
|
23
|
-
from fastapi.responses import
|
|
23
|
+
from fastapi.responses import HTMLResponse, JSONResponse
|
|
24
24
|
from fastapi.security import APIKeyHeader
|
|
25
25
|
from fastapi.templating import Jinja2Templates
|
|
26
26
|
from pydantic import BaseModel, field_validator, Field
|
|
@@ -46,11 +46,7 @@ from supervaizer.routes import (
|
|
|
46
46
|
create_utils_routes,
|
|
47
47
|
get_server,
|
|
48
48
|
)
|
|
49
|
-
from supervaizer.storage import
|
|
50
|
-
PERSISTENCE_ENABLED,
|
|
51
|
-
StorageManager,
|
|
52
|
-
load_running_entities_on_startup,
|
|
53
|
-
)
|
|
49
|
+
from supervaizer.storage import StorageManager, load_running_entities_on_startup
|
|
54
50
|
|
|
55
51
|
insp = inspect
|
|
56
52
|
|
|
@@ -59,6 +55,16 @@ T = TypeVar("T")
|
|
|
59
55
|
# Additional imports for server persistence
|
|
60
56
|
|
|
61
57
|
|
|
58
|
+
def _get_or_create_server_id() -> str:
|
|
59
|
+
"""Use SUPERVAIZER_SERVER_ID from env if set; else create uuid and set env."""
|
|
60
|
+
existing = os.getenv("SUPERVAIZER_SERVER_ID")
|
|
61
|
+
if existing:
|
|
62
|
+
return existing
|
|
63
|
+
new_id = str(uuid.uuid4())
|
|
64
|
+
os.environ["SUPERVAIZER_SERVER_ID"] = new_id
|
|
65
|
+
return new_id
|
|
66
|
+
|
|
67
|
+
|
|
62
68
|
class ServerInfo(BaseModel):
|
|
63
69
|
"""Complete server information for storage."""
|
|
64
70
|
|
|
@@ -74,9 +80,7 @@ class ServerInfo(BaseModel):
|
|
|
74
80
|
|
|
75
81
|
|
|
76
82
|
def save_server_info_to_storage(server_instance: "Server") -> None:
|
|
77
|
-
"""Save server information to storage
|
|
78
|
-
if not PERSISTENCE_ENABLED:
|
|
79
|
-
return
|
|
83
|
+
"""Save server information to storage."""
|
|
80
84
|
try:
|
|
81
85
|
storage = StorageManager()
|
|
82
86
|
|
|
@@ -154,6 +158,10 @@ class ServerAbstract(SvBaseModel):
|
|
|
154
158
|
"""
|
|
155
159
|
|
|
156
160
|
supervaizer_VERSION: ClassVar[str] = VERSION
|
|
161
|
+
server_id: str = Field(
|
|
162
|
+
default_factory=_get_or_create_server_id,
|
|
163
|
+
description="Unique server id (SUPERVAIZER_SERVER_ID env or persisted uuid)",
|
|
164
|
+
)
|
|
157
165
|
scheme: str = Field(description="URL scheme (http or https)")
|
|
158
166
|
host: str = Field(
|
|
159
167
|
description="Host to bind the server to (e.g., 0.0.0.0 for all interfaces)"
|
|
@@ -242,10 +250,10 @@ class Server(ServerAbstract):
|
|
|
242
250
|
supervisor_account: Optional[Account] = None,
|
|
243
251
|
a2a_endpoints: bool = True,
|
|
244
252
|
admin_interface: bool = True,
|
|
245
|
-
scheme: str =
|
|
253
|
+
scheme: str = "http",
|
|
246
254
|
environment: str = os.getenv("SUPERVAIZER_ENVIRONMENT", "dev"),
|
|
247
255
|
host: str = os.getenv("SUPERVAIZER_HOST", "0.0.0.0"),
|
|
248
|
-
port: int = int(os.getenv("SUPERVAIZER_PORT",
|
|
256
|
+
port: int = int(os.getenv("SUPERVAIZER_PORT", 8000)),
|
|
249
257
|
debug: bool = False,
|
|
250
258
|
reload: bool = False,
|
|
251
259
|
mac_addr: str = "",
|
|
@@ -360,6 +368,8 @@ class Server(ServerAbstract):
|
|
|
360
368
|
**kwargs,
|
|
361
369
|
)
|
|
362
370
|
|
|
371
|
+
log.info(f"[Server launch] Server ID: {self.server_id}")
|
|
372
|
+
|
|
363
373
|
# Create routes
|
|
364
374
|
if self.supervisor_account:
|
|
365
375
|
log.info(
|
|
@@ -383,13 +393,6 @@ class Server(ServerAbstract):
|
|
|
383
393
|
# Save server info to storage for admin interface
|
|
384
394
|
save_server_info_to_storage(self)
|
|
385
395
|
|
|
386
|
-
# Favicon (served at root so /docs, /redoc, etc. pick it up)
|
|
387
|
-
_favicon_path = Path(__file__).parent / "admin" / "static" / "favicon.ico"
|
|
388
|
-
|
|
389
|
-
@self.app.get("/favicon.ico", include_in_schema=False)
|
|
390
|
-
async def favicon() -> FileResponse:
|
|
391
|
-
return FileResponse(_favicon_path, media_type="image/x-icon")
|
|
392
|
-
|
|
393
396
|
# Home page (template in admin/templates)
|
|
394
397
|
_home_templates = Jinja2Templates(
|
|
395
398
|
directory=str(Path(__file__).parent / "admin" / "templates")
|
|
@@ -397,20 +400,16 @@ class Server(ServerAbstract):
|
|
|
397
400
|
|
|
398
401
|
@self.app.get("/", response_class=HTMLResponse)
|
|
399
402
|
async def home_page(request: Request) -> HTMLResponse:
|
|
400
|
-
root_index = Path.cwd() / "index.html"
|
|
401
|
-
if root_index.is_file():
|
|
402
|
-
return HTMLResponse(content=root_index.read_text(encoding="utf-8"))
|
|
403
403
|
base = self.public_url or f"{self.scheme}://{self.host}:{self.port}"
|
|
404
404
|
return _home_templates.TemplateResponse(
|
|
405
405
|
"index.html",
|
|
406
406
|
{
|
|
407
407
|
"request": request,
|
|
408
408
|
"base": base,
|
|
409
|
-
"public_url": self.public_url,
|
|
410
|
-
"full_url": f"{self.scheme}://{self.host}:{self.port}",
|
|
411
409
|
"version": VERSION,
|
|
412
410
|
"api_version": API_VERSION,
|
|
413
411
|
"show_admin": bool(self.api_key and admin_interface),
|
|
412
|
+
"server_id": self.server_id,
|
|
414
413
|
},
|
|
415
414
|
)
|
|
416
415
|
|
|
@@ -481,6 +480,7 @@ class Server(ServerAbstract):
|
|
|
481
480
|
"""Get registration info for the server."""
|
|
482
481
|
assert self.public_key is not None, "Public key not initialized"
|
|
483
482
|
return {
|
|
483
|
+
"server_id": self.server_id,
|
|
484
484
|
"url": self.public_url,
|
|
485
485
|
"uri": self.uri,
|
|
486
486
|
"api_version": API_VERSION,
|
|
@@ -500,9 +500,7 @@ class Server(ServerAbstract):
|
|
|
500
500
|
"agents": [agent.registration_info for agent in self.agents],
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
-
def launch(
|
|
504
|
-
self, log_level: Optional[str] = "INFO", start_uvicorn: bool = False
|
|
505
|
-
) -> None:
|
|
503
|
+
def launch(self, log_level: Optional[str] = "INFO") -> None:
|
|
506
504
|
if log_level:
|
|
507
505
|
log.remove()
|
|
508
506
|
log.add(
|
|
@@ -561,16 +559,15 @@ class Server(ServerAbstract):
|
|
|
561
559
|
if updated_agent:
|
|
562
560
|
log.info(f"[Server launch] Updated agent {updated_agent.name}")
|
|
563
561
|
|
|
564
|
-
|
|
565
|
-
import uvicorn
|
|
562
|
+
import uvicorn
|
|
566
563
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
564
|
+
uvicorn.run(
|
|
565
|
+
self.app,
|
|
566
|
+
host=self.host,
|
|
567
|
+
port=self.port,
|
|
568
|
+
reload=self.reload,
|
|
569
|
+
log_level=log_level,
|
|
570
|
+
)
|
|
574
571
|
|
|
575
572
|
def instructions(self) -> None:
|
|
576
573
|
server_url = f"http://{self.host}:{self.port}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
supervaizer/__init__.py,sha256=UNFcgJT-2708tLRFXohWr3320LVAzh3_WZZhrU9j1Iw,2427
|
|
2
|
-
supervaizer/__version__.py,sha256=
|
|
3
|
-
supervaizer/account.py,sha256=
|
|
2
|
+
supervaizer/__version__.py,sha256=i4qCZA4QHMUjh0f98jJvNxzbOymi4JZbT3f5jnMBsqg,349
|
|
3
|
+
supervaizer/account.py,sha256=POChw9c2ZjBNvesz6JmvBzYmMD40M5oxtz5IupuMqsw,11683
|
|
4
4
|
supervaizer/account_service.py,sha256=ZgZ0fhsbSVA076c-35ZZoYJBrQZsAwfFS7namVeoD3s,3459
|
|
5
5
|
supervaizer/agent.py,sha256=EtmqBH9fsO4k8YcHnjj55_4uOmb5URZwLlIIJReWg7A,36516
|
|
6
6
|
supervaizer/case.py,sha256=dOgRujyf4MFcZ-937zxJbqLIPduKg6ZspHuhnWiq13Q,14385
|
|
@@ -13,11 +13,11 @@ supervaizer/job_service.py,sha256=22Qe7Z5_u3R28tcNH_21YMIYciWFtJaM7I-MXtIhBMU,46
|
|
|
13
13
|
supervaizer/lifecycle.py,sha256=5CunJN7MsM5blyNiFMJMLFDUBmTmmAsPE24QC-gSbYA,13958
|
|
14
14
|
supervaizer/parameter.py,sha256=sYDuGof_w6mlix0oxjB6odV0sO0QSBL1KwFZa3Y2cOA,8157
|
|
15
15
|
supervaizer/routes.py,sha256=o3u7pGGLE0MQzWtQNdd5xk1M0G9Y_BR_JiLVmCFtdC4,34319
|
|
16
|
-
supervaizer/server.py,sha256=
|
|
16
|
+
supervaizer/server.py,sha256=JKjxJXM0Mosc6LxuRzWB7TAaV0k-P_Cj_3U39gFARZs,22209
|
|
17
17
|
supervaizer/server_utils.py,sha256=FMglpADQBJynkR2v-pfwANu6obsaPvR9j0BQc5Otpac,1590
|
|
18
18
|
supervaizer/storage.py,sha256=WLX8ggwt1AGF07DrfD1K6PyP2-N45c_Ep4CL0iPLVbI,15332
|
|
19
19
|
supervaizer/telemetry.py,sha256=XSYw8ZwoY8W6C7mhwHU67t7trJzWd7CBkkSNdsDT_HA,2596
|
|
20
|
-
supervaizer/admin/routes.py,sha256=
|
|
20
|
+
supervaizer/admin/routes.py,sha256=LV9BTrJxpetj8ljhpDmSfVlmbUpXgWrggXqhMZKAI6Y,47625
|
|
21
21
|
supervaizer/admin/static/favicon.ico,sha256=wFyXw96AplZoEcW45dJBeC1pHTcPSH07HGWbtrc49mI,5558
|
|
22
22
|
supervaizer/admin/static/js/job-start-form.js,sha256=s--AGVYzgc9mE20POYeM0BNm0Wy41aBZVv99tc0cSPU,11938
|
|
23
23
|
supervaizer/admin/templates/agent_detail.html,sha256=DFOGfjuQNC39FOLYUW_jD0A01WpBY1umatGCslyJ0_c,7581
|
|
@@ -29,7 +29,7 @@ supervaizer/admin/templates/cases_list.html,sha256=UV4SfULzxNiOpG8aNddablpwf6hVN
|
|
|
29
29
|
supervaizer/admin/templates/cases_table.html,sha256=VyL5mEF003FTNHym1UYBD8JkvhA9wR328ciTKNKxdb8,6619
|
|
30
30
|
supervaizer/admin/templates/console.html,sha256=tLGGf8vHjGK77Il6SYlgparoU_xz3nbvNpGVQRkVNCc,13966
|
|
31
31
|
supervaizer/admin/templates/dashboard.html,sha256=3Pu5bR78QUcPNp5MyXkyibfp-wxYdJyyf77v3O_f_hU,7873
|
|
32
|
-
supervaizer/admin/templates/index.html,sha256=
|
|
32
|
+
supervaizer/admin/templates/index.html,sha256=3MFAQ53gptvUgBBfzQoCLOFLAd7JYOV5Ak4NEPsU1f4,2500
|
|
33
33
|
supervaizer/admin/templates/job_detail.html,sha256=LDTMWLURyVCp7SMTxQ4M8AFqNpbbUVUx253negp9JNA,10790
|
|
34
34
|
supervaizer/admin/templates/job_start_test.html,sha256=eAogAit0JfuMU4N5YR7N03w0nD_Bi9mtiX8uJ7dHLPg,4270
|
|
35
35
|
supervaizer/admin/templates/jobs_list.html,sha256=VJ2VYe62dHXvjQQgUAVyKcn58rO5919UuP3VKgxLVhM,9136
|
|
@@ -72,8 +72,8 @@ supervaizer/protocol/a2a/routes.py,sha256=rkQTNBD1NTYimKCb8iOk4bVf9ldDP1LqHfOsyh
|
|
|
72
72
|
supervaizer/utils/__init__.py,sha256=fd0NFwN_cen3QPms2SOnuz4jcetay3f_31dit2As7EA,458
|
|
73
73
|
supervaizer/utils/version_check.py,sha256=-tsOURpHVh0LNTbpQsyJDJENKszC-NzXDSO_EToEQPE,1893
|
|
74
74
|
supervaizer/py.typed,sha256=bHhvLx7c6MqrzXVPbdK3qAOcSxzp4wDtTx4QifMC2EY,74
|
|
75
|
-
supervaizer-0.10.
|
|
76
|
-
supervaizer-0.10.
|
|
77
|
-
supervaizer-0.10.
|
|
78
|
-
supervaizer-0.10.
|
|
79
|
-
supervaizer-0.10.
|
|
75
|
+
supervaizer-0.10.14.dist-info/METADATA,sha256=e85FBmO2LXuMABh6_GLkgOD0zSFiq8qh_4uvTksFnhs,12648
|
|
76
|
+
supervaizer-0.10.14.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
77
|
+
supervaizer-0.10.14.dist-info/entry_points.txt,sha256=vL_IBR_AeEI2u2-6YL4PY9k2Mar4-gprG8-UxERWjmg,52
|
|
78
|
+
supervaizer-0.10.14.dist-info/licenses/LICENSE.md,sha256=dmdnt1vfpxNPr8Lt0BnxKE5uzUwK3CWTthTUStgOXjY,15327
|
|
79
|
+
supervaizer-0.10.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|