supervaizer 0.10.15__tar.gz → 0.10.17__tar.gz

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.
Files changed (79) hide show
  1. {supervaizer-0.10.15 → supervaizer-0.10.17}/PKG-INFO +1 -1
  2. {supervaizer-0.10.15 → supervaizer-0.10.17}/pyproject.toml +1 -1
  3. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/__version__.py +1 -1
  4. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/routes.py +42 -37
  5. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/base.html +11 -1
  6. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/server.html +3 -10
  7. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/server.py +30 -0
  8. {supervaizer-0.10.15 → supervaizer-0.10.17}/.gitignore +0 -0
  9. {supervaizer-0.10.15 → supervaizer-0.10.17}/LICENSE.md +0 -0
  10. {supervaizer-0.10.15 → supervaizer-0.10.17}/README.md +0 -0
  11. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/__init__.py +0 -0
  12. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/account.py +0 -0
  13. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/account_service.py +0 -0
  14. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/static/favicon.ico +0 -0
  15. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/static/js/job-start-form.js +0 -0
  16. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/agent_detail.html +0 -0
  17. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/agents.html +0 -0
  18. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/agents_grid.html +0 -0
  19. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/case_detail.html +0 -0
  20. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/cases_list.html +0 -0
  21. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/cases_table.html +0 -0
  22. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/console.html +0 -0
  23. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/dashboard.html +0 -0
  24. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/index.html +0 -0
  25. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/job_detail.html +0 -0
  26. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/job_start_test.html +0 -0
  27. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/jobs_list.html +0 -0
  28. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/jobs_table.html +0 -0
  29. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/navigation.html +0 -0
  30. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/recent_activity.html +0 -0
  31. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/server_status_cards.html +0 -0
  32. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/admin/templates/supervaize_instructions.html +0 -0
  33. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/agent.py +0 -0
  34. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/case.py +0 -0
  35. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/cli.py +0 -0
  36. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/common.py +0 -0
  37. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/__init__.py +0 -0
  38. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/cli.py +0 -0
  39. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/commands/__init__.py +0 -0
  40. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/commands/clean.py +0 -0
  41. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/commands/down.py +0 -0
  42. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/commands/local.py +0 -0
  43. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/commands/plan.py +0 -0
  44. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/commands/status.py +0 -0
  45. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/commands/up.py +0 -0
  46. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/docker.py +0 -0
  47. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/driver_factory.py +0 -0
  48. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/drivers/__init__.py +0 -0
  49. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/drivers/aws_app_runner.py +0 -0
  50. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/drivers/base.py +0 -0
  51. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/drivers/cloud_run.py +0 -0
  52. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/drivers/do_app_platform.py +0 -0
  53. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/health.py +0 -0
  54. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/state.py +0 -0
  55. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/templates/Dockerfile.template +0 -0
  56. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/templates/debug_env.py +0 -0
  57. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/templates/docker-compose.yml.template +0 -0
  58. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/templates/dockerignore.template +0 -0
  59. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/templates/entrypoint.sh +0 -0
  60. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/templates/index.html +0 -0
  61. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/deploy/utils.py +0 -0
  62. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/event.py +0 -0
  63. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/examples/controller_template.py +0 -0
  64. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/instructions.py +0 -0
  65. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/job.py +0 -0
  66. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/job_service.py +0 -0
  67. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/lifecycle.py +0 -0
  68. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/parameter.py +0 -0
  69. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/protocol/__init__.py +0 -0
  70. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/protocol/a2a/__init__.py +0 -0
  71. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/protocol/a2a/model.py +0 -0
  72. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/protocol/a2a/routes.py +0 -0
  73. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/py.typed +0 -0
  74. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/routes.py +0 -0
  75. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/server_utils.py +0 -0
  76. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/storage.py +0 -0
  77. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/telemetry.py +0 -0
  78. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/utils/__init__.py +0 -0
  79. {supervaizer-0.10.15 → supervaizer-0.10.17}/src/supervaizer/utils/version_check.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supervaizer
3
- Version: 0.10.15
3
+ Version: 0.10.17
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
@@ -121,7 +121,7 @@ mypy_path = "src"
121
121
  disallow_any_expr = false
122
122
 
123
123
  [tool.bumpversion]
124
- current_version = "0.10.15"
124
+ current_version = "0.10.17"
125
125
  commit = true
126
126
  tag = true
127
127
  tag_name = "v{new_version}"
@@ -5,6 +5,6 @@
5
5
  # https://mozilla.org/MPL/2.0/.
6
6
 
7
7
 
8
- VERSION = "0.10.15"
8
+ VERSION = "0.10.17"
9
9
  API_VERSION = "v1"
10
10
  TELEMETRY_VERSION = "v1"
@@ -20,7 +20,7 @@ from pathlib import Path
20
20
  from typing import Any, AsyncGenerator, Dict, List, Optional
21
21
 
22
22
  import psutil
23
- from fastapi import APIRouter, Depends, HTTPException, Query, Request, Security
23
+ from fastapi import APIRouter, HTTPException, Query, Request, Security
24
24
  from fastapi.responses import HTMLResponse, JSONResponse, Response
25
25
  from fastapi.security import APIKeyHeader
26
26
  from fastapi.templating import Jinja2Templates
@@ -168,12 +168,26 @@ def format_uptime(seconds: int) -> str:
168
168
  return f"{minutes}m"
169
169
 
170
170
 
171
- def get_server_status() -> ServerStatus:
172
- """Get current server status and metrics."""
173
- # Get server info from storage - required, no fallback
174
- from supervaizer.server import get_server_info_from_storage
171
+ def _get_server_info(request: Optional[Request]) -> Optional[Any]:
172
+ """Get server info from storage, or from live server (app.state.server) when no persistence."""
173
+ from supervaizer.server import (
174
+ get_server_info_from_live,
175
+ get_server_info_from_storage,
176
+ )
175
177
 
176
178
  server_info = get_server_info_from_storage()
179
+ if server_info is not None:
180
+ return server_info
181
+ if request is not None:
182
+ live = getattr(request.app.state, "server", None)
183
+ if live is not None:
184
+ return get_server_info_from_live(live)
185
+ return None
186
+
187
+
188
+ def get_server_status(request: Optional[Request] = None) -> ServerStatus:
189
+ """Get current server status and metrics."""
190
+ server_info = _get_server_info(request)
177
191
  if not server_info:
178
192
  raise HTTPException(
179
193
  status_code=503,
@@ -217,12 +231,11 @@ def get_server_status() -> ServerStatus:
217
231
  )
218
232
 
219
233
 
220
- def get_server_configuration(storage: StorageManager) -> ServerConfiguration:
234
+ def get_server_configuration(
235
+ storage: StorageManager, request: Optional[Request] = None
236
+ ) -> ServerConfiguration:
221
237
  """Get server configuration details."""
222
- # Get server info from storage - required, no fallback
223
- from supervaizer.server import get_server_info_from_storage
224
-
225
- server_info = get_server_info_from_storage()
238
+ server_info = _get_server_info(request)
226
239
  if not server_info:
227
240
  raise HTTPException(
228
241
  status_code=503,
@@ -304,9 +317,9 @@ def create_admin_routes() -> APIRouter:
304
317
  async def admin_server_page(request: Request) -> Response:
305
318
  """Server status and configuration page."""
306
319
  try:
307
- # Get initial server data
308
- server_status = get_server_status()
309
- server_config = get_server_configuration(storage)
320
+ # Get initial server data (from storage or live when no persistence)
321
+ server_status = get_server_status(request)
322
+ server_config = get_server_configuration(storage, request)
310
323
 
311
324
  return templates.TemplateResponse(
312
325
  request,
@@ -327,9 +340,7 @@ def create_admin_routes() -> APIRouter:
327
340
  async def admin_agents_page(request: Request) -> Response:
328
341
  """Agents management page."""
329
342
  try:
330
- from supervaizer.server import get_server_info_from_storage
331
-
332
- server_info = get_server_info_from_storage()
343
+ server_info = _get_server_info(request)
333
344
  if not server_info:
334
345
  raise HTTPException(
335
346
  status_code=503, detail="Server information not available"
@@ -400,7 +411,7 @@ def create_admin_routes() -> APIRouter:
400
411
  async def get_server_status_api(request: Request) -> Response:
401
412
  """Get current server status for HTMX refresh."""
402
413
  try:
403
- server_status = get_server_status()
414
+ server_status = get_server_status(request)
404
415
 
405
416
  return templates.TemplateResponse(
406
417
  request,
@@ -415,24 +426,22 @@ def create_admin_routes() -> APIRouter:
415
426
  raise HTTPException(status_code=500, detail=str(e))
416
427
 
417
428
  @router.post("/api/server/register")
418
- async def register_server_with_supervisor(
419
- request: Request,
420
- _: bool = Depends(verify_admin_access),
421
- ) -> JSONResponse:
422
- """Trigger SERVER_REGISTER to the supervaizer supervisor."""
429
+ async def register_server_with_supervisor(request: Request) -> JSONResponse:
430
+ """Trigger SERVER_REGISTER to the supervaizer supervisor (no frontend API key; backend sends to SUPERVAIZE_API_URL)."""
423
431
  try:
424
432
  from supervaizer.common import ApiSuccess
425
433
  from supervaizer.routes import get_server
426
434
 
427
- get_current = request.app.dependency_overrides.get(get_server)
428
- if get_current is None:
429
- raise HTTPException(
430
- status_code=503,
431
- detail="Server instance not available (admin not running with live server)",
432
- )
433
- try:
434
- server = await get_current()
435
- except (NotImplementedError, TypeError):
435
+ # Prefer app.state.server (set at launch), else dependency override
436
+ server = getattr(request.app.state, "server", None)
437
+ if server is None:
438
+ get_current = request.app.dependency_overrides.get(get_server)
439
+ if get_current is not None:
440
+ try:
441
+ server = await get_current()
442
+ except (NotImplementedError, TypeError):
443
+ pass
444
+ if server is None:
436
445
  raise HTTPException(
437
446
  status_code=503,
438
447
  detail="Server instance not available (admin not running with live server)",
@@ -477,9 +486,7 @@ def create_admin_routes() -> APIRouter:
477
486
  ) -> Response:
478
487
  """Get agents with filtering for HTMX refresh."""
479
488
  try:
480
- from supervaizer.server import get_server_info_from_storage
481
-
482
- server_info = get_server_info_from_storage()
489
+ server_info = _get_server_info(request)
483
490
  if not server_info:
484
491
  raise HTTPException(
485
492
  status_code=503, detail="Server information not available"
@@ -548,9 +555,7 @@ def create_admin_routes() -> APIRouter:
548
555
  ) -> Response:
549
556
  """Get detailed agent information."""
550
557
  try:
551
- from supervaizer.server import get_server_info_from_storage
552
-
553
- server_info = get_server_info_from_storage()
558
+ server_info = _get_server_info(request)
554
559
  if not server_info:
555
560
  raise HTTPException(
556
561
  status_code=503, detail="Server information not available"
@@ -31,8 +31,18 @@
31
31
  .htmx-request { opacity: 0.5; }
32
32
  .htmx-request.htmx-swapping { opacity: 1; }
33
33
  </style>
34
+ <script>
35
+ // Persist admin API key from URL so it survives navigation (e.g. Register with supervisor)
36
+ (function() {
37
+ var m = /[?&]key=([^&]+)/.exec(window.location.search);
38
+ if (m) try {
39
+ var k = decodeURIComponent(m[1]);
40
+ if (k !== 'None' && k !== 'undefined') sessionStorage.setItem('admin_api_key', k);
41
+ } catch (e) {}
42
+ })();
43
+ </script>
34
44
  </head>
35
- <body class="bg-gray-50 min-h-screen">
45
+ <body class="bg-gray-50 min-h-screen" data-admin-key="{{ (api_key or '')|e }}">
36
46
  <!-- Navigation -->
37
47
  {% include "navigation.html" %}
38
48
 
@@ -109,20 +109,17 @@
109
109
  }
110
110
  }, 30000);
111
111
 
112
- // Register with supervisor button
112
+ // Register with supervisor button — no API key; backend sends SERVER_REGISTER to SUPERVAIZE_API_URL
113
113
  const registerBtn = document.getElementById('register-supervisor-btn');
114
114
  const registerIndicator = document.getElementById('register-indicator');
115
115
  const registerResult = document.getElementById('register-result');
116
116
  if (registerBtn) {
117
117
  registerBtn.addEventListener('click', async function() {
118
- const params = new URLSearchParams(window.location.search);
119
- const key = params.get('key');
120
- const url = key ? '/admin/api/server/register?key=' + encodeURIComponent(key) : '/admin/api/server/register';
121
118
  registerResult.classList.add('hidden');
122
119
  registerIndicator.classList.remove('htmx-indicator');
123
120
  registerBtn.disabled = true;
124
121
  try {
125
- const res = await fetch(url, { method: 'POST' });
122
+ const res = await fetch('/admin/api/server/register', { method: 'POST' });
126
123
  const data = await res.json().catch(function() { return {}; });
127
124
  registerResult.classList.remove('hidden');
128
125
  if (res.ok && data.success) {
@@ -130,11 +127,7 @@
130
127
  registerResult.textContent = data.message || 'Registered successfully.';
131
128
  } else {
132
129
  registerResult.className = 'mt-2 text-sm text-red-700';
133
- if (res.status === 403) {
134
- registerResult.textContent = 'Authentication required. Open this page with ?key=...';
135
- } else {
136
- registerResult.textContent = (data.detail && typeof data.detail === 'object' && data.detail.message) ? data.detail.message : (data.message || 'Registration failed.');
137
- }
130
+ registerResult.textContent = (data.detail && typeof data.detail === 'object' && data.detail.message) ? data.detail.message : (data.message || data.detail || 'Registration failed.');
138
131
  }
139
132
  } catch (e) {
140
133
  registerResult.classList.remove('hidden');
@@ -131,6 +131,32 @@ def get_server_info_from_storage() -> Optional[ServerInfo]:
131
131
  return None
132
132
 
133
133
 
134
+ def get_server_info_from_live(server_instance: "Server") -> ServerInfo:
135
+ """Build ServerInfo from a live Server instance (for when storage has no ServerInfo, e.g. no persistence)."""
136
+ agents = []
137
+ if hasattr(server_instance, "agents") and server_instance.agents:
138
+ for agent in server_instance.agents:
139
+ agents.append({
140
+ "name": agent.name,
141
+ "description": agent.description,
142
+ "version": agent.version,
143
+ "api_path": agent.path,
144
+ "slug": agent.slug,
145
+ "instructions_path": agent.instructions_path,
146
+ })
147
+ start_time = getattr(server_instance, "_start_time", time.time())
148
+ return ServerInfo(
149
+ host=getattr(server_instance, "host", "N/A"),
150
+ port=getattr(server_instance, "port", 0),
151
+ api_version=API_VERSION,
152
+ environment=os.getenv("SUPERVAIZER_ENVIRONMENT", "development"),
153
+ agents=agents,
154
+ start_time=start_time,
155
+ created_at=datetime.now().isoformat(),
156
+ updated_at=datetime.now().isoformat(),
157
+ )
158
+
159
+
134
160
  class ServerAbstract(SvBaseModel):
135
161
  """
136
162
  API Server for the Supervaize Controller.
@@ -428,6 +454,10 @@ class Server(ServerAbstract):
428
454
  # Update the dependency
429
455
  self.app.dependency_overrides[get_server] = get_current_server
430
456
 
457
+ # Expose live server for admin when storage has no ServerInfo (e.g. no persistence)
458
+ self._start_time = time.time()
459
+ self.app.state.server = self
460
+
431
461
  if api_key:
432
462
  log.info("[Server launch] API Key authentication enabled")
433
463
  # Print the API key if it was generated
File without changes
File without changes
File without changes