agent-hitch 0.2.9 → 0.2.10
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 +206 -137
- package/README.zh-CN.md +193 -119
- 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 +14 -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/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 +24 -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 +19 -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-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 +1 -0
- 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/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/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
package/README.zh-CN.md
CHANGED
|
@@ -1,196 +1,270 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
1
3
|
# Hitch
|
|
2
4
|
|
|
5
|
+
### 模型与智能体评测的统一执行层
|
|
6
|
+
|
|
3
7
|
[](https://www.npmjs.com/package/agent-hitch)
|
|
4
8
|
[](https://github.com/rsi-gear/agent-hitch/releases)
|
|
9
|
+
[](LICENSE)
|
|
5
10
|
[](https://discord.gg/cZ4NBbHDk)
|
|
6
11
|
|
|
7
|
-
[English](README.md) |
|
|
12
|
+
[English](README.md) | 简体中文
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
**[User Guide · 用户指南](https://rsigear.xyz/docs/hitch/zh/) · [Quick Start](#quick-start快速开始) · [工作原理](#工作原理) · [Hitch 与 Harbor](#hitch-与-harbor) · [并行与恢复](#并行执行与恢复)**
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
和 DeepSeek Harness。每次运行都会关联 Harness 版本、不可变制品、工作区、
|
|
13
|
-
轨迹、日志和评测证据。
|
|
16
|
+
</div>
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
+
评测模型与智能体 Harness,需要协调镜像构建、沙箱、Harness 版本、模型端点、
|
|
19
|
+
失败重试和证据采集。实验开始并行、扩展到多台机器后,这些工作也随之增加。
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
**Hitch 统一管理从任务定义到可验证结果包的执行流程。** 提交 Harbor 兼容任务,
|
|
22
|
+
选择模型与 Harness,Hitch 负责准备、调度、执行和结果收集。固定 Harness 比较
|
|
23
|
+
模型,或固定模型比较 Harness。
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
> 评测链路已经实现。
|
|
29
|
-
|
|
30
|
-
## 为什么使用 Hitch?
|
|
25
|
+
- [x] **构建与缓存。** 固定 Harness 版本,复用已验证的制品与环境镜像。
|
|
26
|
+
- [x] **适配 Harness。** 通过统一接口运行 Codex、Claude Code 等受支持的 Harness。
|
|
27
|
+
- [x] **接入模型。** 使用云端 API,或托管的本地与远程 SGLang 推理。
|
|
28
|
+
- [x] **分配执行节点。** 在本机 Docker 或已注册的远程 Worker 上运行任务沙箱。
|
|
29
|
+
- [x] **并行与恢复。** 共享资源预算、并行执行 Trial,在支持的恢复路径中保留已完成工作。
|
|
30
|
+
- [x] **收齐结果证据。** 分数、轨迹、Verifier 证据与来源信息归入同一份结果包。
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
> **状态:** pre-alpha。以下能力对应当前 `dev`;配置与支持范围见
|
|
33
|
+
> [User Guide](https://rsigear.xyz/docs/hitch/zh/)。
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
- **比较:** 通过统一的执行契约比较不同 Harness 和模型。
|
|
37
|
-
- **审计:** 用不可变制品、原生事件、规范化轨迹、日志、反馈和评测记录验证
|
|
38
|
-
结果。
|
|
35
|
+
## Quick Start:快速开始
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
流水线的团队。
|
|
37
|
+
需要 **Node.js 22+**、Git 和模型访问权限。本地运行不需要 Docker。
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Hitch 要求 Node.js 22 或更高版本。
|
|
39
|
+
**1. 安装 Hitch,并完成 Harness 认证。** 示例固定了一个 Codex 版本,
|
|
40
|
+
继续前先完成登录流程。
|
|
46
41
|
|
|
47
42
|
```bash
|
|
48
|
-
npm install --global agent-hitch
|
|
49
|
-
|
|
43
|
+
npm install --global agent-hitch@0.2.10
|
|
44
|
+
npx --yes @openai/codex@0.92.0 login
|
|
50
45
|
```
|
|
51
46
|
|
|
52
|
-
|
|
47
|
+
**2. 从干净的 Git 仓库运行。** Worktree 模式要求 `git status --short` 没有
|
|
48
|
+
输出。要包含当前未提交的文件,可以选择
|
|
49
|
+
[`--workspace-mode copy`](docs/guide/zh-CN/versions-and-workspaces.md)。
|
|
53
50
|
|
|
54
51
|
```bash
|
|
52
|
+
git status --short
|
|
55
53
|
hitch run \
|
|
56
54
|
--harness codex@version:0.92.0 \
|
|
57
55
|
--workspace-mode worktree \
|
|
58
|
-
--prompt "
|
|
59
|
-
--
|
|
56
|
+
--prompt "总结这个仓库及其测试命令,不修改文件。" \
|
|
57
|
+
--timeout 5m \
|
|
58
|
+
--output json
|
|
60
59
|
```
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
**3. 检查运行结果。** 用返回的 `run_id` 替换 `RUN_ID`。确认状态、退出码和
|
|
62
|
+
回答,再查看已捕获的轨迹。
|
|
64
63
|
|
|
65
64
|
```bash
|
|
65
|
+
hitch runs inspect RUN_ID --json
|
|
66
66
|
hitch trajectory project RUN_ID --profile analysis --json
|
|
67
|
-
hitch trajectory events RUN_ID --types tool/call,tool/result --limit 100 --json
|
|
68
|
-
hitch trajectory inspect RUN_ID
|
|
69
|
-
hitch verifier inspect RUN_ID --json
|
|
70
67
|
```
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
记录保存在 `~/.hitch/runs/RUN_ID/`。托管工作区会被保留,Hitch 不会自动把
|
|
70
|
+
智能体修改合并回源码仓库。认证方式、模型选择和并行提交示例见
|
|
71
|
+
[完整 Quick Start](https://rsigear.xyz/docs/hitch/zh/quickstart)。
|
|
72
|
+
|
|
73
|
+
## 工作原理
|
|
74
|
+
|
|
75
|
+
```mermaid
|
|
76
|
+
flowchart LR
|
|
77
|
+
tasks["Harbor 兼容任务<br/>模型 + Harness"] --> prepare
|
|
78
|
+
subgraph hitch["Hitch 执行层"]
|
|
79
|
+
prepare["构建与缓存<br/>Harness 适配"] --> execute["任务沙箱<br/>调度与恢复"]
|
|
80
|
+
execute <--> access["模型接入<br/>可选的交互采集"]
|
|
81
|
+
end
|
|
82
|
+
access <--> models["云端 API<br/>本地 / 远程 SGLang"]
|
|
83
|
+
execute --> bundle["结果包<br/>轨迹 · Verifier 证据 · 来源信息"]
|
|
84
|
+
access -.-> bundle
|
|
85
|
+
bundle -.-> candidate["训练数据候选<br/>可选导出"]
|
|
86
|
+
```
|
|
77
87
|
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
CLI 与 daemon HTTP API 使用同一执行层。任务定义指令、环境和 Verifier;
|
|
89
|
+
Hitch 管理准备、执行与证据发布。每份结果包关联实际使用的 Harness 版本、
|
|
90
|
+
模型身份、环境镜像和执行记录。
|
|
80
91
|
|
|
81
|
-
|
|
92
|
+
模型交互采集取决于 Harness、端点和采集策略。训练数据候选保留可用性判定
|
|
93
|
+
和来源信息,供下游审核。
|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
[构建与缓存](docs/environment-images.md) ·
|
|
96
|
+
[执行与证据契约](docs/hitch-harbor-control-plane-implementation-status.md)
|
|
84
97
|
|
|
85
|
-
|
|
86
|
-
# 对本机已经安装的可执行文件生成指纹并运行。
|
|
87
|
-
hitch run --harness codex@installed --prompt "Inspect this repository"
|
|
98
|
+
## Hitch 与 Harbor
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
|
|
100
|
+
Hitch 采用 **Harbor 的任务定义格式**,接入已有 Benchmark 和自定义任务。
|
|
101
|
+
[Benchmark Package](docs/benchmark-packages.md) 定义任务输入、工具、生命周期
|
|
102
|
+
与评分规则;Hitch 管理实验版本、执行编排、故障恢复和结果。
|
|
91
103
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
| 能力 | Harbor CLI | Hitch |
|
|
105
|
+
| --- | :---: | :---: |
|
|
106
|
+
| **跨评测共享资源预算** | — | ✅ |
|
|
107
|
+
| **跨评测公平调度** | — | ✅ |
|
|
108
|
+
| **控制进程崩溃后接管存活 Trial** | — | ✅ |
|
|
109
|
+
| 并行 Trial、失败重试与重新评分 | ✅ | ✅ |
|
|
110
|
+
| 中断评测续跑 | ✅ | ✅ |
|
|
95
111
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
| DeepSeek Harness | ✓ | ✓ | ✓ |
|
|
112
|
+
对比本机 CLI 工作流。**—** 表示需要额外的协调层。
|
|
113
|
+
公平调度要求任务成员已知;存活执行接管要求 POSIX 和完整执行证据。
|
|
114
|
+
[支持范围 →](docs/guide/zh-CN/daemon.md)
|
|
115
|
+
|
|
116
|
+
<details>
|
|
117
|
+
<summary>验证记录与对比范围</summary>
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
2026-09-01 的离线 Harbor 验收记录包含 20 个 Trial、1 次环境构建、19 次缓存
|
|
120
|
+
命中和 0 次 OOM。这验证了该负载下的缓存复用与资源准入,不是与原生 Harbor
|
|
121
|
+
的速度或成本对照实验。
|
|
122
|
+
[验收记录](docs/hitch-harbor-control-plane-implementation-status.md) ·
|
|
123
|
+
[Harness 构建复用](docs/evals.md)
|
|
107
124
|
|
|
108
|
-
|
|
125
|
+
[Harbor 评测](https://www.harborframework.com/docs/run-jobs/run-evals) ·
|
|
126
|
+
[Harbor 重试与恢复](https://github.com/harbor-framework/harbor/blob/main/src/harbor/cli/jobs.py) ·
|
|
127
|
+
[Harbor 重新评分](https://www.harborframework.com/docs/run-jobs/regrade) ·
|
|
128
|
+
[Hitch 调度与恢复](docs/daemon.md)
|
|
109
129
|
|
|
110
|
-
|
|
130
|
+
</details>
|
|
111
131
|
|
|
112
|
-
|
|
113
|
-
- 经过验证、采用内容寻址的可运行制品;
|
|
114
|
-
- 工作区、模型身份、生命周期与最终结果;
|
|
115
|
-
- 规范化控制面事件与原始进程日志;
|
|
116
|
-
- 支持场景下经过脱敏的 provider-native 事件;
|
|
117
|
-
- 采用 SHA-256 绑定文件、兼容 DSH 的规范化轨迹;
|
|
118
|
-
- 带版本的消息反馈,以及有界的 verifier/评测证据。
|
|
132
|
+
## 本地与远程模型推理
|
|
119
133
|
|
|
120
|
-
|
|
134
|
+
当前 `dev` 已包含托管推理。完整的 Hugging Face safetensors checkpoint 只需导入一次,此后继续使用原有
|
|
135
|
+
run/eval 命令,并把模型写成 `local/<name>`。Hitch 会自动选择固定摘要的 CPU 或
|
|
136
|
+
CUDA preview runtime、按需启动 daemon 和 SGLang 服务,并记录不可变的模型、runtime
|
|
137
|
+
和 inference 身份。
|
|
121
138
|
|
|
122
139
|
```bash
|
|
123
|
-
hitch
|
|
124
|
-
|
|
125
|
-
hitch
|
|
126
|
-
|
|
127
|
-
--
|
|
128
|
-
--
|
|
129
|
-
--note "修改保持了足够聚焦"
|
|
140
|
+
hitch models add /models/coder-checkpoint --name coder
|
|
141
|
+
|
|
142
|
+
hitch run \
|
|
143
|
+
--harness codex@version:0.145.0 \
|
|
144
|
+
--model local/coder \
|
|
145
|
+
--prompt "Inspect this repository"
|
|
130
146
|
```
|
|
131
147
|
|
|
132
|
-
|
|
148
|
+
本机预览面向 Linux/amd64 Docker,以及 Intel Xeon AMX CPU 或兼容的单张
|
|
149
|
+
NVIDIA CUDA GPU。托管 Codex 要求上述确定版本及受支持的模型工具解析器;
|
|
150
|
+
不支持的硬件不会回退到云模型。
|
|
151
|
+
|
|
152
|
+
远程推理可以通过 Harness 的模型 API 配置接入,也可以注册托管模型节点。
|
|
153
|
+
节点模型仍使用 `local/<name>`,由绑定选择远程 GPU 主机。配置、Docker 访问、
|
|
154
|
+
并行容量与服务恢复见[模型推理指南](https://rsigear.xyz/docs/hitch/zh/model-inference)。
|
|
133
155
|
|
|
134
|
-
##
|
|
156
|
+
## 并行执行与恢复
|
|
135
157
|
|
|
136
|
-
|
|
137
|
-
|
|
158
|
+
提交一次,用同一个 Eval ID 跟踪执行与恢复。
|
|
159
|
+
|
|
160
|
+
- [x] 多个评测共享 CPU、内存和 GPU 预算。
|
|
161
|
+
- [x] 任务槽位释放后,小评测也能获得调度机会。
|
|
162
|
+
- [x] Daemon 崩溃后接管受支持的存活 Trial。
|
|
163
|
+
- [x] 补收已完成结果,继续未启动任务。
|
|
164
|
+
- [x] 只修复选中的失败,保留有效结果。
|
|
165
|
+
|
|
166
|
+
存活进程接管要求 POSIX 和完整的执行证据;普通 Harness Run 不会在 daemon
|
|
167
|
+
崩溃后自动续跑。
|
|
168
|
+
|
|
169
|
+
[配置、示例与恢复边界 →](https://rsigear.xyz/docs/hitch/zh/daemon)
|
|
170
|
+
|
|
171
|
+
## 评测模型与 Harness
|
|
172
|
+
|
|
173
|
+
- [x] **比较模型:** 固定 Harness、任务和评测配置,更换模型。
|
|
174
|
+
- [x] **比较 Harness:** 固定模型和任务,更换 Harness 或其版本。
|
|
175
|
+
- [x] **无工具模型评测:** 对兼容的 Benchmark 任务使用可信的 `model-call` 驱动。
|
|
176
|
+
|
|
177
|
+
当前执行后端为 Harbor。下面的 Docker 示例需要 Python 3.12+、运行中的
|
|
178
|
+
Docker daemon,以及容器能够使用的模型认证。自定义任务和驱动要求见
|
|
179
|
+
[Benchmark Package](docs/benchmark-packages.md)。
|
|
138
180
|
|
|
139
181
|
```bash
|
|
140
182
|
hitch eval setup harbor
|
|
141
183
|
hitch eval doctor
|
|
142
|
-
|
|
143
|
-
hitch eval run \
|
|
144
|
-
--backend harbor \
|
|
145
|
-
--dataset terminal-bench@2.0 \
|
|
146
|
-
--harness codex@version:0.92.0 \
|
|
147
|
-
--model openai/gpt-5.6
|
|
148
184
|
```
|
|
149
185
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
186
|
+
先按[单任务评测教程](https://rsigear.xyz/docs/hitch/zh/evaluations)运行附带的
|
|
187
|
+
[Hello Hitch 任务](docs/guide/examples/hello-hitch),完成容器认证、执行和结果
|
|
188
|
+
检查,再扩展到大型 Benchmark。若 Hitch daemon 已占用状态目录,按指南使用
|
|
189
|
+
`hitch eval run --daemon` 或 `hitch eval submit`。
|
|
190
|
+
|
|
191
|
+
每个 Trial 发布一个 Hitch Run,关联模型身份、Harness 版本、控制器运行时、后端配置、
|
|
192
|
+
奖励、日志和轨迹。有效零分与无效 observation 会分别处理。Benchmark、资源和
|
|
193
|
+
可移植性契约见 [Harbor 参考](docs/evals.md)。
|
|
194
|
+
|
|
195
|
+
## 支持的 Harness
|
|
196
|
+
|
|
197
|
+
| Harness | 已安装的可执行文件 | 确定的软件包版本 | 源码提交 |
|
|
198
|
+
| --- | :---: | :---: | :---: |
|
|
199
|
+
| Codex | ✓ | ✓ | ✓ |
|
|
200
|
+
| Claude Code | ✓ | ✓ | — |
|
|
201
|
+
| Pi | ✓ | ✓ | ✓ |
|
|
202
|
+
| OpenCode | ✓ | ✓ | — |
|
|
203
|
+
| DeepSeek Harness | ✓ | ✓ | ✓ |
|
|
153
204
|
|
|
154
|
-
|
|
205
|
+
使用 `codex@installed` 运行本机程序,使用 `codex@version:0.92.0` 选择确定的
|
|
206
|
+
软件包版本,或把真实上游提交填入 `codex@commit:COMMIT`。评测要求可移植的
|
|
207
|
+
版本或提交引用。引用选择、制品准备和工作区模式见
|
|
208
|
+
[固定版本与隔离工作区](docs/guide/zh-CN/versions-and-workspaces.md)。
|
|
155
209
|
|
|
156
|
-
|
|
157
|
-
- 支持直接执行或具有并发上限的持久化守护进程
|
|
158
|
-
- 支持共享、detached Git worktree 和独立副本工作区
|
|
159
|
-
- 支持超时、取消、进程树清理和中断运行恢复
|
|
160
|
-
- 通过 `--root <path>` 或 `HITCH_ROOT` 隔离本地状态
|
|
210
|
+
## User Guide · 用户指南
|
|
161
211
|
|
|
162
|
-
|
|
212
|
+
**[在线阅读用户指南](https://rsigear.xyz/docs/hitch/zh/)**,也可以查看
|
|
213
|
+
[仓库中的同一份 Markdown](docs/guide/zh-CN/index.md)。
|
|
163
214
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
215
|
+
| 指南 | 你会学到什么 |
|
|
216
|
+
| --- | --- |
|
|
217
|
+
| [Quick Start](docs/guide/zh-CN/quickstart.md) | 安装、认证、运行任务并提交并行工作 |
|
|
218
|
+
| [本地与远程模型推理](docs/guide/zh-CN/model-inference.md) | 接入远程 API、托管本机 SGLang 和远程模型节点 |
|
|
219
|
+
| [固定版本与隔离工作区](docs/guide/zh-CN/versions-and-workspaces.md) | 固定可执行版本,选择 worktree、copy 或 shared 模式 |
|
|
220
|
+
| [查看运行与证据](docs/guide/zh-CN/runs-and-evidence.md) | 查询结果、轨迹、Verifier 证据和消息反馈 |
|
|
221
|
+
| [第一次评测](docs/guide/zh-CN/evaluations.md) | 运行小型 Docker 任务,理解有效与无效结果 |
|
|
222
|
+
| [Daemon:并行与恢复](docs/guide/zh-CN/daemon.md) | 配置资源预算、共享容量并恢复中断的评测 |
|
|
223
|
+
| [日常运行与排错](docs/guide/zh-CN/operations.md) | 查看队列、取消任务、选择状态目录并诊断失败 |
|
|
224
|
+
| [CLI 命令参考](docs/guide/zh-CN/cli-reference.md) | 查询全部命令、参数、筛选条件和集成入口 |
|
|
168
225
|
|
|
169
|
-
|
|
226
|
+
<details>
|
|
227
|
+
<summary><strong>技术参考与平台说明</strong></summary>
|
|
170
228
|
|
|
171
229
|
- [设计与架构](docs/design.md)
|
|
230
|
+
- [Benchmark Package 与任务协议](docs/benchmark-packages.md)
|
|
172
231
|
- [Harbor 评测](docs/evals.md)
|
|
173
232
|
- [Verifier evidence](docs/verifier-evidence.md)
|
|
174
233
|
- [工作区隔离](docs/workspaces.md)
|
|
175
|
-
- [
|
|
234
|
+
- [Daemon 设计](docs/daemon.md)
|
|
235
|
+
- [带版本的机器接口 Schema](docs/schemas)
|
|
176
236
|
- [Hitch 0.2 开发规范](docs/hitch-0.2-development-spec.md)
|
|
177
237
|
- [发布流程](docs/releasing.md)
|
|
238
|
+
- [贡献指南](CONTRIBUTING.md)
|
|
178
239
|
|
|
179
|
-
|
|
240
|
+
自动化流程可以使用 JSON/JSONL 输出、类型化错误、有界证据查询、超时、取消和
|
|
241
|
+
进程树清理。通过 `--root` 或 `HITCH_ROOT` 选择独立状态目录,并在所有命令中
|
|
242
|
+
保持一致。
|
|
243
|
+
|
|
244
|
+
Windows 已覆盖 Node 22 和 24,包括 npm/Agent 的 `.cmd` 包装程序以及软件包
|
|
245
|
+
Harness 缓存和完整性校验。Daemon 硬崩溃后的本地存活 Harbor 进程接管仅支持 POSIX。
|
|
180
246
|
|
|
181
|
-
|
|
182
|
-
|
|
247
|
+
GPU Harbor Trial 需要兼容的 Docker 主机,以及显式的 `--capacity-gpus` 和
|
|
248
|
+
`--eval-gpus` 参数;Hitch 不会猜测 GPU 容量。维护者可以在兼容的自托管 Runner
|
|
249
|
+
上运行 `NVIDIA GPU hardware canary` 工作流。
|
|
250
|
+
|
|
251
|
+
</details>
|
|
252
|
+
|
|
253
|
+
## 项目状态
|
|
183
254
|
|
|
184
|
-
|
|
255
|
+
Hitch 是 pre-alpha 阶段的模型与 Harness 评测执行层。远端制品同步、命名候选、晋级记录
|
|
256
|
+
和更多 Harness 适配器已列入计划。它是 Git 的补充,目前不提供远端制品注册表、
|
|
257
|
+
分支、标签、候选晋级或回滚策略。
|
|
185
258
|
|
|
186
259
|
## 社区
|
|
187
260
|
|
|
188
|
-
加入 [
|
|
189
|
-
|
|
261
|
+
加入 [Discord](https://discord.gg/cZ4NBbHDk),提问、分享反馈,并讨论模型与
|
|
262
|
+
智能体评测基础设施。
|
|
190
263
|
|
|
191
|
-
Hitch 的设计受到 [Multica](https://github.com/multica-ai/multica)
|
|
192
|
-
[Harbor](https://github.com/harbor-framework/harbor)
|
|
264
|
+
Hitch 的设计受到 [Multica](https://github.com/multica-ai/multica) 启发,采用
|
|
265
|
+
[Harbor](https://github.com/harbor-framework/harbor) 的任务定义格式,并集成
|
|
266
|
+
[SGLang](https://github.com/sgl-project/sglang),提供托管的本地与远程模型推理支持。
|
|
193
267
|
|
|
194
268
|
## 许可证
|
|
195
269
|
|
|
196
|
-
|
|
270
|
+
[Apache License 2.0](LICENSE)。
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { remoteCanaryWorker } from "./canary-worker-host.js";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { createWriteStream } from "node:fs";
|
|
5
|
+
import { mkdir, mkdtemp, readFile, readdir, writeFile } from "node:fs/promises";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { pathToFileURL } from "node:url";
|
|
9
|
+
import { DaemonServer, daemonClient } from "../src/daemon/index.js";
|
|
10
|
+
import { readExecutionLeases, reapOwnedDockerResources, runEval, validateEvalId } from "../src/evals/index.js";
|
|
11
|
+
import { parseTrainingBinding } from "../src/model-access/index.js";
|
|
12
|
+
import { atomicWriteJSON, runCommand, sha256JSON, statePaths } from "../src/foundation/index.js";
|
|
13
|
+
// Real Harbor/Docker and public worker CLI against a separately supervised native gateway.
|
|
14
|
+
// The node independently verifies exact receipts; neither script certifies a training runtime.
|
|
15
|
+
const python = process.env.HITCH_HARBOR_TEST_PYTHON;
|
|
16
|
+
const image = process.env.HITCH_TRAINING_CANARY_IMAGE;
|
|
17
|
+
assert.ok(python && image, "Set HITCH_HARBOR_TEST_PYTHON and HITCH_TRAINING_CANARY_IMAGE (local bash-capable image)");
|
|
18
|
+
const harbor = path.join(path.dirname(python), "harbor");
|
|
19
|
+
const cli = path.resolve("dist/bin/hitch.js");
|
|
20
|
+
const root = await mkdtemp(path.join(tmpdir(), "hitch-native-remote-training-"));
|
|
21
|
+
const externalFile = process.env.HITCH_NATIVE_CANARY_BINDING;
|
|
22
|
+
const output = process.env.HITCH_NATIVE_CANARY_OUTPUT;
|
|
23
|
+
const taskInputFile = process.env.HITCH_NATIVE_CANARY_TASK_INPUT;
|
|
24
|
+
assert.ok(taskInputFile, "Set HITCH_NATIVE_CANARY_TASK_INPUT");
|
|
25
|
+
const taskInput = JSON.parse(await readFile(taskInputFile, "utf8"));
|
|
26
|
+
assert.equal(taskInput.kind, "native-diagnostic-task-input");
|
|
27
|
+
assert.equal(typeof taskInput.instruction, "string");
|
|
28
|
+
assert.ok(externalFile && output, "Set HITCH_NATIVE_CANARY_BINDING and HITCH_NATIVE_CANARY_OUTPUT");
|
|
29
|
+
await mkdir(output, { recursive: true });
|
|
30
|
+
const external = JSON.parse(await readFile(externalFile, "utf8"));
|
|
31
|
+
const binding = parseTrainingBinding(external.binding);
|
|
32
|
+
const secret = external.credential;
|
|
33
|
+
const endpoint = new URL(external.base_url);
|
|
34
|
+
assert.equal(endpoint.protocol, "http:");
|
|
35
|
+
assert.equal(endpoint.hostname, "127.0.0.1");
|
|
36
|
+
assert.equal(endpoint.pathname, "/v1");
|
|
37
|
+
assert.match(secret, /^[a-f0-9]{64}$/);
|
|
38
|
+
const controllerRoot = path.join(root, "controller"), workerRoot = path.join(root, "worker");
|
|
39
|
+
const privateRoot = path.join(root, "private"), dataset = path.join(root, "dataset");
|
|
40
|
+
await mkdir(privateRoot, { recursive: true, mode: 0o700 });
|
|
41
|
+
const resource = { cpu_millis: 1000, memory_bytes: 1024 ** 3, container_slots: 1, build_slots: 0 };
|
|
42
|
+
const zero = { cpu_millis: 0, memory_bytes: 0, container_slots: 0, build_slots: 0 };
|
|
43
|
+
const env = { ...process.env, HITCH_HARBOR_PYTHON_PATH: python };
|
|
44
|
+
delete env.HITCH_TEST_HOST_ARTIFACT_BUILDER;
|
|
45
|
+
const imageInfo = await runCommand("docker", ["image", "inspect", image, "--format", "{{json .}}"], { timeoutMs: 10_000 });
|
|
46
|
+
const inspected = JSON.parse(imageInfo.stdout);
|
|
47
|
+
assert.match(inspected.Id, /^sha256:[a-f0-9]{64}$/);
|
|
48
|
+
assert.equal(inspected.Id, taskInput.image_id);
|
|
49
|
+
assert.equal(`${inspected.Os}/${inspected.Architecture}`, "linux/amd64");
|
|
50
|
+
const version = (await runCommand(python, ["-c", 'import importlib.metadata; print(importlib.metadata.version("harbor"))'], { timeoutMs: 10_000 })).stdout.trim();
|
|
51
|
+
assert.equal(version, "0.21.0");
|
|
52
|
+
const localEngine = (await runCommand("docker", ["info", "--format", "{{.ID}}"], { timeoutMs: 10_000 })).stdout.trim();
|
|
53
|
+
const remoteWorker = await remoteCanaryWorker(root, workerRoot);
|
|
54
|
+
const workerObservation = await remoteWorker?.observe(inspected.Id, localEngine);
|
|
55
|
+
const engine = workerObservation?.engine ?? localEngine;
|
|
56
|
+
const server = new DaemonServer({ root: controllerRoot, port: 0, maxConcurrent: 1,
|
|
57
|
+
resourceCapacity: { ...resource, build_slots: 1 }, evalTrialResources: resource,
|
|
58
|
+
evalExecutor: options => runEval({ ...options, harborExecutable: harbor, env }), logger: () => { } });
|
|
59
|
+
let worker;
|
|
60
|
+
let workerDone;
|
|
61
|
+
const workerLog = createWriteStream(path.join(root, "worker.log"));
|
|
62
|
+
let evalId;
|
|
63
|
+
let passed = false;
|
|
64
|
+
const summary = { kind: "native-harbor-training-transport-diagnostic", validated_gpu: false, worker_host: remoteWorker ? "ssh" : "local-process", root, harbor: version, image_id: inspected.Id, docker_engine_digest: sha256JSON(engine) };
|
|
65
|
+
console.log(JSON.stringify({ event: "canary-start", root, image_id: inspected.Id }));
|
|
66
|
+
try {
|
|
67
|
+
const harness = await prepareInputs();
|
|
68
|
+
await server.start();
|
|
69
|
+
const registration = { schema_version: "1", worker_id: "worker_real_training", provider: "remote-docker",
|
|
70
|
+
collision_domain_id: `docker-engine:${engine}`, platforms: ["linux-x64"], backends: [{ id: "harbor", version }],
|
|
71
|
+
features: { docker: true, buildkit: true, model_proxy: true, isolated_same_task_attempts: false, training_external_binding: "2" },
|
|
72
|
+
task_membership: ["known"], capacity: { total: resource, reserved_for_system: zero, allocatable: resource } };
|
|
73
|
+
const registrationFile = path.join(privateRoot, "registration.json"), credentialFile = path.join(privateRoot, "worker-credential.json");
|
|
74
|
+
const bindingFile = path.join(privateRoot, "binding.json");
|
|
75
|
+
await atomicWriteJSON(registrationFile, registration);
|
|
76
|
+
await atomicWriteJSON(bindingFile, { schema_version: "1", binding, base_url: external.base_url, credential: secret });
|
|
77
|
+
await runCommand(process.execPath, [cli, "--root", controllerRoot, "training", "register", "--file", bindingFile], { env, timeoutMs: 10_000 });
|
|
78
|
+
const baseUrl = `http://127.0.0.1:${server.port}`;
|
|
79
|
+
await runCommand(process.execPath, [cli, "worker", "register", "--server", baseUrl, "--registration", registrationFile,
|
|
80
|
+
"--admin-token-file", statePaths(controllerRoot).token, "--credential-file", credentialFile], { env, timeoutMs: 10_000 });
|
|
81
|
+
worker = remoteWorker ? await remoteWorker.start(server.port, registrationFile, credentialFile) : spawn(process.execPath, [cli, "--root", workerRoot, "worker", "run", "--server", baseUrl, "--registration", registrationFile,
|
|
82
|
+
"--credential-file", credentialFile, "--harbor", harbor, "--docker", "/usr/local/bin/docker", "--once", "--poll-interval", "100ms", "--heartbeat-interval", "1s"], { env, stdio: ["ignore", "pipe", "pipe"] });
|
|
83
|
+
worker.stdout.pipe(workerLog, { end: false });
|
|
84
|
+
worker.stderr.pipe(workerLog, { end: false });
|
|
85
|
+
workerDone = new Promise((resolve, reject) => { worker.once("error", reject); worker.once("exit", code => resolve(code)); });
|
|
86
|
+
void workerDone.catch(() => { });
|
|
87
|
+
const admin = await daemonClient(controllerRoot);
|
|
88
|
+
const submitted = await admin.request("/v1/evals", { method: "POST", body: JSON.stringify({
|
|
89
|
+
request: { dataset, harness_ref: harness, model: `training/${binding.bindingId}`, training_binding: binding,
|
|
90
|
+
max_concurrent: 1, attempts: 1, infrastructure_retries: 0, timeout_ms: 120_000, setup_timeout_ms: 120_000 },
|
|
91
|
+
execution: { provider: "remote-docker", max_parallelism: 1, resources: { default_trial: resource },
|
|
92
|
+
build: { mode: "backend" }, model_capture: { mode: "proxy", required: true } },
|
|
93
|
+
}) });
|
|
94
|
+
evalId = validateEvalId(String(submitted.eval_id));
|
|
95
|
+
console.log(JSON.stringify({ event: "eval-submitted", eval_id: evalId }));
|
|
96
|
+
const deadline = Date.now() + 5 * 60_000;
|
|
97
|
+
let current = {}, previous = "";
|
|
98
|
+
while (Date.now() < deadline) {
|
|
99
|
+
current = await admin.request(`/v1/evals/${evalId}`);
|
|
100
|
+
const phase = JSON.stringify(current.control);
|
|
101
|
+
if (phase !== previous) {
|
|
102
|
+
previous = phase;
|
|
103
|
+
console.log(JSON.stringify({ event: "eval-control", control: current.control }));
|
|
104
|
+
}
|
|
105
|
+
if (current.result)
|
|
106
|
+
break;
|
|
107
|
+
if (worker.exitCode !== null && worker.exitCode !== 0)
|
|
108
|
+
throw new Error(`worker exited before result (${worker.exitCode})`);
|
|
109
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
110
|
+
}
|
|
111
|
+
await atomicWriteJSON(path.join(root, "eval-inspection.json"), current);
|
|
112
|
+
assert.ok(current.result, "real Harbor candidate timed out");
|
|
113
|
+
const result = current.result;
|
|
114
|
+
assert.equal(result.status, "succeeded", JSON.stringify(result));
|
|
115
|
+
assert.equal(result.trials.length, 1);
|
|
116
|
+
assert.equal(result.trials[0].observation_status, "valid");
|
|
117
|
+
const taskReward = result.trials[0].reward;
|
|
118
|
+
assert.ok(taskReward === 0 || taskReward === 1, "the task verifier must return a valid binary reward");
|
|
119
|
+
const boundRun = result.trials[0].run_id;
|
|
120
|
+
const evidence = await runCommand(process.execPath, [cli, "--root", controllerRoot, "training", "evidence", boundRun, "--json"], { env, timeoutMs: 10_000 });
|
|
121
|
+
await writeFile(path.join(root, "training-evidence.json"), evidence.stdout);
|
|
122
|
+
const nativeEvidence = JSON.parse(evidence.stdout);
|
|
123
|
+
assert.equal(nativeEvidence.termination, "terminated");
|
|
124
|
+
assert.equal(nativeEvidence.training_external.policy_version, binding.expectedPolicyVersion);
|
|
125
|
+
const trajectoryPath = nativeEvidence.result.trajectory.path;
|
|
126
|
+
assert.ok(!path.isAbsolute(trajectoryPath) && !trajectoryPath.split("/").includes(".."));
|
|
127
|
+
const trajectory = await readFile(path.join(controllerRoot, "runs", boundRun, trajectoryPath), "utf8");
|
|
128
|
+
const events = trajectory.trim().split("\n").map(line => JSON.parse(line));
|
|
129
|
+
const toolCalls = events.filter(event => event.data?.provider_type === "tool.completed").length;
|
|
130
|
+
const responses = events.filter(event => event.data?.provider_type === "provider.response");
|
|
131
|
+
assert.ok(toolCalls >= 2 && responses.length >= 2, "two sequential tool calls and a subsequent model reply are required");
|
|
132
|
+
assert.ok(responses.every(event => /^receipt_[a-f0-9]{32}$/.test(event.data?.native?.receipt_id ?? "")));
|
|
133
|
+
const receiptIds = responses.map(event => event.data.native.receipt_id);
|
|
134
|
+
assert.equal(new Set(receiptIds).size, receiptIds.length);
|
|
135
|
+
await writeFile(path.join(output, "trajectory.jsonl"), trajectory);
|
|
136
|
+
await writeFile(path.join(output, "training-evidence.json"), evidence.stdout);
|
|
137
|
+
const verifier = await runCommand(process.execPath, [cli, "--root", controllerRoot, "verifier", "inspect", boundRun, "--json"], { env, timeoutMs: 10_000 });
|
|
138
|
+
await writeFile(path.join(output, "verifier.json"), verifier.stdout);
|
|
139
|
+
await atomicWriteJSON(path.join(output, "eval-inspection.json"), current);
|
|
140
|
+
const leases = await readExecutionLeases(path.join(controllerRoot, "evals", evalId));
|
|
141
|
+
assert.equal(leases.length, 1);
|
|
142
|
+
assert.equal(leases[0].state, "released");
|
|
143
|
+
assert.ok(leases[0].release_confirmation);
|
|
144
|
+
assert.equal(await Promise.race([workerDone, new Promise(resolve => setTimeout(() => resolve("timeout"), 10_000))]), 0);
|
|
145
|
+
await remoteWorker?.collect();
|
|
146
|
+
for (const directory of [path.join(controllerRoot, "runs"), path.join(controllerRoot, "evals"), workerRoot]) {
|
|
147
|
+
for (const file of await regularFiles(directory))
|
|
148
|
+
assert.equal((await readFile(file)).includes(Buffer.from(secret)), false, `model credential leaked into ${file}`);
|
|
149
|
+
}
|
|
150
|
+
Object.assign(summary, { status: "passed", task_reward: taskReward, task_succeeded: taskReward === 1,
|
|
151
|
+
eval_id: evalId, run_id: boundRun, model_calls: responses.length, tool_calls: toolCalls, receipt_ids: receiptIds, lease_id: leases[0].lease_id, private_model_credential_in_public_files: false });
|
|
152
|
+
passed = true;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
Object.assign(summary, { status: "failed", error: error instanceof Error ? error.message : String(error) });
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
if (evalId && !passed) {
|
|
160
|
+
const admin = await daemonClient(controllerRoot).catch(() => undefined);
|
|
161
|
+
await admin?.request(`/v1/evals/${evalId}/cancel`, { method: "POST", body: "{}" }).catch(() => { });
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
await remoteWorker?.stop();
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
summary.remote_stop_error = error instanceof Error ? error.message : String(error);
|
|
168
|
+
}
|
|
169
|
+
if (worker && worker.exitCode === null)
|
|
170
|
+
worker.kill("SIGTERM");
|
|
171
|
+
if (workerDone)
|
|
172
|
+
await Promise.race([workerDone.catch(() => null), new Promise(resolve => setTimeout(resolve, 10_000))]);
|
|
173
|
+
if (worker && worker.exitCode === null) {
|
|
174
|
+
worker.kill("SIGKILL");
|
|
175
|
+
await workerDone?.catch(() => null);
|
|
176
|
+
}
|
|
177
|
+
workerLog.end();
|
|
178
|
+
await server.close();
|
|
179
|
+
const leases = evalId ? await readExecutionLeases(path.join(controllerRoot, "evals", evalId)).catch(() => []) : [];
|
|
180
|
+
const leaseIds = leases.map(lease => lease.lease_id);
|
|
181
|
+
const cleanup = await Promise.all([
|
|
182
|
+
reapOwnedDockerResources({ root: controllerRoot, leaseIds, env }),
|
|
183
|
+
remoteWorker ? remoteWorker.cleanup(leaseIds).catch(error => ({ issues: [String(error)], retained: [] }))
|
|
184
|
+
: reapOwnedDockerResources({ root: workerRoot, leaseIds, env }),
|
|
185
|
+
]);
|
|
186
|
+
if (remoteWorker && !passed)
|
|
187
|
+
await remoteWorker.collect().catch(error => { summary.remote_collection_error = String(error); });
|
|
188
|
+
summary.cleanup_proven = !summary.remote_stop_error && cleanup.every(report => report.issues.length === 0 && report.retained.length === 0);
|
|
189
|
+
await atomicWriteJSON(path.join(root, "summary.json"), summary);
|
|
190
|
+
await atomicWriteJSON(path.join(output, "summary.json"), summary);
|
|
191
|
+
console.log(JSON.stringify(summary));
|
|
192
|
+
}
|
|
193
|
+
assert.equal(summary.cleanup_proven, true, "owned Docker resources were not all released");
|
|
194
|
+
async function prepareInputs() {
|
|
195
|
+
const task = path.join(dataset, "one"), source = path.join(root, "training-source");
|
|
196
|
+
await mkdir(path.join(task, "environment"), { recursive: true });
|
|
197
|
+
await mkdir(path.join(task, "tests"));
|
|
198
|
+
await writeFile(path.join(task, "instruction.md"), taskInput.instruction);
|
|
199
|
+
await writeFile(path.join(task, "environment/Dockerfile"), `FROM ${inspected.Id}\n`);
|
|
200
|
+
await writeFile(path.join(task, "task.toml"), `schema_version="1.4"\n[agent]\ntimeout_sec=120\n[environment]\ndocker_image="${inspected.Id}"\ncpus=1\nmemory_mb=1024\n[verifier]\ntimeout_sec=30\n`);
|
|
201
|
+
await writeFile(path.join(task, "tests/test.sh"), '#!/bin/bash\nset -eu\nmkdir -p /logs/verifier\nif test -f /tmp/gear-canary.txt && test "$(cat /tmp/gear-canary.txt)" = first-toolsecond-tool; then\n printf "1" > /logs/verifier/reward.txt\nelse\n printf "0" > /logs/verifier/reward.txt\nfi\n', { mode: 0o755 });
|
|
202
|
+
await mkdir(path.join(source, "integrations/training-tool"), { recursive: true });
|
|
203
|
+
await writeFile(path.join(source, "integrations/training-tool/cli.js"), await readFile("integrations/training-tool/cli.js"), { mode: 0o755 });
|
|
204
|
+
await writeFile(path.join(source, "package.json"), '{"type":"module"}');
|
|
205
|
+
for (const args of [["init"], ["add", "."], ["-c", "user.name=Hitch Canary", "-c", "user.email=canary@hitch.invalid", "commit", "-m", "fixed training harness canary"]])
|
|
206
|
+
await runCommand("git", args, { cwd: source, timeoutMs: 10_000 });
|
|
207
|
+
const commit = (await runCommand("git", ["rev-parse", "HEAD"], { cwd: source, timeoutMs: 10_000 })).stdout.trim();
|
|
208
|
+
return `training-tool@git+${pathToFileURL(source).href}#${commit}`;
|
|
209
|
+
}
|
|
210
|
+
async function regularFiles(directory) {
|
|
211
|
+
const files = [];
|
|
212
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
213
|
+
const file = path.join(directory, entry.name);
|
|
214
|
+
if (entry.isDirectory())
|
|
215
|
+
files.push(...await regularFiles(file));
|
|
216
|
+
else if (entry.isFile())
|
|
217
|
+
files.push(file);
|
|
218
|
+
}
|
|
219
|
+
return files;
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=canary-native-training.js.map
|