@rulvar/core 1.6.0 → 1.7.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 +84 -5
- package/dist/index.js +232 -54
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -608,6 +608,23 @@ interface UsageSlice {
|
|
|
608
608
|
usage: Usage;
|
|
609
609
|
}
|
|
610
610
|
/**
|
|
611
|
+
* Cost-attribution facts a live run knows at settlement and a pure
|
|
612
|
+
* journal fold cannot re-derive: the innermost phase name at the call
|
|
613
|
+
* site, the agent profile, the primary invocation role, the budget
|
|
614
|
+
* account the call debited, and whether the dispatch spent the
|
|
615
|
+
* orchestrator finalize reserve. Policy, never identity, exactly like
|
|
616
|
+
* usageByModel: none of it enters the content key, and entries written
|
|
617
|
+
* before the field shipped fold under the documented fallback buckets
|
|
618
|
+
* (empty phase, 'unknown' agent type, role 'loop').
|
|
619
|
+
*/
|
|
620
|
+
interface CostAttributionFacts {
|
|
621
|
+
phase?: string;
|
|
622
|
+
agentType?: string;
|
|
623
|
+
role?: InvocationRole;
|
|
624
|
+
budgetAccount?: string;
|
|
625
|
+
finalizeReserve?: boolean;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
611
628
|
* The per-model slices of a terminal entry: the recorded split when the
|
|
612
629
|
* call spanned several models, else the whole usage attributed to
|
|
613
630
|
* `servedBy`. The fallback is what makes every journal written before the
|
|
@@ -669,6 +686,13 @@ type JournalEntry = {
|
|
|
669
686
|
* Policy, never identity: it does not enter the content key.
|
|
670
687
|
*/
|
|
671
688
|
usageByModel?: UsageSlice[];
|
|
689
|
+
/**
|
|
690
|
+
* Terminal usage-bearing entries: the attribution facts behind the
|
|
691
|
+
* CostReport breakdowns, so a pure journal fold reproduces the live
|
|
692
|
+
* report byte for byte on replay. Policy, never identity, exactly
|
|
693
|
+
* like usageByModel.
|
|
694
|
+
*/
|
|
695
|
+
costAttribution?: CostAttributionFacts;
|
|
672
696
|
transcriptRef?: string;
|
|
673
697
|
checkpointRef?: string;
|
|
674
698
|
/**
|
|
@@ -2083,6 +2107,8 @@ interface TerminalPatch {
|
|
|
2083
2107
|
servedBy?: ModelRef;
|
|
2084
2108
|
/** Set only when the call spanned several serving models; see JournalEntry. */
|
|
2085
2109
|
usageByModel?: UsageSlice[];
|
|
2110
|
+
/** Attribution facts behind the CostReport breakdowns; see JournalEntry. */
|
|
2111
|
+
costAttribution?: CostAttributionFacts;
|
|
2086
2112
|
transcriptRef?: string;
|
|
2087
2113
|
checkpointRef?: string;
|
|
2088
2114
|
/** Terminal agent entries: Artifact list. */
|
|
@@ -3348,6 +3374,26 @@ interface BudgetAccountView {
|
|
|
3348
3374
|
parentScope?: string;
|
|
3349
3375
|
}
|
|
3350
3376
|
/**
|
|
3377
|
+
* Why a ceiling error ended the work: the first closed account walking
|
|
3378
|
+
* from the debited scope toward the root, plus the root state, so the
|
|
3379
|
+
* outward message can name WHICH ceiling actually crossed instead of
|
|
3380
|
+
* blaming the run ceiling for every crossing.
|
|
3381
|
+
*/
|
|
3382
|
+
interface BudgetExhaustionDiagnostics {
|
|
3383
|
+
crossed?: {
|
|
3384
|
+
scope: string;
|
|
3385
|
+
source: "root" | "orchestrator-cap" | "child-account";
|
|
3386
|
+
ceilingUsd: number;
|
|
3387
|
+
spentUsd: number;
|
|
3388
|
+
committedReserveUsd: number;
|
|
3389
|
+
finalizeReserveUsd: number;
|
|
3390
|
+
};
|
|
3391
|
+
root: {
|
|
3392
|
+
ceilingUsd?: number;
|
|
3393
|
+
spentUsd: number;
|
|
3394
|
+
};
|
|
3395
|
+
}
|
|
3396
|
+
/**
|
|
3351
3397
|
* The per-run budget account tree. All spend accounting is per instance;
|
|
3352
3398
|
* the journal remains the durable source (the root is seeded by the
|
|
3353
3399
|
* ledger fold on resume, M2; sub-account reserves are recovered from
|
|
@@ -3395,7 +3441,20 @@ declare class RunBudget {
|
|
|
3395
3441
|
parentScope?: string;
|
|
3396
3442
|
ceilingUsd?: number;
|
|
3397
3443
|
finalizeReserveUsd?: number;
|
|
3444
|
+
kind?: "orchestrator-cap";
|
|
3398
3445
|
}): void;
|
|
3446
|
+
/**
|
|
3447
|
+
* The diagnostic projection behind a ceiling error: the first CLOSED
|
|
3448
|
+
* account (projected commitments included, exactly the layer-1
|
|
3449
|
+
* closure test) walking from `scope` toward the root, plus the root
|
|
3450
|
+
* state. 'run budget ceiling reached' under a healthy root misled the
|
|
3451
|
+
* v1.6.0 follow-up review's live probe when only a 0.18 USD
|
|
3452
|
+
* orchestrator cap had crossed under a 0.90 USD root; the message can
|
|
3453
|
+
* now name the account that actually ended the work. An unknown scope
|
|
3454
|
+
* degrades to root-only diagnostics instead of throwing: this runs on
|
|
3455
|
+
* the error path.
|
|
3456
|
+
*/
|
|
3457
|
+
exhaustionDiagnostics(scope: string): BudgetExhaustionDiagnostics;
|
|
3399
3458
|
accountView(scope: string): BudgetAccountView | undefined;
|
|
3400
3459
|
/**
|
|
3401
3460
|
* The admission remainder of one account: ceiling minus spend minus
|
|
@@ -4146,9 +4205,14 @@ type WorkflowEvent = {
|
|
|
4146
4205
|
/** Folds the per-run attribution buckets into the normative CostReport. */
|
|
4147
4206
|
declare function buildCostReport(attribution: CostAttribution, totalUsd: number): CostReport;
|
|
4148
4207
|
/**
|
|
4149
|
-
* The pure journal fold:
|
|
4150
|
-
* same summation the kernel ledger uses (terminal usage exactly
|
|
4151
|
-
* priced per servedBy, abandoned subtrees contribute zero).
|
|
4208
|
+
* The pure journal fold: the complete CostReport from terminal entries,
|
|
4209
|
+
* the same summation the kernel ledger uses (terminal usage exactly
|
|
4210
|
+
* once, priced per servedBy slice, abandoned subtrees contribute zero).
|
|
4211
|
+
* The orchestrator block folds too: spend attributed to the
|
|
4212
|
+
* orchestrator sub-account, the reserve-funded share of it, the armed
|
|
4213
|
+
* wake count, and the at-cap freeze flag from the journaled cap
|
|
4214
|
+
* decision, so a replay-only resume reproduces the block instead of
|
|
4215
|
+
* reading this process's live accounts (which a replay never charges).
|
|
4152
4216
|
*/
|
|
4153
4217
|
declare function costReportFromJournal(entries: readonly JournalEntry[], priceUsd: (servedBy: ModelRef, usage: Usage) => number | undefined): CostReport;
|
|
4154
4218
|
//#endregion
|
|
@@ -4171,7 +4235,15 @@ interface CostReport {
|
|
|
4171
4235
|
byPhase: Record<string, number>;
|
|
4172
4236
|
byAgentType: Record<string, number>;
|
|
4173
4237
|
byRole: Record<InvocationRole, number>;
|
|
4174
|
-
/**
|
|
4238
|
+
/**
|
|
4239
|
+
* All-zero with forcedFinish false in runs without a dynamic
|
|
4240
|
+
* orchestrator (or when no cap resolved, so no sub-account opened).
|
|
4241
|
+
* Folded purely from the journal: spentUsd is the priced usage of
|
|
4242
|
+
* entries debited to the orchestrator sub-account, reserveUsedUsd its
|
|
4243
|
+
* reserve-funded forced-finish share, wakes the ARMED (journaled)
|
|
4244
|
+
* wake suspensions (a wait satisfied synchronously never suspends and
|
|
4245
|
+
* is not counted), and forcedFinish the journaled at-cap decision.
|
|
4246
|
+
*/
|
|
4175
4247
|
orchestrator: {
|
|
4176
4248
|
spentUsd: number; /** spentUsd / max(totalUsd, 0.01): the epsilon-floored H-OrchShare input. */
|
|
4177
4249
|
share: number;
|
|
@@ -4852,6 +4924,13 @@ interface OrchestratorExtension {
|
|
|
4852
4924
|
* machinery (reserves, freeze) completes in M7 (DEF-7).
|
|
4853
4925
|
*/
|
|
4854
4926
|
interface OrchestratorBudgetSpec {
|
|
4927
|
+
/**
|
|
4928
|
+
* Absolute bound in USD. It never REPLACES the fraction bound:
|
|
4929
|
+
* effectiveCap = min(capUsd, (capFraction ?? 0.2) * ceiling), so an
|
|
4930
|
+
* explicit capUsd larger than the default fraction of the run ceiling
|
|
4931
|
+
* is still cut to that fraction (and a warn log says so). Pass
|
|
4932
|
+
* capFraction: 1.0 to make capUsd the sole bound.
|
|
4933
|
+
*/
|
|
4855
4934
|
capUsd?: number;
|
|
4856
4935
|
/** default 0.2; effectiveCap = min of the given bounds */
|
|
4857
4936
|
capFraction?: number;
|
|
@@ -6181,4 +6260,4 @@ interface SandboxBridge {
|
|
|
6181
6260
|
}
|
|
6182
6261
|
declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
|
|
6183
6262
|
//#endregion
|
|
6184
|
-
export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, BUDGET_ABORT_REASON, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildIdentityInput, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostReport, CreateEngineOptions, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, 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, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DerivedKey, DeriverRegistry, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINISH_SCHEMA, FINISH_TOOL_NAME, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, InvocationRole, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_DEPTH_CEILING, MatchResult, McpConfig, MechanicalGateProfile, MechanicalGateVerdict, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateOptions, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RandIdentityInput, RandPayload, RefEntryAppender, RefEntryClassification, RefusalInfo, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStatus, RuntimeEventSink, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, 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, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, 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, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
|
6263
|
+
export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, BUDGET_ABORT_REASON, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildIdentityInput, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, 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, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DerivedKey, DeriverRegistry, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINISH_SCHEMA, FINISH_TOOL_NAME, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, InvocationRole, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_DEPTH_CEILING, MatchResult, McpConfig, MechanicalGateProfile, MechanicalGateVerdict, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateOptions, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RandIdentityInput, RandPayload, RefEntryAppender, RefEntryClassification, RefusalInfo, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStatus, RuntimeEventSink, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, atCompactionThreshold, 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, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, 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, readTerminationInit, registryKeyRing, remeasureQueue, replayDisposition, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateSchemaSpec, validateTerminationLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
package/dist/index.js
CHANGED
|
@@ -5484,6 +5484,7 @@ var Replayer = class {
|
|
|
5484
5484
|
if (patch.usageApprox !== void 0) entry.usageApprox = patch.usageApprox;
|
|
5485
5485
|
if (patch.servedBy !== void 0) entry.servedBy = patch.servedBy;
|
|
5486
5486
|
if (patch.usageByModel !== void 0) entry.usageByModel = patch.usageByModel;
|
|
5487
|
+
if (patch.costAttribution !== void 0) entry.costAttribution = patch.costAttribution;
|
|
5487
5488
|
if (patch.transcriptRef !== void 0) entry.transcriptRef = patch.transcriptRef;
|
|
5488
5489
|
if (patch.checkpointRef !== void 0) entry.checkpointRef = patch.checkpointRef;
|
|
5489
5490
|
if (patch.artifacts !== void 0) entry.artifacts = toJournalValue(patch.artifacts, "terminal artifacts");
|
|
@@ -6147,19 +6148,28 @@ var FileTranscriptStore = class {
|
|
|
6147
6148
|
//#endregion
|
|
6148
6149
|
//#region src/engine/cost-report.ts
|
|
6149
6150
|
/**
|
|
6150
|
-
* CostReport builders (M5-T03).
|
|
6151
|
-
* sources, one shape:
|
|
6151
|
+
* CostReport builders (M5-T03; follow-up: one pure fold).
|
|
6152
6152
|
*
|
|
6153
|
-
*
|
|
6154
|
-
*
|
|
6155
|
-
*
|
|
6156
|
-
*
|
|
6157
|
-
*
|
|
6158
|
-
*
|
|
6159
|
-
*
|
|
6160
|
-
*
|
|
6161
|
-
*
|
|
6162
|
-
*
|
|
6153
|
+
* `costReportFromJournal` is THE report: a pure fold over terminal
|
|
6154
|
+
* entries that both the engine's settle path and stored-run inspection
|
|
6155
|
+
* (shells, `rulvar inspect`) use, so a replayed run reports the same
|
|
6156
|
+
* numbers byte for byte. Terminal entries carry their attribution facts
|
|
6157
|
+
* (`costAttribution`: phase, agent type, primary role, budget account,
|
|
6158
|
+
* finalize-reserve flag) exactly so this fold can reproduce every
|
|
6159
|
+
* breakdown without live state; entries written before the facts
|
|
6160
|
+
* shipped fold under the documented fallbacks (empty phase, 'unknown'
|
|
6161
|
+
* agent type, role 'loop').
|
|
6162
|
+
*
|
|
6163
|
+
* Inclusion policy, applied to the total and EVERY breakdown alike:
|
|
6164
|
+
* terminal usage exactly once, priced per serving slice, entries under
|
|
6165
|
+
* abandoned subtrees contribute zero (their spend is tracked separately
|
|
6166
|
+
* in the abandoned-spend ledger the orchestrator sees). Attempts that
|
|
6167
|
+
* were paid but never abandoned (a cancelled root attempt, a dangling
|
|
6168
|
+
* child) are real spend and stay included everywhere.
|
|
6169
|
+
*
|
|
6170
|
+
* `buildCostReport` folds the LIVE per-run attribution buckets around
|
|
6171
|
+
* the ledger total; it remains for hosts that accumulated their own
|
|
6172
|
+
* `CostAttribution`, but the engine no longer builds outcomes from it.
|
|
6163
6173
|
*
|
|
6164
6174
|
* Unpriced models surface in `unpriced`, never as a silent zero.
|
|
6165
6175
|
*/
|
|
@@ -6174,14 +6184,9 @@ const ROLES = [
|
|
|
6174
6184
|
function emptyByRole() {
|
|
6175
6185
|
return Object.fromEntries(ROLES.map((role) => [role, 0]));
|
|
6176
6186
|
}
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
share: 0,
|
|
6181
|
-
wakes: 0,
|
|
6182
|
-
forcedFinish: false,
|
|
6183
|
-
reserveUsedUsd: 0
|
|
6184
|
-
};
|
|
6187
|
+
/** The orchestrator sub-account naming rule of makeOrchestratorWorkflow. */
|
|
6188
|
+
function isOrchestratorAccount(scope) {
|
|
6189
|
+
return scope === "orchestrator" || scope.endsWith("/orchestrator");
|
|
6185
6190
|
}
|
|
6186
6191
|
/** Folds the per-run attribution buckets into the normative CostReport. */
|
|
6187
6192
|
function buildCostReport(attribution, totalUsd) {
|
|
@@ -6207,16 +6212,30 @@ function buildCostReport(attribution, totalUsd) {
|
|
|
6207
6212
|
};
|
|
6208
6213
|
}
|
|
6209
6214
|
/**
|
|
6210
|
-
* The pure journal fold:
|
|
6211
|
-
* same summation the kernel ledger uses (terminal usage exactly
|
|
6212
|
-
* priced per servedBy, abandoned subtrees contribute zero).
|
|
6215
|
+
* The pure journal fold: the complete CostReport from terminal entries,
|
|
6216
|
+
* the same summation the kernel ledger uses (terminal usage exactly
|
|
6217
|
+
* once, priced per servedBy slice, abandoned subtrees contribute zero).
|
|
6218
|
+
* The orchestrator block folds too: spend attributed to the
|
|
6219
|
+
* orchestrator sub-account, the reserve-funded share of it, the armed
|
|
6220
|
+
* wake count, and the at-cap freeze flag from the journaled cap
|
|
6221
|
+
* decision, so a replay-only resume reproduces the block instead of
|
|
6222
|
+
* reading this process's live accounts (which a replay never charges).
|
|
6213
6223
|
*/
|
|
6214
6224
|
function costReportFromJournal(entries, priceUsd) {
|
|
6215
6225
|
const abandonFold = buildAbandonFold(entries);
|
|
6216
6226
|
const byModel = {};
|
|
6227
|
+
const byPhase = {};
|
|
6228
|
+
const byAgentType = {};
|
|
6229
|
+
const byRole = emptyByRole();
|
|
6217
6230
|
const unpriced = [];
|
|
6218
6231
|
let totalUsd = 0;
|
|
6232
|
+
let orchestratorSpentUsd = 0;
|
|
6233
|
+
let reserveUsedUsd = 0;
|
|
6234
|
+
let wakes = 0;
|
|
6235
|
+
let forcedFinish = false;
|
|
6219
6236
|
for (const entry of entries) {
|
|
6237
|
+
if (entry.kind === "decision" && entry.value?.decisionType === "orchestrator_budget_cap") forcedFinish = true;
|
|
6238
|
+
if (entry.kind === "external" && entry.status === "suspended" && typeof entry.value?.key === "string" && (entry.value.key.startsWith("wake:") || entry.value.key.includes(":wake:"))) wakes += 1;
|
|
6220
6239
|
if (entry.kind !== "resolution" && entry.kind !== "abandon" && abandonFold.isAbandoned(entry.ref ?? entry.seq)) continue;
|
|
6221
6240
|
if (entry.status === "running" || entry.usage === void 0) continue;
|
|
6222
6241
|
const priced = priceEntryUsage(entry, priceUsd);
|
|
@@ -6226,14 +6245,30 @@ function costReportFromJournal(entries, priceUsd) {
|
|
|
6226
6245
|
});
|
|
6227
6246
|
for (const slice of priced.priced) byModel[slice.servedBy] = (byModel[slice.servedBy] ?? 0) + slice.usd;
|
|
6228
6247
|
totalUsd += priced.usd;
|
|
6248
|
+
const facts = entry.costAttribution;
|
|
6249
|
+
const phase = facts?.phase ?? "";
|
|
6250
|
+
byPhase[phase] = (byPhase[phase] ?? 0) + priced.usd;
|
|
6251
|
+
const agentType = facts?.agentType ?? "unknown";
|
|
6252
|
+
byAgentType[agentType] = (byAgentType[agentType] ?? 0) + priced.usd;
|
|
6253
|
+
byRole[facts?.role ?? "loop"] += priced.usd;
|
|
6254
|
+
if (facts?.budgetAccount !== void 0 && isOrchestratorAccount(facts.budgetAccount)) {
|
|
6255
|
+
orchestratorSpentUsd += priced.usd;
|
|
6256
|
+
if (facts.finalizeReserve === true) reserveUsedUsd += priced.usd;
|
|
6257
|
+
}
|
|
6229
6258
|
}
|
|
6230
6259
|
return {
|
|
6231
6260
|
totalUsd,
|
|
6232
6261
|
byModel,
|
|
6233
|
-
byPhase
|
|
6234
|
-
byAgentType
|
|
6235
|
-
byRole
|
|
6236
|
-
orchestrator:
|
|
6262
|
+
byPhase,
|
|
6263
|
+
byAgentType,
|
|
6264
|
+
byRole,
|
|
6265
|
+
orchestrator: {
|
|
6266
|
+
spentUsd: orchestratorSpentUsd,
|
|
6267
|
+
share: orchestratorSpentUsd / Math.max(totalUsd, .01),
|
|
6268
|
+
wakes,
|
|
6269
|
+
forcedFinish,
|
|
6270
|
+
reserveUsedUsd
|
|
6271
|
+
},
|
|
6237
6272
|
unpriced
|
|
6238
6273
|
};
|
|
6239
6274
|
}
|
|
@@ -8510,6 +8545,28 @@ async function runAgent(options) {
|
|
|
8510
8545
|
await saveBoundary();
|
|
8511
8546
|
continue loop;
|
|
8512
8547
|
}
|
|
8548
|
+
if (options.terminalTool !== void 0) {
|
|
8549
|
+
noProgress.recordTurn({ toolCalls: 0 });
|
|
8550
|
+
if (noProgress.tripped) {
|
|
8551
|
+
status = "limit";
|
|
8552
|
+
abortClass = "no-progress";
|
|
8553
|
+
agentError = {
|
|
8554
|
+
kind: "terminal",
|
|
8555
|
+
retryable: false
|
|
8556
|
+
};
|
|
8557
|
+
errorMessage = noProgress.describe();
|
|
8558
|
+
break;
|
|
8559
|
+
}
|
|
8560
|
+
messages.push({
|
|
8561
|
+
role: "user",
|
|
8562
|
+
parts: [{
|
|
8563
|
+
type: "text",
|
|
8564
|
+
text: outcome.finish?.reason === "max-tokens" ? `The turn was cut at the output token limit before any tool call. Be brief and call the '${options.terminalTool.name}' tool now; plain text is not a valid completion.` : `The turn ended without a tool call. Call the '${options.terminalTool.name}' tool to complete; plain text is not a valid completion.`
|
|
8565
|
+
}]
|
|
8566
|
+
});
|
|
8567
|
+
await saveBoundary();
|
|
8568
|
+
continue loop;
|
|
8569
|
+
}
|
|
8513
8570
|
if (options.schema === void 0) {
|
|
8514
8571
|
output = outcome.turn.text;
|
|
8515
8572
|
break;
|
|
@@ -8942,8 +8999,43 @@ var RunBudget = class {
|
|
|
8942
8999
|
controller: new AbortController()
|
|
8943
9000
|
};
|
|
8944
9001
|
if (options.ceilingUsd !== void 0) account.ceilingUsd = options.ceilingUsd;
|
|
9002
|
+
if (options.kind !== void 0) account.kind = options.kind;
|
|
8945
9003
|
this.accounts.set(scope, account);
|
|
8946
9004
|
}
|
|
9005
|
+
/**
|
|
9006
|
+
* The diagnostic projection behind a ceiling error: the first CLOSED
|
|
9007
|
+
* account (projected commitments included, exactly the layer-1
|
|
9008
|
+
* closure test) walking from `scope` toward the root, plus the root
|
|
9009
|
+
* state. 'run budget ceiling reached' under a healthy root misled the
|
|
9010
|
+
* v1.6.0 follow-up review's live probe when only a 0.18 USD
|
|
9011
|
+
* orchestrator cap had crossed under a 0.90 USD root; the message can
|
|
9012
|
+
* now name the account that actually ended the work. An unknown scope
|
|
9013
|
+
* degrades to root-only diagnostics instead of throwing: this runs on
|
|
9014
|
+
* the error path.
|
|
9015
|
+
*/
|
|
9016
|
+
exhaustionDiagnostics(scope) {
|
|
9017
|
+
let chain;
|
|
9018
|
+
try {
|
|
9019
|
+
chain = this.chainOf(scope);
|
|
9020
|
+
} catch {
|
|
9021
|
+
chain = [this.root];
|
|
9022
|
+
}
|
|
9023
|
+
const crossed = chain.find((account) => account.ceilingUsd !== void 0 && account.spentUsd + account.committedReserveUsd + account.finalizeReserveUsd >= account.ceilingUsd);
|
|
9024
|
+
const root = this.root;
|
|
9025
|
+
const diagnostics = { root: {
|
|
9026
|
+
spentUsd: root.spentUsd,
|
|
9027
|
+
...root.ceilingUsd === void 0 ? {} : { ceilingUsd: root.ceilingUsd }
|
|
9028
|
+
} };
|
|
9029
|
+
if (crossed?.ceilingUsd !== void 0) diagnostics.crossed = {
|
|
9030
|
+
scope: crossed.scope,
|
|
9031
|
+
source: crossed.scope === "run" ? "root" : crossed.kind === "orchestrator-cap" ? "orchestrator-cap" : "child-account",
|
|
9032
|
+
ceilingUsd: crossed.ceilingUsd,
|
|
9033
|
+
spentUsd: crossed.spentUsd,
|
|
9034
|
+
committedReserveUsd: crossed.committedReserveUsd,
|
|
9035
|
+
finalizeReserveUsd: crossed.finalizeReserveUsd
|
|
9036
|
+
};
|
|
9037
|
+
return diagnostics;
|
|
9038
|
+
}
|
|
8947
9039
|
accountView(scope) {
|
|
8948
9040
|
const account = this.accounts.get(scope);
|
|
8949
9041
|
if (account === void 0) return;
|
|
@@ -9791,6 +9883,13 @@ const kTerminalTool = Symbol("rulvar.terminalTool");
|
|
|
9791
9883
|
* graft boot). Dangling redispatch checkpoints take precedence.
|
|
9792
9884
|
*/
|
|
9793
9885
|
const kBootCheckpoint = Symbol("rulvar.bootCheckpoint");
|
|
9886
|
+
/**
|
|
9887
|
+
* Internal AgentOpts channel: marks the orchestrator forced-finish
|
|
9888
|
+
* dispatch, whose spend draws from the released finalize reserve
|
|
9889
|
+
* (DEF-7). Settlement stamps the flag into the terminal's cost
|
|
9890
|
+
* attribution so the journal fold reproduces reserveUsedUsd.
|
|
9891
|
+
*/
|
|
9892
|
+
const kFinalizeReserve = Symbol("rulvar.finalizeReserve");
|
|
9794
9893
|
/** Typed accessor used by the in-package consumers. */
|
|
9795
9894
|
function runtimeOf(ctx) {
|
|
9796
9895
|
const runtime = ctxRuntimes.get(ctx);
|
|
@@ -10653,6 +10752,13 @@ function createCtx(internals, rootWorkflow) {
|
|
|
10653
10752
|
usage: result.usage,
|
|
10654
10753
|
servedBy: result.servedBy,
|
|
10655
10754
|
...result.usageByModel === void 0 ? {} : { usageByModel: result.usageByModel },
|
|
10755
|
+
costAttribution: {
|
|
10756
|
+
...state.phase === void 0 ? {} : { phase: state.phase },
|
|
10757
|
+
agentType,
|
|
10758
|
+
role: primaryRole,
|
|
10759
|
+
budgetAccount: state.budgetScope ?? "run",
|
|
10760
|
+
...opts[kFinalizeReserve] === true ? { finalizeReserve: true } : {}
|
|
10761
|
+
},
|
|
10656
10762
|
transcriptRef: result.transcriptRef
|
|
10657
10763
|
};
|
|
10658
10764
|
if (result.status === "escalated" && result.escalation !== void 0) terminalPatch.escalation = result.escalation;
|
|
@@ -10720,10 +10826,25 @@ function createCtx(internals, rootWorkflow) {
|
|
|
10720
10826
|
bump(internals.cost.byPhase, state.phase ?? "", usd);
|
|
10721
10827
|
bump(internals.cost.byAgentType, agentType, usd);
|
|
10722
10828
|
internals.cost.byRole.set(primaryRole, (internals.cost.byRole.get(primaryRole) ?? 0) + usd);
|
|
10723
|
-
if (result.error?.kind === "budget" || internals.budget.exhausted && result.status !== "ok")
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10829
|
+
if (result.error?.kind === "budget" || internals.budget.exhausted && result.status !== "ok") {
|
|
10830
|
+
const diagnostics = internals.budget.exhaustionDiagnostics(state.budgetScope ?? "run");
|
|
10831
|
+
const crossed = diagnostics.crossed;
|
|
10832
|
+
const rootSuffix = `run root: spent ${diagnostics.root.spentUsd.toFixed(4)}` + (diagnostics.root.ceilingUsd === void 0 ? " USD, no ceiling" : ` of ${diagnostics.root.ceilingUsd.toFixed(4)} USD`);
|
|
10833
|
+
throw new BudgetExhaustedError(crossed === void 0 || crossed.source === "root" ? "run budget ceiling reached during agent execution" : (crossed.source === "orchestrator-cap" ? "orchestrator budget cap reached during agent execution" : "budget sub-account ceiling reached during agent execution") + ` (account '${crossed.scope}': spent ${crossed.spentUsd.toFixed(4)}` + (crossed.committedReserveUsd + crossed.finalizeReserveUsd > 0 ? ` plus ${(crossed.committedReserveUsd + crossed.finalizeReserveUsd).toFixed(4)} reserved` : "") + ` of ${crossed.ceilingUsd.toFixed(4)} USD; ${rootSuffix})`, { data: {
|
|
10834
|
+
scope: state.scope,
|
|
10835
|
+
entryRef: terminal.seq,
|
|
10836
|
+
source: crossed?.source ?? "root",
|
|
10837
|
+
rootSpentUsd: diagnostics.root.spentUsd,
|
|
10838
|
+
...diagnostics.root.ceilingUsd === void 0 ? {} : { rootCeilingUsd: diagnostics.root.ceilingUsd },
|
|
10839
|
+
...crossed === void 0 ? {} : {
|
|
10840
|
+
crossedScope: crossed.scope,
|
|
10841
|
+
crossedCeilingUsd: crossed.ceilingUsd,
|
|
10842
|
+
crossedSpentUsd: crossed.spentUsd,
|
|
10843
|
+
crossedCommittedReserveUsd: crossed.committedReserveUsd,
|
|
10844
|
+
crossedFinalizeReserveUsd: crossed.finalizeReserveUsd
|
|
10845
|
+
}
|
|
10846
|
+
} });
|
|
10847
|
+
}
|
|
10727
10848
|
if (opts.fallback !== void 0) {
|
|
10728
10849
|
const trigger = fallbackTriggerOf(result);
|
|
10729
10850
|
if (trigger !== void 0 && opts.fallback.on.includes(trigger)) return runFallbackAttempt(running.seq, trigger, spanId);
|
|
@@ -11313,10 +11434,16 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11313
11434
|
const finalizeTurns = spec?.finalizeTurns ?? 2;
|
|
11314
11435
|
const finalizeReserveUsd = spec?.finalizeReserveUsd ?? finalizeTurns * turnEstimateUsd;
|
|
11315
11436
|
if (extension !== void 0 && effectiveCapUsd < finalizeReserveUsd) throw new OrchestratorCapConfigError(`effectiveCap ${effectiveCapUsd.toFixed(4)} USD is below the finalize reserve ${finalizeReserveUsd.toFixed(4)} USD`);
|
|
11437
|
+
if (spec?.capUsd !== void 0 && spec.capFraction === void 0 && effectiveCapUsd < spec.capUsd) internals.events.emit({
|
|
11438
|
+
type: "log",
|
|
11439
|
+
level: "warn",
|
|
11440
|
+
msg: `orchestrator budget.capUsd ${spec.capUsd.toFixed(4)} USD is bounded to ${effectiveCapUsd.toFixed(4)} USD by the default capFraction 0.2 of the run ceiling (effectiveCap = min(capUsd, capFraction * ceiling)); pass capFraction: 1.0 to make capUsd the sole bound`
|
|
11441
|
+
}, callingState.spanId);
|
|
11316
11442
|
orchestratorAccount = callingState.scope === "" ? "orchestrator" : `${callingState.scope}/orchestrator`;
|
|
11317
11443
|
internals.budget.openAccount(orchestratorAccount, {
|
|
11318
11444
|
parentScope: callingState.budgetScope ?? "run",
|
|
11319
|
-
ceilingUsd: effectiveCapUsd
|
|
11445
|
+
ceilingUsd: effectiveCapUsd,
|
|
11446
|
+
kind: "orchestrator-cap"
|
|
11320
11447
|
});
|
|
11321
11448
|
if (extension !== void 0) internals.budget.commitFinalizeReserve(orchestratorAccount, finalizeReserveUsd);
|
|
11322
11449
|
capState = {
|
|
@@ -11332,6 +11459,15 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11332
11459
|
const records = /* @__PURE__ */ new Map();
|
|
11333
11460
|
const byOrdinal = /* @__PURE__ */ new Map();
|
|
11334
11461
|
const rejectedByOrdinal = /* @__PURE__ */ new Map();
|
|
11462
|
+
/**
|
|
11463
|
+
* The journaled spec behind each recovered ordinal: the idempotent
|
|
11464
|
+
* re-execution guard compares it against the incoming call, because
|
|
11465
|
+
* after a cross-attempt resume a REGENERATED turn (the boundary
|
|
11466
|
+
* checkpoint predates the lost turn) may decide differently, and
|
|
11467
|
+
* handing it the prior ordinal's handle would bind the transcript
|
|
11468
|
+
* to a stranger's child.
|
|
11469
|
+
*/
|
|
11470
|
+
const recoveredSpecByOrdinal = /* @__PURE__ */ new Map();
|
|
11335
11471
|
let nextOrdinal = 0;
|
|
11336
11472
|
let orchSeq;
|
|
11337
11473
|
const deliveredNodeIds = /* @__PURE__ */ new Set();
|
|
@@ -11367,7 +11503,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11367
11503
|
const controller = new AbortController();
|
|
11368
11504
|
const upstream = callingState.signal ?? internals.runSignal;
|
|
11369
11505
|
const scope = placement?.childScope ?? childScopeOf();
|
|
11370
|
-
if (placement
|
|
11506
|
+
if (placement?.ownAccount === true) internals.budget.openAccount(scope, {
|
|
11371
11507
|
parentScope: callingState.budgetScope ?? "run",
|
|
11372
11508
|
...placement.childCeilingUsd === void 0 ? {} : { ceilingUsd: placement.childCeilingUsd }
|
|
11373
11509
|
});
|
|
@@ -11375,7 +11511,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11375
11511
|
scope,
|
|
11376
11512
|
spanId: internals.spans.mint(callingState.spanId),
|
|
11377
11513
|
signal: upstream === void 0 ? controller.signal : AbortSignal.any([upstream, controller.signal]),
|
|
11378
|
-
budgetScope: placement
|
|
11514
|
+
budgetScope: placement?.ownAccount === true ? scope : callingState.budgetScope ?? "run"
|
|
11379
11515
|
};
|
|
11380
11516
|
let resolveHandle = () => void 0;
|
|
11381
11517
|
const handlePromise = new Promise((resolve) => {
|
|
@@ -11457,6 +11593,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11457
11593
|
nextOrdinal += 1;
|
|
11458
11594
|
return { handle: (await dispatchChild(spec, spawnOrdinal, identity, {
|
|
11459
11595
|
childScope,
|
|
11596
|
+
ownAccount: true,
|
|
11460
11597
|
...spec.budgetUsd === void 0 ? {} : { childCeilingUsd: spec.budgetUsd }
|
|
11461
11598
|
})).handle };
|
|
11462
11599
|
},
|
|
@@ -11487,33 +11624,61 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11487
11624
|
handle
|
|
11488
11625
|
};
|
|
11489
11626
|
};
|
|
11490
|
-
/**
|
|
11627
|
+
/**
|
|
11628
|
+
* True when `scope` is a root-attempt scope of THIS orchestration:
|
|
11629
|
+
* agentScope(callingState.scope, n) for some dispatch seq n. Nested
|
|
11630
|
+
* orchestrations live under their own wf: child scopes and never
|
|
11631
|
+
* match a foreign calling scope.
|
|
11632
|
+
*/
|
|
11633
|
+
const scopeOfThisOrchestration = (scope) => {
|
|
11634
|
+
const prefix = callingState.scope === "" ? "" : `${callingState.scope}/`;
|
|
11635
|
+
return scope.startsWith(prefix) && /^agent:\d+$/.test(scope.slice(prefix.length));
|
|
11636
|
+
};
|
|
11637
|
+
/**
|
|
11638
|
+
* Rebuilds spawn records from the journal (the crash-resume
|
|
11639
|
+
* contract). Recovery is ORCHESTRATION-scoped, not attempt-scoped:
|
|
11640
|
+
* decisions journal at the orchestrate call's own scope, which is
|
|
11641
|
+
* stable across root attempts, so a rerun after a cancelled root
|
|
11642
|
+
* (the budget-abort shape the v1.6.0 follow-up review resumed) sees
|
|
11643
|
+
* every prior decision instead of re-deciding and re-paying.
|
|
11644
|
+
* Recovered children re-dispatch PINNED to their journaled child
|
|
11645
|
+
* scope: settled ones forward-match and replay for free, a dangling
|
|
11646
|
+
* one redispatches live (at-least-once), and a decision without a
|
|
11647
|
+
* dispatch entry rolls forward to a fresh dispatch.
|
|
11648
|
+
*/
|
|
11491
11649
|
const recover = async () => {
|
|
11492
|
-
const
|
|
11650
|
+
const currentScope = childScopeOf();
|
|
11493
11651
|
const admissions = internals.replayer.snapshot().filter((entry) => {
|
|
11494
|
-
if (entry.kind !== "decision") return false;
|
|
11652
|
+
if (entry.kind !== "decision" || entry.scope !== callingState.scope) return false;
|
|
11495
11653
|
const value = entry.value;
|
|
11496
|
-
return value?.decisionType === "spawn-admission" && (value.origin === "spawn_agent" || value.origin === "parallel_agents")
|
|
11654
|
+
return value?.decisionType === "spawn-admission" && (value.origin === "spawn_agent" || value.origin === "parallel_agents");
|
|
11497
11655
|
}).map((entry) => entry.value).sort((a, b) => a.spawnOrdinal - b.spawnOrdinal);
|
|
11498
11656
|
for (const value of admissions) {
|
|
11499
11657
|
nextOrdinal = Math.max(nextOrdinal, value.spawnOrdinal + 1);
|
|
11500
11658
|
const decision = value.decision;
|
|
11659
|
+
recoveredSpecByOrdinal.set(value.spawnOrdinal, value.spec);
|
|
11501
11660
|
if (decision.verdict.kind !== "admit") {
|
|
11502
11661
|
rejectedByOrdinal.set(value.spawnOrdinal, decision);
|
|
11503
11662
|
continue;
|
|
11504
11663
|
}
|
|
11505
|
-
admission.recoverChild(
|
|
11506
|
-
|
|
11664
|
+
admission.recoverChild(currentScope);
|
|
11665
|
+
const childScope = value.childScope ?? value.orchestratorScope;
|
|
11666
|
+
const record = await dispatchChild(value.spec, value.spawnOrdinal, {
|
|
11507
11667
|
nodeId: decision.nodeId ?? "unknown",
|
|
11508
11668
|
logicalTaskId: decision.verdict.lineage.logicalTaskId
|
|
11509
|
-
});
|
|
11669
|
+
}, { childScope });
|
|
11670
|
+
const dispatched = internals.replayer.snapshot().find((entry) => entry.seq === record.handle);
|
|
11671
|
+
if (dispatched !== void 0) {
|
|
11672
|
+
for (const prior of internals.replayer.snapshot()) if (prior.kind === "agent" && prior.status === "running" && prior.seq !== record.handle && prior.scope === dispatched.scope && prior.key === dispatched.key && prior.ordinal === dispatched.ordinal && !records.has(prior.seq)) records.set(prior.seq, record);
|
|
11673
|
+
}
|
|
11510
11674
|
}
|
|
11511
|
-
const wakePrefix = `wake:${String(orchSeq ?? -1)}:`;
|
|
11512
11675
|
for (const entry of internals.replayer.snapshot()) {
|
|
11513
11676
|
if (entry.status !== "suspended" || entry.kind !== "external") continue;
|
|
11677
|
+
if (!scopeOfThisOrchestration(entry.scope)) continue;
|
|
11514
11678
|
const payload = entry.value;
|
|
11515
|
-
|
|
11516
|
-
|
|
11679
|
+
const match = typeof payload?.key === "string" ? /^wake:\d+:(\d+)$/.exec(payload.key) : null;
|
|
11680
|
+
if (match === null) continue;
|
|
11681
|
+
wakeOrdinal = Math.max(wakeOrdinal, Number(match[1]) + 1);
|
|
11517
11682
|
const suspension = internals.replayer.suspensionState(entry.seq);
|
|
11518
11683
|
if (suspension.state === "resolved") markDelivered(suspension.value);
|
|
11519
11684
|
}
|
|
@@ -11641,10 +11806,12 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11641
11806
|
await recoveryDone;
|
|
11642
11807
|
const spawnOrdinal = nextOrdinal;
|
|
11643
11808
|
nextOrdinal += 1;
|
|
11809
|
+
const priorSpec = recoveredSpecByOrdinal.get(spawnOrdinal);
|
|
11810
|
+
const specMatches = priorSpec === void 0 || priorSpec.agentType === params.agentType && priorSpec.prompt === params.prompt;
|
|
11644
11811
|
const recovered = byOrdinal.get(spawnOrdinal);
|
|
11645
|
-
if (recovered !== void 0) return { handle: recovered.handle };
|
|
11812
|
+
if (recovered !== void 0 && specMatches) return { handle: recovered.handle };
|
|
11646
11813
|
const recoveredRejection = rejectedByOrdinal.get(spawnOrdinal);
|
|
11647
|
-
if (recoveredRejection !== void 0) throw new AdmissionRejectedError(`admission rejected spawn ordinal ${String(spawnOrdinal)} (recovered verdict)`, { data: { decision: recoveredRejection } });
|
|
11814
|
+
if (recoveredRejection !== void 0 && specMatches) throw new AdmissionRejectedError(`admission rejected spawn ordinal ${String(spawnOrdinal)} (recovered verdict)`, { data: { decision: recoveredRejection } });
|
|
11648
11815
|
if (opts?.maxSpawns !== void 0 && spawnOrdinal >= opts.maxSpawns) {
|
|
11649
11816
|
internals.events.emit({
|
|
11650
11817
|
type: "spawn:rejected",
|
|
@@ -11902,7 +12069,11 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11902
12069
|
orchSeq = seq;
|
|
11903
12070
|
recover().then(releaseRecovery, releaseRecovery);
|
|
11904
12071
|
},
|
|
11905
|
-
[kTerminalTool]: { name: FINISH_TOOL_NAME }
|
|
12072
|
+
[kTerminalTool]: { name: FINISH_TOOL_NAME },
|
|
12073
|
+
...(() => {
|
|
12074
|
+
const priorCancelledRoot = internals.replayer.snapshot().filter((entry) => entry.kind === "agent" && entry.scope === callingState.scope && entry.status === "cancelled" && entry.checkpointRef !== void 0).at(-1);
|
|
12075
|
+
return priorCancelledRoot?.checkpointRef === void 0 ? {} : { [kBootCheckpoint]: priorCancelledRoot.checkpointRef };
|
|
12076
|
+
})()
|
|
11906
12077
|
};
|
|
11907
12078
|
const orchestratorState = { ...callingState };
|
|
11908
12079
|
if (orchestratorAccount !== void 0) orchestratorState.budgetScope = orchestratorAccount;
|
|
@@ -11928,7 +12099,8 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
11928
12099
|
limits: { maxTurns: capState?.finalizeTurns ?? 2 },
|
|
11929
12100
|
...capState === void 0 ? {} : { estCost: capState.finalizeReserveUsd },
|
|
11930
12101
|
...opts?.model === void 0 ? {} : { model: opts.model },
|
|
11931
|
-
[kTerminalTool]: { name: FINISH_TOOL_NAME }
|
|
12102
|
+
[kTerminalTool]: { name: FINISH_TOOL_NAME },
|
|
12103
|
+
[kFinalizeReserve]: true
|
|
11932
12104
|
};
|
|
11933
12105
|
const finalState = { ...callingState };
|
|
11934
12106
|
if (orchestratorAccount !== void 0) finalState.budgetScope = orchestratorAccount;
|
|
@@ -12109,14 +12281,20 @@ const detection = new AsyncLocalStorage();
|
|
|
12109
12281
|
let globalsPatched = false;
|
|
12110
12282
|
/**
|
|
12111
12283
|
* Stack line 0 names the Error, line 1 this helper, line 2 the patched
|
|
12112
|
-
* global, line 3 the caller whose provenance decides
|
|
12113
|
-
*
|
|
12114
|
-
*
|
|
12115
|
-
*
|
|
12284
|
+
* global, line 3 the caller whose provenance decides (the layout is
|
|
12285
|
+
* pinned by construction: this helper is only ever called by the two
|
|
12286
|
+
* patched globals). Two origins are exempt: installed dependencies (a
|
|
12287
|
+
* provider SDK, any transitive package, rulvar's own published dist),
|
|
12288
|
+
* which live under node_modules, and Node's own machinery (the undici
|
|
12289
|
+
* transport behind fetch, timers, stream internals), whose frames carry
|
|
12290
|
+
* `node:` specifiers and inherit the run's async context. The guard
|
|
12291
|
+
* exists for workflow code, which imports from both but lives in
|
|
12292
|
+
* neither.
|
|
12116
12293
|
*/
|
|
12117
12294
|
function libraryCaller() {
|
|
12118
12295
|
const caller = (/* @__PURE__ */ new Error()).stack?.split("\n")[3];
|
|
12119
|
-
|
|
12296
|
+
if (caller === void 0) return false;
|
|
12297
|
+
return caller.includes("node_modules") || /[(\s]node:/.test(caller);
|
|
12120
12298
|
}
|
|
12121
12299
|
/**
|
|
12122
12300
|
* Patches Date.now and Math.random ONCE per process and never restores:
|
|
@@ -12468,7 +12646,7 @@ function createEngine(options) {
|
|
|
12468
12646
|
dropped: internals.dropped,
|
|
12469
12647
|
pending,
|
|
12470
12648
|
usage: ledger.usage,
|
|
12471
|
-
cost:
|
|
12649
|
+
cost: costReportFromJournal(replayer.snapshot(), priceUsd)
|
|
12472
12650
|
};
|
|
12473
12651
|
if (value !== void 0 && (status === "ok" || status === "exhausted")) outcome.value = value;
|
|
12474
12652
|
if (wireError !== void 0) outcome.error = wireError;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.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",
|