@tangle-network/agent-runtime 0.340.0 → 0.342.1
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/dist/{activation-DGDl4wwI.d.ts → activation-CXqtijue.d.ts} +2 -2
- package/dist/{activation-D2PVljaw.js → activation-DOH7Fnyp.js} +4 -4
- package/dist/{activation-D2PVljaw.js.map → activation-DOH7Fnyp.js.map} +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +2 -2
- package/dist/{bundle-DNUq-OPW.js → bundle-Cwpit6Tg.js} +2 -2
- package/dist/{bundle-DNUq-OPW.js.map → bundle-Cwpit6Tg.js.map} +1 -1
- package/dist/candidate-execution/index.js +4 -4
- package/dist/{driver-control-acknowledgers-MTrs8HAF.js → coordination-manager-HQE0bIav.js} +4852 -4539
- package/dist/coordination-manager-HQE0bIav.js.map +1 -0
- package/dist/{delegate-CtJIS-tp.js → delegate-DmShSdjy.js} +2 -2
- package/dist/{delegate-CtJIS-tp.js.map → delegate-DmShSdjy.js.map} +1 -1
- package/dist/durable.d.ts +1 -1
- package/dist/durable.js +451 -358
- package/dist/durable.js.map +1 -1
- package/dist/{graph-DfWqp_1e.js → graph-BCghJFlS.js} +5 -5
- package/dist/{graph-DfWqp_1e.js.map → graph-BCghJFlS.js.map} +1 -1
- package/dist/{improve-CKRVQqzt.js → improve-Dga6OYt-.js} +837 -704
- package/dist/improve-Dga6OYt-.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +9 -9
- package/dist/intelligence.d.ts +2 -2
- package/dist/intelligence.js +205 -191
- package/dist/intelligence.js.map +1 -1
- package/dist/kernel.d.ts +1 -1
- package/dist/kernel.js +9 -9
- package/dist/{loop-runner-DNWbTcVm.js → loop-runner-CW87Vqoj.js} +2 -2
- package/dist/{loop-runner-DNWbTcVm.js.map → loop-runner-CW87Vqoj.js.map} +1 -1
- package/dist/{loop-runner-C4EWEcXf.d.ts → loop-runner-CuhbgVGo.d.ts} +2 -2
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +5 -5
- package/dist/{prepare-FzJoS68l.js → prepare-C-cWCyt3.js} +988 -735
- package/dist/prepare-C-cWCyt3.js.map +1 -0
- package/dist/{profile-DToH0XEs.js → profile-CbMw5hAn.js} +2 -2
- package/dist/{profile-DToH0XEs.js.map → profile-CbMw5hAn.js.map} +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/{provision-supervisor-DqvWXmAE.js → provision-supervisor-BWR_TJFg.js} +444 -419
- package/dist/provision-supervisor-BWR_TJFg.js.map +1 -0
- package/dist/{runtime-C55Zgo1R.js → runtime-CuRTZFe6.js} +1245 -1028
- package/dist/runtime-CuRTZFe6.js.map +1 -0
- package/dist/{sandbox-profile-compat-DRr3JwDx.js → sandbox-profile-compat-FN2kab2-.js} +72 -72
- package/dist/{sandbox-profile-compat-DRr3JwDx.js.map → sandbox-profile-compat-FN2kab2-.js.map} +1 -1
- package/dist/{search-executor-ChOlRBgg.js → search-executor-0-SjHAao.js} +3 -3
- package/dist/{search-executor-ChOlRBgg.js.map → search-executor-0-SjHAao.js.map} +1 -1
- package/dist/{server-DkVBSN_S.js → server-DTUK2wW1.js} +4 -4
- package/dist/{server-DkVBSN_S.js.map → server-DTUK2wW1.js.map} +1 -1
- package/dist/{structural-rollout-C1LEk_zq.js → structural-rollout-kfaZgAkd.js} +3 -3
- package/dist/{structural-rollout-C1LEk_zq.js.map → structural-rollout-kfaZgAkd.js.map} +1 -1
- package/dist/{supervise-CaUAxZZP.js → supervise-C_GAgiJU.js} +6346 -5447
- package/dist/supervise-C_GAgiJU.js.map +1 -0
- package/dist/{supervisor-VXuN2OHT.js → supervisor-C_03z693.js} +13823 -12826
- package/dist/supervisor-C_03z693.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +13 -13
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/{types-DZ6L0Bv3.d.ts → types-Cgs89PQd.d.ts} +266 -356
- package/dist/workspace-store/index.js +273 -265
- package/dist/workspace-store/index.js.map +1 -1
- package/package.json +10 -10
- package/dist/driver-control-acknowledgers-MTrs8HAF.js.map +0 -1
- package/dist/improve-CKRVQqzt.js.map +0 -1
- package/dist/prepare-FzJoS68l.js.map +0 -1
- package/dist/provision-supervisor-DqvWXmAE.js.map +0 -1
- package/dist/runtime-C55Zgo1R.js.map +0 -1
- package/dist/supervise-CaUAxZZP.js.map +0 -1
- package/dist/supervisor-VXuN2OHT.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { _ as parseAgentCandidateProfileActivation, c as buildLaunch, f as exactProfileExecutorFiles, h as modelRoutes, l as candidateEntrypointReceipt, m as materializeAgentCandidateProfilePlan, n as PI_CANDIDATE_SESSION_DIR_ENV, r as absoluteExecutionCwd, s as assertCandidateProfileExecutionSupport, t as PI_CANDIDATE_AGENT_DIR_ENV, u as candidateProfileAgentPaths, x as requirePublicCandidateConfigValue } from "./profile-
|
|
1
|
+
import { A as verifyMaterializedProfileWorkspace, B as sha256Bytes$1, D as readMaterializedWorkspaceFiles, F as canonicalCandidateDocument, H as hasControlCharacter, I as deepFreezeCandidate, L as embeddedCandidateArtifact, M as verifyWorkspaceSnapshotArtifacts, N as canonicalCandidateBytes$1, O as readVerifiedArtifact, P as canonicalCandidateDigest$1, R as immutableCandidateValue, S as isWellFormedUnicode, X as errorMessage, b as persistCandidateOutputArtifact, d as readCandidateGitHubResource, f as verifyCandidateCode, j as verifyMaterializedWorkspace, k as verifyBytes, m as verifyTaskOutcomePatch, p as verifyTaskCheckout, w as artifactCacheKey, x as assertExactObjectKeys, z as omitTopLevelDigest } from "./sandbox-profile-compat-FN2kab2-.js";
|
|
2
|
+
import { _ as parseAgentCandidateProfileActivation, c as buildLaunch, f as exactProfileExecutorFiles, h as modelRoutes, l as candidateEntrypointReceipt, m as materializeAgentCandidateProfilePlan, n as PI_CANDIDATE_SESSION_DIR_ENV, r as absoluteExecutionCwd, s as assertCandidateProfileExecutionSupport, t as PI_CANDIDATE_AGENT_DIR_ENV, u as candidateProfileAgentPaths, x as requirePublicCandidateConfigValue } from "./profile-CbMw5hAn.js";
|
|
3
3
|
import { i as redactProtectedValue, n as createProtectedRecordRedactor, r as redactProtectedReason, t as assertNoProtectedBytes } from "./protected-redaction-DFCeo4vg.js";
|
|
4
4
|
import { agentCandidateArtifactRefSchema, agentCandidateBenchmarkResultEvidenceSchema, agentCandidateBenchmarkSuiteSchema, agentCandidateBenchmarkTaskSchema, agentCandidateBundleSchema, agentCandidateContainerSchema, agentCandidateExecutionLimitsSchema, agentCandidateExecutionPlanEvidenceSchema, agentCandidateExecutionPlanMaterialSchema, agentCandidateMaterializationReceiptSchema, agentCandidateModelAccessNetworkSchema, agentCandidateModelSettlementEvidenceSchema, agentCandidateProfilePlanEvidenceSchema, agentCandidateResolvedModelSchema, agentCandidateRunCellSchema, agentCandidateRunReceiptSchema, agentCandidateTaskOutcomeEvidenceSchema, agentCandidateTaskOutcomeSpecSchema, agentCandidateTerminationSchema, agentCandidateWorkspaceManifestMaterialSchema, agentCandidateWorkspaceSnapshotEvidenceSchema, sha256DigestSchema } from "@tangle-network/agent-interface";
|
|
5
5
|
import { REDACTION_VERSION, isLlmSpan } from "@tangle-network/agent-eval";
|
|
@@ -2334,89 +2334,6 @@ function retryLineageDigest(prepared, resultTimeoutMs) {
|
|
|
2334
2334
|
});
|
|
2335
2335
|
}
|
|
2336
2336
|
//#endregion
|
|
2337
|
-
//#region src/candidate-execution/executor-capture.ts
|
|
2338
|
-
const sealedFinalCaptureBrand = Symbol("sealedAgentCandidateExecutorFinalCapture");
|
|
2339
|
-
/** Validate and detach the only candidate-authored fields accepted from execution. */
|
|
2340
|
-
function sealAgentCandidateProtectedRunCapture(value) {
|
|
2341
|
-
const capture = requireRecord(value, "candidate execution capture");
|
|
2342
|
-
assertExactObjectKeys(capture, ["executionId", "termination"], "candidate execution capture");
|
|
2343
|
-
if (typeof capture.executionId !== "string" || capture.executionId.length === 0) throw new Error("candidate execution capture has an invalid executionId");
|
|
2344
|
-
return Object.freeze({
|
|
2345
|
-
executionId: capture.executionId,
|
|
2346
|
-
termination: Object.freeze(agentCandidateTerminationSchema.parse(capture.termination))
|
|
2347
|
-
});
|
|
2348
|
-
}
|
|
2349
|
-
/** Validate, detach, and freeze evaluator-owned evidence captured after process death. */
|
|
2350
|
-
function sealAgentCandidateExecutorFinalCapture(value, expectedOutcome) {
|
|
2351
|
-
const capture = requireRecord(value, "candidate final capture");
|
|
2352
|
-
assertExactObjectKeys(capture, [], "candidate final capture", [
|
|
2353
|
-
"taskOutcome",
|
|
2354
|
-
"memoryAfter",
|
|
2355
|
-
"evidence"
|
|
2356
|
-
]);
|
|
2357
|
-
const taskOutcome = capture.taskOutcome ? sealTaskOutcomeCapture(capture.taskOutcome, expectedOutcome) : void 0;
|
|
2358
|
-
const memoryAfter = capture.memoryAfter ? sealMemoryCapture(capture.memoryAfter) : void 0;
|
|
2359
|
-
if (capture.evidence !== void 0 && !(capture.evidence instanceof Uint8Array)) throw new Error("candidate executor evidence must be a byte array");
|
|
2360
|
-
const evidence = capture.evidence ? Uint8Array.from(capture.evidence) : void 0;
|
|
2361
|
-
return Object.freeze({
|
|
2362
|
-
...taskOutcome ? { taskOutcome } : {},
|
|
2363
|
-
...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {},
|
|
2364
|
-
...evidence ? { evidence } : {},
|
|
2365
|
-
[sealedFinalCaptureBrand]: true
|
|
2366
|
-
});
|
|
2367
|
-
}
|
|
2368
|
-
/** Prove exact process death before any final evidence capture. */
|
|
2369
|
-
function sealAgentCandidateExecutorStopAcknowledgement(value) {
|
|
2370
|
-
const capture = requireRecord(value, "candidate stop acknowledgement");
|
|
2371
|
-
assertExactObjectKeys(capture, ["stopped"], "candidate stop acknowledgement");
|
|
2372
|
-
if (capture.stopped !== true) throw new Error("candidate stop acknowledgement does not prove process death");
|
|
2373
|
-
}
|
|
2374
|
-
function sealMemoryCapture(value) {
|
|
2375
|
-
const capture = requireRecord(value, "candidate memory capture");
|
|
2376
|
-
assertExactObjectKeys(capture, ["afterState", "archive"], "candidate memory capture");
|
|
2377
|
-
if (!(capture.archive instanceof Uint8Array)) throw new Error("candidate memory capture archive must be a byte array");
|
|
2378
|
-
return Object.freeze({
|
|
2379
|
-
afterState: Object.freeze(agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState)),
|
|
2380
|
-
archive: Uint8Array.from(capture.archive)
|
|
2381
|
-
});
|
|
2382
|
-
}
|
|
2383
|
-
function sealTaskOutcomeCapture(value, expected) {
|
|
2384
|
-
const capture = requireRecord(value, "candidate task capture");
|
|
2385
|
-
if (capture.kind === "output") {
|
|
2386
|
-
assertExactObjectKeys(capture, ["kind", "bytes"], "candidate task output capture");
|
|
2387
|
-
if (expected.kind !== "output") throw new Error("candidate task output capture does not match the signed outcome kind");
|
|
2388
|
-
if (!(capture.bytes instanceof Uint8Array)) throw new Error("candidate task output capture must contain a byte array");
|
|
2389
|
-
if (capture.bytes.byteLength > expected.maxBytes) throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
|
|
2390
|
-
return Object.freeze({
|
|
2391
|
-
kind: "output",
|
|
2392
|
-
bytes: Uint8Array.from(capture.bytes)
|
|
2393
|
-
});
|
|
2394
|
-
}
|
|
2395
|
-
assertExactObjectKeys(capture, [
|
|
2396
|
-
"kind",
|
|
2397
|
-
"resultTree",
|
|
2398
|
-
"afterState",
|
|
2399
|
-
"archive",
|
|
2400
|
-
"gitDiff"
|
|
2401
|
-
], "candidate task capture");
|
|
2402
|
-
if (capture.kind !== "workspace") throw new Error("candidate task capture has an invalid outcome kind");
|
|
2403
|
-
if (expected.kind !== "workspace") throw new Error("candidate workspace capture does not match the signed outcome kind");
|
|
2404
|
-
if (typeof capture.resultTree !== "string" || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(capture.resultTree)) throw new Error("candidate task capture resultTree is not a Git object id");
|
|
2405
|
-
if (!(capture.archive instanceof Uint8Array) || !(capture.gitDiff instanceof Uint8Array)) throw new Error("candidate task capture archive and gitDiff must be byte arrays");
|
|
2406
|
-
const afterState = agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState);
|
|
2407
|
-
return Object.freeze({
|
|
2408
|
-
kind: "workspace",
|
|
2409
|
-
resultTree: capture.resultTree,
|
|
2410
|
-
afterState: Object.freeze(afterState),
|
|
2411
|
-
archive: Uint8Array.from(capture.archive),
|
|
2412
|
-
gitDiff: Uint8Array.from(capture.gitDiff)
|
|
2413
|
-
});
|
|
2414
|
-
}
|
|
2415
|
-
function requireRecord(value, label) {
|
|
2416
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
|
|
2417
|
-
return value;
|
|
2418
|
-
}
|
|
2419
|
-
//#endregion
|
|
2420
2337
|
//#region src/candidate-execution/finalize.ts
|
|
2421
2338
|
/** Builds a candidate run receipt exclusively from protected trace and memory evidence. */
|
|
2422
2339
|
async function finalizeAgentCandidateRun(state, capture, traceStore, traceIdentity, settlement, evidence, protectedValues, writeRedactionReport, signal) {
|
|
@@ -3117,230 +3034,187 @@ async function persistFailureEvidence(state, reason, failureClass, termination,
|
|
|
3117
3034
|
});
|
|
3118
3035
|
}
|
|
3119
3036
|
//#endregion
|
|
3120
|
-
//#region src/candidate-execution/
|
|
3121
|
-
/**
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
const
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
}
|
|
3134
|
-
let tracked;
|
|
3135
|
-
tracked = started.finally(() => pendingWrites.delete(tracked));
|
|
3136
|
-
pendingWrites.add(tracked);
|
|
3137
|
-
return tracked;
|
|
3138
|
-
};
|
|
3139
|
-
const store = Object.freeze({
|
|
3140
|
-
appendRun: (run) => write(() => inner.appendRun(redactor.record(run))),
|
|
3141
|
-
updateRun: (runId, patch) => write(() => inner.updateRun(redactor.identifier(runId), redactor.record(patch))),
|
|
3142
|
-
appendSpan: (span) => write(async () => {
|
|
3143
|
-
if (span.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
|
|
3144
|
-
await inner.appendSpan(redactor.record(span));
|
|
3145
|
-
}),
|
|
3146
|
-
updateSpan: (spanId, patch) => write(async () => {
|
|
3147
|
-
if (patch.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
|
|
3148
|
-
await inner.updateSpan(redactor.identifier(spanId), redactor.record(patch));
|
|
3149
|
-
}),
|
|
3150
|
-
appendEvent: (event) => write(() => inner.appendEvent(redactor.record(event))),
|
|
3151
|
-
appendArtifact: (artifact) => write(() => inner.appendArtifact(redactor.record(artifact))),
|
|
3152
|
-
appendBudgetEntry: (entry) => write(() => inner.appendBudgetEntry(redactor.record(entry))),
|
|
3153
|
-
getRun: async (runId) => inner.getRun(redactor.identifier(runId)),
|
|
3154
|
-
listRuns: async (filter) => inner.listRuns(filter ? redactor.query(filter) : void 0),
|
|
3155
|
-
spans: async (filter) => inner.spans(filter ? redactor.query(filter) : void 0),
|
|
3156
|
-
events: async (filter) => inner.events(filter ? redactor.query(filter) : void 0),
|
|
3157
|
-
budget: async (runId) => inner.budget(redactor.identifier(runId)),
|
|
3158
|
-
artifacts: async (runId) => inner.artifacts(redactor.identifier(runId))
|
|
3159
|
-
});
|
|
3160
|
-
return Object.freeze({
|
|
3161
|
-
store,
|
|
3162
|
-
closeWrites: async () => {
|
|
3163
|
-
acceptsWrites = false;
|
|
3164
|
-
await Promise.all([...pendingWrites]);
|
|
3165
|
-
},
|
|
3166
|
-
identity: (trace) => redactor.traceIdentity(trace),
|
|
3167
|
-
report: () => redactor.report()
|
|
3168
|
-
});
|
|
3037
|
+
//#region src/candidate-execution/execute-cleanup.ts
|
|
3038
|
+
/**
|
|
3039
|
+
* Failure and cleanup paths of an execution: closing isolated memory, settling the model grant,
|
|
3040
|
+
* recording a failed attempt's terminal result, and reporting why a run failed.
|
|
3041
|
+
*/
|
|
3042
|
+
async function failBeforeActivation(run, error, reason) {
|
|
3043
|
+
const { prepared, state } = run;
|
|
3044
|
+
beginPreparedCandidateSettlement(prepared);
|
|
3045
|
+
const cleanupDeadlineAtMs = candidateCleanupDeadline(run.cleanupTimeoutMs);
|
|
3046
|
+
const [memoryClose, settled] = await Promise.all([closeMemoryAccess(state, reason, cleanupDeadlineAtMs), settleModelGrant(state, reason, cleanupDeadlineAtMs)]);
|
|
3047
|
+
const cleanupProven = memoryClose.closed && settled.settlement !== void 0;
|
|
3048
|
+
consumePreparedCandidateExecution(prepared, cleanupProven ? "failed" : "cleanup-failed");
|
|
3049
|
+
return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, memoryClose.error, settled.error, !cleanupProven ? /* @__PURE__ */ new Error("prepared access cleanup remains incomplete and may be retried by disposal") : void 0), []), void 0, settled.settlement?.usage ?? null);
|
|
3169
3050
|
}
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
const
|
|
3175
|
-
const
|
|
3176
|
-
|
|
3177
|
-
const
|
|
3178
|
-
|
|
3179
|
-
let
|
|
3180
|
-
try {
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
executionId: state.executionId,
|
|
3194
|
-
purpose: "execution-plan",
|
|
3195
|
-
bytes: state.executionPlan.bytes
|
|
3196
|
-
}), persistCandidateOutputArtifact(options.outputArtifacts, {
|
|
3197
|
-
executionId: state.executionId,
|
|
3198
|
-
purpose: "materialization-receipt",
|
|
3199
|
-
bytes: state.materializationReceipt.bytes
|
|
3200
|
-
})]);
|
|
3201
|
-
preparationEvidence = Object.freeze({
|
|
3202
|
-
executionPlan,
|
|
3203
|
-
materializationReceipt
|
|
3204
|
-
});
|
|
3205
|
-
} catch (error) {
|
|
3206
|
-
return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
|
|
3207
|
-
}
|
|
3208
|
-
let acquired;
|
|
3209
|
-
try {
|
|
3210
|
-
acquired = await options.claimStore.tryClaim(candidateExecutionClaim(prepared, preparationEvidence));
|
|
3211
|
-
} catch (error) {
|
|
3212
|
-
return await failBeforeActivation(prepared, state, error, "failed", cleanupTimeoutMs);
|
|
3051
|
+
/** Fail a claimed attempt before the candidate may run: clean up, then record the failure. */
|
|
3052
|
+
async function failClaimedExecution(run, lease, error, failureClass, access = {}) {
|
|
3053
|
+
const { prepared, state, claimStore, outputArtifacts } = run;
|
|
3054
|
+
beginPreparedCandidateSettlement(prepared);
|
|
3055
|
+
const cleanupDeadlineAtMs = candidateCleanupDeadline(run.cleanupTimeoutMs);
|
|
3056
|
+
const [memoryClose, settled] = await Promise.all([closeMemoryAccess(state, "failed", cleanupDeadlineAtMs), settleModelGrant(state, "failed", cleanupDeadlineAtMs)]);
|
|
3057
|
+
const protectedValues = protectedEnvironmentValues(access.activation, access.memoryActivation);
|
|
3058
|
+
const safeReason = redactProtectedReason(joinErrors(error, memoryClose.error, settled.error), protectedValues);
|
|
3059
|
+
let finishFailed = false;
|
|
3060
|
+
let persistenceFailure;
|
|
3061
|
+
if (settled.settlement && memoryClose.closed) try {
|
|
3062
|
+
const modelSettlement = await withinCandidateCleanupDeadline(() => persistCandidateModelSettlement(state, settled.settlement, outputArtifacts), lease.expiresAtMs, "candidate pre-run model-settlement persistence");
|
|
3063
|
+
const failureEvidence = await withinCandidateCleanupDeadline(() => persistFailureEvidence(state, safeReason, failureClass, void 0, outputArtifacts), lease.expiresAtMs, "candidate pre-run failure-evidence persistence");
|
|
3064
|
+
finishFailed = !await finishClaim(claimStore, lease, {
|
|
3065
|
+
status: "failed",
|
|
3066
|
+
failureClass,
|
|
3067
|
+
usage: settled.settlement.usage,
|
|
3068
|
+
modelSettlement: modelSettlement.artifact,
|
|
3069
|
+
failureEvidence
|
|
3070
|
+
}, lease.expiresAtMs);
|
|
3071
|
+
} catch (persistenceError) {
|
|
3072
|
+
finishFailed = true;
|
|
3073
|
+
persistenceFailure = persistenceError;
|
|
3213
3074
|
}
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
if (Date.now() >= deadlineAtMs || deadlineAtMs > state.reservationExpiresAtMs || requiredLeaseExpiry > acquired.lease.expiresAtMs) return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, /* @__PURE__ */ new Error("candidate claim no longer covers its full execution and cleanup window"), "failed", cleanupTimeoutMs, "pre-model-infrastructure");
|
|
3220
|
-
let activation;
|
|
3075
|
+
consumePreparedCandidateExecution(prepared, "failed");
|
|
3076
|
+
return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(safeReason, persistenceFailure, memoryClose.error, settled.error, !memoryClose.closed || !settled.settlement ? /* @__PURE__ */ new Error("candidate claim remains recoverable until protected cleanup is proven") : void 0, finishFailed ? /* @__PURE__ */ new Error("candidate execution terminal record could not be persisted") : void 0), protectedValues), void 0, settled.settlement?.usage ?? null);
|
|
3077
|
+
}
|
|
3078
|
+
async function closeMemoryAccess(state, reason, cleanupDeadlineAtMs) {
|
|
3079
|
+
if (state.memory.mode === "disabled") return { closed: true };
|
|
3221
3080
|
try {
|
|
3222
|
-
const activated = await withinCandidateCleanupDeadline(() => state.ports.models.activateGrant({
|
|
3223
|
-
executionId: state.executionId,
|
|
3224
|
-
preparationId: state.preparationId,
|
|
3225
|
-
grantDigest: state.modelReservation.digest,
|
|
3226
|
-
resolved: state.resolvedModel,
|
|
3227
|
-
deadlineAtMs
|
|
3228
|
-
}), Math.min(deadlineAtMs, candidateCleanupDeadline(cleanupTimeoutMs)), "protected model activation");
|
|
3229
|
-
activation = Object.freeze({ env: Object.freeze({ ...activated.env }) });
|
|
3230
|
-
} catch (error) {
|
|
3231
|
-
return await failClaimedExecution(prepared, state, acquired.lease, options.claimStore, options.outputArtifacts, new Error("protected model activation failed", { cause: error }), "failed", cleanupTimeoutMs, "pre-model-infrastructure");
|
|
3232
|
-
}
|
|
3233
|
-
let memoryActivation;
|
|
3234
|
-
if (state.memory.mode === "isolated") try {
|
|
3235
3081
|
const reservation = state.memoryReservation;
|
|
3236
3082
|
if (!reservation) throw new Error("isolated memory reservation is missing");
|
|
3237
|
-
const
|
|
3083
|
+
const closed = await withinCandidateCleanupDeadline(() => state.ports.memory.close({
|
|
3238
3084
|
executionId: state.executionId,
|
|
3239
3085
|
preparationId: reservation.preparationId,
|
|
3240
3086
|
accessDigest: reservation.accessDigest,
|
|
3241
3087
|
effectiveNamespace: reservation.effectiveNamespace,
|
|
3242
|
-
|
|
3243
|
-
}),
|
|
3244
|
-
|
|
3088
|
+
reason
|
|
3089
|
+
}), cleanupDeadlineAtMs, "isolated memory closure");
|
|
3090
|
+
if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("isolated memory access did not acknowledge closure");
|
|
3091
|
+
return { closed: true };
|
|
3245
3092
|
} catch (error) {
|
|
3246
|
-
return
|
|
3093
|
+
return {
|
|
3094
|
+
closed: false,
|
|
3095
|
+
error
|
|
3096
|
+
};
|
|
3247
3097
|
}
|
|
3248
|
-
|
|
3098
|
+
}
|
|
3099
|
+
async function settleModelGrant(state, reason, cleanupDeadlineAtMs) {
|
|
3249
3100
|
try {
|
|
3250
|
-
|
|
3101
|
+
return { settlement: sealAgentCandidateModelSettlement(await withinCandidateCleanupDeadline(() => state.ports.models.settleGrant({
|
|
3102
|
+
executionId: state.executionId,
|
|
3103
|
+
preparationId: state.preparationId,
|
|
3104
|
+
grantDigest: state.modelReservation.digest,
|
|
3105
|
+
resolved: state.resolvedModel,
|
|
3106
|
+
reason
|
|
3107
|
+
}), cleanupDeadlineAtMs, "protected model settlement"), {
|
|
3108
|
+
preparationId: state.preparationId,
|
|
3109
|
+
grantDigest: state.modelReservation.digest,
|
|
3110
|
+
model: state.resolvedModel.model
|
|
3111
|
+
}) };
|
|
3251
3112
|
} catch (error) {
|
|
3252
|
-
return
|
|
3113
|
+
return { error: new Error("protected model settlement failed", { cause: error }) };
|
|
3253
3114
|
}
|
|
3115
|
+
}
|
|
3116
|
+
async function finishClaim(store, lease, terminal, deadlineAtMs) {
|
|
3254
3117
|
try {
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3118
|
+
const staged = await withinCandidateCleanupDeadline(() => store.stageTerminal(lease, terminal), deadlineAtMs ?? lease.expiresAtMs, "candidate terminal staging");
|
|
3119
|
+
if (!staged.staged && !staged.exactReplay) return false;
|
|
3120
|
+
const result = await withinCandidateCleanupDeadline(() => store.finish(lease, staged.terminal.terminalDigest), deadlineAtMs ?? lease.expiresAtMs, "candidate terminal publication");
|
|
3121
|
+
return result.finished || result.exactReplay;
|
|
3122
|
+
} catch {
|
|
3123
|
+
return false;
|
|
3258
3124
|
}
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3125
|
+
}
|
|
3126
|
+
function protectedEnvironmentValues(activation, memoryActivation) {
|
|
3127
|
+
return [...Object.values(activation?.env ?? {}), ...Object.values(memoryActivation?.env ?? {})];
|
|
3128
|
+
}
|
|
3129
|
+
function joinErrors(...errors) {
|
|
3130
|
+
return errors.filter((error) => error !== void 0).map(errorMessage).join("; ");
|
|
3131
|
+
}
|
|
3132
|
+
//#endregion
|
|
3133
|
+
//#region src/candidate-execution/executor-capture.ts
|
|
3134
|
+
const sealedFinalCaptureBrand = Symbol("sealedAgentCandidateExecutorFinalCapture");
|
|
3135
|
+
/** Validate and detach the only candidate-authored fields accepted from execution. */
|
|
3136
|
+
function sealAgentCandidateProtectedRunCapture(value) {
|
|
3137
|
+
const capture = requireRecord(value, "candidate execution capture");
|
|
3138
|
+
assertExactObjectKeys(capture, ["executionId", "termination"], "candidate execution capture");
|
|
3139
|
+
if (typeof capture.executionId !== "string" || capture.executionId.length === 0) throw new Error("candidate execution capture has an invalid executionId");
|
|
3140
|
+
return Object.freeze({
|
|
3141
|
+
executionId: capture.executionId,
|
|
3142
|
+
termination: Object.freeze(agentCandidateTerminationSchema.parse(capture.termination))
|
|
3143
|
+
});
|
|
3144
|
+
}
|
|
3145
|
+
/** Validate, detach, and freeze evaluator-owned evidence captured after process death. */
|
|
3146
|
+
function sealAgentCandidateExecutorFinalCapture(value, expectedOutcome) {
|
|
3147
|
+
const capture = requireRecord(value, "candidate final capture");
|
|
3148
|
+
assertExactObjectKeys(capture, [], "candidate final capture", [
|
|
3149
|
+
"taskOutcome",
|
|
3150
|
+
"memoryAfter",
|
|
3151
|
+
"evidence"
|
|
3278
3152
|
]);
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
}
|
|
3316
|
-
}
|
|
3317
|
-
let terminal;
|
|
3318
|
-
try {
|
|
3319
|
-
terminal = result.succeeded ? {
|
|
3320
|
-
status: "succeeded",
|
|
3321
|
-
usage: settlementResult.settlement.usage,
|
|
3322
|
-
modelSettlement: result.artifacts.modelSettlement,
|
|
3323
|
-
taskOutcome: result.artifacts.taskOutcome,
|
|
3324
|
-
benchmarkResult: result.artifacts.benchmarkResult,
|
|
3325
|
-
runReceipt: result.artifacts.runReceipt
|
|
3326
|
-
} : {
|
|
3327
|
-
status: "failed",
|
|
3328
|
-
failureClass,
|
|
3329
|
-
usage: settlementResult.settlement.usage,
|
|
3330
|
-
modelSettlement: modelSettlement.artifact,
|
|
3331
|
-
failureEvidence: await withinCandidateCleanupDeadline(() => persistFailureEvidence(state, result.reason, failureClass, execution.termination, options.outputArtifacts), acquired.lease.expiresAtMs, "candidate failure-evidence persistence")
|
|
3332
|
-
};
|
|
3333
|
-
} catch (error) {
|
|
3334
|
-
consumePreparedCandidateExecution(prepared, "failed");
|
|
3335
|
-
return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, /* @__PURE__ */ new Error("candidate claim remains recoverable until terminal evidence is durable")), protectedValues), execution.termination, settlementResult.settlement.usage);
|
|
3336
|
-
}
|
|
3337
|
-
if (await finishClaim(options.claimStore, acquired.lease, terminal, acquired.lease.expiresAtMs)) {
|
|
3338
|
-
consumePreparedCandidateExecution(prepared, result.succeeded ? "succeeded" : "failed");
|
|
3339
|
-
return result;
|
|
3153
|
+
const taskOutcome = capture.taskOutcome ? sealTaskOutcomeCapture(capture.taskOutcome, expectedOutcome) : void 0;
|
|
3154
|
+
const memoryAfter = capture.memoryAfter ? sealMemoryCapture(capture.memoryAfter) : void 0;
|
|
3155
|
+
if (capture.evidence !== void 0 && !(capture.evidence instanceof Uint8Array)) throw new Error("candidate executor evidence must be a byte array");
|
|
3156
|
+
const evidence = capture.evidence ? Uint8Array.from(capture.evidence) : void 0;
|
|
3157
|
+
return Object.freeze({
|
|
3158
|
+
...taskOutcome ? { taskOutcome } : {},
|
|
3159
|
+
...memoryAfter ? { memoryAfter: Object.freeze(memoryAfter) } : {},
|
|
3160
|
+
...evidence ? { evidence } : {},
|
|
3161
|
+
[sealedFinalCaptureBrand]: true
|
|
3162
|
+
});
|
|
3163
|
+
}
|
|
3164
|
+
/** Prove exact process death before any final evidence capture. */
|
|
3165
|
+
function sealAgentCandidateExecutorStopAcknowledgement(value) {
|
|
3166
|
+
const capture = requireRecord(value, "candidate stop acknowledgement");
|
|
3167
|
+
assertExactObjectKeys(capture, ["stopped"], "candidate stop acknowledgement");
|
|
3168
|
+
if (capture.stopped !== true) throw new Error("candidate stop acknowledgement does not prove process death");
|
|
3169
|
+
}
|
|
3170
|
+
function sealMemoryCapture(value) {
|
|
3171
|
+
const capture = requireRecord(value, "candidate memory capture");
|
|
3172
|
+
assertExactObjectKeys(capture, ["afterState", "archive"], "candidate memory capture");
|
|
3173
|
+
if (!(capture.archive instanceof Uint8Array)) throw new Error("candidate memory capture archive must be a byte array");
|
|
3174
|
+
return Object.freeze({
|
|
3175
|
+
afterState: Object.freeze(agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState)),
|
|
3176
|
+
archive: Uint8Array.from(capture.archive)
|
|
3177
|
+
});
|
|
3178
|
+
}
|
|
3179
|
+
function sealTaskOutcomeCapture(value, expected) {
|
|
3180
|
+
const capture = requireRecord(value, "candidate task capture");
|
|
3181
|
+
if (capture.kind === "output") {
|
|
3182
|
+
assertExactObjectKeys(capture, ["kind", "bytes"], "candidate task output capture");
|
|
3183
|
+
if (expected.kind !== "output") throw new Error("candidate task output capture does not match the signed outcome kind");
|
|
3184
|
+
if (!(capture.bytes instanceof Uint8Array)) throw new Error("candidate task output capture must contain a byte array");
|
|
3185
|
+
if (capture.bytes.byteLength > expected.maxBytes) throw new Error(`candidate task output exceeds the frozen ${expected.maxBytes}-byte maximum`);
|
|
3186
|
+
return Object.freeze({
|
|
3187
|
+
kind: "output",
|
|
3188
|
+
bytes: Uint8Array.from(capture.bytes)
|
|
3189
|
+
});
|
|
3340
3190
|
}
|
|
3341
|
-
|
|
3342
|
-
|
|
3191
|
+
assertExactObjectKeys(capture, [
|
|
3192
|
+
"kind",
|
|
3193
|
+
"resultTree",
|
|
3194
|
+
"afterState",
|
|
3195
|
+
"archive",
|
|
3196
|
+
"gitDiff"
|
|
3197
|
+
], "candidate task capture");
|
|
3198
|
+
if (capture.kind !== "workspace") throw new Error("candidate task capture has an invalid outcome kind");
|
|
3199
|
+
if (expected.kind !== "workspace") throw new Error("candidate workspace capture does not match the signed outcome kind");
|
|
3200
|
+
if (typeof capture.resultTree !== "string" || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(capture.resultTree)) throw new Error("candidate task capture resultTree is not a Git object id");
|
|
3201
|
+
if (!(capture.archive instanceof Uint8Array) || !(capture.gitDiff instanceof Uint8Array)) throw new Error("candidate task capture archive and gitDiff must be byte arrays");
|
|
3202
|
+
const afterState = agentCandidateWorkspaceManifestMaterialSchema.parse(capture.afterState);
|
|
3203
|
+
return Object.freeze({
|
|
3204
|
+
kind: "workspace",
|
|
3205
|
+
resultTree: capture.resultTree,
|
|
3206
|
+
afterState: Object.freeze(afterState),
|
|
3207
|
+
archive: Uint8Array.from(capture.archive),
|
|
3208
|
+
gitDiff: Uint8Array.from(capture.gitDiff)
|
|
3209
|
+
});
|
|
3343
3210
|
}
|
|
3211
|
+
function requireRecord(value, label) {
|
|
3212
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
|
|
3213
|
+
return value;
|
|
3214
|
+
}
|
|
3215
|
+
//#endregion
|
|
3216
|
+
//#region src/candidate-execution/execute-executor.ts
|
|
3217
|
+
/** Run the executor until it returns or the deadline passes, then stop and capture it. */
|
|
3344
3218
|
async function runAndStopExecutor(executor, request, expectedOutcome, traceStore, deadlineAtMs, cleanupTimeoutMs) {
|
|
3345
3219
|
const timeoutMs = request.hardLimits.timeoutMs;
|
|
3346
3220
|
const timeoutError = new CandidateExecutionDeadlineError(timeoutMs);
|
|
@@ -3353,113 +3227,49 @@ async function runAndStopExecutor(executor, request, expectedOutcome, traceStore
|
|
|
3353
3227
|
},
|
|
3354
3228
|
processStopped: true
|
|
3355
3229
|
};
|
|
3356
|
-
const
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
const executionPromise = Promise.resolve().then(() => executor.execute(request, {
|
|
3362
|
-
traceStore,
|
|
3363
|
-
signal: controller.signal,
|
|
3364
|
-
deadlineAtMs
|
|
3365
|
-
}));
|
|
3366
|
-
executionPromise.catch(() => void 0);
|
|
3367
|
-
const deadlinePromise = new Promise((_resolve, reject) => {
|
|
3368
|
-
timer = setTimeout(() => {
|
|
3369
|
-
timedOut = true;
|
|
3370
|
-
controller.abort(timeoutError);
|
|
3371
|
-
reject(timeoutError);
|
|
3372
|
-
}, Math.max(0, deadlineAtMs - Date.now()));
|
|
3373
|
-
});
|
|
3374
|
-
deadlinePromise.catch(() => void 0);
|
|
3375
|
-
try {
|
|
3376
|
-
capture = sealAgentCandidateProtectedRunCapture(await Promise.race([executionPromise, deadlinePromise]));
|
|
3377
|
-
} catch (error) {
|
|
3378
|
-
executionError = error;
|
|
3379
|
-
}
|
|
3380
|
-
if (!timedOut && capture && capture.executionId !== request.executionId) {
|
|
3381
|
-
executionError = /* @__PURE__ */ new Error("candidate execution capture id does not match the request");
|
|
3382
|
-
capture = void 0;
|
|
3383
|
-
} else if (!timedOut && capture && Date.now() >= deadlineAtMs) {
|
|
3384
|
-
timedOut = true;
|
|
3385
|
-
executionError = timeoutError;
|
|
3386
|
-
capture = void 0;
|
|
3387
|
-
} else if (!timedOut && capture?.termination.kind === "timeout") {
|
|
3388
|
-
executionError = /* @__PURE__ */ new Error("candidate executor cannot declare the runtime-owned timeout");
|
|
3389
|
-
capture = void 0;
|
|
3390
|
-
}
|
|
3391
|
-
if (!capture || timedOut) controller.abort(executionError);
|
|
3392
|
-
const stopReason = timedOut ? "timeout" : capture ? "completed" : "failed";
|
|
3230
|
+
const run = await executeUntilDeadline(executor, request, traceStore, deadlineAtMs, timeoutError);
|
|
3231
|
+
rejectAmbiguousCapture(run, request, deadlineAtMs);
|
|
3232
|
+
const { controller } = run;
|
|
3233
|
+
if (!run.capture || run.timedOut) controller.abort(run.executionError);
|
|
3234
|
+
const stopReason = run.timedOut ? "timeout" : run.capture ? "completed" : "failed";
|
|
3393
3235
|
const cleanupDeadlineAtMs = Date.now() + cleanupTimeoutMs;
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
}), cleanupDeadlineAtMs, "candidate process termination"));
|
|
3404
|
-
} catch (stopError) {
|
|
3405
|
-
let disposalError;
|
|
3406
|
-
try {
|
|
3407
|
-
await disposeExecutor(executor, request, cleanupDeadlineAtMs);
|
|
3408
|
-
} catch (error) {
|
|
3409
|
-
disposalError = error;
|
|
3410
|
-
}
|
|
3411
|
-
if (timer) clearTimeout(timer);
|
|
3412
|
-
controller.abort(stopError);
|
|
3236
|
+
const timeoutTermination = () => run.timedOut ? { termination: {
|
|
3237
|
+
kind: "timeout",
|
|
3238
|
+
timeoutMs
|
|
3239
|
+
} } : {};
|
|
3240
|
+
const stop = await stopExecutor(executor, request, traceStore, stopReason, cleanupDeadlineAtMs);
|
|
3241
|
+
if (!stop.stopped) {
|
|
3242
|
+
const disposalError = await disposalFailure(executor, request, cleanupDeadlineAtMs);
|
|
3243
|
+
if (run.timer) clearTimeout(run.timer);
|
|
3244
|
+
controller.abort(stop.error);
|
|
3413
3245
|
return {
|
|
3414
3246
|
kind: "error",
|
|
3415
|
-
error: new Error(joinErrors(executionError,
|
|
3416
|
-
...
|
|
3417
|
-
kind: "timeout",
|
|
3418
|
-
timeoutMs
|
|
3419
|
-
} } : {},
|
|
3247
|
+
error: new Error(joinErrors(run.executionError, stop.error, disposalError)),
|
|
3248
|
+
...timeoutTermination(),
|
|
3420
3249
|
processStopped: false
|
|
3421
3250
|
};
|
|
3422
3251
|
}
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
}, {
|
|
3430
|
-
traceStore,
|
|
3431
|
-
signal: cleanupSignal
|
|
3432
|
-
}), cleanupDeadlineAtMs, "candidate final evidence capture"), expectedOutcome);
|
|
3433
|
-
} catch (captureError) {
|
|
3434
|
-
finalCaptureError = captureError;
|
|
3435
|
-
}
|
|
3436
|
-
let disposalError;
|
|
3437
|
-
try {
|
|
3438
|
-
await disposeExecutor(executor, request, cleanupDeadlineAtMs);
|
|
3439
|
-
} catch (disposeError) {
|
|
3440
|
-
disposalError = disposeError;
|
|
3441
|
-
}
|
|
3442
|
-
if (finalCaptureError || disposalError || !finalCapture) {
|
|
3443
|
-
if (timer) clearTimeout(timer);
|
|
3444
|
-
controller.abort(finalCaptureError ?? disposalError);
|
|
3252
|
+
const final = await captureFinalEvidence(executor, request, traceStore, expectedOutcome, cleanupDeadlineAtMs);
|
|
3253
|
+
const disposalError = await disposalFailure(executor, request, cleanupDeadlineAtMs);
|
|
3254
|
+
const { finalCapture } = final;
|
|
3255
|
+
if (final.error || disposalError || !finalCapture) {
|
|
3256
|
+
if (run.timer) clearTimeout(run.timer);
|
|
3257
|
+
controller.abort(final.error ?? disposalError);
|
|
3445
3258
|
return {
|
|
3446
3259
|
kind: "error",
|
|
3447
|
-
error: new Error(joinErrors(executionError,
|
|
3448
|
-
...
|
|
3449
|
-
kind: "timeout",
|
|
3450
|
-
timeoutMs
|
|
3451
|
-
} } : {},
|
|
3260
|
+
error: new Error(joinErrors(run.executionError, final.error, disposalError)),
|
|
3261
|
+
...timeoutTermination(),
|
|
3452
3262
|
processStopped: true
|
|
3453
3263
|
};
|
|
3454
3264
|
}
|
|
3455
3265
|
if (Date.now() >= deadlineAtMs) {
|
|
3456
|
-
timedOut = true;
|
|
3457
|
-
executionError = timeoutError;
|
|
3458
|
-
capture = void 0;
|
|
3266
|
+
run.timedOut = true;
|
|
3267
|
+
run.executionError = timeoutError;
|
|
3268
|
+
run.capture = void 0;
|
|
3459
3269
|
controller.abort(timeoutError);
|
|
3460
3270
|
}
|
|
3461
|
-
if (timer) clearTimeout(timer);
|
|
3462
|
-
if (timedOut) return {
|
|
3271
|
+
if (run.timer) clearTimeout(run.timer);
|
|
3272
|
+
if (run.timedOut) return {
|
|
3463
3273
|
kind: "timeout",
|
|
3464
3274
|
termination: {
|
|
3465
3275
|
kind: "timeout",
|
|
@@ -3468,144 +3278,603 @@ async function runAndStopExecutor(executor, request, expectedOutcome, traceStore
|
|
|
3468
3278
|
finalCapture,
|
|
3469
3279
|
processStopped: true
|
|
3470
3280
|
};
|
|
3471
|
-
if (executionError || !capture) return {
|
|
3281
|
+
if (run.executionError || !run.capture) return {
|
|
3472
3282
|
kind: "error",
|
|
3473
|
-
error: executionError ?? /* @__PURE__ */ new Error("candidate executor returned no capture"),
|
|
3283
|
+
error: run.executionError ?? /* @__PURE__ */ new Error("candidate executor returned no capture"),
|
|
3474
3284
|
finalCapture,
|
|
3475
3285
|
processStopped: true
|
|
3476
3286
|
};
|
|
3477
3287
|
return {
|
|
3478
3288
|
kind: "capture",
|
|
3479
|
-
capture,
|
|
3480
|
-
termination: capture.termination,
|
|
3289
|
+
capture: run.capture,
|
|
3290
|
+
termination: run.capture.termination,
|
|
3481
3291
|
finalCapture,
|
|
3482
3292
|
processStopped: true
|
|
3483
3293
|
};
|
|
3484
3294
|
}
|
|
3485
|
-
async function
|
|
3486
|
-
const
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3295
|
+
async function executeUntilDeadline(executor, request, traceStore, deadlineAtMs, timeoutError) {
|
|
3296
|
+
const run = {
|
|
3297
|
+
controller: new AbortController(),
|
|
3298
|
+
timeoutError,
|
|
3299
|
+
timer: void 0,
|
|
3300
|
+
timedOut: false,
|
|
3301
|
+
capture: void 0,
|
|
3302
|
+
executionError: void 0
|
|
3303
|
+
};
|
|
3304
|
+
const executionPromise = Promise.resolve().then(() => executor.execute(request, {
|
|
3305
|
+
traceStore,
|
|
3306
|
+
signal: run.controller.signal,
|
|
3307
|
+
deadlineAtMs
|
|
3308
|
+
}));
|
|
3309
|
+
executionPromise.catch(() => void 0);
|
|
3310
|
+
const deadlinePromise = new Promise((_resolve, reject) => {
|
|
3311
|
+
run.timer = setTimeout(() => {
|
|
3312
|
+
run.timedOut = true;
|
|
3313
|
+
run.controller.abort(timeoutError);
|
|
3314
|
+
reject(timeoutError);
|
|
3315
|
+
}, Math.max(0, deadlineAtMs - Date.now()));
|
|
3316
|
+
});
|
|
3317
|
+
deadlinePromise.catch(() => void 0);
|
|
3318
|
+
try {
|
|
3319
|
+
run.capture = sealAgentCandidateProtectedRunCapture(await Promise.race([executionPromise, deadlinePromise]));
|
|
3320
|
+
} catch (error) {
|
|
3321
|
+
run.executionError = error;
|
|
3322
|
+
}
|
|
3323
|
+
return run;
|
|
3324
|
+
}
|
|
3325
|
+
/** Refuse a capture for another execution, one at the deadline, or one that claims the timeout. */
|
|
3326
|
+
function rejectAmbiguousCapture(run, request, deadlineAtMs) {
|
|
3327
|
+
const { capture } = run;
|
|
3328
|
+
if (!run.timedOut && capture && capture.executionId !== request.executionId) {
|
|
3329
|
+
run.executionError = /* @__PURE__ */ new Error("candidate execution capture id does not match the request");
|
|
3330
|
+
run.capture = void 0;
|
|
3331
|
+
} else if (!run.timedOut && capture && Date.now() >= deadlineAtMs) {
|
|
3332
|
+
run.timedOut = true;
|
|
3333
|
+
run.executionError = run.timeoutError;
|
|
3334
|
+
run.capture = void 0;
|
|
3335
|
+
} else if (!run.timedOut && capture?.termination.kind === "timeout") {
|
|
3336
|
+
run.executionError = /* @__PURE__ */ new Error("candidate executor cannot declare the runtime-owned timeout");
|
|
3337
|
+
run.capture = void 0;
|
|
3338
|
+
}
|
|
3493
3339
|
}
|
|
3494
|
-
async function
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3340
|
+
async function stopExecutor(executor, request, traceStore, reason, cleanupDeadlineAtMs) {
|
|
3341
|
+
try {
|
|
3342
|
+
sealAgentCandidateExecutorStopAcknowledgement(await withinCandidateCleanupDeadline((cleanupSignal) => executor.stop(executionTarget(request), {
|
|
3343
|
+
traceStore,
|
|
3344
|
+
reason,
|
|
3345
|
+
signal: cleanupSignal,
|
|
3346
|
+
deadlineAtMs: cleanupDeadlineAtMs
|
|
3347
|
+
}), cleanupDeadlineAtMs, "candidate process termination"));
|
|
3348
|
+
return { stopped: true };
|
|
3349
|
+
} catch (error) {
|
|
3350
|
+
return {
|
|
3351
|
+
stopped: false,
|
|
3352
|
+
error
|
|
3353
|
+
};
|
|
3354
|
+
}
|
|
3501
3355
|
}
|
|
3502
|
-
async function
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3356
|
+
async function captureFinalEvidence(executor, request, traceStore, expectedOutcome, cleanupDeadlineAtMs) {
|
|
3357
|
+
try {
|
|
3358
|
+
return { finalCapture: sealAgentCandidateExecutorFinalCapture(await withinCandidateCleanupDeadline((cleanupSignal) => executor.capture(executionTarget(request), {
|
|
3359
|
+
traceStore,
|
|
3360
|
+
signal: cleanupSignal
|
|
3361
|
+
}), cleanupDeadlineAtMs, "candidate final evidence capture"), expectedOutcome) };
|
|
3362
|
+
} catch (error) {
|
|
3363
|
+
return { error };
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
/** The error disposal threw, or undefined when the executor's resources were disposed. */
|
|
3367
|
+
async function disposalFailure(executor, request, cleanupDeadlineAtMs) {
|
|
3368
|
+
try {
|
|
3369
|
+
const dispose = executor.dispose;
|
|
3370
|
+
if (!dispose) return void 0;
|
|
3371
|
+
const disposed = await withinCandidateCleanupDeadline((cleanupSignal) => dispose.call(executor, executionTarget(request), { signal: cleanupSignal }), cleanupDeadlineAtMs, "candidate execution resource disposal");
|
|
3372
|
+
if (disposed?.disposed !== true || Object.keys(disposed).some((key) => key !== "disposed")) throw new Error("candidate executor did not acknowledge resource disposal");
|
|
3373
|
+
return;
|
|
3374
|
+
} catch (error) {
|
|
3375
|
+
return error;
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
const executionTarget = (request) => ({
|
|
3379
|
+
executionId: request.executionId,
|
|
3380
|
+
executionPlanDigest: request.executionPlan.value.digest
|
|
3381
|
+
});
|
|
3382
|
+
var CandidateExecutionDeadlineError = class extends Error {
|
|
3383
|
+
constructor(timeoutMs) {
|
|
3384
|
+
super(`candidate execution reached its frozen ${timeoutMs}ms deadline`);
|
|
3385
|
+
this.name = "CandidateExecutionDeadlineError";
|
|
3386
|
+
}
|
|
3387
|
+
};
|
|
3388
|
+
//#endregion
|
|
3389
|
+
//#region src/candidate-execution/protected-trace-store.ts
|
|
3390
|
+
/** Keep the identity key in evaluator-owned closures and expose only the redacting store to code. */
|
|
3391
|
+
function createProtectedAgentCandidateTraceAccess(inner, protectedValues) {
|
|
3392
|
+
const redactor = createProtectedRecordRedactor(protectedValues);
|
|
3393
|
+
const pendingWrites = /* @__PURE__ */ new Set();
|
|
3394
|
+
let acceptsWrites = true;
|
|
3395
|
+
const write = (operation) => {
|
|
3396
|
+
if (!acceptsWrites) return Promise.reject(/* @__PURE__ */ new Error("candidate trace writes are closed"));
|
|
3397
|
+
let started;
|
|
3398
|
+
try {
|
|
3399
|
+
started = operation();
|
|
3400
|
+
} catch (error) {
|
|
3401
|
+
return Promise.reject(error);
|
|
3402
|
+
}
|
|
3403
|
+
let tracked;
|
|
3404
|
+
tracked = started.finally(() => pendingWrites.delete(tracked));
|
|
3405
|
+
pendingWrites.add(tracked);
|
|
3406
|
+
return tracked;
|
|
3407
|
+
};
|
|
3408
|
+
const store = Object.freeze({
|
|
3409
|
+
appendRun: (run) => write(() => inner.appendRun(redactor.record(run))),
|
|
3410
|
+
updateRun: (runId, patch) => write(() => inner.updateRun(redactor.identifier(runId), redactor.record(patch))),
|
|
3411
|
+
appendSpan: (span) => write(async () => {
|
|
3412
|
+
if (span.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
|
|
3413
|
+
await inner.appendSpan(redactor.record(span));
|
|
3414
|
+
}),
|
|
3415
|
+
updateSpan: (spanId, patch) => write(async () => {
|
|
3416
|
+
if (patch.kind === "llm") throw new Error("candidate executors cannot author protected model spans");
|
|
3417
|
+
await inner.updateSpan(redactor.identifier(spanId), redactor.record(patch));
|
|
3418
|
+
}),
|
|
3419
|
+
appendEvent: (event) => write(() => inner.appendEvent(redactor.record(event))),
|
|
3420
|
+
appendArtifact: (artifact) => write(() => inner.appendArtifact(redactor.record(artifact))),
|
|
3421
|
+
appendBudgetEntry: (entry) => write(() => inner.appendBudgetEntry(redactor.record(entry))),
|
|
3422
|
+
getRun: async (runId) => inner.getRun(redactor.identifier(runId)),
|
|
3423
|
+
listRuns: async (filter) => inner.listRuns(filter ? redactor.query(filter) : void 0),
|
|
3424
|
+
spans: async (filter) => inner.spans(filter ? redactor.query(filter) : void 0),
|
|
3425
|
+
events: async (filter) => inner.events(filter ? redactor.query(filter) : void 0),
|
|
3426
|
+
budget: async (runId) => inner.budget(redactor.identifier(runId)),
|
|
3427
|
+
artifacts: async (runId) => inner.artifacts(redactor.identifier(runId))
|
|
3428
|
+
});
|
|
3429
|
+
return Object.freeze({
|
|
3430
|
+
store,
|
|
3431
|
+
closeWrites: async () => {
|
|
3432
|
+
acceptsWrites = false;
|
|
3433
|
+
await Promise.all([...pendingWrites]);
|
|
3434
|
+
},
|
|
3435
|
+
identity: (trace) => redactor.traceIdentity(trace),
|
|
3436
|
+
report: () => redactor.report()
|
|
3437
|
+
});
|
|
3438
|
+
}
|
|
3439
|
+
//#endregion
|
|
3440
|
+
//#region src/candidate-execution/execute.ts
|
|
3441
|
+
/** Executes and finalizes one durably claimed candidate without exposing an unproven result. */
|
|
3442
|
+
async function executePreparedAgentCandidate(prepared, options) {
|
|
3443
|
+
const initialState = assertPreparedCandidateIntegrity(prepared);
|
|
3444
|
+
const cleanupTimeoutMs = candidateCleanupTimeout(options.cleanupTimeoutMs ?? initialState.cleanupTimeoutMs);
|
|
3445
|
+
if (cleanupTimeoutMs > initialState.cleanupTimeoutMs) throw new Error("execution cleanup timeout exceeds the frozen preparation bound");
|
|
3446
|
+
const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs ?? initialState.resultTimeoutMs, initialState.resultTimeoutMs);
|
|
3447
|
+
if (resultTimeoutMs > initialState.resultTimeoutMs) throw new Error("execution result timeout exceeds the frozen preparation bound");
|
|
3448
|
+
let state;
|
|
3449
|
+
try {
|
|
3450
|
+
state = beginPreparedCandidateClaim(prepared);
|
|
3451
|
+
} catch (error) {
|
|
3452
|
+
return failedAgentCandidateRun(initialState, errorMessage(error));
|
|
3453
|
+
}
|
|
3454
|
+
const run = {
|
|
3455
|
+
prepared,
|
|
3456
|
+
state,
|
|
3457
|
+
claimStore: options.claimStore,
|
|
3458
|
+
outputArtifacts: options.outputArtifacts,
|
|
3459
|
+
cleanupTimeoutMs,
|
|
3460
|
+
resultTimeoutMs
|
|
3461
|
+
};
|
|
3462
|
+
const claimed = await claimExecution(run, options);
|
|
3463
|
+
if (!claimed.ok) return claimed.result;
|
|
3464
|
+
const launchable = await activateAccess(run, claimed.value);
|
|
3465
|
+
if (!launchable.ok) return launchable.result;
|
|
3466
|
+
const settled = await runAndSettle(run, options, claimed.value, launchable.value);
|
|
3467
|
+
if (!settled.ok) return settled.result;
|
|
3468
|
+
const { execution, settlement } = settled.value;
|
|
3469
|
+
let modelSettlement;
|
|
3470
|
+
try {
|
|
3471
|
+
modelSettlement = await withinCandidateCleanupDeadline(() => persistCandidateModelSettlement(state, settlement, options.outputArtifacts), candidateCleanupDeadline(cleanupTimeoutMs), "candidate model settlement persistence");
|
|
3472
|
+
} catch (error) {
|
|
3473
|
+
consumePreparedCandidateExecution(prepared, "failed");
|
|
3474
|
+
return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, /* @__PURE__ */ new Error("candidate claim remains recoverable until settlement evidence is durable")), settled.value.protectedValues), execution.termination, settlement.usage);
|
|
3475
|
+
}
|
|
3476
|
+
const result = await finalizeEvidence(run, options, claimed.value, settled.value, modelSettlement);
|
|
3477
|
+
return recordTerminal(run, claimed.value, settled.value, modelSettlement, result);
|
|
3478
|
+
}
|
|
3479
|
+
/** Stage and publish the attempt's terminal record, then consume the prepared execution. */
|
|
3480
|
+
async function recordTerminal(run, claimed, settled, modelSettlement, result) {
|
|
3481
|
+
const { prepared, state } = run;
|
|
3482
|
+
const { execution, settlement } = settled;
|
|
3483
|
+
const { lease } = claimed.acquired;
|
|
3484
|
+
const failureClass = execution.kind === "error" ? "execution" : "post-model-infrastructure";
|
|
3485
|
+
let terminal;
|
|
3486
|
+
try {
|
|
3487
|
+
terminal = result.succeeded ? {
|
|
3488
|
+
status: "succeeded",
|
|
3489
|
+
usage: settlement.usage,
|
|
3490
|
+
modelSettlement: result.artifacts.modelSettlement,
|
|
3491
|
+
taskOutcome: result.artifacts.taskOutcome,
|
|
3492
|
+
benchmarkResult: result.artifacts.benchmarkResult,
|
|
3493
|
+
runReceipt: result.artifacts.runReceipt
|
|
3494
|
+
} : {
|
|
3514
3495
|
status: "failed",
|
|
3515
3496
|
failureClass,
|
|
3516
|
-
usage:
|
|
3497
|
+
usage: settlement.usage,
|
|
3517
3498
|
modelSettlement: modelSettlement.artifact,
|
|
3518
|
-
failureEvidence
|
|
3519
|
-
}
|
|
3520
|
-
} catch (
|
|
3521
|
-
|
|
3522
|
-
|
|
3499
|
+
failureEvidence: await withinCandidateCleanupDeadline(() => persistFailureEvidence(state, result.reason, failureClass, execution.termination, run.outputArtifacts), lease.expiresAtMs, "candidate failure-evidence persistence")
|
|
3500
|
+
};
|
|
3501
|
+
} catch (error) {
|
|
3502
|
+
consumePreparedCandidateExecution(prepared, "failed");
|
|
3503
|
+
return failedAgentCandidateRun(state, redactProtectedReason(joinErrors(error, /* @__PURE__ */ new Error("candidate claim remains recoverable until terminal evidence is durable")), settled.protectedValues), execution.termination, settlement.usage);
|
|
3504
|
+
}
|
|
3505
|
+
if (await finishClaim(run.claimStore, lease, terminal, lease.expiresAtMs)) {
|
|
3506
|
+
consumePreparedCandidateExecution(prepared, result.succeeded ? "succeeded" : "failed");
|
|
3507
|
+
return result;
|
|
3523
3508
|
}
|
|
3524
3509
|
consumePreparedCandidateExecution(prepared, "failed");
|
|
3525
|
-
return failedAgentCandidateRun(state,
|
|
3510
|
+
return failedAgentCandidateRun(state, "candidate execution terminal record could not be persisted", execution.termination, settlement.usage);
|
|
3526
3511
|
}
|
|
3527
|
-
|
|
3528
|
-
|
|
3512
|
+
/** Persist the plan and receipt, claim the attempt, and check the claim covers the run. */
|
|
3513
|
+
async function claimExecution(run, options) {
|
|
3514
|
+
const { prepared, state, cleanupTimeoutMs, resultTimeoutMs } = run;
|
|
3529
3515
|
try {
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3516
|
+
await assertPreparedCandidateWorkspaces(state);
|
|
3517
|
+
} catch (error) {
|
|
3518
|
+
return {
|
|
3519
|
+
ok: false,
|
|
3520
|
+
result: await failBeforeActivation(run, error, "failed")
|
|
3521
|
+
};
|
|
3522
|
+
}
|
|
3523
|
+
let preparationEvidence;
|
|
3524
|
+
try {
|
|
3525
|
+
const [executionPlan, materializationReceipt] = await Promise.all([persistCandidateOutputArtifact(options.outputArtifacts, {
|
|
3533
3526
|
executionId: state.executionId,
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3527
|
+
purpose: "execution-plan",
|
|
3528
|
+
bytes: state.executionPlan.bytes
|
|
3529
|
+
}), persistCandidateOutputArtifact(options.outputArtifacts, {
|
|
3530
|
+
executionId: state.executionId,
|
|
3531
|
+
purpose: "materialization-receipt",
|
|
3532
|
+
bytes: state.materializationReceipt.bytes
|
|
3533
|
+
})]);
|
|
3534
|
+
preparationEvidence = Object.freeze({
|
|
3535
|
+
executionPlan,
|
|
3536
|
+
materializationReceipt
|
|
3537
|
+
});
|
|
3541
3538
|
} catch (error) {
|
|
3542
3539
|
return {
|
|
3543
|
-
|
|
3544
|
-
error
|
|
3540
|
+
ok: false,
|
|
3541
|
+
result: await failBeforeActivation(run, error, "failed")
|
|
3542
|
+
};
|
|
3543
|
+
}
|
|
3544
|
+
let acquired;
|
|
3545
|
+
try {
|
|
3546
|
+
acquired = await options.claimStore.tryClaim(candidateExecutionClaim(prepared, preparationEvidence));
|
|
3547
|
+
} catch (error) {
|
|
3548
|
+
return {
|
|
3549
|
+
ok: false,
|
|
3550
|
+
result: await failBeforeActivation(run, error, "failed")
|
|
3545
3551
|
};
|
|
3546
3552
|
}
|
|
3553
|
+
if (!acquired.acquired) return {
|
|
3554
|
+
ok: false,
|
|
3555
|
+
result: await failBeforeActivation(run, /* @__PURE__ */ new Error(acquired.reason === "retry-not-eligible" ? `candidate execution retry is not eligible: ${acquired.detail}` : "candidate execution attempt is already claimed"), "replayed")
|
|
3556
|
+
};
|
|
3557
|
+
markPreparedCandidateClaimed(prepared);
|
|
3558
|
+
const postRunWindowMs = candidatePostRunWindowMs(cleanupTimeoutMs, resultTimeoutMs);
|
|
3559
|
+
const deadlineAtMs = acquired.claim.leaseExpiresAtMs - candidatePostRunWindowMs(state.cleanupTimeoutMs, state.resultTimeoutMs);
|
|
3560
|
+
const requiredLeaseExpiry = deadlineAtMs + postRunWindowMs;
|
|
3561
|
+
if (Date.now() >= deadlineAtMs || deadlineAtMs > state.reservationExpiresAtMs || requiredLeaseExpiry > acquired.lease.expiresAtMs) return {
|
|
3562
|
+
ok: false,
|
|
3563
|
+
result: await failClaimedExecution(run, acquired.lease, /* @__PURE__ */ new Error("candidate claim no longer covers its full execution and cleanup window"), "pre-model-infrastructure")
|
|
3564
|
+
};
|
|
3565
|
+
return {
|
|
3566
|
+
ok: true,
|
|
3567
|
+
value: {
|
|
3568
|
+
acquired,
|
|
3569
|
+
deadlineAtMs
|
|
3570
|
+
}
|
|
3571
|
+
};
|
|
3547
3572
|
}
|
|
3548
|
-
|
|
3573
|
+
/** Activate model and memory access, build the executor request, and persist that it may run. */
|
|
3574
|
+
async function activateAccess(run, claimed) {
|
|
3575
|
+
const { prepared, state, cleanupTimeoutMs } = run;
|
|
3576
|
+
const { acquired, deadlineAtMs } = claimed;
|
|
3577
|
+
const fail = async (error, failureClass, access) => ({
|
|
3578
|
+
ok: false,
|
|
3579
|
+
result: await failClaimedExecution(run, acquired.lease, error, failureClass, access)
|
|
3580
|
+
});
|
|
3581
|
+
let activation;
|
|
3549
3582
|
try {
|
|
3550
|
-
|
|
3583
|
+
const activated = await withinCandidateCleanupDeadline(() => state.ports.models.activateGrant({
|
|
3551
3584
|
executionId: state.executionId,
|
|
3552
3585
|
preparationId: state.preparationId,
|
|
3553
3586
|
grantDigest: state.modelReservation.digest,
|
|
3554
3587
|
resolved: state.resolvedModel,
|
|
3555
|
-
|
|
3556
|
-
}),
|
|
3557
|
-
|
|
3558
|
-
grantDigest: state.modelReservation.digest,
|
|
3559
|
-
model: state.resolvedModel.model
|
|
3560
|
-
}) };
|
|
3588
|
+
deadlineAtMs
|
|
3589
|
+
}), Math.min(deadlineAtMs, candidateCleanupDeadline(cleanupTimeoutMs)), "protected model activation");
|
|
3590
|
+
activation = Object.freeze({ env: Object.freeze({ ...activated.env }) });
|
|
3561
3591
|
} catch (error) {
|
|
3562
|
-
return
|
|
3592
|
+
return fail(new Error("protected model activation failed", { cause: error }), "pre-model-infrastructure");
|
|
3593
|
+
}
|
|
3594
|
+
let memoryActivation;
|
|
3595
|
+
if (state.memory.mode === "isolated") try {
|
|
3596
|
+
const reservation = state.memoryReservation;
|
|
3597
|
+
if (!reservation) throw new Error("isolated memory reservation is missing");
|
|
3598
|
+
const activated = await withinCandidateCleanupDeadline(() => state.ports.memory.activate({
|
|
3599
|
+
executionId: state.executionId,
|
|
3600
|
+
preparationId: reservation.preparationId,
|
|
3601
|
+
accessDigest: reservation.accessDigest,
|
|
3602
|
+
effectiveNamespace: reservation.effectiveNamespace,
|
|
3603
|
+
deadlineAtMs
|
|
3604
|
+
}), Math.min(deadlineAtMs, candidateCleanupDeadline(cleanupTimeoutMs)), "isolated memory activation");
|
|
3605
|
+
memoryActivation = Object.freeze({ env: Object.freeze({ ...activated.env }) });
|
|
3606
|
+
} catch (error) {
|
|
3607
|
+
return fail(new Error("isolated memory activation failed", { cause: error }), "pre-model-infrastructure", { activation });
|
|
3608
|
+
}
|
|
3609
|
+
const access = {
|
|
3610
|
+
activation,
|
|
3611
|
+
memoryActivation
|
|
3612
|
+
};
|
|
3613
|
+
let request;
|
|
3614
|
+
try {
|
|
3615
|
+
request = beginPreparedCandidateRun(prepared, activation, memoryActivation).request;
|
|
3616
|
+
} catch (error) {
|
|
3617
|
+
return fail(error, "pre-model-infrastructure", access);
|
|
3618
|
+
}
|
|
3619
|
+
try {
|
|
3620
|
+
if ((await run.claimStore.markCandidateMayRun(acquired.lease)).phase !== "candidate-may-run") throw new Error("candidate claim did not persist the candidate-may-run phase");
|
|
3621
|
+
} catch (error) {
|
|
3622
|
+
return fail(new Error("candidate execution phase persistence failed", { cause: error }), "pre-model-infrastructure", access);
|
|
3623
|
+
}
|
|
3624
|
+
if (Date.now() >= deadlineAtMs) return fail(/* @__PURE__ */ new Error("candidate execution deadline elapsed while persisting its launch phase"), "unknown", access);
|
|
3625
|
+
return {
|
|
3626
|
+
ok: true,
|
|
3627
|
+
value: {
|
|
3628
|
+
...access,
|
|
3629
|
+
request
|
|
3630
|
+
}
|
|
3631
|
+
};
|
|
3632
|
+
}
|
|
3633
|
+
/** Run the executor, prove its process stopped, and close and settle the protected access. */
|
|
3634
|
+
async function runAndSettle(run, options, claimed, launchable) {
|
|
3635
|
+
const { prepared, state, cleanupTimeoutMs } = run;
|
|
3636
|
+
const protectedValues = protectedEnvironmentValues(launchable.activation, launchable.memoryActivation);
|
|
3637
|
+
const protectedTrace = createProtectedAgentCandidateTraceAccess(options.traceStore, protectedValues);
|
|
3638
|
+
const persistedTrace = protectedTrace.identity(state.trace);
|
|
3639
|
+
const execution = await runAndStopExecutor(options.executor, launchable.request, state.benchmarkTask.outcome, protectedTrace.store, claimed.deadlineAtMs, cleanupTimeoutMs);
|
|
3640
|
+
beginPreparedCandidateSettlement(prepared);
|
|
3641
|
+
const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
|
|
3642
|
+
const accessReason = execution.kind === "timeout" || execution.termination?.kind === "timeout" ? "timeout" : execution.kind === "capture" ? "completed" : "failed";
|
|
3643
|
+
const traceClosure = withinCandidateCleanupDeadline(() => protectedTrace.closeWrites(), cleanupDeadlineAtMs, "candidate trace write closure").then(() => ({
|
|
3644
|
+
closed: true,
|
|
3645
|
+
error: void 0
|
|
3646
|
+
}), (error) => ({
|
|
3647
|
+
closed: false,
|
|
3648
|
+
error
|
|
3649
|
+
}));
|
|
3650
|
+
const [traceClose, memoryClose, settlementResult] = await Promise.all([
|
|
3651
|
+
traceClosure,
|
|
3652
|
+
closeMemoryAccess(state, accessReason, cleanupDeadlineAtMs),
|
|
3653
|
+
settleModelGrant(state, accessReason, cleanupDeadlineAtMs)
|
|
3654
|
+
]);
|
|
3655
|
+
if (!execution.processStopped || !traceClose.closed || !settlementResult.settlement || !memoryClose.closed) {
|
|
3656
|
+
consumePreparedCandidateExecution(prepared, "failed");
|
|
3657
|
+
return {
|
|
3658
|
+
ok: false,
|
|
3659
|
+
result: failedAgentCandidateRun(state, redactProtectedReason(joinErrors(execution.error, !execution.processStopped ? /* @__PURE__ */ new Error("candidate process termination is not proven") : void 0, traceClose.error, memoryClose.error, settlementResult.error ?? (!settlementResult.settlement ? /* @__PURE__ */ new Error("model settlement failed") : void 0), /* @__PURE__ */ new Error("candidate claim remains recoverable until protected cleanup is proven")), protectedValues), execution.termination, settlementResult.settlement?.usage ?? null)
|
|
3660
|
+
};
|
|
3563
3661
|
}
|
|
3662
|
+
return {
|
|
3663
|
+
ok: true,
|
|
3664
|
+
value: {
|
|
3665
|
+
execution,
|
|
3666
|
+
settlement: settlementResult.settlement,
|
|
3667
|
+
protectedValues,
|
|
3668
|
+
persistedTrace,
|
|
3669
|
+
protectedTrace
|
|
3670
|
+
}
|
|
3671
|
+
};
|
|
3564
3672
|
}
|
|
3565
|
-
|
|
3673
|
+
/** Verify and grade the captured evidence into the run's result; a failure is a failed run. */
|
|
3674
|
+
async function finalizeEvidence(run, options, claimed, settled, modelSettlement) {
|
|
3675
|
+
const { state, cleanupTimeoutMs, resultTimeoutMs } = run;
|
|
3676
|
+
const { execution, settlement, protectedValues, persistedTrace, protectedTrace } = settled;
|
|
3677
|
+
if (execution.kind === "error") return failedAgentCandidateRun(state, redactProtectedReason(errorMessage(execution.error), protectedValues), execution.termination, settlement.usage);
|
|
3678
|
+
if (!execution.finalCapture.taskOutcome) return failedAgentCandidateRun(state, "candidate executor stopped without a captured task outcome", execution.termination, settlement.usage);
|
|
3679
|
+
const capture = execution.kind === "capture" ? execution.capture : {
|
|
3680
|
+
executionId: state.executionId,
|
|
3681
|
+
termination: execution.termination
|
|
3682
|
+
};
|
|
3566
3683
|
try {
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3684
|
+
return await withinCandidateResultDeadline(async (signal) => {
|
|
3685
|
+
await appendAuthoritativeModelSettlementSpans(options.traceStore, persistedTrace.runId, settlement);
|
|
3686
|
+
const { persistedCapture, taskOutcome } = await persistVerifiedAgentCandidateExecutorCapture(state, execution.finalCapture, options.outputArtifacts, protectedValues, signal);
|
|
3687
|
+
const benchmarkResult = await persistCandidateBenchmarkResult(state, capture.termination, taskOutcome, options.grader, options.outputArtifacts, protectedValues, signal);
|
|
3688
|
+
return await finalizeAgentCandidateRun(state, capture, options.traceStore, persistedTrace, settlement, {
|
|
3689
|
+
finalCapture: execution.finalCapture,
|
|
3690
|
+
persistedCapture,
|
|
3691
|
+
modelSettlement,
|
|
3692
|
+
taskOutcome,
|
|
3693
|
+
benchmarkResult,
|
|
3694
|
+
outputArtifacts: options.outputArtifacts
|
|
3695
|
+
}, protectedValues, protectedTrace.report(), signal);
|
|
3696
|
+
}, Math.min(Date.now() + resultTimeoutMs, claimed.acquired.lease.expiresAtMs - candidateTerminalWindowMs(cleanupTimeoutMs)), "candidate evidence finalization");
|
|
3697
|
+
} catch (error) {
|
|
3698
|
+
return failedAgentCandidateRun(state, redactProtectedReason(errorMessage(error), protectedValues), execution.termination, settlement.usage);
|
|
3573
3699
|
}
|
|
3574
3700
|
}
|
|
3575
|
-
|
|
3576
|
-
|
|
3701
|
+
//#endregion
|
|
3702
|
+
//#region src/candidate-execution/prepare-plan.ts
|
|
3703
|
+
/**
|
|
3704
|
+
* The evaluator-owned documents of a preparation: the launch environment, the execution plan,
|
|
3705
|
+
* the materialization receipt, and the trace bindings that tie a run back to them.
|
|
3706
|
+
*/
|
|
3707
|
+
/** The public environment: the candidate's own, the profile's, and the evaluator's path bindings. */
|
|
3708
|
+
function launchEnvironment(candidate, profile, knowledgePaths) {
|
|
3709
|
+
const { execution } = candidate.bundle;
|
|
3710
|
+
const { agentPaths } = profile;
|
|
3711
|
+
return mergePublicEnvironment(execution.env ?? {}, profile.application.env, agentPaths ? {
|
|
3712
|
+
[PI_CANDIDATE_AGENT_DIR_ENV]: {
|
|
3713
|
+
kind: "public",
|
|
3714
|
+
value: agentPaths.agentDir
|
|
3715
|
+
},
|
|
3716
|
+
[PI_CANDIDATE_SESSION_DIR_ENV]: {
|
|
3717
|
+
kind: "public",
|
|
3718
|
+
value: agentPaths.sessionDir
|
|
3719
|
+
}
|
|
3720
|
+
} : {}, execution.instructionDelivery.kind === "utf8-file" ? { [execution.instructionDelivery.env]: {
|
|
3721
|
+
kind: "public",
|
|
3722
|
+
value: execution.instructionDelivery.path
|
|
3723
|
+
} } : {}, knowledgePaths ? {
|
|
3724
|
+
[CANDIDATE_KNOWLEDGE_ROOT_ENV]: {
|
|
3725
|
+
kind: "public",
|
|
3726
|
+
value: knowledgePaths.root
|
|
3727
|
+
},
|
|
3728
|
+
...knowledgePaths.retrievalConfig ? { [CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV]: {
|
|
3729
|
+
kind: "public",
|
|
3730
|
+
value: knowledgePaths.retrievalConfig
|
|
3731
|
+
} } : {}
|
|
3732
|
+
} : {});
|
|
3577
3733
|
}
|
|
3578
|
-
|
|
3579
|
-
|
|
3734
|
+
/** The plan material for one execution: workspaces, profile, model access, launch and memory. */
|
|
3735
|
+
function executionPlanMaterial(input) {
|
|
3736
|
+
const { candidate, task } = input;
|
|
3737
|
+
const { bundle } = candidate;
|
|
3738
|
+
return {
|
|
3739
|
+
kind: "agent-candidate-execution-plan-material",
|
|
3740
|
+
runCell: task.runCell,
|
|
3741
|
+
executionId: task.executionId,
|
|
3742
|
+
workspaces: {
|
|
3743
|
+
taskRoot: task.executionRoots.taskRoot,
|
|
3744
|
+
...task.executionRoots.candidateRoot ? { candidateRoot: task.executionRoots.candidateRoot } : {}
|
|
3745
|
+
},
|
|
3746
|
+
codeKind: bundle.code.kind,
|
|
3747
|
+
...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
|
|
3748
|
+
profile: input.profile.application.application,
|
|
3749
|
+
harness: bundle.execution.harness,
|
|
3750
|
+
harnessVersion: bundle.execution.harnessVersion,
|
|
3751
|
+
instructionDelivery: bundle.execution.instructionDelivery,
|
|
3752
|
+
limits: task.task.limits,
|
|
3753
|
+
container: input.container,
|
|
3754
|
+
model: {
|
|
3755
|
+
policy: "single",
|
|
3756
|
+
resolved: input.resolvedModel,
|
|
3757
|
+
access: {
|
|
3758
|
+
kind: "evaluator-mediated",
|
|
3759
|
+
grantDigest: input.modelReservation.digest,
|
|
3760
|
+
network: input.modelReservation.network
|
|
3761
|
+
},
|
|
3762
|
+
routes: modelRoutes(bundle.profile, task.task.model.requested)
|
|
3763
|
+
},
|
|
3764
|
+
launch: {
|
|
3765
|
+
executable: input.launch.executable,
|
|
3766
|
+
args: input.launch.args,
|
|
3767
|
+
env: input.publicEnv,
|
|
3768
|
+
cwd: bundle.execution.cwd
|
|
3769
|
+
},
|
|
3770
|
+
...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
|
|
3771
|
+
memory: input.memory,
|
|
3772
|
+
network: { mode: "disabled" }
|
|
3773
|
+
};
|
|
3580
3774
|
}
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3775
|
+
/** Check and canonically serialize the plan material into the plan's evidence. */
|
|
3776
|
+
function sealExecutionPlan(material) {
|
|
3777
|
+
agentCandidateExecutionPlanMaterialSchema.parse(material);
|
|
3778
|
+
const bytes = canonicalCandidateBytes$1(material);
|
|
3779
|
+
const digest = canonicalCandidateDigest$1(material);
|
|
3780
|
+
if (sha256Bytes$1(bytes) !== digest) throw new Error("execution plan canonical serializers disagree");
|
|
3781
|
+
return {
|
|
3782
|
+
evidence: agentCandidateExecutionPlanEvidenceSchema.parse({
|
|
3783
|
+
kind: "agent-candidate-execution-plan",
|
|
3784
|
+
digest,
|
|
3785
|
+
material,
|
|
3786
|
+
artifact: embeddedCandidateArtifact(bytes)
|
|
3787
|
+
}),
|
|
3788
|
+
bytes
|
|
3789
|
+
};
|
|
3790
|
+
}
|
|
3791
|
+
/** The receipt that binds the bundle, the benchmark task, and the sealed plan together. */
|
|
3792
|
+
function sealMaterializationReceipt(input) {
|
|
3793
|
+
const { candidate, task } = input;
|
|
3794
|
+
const { bundle } = candidate;
|
|
3795
|
+
const benchmarkTask = task.task;
|
|
3796
|
+
const entrypoint = candidateEntrypointReceipt(candidate);
|
|
3797
|
+
const materializationReceipt = canonicalCandidateDocument({
|
|
3798
|
+
kind: "agent-candidate-materialization",
|
|
3799
|
+
digestAlgorithm: "rfc8785-sha256",
|
|
3800
|
+
bundleDigest: bundle.digest,
|
|
3801
|
+
benchmark: {
|
|
3802
|
+
suite: {
|
|
3803
|
+
digest: task.benchmarkSuite.digest,
|
|
3804
|
+
material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(task.benchmarkSuite)))
|
|
3805
|
+
},
|
|
3806
|
+
task: {
|
|
3807
|
+
digest: benchmarkTask.digest,
|
|
3808
|
+
material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(benchmarkTask)))
|
|
3809
|
+
}
|
|
3810
|
+
},
|
|
3811
|
+
profileActivation: input.profile.application.profileActivation,
|
|
3812
|
+
executionPlan: input.executionPlan,
|
|
3813
|
+
...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
|
|
3814
|
+
codeKind: bundle.code.kind,
|
|
3815
|
+
...candidate.materializedTree ? { materializedTree: candidate.materializedTree } : {},
|
|
3816
|
+
harness: bundle.execution.harness,
|
|
3817
|
+
harnessVersion: bundle.execution.harnessVersion,
|
|
3818
|
+
container: input.container,
|
|
3819
|
+
resolvedModel: input.resolvedModel,
|
|
3820
|
+
...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
|
|
3821
|
+
...entrypoint ? { entrypoint } : {}
|
|
3822
|
+
});
|
|
3823
|
+
agentCandidateMaterializationReceiptSchema.parse(materializationReceipt.value);
|
|
3824
|
+
return materializationReceipt;
|
|
3825
|
+
}
|
|
3826
|
+
/** The run id, tags and environment that tie a trace to this execution's sealed documents. */
|
|
3827
|
+
function candidateTraceBindings(input) {
|
|
3828
|
+
const { task, bundleDigest, executionPlanDigest, materializationReceiptDigest } = input;
|
|
3829
|
+
const runId = `${task.executionId}:attempt-${input.attemptNumber}:${canonicalCandidateDigest$1({ preparationId: input.preparationId }).slice(7, 23)}`;
|
|
3830
|
+
const tags = {
|
|
3831
|
+
[CANDIDATE_TRACE_TAGS.executionId]: task.executionId,
|
|
3832
|
+
[CANDIDATE_TRACE_TAGS.bundleDigest]: bundleDigest,
|
|
3833
|
+
[CANDIDATE_TRACE_TAGS.executionPlanDigest]: executionPlanDigest,
|
|
3834
|
+
[CANDIDATE_TRACE_TAGS.materializationReceiptDigest]: materializationReceiptDigest
|
|
3835
|
+
};
|
|
3836
|
+
const env = {
|
|
3837
|
+
[CANDIDATE_TRACE_ENV.executionId]: task.executionId,
|
|
3838
|
+
[CANDIDATE_TRACE_ENV.bundleDigest]: bundleDigest,
|
|
3839
|
+
[CANDIDATE_TRACE_ENV.executionPlanDigest]: executionPlanDigest,
|
|
3840
|
+
[CANDIDATE_TRACE_ENV.materializationReceiptDigest]: materializationReceiptDigest,
|
|
3841
|
+
[CANDIDATE_TRACE_ENV.traceRunId]: runId
|
|
3842
|
+
};
|
|
3843
|
+
assertEnvironmentDisjoint(input.publicEnv, env);
|
|
3844
|
+
return {
|
|
3845
|
+
runId,
|
|
3846
|
+
tags,
|
|
3847
|
+
env
|
|
3848
|
+
};
|
|
3849
|
+
}
|
|
3850
|
+
function unwrapPublicEnvironment(values) {
|
|
3851
|
+
return Object.fromEntries(Object.entries(values).map(([name, value]) => [name, requirePublicCandidateConfigValue(value, `env.${name}`)]));
|
|
3852
|
+
}
|
|
3853
|
+
function mergePublicEnvironment(...records) {
|
|
3854
|
+
const output = {};
|
|
3855
|
+
for (const record of records) for (const [name, value] of Object.entries(record)) {
|
|
3856
|
+
const previous = output[name];
|
|
3857
|
+
const publicValue = requirePublicCandidateConfigValue(value, `env.${name}`);
|
|
3858
|
+
if (previous && requirePublicCandidateConfigValue(previous, `env.${name}`) !== publicValue) throw new Error(`candidate and profile environment disagree on ${name}`);
|
|
3859
|
+
output[name] = value;
|
|
3585
3860
|
}
|
|
3586
|
-
|
|
3861
|
+
return output;
|
|
3862
|
+
}
|
|
3863
|
+
function assertEnvironmentDisjoint(publicEnv, traceEnv) {
|
|
3864
|
+
const seen = new Set(Object.keys(publicEnv));
|
|
3865
|
+
for (const name of Object.keys(traceEnv)) {
|
|
3866
|
+
if (seen.has(name)) throw new Error(`evaluator environment binding collides with ${name}`);
|
|
3867
|
+
seen.add(name);
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3587
3870
|
//#endregion
|
|
3588
|
-
//#region src/candidate-execution/prepare.ts
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
assertSameVerificationPorts(getVerifiedCandidateState(candidate).ports, ports);
|
|
3595
|
-
const bundle = candidate.bundle;
|
|
3596
|
-
if (task.runCell.bundleDigest !== bundle.digest) throw new Error("candidate experiment cell does not bind the verified bundle");
|
|
3871
|
+
//#region src/candidate-execution/prepare-workspaces.ts
|
|
3872
|
+
/**
|
|
3873
|
+
* The three host staging roots of a preparation: the task workspace, the candidate workspace,
|
|
3874
|
+
* and the profile workspace, each materialized and verified against its signed material.
|
|
3875
|
+
*/
|
|
3876
|
+
async function materializeTaskWorkspace(task, ports) {
|
|
3597
3877
|
const benchmarkTask = task.task;
|
|
3598
|
-
const attempt = {
|
|
3599
|
-
number: task.runCell.attempt,
|
|
3600
|
-
maxAttempts: benchmarkTask.attempt.maxAttempts,
|
|
3601
|
-
retryPolicy: benchmarkTask.attempt.retryPolicy
|
|
3602
|
-
};
|
|
3603
|
-
assertTaskInput(task, bundle.execution.instructionDelivery);
|
|
3604
|
-
const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs, benchmarkTask.limits.timeoutMs);
|
|
3605
|
-
const reservationWindowMs = candidateExecutionOwnerWindowMs(benchmarkTask.limits.timeoutMs, cleanupTimeoutMs, resultTimeoutMs) + PREPARED_HOLD_MARGIN_MS;
|
|
3606
|
-
if (reservationWindowMs > 2147483647) throw new Error("candidate reservation window exceeds the supported timer range");
|
|
3607
|
-
assertDisjointHostStagingRoots(task);
|
|
3608
|
-
const instructionBytes = Buffer.from(benchmarkTask.instruction, "utf8");
|
|
3609
3878
|
const taskArtifacts = await verifyWorkspaceSnapshotArtifacts(benchmarkTask.workspace, ports.artifacts);
|
|
3610
3879
|
await ports.workspaces.materialize({
|
|
3611
3880
|
role: "task",
|
|
@@ -3615,23 +3884,31 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
3615
3884
|
});
|
|
3616
3885
|
await verifyMaterializedWorkspace(task.stagingRoots.taskRoot, benchmarkTask.workspace.material, { ignoredProtectedRootEntries: [".git", ".sidecar"] });
|
|
3617
3886
|
if (benchmarkTask.repository) await verifyTaskCheckout(task.stagingRoots.taskRoot, benchmarkTask.repository);
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3887
|
+
return readMaterializedWorkspaceFiles(task.stagingRoots.taskRoot, benchmarkTask.workspace.material, { ignoredProtectedRootEntries: [".git", ".sidecar"] });
|
|
3888
|
+
}
|
|
3889
|
+
/** The candidate's own workspace files, or undefined when its code is disabled. */
|
|
3890
|
+
async function materializeCandidateWorkspace(candidate, task, ports) {
|
|
3891
|
+
const workspace = candidate.bundle.execution.workspace;
|
|
3892
|
+
if (!workspace) {
|
|
3893
|
+
if (task.stagingRoots.candidateRoot || task.executionRoots.candidateRoot) throw new Error("disabled code cannot receive a candidate workspace root");
|
|
3894
|
+
return;
|
|
3895
|
+
}
|
|
3896
|
+
if (!task.stagingRoots.candidateRoot || !task.executionRoots.candidateRoot) throw new Error("active candidate execution requires host and container candidate roots");
|
|
3897
|
+
const archive = await verifiedArtifactBytes(candidate, workspace.archive);
|
|
3898
|
+
await ports.workspaces.materialize({
|
|
3899
|
+
role: "candidate",
|
|
3900
|
+
snapshot: workspace,
|
|
3901
|
+
archive,
|
|
3902
|
+
destination: task.stagingRoots.candidateRoot
|
|
3903
|
+
});
|
|
3904
|
+
await verifyMaterializedWorkspace(task.stagingRoots.candidateRoot, workspace.material);
|
|
3905
|
+
return readMaterializedWorkspaceFiles(task.stagingRoots.candidateRoot, workspace.material);
|
|
3906
|
+
}
|
|
3907
|
+
/** Materialize the profile into its empty staging root and check the plan's exact bytes. */
|
|
3908
|
+
async function stageCandidateProfile(candidate, task, ports) {
|
|
3909
|
+
const { bundle } = candidate;
|
|
3633
3910
|
await assertEmptyDirectory(task.stagingRoots.profileRoot);
|
|
3634
|
-
const
|
|
3911
|
+
const workspacePlan = materializeAgentCandidateProfilePlan({
|
|
3635
3912
|
profile: bundle.profile,
|
|
3636
3913
|
harness: bundle.execution.harness,
|
|
3637
3914
|
launch: bundle.execution.launch,
|
|
@@ -3642,22 +3919,46 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
3642
3919
|
},
|
|
3643
3920
|
resolvedResources: verifiedResourceTextByDigest(candidate)
|
|
3644
3921
|
});
|
|
3645
|
-
const
|
|
3646
|
-
const
|
|
3647
|
-
let
|
|
3922
|
+
const agentPaths = candidateProfileAgentPaths(workspacePlan, task.executionRoots.profileRoot);
|
|
3923
|
+
const agentStagingRoot = workspacePlan.files.some((file) => file.root === "agent") ? await mkdtemp(join(tmpdir(), "tangle-candidate-profile-agent-")) : void 0;
|
|
3924
|
+
let application;
|
|
3648
3925
|
try {
|
|
3649
|
-
|
|
3650
|
-
await verifyMaterializedProfileWorkspace(task.stagingRoots.profileRoot,
|
|
3651
|
-
if (
|
|
3926
|
+
application = applyAgentCandidateWorkspacePlan(workspacePlan, task.stagingRoots.profileRoot, bundle.execution.cwd.workspace, agentStagingRoot ? { agentDir: agentStagingRoot } : void 0);
|
|
3927
|
+
await verifyMaterializedProfileWorkspace(task.stagingRoots.profileRoot, application.profileActivation.profilePlan.material);
|
|
3928
|
+
if (agentStagingRoot) await verifyMaterializedProfileWorkspace(agentStagingRoot, application.profileActivation.profilePlan.material, "agent");
|
|
3652
3929
|
} finally {
|
|
3653
|
-
if (
|
|
3930
|
+
if (agentStagingRoot) await rm(agentStagingRoot, {
|
|
3654
3931
|
recursive: true,
|
|
3655
3932
|
force: true
|
|
3656
3933
|
});
|
|
3657
3934
|
}
|
|
3658
|
-
const
|
|
3659
|
-
if (!Buffer.from(
|
|
3660
|
-
|
|
3935
|
+
const planBytes = await readVerifiedArtifact(application.profileActivation.profilePlan.artifact, ports.artifacts);
|
|
3936
|
+
if (!Buffer.from(planBytes).equals(Buffer.from(canonicalCandidateBytes$1(application.profileActivation.profilePlan.material)))) throw new Error("profile materializer did not capture exact canonical plan bytes");
|
|
3937
|
+
return {
|
|
3938
|
+
workspacePlan,
|
|
3939
|
+
agentPaths,
|
|
3940
|
+
application,
|
|
3941
|
+
planBytes
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3944
|
+
async function assertEmptyDirectory(path) {
|
|
3945
|
+
const stats = await lstat(path);
|
|
3946
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) throw new Error("profile staging root must be a real directory");
|
|
3947
|
+
if ((await readdir(path)).length !== 0) throw new Error("profile staging root must be empty before materialization");
|
|
3948
|
+
}
|
|
3949
|
+
//#endregion
|
|
3950
|
+
//#region src/candidate-execution/prepare.ts
|
|
3951
|
+
const MIN_RESERVATION_TTL_MS = 15 * 6e4;
|
|
3952
|
+
const PREPARED_HOLD_MARGIN_MS = 5 * 6e4;
|
|
3953
|
+
/** Materializes a verified candidate into one immutable evaluator-owned execution plan. */
|
|
3954
|
+
async function prepareAgentCandidateExecution(candidate, task, ports, options = {}) {
|
|
3955
|
+
const { cleanupTimeoutMs, resultTimeoutMs, reservationWindowMs } = checkPreparation(candidate, task, ports, options);
|
|
3956
|
+
const bundle = candidate.bundle;
|
|
3957
|
+
const benchmarkTask = task.task;
|
|
3958
|
+
const instructionBytes = Buffer.from(benchmarkTask.instruction, "utf8");
|
|
3959
|
+
const taskExecutorFiles = await materializeTaskWorkspace(task, ports);
|
|
3960
|
+
const candidateExecutorFiles = await materializeCandidateWorkspace(candidate, task, ports);
|
|
3961
|
+
const profile = await stageCandidateProfile(candidate, task, ports);
|
|
3661
3962
|
const container = await resolveContainer(candidate, task, ports);
|
|
3662
3963
|
const resolvedModel = await resolveModel(candidate, task, ports);
|
|
3663
3964
|
const preparationId = `candidate-preparation.${randomBytes(32).toString("base64url")}`;
|
|
@@ -3666,7 +3967,7 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
3666
3967
|
executionId: task.executionId,
|
|
3667
3968
|
preparationId,
|
|
3668
3969
|
expiresAtMs: reservationExpiresAtMs,
|
|
3669
|
-
attempt,
|
|
3970
|
+
attempt: attemptOf(task),
|
|
3670
3971
|
bundleDigest: bundle.digest,
|
|
3671
3972
|
resolved: resolvedModel,
|
|
3672
3973
|
limits: modelLimits(benchmarkTask.limits)
|
|
@@ -3675,221 +3976,160 @@ async function prepareAgentCandidateExecution(candidate, task, ports, options =
|
|
|
3675
3976
|
try {
|
|
3676
3977
|
validateProtectedModelReservation(modelReservation, benchmarkTask.limits, preparationId, reservationExpiresAtMs);
|
|
3677
3978
|
preparedMemory = await prepareMemory(candidate, task, ports, preparationId, reservationExpiresAtMs, cleanupTimeoutMs);
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
[PI_CANDIDATE_SESSION_DIR_ENV]: {
|
|
3688
|
-
kind: "public",
|
|
3689
|
-
value: profileAgentPaths.sessionDir
|
|
3690
|
-
}
|
|
3691
|
-
} : {}, bundle.execution.instructionDelivery.kind === "utf8-file" ? { [bundle.execution.instructionDelivery.env]: {
|
|
3692
|
-
kind: "public",
|
|
3693
|
-
value: bundle.execution.instructionDelivery.path
|
|
3694
|
-
} } : {}, knowledgePaths ? {
|
|
3695
|
-
[CANDIDATE_KNOWLEDGE_ROOT_ENV]: {
|
|
3696
|
-
kind: "public",
|
|
3697
|
-
value: knowledgePaths.root
|
|
3698
|
-
},
|
|
3699
|
-
...knowledgePaths.retrievalConfig ? { [CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV]: {
|
|
3700
|
-
kind: "public",
|
|
3701
|
-
value: knowledgePaths.retrievalConfig
|
|
3702
|
-
} } : {}
|
|
3703
|
-
} : {});
|
|
3704
|
-
const routes = modelRoutes(bundle.profile, benchmarkTask.model.requested);
|
|
3705
|
-
const executionMaterial = {
|
|
3706
|
-
kind: "agent-candidate-execution-plan-material",
|
|
3707
|
-
runCell: task.runCell,
|
|
3708
|
-
executionId: task.executionId,
|
|
3709
|
-
workspaces: {
|
|
3710
|
-
taskRoot: task.executionRoots.taskRoot,
|
|
3711
|
-
...task.executionRoots.candidateRoot ? { candidateRoot: task.executionRoots.candidateRoot } : {}
|
|
3712
|
-
},
|
|
3713
|
-
codeKind: bundle.code.kind,
|
|
3714
|
-
...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
|
|
3715
|
-
profile: profileApplication.application,
|
|
3716
|
-
harness: bundle.execution.harness,
|
|
3717
|
-
harnessVersion: bundle.execution.harnessVersion,
|
|
3718
|
-
instructionDelivery: bundle.execution.instructionDelivery,
|
|
3719
|
-
limits: benchmarkTask.limits,
|
|
3720
|
-
container,
|
|
3721
|
-
model: {
|
|
3722
|
-
policy: "single",
|
|
3723
|
-
resolved: resolvedModel,
|
|
3724
|
-
access: {
|
|
3725
|
-
kind: "evaluator-mediated",
|
|
3726
|
-
grantDigest: modelReservation.digest,
|
|
3727
|
-
network: modelReservation.network
|
|
3728
|
-
},
|
|
3729
|
-
routes
|
|
3730
|
-
},
|
|
3731
|
-
launch: {
|
|
3732
|
-
executable: baseLaunch.executable,
|
|
3733
|
-
args: baseLaunch.args,
|
|
3734
|
-
env: publicEnv,
|
|
3735
|
-
cwd: bundle.execution.cwd
|
|
3736
|
-
},
|
|
3737
|
-
...bundle.knowledge ? { knowledgeManifestDigest: bundle.knowledge.snapshot.digest } : {},
|
|
3738
|
-
memory,
|
|
3739
|
-
network: { mode: "disabled" }
|
|
3740
|
-
};
|
|
3741
|
-
agentCandidateExecutionPlanMaterialSchema.parse(executionMaterial);
|
|
3742
|
-
const executionBytes = canonicalCandidateBytes$1(executionMaterial);
|
|
3743
|
-
const executionDigest = canonicalCandidateDigest$1(executionMaterial);
|
|
3744
|
-
if (sha256Bytes$1(executionBytes) !== executionDigest) throw new Error("execution plan canonical serializers disagree");
|
|
3745
|
-
const executionPlan = agentCandidateExecutionPlanEvidenceSchema.parse({
|
|
3746
|
-
kind: "agent-candidate-execution-plan",
|
|
3747
|
-
digest: executionDigest,
|
|
3748
|
-
material: executionMaterial,
|
|
3749
|
-
artifact: embeddedCandidateArtifact(executionBytes)
|
|
3750
|
-
});
|
|
3751
|
-
const entrypoint = candidateEntrypointReceipt(candidate);
|
|
3752
|
-
const materializationReceipt = canonicalCandidateDocument({
|
|
3753
|
-
kind: "agent-candidate-materialization",
|
|
3754
|
-
digestAlgorithm: "rfc8785-sha256",
|
|
3755
|
-
bundleDigest: bundle.digest,
|
|
3756
|
-
benchmark: {
|
|
3757
|
-
suite: {
|
|
3758
|
-
digest: task.benchmarkSuite.digest,
|
|
3759
|
-
material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(task.benchmarkSuite)))
|
|
3760
|
-
},
|
|
3761
|
-
task: {
|
|
3762
|
-
digest: benchmarkTask.digest,
|
|
3763
|
-
material: embeddedCandidateArtifact(canonicalCandidateBytes$1(omitTopLevelDigest(benchmarkTask)))
|
|
3764
|
-
}
|
|
3765
|
-
},
|
|
3766
|
-
profileActivation,
|
|
3767
|
-
executionPlan,
|
|
3768
|
-
...bundle.execution.workspace ? { candidateWorkspace: bundle.execution.workspace } : {},
|
|
3769
|
-
codeKind: bundle.code.kind,
|
|
3770
|
-
...candidate.materializedTree ? { materializedTree: candidate.materializedTree } : {},
|
|
3771
|
-
harness: bundle.execution.harness,
|
|
3772
|
-
harnessVersion: bundle.execution.harnessVersion,
|
|
3979
|
+
return await assemblePrepared({
|
|
3980
|
+
candidate,
|
|
3981
|
+
task,
|
|
3982
|
+
ports,
|
|
3983
|
+
cleanupTimeoutMs,
|
|
3984
|
+
resultTimeoutMs,
|
|
3985
|
+
taskExecutorFiles,
|
|
3986
|
+
candidateExecutorFiles,
|
|
3987
|
+
profile,
|
|
3773
3988
|
container,
|
|
3774
3989
|
resolvedModel,
|
|
3775
|
-
|
|
3776
|
-
|
|
3990
|
+
preparationId,
|
|
3991
|
+
reservationExpiresAtMs,
|
|
3992
|
+
modelReservation,
|
|
3993
|
+
preparedMemory,
|
|
3994
|
+
instructionBytes
|
|
3777
3995
|
});
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
[CANDIDATE_TRACE_TAGS.executionId]: task.executionId,
|
|
3782
|
-
[CANDIDATE_TRACE_TAGS.bundleDigest]: bundle.digest,
|
|
3783
|
-
[CANDIDATE_TRACE_TAGS.executionPlanDigest]: executionPlan.digest,
|
|
3784
|
-
[CANDIDATE_TRACE_TAGS.materializationReceiptDigest]: materializationReceipt.digest
|
|
3785
|
-
};
|
|
3786
|
-
const traceEnv = {
|
|
3787
|
-
[CANDIDATE_TRACE_ENV.executionId]: task.executionId,
|
|
3788
|
-
[CANDIDATE_TRACE_ENV.bundleDigest]: bundle.digest,
|
|
3789
|
-
[CANDIDATE_TRACE_ENV.executionPlanDigest]: executionPlan.digest,
|
|
3790
|
-
[CANDIDATE_TRACE_ENV.materializationReceiptDigest]: materializationReceipt.digest,
|
|
3791
|
-
[CANDIDATE_TRACE_ENV.traceRunId]: traceRunId
|
|
3792
|
-
};
|
|
3793
|
-
assertEnvironmentDisjoint(publicEnv, traceEnv);
|
|
3794
|
-
return createPreparedCandidateExecution({
|
|
3996
|
+
} catch (error) {
|
|
3997
|
+
await cleanupFailedPreparation({
|
|
3998
|
+
task,
|
|
3795
3999
|
ports,
|
|
3796
|
-
bundle,
|
|
3797
|
-
benchmarkSuite: task.benchmarkSuite,
|
|
3798
|
-
benchmarkTask,
|
|
3799
|
-
executionId: task.executionId,
|
|
3800
|
-
roots: {
|
|
3801
|
-
execution: { ...task.executionRoots },
|
|
3802
|
-
staging: { ...task.stagingRoots }
|
|
3803
|
-
},
|
|
3804
|
-
profilePlan: {
|
|
3805
|
-
value: profileApplication.profileActivation.profilePlan,
|
|
3806
|
-
bytes: profilePlanBytes,
|
|
3807
|
-
written: [...profileApplication.application.mountPaths]
|
|
3808
|
-
},
|
|
3809
|
-
profileActivation,
|
|
3810
|
-
executionPlan: {
|
|
3811
|
-
value: executionPlan,
|
|
3812
|
-
bytes: executionBytes
|
|
3813
|
-
},
|
|
3814
|
-
materializationReceipt,
|
|
3815
|
-
launch: {
|
|
3816
|
-
executable: baseLaunch.executable,
|
|
3817
|
-
args: baseLaunch.args.map((value, index) => requirePublicCandidateConfigValue(value, `launch.args[${index}]`)),
|
|
3818
|
-
env: unwrapPublicEnvironment(publicEnv),
|
|
3819
|
-
flags: profileApplication.flags.map((value, index) => requirePublicCandidateConfigValue(value, `profile.flags[${index}]`)),
|
|
3820
|
-
cwd: absoluteExecutionCwd(bundle.execution.cwd, task.executionRoots)
|
|
3821
|
-
},
|
|
3822
|
-
instruction: {
|
|
3823
|
-
bytes: Uint8Array.from(instructionBytes),
|
|
3824
|
-
delivery: bundle.execution.instructionDelivery
|
|
3825
|
-
},
|
|
3826
|
-
resolvedModel,
|
|
3827
4000
|
preparationId,
|
|
3828
|
-
reservationExpiresAtMs,
|
|
3829
4001
|
cleanupTimeoutMs,
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
digest: modelReservation.digest,
|
|
3834
|
-
expiresAtMs: modelReservation.expiresAtMs,
|
|
3835
|
-
enforcedLimits: modelReservation.enforcedLimits,
|
|
3836
|
-
network: modelReservation.network
|
|
3837
|
-
},
|
|
3838
|
-
executorInputs: {
|
|
3839
|
-
taskFiles: taskExecutorFiles,
|
|
3840
|
-
...candidateExecutorFiles ? { candidateFiles: candidateExecutorFiles } : {},
|
|
3841
|
-
profileFiles: exactProfileExecutorFiles(profileWorkspacePlan.files, profileApplication.profileActivation.profilePlan.material.files)
|
|
3842
|
-
},
|
|
3843
|
-
...preparedMemory.accessDigest && preparedMemory.value.mode === "isolated" ? { memoryReservation: {
|
|
3844
|
-
preparationId,
|
|
4002
|
+
modelGrantDigest: modelReservation.digest,
|
|
4003
|
+
resolvedModel,
|
|
4004
|
+
...preparedMemory?.value.mode === "isolated" ? { memory: {
|
|
3845
4005
|
accessDigest: preparedMemory.accessDigest,
|
|
3846
|
-
expiresAtMs: reservationExpiresAtMs,
|
|
3847
4006
|
effectiveNamespace: preparedMemory.value.effectiveNamespace
|
|
3848
|
-
} } : {}
|
|
3849
|
-
|
|
3850
|
-
trace: {
|
|
3851
|
-
runId: traceRunId,
|
|
3852
|
-
tags: traceTags,
|
|
3853
|
-
env: traceEnv
|
|
3854
|
-
},
|
|
3855
|
-
memory
|
|
3856
|
-
});
|
|
3857
|
-
} catch (error) {
|
|
3858
|
-
const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs);
|
|
3859
|
-
const cleanup = [];
|
|
3860
|
-
if (preparedMemory?.value.mode === "isolated") {
|
|
3861
|
-
const accessDigest = preparedMemory.accessDigest;
|
|
3862
|
-
const effectiveNamespace = preparedMemory.value.effectiveNamespace;
|
|
3863
|
-
if (!accessDigest) throw new Error("isolated memory preparation is missing access identity");
|
|
3864
|
-
cleanup.push(withinCandidateCleanupDeadline(async () => {
|
|
3865
|
-
const closed = await ports.memory.close({
|
|
3866
|
-
executionId: task.executionId,
|
|
3867
|
-
preparationId,
|
|
3868
|
-
accessDigest,
|
|
3869
|
-
effectiveNamespace,
|
|
3870
|
-
reason: "preparation-failed"
|
|
3871
|
-
});
|
|
3872
|
-
if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("failed preparation did not close isolated memory access");
|
|
3873
|
-
}, cleanupDeadlineAtMs, "failed preparation memory cleanup"));
|
|
3874
|
-
}
|
|
3875
|
-
cleanup.push(withinCandidateCleanupDeadline(async () => {
|
|
3876
|
-
if (sealAgentCandidateModelSettlement(await ports.models.settleGrant({
|
|
3877
|
-
executionId: task.executionId,
|
|
3878
|
-
preparationId,
|
|
3879
|
-
grantDigest: modelReservation.digest,
|
|
3880
|
-
resolved: resolvedModel,
|
|
3881
|
-
reason: "preparation-failed"
|
|
3882
|
-
}), {
|
|
3883
|
-
preparationId,
|
|
3884
|
-
grantDigest: modelReservation.digest,
|
|
3885
|
-
model: resolvedModel.model
|
|
3886
|
-
}).usage.modelCalls !== 0) throw new Error("failed preparation unexpectedly contains model calls");
|
|
3887
|
-
}, cleanupDeadlineAtMs, "failed preparation model cleanup"));
|
|
3888
|
-
const cleanupErrors = (await Promise.allSettled(cleanup)).filter((result) => result.status === "rejected").map((result) => result.reason);
|
|
3889
|
-
if (cleanupErrors.length > 0) throw new Error(`candidate preparation failed and protected access cleanup failed: ${cleanupErrors.map(errorMessage).join("; ")}`, { cause: error });
|
|
4007
|
+
} } : {}
|
|
4008
|
+
}, error);
|
|
3890
4009
|
throw error;
|
|
3891
4010
|
}
|
|
3892
4011
|
}
|
|
4012
|
+
const attemptOf = (task) => ({
|
|
4013
|
+
number: task.runCell.attempt,
|
|
4014
|
+
maxAttempts: task.task.attempt.maxAttempts,
|
|
4015
|
+
retryPolicy: task.task.attempt.retryPolicy
|
|
4016
|
+
});
|
|
4017
|
+
/** Check the call before any compute, and size its timeouts and reservation window. */
|
|
4018
|
+
function checkPreparation(candidate, task, ports, options) {
|
|
4019
|
+
const cleanupTimeoutMs = candidateCleanupTimeout(options.cleanupTimeoutMs);
|
|
4020
|
+
assertSameVerificationPorts(getVerifiedCandidateState(candidate).ports, ports);
|
|
4021
|
+
const bundle = candidate.bundle;
|
|
4022
|
+
if (task.runCell.bundleDigest !== bundle.digest) throw new Error("candidate experiment cell does not bind the verified bundle");
|
|
4023
|
+
const benchmarkTask = task.task;
|
|
4024
|
+
assertTaskInput(task, bundle.execution.instructionDelivery);
|
|
4025
|
+
const resultTimeoutMs = candidateResultTimeout(options.resultTimeoutMs, benchmarkTask.limits.timeoutMs);
|
|
4026
|
+
const reservationWindowMs = candidateExecutionOwnerWindowMs(benchmarkTask.limits.timeoutMs, cleanupTimeoutMs, resultTimeoutMs) + PREPARED_HOLD_MARGIN_MS;
|
|
4027
|
+
if (reservationWindowMs > 2147483647) throw new Error("candidate reservation window exceeds the supported timer range");
|
|
4028
|
+
assertDisjointHostStagingRoots(task);
|
|
4029
|
+
return {
|
|
4030
|
+
cleanupTimeoutMs,
|
|
4031
|
+
resultTimeoutMs,
|
|
4032
|
+
reservationWindowMs
|
|
4033
|
+
};
|
|
4034
|
+
}
|
|
4035
|
+
/** Seal the plan and receipt over what the preparation staged and reserved, and freeze it. */
|
|
4036
|
+
async function assemblePrepared(hold) {
|
|
4037
|
+
const { candidate, task, ports, profile, container, resolvedModel, preparedMemory } = hold;
|
|
4038
|
+
const { bundle } = candidate;
|
|
4039
|
+
const memory = preparedMemory.value;
|
|
4040
|
+
const knowledge = await prepareAgentCandidateKnowledge(candidate, ports, task.runCell.arm);
|
|
4041
|
+
const knowledgePaths = knowledge ? candidateKnowledgeExecutionPaths(task.executionRoots.taskRoot, knowledge.retrievalConfig !== void 0) : void 0;
|
|
4042
|
+
const baseLaunch = buildLaunch(candidate, task, profile.application.flags);
|
|
4043
|
+
const publicEnv = launchEnvironment(candidate, profile, knowledgePaths);
|
|
4044
|
+
const executionPlan = sealExecutionPlan(executionPlanMaterial({
|
|
4045
|
+
candidate,
|
|
4046
|
+
task,
|
|
4047
|
+
profile,
|
|
4048
|
+
container,
|
|
4049
|
+
resolvedModel,
|
|
4050
|
+
modelReservation: hold.modelReservation,
|
|
4051
|
+
launch: baseLaunch,
|
|
4052
|
+
publicEnv,
|
|
4053
|
+
memory
|
|
4054
|
+
}));
|
|
4055
|
+
const materializationReceipt = sealMaterializationReceipt({
|
|
4056
|
+
candidate,
|
|
4057
|
+
task,
|
|
4058
|
+
profile,
|
|
4059
|
+
executionPlan: executionPlan.evidence,
|
|
4060
|
+
container,
|
|
4061
|
+
resolvedModel
|
|
4062
|
+
});
|
|
4063
|
+
const trace = candidateTraceBindings({
|
|
4064
|
+
task,
|
|
4065
|
+
bundleDigest: bundle.digest,
|
|
4066
|
+
attemptNumber: task.runCell.attempt,
|
|
4067
|
+
preparationId: hold.preparationId,
|
|
4068
|
+
executionPlanDigest: executionPlan.evidence.digest,
|
|
4069
|
+
materializationReceiptDigest: materializationReceipt.digest,
|
|
4070
|
+
publicEnv
|
|
4071
|
+
});
|
|
4072
|
+
const { modelReservation } = hold;
|
|
4073
|
+
return createPreparedCandidateExecution({
|
|
4074
|
+
ports,
|
|
4075
|
+
bundle,
|
|
4076
|
+
benchmarkSuite: task.benchmarkSuite,
|
|
4077
|
+
benchmarkTask: task.task,
|
|
4078
|
+
executionId: task.executionId,
|
|
4079
|
+
roots: {
|
|
4080
|
+
execution: { ...task.executionRoots },
|
|
4081
|
+
staging: { ...task.stagingRoots }
|
|
4082
|
+
},
|
|
4083
|
+
profilePlan: {
|
|
4084
|
+
value: profile.application.profileActivation.profilePlan,
|
|
4085
|
+
bytes: profile.planBytes,
|
|
4086
|
+
written: [...profile.application.application.mountPaths]
|
|
4087
|
+
},
|
|
4088
|
+
profileActivation: profile.application.profileActivation,
|
|
4089
|
+
executionPlan: {
|
|
4090
|
+
value: executionPlan.evidence,
|
|
4091
|
+
bytes: executionPlan.bytes
|
|
4092
|
+
},
|
|
4093
|
+
materializationReceipt,
|
|
4094
|
+
launch: {
|
|
4095
|
+
executable: baseLaunch.executable,
|
|
4096
|
+
args: baseLaunch.args.map((value, index) => requirePublicCandidateConfigValue(value, `launch.args[${index}]`)),
|
|
4097
|
+
env: unwrapPublicEnvironment(publicEnv),
|
|
4098
|
+
flags: profile.application.flags.map((value, index) => requirePublicCandidateConfigValue(value, `profile.flags[${index}]`)),
|
|
4099
|
+
cwd: absoluteExecutionCwd(bundle.execution.cwd, task.executionRoots)
|
|
4100
|
+
},
|
|
4101
|
+
instruction: {
|
|
4102
|
+
bytes: Uint8Array.from(hold.instructionBytes),
|
|
4103
|
+
delivery: bundle.execution.instructionDelivery
|
|
4104
|
+
},
|
|
4105
|
+
resolvedModel,
|
|
4106
|
+
preparationId: hold.preparationId,
|
|
4107
|
+
reservationExpiresAtMs: hold.reservationExpiresAtMs,
|
|
4108
|
+
cleanupTimeoutMs: hold.cleanupTimeoutMs,
|
|
4109
|
+
resultTimeoutMs: hold.resultTimeoutMs,
|
|
4110
|
+
modelReservation: {
|
|
4111
|
+
preparationId: modelReservation.preparationId,
|
|
4112
|
+
digest: modelReservation.digest,
|
|
4113
|
+
expiresAtMs: modelReservation.expiresAtMs,
|
|
4114
|
+
enforcedLimits: modelReservation.enforcedLimits,
|
|
4115
|
+
network: modelReservation.network
|
|
4116
|
+
},
|
|
4117
|
+
executorInputs: {
|
|
4118
|
+
taskFiles: hold.taskExecutorFiles,
|
|
4119
|
+
...hold.candidateExecutorFiles ? { candidateFiles: hold.candidateExecutorFiles } : {},
|
|
4120
|
+
profileFiles: exactProfileExecutorFiles(profile.workspacePlan.files, profile.application.profileActivation.profilePlan.material.files)
|
|
4121
|
+
},
|
|
4122
|
+
...preparedMemory.accessDigest && memory.mode === "isolated" ? { memoryReservation: {
|
|
4123
|
+
preparationId: hold.preparationId,
|
|
4124
|
+
accessDigest: preparedMemory.accessDigest,
|
|
4125
|
+
expiresAtMs: hold.reservationExpiresAtMs,
|
|
4126
|
+
effectiveNamespace: memory.effectiveNamespace
|
|
4127
|
+
} } : {},
|
|
4128
|
+
...knowledge ? { knowledge } : {},
|
|
4129
|
+
trace,
|
|
4130
|
+
memory
|
|
4131
|
+
});
|
|
4132
|
+
}
|
|
3893
4133
|
function assertSameVerificationPorts(verified, execution) {
|
|
3894
4134
|
if (verified.artifacts !== execution.artifacts || verified.repositories !== execution.repositories) throw new Error("prepare must use the same artifact and repository ports that verified the bundle");
|
|
3895
4135
|
}
|
|
@@ -3970,11 +4210,6 @@ function isContainedPath(parent, child) {
|
|
|
3970
4210
|
const path = relative(parent, child);
|
|
3971
4211
|
return path !== "" && !path.startsWith("..") && !isAbsolute(path);
|
|
3972
4212
|
}
|
|
3973
|
-
async function assertEmptyDirectory(path) {
|
|
3974
|
-
const stats = await lstat(path);
|
|
3975
|
-
if (!stats.isDirectory() || stats.isSymbolicLink()) throw new Error("profile staging root must be a real directory");
|
|
3976
|
-
if ((await readdir(path)).length !== 0) throw new Error("profile staging root must be empty before materialization");
|
|
3977
|
-
}
|
|
3978
4213
|
async function resolveContainer(candidate, task, ports) {
|
|
3979
4214
|
const environment = candidate.bundle.execution.environment;
|
|
3980
4215
|
const evaluatorTaskContainer = task.task.evaluatorTaskContainer;
|
|
@@ -4054,19 +4289,6 @@ async function prepareMemory(candidate, task, ports, preparationId, expiresAtMs,
|
|
|
4054
4289
|
throw error;
|
|
4055
4290
|
}
|
|
4056
4291
|
}
|
|
4057
|
-
function mergePublicEnvironment(...records) {
|
|
4058
|
-
const output = {};
|
|
4059
|
-
for (const record of records) for (const [name, value] of Object.entries(record)) {
|
|
4060
|
-
const previous = output[name];
|
|
4061
|
-
const publicValue = requirePublicCandidateConfigValue(value, `env.${name}`);
|
|
4062
|
-
if (previous && requirePublicCandidateConfigValue(previous, `env.${name}`) !== publicValue) throw new Error(`candidate and profile environment disagree on ${name}`);
|
|
4063
|
-
output[name] = value;
|
|
4064
|
-
}
|
|
4065
|
-
return output;
|
|
4066
|
-
}
|
|
4067
|
-
function unwrapPublicEnvironment(values) {
|
|
4068
|
-
return Object.fromEntries(Object.entries(values).map(([name, value]) => [name, requirePublicCandidateConfigValue(value, `env.${name}`)]));
|
|
4069
|
-
}
|
|
4070
4292
|
function validateProtectedModelReservation(reservation, expectedLimits, preparationId, expiresAtMs) {
|
|
4071
4293
|
if (!/^sha256:[a-f0-9]{64}$/.test(reservation.digest)) throw new Error("protected model reservation has an invalid identity digest");
|
|
4072
4294
|
if (reservation.preparationId !== preparationId || reservation.expiresAtMs !== expiresAtMs) throw new Error("protected model reservation is not scoped to this preparation");
|
|
@@ -4075,14 +4297,45 @@ function validateProtectedModelReservation(reservation, expectedLimits, preparat
|
|
|
4075
4297
|
const expectedNetworkMode = limits.maxModelCalls === 0 ? "disabled" : "gateway-only";
|
|
4076
4298
|
if (agentCandidateModelAccessNetworkSchema.parse(reservation.network).mode !== expectedNetworkMode) throw new Error("protected model reservation has the wrong network policy for its call limit");
|
|
4077
4299
|
}
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4300
|
+
/**
|
|
4301
|
+
* Close the isolated memory and settle the model grant of a preparation that failed. Throws a
|
|
4302
|
+
* combined error, with `cause` set to the preparation's own, when a cleanup fails too.
|
|
4303
|
+
*/
|
|
4304
|
+
async function cleanupFailedPreparation(held, error) {
|
|
4305
|
+
const { task, ports, preparationId, resolvedModel } = held;
|
|
4306
|
+
const cleanupDeadlineAtMs = candidateCleanupDeadline(held.cleanupTimeoutMs);
|
|
4307
|
+
const cleanup = [];
|
|
4308
|
+
if (held.memory !== void 0) {
|
|
4309
|
+
const { accessDigest, effectiveNamespace } = held.memory;
|
|
4310
|
+
if (!accessDigest) throw new Error("isolated memory preparation is missing access identity");
|
|
4311
|
+
cleanup.push(withinCandidateCleanupDeadline(async () => {
|
|
4312
|
+
const closed = await ports.memory.close({
|
|
4313
|
+
executionId: task.executionId,
|
|
4314
|
+
preparationId,
|
|
4315
|
+
accessDigest,
|
|
4316
|
+
effectiveNamespace,
|
|
4317
|
+
reason: "preparation-failed"
|
|
4318
|
+
});
|
|
4319
|
+
if (closed.closed !== true || Object.keys(closed).some((key) => key !== "closed")) throw new Error("failed preparation did not close isolated memory access");
|
|
4320
|
+
}, cleanupDeadlineAtMs, "failed preparation memory cleanup"));
|
|
4083
4321
|
}
|
|
4322
|
+
cleanup.push(withinCandidateCleanupDeadline(async () => {
|
|
4323
|
+
if (sealAgentCandidateModelSettlement(await ports.models.settleGrant({
|
|
4324
|
+
executionId: task.executionId,
|
|
4325
|
+
preparationId,
|
|
4326
|
+
grantDigest: held.modelGrantDigest,
|
|
4327
|
+
resolved: resolvedModel,
|
|
4328
|
+
reason: "preparation-failed"
|
|
4329
|
+
}), {
|
|
4330
|
+
preparationId,
|
|
4331
|
+
grantDigest: held.modelGrantDigest,
|
|
4332
|
+
model: resolvedModel.model
|
|
4333
|
+
}).usage.modelCalls !== 0) throw new Error("failed preparation unexpectedly contains model calls");
|
|
4334
|
+
}, cleanupDeadlineAtMs, "failed preparation model cleanup"));
|
|
4335
|
+
const cleanupErrors = (await Promise.allSettled(cleanup)).filter((result) => result.status === "rejected").map((result) => result.reason);
|
|
4336
|
+
if (cleanupErrors.length > 0) throw new Error(`candidate preparation failed and protected access cleanup failed: ${cleanupErrors.map(errorMessage).join("; ")}`, { cause: error });
|
|
4084
4337
|
}
|
|
4085
4338
|
//#endregion
|
|
4086
4339
|
export { verifiedResourceTextByDigest as C, AGENT_CANDIDATE_EXECUTION_SUPPORT as S, sealTerminalDigest as _, consumePreparedCandidateExecution as a, sealAgentCandidateModelSettlement as b, withinCandidateCleanupDeadline as c, assertTerminalMatchesClaim as d, assertTerminalMatchesStaged as f, requireStagedTerminal as g, rejectedStage as h, beginPreparedCandidateDisposal as i, assertRecoveryMatchesStaged as l, rejectedFinish as m, executePreparedAgentCandidate as n, candidateClaimFileInternals as o, recoveredTerminalRecord as p, assertPreparedCandidateIntegrity as r, candidateCleanupDeadline as s, prepareAgentCandidateExecution as t, assertTerminalAllowedInPhase as u, terminalRecord as v, verifyAgentCandidateBundle as w, exactProcessProviderAsCandidateExecutor as x, createProtectedAgentCandidateModelPort as y };
|
|
4087
4340
|
|
|
4088
|
-
//# sourceMappingURL=prepare-
|
|
4341
|
+
//# sourceMappingURL=prepare-C-cWCyt3.js.map
|