@mcoda/mswarm 0.1.134 → 0.1.135-codali.2

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 (248) hide show
  1. package/README.md +40 -0
  2. package/dist/codali-executor.d.ts +63 -0
  3. package/dist/codali-executor.d.ts.map +1 -1
  4. package/dist/codali-executor.js +78 -8
  5. package/dist/codali-executor.js.map +1 -1
  6. package/dist/invocation-token.d.ts.map +1 -1
  7. package/dist/invocation-token.js +1 -0
  8. package/dist/invocation-token.js.map +1 -1
  9. package/dist/native-reasoning.d.ts +8 -0
  10. package/dist/native-reasoning.d.ts.map +1 -0
  11. package/dist/native-reasoning.js +18 -0
  12. package/dist/native-reasoning.js.map +1 -0
  13. package/dist/runtime.d.ts +23 -1
  14. package/dist/runtime.d.ts.map +1 -1
  15. package/dist/runtime.js +181 -15
  16. package/dist/runtime.js.map +1 -1
  17. package/dist/server.d.ts +3 -1
  18. package/dist/server.d.ts.map +1 -1
  19. package/dist/server.js +58 -8
  20. package/dist/server.js.map +1 -1
  21. package/dist/vendor/codali/agents/RoleResolution.d.ts.map +1 -1
  22. package/dist/vendor/codali/agents/RoleResolution.js +4 -4
  23. package/dist/vendor/codali/api/CodaliApi.d.ts +16 -0
  24. package/dist/vendor/codali/api/CodaliApi.d.ts.map +1 -1
  25. package/dist/vendor/codali/api/CodaliApi.js +39 -10
  26. package/dist/vendor/codali/cli/AskCommand.d.ts +3 -0
  27. package/dist/vendor/codali/cli/AskCommand.d.ts.map +1 -1
  28. package/dist/vendor/codali/cli/AskCommand.js +76 -13
  29. package/dist/vendor/codali/cli/RunCommand.d.ts +4 -0
  30. package/dist/vendor/codali/cli/RunCommand.d.ts.map +1 -1
  31. package/dist/vendor/codali/cli/RunCommand.js +110 -24
  32. package/dist/vendor/codali/cli/TerminalCommand.d.ts +35 -0
  33. package/dist/vendor/codali/cli/TerminalCommand.d.ts.map +1 -0
  34. package/dist/vendor/codali/cli/TerminalCommand.js +616 -0
  35. package/dist/vendor/codali/cli/TerminalCredentials.d.ts +3 -0
  36. package/dist/vendor/codali/cli/TerminalCredentials.d.ts.map +1 -0
  37. package/dist/vendor/codali/cli/TerminalCredentials.js +89 -0
  38. package/dist/vendor/codali/cli/TerminalInput.d.ts +24 -0
  39. package/dist/vendor/codali/cli/TerminalInput.d.ts.map +1 -0
  40. package/dist/vendor/codali/cli/TerminalInput.js +98 -0
  41. package/dist/vendor/codali/cli/TerminalText.d.ts +10 -0
  42. package/dist/vendor/codali/cli/TerminalText.d.ts.map +1 -0
  43. package/dist/vendor/codali/cli/TerminalText.js +53 -0
  44. package/dist/vendor/codali/cli.d.ts.map +1 -1
  45. package/dist/vendor/codali/cli.js +33 -4
  46. package/dist/vendor/codali/cognitive/ConfiguredPipeline.d.ts +34 -0
  47. package/dist/vendor/codali/cognitive/ConfiguredPipeline.d.ts.map +1 -0
  48. package/dist/vendor/codali/cognitive/ConfiguredPipeline.js +50 -0
  49. package/dist/vendor/codali/cognitive/ValidationRunner.d.ts +4 -0
  50. package/dist/vendor/codali/cognitive/ValidationRunner.d.ts.map +1 -1
  51. package/dist/vendor/codali/cognitive/ValidationRunner.js +18 -41
  52. package/dist/vendor/codali/config/NodeOrchestration.d.ts +21 -0
  53. package/dist/vendor/codali/config/NodeOrchestration.d.ts.map +1 -0
  54. package/dist/vendor/codali/config/NodeOrchestration.js +54 -0
  55. package/dist/vendor/codali/config/OrchestrationConfig.d.ts +100 -0
  56. package/dist/vendor/codali/config/OrchestrationConfig.d.ts.map +1 -0
  57. package/dist/vendor/codali/config/OrchestrationConfig.js +245 -0
  58. package/dist/vendor/codali/connectors/mcp/McpClient.d.ts +3 -1
  59. package/dist/vendor/codali/connectors/mcp/McpClient.d.ts.map +1 -1
  60. package/dist/vendor/codali/connectors/mcp/McpClient.js +3 -2
  61. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.d.ts +2 -2
  62. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.d.ts.map +1 -1
  63. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.js +39 -16
  64. package/dist/vendor/codali/connectors/mcp/McpToolAdapter.js +2 -2
  65. package/dist/vendor/codali/connectors/media/ConfiguredMediaTools.d.ts +6 -0
  66. package/dist/vendor/codali/connectors/media/ConfiguredMediaTools.d.ts.map +1 -0
  67. package/dist/vendor/codali/connectors/media/ConfiguredMediaTools.js +41 -0
  68. package/dist/vendor/codali/connectors/media/ImageGenerationTool.js +3 -3
  69. package/dist/vendor/codali/connectors/media/MediaArtifactReceipt.d.ts +5 -0
  70. package/dist/vendor/codali/connectors/media/MediaArtifactReceipt.d.ts.map +1 -0
  71. package/dist/vendor/codali/connectors/media/MediaArtifactReceipt.js +65 -0
  72. package/dist/vendor/codali/connectors/media/MediaJobStore.d.ts +68 -0
  73. package/dist/vendor/codali/connectors/media/MediaJobStore.d.ts.map +1 -0
  74. package/dist/vendor/codali/connectors/media/MediaJobStore.js +199 -0
  75. package/dist/vendor/codali/connectors/media/MediaJobWorker.d.ts +2 -0
  76. package/dist/vendor/codali/connectors/media/MediaJobWorker.d.ts.map +1 -0
  77. package/dist/vendor/codali/connectors/media/MediaJobWorker.js +65 -0
  78. package/dist/vendor/codali/connectors/media/RemoteMediaJob.d.ts +6 -0
  79. package/dist/vendor/codali/connectors/media/RemoteMediaJob.d.ts.map +1 -0
  80. package/dist/vendor/codali/connectors/media/RemoteMediaJob.js +80 -0
  81. package/dist/vendor/codali/docdex/DocdexClient.d.ts +18 -1
  82. package/dist/vendor/codali/docdex/DocdexClient.d.ts.map +1 -1
  83. package/dist/vendor/codali/docdex/DocdexClient.js +135 -19
  84. package/dist/vendor/codali/docdex/ManagedDocdex.d.ts +29 -0
  85. package/dist/vendor/codali/docdex/ManagedDocdex.d.ts.map +1 -0
  86. package/dist/vendor/codali/docdex/ManagedDocdex.js +215 -0
  87. package/dist/vendor/codali/docdex/ManagedRuntime.d.ts +28 -0
  88. package/dist/vendor/codali/docdex/ManagedRuntime.d.ts.map +1 -0
  89. package/dist/vendor/codali/docdex/ManagedRuntime.js +212 -0
  90. package/dist/vendor/codali/eval/EvaluationProcess.d.ts +13 -0
  91. package/dist/vendor/codali/eval/EvaluationProcess.d.ts.map +1 -0
  92. package/dist/vendor/codali/eval/EvaluationProcess.js +76 -0
  93. package/dist/vendor/codali/eval/LongWorkflowJourney.d.ts +34 -0
  94. package/dist/vendor/codali/eval/LongWorkflowJourney.d.ts.map +1 -0
  95. package/dist/vendor/codali/eval/LongWorkflowJourney.js +243 -0
  96. package/dist/vendor/codali/eval/PlanningCorpus.d.ts +45 -0
  97. package/dist/vendor/codali/eval/PlanningCorpus.d.ts.map +1 -0
  98. package/dist/vendor/codali/eval/PlanningCorpus.js +189 -0
  99. package/dist/vendor/codali/eval/PlanningCorpusRunner.d.ts +13 -0
  100. package/dist/vendor/codali/eval/PlanningCorpusRunner.d.ts.map +1 -0
  101. package/dist/vendor/codali/eval/PlanningCorpusRunner.js +89 -0
  102. package/dist/vendor/codali/eval/TerminalCorpusRunner.d.ts +36 -0
  103. package/dist/vendor/codali/eval/TerminalCorpusRunner.d.ts.map +1 -0
  104. package/dist/vendor/codali/eval/TerminalCorpusRunner.js +222 -0
  105. package/dist/vendor/codali/eval/TerminalTaskCorpus.d.ts +26 -0
  106. package/dist/vendor/codali/eval/TerminalTaskCorpus.d.ts.map +1 -0
  107. package/dist/vendor/codali/eval/TerminalTaskCorpus.js +105 -0
  108. package/dist/vendor/codali/eval/TerminalWorkflowCorpus.d.ts +11 -0
  109. package/dist/vendor/codali/eval/TerminalWorkflowCorpus.d.ts.map +1 -0
  110. package/dist/vendor/codali/eval/TerminalWorkflowCorpus.js +116 -0
  111. package/dist/vendor/codali/eval/fixtures/TerminalRecoveryJourney.d.ts +4 -0
  112. package/dist/vendor/codali/eval/fixtures/TerminalRecoveryJourney.d.ts.map +1 -0
  113. package/dist/vendor/codali/eval/fixtures/TerminalRecoveryJourney.js +132 -0
  114. package/dist/vendor/codali/gateway/CodaliGateway.d.ts +2 -0
  115. package/dist/vendor/codali/gateway/CodaliGateway.d.ts.map +1 -1
  116. package/dist/vendor/codali/gateway/CodaliGateway.js +11 -1
  117. package/dist/vendor/codali/gateway/ConfiguredGateway.d.ts +23 -0
  118. package/dist/vendor/codali/gateway/ConfiguredGateway.d.ts.map +1 -0
  119. package/dist/vendor/codali/gateway/ConfiguredGateway.js +44 -0
  120. package/dist/vendor/codali/gateway/GatewayTracer.d.ts +1 -1
  121. package/dist/vendor/codali/gateway/GatewayTracer.d.ts.map +1 -1
  122. package/dist/vendor/codali/gateway/GatewayTracer.js +2 -27
  123. package/dist/vendor/codali/index.d.ts +23 -0
  124. package/dist/vendor/codali/index.d.ts.map +1 -1
  125. package/dist/vendor/codali/index.js +12 -0
  126. package/dist/vendor/codali/permissions/PermissionGate.d.ts +44 -0
  127. package/dist/vendor/codali/permissions/PermissionGate.d.ts.map +1 -0
  128. package/dist/vendor/codali/permissions/PermissionGate.js +97 -0
  129. package/dist/vendor/codali/providers/ConfiguredEmbeddings.d.ts +43 -0
  130. package/dist/vendor/codali/providers/ConfiguredEmbeddings.d.ts.map +1 -0
  131. package/dist/vendor/codali/providers/ConfiguredEmbeddings.js +87 -0
  132. package/dist/vendor/codali/providers/ConfiguredModelScope.d.ts +69 -0
  133. package/dist/vendor/codali/providers/ConfiguredModelScope.d.ts.map +1 -0
  134. package/dist/vendor/codali/providers/ConfiguredModelScope.js +113 -0
  135. package/dist/vendor/codali/providers/ConfiguredProvider.d.ts +79 -0
  136. package/dist/vendor/codali/providers/ConfiguredProvider.d.ts.map +1 -0
  137. package/dist/vendor/codali/providers/ConfiguredProvider.js +238 -0
  138. package/dist/vendor/codali/providers/ModelServiceError.d.ts +10 -0
  139. package/dist/vendor/codali/providers/ModelServiceError.d.ts.map +1 -0
  140. package/dist/vendor/codali/providers/ModelServiceError.js +45 -0
  141. package/dist/vendor/codali/providers/MswarmWorkerProvider.d.ts.map +1 -1
  142. package/dist/vendor/codali/providers/MswarmWorkerProvider.js +4 -0
  143. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.d.ts.map +1 -1
  144. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.js +91 -50
  145. package/dist/vendor/codali/providers/ProviderTypes.d.ts +12 -0
  146. package/dist/vendor/codali/providers/ProviderTypes.d.ts.map +1 -1
  147. package/dist/vendor/codali/runtime/CodaliJobRuntime.d.ts +6 -0
  148. package/dist/vendor/codali/runtime/CodaliJobRuntime.d.ts.map +1 -1
  149. package/dist/vendor/codali/runtime/CodaliJobRuntime.js +36 -1
  150. package/dist/vendor/codali/runtime/CodaliRuntime.d.ts +28 -0
  151. package/dist/vendor/codali/runtime/CodaliRuntime.d.ts.map +1 -1
  152. package/dist/vendor/codali/runtime/CodaliRuntime.js +69 -1
  153. package/dist/vendor/codali/runtime/CompletionReport.d.ts +5 -0
  154. package/dist/vendor/codali/runtime/CompletionReport.d.ts.map +1 -0
  155. package/dist/vendor/codali/runtime/CompletionReport.js +12 -0
  156. package/dist/vendor/codali/runtime/ProgressTracker.d.ts +17 -0
  157. package/dist/vendor/codali/runtime/ProgressTracker.d.ts.map +1 -0
  158. package/dist/vendor/codali/runtime/ProgressTracker.js +27 -0
  159. package/dist/vendor/codali/runtime/RequestedTestEvidence.d.ts +12 -0
  160. package/dist/vendor/codali/runtime/RequestedTestEvidence.d.ts.map +1 -0
  161. package/dist/vendor/codali/runtime/RequestedTestEvidence.js +16 -0
  162. package/dist/vendor/codali/runtime/RequiredRetrieval.d.ts +13 -0
  163. package/dist/vendor/codali/runtime/RequiredRetrieval.d.ts.map +1 -0
  164. package/dist/vendor/codali/runtime/RequiredRetrieval.js +25 -0
  165. package/dist/vendor/codali/runtime/ReviewSource.d.ts +6 -0
  166. package/dist/vendor/codali/runtime/ReviewSource.d.ts.map +1 -0
  167. package/dist/vendor/codali/runtime/ReviewSource.js +38 -0
  168. package/dist/vendor/codali/runtime/Runner.d.ts +7 -0
  169. package/dist/vendor/codali/runtime/Runner.d.ts.map +1 -1
  170. package/dist/vendor/codali/runtime/Runner.js +215 -171
  171. package/dist/vendor/codali/runtime/SecretRedaction.d.ts +11 -0
  172. package/dist/vendor/codali/runtime/SecretRedaction.d.ts.map +1 -0
  173. package/dist/vendor/codali/runtime/SecretRedaction.js +85 -0
  174. package/dist/vendor/codali/runtime/SessionController.d.ts +148 -0
  175. package/dist/vendor/codali/runtime/SessionController.d.ts.map +1 -0
  176. package/dist/vendor/codali/runtime/SessionController.js +1356 -0
  177. package/dist/vendor/codali/runtime/StructuralEvidence.d.ts +22 -0
  178. package/dist/vendor/codali/runtime/StructuralEvidence.d.ts.map +1 -0
  179. package/dist/vendor/codali/runtime/StructuralEvidence.js +87 -0
  180. package/dist/vendor/codali/runtime/TaskReviewContext.d.ts +34 -0
  181. package/dist/vendor/codali/runtime/TaskReviewContext.d.ts.map +1 -0
  182. package/dist/vendor/codali/runtime/TaskReviewContext.js +34 -0
  183. package/dist/vendor/codali/runtime/ValidationOutput.d.ts +5 -0
  184. package/dist/vendor/codali/runtime/ValidationOutput.d.ts.map +1 -0
  185. package/dist/vendor/codali/runtime/ValidationOutput.js +32 -0
  186. package/dist/vendor/codali/runtime/VerificationCommand.d.ts +3 -0
  187. package/dist/vendor/codali/runtime/VerificationCommand.d.ts.map +1 -0
  188. package/dist/vendor/codali/runtime/VerificationCommand.js +48 -0
  189. package/dist/vendor/codali/runtime/WorkStatusPage.d.ts +15 -0
  190. package/dist/vendor/codali/runtime/WorkStatusPage.d.ts.map +1 -0
  191. package/dist/vendor/codali/runtime/WorkStatusPage.js +58 -0
  192. package/dist/vendor/codali/runtime/WorkspaceLedger.d.ts +13 -0
  193. package/dist/vendor/codali/runtime/WorkspaceLedger.d.ts.map +1 -0
  194. package/dist/vendor/codali/runtime/WorkspaceLedger.js +145 -0
  195. package/dist/vendor/codali/runtime/WorkspaceLock.d.ts.map +1 -1
  196. package/dist/vendor/codali/runtime/WorkspaceLock.js +20 -17
  197. package/dist/vendor/codali/runtime/WorkspaceSnapshot.d.ts +13 -0
  198. package/dist/vendor/codali/runtime/WorkspaceSnapshot.d.ts.map +1 -0
  199. package/dist/vendor/codali/runtime/WorkspaceSnapshot.js +88 -0
  200. package/dist/vendor/codali/session/AtomicState.d.ts +13 -0
  201. package/dist/vendor/codali/session/AtomicState.d.ts.map +1 -0
  202. package/dist/vendor/codali/session/AtomicState.js +109 -0
  203. package/dist/vendor/codali/session/SessionStoragePath.d.ts +15 -0
  204. package/dist/vendor/codali/session/SessionStoragePath.d.ts.map +1 -0
  205. package/dist/vendor/codali/session/SessionStoragePath.js +89 -0
  206. package/dist/vendor/codali/session/SessionStore.d.ts +9 -0
  207. package/dist/vendor/codali/session/SessionStore.d.ts.map +1 -1
  208. package/dist/vendor/codali/session/SessionStore.js +181 -47
  209. package/dist/vendor/codali/session/WorkState.d.ts +23 -0
  210. package/dist/vendor/codali/session/WorkState.d.ts.map +1 -0
  211. package/dist/vendor/codali/session/WorkState.js +367 -0
  212. package/dist/vendor/codali/session/WorkTypes.d.ts +94 -0
  213. package/dist/vendor/codali/session/WorkTypes.d.ts.map +1 -0
  214. package/dist/vendor/codali/session/WorkTypes.js +1 -0
  215. package/dist/vendor/codali/tools/ToolRegistry.d.ts +2 -0
  216. package/dist/vendor/codali/tools/ToolRegistry.d.ts.map +1 -1
  217. package/dist/vendor/codali/tools/ToolRegistry.js +12 -2
  218. package/dist/vendor/codali/tools/ToolTypes.d.ts +16 -0
  219. package/dist/vendor/codali/tools/ToolTypes.d.ts.map +1 -1
  220. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts +2 -0
  221. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts.map +1 -1
  222. package/dist/vendor/codali/tools/docdex/DocdexTools.js +17 -2
  223. package/dist/vendor/codali/tools/filesystem/FileTools.d.ts.map +1 -1
  224. package/dist/vendor/codali/tools/filesystem/FileTools.js +30 -10
  225. package/dist/vendor/codali/tools/shell/AsyncProcess.d.ts +16 -0
  226. package/dist/vendor/codali/tools/shell/AsyncProcess.d.ts.map +1 -0
  227. package/dist/vendor/codali/tools/shell/AsyncProcess.js +94 -0
  228. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.d.ts +13 -0
  229. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.d.ts.map +1 -0
  230. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.js +130 -0
  231. package/dist/vendor/codali/tools/shell/HostToolchain.d.ts +19 -0
  232. package/dist/vendor/codali/tools/shell/HostToolchain.d.ts.map +1 -0
  233. package/dist/vendor/codali/tools/shell/HostToolchain.js +264 -0
  234. package/dist/vendor/codali/tools/shell/IsolatedExecutor.d.ts +15 -0
  235. package/dist/vendor/codali/tools/shell/IsolatedExecutor.d.ts.map +1 -0
  236. package/dist/vendor/codali/tools/shell/IsolatedExecutor.js +134 -0
  237. package/dist/vendor/codali/tools/shell/ShellTool.d.ts.map +1 -1
  238. package/dist/vendor/codali/tools/shell/ShellTool.js +9 -29
  239. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.d.ts +3 -0
  240. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.d.ts.map +1 -0
  241. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.js +30 -0
  242. package/package.json +31 -29
  243. package/scripts/backend-http-drain.mjs +152 -0
  244. package/scripts/media_gpu_lock.py +238 -0
  245. package/scripts/stable-audio-3-openai-server.py +45 -14
  246. package/scripts/stable-diffusion-cpp-openai-server.py +34 -4
  247. package/scripts/stable-diffusion-cpp-webm-duration.patch +22 -0
  248. package/scripts/wan22-openai-server.py +97 -18
@@ -10,6 +10,7 @@ import ipaddress
10
10
  import json
11
11
  import logging
12
12
  import math
13
+ import re
13
14
  import secrets
14
15
  import signal
15
16
  import threading
@@ -22,6 +23,8 @@ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
22
23
  from socketserver import TCPServer
23
24
  from typing import Any
24
25
 
26
+ from media_gpu_lock import MediaGpuError, MediaGpuLease, media_gpu_health, media_gpu_slot
27
+
25
28
 
26
29
  DEFAULT_HOST = "127.0.0.1"
27
30
  DEFAULT_PORT = 11448
@@ -103,7 +106,7 @@ class ServerState:
103
106
 
104
107
 
105
108
  class VideoHttpServer(ThreadingHTTPServer):
106
- daemon_threads = True
109
+ daemon_threads = False
107
110
  request_queue_size = 8
108
111
 
109
112
  def server_bind(self) -> None:
@@ -411,17 +414,20 @@ def _native_request(request: dict[str, Any]) -> dict[str, Any]:
411
414
  }
412
415
 
413
416
 
414
- def _cancel_job(state: ServerState, job_id: str) -> None:
417
+ def _cancel_job(state: ServerState, job_id: str) -> bool:
415
418
  try:
416
- _bounded_json_request(
419
+ status, job = _bounded_json_request(
417
420
  f"{state.upstream_base_url}/sdcpp/v1/jobs/{urllib.parse.quote(job_id, safe='')}/cancel",
418
421
  method="POST",
419
422
  timeout=state.request_timeout_seconds,
420
423
  max_bytes=65_536,
421
424
  payload={},
422
425
  )
426
+ return status == 200 and job.get("id") == job_id and job.get("status") in (
427
+ "completed", "failed", "cancelled"
428
+ )
423
429
  except UpstreamError:
424
- pass
430
+ return False
425
431
 
426
432
 
427
433
  def _set_active_job(state: ServerState, job_id: str) -> None:
@@ -435,8 +441,39 @@ def _clear_active_job(state: ServerState, job_id: str) -> None:
435
441
  state.active_job_id = None
436
442
 
437
443
 
438
- def _generate_video(state: ServerState, request: dict[str, Any]) -> dict[str, Any]:
444
+ def _wait_for_native_job_end(state: ServerState, job_id: str) -> None:
445
+ """Keep the GPU lease until a running, non-cancellable native job ends."""
446
+ url = f"{state.upstream_base_url}/sdcpp/v1/jobs/{urllib.parse.quote(job_id, safe='')}"
447
+ max_bytes = math.ceil(state.max_output_bytes / 3) * 4 + 65_536
448
+ logged_wait = False
449
+ while True:
450
+ try:
451
+ status, job = _bounded_json_request(
452
+ url, method="GET", timeout=state.request_timeout_seconds,
453
+ max_bytes=max_bytes,
454
+ )
455
+ if (
456
+ status == 200 and job.get("id") == job_id
457
+ and job.get("status") in ("completed", "failed", "cancelled")
458
+ ):
459
+ return
460
+ except UpstreamError:
461
+ # A lost HTTP connection does not prove GPU inference has stopped.
462
+ pass
463
+ if not logged_wait:
464
+ logging.warning("waiting for native video completion before releasing media GPU")
465
+ logged_wait = True
466
+ time.sleep(max(0.1, state.poll_interval_seconds))
467
+
468
+
469
+ def _generate_video(state: ServerState, request: dict[str, Any], cancelled: threading.Event | None = None) -> dict[str, Any]:
470
+ with media_gpu_slot("video", cancelled=cancelled, shutdown=state.shutdown_requested) as lease:
471
+ return _generate_video_locked(state, request, lease)
472
+
473
+
474
+ def _generate_video_locked(state: ServerState, request: dict[str, Any], lease: MediaGpuLease) -> dict[str, Any]:
439
475
  max_json_bytes = math.ceil(state.max_output_bytes / 3) * 4 + 65_536
476
+ lease.mark_uncertain("video_submission_pending")
440
477
  status, submission = _bounded_json_request(
441
478
  f"{state.upstream_base_url}/sdcpp/v1/vid_gen",
442
479
  method="POST",
@@ -445,6 +482,7 @@ def _generate_video(state: ServerState, request: dict[str, Any]) -> dict[str, An
445
482
  payload=_native_request(request),
446
483
  )
447
484
  if status == 429:
485
+ lease.confirm_finished()
448
486
  raise ApiError(
449
487
  429,
450
488
  "the local video generator queue is full",
@@ -452,18 +490,23 @@ def _generate_video(state: ServerState, request: dict[str, Any]) -> dict[str, An
452
490
  code="upstream_queue_saturated",
453
491
  )
454
492
  if status != 202:
493
+ lease.confirm_finished()
455
494
  raise UpstreamError(f"stable-diffusion.cpp rejected video submission ({status})")
456
495
  job_id = submission.get("id")
457
496
  poll_url = submission.get("poll_url")
458
- expected_poll_url = f"/sdcpp/v1/jobs/{job_id}" if isinstance(job_id, str) else None
497
+ valid_job_id = isinstance(job_id, str) and re.fullmatch(r"[A-Za-z0-9_-]{1,256}", job_id) is not None
498
+ expected_poll_url = f"/sdcpp/v1/jobs/{job_id}" if valid_job_id else None
499
+ if valid_job_id:
500
+ lease.record_native_job(job_id)
459
501
  if (
460
- not isinstance(job_id, str)
461
- or not job_id
502
+ not valid_job_id
462
503
  or poll_url != expected_poll_url
463
504
  or submission.get("kind") != "vid_gen"
464
505
  ):
465
- if isinstance(job_id, str) and job_id:
466
- _cancel_job(state, job_id)
506
+ if valid_job_id:
507
+ if not _cancel_job(state, job_id):
508
+ _wait_for_native_job_end(state, job_id)
509
+ lease.confirm_finished()
467
510
  raise UpstreamError("stable-diffusion.cpp returned an invalid video job")
468
511
 
469
512
  _set_active_job(state, job_id)
@@ -478,20 +521,25 @@ def _generate_video(state: ServerState, request: dict[str, Any]) -> dict[str, An
478
521
  )
479
522
  if status != 200:
480
523
  raise UpstreamError(f"stable-diffusion.cpp video poll failed ({status})")
524
+ if job.get("id") != job_id:
525
+ raise UpstreamError("stable-diffusion.cpp returned another video job")
481
526
  job_status = job.get("status")
482
527
  if job_status in ("queued", "generating"):
483
528
  state.shutdown_requested.wait(state.poll_interval_seconds)
484
529
  continue
485
530
  if job_status == "failed":
531
+ lease.confirm_finished()
486
532
  error = job.get("error")
487
533
  code = error.get("code") if isinstance(error, dict) else None
488
534
  raise UpstreamError(
489
535
  f"stable-diffusion.cpp video generation failed ({code or 'generation_failed'})"
490
536
  )
491
537
  if job_status == "cancelled":
538
+ lease.confirm_finished()
492
539
  raise UpstreamError("stable-diffusion.cpp video generation was cancelled")
493
540
  if job_status != "completed" or job.get("kind") != "vid_gen":
494
541
  raise UpstreamError("stable-diffusion.cpp returned an invalid video job status")
542
+ lease.confirm_finished()
495
543
  result = job.get("result")
496
544
  if not isinstance(result, dict):
497
545
  raise UpstreamError("stable-diffusion.cpp completed without a video result")
@@ -510,7 +558,9 @@ def _generate_video(state: ServerState, request: dict[str, Any]) -> dict[str, An
510
558
  code="generation_timeout",
511
559
  )
512
560
  except Exception:
513
- _cancel_job(state, job_id)
561
+ if not _cancel_job(state, job_id):
562
+ _wait_for_native_job_end(state, job_id)
563
+ lease.confirm_finished()
514
564
  raise
515
565
  finally:
516
566
  _clear_active_job(state, job_id)
@@ -600,6 +650,10 @@ def _handler_for(state: ServerState) -> type[BaseHTTPRequestHandler]:
600
650
 
601
651
  def do_GET(self) -> None:
602
652
  if self.path == "/healthz":
653
+ gpu = media_gpu_health()
654
+ if gpu not in ("ready", "busy"):
655
+ self._send_json(503, {"status": "unhealthy", "model": state.model_id, "media_gpu": gpu})
656
+ return
603
657
  try:
604
658
  _check_upstream_ready(state)
605
659
  except UpstreamError:
@@ -614,6 +668,7 @@ def _handler_for(state: ServerState) -> type[BaseHTTPRequestHandler]:
614
668
  "status": "ok",
615
669
  "model": state.model_id,
616
670
  "upstream": "stable-diffusion.cpp",
671
+ "media_gpu": gpu,
617
672
  },
618
673
  )
619
674
  return
@@ -694,9 +749,31 @@ def _handler_for(state: ServerState) -> type[BaseHTTPRequestHandler]:
694
749
  )
695
750
  return
696
751
  started_at = time.monotonic()
697
- try:
698
- native_result = _generate_video(state, parsed)
699
- output = _validate_result(native_result, parsed, state)
752
+ completed = threading.Event()
753
+ cancelled = threading.Event()
754
+ outcome: dict[str, Any] = {}
755
+
756
+ def run_generation() -> None:
757
+ try:
758
+ native_result = _generate_video(state, parsed, cancelled)
759
+ outcome["output"] = _validate_result(native_result, parsed, state)
760
+ except BaseException as error:
761
+ outcome["error"] = error
762
+ finally:
763
+ # A response deadline does not release native GPU ownership.
764
+ state.inference_slots.release()
765
+ completed.set()
766
+
767
+ threading.Thread(target=run_generation, name="wan-video-generation", daemon=False).start()
768
+ if not completed.wait(state.inference_timeout_seconds):
769
+ # Stop a request still waiting for admission. Already-admitted
770
+ # native jobs keep their slot/lease until their state is terminal.
771
+ cancelled.set()
772
+ self._send_error(ApiError(504, "video generation timed out", error_type="server_error", code="generation_timeout"))
773
+ return
774
+ error = outcome.get("error")
775
+ if error is None:
776
+ output = outcome["output"]
700
777
  self._send_json(
701
778
  200,
702
779
  {
@@ -711,9 +788,13 @@ def _handler_for(state: ServerState) -> type[BaseHTTPRequestHandler]:
711
788
  output["fps"],
712
789
  int((time.monotonic() - started_at) * 1000),
713
790
  )
714
- except ApiError as error:
791
+ elif isinstance(error, ApiError):
715
792
  self._send_error(error)
716
- except UpstreamError as error:
793
+ elif isinstance(error, MediaGpuError):
794
+ self._send_error(
795
+ ApiError(error.status, str(error), error_type="server_error", code=error.code)
796
+ )
797
+ else:
717
798
  logging.error("generation failed reason=%s", str(error))
718
799
  self._send_error(
719
800
  ApiError(
@@ -723,8 +804,6 @@ def _handler_for(state: ServerState) -> type[BaseHTTPRequestHandler]:
723
804
  code="upstream_generation_failed",
724
805
  )
725
806
  )
726
- finally:
727
- state.inference_slots.release()
728
807
 
729
808
  return Handler
730
809