supervaizer 0.10.9__py3-none-any.whl → 0.10.11__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.
@@ -5,6 +5,6 @@
5
5
  # https://mozilla.org/MPL/2.0/.
6
6
 
7
7
 
8
- VERSION = "0.10.9"
8
+ VERSION = "0.10.11"
9
9
  API_VERSION = "v1"
10
10
  TELEMETRY_VERSION = "v1"
supervaizer/account.py CHANGED
@@ -8,7 +8,7 @@
8
8
  from typing import TYPE_CHECKING, Any, ClassVar, Dict, Optional, Union
9
9
 
10
10
  import httpx
11
- from pydantic import Field
11
+ from pydantic import Field, field_validator
12
12
 
13
13
  from supervaizer.__version__ import VERSION
14
14
  from supervaizer.common import ApiError, ApiResult, ApiSuccess, SvBaseModel
@@ -55,6 +55,14 @@ class AccountAbstract(SvBaseModel):
55
55
  description="The URL of the Supervaize SaaS API provided by Supervaize.com"
56
56
  )
57
57
 
58
+ @field_validator("workspace_id", "api_key", "api_url", mode="before")
59
+ @classmethod
60
+ def strip_whitespace(cls, v: Any) -> Any:
61
+ """Strip leading/trailing whitespace (e.g. newlines from env vars)."""
62
+ if isinstance(v, str):
63
+ return v.strip()
64
+ return v
65
+
58
66
  model_config = {
59
67
  "reference_group": "Core",
60
68
  "json_schema_extra": {
@@ -121,7 +129,7 @@ class Account(AccountAbstract):
121
129
  """URL for the Supervaize Control API.
122
130
  Tested in tests/test_account.py
123
131
  """
124
- return f"{self.api_url_w_v1}/ctrl-events/"
132
+ return f"{self.api_url_w_v1}/ctrl-events/".strip()
125
133
 
126
134
  def get_url(self, pattern_name: str, **kwargs: Any) -> str:
127
135
  """Generate a URL using the predefined patterns.
@@ -59,14 +59,17 @@ def send_event(
59
59
 
60
60
  headers = account.api_headers
61
61
  payload = event.payload
62
+ url_event = (
63
+ account.url_event.strip()
64
+ ) # defensive: env vars often have trailing newline
62
65
 
63
66
  # Generate curl equivalent for debugging
64
67
 
65
68
  curl_headers = " ".join([f'-H "{k}: {v}"' for k, v in headers.items()])
66
- curl_cmd = f"curl -X 'GET' '{account.url_event}' {curl_headers}"
69
+ curl_cmd = f"curl -X 'GET' '{url_event}' {curl_headers}"
67
70
 
68
71
  try:
69
- response = _httpx_client.post(account.url_event, headers=headers, json=payload)
72
+ response = _httpx_client.post(url_event, headers=headers, json=payload)
70
73
 
71
74
  # Log response details before raising for status
72
75
 
@@ -76,6 +79,13 @@ def send_event(
76
79
  )
77
80
 
78
81
  log.success(result.log_message)
82
+ except (httpx.ConnectError, httpx.ConnectTimeout) as e:
83
+ log.error(
84
+ f"Supervaize controller is not available at {url_event}. "
85
+ "Connection refused or timed out. Is the controller server running?"
86
+ )
87
+ log.error(f"❌ Error sending event {event.type.name}: {e!s}")
88
+ raise e
79
89
  except httpx.HTTPError as e:
80
90
  # Enhanced error logging
81
91
  log.error("[Send event] HTTP Error occurred")
@@ -83,7 +93,7 @@ def send_event(
83
93
 
84
94
  error_result = ApiError(
85
95
  message=f"Error sending event {event.type.name}",
86
- url=account.url_event,
96
+ url=url_event,
87
97
  payload=event.payload,
88
98
  exception=e,
89
99
  )
Binary file
@@ -0,0 +1,57 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Supervaizer API</title>
7
+ <!-- Tailwind CSS -->
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ </head>
10
+ <body class="bg-gray-50 min-h-screen">
11
+ <main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
12
+ <div class="px-4 py-6 sm:px-0">
13
+ <h1 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
14
+ Supervaizer API
15
+ </h1>
16
+ <p class="mt-2 text-sm text-gray-500">
17
+ Controller version {{ version }} · API version {{ api_version }}
18
+ </p>
19
+
20
+ <div class="mt-8">
21
+ <h2 class="text-lg font-medium text-gray-900 mb-4">Links</h2>
22
+ <ul class="space-y-2">
23
+ <li>
24
+ <a href="/docs" class="text-blue-600 hover:text-blue-800 font-medium">
25
+ Swagger UI
26
+ </a>
27
+ </li>
28
+ <li>
29
+ <a href="/redoc" class="text-blue-600 hover:text-blue-800 font-medium">
30
+ ReDoc
31
+ </a>
32
+ </li>
33
+ <li>
34
+ <a href="/openapi.json" class="text-blue-600 hover:text-blue-800 font-medium">
35
+ OpenAPI
36
+ </a>
37
+ </li>
38
+ {% if show_admin %}
39
+ <li>
40
+ <a href="/admin" class="text-blue-600 hover:text-blue-800 font-medium">
41
+ Admin
42
+ </a>
43
+ </li>
44
+ {% endif %}
45
+ <li>
46
+ <a href="/console" class="text-blue-600 hover:text-blue-800 font-medium">
47
+ Console
48
+ </a>
49
+ </li>
50
+ <li> BASE: {{ base }}
51
+ </li>
52
+ </ul>
53
+ </div>
54
+ </div>
55
+ </main>
56
+ </body>
57
+ </html>
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 HTMLResponse, JSONResponse
23
+ from fastapi.responses import FileResponse, 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,7 +46,11 @@ from supervaizer.routes import (
46
46
  create_utils_routes,
47
47
  get_server,
48
48
  )
49
- from supervaizer.storage import StorageManager, load_running_entities_on_startup
49
+ from supervaizer.storage import (
50
+ PERSISTENCE_ENABLED,
51
+ StorageManager,
52
+ load_running_entities_on_startup,
53
+ )
50
54
 
51
55
  insp = inspect
52
56
 
@@ -70,7 +74,9 @@ class ServerInfo(BaseModel):
70
74
 
71
75
 
72
76
  def save_server_info_to_storage(server_instance: "Server") -> None:
73
- """Save server information to storage."""
77
+ """Save server information to storage (only when persistence is enabled)."""
78
+ if not PERSISTENCE_ENABLED:
79
+ return
74
80
  try:
75
81
  storage = StorageManager()
76
82
 
@@ -377,6 +383,13 @@ class Server(ServerAbstract):
377
383
  # Save server info to storage for admin interface
378
384
  save_server_info_to_storage(self)
379
385
 
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
+
380
393
  # Home page (template in admin/templates)
381
394
  _home_templates = Jinja2Templates(
382
395
  directory=str(Path(__file__).parent / "admin" / "templates")
@@ -487,7 +500,9 @@ class Server(ServerAbstract):
487
500
  "agents": [agent.registration_info for agent in self.agents],
488
501
  }
489
502
 
490
- def launch(self, log_level: Optional[str] = "INFO") -> None:
503
+ def launch(
504
+ self, log_level: Optional[str] = "INFO", start_uvicorn: bool = False
505
+ ) -> None:
491
506
  if log_level:
492
507
  log.remove()
493
508
  log.add(
@@ -546,15 +561,16 @@ class Server(ServerAbstract):
546
561
  if updated_agent:
547
562
  log.info(f"[Server launch] Updated agent {updated_agent.name}")
548
563
 
549
- import uvicorn
564
+ if start_uvicorn:
565
+ import uvicorn
550
566
 
551
- uvicorn.run(
552
- self.app,
553
- host=self.host,
554
- port=self.port,
555
- reload=self.reload,
556
- log_level=log_level,
557
- )
567
+ uvicorn.run(
568
+ self.app,
569
+ host=self.host,
570
+ port=self.port,
571
+ reload=self.reload,
572
+ log_level=log_level,
573
+ )
558
574
 
559
575
  def instructions(self) -> None:
560
576
  server_url = f"http://{self.host}:{self.port}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supervaizer
3
- Version: 0.10.9
3
+ Version: 0.10.11
4
4
  Summary: Controller system for Supervaize
5
5
  Project-URL: Homepage, https://supervaize.com
6
6
  Project-URL: Repository, https://github.com/supervaize/supervaizer
@@ -1,7 +1,7 @@
1
1
  supervaizer/__init__.py,sha256=eBbGjduMBH-FDjcGlSqeR4Kf4uo60Cf1DrRur8VGkJo,2341
2
- supervaizer/__version__.py,sha256=LtDXeoaiX6Sv5-o1zm5x4AX1tKa1Zt9vXyke7riyv84,348
3
- supervaizer/account.py,sha256=bxANsh-97dRGGpzstT1XKGThPHqRqvJC022Hfrb2RyM,11102
4
- supervaizer/account_service.py,sha256=z4lw8qp8XvCrU6Ndf4VHRnQwY_071410ts5_7E8YDAs,3046
2
+ supervaizer/__version__.py,sha256=nMELcLDyp7XnPLe74EnEqTFcqZkxnRP1_s0G43H3RDQ,349
3
+ supervaizer/account.py,sha256=TZQdDo1OdjquFsLFxPvUUqzOcdMOIAQHHaREghD5SJ4,11421
4
+ supervaizer/account_service.py,sha256=ZgZ0fhsbSVA076c-35ZZoYJBrQZsAwfFS7namVeoD3s,3459
5
5
  supervaizer/agent.py,sha256=Clenvdr_v-lV7_v6YCcevp8dj5JUNvpTWrBZBYM82lg,36509
6
6
  supervaizer/case.py,sha256=dOgRujyf4MFcZ-937zxJbqLIPduKg6ZspHuhnWiq13Q,14385
7
7
  supervaizer/cli.py,sha256=3KH4gZXTiJ9GtY375kGm5HaKCGV2V8WEbcWdF_sWWEc,13936
@@ -13,11 +13,12 @@ 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=O6zoGk01-owb7kh9lI6mTlIfkPeqwY-rbYUzfOj2v34,21902
16
+ supervaizer/server.py,sha256=79MtQcB4fpV9VgFh-dBsbwbHf097waeLmBnArhClVb8,22473
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
20
  supervaizer/admin/routes.py,sha256=r9hucWtNiTGQHgv9DsRkVpwnLbyLFaqrbse1orl-oTA,45627
21
+ supervaizer/admin/static/favicon.ico,sha256=wFyXw96AplZoEcW45dJBeC1pHTcPSH07HGWbtrc49mI,5558
21
22
  supervaizer/admin/static/js/job-start-form.js,sha256=s--AGVYzgc9mE20POYeM0BNm0Wy41aBZVv99tc0cSPU,11938
22
23
  supervaizer/admin/templates/agent_detail.html,sha256=DFOGfjuQNC39FOLYUW_jD0A01WpBY1umatGCslyJ0_c,7581
23
24
  supervaizer/admin/templates/agents.html,sha256=orB_z1iMFE2MKhFm9XejwZjmzMC1PVT69oB-F9YZPHQ,12678
@@ -62,6 +63,7 @@ supervaizer/deploy/templates/debug_env.py,sha256=WFlxfiCAlkxM1NybNvtmmG5zJnoSvjW
62
63
  supervaizer/deploy/templates/docker-compose.yml.template,sha256=ZcW8WyhmqMElaxBpokuZG12n0tFJL8BY7k7Tvdz6tdw,1100
63
64
  supervaizer/deploy/templates/dockerignore.template,sha256=bYFRn6QGsjtRDH-Y7vzWk3-u3jIp90FajV2Ed94ah5M,515
64
65
  supervaizer/deploy/templates/entrypoint.sh,sha256=z079VUotu6DJX92fJiBB3eVwCEgcP6B9D9Fvwv_FL9w,463
66
+ supervaizer/deploy/templates/index.html,sha256=z2ocEOYbWbl1Rz3Toc5JZkN7OAoW_GFV1yKKhdyC3vw,2160
65
67
  supervaizer/examples/controller_template.py,sha256=bQRtZdq9Z8Pg0b3bRy4oVy6YIIM_e5DzhXVPOr1gFvk,6337
66
68
  supervaizer/protocol/__init__.py,sha256=00GHbUsLNsf0a1rQrUPpVN2Uy-7rDz72Ps6TUVD91tE,389
67
69
  supervaizer/protocol/a2a/__init__.py,sha256=1ACfPGLzS6XdZPiFxn1nVamvbasqtJJ7U1BBbSmT-nI,625
@@ -70,8 +72,8 @@ supervaizer/protocol/a2a/routes.py,sha256=rkQTNBD1NTYimKCb8iOk4bVf9ldDP1LqHfOsyh
70
72
  supervaizer/utils/__init__.py,sha256=fd0NFwN_cen3QPms2SOnuz4jcetay3f_31dit2As7EA,458
71
73
  supervaizer/utils/version_check.py,sha256=-tsOURpHVh0LNTbpQsyJDJENKszC-NzXDSO_EToEQPE,1893
72
74
  supervaizer/py.typed,sha256=bHhvLx7c6MqrzXVPbdK3qAOcSxzp4wDtTx4QifMC2EY,74
73
- supervaizer-0.10.9.dist-info/METADATA,sha256=c3n7f3HrIez3_PQ7BXE6gpgmaxmc2DgIB9N18lAlVS0,12647
74
- supervaizer-0.10.9.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
75
- supervaizer-0.10.9.dist-info/entry_points.txt,sha256=vL_IBR_AeEI2u2-6YL4PY9k2Mar4-gprG8-UxERWjmg,52
76
- supervaizer-0.10.9.dist-info/licenses/LICENSE.md,sha256=dmdnt1vfpxNPr8Lt0BnxKE5uzUwK3CWTthTUStgOXjY,15327
77
- supervaizer-0.10.9.dist-info/RECORD,,
75
+ supervaizer-0.10.11.dist-info/METADATA,sha256=Ec_LGKWoFOmqjOks7mlaIHaE46hCCZMqSlDUFS8zif0,12648
76
+ supervaizer-0.10.11.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
77
+ supervaizer-0.10.11.dist-info/entry_points.txt,sha256=vL_IBR_AeEI2u2-6YL4PY9k2Mar4-gprG8-UxERWjmg,52
78
+ supervaizer-0.10.11.dist-info/licenses/LICENSE.md,sha256=dmdnt1vfpxNPr8Lt0BnxKE5uzUwK3CWTthTUStgOXjY,15327
79
+ supervaizer-0.10.11.dist-info/RECORD,,