agent-hitch 0.2.13 → 0.2.14
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/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,27 @@
|
|
|
1
|
+
# Opt-in resource adapter
|
|
2
|
+
|
|
3
|
+
The existing `import.mjs` and v4 datasets remain unchanged. `resources.mjs`
|
|
4
|
+
accepts an existing, verified v4 public-source dataset and explicit task IDs.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
node benchmark-packages/automationbench/resources.mjs prepare-runtime --legacy /v4 --out /new/runtime-context --root /hitch --task marketing-ad_performance_review
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Build this context once for `linux/amd64` and publish it to a registry you control.
|
|
11
|
+
The script never publishes. Record the platform manifest digest and configure
|
|
12
|
+
Hitch transport for both that runtime and an immutable candidate Python base.
|
|
13
|
+
The runtime recipe, source CAS, uv lock, upstream revision and image config are
|
|
14
|
+
distinct evidence. `prepare-runtime` creates a durable rebuild-input pin.
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
node benchmark-packages/automationbench/resources.mjs import --legacy /v4 --out /new/v5 --root /hitch --task marketing-ad_performance_review --recipe /new/runtime-context/recipe.json --runtime-image registry/runtime@sha256:PLATFORM_MANIFEST --candidate-image registry/python@sha256:PLATFORM_MANIFEST
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Import verifies every selected v4 task, every shared runtime source against the
|
|
21
|
+
recipe and the source bytes inside the actual runtime image. It preserves task
|
|
22
|
+
instructions, simulator state, verifier, raw metric and scoring contracts.
|
|
23
|
+
Candidate, simulator and verifier have disjoint contexts. The new dataset has a
|
|
24
|
+
new identity. Existing v4 experiments must continue using their original refs.
|
|
25
|
+
|
|
26
|
+
See `docs/resource-storage.zh-CN.md` for supported backend limits, cache-only
|
|
27
|
+
offline requirements, explicit legacy export, pins, budgets and GC.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Opt-in v5 adapter over an explicitly selected v4 package. Uses public APIs only.
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { cp, lstat, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { buildBenchmarkAdapterManifest } from 'agent-hitch/evals';
|
|
8
|
+
import { hash, identity, resourceRequest, configuredResourceStore } from 'agent-hitch/resources';
|
|
9
|
+
const args = process.argv.slice(2), action = args.shift();
|
|
10
|
+
const option = name => { const i = args.indexOf(name); return i < 0 ? undefined : args.splice(i, 2)[1]; };
|
|
11
|
+
const legacy = option('--legacy'), output = option('--out'), root = option('--root'), image = option('--runtime-image'), candidateBase = option('--candidate-image'), recipeFile = option('--recipe');
|
|
12
|
+
const selected = []; while (args.includes('--task')) selected.push(option('--task'));
|
|
13
|
+
if (args.length || !['prepare-runtime', 'import'].includes(action) || !legacy || !output || !root) throw new Error('Usage: resources.mjs prepare-runtime|import --legacy V4_DATASET --out NEW_DIRECTORY --root HITCH_ROOT [--task ID] [--runtime-image DIGEST_REF --candidate-image DIGEST_REF --recipe RECIPE_JSON]');
|
|
14
|
+
const old = JSON.parse(await readFile(path.join(legacy, 'benchmark.adapter.json'), 'utf8'));
|
|
15
|
+
if (old.schema_version !== '1' || old.adapter.id !== 'automationbench-public-source') throw new Error('expected a v1 AutomationBench public source package');
|
|
16
|
+
const ids = selected.length ? [...selected].sort() : old.tasks.map(t => t.task_id);
|
|
17
|
+
if (!ids.length || new Set(ids).size !== ids.length || ids.some(id => !old.tasks.some(t => t.task_id === id))) throw new Error('invalid explicit task selection');
|
|
18
|
+
const verified = await buildBenchmarkAdapterManifest({ dataset: legacy, benchmark: old.benchmark, adapter: old.adapter, scoring: old.scoring, taskIds: ids });
|
|
19
|
+
if (verified.tasks.some(t => t.task_digest !== old.tasks.find(item => item.task_id === t.task_id)?.task_digest)) throw new Error('selected v4 task integrity mismatch');
|
|
20
|
+
await mkdir(output);
|
|
21
|
+
const owner = `producer:automationbench-v5:${path.resolve(output)}`, first = path.join(legacy, ids[0]);
|
|
22
|
+
if (action === 'prepare-runtime') {
|
|
23
|
+
const runtime = path.join(output, 'runtime');
|
|
24
|
+
await cp(path.join(first, 'tests/runtime'), runtime, { recursive: true, filter: file => path.basename(file) !== 'task.json' });
|
|
25
|
+
const originalDockerfile = await readFile(path.join(first, 'tests/Dockerfile'), 'utf8');
|
|
26
|
+
const base = originalDockerfile.match(/^FROM (\S+)$/m)?.[1]; if (!/@sha256:[a-f0-9]{64}$/.test(base ?? '')) throw new Error('runtime base must be immutable');
|
|
27
|
+
// Dependencies are installed once. The recipe retains every source byte,
|
|
28
|
+
// executable bit, empty directory, uv lock and adapter script in the file CAS.
|
|
29
|
+
const dockerfile = `FROM ${base}\nRUN pip install --no-cache-dir uv==0.8.15\nCOPY runtime/upstream /opt/upstream\nWORKDIR /opt/upstream\nRUN uv sync --frozen --no-dev\nCOPY runtime/official.py runtime/server.py runtime/score_contract.py /runtime/\nENV PATH="/opt/upstream/.venv/bin:$PATH" PYTHONPATH="/runtime:/opt/upstream" PYTHONDONTWRITEBYTECODE=1 HF_HOME=/tmp/hf\nCOPY recipe.json /runtime/hitch-resource-recipe.json\n`;
|
|
30
|
+
await writeFile(path.join(output, 'Dockerfile'), dockerfile);
|
|
31
|
+
const source = await resourceRequest(root, 'import', { source: runtime, kind: 'tree', owner: `${owner}:runtime-source` });
|
|
32
|
+
const body = { protocol: 'automationbench-runtime-recipe@1', source: source.resource, dockerfileDigest: hash(dockerfile), upstreamRevision: old.benchmark.revision, platform: 'linux/amd64' };
|
|
33
|
+
const recipe = { ...body, digest: identity(body.protocol, body) }; await writeFile(path.join(output, 'recipe.json'), JSON.stringify(recipe, null, 2));
|
|
34
|
+
await resourceRequest(root, 'pin', { owner, generation: 1, purpose: 'rebuild-inputs', lock: { protocol: 'hitch-resource-lock@1', resources: { source: source.resource }, bindings: [], requiredCapabilities: [] } });
|
|
35
|
+
await resourceRequest(root, 'lease-end', { leaseId: source.leaseId, confirmation: 'ended' });
|
|
36
|
+
console.log(JSON.stringify({ context: path.resolve(output), recipe: recipe.digest, next: 'Build and explicitly publish this context; pass its platform manifest digest to import.' }));
|
|
37
|
+
} else {
|
|
38
|
+
if (!recipeFile || ![image, candidateBase].every(ref => /@sha256:[a-f0-9]{64}$/.test(ref ?? ''))) throw new Error('import requires a recipe and fixed runtime/candidate image digests');
|
|
39
|
+
const recipe = JSON.parse(await readFile(recipeFile, 'utf8')), { digest, ...body } = recipe;
|
|
40
|
+
if (digest !== identity('automationbench-runtime-recipe@1', body) || recipe.upstreamRevision !== old.benchmark.revision) throw new Error('runtime recipe identity mismatch');
|
|
41
|
+
const observed = JSON.parse(await command('docker', ['run', '--rm', '--network', 'none', '--platform', recipe.platform, '--entrypoint', 'cat', image, '/runtime/hitch-resource-recipe.json']));
|
|
42
|
+
if (JSON.stringify(observed) !== JSON.stringify(recipe)) throw new Error('runtime image was built from a different recipe');
|
|
43
|
+
const { store } = await configuredResourceStore(root);
|
|
44
|
+
const tree = await store.objects.readTree(recipe.source.manifestDigest);
|
|
45
|
+
for (const id of ids) await verifyRuntime(path.join(legacy, id, 'tests/runtime'), tree);
|
|
46
|
+
const expected = tree.entries.filter(e => e.kind === 'file' && (e.path.startsWith('upstream/') || ['official.py', 'server.py', 'score_contract.py'].includes(e.path))).map(e => ({ path: e.path.startsWith('upstream/') ? '/opt/' + e.path : '/runtime/' + e.path, digest: e.digest }));
|
|
47
|
+
await command('docker', ['run', '--rm', '-i', '--network', 'none', '--platform', recipe.platform, '--entrypoint', 'python', image, '-c', 'import json,hashlib,sys,pathlib; rows=json.load(sys.stdin); assert all("sha256:"+hashlib.sha256(pathlib.Path(r["path"]).read_bytes()).hexdigest()==r["digest"] for r in rows), "runtime image source differs from recipe"'], JSON.stringify(expected));
|
|
48
|
+
const adapterRevision = hash(await readFile(fileURLToPath(import.meta.url)));
|
|
49
|
+
for (const id of ids) {
|
|
50
|
+
const source = path.join(legacy, id), target = path.join(output, id);
|
|
51
|
+
await mkdir(path.join(target, 'environment/candidate/runtime'), { recursive: true }); await mkdir(path.join(target, 'environment/services/simulator'), { recursive: true }); await mkdir(path.join(target, 'tests'));
|
|
52
|
+
for (const name of ['task.toml', 'instruction.md', 'source-prompt.json']) await cp(path.join(source, name), path.join(target, name));
|
|
53
|
+
for (const name of ['call.py', 'tools.json']) await cp(path.join(source, 'environment/runtime', name), path.join(target, 'environment/candidate/runtime', name));
|
|
54
|
+
await cp(path.join(source, 'tests/test.sh'), path.join(target, 'tests/test.sh'));
|
|
55
|
+
const row = await readFile(path.join(source, 'tests/runtime/task.json'));
|
|
56
|
+
await writeFile(path.join(target, 'tests/task.json'), row); await writeFile(path.join(target, 'environment/services/simulator/task.json'), row);
|
|
57
|
+
await writeFile(path.join(target, 'environment/candidate/Dockerfile'), `FROM ${candidateBase}\nCOPY runtime /runtime\nWORKDIR /app\nCMD ["sleep", "infinity"]\n`);
|
|
58
|
+
await writeFile(path.join(target, 'environment/services/simulator/Dockerfile'), `FROM ${image}\nCOPY task.json /data/task.json\nCMD ["python", "/runtime/server.py"]\n`);
|
|
59
|
+
await writeFile(path.join(target, 'tests/Dockerfile'), `FROM ${image}\nCOPY task.json /data/task.json\nCOPY test.sh /tests/test.sh\nCMD ["sleep", "infinity"]\n`);
|
|
60
|
+
const compose = JSON.parse(await readFile(path.join(source, 'environment/docker-compose.yaml'), 'utf8'));
|
|
61
|
+
compose.services.main.build = { context: 'candidate', dockerfile: 'Dockerfile' }; compose.services.simulator.build = { context: 'services/simulator', dockerfile: 'Dockerfile' };
|
|
62
|
+
await writeFile(path.join(target, 'environment/docker-compose.yaml'), JSON.stringify(compose));
|
|
63
|
+
await writeFile(path.join(target, 'runtime-provenance.json'), JSON.stringify({ protocol: 'automationbench-resource-adapter@1', sourceTask: old.tasks.find(t => t.task_id === id), sourceDataset: old.dataset_digest, recipe }));
|
|
64
|
+
const resources = { candidate: { kind: 'oci-image', manifestDigest: candidateBase.split('@')[1], platform: recipe.platform }, runtime: { kind: 'oci-image', manifestDigest: image.split('@')[1], platform: recipe.platform }, rebuild: recipe.source };
|
|
65
|
+
const bindings = [{ resource: 'candidate', consumer: { role: 'candidate' }, use: 'environment-image', slot: 'build-base' }, ...[{ role: 'verifier' }, { role: 'service', serviceId: 'simulator' }].map(consumer => ({ resource: 'runtime', consumer, use: 'environment-image', slot: 'build-base' }))];
|
|
66
|
+
await writeFile(path.join(target, 'resource.lock.json'), JSON.stringify({ protocol: 'hitch-resource-lock@1', resources, bindings, requiredCapabilities: ['oci-image@1', 'harbor-role-context@1'] }));
|
|
67
|
+
}
|
|
68
|
+
const manifest = await resourceRequest(root, 'seal-dataset', { directory: path.resolve(output), owner, taskIds: ids, manifest: { benchmark: old.benchmark, adapter: { ...old.adapter, revision: adapterRevision }, scoring: old.scoring, ...(old.raw_metrics ? { raw_metrics: old.raw_metrics } : {}), required_capabilities: ['harbor-role-context@1'], execution: { backend: 'harbor-role-context@1', resolver: 'hitch-resource-resolver@1', platform: recipe.platform } } });
|
|
69
|
+
console.log(JSON.stringify({ dataset: path.resolve(output), digest: manifest.dataset_digest, recipe: recipe.digest }));
|
|
70
|
+
}
|
|
71
|
+
async function command(executable, argv, input) { return new Promise((resolve, reject) => { const child = spawn(executable, argv, { stdio: [input === undefined ? 'ignore' : 'pipe', 'pipe', 'inherit'] }); let text = ''; if (input !== undefined) child.stdin.end(input); child.stdout.on('data', chunk => { text += chunk; if (text.length > 1024 * 1024) child.kill(); }); child.on('error', reject); child.on('exit', code => code === 0 ? resolve(text) : reject(new Error(`${executable} exited ${code}`))); }); }
|
|
72
|
+
async function verifyRuntime(directory, tree) {
|
|
73
|
+
const remaining = new Map(tree.entries.map(entry => [entry.path, entry]));
|
|
74
|
+
async function visit(dir, prefix = '') {
|
|
75
|
+
for (const name of await readdir(dir)) {
|
|
76
|
+
const relative = prefix ? `${prefix}/${name}` : name;
|
|
77
|
+
if (relative === 'task.json') continue;
|
|
78
|
+
const file = path.join(dir, name), info = await lstat(file), entry = remaining.get(relative);
|
|
79
|
+
if (!entry || info.isSymbolicLink()) throw new Error('v4 runtime differs from the shared recipe');
|
|
80
|
+
remaining.delete(relative);
|
|
81
|
+
if (entry.kind === 'directory' && info.isDirectory()) await visit(file, relative);
|
|
82
|
+
else if (entry.kind !== 'file' || !info.isFile() || entry.size !== info.size || entry.executable !== Boolean(info.mode & 0o111) || entry.digest !== hash(await readFile(file))) throw new Error('v4 runtime differs from the shared recipe');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await visit(directory); if (remaining.size) throw new Error('v4 runtime is missing recipe inputs');
|
|
86
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Shared tree terminal producer
|
|
2
|
+
|
|
3
|
+
Configure the Hitch resource host with an immutable Python image transport first
|
|
4
|
+
(see `docs/resource-storage.zh-CN.md`). The source directory must contain a
|
|
5
|
+
`values.json` array of finite numbers and remain unchanged during import.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
node benchmark-packages/shared-tree/import.mjs --source /data/tree --out /new/tasks --root /hitch --base-image registry/python@sha256:PLATFORM_MANIFEST --tasks 100 --platform linux/amd64
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
All tasks bind one CAS tree into a private candidate context. Each task asks for
|
|
12
|
+
the sum of a different prefix; the expected answer is verifier-only. Output
|
|
13
|
+
must be a new directory. This emits manifest v2, not a directly usable legacy
|
|
14
|
+
directory; use Hitch resource execution or explicit `resources legacy-export`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// A terminal producer whose primary shared dependency is a data tree.
|
|
3
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { resourceRequest } from 'agent-hitch/resources';
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const option = name => { const i = args.indexOf(name); return i < 0 ? undefined : args.splice(i, 2)[1]; };
|
|
8
|
+
const source = option('--source'), output = option('--out'), root = option('--root'), base = option('--base-image'), count = Number(option('--tasks') ?? 3), platform = option('--platform') ?? 'linux/amd64';
|
|
9
|
+
if (args.length || !source || !output || !root || !/@sha256:[a-f0-9]{64}$/.test(base ?? '') || !Number.isSafeInteger(count) || count < 1 || count > 1000) throw new Error('Usage: node import.mjs --source DATA_TREE --out NEW_DIRECTORY --root HITCH_ROOT --base-image PINNED_PYTHON_IMAGE [--tasks N] [--platform linux/amd64]');
|
|
10
|
+
const values = JSON.parse(await readFile(path.join(source, 'values.json'), 'utf8'));
|
|
11
|
+
if (!Array.isArray(values) || !values.length || !values.every(Number.isFinite)) throw new Error('source values.json must be a nonempty array of finite numbers');
|
|
12
|
+
await mkdir(output); // Never alter an existing dataset.
|
|
13
|
+
const owner = `producer:shared-tree:${path.resolve(output)}`;
|
|
14
|
+
const imported = await resourceRequest(root, 'import', { source: path.resolve(source), kind: 'tree', owner });
|
|
15
|
+
const image = { kind: 'oci-image', manifestDigest: base.split('@')[1], platform }, ids = [];
|
|
16
|
+
for (let i = 0; i < count; i++) {
|
|
17
|
+
const id = `sum-${String(i + 1).padStart(4, '0')}`, task = path.join(output, id); ids.push(id);
|
|
18
|
+
await mkdir(path.join(task, 'environment/candidate'), { recursive: true }); await mkdir(path.join(task, 'tests'));
|
|
19
|
+
await writeFile(path.join(task, 'instruction.md'), `Read /data/values.json and write the sum of its first ${i + 1} values to /app/answer.json.\n`);
|
|
20
|
+
await writeFile(path.join(task, 'environment/docker-compose.yaml'), JSON.stringify({ services: { main: { platform, build: { context: 'candidate', dockerfile: 'Dockerfile' } } } }));
|
|
21
|
+
await writeFile(path.join(task, 'environment/candidate/Dockerfile'), `FROM ${base}\nCOPY data /data\nWORKDIR /app\nCMD ["sleep", "infinity"]\n`);
|
|
22
|
+
await writeFile(path.join(task, 'tests/Dockerfile'), `FROM ${base}\nCOPY . /tests\nCMD ["sleep", "infinity"]\n`);
|
|
23
|
+
await writeFile(path.join(task, 'tests/expected.json'), JSON.stringify(values.slice(0, i + 1).reduce((n, x) => n + x, 0)));
|
|
24
|
+
await writeFile(path.join(task, 'tests/verify.py'), 'import json, pathlib, sys\nanswer = pathlib.Path(sys.argv[1])\nexpected = json.loads(pathlib.Path("/tests/expected.json").read_text())\nscore = int(answer.exists() and json.loads(answer.read_text()) == expected)\noutput = pathlib.Path("/logs/verifier"); output.mkdir(parents=True, exist_ok=True)\n(output / "reward.json").write_text(json.dumps({"reward": score}))\n');
|
|
25
|
+
await writeFile(path.join(task, 'tests/test.sh'), '#!/bin/sh\nset -eu\npython /tests/verify.py /evidence/answer.json\n', { mode: 0o755 });
|
|
26
|
+
// Candidate artifacts cross the role boundary only via Harbor's explicit evidence export.
|
|
27
|
+
await writeFile(path.join(task, 'task.toml'), 'schema_version = "1.4"\nartifacts = [{ source = "/app/answer.json" }]\n[environment]\nworkdir = "/app"\nnetwork_mode = "none"\n[verifier]\nenvironment_mode = "separate"\n[verifier.environment]\nnetwork_mode = "none"\n');
|
|
28
|
+
await writeFile(path.join(task, 'resource.lock.json'), JSON.stringify({ protocol: 'hitch-resource-lock@1', resources: { data: imported.resource, python: image }, requiredCapabilities: ['tree@1', 'private-copy@1'], bindings: [
|
|
29
|
+
{ resource: 'data', consumer: { role: 'candidate' }, use: 'input-tree', target: 'data', access: 'private-copy' },
|
|
30
|
+
...['candidate', 'verifier'].map(role => ({ resource: 'python', consumer: { role }, use: 'environment-image', slot: 'build-base' })),
|
|
31
|
+
] }));
|
|
32
|
+
}
|
|
33
|
+
const manifest = await resourceRequest(root, 'seal-dataset', { directory: path.resolve(output), owner, taskIds: ids, manifest: {
|
|
34
|
+
benchmark: { id: 'shared-tree-sums', revision: imported.resource.manifestDigest }, adapter: { id: 'shared-tree-terminal', revision: '1', output_protocol: 'gear-harbor-eval-result-v1' },
|
|
35
|
+
required_capabilities: ['harbor-role-context@1'], execution: { backend: 'harbor-role-context@1', resolver: 'hitch-resource-resolver@1', platform },
|
|
36
|
+
scoring: { total_score: { source_metric: 'reward', direction: 'maximize', range: [0, 1], reducer: 'task-macro-mean' } },
|
|
37
|
+
} });
|
|
38
|
+
await resourceRequest(root, 'lease-end', { leaseId: imported.leaseId, confirmation: 'ended' });
|
|
39
|
+
console.log(JSON.stringify({ dataset: path.resolve(output), digest: manifest.dataset_digest, sharedTree: imported.resource }));
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { mkdtemp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { runCommand } from "../src/foundation/index.js";
|
|
6
|
+
import { configuredResourceStore, preflightResourceInput, materializeResourceTask, finishResourceWorkspace, sealResourceEvidence, resourceStorageStats } from "../src/resources/index.js";
|
|
7
|
+
// Explicit local canary: no model requests and no registry publication.
|
|
8
|
+
const [root, dataset, legacy, taskId] = process.argv.slice(2);
|
|
9
|
+
if (!root || !dataset || !legacy || !taskId)
|
|
10
|
+
throw new Error("Usage: canary-automation-resources ROOT V2_DATASET V4_DATASET TASK_ID");
|
|
11
|
+
const output = await mkdtemp(path.join(os.tmpdir(), "hitch-automation-execution-"));
|
|
12
|
+
const tags = [], containers = [], observed = [];
|
|
13
|
+
const docker = (args) => runCommand(process.env.HITCH_DOCKER_PATH || "docker", args, { timeoutMs: 240_000 });
|
|
14
|
+
const { store, config } = await configuredResourceStore(root);
|
|
15
|
+
const preflight = (await preflightResourceInput(store, dataset, { owner: "automation-canary", generation: 1, platform: config.platform }));
|
|
16
|
+
const plan = preflight.plans.find(p => p.task.task_id === taskId);
|
|
17
|
+
const workspace = await materializeResourceTask(store, plan, { owner: `automation-canary:${taskId}`, generation: 1, policy: { mode: "copy" } });
|
|
18
|
+
async function build(directory, file = "Dockerfile") {
|
|
19
|
+
const tag = `hitch-automation-resource-canary:${randomUUID()}`;
|
|
20
|
+
tags.push(tag);
|
|
21
|
+
await docker(["build", "--platform", config.platform, "--pull=false", "--quiet", "-t", tag, "-f", path.join(directory, file), directory]);
|
|
22
|
+
return tag;
|
|
23
|
+
}
|
|
24
|
+
async function observe(name) {
|
|
25
|
+
const image = (await docker(["inspect", "--format", "{{.Image}}", name])).stdout.trim();
|
|
26
|
+
observed.push({ image_config_digest: image });
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const candidate = await build(path.join(workspace.taskDirectory, "environment/candidate"));
|
|
30
|
+
const candidateName = `hitch-resource-candidate-${randomUUID()}`;
|
|
31
|
+
containers.push(candidateName);
|
|
32
|
+
await docker(["run", "--name", candidateName, "--network", "none", "--platform", config.platform, "--entrypoint", "python", candidate, "-c", 'from pathlib import Path; assert not Path("/data/task.json").exists(); assert not Path("/runtime/official.py").exists()']);
|
|
33
|
+
await observe(candidateName);
|
|
34
|
+
const scores = [], snapshots = [];
|
|
35
|
+
for (const kind of ["resource", "legacy"]) {
|
|
36
|
+
const verifier = await build(path.join(kind === "resource" ? workspace.taskDirectory : path.join(legacy, taskId), "tests"));
|
|
37
|
+
const service = kind === "resource" ? await build(path.join(workspace.taskDirectory, "environment/services/simulator")) : verifier;
|
|
38
|
+
const name = `hitch-resource-simulator-${randomUUID()}`, evidence = path.join(output, kind);
|
|
39
|
+
containers.push(name);
|
|
40
|
+
await mkdir(evidence);
|
|
41
|
+
await docker(["run", "-d", "--name", name, "--network", "none", "--platform", config.platform, "-v", `${evidence}:/evidence`, "--entrypoint", "python", service, "/runtime/server.py"]);
|
|
42
|
+
const call = 'import json,time,urllib.request\nfor i in range(90):\n try:\n urllib.request.urlopen("http://127.0.0.1:8765/health"); break\n except Exception: time.sleep(1)\nelse: raise RuntimeError("simulator not ready")\ndata=json.dumps({"name":"api_search","arguments":{"query":"campaign performance spreadsheet","top_k":3}}).encode()\nr=json.load(urllib.request.urlopen(urllib.request.Request("http://127.0.0.1:8765/call",data=data,headers={"Content-Type":"application/json"})))\nassert "tool_error" not in r, r\nprint(json.dumps(r))';
|
|
43
|
+
await docker(["exec", name, "python", "-c", call]);
|
|
44
|
+
if (kind === "resource")
|
|
45
|
+
await observe(name);
|
|
46
|
+
const verifierName = `hitch-resource-verifier-${randomUUID()}`;
|
|
47
|
+
containers.push(verifierName);
|
|
48
|
+
await docker(["run", "--name", verifierName, "--network", "none", "--platform", config.platform, "-v", `${evidence}:/evidence:ro`, "--entrypoint", "python", verifier, "/runtime/official.py", "/data/task.json", "/evidence/snapshot.json", "/logs/verifier"]);
|
|
49
|
+
await docker(["cp", `${verifierName}:/logs/verifier`, path.join(evidence, "result")]);
|
|
50
|
+
if (kind === "resource")
|
|
51
|
+
await observe(verifierName);
|
|
52
|
+
scores.push({ kind, reward: JSON.parse(await readFile(path.join(evidence, "result/reward.json"), "utf8")), assertions: JSON.parse(await readFile(path.join(evidence, "result/assertions.json"), "utf8")), process: JSON.parse(await readFile(path.join(evidence, "result/process.json"), "utf8")) });
|
|
53
|
+
snapshots.push(JSON.parse(await readFile(path.join(evidence, "snapshot.json"), "utf8")));
|
|
54
|
+
}
|
|
55
|
+
for (const key of ["reward", "assertions", "process"])
|
|
56
|
+
if (JSON.stringify(scores[0][key]) !== JSON.stringify(scores[1][key]))
|
|
57
|
+
throw new Error(`v4/v5 ${key} mismatch`);
|
|
58
|
+
// Upstream assigns random row IDs and current timestamps during setup.
|
|
59
|
+
// Compare stable contract/tool observations, then cross-grade exactly the
|
|
60
|
+
// same source snapshot through the other runtime, without normalizing it.
|
|
61
|
+
if (snapshots[0].task_contract_sha256 !== snapshots[1].task_contract_sha256 || JSON.stringify(snapshots[0].audit) !== JSON.stringify(snapshots[1].audit))
|
|
62
|
+
throw new Error("v4/v5 simulator contract/tool results differ");
|
|
63
|
+
const legacyVerifier = tags[tags.length - 1];
|
|
64
|
+
const crossName = `hitch-resource-crossgrade-${randomUUID()}`;
|
|
65
|
+
containers.push(crossName);
|
|
66
|
+
await docker(["run", "--name", crossName, "--network", "none", "--platform", config.platform, "-v", `${path.join(output, "resource")}:/evidence:ro`, "--entrypoint", "python", legacyVerifier, "/runtime/official.py", "/data/task.json", "/evidence/snapshot.json", "/logs/verifier"]);
|
|
67
|
+
await docker(["cp", `${crossName}:/logs/verifier`, path.join(output, "crossgrade")]);
|
|
68
|
+
for (const [key, fileName] of [["reward", "reward"], ["assertions", "assertions"], ["process", "process"]])
|
|
69
|
+
if (JSON.stringify(scores[0][key]) !== JSON.stringify(JSON.parse(await readFile(path.join(output, `crossgrade/${fileName}.json`), "utf8"))))
|
|
70
|
+
throw new Error(`cross-grade ${key} mismatch`);
|
|
71
|
+
const file = path.join(output, "workspace.json");
|
|
72
|
+
await writeFile(file, JSON.stringify({ ...workspace, executionEnded: true, preflightPlanDigest: preflight.planDigest }));
|
|
73
|
+
await sealResourceEvidence({ store, file, runDirectory: output, owner: `canary-run:${path.basename(output)}`, taskId, requireObserved: true, execution: { observed: { containers: observed } } });
|
|
74
|
+
await finishResourceWorkspace(store, workspace.id, { executionEnded: true, resultSealed: true });
|
|
75
|
+
const result = { protocol: "automationbench-resource-canary@1", output, taskId, paidModelCalls: 0, planDigest: plan.digest, materializedDigest: workspace.materialized_task_digest, identicalToolResults: true, identicalCrossGrade: true, observedRoles: 3, scores, storage: await resourceStorageStats(store) };
|
|
76
|
+
await writeFile(path.join(output, "result.json"), JSON.stringify(result, null, 2));
|
|
77
|
+
console.log(JSON.stringify({ output, identicalToolResults: true, identicalCrossGrade: true, scores: scores.map(({ kind, reward }) => ({ kind, reward })) }));
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
for (const name of containers)
|
|
81
|
+
await docker(["rm", "-f", name]).catch(() => undefined);
|
|
82
|
+
for (const tag of tags)
|
|
83
|
+
await docker(["image", "rm", tag]).catch(() => undefined);
|
|
84
|
+
console.error(`Canary artifacts: ${output}`);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=canary-automation-resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canary-automation-resources.js","sourceRoot":"","sources":["../../scripts/canary-automation-resources.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { mkdtemp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { runCommand } from "../src/foundation/index.js";
|
|
7
|
+
import { configuredResourceStore, finishResourceWorkspace, importResourceBundle, materializeResourceTask, preflightResourceTask, resourceRequest, resourceStorageStats, sealResourceEvidence } from "../src/resources/index.js";
|
|
8
|
+
import { ResourceSpaceSampler } from "./resource-space-sampler.js";
|
|
9
|
+
// Isolated Docker-in-Docker test. Requires preloaded docker:27-dind and registry:2
|
|
10
|
+
// infrastructure images; no host Docker socket or user directories are mounted.
|
|
11
|
+
const [bundle] = process.argv.slice(2);
|
|
12
|
+
if (!bundle)
|
|
13
|
+
throw new Error("Usage: canary-resource-empty-daemon SHARED_TREE_CANARY_BUNDLE");
|
|
14
|
+
const index = JSON.parse(await readFile(path.join(bundle, "index.json"), "utf8"));
|
|
15
|
+
if (index.delivery?.selection?.manifest?.benchmark?.id !== "shared-tree-sums" || index.delivery.selection.tasks.length !== 1
|
|
16
|
+
|| index.delivery.selection.tasks[0].task_id !== "sum-0002")
|
|
17
|
+
throw new Error("expected the shared-tree sum-0002 canary bundle");
|
|
18
|
+
const directory = await mkdtemp(path.join(os.tmpdir(), "hitch-empty-daemon-")), root = path.join(directory, "host");
|
|
19
|
+
const outer = `hitch-empty-daemon-${randomUUID()}`, hostDocker = process.env.HITCH_HOST_DOCKER_PATH || "docker";
|
|
20
|
+
const port = Number(process.env.HITCH_RESOURCE_CANARY_REGISTRY_PORT ?? 52990);
|
|
21
|
+
if (!Number.isSafeInteger(port) || port < 1024 || port > 65535)
|
|
22
|
+
throw new Error("invalid canary port");
|
|
23
|
+
const dind = process.env.HITCH_RESOURCE_DIND_IMAGE || "mirror.gcr.io/library/docker:27-dind";
|
|
24
|
+
const host = (args, timeoutMs = 240_000) => runCommand(hostDocker, args, { timeoutMs });
|
|
25
|
+
const inner = (args, timeoutMs = 240_000) => host(["exec", outer, "docker", ...args], timeoutMs);
|
|
26
|
+
const dataset = path.join(path.dirname(bundle), "dataset");
|
|
27
|
+
const selections = path.join(directory, "selections"), evidenceDirectory = path.join(directory, "retained-evidence");
|
|
28
|
+
let accountingRetries = 0;
|
|
29
|
+
async function dockerAllocated() {
|
|
30
|
+
for (let attempt = 0;; attempt++) {
|
|
31
|
+
try {
|
|
32
|
+
return Number((await host(["exec", outer, "du", "-sk", "/var/lib/docker"])).stdout.split(/\s+/)[0]) * 1024;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
// BuildKit removes owned temporary layers concurrently with the read-only
|
|
36
|
+
// walk. Retry that snapshot, never interpret a failed walk as zero bytes.
|
|
37
|
+
if (attempt >= 4 || !String(error).includes("No such file or directory") || !String(error).includes("du: /var/lib/docker/"))
|
|
38
|
+
throw error;
|
|
39
|
+
accountingRetries++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const sampler = new ResourceSpaceSampler([
|
|
44
|
+
{ directory: dataset, classify: () => "source-dataset-descriptors" },
|
|
45
|
+
{ directory: selections, classify: () => "gear-selection-projections" },
|
|
46
|
+
{ directory: bundle, classify: () => "offline-bundle-input" },
|
|
47
|
+
{ directory: evidenceDirectory, classify: () => "retained-run-evidence" },
|
|
48
|
+
{ directory: root, classify: relative => {
|
|
49
|
+
const prefix = "store/benchmark-resources/";
|
|
50
|
+
if (!relative.startsWith(prefix))
|
|
51
|
+
return "host-configuration-and-records";
|
|
52
|
+
const scope = relative.slice(prefix.length).split(path.sep)[0];
|
|
53
|
+
return { objects: "file-CAS", "descriptor-views": "directory-views-and-unpack-cache", workspaces: "active-private-workspaces", staging: "temporary-import-staging" }[scope] ?? "resource-references-and-quarantine";
|
|
54
|
+
} },
|
|
55
|
+
], dockerAllocated);
|
|
56
|
+
const previousDocker = process.env.HITCH_DOCKER_PATH;
|
|
57
|
+
const result = { protocol: "hitch-empty-daemon-canary@1", directory, paidModelCalls: 0, samples: [] };
|
|
58
|
+
async function sample(phase) {
|
|
59
|
+
const accounting = (await inner(["system", "df", "--format", "{{json .}}"])).stdout.trim();
|
|
60
|
+
const daemonAllocatedKiB = Number((await host(["exec", outer, "du", "-sk", "/var/lib/docker"])).stdout.split(/\s+/)[0]);
|
|
61
|
+
result.samples.push({ phase, daemonAllocatedKiB, dockerAccounting: accounting });
|
|
62
|
+
}
|
|
63
|
+
async function pipeCommands(source, destination) {
|
|
64
|
+
const pack = spawn(...source, { stdio: ["ignore", "pipe", "pipe"] });
|
|
65
|
+
const builder = spawn(...destination, { stdio: ["pipe", "pipe", "pipe"] });
|
|
66
|
+
let diagnostics = "";
|
|
67
|
+
for (const stream of [pack.stderr, builder.stderr, builder.stdout])
|
|
68
|
+
stream.on("data", c => { diagnostics = (diagnostics + c).slice(-8192); });
|
|
69
|
+
pack.stdout.pipe(builder.stdin);
|
|
70
|
+
builder.stdin.on("error", () => pack.kill());
|
|
71
|
+
const timer = setTimeout(() => { pack.kill("SIGKILL"); builder.kill("SIGKILL"); }, 240_000);
|
|
72
|
+
const wait = (child) => new Promise((resolve, reject) => { child.once("error", reject); child.once("close", code => code === 0 ? resolve() : reject(new Error(`canary build failed: ${diagnostics}`))); });
|
|
73
|
+
const pending = [wait(pack), wait(builder)];
|
|
74
|
+
try {
|
|
75
|
+
await Promise.all(pending);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
pack.kill("SIGKILL");
|
|
79
|
+
builder.kill("SIGKILL");
|
|
80
|
+
await Promise.allSettled(pending);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
clearTimeout(timer);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function build(context, tag, platform) {
|
|
88
|
+
await pipeCommands(["tar", ["-C", context, "-cf", "-", "."]], [hostDocker, ["exec", "-i", outer, "docker", "build", "--network=none", "--platform", platform, "--pull=false", "--quiet", "-t", tag, "-"]]);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
result.infrastructureImage = (await host(["image", "inspect", dind, "--format", "{{.Id}}"])).stdout.trim();
|
|
92
|
+
await host(["run", "-d", "--privileged", "--name", outer, "-e", "DOCKER_TLS_CERTDIR=", "-p", `127.0.0.1:${port}:${port}`, dind,
|
|
93
|
+
"dockerd", "--host=unix:///var/run/docker.sock", "--storage-driver=vfs"]);
|
|
94
|
+
let ready = false;
|
|
95
|
+
for (let i = 0; i < 60; i++) {
|
|
96
|
+
try {
|
|
97
|
+
await inner(["info", "--format", "{{.ID}}"], 3000);
|
|
98
|
+
ready = true;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!ready)
|
|
106
|
+
throw new Error("isolated Docker daemon did not become ready");
|
|
107
|
+
const initial = (await inner(["image", "ls", "-aq"])).stdout.trim();
|
|
108
|
+
if (initial)
|
|
109
|
+
throw new Error("new daemon unexpectedly contains images");
|
|
110
|
+
result.emptyInitialDockerStore = true;
|
|
111
|
+
await sample("empty-daemon");
|
|
112
|
+
await pipeCommands([hostDocker, ["image", "save", "registry:2"]], [hostDocker, ["exec", "-i", outer, "docker", "image", "load"]]);
|
|
113
|
+
await inner(["run", "-d", "--name", "offline-registry", "--network", "host", "-e", `REGISTRY_HTTP_ADDR=0.0.0.0:${port}`, "registry:2"]);
|
|
114
|
+
let registryReady = false;
|
|
115
|
+
for (let i = 0; i < 30; i++) {
|
|
116
|
+
try {
|
|
117
|
+
const response = await fetch(`http://localhost:${port}/v2/`, { signal: AbortSignal.timeout(1000) });
|
|
118
|
+
await response.body?.cancel();
|
|
119
|
+
if (response.ok) {
|
|
120
|
+
registryReady = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch { /* Startup is bounded and the actual bundle import remains strict. */ }
|
|
125
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
126
|
+
}
|
|
127
|
+
if (!registryReady)
|
|
128
|
+
throw new Error("isolated registry did not become ready");
|
|
129
|
+
await sample("registry-infrastructure-only");
|
|
130
|
+
await sampler.mark("baseline-with-infrastructure-and-bundle");
|
|
131
|
+
sampler.start();
|
|
132
|
+
await mkdir(selections);
|
|
133
|
+
await writeFile(path.join(selections, "sum-0002.json"), JSON.stringify(index.delivery.selection));
|
|
134
|
+
await sampler.mark("selection-published");
|
|
135
|
+
const wrapper = path.join(directory, "isolated-docker.cjs");
|
|
136
|
+
await writeFile(wrapper, `#!${process.execPath}\nconst child=require('node:child_process').spawn(${JSON.stringify(hostDocker)},['exec',${JSON.stringify(outer)},'docker',...process.argv.slice(2)],{stdio:'inherit'}); child.on('error',e=>{console.error(e);process.exit(1)}); child.on('exit',code=>process.exit(code??1));\n`, { mode: 0o755 });
|
|
137
|
+
process.env.HITCH_DOCKER_PATH = wrapper;
|
|
138
|
+
const transport = Object.fromEntries(index.delivery.images.map((image, i) => [image.resource.manifestDigest, `localhost:${port}/canary/image-${i}@${image.resource.manifestDigest}`]));
|
|
139
|
+
const platform = index.delivery.selection.manifest.execution.platform;
|
|
140
|
+
await resourceRequest(root, "configure", { protocol: "hitch-resource-host@1", transport, imagePolicy: "cache-only", platform, workspace: { mode: "copy" }, offline: { registry: `http://localhost:${port}` } });
|
|
141
|
+
const { store } = await configuredResourceStore(root);
|
|
142
|
+
await sampler.mark("importing");
|
|
143
|
+
const imported = await importResourceBundle(store, bundle, "empty-daemon");
|
|
144
|
+
await sampler.mark("imported");
|
|
145
|
+
const repeated = await importResourceBundle(store, bundle, "empty-daemon");
|
|
146
|
+
if (repeated.transferredBytes !== 0)
|
|
147
|
+
throw new Error("repeat import transferred existing objects");
|
|
148
|
+
await sample("imported");
|
|
149
|
+
await sampler.mark("repeat-imported");
|
|
150
|
+
await inner(["stop", "offline-registry"]);
|
|
151
|
+
await host(["network", "disconnect", "bridge", outer]);
|
|
152
|
+
const { plan } = await preflightResourceTask(store, imported.selection.tasks[0], { owner: "offline-execution", generation: 1, platform });
|
|
153
|
+
const workspace = await materializeResourceTask(store, plan, { owner: "offline-execution", generation: 1, policy: { mode: "copy" } });
|
|
154
|
+
await sampler.mark("active-workspace-and-builds");
|
|
155
|
+
await build(path.join(workspace.taskDirectory, "environment/candidate"), "canary-candidate:fixed", platform);
|
|
156
|
+
await build(path.join(workspace.taskDirectory, "tests"), "canary-verifier:fixed", platform);
|
|
157
|
+
const answer = JSON.parse((await inner(["run", "--rm", "--network", "none", "--platform", platform, "--entrypoint", "python", "canary-candidate:fixed", "-c", 'import json,pathlib; assert not pathlib.Path("/tests/expected.json").exists(); print(json.dumps(sum(json.loads(pathlib.Path("/data/values.json").read_text())[:2])))'])).stdout);
|
|
158
|
+
if (answer !== 3)
|
|
159
|
+
throw new Error("isolated candidate answer differs");
|
|
160
|
+
const score = JSON.parse((await inner(["run", "--rm", "--network", "none", "--platform", platform, "--entrypoint", "sh", "canary-verifier:fixed", "-c", 'mkdir -p /evidence; printf 3 > /evidence/answer.json; python /tests/verify.py /evidence/answer.json && cat /logs/verifier/reward.json'])).stdout);
|
|
161
|
+
if (score.reward !== 1)
|
|
162
|
+
throw new Error("isolated verifier score differs");
|
|
163
|
+
await sample("offline-executed");
|
|
164
|
+
await mkdir(evidenceDirectory);
|
|
165
|
+
const workspaceEvidence = path.join(evidenceDirectory, "workspace.json");
|
|
166
|
+
await writeFile(workspaceEvidence, JSON.stringify({ ...workspace, executionEnded: true, preflightPlanDigest: plan.digest }));
|
|
167
|
+
await sealResourceEvidence({ store, file: workspaceEvidence, runDirectory: evidenceDirectory, owner: "joint-space-canary-sealed-run", taskId: plan.task.task_id, requireObserved: false });
|
|
168
|
+
await writeFile(path.join(evidenceDirectory, "score.json"), JSON.stringify({ answer, score }));
|
|
169
|
+
await sampler.mark("executed-and-evidence-sealed");
|
|
170
|
+
Object.assign(result, { emptyInitialFileCAS: true, emptyTargetRegistry: true, sharedHostDockerLayers: false, externalNetworkDisconnected: true,
|
|
171
|
+
registryStoppedDuringExecution: true, answer, score, transferredBytes: imported.transferredBytes, repeatTransferredBytes: repeated.transferredBytes,
|
|
172
|
+
materializedTaskDigest: workspace.materialized_task_digest, storage: await resourceStorageStats(store) });
|
|
173
|
+
await finishResourceWorkspace(store, workspace.id, { executionEnded: true, resultSealed: true });
|
|
174
|
+
await sampler.mark("workspace-reclaimed-evidence-retained");
|
|
175
|
+
await sampler.stop();
|
|
176
|
+
result.jointSpace = { ...sampler.report(), accountingRetries };
|
|
177
|
+
result.materialization = { copiedBytes: workspace.copiedBytes, clonedBytes: workspace.clonedBytes, fallbackReasons: workspace.fallbackReasons };
|
|
178
|
+
result.finalStorage = await resourceStorageStats(store);
|
|
179
|
+
await writeFile(path.join(directory, "result.json"), JSON.stringify(result, null, 2));
|
|
180
|
+
console.log(JSON.stringify({ directory, emptyInitialDockerStore: true, externalNetworkDisconnected: true, answer, score }));
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
await writeFile(path.join(directory, "failure.json"), JSON.stringify({ ...result, error: String(error) }, null, 2));
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
await sampler.stop().catch(error => console.error(`Space sampling failed: ${String(error)}`));
|
|
188
|
+
if (previousDocker === undefined)
|
|
189
|
+
delete process.env.HITCH_DOCKER_PATH;
|
|
190
|
+
else
|
|
191
|
+
process.env.HITCH_DOCKER_PATH = previousDocker;
|
|
192
|
+
await host(["rm", "-f", "-v", outer]).catch(() => undefined);
|
|
193
|
+
console.error(`Canary artifacts: ${directory}`);
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=canary-resource-empty-daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canary-resource-empty-daemon.js","sourceRoot":"","sources":["../../scripts/canary-resource-empty-daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,eAAe,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEhO,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,mFAAmF;AACnF,gFAAgF;AAChF,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvC,IAAI,CAAC,MAAM;IAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;AAC9F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAClF,IAAI,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,kBAAkB,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;OACvH,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,UAAU;IAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AAClI,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACpH,MAAM,KAAK,GAAG,sBAAsB,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,QAAQ,CAAC;AAChH,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,mCAAmC,IAAI,KAAK,CAAC,CAAC;AAC9E,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK;IAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AACvG,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,sCAAsC,CAAC;AAC7F,MAAM,IAAI,GAAG,CAAC,IAAc,EAAE,SAAS,GAAG,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;AAClG,MAAM,KAAK,GAAG,CAAC,IAAc,EAAE,SAAS,GAAG,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;AAC3G,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC;AAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;AACrH,IAAI,iBAAiB,GAAG,CAAC,CAAC;AAC1B,KAAK,UAAU,eAAe;IAC5B,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC;YAAC,OAAO,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,EAAC,KAAK,EAAC,IAAI,EAAC,KAAK,EAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAAC,CAAC;QAC/G,OAAO,KAAK,EAAE,CAAC;YACb,0EAA0E;YAC1E,0EAA0E;YAC1E,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;gBAAE,MAAM,KAAK,CAAC;YACzI,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;AACH,CAAC;AACD,MAAM,OAAO,GAAG,IAAI,oBAAoB,CAAC;IACvC,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,4BAA4B,EAAE;IACpE,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,4BAA4B,EAAE;IACvE,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,sBAAsB,EAAE;IAC7D,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,uBAAuB,EAAE;IACzE,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;YACtC,MAAM,MAAM,GAAG,4BAA4B,CAAC;YAC5C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;gBAAE,OAAO,gCAAgC,CAAC;YAC1E,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;YAChE,OAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,kCAAkC,EAAE,UAAU,EAAE,2BAA2B,EAAE,OAAO,EAAE,0BAA0B,EAA4B,CAAC,KAAK,CAAC,IAAI,oCAAoC,CAAC;QACjP,CAAC,EAAE;CACJ,EAAE,eAAe,CAAC,CAAC;AACpB,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;AACrD,MAAM,MAAM,GAA4B,EAAE,QAAQ,EAAE,6BAA6B,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC/H,KAAK,UAAU,MAAM,CAAC,KAAa;IACjC,MAAM,UAAU,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3F,MAAM,kBAAkB,GAAG,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvH,MAAM,CAAC,OAAqB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC;AAClG,CAAC;AACD,KAAK,UAAU,YAAY,CAAC,MAA0B,EAAE,WAA+B;IACrF,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3E,IAAI,WAAW,GAAG,EAAE,CAAC;IAAC,KAAK,MAAM,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,WAAW,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/N,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,IAAI,CAAC;QAAC,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;IACnC,OAAO,KAAK,EAAE,CAAC;QAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAAC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAAC,MAAM,KAAK,CAAC;IAAC,CAAC;YACxG,CAAC;QAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;AAClC,CAAC;AACD,KAAK,UAAU,KAAK,CAAC,OAAe,EAAE,GAAW,EAAE,QAAgB;IACjE,MAAM,YAAY,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AAC7M,CAAC;AACD,IAAI,CAAC;IACH,MAAM,CAAC,mBAAmB,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3G,MAAM,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,aAAa,IAAI,IAAI,IAAI,EAAE,EAAE,IAAI;QAC5H,SAAS,EAAE,oCAAoC,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAC5E,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC;YAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;YAAC,KAAK,GAAG,IAAI,CAAC;YAAC,MAAM;QAAC,CAAC;QAChF,MAAM,CAAC;YAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAAC,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAAC,IAAI,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7I,MAAM,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAAC,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IACpE,MAAM,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAClI,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IACxI,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC;YAAC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,oBAAoB,IAAI,MAAM,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YAAC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAAC,aAAa,GAAG,IAAI,CAAC;gBAAC,MAAM;YAAC,CAAC;QAAC,CAAC;QAC7L,MAAM,CAAC,CAAC,qEAAqE,CAAC,CAAC;QAC/E,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC9E,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;IAC7C,MAAM,OAAO,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC/E,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;IAAC,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAC,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1H,MAAM,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAC5D,MAAM,SAAS,CAAC,OAAO,EAAE,KAAK,OAAO,CAAC,QAAQ,qDAAqD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,kKAAkK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACnV,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC;IACxC,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAA+C,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,EAAE,aAAa,IAAI,iBAAiB,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;IACzO,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC;IACtE,MAAM,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,uBAAuB,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,oBAAoB,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAChN,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3E,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3E,IAAI,QAAQ,CAAC,gBAAgB,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACnG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IAAC,MAAM,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAChE,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAAC,MAAM,IAAI,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAClG,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,qBAAqB,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC3I,MAAM,SAAS,GAAG,MAAM,uBAAuB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACtI,MAAM,OAAO,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAClD,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,uBAAuB,CAAC,EAAE,wBAAwB,EAAE,QAAQ,CAAC,CAAC;IAC7G,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,uBAAuB,EAAE,QAAQ,CAAC,CAAC;IAC5F,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,wBAAwB,EAAE,IAAI,EAAE,sKAAsK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAChV,IAAI,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,uIAAuI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3S,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC3E,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACjC,MAAM,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC/B,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAC,gBAAgB,CAAC,CAAC;IACxE,MAAM,SAAS,CAAC,iBAAiB,EAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5H,MAAM,oBAAoB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,iBAAiB,EAAE,KAAK,EAAE,+BAA+B,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3L,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAC,YAAY,CAAC,EAAC,IAAI,CAAC,SAAS,CAAC,EAAC,MAAM,EAAC,KAAK,EAAC,CAAC,CAAC,CAAC;IAC1F,MAAM,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACnD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,mBAAmB,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,2BAA2B,EAAE,IAAI;QAC5I,8BAA8B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,EAAE,sBAAsB,EAAE,QAAQ,CAAC,gBAAgB;QACnJ,sBAAsB,EAAE,SAAS,CAAC,wBAAwB,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5G,MAAM,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IACjG,MAAM,OAAO,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IAClF,MAAM,CAAC,UAAU,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,iBAAiB,EAAE,CAAC;IAC/D,MAAM,CAAC,eAAe,GAAG,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,eAAe,EAAE,SAAS,CAAC,eAAe,EAAE,CAAC;IAChJ,MAAM,CAAC,YAAY,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,uBAAuB,EAAE,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAC9H,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAAC,MAAM,KAAK,CAAC;AACnI,CAAC;QAAS,CAAC;IACT,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,0BAA0B,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,IAAI,cAAc,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;;QAAM,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,cAAc,CAAC;IAC5H,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC7D,OAAO,CAAC,KAAK,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;AAClD,CAAC"}
|