agent-hitch 0.2.16 → 0.2.17

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 (361) hide show
  1. package/README.md +7 -28
  2. package/README.zh-CN.md +6 -26
  3. package/dist/scripts/benchmark-dataset-verification.js +118 -0
  4. package/dist/scripts/benchmark-dataset-verification.js.map +1 -0
  5. package/dist/scripts/canary-external-endpoint.js +56 -0
  6. package/dist/scripts/canary-external-endpoint.js.map +1 -0
  7. package/dist/scripts/canary-native-training.js +8 -6
  8. package/dist/scripts/canary-native-training.js.map +1 -1
  9. package/dist/scripts/canary-remote-training.js +8 -6
  10. package/dist/scripts/canary-remote-training.js.map +1 -1
  11. package/dist/scripts/check-architecture.js +1 -1
  12. package/dist/scripts/check-architecture.js.map +1 -1
  13. package/dist/src/adapters/providers/codex.js +5 -2
  14. package/dist/src/adapters/providers/codex.js.map +1 -1
  15. package/dist/src/adapters/providers/model-call.js +1 -2
  16. package/dist/src/adapters/providers/model-call.js.map +1 -1
  17. package/dist/src/adapters/providers/training-tool.js +2 -0
  18. package/dist/src/adapters/providers/training-tool.js.map +1 -1
  19. package/dist/src/backends/harbor/artifact-pins.js +42 -0
  20. package/dist/src/backends/harbor/artifact-pins.js.map +1 -0
  21. package/dist/src/backends/harbor/backend.js +16 -8
  22. package/dist/src/backends/harbor/backend.js.map +1 -1
  23. package/dist/src/backends/harbor/bound-credential-helper.js +24 -0
  24. package/dist/src/backends/harbor/bound-credential-helper.js.map +1 -0
  25. package/dist/src/backends/harbor/credential-snapshot.js +71 -0
  26. package/dist/src/backends/harbor/credential-snapshot.js.map +1 -0
  27. package/dist/src/backends/harbor/environment-config.js +25 -2
  28. package/dist/src/backends/harbor/environment-config.js.map +1 -1
  29. package/dist/src/backends/harbor/environment-files.js +143 -0
  30. package/dist/src/backends/harbor/environment-files.js.map +1 -0
  31. package/dist/src/backends/harbor/evaluation-binding.js +160 -0
  32. package/dist/src/backends/harbor/evaluation-binding.js.map +1 -0
  33. package/dist/src/backends/harbor/host-credential-helper.js +5 -0
  34. package/dist/src/backends/harbor/host-credential-helper.js.map +1 -1
  35. package/dist/src/backends/harbor/index.js +2 -0
  36. package/dist/src/backends/harbor/index.js.map +1 -1
  37. package/dist/src/backends/harbor/model-proxy-config.js +3 -18
  38. package/dist/src/backends/harbor/model-proxy-config.js.map +1 -1
  39. package/dist/src/backends/harbor/portable-regrade.js +15 -3
  40. package/dist/src/backends/harbor/portable-regrade.js.map +1 -1
  41. package/dist/src/backends/harbor/python-runtime.js +71 -0
  42. package/dist/src/backends/harbor/python-runtime.js.map +1 -0
  43. package/dist/src/backends/harbor/tools.js +6 -4
  44. package/dist/src/backends/harbor/tools.js.map +1 -1
  45. package/dist/src/backends/index.js +3 -0
  46. package/dist/src/backends/index.js.map +1 -1
  47. package/dist/src/cli/arguments.js +30 -30
  48. package/dist/src/cli/arguments.js.map +1 -1
  49. package/dist/src/cli/commands/capabilities.js +7 -3
  50. package/dist/src/cli/commands/capabilities.js.map +1 -1
  51. package/dist/src/cli/commands/daemon.js +0 -17
  52. package/dist/src/cli/commands/daemon.js.map +1 -1
  53. package/dist/src/cli/commands/eval-binding.js +32 -0
  54. package/dist/src/cli/commands/eval-binding.js.map +1 -0
  55. package/dist/src/cli/commands/eval.js +21 -15
  56. package/dist/src/cli/commands/eval.js.map +1 -1
  57. package/dist/src/cli/commands/models.js +32 -45
  58. package/dist/src/cli/commands/models.js.map +1 -1
  59. package/dist/src/cli/commands/run.js +0 -35
  60. package/dist/src/cli/commands/run.js.map +1 -1
  61. package/dist/src/cli/main.js +0 -4
  62. package/dist/src/cli/main.js.map +1 -1
  63. package/dist/src/cli/output.js +5 -16
  64. package/dist/src/cli/output.js.map +1 -1
  65. package/dist/src/control-plane/eval-records.js +3 -1
  66. package/dist/src/control-plane/eval-records.js.map +1 -1
  67. package/dist/src/control-plane/eval-recovery.js +4 -1
  68. package/dist/src/control-plane/eval-recovery.js.map +1 -1
  69. package/dist/src/control-plane/eval-scheduler.js +16 -8
  70. package/dist/src/control-plane/eval-scheduler.js.map +1 -1
  71. package/dist/src/control-plane/index.js +0 -2
  72. package/dist/src/control-plane/index.js.map +1 -1
  73. package/dist/src/control-plane/model-capture-planning.js +3 -4
  74. package/dist/src/control-plane/model-capture-planning.js.map +1 -1
  75. package/dist/src/control-plane/remote-model-routes.js +4 -24
  76. package/dist/src/control-plane/remote-model-routes.js.map +1 -1
  77. package/dist/src/control-plane/remote-offer-contract.js +2 -2
  78. package/dist/src/control-plane/remote-offer-contract.js.map +1 -1
  79. package/dist/src/control-plane/remote-result-transport.js +7 -8
  80. package/dist/src/control-plane/remote-result-transport.js.map +1 -1
  81. package/dist/src/control-plane/remote-work-coordinator.js +2 -2
  82. package/dist/src/control-plane/remote-work-coordinator.js.map +1 -1
  83. package/dist/src/control-plane/remote-work-recovery.js +2 -2
  84. package/dist/src/control-plane/remote-work-recovery.js.map +1 -1
  85. package/dist/src/control-plane/remote-worker-protocol.js +1 -1
  86. package/dist/src/control-plane/remote-worker-protocol.js.map +1 -1
  87. package/dist/src/control-plane/remote-worker-runner.js +21 -6
  88. package/dist/src/control-plane/remote-worker-runner.js.map +1 -1
  89. package/dist/src/control-plane/remote-workers.js +2 -2
  90. package/dist/src/control-plane/remote-workers.js.map +1 -1
  91. package/dist/src/control-plane/rerun-recovery.js +1 -1
  92. package/dist/src/control-plane/rerun-recovery.js.map +1 -1
  93. package/dist/src/control-plane/rerun-scheduler.js +21 -14
  94. package/dist/src/control-plane/rerun-scheduler.js.map +1 -1
  95. package/dist/src/control-plane/rerun-source.js +5 -2
  96. package/dist/src/control-plane/rerun-source.js.map +1 -1
  97. package/dist/src/control-plane/rerun-submission.js +7 -5
  98. package/dist/src/control-plane/rerun-submission.js.map +1 -1
  99. package/dist/src/control-plane/synthetic-result.js +3 -2
  100. package/dist/src/control-plane/synthetic-result.js.map +1 -1
  101. package/dist/src/control-plane/worker-model-relay.js +1 -1
  102. package/dist/src/control-plane/worker-model-relay.js.map +1 -1
  103. package/dist/src/controller-runtime/hash.js +6 -0
  104. package/dist/src/controller-runtime/hash.js.map +1 -1
  105. package/dist/src/daemon/client.js +12 -35
  106. package/dist/src/daemon/client.js.map +1 -1
  107. package/dist/src/daemon/evaluation-binding.js +33 -0
  108. package/dist/src/daemon/evaluation-binding.js.map +1 -0
  109. package/dist/src/daemon/evaluation-submission.js +27 -0
  110. package/dist/src/daemon/evaluation-submission.js.map +1 -0
  111. package/dist/src/daemon/index.js +1 -0
  112. package/dist/src/daemon/index.js.map +1 -1
  113. package/dist/src/daemon/json-stream.js +98 -0
  114. package/dist/src/daemon/json-stream.js.map +1 -0
  115. package/dist/src/daemon/scheduler.js +1 -4
  116. package/dist/src/daemon/scheduler.js.map +1 -1
  117. package/dist/src/daemon/server.js +14 -54
  118. package/dist/src/daemon/server.js.map +1 -1
  119. package/dist/src/domain/endpoints.js +2 -0
  120. package/dist/src/domain/endpoints.js.map +1 -0
  121. package/dist/src/domain/evaluation-binding.js +5 -0
  122. package/dist/src/domain/evaluation-binding.js.map +1 -0
  123. package/dist/src/domain/index.js +2 -0
  124. package/dist/src/domain/index.js.map +1 -1
  125. package/dist/src/domain/runs.js.map +1 -1
  126. package/dist/src/evals/benchmark-adapter-manifest.js +95 -32
  127. package/dist/src/evals/benchmark-adapter-manifest.js.map +1 -1
  128. package/dist/src/evals/benchmark-verification.js +106 -0
  129. package/dist/src/evals/benchmark-verification.js.map +1 -0
  130. package/dist/src/evals/collect-only-rerun.js +3 -2
  131. package/dist/src/evals/collect-only-rerun.js.map +1 -1
  132. package/dist/src/evals/directory.js +9 -1
  133. package/dist/src/evals/directory.js.map +1 -1
  134. package/dist/src/evals/endpoint-attempts.js +112 -0
  135. package/dist/src/evals/endpoint-attempts.js.map +1 -0
  136. package/dist/src/evals/endpoint-usage.js +8 -0
  137. package/dist/src/evals/endpoint-usage.js.map +1 -0
  138. package/dist/src/evals/environment-binding.js +9 -0
  139. package/dist/src/evals/environment-binding.js.map +1 -0
  140. package/dist/src/evals/eval-artifact-planning.js +10 -1
  141. package/dist/src/evals/eval-artifact-planning.js.map +1 -1
  142. package/dist/src/evals/eval-finalization.js +2 -3
  143. package/dist/src/evals/eval-finalization.js.map +1 -1
  144. package/dist/src/evals/eval-logical-plan.js +2 -0
  145. package/dist/src/evals/eval-logical-plan.js.map +1 -1
  146. package/dist/src/evals/eval-result-builder.js +4 -0
  147. package/dist/src/evals/eval-result-builder.js.map +1 -1
  148. package/dist/src/evals/eval-state.js +22 -0
  149. package/dist/src/evals/eval-state.js.map +1 -0
  150. package/dist/src/evals/execution-plan.js +6 -2
  151. package/dist/src/evals/execution-plan.js.map +1 -1
  152. package/dist/src/evals/index.js +5 -1
  153. package/dist/src/evals/index.js.map +1 -1
  154. package/dist/src/evals/infrastructure-retry.js +2 -0
  155. package/dist/src/evals/infrastructure-retry.js.map +1 -1
  156. package/dist/src/evals/model-capture-runtime.js +9 -13
  157. package/dist/src/evals/model-capture-runtime.js.map +1 -1
  158. package/dist/src/evals/native-phase-evidence.js +8 -2
  159. package/dist/src/evals/native-phase-evidence.js.map +1 -1
  160. package/dist/src/evals/planned-execution.js +7 -2
  161. package/dist/src/evals/planned-execution.js.map +1 -1
  162. package/dist/src/evals/planned-progress-publisher.js +18 -5
  163. package/dist/src/evals/planned-progress-publisher.js.map +1 -1
  164. package/dist/src/evals/planned-retry-execution.js +1 -0
  165. package/dist/src/evals/planned-retry-execution.js.map +1 -1
  166. package/dist/src/evals/preparation-rerun.js +0 -1
  167. package/dist/src/evals/preparation-rerun.js.map +1 -1
  168. package/dist/src/evals/progress.js +92 -7
  169. package/dist/src/evals/progress.js.map +1 -1
  170. package/dist/src/evals/records.js +12 -2
  171. package/dist/src/evals/records.js.map +1 -1
  172. package/dist/src/evals/recovery.js +2 -0
  173. package/dist/src/evals/recovery.js.map +1 -1
  174. package/dist/src/evals/remote-rerun-execution.js +1 -3
  175. package/dist/src/evals/remote-rerun-execution.js.map +1 -1
  176. package/dist/src/evals/remote-verifier-rerun.js +1 -1
  177. package/dist/src/evals/remote-verifier-rerun.js.map +1 -1
  178. package/dist/src/evals/request.js +14 -45
  179. package/dist/src/evals/request.js.map +1 -1
  180. package/dist/src/evals/rerun-observation.js +31 -0
  181. package/dist/src/evals/rerun-observation.js.map +1 -0
  182. package/dist/src/evals/rerun.js +23 -28
  183. package/dist/src/evals/rerun.js.map +1 -1
  184. package/dist/src/evals/service.js +45 -42
  185. package/dist/src/evals/service.js.map +1 -1
  186. package/dist/src/evals/shared-runtime.js +125 -0
  187. package/dist/src/evals/shared-runtime.js.map +1 -0
  188. package/dist/src/evals/trial-import.js +10 -2
  189. package/dist/src/evals/trial-import.js.map +1 -1
  190. package/dist/src/evals/trial-publication-recovery.js +1 -1
  191. package/dist/src/evals/trial-publication-recovery.js.map +1 -1
  192. package/dist/src/evals/verifier-artifacts.js +1 -0
  193. package/dist/src/evals/verifier-artifacts.js.map +1 -1
  194. package/dist/src/evals/verifier-only-rerun.js +1 -1
  195. package/dist/src/evals/verifier-only-rerun.js.map +1 -1
  196. package/dist/src/evals/verifier-rerun-result.js +3 -2
  197. package/dist/src/evals/verifier-rerun-result.js.map +1 -1
  198. package/dist/src/evals/verifier-score-artifacts.js +9 -1
  199. package/dist/src/evals/verifier-score-artifacts.js.map +1 -1
  200. package/dist/src/foundation/config.js +0 -5
  201. package/dist/src/foundation/config.js.map +1 -1
  202. package/dist/src/inference/index.js +3 -22
  203. package/dist/src/inference/index.js.map +1 -1
  204. package/dist/src/inference/lock.js +44 -130
  205. package/dist/src/inference/lock.js.map +1 -1
  206. package/dist/src/model-access/endpoint-contract.js +127 -0
  207. package/dist/src/model-access/endpoint-contract.js.map +1 -0
  208. package/dist/src/model-access/endpoint-credentials.js +54 -0
  209. package/dist/src/model-access/endpoint-credentials.js.map +1 -0
  210. package/dist/src/model-access/endpoint-probe-stream.js +66 -0
  211. package/dist/src/model-access/endpoint-probe-stream.js.map +1 -0
  212. package/dist/src/model-access/endpoint-verification.js +76 -0
  213. package/dist/src/model-access/endpoint-verification.js.map +1 -0
  214. package/dist/src/model-access/endpoints.js +105 -0
  215. package/dist/src/model-access/endpoints.js.map +1 -0
  216. package/dist/src/model-access/index.js +5 -1
  217. package/dist/src/model-access/index.js.map +1 -1
  218. package/dist/src/model-access/proxy.js +57 -14
  219. package/dist/src/model-access/proxy.js.map +1 -1
  220. package/dist/src/model-access/remote-model.js +21 -29
  221. package/dist/src/model-access/remote-model.js.map +1 -1
  222. package/dist/src/model-access/usage.js +30 -0
  223. package/dist/src/model-access/usage.js.map +1 -0
  224. package/dist/src/runs/endpoint-runtime.js +40 -0
  225. package/dist/src/runs/endpoint-runtime.js.map +1 -0
  226. package/dist/src/runs/executor.js +28 -42
  227. package/dist/src/runs/executor.js.map +1 -1
  228. package/dist/src/runs/local-inference-environment.js +5 -53
  229. package/dist/src/runs/local-inference-environment.js.map +1 -1
  230. package/dist/src/runs/manifest.js +1 -0
  231. package/dist/src/runs/manifest.js.map +1 -1
  232. package/dist/src/runs/outcome.js +3 -10
  233. package/dist/src/runs/outcome.js.map +1 -1
  234. package/dist/src/runs/queued.js +3 -2
  235. package/dist/src/runs/queued.js.map +1 -1
  236. package/dist/src/runs/records.js +3 -0
  237. package/dist/src/runs/records.js.map +1 -1
  238. package/dist/src/runs/request.js +10 -38
  239. package/dist/src/runs/request.js.map +1 -1
  240. package/dist/src/workers/remote-harbor-work-spec.js +8 -10
  241. package/dist/src/workers/remote-harbor-work-spec.js.map +1 -1
  242. package/dist/src/workers/remote-harbor-worker.js +3 -0
  243. package/dist/src/workers/remote-harbor-worker.js.map +1 -1
  244. package/docs/evidence/eval-preparation-2026-10-09.json +393 -0
  245. package/docs/evidence/eval-preparation-2026-10-09.md +178 -0
  246. package/docs/local-model-inference-spec.zh-CN.md +4 -663
  247. package/docs/resource-storage.zh-CN.md +116 -0
  248. package/docs/schemas/endpoint-evaluation-attempt.schema.json +29 -0
  249. package/docs/schemas/eval-artifact-pin.schema.json +14 -0
  250. package/docs/schemas/eval-execution-plan.schema.json +486 -105
  251. package/docs/schemas/eval-progress.schema.json +1 -1
  252. package/docs/schemas/eval-request.schema.json +149 -18
  253. package/docs/schemas/eval-rerun-submission.schema.json +8 -1
  254. package/docs/schemas/eval-result.schema.json +310 -56
  255. package/docs/schemas/evaluation-binding.schema.json +15 -0
  256. package/docs/schemas/external-endpoint-binding.schema.json +153 -0
  257. package/docs/schemas/external-endpoint-config.schema.json +93 -0
  258. package/docs/schemas/inference-execution-evidence.schema.json +253 -3
  259. package/docs/schemas/inference-lock-v3.schema.json +6 -0
  260. package/docs/schemas/inference-lock.schema.json +842 -341
  261. package/docs/schemas/ordered-eval-control.schema.json +7 -1
  262. package/docs/schemas/ready-endpoint-binding.schema.json +201 -0
  263. package/docs/schemas/run-manifest.schema.json +6 -0
  264. package/docs/schemas/run-request.schema.json +122 -20
  265. package/examples/external-inference/.env.example +16 -0
  266. package/examples/external-inference/README.md +203 -0
  267. package/examples/external-inference/accept.mjs +297 -0
  268. package/examples/external-inference/compose.gateway.yaml +119 -0
  269. package/examples/external-inference/compose.single.yaml +64 -0
  270. package/examples/external-inference/compose.tp2.yaml +15 -0
  271. package/examples/external-inference/deployment.example.json +58 -0
  272. package/examples/external-inference/endpoint.chat-completions.example.json +13 -0
  273. package/examples/external-inference/endpoint.responses.example.json +13 -0
  274. package/integrations/harbor/hitch_build_inputs.py +213 -0
  275. package/integrations/harbor/hitch_build_process.py +126 -0
  276. package/integrations/harbor/hitch_compose_preparation.py +274 -0
  277. package/integrations/harbor/hitch_harbor_agent.py +25 -39
  278. package/integrations/harbor/hitch_harbor_environment.py +96 -3
  279. package/integrations/harbor/hitch_image_cache.py +357 -0
  280. package/integrations/harbor/hitch_python_runtime.py +303 -0
  281. package/integrations/harbor/hitch_shared_runtime.py +123 -0
  282. package/integrations/model-call/cli.js +11 -10
  283. package/integrations/training-tool/cli.js +5 -3
  284. package/node_modules/smol-toml/LICENSE +24 -0
  285. package/node_modules/smol-toml/README.md +418 -0
  286. package/node_modules/smol-toml/dist/date.d.ts +41 -0
  287. package/node_modules/smol-toml/dist/date.js +127 -0
  288. package/node_modules/smol-toml/dist/error.d.ts +38 -0
  289. package/node_modules/smol-toml/dist/error.js +63 -0
  290. package/node_modules/smol-toml/dist/extract.js +69 -0
  291. package/node_modules/smol-toml/dist/index.cjs +734 -0
  292. package/node_modules/smol-toml/dist/index.d.ts +43 -0
  293. package/node_modules/smol-toml/dist/index.js +33 -0
  294. package/node_modules/smol-toml/dist/parse.d.ts +36 -0
  295. package/node_modules/smol-toml/dist/parse.js +149 -0
  296. package/node_modules/smol-toml/dist/primitive.js +238 -0
  297. package/node_modules/smol-toml/dist/stringify.d.ts +31 -0
  298. package/node_modules/smol-toml/dist/stringify.js +181 -0
  299. package/node_modules/smol-toml/dist/struct.js +179 -0
  300. package/node_modules/smol-toml/dist/util.d.ts +38 -0
  301. package/node_modules/smol-toml/dist/util.js +89 -0
  302. package/node_modules/smol-toml/package.json +68 -0
  303. package/package.json +15 -4
  304. package/dist/src/cli/commands/local.js +0 -130
  305. package/dist/src/cli/commands/local.js.map +0 -1
  306. package/dist/src/cli/commands/model-node.js +0 -26
  307. package/dist/src/cli/commands/model-node.js.map +0 -1
  308. package/dist/src/control-plane/inference-manager.js +0 -357
  309. package/dist/src/control-plane/inference-manager.js.map +0 -1
  310. package/dist/src/control-plane/managed-gateway-receipt.js +0 -26
  311. package/dist/src/control-plane/managed-gateway-receipt.js.map +0 -1
  312. package/dist/src/control-plane/managed-service-recovery.js +0 -158
  313. package/dist/src/control-plane/managed-service-recovery.js.map +0 -1
  314. package/dist/src/daemon/inference-prepare.js +0 -47
  315. package/dist/src/daemon/inference-prepare.js.map +0 -1
  316. package/dist/src/inference/daemon-capacity.js +0 -41
  317. package/dist/src/inference/daemon-capacity.js.map +0 -1
  318. package/dist/src/inference/device-reservation.js +0 -58
  319. package/dist/src/inference/device-reservation.js.map +0 -1
  320. package/dist/src/inference/doctor.js +0 -95
  321. package/dist/src/inference/doctor.js.map +0 -1
  322. package/dist/src/inference/generation-recovery.js +0 -83
  323. package/dist/src/inference/generation-recovery.js.map +0 -1
  324. package/dist/src/inference/managed-launcher.js +0 -35
  325. package/dist/src/inference/managed-launcher.js.map +0 -1
  326. package/dist/src/inference/materialize.js +0 -66
  327. package/dist/src/inference/materialize.js.map +0 -1
  328. package/dist/src/inference/model-location.js +0 -34
  329. package/dist/src/inference/model-location.js.map +0 -1
  330. package/dist/src/inference/node-client.js +0 -167
  331. package/dist/src/inference/node-client.js.map +0 -1
  332. package/dist/src/inference/node-registry.js +0 -79
  333. package/dist/src/inference/node-registry.js.map +0 -1
  334. package/dist/src/inference/observation.js +0 -79
  335. package/dist/src/inference/observation.js.map +0 -1
  336. package/dist/src/inference/preflight.js +0 -132
  337. package/dist/src/inference/preflight.js.map +0 -1
  338. package/dist/src/inference/process-sglang.js +0 -169
  339. package/dist/src/inference/process-sglang.js.map +0 -1
  340. package/dist/src/inference/protocol-probe.js +0 -29
  341. package/dist/src/inference/protocol-probe.js.map +0 -1
  342. package/dist/src/inference/remote-model-store.js +0 -24
  343. package/dist/src/inference/remote-model-store.js.map +0 -1
  344. package/dist/src/inference/runtime-catalog.js +0 -41
  345. package/dist/src/inference/runtime-catalog.js.map +0 -1
  346. package/dist/src/inference/runtime-store.js +0 -93
  347. package/dist/src/inference/runtime-store.js.map +0 -1
  348. package/dist/src/inference/service-attachment.js +0 -46
  349. package/dist/src/inference/service-attachment.js.map +0 -1
  350. package/dist/src/inference/service-inspection.js +0 -38
  351. package/dist/src/inference/service-inspection.js.map +0 -1
  352. package/dist/src/inference/sglang.js +0 -279
  353. package/dist/src/inference/sglang.js.map +0 -1
  354. package/dist/src/inference/supervisor.js +0 -460
  355. package/dist/src/inference/supervisor.js.map +0 -1
  356. package/dist/src/model-access/local-gateway-request.js +0 -139
  357. package/dist/src/model-access/local-gateway-request.js.map +0 -1
  358. package/dist/src/model-access/local-gateway.js +0 -323
  359. package/dist/src/model-access/local-gateway.js.map +0 -1
  360. package/dist/src/runs/local-inference-run.js +0 -53
  361. package/dist/src/runs/local-inference-run.js.map +0 -1
@@ -128,7 +128,6 @@ class HitchHarborAgent(BaseAgent):
128
128
  verifier_identity: str | None = None,
129
129
  logical_attempt: int | None = None,
130
130
  model_capture: dict[str, Any] | None = None,
131
- managed_local_inference: dict[str, Any] | None = None,
132
131
  **kwargs: Any,
133
132
  ) -> None:
134
133
  super().__init__(logs_dir=logs_dir, **kwargs)
@@ -167,14 +166,6 @@ class HitchHarborAgent(BaseAgent):
167
166
  raise ValueError("logical_attempt must be a positive integer")
168
167
  self.logical_attempt = logical_attempt
169
168
  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")
178
169
  self._hitch_version: str | None = None
179
170
  self._entrypoint: str | None = None
180
171
  self._artifact_manifest: dict[str, Any] | None = None
@@ -249,7 +240,10 @@ class HitchHarborAgent(BaseAgent):
249
240
  # Upload the cached bundle's payload (package.json + dist/) as the
250
241
  # package root under /opt/hitch; the local cache path is host-side
251
242
  # bookkeeping and is not identity (spec §4.2).
252
- await environment.upload_dir(payload_dir, "/opt/hitch")
243
+ shared = getattr(environment, "hitch_verify_shared_runtime", None)
244
+ shared_ready = await shared(payload_dir, self._artifact_host_directory) if shared else False
245
+ if not shared_ready:
246
+ await environment.upload_dir(payload_dir, "/opt/hitch")
253
247
  await self._ensure_node(environment)
254
248
  platform, node_version = await self._container_node_identity(environment)
255
249
  if self._artifact_manifest is None or not self._artifact_compatible(
@@ -259,8 +253,12 @@ class HitchHarborAgent(BaseAgent):
259
253
  "hitch-artifact-platform: dedicated-builder artifact is incompatible with "
260
254
  f"trial runtime {platform}/{node_version}"
261
255
  )
262
- await self._upload_harness_artifact(environment, self._artifact_host_directory)
263
- self._artifact_transport_status = "dedicated_builder_upload"
256
+ if shared_ready:
257
+ self._artifact_uploaded = True
258
+ self._artifact_transport_status = "shared_readonly_bind"
259
+ else:
260
+ await self._upload_harness_artifact(environment, self._artifact_host_directory)
261
+ self._artifact_transport_status = "dedicated_builder_upload"
264
262
  entry = self._remote_entry(entrypoint)
265
263
  version = await self._exec(environment, f"{self._node_prefix()} node {entry} --version")
266
264
  self._hitch_version = (version.stdout or "").strip() or None
@@ -1417,6 +1415,7 @@ mv "$stage_dir" "$target_dir"
1417
1415
  return [], "degraded-unreachable"
1418
1416
  base = self.model_capture["base_url_template"].replace("{run_id}", run_id)
1419
1417
  training = self.model_capture.get("training_external")
1418
+ external = self.model_capture.get("external_endpoint")
1420
1419
  return [
1421
1420
  f"OPENAI_BASE_URL={shlex.quote(base.replace('{provider}', 'openai'))}",
1422
1421
  f"ANTHROPIC_BASE_URL={shlex.quote(base.replace('{provider}', 'anthropic'))}",
@@ -1427,14 +1426,10 @@ mv "$stage_dir" "$target_dir"
1427
1426
  "OPENAI_API_KEY=hitch-training-external",
1428
1427
  ] if training else []),
1429
1428
  *([
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 []),
1429
+ f"HITCH_EXTERNAL_RUN_ID={run_id}",
1430
+ f"HITCH_EXTERNAL_ENDPOINT_BINDING={shlex.quote(json.dumps(external, separators=(',', ':')))}",
1431
+ "OPENAI_API_KEY=hitch-external-endpoint",
1432
+ ] if external else []),
1438
1433
  ], "healthy"
1439
1434
 
1440
1435
  @staticmethod
@@ -1899,7 +1894,7 @@ def _validate_model_capture(value: dict[str, Any] | None) -> dict[str, Any] | No
1899
1894
  required_fields = {
1900
1895
  "schema_version", "mode", "required", "topology", "base_url_template", "health_url_template"
1901
1896
  }
1902
- if not isinstance(value, dict) or not required_fields.issubset(value) or set(value) - required_fields - {"managed_inference", "training_external"}:
1897
+ if not isinstance(value, dict) or not required_fields.issubset(value) or set(value) - required_fields - {"external_endpoint", "training_external"}:
1903
1898
  raise ValueError("model_capture fields are invalid")
1904
1899
  if (
1905
1900
  value.get("schema_version") != "1"
@@ -1924,35 +1919,26 @@ def _validate_model_capture(value: dict[str, Any] | None) -> dict[str, Any] | No
1924
1919
  )
1925
1920
  if parsed.scheme not in {"http", "https"} or not parsed.hostname or parsed.username or parsed.password:
1926
1921
  raise ValueError(f"model_capture {field} URL is invalid")
1927
- managed = value.get("managed_inference")
1922
+ external = value.get("external_endpoint")
1928
1923
  training = value.get("training_external")
1929
1924
  if training is not None:
1930
- if (managed is not None or not isinstance(training, dict)
1925
+ if (external is not None or not isinstance(training, dict)
1931
1926
  or set(training) != {"binding_id", "training_run_id", "policy_version", "generation_contract_digest", "api", "max_output_tokens", "max_episode_steps"}
1932
1927
  or training.get("api") != "chat-completions" or value.get("required") is not True
1933
1928
  or any(not isinstance(training.get(k), str) or not training[k] for k in ("binding_id", "training_run_id", "policy_version"))
1934
1929
  or re.fullmatch(r"sha256:[a-f0-9]{64}", str(training.get("generation_contract_digest"))) is None
1935
1930
  or any(type(training.get(k)) is not int or training[k] <= 0 for k in ("max_output_tokens", "max_episode_steps"))):
1936
1931
  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")
1932
+ if external is not None:
1933
+ if (not isinstance(external, dict) or external.get("kind") != "external-endpoint"
1934
+ or external.get("schema_version") != "1" or "connection" in external
1935
+ or external.get("api") not in {"responses", "chat-completions"}
1936
+ or re.fullmatch(r"sha256:[a-f0-9]{64}", str(external.get("endpoint_revision"))) is None
1937
+ or value.get("required") is not True):
1938
+ raise ValueError("model_capture external endpoint binding is invalid")
1939
1939
  return dict(value)
1940
1940
 
1941
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
-
1956
1942
  def canonical_manifest_json(manifest: dict[str, Any]) -> str:
1957
1943
  """Canonically encode the runtime identity `{ schema_version, node_range,
1958
1944
  entrypoints, files }` with sorted object keys and no insignificant
@@ -34,10 +34,24 @@ _GPU_OVERRIDE_PREFIX = "__HITCH_GPU_OVERRIDE_"
34
34
  _HOST_CREDENTIAL_HELPER_ENV = "HITCH_HOST_CREDENTIAL_HELPER_JSON"
35
35
 
36
36
 
37
+ class _SharedRuntimeConfigurationError(ValueError):
38
+ """No candidate was started; cleanup must preserve existing images."""
39
+
40
+
41
+ def _candidate_session(session_id: str, trial_name: str | None) -> bool:
42
+ # Keep role selection self-contained: historical verifier repairs replace
43
+ # only this provider and retain the original runtime's module membership.
44
+ # Verifier sessions may truncate their role marker or use a step named env.
45
+ if trial_name is not None:
46
+ return session_id == f"{trial_name}__env"
47
+ return session_id.endswith("__env") and "__verifier__" not in session_id
48
+
49
+
37
50
  class HitchHarborDockerEnvironment(DockerEnvironment):
38
51
  """Use Harbor's Docker semantics with a final ownership-label overlay."""
39
52
 
40
53
  _hitch_static_no_network = False
54
+ _hitch_preparation = None
41
55
 
42
56
  def __init__(
43
57
  self,
@@ -48,6 +62,10 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
48
62
  hitch_prebuilt_task_image: str | None = None,
49
63
  hitch_model_proxy_host_gateway: bool = False,
50
64
  hitch_main_gpu_count: int = 0,
65
+ hitch_shared_runtime: Mapping[str, str] | None = None,
66
+ hitch_image_cache_dir: str | None = None,
67
+ hitch_image_build_slots: int = 2,
68
+ hitch_managed_keepalive: bool = False,
51
69
  **kwargs: Any,
52
70
  ) -> None:
53
71
  self._hitch_ownership_labels = _validate_labels(hitch_ownership_labels)
@@ -58,12 +76,32 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
58
76
  self._hitch_prebuilt_task_image = _validate_prebuilt_task_image(
59
77
  hitch_prebuilt_task_image
60
78
  )
79
+ # Harbor passes environment kwargs to separate verifiers too. A planned
80
+ # candidate image must never replace a verifier's independent context.
81
+ session_id = kwargs.get("session_id", args[2] if len(args) > 2 else "")
82
+ trial_paths = kwargs.get("trial_paths", args[3] if len(args) > 3 else None)
83
+ trial_name = trial_paths.trial_dir.name if trial_paths is not None else None
84
+ candidate = _candidate_session(session_id, trial_name)
85
+ if session_id and not candidate:
86
+ self._hitch_prebuilt_task_image = None
87
+ if hitch_image_cache_dir is not None and (not isinstance(hitch_image_cache_dir, str) or not Path(hitch_image_cache_dir).is_absolute()):
88
+ raise ValueError("Hitch image cache directory must be absolute")
89
+ if not isinstance(hitch_managed_keepalive, bool):
90
+ raise ValueError("Hitch managed keepalive flag is invalid")
91
+ self._hitch_preparation = None
92
+ if hitch_image_cache_dir or hitch_managed_keepalive:
93
+ from hitch_compose_preparation import ComposePreparation
94
+ self._hitch_preparation = ComposePreparation(self, hitch_image_cache_dir, hitch_image_build_slots, hitch_managed_keepalive)
61
95
  if not isinstance(hitch_model_proxy_host_gateway, bool):
62
96
  raise ValueError("Hitch model proxy host gateway flag is invalid")
63
97
  self._hitch_model_proxy_host_gateway = hitch_model_proxy_host_gateway
64
98
  if isinstance(hitch_main_gpu_count, bool) or not isinstance(hitch_main_gpu_count, int) or hitch_main_gpu_count < 0:
65
99
  raise ValueError("Hitch main GPU count is invalid")
66
100
  self._hitch_main_gpu_count = hitch_main_gpu_count
101
+ self._hitch_shared_runtime = None
102
+ if hitch_shared_runtime is not None:
103
+ import hitch_shared_runtime as shared_runtime
104
+ self._hitch_shared_runtime = shared_runtime.configure(hitch_shared_runtime, candidate)
67
105
  self._hitch_ownership_temp_dir: tempfile.TemporaryDirectory[str] | None = None
68
106
  self._hitch_ownership_compose_path: Path | None = None
69
107
  self._hitch_phase_compose_path: Path | None = None
@@ -103,6 +141,7 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
103
141
  or self._hitch_main_gpu_count > 0
104
142
  or self._hitch_benchmark_platform
105
143
  or self._hitch_static_no_network
144
+ or self._hitch_shared_runtime
106
145
  ):
107
146
  self._hitch_ownership_compose_path = self._write_ownership_overlay()
108
147
 
@@ -113,10 +152,52 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
113
152
  paths = list(super()._docker_compose_paths)
114
153
  if self._hitch_ownership_compose_path is not None:
115
154
  paths.append(self._hitch_ownership_compose_path)
155
+ if self._hitch_preparation and self._hitch_preparation.path is not None:
156
+ paths.append(self._hitch_preparation.path)
116
157
  if self._hitch_phase_compose_path is not None:
117
158
  paths.append(self._hitch_phase_compose_path)
118
159
  return paths
119
160
 
161
+ @property
162
+ def _main_image_name(self):
163
+ preparation = getattr(self, "_hitch_preparation", None)
164
+ return preparation.images.get(MAIN_SERVICE_NAME, super()._main_image_name) if preparation else super()._main_image_name
165
+
166
+ async def _run_docker_compose_command(self, command, *args, **kwargs):
167
+ run = super()._run_docker_compose_command
168
+ if command[:1] == ["up"] and self._hitch_shared_runtime:
169
+ import hitch_shared_runtime as shared_runtime
170
+ from hitch_compose_preparation import compose_services
171
+ # Resolve the task's merged/interpolated configuration before our
172
+ # bind mounts can hide a conflicting task mount. Revalidate on every
173
+ # start, and never expose host snapshots to a privileged candidate.
174
+ try:
175
+ self._hitch_ownership_compose_path = self._write_ownership_overlay()
176
+ resolved = await run(["config", "--format", "json"])
177
+ shared_runtime.reject_conflicts(compose_services(resolved.stdout))
178
+ self._hitch_ownership_compose_path = self._write_ownership_overlay(include_shared_runtime=True)
179
+ except Exception as error:
180
+ raise _SharedRuntimeConfigurationError(str(error)) from error
181
+ preparation = self._hitch_preparation
182
+ if preparation:
183
+ if command == ["build"]:
184
+ cached = await preparation.build(run)
185
+ if cached is not None:
186
+ return cached
187
+ elif command[:1] == ["up"]:
188
+ # If Harbor selected a prebuilt image and skipped build, retain
189
+ # Compose's original image/pull-policy choices, including any
190
+ # sidecars. An implicit up is not an explicit build request.
191
+ await preparation.runtime(run)
192
+ elif command[:1] == ["down"] and preparation.images and "--rmi" in command:
193
+ index = command.index("--rmi")
194
+ if command[index + 1:index + 2] == ["local"]:
195
+ # Compose treats an immutable image ID as an untagged local
196
+ # image even though our persistent cache also owns a tag.
197
+ # Keep prepared images; retain all container/volume cleanup.
198
+ command = command[:index] + command[index + 2:]
199
+ return await run(command, *args, **kwargs)
200
+
120
201
  def _requires_egress_control(self, *, startup_network_policy, phase_network_policies):
121
202
  if self._hitch_static_no_network:
122
203
  return False
@@ -148,6 +229,12 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
148
229
  user=user,
149
230
  )
150
231
 
232
+ async def hitch_verify_shared_runtime(self, controller_payload, artifact_directory):
233
+ if self._hitch_shared_runtime is None:
234
+ return False
235
+ import hitch_shared_runtime as shared_runtime
236
+ return await shared_runtime.verify_environment(self, controller_payload, artifact_directory)
237
+
151
238
  async def _apply_network_policy(self, network_policy):
152
239
  if self._hitch_static_no_network:
153
240
  if network_policy != self.network_policy:
@@ -188,15 +275,17 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
188
275
 
189
276
  async def start(self, force_build: bool):
190
277
  try:
278
+ if self._hitch_preparation:
279
+ self._hitch_preparation.reset(force_build)
191
280
  await super().start(force_build)
192
281
  if self._hitch_static_no_network:
193
282
  await self._verify_static_network()
194
283
  if self._hitch_benchmark:
195
284
  await self._hitch_benchmark.prepare()
196
- except BaseException:
285
+ except BaseException as error:
197
286
  # Harbor may abort setup before entering its normal teardown path.
198
287
  try:
199
- await self.stop(delete=True)
288
+ await self.stop(delete=not isinstance(error, _SharedRuntimeConfigurationError))
200
289
  except BaseException:
201
290
  pass
202
291
  raise
@@ -222,7 +311,9 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
222
311
  finally:
223
312
  await super().stop(delete)
224
313
 
225
- def _write_ownership_overlay(self) -> Path:
314
+ def _write_ownership_overlay(self, *, include_shared_runtime=False) -> Path:
315
+ if include_shared_runtime and self._hitch_shared_runtime:
316
+ import hitch_shared_runtime as shared_runtime
226
317
  services = {MAIN_SERVICE_NAME}
227
318
  if self._enable_egress_control:
228
319
  services.add(self._EGRESS_CONTROL_SERVICE_NAME)
@@ -265,6 +356,8 @@ class HitchHarborDockerEnvironment(DockerEnvironment):
265
356
  service_overlays: dict[str, dict[str, Any]] = {}
266
357
  for name in sorted(services):
267
358
  config: dict[str, Any] = {}
359
+ if name == MAIN_SERVICE_NAME and include_shared_runtime and self._hitch_shared_runtime:
360
+ config["volumes"] = shared_runtime.compose_mounts(self._hitch_shared_runtime)
268
361
  # The benchmark default must not replace explicit per-service
269
362
  # architecture, e.g. an ARM QEMU sidecar beside an AMD64 candidate.
270
363
  if getattr(self, "_hitch_benchmark_platform", None) and name not in declared_platforms: