@rulvar/core 1.54.0 → 1.56.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 +381 -3
- package/dist/index.js +611 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3750,6 +3750,197 @@ function repositoryResearchToolset(options) {
|
|
|
3750
3750
|
};
|
|
3751
3751
|
}
|
|
3752
3752
|
//#endregion
|
|
3753
|
+
//#region src/tools/progress.ts
|
|
3754
|
+
/** The stock progress tool name the engine scans terminals for. */
|
|
3755
|
+
const PROGRESS_REPORT_TOOL_NAME = "report_progress";
|
|
3756
|
+
const PROGRESS_SCHEMA = {
|
|
3757
|
+
type: "object",
|
|
3758
|
+
additionalProperties: false,
|
|
3759
|
+
required: ["facts"],
|
|
3760
|
+
properties: {
|
|
3761
|
+
facts: {
|
|
3762
|
+
type: "array",
|
|
3763
|
+
items: { type: "string" },
|
|
3764
|
+
description: "New facts established since the last report; may be empty early on."
|
|
3765
|
+
},
|
|
3766
|
+
evidence: {
|
|
3767
|
+
type: "array",
|
|
3768
|
+
items: { type: "string" },
|
|
3769
|
+
description: "Evidence references backing the facts (file:line or recorded evidence ids)."
|
|
3770
|
+
},
|
|
3771
|
+
questions: {
|
|
3772
|
+
type: "array",
|
|
3773
|
+
items: { type: "string" },
|
|
3774
|
+
description: "Remaining unresolved questions."
|
|
3775
|
+
},
|
|
3776
|
+
note: {
|
|
3777
|
+
type: "string",
|
|
3778
|
+
description: "Optional short status note."
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
};
|
|
3782
|
+
/**
|
|
3783
|
+
* The stock progress-report tool. Stateless and deterministic: the
|
|
3784
|
+
* result echoes the counts, so a verbatim repeated report is a
|
|
3785
|
+
* duplicate result digest to the exploration guards. The value is the
|
|
3786
|
+
* side contract: the engine captures the LAST successful call of this
|
|
3787
|
+
* tool as the structured terminal partial of a 'limit' invocation, so
|
|
3788
|
+
* an agent that reports after every batch never loses its collected
|
|
3789
|
+
* work to a budget expiry.
|
|
3790
|
+
*/
|
|
3791
|
+
function progressReportTool() {
|
|
3792
|
+
return tool({
|
|
3793
|
+
name: PROGRESS_REPORT_TOOL_NAME,
|
|
3794
|
+
description: "Report research progress after every batch of tool calls: the new facts you established, the evidence references backing them, and the questions still open. If the invocation ends at a limit, your LAST report is returned to the caller as the structured partial result, so report before the budget runs out.",
|
|
3795
|
+
parameters: PROGRESS_SCHEMA,
|
|
3796
|
+
risk: "read",
|
|
3797
|
+
execute: (input) => {
|
|
3798
|
+
const report = input;
|
|
3799
|
+
return Promise.resolve({
|
|
3800
|
+
recorded: true,
|
|
3801
|
+
facts: report.facts?.length ?? 0,
|
|
3802
|
+
evidence: report.evidence?.length ?? 0,
|
|
3803
|
+
questions: report.questions?.length ?? 0
|
|
3804
|
+
});
|
|
3805
|
+
}
|
|
3806
|
+
});
|
|
3807
|
+
}
|
|
3808
|
+
function stringArray(value) {
|
|
3809
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
3810
|
+
}
|
|
3811
|
+
/**
|
|
3812
|
+
* The deterministic terminal scan: pairs `report_progress` tool calls
|
|
3813
|
+
* with their SUCCESSFUL results by id (a denied or failed call never
|
|
3814
|
+
* counts, mirroring the exploration guard's restore) and normalizes the
|
|
3815
|
+
* last one into a {@link ProgressReport}. Pure over the message window
|
|
3816
|
+
* it is given: the live loop hands its own history, the replay path
|
|
3817
|
+
* hands the terminal checkpoint's messages, and a compaction naturally
|
|
3818
|
+
* narrows the window to what the model itself still sees.
|
|
3819
|
+
*/
|
|
3820
|
+
function latestProgressReport(messages) {
|
|
3821
|
+
const callsById = /* @__PURE__ */ new Map();
|
|
3822
|
+
let latest;
|
|
3823
|
+
for (const msg of messages) for (const part of msg.parts) if (part.type === "tool-call" && part.name === "report_progress") callsById.set(part.id, part.args);
|
|
3824
|
+
else if (part.type === "tool-result" && part.name === "report_progress" && part.isError !== true && callsById.has(part.id)) {
|
|
3825
|
+
const args = callsById.get(part.id);
|
|
3826
|
+
if (typeof args === "object" && args !== null && !Array.isArray(args)) {
|
|
3827
|
+
const record = args;
|
|
3828
|
+
const report = {
|
|
3829
|
+
facts: stringArray(record.facts),
|
|
3830
|
+
evidence: stringArray(record.evidence),
|
|
3831
|
+
questions: stringArray(record.questions)
|
|
3832
|
+
};
|
|
3833
|
+
if (typeof record.note === "string") report.note = record.note;
|
|
3834
|
+
latest = report;
|
|
3835
|
+
}
|
|
3836
|
+
}
|
|
3837
|
+
return latest;
|
|
3838
|
+
}
|
|
3839
|
+
//#endregion
|
|
3840
|
+
//#region src/engine/profile-templates.ts
|
|
3841
|
+
/**
|
|
3842
|
+
* The research template's stop conditions: a weighted unit budget over
|
|
3843
|
+
* the research tools (bookkeeping tools are free), per-tool caps, both
|
|
3844
|
+
* repetition guards, and soft budget notices. Exported so hosts and
|
|
3845
|
+
* tests can read the exact defaults they are overriding.
|
|
3846
|
+
*/
|
|
3847
|
+
const RESEARCH_PROFILE_LIMITS = {
|
|
3848
|
+
maxTurns: 24,
|
|
3849
|
+
maxToolCalls: 48,
|
|
3850
|
+
toolBudgetNotices: true,
|
|
3851
|
+
maxRepeatedToolSignature: 2,
|
|
3852
|
+
maxNoNewEvidenceCalls: 6,
|
|
3853
|
+
maxCallsPerTool: {
|
|
3854
|
+
list_files: 12,
|
|
3855
|
+
search_files: 20,
|
|
3856
|
+
read_file: 30
|
|
3857
|
+
},
|
|
3858
|
+
toolUnits: {
|
|
3859
|
+
max: 64,
|
|
3860
|
+
costs: {
|
|
3861
|
+
list_files: 1,
|
|
3862
|
+
search_files: 2,
|
|
3863
|
+
read_file: 2,
|
|
3864
|
+
record_evidence: 0,
|
|
3865
|
+
list_evidence: 0,
|
|
3866
|
+
report_progress: 0
|
|
3867
|
+
}
|
|
3868
|
+
}
|
|
3869
|
+
};
|
|
3870
|
+
/** The implementation template's stop conditions. */
|
|
3871
|
+
const IMPLEMENTATION_PROFILE_LIMITS = {
|
|
3872
|
+
maxTurns: 32,
|
|
3873
|
+
maxToolCalls: 64,
|
|
3874
|
+
toolBudgetNotices: true,
|
|
3875
|
+
maxRepeatedToolSignature: 3,
|
|
3876
|
+
noProgressTurns: 3
|
|
3877
|
+
};
|
|
3878
|
+
/** The review template's stop conditions. */
|
|
3879
|
+
const REVIEW_PROFILE_LIMITS = {
|
|
3880
|
+
maxTurns: 16,
|
|
3881
|
+
maxToolCalls: 32,
|
|
3882
|
+
toolBudgetNotices: true,
|
|
3883
|
+
maxRepeatedToolSignature: 2,
|
|
3884
|
+
maxNoNewEvidenceCalls: 8
|
|
3885
|
+
};
|
|
3886
|
+
function mergeLimits(template, overrides) {
|
|
3887
|
+
return {
|
|
3888
|
+
...template,
|
|
3889
|
+
...overrides ?? {}
|
|
3890
|
+
};
|
|
3891
|
+
}
|
|
3892
|
+
/**
|
|
3893
|
+
* The batteries-included research child: the confined
|
|
3894
|
+
* {@link repositoryResearchToolset} over `root`, the stock
|
|
3895
|
+
* report_progress tool, and {@link RESEARCH_PROFILE_LIMITS} as the stop
|
|
3896
|
+
* conditions. A child spawned from this profile that runs out of budget
|
|
3897
|
+
* settles 'limit' WITH its last progress report as the structured
|
|
3898
|
+
* partial, and the recorded evidence stays readable host-side through
|
|
3899
|
+
* `evidence()`.
|
|
3900
|
+
*/
|
|
3901
|
+
function researchAgentProfile(options) {
|
|
3902
|
+
const { description, limits, extraTools, ...toolsetOptions } = options;
|
|
3903
|
+
const kit = repositoryResearchToolset(toolsetOptions);
|
|
3904
|
+
return {
|
|
3905
|
+
profile: {
|
|
3906
|
+
description: description ?? "Repository research over a confined root: paginated list_files/search_files/read_file with stable cursors, record_evidence verifying every citation, and report_progress after every batch. Stop conditions built in: weighted tool units, per-tool caps, repetition and no-new-evidence guards, budget notices. On limit the last progress report is the structured partial.",
|
|
3907
|
+
tools: [
|
|
3908
|
+
...kit.tools,
|
|
3909
|
+
progressReportTool(),
|
|
3910
|
+
...extraTools ?? []
|
|
3911
|
+
],
|
|
3912
|
+
limits: mergeLimits(RESEARCH_PROFILE_LIMITS, limits)
|
|
3913
|
+
},
|
|
3914
|
+
evidence: () => kit.evidence()
|
|
3915
|
+
};
|
|
3916
|
+
}
|
|
3917
|
+
/**
|
|
3918
|
+
* The implementation child template: the caller's task tools plus the
|
|
3919
|
+
* progress contract, with {@link IMPLEMENTATION_PROFILE_LIMITS} as the
|
|
3920
|
+
* stop conditions (a no-progress detector instead of the research
|
|
3921
|
+
* no-new-evidence guard: implementation legitimately re-reads state).
|
|
3922
|
+
*/
|
|
3923
|
+
function implementationAgentProfile(options = {}) {
|
|
3924
|
+
return {
|
|
3925
|
+
description: options.description ?? "Implementation work with built-in stop conditions: tool budget with notices, repeated-call guard, no-progress detector. Report progress with report_progress after every batch; on limit the last report is the structured partial.",
|
|
3926
|
+
tools: [progressReportTool(), ...options.tools ?? []],
|
|
3927
|
+
limits: mergeLimits(IMPLEMENTATION_PROFILE_LIMITS, options.limits)
|
|
3928
|
+
};
|
|
3929
|
+
}
|
|
3930
|
+
/**
|
|
3931
|
+
* The review child template: the caller's task tools plus the progress
|
|
3932
|
+
* contract, with {@link REVIEW_PROFILE_LIMITS} as the stop conditions
|
|
3933
|
+
* (a tighter turn budget and the no-new-evidence guard: a reviewer
|
|
3934
|
+
* circling over the same pages should stop, not spin).
|
|
3935
|
+
*/
|
|
3936
|
+
function reviewAgentProfile(options = {}) {
|
|
3937
|
+
return {
|
|
3938
|
+
description: options.description ?? "Focused review with built-in stop conditions: tight turn and tool budgets with notices, repetition and no-new-evidence guards. Report findings with report_progress after every batch; on limit the last report is the structured partial.",
|
|
3939
|
+
tools: [progressReportTool(), ...options.tools ?? []],
|
|
3940
|
+
limits: mergeLimits(REVIEW_PROFILE_LIMITS, options.limits)
|
|
3941
|
+
};
|
|
3942
|
+
}
|
|
3943
|
+
//#endregion
|
|
3753
3944
|
//#region src/journal/identity.ts
|
|
3754
3945
|
/**
|
|
3755
3946
|
* Content-addressed entry identity (M1-T04): IdentityInput records per
|
|
@@ -7733,9 +7924,10 @@ var Semaphore = class {
|
|
|
7733
7924
|
* ride RetryPolicy; hosts with known tier limits opt in per adapter id
|
|
7734
7925
|
* via createEngine concurrency.perProvider.
|
|
7735
7926
|
*
|
|
7736
|
-
*
|
|
7737
|
-
* processes sharing one API key coordinate
|
|
7738
|
-
*
|
|
7927
|
+
* This keyed limiter bounds PARALLELISM inside one engine only. Two
|
|
7928
|
+
* processes sharing one API key coordinate through the QuotaLimiter
|
|
7929
|
+
* SPI instead (RV-215, createEngine `quota`): rate and volume live
|
|
7930
|
+
* there, in shared storage; in-flight slots live here.
|
|
7739
7931
|
*/
|
|
7740
7932
|
var KeyedLimiter = class {
|
|
7741
7933
|
semaphores = /* @__PURE__ */ new Map();
|
|
@@ -7936,6 +8128,223 @@ function liftRetainedParts(providerMetadata, adapter) {
|
|
|
7936
8128
|
}));
|
|
7937
8129
|
}
|
|
7938
8130
|
//#endregion
|
|
8131
|
+
//#region src/model/quota.ts
|
|
8132
|
+
/**
|
|
8133
|
+
* Quota rules and the in-process reference QuotaLimiter (RV-215).
|
|
8134
|
+
* The rule model is shared by every reference implementation
|
|
8135
|
+
* (memoryQuotaLimiter here, SqliteQuotaLimiter in
|
|
8136
|
+
* @rulvar/store-sqlite): fixed one-minute windows aligned to the
|
|
8137
|
+
* epoch, admission at reservation time, reconciliation to actual
|
|
8138
|
+
* usage inside the same window. The hard guarantee is on
|
|
8139
|
+
* `requestsPerMinute` (every wire attempt is exactly one request);
|
|
8140
|
+
* `tokensPerMinute` admits on the heuristic estimate and settles to
|
|
8141
|
+
* actual usage, so token windows are approximate at admission and
|
|
8142
|
+
* exact at settlement.
|
|
8143
|
+
*
|
|
8144
|
+
* Docs: https://docs.rulvar.com/guide/model-routing
|
|
8145
|
+
*/
|
|
8146
|
+
/**
|
|
8147
|
+
* Captured at module load, before the InProcessRunner's
|
|
8148
|
+
* nondeterminism guard can patch the global: the limiter's clock is
|
|
8149
|
+
* engine infrastructure on the live-only dispatch path and must never
|
|
8150
|
+
* be blamed on workflow code.
|
|
8151
|
+
*/
|
|
8152
|
+
const nativeNow = Date.now;
|
|
8153
|
+
/** The fixed accounting window every PerMinute cap counts over. */
|
|
8154
|
+
const QUOTA_WINDOW_MS = 6e4;
|
|
8155
|
+
/**
|
|
8156
|
+
* Validates a quota rule set as a typed ConfigError before any
|
|
8157
|
+
* limiter can admit under it: a non-array or empty set, a rule
|
|
8158
|
+
* without a cap, a malformed dimension, or a malformed cap all fail
|
|
8159
|
+
* loud at construction. Shared by every reference implementation.
|
|
8160
|
+
*/
|
|
8161
|
+
function validateQuotaRules(rules, site = "quota rules") {
|
|
8162
|
+
const raw = rules;
|
|
8163
|
+
if (!Array.isArray(raw)) throw new ConfigError(`${site} must be an array of QuotaRule objects`);
|
|
8164
|
+
if (raw.length === 0) throw new ConfigError(`${site} must contain at least one rule`);
|
|
8165
|
+
raw.forEach((entry, index) => {
|
|
8166
|
+
const at = `${site}[${String(index)}]`;
|
|
8167
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) throw new ConfigError(`${at} must be a QuotaRule object`);
|
|
8168
|
+
const rule = entry;
|
|
8169
|
+
for (const dimension of [
|
|
8170
|
+
"provider",
|
|
8171
|
+
"model",
|
|
8172
|
+
"tenant"
|
|
8173
|
+
]) {
|
|
8174
|
+
const value = rule[dimension];
|
|
8175
|
+
if (value !== void 0 && (typeof value !== "string" || value === "")) throw new ConfigError(`${at}.${dimension} must be a nonempty string when given`);
|
|
8176
|
+
}
|
|
8177
|
+
if (rule.requestsPerMinute === void 0 && rule.tokensPerMinute === void 0) throw new ConfigError(`${at} must set requestsPerMinute or tokensPerMinute (or both)`);
|
|
8178
|
+
for (const cap of ["requestsPerMinute", "tokensPerMinute"]) if (rule[cap] !== void 0) requirePositiveInteger(rule[cap], `${at}.${cap}`);
|
|
8179
|
+
});
|
|
8180
|
+
}
|
|
8181
|
+
/** True when every dimension the rule pins matches the request. */
|
|
8182
|
+
function quotaRuleMatches(rule, request) {
|
|
8183
|
+
return (rule.provider === void 0 || rule.provider === request.provider) && (rule.model === void 0 || rule.model === request.model) && (rule.tenant === void 0 || rule.tenant === request.tenant);
|
|
8184
|
+
}
|
|
8185
|
+
/** The tokens a reservation is admitted under: input estimate plus the output cap. */
|
|
8186
|
+
function quotaEstimateTokens(request) {
|
|
8187
|
+
return request.estimate.inputTokens + (request.estimate.maxOutputTokens ?? 0);
|
|
8188
|
+
}
|
|
8189
|
+
/** The tokens a settled attempt actually consumed. */
|
|
8190
|
+
function quotaActualTokens(usage) {
|
|
8191
|
+
return usage.inputTokens + usage.outputTokens;
|
|
8192
|
+
}
|
|
8193
|
+
/**
|
|
8194
|
+
* One rule's admission verdict against its current-window counters,
|
|
8195
|
+
* the pure decision both reference implementations share. A denial
|
|
8196
|
+
* carries the window remainder as retryAfterMs, except when the
|
|
8197
|
+
* estimate alone can never fit the token cap: that denial says
|
|
8198
|
+
* retryAfterMs 0 (retry immediately), so the caller's bounded
|
|
8199
|
+
* attempts exhaust without waiting and failover gets its chance.
|
|
8200
|
+
*/
|
|
8201
|
+
function quotaRuleAdmission(rule, counters, estimate, msUntilWindowEnd) {
|
|
8202
|
+
if (rule.requestsPerMinute !== void 0 && counters.requests + estimate.requests > rule.requestsPerMinute) return {
|
|
8203
|
+
admit: false,
|
|
8204
|
+
retryAfterMs: msUntilWindowEnd,
|
|
8205
|
+
reason: `requestsPerMinute ${String(rule.requestsPerMinute)} exhausted`
|
|
8206
|
+
};
|
|
8207
|
+
if (rule.tokensPerMinute !== void 0) {
|
|
8208
|
+
if (estimate.tokens > rule.tokensPerMinute) return {
|
|
8209
|
+
admit: false,
|
|
8210
|
+
retryAfterMs: 0,
|
|
8211
|
+
reason: `the estimate of ${String(estimate.tokens)} tokens can never fit tokensPerMinute ${String(rule.tokensPerMinute)}`
|
|
8212
|
+
};
|
|
8213
|
+
if (counters.tokens + estimate.tokens > rule.tokensPerMinute) return {
|
|
8214
|
+
admit: false,
|
|
8215
|
+
retryAfterMs: msUntilWindowEnd,
|
|
8216
|
+
reason: `tokensPerMinute ${String(rule.tokensPerMinute)} exhausted`
|
|
8217
|
+
};
|
|
8218
|
+
}
|
|
8219
|
+
return { admit: true };
|
|
8220
|
+
}
|
|
8221
|
+
/**
|
|
8222
|
+
* Folds one more failing rule into the decision the caller returns:
|
|
8223
|
+
* the wait is the LONGEST failing horizon (every matching rule must
|
|
8224
|
+
* admit), and the FIRST failing rule names the denial.
|
|
8225
|
+
*/
|
|
8226
|
+
function mergeQuotaDenial(current, next) {
|
|
8227
|
+
if (current === void 0) return {
|
|
8228
|
+
retryAfterMs: next.retryAfterMs,
|
|
8229
|
+
reason: next.reason
|
|
8230
|
+
};
|
|
8231
|
+
return next.retryAfterMs > current.retryAfterMs ? {
|
|
8232
|
+
retryAfterMs: next.retryAfterMs,
|
|
8233
|
+
reason: current.reason
|
|
8234
|
+
} : current;
|
|
8235
|
+
}
|
|
8236
|
+
/**
|
|
8237
|
+
* The in-process reference QuotaLimiter: fixed epoch-aligned
|
|
8238
|
+
* one-minute windows over the shared rule model. Coordinates every
|
|
8239
|
+
* engine that shares THIS instance inside one process; processes
|
|
8240
|
+
* coordinate through a shared-storage implementation of the same SPI
|
|
8241
|
+
* (SqliteQuotaLimiter in @rulvar/store-sqlite) instead.
|
|
8242
|
+
*/
|
|
8243
|
+
function memoryQuotaLimiter(rules, options = {}) {
|
|
8244
|
+
validateQuotaRules(rules, "memoryQuotaLimiter rules");
|
|
8245
|
+
const now = options.now ?? (() => nativeNow());
|
|
8246
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
8247
|
+
const reservations = /* @__PURE__ */ new Map();
|
|
8248
|
+
let nextReservation = 0;
|
|
8249
|
+
const windowStartAt = (at) => at - at % QUOTA_WINDOW_MS;
|
|
8250
|
+
const bucketFor = (ruleIndex, windowStart) => {
|
|
8251
|
+
let bucket = buckets.get(ruleIndex);
|
|
8252
|
+
if (bucket === void 0 || bucket.windowStart !== windowStart) {
|
|
8253
|
+
bucket = {
|
|
8254
|
+
windowStart,
|
|
8255
|
+
requests: 0,
|
|
8256
|
+
tokens: 0
|
|
8257
|
+
};
|
|
8258
|
+
buckets.set(ruleIndex, bucket);
|
|
8259
|
+
}
|
|
8260
|
+
return bucket;
|
|
8261
|
+
};
|
|
8262
|
+
const prune = (windowStart) => {
|
|
8263
|
+
for (const [id, reservation] of reservations) if (reservation.windowStart < windowStart) reservations.delete(id);
|
|
8264
|
+
};
|
|
8265
|
+
return {
|
|
8266
|
+
reserve(request) {
|
|
8267
|
+
const at = now();
|
|
8268
|
+
const windowStart = windowStartAt(at);
|
|
8269
|
+
prune(windowStart);
|
|
8270
|
+
const estimateTokens = quotaEstimateTokens(request);
|
|
8271
|
+
const msUntilWindowEnd = windowStart + QUOTA_WINDOW_MS - at;
|
|
8272
|
+
const matched = [];
|
|
8273
|
+
let denial;
|
|
8274
|
+
rules.forEach((rule, index) => {
|
|
8275
|
+
if (!quotaRuleMatches(rule, request)) return;
|
|
8276
|
+
matched.push(index);
|
|
8277
|
+
const verdict = quotaRuleAdmission(rule, bucketFor(index, windowStart), {
|
|
8278
|
+
requests: request.estimate.requests,
|
|
8279
|
+
tokens: estimateTokens
|
|
8280
|
+
}, msUntilWindowEnd);
|
|
8281
|
+
if (!verdict.admit) denial = mergeQuotaDenial(denial, verdict);
|
|
8282
|
+
});
|
|
8283
|
+
if (denial !== void 0) return Promise.resolve({
|
|
8284
|
+
granted: false,
|
|
8285
|
+
...denial
|
|
8286
|
+
});
|
|
8287
|
+
for (const index of matched) {
|
|
8288
|
+
const bucket = bucketFor(index, windowStart);
|
|
8289
|
+
bucket.requests += request.estimate.requests;
|
|
8290
|
+
bucket.tokens += estimateTokens;
|
|
8291
|
+
}
|
|
8292
|
+
nextReservation += 1;
|
|
8293
|
+
const reservationId = `mq-${String(nextReservation)}`;
|
|
8294
|
+
reservations.set(reservationId, {
|
|
8295
|
+
windowStart,
|
|
8296
|
+
estimateTokens,
|
|
8297
|
+
ruleIndexes: matched
|
|
8298
|
+
});
|
|
8299
|
+
return Promise.resolve({
|
|
8300
|
+
granted: true,
|
|
8301
|
+
reservationId
|
|
8302
|
+
});
|
|
8303
|
+
},
|
|
8304
|
+
reconcile(reservationId, usage) {
|
|
8305
|
+
const reservation = reservations.get(reservationId);
|
|
8306
|
+
if (reservation === void 0) return Promise.resolve();
|
|
8307
|
+
reservations.delete(reservationId);
|
|
8308
|
+
const windowStart = windowStartAt(now());
|
|
8309
|
+
if (reservation.windowStart !== windowStart) return Promise.resolve();
|
|
8310
|
+
const delta = quotaActualTokens(usage) - reservation.estimateTokens;
|
|
8311
|
+
for (const index of reservation.ruleIndexes) {
|
|
8312
|
+
const bucket = buckets.get(index);
|
|
8313
|
+
if (bucket !== void 0 && bucket.windowStart === windowStart) bucket.tokens = Math.max(0, bucket.tokens + delta);
|
|
8314
|
+
}
|
|
8315
|
+
return Promise.resolve();
|
|
8316
|
+
},
|
|
8317
|
+
snapshot() {
|
|
8318
|
+
const windowStart = windowStartAt(now());
|
|
8319
|
+
return rules.map((rule, index) => {
|
|
8320
|
+
const bucket = buckets.get(index);
|
|
8321
|
+
const current = bucket !== void 0 && bucket.windowStart === windowStart;
|
|
8322
|
+
return {
|
|
8323
|
+
rule,
|
|
8324
|
+
windowStart,
|
|
8325
|
+
requests: current ? bucket.requests : 0,
|
|
8326
|
+
tokens: current ? bucket.tokens : 0
|
|
8327
|
+
};
|
|
8328
|
+
});
|
|
8329
|
+
}
|
|
8330
|
+
};
|
|
8331
|
+
}
|
|
8332
|
+
/**
|
|
8333
|
+
* Validates createEngine's quota config as a typed ConfigError before
|
|
8334
|
+
* any run could dispatch under a malformed limiter (the intake
|
|
8335
|
+
* discipline every engine option follows).
|
|
8336
|
+
*/
|
|
8337
|
+
function validateEngineQuotaConfig(config, site = "createEngine quota") {
|
|
8338
|
+
if (config === void 0) return;
|
|
8339
|
+
const raw = config;
|
|
8340
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new ConfigError(`${site} must be an object with a limiter`);
|
|
8341
|
+
const candidate = raw;
|
|
8342
|
+
const limiter = candidate.limiter;
|
|
8343
|
+
if (typeof limiter !== "object" || limiter === null || typeof limiter.reserve !== "function" || typeof limiter.reconcile !== "function") throw new ConfigError(`${site}.limiter must implement QuotaLimiter (reserve and reconcile functions)`);
|
|
8344
|
+
if (candidate.tenant !== void 0 && (typeof candidate.tenant !== "string" || candidate.tenant === "")) throw new ConfigError(`${site}.tenant must be a nonempty string when given`);
|
|
8345
|
+
if (candidate.onLimiterError !== void 0 && candidate.onLimiterError !== "deny" && candidate.onLimiterError !== "allow") throw new ConfigError(`${site}.onLimiterError must be 'deny' or 'allow' when given`);
|
|
8346
|
+
}
|
|
8347
|
+
//#endregion
|
|
7939
8348
|
//#region src/model/retry.ts
|
|
7940
8349
|
/**
|
|
7941
8350
|
* Transport RetryPolicy (M4-T05): retries live UNDER the journal. A
|
|
@@ -8461,6 +8870,10 @@ function mergeUsageLimits(call, profile, engine) {
|
|
|
8461
8870
|
if (maxRepeatedToolSignature !== void 0) merged.maxRepeatedToolSignature = maxRepeatedToolSignature;
|
|
8462
8871
|
const maxNoNewEvidenceCalls = pick("maxNoNewEvidenceCalls");
|
|
8463
8872
|
if (maxNoNewEvidenceCalls !== void 0) merged.maxNoNewEvidenceCalls = maxNoNewEvidenceCalls;
|
|
8873
|
+
const maxCallsPerTool = pick("maxCallsPerTool");
|
|
8874
|
+
if (maxCallsPerTool !== void 0) merged.maxCallsPerTool = maxCallsPerTool;
|
|
8875
|
+
const toolUnits = pick("toolUnits");
|
|
8876
|
+
if (toolUnits !== void 0) merged.toolUnits = toolUnits;
|
|
8464
8877
|
return merged;
|
|
8465
8878
|
}
|
|
8466
8879
|
/**
|
|
@@ -8485,6 +8898,21 @@ function validateUsageLimits(limits, site) {
|
|
|
8485
8898
|
if (limits.toolBudgetNotices !== void 0 && typeof limits.toolBudgetNotices !== "boolean") throw new ConfigError(`${site}.toolBudgetNotices must be a boolean; got ${typeof limits.toolBudgetNotices}`);
|
|
8486
8899
|
if (limits.maxRepeatedToolSignature !== void 0) requirePositiveInteger(limits.maxRepeatedToolSignature, `${site}.maxRepeatedToolSignature`);
|
|
8487
8900
|
if (limits.maxNoNewEvidenceCalls !== void 0) requirePositiveInteger(limits.maxNoNewEvidenceCalls, `${site}.maxNoNewEvidenceCalls`);
|
|
8901
|
+
if (limits.maxCallsPerTool !== void 0) {
|
|
8902
|
+
const caps = limits.maxCallsPerTool;
|
|
8903
|
+
if (typeof caps !== "object" || caps === null || Array.isArray(caps)) throw new ConfigError(`${site}.maxCallsPerTool must be a record of per-tool caps`);
|
|
8904
|
+
for (const [name, cap] of Object.entries(caps)) requireNonNegativeInteger(cap, `${site}.maxCallsPerTool['${name}']`);
|
|
8905
|
+
}
|
|
8906
|
+
if (limits.toolUnits !== void 0) {
|
|
8907
|
+
const units = limits.toolUnits;
|
|
8908
|
+
if (typeof units !== "object" || units === null || Array.isArray(units)) throw new ConfigError(`${site}.toolUnits must be { max, costs? }`);
|
|
8909
|
+
const { max, costs } = units;
|
|
8910
|
+
requirePositiveInteger(max, `${site}.toolUnits.max`);
|
|
8911
|
+
if (costs !== void 0) {
|
|
8912
|
+
if (typeof costs !== "object" || costs === null || Array.isArray(costs)) throw new ConfigError(`${site}.toolUnits.costs must be a record of per-tool costs`);
|
|
8913
|
+
for (const [name, cost] of Object.entries(costs)) requireNonNegativeInteger(cost, `${site}.toolUnits.costs['${name}']`);
|
|
8914
|
+
}
|
|
8915
|
+
}
|
|
8488
8916
|
}
|
|
8489
8917
|
//#endregion
|
|
8490
8918
|
//#region src/runtime/model-retry.ts
|
|
@@ -9019,7 +9447,7 @@ function formatRePrompt(issues, attempt, maxAttempts) {
|
|
|
9019
9447
|
const GUARD_DOCS_URL = "https://docs.rulvar.com/guide/agents#exploration-guards";
|
|
9020
9448
|
/** True when any exploration guard field asks for tracking. */
|
|
9021
9449
|
function explorationTrackingEnabled(limits) {
|
|
9022
|
-
return limits.maxRepeatedToolSignature !== void 0 || limits.maxNoNewEvidenceCalls !== void 0 || limits.toolBudgetNotices === true;
|
|
9450
|
+
return limits.maxRepeatedToolSignature !== void 0 || limits.maxNoNewEvidenceCalls !== void 0 || limits.toolBudgetNotices === true || limits.maxCallsPerTool !== void 0 || limits.toolUnits !== void 0;
|
|
9023
9451
|
}
|
|
9024
9452
|
function digestOf$1(value) {
|
|
9025
9453
|
try {
|
|
@@ -9038,6 +9466,8 @@ var ExplorationGuard = class {
|
|
|
9038
9466
|
repeated = 0;
|
|
9039
9467
|
duplicateResults = 0;
|
|
9040
9468
|
denied = 0;
|
|
9469
|
+
deniedToolCap = 0;
|
|
9470
|
+
unitsUsed = 0;
|
|
9041
9471
|
unserializableSeq = 0;
|
|
9042
9472
|
constructor(config) {
|
|
9043
9473
|
this.config = config;
|
|
@@ -9075,10 +9505,25 @@ var ExplorationGuard = class {
|
|
|
9075
9505
|
}
|
|
9076
9506
|
}
|
|
9077
9507
|
/**
|
|
9078
|
-
* The pre-dispatch verdict: denies the call that would exceed
|
|
9079
|
-
*
|
|
9508
|
+
* The pre-dispatch verdict: denies the call that would exceed its
|
|
9509
|
+
* tool's maxCallsPerTool cap, then the call that would exceed
|
|
9510
|
+
* maxRepeatedToolSignature executions of the same signature. A denial
|
|
9511
|
+
* never consumes maxToolCalls or tool units.
|
|
9080
9512
|
*/
|
|
9081
9513
|
beforeExecute(name, args) {
|
|
9514
|
+
const cap = this.config.maxCallsPerTool?.[name];
|
|
9515
|
+
if (cap !== void 0) {
|
|
9516
|
+
const executions = this.byTool.get(name) ?? 0;
|
|
9517
|
+
if (executions >= cap) {
|
|
9518
|
+
this.deniedToolCap += 1;
|
|
9519
|
+
return {
|
|
9520
|
+
deny: true,
|
|
9521
|
+
guard: "per-tool-cap",
|
|
9522
|
+
executions,
|
|
9523
|
+
reason: `exploration guard: '${name}' already executed ${String(executions)} time(s) this invocation (maxCallsPerTool ${String(cap)}). Use what you have or a different tool (${GUARD_DOCS_URL}).`
|
|
9524
|
+
};
|
|
9525
|
+
}
|
|
9526
|
+
}
|
|
9082
9527
|
const max = this.config.maxRepeatedToolSignature;
|
|
9083
9528
|
if (max === void 0) return { deny: false };
|
|
9084
9529
|
const executions = this.signatureExecutions.get(this.signatureOf(name, args)) ?? 0;
|
|
@@ -9086,6 +9531,7 @@ var ExplorationGuard = class {
|
|
|
9086
9531
|
this.denied += 1;
|
|
9087
9532
|
return {
|
|
9088
9533
|
deny: true,
|
|
9534
|
+
guard: "repeated-signature",
|
|
9089
9535
|
executions,
|
|
9090
9536
|
reason: `exploration guard: this exact '${name}' call already executed ${String(executions)} time(s) this invocation (maxRepeatedToolSignature ${String(max)}). Reuse the earlier result or change the arguments (${GUARD_DOCS_URL}).`
|
|
9091
9537
|
};
|
|
@@ -9103,6 +9549,7 @@ var ExplorationGuard = class {
|
|
|
9103
9549
|
recordExecution(name, args, result, successful) {
|
|
9104
9550
|
this.executed += 1;
|
|
9105
9551
|
this.byTool.set(name, (this.byTool.get(name) ?? 0) + 1);
|
|
9552
|
+
if (this.config.toolUnits !== void 0) this.unitsUsed += this.config.toolUnits.costs?.[name] ?? 1;
|
|
9106
9553
|
const signature = this.signatureOf(name, args);
|
|
9107
9554
|
const prior = this.signatureExecutions.get(signature) ?? 0;
|
|
9108
9555
|
if (prior > 0) this.repeated += 1;
|
|
@@ -9119,6 +9566,14 @@ var ExplorationGuard = class {
|
|
|
9119
9566
|
const max = this.config.maxNoNewEvidenceCalls;
|
|
9120
9567
|
return max !== void 0 && this.noNewEvidenceStreak >= max;
|
|
9121
9568
|
}
|
|
9569
|
+
/**
|
|
9570
|
+
* True once the spent tool units reached the weighted budget: the
|
|
9571
|
+
* loop's pre-dispatch check, mirroring maxToolCalls (terminal 'limit',
|
|
9572
|
+
* paid partial work). Never true without toolUnits configured.
|
|
9573
|
+
*/
|
|
9574
|
+
unitsExhausted() {
|
|
9575
|
+
return this.config.toolUnits !== void 0 && this.unitsUsed >= this.config.toolUnits.max;
|
|
9576
|
+
}
|
|
9122
9577
|
/** The abort message for a tripped no-new-evidence guard. */
|
|
9123
9578
|
describeTrip() {
|
|
9124
9579
|
return `exploration guard: ${String(this.noNewEvidenceStreak)} consecutive tool calls returned no new evidence (maxNoNewEvidenceCalls ${String(this.config.maxNoNewEvidenceCalls ?? this.noNewEvidenceStreak)}; every result was already seen this invocation). The executed work is kept; narrow the scope, vary the queries, or raise the limit (${GUARD_DOCS_URL}).`;
|
|
@@ -9133,7 +9588,9 @@ var ExplorationGuard = class {
|
|
|
9133
9588
|
repeatedCalls: this.repeated,
|
|
9134
9589
|
duplicateResultCalls: this.duplicateResults,
|
|
9135
9590
|
deniedRepeats: this.denied,
|
|
9136
|
-
byTool
|
|
9591
|
+
byTool,
|
|
9592
|
+
...this.config.maxCallsPerTool === void 0 ? {} : { deniedToolCap: this.deniedToolCap },
|
|
9593
|
+
...this.config.toolUnits === void 0 ? {} : { toolUnitsUsed: this.unitsUsed }
|
|
9137
9594
|
};
|
|
9138
9595
|
}
|
|
9139
9596
|
};
|
|
@@ -9743,6 +10200,10 @@ async function runAgent(options) {
|
|
|
9743
10200
|
parts,
|
|
9744
10201
|
limitHit: true
|
|
9745
10202
|
};
|
|
10203
|
+
if (guard !== void 0 && guard.unitsExhausted()) return {
|
|
10204
|
+
parts,
|
|
10205
|
+
limitHit: true
|
|
10206
|
+
};
|
|
9746
10207
|
const def = runtime.defs.find((candidate) => candidate.name === call.name);
|
|
9747
10208
|
events?.emit({
|
|
9748
10209
|
type: "tool:start",
|
|
@@ -9898,11 +10359,11 @@ async function runAgent(options) {
|
|
|
9898
10359
|
toolName: gatedCall.name,
|
|
9899
10360
|
outcome: "denied",
|
|
9900
10361
|
durationMs: now() - gateStartedAt,
|
|
9901
|
-
guard:
|
|
10362
|
+
guard: guardVerdict.guard
|
|
9902
10363
|
});
|
|
9903
10364
|
parts.push(errorPart(call, {
|
|
9904
10365
|
error: guardVerdict.reason,
|
|
9905
|
-
guard:
|
|
10366
|
+
guard: guardVerdict.guard
|
|
9906
10367
|
}));
|
|
9907
10368
|
continue;
|
|
9908
10369
|
}
|
|
@@ -10068,12 +10529,74 @@ async function runAgent(options) {
|
|
|
10068
10529
|
const target = site.chain[site.cursor.index] ?? site.chain[0];
|
|
10069
10530
|
let tries = 0;
|
|
10070
10531
|
inner: for (;;) {
|
|
10532
|
+
let reservationId;
|
|
10533
|
+
const quotaDeniedOutcome = (denial) => ({
|
|
10534
|
+
turn: {
|
|
10535
|
+
text: "",
|
|
10536
|
+
toolCalls: []
|
|
10537
|
+
},
|
|
10538
|
+
usage: ZERO_USAGE$1,
|
|
10539
|
+
reported: ZERO_USAGE$1,
|
|
10540
|
+
usageApprox: false,
|
|
10541
|
+
quotaDenied: true,
|
|
10542
|
+
wireError: {
|
|
10543
|
+
code: denial.infrastructure === void 0 ? "rate-limit" : "quota-limiter",
|
|
10544
|
+
message: denial.infrastructure ?? `the shared quota limiter denied ${target.resolved.ref}` + (denial.reason === void 0 ? "" : `: ${denial.reason}`),
|
|
10545
|
+
retryable: true,
|
|
10546
|
+
data: {
|
|
10547
|
+
kind: denial.infrastructure === void 0 ? "rate-limit" : "transport",
|
|
10548
|
+
source: "quota-limiter",
|
|
10549
|
+
...denial.retryAfterMs === void 0 ? {} : { retryAfterMs: denial.retryAfterMs },
|
|
10550
|
+
...denial.reason === void 0 ? {} : { reason: denial.reason }
|
|
10551
|
+
}
|
|
10552
|
+
}
|
|
10553
|
+
});
|
|
10554
|
+
const dispatchWithQuota = async (quota) => {
|
|
10555
|
+
const req = site.requestFor(target);
|
|
10556
|
+
let decision;
|
|
10557
|
+
try {
|
|
10558
|
+
decision = await quota.reserve({
|
|
10559
|
+
provider: target.adapter.id,
|
|
10560
|
+
model: target.resolved.model,
|
|
10561
|
+
estimate: {
|
|
10562
|
+
requests: 1,
|
|
10563
|
+
inputTokens: estimateInputTokens(req.messages),
|
|
10564
|
+
...req.maxOutputTokens === void 0 ? {} : { maxOutputTokens: req.maxOutputTokens }
|
|
10565
|
+
}
|
|
10566
|
+
});
|
|
10567
|
+
} catch (thrown) {
|
|
10568
|
+
const detail = thrown instanceof Error ? thrown.message : String(thrown);
|
|
10569
|
+
if (quota.onLimiterError === "allow") {
|
|
10570
|
+
events?.emit({
|
|
10571
|
+
type: "log",
|
|
10572
|
+
level: "warn",
|
|
10573
|
+
msg: `the shared quota limiter failed; dispatching ${target.resolved.ref} without a reservation (onLimiterError 'allow'): ${detail}`
|
|
10574
|
+
});
|
|
10575
|
+
return streamTurn(target.adapter, req, site.streamOptionsFor(target));
|
|
10576
|
+
}
|
|
10577
|
+
return quotaDeniedOutcome({ infrastructure: `the shared quota limiter failed (onLimiterError 'deny'): ${detail}` });
|
|
10578
|
+
}
|
|
10579
|
+
if (!decision.granted) return quotaDeniedOutcome(decision);
|
|
10580
|
+
reservationId = decision.reservationId;
|
|
10581
|
+
return streamTurn(target.adapter, req, site.streamOptionsFor(target));
|
|
10582
|
+
};
|
|
10071
10583
|
const dispatch = () => {
|
|
10072
10584
|
const aborted = abortKind();
|
|
10073
|
-
|
|
10585
|
+
if (aborted !== void 0) return Promise.resolve(abortedOutcome(aborted));
|
|
10586
|
+
return options.quota === void 0 ? streamTurn(target.adapter, site.requestFor(target), site.streamOptionsFor(target)) : dispatchWithQuota(options.quota);
|
|
10074
10587
|
};
|
|
10075
10588
|
const outcome = await (options.providerSlot === void 0 ? dispatch() : options.providerSlot(target.adapter.id, dispatch, options.signal));
|
|
10076
|
-
|
|
10589
|
+
if (reservationId !== void 0 && options.quota !== void 0) try {
|
|
10590
|
+
await options.quota.reconcile(reservationId, outcome.usage);
|
|
10591
|
+
} catch (thrown) {
|
|
10592
|
+
const detail = thrown instanceof Error ? thrown.message : String(thrown);
|
|
10593
|
+
events?.emit({
|
|
10594
|
+
type: "log",
|
|
10595
|
+
level: "warn",
|
|
10596
|
+
msg: `the shared quota limiter failed to reconcile a reservation: ${detail}`
|
|
10597
|
+
});
|
|
10598
|
+
}
|
|
10599
|
+
if (outcome.quotaDenied !== true) recordUsage(outcome.usage, outcome.reported, target.adapter.id, target.resolved.ref, site.role, outcome.usageViolation);
|
|
10077
10600
|
tries += 1;
|
|
10078
10601
|
const retryClass = outcome.aborted === "idle" ? "transport" : outcome.wireError === void 0 ? void 0 : retryClassOf(outcome.wireError);
|
|
10079
10602
|
if (retryClass === void 0) return {
|
|
@@ -10751,6 +11274,8 @@ async function runAgent(options) {
|
|
|
10751
11274
|
}
|
|
10752
11275
|
endPhase(extractPhase, phaseOutcome(), extractServed);
|
|
10753
11276
|
}
|
|
11277
|
+
const limitPartial = status === "limit" ? latestProgressReport(messages) : void 0;
|
|
11278
|
+
if (limitPartial !== void 0) await saveBoundary();
|
|
10754
11279
|
let transcriptRef = "";
|
|
10755
11280
|
if (options.transcript !== void 0) {
|
|
10756
11281
|
transcriptRef = options.transcript.mintRef();
|
|
@@ -10773,6 +11298,7 @@ async function runAgent(options) {
|
|
|
10773
11298
|
if (abortClass !== void 0) result.abortClass = abortClass;
|
|
10774
11299
|
if (errorMessage !== void 0) result.errorMessage = errorMessage;
|
|
10775
11300
|
if (guard !== void 0) result.exploration = guard.summary(toolCallsUsed);
|
|
11301
|
+
if (limitPartial !== void 0) result.partial = limitPartial;
|
|
10776
11302
|
if (usageApprox) result.usageApprox = true;
|
|
10777
11303
|
if (transportRetries > 0) result.transportRetries = transportRetries;
|
|
10778
11304
|
return result;
|
|
@@ -11744,7 +12270,13 @@ const WAKE_SUMMARY_RENDER_BUDGET_CHARS = 400;
|
|
|
11744
12270
|
* spawn ordinal; the LLM distillation upgrade is M7 territory).
|
|
11745
12271
|
*/
|
|
11746
12272
|
function summarizeOutput(result) {
|
|
11747
|
-
|
|
12273
|
+
let raw;
|
|
12274
|
+
if (result.status === "ok") raw = typeof result.output === "string" ? result.output : JSON.stringify(result.output ?? null);
|
|
12275
|
+
else {
|
|
12276
|
+
raw = result.errorMessage ?? `terminal status ${result.status}`;
|
|
12277
|
+
if (result.partial !== void 0) raw = `${raw}; partial: ${JSON.stringify(result.partial)}`;
|
|
12278
|
+
}
|
|
12279
|
+
return truncateToBudget(raw, 400);
|
|
11748
12280
|
}
|
|
11749
12281
|
/** Folds one settled child into its digest (spawn-ordinal ordering is the caller's). */
|
|
11750
12282
|
function digestOf(record, result) {
|
|
@@ -12617,6 +13149,10 @@ function createCtx(internals, rootWorkflow) {
|
|
|
12617
13149
|
const checkpoint = blob === null ? void 0 : decodeCheckpoint(blob);
|
|
12618
13150
|
if (checkpoint !== void 0) {
|
|
12619
13151
|
result.turns = checkpoint.turns;
|
|
13152
|
+
if (result.status === "limit") {
|
|
13153
|
+
const partialReport = latestProgressReport(checkpoint.messages);
|
|
13154
|
+
if (partialReport !== void 0) result.partial = partialReport;
|
|
13155
|
+
}
|
|
12620
13156
|
replayedToolResults = checkpoint.messages.filter((msg) => msg.role === "tool").flatMap((msg) => msg.parts).filter((part) => part.type === "tool-result").map((part) => ({
|
|
12621
13157
|
name: part.name,
|
|
12622
13158
|
isError: part.isError === true
|
|
@@ -12995,6 +13531,18 @@ function createCtx(internals, rootWorkflow) {
|
|
|
12995
13531
|
if (profile?.compaction !== void 0) runAgentOptions.compaction = profile.compaction;
|
|
12996
13532
|
if (loopFallbacks.length > 0) runAgentOptions.fallbacks = loopFallbacks;
|
|
12997
13533
|
if (retryPolicy !== void 0) runAgentOptions.retry = { policy: retryPolicy };
|
|
13534
|
+
if (internals.quota !== void 0) {
|
|
13535
|
+
const quota = internals.quota;
|
|
13536
|
+
runAgentOptions.quota = {
|
|
13537
|
+
reserve: (request) => quota.limiter.reserve({
|
|
13538
|
+
...request,
|
|
13539
|
+
runId: internals.runId,
|
|
13540
|
+
...quota.tenant === void 0 ? {} : { tenant: quota.tenant }
|
|
13541
|
+
}),
|
|
13542
|
+
reconcile: (reservationId, usage) => quota.limiter.reconcile(reservationId, usage),
|
|
13543
|
+
onLimiterError: quota.onLimiterError
|
|
13544
|
+
};
|
|
13545
|
+
}
|
|
12998
13546
|
if (internals.providerLimiter !== void 0) {
|
|
12999
13547
|
const limiter = internals.providerLimiter;
|
|
13000
13548
|
runAgentOptions.providerSlot = (key, fn, signal) => limiter.withSlot(key, fn, () => internals.events.emit({
|
|
@@ -13817,7 +14365,14 @@ function pageOf(content, rawOffset, rawMaxChars) {
|
|
|
13817
14365
|
}
|
|
13818
14366
|
/** The serialized full result of a settled child: the raw string, or JSON. */
|
|
13819
14367
|
function serializeChildOutput(result) {
|
|
13820
|
-
if (result.status !== "ok")
|
|
14368
|
+
if (result.status !== "ok") {
|
|
14369
|
+
const base = result.errorMessage ?? `terminal status ${result.status}`;
|
|
14370
|
+
if (result.partial !== void 0) return JSON.stringify({
|
|
14371
|
+
error: base,
|
|
14372
|
+
partial: result.partial
|
|
14373
|
+
});
|
|
14374
|
+
return base;
|
|
14375
|
+
}
|
|
13821
14376
|
return typeof result.output === "string" ? result.output : JSON.stringify(result.output ?? null);
|
|
13822
14377
|
}
|
|
13823
14378
|
/**
|
|
@@ -13839,6 +14394,8 @@ function validateOrchestrateOptions(opts) {
|
|
|
13839
14394
|
const minSuccessful = typeof policy === "object" && policy !== null && !Array.isArray(policy) ? policy.minSuccessful : void 0;
|
|
13840
14395
|
if (policy !== "all-ok" && minSuccessful === void 0) throw new ConfigError(`orchestrate acceptance.childPolicy must be 'all-ok' or { minSuccessful: N }; got ${JSON.stringify(policy)}`);
|
|
13841
14396
|
if (policy !== "all-ok") requirePositiveInteger(minSuccessful, "orchestrate acceptance.childPolicy.minSuccessful");
|
|
14397
|
+
const acceptPartial = opts.acceptance.acceptPartialChildren;
|
|
14398
|
+
if (acceptPartial !== void 0 && typeof acceptPartial !== "boolean") throw new ConfigError(`orchestrate acceptance.acceptPartialChildren must be a boolean; got ${typeof acceptPartial}`);
|
|
13842
14399
|
}
|
|
13843
14400
|
if (opts.finishValidation !== void 0) {
|
|
13844
14401
|
const fv = opts.finishValidation;
|
|
@@ -13903,6 +14460,16 @@ function finishValidationPromptLines(spec) {
|
|
|
13903
14460
|
return [`The host validates every finish({ result }) with deterministic validators: ${names}.`, "A rejected finish returns the failure reasons as the tool error result; repair the result and call finish again. " + (repairs === 0 ? "No repair attempt is granted: the first rejected finish fails the run." : repairs === 1 ? "At most one repair attempt is granted before the run fails." : `At most ${String(repairs)} repair attempts are granted before the run fails.`)];
|
|
13904
14461
|
}
|
|
13905
14462
|
/**
|
|
14463
|
+
* The partial-salvage contract rides the PROMPT exactly like finish
|
|
14464
|
+
* validation (RV-210 close-out): present only when
|
|
14465
|
+
* acceptance.acceptPartialChildren is set, so every other configuration
|
|
14466
|
+
* keeps byte-identical coordination prompts.
|
|
14467
|
+
*/
|
|
14468
|
+
function acceptancePromptLines(acceptance) {
|
|
14469
|
+
if (acceptance?.acceptPartialChildren !== true) return [];
|
|
14470
|
+
return ["Partial salvage is on: a child that ends at its limit AFTER recording progress with report_progress counts as a partial success for acceptance; its digest carries the partial and get_child_result (when enabled) pages the full report. When the gap matters, respawn a NARROWED child carrying the partial instead of repeating the task."];
|
|
14471
|
+
}
|
|
14472
|
+
/**
|
|
13906
14473
|
* Resolves per-spawn dispatch options against the engine registries
|
|
13907
14474
|
* (registered SchemaSpec and tool profile names; M7-T05). An
|
|
13908
14475
|
* unknown ref is a typed ConfigError, surfaced as a tool error to the
|
|
@@ -15232,7 +15799,11 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
15232
15799
|
const priorRejection = validationDecisions().find((decision) => decision.verdict === "rejected");
|
|
15233
15800
|
if (priorRejection !== void 0) throw finishValidationError(priorRejection);
|
|
15234
15801
|
}
|
|
15235
|
-
const promptLines = [
|
|
15802
|
+
const promptLines = [
|
|
15803
|
+
...extension?.promptLines?.() ?? [],
|
|
15804
|
+
...finishValidationPromptLines(validationSpec),
|
|
15805
|
+
...acceptancePromptLines(opts?.acceptance)
|
|
15806
|
+
];
|
|
15236
15807
|
const result = await runtime.runInScope(orchestratorState, () => ctx.agent(orchestratorPrompt(goal, opts?.maxSpawns, promptLines.length === 0 ? void 0 : promptLines), agentOpts));
|
|
15237
15808
|
const liveTermination = extensionTermination;
|
|
15238
15809
|
if (liveTermination !== void 0) throw liveTermination;
|
|
@@ -15248,21 +15819,32 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
15248
15819
|
else {
|
|
15249
15820
|
const childStatusCounts = {};
|
|
15250
15821
|
const degradedReasons = [];
|
|
15822
|
+
const salvaged = [];
|
|
15823
|
+
let hardDegraded = 0;
|
|
15824
|
+
const acceptPartial = opts.acceptance.acceptPartialChildren === true;
|
|
15251
15825
|
const sortedRecords = [...records.values()].sort((a, b) => a.spawnOrdinal - b.spawnOrdinal);
|
|
15252
15826
|
for (const record of sortedRecords) {
|
|
15253
15827
|
const status = record.settled?.status ?? "running";
|
|
15254
15828
|
childStatusCounts[status] = (childStatusCounts[status] ?? 0) + 1;
|
|
15255
|
-
if (status
|
|
15829
|
+
if (status === "ok") continue;
|
|
15830
|
+
if (acceptPartial && status === "limit" && record.settled?.partial !== void 0) {
|
|
15831
|
+
salvaged.push(record.nodeId);
|
|
15832
|
+
degradedReasons.push(`child ${record.nodeId} accepted as partial (settled 'limit' with a structured partial)`);
|
|
15833
|
+
continue;
|
|
15834
|
+
}
|
|
15835
|
+
hardDegraded += 1;
|
|
15836
|
+
degradedReasons.push(status === "running" ? `child ${record.nodeId} was still running when finish validated` : `child ${record.nodeId} settled '${status}'`);
|
|
15256
15837
|
}
|
|
15257
15838
|
const childPolicy = opts.acceptance.childPolicy;
|
|
15258
|
-
const accepted = childPolicy === "all-ok" ?
|
|
15839
|
+
const accepted = childPolicy === "all-ok" ? hardDegraded === 0 : (childStatusCounts.ok ?? 0) + salvaged.length >= childPolicy.minSuccessful;
|
|
15259
15840
|
decision = {
|
|
15260
15841
|
decisionType: "orchestrator_acceptance",
|
|
15261
15842
|
verdict: accepted ? "accepted" : "rejected",
|
|
15262
15843
|
completion: !accepted ? "rejected" : degradedReasons.length === 0 ? "complete" : "partial",
|
|
15263
15844
|
childPolicy,
|
|
15264
15845
|
childStatusCounts,
|
|
15265
|
-
degradedReasons
|
|
15846
|
+
degradedReasons,
|
|
15847
|
+
...salvaged.length === 0 ? {} : { salvagedPartialChildren: salvaged }
|
|
15266
15848
|
};
|
|
15267
15849
|
await internals.replayer.appendSinglePhase({
|
|
15268
15850
|
scope: callingState.scope,
|
|
@@ -15281,14 +15863,16 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
15281
15863
|
completion: "rejected",
|
|
15282
15864
|
childPolicy: decision.childPolicy,
|
|
15283
15865
|
childStatusCounts: decision.childStatusCounts,
|
|
15284
|
-
degradedReasons: decision.degradedReasons
|
|
15866
|
+
degradedReasons: decision.degradedReasons,
|
|
15867
|
+
...decision.salvagedPartialChildren === void 0 ? {} : { salvagedPartialChildren: decision.salvagedPartialChildren }
|
|
15285
15868
|
} });
|
|
15286
15869
|
}
|
|
15287
15870
|
return {
|
|
15288
15871
|
result: await runSynthesis(result.output),
|
|
15289
15872
|
completion: decision.completion,
|
|
15290
15873
|
childStatusCounts: decision.childStatusCounts,
|
|
15291
|
-
degradedReasons: decision.degradedReasons
|
|
15874
|
+
degradedReasons: decision.degradedReasons,
|
|
15875
|
+
...decision.salvagedPartialChildren === void 0 ? {} : { salvagedPartialChildren: decision.salvagedPartialChildren }
|
|
15292
15876
|
};
|
|
15293
15877
|
});
|
|
15294
15878
|
}
|
|
@@ -16030,6 +16614,12 @@ function createEngine(options) {
|
|
|
16030
16614
|
if (profile.compaction?.threshold !== void 0) requireFraction(profile.compaction.threshold, `createEngine defaults.profiles['${name}'].compaction.threshold`);
|
|
16031
16615
|
}
|
|
16032
16616
|
validateDeterminismConfig(options.determinism);
|
|
16617
|
+
validateEngineQuotaConfig(options.quota);
|
|
16618
|
+
const quotaRuntime = options.quota === void 0 ? void 0 : {
|
|
16619
|
+
limiter: options.quota.limiter,
|
|
16620
|
+
...options.quota.tenant === void 0 ? {} : { tenant: options.quota.tenant },
|
|
16621
|
+
onLimiterError: options.quota.onLimiterError ?? "deny"
|
|
16622
|
+
};
|
|
16033
16623
|
const knowledgeStore = options.stores?.modelKnowledge;
|
|
16034
16624
|
const knowledge = knowledgeStore === void 0 ? void 0 : { current: () => knowledgeStore.current() };
|
|
16035
16625
|
const runner = new InProcessRunner(options.onEscalation === void 0 ? void 0 : { onEscalation: options.onEscalation });
|
|
@@ -16136,6 +16726,7 @@ function createEngine(options) {
|
|
|
16136
16726
|
admission,
|
|
16137
16727
|
semaphore: new Semaphore(options.concurrency?.perRun ?? 12),
|
|
16138
16728
|
providerLimiter,
|
|
16729
|
+
...quotaRuntime === void 0 ? {} : { quota: quotaRuntime },
|
|
16139
16730
|
...options.pricing === void 0 ? {} : { pricingVersion: options.pricing.pricingVersion },
|
|
16140
16731
|
...options.budgetDefaults?.flatReserveUsd === void 0 ? {} : { flatReserveUsd: options.budgetDefaults.flatReserveUsd },
|
|
16141
16732
|
...defaults.roleFloors === void 0 ? {} : { floors: defaults.roleFloors },
|
|
@@ -16810,4 +17401,4 @@ function createSandboxBridge(ctx, options) {
|
|
|
16810
17401
|
};
|
|
16811
17402
|
}
|
|
16812
17403
|
//#endregion
|
|
16813
|
-
export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GitWorktreeProvider, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, PlanInvariantError, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
|
17404
|
+
export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GitWorktreeProvider, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, PlanInvariantError, QUOTA_WINDOW_MS, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, implementationAgentProfile, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|