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.
- package/README.md +208 -138
- package/README.zh-CN.md +195 -120
- package/dist/scripts/canary-native-training.js +221 -0
- package/dist/scripts/canary-native-training.js.map +1 -0
- package/dist/scripts/canary-remote-training.js +246 -0
- package/dist/scripts/canary-remote-training.js.map +1 -0
- package/dist/scripts/canary-remote-verifier.js +124 -0
- package/dist/scripts/canary-remote-verifier.js.map +1 -0
- package/dist/scripts/canary-worker-host.js +113 -0
- package/dist/scripts/canary-worker-host.js.map +1 -0
- package/dist/scripts/canary-worker-peer.js +188 -0
- package/dist/scripts/canary-worker-peer.js.map +1 -0
- package/dist/scripts/check-architecture.js +4 -3
- package/dist/scripts/check-architecture.js.map +1 -1
- package/dist/src/adapters/catalog.js +2 -1
- package/dist/src/adapters/catalog.js.map +1 -1
- package/dist/src/adapters/providers/codex.js +65 -2
- package/dist/src/adapters/providers/codex.js.map +1 -1
- package/dist/src/adapters/providers/model-call.js +17 -1
- package/dist/src/adapters/providers/model-call.js.map +1 -1
- package/dist/src/adapters/providers/training-tool.js +29 -0
- package/dist/src/adapters/providers/training-tool.js.map +1 -0
- package/dist/src/artifacts/index.js +1 -1
- package/dist/src/artifacts/index.js.map +1 -1
- package/dist/src/artifacts/store.js +15 -10
- package/dist/src/artifacts/store.js.map +1 -1
- package/dist/src/backends/harbor/backend.js +24 -15
- package/dist/src/backends/harbor/backend.js.map +1 -1
- package/dist/src/backends/harbor/bridge-environment.js +12 -0
- package/dist/src/backends/harbor/bridge-environment.js.map +1 -0
- package/dist/src/backends/harbor/environment-config.js +2 -2
- package/dist/src/backends/harbor/environment-config.js.map +1 -1
- package/dist/src/backends/harbor/host-credential-helper.js +81 -0
- package/dist/src/backends/harbor/host-credential-helper.js.map +1 -0
- package/dist/src/backends/harbor/index.js +3 -0
- package/dist/src/backends/harbor/index.js.map +1 -1
- package/dist/src/backends/harbor/model-proxy-config.js +18 -1
- package/dist/src/backends/harbor/model-proxy-config.js.map +1 -1
- package/dist/src/backends/harbor/observation.js +61 -0
- package/dist/src/backends/harbor/observation.js.map +1 -0
- package/dist/src/backends/harbor/portable-regrade.js +150 -0
- package/dist/src/backends/harbor/portable-regrade.js.map +1 -0
- package/dist/src/backends/harbor/process.js +26 -5
- package/dist/src/backends/harbor/process.js.map +1 -1
- package/dist/src/backends/harbor/regrade.js +4 -1
- package/dist/src/backends/harbor/regrade.js.map +1 -1
- package/dist/src/backends/harbor/supervisor.js +22 -0
- package/dist/src/backends/harbor/supervisor.js.map +1 -1
- package/dist/src/backends/harbor/tools.js +2 -0
- package/dist/src/backends/harbor/tools.js.map +1 -1
- package/dist/src/backends/index.js +3 -0
- package/dist/src/backends/index.js.map +1 -1
- package/dist/src/cli/arguments.js +33 -0
- package/dist/src/cli/arguments.js.map +1 -1
- package/dist/src/cli/commands/capabilities.js +15 -1
- package/dist/src/cli/commands/capabilities.js.map +1 -1
- package/dist/src/cli/commands/daemon.js +19 -0
- package/dist/src/cli/commands/daemon.js.map +1 -1
- package/dist/src/cli/commands/eval.js +38 -10
- package/dist/src/cli/commands/eval.js.map +1 -1
- package/dist/src/cli/commands/local.js +130 -0
- package/dist/src/cli/commands/local.js.map +1 -0
- package/dist/src/cli/commands/model-node.js +26 -0
- package/dist/src/cli/commands/model-node.js.map +1 -0
- package/dist/src/cli/commands/models.js +72 -0
- package/dist/src/cli/commands/models.js.map +1 -0
- package/dist/src/cli/commands/run.js +36 -1
- package/dist/src/cli/commands/run.js.map +1 -1
- package/dist/src/cli/commands/training.js +32 -0
- package/dist/src/cli/commands/training.js.map +1 -0
- package/dist/src/cli/commands/verifier.js +54 -3
- package/dist/src/cli/commands/verifier.js.map +1 -1
- package/dist/src/cli/commands/worker.js +30 -2
- package/dist/src/cli/commands/worker.js.map +1 -1
- package/dist/src/cli/main.js +8 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/output.js +26 -2
- package/dist/src/cli/output.js.map +1 -1
- package/dist/src/control-plane/eval-records.js +2 -0
- package/dist/src/control-plane/eval-records.js.map +1 -1
- package/dist/src/control-plane/eval-recovery.js +7 -1
- package/dist/src/control-plane/eval-recovery.js.map +1 -1
- package/dist/src/control-plane/eval-scheduler.js +24 -50
- package/dist/src/control-plane/eval-scheduler.js.map +1 -1
- package/dist/src/control-plane/eval-submission-persist.js +30 -0
- package/dist/src/control-plane/eval-submission-persist.js.map +1 -0
- package/dist/src/control-plane/execution-observation-contract.js +60 -0
- package/dist/src/control-plane/execution-observation-contract.js.map +1 -0
- package/dist/src/control-plane/index.js +10 -0
- package/dist/src/control-plane/index.js.map +1 -1
- package/dist/src/control-plane/inference-manager.js +357 -0
- package/dist/src/control-plane/inference-manager.js.map +1 -0
- package/dist/src/control-plane/managed-gateway-receipt.js +26 -0
- package/dist/src/control-plane/managed-gateway-receipt.js.map +1 -0
- package/dist/src/control-plane/managed-service-recovery.js +158 -0
- package/dist/src/control-plane/managed-service-recovery.js.map +1 -0
- package/dist/src/control-plane/model-capture-planning.js +15 -1
- package/dist/src/control-plane/model-capture-planning.js.map +1 -1
- package/dist/src/control-plane/ordered-eval-control.js +221 -0
- package/dist/src/control-plane/ordered-eval-control.js.map +1 -0
- package/dist/src/control-plane/remote-backend-result.js +18 -0
- package/dist/src/control-plane/remote-backend-result.js.map +1 -0
- package/dist/src/control-plane/remote-execution-lease.js +15 -0
- package/dist/src/control-plane/remote-execution-lease.js.map +1 -0
- package/dist/src/control-plane/remote-execution-observation.js +108 -0
- package/dist/src/control-plane/remote-execution-observation.js.map +1 -0
- package/dist/src/control-plane/remote-model-routes.js +107 -0
- package/dist/src/control-plane/remote-model-routes.js.map +1 -0
- package/dist/src/control-plane/remote-observation-reporter.js +37 -0
- package/dist/src/control-plane/remote-observation-reporter.js.map +1 -0
- package/dist/src/control-plane/remote-offer-contract.js +48 -0
- package/dist/src/control-plane/remote-offer-contract.js.map +1 -0
- package/dist/src/control-plane/remote-rerun-journal.js +61 -0
- package/dist/src/control-plane/remote-rerun-journal.js.map +1 -0
- package/dist/src/control-plane/remote-result-transport.js +55 -9
- package/dist/src/control-plane/remote-result-transport.js.map +1 -1
- package/dist/src/control-plane/remote-verifier-import.js +52 -0
- package/dist/src/control-plane/remote-verifier-import.js.map +1 -0
- package/dist/src/control-plane/remote-verifier-result.js +61 -0
- package/dist/src/control-plane/remote-verifier-result.js.map +1 -0
- package/dist/src/control-plane/remote-verifier-source-transport.js +68 -0
- package/dist/src/control-plane/remote-verifier-source-transport.js.map +1 -0
- package/dist/src/control-plane/remote-work-coordinator.js +103 -47
- package/dist/src/control-plane/remote-work-coordinator.js.map +1 -1
- package/dist/src/control-plane/remote-work-inputs.js +26 -5
- package/dist/src/control-plane/remote-work-inputs.js.map +1 -1
- package/dist/src/control-plane/remote-work-recovery.js +123 -34
- package/dist/src/control-plane/remote-work-recovery.js.map +1 -1
- package/dist/src/control-plane/remote-worker-artifacts.js +10 -7
- package/dist/src/control-plane/remote-worker-artifacts.js.map +1 -1
- package/dist/src/control-plane/remote-worker-cleanup.js +104 -0
- package/dist/src/control-plane/remote-worker-cleanup.js.map +1 -0
- package/dist/src/control-plane/remote-worker-client.js +156 -14
- package/dist/src/control-plane/remote-worker-client.js.map +1 -1
- package/dist/src/control-plane/remote-worker-codecs.js +160 -0
- package/dist/src/control-plane/remote-worker-codecs.js.map +1 -0
- package/dist/src/control-plane/remote-worker-generation-recovery.js +67 -0
- package/dist/src/control-plane/remote-worker-generation-recovery.js.map +1 -0
- package/dist/src/control-plane/remote-worker-ownership.js +51 -0
- package/dist/src/control-plane/remote-worker-ownership.js.map +1 -0
- package/dist/src/control-plane/remote-worker-protocol.js +85 -119
- package/dist/src/control-plane/remote-worker-protocol.js.map +1 -1
- package/dist/src/control-plane/remote-worker-runner.js +95 -18
- package/dist/src/control-plane/remote-worker-runner.js.map +1 -1
- package/dist/src/control-plane/remote-workers.js +33 -5
- package/dist/src/control-plane/remote-workers.js.map +1 -1
- package/dist/src/control-plane/rerun-recovery.js +89 -0
- package/dist/src/control-plane/rerun-recovery.js.map +1 -0
- package/dist/src/control-plane/rerun-scheduler.js +70 -96
- package/dist/src/control-plane/rerun-scheduler.js.map +1 -1
- package/dist/src/control-plane/rerun-source.js +57 -0
- package/dist/src/control-plane/rerun-source.js.map +1 -0
- package/dist/src/control-plane/worker-model-relay.js +76 -0
- package/dist/src/control-plane/worker-model-relay.js.map +1 -0
- package/dist/src/controller-runtime/hash.js +3 -0
- package/dist/src/controller-runtime/hash.js.map +1 -1
- package/dist/src/controller-runtime/index.js +2 -0
- package/dist/src/controller-runtime/index.js.map +1 -1
- package/dist/src/controller-runtime/observation.js +29 -0
- package/dist/src/controller-runtime/observation.js.map +1 -0
- package/dist/src/controller-runtime/resident.js +22 -0
- package/dist/src/controller-runtime/resident.js.map +1 -0
- package/dist/src/daemon/client.js +34 -1
- package/dist/src/daemon/client.js.map +1 -1
- package/dist/src/daemon/execution-observation.js +38 -0
- package/dist/src/daemon/execution-observation.js.map +1 -0
- package/dist/src/daemon/http.js +57 -0
- package/dist/src/daemon/http.js.map +1 -0
- package/dist/src/daemon/inference-prepare.js +47 -0
- package/dist/src/daemon/inference-prepare.js.map +1 -0
- package/dist/src/daemon/scheduler.js +4 -1
- package/dist/src/daemon/scheduler.js.map +1 -1
- package/dist/src/daemon/server.js +80 -82
- package/dist/src/daemon/server.js.map +1 -1
- package/dist/src/daemon/worker-observation.js +34 -0
- package/dist/src/daemon/worker-observation.js.map +1 -0
- package/dist/src/daemon/worker-ownership.js +71 -0
- package/dist/src/daemon/worker-ownership.js.map +1 -0
- package/dist/src/daemon/worker-routes.js +83 -15
- package/dist/src/daemon/worker-routes.js.map +1 -1
- package/dist/src/domain/execution-observation.js +2 -0
- package/dist/src/domain/execution-observation.js.map +1 -0
- package/dist/src/domain/index.js +1 -0
- package/dist/src/domain/index.js.map +1 -1
- package/dist/src/domain/inference.js +2 -0
- package/dist/src/domain/inference.js.map +1 -0
- package/dist/src/domain/runs.js.map +1 -1
- package/dist/src/domain/training.js +2 -0
- package/dist/src/domain/training.js.map +1 -0
- package/dist/src/domain/validation.js +11 -0
- package/dist/src/domain/validation.js.map +1 -1
- package/dist/src/domain/verifier-source.js +2 -0
- package/dist/src/domain/verifier-source.js.map +1 -0
- package/dist/src/domain/worker-recovery.js +2 -0
- package/dist/src/domain/worker-recovery.js.map +1 -0
- package/dist/src/evals/eval-logical-plan.js +8 -1
- package/dist/src/evals/eval-logical-plan.js.map +1 -1
- package/dist/src/evals/execution-leases.js +15 -2
- package/dist/src/evals/execution-leases.js.map +1 -1
- package/dist/src/evals/execution-plan.js +11 -1
- package/dist/src/evals/execution-plan.js.map +1 -1
- package/dist/src/evals/harbor-bridge-error.js +8 -0
- package/dist/src/evals/harbor-bridge-error.js.map +1 -1
- package/dist/src/evals/index.js +20 -0
- package/dist/src/evals/index.js.map +1 -1
- package/dist/src/evals/model-capture-plan.js +12 -0
- package/dist/src/evals/model-capture-plan.js.map +1 -1
- package/dist/src/evals/model-capture-runtime.js +25 -0
- package/dist/src/evals/model-capture-runtime.js.map +1 -1
- package/dist/src/evals/physical-work-plan.js +57 -0
- package/dist/src/evals/physical-work-plan.js.map +1 -0
- package/dist/src/evals/preparation-rerun.js +6 -0
- package/dist/src/evals/preparation-rerun.js.map +1 -1
- package/dist/src/evals/recovery.js +8 -1
- package/dist/src/evals/recovery.js.map +1 -1
- package/dist/src/evals/regrade-evidence.js +4 -4
- package/dist/src/evals/regrade-evidence.js.map +1 -1
- package/dist/src/evals/remote-execution-ownership.js +50 -0
- package/dist/src/evals/remote-execution-ownership.js.map +1 -0
- package/dist/src/evals/remote-infrastructure-retry.js +2 -0
- package/dist/src/evals/remote-infrastructure-retry.js.map +1 -1
- package/dist/src/evals/remote-lease-release.js +58 -0
- package/dist/src/evals/remote-lease-release.js.map +1 -0
- package/dist/src/evals/remote-rerun-execution.js +85 -0
- package/dist/src/evals/remote-rerun-execution.js.map +1 -0
- package/dist/src/evals/remote-trial.js +6 -0
- package/dist/src/evals/remote-trial.js.map +1 -0
- package/dist/src/evals/remote-verifier-assessment.js +85 -0
- package/dist/src/evals/remote-verifier-assessment.js.map +1 -0
- package/dist/src/evals/remote-verifier-contract.js +43 -0
- package/dist/src/evals/remote-verifier-contract.js.map +1 -0
- package/dist/src/evals/remote-verifier-execution.js +105 -0
- package/dist/src/evals/remote-verifier-execution.js.map +1 -0
- package/dist/src/evals/remote-verifier-journal.js +21 -0
- package/dist/src/evals/remote-verifier-journal.js.map +1 -0
- package/dist/src/evals/remote-verifier-outcome.js +51 -0
- package/dist/src/evals/remote-verifier-outcome.js.map +1 -0
- package/dist/src/evals/remote-verifier-rerun.js +134 -0
- package/dist/src/evals/remote-verifier-rerun.js.map +1 -0
- package/dist/src/evals/remote-verifier-selection.js +61 -0
- package/dist/src/evals/remote-verifier-selection.js.map +1 -0
- package/dist/src/evals/remote-verifier-source.js +33 -0
- package/dist/src/evals/remote-verifier-source.js.map +1 -0
- package/dist/src/evals/remote-worker-cleanup.js +46 -0
- package/dist/src/evals/remote-worker-cleanup.js.map +1 -0
- package/dist/src/evals/request.js +58 -1
- package/dist/src/evals/request.js.map +1 -1
- package/dist/src/evals/rerun-completion.js +39 -0
- package/dist/src/evals/rerun-completion.js.map +1 -0
- package/dist/src/evals/rerun-resume.js +70 -0
- package/dist/src/evals/rerun-resume.js.map +1 -0
- package/dist/src/evals/rerun-state.js +25 -0
- package/dist/src/evals/rerun-state.js.map +1 -0
- package/dist/src/evals/rerun-types.js.map +1 -1
- package/dist/src/evals/rerun.js +90 -46
- package/dist/src/evals/rerun.js.map +1 -1
- package/dist/src/evals/service.js +59 -5
- package/dist/src/evals/service.js.map +1 -1
- package/dist/src/evals/verifier-artifacts.js +98 -153
- package/dist/src/evals/verifier-artifacts.js.map +1 -1
- package/dist/src/evals/verifier-diagnostic-repair.js +276 -0
- package/dist/src/evals/verifier-diagnostic-repair.js.map +1 -0
- package/dist/src/evals/verifier-only-rerun.js +2 -16
- package/dist/src/evals/verifier-only-rerun.js.map +1 -1
- package/dist/src/evals/verifier-rerun-result.js +24 -0
- package/dist/src/evals/verifier-rerun-result.js.map +1 -0
- package/dist/src/evals/verifier-source-import.js +48 -0
- package/dist/src/evals/verifier-source-import.js.map +1 -0
- package/dist/src/evals/verifier-source.js +139 -0
- package/dist/src/evals/verifier-source.js.map +1 -0
- package/dist/src/foundation/base64.js +19 -0
- package/dist/src/foundation/base64.js.map +1 -0
- package/dist/src/foundation/config.js +10 -0
- package/dist/src/foundation/config.js.map +1 -1
- package/dist/src/foundation/credential-redaction.js +22 -9
- package/dist/src/foundation/credential-redaction.js.map +1 -1
- package/dist/src/foundation/index.js +1 -0
- package/dist/src/foundation/index.js.map +1 -1
- package/dist/src/foundation/process-identity.js +13 -9
- package/dist/src/foundation/process-identity.js.map +1 -1
- package/dist/src/inference/daemon-capacity.js +41 -0
- package/dist/src/inference/daemon-capacity.js.map +1 -0
- package/dist/src/inference/device-reservation.js +58 -0
- package/dist/src/inference/device-reservation.js.map +1 -0
- package/dist/src/inference/doctor.js +95 -0
- package/dist/src/inference/doctor.js.map +1 -0
- package/dist/src/inference/generation-recovery.js +83 -0
- package/dist/src/inference/generation-recovery.js.map +1 -0
- package/dist/src/inference/index.js +24 -0
- package/dist/src/inference/index.js.map +1 -0
- package/dist/src/inference/lock.js +331 -0
- package/dist/src/inference/lock.js.map +1 -0
- package/dist/src/inference/managed-launcher.js +35 -0
- package/dist/src/inference/managed-launcher.js.map +1 -0
- package/dist/src/inference/manifest.js +262 -0
- package/dist/src/inference/manifest.js.map +1 -0
- package/dist/src/inference/materialize.js +66 -0
- package/dist/src/inference/materialize.js.map +1 -0
- package/dist/src/inference/model-location.js +34 -0
- package/dist/src/inference/model-location.js.map +1 -0
- package/dist/src/inference/model-store.js +439 -0
- package/dist/src/inference/model-store.js.map +1 -0
- package/dist/src/inference/node-client.js +167 -0
- package/dist/src/inference/node-client.js.map +1 -0
- package/dist/src/inference/node-registry.js +79 -0
- package/dist/src/inference/node-registry.js.map +1 -0
- package/dist/src/inference/observation.js +79 -0
- package/dist/src/inference/observation.js.map +1 -0
- package/dist/src/inference/preflight.js +132 -0
- package/dist/src/inference/preflight.js.map +1 -0
- package/dist/src/inference/process-sglang.js +169 -0
- package/dist/src/inference/process-sglang.js.map +1 -0
- package/dist/src/inference/protocol-probe.js +29 -0
- package/dist/src/inference/protocol-probe.js.map +1 -0
- package/dist/src/inference/remote-model-store.js +24 -0
- package/dist/src/inference/remote-model-store.js.map +1 -0
- package/dist/src/inference/runtime-catalog.js +41 -0
- package/dist/src/inference/runtime-catalog.js.map +1 -0
- package/dist/src/inference/runtime-store.js +93 -0
- package/dist/src/inference/runtime-store.js.map +1 -0
- package/dist/src/inference/service-attachment.js +46 -0
- package/dist/src/inference/service-attachment.js.map +1 -0
- package/dist/src/inference/service-inspection.js +38 -0
- package/dist/src/inference/service-inspection.js.map +1 -0
- package/dist/src/inference/sglang.js +279 -0
- package/dist/src/inference/sglang.js.map +1 -0
- package/dist/src/inference/supervisor.js +460 -0
- package/dist/src/inference/supervisor.js.map +1 -0
- package/dist/src/model-access/environment.js +28 -0
- package/dist/src/model-access/environment.js.map +1 -0
- package/dist/src/model-access/index.js +4 -0
- package/dist/src/model-access/index.js.map +1 -1
- package/dist/src/model-access/local-gateway-request.js +139 -0
- package/dist/src/model-access/local-gateway-request.js.map +1 -0
- package/dist/src/model-access/local-gateway.js +323 -0
- package/dist/src/model-access/local-gateway.js.map +1 -0
- package/dist/src/model-access/proxy.js +90 -5
- package/dist/src/model-access/proxy.js.map +1 -1
- package/dist/src/model-access/remote-model.js +58 -0
- package/dist/src/model-access/remote-model.js.map +1 -0
- package/dist/src/model-access/training.js +115 -0
- package/dist/src/model-access/training.js.map +1 -0
- package/dist/src/runs/adapter-process.js +2 -2
- package/dist/src/runs/adapter-process.js.map +1 -1
- package/dist/src/runs/executor-types.js +2 -0
- package/dist/src/runs/executor-types.js.map +1 -0
- package/dist/src/runs/executor.js +54 -34
- package/dist/src/runs/executor.js.map +1 -1
- package/dist/src/runs/index.js +4 -2
- package/dist/src/runs/index.js.map +1 -1
- package/dist/src/runs/local-inference-environment.js +59 -0
- package/dist/src/runs/local-inference-environment.js.map +1 -0
- package/dist/src/runs/local-inference-run.js +53 -0
- package/dist/src/runs/local-inference-run.js.map +1 -0
- package/dist/src/runs/outcome.js +22 -0
- package/dist/src/runs/outcome.js.map +1 -1
- package/dist/src/runs/records.js +9 -0
- package/dist/src/runs/records.js.map +1 -1
- package/dist/src/runs/request.js +58 -3
- package/dist/src/runs/request.js.map +1 -1
- package/dist/src/runs/training-evidence.js +22 -0
- package/dist/src/runs/training-evidence.js.map +1 -0
- package/dist/src/runs/training-runtime.js +20 -0
- package/dist/src/runs/training-runtime.js.map +1 -0
- package/dist/src/runs/verifier-diagnostic-storage.js +237 -0
- package/dist/src/runs/verifier-diagnostic-storage.js.map +1 -0
- package/dist/src/runs/verifier-diagnostic-supplement.js +228 -0
- package/dist/src/runs/verifier-diagnostic-supplement.js.map +1 -0
- package/dist/src/runs/verifier-evidence.js +119 -118
- package/dist/src/runs/verifier-evidence.js.map +1 -1
- package/dist/src/trajectories/providers/deepseek.js +52 -38
- package/dist/src/trajectories/providers/deepseek.js.map +1 -1
- package/dist/src/trajectories/store.js +17 -0
- package/dist/src/trajectories/store.js.map +1 -1
- package/dist/src/workers/execution-observation.js +32 -0
- package/dist/src/workers/execution-observation.js.map +1 -0
- package/dist/src/workers/index.js +2 -0
- package/dist/src/workers/index.js.map +1 -1
- package/dist/src/workers/remote-harbor-ownership.js +266 -0
- package/dist/src/workers/remote-harbor-ownership.js.map +1 -0
- package/dist/src/workers/remote-harbor-verifier.js +76 -0
- package/dist/src/workers/remote-harbor-verifier.js.map +1 -0
- package/dist/src/workers/remote-harbor-work-spec.js +66 -10
- package/dist/src/workers/remote-harbor-work-spec.js.map +1 -1
- package/dist/src/workers/remote-harbor-worker.js +56 -49
- package/dist/src/workers/remote-harbor-worker.js.map +1 -1
- package/dist/src/workers/remote-worker-host.js +33 -0
- package/dist/src/workers/remote-worker-host.js.map +1 -0
- package/docs/local-model-inference-spec.zh-CN.md +666 -0
- package/docs/schemas/controller-runtime-observation.schema.json +21 -0
- package/docs/schemas/eval-execution-plan.schema.json +1 -0
- package/docs/schemas/eval-request.schema.json +3 -1
- package/docs/schemas/execution-lease.schema.json +95 -1
- package/docs/schemas/execution-provider-status.schema.json +162 -28
- package/docs/schemas/inference-execution-evidence.schema.json +487 -0
- package/docs/schemas/inference-lock.schema.json +487 -0
- package/docs/schemas/inference-runtime-manifest.schema.json +156 -0
- package/docs/schemas/inference-service-record.schema.json +227 -0
- package/docs/schemas/local-inference-selection.schema.json +98 -0
- package/docs/schemas/local-model-manifest.schema.json +43 -0
- package/docs/schemas/model-node-binding.schema.json +34 -0
- package/docs/schemas/model-node-generation-release.schema.json +46 -0
- package/docs/schemas/ordered-eval-control.schema.json +39 -0
- package/docs/schemas/remote-execution-lease-grant.schema.json +45 -0
- package/docs/schemas/remote-harbor-work-spec.schema.json +325 -0
- package/docs/schemas/remote-model-binding.schema.json +21 -0
- package/docs/schemas/remote-physical-execution.schema.json +108 -0
- package/docs/schemas/remote-result-envelope.schema.json +9 -3
- package/docs/schemas/remote-tree-envelope.schema.json +17 -3
- package/docs/schemas/remote-verifier-result.schema.json +203 -0
- package/docs/schemas/remote-verifier-source.schema.json +52 -0
- package/docs/schemas/remote-verifier-work.schema.json +125 -0
- package/docs/schemas/remote-work-offer.schema.json +170 -34
- package/docs/schemas/remote-worker-execution-admission.schema.json +214 -0
- package/docs/schemas/remote-worker-generation-cleanup.schema.json +199 -0
- package/docs/schemas/remote-worker-registration.schema.json +226 -25
- package/docs/schemas/run-manifest.schema.json +211 -44
- package/docs/schemas/run-request.schema.json +2 -1
- package/docs/schemas/training-external-binding.schema.json +26 -0
- package/docs/schemas/verifier-diagnostic-page.schema.json +97 -0
- package/integrations/harbor/hitch_harbor_agent.py +241 -13
- package/integrations/harbor/hitch_harbor_environment.py +22 -1
- package/integrations/harbor/hitch_host_credentials.py +354 -0
- package/integrations/harbor/hitch_private_exec.py +150 -0
- package/integrations/model-call/cli.js +13 -5
- package/integrations/training-tool/cli.js +72 -0
- 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
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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")
|
|
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)
|
|
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, ""))
|