@rulvar/core 1.72.0 → 1.73.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/index.d.ts +65 -0
- package/dist/index.js +93 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4405,6 +4405,18 @@ interface RunAgentOptions<S extends SchemaSpec = JsonSchema> {
|
|
|
4405
4405
|
ok: false;
|
|
4406
4406
|
feedback: Record<string, unknown>;
|
|
4407
4407
|
}>;
|
|
4408
|
+
/**
|
|
4409
|
+
* The repair reserve (the v1.71 experiment review, P0.4): max EXTRA
|
|
4410
|
+
* turns the loop may grant past limits.maxTurns, one per rejected
|
|
4411
|
+
* terminal-tool exchange, schema-invalid arguments and host
|
|
4412
|
+
* validation rejections alike. The grant count derives from the
|
|
4413
|
+
* message window itself (error tool results named after the
|
|
4414
|
+
* terminal tool, clamped to the reserve), so a resumed segment that
|
|
4415
|
+
* restored the window mid-exchange re-derives the same grants and
|
|
4416
|
+
* nothing needs journaling. Zero (or absent) keeps the ceiling
|
|
4417
|
+
* byte identical to the pre 1.73 loop.
|
|
4418
|
+
*/
|
|
4419
|
+
repairTurnReserve?: number;
|
|
4408
4420
|
};
|
|
4409
4421
|
agentType?: string;
|
|
4410
4422
|
/** The primary invocation role of the tool loop; default 'loop' (M6-T05; RV-211 adds synthesize). */
|
|
@@ -7038,6 +7050,23 @@ interface FinishValidationSpec {
|
|
|
7038
7050
|
*/
|
|
7039
7051
|
maxRepairs?: number;
|
|
7040
7052
|
/**
|
|
7053
|
+
* The repair turn reserve (the v1.71 experiment review, P0.4; the
|
|
7054
|
+
* reserve RV-204 deliberately deferred). A nonnegative integer,
|
|
7055
|
+
* default 0: max EXTRA turns the invocation the validators bind (the
|
|
7056
|
+
* synthesis invocation when `synthesis` is configured, the
|
|
7057
|
+
* coordination loop otherwise) may consume past its `maxTurns`, one
|
|
7058
|
+
* granted per rejected finish exchange, schema-invalid finish
|
|
7059
|
+
* arguments and host validation rejections alike. Without it, repair
|
|
7060
|
+
* exchanges and generation compete for the same turn budget: the
|
|
7061
|
+
* v1.71 experiment lost its whole run to one malformed finish plus
|
|
7062
|
+
* one validator rejection inside maxTurns 3. The reserve is bounded,
|
|
7063
|
+
* spends from the ordinary budget ceilings (a granted turn is a paid
|
|
7064
|
+
* provider turn), and folds into the preflight turn projection
|
|
7065
|
+
* (`projectedProviderTurns` and the run ceiling) when declared
|
|
7066
|
+
* there. Zero keeps the pre 1.73 ceiling byte identical.
|
|
7067
|
+
*/
|
|
7068
|
+
repairTurnReserve?: number;
|
|
7069
|
+
/**
|
|
7041
7070
|
* The unified output contract this validator set enforces (the v1.71
|
|
7042
7071
|
* experiment review, P0.1/P0.2). Construction then runs the golden
|
|
7043
7072
|
* self test with the contract's fixtures as defaults, the contract's
|
|
@@ -8749,6 +8778,23 @@ interface PreflightOrchestratorSpec {
|
|
|
8749
8778
|
* root, so only they subtract it from spawn-admission headroom.
|
|
8750
8779
|
*/
|
|
8751
8780
|
extension?: boolean;
|
|
8781
|
+
/**
|
|
8782
|
+
* The separate synthesis invocation (RV-211), when the orchestration
|
|
8783
|
+
* configures one (the v1.71 experiment review: the run ceiling used
|
|
8784
|
+
* to stop at the coordination loop, undercounting the synthesis
|
|
8785
|
+
* turns). `limits` mirrors OrchestrateSynthesis.limits exactly
|
|
8786
|
+
* (absent = the DEFAULT_SYNTHESIS_MAX_TURNS invocation), `model`
|
|
8787
|
+
* mirrors its model override (absent = defaults.routing.synthesize),
|
|
8788
|
+
* and `estInputTokens` is the prompt-size stand-in for the derived
|
|
8789
|
+
* synthesis prompt. When `finishValidation.repairTurnReserve` is
|
|
8790
|
+
* declared, the reserve folds into THIS invocation's projected turns,
|
|
8791
|
+
* because the validators bind the synthesis finish.
|
|
8792
|
+
*/
|
|
8793
|
+
synthesis?: {
|
|
8794
|
+
model?: ModelSpec;
|
|
8795
|
+
limits?: UsageLimits;
|
|
8796
|
+
estInputTokens?: number;
|
|
8797
|
+
};
|
|
8752
8798
|
}
|
|
8753
8799
|
/** The full input: engine surface, run surface, and the declared wave. */
|
|
8754
8800
|
interface PreflightInput {
|
|
@@ -8780,6 +8826,15 @@ interface PreflightInput {
|
|
|
8780
8826
|
validators: FinishValidator[];
|
|
8781
8827
|
contract?: FinishContract;
|
|
8782
8828
|
selfTest?: FinishSelfTestFixtures;
|
|
8829
|
+
/**
|
|
8830
|
+
* Mirrors FinishValidationSpec.repairTurnReserve: folds the
|
|
8831
|
+
* declared repair headroom into the projected turns of the
|
|
8832
|
+
* invocation the validators bind (the synthesis invocation when
|
|
8833
|
+
* orchestrator.synthesis is declared, the coordination loop
|
|
8834
|
+
* otherwise), so the run ceiling prices the repair exchange the
|
|
8835
|
+
* runtime would actually grant.
|
|
8836
|
+
*/
|
|
8837
|
+
repairTurnReserve?: number;
|
|
8783
8838
|
};
|
|
8784
8839
|
}
|
|
8785
8840
|
/** One linter verdict; `spawn` names the wave entry it is about. */
|
|
@@ -8861,6 +8916,16 @@ interface PreflightReport {
|
|
|
8861
8916
|
finalizeTurns: number; /** Whether the finalize reserve is committed against the run root (extension runs). */
|
|
8862
8917
|
reserveCommitted: boolean; /** The orchestrator agent's own loop ceiling, derived exactly like a spawn's. */
|
|
8863
8918
|
projectedProviderTurns: number;
|
|
8919
|
+
/**
|
|
8920
|
+
* The separate synthesis invocation's projection, present when
|
|
8921
|
+
* input.orchestrator.synthesis was declared and the role
|
|
8922
|
+
* resolves: its turn ceiling (the repair turn reserve folded in
|
|
8923
|
+
* when declared) and its serving model.
|
|
8924
|
+
*/
|
|
8925
|
+
synthesis?: {
|
|
8926
|
+
projectedProviderTurns: number;
|
|
8927
|
+
servedBy?: ModelRef;
|
|
8928
|
+
};
|
|
8864
8929
|
};
|
|
8865
8930
|
};
|
|
8866
8931
|
quota: {
|
package/dist/index.js
CHANGED
|
@@ -11087,7 +11087,9 @@ async function runAgent(options) {
|
|
|
11087
11087
|
status = "limit";
|
|
11088
11088
|
break;
|
|
11089
11089
|
}
|
|
11090
|
-
|
|
11090
|
+
const repairReserve = options.terminalTool?.repairTurnReserve ?? 0;
|
|
11091
|
+
const grantedRepairTurns = repairReserve === 0 ? 0 : Math.min(repairReserve, messages.reduce((count, message) => count + message.parts.filter((part) => part.type === "tool-result" && part.name === options.terminalTool?.name && part.isError === true).length, 0));
|
|
11092
|
+
if (turns >= limits.maxTurns + grantedRepairTurns) {
|
|
11091
11093
|
status = "limit";
|
|
11092
11094
|
break;
|
|
11093
11095
|
}
|
|
@@ -15651,6 +15653,7 @@ function validateOrchestrateOptions(opts) {
|
|
|
15651
15653
|
seen.add(validator.name);
|
|
15652
15654
|
}
|
|
15653
15655
|
if (fv.maxRepairs !== void 0) requireNonNegativeInteger(fv.maxRepairs, "orchestrate finishValidation.maxRepairs");
|
|
15656
|
+
if (fv.repairTurnReserve !== void 0) requireNonNegativeInteger(fv.repairTurnReserve, "orchestrate finishValidation.repairTurnReserve");
|
|
15654
15657
|
const contract = fv.contract;
|
|
15655
15658
|
if (contract !== void 0) {
|
|
15656
15659
|
const shape = contract;
|
|
@@ -16756,7 +16759,10 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
16756
16759
|
},
|
|
16757
16760
|
[kTerminalTool]: {
|
|
16758
16761
|
name: FINISH_TOOL_NAME,
|
|
16759
|
-
...validationSpec === void 0 || opts?.synthesis !== void 0 ? {} : {
|
|
16762
|
+
...validationSpec === void 0 || opts?.synthesis !== void 0 ? {} : {
|
|
16763
|
+
validate: validateFinish,
|
|
16764
|
+
...validationSpec.repairTurnReserve === void 0 ? {} : { repairTurnReserve: validationSpec.repairTurnReserve }
|
|
16765
|
+
}
|
|
16760
16766
|
},
|
|
16761
16767
|
...(() => {
|
|
16762
16768
|
const priorCancelledRoot = internals.replayer.snapshot().filter((entry) => entry.kind === "agent" && entry.scope === callingState.scope && entry.status === "cancelled" && entry.checkpointRef !== void 0).at(-1);
|
|
@@ -17056,7 +17062,10 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
17056
17062
|
...spec.estCost === void 0 ? {} : { estCost: spec.estCost },
|
|
17057
17063
|
[kTerminalTool]: {
|
|
17058
17064
|
name: FINISH_TOOL_NAME,
|
|
17059
|
-
...validationSpec === void 0 ? {} : {
|
|
17065
|
+
...validationSpec === void 0 ? {} : {
|
|
17066
|
+
validate: validateFinish,
|
|
17067
|
+
...validationSpec.repairTurnReserve === void 0 ? {} : { repairTurnReserve: validationSpec.repairTurnReserve }
|
|
17068
|
+
}
|
|
17060
17069
|
}
|
|
17061
17070
|
};
|
|
17062
17071
|
const synthesized = await runtime.runInScope(synthesisState, () => ctx.agent(prompt, synthesisOpts));
|
|
@@ -17136,7 +17145,40 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
17136
17145
|
if (validationTermination !== void 0) throw validationTermination;
|
|
17137
17146
|
if (orchestratorAccount !== void 0) internals.cost.orchestrator.spentUsd = internals.budget.accountView(orchestratorAccount)?.spentUsd ?? 0;
|
|
17138
17147
|
if (result.status !== "ok") throw new ConfigError(`the orchestrator agent terminated with status '${result.status}'` + (result.errorMessage === void 0 ? "" : `: ${result.errorMessage}`));
|
|
17139
|
-
|
|
17148
|
+
/**
|
|
17149
|
+
* The synthesis failure enrichment (the v1.71 experiment review,
|
|
17150
|
+
* P0.8 remainder + P1.7): every typed failure a synthesis
|
|
17151
|
+
* invocation throws gains the verdict-derived repair taxonomy read
|
|
17152
|
+
* from the JOURNALED validation decisions (identical live and on
|
|
17153
|
+
* replay), and, when an acceptance verdict exists, the acceptance
|
|
17154
|
+
* snapshot the children already earned; the completion mirror then
|
|
17155
|
+
* lifts completion and childStatusCounts onto the error outcome,
|
|
17156
|
+
* exactly like the acceptance rejection path. The experiment's
|
|
17157
|
+
* outcome showed completion null beside four accepted children;
|
|
17158
|
+
* these are the fields that say "the fan-out work is complete, the
|
|
17159
|
+
* failure is downstream". The rejection-past-the-bound error keeps
|
|
17160
|
+
* its own repairsUsed/maxRepairs/failed untouched.
|
|
17161
|
+
*/
|
|
17162
|
+
const enrichSynthesisFailure = (thrown, snapshot) => {
|
|
17163
|
+
if (!(thrown instanceof FailRunError)) throw thrown;
|
|
17164
|
+
const base = thrown.data ?? {};
|
|
17165
|
+
const spent = validationDecisions().filter((candidate) => candidate.verdict !== "accepted");
|
|
17166
|
+
const rejectedValidators = [...new Set(spent.flatMap((candidate) => candidate.failed.map((f) => f.name)))];
|
|
17167
|
+
throw new FailRunError(thrown.message, { data: {
|
|
17168
|
+
...base,
|
|
17169
|
+
...snapshot ?? {},
|
|
17170
|
+
...spent.length === 0 || base.repairsUsed !== void 0 ? {} : {
|
|
17171
|
+
repairsUsed: spent.length,
|
|
17172
|
+
maxRepairs: validationSpec?.maxRepairs ?? 1,
|
|
17173
|
+
rejectedValidators
|
|
17174
|
+
}
|
|
17175
|
+
} });
|
|
17176
|
+
};
|
|
17177
|
+
if (opts?.acceptance === void 0) try {
|
|
17178
|
+
return await runSynthesis(result.output);
|
|
17179
|
+
} catch (thrown) {
|
|
17180
|
+
return enrichSynthesisFailure(thrown);
|
|
17181
|
+
}
|
|
17140
17182
|
const acceptanceKey = "acceptance";
|
|
17141
17183
|
const priorAcceptance = internals.replayer.snapshot().find((entry) => entry.kind === "decision" && entry.scope === callingState.scope && entry.key === acceptanceKey);
|
|
17142
17184
|
let decision;
|
|
@@ -17209,8 +17251,17 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
17209
17251
|
...decision.synthesisSkipped === void 0 ? {} : { synthesisSkipped: decision.synthesisSkipped }
|
|
17210
17252
|
} });
|
|
17211
17253
|
}
|
|
17254
|
+
let synthesizedFinal;
|
|
17255
|
+
try {
|
|
17256
|
+
synthesizedFinal = await runSynthesis(result.output);
|
|
17257
|
+
} catch (thrown) {
|
|
17258
|
+
enrichSynthesisFailure(thrown, {
|
|
17259
|
+
completion: decision.completion,
|
|
17260
|
+
childStatusCounts: decision.childStatusCounts
|
|
17261
|
+
});
|
|
17262
|
+
}
|
|
17212
17263
|
return {
|
|
17213
|
-
result:
|
|
17264
|
+
result: synthesizedFinal,
|
|
17214
17265
|
completion: decision.completion,
|
|
17215
17266
|
childStatusCounts: decision.childStatusCounts,
|
|
17216
17267
|
degradedReasons: decision.degradedReasons,
|
|
@@ -17351,6 +17402,8 @@ function preflightEstimate(input) {
|
|
|
17351
17402
|
const maxDepth = engine.budgetDefaults?.maxDepth ?? 1;
|
|
17352
17403
|
const perRun = engine.concurrency?.perRun ?? 12;
|
|
17353
17404
|
const runLimits = mergeUsageLimits(void 0, input.run?.limits, defaults.limits);
|
|
17405
|
+
const finishRepairReserve = input.finishValidation?.repairTurnReserve ?? 0;
|
|
17406
|
+
const coordinationRepairReserve = input.orchestrator?.synthesis === void 0 ? finishRepairReserve : 0;
|
|
17354
17407
|
let orchestratorEcho;
|
|
17355
17408
|
let reservedForFinalizationUsd = 0;
|
|
17356
17409
|
let effectiveCapUsd;
|
|
@@ -17371,7 +17424,7 @@ function preflightEstimate(input) {
|
|
|
17371
17424
|
finalizeReserveUsd,
|
|
17372
17425
|
finalizeTurns,
|
|
17373
17426
|
reserveCommitted,
|
|
17374
|
-
projectedProviderTurns: projectedProviderTurnsOf(echoLimits, overallExecutedCeiling(echoLimits, toolCeilingsOf(echoLimits)))
|
|
17427
|
+
projectedProviderTurns: projectedProviderTurnsOf(echoLimits, overallExecutedCeiling(echoLimits, toolCeilingsOf(echoLimits))) + coordinationRepairReserve
|
|
17375
17428
|
};
|
|
17376
17429
|
if (spec?.capUsd !== void 0 && spec.capFraction === void 0 && effectiveCapUsd !== void 0 && effectiveCapUsd < spec.capUsd) say({
|
|
17377
17430
|
severity: "warning",
|
|
@@ -17589,7 +17642,7 @@ function preflightEstimate(input) {
|
|
|
17589
17642
|
model,
|
|
17590
17643
|
inputFloor: input.orchestrator.estInputTokens ?? 0,
|
|
17591
17644
|
outputBound: outputBound ?? 0,
|
|
17592
|
-
turns: projectedProviderTurnsOf(orchLimits, overallExecutedCeiling(orchLimits, toolCeilingsOf(orchLimits))),
|
|
17645
|
+
turns: projectedProviderTurnsOf(orchLimits, overallExecutedCeiling(orchLimits, toolCeilingsOf(orchLimits))) + coordinationRepairReserve,
|
|
17593
17646
|
count: 1
|
|
17594
17647
|
});
|
|
17595
17648
|
if (effectiveCapUsd !== void 0) orchestratorReserveUsd = Math.max(0, orchestratorAdmissionEstCostUsd(effectiveCapUsd, reservedForFinalizationUsd));
|
|
@@ -17601,6 +17654,38 @@ function preflightEstimate(input) {
|
|
|
17601
17654
|
flatReserveUsd
|
|
17602
17655
|
});
|
|
17603
17656
|
}
|
|
17657
|
+
if (input.orchestrator.synthesis !== void 0) {
|
|
17658
|
+
const synthesis = input.orchestrator.synthesis;
|
|
17659
|
+
if (synthesis.limits !== void 0) validateUsageLimits(synthesis.limits, "preflight orchestrator.synthesis.limits");
|
|
17660
|
+
if (synthesis.estInputTokens !== void 0) requireNonNegativeInteger(synthesis.estInputTokens, "preflight orchestrator.synthesis.estInputTokens");
|
|
17661
|
+
const servedBy = resolveServing(synthesis.model) ?? resolveServing(defaults.routing?.synthesize);
|
|
17662
|
+
if (servedBy === void 0) say({
|
|
17663
|
+
severity: "error",
|
|
17664
|
+
code: "unrouted-role",
|
|
17665
|
+
message: "the synthesis invocation resolves no model for role 'synthesize': set defaults.routing.synthesize or a synthesis model on the call",
|
|
17666
|
+
spawn: "synthesis"
|
|
17667
|
+
});
|
|
17668
|
+
else {
|
|
17669
|
+
const caps = capsOf(servedBy);
|
|
17670
|
+
const merged = mergeUsageLimits(synthesis.limits ?? { maxTurns: 4 }, void 0, defaults.limits);
|
|
17671
|
+
const outputBound = caps === void 0 ? merged.maxOutputTokensPerTurn : merged.maxOutputTokensPerTurn === void 0 ? caps.maxOutputTokens : Math.min(caps.maxOutputTokens, merged.maxOutputTokensPerTurn);
|
|
17672
|
+
const projected = projectedProviderTurnsOf(merged, overallExecutedCeiling(merged, toolCeilingsOf(merged))) + finishRepairReserve;
|
|
17673
|
+
if (orchestratorEcho !== void 0) orchestratorEcho.synthesis = {
|
|
17674
|
+
projectedProviderTurns: projected,
|
|
17675
|
+
servedBy
|
|
17676
|
+
};
|
|
17677
|
+
const { adapterId, model } = parseModelRef(servedBy);
|
|
17678
|
+
shapes.push({
|
|
17679
|
+
label: "synthesis",
|
|
17680
|
+
provider: adapterId,
|
|
17681
|
+
model,
|
|
17682
|
+
inputFloor: synthesis.estInputTokens ?? 0,
|
|
17683
|
+
outputBound: outputBound ?? 0,
|
|
17684
|
+
turns: projected,
|
|
17685
|
+
count: 1
|
|
17686
|
+
});
|
|
17687
|
+
}
|
|
17688
|
+
}
|
|
17604
17689
|
}
|
|
17605
17690
|
const wave = [];
|
|
17606
17691
|
let committed = 0;
|
|
@@ -17807,6 +17892,7 @@ function preflightEstimate(input) {
|
|
|
17807
17892
|
if (typeof validator.validate !== "function") throw new ConfigError(`preflight finish validator '${validator.name}' has no validate function`);
|
|
17808
17893
|
names.add(validator.name);
|
|
17809
17894
|
}
|
|
17895
|
+
if (fv.repairTurnReserve !== void 0) requireNonNegativeInteger(fv.repairTurnReserve, "preflight finishValidation.repairTurnReserve");
|
|
17810
17896
|
if (fv.contract !== void 0) {
|
|
17811
17897
|
for (const contractValidator of fv.contract.validators) if (!names.has(contractValidator.name)) findings.push({
|
|
17812
17898
|
severity: "error",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.73.0",
|
|
4
4
|
"description": "Rulvar core: L0 contracts, journal kernel, ctx primitives, agent runtime, model router, tool system, dynamic orchestrator, InMemory and JSONL stores, event stream.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|