agent-hitch 0.2.13 → 0.2.15
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/benchmark-packages/automationbench/RESOURCES.md +27 -0
- package/benchmark-packages/automationbench/resources.mjs +86 -0
- package/benchmark-packages/shared-tree/README.md +14 -0
- package/benchmark-packages/shared-tree/import.mjs +39 -0
- package/dist/scripts/canary-automation-resources.js +86 -0
- package/dist/scripts/canary-automation-resources.js.map +1 -0
- package/dist/scripts/canary-resource-empty-daemon.js +195 -0
- package/dist/scripts/canary-resource-empty-daemon.js.map +1 -0
- package/dist/scripts/canary-resources.js +89 -0
- package/dist/scripts/canary-resources.js.map +1 -0
- package/dist/scripts/check-architecture.js +6 -5
- package/dist/scripts/check-architecture.js.map +1 -1
- package/dist/scripts/resource-space-sampler.js +83 -0
- package/dist/scripts/resource-space-sampler.js.map +1 -0
- package/dist/src/backends/harbor/backend.js +5 -1
- package/dist/src/backends/harbor/backend.js.map +1 -1
- package/dist/src/backends/harbor/resource-admission.js +23 -0
- package/dist/src/backends/harbor/resource-admission.js.map +1 -0
- package/dist/src/cli/commands/resources.js +23 -0
- package/dist/src/cli/commands/resources.js.map +1 -0
- package/dist/src/cli/main.js +2 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/control-plane/remote-offer-contract.js +11 -2
- package/dist/src/control-plane/remote-offer-contract.js.map +1 -1
- package/dist/src/control-plane/remote-result-transport.js +10 -0
- package/dist/src/control-plane/remote-result-transport.js.map +1 -1
- package/dist/src/control-plane/remote-work-coordinator.js +4 -1
- package/dist/src/control-plane/remote-work-coordinator.js.map +1 -1
- package/dist/src/control-plane/remote-work-inputs.js +16 -4
- package/dist/src/control-plane/remote-work-inputs.js.map +1 -1
- package/dist/src/control-plane/remote-worker-client.js +22 -0
- package/dist/src/control-plane/remote-worker-client.js.map +1 -1
- package/dist/src/control-plane/remote-worker-codecs.js +1 -1
- package/dist/src/control-plane/remote-worker-codecs.js.map +1 -1
- package/dist/src/control-plane/remote-worker-protocol.js +12 -2
- package/dist/src/control-plane/remote-worker-protocol.js.map +1 -1
- package/dist/src/control-plane/remote-worker-runner.js +1 -1
- package/dist/src/control-plane/remote-worker-runner.js.map +1 -1
- package/dist/src/control-plane/remote-workers.js +2 -1
- package/dist/src/control-plane/remote-workers.js.map +1 -1
- package/dist/src/evals/benchmark-adapter-manifest.js +4 -0
- package/dist/src/evals/benchmark-adapter-manifest.js.map +1 -1
- package/dist/src/evals/benchmark-candidate.js +11 -3
- package/dist/src/evals/benchmark-candidate.js.map +1 -1
- package/dist/src/evals/eval-result-builder.js +22 -1
- package/dist/src/evals/eval-result-builder.js.map +1 -1
- package/dist/src/evals/index.js +1 -0
- package/dist/src/evals/index.js.map +1 -1
- package/dist/src/evals/planned-execution.js +5 -14
- package/dist/src/evals/planned-execution.js.map +1 -1
- package/dist/src/evals/request.js +9 -0
- package/dist/src/evals/request.js.map +1 -1
- package/dist/src/evals/resource-eval-lifecycle.js +31 -0
- package/dist/src/evals/resource-eval-lifecycle.js.map +1 -0
- package/dist/src/evals/resource-legacy-export.js +57 -0
- package/dist/src/evals/resource-legacy-export.js.map +1 -0
- package/dist/src/evals/service.js +5 -20
- package/dist/src/evals/service.js.map +1 -1
- package/dist/src/evals/task-resources.js +12 -4
- package/dist/src/evals/task-resources.js.map +1 -1
- package/dist/src/evals/trial-bundle-files.js +81 -0
- package/dist/src/evals/trial-bundle-files.js.map +1 -0
- package/dist/src/evals/trial-import.js +7 -78
- package/dist/src/evals/trial-import.js.map +1 -1
- package/dist/src/foundation/durable-json.js +33 -0
- package/dist/src/foundation/durable-json.js.map +1 -0
- package/dist/src/foundation/index.js +2 -0
- package/dist/src/foundation/index.js.map +1 -1
- package/dist/src/foundation/resource-image-references.js +52 -0
- package/dist/src/foundation/resource-image-references.js.map +1 -0
- package/dist/src/images/gc.js +2 -2
- package/dist/src/images/gc.js.map +1 -1
- package/dist/src/images/registry.js +27 -2
- package/dist/src/images/registry.js.map +1 -1
- package/dist/src/resources/api.js +207 -0
- package/dist/src/resources/api.js.map +1 -0
- package/dist/src/resources/bundle.js +117 -0
- package/dist/src/resources/bundle.js.map +1 -0
- package/dist/src/resources/evidence.js +93 -0
- package/dist/src/resources/evidence.js.map +1 -0
- package/dist/src/resources/gc.js +123 -0
- package/dist/src/resources/gc.js.map +1 -0
- package/dist/src/resources/index.js +14 -0
- package/dist/src/resources/index.js.map +1 -0
- package/dist/src/resources/materialize.js +143 -0
- package/dist/src/resources/materialize.js.map +1 -0
- package/dist/src/resources/object-store.js +191 -0
- package/dist/src/resources/object-store.js.map +1 -0
- package/dist/src/resources/oci-layer-validation.js +202 -0
- package/dist/src/resources/oci-layer-validation.js.map +1 -0
- package/dist/src/resources/oci-provider.js +101 -0
- package/dist/src/resources/oci-provider.js.map +1 -0
- package/dist/src/resources/oci-registry-bundle.js +253 -0
- package/dist/src/resources/oci-registry-bundle.js.map +1 -0
- package/dist/src/resources/protocol.js +222 -0
- package/dist/src/resources/protocol.js.map +1 -0
- package/dist/src/resources/result-retention.js +93 -0
- package/dist/src/resources/result-retention.js.map +1 -0
- package/dist/src/resources/role-context.js +54 -0
- package/dist/src/resources/role-context.js.map +1 -0
- package/dist/src/resources/stats.js +36 -0
- package/dist/src/resources/stats.js.map +1 -0
- package/dist/src/resources/store.js +310 -0
- package/dist/src/resources/store.js.map +1 -0
- package/dist/src/resources/tasks.js +153 -0
- package/dist/src/resources/tasks.js.map +1 -0
- package/dist/src/resources/transfer.js +162 -0
- package/dist/src/resources/transfer.js.map +1 -0
- package/dist/src/resources/views.js +130 -0
- package/dist/src/resources/views.js.map +1 -0
- package/dist/src/runs/adapter-process.js +10 -0
- package/dist/src/runs/adapter-process.js.map +1 -1
- package/dist/src/runs/executor.js +2 -2
- package/dist/src/runs/executor.js.map +1 -1
- package/dist/src/trajectories/providers/deepseek.js +6 -1
- package/dist/src/trajectories/providers/deepseek.js.map +1 -1
- package/dist/src/workers/remote-harbor-work-spec.js +9 -3
- package/dist/src/workers/remote-harbor-work-spec.js.map +1 -1
- package/dist/src/workers/remote-harbor-worker.js +24 -9
- package/dist/src/workers/remote-harbor-worker.js.map +1 -1
- package/docs/resource-storage.zh-CN.md +95 -0
- package/docs/schemas/execution-provider-status.schema.json +20 -0
- package/docs/schemas/hitch-resource-dataset-v2.schema.json +590 -0
- package/docs/schemas/hitch-resource-lock-v1.schema.json +341 -0
- package/docs/schemas/hitch-resource-plan-v1.schema.json +423 -0
- package/docs/schemas/hitch-resource-selection-v1.schema.json +608 -0
- package/docs/schemas/hitch-tree-v1.schema.json +75 -0
- package/docs/schemas/remote-harbor-work-spec.schema.json +47 -3
- package/docs/schemas/remote-work-offer.schema.json +2 -1
- package/docs/schemas/remote-worker-registration.schema.json +20 -0
- package/package.json +9 -3
- package/test-contracts/hitch-resources-v1.json +197 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { resourceDescriptorDirectory } from "./views.js";
|
|
2
|
+
import { validateRoleContexts } from "./role-context.js";
|
|
3
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { canonical, identity, object, parseResourceLock, parseStrictJson, portablePath, resourceId, sha } from "./protocol.js";
|
|
6
|
+
export const RESOURCE_EXECUTION_CAPABILITIES = ["blob@1", "tree@1", "oci-image@1", "input-file@1", "input-tree@1", "environment-image@1", "private-copy@1", "harbor-role-context@1"];
|
|
7
|
+
export function parseResourceTask(value) {
|
|
8
|
+
const raw = object(value, ["task_id", "source_task_digest", "resource_closure_digest", "task_digest", "sourceTree", "lock"]);
|
|
9
|
+
const tree = object(raw.sourceTree, ["kind", "format", "manifestDigest"]);
|
|
10
|
+
if (tree.kind !== "tree" || tree.format !== "hitch-tree@1")
|
|
11
|
+
throw new TypeError("task source must be a versioned tree");
|
|
12
|
+
const sourceTree = { kind: "tree", format: "hitch-tree@1", manifestDigest: sha(tree.manifestDigest) };
|
|
13
|
+
const source = identity("hitch-source-task@1", sourceTree);
|
|
14
|
+
if (sha(raw.source_task_digest) !== source)
|
|
15
|
+
throw new TypeError("source task identity mismatch");
|
|
16
|
+
const resource_closure_digest = sha(raw.resource_closure_digest), task_digest = identity("hitch-task@2", { source_task_digest: source, resource_closure_digest });
|
|
17
|
+
if (sha(raw.task_digest) !== task_digest)
|
|
18
|
+
throw new TypeError("resource task identity mismatch");
|
|
19
|
+
return { task_id: portablePath(resourceId(raw.task_id)), sourceTree, source_task_digest: source, resource_closure_digest, task_digest, lock: parseResourceLock(raw.lock) };
|
|
20
|
+
}
|
|
21
|
+
export function parseResourceDataset(value) {
|
|
22
|
+
const raw = object(value, ["schema_version", "kind", "resource_protocol", "execution", "required_capabilities", "benchmark", "adapter", "scoring", "raw_metrics", "tasks", "dataset_digest"]);
|
|
23
|
+
if (raw.schema_version !== "2" || raw.kind !== "gear-harbor-benchmark" || raw.resource_protocol !== "hitch-resource-lock@1")
|
|
24
|
+
throw new TypeError("unsupported resource dataset");
|
|
25
|
+
const execution = object(raw.execution, ["backend", "resolver", "platform"]);
|
|
26
|
+
if (execution.backend !== "harbor-role-context@1" || execution.resolver !== "hitch-resource-resolver@1" || typeof execution.platform !== "string" || !/^linux\/(amd64|arm64)(\/v[0-9]+)?$/.test(execution.platform))
|
|
27
|
+
throw new TypeError("unsupported resource execution contract");
|
|
28
|
+
const benchmark = object(raw.benchmark, ["id", "revision"]), adapter = object(raw.adapter, ["id", "revision", "output_protocol"]);
|
|
29
|
+
for (const item of [benchmark, adapter])
|
|
30
|
+
if (typeof item.id !== "string" || !item.id || typeof item.revision !== "string" || !item.revision || item.revision === "latest")
|
|
31
|
+
throw new TypeError("invalid benchmark/adapter identity");
|
|
32
|
+
if (adapter.output_protocol !== "gear-harbor-eval-result-v1" || !Array.isArray(raw.tasks) || !raw.tasks.length)
|
|
33
|
+
throw new TypeError("invalid resource dataset tasks or adapter");
|
|
34
|
+
const scoring = object(raw.scoring, ["total_score", "process_score"]);
|
|
35
|
+
for (const key of ["total_score", ...(scoring.process_score === undefined ? [] : ["process_score"])]) {
|
|
36
|
+
const score = object(scoring[key], ["source_metric", "direction", "range", "reducer"]);
|
|
37
|
+
if (typeof score.source_metric !== "string" || !score.source_metric || !["maximize", "minimize"].includes(String(score.direction)) || score.reducer !== "task-macro-mean"
|
|
38
|
+
|| !Array.isArray(score.range) || score.range.length !== 2 || !score.range.every(Number.isFinite) || score.range[0] >= score.range[1])
|
|
39
|
+
throw new TypeError("invalid resource scoring contract");
|
|
40
|
+
}
|
|
41
|
+
if (!Array.isArray(raw.required_capabilities) || raw.required_capabilities.some(c => typeof c !== "string") || new Set(raw.required_capabilities).size !== raw.required_capabilities.length)
|
|
42
|
+
throw new TypeError("invalid resource dataset capabilities");
|
|
43
|
+
if (raw.raw_metrics !== undefined) {
|
|
44
|
+
const registry = object(raw.raw_metrics, ["schema_version", "metrics"]);
|
|
45
|
+
if (registry.schema_version !== "1" || !Array.isArray(registry.metrics))
|
|
46
|
+
throw new TypeError("invalid raw metric registry");
|
|
47
|
+
}
|
|
48
|
+
const tasks = raw.tasks.map(parseResourceTask), ids = tasks.map(t => t.task_id);
|
|
49
|
+
if (new Set(ids.map(id => id.toLowerCase())).size !== ids.length || canonical(ids) !== canonical([...ids].sort()))
|
|
50
|
+
throw new TypeError("resource dataset tasks must be sorted and unique");
|
|
51
|
+
const { dataset_digest, ...body } = raw;
|
|
52
|
+
if (sha(dataset_digest) !== identity("hitch-resource-dataset@2", body))
|
|
53
|
+
throw new TypeError("resource dataset digest mismatch");
|
|
54
|
+
return { ...raw, tasks };
|
|
55
|
+
}
|
|
56
|
+
export function selectResources(dataset, ids) {
|
|
57
|
+
const sorted = [...ids].sort();
|
|
58
|
+
if (!sorted.length || new Set(ids.map(id => id.toLowerCase())).size !== ids.length || sorted.some(id => !dataset.tasks.some(t => t.task_id === id)))
|
|
59
|
+
throw new TypeError("invalid resource selection");
|
|
60
|
+
const { tasks, dataset_digest, ...manifest } = dataset;
|
|
61
|
+
const body = { protocol: "hitch-resource-selection@1", sourceDatasetDigest: dataset_digest, manifest, tasks: tasks.filter(t => sorted.includes(t.task_id)) };
|
|
62
|
+
return { ...body, digest: identity(body.protocol, body) };
|
|
63
|
+
}
|
|
64
|
+
export function parseResourceSelection(value) {
|
|
65
|
+
const raw = object(value, ["protocol", "sourceDatasetDigest", "manifest", "tasks", "digest"]);
|
|
66
|
+
if (raw.protocol !== "hitch-resource-selection@1")
|
|
67
|
+
throw new TypeError("unsupported resource selection");
|
|
68
|
+
const { digest, ...body } = raw;
|
|
69
|
+
if (sha(digest) !== identity(raw.protocol, body))
|
|
70
|
+
throw new TypeError("resource selection digest mismatch");
|
|
71
|
+
sha(raw.sourceDatasetDigest);
|
|
72
|
+
const manifest = object(raw.manifest, ["schema_version", "kind", "resource_protocol", "execution", "required_capabilities", "benchmark", "adapter", "scoring", "raw_metrics"]);
|
|
73
|
+
const datasetBody = { ...manifest, tasks: raw.tasks };
|
|
74
|
+
const dataset = parseResourceDataset({ ...datasetBody, dataset_digest: identity("hitch-resource-dataset@2", datasetBody) });
|
|
75
|
+
return { ...raw, tasks: dataset.tasks };
|
|
76
|
+
}
|
|
77
|
+
export async function readResourceInput(input) {
|
|
78
|
+
const info = await lstat(input).catch((e) => { if (e.code !== "ENOENT")
|
|
79
|
+
throw e; return undefined; });
|
|
80
|
+
if (!info)
|
|
81
|
+
return undefined;
|
|
82
|
+
if (info.isFile()) {
|
|
83
|
+
if (info.size > 16 * 1024 ** 2)
|
|
84
|
+
throw new Error("resource selection size limit exceeded");
|
|
85
|
+
return parseResourceSelection(parseStrictJson(await readFile(input, "utf8")));
|
|
86
|
+
}
|
|
87
|
+
if (!info.isDirectory())
|
|
88
|
+
throw new TypeError("resource input must be a regular file or directory");
|
|
89
|
+
try {
|
|
90
|
+
const file = path.join(input, "benchmark.adapter.json"), metadata = await lstat(file);
|
|
91
|
+
if (!metadata.isFile() || metadata.size > 16 * 1024 ** 2)
|
|
92
|
+
throw new Error("resource manifest must be a bounded regular file");
|
|
93
|
+
const text = await readFile(file, "utf8"), raw = parseStrictJson(text);
|
|
94
|
+
return raw.schema_version === "2" ? parseResourceDataset(raw) : undefined;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error.code === "ENOENT")
|
|
98
|
+
return undefined;
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export async function sealResourceTask(store, directory, taskId, owner, signal) {
|
|
103
|
+
const lock = parseResourceLock(parseStrictJson(await readFile(path.join(directory, "resource.lock.json"), "utf8")));
|
|
104
|
+
const source = await store.import(directory, "tree", `${owner}:source`, signal);
|
|
105
|
+
if (source.resource.kind !== "tree")
|
|
106
|
+
throw new Error("invalid source import");
|
|
107
|
+
const acquired = await store.acquire(owner, lock, "preflight", signal);
|
|
108
|
+
const source_task_digest = identity("hitch-source-task@1", source.resource), resource_closure_digest = acquired.closure.digest;
|
|
109
|
+
const task = { task_id: resourceId(taskId), sourceTree: source.resource, lock, source_task_digest, resource_closure_digest,
|
|
110
|
+
task_digest: identity("hitch-task@2", { source_task_digest, resource_closure_digest }) };
|
|
111
|
+
// The producer's stable durable pin retains both source and runtime inputs.
|
|
112
|
+
await store.pin({ owner, generation: 1, purpose: "dataset-task", lock: taskClosureLock(task) }, signal);
|
|
113
|
+
await store.finishLease(source.leaseId, "ended");
|
|
114
|
+
await store.finishLease(acquired.lease.id, "ended");
|
|
115
|
+
return task;
|
|
116
|
+
}
|
|
117
|
+
export function taskClosureLock(task) {
|
|
118
|
+
if ("hitch-task-source" in task.lock.resources)
|
|
119
|
+
throw new TypeError("reserved resource ID hitch-task-source");
|
|
120
|
+
return { ...task.lock, resources: { ...task.lock.resources, "hitch-task-source": task.sourceTree } };
|
|
121
|
+
}
|
|
122
|
+
export async function preflightResourceTask(store, task, input) {
|
|
123
|
+
task = parseResourceTask(task);
|
|
124
|
+
for (const capability of task.lock.requiredCapabilities)
|
|
125
|
+
if (!RESOURCE_EXECUTION_CAPABILITIES.includes(capability))
|
|
126
|
+
throw new Error(`unsupported required resource capability: ${capability}`);
|
|
127
|
+
for (const binding of task.lock.bindings)
|
|
128
|
+
if (binding.use !== "environment-image" && binding.access === "read-only")
|
|
129
|
+
throw new Error("Harbor role-context backend cannot enforce read-only input bindings");
|
|
130
|
+
for (const resource of Object.values(task.lock.resources))
|
|
131
|
+
if (resource.kind === "oci-image" && resource.platform !== input.platform)
|
|
132
|
+
throw new Error("resource platform mismatch");
|
|
133
|
+
const root = await store.pin({ owner: input.owner, generation: input.generation, purpose: "frozen-task", lock: taskClosureLock(task) }, input.signal);
|
|
134
|
+
const runtime = await store.acquire(`${input.owner}:verification`, task.lock, "preflight", input.signal);
|
|
135
|
+
if (runtime.closure.digest !== task.resource_closure_digest)
|
|
136
|
+
throw new Error("resource runtime closure changed");
|
|
137
|
+
await store.finishLease(runtime.lease.id, "ended");
|
|
138
|
+
const tree = await store.objects.readTree(task.sourceTree.manifestDigest), entry = tree.entries.find(e => e.path === "resource.lock.json");
|
|
139
|
+
if (entry?.kind !== "file" || canonical(parseResourceLock(parseStrictJson(await readFile(store.objects.objectPath(entry.digest), "utf8")))) !== canonical(task.lock))
|
|
140
|
+
throw new Error("task lock does not match its sealed source tree");
|
|
141
|
+
await validateRoleContexts(await resourceDescriptorDirectory(store, task), task.lock.bindings, input.platform, root.closure.images);
|
|
142
|
+
for (const binding of task.lock.bindings)
|
|
143
|
+
if (binding.use !== "environment-image") {
|
|
144
|
+
const role = binding.consumer.role === "candidate" ? "environment/candidate" : binding.consumer.role === "verifier" ? "tests" : `environment/services/${binding.consumer.serviceId}`;
|
|
145
|
+
const target = `${role}/${binding.target}`.toLowerCase();
|
|
146
|
+
if (tree.entries.some(e => e.path.toLowerCase() === target || e.path.toLowerCase().startsWith(`${target}/`) || e.kind === "file" && target.startsWith(`${e.path.toLowerCase()}/`)))
|
|
147
|
+
throw new Error("resource target collides with source descriptor");
|
|
148
|
+
}
|
|
149
|
+
const body = { protocol: "hitch-resource-plan@1", resolver: "hitch-resource-resolver@1", backend: "harbor-role-context@1", platform: input.platform, task };
|
|
150
|
+
return { plan: { ...body, digest: identity(body.protocol, body) }, closure: root.closure };
|
|
151
|
+
}
|
|
152
|
+
export { resourceDescriptorDirectory } from "./views.js";
|
|
153
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/resources/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { lstat, mkdir, open, rename, rm, statfs } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { canonical, identity, natural, object, parseResource, sha } from "./protocol.js";
|
|
5
|
+
import { parseResourceSelection, preflightResourceTask } from "./tasks.js";
|
|
6
|
+
export function parseResourceDelivery(value) {
|
|
7
|
+
const raw = object(value, ["protocol", "selection", "objects", "images", "plans", "digest"]);
|
|
8
|
+
if (raw.protocol !== "hitch-resource-delivery@1" || !Array.isArray(raw.objects) || !Array.isArray(raw.images) || !Array.isArray(raw.plans))
|
|
9
|
+
throw new TypeError("invalid resource delivery");
|
|
10
|
+
const selection = parseResourceSelection(raw.selection);
|
|
11
|
+
const objects = raw.objects.map(v => { const o = object(v, ["digest", "size"]); return { digest: sha(o.digest), size: natural(o.size) }; });
|
|
12
|
+
if (canonical(objects.map(o => o.digest)) !== canonical([...new Set(objects.map(o => o.digest))].sort()))
|
|
13
|
+
throw new TypeError("delivery objects must be sorted and unique");
|
|
14
|
+
const images = raw.images.map(item => {
|
|
15
|
+
const i = object(item, ["resource", "reference", "configDigest"]), resource = parseResource(i.resource);
|
|
16
|
+
if (resource.kind !== "oci-image" || typeof i.reference !== "string" || !i.reference.endsWith(`@${resource.manifestDigest}`) || /[\s\0]/.test(i.reference))
|
|
17
|
+
throw new TypeError("invalid delivery image");
|
|
18
|
+
return { resource, reference: i.reference, configDigest: sha(i.configDigest) };
|
|
19
|
+
});
|
|
20
|
+
const expectedImages = [...new Set(selection.tasks.flatMap(task => Object.values(task.lock.resources)
|
|
21
|
+
.filter(resource => resource.kind === "oci-image").map(resource => canonical(resource))))].sort((a, b) => a.localeCompare(b));
|
|
22
|
+
if (canonical(images.map(image => canonical(image.resource))) !== canonical(expectedImages))
|
|
23
|
+
throw new TypeError("delivery images must exactly match the sorted unique selection closure");
|
|
24
|
+
const plans = raw.plans.map(v => { const p = object(v, ["taskId", "digest"]); if (typeof p.taskId !== "string")
|
|
25
|
+
throw new TypeError("invalid delivery plan"); return { taskId: p.taskId, digest: sha(p.digest) }; });
|
|
26
|
+
if (canonical(plans.map(p => p.taskId)) !== canonical(selection.tasks.map(t => t.task_id)))
|
|
27
|
+
throw new TypeError("delivery plans do not match selection");
|
|
28
|
+
const { digest, ...body } = raw;
|
|
29
|
+
if (sha(digest) !== identity(raw.protocol, body))
|
|
30
|
+
throw new TypeError("resource delivery digest mismatch");
|
|
31
|
+
return raw;
|
|
32
|
+
}
|
|
33
|
+
export async function createResourceDelivery(store, selection, owner, generation, signal) {
|
|
34
|
+
return store.admission(() => assembleResourceDelivery(store, selection, owner, generation, signal));
|
|
35
|
+
}
|
|
36
|
+
async function assembleResourceDelivery(store, selection, owner, generation, signal) {
|
|
37
|
+
selection = parseResourceSelection(selection);
|
|
38
|
+
const objects = new Map(), images = new Map(), plans = [];
|
|
39
|
+
for (const task of selection.tasks) {
|
|
40
|
+
const checked = await preflightResourceTask(store, task, { owner: `${owner}:${task.task_id}`, generation, platform: selection.manifest.execution.platform, ...(signal ? { signal } : {}) });
|
|
41
|
+
plans.push({ taskId: task.task_id, digest: checked.plan.digest });
|
|
42
|
+
for (const digest of checked.closure.objectDigests)
|
|
43
|
+
objects.set(digest, await store.objects.verify(digest));
|
|
44
|
+
for (const image of checked.closure.images) {
|
|
45
|
+
const resource = task.lock.resources[image.resource];
|
|
46
|
+
if (resource?.kind !== "oci-image")
|
|
47
|
+
throw new Error("delivery image not declared");
|
|
48
|
+
images.set(canonical(resource), { resource, reference: image.reference, configDigest: image.configDigest });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const body = { protocol: "hitch-resource-delivery@1", selection, objects: [...objects].sort(([a], [b]) => a.localeCompare(b)).map(([digest, size]) => ({ digest, size })), images: [...images].sort(([a], [b]) => a.localeCompare(b)).map(([, i]) => i), plans };
|
|
52
|
+
return parseResourceDelivery({ ...body, digest: identity(body.protocol, body) });
|
|
53
|
+
}
|
|
54
|
+
function interruptible(pending, signal) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const abort = () => { signal.removeEventListener("abort", abort); reject(signal.reason); };
|
|
57
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
58
|
+
pending.then(value => { signal.removeEventListener("abort", abort); resolve(value); }, error => { signal.removeEventListener("abort", abort); reject(error); });
|
|
59
|
+
if (signal.aborted)
|
|
60
|
+
abort();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async function* boundedRead(reader, item, signal) {
|
|
64
|
+
const opened = Promise.resolve().then(() => { signal.throwIfAborted(); return reader(item, signal); }).then(stream => stream[Symbol.asyncIterator]());
|
|
65
|
+
let finished = false;
|
|
66
|
+
try {
|
|
67
|
+
const iterator = await interruptible(opened, signal);
|
|
68
|
+
while (true) {
|
|
69
|
+
signal.throwIfAborted();
|
|
70
|
+
const next = await interruptible(Promise.resolve(iterator.next()), signal);
|
|
71
|
+
if (next.done) {
|
|
72
|
+
finished = true;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
yield next.value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
// Close late readers too, but never let uncooperative stream cleanup retain the store lock.
|
|
80
|
+
if (!finished)
|
|
81
|
+
void opened.then(iterator => iterator.return?.()).catch(() => { });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** One bounded object stream at a time. Existing bytes are verified, never overwritten. */
|
|
85
|
+
export async function receiveResourceDelivery(store, value, reader, owner, generation, signal) {
|
|
86
|
+
const delivery = parseResourceDelivery(value), limits = store.objects.budget;
|
|
87
|
+
if (delivery.objects.length > limits.maxFiles || delivery.objects.some(o => o.size > limits.maxObjectBytes) || delivery.objects.reduce((n, o) => n + o.size, 0) > limits.maxTotalBytes)
|
|
88
|
+
throw new Error("resource transfer budget exceeded");
|
|
89
|
+
const received = await store.locked(async () => {
|
|
90
|
+
const lease = await store.beginLease(owner, "import"), staging = path.join(store.directory, "staging", lease.id);
|
|
91
|
+
let transferredBytes = 0, missingObjects = 0;
|
|
92
|
+
await mkdir(staging, { recursive: true });
|
|
93
|
+
try {
|
|
94
|
+
for (const item of delivery.objects) {
|
|
95
|
+
signal?.throwIfAborted();
|
|
96
|
+
await store.protect(lease, item.digest);
|
|
97
|
+
const target = store.objects.objectPath(item.digest), existing = await lstat(target).catch(e => { if (e.code !== "ENOENT")
|
|
98
|
+
throw e; return undefined; });
|
|
99
|
+
if (existing) {
|
|
100
|
+
await store.objects.verify(item.digest, item.size);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const quarantine = path.join(store.directory, "quarantine", item.digest.slice(7));
|
|
104
|
+
if (await lstat(quarantine).catch(e => { if (e.code !== "ENOENT")
|
|
105
|
+
throw e; return undefined; })) {
|
|
106
|
+
await store.objects.verify(item.digest, item.size, quarantine);
|
|
107
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
108
|
+
await rename(quarantine, target);
|
|
109
|
+
await rm(path.join(store.directory, "quarantine-index", `${item.digest.slice(7)}.json`), { force: true });
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const space = await statfs(staging, { bigint: true });
|
|
113
|
+
if (space.bsize * space.bavail < BigInt(item.size + limits.minFreeBytes))
|
|
114
|
+
throw new Error("resource transfer free-space reserve exceeded");
|
|
115
|
+
const file = path.join(staging, randomUUID()), output = await open(file, "wx", 0o600);
|
|
116
|
+
let size = 0;
|
|
117
|
+
const timeout = AbortSignal.timeout(120_000), bounded = signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
118
|
+
try {
|
|
119
|
+
for await (const chunk of boundedRead(reader, item, bounded)) {
|
|
120
|
+
bounded.throwIfAborted();
|
|
121
|
+
size += chunk.byteLength;
|
|
122
|
+
if (size > item.size)
|
|
123
|
+
throw new Error("resource transfer exceeds declared size");
|
|
124
|
+
await output.writeFile(chunk);
|
|
125
|
+
}
|
|
126
|
+
bounded.throwIfAborted();
|
|
127
|
+
await output.sync();
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
await output.close();
|
|
131
|
+
}
|
|
132
|
+
if (size !== item.size)
|
|
133
|
+
throw new Error("resource transfer is truncated");
|
|
134
|
+
await store.objects.verify(item.digest, item.size, file);
|
|
135
|
+
signal?.throwIfAborted();
|
|
136
|
+
await store.objects.publish(file, item.digest, item.size, d => store.protect(lease, d));
|
|
137
|
+
missingObjects++;
|
|
138
|
+
transferredBytes += size;
|
|
139
|
+
}
|
|
140
|
+
return { leaseId: lease.id, transferredBytes, missingObjects };
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await rm(staging, { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
}, signal);
|
|
146
|
+
// Producer protection survives failures until an operator confirms recovery.
|
|
147
|
+
const expected = new Set();
|
|
148
|
+
for (const task of delivery.selection.tasks) {
|
|
149
|
+
const checked = await preflightResourceTask(store, task, { owner: `${owner}:${task.task_id}`, generation, platform: delivery.selection.manifest.execution.platform, ...(signal ? { signal } : {}) });
|
|
150
|
+
if (checked.plan.digest !== delivery.plans.find(p => p.taskId === task.task_id)?.digest)
|
|
151
|
+
throw new Error("remote resource plan changed");
|
|
152
|
+
checked.closure.objectDigests.forEach(d => expected.add(d));
|
|
153
|
+
for (const i of checked.closure.images)
|
|
154
|
+
if (!delivery.images.some(e => e.resource.manifestDigest === i.manifestDigest && e.resource.platform === i.platform && e.configDigest === i.configDigest))
|
|
155
|
+
throw new Error("remote OCI config changed");
|
|
156
|
+
}
|
|
157
|
+
if (canonical([...expected].sort()) !== canonical(delivery.objects.map(o => o.digest)))
|
|
158
|
+
throw new Error("delivery contains an incomplete or extraneous closure");
|
|
159
|
+
await store.finishLease(received.leaseId, "ended");
|
|
160
|
+
return received;
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=transfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfer.js","sourceRoot":"","sources":["../../../src/resources/transfer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { chmod, copyFile, lstat, mkdir, readFile, readdir, rename, rm, statfs } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { durableWriteJSON } from "../foundation/index.js";
|
|
6
|
+
import { canonical, hash, object, parseStrictJson, parseTree } from "./protocol.js";
|
|
7
|
+
const names = (directory) => readdir(directory).catch(e => { if (e.code !== "ENOENT")
|
|
8
|
+
throw e; return []; });
|
|
9
|
+
async function verifyView(store, directory, tree) {
|
|
10
|
+
const expected = new Map(tree.entries.map(e => [e.path, e]));
|
|
11
|
+
const visit = async (dir, prefix = "") => {
|
|
12
|
+
if (!(await lstat(dir)).isDirectory())
|
|
13
|
+
throw new Error("descriptor view is not a directory");
|
|
14
|
+
for (const name of await readdir(dir)) {
|
|
15
|
+
const rel = prefix ? `${prefix}/${name}` : name, entry = expected.get(rel);
|
|
16
|
+
if (!entry)
|
|
17
|
+
throw new Error("descriptor view contains extra content");
|
|
18
|
+
expected.delete(rel);
|
|
19
|
+
const file = path.join(dir, name), info = await lstat(file);
|
|
20
|
+
if (entry.kind === "directory")
|
|
21
|
+
await visit(file, rel);
|
|
22
|
+
else if (!info.isFile() || Boolean(info.mode & 0o111) !== entry.executable || await store.objects.verify(entry.digest, entry.size, file) !== entry.size)
|
|
23
|
+
throw new Error("descriptor view changed");
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
await visit(directory);
|
|
27
|
+
if (expected.size)
|
|
28
|
+
throw new Error("descriptor view incomplete");
|
|
29
|
+
}
|
|
30
|
+
/** Bounded cache of small descriptors. Large external bindings never enter it. */
|
|
31
|
+
export async function resourceDescriptorDirectory(store, task) {
|
|
32
|
+
return store.locked(async () => {
|
|
33
|
+
const key = task.sourceTree.manifestDigest.slice(7), ref = path.join(store.directory, "descriptor-views", key), isolated = path.join(store.directory, "view-quarantine", key), tree = await store.objects.readTree(task.sourceTree.manifestDigest);
|
|
34
|
+
const size = tree.entries.reduce((n, e) => n + (e.kind === "file" ? e.size : 0), 0);
|
|
35
|
+
if (size > 32 * 1024 ** 2)
|
|
36
|
+
throw new Error("task descriptor exceeds 32 MiB; declare large inputs as resources");
|
|
37
|
+
if (await lstat(ref).catch(e => { if (e.code !== "ENOENT")
|
|
38
|
+
throw e; return undefined; })) {
|
|
39
|
+
await verifyView(store, ref, tree);
|
|
40
|
+
return ref;
|
|
41
|
+
}
|
|
42
|
+
if (await lstat(isolated).catch(e => { if (e.code !== "ENOENT")
|
|
43
|
+
throw e; return undefined; })) {
|
|
44
|
+
await verifyView(store, isolated, tree);
|
|
45
|
+
await mkdir(path.dirname(ref), { recursive: true });
|
|
46
|
+
await rename(isolated, ref);
|
|
47
|
+
await rm(path.join(store.directory, "view-quarantine-index", `${key}.json`), { force: true });
|
|
48
|
+
return ref;
|
|
49
|
+
}
|
|
50
|
+
let cached = 0;
|
|
51
|
+
const measure = async (dir) => { for (const name of await names(dir)) {
|
|
52
|
+
const file = path.join(dir, name), info = await lstat(file);
|
|
53
|
+
if (info.isDirectory())
|
|
54
|
+
await measure(file);
|
|
55
|
+
else if (info.isFile())
|
|
56
|
+
cached += info.size;
|
|
57
|
+
else
|
|
58
|
+
throw new Error("unsafe descriptor cache entry");
|
|
59
|
+
} };
|
|
60
|
+
await measure(path.dirname(ref));
|
|
61
|
+
await measure(path.dirname(isolated));
|
|
62
|
+
if (cached + size > store.objects.budget.maxViewBytes)
|
|
63
|
+
throw new Error("descriptor view cache budget exceeded; inspect and release unused roots before explicit GC");
|
|
64
|
+
const temp = `${ref}.${randomUUID()}.tmp`;
|
|
65
|
+
await mkdir(temp, { recursive: true, mode: 0o700 });
|
|
66
|
+
try {
|
|
67
|
+
const space = await statfs(temp, { bigint: true });
|
|
68
|
+
if (space.bsize * space.bavail < BigInt(size + store.objects.budget.minFreeBytes))
|
|
69
|
+
throw new Error("descriptor view free-space reserve exceeded");
|
|
70
|
+
for (const entry of tree.entries) {
|
|
71
|
+
const target = path.join(temp, entry.path);
|
|
72
|
+
if (entry.kind === "directory")
|
|
73
|
+
await mkdir(target);
|
|
74
|
+
else {
|
|
75
|
+
await store.objects.verify(entry.digest, entry.size);
|
|
76
|
+
await copyFile(store.objects.objectPath(entry.digest), target, constants.COPYFILE_EXCL);
|
|
77
|
+
await chmod(target, entry.executable ? 0o755 : 0o644);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
await verifyView(store, temp, tree);
|
|
81
|
+
await rename(temp, ref);
|
|
82
|
+
return ref;
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
await rm(temp, { recursive: true, force: true });
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Caller holds the same store lock used by view creation and root acquisition. */
|
|
90
|
+
export async function planViewGc(store, marked, graceMs) {
|
|
91
|
+
const active = path.join(store.directory, "descriptor-views"), quarantine = path.join(store.directory, "view-quarantine"), index = path.join(store.directory, "view-quarantine-index");
|
|
92
|
+
const isolated = new Map(), eligible = new Map();
|
|
93
|
+
for (const key of await names(quarantine)) {
|
|
94
|
+
if (!/^[a-f0-9]{64}$/.test(key))
|
|
95
|
+
throw new Error("unknown quarantined descriptor view");
|
|
96
|
+
const record = object(parseStrictJson(await readFile(path.join(index, `${key}.json`), "utf8")), ["protocol", "tree", "at"]), tree = parseTree(record.tree);
|
|
97
|
+
if (record.protocol !== "hitch-view-quarantine@1" || hash(canonical(tree)) !== `sha256:${key}` || !Number.isSafeInteger(record.at))
|
|
98
|
+
throw new Error("invalid descriptor quarantine identity");
|
|
99
|
+
await verifyView(store, path.join(quarantine, key), tree);
|
|
100
|
+
isolated.set(key, { tree, at: record.at });
|
|
101
|
+
}
|
|
102
|
+
for (const key of await names(active)) {
|
|
103
|
+
if (!/^[a-f0-9]{64}$/.test(key))
|
|
104
|
+
continue; // Interrupted private staging is retained for explicit recovery.
|
|
105
|
+
const tree = await store.objects.readTree(`sha256:${key}`);
|
|
106
|
+
await verifyView(store, path.join(active, key), tree);
|
|
107
|
+
if (!marked.has(`sha256:${key}`))
|
|
108
|
+
eligible.set(key, tree);
|
|
109
|
+
}
|
|
110
|
+
return async () => {
|
|
111
|
+
for (const [key, record] of isolated) {
|
|
112
|
+
if (marked.has(`sha256:${key}`)) {
|
|
113
|
+
await mkdir(active, { recursive: true });
|
|
114
|
+
await rename(path.join(quarantine, key), path.join(active, key));
|
|
115
|
+
await rm(path.join(index, `${key}.json`));
|
|
116
|
+
}
|
|
117
|
+
else if (Date.now() - record.at >= graceMs) {
|
|
118
|
+
await rm(path.join(quarantine, key), { recursive: true });
|
|
119
|
+
await rm(path.join(index, `${key}.json`));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const [key, tree] of eligible) {
|
|
123
|
+
await mkdir(quarantine, { recursive: true });
|
|
124
|
+
await durableWriteJSON(path.join(index, `${key}.json`), { protocol: "hitch-view-quarantine@1", tree, at: Date.now() });
|
|
125
|
+
await rename(path.join(active, key), path.join(quarantine, key));
|
|
126
|
+
}
|
|
127
|
+
return { quarantined: [...eligible.keys()] };
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"views.js","sourceRoot":"","sources":["../../../src/resources/views.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACxG,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAqB,MAAM,eAAe,CAAC;AAIvG,MAAM,KAAK,GAAG,CAAC,SAAiB,EAAqB,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;IAAE,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA,CAAC,CAAC,CAAC,CAAC;AACvI,KAAK,UAAU,UAAU,CAAC,KAAoB,EAAE,SAAiB,EAAE,IAAkB;IACnF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,KAAK,EAAE,GAAW,EAAE,MAAM,GAAG,EAAE,EAAiB,EAAE;QAC9D,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC7F,KAAK,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAAC,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxK,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5D,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,MAAM,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;iBAClD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,UAAU,IAAI,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACtM,CAAC;IACH,CAAC,CAAC;IACF,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;IAAC,IAAI,QAAQ,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;AAC3F,CAAC;AACD,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAAoB,EAAE,IAAkB;IACxF,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,iBAAiB,EAAE,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACnP,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpF,IAAI,IAAI,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QAChH,IAAI,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,CAAC,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAAC,MAAM,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAAC,OAAO,GAAG,CAAC;QAAC,CAAC;QAC7I,IAAI,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,CAAC,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAAC,MAAM,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,MAAM,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,uBAAuB,EAAE,GAAG,GAAG,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,OAAO,GAAG,CAAC;QAAC,CAAC;QACxU,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,EAAE,GAAW,EAAiB,EAAE,GAAG,KAAK,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAAC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAAC,IAAI,IAAI,CAAC,WAAW,EAAE;gBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;iBAAM,IAAI,IAAI,CAAC,MAAM,EAAE;gBAAE,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC;;gBAAM,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC;QACjT,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAAC,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxE,IAAI,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,4FAA4F,CAAC,CAAC;QACrK,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/F,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,IAAI,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACtM,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAAC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAAC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;oBAAE,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;qBAAM,CAAC;oBAAC,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;oBAAC,MAAM,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBAAC,CAAC;YAAC,CAAC;YACrV,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAAC,MAAM,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAAC,OAAO,GAAG,CAAC;QAC3E,CAAC;gBAAS,CAAC;YAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC;AACD,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAoB,EAAE,MAAoC,EAAE,OAAe;IAC1G,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,kBAAkB,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;IACvL,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8C,EAAE,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IACnH,KAAK,MAAM,GAAG,IAAI,MAAM,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3J,IAAI,MAAM,CAAC,QAAQ,KAAK,yBAAyB,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,UAAU,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC9L,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,EAAY,EAAE,CAAC,CAAC;IAClH,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,iEAAiE;QAC5G,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QAAC,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAClH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,GAAG,EAAE,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,IAAI,EAAE;QAChB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACrC,IAAI,MAAM,CAAC,GAAG,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC;gBAAC,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;gBAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;YAAC,CAAC;iBACtL,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,OAAO,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;YAAC,CAAC;QACvJ,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;YAAC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAAC,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,yBAAyB,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,CAAC;QAC/Q,OAAO,EAAE,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { statePaths } from "../foundation/index.js";
|
|
4
|
+
export async function prepareAdapterRuntimeHome(root, runId) {
|
|
5
|
+
// Harness homes contain private state and dependency symlinks. Only redacted
|
|
6
|
+
// provider evidence and canonical trajectories belong in the sealed bundle.
|
|
7
|
+
const runtimeHome = path.join(statePaths(root).temporary, "runtime-homes", runId);
|
|
8
|
+
await mkdir(runtimeHome, { recursive: true, mode: 0o700 });
|
|
9
|
+
return runtimeHome;
|
|
10
|
+
}
|
|
1
11
|
/** Bind a verified artifact and its invocation prefix to the adapter request. */
|
|
2
12
|
export async function prepareAdapterProcess(adapter, request, artifact, resolution, runDirectory, runtimeHome, runtimeOverrides = {}) {
|
|
3
13
|
const specification = await adapter.process(request, artifact.executable, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-process.js","sourceRoot":"","sources":["../../../src/runs/adapter-process.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adapter-process.js","sourceRoot":"","sources":["../../../src/runs/adapter-process.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,IAAY,EAAE,KAAa;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC;IAClF,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3D,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAA0B,EAC1B,OAAuB,EACvB,QAA0B,EAC1B,UAA4B,EAC5B,YAAoB,EACpB,WAAmB,EACnB,mBAAqI,EAAE;IAEvI,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAE;QACxE,oBAAoB,EAAE,QAAQ,CAAC,oBAAoB;QACnD,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,IAAI,SAAS;QACxD,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,gBAAgB;KACxF,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,eAAe,EAAE,MAAM;QAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC9F,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
|
@@ -13,7 +13,7 @@ import { buildManifest, safeAgentArgsForPersistence } from "./manifest.js";
|
|
|
13
13
|
import { assertQueuedRunIdentity } from "./queued.js";
|
|
14
14
|
import { adapterFidelity, applyEffectiveModelIdentity, failureResult, mergeRedactions, providerModelId } from "./outcome.js";
|
|
15
15
|
import { writeResultBundleIndex } from "./bundle.js";
|
|
16
|
-
import { prepareAdapterProcess } from "./adapter-process.js";
|
|
16
|
+
import { prepareAdapterProcess, prepareAdapterRuntimeHome } from "./adapter-process.js";
|
|
17
17
|
import { completedRunManifest } from "./finalizer.js";
|
|
18
18
|
import { harnessChildEnvironment, managedHarborModelRuntime } from "./local-inference-environment.js";
|
|
19
19
|
import { acquireRunInference, bindManagedModelProxy } from "./local-inference-run.js";
|
|
@@ -37,7 +37,6 @@ export async function executeRun({ runId, request, runsRoot, root = path.dirname
|
|
|
37
37
|
}
|
|
38
38
|
workspacePlan ||= await planWorkspace({ runId, sourceCwd: normalized.cwd, mode: normalized.workspace_mode, root });
|
|
39
39
|
const runDirectory = path.join(runsRoot, runId);
|
|
40
|
-
const runtimeHome = path.join(runDirectory, "runtime-home");
|
|
41
40
|
const priorManifest = await readJSON(path.join(runDirectory, "manifest.json"), null);
|
|
42
41
|
if (priorManifest && ["succeeded", "failed", "timed_out", "cancelled"].includes(String(priorManifest.status))) {
|
|
43
42
|
throw new HitchError(`run ${runId} is sealed and cannot be overwritten`, { code: "run_sealed", exitCode: 11 });
|
|
@@ -45,6 +44,7 @@ export async function executeRun({ runId, request, runsRoot, root = path.dirname
|
|
|
45
44
|
if (priorManifest)
|
|
46
45
|
assertQueuedRunIdentity(priorManifest, buildManifest(runId, normalized, workspacePlan));
|
|
47
46
|
await ensureDir(runDirectory);
|
|
47
|
+
const runtimeHome = await prepareAdapterRuntimeHome(root, runId);
|
|
48
48
|
const workspacePath = workspaceRecordPath(root, runId);
|
|
49
49
|
await atomicWriteJSON(workspacePath, workspacePlan);
|
|
50
50
|
const manifestPath = path.join(runDirectory, "manifest.json");
|