@rulvar/core 1.112.0 → 1.114.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 +44 -0
- package/dist/index.js +63 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3130,6 +3130,17 @@ declare const QUOTA_WINDOW_MS = 6e4;
|
|
|
3130
3130
|
* from each of them. The counters are rule-scoped: one rule matching
|
|
3131
3131
|
* two models pools them under one cap; write one rule per model for
|
|
3132
3132
|
* per-model buckets.
|
|
3133
|
+
*
|
|
3134
|
+
* Window semantics, named as the deliberate compromise it is (RV708):
|
|
3135
|
+
* every PerMinute cap counts over FIXED epoch-aligned 60 s windows
|
|
3136
|
+
* ({@link QUOTA_WINDOW_MS}), not a sliding minute. Each fixed window
|
|
3137
|
+
* enforces its cap exactly, and a burst placed astride a boundary can
|
|
3138
|
+
* therefore consume up to TWO caps inside one sliding 60 s; that
|
|
3139
|
+
* bounded burst is the price of cross-process parity (every reference
|
|
3140
|
+
* limiter in every process computes the same window from the same
|
|
3141
|
+
* clock with no shared sliding state), and provider-side minute
|
|
3142
|
+
* windows are themselves fuzzy. Size caps with the boundary burst in
|
|
3143
|
+
* mind; the semantics are pinned as intended, not scheduled to change.
|
|
3133
3144
|
*/
|
|
3134
3145
|
interface QuotaRule {
|
|
3135
3146
|
/** Adapter id, as in `concurrency.perProvider` keys. */
|
|
@@ -4761,6 +4772,18 @@ interface RunAgentOptions<S extends SchemaSpec = JsonSchema> {
|
|
|
4761
4772
|
fallbacks?: PhaseTarget[];
|
|
4762
4773
|
};
|
|
4763
4774
|
/**
|
|
4775
|
+
* Opt-in policy-facts digest (RV709): when true AND a finalize
|
|
4776
|
+
* invocation fires, one additional REQUEST-ONLY user message
|
|
4777
|
+
* precedes the synthesis instruction, carrying the deterministic
|
|
4778
|
+
* runtime facts the loop observed (quota denials and recoveries,
|
|
4779
|
+
* tool budget pressure, the finalization window, recorded spend with
|
|
4780
|
+
* its cost basis), so the final model can cite the run's own live
|
|
4781
|
+
* evidence instead of underclaiming it. Never touches the durable
|
|
4782
|
+
* transcript, never enters spawn identity; unset keeps the finalize
|
|
4783
|
+
* request byte identical.
|
|
4784
|
+
*/
|
|
4785
|
+
policyFacts?: boolean;
|
|
4786
|
+
/**
|
|
4764
4787
|
* Summarize invocation target for compaction (M4-T03): resolved
|
|
4765
4788
|
* through the chain with role 'summarize', falling back to the loop
|
|
4766
4789
|
* model when routing resolves nothing. Compaction
|
|
@@ -7962,6 +7985,18 @@ interface OrchestrateSynthesis {
|
|
|
7962
7985
|
/** Extra deterministic instruction lines appended to the synthesis prompt. */
|
|
7963
7986
|
instructions?: string;
|
|
7964
7987
|
/**
|
|
7988
|
+
* Opt-in policy-facts line in the 'single' synthesis prompt (RV709):
|
|
7989
|
+
* a deterministic digest of the settled children's durable
|
|
7990
|
+
* tool-budget facts (statuses, extension grants, finalization
|
|
7991
|
+
* windows and reserves), so the composing model can cite the run's
|
|
7992
|
+
* own observed evidence instead of underclaiming it. Folded ONLY
|
|
7993
|
+
* from replay-stable material (the settled results the journal
|
|
7994
|
+
* replays verbatim), so a resumed synthesis re-derives identical
|
|
7995
|
+
* prompt bytes; off by default, and the prompt stays byte identical
|
|
7996
|
+
* when unset (prompt bytes are journal identity).
|
|
7997
|
+
*/
|
|
7998
|
+
policyFacts?: boolean;
|
|
7999
|
+
/**
|
|
7965
8000
|
* Admission estimate for the synthesize invocation, like
|
|
7966
8001
|
* AgentOpts.estCost: under a tight orchestrator cap the default
|
|
7967
8002
|
* reserve (full maxOutputTokens pricing) can refuse the dispatch; an
|
|
@@ -9700,6 +9735,15 @@ interface InvoicePricingProvenance {
|
|
|
9700
9735
|
* bound.
|
|
9701
9736
|
*/
|
|
9702
9737
|
pinnedThroughSeq?: number | undefined;
|
|
9738
|
+
/**
|
|
9739
|
+
* The version of the caller's CURRENT table (RV706): on `composed`
|
|
9740
|
+
* exports, the table that priced everything past `pinnedThroughSeq`;
|
|
9741
|
+
* on `current-table` exports, the whole fold's table. The pinned
|
|
9742
|
+
* segments each name their own version, and without this field the
|
|
9743
|
+
* composition's second half stayed anonymous. Absent when the
|
|
9744
|
+
* caller's table declares no version.
|
|
9745
|
+
*/
|
|
9746
|
+
currentPricingVersion?: string | undefined;
|
|
9703
9747
|
}
|
|
9704
9748
|
/** The machine-readable invoice: rows plus the ledger totals. */
|
|
9705
9749
|
interface InvoiceExport {
|
package/dist/index.js
CHANGED
|
@@ -11113,6 +11113,8 @@ async function runAgent(options) {
|
|
|
11113
11113
|
let invocationCounter = 0;
|
|
11114
11114
|
let transportRetries = 0;
|
|
11115
11115
|
let schemaRecoveredTerminalExchanges = 0;
|
|
11116
|
+
let quotaDenials = 0;
|
|
11117
|
+
let quotaRecoveries = 0;
|
|
11116
11118
|
const rateLimitObservations = /* @__PURE__ */ new Map();
|
|
11117
11119
|
const roleUsageSnapshot = (role) => {
|
|
11118
11120
|
const snapshot = /* @__PURE__ */ new Map();
|
|
@@ -12012,6 +12014,7 @@ async function runAgent(options) {
|
|
|
12012
12014
|
}
|
|
12013
12015
|
};
|
|
12014
12016
|
const dispatchPhase = async (site) => {
|
|
12017
|
+
let deniedEpisode = false;
|
|
12015
12018
|
for (;;) {
|
|
12016
12019
|
const target = site.chain[site.cursor.index] ?? site.chain[0];
|
|
12017
12020
|
let tries = 0;
|
|
@@ -12083,6 +12086,13 @@ async function runAgent(options) {
|
|
|
12083
12086
|
msg: `the shared quota limiter failed to reconcile a reservation: ${detail}`
|
|
12084
12087
|
});
|
|
12085
12088
|
}
|
|
12089
|
+
if (outcome.quotaDenied === true) {
|
|
12090
|
+
quotaDenials += 1;
|
|
12091
|
+
deniedEpisode = true;
|
|
12092
|
+
} else if (deniedEpisode && outcome.neverDispatched !== true) {
|
|
12093
|
+
quotaRecoveries += 1;
|
|
12094
|
+
deniedEpisode = false;
|
|
12095
|
+
}
|
|
12086
12096
|
if (outcome.quotaDenied !== true && outcome.neverDispatched !== true) {
|
|
12087
12097
|
const accounted = recordUsage(outcome.usage, outcome.reported, target.adapter.id, target.resolved.ref, site.role, outcome.usageViolation);
|
|
12088
12098
|
const namespace = outcome.providerMetadata?.[target.adapter.id];
|
|
@@ -12685,13 +12695,37 @@ async function runAgent(options) {
|
|
|
12685
12695
|
}
|
|
12686
12696
|
if (proceed) {
|
|
12687
12697
|
turns += 1;
|
|
12688
|
-
const
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
|
|
12692
|
-
|
|
12693
|
-
|
|
12694
|
-
|
|
12698
|
+
const policyFactsLines = () => {
|
|
12699
|
+
const lines = ["POLICY FACTS (request-only runtime digest): deterministic facts this run observed; cite the ones your answer relies on."];
|
|
12700
|
+
if (options.quota !== void 0) lines.push(`quota: ${String(quotaDenials)} denial(s), ${String(quotaRecoveries)} recovered`);
|
|
12701
|
+
if (limits.maxToolCalls !== void 0 || limits.toolUnits !== void 0 || extension !== void 0) {
|
|
12702
|
+
const cap = effectiveMaxToolCalls();
|
|
12703
|
+
let budgetLine = `tool budget: ${String(toolCallsUsed)}${cap === void 0 ? "" : ` of ${String(cap)}`} calls used`;
|
|
12704
|
+
if (extension !== void 0) budgetLine += `; extensions granted: ${String(extensionGrants)}`;
|
|
12705
|
+
lines.push(budgetLine);
|
|
12706
|
+
}
|
|
12707
|
+
if (finalizationWindow !== void 0) lines.push(`finalization window: ${windowEntered ? "entered" : "not entered"}`);
|
|
12708
|
+
const spend = recordedSpend();
|
|
12709
|
+
lines.push(`recorded spend: $${spend.usd.toFixed(4)} (${spend.basis})` + (spend.basis === "aggregate-estimate" ? "; per-call records did not cover all usage, treat the number as an estimate" : ""));
|
|
12710
|
+
return lines;
|
|
12711
|
+
};
|
|
12712
|
+
const synthesisMessages = [
|
|
12713
|
+
...messages,
|
|
12714
|
+
...options.policyFacts === true ? [{
|
|
12715
|
+
role: "user",
|
|
12716
|
+
parts: [{
|
|
12717
|
+
type: "text",
|
|
12718
|
+
text: policyFactsLines().join("\n")
|
|
12719
|
+
}]
|
|
12720
|
+
}] : [],
|
|
12721
|
+
{
|
|
12722
|
+
role: "user",
|
|
12723
|
+
parts: [{
|
|
12724
|
+
type: "text",
|
|
12725
|
+
text: FINALIZE_SYNTHESIS_INSTRUCTION
|
|
12726
|
+
}]
|
|
12727
|
+
}
|
|
12728
|
+
];
|
|
12695
12729
|
let finalizeDispatch;
|
|
12696
12730
|
try {
|
|
12697
12731
|
finalizeDispatch = await dispatchPhase({
|
|
@@ -17384,6 +17418,8 @@ function validateOrchestrateOptions(opts) {
|
|
|
17384
17418
|
].includes(synthesis.effort)) throw new ConfigError(`orchestrate synthesis.effort must be one of 'low' | 'medium' | 'high' | 'xhigh' | 'max'; got ${JSON.stringify(synthesis.effort)}`);
|
|
17385
17419
|
if (synthesis.limits !== void 0) validateUsageLimits(synthesis.limits, "orchestrate synthesis.limits");
|
|
17386
17420
|
if (synthesis.instructions !== void 0 && typeof synthesis.instructions !== "string") throw new ConfigError(`orchestrate synthesis.instructions must be a string; got ${typeof synthesis.instructions}`);
|
|
17421
|
+
const facts = synthesis;
|
|
17422
|
+
if (facts.policyFacts !== void 0 && typeof facts.policyFacts !== "boolean") throw new ConfigError(`orchestrate synthesis.policyFacts must be a boolean; got ${typeof facts.policyFacts}`);
|
|
17387
17423
|
if (synthesis.estCost !== void 0) requireNonNegativeNumber(synthesis.estCost, "orchestrate synthesis.estCost");
|
|
17388
17424
|
}
|
|
17389
17425
|
const spec = opts.budget;
|
|
@@ -18922,6 +18958,26 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
18922
18958
|
...repeatedClaims === void 0 ? [] : ["Repeated claims across children were deduplicated before this prompt: only the first occurrence of each repeated line remains in the digest, and the REPEATED CLAIMS index below lists each one with its reporters."],
|
|
18923
18959
|
...spec.instructions === void 0 ? [] : [spec.instructions],
|
|
18924
18960
|
...finishValidationPromptLines(validationSpec),
|
|
18961
|
+
...spec.policyFacts === true ? [(() => {
|
|
18962
|
+
const byStatus = {};
|
|
18963
|
+
let extensionsGranted = 0;
|
|
18964
|
+
let windowsEntered = 0;
|
|
18965
|
+
let reservesUsed = 0;
|
|
18966
|
+
for (const [, record] of settledEntries) {
|
|
18967
|
+
const settled = record.settled;
|
|
18968
|
+
byStatus[settled.status] = (byStatus[settled.status] ?? 0) + 1;
|
|
18969
|
+
extensionsGranted += settled.toolBudget?.extensionsGranted ?? 0;
|
|
18970
|
+
if (settled.toolBudget?.finalizationWindowEntered === true) windowsEntered += 1;
|
|
18971
|
+
if (settled.toolBudget?.finalizationReserveUsed === true) reservesUsed += 1;
|
|
18972
|
+
}
|
|
18973
|
+
return `POLICY FACTS: ${JSON.stringify({
|
|
18974
|
+
children: settledEntries.length,
|
|
18975
|
+
byStatus: Object.fromEntries(Object.keys(byStatus).sort().map((status) => [status, byStatus[status]])),
|
|
18976
|
+
extensionsGranted,
|
|
18977
|
+
finalizationWindowsEntered: windowsEntered,
|
|
18978
|
+
finalizationReservesUsed: reservesUsed
|
|
18979
|
+
})}`;
|
|
18980
|
+
})()] : [],
|
|
18925
18981
|
`GOAL: ${goal}`,
|
|
18926
18982
|
`DRAFT: ${draftJson}`,
|
|
18927
18983
|
`DIGEST: ${digestJson}`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.114.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",
|