@mcoda/mswarm 0.1.133 → 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 (250) hide show
  1. package/README.md +44 -0
  2. package/dist/codali-executor.d.ts +66 -1
  3. package/dist/codali-executor.d.ts.map +1 -1
  4. package/dist/codali-executor.js +83 -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 +25 -1
  14. package/dist/runtime.d.ts.map +1 -1
  15. package/dist/runtime.js +220 -20
  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 +16 -4
  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/gateway/LocalGatewayTaskRunner.d.ts.map +1 -1
  124. package/dist/vendor/codali/gateway/LocalGatewayTaskRunner.js +13 -1
  125. package/dist/vendor/codali/index.d.ts +23 -0
  126. package/dist/vendor/codali/index.d.ts.map +1 -1
  127. package/dist/vendor/codali/index.js +12 -0
  128. package/dist/vendor/codali/permissions/PermissionGate.d.ts +44 -0
  129. package/dist/vendor/codali/permissions/PermissionGate.d.ts.map +1 -0
  130. package/dist/vendor/codali/permissions/PermissionGate.js +97 -0
  131. package/dist/vendor/codali/providers/ConfiguredEmbeddings.d.ts +43 -0
  132. package/dist/vendor/codali/providers/ConfiguredEmbeddings.d.ts.map +1 -0
  133. package/dist/vendor/codali/providers/ConfiguredEmbeddings.js +87 -0
  134. package/dist/vendor/codali/providers/ConfiguredModelScope.d.ts +69 -0
  135. package/dist/vendor/codali/providers/ConfiguredModelScope.d.ts.map +1 -0
  136. package/dist/vendor/codali/providers/ConfiguredModelScope.js +113 -0
  137. package/dist/vendor/codali/providers/ConfiguredProvider.d.ts +79 -0
  138. package/dist/vendor/codali/providers/ConfiguredProvider.d.ts.map +1 -0
  139. package/dist/vendor/codali/providers/ConfiguredProvider.js +238 -0
  140. package/dist/vendor/codali/providers/ModelServiceError.d.ts +10 -0
  141. package/dist/vendor/codali/providers/ModelServiceError.d.ts.map +1 -0
  142. package/dist/vendor/codali/providers/ModelServiceError.js +45 -0
  143. package/dist/vendor/codali/providers/MswarmWorkerProvider.d.ts.map +1 -1
  144. package/dist/vendor/codali/providers/MswarmWorkerProvider.js +4 -0
  145. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.d.ts.map +1 -1
  146. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.js +134 -52
  147. package/dist/vendor/codali/providers/ProviderTypes.d.ts +14 -0
  148. package/dist/vendor/codali/providers/ProviderTypes.d.ts.map +1 -1
  149. package/dist/vendor/codali/runtime/CodaliJobRuntime.d.ts +6 -0
  150. package/dist/vendor/codali/runtime/CodaliJobRuntime.d.ts.map +1 -1
  151. package/dist/vendor/codali/runtime/CodaliJobRuntime.js +36 -1
  152. package/dist/vendor/codali/runtime/CodaliRuntime.d.ts +30 -0
  153. package/dist/vendor/codali/runtime/CodaliRuntime.d.ts.map +1 -1
  154. package/dist/vendor/codali/runtime/CodaliRuntime.js +71 -1
  155. package/dist/vendor/codali/runtime/CompletionReport.d.ts +5 -0
  156. package/dist/vendor/codali/runtime/CompletionReport.d.ts.map +1 -0
  157. package/dist/vendor/codali/runtime/CompletionReport.js +12 -0
  158. package/dist/vendor/codali/runtime/ProgressTracker.d.ts +17 -0
  159. package/dist/vendor/codali/runtime/ProgressTracker.d.ts.map +1 -0
  160. package/dist/vendor/codali/runtime/ProgressTracker.js +27 -0
  161. package/dist/vendor/codali/runtime/RequestedTestEvidence.d.ts +12 -0
  162. package/dist/vendor/codali/runtime/RequestedTestEvidence.d.ts.map +1 -0
  163. package/dist/vendor/codali/runtime/RequestedTestEvidence.js +16 -0
  164. package/dist/vendor/codali/runtime/RequiredRetrieval.d.ts +13 -0
  165. package/dist/vendor/codali/runtime/RequiredRetrieval.d.ts.map +1 -0
  166. package/dist/vendor/codali/runtime/RequiredRetrieval.js +25 -0
  167. package/dist/vendor/codali/runtime/ReviewSource.d.ts +6 -0
  168. package/dist/vendor/codali/runtime/ReviewSource.d.ts.map +1 -0
  169. package/dist/vendor/codali/runtime/ReviewSource.js +38 -0
  170. package/dist/vendor/codali/runtime/Runner.d.ts +13 -0
  171. package/dist/vendor/codali/runtime/Runner.d.ts.map +1 -1
  172. package/dist/vendor/codali/runtime/Runner.js +220 -158
  173. package/dist/vendor/codali/runtime/SecretRedaction.d.ts +11 -0
  174. package/dist/vendor/codali/runtime/SecretRedaction.d.ts.map +1 -0
  175. package/dist/vendor/codali/runtime/SecretRedaction.js +85 -0
  176. package/dist/vendor/codali/runtime/SessionController.d.ts +148 -0
  177. package/dist/vendor/codali/runtime/SessionController.d.ts.map +1 -0
  178. package/dist/vendor/codali/runtime/SessionController.js +1356 -0
  179. package/dist/vendor/codali/runtime/StructuralEvidence.d.ts +22 -0
  180. package/dist/vendor/codali/runtime/StructuralEvidence.d.ts.map +1 -0
  181. package/dist/vendor/codali/runtime/StructuralEvidence.js +87 -0
  182. package/dist/vendor/codali/runtime/TaskReviewContext.d.ts +34 -0
  183. package/dist/vendor/codali/runtime/TaskReviewContext.d.ts.map +1 -0
  184. package/dist/vendor/codali/runtime/TaskReviewContext.js +34 -0
  185. package/dist/vendor/codali/runtime/ValidationOutput.d.ts +5 -0
  186. package/dist/vendor/codali/runtime/ValidationOutput.d.ts.map +1 -0
  187. package/dist/vendor/codali/runtime/ValidationOutput.js +32 -0
  188. package/dist/vendor/codali/runtime/VerificationCommand.d.ts +3 -0
  189. package/dist/vendor/codali/runtime/VerificationCommand.d.ts.map +1 -0
  190. package/dist/vendor/codali/runtime/VerificationCommand.js +48 -0
  191. package/dist/vendor/codali/runtime/WorkStatusPage.d.ts +15 -0
  192. package/dist/vendor/codali/runtime/WorkStatusPage.d.ts.map +1 -0
  193. package/dist/vendor/codali/runtime/WorkStatusPage.js +58 -0
  194. package/dist/vendor/codali/runtime/WorkspaceLedger.d.ts +13 -0
  195. package/dist/vendor/codali/runtime/WorkspaceLedger.d.ts.map +1 -0
  196. package/dist/vendor/codali/runtime/WorkspaceLedger.js +145 -0
  197. package/dist/vendor/codali/runtime/WorkspaceLock.d.ts.map +1 -1
  198. package/dist/vendor/codali/runtime/WorkspaceLock.js +20 -17
  199. package/dist/vendor/codali/runtime/WorkspaceSnapshot.d.ts +13 -0
  200. package/dist/vendor/codali/runtime/WorkspaceSnapshot.d.ts.map +1 -0
  201. package/dist/vendor/codali/runtime/WorkspaceSnapshot.js +88 -0
  202. package/dist/vendor/codali/session/AtomicState.d.ts +13 -0
  203. package/dist/vendor/codali/session/AtomicState.d.ts.map +1 -0
  204. package/dist/vendor/codali/session/AtomicState.js +109 -0
  205. package/dist/vendor/codali/session/SessionStoragePath.d.ts +15 -0
  206. package/dist/vendor/codali/session/SessionStoragePath.d.ts.map +1 -0
  207. package/dist/vendor/codali/session/SessionStoragePath.js +89 -0
  208. package/dist/vendor/codali/session/SessionStore.d.ts +9 -0
  209. package/dist/vendor/codali/session/SessionStore.d.ts.map +1 -1
  210. package/dist/vendor/codali/session/SessionStore.js +181 -47
  211. package/dist/vendor/codali/session/WorkState.d.ts +23 -0
  212. package/dist/vendor/codali/session/WorkState.d.ts.map +1 -0
  213. package/dist/vendor/codali/session/WorkState.js +367 -0
  214. package/dist/vendor/codali/session/WorkTypes.d.ts +94 -0
  215. package/dist/vendor/codali/session/WorkTypes.d.ts.map +1 -0
  216. package/dist/vendor/codali/session/WorkTypes.js +1 -0
  217. package/dist/vendor/codali/tools/ToolRegistry.d.ts +2 -0
  218. package/dist/vendor/codali/tools/ToolRegistry.d.ts.map +1 -1
  219. package/dist/vendor/codali/tools/ToolRegistry.js +12 -2
  220. package/dist/vendor/codali/tools/ToolTypes.d.ts +16 -0
  221. package/dist/vendor/codali/tools/ToolTypes.d.ts.map +1 -1
  222. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts +2 -0
  223. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts.map +1 -1
  224. package/dist/vendor/codali/tools/docdex/DocdexTools.js +17 -2
  225. package/dist/vendor/codali/tools/filesystem/FileTools.d.ts.map +1 -1
  226. package/dist/vendor/codali/tools/filesystem/FileTools.js +30 -10
  227. package/dist/vendor/codali/tools/shell/AsyncProcess.d.ts +16 -0
  228. package/dist/vendor/codali/tools/shell/AsyncProcess.d.ts.map +1 -0
  229. package/dist/vendor/codali/tools/shell/AsyncProcess.js +94 -0
  230. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.d.ts +13 -0
  231. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.d.ts.map +1 -0
  232. package/dist/vendor/codali/tools/shell/DarwinRuntimeLibraries.js +130 -0
  233. package/dist/vendor/codali/tools/shell/HostToolchain.d.ts +19 -0
  234. package/dist/vendor/codali/tools/shell/HostToolchain.d.ts.map +1 -0
  235. package/dist/vendor/codali/tools/shell/HostToolchain.js +264 -0
  236. package/dist/vendor/codali/tools/shell/IsolatedExecutor.d.ts +15 -0
  237. package/dist/vendor/codali/tools/shell/IsolatedExecutor.d.ts.map +1 -0
  238. package/dist/vendor/codali/tools/shell/IsolatedExecutor.js +134 -0
  239. package/dist/vendor/codali/tools/shell/ShellTool.d.ts.map +1 -1
  240. package/dist/vendor/codali/tools/shell/ShellTool.js +9 -29
  241. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.d.ts +3 -0
  242. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.d.ts.map +1 -0
  243. package/dist/vendor/codali/tools/shell/ShellWorkingDirectory.js +30 -0
  244. package/package.json +31 -29
  245. package/scripts/backend-http-drain.mjs +152 -0
  246. package/scripts/media_gpu_lock.py +238 -0
  247. package/scripts/stable-audio-3-openai-server.py +45 -14
  248. package/scripts/stable-diffusion-cpp-openai-server.py +34 -4
  249. package/scripts/stable-diffusion-cpp-webm-duration.patch +22 -0
  250. package/scripts/wan22-openai-server.py +97 -18
package/dist/runtime.js CHANGED
@@ -5,9 +5,10 @@ import { spawn } from "node:child_process";
5
5
  import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
6
6
  import { isIP } from "node:net";
7
7
  import { Agent, fetch as undiciFetch } from "undici";
8
+ import { nativeReasoningRequest } from "./native-reasoning.js";
8
9
  import { GlobalRepository } from "@mcoda/db";
9
10
  import { MswarmCodaliExecutor } from "./codali-executor.js";
10
- import { GENERATIVE_OPERATION_DEFAULT_PATHS, GENERATIVE_REQUEST_PARAMETER_ALLOWLISTS, MSWARM_CAPABILITY_SCHEMA_VERSION, CryptoHelper, assertMswarmSafeRelativePath, validateMswarmArchiveEntry, buildMswarmCapabilityNames, buildMswarmPrivateCapabilityCatalogEntry, buildMswarmLocalArtifactUri, buildMswarmSandboxProfile, defaultMswarmArtifactAccessPolicy, defaultMswarmArtifactRetentionPolicy, normalizeGenerativeModalities, normalizeSelfHostedGenerativeOperation, projectMswarmPublicCapabilities, validateMswarmGenericJobRequest } from "@mcoda/shared";
11
+ import { GENERATIVE_OPERATION_DEFAULT_PATHS, GENERATIVE_REQUEST_PARAMETER_ALLOWLISTS, validateEmbeddingRequest, validateEmbeddingResponse, validateEmbeddingPreprocessing, MSWARM_CAPABILITY_SCHEMA_VERSION, CryptoHelper, assertMswarmSafeRelativePath, validateMswarmArchiveEntry, buildMswarmCapabilityNames, buildMswarmPrivateCapabilityCatalogEntry, buildMswarmLocalArtifactUri, buildMswarmSandboxProfile, defaultMswarmArtifactAccessPolicy, defaultMswarmArtifactRetentionPolicy, normalizeGenerativeModalities, normalizeSelfHostedGenerativeOperation, projectMswarmPublicCapabilities, validateMswarmGenericJobRequest } from "@mcoda/shared";
11
12
  const REGISTRATION_POLL_INTERVAL_MS = 5000;
12
13
  const REGISTRATION_POLL_TIMEOUT_MS = 30 * 60000;
13
14
  /**
@@ -202,12 +203,16 @@ function resolvePersistentNodePath(nodePath) {
202
203
  const DEFAULT_EXPOSE_ALL_MODELS = true;
203
204
  const LOCAL_OPENAI_COMPATIBLE_ADAPTERS = new Set([
204
205
  "openai-compatible-local",
206
+ "strata-local",
205
207
  "vllm-local",
206
208
  "llama-cpp-local",
207
209
  "llamacpp-local"
208
210
  ]);
209
211
  const SECRET_LOCAL_RUNNER_HEADER_KEYS = new Set(["authorization", "proxy-authorization", "x-api-key", "api-key"]);
210
212
  const RESERVED_LOCAL_RUNNER_EXTRA_BODY_KEYS = new Set([
213
+ "input",
214
+ "dimensions",
215
+ "encoding_format",
211
216
  "model",
212
217
  "messages",
213
218
  "prompt",
@@ -229,6 +234,7 @@ const RESERVED_LOCAL_RUNNER_EXTRA_BODY_KEYS = new Set([
229
234
  "temperature"
230
235
  ]);
231
236
  const REQUIRED_GENERATIVE_OPERATION_REQUEST_PARAMETERS = {
237
+ embeddings: ["model", "input", "encoding_format"],
232
238
  "chat.completions": ["model", "messages"],
233
239
  "images.generations": ["model", "prompt", "response_format"],
234
240
  "audio.generations": ["model", "prompt", "response_format"],
@@ -244,6 +250,7 @@ const DEFAULT_VIDEO_GENERATIVE_OUTPUT_BYTES = 256 * 1024 * 1024;
244
250
  const GENERATIVE_RESPONSE_JSON_OVERHEAD_BYTES = 64 * 1024;
245
251
  const LOCAL_RUNNER_KIND_ALIASES = {
246
252
  vllm: "vllm",
253
+ strata: "strata",
247
254
  "llama-cpp": "llama-cpp",
248
255
  "llama.cpp": "llama-cpp",
249
256
  llamacpp: "llama-cpp",
@@ -328,7 +335,7 @@ function isRecord(value) {
328
335
  }
329
336
  export function normalizeSelfHostedGenerativeOperationName(value) {
330
337
  const normalized = optionalText(value);
331
- return normalized === "chat.completions" ||
338
+ return normalized === "embeddings" || normalized === "chat.completions" ||
332
339
  normalized === "images.generations" ||
333
340
  normalized === "audio.generations" ||
334
341
  normalized === "videos.generations"
@@ -369,7 +376,7 @@ function normalizeGenerativeOperationDescriptor(value) {
369
376
  ]));
370
377
  const responseFormats = normalized.responseFormats?.length
371
378
  ? normalized.responseFormats
372
- : operation === "chat.completions"
379
+ : operation === "embeddings" ? ["float"] : operation === "chat.completions"
373
380
  ? undefined
374
381
  : operation === "images.generations"
375
382
  ? ["b64_json"]
@@ -420,6 +427,8 @@ function normalizeGenerativeOperations(value) {
420
427
  function inferGenerativeModalities(operations, direction) {
421
428
  const modalities = new Set();
422
429
  for (const descriptor of operations) {
430
+ if (direction === "output" && descriptor.operation === "embeddings")
431
+ modalities.add("embedding");
423
432
  if (direction === "input" || descriptor.operation === "chat.completions") {
424
433
  modalities.add("text");
425
434
  }
@@ -438,6 +447,10 @@ function inferGenerativeModalities(operations, direction) {
438
447
  function generativeOperationCatalogInput(descriptor) {
439
448
  const limits = descriptor.limits
440
449
  ? {
450
+ ...(descriptor.limits.maxInputItems !== undefined ? { max_input_items: descriptor.limits.maxInputItems } : {}),
451
+ ...(descriptor.limits.maxInputChars !== undefined ? { max_input_chars: descriptor.limits.maxInputChars } : {}),
452
+ ...(descriptor.limits.maxTotalInputChars !== undefined ? { max_total_input_chars: descriptor.limits.maxTotalInputChars } : {}),
453
+ ...(descriptor.limits.embeddingDimensions !== undefined ? { embedding_dimensions: descriptor.limits.embeddingDimensions } : {}),
441
454
  ...(descriptor.limits.maxRequestBytes !== undefined
442
455
  ? { max_request_bytes: descriptor.limits.maxRequestBytes }
443
456
  : {}),
@@ -526,6 +539,8 @@ function defaultLocalRunnerKindForAdapter(adapter) {
526
539
  const lookupKey = normalizeLookupKey(normalized);
527
540
  if (lookupKey === "vllm-local")
528
541
  return "vllm";
542
+ if (lookupKey === "strata-local")
543
+ return "strata";
529
544
  if (lookupKey === "llama-cpp-local" || lookupKey === "llamacpp-local")
530
545
  return "llama-cpp";
531
546
  return undefined;
@@ -617,6 +632,7 @@ function normalizeMcodaLocalRunnerConfig(adapter, config) {
617
632
  inputModalities: normalizeGenerativeModalities(merged.inputModalities ?? merged.input_modalities),
618
633
  outputModalities: normalizeGenerativeModalities(merged.outputModalities ?? merged.output_modalities),
619
634
  operations: normalizeGenerativeOperations(merged.operations),
635
+ embedding: merged.embedding === undefined || merged.embedding === null ? undefined : validateEmbeddingPreprocessing(merged.embedding),
620
636
  publicModelId: readConfigString(merged, ["publicModelId", "public_model_id"])
621
637
  };
622
638
  }
@@ -1228,12 +1244,12 @@ export function agentRunsOnThisNode(agent) {
1228
1244
  return false;
1229
1245
  }
1230
1246
  }
1231
- function isAgentExposed(agentSlug, defaultModel, bestUsage, config) {
1247
+ function isAgentExposed(agentSlug, defaultModel, bestUsage, config, supportsEmbeddings = false) {
1232
1248
  const identities = [agentSlug, defaultModel].filter((value) => Boolean(value));
1233
1249
  if (identities.some((identity) => config.modelBlocklist.includes(identity))) {
1234
1250
  return false;
1235
1251
  }
1236
- if (isEmbeddingUsage(bestUsage) || identities.some((identity) => isEmbeddingModel(identity))) {
1252
+ if (!supportsEmbeddings && (isEmbeddingUsage(bestUsage) || identities.some((identity) => isEmbeddingModel(identity)))) {
1237
1253
  return false;
1238
1254
  }
1239
1255
  if (config.modelAllowlist.length > 0) {
@@ -1500,6 +1516,8 @@ Wants=network-online.target
1500
1516
  Type=simple
1501
1517
  ExecStart=${quoteSystemdValue(input.wrapperPath)}
1502
1518
  Restart=always
1519
+ TimeoutStopSec=infinity
1520
+ KillMode=mixed
1503
1521
  RestartSec=5
1504
1522
  StandardOutput=append:${input.logPath}
1505
1523
  StandardError=append:${input.errorLogPath}
@@ -2095,6 +2113,8 @@ export function mapMcodaAgentToSelfHostedModel(agent, config) {
2095
2113
  model_id: publicModelId || model,
2096
2114
  public_model_id: publicModelId,
2097
2115
  upstream_model: model,
2116
+ digest: optionalText(legacyConfig.modelDigest),
2117
+ embedding: localRunner?.embedding,
2098
2118
  base_url: localRunner?.baseUrl ?? legacyNativeBase ?? undefined,
2099
2119
  runner_kind: localRunner?.generativeRunnerKind ?? localRunner?.runnerKind ?? (legacyNativeBase ? "llama-cpp" : undefined),
2100
2120
  auth_mode: localRunner?.authMode ?? (legacyNativeBase ? normalizeLocalRunnerAuthMode(legacyConfig.authMode) : undefined),
@@ -2109,10 +2129,13 @@ export function mapMcodaAgentToSelfHostedModel(agent, config) {
2109
2129
  supports_vision: supportsVision,
2110
2130
  supports_json_schema: localRunner?.supportsJsonSchema,
2111
2131
  supports_gbnf: localRunner?.supportsGbnf,
2132
+ // Transport metadata must not change semantic model capability sets: those
2133
+ // sets participate in stable load-balanced pool identifiers on the gateway.
2134
+ native_reasoning_transport_version: localRunner?.runnerKind === "strata" ? 1 : undefined,
2112
2135
  openai_compatible: openaiCompatible,
2113
2136
  exposed: healthStatus !== "blocked" &&
2114
2137
  agentRunsOnThisNode(agent) &&
2115
- isAgentExposed(slug, defaultModel, bestUsage, config),
2138
+ isAgentExposed(slug, defaultModel, bestUsage, config, operations.some(entry => entry.operation === "embeddings")),
2116
2139
  best_usage: bestUsage,
2117
2140
  capabilities,
2118
2141
  cost_per_million: optionalNumber(agent.costPerMillion, agent.cost_per_million),
@@ -2465,6 +2488,8 @@ function mapMcodaAgentToCodaliAgent(agent, fallbackSlug) {
2465
2488
  const generativeOperations = localRunner?.operations ??
2466
2489
  [defaultGenerativeOperationDescriptor("chat.completions", localRunner ? "/chat/completions" : undefined)];
2467
2490
  return {
2491
+ modelDigest: configText(config, "modelDigest"),
2492
+ orchestrationConfigPath: configText(config, "codaliOrchestrationPath"),
2468
2493
  slug: optionalText(agent.slug) || fallbackSlug,
2469
2494
  adapter,
2470
2495
  provider: resolveCodaliProviderForAgent(agent),
@@ -2491,6 +2516,10 @@ function mapMcodaAgentToCodaliAgent(agent, fallbackSlug) {
2491
2516
  supportsJsonSchema: localRunner?.supportsJsonSchema,
2492
2517
  supportsGbnf: localRunner?.supportsGbnf,
2493
2518
  capabilities: normalizeCapabilities(agent.capabilities),
2519
+ rating: optionalNumber(agent.rating) ?? undefined,
2520
+ reasoningRating: optionalNumber(agent.reasoningRating, agent.reasoning_rating) ?? undefined,
2521
+ maxComplexity: optionalNumber(agent.maxComplexity, agent.max_complexity) ?? undefined,
2522
+ bestUsage: optionalText(agent.bestUsage) ?? optionalText(agent.best_usage) ?? undefined,
2494
2523
  contextWindow: optionalNumber(agent.contextWindow, agent.context_window) ?? undefined,
2495
2524
  maxOutputTokens: optionalNumber(agent.maxOutputTokens, agent.max_output_tokens) ?? undefined,
2496
2525
  generativeOperations,
@@ -4467,11 +4496,18 @@ export class MswarmSelfHostedNodeClient {
4467
4496
  }
4468
4497
  }
4469
4498
  export class SelfHostedNodeRuntime {
4499
+ get isDraining() {
4500
+ return this.admissionClosed || this.config.drainMode === true;
4501
+ }
4502
+ beginDrain() {
4503
+ this.admissionClosed = true;
4504
+ }
4470
4505
  constructor(config, deps) {
4471
4506
  this.activeChatJobs = 0;
4472
4507
  this.activeRequestIds = new Set();
4473
4508
  this.lastModels = [];
4474
4509
  this.loadRuntimeToken = null;
4510
+ this.loadReportQueue = Promise.resolve();
4475
4511
  this.fastLoadUnsupported = false;
4476
4512
  this.nativeActiveJobs = 0;
4477
4513
  this.nativeProbeKeys = new Map();
@@ -4484,6 +4520,9 @@ export class SelfHostedNodeRuntime {
4484
4520
  this.latencySamplesMs = [];
4485
4521
  this.recentFailures = [];
4486
4522
  this.lifecyclePollingDisabled = false;
4523
+ this.admissionClosed = false;
4524
+ this.admittedJobs = 0;
4525
+ this.manualRelayOperations = 0;
4487
4526
  /**
4488
4527
  * The capability snapshot a heartbeat carries, without making the heartbeat
4489
4528
  * wait for it.
@@ -4677,7 +4716,7 @@ export class SelfHostedNodeRuntime {
4677
4716
  return Math.round(total / this.latencySamplesMs.length);
4678
4717
  }
4679
4718
  buildLoadTelemetry(input) {
4680
- const drainMode = this.config.drainMode === true;
4719
+ const drainMode = this.isDraining;
4681
4720
  const llmMaxConcurrency = Math.max(1, Math.floor(this.config.maxConcurrentLlmJobs || this.config.maxConcurrentJobs || 1));
4682
4721
  const genericMaxConcurrency = Math.max(1, Math.floor(this.config.genericJobMaxConcurrency || 1));
4683
4722
  const maxConcurrency = Math.max(1, Math.floor(this.config.maxConcurrentJobs || 1), llmMaxConcurrency, this.config.genericJobsEnabled ? genericMaxConcurrency : 1);
@@ -5034,7 +5073,7 @@ export class SelfHostedNodeRuntime {
5034
5073
  generic_jobs_enabled: this.config.genericJobsEnabled,
5035
5074
  generic_job_timeout_ms: this.config.genericJobTimeoutMs,
5036
5075
  generic_job_max_concurrency: this.config.genericJobMaxConcurrency,
5037
- drain_mode: this.config.drainMode === true,
5076
+ drain_mode: this.isDraining,
5038
5077
  load_reporting_enabled: this.config.loadReportingEnabled !== false,
5039
5078
  hardware_telemetry_enabled: this.config.hardwareTelemetryEnabled === true,
5040
5079
  expose_all_models: this.config.exposeAllModels,
@@ -5100,6 +5139,9 @@ export class SelfHostedNodeRuntime {
5100
5139
  body.max_tokens = job.openai_request.max_tokens;
5101
5140
  if (job.openai_request.stop !== undefined)
5102
5141
  body.stop = job.openai_request.stop;
5142
+ if (job.openai_request.response_format !== undefined)
5143
+ body.response_format = job.openai_request.response_format;
5144
+ Object.assign(body, nativeReasoningRequest(job.openai_request));
5103
5145
  const url = `${baseUrl.replace(/\/+$/, "")}/chat/completions`;
5104
5146
  const response = await this.fetchImpl(url, { method: "POST", headers, body: JSON.stringify(body) });
5105
5147
  const text = await response.text();
@@ -5358,6 +5400,61 @@ export class SelfHostedNodeRuntime {
5358
5400
  body
5359
5401
  };
5360
5402
  }
5403
+ prepareEmbeddingPassthrough(job, agent) {
5404
+ if (job.policy?.expected_model_digest && agent.modelDigest !== job.policy.expected_model_digest) {
5405
+ throw new SelfHostedPreStartJobError("selected_agent_unavailable", "Embedding model revision changed after admission");
5406
+ }
5407
+ const descriptor = this.generativeOperationForAgent(agent, "embeddings");
5408
+ const baseUrl = optionalText(agent.baseUrl);
5409
+ let endpoint;
5410
+ try {
5411
+ endpoint = new URL(baseUrl || "");
5412
+ }
5413
+ catch {
5414
+ throw new SelfHostedPreStartJobError("selected_agent_unavailable", "embedding runner URL is missing or invalid");
5415
+ }
5416
+ if (!["http:", "https:"].includes(endpoint.protocol) || endpoint.username || endpoint.password || endpoint.search || endpoint.hash) {
5417
+ throw new SelfHostedPreStartJobError("selected_agent_unavailable", "embedding runner URL is invalid");
5418
+ }
5419
+ let body;
5420
+ try {
5421
+ body = validateEmbeddingRequest(job.openai_request, optionalText(agent.model) || job.openai_request.model, descriptor.limits);
5422
+ }
5423
+ catch (error) {
5424
+ throw new SelfHostedPreStartJobError("validation_failed", error instanceof Error ? error.message : "invalid embedding request");
5425
+ }
5426
+ if (Buffer.byteLength(JSON.stringify(body)) > Math.min(descriptor.limits?.maxRequestBytes || 1048576, 1048576)) {
5427
+ throw new SelfHostedPreStartJobError("validation_failed", "embedding request exceeds byte limit");
5428
+ }
5429
+ const headers = {};
5430
+ const bearer = agent.authMode === "bearer" ? optionalText(agent.apiKey)
5431
+ : agent.authMode === "dummy-bearer" ? optionalText(agent.dummyBearerToken) || "local" : undefined;
5432
+ if (bearer)
5433
+ headers.authorization = `Bearer ${bearer}`;
5434
+ for (const [key, value] of Object.entries(agent.headers ?? {}))
5435
+ if (typeof value === "string")
5436
+ headers[key.toLowerCase()] = value;
5437
+ headers["content-type"] = "application/json";
5438
+ return { descriptor, body, headers, url: `${baseUrl.replace(/\/+$/, "")}${descriptor.path}` };
5439
+ }
5440
+ async executeEmbeddingPassthrough(prepared) {
5441
+ const controller = new AbortController();
5442
+ const timeout = setTimeout(() => controller.abort(), Math.min(this.config.jobTimeoutMs, 120000));
5443
+ try {
5444
+ const response = await this.fetchImpl(prepared.url, {
5445
+ method: "POST", headers: prepared.headers, body: JSON.stringify(prepared.body), signal: controller.signal,
5446
+ });
5447
+ if (!response.ok) {
5448
+ await response.body?.cancel().catch(() => undefined);
5449
+ throw new Error(`local embeddings runner request failed with status ${response.status}`);
5450
+ }
5451
+ const raw = await readBoundedResponseText(response, Math.min(prepared.descriptor.limits?.maxOutputBytes || 16777216, 16777216), "embedding response exceeds byte limit");
5452
+ return validateEmbeddingResponse(JSON.parse(raw), prepared.body.input.length, prepared.descriptor.limits?.embeddingDimensions ?? prepared.body.dimensions, prepared.body.model);
5453
+ }
5454
+ finally {
5455
+ clearTimeout(timeout);
5456
+ }
5457
+ }
5361
5458
  async executeOpenAiGenerativePassthrough(prepared, operation) {
5362
5459
  const outputByteLimit = generativeOutputByteLimit(operation, prepared.descriptor.limits?.maxOutputBytes);
5363
5460
  const jsonResponseByteLimit = generativeJsonResponseByteLimit(outputByteLimit);
@@ -5505,6 +5602,21 @@ export class SelfHostedNodeRuntime {
5505
5602
  return codaliAgent;
5506
5603
  }
5507
5604
  async executeGenericJob(envelope, options = {}) {
5605
+ if (this.isDraining)
5606
+ throw new SelfHostedPreStartJobError("node_draining", "Node is draining; no new work was admitted.");
5607
+ return this.executePreviouslyAdmittedGenericJob(envelope, options);
5608
+ }
5609
+ /** Host scheduler only: finish work accepted before admission was closed. */
5610
+ async executePreviouslyAdmittedGenericJob(envelope, options = {}) {
5611
+ this.admittedJobs += 1;
5612
+ try {
5613
+ return await this.executeAdmittedGenericJob(envelope, options);
5614
+ }
5615
+ finally {
5616
+ this.admittedJobs -= 1;
5617
+ }
5618
+ }
5619
+ async executeAdmittedGenericJob(envelope, options) {
5508
5620
  const startedAt = Date.now();
5509
5621
  this.beginExecutionTelemetry("generic_job");
5510
5622
  const events = [];
@@ -5678,12 +5790,26 @@ export class SelfHostedNodeRuntime {
5678
5790
  }
5679
5791
  }
5680
5792
  async executeJob(job, options = {}) {
5793
+ if (this.isDraining) {
5794
+ return {
5795
+ job_id: job.job_id, request_id: job.request_id, status: "failed",
5796
+ error: { code: "node_draining", message: "Node is draining; no new work was admitted." }
5797
+ };
5798
+ }
5799
+ return this.executeAdmittedJob(job, options);
5800
+ }
5801
+ async executeAdmittedJob(job, options) {
5802
+ this.admittedJobs += 1;
5681
5803
  this.activeRequestIds.add(job.request_id);
5682
5804
  try {
5683
5805
  return await this.executeTrackedJob(job, options);
5684
5806
  }
5685
5807
  finally {
5686
5808
  this.activeRequestIds.delete(job.request_id);
5809
+ // A product often starts its next stage immediately after this result.
5810
+ // Publish the newly free native slot before the gateway delivers it.
5811
+ await this.reportLoad().catch(() => undefined);
5812
+ this.admittedJobs -= 1;
5687
5813
  }
5688
5814
  }
5689
5815
  async executeTrackedJob(job, options) {
@@ -5749,6 +5875,9 @@ export class SelfHostedNodeRuntime {
5749
5875
  throw new SelfHostedPreStartJobError("unsupported_operation", `unsupported self-hosted operation ${optionalText(job.operation) || String(job.operation)}`);
5750
5876
  }
5751
5877
  if (job.provider === "ollama") {
5878
+ if (Object.keys(nativeReasoningRequest(job.openai_request)).length) {
5879
+ throw new SelfHostedPreStartJobError("unsupported_operation", "Native reasoning options require an OpenAI-compatible runner");
5880
+ }
5752
5881
  if (operation !== "chat.completions") {
5753
5882
  throw new SelfHostedPreStartJobError("unsupported_operation", `Ollama relay jobs do not support ${operation}`);
5754
5883
  }
@@ -5822,6 +5951,17 @@ export class SelfHostedNodeRuntime {
5822
5951
  const agent = await this.resolveMcodaAgentForJob(job);
5823
5952
  selectedAgent = agent;
5824
5953
  this.generativeOperationForAgent(agent, operation);
5954
+ if (operation === "embeddings") {
5955
+ const prepared = this.prepareEmbeddingPassthrough(job, agent);
5956
+ await acknowledgeStarted(agent);
5957
+ await recordProgress({ type: "agent_selected", operation, job_id: job.job_id,
5958
+ request_id: job.request_id, agent_slug: agent.slug, adapter: agent.adapter, local_model: prepared.body.model });
5959
+ const result = await this.executeEmbeddingPassthrough(prepared);
5960
+ this.finishExecutionTelemetry({ executionClass, startedAt, ok: true });
5961
+ return { job_id: job.job_id, request_id: job.request_id, operation, status: "success",
5962
+ openai_response: { ...result, ...(agent.modelDigest ? { embedding_revision: agent.modelDigest } : {}) }, ...(result.usage ? { usage: { ...result.usage, completion_tokens: 0 } } : {}),
5963
+ ...(progressEvents.length ? { progress_events: progressEvents } : {}), timing: { local_latency_ms: Date.now() - startedAt } };
5964
+ }
5825
5965
  if (operation === "images.generations" ||
5826
5966
  operation === "audio.generations" ||
5827
5967
  operation === "videos.generations") {
@@ -5899,6 +6039,7 @@ export class SelfHostedNodeRuntime {
5899
6039
  attachedMswarmApiKey,
5900
6040
  policy: buildCodaliPolicy(job),
5901
6041
  temperature: job.openai_request.temperature,
6042
+ nativeReasoning: nativeReasoningRequest(job.openai_request),
5902
6043
  responseFormat: isRecord(job.openai_request.response_format)
5903
6044
  ? job.openai_request.response_format
5904
6045
  : null,
@@ -5976,6 +6117,7 @@ export class SelfHostedNodeRuntime {
5976
6117
  agent_slug: response.metadata.agent_slug,
5977
6118
  runtime: response.metadata.runtime,
5978
6119
  codali_run_id: response.metadata.run_id,
6120
+ orchestration: response.metadata.orchestration,
5979
6121
  tool_calls_executed: response.metadata.tool_calls_executed,
5980
6122
  called_tools: response.metadata.called_tools,
5981
6123
  dynamic_tools_considered: response.metadata.dynamic_tools_considered,
@@ -6057,14 +6199,15 @@ export class SelfHostedNodeRuntime {
6057
6199
  async refreshNativeLoad() {
6058
6200
  const runners = new Map();
6059
6201
  for (const model of this.lastModels) {
6202
+ const isStrata = model.runner_kind === "strata" || model.adapter === "strata-local";
6060
6203
  if (model.exposed === false || !model.base_url ||
6061
- (model.runner_kind !== "llama-cpp" && model.adapter !== "llama-cpp-local"))
6204
+ (!isStrata && model.runner_kind !== "llama-cpp" && model.adapter !== "llama-cpp-local"))
6062
6205
  continue;
6063
6206
  try {
6064
6207
  const url = new URL(model.base_url);
6065
6208
  if (!["127.0.0.1", "localhost", "[::1]"].includes(url.hostname))
6066
6209
  continue;
6067
- const endpoint = new URL("/slots", url).toString();
6210
+ const endpoint = new URL(isStrata ? "/v1/status" : "/slots", url).toString();
6068
6211
  const models = runners.get(endpoint) || [];
6069
6212
  models.push(model);
6070
6213
  runners.set(endpoint, models);
@@ -6089,12 +6232,30 @@ export class SelfHostedNodeRuntime {
6089
6232
  }
6090
6233
  const response = await this.fetchImpl(endpoint, { signal: AbortSignal.timeout(1500),
6091
6234
  ...(apiKey ? { headers: { authorization: `Bearer ${apiKey}` } } : {}) });
6092
- // Slot introspection is optional and may require different local credentials.
6093
- if ([401, 403, 404].includes(response.status))
6235
+ const isStrata = new URL(endpoint).pathname === "/v1/status";
6236
+ // llama.cpp slot introspection is optional. Strata status also proves the model is loaded.
6237
+ if (!isStrata && [401, 403, 404].includes(response.status))
6094
6238
  return;
6095
6239
  if (!response.ok)
6096
6240
  throw new Error("runner_load_unavailable");
6097
6241
  const slots = await response.json();
6242
+ if (isStrata) {
6243
+ const concurrency = isRecord(slots) && isRecord(slots.concurrency) ? slots.concurrency.serving : undefined;
6244
+ const inFlight = isRecord(slots) && isRecord(slots.activity) ? slots.activity.in_flight : undefined;
6245
+ if (!isRecord(slots) || slots.loaded !== true ||
6246
+ typeof concurrency !== "number" || !Number.isSafeInteger(concurrency) || concurrency < 1 ||
6247
+ typeof inFlight !== "number" || !Number.isSafeInteger(inFlight) || inFlight < 0) {
6248
+ throw new Error("runner_load_unavailable");
6249
+ }
6250
+ const processing = Math.min(concurrency, inFlight);
6251
+ active += processing;
6252
+ const capacity = { max_concurrency: concurrency, active_jobs: processing,
6253
+ queued_jobs: Math.max(0, inFlight - concurrency), free_slots: Math.max(0, concurrency - inFlight),
6254
+ pool: `runner:${createHash("sha256").update(endpoint).digest("hex").slice(0, 16)}` };
6255
+ for (const model of models)
6256
+ modelCapacity[model.model_id || model.model || model.name] = capacity;
6257
+ return;
6258
+ }
6098
6259
  if (!Array.isArray(slots))
6099
6260
  return;
6100
6261
  const processing = slots.filter((slot) => isRecord(slot) && slot.is_processing === true).length;
@@ -6114,7 +6275,14 @@ export class SelfHostedNodeRuntime {
6114
6275
  this.nativeModelCapacity = modelCapacity;
6115
6276
  this.unavailableModelIds = [...new Set(unavailable)];
6116
6277
  }
6117
- async reportLoad() {
6278
+ reportLoad() {
6279
+ // Serialize probes and writes so an older busy snapshot cannot overwrite
6280
+ // the completion snapshot when the periodic reporter is already running.
6281
+ const pending = this.loadReportQueue.then(() => this.reportLoadSnapshot());
6282
+ this.loadReportQueue = pending.catch(() => undefined);
6283
+ return pending;
6284
+ }
6285
+ async reportLoadSnapshot() {
6118
6286
  if (this.config.loadReportingEnabled === false || this.fastLoadUnsupported || !this.loadRuntimeToken)
6119
6287
  return;
6120
6288
  await this.refreshNativeLoad();
@@ -6210,7 +6378,7 @@ export class SelfHostedNodeRuntime {
6210
6378
  relay_mode: this.config.relayMode || "outbound",
6211
6379
  load_reporting_enabled: loadReportingEnabled,
6212
6380
  hardware_telemetry_enabled: this.config.hardwareTelemetryEnabled === true,
6213
- drain_mode: this.config.drainMode === true,
6381
+ drain_mode: this.isDraining,
6214
6382
  ...(lifecycleProtocolDegraded
6215
6383
  ? {
6216
6384
  lifecycle: {
@@ -6385,7 +6553,9 @@ export class SelfHostedNodeRuntime {
6385
6553
  streamEventForwardingFailed = true;
6386
6554
  }
6387
6555
  };
6388
- let result = await this.executeJob(job, {
6556
+ // A claim returned by an outstanding poll already belongs to this node,
6557
+ // including a poll that finishes after drain began. Never discard it.
6558
+ let result = await this.executeAdmittedJob(job, {
6389
6559
  attachedMswarmApiKey: claim.attachedMswarmApiKey,
6390
6560
  onStarted: async (event) => {
6391
6561
  try {
@@ -6473,11 +6643,19 @@ export class SelfHostedNodeRuntime {
6473
6643
  return { executed: true, job_id: job.job_id, status: result.status };
6474
6644
  }
6475
6645
  async pollAndExecuteJob(waitMs = DEFAULT_JOB_POLL_WAIT_MS) {
6476
- const polled = await this.pollRelayJob(waitMs);
6477
- if (!polled.claim) {
6478
- return { executed: false, ...(polled.status ? { status: polled.status } : {}) };
6646
+ if (this.isDraining)
6647
+ return { executed: false };
6648
+ this.manualRelayOperations += 1;
6649
+ try {
6650
+ const polled = await this.pollRelayJob(waitMs);
6651
+ if (!polled.claim) {
6652
+ return { executed: false, ...(polled.status ? { status: polled.status } : {}) };
6653
+ }
6654
+ return await this.executeRelayJobClaim(polled.claim);
6655
+ }
6656
+ finally {
6657
+ this.manualRelayOperations -= 1;
6479
6658
  }
6480
- return this.executeRelayJobClaim(polled.claim);
6481
6659
  }
6482
6660
  async doctor() {
6483
6661
  const checks = [];
@@ -6591,6 +6769,7 @@ export class SelfHostedNodeRuntime {
6591
6769
  const currentRelayRetryDelayMs = () => Math.max(pollRetryDelayMs(relayPollFailureStreak), pollRetryDelayMs(relayExecutionFailureStreak));
6592
6770
  const schedulePoll = (delayMs) => {
6593
6771
  if (stopped ||
6772
+ this.isDraining ||
6594
6773
  polling ||
6595
6774
  revoked ||
6596
6775
  this.lifecyclePollingDisabled ||
@@ -6612,6 +6791,7 @@ export class SelfHostedNodeRuntime {
6612
6791
  };
6613
6792
  const poll = () => {
6614
6793
  if (stopped ||
6794
+ this.isDraining ||
6615
6795
  polling ||
6616
6796
  revoked ||
6617
6797
  this.lifecyclePollingDisabled ||
@@ -6710,7 +6890,27 @@ export class SelfHostedNodeRuntime {
6710
6890
  schedule();
6711
6891
  schedulePoll(0);
6712
6892
  });
6713
- return { stop: halt };
6893
+ return {
6894
+ stop: halt,
6895
+ drain: async ({ timeoutMs } = {}) => {
6896
+ if (timeoutMs !== undefined && (!Number.isFinite(timeoutMs) || timeoutMs < 0)) {
6897
+ throw new Error("drain timeoutMs must be a finite non-negative number");
6898
+ }
6899
+ this.beginDrain();
6900
+ clearPollTimer();
6901
+ // Keep regular heartbeats alive during a drain and publish zero free
6902
+ // slots promptly. Failure to report cannot reopen local admission.
6903
+ void this.reportLoad().catch(() => undefined);
6904
+ const deadline = timeoutMs === undefined ? Infinity : Date.now() + timeoutMs;
6905
+ while (polling || activeRelayExecutions > 0 || this.admittedJobs > 0 || this.queuedGenericJobs > 0 || this.manualRelayOperations > 0) {
6906
+ if (Date.now() >= deadline)
6907
+ return false;
6908
+ await sleep(Math.min(25, Math.max(1, deadline - Date.now())));
6909
+ }
6910
+ await this.reportLoad().catch(() => undefined);
6911
+ return true;
6912
+ }
6913
+ };
6714
6914
  }
6715
6915
  }
6716
6916
  //# sourceMappingURL=runtime.js.map