@tangle-network/agent-runtime 0.240.0 → 0.247.0
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-q224yRQK.js → activation-DYqnl8zq.js} +3 -3
- package/dist/{activation-q224yRQK.js.map → activation-DYqnl8zq.js.map} +1 -1
- package/dist/{activation-CtkpoWet.d.ts → activation-DizpINK3.d.ts} +115 -5
- package/dist/agent.d.ts +2 -2
- package/dist/agent.js +2 -2
- package/dist/candidate-execution/index.js +7 -7
- package/dist/candidate-execution/index.js.map +1 -1
- package/dist/{coordination-driver-CMprWr0k.js → coordination-driver-BV4AAUns.js} +35 -14
- package/dist/coordination-driver-BV4AAUns.js.map +1 -0
- package/dist/{delegate-kwBecu_w.js → delegate-DQAzB5Xv.js} +2 -2
- package/dist/{delegate-kwBecu_w.js.map → delegate-DQAzB5Xv.js.map} +1 -1
- package/dist/{durable-file-D24y9zg7.js → durable-file-DWQA4ooo.js} +2 -2
- package/dist/{durable-file-D24y9zg7.js.map → durable-file-DWQA4ooo.js.map} +1 -1
- package/dist/durable.d.ts +2 -2
- package/dist/durable.js +3 -3
- package/dist/{graph-Bke7I2gs.js → graph-DcBmMLIp.js} +3 -3
- package/dist/{graph-Bke7I2gs.js.map → graph-DcBmMLIp.js.map} +1 -1
- package/dist/{improvement-cycle-BpSVwIJw.js → improvement-cycle-B049YmQ8.js} +458 -60
- package/dist/improvement-cycle-B049YmQ8.js.map +1 -0
- package/dist/{index-CbZaoYbD.d.ts → index-DLzlXwr6.d.ts} +14 -9
- package/dist/index.d.ts +11 -8
- package/dist/index.js +27 -17
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +7 -5
- package/dist/intelligence.js +15 -11
- package/dist/intelligence.js.map +1 -1
- package/dist/kernel.d.ts +3 -3
- package/dist/kernel.js +9 -9
- package/dist/{loop-runner-bin-BUkkPt10.d.ts → loop-runner-bin-HbMECmxT.d.ts} +3 -3
- package/dist/{loop-runner-bin-DU8XqsGN.js → loop-runner-bin-iqq1azfy.js} +3 -3
- package/dist/{loop-runner-bin-DU8XqsGN.js.map → loop-runner-bin-iqq1azfy.js.map} +1 -1
- 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 +5 -5
- package/dist/mcp/index.js +4 -4
- package/dist/{openai-tools-BI1ofIfL.d.ts → openai-tools-DvLk_Ddg.d.ts} +2 -2
- package/dist/{prepare-Dc30WRB0.js → prepare-CibQrhfi.js} +28 -28
- package/dist/prepare-CibQrhfi.js.map +1 -0
- package/dist/profiles.d.ts +2 -2
- package/dist/{protected-model-port-D5gDcnrH.js → protected-model-port-Dhdi5mDl.js} +3 -3
- package/dist/{protected-model-port-D5gDcnrH.js.map → protected-model-port-Dhdi5mDl.js.map} +1 -1
- package/dist/{protected-redaction-wGo44k2K.js → protected-redaction-Fn1ETfJ-.js} +6 -6
- package/dist/protected-redaction-Fn1ETfJ-.js.map +1 -0
- package/dist/{provision-supervisor-DoSrqsM7.js → provision-supervisor-BgQx2Avp.js} +5 -5
- package/dist/{provision-supervisor-DoSrqsM7.js.map → provision-supervisor-BgQx2Avp.js.map} +1 -1
- package/dist/{run-layout-hZREkcfu.js → run-layout-hKAJGF4g.js} +7 -2
- package/dist/run-layout-hKAJGF4g.js.map +1 -0
- package/dist/{runtime-CmuAQsWI.js → runtime-HpTXhB3g.js} +16 -13
- package/dist/{runtime-CmuAQsWI.js.map → runtime-HpTXhB3g.js.map} +1 -1
- package/dist/{server-shkdLqls.js → server-OOE7mXrN.js} +3 -3
- package/dist/{server-shkdLqls.js.map → server-OOE7mXrN.js.map} +1 -1
- package/dist/{stream-agent-turn-DayHmtvw.d.ts → stream-agent-turn-CcumM0Bu.d.ts} +2 -2
- package/dist/{structural-rollout-CW67upUV.js → structural-rollout-z1A0okaB.js} +2 -2
- package/dist/{structural-rollout-CW67upUV.js.map → structural-rollout-z1A0okaB.js.map} +1 -1
- package/dist/{substrate-iQOskmQ_.d.ts → substrate-CQ0hfewn.d.ts} +2 -2
- package/dist/{supervise-DzoCYAe-.js → supervise-DZEOpzRw.js} +148 -35
- package/dist/supervise-DZEOpzRw.js.map +1 -0
- package/dist/{supervisor-CFSPj8rx.js → supervisor-BIBWUFUr.js} +325 -150
- package/dist/supervisor-BIBWUFUr.js.map +1 -0
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +398 -398
- package/dist/{top-app-CMMd8DgR.js → top-app-d-bmwO7O.js} +2 -2
- package/dist/{top-app-CMMd8DgR.js.map → top-app-d-bmwO7O.js.map} +1 -1
- package/dist/tui/bin.js +1 -1
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +2 -2
- package/dist/{types-CEma9LKR.d.ts → types-BUhz284C.d.ts} +25 -11
- package/dist/{workspace-archive-CBX0hwL_.js → workspace-archive-DSRT4Tro.js} +8 -8
- package/dist/workspace-archive-DSRT4Tro.js.map +1 -0
- package/package.json +6 -6
- package/dist/coordination-driver-CMprWr0k.js.map +0 -1
- package/dist/improvement-cycle-BpSVwIJw.js.map +0 -1
- package/dist/prepare-Dc30WRB0.js.map +0 -1
- package/dist/protected-redaction-wGo44k2K.js.map +0 -1
- package/dist/run-layout-hZREkcfu.js.map +0 -1
- package/dist/supervise-DzoCYAe-.js.map +0 -1
- package/dist/supervisor-CFSPj8rx.js.map +0 -1
- package/dist/workspace-archive-CBX0hwL_.js.map +0 -1
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { Sr as runSettledCommand,
|
|
1
|
+
import { Bn as linkAbort, Nr as terminateProcessTreeAndConfirm, Sr as runSettledCommand, Vn as runAbortable, ia as armDeadlineTimer, ut as createExecutor, xi as detachedSnapshot } from "./supervisor-BIBWUFUr.js";
|
|
2
2
|
import { i as ConfigError } from "./errors-DodWX-cb.js";
|
|
3
|
-
import { A as collectAgentTurn, O as optimizerMethod, a as defaultStructuralRolloutPolicy, j as streamAgentTurn } from "./structural-rollout-
|
|
3
|
+
import { A as collectAgentTurn, O as optimizerMethod, a as defaultStructuralRolloutPolicy, j as streamAgentTurn } from "./structural-rollout-z1A0okaB.js";
|
|
4
4
|
import { a as concreteProfileModel, t as assertExecutableAgentProfile } from "./model-policy-BbSCSak0.js";
|
|
5
|
-
import {
|
|
5
|
+
import { i as syncDurableDirectory, r as publishExclusiveDurableFile } from "./durable-file-DWQA4ooo.js";
|
|
6
|
+
import { a as canonicalCandidateBytes$1, d as omitTopLevelDigest, f as sha256Bytes, o as canonicalCandidateDigest$1, p as verifyCanonicalCandidateDocument, s as canonicalCandidateDocument, u as immutableCandidateValue } from "./protected-redaction-Fn1ETfJ-.js";
|
|
6
7
|
import { t as runAnalystLoop } from "./analyst-loop-DZw5QWT9.js";
|
|
7
|
-
import { A as omitUndefinedObjectFields, C as agentCandidateProfileAsAgentProfile, D as createAgentCandidateProfileActivation, M as parseExactAgentProfile, T as assertCandidateProfileBinding, c as executePreparedAgentCandidate, j as parseAgentCandidateProfileActivation, k as materializeAgentCandidateProfilePlan, o as verifiedResourceTextByDigest, s as verifyAgentCandidateBundle, t as prepareAgentCandidateExecution, w as applyExactAgentProfileDiff } from "./prepare-
|
|
8
|
-
import { AGENT_IMPROVEMENT_SOURCE_METADATA_KEY, agentCandidateMaterializationReceiptSchema, agentCandidateRunReceiptSchema, agentImprovementActivationSchema, agentImprovementProposalSchema, agentImprovementReviewSchema, agentImprovementSourceMetadata, agentImprovementSourceSchema, agentProfileDiffSchema, agentProfileImprovementArmSchema, agentProfileImprovementExecutionRefSchema, agentProfileModelHintsSchema, agentProfileSchema, applyAgentProfileDiff, candidateExecutionEvidenceSchema, canonicalAgentProfileDigest,
|
|
8
|
+
import { A as omitUndefinedObjectFields, C as agentCandidateProfileAsAgentProfile, D as createAgentCandidateProfileActivation, M as parseExactAgentProfile, T as assertCandidateProfileBinding, c as executePreparedAgentCandidate, j as parseAgentCandidateProfileActivation, k as materializeAgentCandidateProfilePlan, o as verifiedResourceTextByDigest, s as verifyAgentCandidateBundle, t as prepareAgentCandidateExecution, w as applyExactAgentProfileDiff } from "./prepare-CibQrhfi.js";
|
|
9
|
+
import { AGENT_IMPROVEMENT_SOURCE_METADATA_KEY, agentCandidateMaterializationReceiptSchema, agentCandidateRunReceiptSchema, agentImprovementActivationSchema, agentImprovementProposalSchema, agentImprovementReviewSchema, agentImprovementSourceMetadata, agentImprovementSourceSchema, agentProfileDiffSchema, agentProfileEnvironmentSchema, agentProfileImprovementArmSchema, agentProfileImprovementExecutionRefSchema, agentProfileModelHintsSchema, agentProfileSchema, agentProfileTrainingSchema, agentTrainingDatasetIdentitySchema, agentTrainingParametersSchema, agentTrainingReceiptSchema, agentTrainingTaskKey, agentTrainingTaskSchema, applyAgentProfileDiff, candidateExecutionEvidenceSchema, canonicalAgentProfileDigest, canonicalCandidateBytes, changedProfileImprovementSurfaces, defineAgentProfileDiff, diffAgentProfiles, numbersApproximatelyEqual, sha256DigestSchema, snapshotAgentProfile, trainedModelIdForArtifact } from "@tangle-network/agent-interface";
|
|
9
10
|
import { CostLedger, canonicalJson, makeProposalFinding } from "@tangle-network/agent-eval";
|
|
10
11
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
|
-
import { spawnSync } from "node:child_process";
|
|
12
|
-
import { existsSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
13
|
-
import { basename, join, resolve } from "node:path";
|
|
14
|
-
import { realpath } from "node:fs/promises";
|
|
12
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
13
|
+
import { constants, existsSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
14
|
+
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
15
|
+
import { chmod, mkdir, mkdtemp, open, realpath, rm, writeFile } from "node:fs/promises";
|
|
15
16
|
import { tmpdir } from "node:os";
|
|
16
17
|
import { isDeepStrictEqual } from "node:util";
|
|
17
18
|
import { assertProposalFindings } from "@tangle-network/agent-eval/analyst";
|
|
@@ -1000,7 +1001,7 @@ function materializeImprovementProfileCandidate(profile, surface, winner, skills
|
|
|
1000
1001
|
if (isComponentSurface(winner)) {
|
|
1001
1002
|
if (surface !== "agent-profile" || !profileComponents) throw new ConfigError(`improve(): the '${surface}' candidate has no profile component mapping`);
|
|
1002
1003
|
const winnerComponents = immutableCandidateValue({ ...winner.components });
|
|
1003
|
-
const validated =
|
|
1004
|
+
const validated = parseMaterializedProfile(profileComponents.apply(profile, winnerComponents), surface);
|
|
1004
1005
|
const materializedComponents = Object.fromEntries(validateComponents(profileComponents.read(validated), "profileComponents.read after apply"));
|
|
1005
1006
|
const names = Object.keys(winnerComponents);
|
|
1006
1007
|
if (names.length !== Object.keys(materializedComponents).length || names.some((name) => materializedComponents[name] !== winnerComponents[name])) throw new ConfigError("improve(): profileComponents.apply must round-trip every winning component exactly");
|
|
@@ -1074,9 +1075,9 @@ function materializeImprovementProfileCandidate(profile, surface, winner, skills
|
|
|
1074
1075
|
break;
|
|
1075
1076
|
}
|
|
1076
1077
|
}
|
|
1077
|
-
return
|
|
1078
|
+
return parseMaterializedProfile(candidate, surface);
|
|
1078
1079
|
}
|
|
1079
|
-
function
|
|
1080
|
+
function parseMaterializedProfile(candidate, surface) {
|
|
1080
1081
|
const parsed = agentProfileSchema.safeParse(candidate);
|
|
1081
1082
|
if (!parsed.success) throw new ConfigError(`improve(): the '${surface}' candidate does not produce a valid AgentProfile: ${parsed.error.message}`);
|
|
1082
1083
|
return immutableCandidateValue(parsed.data);
|
|
@@ -1583,6 +1584,37 @@ async function runCodeImprovement(opts) {
|
|
|
1583
1584
|
};
|
|
1584
1585
|
}
|
|
1585
1586
|
//#endregion
|
|
1587
|
+
//#region src/improvement/candidate-validation.ts
|
|
1588
|
+
/** One spelling of the execution-identity rule for optimization, training, and the harness. */
|
|
1589
|
+
function parseExecutionRef(value, label) {
|
|
1590
|
+
const parsed = sha256DigestSchema.safeParse(value);
|
|
1591
|
+
if (!parsed.success) throw new ConfigError(`${label}: executionRef must be a lowercase sha256:<64 hex> digest`);
|
|
1592
|
+
return parsed.data;
|
|
1593
|
+
}
|
|
1594
|
+
/** Validate the callback itself before any optimizer, trainer, or candidate work starts. */
|
|
1595
|
+
function assertCandidateValidator(validator) {
|
|
1596
|
+
if (validator !== void 0 && typeof validator !== "function") throw new ConfigError("validateCandidate must be a function when present");
|
|
1597
|
+
}
|
|
1598
|
+
/** A validator accepts synchronously by returning void, or rejects by throwing. */
|
|
1599
|
+
function validateProfileCandidate(validator, input) {
|
|
1600
|
+
assertCandidateValidator(validator);
|
|
1601
|
+
const result = validator?.(Object.freeze(input));
|
|
1602
|
+
if (result !== void 0) {
|
|
1603
|
+
Promise.resolve(result).catch(() => {});
|
|
1604
|
+
throw new ConfigError("candidate validators must return void synchronously or throw");
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
/**
|
|
1608
|
+
* Refuse exact held-out content digests already declared in this profile's training lineage.
|
|
1609
|
+
* Both training and trainer-visible validation rows are exposure. This is an exact
|
|
1610
|
+
* provenance check, not fuzzy decontamination or proof that undeclared training was fresh.
|
|
1611
|
+
*/
|
|
1612
|
+
function assertProfileTrainingIsHeldOut(profile, heldOutDigests) {
|
|
1613
|
+
const training = profile.metadata?.training;
|
|
1614
|
+
if (!training) return;
|
|
1615
|
+
for (const receipt of [training.receipt, ...training.ancestors]) if (receipt.dataset.tasks.some((task) => heldOutDigests.has(task.contentDigest))) throw new ConfigError("known training exposure overlaps held-out evaluation");
|
|
1616
|
+
}
|
|
1617
|
+
//#endregion
|
|
1586
1618
|
//#region src/improvement/method-controls.ts
|
|
1587
1619
|
const methodRuntimeControls = Symbol("agent-runtime.improvement.method-runtime-controls");
|
|
1588
1620
|
function withMethodRuntimeControls(method, controls) {
|
|
@@ -1750,14 +1782,6 @@ function resolveOptimizationMethod(source, context) {
|
|
|
1750
1782
|
if (!method || typeof method !== "object" || typeof method.name !== "string" || method.name.trim() !== method.name || method.name.length === 0 || typeof method.optimize !== "function") throw new ConfigError("improve(): method must be a complete OptimizationMethod with a trimmed name and optimize(input)");
|
|
1751
1783
|
return method;
|
|
1752
1784
|
}
|
|
1753
|
-
function copyProvenance(provenance) {
|
|
1754
|
-
return immutableCandidateValue(provenance);
|
|
1755
|
-
}
|
|
1756
|
-
function validateExecutionRef(value) {
|
|
1757
|
-
const parsed = sha256DigestSchema.safeParse(value);
|
|
1758
|
-
if (!parsed.success) throw new ConfigError("improve(): executionRef must be a lowercase sha256:<64 hex> digest");
|
|
1759
|
-
return parsed.data;
|
|
1760
|
-
}
|
|
1761
1785
|
function materializationError(error) {
|
|
1762
1786
|
if (error instanceof Error) return {
|
|
1763
1787
|
name: error.name,
|
|
@@ -1839,7 +1863,7 @@ function profileCandidatePopulation(provenance, baselineProfile, materializeProf
|
|
|
1839
1863
|
reason: "optimizer-did-not-report-candidate-lineage"
|
|
1840
1864
|
}
|
|
1841
1865
|
};
|
|
1842
|
-
const surfaceDigest = canonicalCandidateDigest(entry.value);
|
|
1866
|
+
const surfaceDigest = canonicalCandidateDigest$1(entry.value);
|
|
1843
1867
|
let candidateProfile;
|
|
1844
1868
|
try {
|
|
1845
1869
|
candidateProfile = materializeProfile(entry.value);
|
|
@@ -1853,9 +1877,9 @@ function profileCandidatePopulation(provenance, baselineProfile, materializeProf
|
|
|
1853
1877
|
error: materializationError(error)
|
|
1854
1878
|
};
|
|
1855
1879
|
}
|
|
1856
|
-
const profileDigest = canonicalCandidateDigest(candidateProfile);
|
|
1880
|
+
const profileDigest = canonicalCandidateDigest$1(candidateProfile);
|
|
1857
1881
|
const diffs = diffAgentProfiles(baselineProfile, candidateProfile);
|
|
1858
|
-
if (canonicalCandidateDigest(diffs.reduce(applyAgentProfileDiff, baselineProfile)) !== profileDigest) throw new ConfigError(`improve(): Interface profile diffs do not reproduce optimizer candidate ${entry.candidateDigest}`);
|
|
1882
|
+
if (canonicalCandidateDigest$1(diffs.reduce(applyAgentProfileDiff, baselineProfile)) !== profileDigest) throw new ConfigError(`improve(): Interface profile diffs do not reproduce optimizer candidate ${entry.candidateDigest}`);
|
|
1859
1883
|
materializedCandidates += 1;
|
|
1860
1884
|
return {
|
|
1861
1885
|
status: "materialized",
|
|
@@ -1865,7 +1889,7 @@ function profileCandidatePopulation(provenance, baselineProfile, materializeProf
|
|
|
1865
1889
|
profile: candidateProfile,
|
|
1866
1890
|
profileDigest,
|
|
1867
1891
|
diffs,
|
|
1868
|
-
diffDigests: diffs.map(canonicalCandidateDigest)
|
|
1892
|
+
diffDigests: diffs.map(canonicalCandidateDigest$1)
|
|
1869
1893
|
};
|
|
1870
1894
|
});
|
|
1871
1895
|
return immutableCandidateValue({
|
|
@@ -1891,9 +1915,10 @@ function profileCandidatePopulation(provenance, baselineProfile, materializeProf
|
|
|
1891
1915
|
}
|
|
1892
1916
|
async function runMethodImprovement(profile, opts) {
|
|
1893
1917
|
const { surface = "prompt", executionRef: inputExecutionRef, method: methodSource, agent, validateCandidate, findings: inputFindings = [], skills, profileComponents, optimizationRunOptions, minimumLift = 0, ...comparisonOptions } = opts;
|
|
1918
|
+
assertCandidateValidator(validateCandidate);
|
|
1894
1919
|
if (!Number.isFinite(minimumLift) || minimumLift < 0) throw new ConfigError("improve(): minimumLift must be a finite number greater than or equal to 0");
|
|
1895
1920
|
if (profileComponents && surface !== "agent-profile") throw new ConfigError("improve(): profileComponents is valid only with surface 'agent-profile'");
|
|
1896
|
-
const executionRef =
|
|
1921
|
+
const executionRef = parseExecutionRef(inputExecutionRef, "improve()");
|
|
1897
1922
|
const findings = immutableCandidateValue([...assertProposalFindings(inputFindings, "improve() method findings")]);
|
|
1898
1923
|
const preparedSurface = prepareProfileSurface(profile, surface, skills, profileComponents);
|
|
1899
1924
|
const baselineSurface = preparedSurface.surface;
|
|
@@ -1927,34 +1952,38 @@ async function runMethodImprovement(profile, opts) {
|
|
|
1927
1952
|
}));
|
|
1928
1953
|
const rawMaterializeProfile = createProfileCandidateMaterializer(profile, surface, baselineSurface, skills, profileComponents);
|
|
1929
1954
|
const runtimeInvocationId = `runtime-optimization:${randomUUID()}`;
|
|
1930
|
-
const method = resolveOptimizationMethod(methodSource, {
|
|
1931
|
-
profile,
|
|
1932
|
-
evaluationRef,
|
|
1933
|
-
surface,
|
|
1934
|
-
baselineSurface,
|
|
1935
|
-
baselineValue,
|
|
1936
|
-
findings
|
|
1937
|
-
});
|
|
1938
1955
|
const baselineSurfaceDigest = canonicalCandidateDigest$1(baselineSurface);
|
|
1956
|
+
const heldOutDigests = new Set(scenarioPartitions.finalTest.map((task) => task.scenarioDigest));
|
|
1939
1957
|
const validatedCandidates = /* @__PURE__ */ new Set();
|
|
1958
|
+
const validateMaterialized = (validator, candidate, candidateSurface, isBaseline) => {
|
|
1959
|
+
const prepared = prepareProfileSurface(candidate, surface, skills, profileComponents);
|
|
1960
|
+
validateProfileCandidate(validator, {
|
|
1961
|
+
profile: candidate,
|
|
1962
|
+
surface,
|
|
1963
|
+
candidateSurface,
|
|
1964
|
+
value: immutableCandidateValue(prepared.value),
|
|
1965
|
+
isBaseline
|
|
1966
|
+
});
|
|
1967
|
+
};
|
|
1940
1968
|
const materializeProfile = (candidateSurface) => {
|
|
1941
1969
|
const candidate = rawMaterializeProfile(candidateSurface);
|
|
1942
1970
|
const candidateDigest = canonicalCandidateDigest$1(candidateSurface);
|
|
1943
1971
|
if (!validatedCandidates.has(candidateDigest)) {
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
profile: candidate,
|
|
1947
|
-
surface,
|
|
1948
|
-
candidateSurface: immutableCandidateValue(candidateSurface),
|
|
1949
|
-
value: immutableCandidateValue(prepared.value),
|
|
1950
|
-
isBaseline: candidateDigest === baselineSurfaceDigest
|
|
1951
|
-
});
|
|
1952
|
-
validateCandidate?.(validationInput);
|
|
1972
|
+
assertProfileTrainingIsHeldOut(candidate, heldOutDigests);
|
|
1973
|
+
validateMaterialized(validateCandidate, candidate, immutableCandidateValue(candidateSurface), candidateDigest === baselineSurfaceDigest);
|
|
1953
1974
|
validatedCandidates.add(candidateDigest);
|
|
1954
1975
|
}
|
|
1955
1976
|
return candidate;
|
|
1956
1977
|
};
|
|
1957
1978
|
materializeProfile(baselineSurface);
|
|
1979
|
+
const method = resolveOptimizationMethod(methodSource, {
|
|
1980
|
+
profile,
|
|
1981
|
+
evaluationRef,
|
|
1982
|
+
surface,
|
|
1983
|
+
baselineSurface,
|
|
1984
|
+
baselineValue,
|
|
1985
|
+
findings
|
|
1986
|
+
});
|
|
1958
1987
|
const costScope = {
|
|
1959
1988
|
evaluationRef,
|
|
1960
1989
|
invocationId: runtimeInvocationId
|
|
@@ -1976,15 +2005,7 @@ async function runMethodImprovement(profile, opts) {
|
|
|
1976
2005
|
const rootSurface = toRoot(value);
|
|
1977
2006
|
const candidateDigest = canonicalCandidateDigest$1(rootSurface);
|
|
1978
2007
|
if (checked.has(candidateDigest)) return;
|
|
1979
|
-
|
|
1980
|
-
const prepared = prepareProfileSurface(candidate, surface, skills, profileComponents);
|
|
1981
|
-
controls?.validateCandidate(Object.freeze({
|
|
1982
|
-
profile: immutableCandidateValue(candidate),
|
|
1983
|
-
surface,
|
|
1984
|
-
candidateSurface: rootSurface,
|
|
1985
|
-
value: immutableCandidateValue(prepared.value),
|
|
1986
|
-
isBaseline: candidateDigest === currentBaselineDigest
|
|
1987
|
-
}));
|
|
2008
|
+
validateMaterialized(controls?.validateCandidate, materializeProfile(rootSurface), rootSurface, candidateDigest === currentBaselineDigest);
|
|
1988
2009
|
checked.add(candidateDigest);
|
|
1989
2010
|
};
|
|
1990
2011
|
check(input.baselineSurface);
|
|
@@ -2044,7 +2065,7 @@ async function runMethodImprovement(profile, opts) {
|
|
|
2044
2065
|
return {
|
|
2045
2066
|
mode: "method",
|
|
2046
2067
|
method: method.name,
|
|
2047
|
-
...score.provenance ? { provenance:
|
|
2068
|
+
...score.provenance ? { provenance: immutableCandidateValue(score.provenance) } : {},
|
|
2048
2069
|
candidate,
|
|
2049
2070
|
decision: cost.accountingComplete && score.decision.promote && score.decision.low > minimumLift ? "ship" : "hold",
|
|
2050
2071
|
lift: score.lift,
|
|
@@ -2066,6 +2087,375 @@ async function runMethodImprovement(profile, opts) {
|
|
|
2066
2087
|
};
|
|
2067
2088
|
}
|
|
2068
2089
|
//#endregion
|
|
2090
|
+
//#region src/improvement/training.ts
|
|
2091
|
+
function positiveLimit(value, label) {
|
|
2092
|
+
if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`invalid ${label}`);
|
|
2093
|
+
}
|
|
2094
|
+
async function hashFile(path, maximum, signal, capture = false) {
|
|
2095
|
+
signal.throwIfAborted();
|
|
2096
|
+
const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
2097
|
+
try {
|
|
2098
|
+
const before = await file.stat();
|
|
2099
|
+
if (!before.isFile() || !Number.isSafeInteger(before.size) || before.size > maximum) throw new Error("artifact must be a bounded regular file");
|
|
2100
|
+
const hash = createHash("sha256");
|
|
2101
|
+
const chunks = [];
|
|
2102
|
+
let bytes = 0;
|
|
2103
|
+
for await (const chunk of file.createReadStream({
|
|
2104
|
+
autoClose: false,
|
|
2105
|
+
signal
|
|
2106
|
+
})) {
|
|
2107
|
+
bytes += chunk.length;
|
|
2108
|
+
if (bytes > maximum) throw new Error("artifact exceeded its byte limit");
|
|
2109
|
+
if (bytes > before.size) throw new Error("artifact changed while being hashed");
|
|
2110
|
+
hash.update(chunk);
|
|
2111
|
+
if (capture) chunks.push(Buffer.from(chunk));
|
|
2112
|
+
}
|
|
2113
|
+
const after = await file.stat();
|
|
2114
|
+
if (before.size !== bytes || after.size !== bytes || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs) throw new Error("artifact changed while being hashed");
|
|
2115
|
+
return {
|
|
2116
|
+
digest: `sha256:${hash.digest("hex")}`,
|
|
2117
|
+
bytes,
|
|
2118
|
+
...capture ? { content: Buffer.concat(chunks) } : {}
|
|
2119
|
+
};
|
|
2120
|
+
} finally {
|
|
2121
|
+
await file.close();
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
/** Execute one pinned command without a shell, in the runtime-owned job directory. POSIX only. */
|
|
2125
|
+
function createCommandProfileTrainer(input) {
|
|
2126
|
+
const command = immutableCandidateValue(input);
|
|
2127
|
+
positiveLimit(command.maxOutputBytes, "trainer output limit");
|
|
2128
|
+
if (!command.id || command.id.trim() !== command.id || !Array.isArray(command.args) || !command.args.every((arg) => typeof arg === "string" && !arg.includes("\0"))) throw new Error("invalid trainer command");
|
|
2129
|
+
for (const file of [command.executable, ...command.inputs]) {
|
|
2130
|
+
if (!isAbsolute(file.path)) throw new Error("trainer files must use absolute paths");
|
|
2131
|
+
sha256DigestSchema.parse(file.digest);
|
|
2132
|
+
}
|
|
2133
|
+
for (const [name, value] of Object.entries(command.environment)) if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) || value.includes("\0")) throw new Error("invalid trainer environment");
|
|
2134
|
+
agentProfileEnvironmentSchema.parse(Object.fromEntries(Object.entries(command.environment).map(([key, value]) => [key, {
|
|
2135
|
+
kind: "public",
|
|
2136
|
+
value
|
|
2137
|
+
}])));
|
|
2138
|
+
const identity = immutableCandidateValue({
|
|
2139
|
+
mode: "command",
|
|
2140
|
+
id: command.id,
|
|
2141
|
+
revision: canonicalCandidateDigest$1(command)
|
|
2142
|
+
});
|
|
2143
|
+
agentTrainingReceiptSchema.shape.trainer.parse({
|
|
2144
|
+
...identity,
|
|
2145
|
+
parameters: {}
|
|
2146
|
+
});
|
|
2147
|
+
return Object.freeze({
|
|
2148
|
+
identity,
|
|
2149
|
+
async execute(request, signal) {
|
|
2150
|
+
try {
|
|
2151
|
+
if (process.platform === "win32") throw new Error("controlled trainers require POSIX process-group cancellation");
|
|
2152
|
+
const requestSnapshot = immutableCandidateValue(request);
|
|
2153
|
+
const inputBytes = Buffer.from(canonicalCandidateBytes(requestSnapshot));
|
|
2154
|
+
const verifyInputs = async () => {
|
|
2155
|
+
for (const file of [command.executable, ...command.inputs]) if ((await hashFile(file.path, Number.MAX_SAFE_INTEGER, signal)).digest !== file.digest) throw new Error("trainer executable or input digest mismatch");
|
|
2156
|
+
};
|
|
2157
|
+
await verifyInputs();
|
|
2158
|
+
signal.throwIfAborted();
|
|
2159
|
+
await new Promise((resolve, reject) => {
|
|
2160
|
+
const child = spawn(command.executable.path, command.args, {
|
|
2161
|
+
cwd: dirname(requestSnapshot.checkpointPath),
|
|
2162
|
+
env: command.environment,
|
|
2163
|
+
shell: false,
|
|
2164
|
+
detached: true,
|
|
2165
|
+
stdio: [
|
|
2166
|
+
"pipe",
|
|
2167
|
+
"pipe",
|
|
2168
|
+
"pipe"
|
|
2169
|
+
]
|
|
2170
|
+
});
|
|
2171
|
+
let failure;
|
|
2172
|
+
let outputBytes = 0;
|
|
2173
|
+
let leaderClosed = false;
|
|
2174
|
+
let termination;
|
|
2175
|
+
const stop = () => {
|
|
2176
|
+
if (!termination) {
|
|
2177
|
+
termination = terminateProcessTreeAndConfirm(child, () => leaderClosed, "createCommandProfileTrainer");
|
|
2178
|
+
termination.catch((error) => {
|
|
2179
|
+
failure ??= error;
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2182
|
+
return termination;
|
|
2183
|
+
};
|
|
2184
|
+
const abort = () => {
|
|
2185
|
+
failure ??= /* @__PURE__ */ new Error("trainer cancelled");
|
|
2186
|
+
stop();
|
|
2187
|
+
};
|
|
2188
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
2189
|
+
if (signal.aborted) abort();
|
|
2190
|
+
const count = (chunk) => {
|
|
2191
|
+
outputBytes += chunk.length;
|
|
2192
|
+
if (outputBytes > command.maxOutputBytes) {
|
|
2193
|
+
failure ??= /* @__PURE__ */ new Error("trainer output limit exceeded");
|
|
2194
|
+
stop();
|
|
2195
|
+
}
|
|
2196
|
+
};
|
|
2197
|
+
child.stdout.on("data", count);
|
|
2198
|
+
child.stderr.on("data", count);
|
|
2199
|
+
child.stdin.on("error", (error) => {
|
|
2200
|
+
failure ??= error;
|
|
2201
|
+
stop();
|
|
2202
|
+
});
|
|
2203
|
+
child.on("error", (error) => {
|
|
2204
|
+
failure ??= error;
|
|
2205
|
+
});
|
|
2206
|
+
child.on("exit", stop);
|
|
2207
|
+
child.on("close", (code, exitSignal) => {
|
|
2208
|
+
leaderClosed = true;
|
|
2209
|
+
signal.removeEventListener("abort", abort);
|
|
2210
|
+
stop().then(() => {
|
|
2211
|
+
if (failure) reject(failure);
|
|
2212
|
+
else if (code !== 0 || exitSignal !== null) reject(/* @__PURE__ */ new Error(`trainer exited unsuccessfully (${code ?? exitSignal})`));
|
|
2213
|
+
else resolve();
|
|
2214
|
+
}, reject);
|
|
2215
|
+
});
|
|
2216
|
+
child.stdin.end(inputBytes);
|
|
2217
|
+
});
|
|
2218
|
+
await verifyInputs();
|
|
2219
|
+
return {
|
|
2220
|
+
succeeded: true,
|
|
2221
|
+
value: void 0
|
|
2222
|
+
};
|
|
2223
|
+
} catch (error) {
|
|
2224
|
+
return {
|
|
2225
|
+
succeeded: false,
|
|
2226
|
+
reason: error instanceof Error ? error.message : "trainer failed"
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
function datasetIdentity(bytes) {
|
|
2233
|
+
const dataset = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
2234
|
+
canonicalCandidateBytes(dataset);
|
|
2235
|
+
if (!dataset || typeof dataset !== "object" || Object.keys(dataset).sort().join(",") !== "format,rows,version" || dataset.version !== 1 || ![
|
|
2236
|
+
"sft",
|
|
2237
|
+
"dpo",
|
|
2238
|
+
"grpo"
|
|
2239
|
+
].includes(dataset.format) || !Array.isArray(dataset.rows) || dataset.rows.length === 0 || dataset.rows.length > 1e6) throw new Error("invalid training dataset");
|
|
2240
|
+
const tasks = /* @__PURE__ */ new Map();
|
|
2241
|
+
const partitions = /* @__PURE__ */ new Map();
|
|
2242
|
+
let trainingRows = 0;
|
|
2243
|
+
for (const row of dataset.rows) {
|
|
2244
|
+
if (!row || typeof row !== "object" || Object.keys(row).sort().join(",") !== "data,partition,task" || !["train", "validation"].includes(row.partition)) throw new Error("every dataset row needs its exposure identity and partition");
|
|
2245
|
+
if (row.partition === "train") trainingRows++;
|
|
2246
|
+
const task = agentTrainingTaskSchema.parse(row.task);
|
|
2247
|
+
for (const identity of [JSON.stringify([task.benchmark, task.task]), task.contentDigest]) {
|
|
2248
|
+
const previous = partitions.get(identity);
|
|
2249
|
+
if (previous !== void 0 && previous !== row.partition) throw new Error("training and validation task partitions intersect");
|
|
2250
|
+
partitions.set(identity, row.partition);
|
|
2251
|
+
}
|
|
2252
|
+
tasks.set(agentTrainingTaskKey(task), task);
|
|
2253
|
+
}
|
|
2254
|
+
if (trainingRows === 0) throw new Error("dataset contains no training rows");
|
|
2255
|
+
const members = [...tasks.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([, task]) => task);
|
|
2256
|
+
return agentTrainingDatasetIdentitySchema.parse({
|
|
2257
|
+
digest: sha256Bytes(bytes),
|
|
2258
|
+
taskSetDigest: canonicalCandidateDigest$1(members),
|
|
2259
|
+
tasks: members
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
/** Training materializes a candidate; it never emits a ship verdict or changes a live agent. */
|
|
2263
|
+
async function runProfileTraining(profile, options) {
|
|
2264
|
+
let stage = "admission";
|
|
2265
|
+
let jobDirectory;
|
|
2266
|
+
const cancellation = linkAbort(...options.signal ? [options.signal] : []);
|
|
2267
|
+
const signal = cancellation.signal;
|
|
2268
|
+
const outputDirectory = options.outputDirectory;
|
|
2269
|
+
const timeoutMs = options.timeoutMs;
|
|
2270
|
+
let servingMayExist = false;
|
|
2271
|
+
let trainingMayExist = false;
|
|
2272
|
+
let clearTimer;
|
|
2273
|
+
try {
|
|
2274
|
+
if (options.mode !== "training") throw new Error("training mode is required");
|
|
2275
|
+
const parent = snapshotAgentProfile(profile);
|
|
2276
|
+
if (!parent.harness || !parent.model?.default?.trim() || !parent.model.provider?.trim()) throw new Error("training requires an explicit parent harness, provider and model");
|
|
2277
|
+
const parentProfileDigest = canonicalAgentProfileDigest(parent);
|
|
2278
|
+
const parentBytes = Buffer.from(JSON.stringify(parent), "utf8");
|
|
2279
|
+
sha256DigestSchema.parse(options.dataset.digest);
|
|
2280
|
+
if (timeoutMs !== void 0) positiveLimit(timeoutMs, "training timeout");
|
|
2281
|
+
positiveLimit(options.maxCheckpointBytes, "checkpoint byte limit");
|
|
2282
|
+
if (typeof options.trainer?.execute !== "function" || typeof options.serving?.serve !== "function") throw new Error("trainer and verified serving ports are required");
|
|
2283
|
+
const trainer = immutableCandidateValue(options.trainer.identity);
|
|
2284
|
+
const parameters = immutableCandidateValue(agentTrainingParametersSchema.parse(options.parameters));
|
|
2285
|
+
agentTrainingReceiptSchema.shape.trainer.parse({
|
|
2286
|
+
...trainer,
|
|
2287
|
+
parameters
|
|
2288
|
+
});
|
|
2289
|
+
assertCandidateValidator(options.validateCandidate);
|
|
2290
|
+
const execute = options.trainer.execute.bind(options.trainer);
|
|
2291
|
+
const serve = options.serving.serve.bind(options.serving);
|
|
2292
|
+
const executionRef = parseExecutionRef(options.executionRef, "training");
|
|
2293
|
+
const expectedDatasetDigest = options.dataset.digest;
|
|
2294
|
+
const sourceDataset = options.dataset.path;
|
|
2295
|
+
const maxCheckpointBytes = options.maxCheckpointBytes;
|
|
2296
|
+
const validateCandidate = options.validateCandidate;
|
|
2297
|
+
const ancestry = agentProfileTrainingSchema.shape.ancestors.parse(parent.metadata?.training ? [parent.metadata.training.receipt, ...parent.metadata.training.ancestors] : []);
|
|
2298
|
+
const validate = (candidate, isBaseline) => validateProfileCandidate(validateCandidate, {
|
|
2299
|
+
profile: candidate,
|
|
2300
|
+
surface: "agent-profile",
|
|
2301
|
+
candidateSurface: JSON.stringify(candidate),
|
|
2302
|
+
value: candidate,
|
|
2303
|
+
isBaseline
|
|
2304
|
+
});
|
|
2305
|
+
if (timeoutMs !== void 0) clearTimer = armDeadlineTimer(timeoutMs, () => cancellation.abort(/* @__PURE__ */ new Error("training deadline exceeded")), true);
|
|
2306
|
+
signal.throwIfAborted();
|
|
2307
|
+
validate(parent, true);
|
|
2308
|
+
await mkdir(outputDirectory, { recursive: true });
|
|
2309
|
+
const outputRoot = await realpath(outputDirectory);
|
|
2310
|
+
jobDirectory = await mkdtemp(join(outputRoot, "training-"));
|
|
2311
|
+
await chmod(jobDirectory, 448);
|
|
2312
|
+
syncDurableDirectory(outputRoot);
|
|
2313
|
+
const datasetPath = join(jobDirectory, "dataset.json");
|
|
2314
|
+
const parentProfilePath = join(jobDirectory, "parent-profile.json");
|
|
2315
|
+
const artifactPath = join(jobDirectory, "checkpoint.bin");
|
|
2316
|
+
stage = "dataset";
|
|
2317
|
+
const source = await hashFile(sourceDataset, 128 * 1024 * 1024, signal, true);
|
|
2318
|
+
if (source.digest !== expectedDatasetDigest) throw new Error("training dataset digest mismatch");
|
|
2319
|
+
const bytes = source.content;
|
|
2320
|
+
if (bytes.length !== source.bytes) throw new Error("training dataset snapshot is incomplete");
|
|
2321
|
+
const dataset = datasetIdentity(bytes);
|
|
2322
|
+
await writeFile(datasetPath, bytes, {
|
|
2323
|
+
flag: "wx",
|
|
2324
|
+
mode: 256
|
|
2325
|
+
});
|
|
2326
|
+
await writeFile(parentProfilePath, parentBytes, {
|
|
2327
|
+
flag: "wx",
|
|
2328
|
+
mode: 256
|
|
2329
|
+
});
|
|
2330
|
+
const request = immutableCandidateValue({
|
|
2331
|
+
version: 1,
|
|
2332
|
+
invocationId: jobDirectory,
|
|
2333
|
+
datasetPath,
|
|
2334
|
+
checkpointPath: artifactPath,
|
|
2335
|
+
parentProfilePath,
|
|
2336
|
+
parentProfileDigest,
|
|
2337
|
+
parameters,
|
|
2338
|
+
executionRef
|
|
2339
|
+
});
|
|
2340
|
+
stage = "training";
|
|
2341
|
+
const trained = await runAbortable(() => {
|
|
2342
|
+
trainingMayExist = true;
|
|
2343
|
+
return execute(request, signal);
|
|
2344
|
+
}, signal, "training cancelled");
|
|
2345
|
+
signal.throwIfAborted();
|
|
2346
|
+
if (trained?.succeeded !== true) throw new Error(trained?.reason ?? "trainer did not report success");
|
|
2347
|
+
trainingMayExist = false;
|
|
2348
|
+
stage = "checkpoint";
|
|
2349
|
+
if ((await hashFile(datasetPath, 128 * 1024 * 1024, signal)).digest !== dataset.digest || (await hashFile(parentProfilePath, parentBytes.byteLength, signal)).digest !== sha256Bytes(parentBytes)) throw new Error("trainer changed its pinned inputs");
|
|
2350
|
+
const artifact = await hashFile(artifactPath, maxCheckpointBytes, signal);
|
|
2351
|
+
if (artifact.bytes === 0) throw new Error("checkpoint must be nonempty");
|
|
2352
|
+
await chmod(artifactPath, 256);
|
|
2353
|
+
const checkpoint = await open(artifactPath, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
2354
|
+
try {
|
|
2355
|
+
await checkpoint.sync();
|
|
2356
|
+
} finally {
|
|
2357
|
+
await checkpoint.close();
|
|
2358
|
+
}
|
|
2359
|
+
stage = "serving";
|
|
2360
|
+
const served = await runAbortable(() => {
|
|
2361
|
+
servingMayExist = true;
|
|
2362
|
+
return serve({
|
|
2363
|
+
artifactPath,
|
|
2364
|
+
artifactDigest: artifact.digest,
|
|
2365
|
+
artifactBytes: artifact.bytes,
|
|
2366
|
+
routerModelId: trainedModelIdForArtifact(artifact.digest),
|
|
2367
|
+
signal
|
|
2368
|
+
});
|
|
2369
|
+
}, signal, "checkpoint serving cancelled");
|
|
2370
|
+
signal.throwIfAborted();
|
|
2371
|
+
if (served?.succeeded !== true) throw new Error(served?.reason ?? "checkpoint serving is unverified");
|
|
2372
|
+
if (served.value.artifactDigest !== artifact.digest) throw new Error("Router serving evidence names a different checkpoint");
|
|
2373
|
+
const receipt = immutableCandidateValue(agentTrainingReceiptSchema.parse({
|
|
2374
|
+
version: 1,
|
|
2375
|
+
dataset,
|
|
2376
|
+
parentProfileDigest,
|
|
2377
|
+
parentReceiptDigest: ancestry[0] ? canonicalCandidateDigest$1(ancestry[0]) : null,
|
|
2378
|
+
executionRef,
|
|
2379
|
+
trainer: {
|
|
2380
|
+
...trainer,
|
|
2381
|
+
parameters
|
|
2382
|
+
},
|
|
2383
|
+
checkpoint: {
|
|
2384
|
+
artifactDigest: artifact.digest,
|
|
2385
|
+
artifactBytes: artifact.bytes,
|
|
2386
|
+
routerModelId: served.value.routerModelId,
|
|
2387
|
+
servingDigest: served.value.evidenceDigest
|
|
2388
|
+
}
|
|
2389
|
+
}));
|
|
2390
|
+
if ((await hashFile(artifactPath, maxCheckpointBytes, signal)).digest !== artifact.digest) throw new Error("checkpoint changed during serving");
|
|
2391
|
+
stage = "profile";
|
|
2392
|
+
const previousModel = parent.metadata?.training?.receipt.checkpoint.routerModelId;
|
|
2393
|
+
const routerModelId = receipt.checkpoint.routerModelId;
|
|
2394
|
+
const rebindModels = (entries) => Object.fromEntries(Object.entries(entries).map(([key, value]) => [key, previousModel && value.model === previousModel ? {
|
|
2395
|
+
...value,
|
|
2396
|
+
model: routerModelId
|
|
2397
|
+
} : value]));
|
|
2398
|
+
const candidate = snapshotAgentProfile({
|
|
2399
|
+
...parent,
|
|
2400
|
+
model: {
|
|
2401
|
+
...parent.model,
|
|
2402
|
+
default: routerModelId,
|
|
2403
|
+
...previousModel && parent.model.small === previousModel ? { small: routerModelId } : {}
|
|
2404
|
+
},
|
|
2405
|
+
...parent.subagents && { subagents: rebindModels(parent.subagents) },
|
|
2406
|
+
...parent.modes && { modes: rebindModels(parent.modes) },
|
|
2407
|
+
metadata: {
|
|
2408
|
+
...parent.metadata,
|
|
2409
|
+
training: {
|
|
2410
|
+
receipt,
|
|
2411
|
+
ancestors: ancestry
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
});
|
|
2415
|
+
validate(candidate, false);
|
|
2416
|
+
if ((await hashFile(artifactPath, maxCheckpointBytes, signal)).digest !== artifact.digest) throw new Error("checkpoint changed during candidate validation");
|
|
2417
|
+
stage = "persistence";
|
|
2418
|
+
const receiptPath = join(jobDirectory, "receipt.json");
|
|
2419
|
+
const profilePath = join(jobDirectory, "profile.json");
|
|
2420
|
+
const profileDigest = canonicalAgentProfileDigest(candidate);
|
|
2421
|
+
for (const [path, value] of [[receiptPath, receipt], [profilePath, candidate]]) {
|
|
2422
|
+
signal.throwIfAborted();
|
|
2423
|
+
if (!publishExclusiveDurableFile(path, JSON.stringify(value), { mode: 256 })) throw new Error("training publication path already exists");
|
|
2424
|
+
}
|
|
2425
|
+
return {
|
|
2426
|
+
mode: "training",
|
|
2427
|
+
succeeded: true,
|
|
2428
|
+
profile: candidate,
|
|
2429
|
+
profileDigest,
|
|
2430
|
+
receipt,
|
|
2431
|
+
artifactPath,
|
|
2432
|
+
receiptPath,
|
|
2433
|
+
profilePath
|
|
2434
|
+
};
|
|
2435
|
+
} catch (error) {
|
|
2436
|
+
let cleanupError;
|
|
2437
|
+
if (jobDirectory) try {
|
|
2438
|
+
await rm(join(jobDirectory, "profile.json"), { force: true });
|
|
2439
|
+
syncDurableDirectory(jobDirectory);
|
|
2440
|
+
} catch (failure) {
|
|
2441
|
+
cleanupError = failure instanceof Error ? failure.message : "profile cleanup failed";
|
|
2442
|
+
}
|
|
2443
|
+
return {
|
|
2444
|
+
mode: "training",
|
|
2445
|
+
succeeded: false,
|
|
2446
|
+
stage,
|
|
2447
|
+
reason: error instanceof Error ? error.message : typeof error === "string" ? error : "training failed",
|
|
2448
|
+
servingMayExist,
|
|
2449
|
+
trainingMayExist,
|
|
2450
|
+
...cleanupError ? { cleanupError } : {},
|
|
2451
|
+
...jobDirectory ? { outputDirectory: jobDirectory } : {}
|
|
2452
|
+
};
|
|
2453
|
+
} finally {
|
|
2454
|
+
clearTimer?.();
|
|
2455
|
+
cancellation.release();
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
//#endregion
|
|
2069
2459
|
//#region src/improvement/improve.ts
|
|
2070
2460
|
async function improve(profileOrCode, opts) {
|
|
2071
2461
|
if (opts === void 0) {
|
|
@@ -2073,6 +2463,11 @@ async function improve(profileOrCode, opts) {
|
|
|
2073
2463
|
if (code?.surface !== "code") throw new ConfigError("improve(): the one-argument form requires { surface: 'code', ... }");
|
|
2074
2464
|
return runCodeImprovement(code);
|
|
2075
2465
|
}
|
|
2466
|
+
if (opts === null || typeof opts !== "object") throw new ConfigError("improve(): options must be an object");
|
|
2467
|
+
if ("mode" in opts) {
|
|
2468
|
+
if (opts.mode !== "training") throw new ConfigError("improve(): unsupported mode");
|
|
2469
|
+
return runProfileTraining(profileOrCode, opts);
|
|
2470
|
+
}
|
|
2076
2471
|
if (opts.surface === "code") throw new ConfigError("improve(): code takes one argument: improve({ surface: 'code', ... })");
|
|
2077
2472
|
const parsedProfile = agentProfileSchema.safeParse(profileOrCode);
|
|
2078
2473
|
if (!parsedProfile.success) throw new ConfigError(`improve(): input is not a valid AgentProfile: ${parsedProfile.error.message}`);
|
|
@@ -2967,6 +3362,12 @@ async function proposeAgentProfileImprovement(options) {
|
|
|
2967
3362
|
const baselineStateDigest = profileStateDigest(options.stateDigest, source.sourceIdentity, profile);
|
|
2968
3363
|
if (baselineStateDigest !== source.sourceDigest) throw new Error("profile improvement source digest does not match the measured profile state");
|
|
2969
3364
|
const policy = profilePolicyWithBudget(options.benchmark.policy, options.budgetUsd);
|
|
3365
|
+
const benchmark = sealProfileImprovementBenchmark({
|
|
3366
|
+
...options.benchmark,
|
|
3367
|
+
policy
|
|
3368
|
+
});
|
|
3369
|
+
const heldOutDigests = new Set(benchmark.tasks.map((task) => task.scenario.digest));
|
|
3370
|
+
assertProfileTrainingIsHeldOut(profile, heldOutDigests);
|
|
2970
3371
|
if (options.improvement.costCeiling !== void 0 && !numbersApproximatelyEqual(options.improvement.costCeiling, options.budgetUsd)) throw new Error("profile improvement costCeiling must equal the run budgetUsd");
|
|
2971
3372
|
const { analysis, findings } = await analyzeAgentImprovement(options.runId, options.analysis, costLedger, options.signal);
|
|
2972
3373
|
const proposalFindings = immutableCandidateValue([...inputFindings, ...findings]);
|
|
@@ -2994,10 +3395,7 @@ async function proposeAgentProfileImprovement(options) {
|
|
|
2994
3395
|
if (!step.id) throw new Error("profile improvement change requires an exact diff id");
|
|
2995
3396
|
return step.id;
|
|
2996
3397
|
});
|
|
2997
|
-
|
|
2998
|
-
...options.benchmark,
|
|
2999
|
-
policy
|
|
3000
|
-
});
|
|
3398
|
+
assertProfileTrainingIsHeldOut(candidateProfile, heldOutDigests);
|
|
3001
3399
|
assertProfileReleaseWorkIsFresh(benchmark, improvement);
|
|
3002
3400
|
const experiment = sealAgentProfileImprovementExperiment({
|
|
3003
3401
|
kind: "agent-profile-improvement-experiment",
|
|
@@ -3294,17 +3692,17 @@ function assertExactExperimentInput(input, experiment, bundle) {
|
|
|
3294
3692
|
if (input.experiment.digest !== experiment.digest || input.bundle.digest !== bundle.digest || !task || input.task.digest !== task.digest || input.benchmarkCell.suiteDigest !== experiment.benchmark.suite.digest || input.seed !== experiment.benchmark.suite.seeds[index]) throw new Error("Runtime received a substituted candidate experiment cell");
|
|
3295
3693
|
}
|
|
3296
3694
|
function assertCapturedInput(captured, expected, label) {
|
|
3297
|
-
const bytes = canonicalCandidateBytes(omitTopLevelDigest(expected));
|
|
3695
|
+
const bytes = canonicalCandidateBytes$1(omitTopLevelDigest(expected));
|
|
3298
3696
|
if (captured.digest !== expected.digest || captured.material.sha256 !== expected.digest || captured.material.byteLength !== bytes.byteLength) throw new Error(`candidate materialization substituted its ${label}`);
|
|
3299
3697
|
}
|
|
3300
3698
|
function assertEvidenceMaterialDigest(evidence, label) {
|
|
3301
|
-
const bytes = canonicalCandidateBytes(evidence.material);
|
|
3699
|
+
const bytes = canonicalCandidateBytes$1(evidence.material);
|
|
3302
3700
|
if (canonicalCandidateDigest$1(evidence.material) !== evidence.digest || evidence.artifact.sha256 !== evidence.digest || evidence.artifact.byteLength !== bytes.byteLength) throw new Error(`${label} digest does not match its canonical material`);
|
|
3303
3701
|
}
|
|
3304
3702
|
function sameOrderedValues(left, right) {
|
|
3305
3703
|
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
3306
3704
|
}
|
|
3307
3705
|
//#endregion
|
|
3308
|
-
export { agentImprovementTargetInput as A,
|
|
3706
|
+
export { agentImprovementTargetInput as A, assertCandidateValidator as B, optimizationActivationReceiptFromMetadata as C, agentImprovementProfileSurfaceDigest as D, agentImprovementProfileDiffs as E, isAgentImprovementProfileSurface as F, applyRolloutPolicyToProfile as G, parseExecutionRef as H, isAgentProfileMeasuredSurface as I, serializeRolloutPolicy as J, normalizeRolloutPolicy as K, improve as L, agentProfileImprovementStateDigest as M, assertProfileImprovementTargetsShareIdentity as N, agentImprovementProfileSurfaceInput as O, buildAgentImprovementActivationTargets as P, defaultBuildPrompt as Q, createCommandProfileTrainer as R, createOptimizationActivationReceipt as S, AGENT_PROFILE_MEASURED_SURFACES as T, rawTraceDistiller as U, assertProfileTrainingIsHeldOut as V, ROLLOUT_POLICY_EXTENSION as W, agenticGenerator as X, structuralRolloutPolicyFromProfile as Y, commandVerifier as Z, profilePolicyWithBudget as _, executeAgentCandidateExperimentCell as a, profileTaskScenarioIdentity as b, requireSealedCandidateExperiment as c, verifyAgentImprovementActivation as d, verifyAgentImprovementProposal as f, profileImprovementMetadata as g, createProfileImprovementCostLedger as h, createAgentImprovementProposal as i, agentImprovementTargetProfileDiffs as j, agentImprovementTargetDigest as k, reviewAgentImprovementProposal as l, verifyCandidateExecutionEvidence as m, createAgentImprovementActivation as n, proposeAgentImprovement as o, verifyAgentImprovementReview as p, parseRolloutPolicy as q, createAgentImprovementMeasuredComparison as r, proposeAgentProfileImprovement as s, AgentCandidateExperimentCellExecutionError as t, runAgentCandidateExperiment as u, profilePreparationAccounting as v, AGENT_IMPROVEMENT_PROFILE_SURFACES as w, sealProfileImprovementBenchmark as x, profileStateDigest as y, withMethodRuntimeControls as z };
|
|
3309
3707
|
|
|
3310
|
-
//# sourceMappingURL=improvement-cycle-
|
|
3708
|
+
//# sourceMappingURL=improvement-cycle-B049YmQ8.js.map
|