agent-hitch 0.2.9 → 0.2.11

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 (427) hide show
  1. package/README.md +208 -138
  2. package/README.zh-CN.md +195 -120
  3. package/dist/scripts/canary-native-training.js +221 -0
  4. package/dist/scripts/canary-native-training.js.map +1 -0
  5. package/dist/scripts/canary-remote-training.js +246 -0
  6. package/dist/scripts/canary-remote-training.js.map +1 -0
  7. package/dist/scripts/canary-remote-verifier.js +124 -0
  8. package/dist/scripts/canary-remote-verifier.js.map +1 -0
  9. package/dist/scripts/canary-worker-host.js +113 -0
  10. package/dist/scripts/canary-worker-host.js.map +1 -0
  11. package/dist/scripts/canary-worker-peer.js +188 -0
  12. package/dist/scripts/canary-worker-peer.js.map +1 -0
  13. package/dist/scripts/check-architecture.js +4 -3
  14. package/dist/scripts/check-architecture.js.map +1 -1
  15. package/dist/src/adapters/catalog.js +2 -1
  16. package/dist/src/adapters/catalog.js.map +1 -1
  17. package/dist/src/adapters/providers/codex.js +65 -2
  18. package/dist/src/adapters/providers/codex.js.map +1 -1
  19. package/dist/src/adapters/providers/model-call.js +17 -1
  20. package/dist/src/adapters/providers/model-call.js.map +1 -1
  21. package/dist/src/adapters/providers/training-tool.js +29 -0
  22. package/dist/src/adapters/providers/training-tool.js.map +1 -0
  23. package/dist/src/artifacts/index.js +1 -1
  24. package/dist/src/artifacts/index.js.map +1 -1
  25. package/dist/src/artifacts/store.js +15 -10
  26. package/dist/src/artifacts/store.js.map +1 -1
  27. package/dist/src/backends/harbor/backend.js +24 -15
  28. package/dist/src/backends/harbor/backend.js.map +1 -1
  29. package/dist/src/backends/harbor/bridge-environment.js +12 -0
  30. package/dist/src/backends/harbor/bridge-environment.js.map +1 -0
  31. package/dist/src/backends/harbor/environment-config.js +2 -2
  32. package/dist/src/backends/harbor/environment-config.js.map +1 -1
  33. package/dist/src/backends/harbor/host-credential-helper.js +81 -0
  34. package/dist/src/backends/harbor/host-credential-helper.js.map +1 -0
  35. package/dist/src/backends/harbor/index.js +3 -0
  36. package/dist/src/backends/harbor/index.js.map +1 -1
  37. package/dist/src/backends/harbor/model-proxy-config.js +18 -1
  38. package/dist/src/backends/harbor/model-proxy-config.js.map +1 -1
  39. package/dist/src/backends/harbor/observation.js +61 -0
  40. package/dist/src/backends/harbor/observation.js.map +1 -0
  41. package/dist/src/backends/harbor/portable-regrade.js +150 -0
  42. package/dist/src/backends/harbor/portable-regrade.js.map +1 -0
  43. package/dist/src/backends/harbor/process.js +26 -5
  44. package/dist/src/backends/harbor/process.js.map +1 -1
  45. package/dist/src/backends/harbor/regrade.js +4 -1
  46. package/dist/src/backends/harbor/regrade.js.map +1 -1
  47. package/dist/src/backends/harbor/supervisor.js +22 -0
  48. package/dist/src/backends/harbor/supervisor.js.map +1 -1
  49. package/dist/src/backends/harbor/tools.js +2 -0
  50. package/dist/src/backends/harbor/tools.js.map +1 -1
  51. package/dist/src/backends/index.js +3 -0
  52. package/dist/src/backends/index.js.map +1 -1
  53. package/dist/src/cli/arguments.js +33 -0
  54. package/dist/src/cli/arguments.js.map +1 -1
  55. package/dist/src/cli/commands/capabilities.js +15 -1
  56. package/dist/src/cli/commands/capabilities.js.map +1 -1
  57. package/dist/src/cli/commands/daemon.js +19 -0
  58. package/dist/src/cli/commands/daemon.js.map +1 -1
  59. package/dist/src/cli/commands/eval.js +38 -10
  60. package/dist/src/cli/commands/eval.js.map +1 -1
  61. package/dist/src/cli/commands/local.js +130 -0
  62. package/dist/src/cli/commands/local.js.map +1 -0
  63. package/dist/src/cli/commands/model-node.js +26 -0
  64. package/dist/src/cli/commands/model-node.js.map +1 -0
  65. package/dist/src/cli/commands/models.js +72 -0
  66. package/dist/src/cli/commands/models.js.map +1 -0
  67. package/dist/src/cli/commands/run.js +36 -1
  68. package/dist/src/cli/commands/run.js.map +1 -1
  69. package/dist/src/cli/commands/training.js +32 -0
  70. package/dist/src/cli/commands/training.js.map +1 -0
  71. package/dist/src/cli/commands/verifier.js +54 -3
  72. package/dist/src/cli/commands/verifier.js.map +1 -1
  73. package/dist/src/cli/commands/worker.js +30 -2
  74. package/dist/src/cli/commands/worker.js.map +1 -1
  75. package/dist/src/cli/main.js +8 -0
  76. package/dist/src/cli/main.js.map +1 -1
  77. package/dist/src/cli/output.js +26 -2
  78. package/dist/src/cli/output.js.map +1 -1
  79. package/dist/src/control-plane/eval-records.js +2 -0
  80. package/dist/src/control-plane/eval-records.js.map +1 -1
  81. package/dist/src/control-plane/eval-recovery.js +7 -1
  82. package/dist/src/control-plane/eval-recovery.js.map +1 -1
  83. package/dist/src/control-plane/eval-scheduler.js +24 -50
  84. package/dist/src/control-plane/eval-scheduler.js.map +1 -1
  85. package/dist/src/control-plane/eval-submission-persist.js +30 -0
  86. package/dist/src/control-plane/eval-submission-persist.js.map +1 -0
  87. package/dist/src/control-plane/execution-observation-contract.js +60 -0
  88. package/dist/src/control-plane/execution-observation-contract.js.map +1 -0
  89. package/dist/src/control-plane/index.js +10 -0
  90. package/dist/src/control-plane/index.js.map +1 -1
  91. package/dist/src/control-plane/inference-manager.js +357 -0
  92. package/dist/src/control-plane/inference-manager.js.map +1 -0
  93. package/dist/src/control-plane/managed-gateway-receipt.js +26 -0
  94. package/dist/src/control-plane/managed-gateway-receipt.js.map +1 -0
  95. package/dist/src/control-plane/managed-service-recovery.js +158 -0
  96. package/dist/src/control-plane/managed-service-recovery.js.map +1 -0
  97. package/dist/src/control-plane/model-capture-planning.js +15 -1
  98. package/dist/src/control-plane/model-capture-planning.js.map +1 -1
  99. package/dist/src/control-plane/ordered-eval-control.js +221 -0
  100. package/dist/src/control-plane/ordered-eval-control.js.map +1 -0
  101. package/dist/src/control-plane/remote-backend-result.js +18 -0
  102. package/dist/src/control-plane/remote-backend-result.js.map +1 -0
  103. package/dist/src/control-plane/remote-execution-lease.js +15 -0
  104. package/dist/src/control-plane/remote-execution-lease.js.map +1 -0
  105. package/dist/src/control-plane/remote-execution-observation.js +108 -0
  106. package/dist/src/control-plane/remote-execution-observation.js.map +1 -0
  107. package/dist/src/control-plane/remote-model-routes.js +107 -0
  108. package/dist/src/control-plane/remote-model-routes.js.map +1 -0
  109. package/dist/src/control-plane/remote-observation-reporter.js +37 -0
  110. package/dist/src/control-plane/remote-observation-reporter.js.map +1 -0
  111. package/dist/src/control-plane/remote-offer-contract.js +48 -0
  112. package/dist/src/control-plane/remote-offer-contract.js.map +1 -0
  113. package/dist/src/control-plane/remote-rerun-journal.js +61 -0
  114. package/dist/src/control-plane/remote-rerun-journal.js.map +1 -0
  115. package/dist/src/control-plane/remote-result-transport.js +55 -9
  116. package/dist/src/control-plane/remote-result-transport.js.map +1 -1
  117. package/dist/src/control-plane/remote-verifier-import.js +52 -0
  118. package/dist/src/control-plane/remote-verifier-import.js.map +1 -0
  119. package/dist/src/control-plane/remote-verifier-result.js +61 -0
  120. package/dist/src/control-plane/remote-verifier-result.js.map +1 -0
  121. package/dist/src/control-plane/remote-verifier-source-transport.js +68 -0
  122. package/dist/src/control-plane/remote-verifier-source-transport.js.map +1 -0
  123. package/dist/src/control-plane/remote-work-coordinator.js +103 -47
  124. package/dist/src/control-plane/remote-work-coordinator.js.map +1 -1
  125. package/dist/src/control-plane/remote-work-inputs.js +26 -5
  126. package/dist/src/control-plane/remote-work-inputs.js.map +1 -1
  127. package/dist/src/control-plane/remote-work-recovery.js +123 -34
  128. package/dist/src/control-plane/remote-work-recovery.js.map +1 -1
  129. package/dist/src/control-plane/remote-worker-artifacts.js +10 -7
  130. package/dist/src/control-plane/remote-worker-artifacts.js.map +1 -1
  131. package/dist/src/control-plane/remote-worker-cleanup.js +104 -0
  132. package/dist/src/control-plane/remote-worker-cleanup.js.map +1 -0
  133. package/dist/src/control-plane/remote-worker-client.js +156 -14
  134. package/dist/src/control-plane/remote-worker-client.js.map +1 -1
  135. package/dist/src/control-plane/remote-worker-codecs.js +160 -0
  136. package/dist/src/control-plane/remote-worker-codecs.js.map +1 -0
  137. package/dist/src/control-plane/remote-worker-generation-recovery.js +67 -0
  138. package/dist/src/control-plane/remote-worker-generation-recovery.js.map +1 -0
  139. package/dist/src/control-plane/remote-worker-ownership.js +51 -0
  140. package/dist/src/control-plane/remote-worker-ownership.js.map +1 -0
  141. package/dist/src/control-plane/remote-worker-protocol.js +85 -119
  142. package/dist/src/control-plane/remote-worker-protocol.js.map +1 -1
  143. package/dist/src/control-plane/remote-worker-runner.js +95 -18
  144. package/dist/src/control-plane/remote-worker-runner.js.map +1 -1
  145. package/dist/src/control-plane/remote-workers.js +33 -5
  146. package/dist/src/control-plane/remote-workers.js.map +1 -1
  147. package/dist/src/control-plane/rerun-recovery.js +89 -0
  148. package/dist/src/control-plane/rerun-recovery.js.map +1 -0
  149. package/dist/src/control-plane/rerun-scheduler.js +70 -96
  150. package/dist/src/control-plane/rerun-scheduler.js.map +1 -1
  151. package/dist/src/control-plane/rerun-source.js +57 -0
  152. package/dist/src/control-plane/rerun-source.js.map +1 -0
  153. package/dist/src/control-plane/worker-model-relay.js +76 -0
  154. package/dist/src/control-plane/worker-model-relay.js.map +1 -0
  155. package/dist/src/controller-runtime/hash.js +3 -0
  156. package/dist/src/controller-runtime/hash.js.map +1 -1
  157. package/dist/src/controller-runtime/index.js +2 -0
  158. package/dist/src/controller-runtime/index.js.map +1 -1
  159. package/dist/src/controller-runtime/observation.js +29 -0
  160. package/dist/src/controller-runtime/observation.js.map +1 -0
  161. package/dist/src/controller-runtime/resident.js +22 -0
  162. package/dist/src/controller-runtime/resident.js.map +1 -0
  163. package/dist/src/daemon/client.js +34 -1
  164. package/dist/src/daemon/client.js.map +1 -1
  165. package/dist/src/daemon/execution-observation.js +38 -0
  166. package/dist/src/daemon/execution-observation.js.map +1 -0
  167. package/dist/src/daemon/http.js +57 -0
  168. package/dist/src/daemon/http.js.map +1 -0
  169. package/dist/src/daemon/inference-prepare.js +47 -0
  170. package/dist/src/daemon/inference-prepare.js.map +1 -0
  171. package/dist/src/daemon/scheduler.js +4 -1
  172. package/dist/src/daemon/scheduler.js.map +1 -1
  173. package/dist/src/daemon/server.js +80 -82
  174. package/dist/src/daemon/server.js.map +1 -1
  175. package/dist/src/daemon/worker-observation.js +34 -0
  176. package/dist/src/daemon/worker-observation.js.map +1 -0
  177. package/dist/src/daemon/worker-ownership.js +71 -0
  178. package/dist/src/daemon/worker-ownership.js.map +1 -0
  179. package/dist/src/daemon/worker-routes.js +83 -15
  180. package/dist/src/daemon/worker-routes.js.map +1 -1
  181. package/dist/src/domain/execution-observation.js +2 -0
  182. package/dist/src/domain/execution-observation.js.map +1 -0
  183. package/dist/src/domain/index.js +1 -0
  184. package/dist/src/domain/index.js.map +1 -1
  185. package/dist/src/domain/inference.js +2 -0
  186. package/dist/src/domain/inference.js.map +1 -0
  187. package/dist/src/domain/runs.js.map +1 -1
  188. package/dist/src/domain/training.js +2 -0
  189. package/dist/src/domain/training.js.map +1 -0
  190. package/dist/src/domain/validation.js +11 -0
  191. package/dist/src/domain/validation.js.map +1 -1
  192. package/dist/src/domain/verifier-source.js +2 -0
  193. package/dist/src/domain/verifier-source.js.map +1 -0
  194. package/dist/src/domain/worker-recovery.js +2 -0
  195. package/dist/src/domain/worker-recovery.js.map +1 -0
  196. package/dist/src/evals/eval-logical-plan.js +8 -1
  197. package/dist/src/evals/eval-logical-plan.js.map +1 -1
  198. package/dist/src/evals/execution-leases.js +15 -2
  199. package/dist/src/evals/execution-leases.js.map +1 -1
  200. package/dist/src/evals/execution-plan.js +11 -1
  201. package/dist/src/evals/execution-plan.js.map +1 -1
  202. package/dist/src/evals/harbor-bridge-error.js +8 -0
  203. package/dist/src/evals/harbor-bridge-error.js.map +1 -1
  204. package/dist/src/evals/index.js +20 -0
  205. package/dist/src/evals/index.js.map +1 -1
  206. package/dist/src/evals/model-capture-plan.js +12 -0
  207. package/dist/src/evals/model-capture-plan.js.map +1 -1
  208. package/dist/src/evals/model-capture-runtime.js +25 -0
  209. package/dist/src/evals/model-capture-runtime.js.map +1 -1
  210. package/dist/src/evals/physical-work-plan.js +57 -0
  211. package/dist/src/evals/physical-work-plan.js.map +1 -0
  212. package/dist/src/evals/preparation-rerun.js +6 -0
  213. package/dist/src/evals/preparation-rerun.js.map +1 -1
  214. package/dist/src/evals/recovery.js +8 -1
  215. package/dist/src/evals/recovery.js.map +1 -1
  216. package/dist/src/evals/regrade-evidence.js +4 -4
  217. package/dist/src/evals/regrade-evidence.js.map +1 -1
  218. package/dist/src/evals/remote-execution-ownership.js +50 -0
  219. package/dist/src/evals/remote-execution-ownership.js.map +1 -0
  220. package/dist/src/evals/remote-infrastructure-retry.js +2 -0
  221. package/dist/src/evals/remote-infrastructure-retry.js.map +1 -1
  222. package/dist/src/evals/remote-lease-release.js +58 -0
  223. package/dist/src/evals/remote-lease-release.js.map +1 -0
  224. package/dist/src/evals/remote-rerun-execution.js +85 -0
  225. package/dist/src/evals/remote-rerun-execution.js.map +1 -0
  226. package/dist/src/evals/remote-trial.js +6 -0
  227. package/dist/src/evals/remote-trial.js.map +1 -0
  228. package/dist/src/evals/remote-verifier-assessment.js +85 -0
  229. package/dist/src/evals/remote-verifier-assessment.js.map +1 -0
  230. package/dist/src/evals/remote-verifier-contract.js +43 -0
  231. package/dist/src/evals/remote-verifier-contract.js.map +1 -0
  232. package/dist/src/evals/remote-verifier-execution.js +105 -0
  233. package/dist/src/evals/remote-verifier-execution.js.map +1 -0
  234. package/dist/src/evals/remote-verifier-journal.js +21 -0
  235. package/dist/src/evals/remote-verifier-journal.js.map +1 -0
  236. package/dist/src/evals/remote-verifier-outcome.js +51 -0
  237. package/dist/src/evals/remote-verifier-outcome.js.map +1 -0
  238. package/dist/src/evals/remote-verifier-rerun.js +134 -0
  239. package/dist/src/evals/remote-verifier-rerun.js.map +1 -0
  240. package/dist/src/evals/remote-verifier-selection.js +61 -0
  241. package/dist/src/evals/remote-verifier-selection.js.map +1 -0
  242. package/dist/src/evals/remote-verifier-source.js +33 -0
  243. package/dist/src/evals/remote-verifier-source.js.map +1 -0
  244. package/dist/src/evals/remote-worker-cleanup.js +46 -0
  245. package/dist/src/evals/remote-worker-cleanup.js.map +1 -0
  246. package/dist/src/evals/request.js +58 -1
  247. package/dist/src/evals/request.js.map +1 -1
  248. package/dist/src/evals/rerun-completion.js +39 -0
  249. package/dist/src/evals/rerun-completion.js.map +1 -0
  250. package/dist/src/evals/rerun-resume.js +70 -0
  251. package/dist/src/evals/rerun-resume.js.map +1 -0
  252. package/dist/src/evals/rerun-state.js +25 -0
  253. package/dist/src/evals/rerun-state.js.map +1 -0
  254. package/dist/src/evals/rerun-types.js.map +1 -1
  255. package/dist/src/evals/rerun.js +90 -46
  256. package/dist/src/evals/rerun.js.map +1 -1
  257. package/dist/src/evals/service.js +59 -5
  258. package/dist/src/evals/service.js.map +1 -1
  259. package/dist/src/evals/verifier-artifacts.js +98 -153
  260. package/dist/src/evals/verifier-artifacts.js.map +1 -1
  261. package/dist/src/evals/verifier-diagnostic-repair.js +276 -0
  262. package/dist/src/evals/verifier-diagnostic-repair.js.map +1 -0
  263. package/dist/src/evals/verifier-only-rerun.js +2 -16
  264. package/dist/src/evals/verifier-only-rerun.js.map +1 -1
  265. package/dist/src/evals/verifier-rerun-result.js +24 -0
  266. package/dist/src/evals/verifier-rerun-result.js.map +1 -0
  267. package/dist/src/evals/verifier-source-import.js +48 -0
  268. package/dist/src/evals/verifier-source-import.js.map +1 -0
  269. package/dist/src/evals/verifier-source.js +139 -0
  270. package/dist/src/evals/verifier-source.js.map +1 -0
  271. package/dist/src/foundation/base64.js +19 -0
  272. package/dist/src/foundation/base64.js.map +1 -0
  273. package/dist/src/foundation/config.js +10 -0
  274. package/dist/src/foundation/config.js.map +1 -1
  275. package/dist/src/foundation/credential-redaction.js +22 -9
  276. package/dist/src/foundation/credential-redaction.js.map +1 -1
  277. package/dist/src/foundation/index.js +1 -0
  278. package/dist/src/foundation/index.js.map +1 -1
  279. package/dist/src/foundation/process-identity.js +13 -9
  280. package/dist/src/foundation/process-identity.js.map +1 -1
  281. package/dist/src/inference/daemon-capacity.js +41 -0
  282. package/dist/src/inference/daemon-capacity.js.map +1 -0
  283. package/dist/src/inference/device-reservation.js +58 -0
  284. package/dist/src/inference/device-reservation.js.map +1 -0
  285. package/dist/src/inference/doctor.js +95 -0
  286. package/dist/src/inference/doctor.js.map +1 -0
  287. package/dist/src/inference/generation-recovery.js +83 -0
  288. package/dist/src/inference/generation-recovery.js.map +1 -0
  289. package/dist/src/inference/index.js +24 -0
  290. package/dist/src/inference/index.js.map +1 -0
  291. package/dist/src/inference/lock.js +331 -0
  292. package/dist/src/inference/lock.js.map +1 -0
  293. package/dist/src/inference/managed-launcher.js +35 -0
  294. package/dist/src/inference/managed-launcher.js.map +1 -0
  295. package/dist/src/inference/manifest.js +262 -0
  296. package/dist/src/inference/manifest.js.map +1 -0
  297. package/dist/src/inference/materialize.js +66 -0
  298. package/dist/src/inference/materialize.js.map +1 -0
  299. package/dist/src/inference/model-location.js +34 -0
  300. package/dist/src/inference/model-location.js.map +1 -0
  301. package/dist/src/inference/model-store.js +439 -0
  302. package/dist/src/inference/model-store.js.map +1 -0
  303. package/dist/src/inference/node-client.js +167 -0
  304. package/dist/src/inference/node-client.js.map +1 -0
  305. package/dist/src/inference/node-registry.js +79 -0
  306. package/dist/src/inference/node-registry.js.map +1 -0
  307. package/dist/src/inference/observation.js +79 -0
  308. package/dist/src/inference/observation.js.map +1 -0
  309. package/dist/src/inference/preflight.js +132 -0
  310. package/dist/src/inference/preflight.js.map +1 -0
  311. package/dist/src/inference/process-sglang.js +169 -0
  312. package/dist/src/inference/process-sglang.js.map +1 -0
  313. package/dist/src/inference/protocol-probe.js +29 -0
  314. package/dist/src/inference/protocol-probe.js.map +1 -0
  315. package/dist/src/inference/remote-model-store.js +24 -0
  316. package/dist/src/inference/remote-model-store.js.map +1 -0
  317. package/dist/src/inference/runtime-catalog.js +41 -0
  318. package/dist/src/inference/runtime-catalog.js.map +1 -0
  319. package/dist/src/inference/runtime-store.js +93 -0
  320. package/dist/src/inference/runtime-store.js.map +1 -0
  321. package/dist/src/inference/service-attachment.js +46 -0
  322. package/dist/src/inference/service-attachment.js.map +1 -0
  323. package/dist/src/inference/service-inspection.js +38 -0
  324. package/dist/src/inference/service-inspection.js.map +1 -0
  325. package/dist/src/inference/sglang.js +279 -0
  326. package/dist/src/inference/sglang.js.map +1 -0
  327. package/dist/src/inference/supervisor.js +460 -0
  328. package/dist/src/inference/supervisor.js.map +1 -0
  329. package/dist/src/model-access/environment.js +28 -0
  330. package/dist/src/model-access/environment.js.map +1 -0
  331. package/dist/src/model-access/index.js +4 -0
  332. package/dist/src/model-access/index.js.map +1 -1
  333. package/dist/src/model-access/local-gateway-request.js +139 -0
  334. package/dist/src/model-access/local-gateway-request.js.map +1 -0
  335. package/dist/src/model-access/local-gateway.js +323 -0
  336. package/dist/src/model-access/local-gateway.js.map +1 -0
  337. package/dist/src/model-access/proxy.js +90 -5
  338. package/dist/src/model-access/proxy.js.map +1 -1
  339. package/dist/src/model-access/remote-model.js +58 -0
  340. package/dist/src/model-access/remote-model.js.map +1 -0
  341. package/dist/src/model-access/training.js +115 -0
  342. package/dist/src/model-access/training.js.map +1 -0
  343. package/dist/src/runs/adapter-process.js +2 -2
  344. package/dist/src/runs/adapter-process.js.map +1 -1
  345. package/dist/src/runs/executor-types.js +2 -0
  346. package/dist/src/runs/executor-types.js.map +1 -0
  347. package/dist/src/runs/executor.js +54 -34
  348. package/dist/src/runs/executor.js.map +1 -1
  349. package/dist/src/runs/index.js +4 -2
  350. package/dist/src/runs/index.js.map +1 -1
  351. package/dist/src/runs/local-inference-environment.js +59 -0
  352. package/dist/src/runs/local-inference-environment.js.map +1 -0
  353. package/dist/src/runs/local-inference-run.js +53 -0
  354. package/dist/src/runs/local-inference-run.js.map +1 -0
  355. package/dist/src/runs/outcome.js +22 -0
  356. package/dist/src/runs/outcome.js.map +1 -1
  357. package/dist/src/runs/records.js +9 -0
  358. package/dist/src/runs/records.js.map +1 -1
  359. package/dist/src/runs/request.js +58 -3
  360. package/dist/src/runs/request.js.map +1 -1
  361. package/dist/src/runs/training-evidence.js +22 -0
  362. package/dist/src/runs/training-evidence.js.map +1 -0
  363. package/dist/src/runs/training-runtime.js +20 -0
  364. package/dist/src/runs/training-runtime.js.map +1 -0
  365. package/dist/src/runs/verifier-diagnostic-storage.js +237 -0
  366. package/dist/src/runs/verifier-diagnostic-storage.js.map +1 -0
  367. package/dist/src/runs/verifier-diagnostic-supplement.js +228 -0
  368. package/dist/src/runs/verifier-diagnostic-supplement.js.map +1 -0
  369. package/dist/src/runs/verifier-evidence.js +119 -118
  370. package/dist/src/runs/verifier-evidence.js.map +1 -1
  371. package/dist/src/trajectories/providers/deepseek.js +52 -38
  372. package/dist/src/trajectories/providers/deepseek.js.map +1 -1
  373. package/dist/src/trajectories/store.js +17 -0
  374. package/dist/src/trajectories/store.js.map +1 -1
  375. package/dist/src/workers/execution-observation.js +32 -0
  376. package/dist/src/workers/execution-observation.js.map +1 -0
  377. package/dist/src/workers/index.js +2 -0
  378. package/dist/src/workers/index.js.map +1 -1
  379. package/dist/src/workers/remote-harbor-ownership.js +266 -0
  380. package/dist/src/workers/remote-harbor-ownership.js.map +1 -0
  381. package/dist/src/workers/remote-harbor-verifier.js +76 -0
  382. package/dist/src/workers/remote-harbor-verifier.js.map +1 -0
  383. package/dist/src/workers/remote-harbor-work-spec.js +66 -10
  384. package/dist/src/workers/remote-harbor-work-spec.js.map +1 -1
  385. package/dist/src/workers/remote-harbor-worker.js +56 -49
  386. package/dist/src/workers/remote-harbor-worker.js.map +1 -1
  387. package/dist/src/workers/remote-worker-host.js +33 -0
  388. package/dist/src/workers/remote-worker-host.js.map +1 -0
  389. package/docs/local-model-inference-spec.zh-CN.md +666 -0
  390. package/docs/schemas/controller-runtime-observation.schema.json +21 -0
  391. package/docs/schemas/eval-execution-plan.schema.json +1 -0
  392. package/docs/schemas/eval-request.schema.json +3 -1
  393. package/docs/schemas/execution-lease.schema.json +95 -1
  394. package/docs/schemas/execution-provider-status.schema.json +162 -28
  395. package/docs/schemas/inference-execution-evidence.schema.json +487 -0
  396. package/docs/schemas/inference-lock.schema.json +487 -0
  397. package/docs/schemas/inference-runtime-manifest.schema.json +156 -0
  398. package/docs/schemas/inference-service-record.schema.json +227 -0
  399. package/docs/schemas/local-inference-selection.schema.json +98 -0
  400. package/docs/schemas/local-model-manifest.schema.json +43 -0
  401. package/docs/schemas/model-node-binding.schema.json +34 -0
  402. package/docs/schemas/model-node-generation-release.schema.json +46 -0
  403. package/docs/schemas/ordered-eval-control.schema.json +39 -0
  404. package/docs/schemas/remote-execution-lease-grant.schema.json +45 -0
  405. package/docs/schemas/remote-harbor-work-spec.schema.json +325 -0
  406. package/docs/schemas/remote-model-binding.schema.json +21 -0
  407. package/docs/schemas/remote-physical-execution.schema.json +108 -0
  408. package/docs/schemas/remote-result-envelope.schema.json +9 -3
  409. package/docs/schemas/remote-tree-envelope.schema.json +17 -3
  410. package/docs/schemas/remote-verifier-result.schema.json +203 -0
  411. package/docs/schemas/remote-verifier-source.schema.json +52 -0
  412. package/docs/schemas/remote-verifier-work.schema.json +125 -0
  413. package/docs/schemas/remote-work-offer.schema.json +170 -34
  414. package/docs/schemas/remote-worker-execution-admission.schema.json +214 -0
  415. package/docs/schemas/remote-worker-generation-cleanup.schema.json +199 -0
  416. package/docs/schemas/remote-worker-registration.schema.json +226 -25
  417. package/docs/schemas/run-manifest.schema.json +211 -44
  418. package/docs/schemas/run-request.schema.json +2 -1
  419. package/docs/schemas/training-external-binding.schema.json +26 -0
  420. package/docs/schemas/verifier-diagnostic-page.schema.json +97 -0
  421. package/integrations/harbor/hitch_harbor_agent.py +241 -13
  422. package/integrations/harbor/hitch_harbor_environment.py +22 -1
  423. package/integrations/harbor/hitch_host_credentials.py +354 -0
  424. package/integrations/harbor/hitch_private_exec.py +150 -0
  425. package/integrations/model-call/cli.js +13 -5
  426. package/integrations/training-tool/cli.js +72 -0
  427. package/package.json +8 -2
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import hashlib
7
7
  import json
8
+ import math
8
9
  import os
9
10
  import re
10
11
  import secrets
@@ -127,6 +128,7 @@ class HitchHarborAgent(BaseAgent):
127
128
  verifier_identity: str | None = None,
128
129
  logical_attempt: int | None = None,
129
130
  model_capture: dict[str, Any] | None = None,
131
+ managed_local_inference: dict[str, Any] | None = None,
130
132
  **kwargs: Any,
131
133
  ) -> None:
132
134
  super().__init__(logs_dir=logs_dir, **kwargs)
@@ -165,6 +167,14 @@ class HitchHarborAgent(BaseAgent):
165
167
  raise ValueError("logical_attempt must be a positive integer")
166
168
  self.logical_attempt = logical_attempt
167
169
  self.model_capture = _validate_model_capture(model_capture)
170
+ if managed_local_inference is not None and not _valid_managed_model_identity(managed_local_inference):
171
+ raise ValueError("managed_local_inference identity is invalid")
172
+ if managed_local_inference is not None and self.model_capture is None:
173
+ raise ValueError("managed_local_inference requires model_capture")
174
+ self.managed_local_inference = dict(managed_local_inference) if managed_local_inference else None
175
+ capture_inference = self.model_capture.get("managed_inference") if self.model_capture else None
176
+ if capture_inference != self.managed_local_inference:
177
+ raise ValueError("managed_local_inference must match model_capture identity")
168
178
  self._hitch_version: str | None = None
169
179
  self._entrypoint: str | None = None
170
180
  self._artifact_manifest: dict[str, Any] | None = None
@@ -884,17 +894,38 @@ class HitchHarborAgent(BaseAgent):
884
894
  if timeout_ms <= 0:
885
895
  raise RuntimeError("candidate whole-task budget expired during phase binding/upload")
886
896
  elif session:
887
- preparation_ms = (time.monotonic_ns() - invocation_started_ns) // 1_000_000
888
- timeout_ms = task_budget_ms - preparation_ms
889
- (self.logs_dir / "hitch-agent-budget.json").write_text(json.dumps({
890
- "schema_version": "hitch-agent-budget@1", "run_id": run_id,
891
- "task_budget_ms": task_budget_ms, "preparation_ms": preparation_ms,
892
- "hitch_timeout_ms": max(0, timeout_ms),
893
- "collection_timeout_ms": session.config["profile"]["budget"]["collection_timeout_ms"],
894
- "scope": "invocation-budget-and-collection-allowance",
895
- }))
897
+ timeout_ms = self._record_session_budget(
898
+ session, run_id, invocation_started_ns, task_budget_ms
899
+ )
896
900
  if timeout_ms <= 0:
897
901
  raise RuntimeError("candidate budget expired during input preparation; no model was launched")
902
+ private_environment, native_deadline_ns = await self._host_task_credentials(
903
+ environment,
904
+ context,
905
+ run_id,
906
+ timeout_ms,
907
+ invocation_started_ns=(
908
+ invocation_started_ns
909
+ if prepared_phase is None and session is None
910
+ else None
911
+ ),
912
+ )
913
+ if private_environment is not None:
914
+ if prepared_phase is not None:
915
+ timeout_ms = (prepared_phase.deadline_ns - time.monotonic_ns()) // 1_000_000
916
+ if native_deadline_ns is not None:
917
+ native_remaining_ms = (native_deadline_ns - time.monotonic_ns()) // 1_000_000
918
+ if native_remaining_ms <= 0:
919
+ raise RuntimeError("candidate native Harbor budget expired during host credential preparation; no model was launched")
920
+ elif timeout_ms <= 0:
921
+ raise RuntimeError("candidate budget expired during host credential preparation; no model was launched")
922
+ if prepared_phase is None and session:
923
+ timeout_ms = self._record_session_budget(
924
+ session, run_id, invocation_started_ns, task_budget_ms
925
+ )
926
+ if timeout_ms <= 0:
927
+ stage = "host credential preparation" if private_environment is not None else "input preparation"
928
+ raise RuntimeError(f"candidate budget expired during {stage}; no model was launched")
898
929
  arguments = [
899
930
  self._node_prefix(),
900
931
  "HITCH_ROOT=/tmp/hitch-state",
@@ -934,7 +965,14 @@ class HitchHarborAgent(BaseAgent):
934
965
  arguments.extend(["--internal-credential-name", shlex.quote(name)])
935
966
  command = self._logged_run_command(" ".join(arguments))
936
967
  try:
937
- execution = await environment.exec(command, cwd=workdir)
968
+ if private_environment is None:
969
+ execution = await environment.exec(command, cwd=workdir)
970
+ else:
971
+ execution = await environment.hitch_exec_with_private_env(
972
+ command,
973
+ cwd=workdir,
974
+ env=private_environment,
975
+ )
938
976
  except (Exception, asyncio.CancelledError):
939
977
  # Harbor cancels this await on its agent deadline. Collect what is
940
978
  # already durable before it removes the container, without turning
@@ -959,6 +997,153 @@ class HitchHarborAgent(BaseAgent):
959
997
  (self.logs_dir / "hitch-collection-timeout.json").write_text(json.dumps(receipt))
960
998
  raise RuntimeError("hitch_run_collection_timeout: terminal evidence export exceeded its allowance") from error
961
999
 
1000
+ async def _host_task_credentials(
1001
+ self,
1002
+ environment: BaseEnvironment,
1003
+ context: AgentContext,
1004
+ run_id: str,
1005
+ remaining_timeout_ms: int,
1006
+ *,
1007
+ invocation_started_ns: int | None,
1008
+ ) -> tuple[dict[str, str] | None, int | None]:
1009
+ # Preserve the original single-file bridge behavior when this optional
1010
+ # host feature is not configured. An empty value remains configured and
1011
+ # reaches the strict parser below.
1012
+ if "HITCH_HOST_CREDENTIAL_HELPER_JSON" not in os.environ:
1013
+ return None, None
1014
+ from hitch_host_credentials import (
1015
+ HOST_CREDENTIAL_VALIDITY_MARGIN_MS,
1016
+ HostCredentialHelperError,
1017
+ load_host_credential_helper,
1018
+ prepare_host_credentials,
1019
+ )
1020
+
1021
+ try:
1022
+ config = load_host_credential_helper(self.credential_names)
1023
+ if config is None:
1024
+ return None, None
1025
+ if not callable(getattr(environment, "hitch_exec_with_private_env", None)):
1026
+ raise HostCredentialHelperError(
1027
+ "host_credential_transport_unsupported",
1028
+ "Harbor environment does not support private Target credentials",
1029
+ )
1030
+ native_deadline_ns: int | None = None
1031
+ if invocation_started_ns is not None and remaining_timeout_ms <= 0:
1032
+ native_timeout_ms = self._native_harbor_agent_timeout_ms(environment)
1033
+ if native_timeout_ms is None:
1034
+ raise HostCredentialHelperError(
1035
+ "host_credential_helper_request_invalid",
1036
+ "native Harbor agent timeout is not finite",
1037
+ )
1038
+ native_deadline_ns = invocation_started_ns + native_timeout_ms * 1_000_000
1039
+ native_remaining_ms = (native_deadline_ns - time.monotonic_ns()) // 1_000_000
1040
+ if native_remaining_ms <= 0:
1041
+ raise RuntimeError("candidate native Harbor budget expired during input preparation; no model was launched")
1042
+ remaining_timeout_ms = native_remaining_ms
1043
+ credentials = await prepare_host_credentials(
1044
+ config,
1045
+ remaining_timeout_ms + HOST_CREDENTIAL_VALIDITY_MARGIN_MS,
1046
+ )
1047
+ return credentials, native_deadline_ns
1048
+ except HostCredentialHelperError as error:
1049
+ trial_id, task_id, attempt = self._trial_identity()
1050
+ evidence = {
1051
+ "schema_version": "1",
1052
+ "code": error.code,
1053
+ "message": error.message,
1054
+ "recorded_at": datetime.now(timezone.utc).isoformat(),
1055
+ "scope": "host-task-credential-helper",
1056
+ "eval_id": self.eval_id,
1057
+ "trial_id": trial_id,
1058
+ "task_id": task_id,
1059
+ "attempt": attempt,
1060
+ "assigned_run_id": run_id,
1061
+ }
1062
+ if context.metadata is None:
1063
+ context.metadata = {}
1064
+ context.metadata["hitch_bridge_error_code"] = error.code
1065
+ context.metadata["hitch_bridge_error_artifact"] = "hitch-bridge-error.json"
1066
+ try:
1067
+ await self._write_bridge_error(environment, evidence)
1068
+ except Exception:
1069
+ pass
1070
+ raise HitchBridgeError(error.code, error.message, evidence) from None
1071
+
1072
+ def _native_harbor_agent_timeout_ms(self, environment: BaseEnvironment) -> int | None:
1073
+ """Resolve Harbor 0.21's effective native agent timeout from its own inputs."""
1074
+ try:
1075
+ from harbor.models.task.config import TaskConfig
1076
+ from harbor.models.trial.config import TrialConfig
1077
+
1078
+ environment_dir = Path(getattr(environment, "environment_dir"))
1079
+ trial_paths = getattr(environment, "trial_paths")
1080
+ config_path = Path(getattr(trial_paths, "config_path"))
1081
+ task_config = TaskConfig.model_validate_toml(
1082
+ (environment_dir.parent / "task.toml").read_text(encoding="utf-8")
1083
+ )
1084
+ trial_config = TrialConfig.model_validate_json(
1085
+ config_path.read_text(encoding="utf-8")
1086
+ )
1087
+
1088
+ def resolve(default_timeout_sec: float | None) -> float | None:
1089
+ base_timeout_sec = trial_config.agent.override_timeout_sec or default_timeout_sec
1090
+ if base_timeout_sec is None:
1091
+ return None
1092
+ multiplier = trial_config.agent_timeout_multiplier
1093
+ if multiplier is None:
1094
+ multiplier = trial_config.timeout_multiplier
1095
+ return min(
1096
+ base_timeout_sec,
1097
+ trial_config.agent.max_timeout_sec or float("inf"),
1098
+ ) * multiplier
1099
+
1100
+ if task_config.steps:
1101
+ resolved = [
1102
+ resolve(
1103
+ step.agent.timeout_sec
1104
+ if step.agent.timeout_sec is not None
1105
+ else task_config.agent.timeout_sec
1106
+ )
1107
+ for step in task_config.steps
1108
+ ]
1109
+ # Harbor does not identify the current step in BaseAgent.run().
1110
+ # Requiring the largest finite step budget prevents a credential
1111
+ # from expiring during any native step without guessing order.
1112
+ timeout_sec = None if any(value is None for value in resolved) else max(resolved)
1113
+ else:
1114
+ timeout_sec = resolve(task_config.agent.timeout_sec)
1115
+ if timeout_sec is None:
1116
+ return None
1117
+ timeout_ms = math.ceil(timeout_sec * 1_000)
1118
+ if not math.isfinite(timeout_sec) or not 1 <= timeout_ms <= 9_007_199_254_740_991:
1119
+ raise ValueError("native Harbor timeout is outside the supported range")
1120
+ return timeout_ms
1121
+ except Exception:
1122
+ # Task/config contents and host paths are not safe diagnostic text.
1123
+ from hitch_host_credentials import HostCredentialHelperError
1124
+ raise HostCredentialHelperError(
1125
+ "host_credential_helper_request_invalid",
1126
+ "native Harbor agent timeout could not be resolved",
1127
+ ) from None
1128
+
1129
+ def _record_session_budget(
1130
+ self,
1131
+ session,
1132
+ run_id: str,
1133
+ invocation_started_ns: int,
1134
+ task_budget_ms: int,
1135
+ ) -> int:
1136
+ preparation_ms = (time.monotonic_ns() - invocation_started_ns) // 1_000_000
1137
+ timeout_ms = task_budget_ms - preparation_ms
1138
+ (self.logs_dir / "hitch-agent-budget.json").write_text(json.dumps({
1139
+ "schema_version": "hitch-agent-budget@1", "run_id": run_id,
1140
+ "task_budget_ms": task_budget_ms, "preparation_ms": preparation_ms,
1141
+ "hitch_timeout_ms": max(0, timeout_ms),
1142
+ "collection_timeout_ms": session.config["profile"]["budget"]["collection_timeout_ms"],
1143
+ "scope": "invocation-budget-and-collection-allowance",
1144
+ }))
1145
+ return timeout_ms
1146
+
962
1147
  @staticmethod
963
1148
  def _logged_run_command(invocation: str) -> str:
964
1149
  # Bash process substitution leaves an extra pipe FD in the harness and
@@ -1231,9 +1416,25 @@ mv "$stage_dir" "$target_dir"
1231
1416
  raise RuntimeError("hitch-model-proxy-health: required model proxy is unreachable")
1232
1417
  return [], "degraded-unreachable"
1233
1418
  base = self.model_capture["base_url_template"].replace("{run_id}", run_id)
1419
+ training = self.model_capture.get("training_external")
1234
1420
  return [
1235
1421
  f"OPENAI_BASE_URL={shlex.quote(base.replace('{provider}', 'openai'))}",
1236
1422
  f"ANTHROPIC_BASE_URL={shlex.quote(base.replace('{provider}', 'anthropic'))}",
1423
+ *([
1424
+ "HITCH_TRAINING_EXTERNAL=1",
1425
+ f"HITCH_TRAINING_RUN_ID={run_id}",
1426
+ f"HITCH_TRAINING_BINDING={shlex.quote(json.dumps(training, separators=(',', ':')))}",
1427
+ "OPENAI_API_KEY=hitch-training-external",
1428
+ ] if training else []),
1429
+ *([
1430
+ "HITCH_MANAGED_LOCAL_INFERENCE=1",
1431
+ f"HITCH_MANAGED_RUN_ID={run_id}",
1432
+ f"HITCH_MANAGED_INFERENCE_ID={self.managed_local_inference['inference_id']}",
1433
+ f"HITCH_MANAGED_MODEL_ID={self.managed_local_inference['model_id']}",
1434
+ "OPENAI_API_KEY=hitch-managed-local",
1435
+ *([f"HITCH_MANAGED_NODE_BINDING={shlex.quote(json.dumps(self.managed_local_inference['model_node'], separators=(',', ':')))}"]
1436
+ if self.managed_local_inference.get("model_node") else []),
1437
+ ] if self.managed_local_inference else []),
1237
1438
  ], "healthy"
1238
1439
 
1239
1440
  @staticmethod
@@ -1695,15 +1896,16 @@ esac""", "hitch_node_runtime_incompatible")
1695
1896
  def _validate_model_capture(value: dict[str, Any] | None) -> dict[str, Any] | None:
1696
1897
  if value is None:
1697
1898
  return None
1698
- if not isinstance(value, dict) or set(value) != {
1899
+ required_fields = {
1699
1900
  "schema_version", "mode", "required", "topology", "base_url_template", "health_url_template"
1700
- }:
1901
+ }
1902
+ if not isinstance(value, dict) or not required_fields.issubset(value) or set(value) - required_fields - {"managed_inference", "training_external"}:
1701
1903
  raise ValueError("model_capture fields are invalid")
1702
1904
  if (
1703
1905
  value.get("schema_version") != "1"
1704
1906
  or value.get("mode") not in {"proxy", "hybrid"}
1705
1907
  or not isinstance(value.get("required"), bool)
1706
- or value.get("topology") != "host-side"
1908
+ or value.get("topology") not in {"host-side", "in-sandbox"}
1707
1909
  ):
1708
1910
  raise ValueError("model_capture identity is invalid")
1709
1911
  for field, provider_count in (("base_url_template", 1), ("health_url_template", 0)):
@@ -1722,9 +1924,35 @@ def _validate_model_capture(value: dict[str, Any] | None) -> dict[str, Any] | No
1722
1924
  )
1723
1925
  if parsed.scheme not in {"http", "https"} or not parsed.hostname or parsed.username or parsed.password:
1724
1926
  raise ValueError(f"model_capture {field} URL is invalid")
1927
+ managed = value.get("managed_inference")
1928
+ training = value.get("training_external")
1929
+ if training is not None:
1930
+ if (managed is not None or not isinstance(training, dict)
1931
+ or set(training) != {"binding_id", "training_run_id", "policy_version", "generation_contract_digest", "api", "max_output_tokens", "max_episode_steps"}
1932
+ or training.get("api") != "chat-completions" or value.get("required") is not True
1933
+ or any(not isinstance(training.get(k), str) or not training[k] for k in ("binding_id", "training_run_id", "policy_version"))
1934
+ or re.fullmatch(r"sha256:[a-f0-9]{64}", str(training.get("generation_contract_digest"))) is None
1935
+ or any(type(training.get(k)) is not int or training[k] <= 0 for k in ("max_output_tokens", "max_episode_steps"))):
1936
+ raise ValueError("model_capture training identity is invalid")
1937
+ if managed is not None and not _valid_managed_model_identity(managed):
1938
+ raise ValueError("model_capture managed inference identity is invalid")
1725
1939
  return dict(value)
1726
1940
 
1727
1941
 
1942
+ def _valid_managed_model_identity(value: Any) -> bool:
1943
+ if (not isinstance(value, dict) or not {"inference_id", "model_id"}.issubset(value)
1944
+ or set(value) - {"inference_id", "model_id", "model_node"}
1945
+ or any(not isinstance(value[k], str) or re.fullmatch(r"sha256:[a-f0-9]{64}", value[k]) is None for k in ("inference_id", "model_id"))):
1946
+ return False
1947
+ if "model_node" not in value:
1948
+ return True
1949
+ node = value["model_node"]
1950
+ return (isinstance(node, dict) and set(node) == {"schema_version", "node_id", "generation", "runtime_digest", "launcher"}
1951
+ and node["schema_version"] == "2" and node["launcher"] == "process"
1952
+ and all(isinstance(node[k], str) and re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_.-]{0,127}", node[k]) is not None for k in ("node_id", "generation"))
1953
+ and isinstance(node["runtime_digest"], str) and re.fullmatch(r"sha256:[a-f0-9]{64}", node["runtime_digest"]) is not None)
1954
+
1955
+
1728
1956
  def canonical_manifest_json(manifest: dict[str, Any]) -> str:
1729
1957
  """Canonically encode the runtime identity `{ schema_version, node_range,
1730
1958
  entrypoints, files }` with sorted object keys and no insignificant
@@ -31,6 +31,7 @@ _REQUIRED_LABELS = {
31
31
  _ALLOWED_LABELS = _REQUIRED_LABELS | {_LABEL_TASK}
32
32
  _COMPOSE_RESET_MARKER = "__HITCH_COMPOSE_RESET_NULL__"
33
33
  _GPU_OVERRIDE_PREFIX = "__HITCH_GPU_OVERRIDE_"
34
+ _HOST_CREDENTIAL_HELPER_ENV = "HITCH_HOST_CREDENTIAL_HELPER_JSON"
34
35
 
35
36
 
36
37
  class HitchHarborDockerEnvironment(DockerEnvironment):
@@ -128,6 +129,25 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
128
129
  return result.model_copy(update={"disable_internet": True, "dynamic_network_policy": False})
129
130
  return result
130
131
 
132
+ def _compose_env_vars(self, include_os_env=True):
133
+ result = super()._compose_env_vars(include_os_env=include_os_env)
134
+ # The host-only helper command is not a task Compose interpolation
135
+ # input. The agent reads it directly from its trusted host process.
136
+ result.pop(_HOST_CREDENTIAL_HELPER_ENV, None)
137
+ return result
138
+
139
+ async def hitch_exec_with_private_env(self, command, *, env, cwd=None, timeout_sec=None, user=None):
140
+ """Execute one Target without placing per-exec credential values in argv."""
141
+ from hitch_private_exec import exec_with_private_environment
142
+ return await exec_with_private_environment(
143
+ self,
144
+ command,
145
+ env=env,
146
+ cwd=cwd,
147
+ timeout_sec=timeout_sec,
148
+ user=user,
149
+ )
150
+
131
151
  async def _apply_network_policy(self, network_policy):
132
152
  if self._hitch_static_no_network:
133
153
  if network_policy != self.network_policy:
@@ -375,7 +395,8 @@ def _validate_labels(value: Mapping[str, str] | None) -> dict[str, str]:
375
395
  labels = dict(value)
376
396
  if (
377
397
  not re.fullmatch(r"[a-f0-9]{24}", labels.get(_LABEL_ROOT, ""))
378
- or labels.get(_LABEL_PROVIDER) != "local-docker"
398
+ or not isinstance(labels.get(_LABEL_PROVIDER), str)
399
+ or not re.fullmatch(r"[a-z0-9][a-z0-9._-]{0,127}", labels[_LABEL_PROVIDER])
379
400
  or not re.fullmatch(r"eval_[a-f0-9]{32}", labels.get(_LABEL_EVAL, ""))
380
401
  or not re.fullmatch(r"work_[a-f0-9]{32}", labels.get(_LABEL_WORK, ""))
381
402
  or not re.fullmatch(r"lease_[a-f0-9]{32}", labels.get(_LABEL_LEASE, ""))