@yielded/agent 0.1.0-beta.173 → 0.1.0-beta.174
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/{Admin-BX9ns28E.d.mts → Admin-BHmp2V9p.d.mts} +25 -16
- package/dist/{Agent-9aBoIi74.d.mts → Agent-B39jRnFv.d.mts} +2 -2
- package/dist/{Agent-0WvBWWbM.mjs → Agent-BiRbr73L.mjs} +7 -6
- package/dist/Agent-BiRbr73L.mjs.map +1 -0
- package/dist/{AgentRuntime-CQ-qcETl.mjs → AgentRuntime-B6qZlD3f.mjs} +199 -191
- package/dist/AgentRuntime-B6qZlD3f.mjs.map +1 -0
- package/dist/{AgentRuntime-BfP14534.d.mts → AgentRuntime-BD3ZHAMq.d.mts} +10 -10
- package/dist/{Digest-DCuPlhNk.mjs → Digest-EpeqWEdv.mjs} +41 -14
- package/dist/Digest-EpeqWEdv.mjs.map +1 -0
- package/dist/{DurableAgentRuntime-BAmSkWYr.mjs → DurableAgentRuntime-CBBjRNJN.mjs} +1447 -1424
- package/dist/DurableAgentRuntime-CBBjRNJN.mjs.map +1 -0
- package/dist/{EventSource-BwliwQz9.d.mts → EventSource-C9aaJaXT.d.mts} +2 -2
- package/dist/{MessageDelivery-B943ebI_.d.mts → MessageDelivery-BGDm-c46.d.mts} +42 -42
- package/dist/{Messaging-C_6OOg_s.d.mts → Messaging-SVu6rWV8.d.mts} +12 -6
- package/dist/{MessagingHost-B8oKM7AC.d.mts → MessagingHost-C6SOAcoG.d.mts} +2 -2
- package/dist/{Output-Dsx6k52t.d.mts → Output-CRamN1Fy.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-CxSJSiTl.d.mts → PreparedInputAdmission-BvDqlgiP.d.mts} +3 -3
- package/dist/{RunContinuation-DHYNAQFi.mjs → RunContinuation-4ZATcVLB.mjs} +113 -56
- package/dist/RunContinuation-4ZATcVLB.mjs.map +1 -0
- package/dist/{RunContinuation-FHM7XPjq.d.mts → RunContinuation-CTJ1jGrO.d.mts} +6 -6
- package/dist/{RunJournal-kfKVxJj7.mjs → RunJournal-CNZqA3Ge.mjs} +33 -5
- package/dist/RunJournal-CNZqA3Ge.mjs.map +1 -0
- package/dist/{RunOptions-D8zxFIrZ.d.mts → RunOptions-Be77lKVZ.d.mts} +2 -2
- package/dist/{RunStorage-uqPxps09.mjs → RunStorage-BHjuuERI.mjs} +9 -6
- package/dist/RunStorage-BHjuuERI.mjs.map +1 -0
- package/dist/{Scheduling-CVyfXlBR.mjs → Scheduling-NG8slKdI.mjs} +11 -11
- package/dist/Scheduling-NG8slKdI.mjs.map +1 -0
- package/dist/{Subagent-vpffemql.mjs → Subagent-CTIpnzlB.mjs} +53 -40
- package/dist/Subagent-CTIpnzlB.mjs.map +1 -0
- package/dist/{Subagent-E6tvd7-k.d.mts → Subagent-DKhZA72u.d.mts} +19 -8
- package/dist/{SubagentHost-B6w2m-SI.d.mts → SubagentHost-D1xBgn9g.d.mts} +2 -2
- package/dist/{Subscription-DONig54Q.d.mts → Subscription-BNg9VCRl.d.mts} +2 -2
- package/dist/{SubscriptionInput-mJIRxWJM.d.mts → SubscriptionInput-BUoXv-_K.d.mts} +2 -2
- package/dist/{ThreadImport-DpHxjBrA.d.mts → ThreadImport-CMgzttvr.d.mts} +5 -5
- package/dist/{ThreadImport-DckUMEqJ.mjs → ThreadImport-CodYoJoa.mjs} +7 -7
- package/dist/ThreadImport-CodYoJoa.mjs.map +1 -0
- package/dist/{ThreadStore-CEekRa80.mjs → ThreadStore-59uDGXul.mjs} +163 -84
- package/dist/ThreadStore-59uDGXul.mjs.map +1 -0
- package/dist/{ThreadTransfer-B4gTQLIl.mjs → ThreadTransfer-3jigUl3g.mjs} +3 -3
- package/dist/{ThreadTransfer-B4gTQLIl.mjs.map → ThreadTransfer-3jigUl3g.mjs.map} +1 -1
- package/dist/{WorkerAdmission-DFVbbVh2.mjs → WorkerAdmission-DDYJdOsU.mjs} +4 -4
- package/dist/{WorkerAdmission-DFVbbVh2.mjs.map → WorkerAdmission-DDYJdOsU.mjs.map} +1 -1
- package/dist/{agent-registration-ByMZ_cK5.mjs → agent-registration-DRbyhAu-.mjs} +69 -56
- package/dist/agent-registration-DRbyhAu-.mjs.map +1 -0
- package/dist/capabilities/Approval.mjs +2 -2
- package/dist/capabilities/Approval.mjs.map +1 -1
- package/dist/capabilities/BrowserUse.d.mts +102 -1867
- package/dist/capabilities/BrowserUse.mjs +74 -798
- package/dist/capabilities/BrowserUse.mjs.map +1 -1
- package/dist/capabilities/Budget.mjs +3 -1
- package/dist/capabilities/Budget.mjs.map +1 -1
- package/dist/capabilities/CodeMode.d.mts +1 -1
- package/dist/capabilities/CodeMode.mjs +16 -9
- package/dist/capabilities/CodeMode.mjs.map +1 -1
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/McpClient.mjs +1 -1
- package/dist/capabilities/McpClient.mjs.map +1 -1
- package/dist/capabilities/Messaging.d.mts +1 -1
- package/dist/capabilities/Messaging.mjs +4 -4
- package/dist/capabilities/Messaging.mjs.map +1 -1
- package/dist/capabilities/ModelContext.mjs +7 -5
- package/dist/capabilities/ModelContext.mjs.map +1 -1
- package/dist/capabilities/Redaction.mjs +49 -19
- package/dist/capabilities/Redaction.mjs.map +1 -1
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/RunHooks.mjs +1 -1
- package/dist/capabilities/RunHooks.mjs.map +1 -1
- package/dist/capabilities/Subagent.d.mts +1 -1
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/capabilities/SubagentReservations.mjs +3 -1
- package/dist/capabilities/SubagentReservations.mjs.map +1 -1
- package/dist/capabilities/WebCapture.mjs.map +1 -1
- package/dist/capabilities/WebSearch.mjs +7 -7
- package/dist/capabilities/WebSearch.mjs.map +1 -1
- package/dist/core/Agent.d.mts +1 -1
- package/dist/core/Agent.mjs +1 -1
- package/dist/core/AgentUpdates.mjs +8 -8
- package/dist/core/AgentUpdates.mjs.map +1 -1
- package/dist/core/Thread.mjs +1 -1
- package/dist/core/Thread.mjs.map +1 -1
- package/dist/core/Usage.mjs +2 -2
- package/dist/core/Usage.mjs.map +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/AgentRegistration.mjs +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/CommittedActivity.mjs +2 -2
- package/dist/durable/Digest.mjs +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +2 -2
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/EventSource.mjs +6 -6
- package/dist/durable/EventSource.mjs.map +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/LifecyclePublication.mjs +1 -1
- package/dist/durable/MessageDelivery.d.mts +1 -1
- package/dist/durable/MessageDelivery.mjs +1 -1
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +2 -2
- package/dist/durable/MessageDeliveryStoreConformance.mjs +1 -1
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PersistentHistory.mjs +3 -3
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/RecordFormat.mjs +2 -2
- package/dist/durable/RecordFormat.mjs.map +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/RunContinuation.d.mts +2 -2
- package/dist/durable/RunContinuation.mjs +2 -2
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/RunJournal.mjs +1 -1
- package/dist/durable/RunStorage.d.mts +1 -1
- package/dist/durable/RunStorage.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +1 -1
- package/dist/durable/Scheduling.mjs +1 -1
- package/dist/durable/SettlementPublisher.d.mts +1 -1
- package/dist/durable/SettlementPublisher.mjs +2 -2
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +5 -1
- package/dist/durable/SubmissionLedger.mjs.map +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +4 -4
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +3 -3
- package/dist/durable/SubscriptionInput.mjs.map +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +2 -2
- package/dist/durable/SubscriptionStoreConformance.mjs.map +1 -1
- package/dist/durable/SubscriptionTools.d.mts +2 -2
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/Subscriptions.mjs +2 -2
- package/dist/durable/Subscriptions.mjs.map +1 -1
- package/dist/durable/ThreadArchiveRange.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.mjs +1 -1
- package/dist/durable/ThreadImport.d.mts +1 -1
- package/dist/durable/ThreadImport.mjs +1 -1
- package/dist/durable/ThreadInvariants.d.mts +3 -3
- package/dist/durable/ThreadInvariants.mjs +4 -4
- package/dist/durable/ThreadInvariants.mjs.map +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadReader.d.mts +1 -1
- package/dist/durable/ThreadReader.mjs +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +1 -1
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +3 -3
- package/dist/durable/ThreadTransfer.d.mts +1 -1
- package/dist/durable/ThreadTransfer.mjs +1 -1
- package/dist/durable/ThreadWork.d.mts +1 -1
- package/dist/durable/ThreadWork.mjs +4 -4
- package/dist/durable/ThreadWork.mjs.map +1 -1
- package/dist/durable/WorkerAdmission.d.mts +1 -1
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +2 -2
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/MessagingHost.d.mts +1 -1
- package/dist/engine/Output.d.mts +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/index.d.mts +19 -19
- package/dist/index.mjs +14 -14
- package/dist/{run-context-reader-OcsZr4bk.d.mts → run-context-reader-CC7ZD95F.d.mts} +2 -2
- package/package.json +1 -1
- package/src/capabilities/Approval.ts +58 -60
- package/src/capabilities/BrowserUse.ts +89 -944
- package/src/capabilities/Budget.ts +8 -1
- package/src/capabilities/CodeMode.ts +57 -33
- package/src/capabilities/McpClient.ts +2 -2
- package/src/capabilities/Messaging.ts +51 -55
- package/src/capabilities/ModelContext.ts +5 -2
- package/src/capabilities/Redaction.ts +64 -34
- package/src/capabilities/RunHooks.ts +52 -55
- package/src/capabilities/Subagent.ts +33 -33
- package/src/capabilities/SubagentReservations.ts +9 -1
- package/src/capabilities/WebCapture.ts +6 -0
- package/src/capabilities/WebSearch.ts +10 -7
- package/src/capabilities/internal/subagent-background.ts +202 -158
- package/src/core/Agent.ts +11 -6
- package/src/core/AgentUpdates.ts +8 -8
- package/src/core/Thread.ts +9 -10
- package/src/core/Usage.ts +7 -8
- package/src/core/internal/agent-updates.ts +1 -0
- package/src/durable/DurableAgentRuntime.ts +645 -625
- package/src/durable/EventSource.ts +15 -9
- package/src/durable/RecordFormat.ts +5 -3
- package/src/durable/RunContinuation.ts +233 -81
- package/src/durable/RunJournal.ts +10 -9
- package/src/durable/RunStorage.ts +122 -124
- package/src/durable/Scheduling.ts +639 -651
- package/src/durable/SubmissionLedger.ts +4 -0
- package/src/durable/SubscriptionInput.ts +5 -3
- package/src/durable/SubscriptionStoreConformance.ts +23 -23
- package/src/durable/Subscriptions.ts +18 -19
- package/src/durable/ThreadImport.ts +18 -19
- package/src/durable/ThreadInvariants.ts +2 -1
- package/src/durable/ThreadStore.ts +215 -111
- package/src/durable/ThreadWork.ts +1 -2
- package/src/durable/internal/StorageOwner.ts +10 -4
- package/src/durable/internal/agent-registration.ts +96 -89
- package/src/durable/internal/canonical-json.ts +61 -20
- package/src/durable/internal/prompt-history-cache.ts +13 -4
- package/src/durable/internal/record-encoding.ts +120 -64
- package/src/durable/internal/schedule-time.ts +6 -6
- package/src/durable/internal/usage-totals.ts +38 -0
- package/src/durable/internal/worker-host.ts +69 -74
- package/src/engine/internal/agent-runtime.ts +1067 -1018
- package/src/engine/internal/provisional-text.ts +12 -10
- package/src/engine/internal/tool-exposure.ts +22 -18
- package/src/engine/internal/tool-telemetry.ts +12 -7
- package/dist/Agent-0WvBWWbM.mjs.map +0 -1
- package/dist/AgentRuntime-CQ-qcETl.mjs.map +0 -1
- package/dist/Digest-DCuPlhNk.mjs.map +0 -1
- package/dist/DurableAgentRuntime-BAmSkWYr.mjs.map +0 -1
- package/dist/RunContinuation-DHYNAQFi.mjs.map +0 -1
- package/dist/RunJournal-kfKVxJj7.mjs.map +0 -1
- package/dist/RunStorage-uqPxps09.mjs.map +0 -1
- package/dist/Scheduling-CVyfXlBR.mjs.map +0 -1
- package/dist/Subagent-vpffemql.mjs.map +0 -1
- package/dist/ThreadImport-DckUMEqJ.mjs.map +0 -1
- package/dist/ThreadStore-CEekRa80.mjs.map +0 -1
- package/dist/agent-registration-ByMZ_cK5.mjs.map +0 -1
|
@@ -16,33 +16,33 @@ import { a as PeerMessageCapacity, d as MessageAdmission, f as MessagingError, i
|
|
|
16
16
|
import { SubagentHost } from "./engine/SubagentHost.mjs";
|
|
17
17
|
import { ThreadHistory } from "./engine/ThreadHistory.mjs";
|
|
18
18
|
import { n as RunToolVisibility } from "./ToolExposure-DBATXxmL.mjs";
|
|
19
|
-
import { C as boundedValueFootprint, n as AgentChildPending, p as renderInputPrompt, u as executeWithUsageAccountingUnknown } from "./AgentRuntime-
|
|
19
|
+
import { C as boundedValueFootprint, n as AgentChildPending, p as renderInputPrompt, u as executeWithUsageAccountingUnknown } from "./AgentRuntime-B6qZlD3f.mjs";
|
|
20
20
|
import { ContextRolloverTool } from "./engine/ContextWindow.mjs";
|
|
21
21
|
import { getToolExecutionClass } from "./engine/DurableStep.mjs";
|
|
22
22
|
import { CompactionError, ContextCompactor } from "./engine/ContextCompactor.mjs";
|
|
23
23
|
import { AgentUpdateAcceptance, CurrentToolFailureObserver, ModelUsageAccounting, RunContextPreparation, RunContextPreparationPassthrough, RunToolAuthorization, RunToolScheduling } from "./engine/RunOptions.mjs";
|
|
24
24
|
import { A as MAX_RUN_EVIDENCE_RECORDS, At as WorkHandoffCompleted, Bt as WorkerReportingIntent, Ct as ToolCallResolved, Dt as ToolStepSettled, Et as ToolOperation, Ft as WorkerInputRequested, G as PromptRecord, H as PeerMessagePrepared, I as ModelCallAborted, It as WorkerOrigin, Mt as WorkerContinuation, Nt as WorkerInputCompleted, O as MAX_RUN_CONTINUATION_BYTES, Ot as ToolUnavailable, P as MAX_RUN_TOOL_CALL_IDENTITIES, Pt as WorkerInputRefused, R as ModelResponseInterrupted, Rt as WorkerReportPrepared, Tt as ToolCallUnknown, U as PersistedJson, V as PROMPT_EVIDENCE_TAGS, Vt as WorkerStopRequested, X as RecordEnvelope, Z as RecordId, _t as SubmissionSettledRecord, at as RunDurationExhausted, bt as ToolApprovalDecided, c as CanonicalBatch, et as RepairAnnotated, f as CanonicalSequence, ft as SubagentJoined, g as DeclaredToolCall, gt as SubmissionSettled, ht as SubagentStarted, i as BatchId, jt as WorkerAdmission, kt as UserInputRecorded, lt as RunStartedRecord, mt as SubagentRequested, n as AgentUpdateEmitted, o as CURRENT_RECORD_FORMAT, p as CompactionCreated, pt as SubagentLineageRecorded, rt as RunContextRecorded, st as RunPolicyUsageReserved, t as AbortRequested, ut as SettlementFailureDiagnostic, v as DefinitionDigests, vt as SubtreeBudgetReserved, w as MAX_PERSISTED_JSON_BYTES, wt as ToolCallSettled, xt as ToolApprovalRequested, zt as WorkerReportRefused } from "./Records-BiuJDWNe.mjs";
|
|
25
|
-
import { i as digestCanonicalJson, r as canonicalJson, s as digestJson } from "./Digest-
|
|
25
|
+
import { i as digestCanonicalJson, r as canonicalJson, s as digestJson } from "./Digest-EpeqWEdv.mjs";
|
|
26
26
|
import { AbortCommand, AbortIntentRequest, AdmissionPolicyError, AdmissionRequest, ApprovalDecisionCommand, ApprovalPendingSuspension, BeginChildBudgetReleaseRequest, ChildReservationId, ChildSettledNotification, ClaimHandoff, ClaimRequest, FundingOwnerRequest, LedgerError, MarkReadyRequest, MarkUnknownRequest, ParentLinkage, RecoverySnapshotRequest, ReleaseChildBudgetRequest, RevertJoiningRequest, Settlement, SettlementFinalization, SubmissionLedger, SubmissionLookupById, SubmissionLookupByKey, SubmissionScheduling, UnknownResolutionCommand, WaitingChild, WaitingForChildSuspension, WorkerLedgerState, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId, unknownResolutionKind } from "./durable/SubmissionLedger.mjs";
|
|
27
27
|
import { DeclaredPendingBatchEvidence, OpenDelegationCallEvidence, OpenToolCallEvidence, PendingApprovalEvidence, RecoveryDecision, RecoveryEvidence, classifyRecovery, pendingApprovalForRecovery } from "./durable/Recovery.mjs";
|
|
28
28
|
import { ExplainedEvidence, ExplainedSubmission, ExplainedUnknownCall, ObligationEntry, ObligationReport, RecoveryExplanation, RetryRefused, obligationSeverityOf, predictRecoveryDisposition, recoveryDecisionMeaning } from "./durable/Admin.mjs";
|
|
29
|
-
import { a as compileRegistrations, c as resolveDefinitionBinding, l as resolveWorkerBinding, n as CurrentBindingSelection, o as definitionDigestsEqual, s as makeLegacyWorkerBinding, t as BindingUnavailable, u as toolReplayContracts } from "./agent-registration-
|
|
30
|
-
import { A as subagentStartedBatchId, B as turnApprovalsBatchId, C as runStartedRecordId, D as subagentLineageRecordId, E as subagentLineageBatchId, F as toolCallResolvedRecordId, G as turnResponseBatchId, H as turnCanonicalBatch, I as toolCallResultBatchId, J as workerInputRecordId, K as turnResultsBatch, L as toolCallUnknownRecordId, M as toolApprovalDecisionRecordId, N as toolApprovalRequestRecordId, O as subagentRequestedBatchId, P as toolCallResolutionBatchId, Q as
|
|
31
|
-
import { $ as ThreadTailRequest, B as ThreadPromptRead, F as ThreadIdentityRequest, I as ThreadMaterialization, J as ThreadStore, R as ThreadObservation, U as ThreadReader, V as ThreadRead, X as ThreadStoreError, Y as ThreadStoreDiagnostic, _t as isPreContinuationFact, bt as terminalUsageCharge, gt as executionRunIds, ht as canonicalRunIds, lt as readWorkerState, n as AppendRequest, ot as getRecord, p as MAX_THREAD_EXPORT_PAGE_BYTES, pt as captureRecord, st as getRunInput } from "./ThreadStore-
|
|
29
|
+
import { a as compileRegistrations, c as resolveDefinitionBinding, l as resolveWorkerBinding, n as CurrentBindingSelection, o as definitionDigestsEqual, s as makeLegacyWorkerBinding, t as BindingUnavailable, u as toolReplayContracts } from "./agent-registration-DRbyhAu-.mjs";
|
|
30
|
+
import { $ as toolCallSettledRecordId, A as subagentStartedBatchId, B as turnApprovalsBatchId, C as runStartedRecordId, D as subagentLineageRecordId, E as subagentLineageBatchId, F as toolCallResolvedRecordId, G as turnResponseBatchId, H as turnCanonicalBatch, I as toolCallResultBatchId, J as workerInputRecordId, K as turnResultsBatch, L as toolCallUnknownRecordId, M as toolApprovalDecisionRecordId, N as toolApprovalRequestRecordId, O as subagentRequestedBatchId, P as toolCallResolutionBatchId, Q as makeJournalMetadata, R as toolStepSettledBatchId, S as runStartedBatchId, T as subagentJoinedRecordId, U as turnIdForRun, W as turnResponseBatch, X as workerReportRecordId, Y as workerOriginRecordId, a as childIdempotencyKeyFor, b as runDurationRecordId, c as compactionRecordId, d as modelResponseInterruptedBatchId, f as modelResponseInterruptedRecordId, g as projectRunJournalStream, i as approvalDecisionBatchId, j as subagentStartedRecordId, k as subagentRequestedRecordId, l as firstWorkerInputRecordId, m as peerMessageRecordId, o as childThreadIdFor, p as modelResponseRecordId, r as agentUpdateRecordId, s as compactionBatchId, t as RunJournalError, u as markUnknownBatchId, v as runCompletedRecordId, w as subagentJoinBatchId, x as runIdForSubmission, y as runDurationBatchId, z as toolStepSettledRecordId } from "./RunJournal-CNZqA3Ge.mjs";
|
|
31
|
+
import { $ as ThreadTailRequest, B as ThreadPromptRead, F as ThreadIdentityRequest, I as ThreadMaterialization, J as ThreadStore, R as ThreadObservation, U as ThreadReader, V as ThreadRead, X as ThreadStoreError, Y as ThreadStoreDiagnostic, _t as isPreContinuationFact, bt as terminalUsageCharge, gt as executionRunIds, ht as canonicalRunIds, lt as readWorkerState, n as AppendRequest, ot as getRecord, p as MAX_THREAD_EXPORT_PAGE_BYTES, pt as captureRecord, st as getRunInput } from "./ThreadStore-59uDGXul.mjs";
|
|
32
32
|
import { ScheduledInputRefused, ScheduledInputRetryable } from "./durable/Schedule.mjs";
|
|
33
33
|
import { PreparedInputAdmission } from "./durable/PreparedInputAdmission.mjs";
|
|
34
34
|
import { PreparedInput } from "./durable/Subscription.mjs";
|
|
35
35
|
import { MessageDeliveryDriver, MessageDeliveryFailpoint, MessageDeliveryRecord, MessageDeliveryStore, prepareMessageDelivery } from "./durable/MessageDelivery.mjs";
|
|
36
36
|
import { DurableRuntimeFailpoint } from "./durable/DurableFailpoint.mjs";
|
|
37
|
-
import { _ as readRunContext, a as canonicalRecordBytes, b as reference, f as runEvidence, g as digestRunHistory, l as readContinuation, m as validateSuffix, n as CurrentRunWriter, s as makeProgressWriter, t as CurrentRunSettlement, u as readRunEvidenceSnapshot, x as resolveEvidence, y as RunContextReader } from "./RunContinuation-
|
|
37
|
+
import { _ as readRunContext, a as canonicalRecordBytes, b as reference, f as runEvidence, g as digestRunHistory, l as readContinuation, m as validateSuffix, n as CurrentRunWriter, s as makeProgressWriter, t as CurrentRunSettlement, u as readRunEvidenceSnapshot, x as resolveEvidence, y as RunContextReader } from "./RunContinuation-4ZATcVLB.mjs";
|
|
38
38
|
import { MAX_WORK_CURSOR_CHARS, ThreadWorkDiscovery, ThreadWorkEntry, ThreadWorkRequest, WorkDiscoveryUnavailable, decodeWorkCursor, deliveryPredecessor, encodeWorkCursor, operationEvidence, resolveWorkEvidence, validateWorkPage, workId } from "./durable/ThreadWork.mjs";
|
|
39
39
|
import { WakeScheduler } from "./durable/WakeScheduler.mjs";
|
|
40
40
|
import { n as safeUnknownString, t as inspectForeignDiagnostic } from "./foreign-diagnostic-DBQ1XHKh.mjs";
|
|
41
|
-
import { c as threadCreatedBatchId, l as threadCreatedRecordId, n as WorkerAdmissionPort, o as ensureThreadCreated, r as WorkerAdmissionRequest, s as ensureWorkerOrigin } from "./WorkerAdmission-
|
|
41
|
+
import { c as threadCreatedBatchId, l as threadCreatedRecordId, n as WorkerAdmissionPort, o as ensureThreadCreated, r as WorkerAdmissionRequest, s as ensureWorkerOrigin } from "./WorkerAdmission-DDYJdOsU.mjs";
|
|
42
42
|
import { i as unresolvedToolOperations, n as isUnresolvedToolOperation, r as toolOperationStates, t as initialDispatchBlockedTurns } from "./tool-operations-BXBmagY1.mjs";
|
|
43
43
|
import { WorkerBudgetAuthorizer, WorkerConcurrencyLimit, WorkerConcurrencyResolver, WorkerHostAuthorizer, WorkerHostConfig, WorkerPolicyResolver } from "./durable/WorkerHost.mjs";
|
|
44
44
|
import { OperationAuthorizationRequest, OperationAuthorizer, OperationDenied } from "./durable/OperationAuthorizer.mjs";
|
|
45
|
-
import { o as makeRunWriter, r as RunStorage, s as StorageOwner } from "./RunStorage-
|
|
45
|
+
import { o as makeRunWriter, r as RunStorage, s as StorageOwner } from "./RunStorage-BHjuuERI.mjs";
|
|
46
46
|
import { SettlementPublication } from "./durable/SettlementPublisher.mjs";
|
|
47
47
|
import { PendingSubmission, SettledSubmission } from "./durable/SubmissionStatus.mjs";
|
|
48
48
|
import { DeclaredToolCallEvidence, ToolReconciler } from "./durable/ToolReconciler.mjs";
|
|
@@ -736,7 +736,7 @@ function hydratePart(part) {
|
|
|
736
736
|
case "tool-approval-request": return Prompt.toolApprovalRequestPart(part);
|
|
737
737
|
case "tool-approval-response": return Prompt.toolApprovalResponsePart(part);
|
|
738
738
|
}
|
|
739
|
-
|
|
739
|
+
return part;
|
|
740
740
|
}
|
|
741
741
|
const hydrateMessage = (message) => {
|
|
742
742
|
switch (message.role) {
|
|
@@ -754,7 +754,7 @@ const hydrateMessage = (message) => {
|
|
|
754
754
|
content: message.content.map((p) => hydratePart(p))
|
|
755
755
|
});
|
|
756
756
|
}
|
|
757
|
-
|
|
757
|
+
return message;
|
|
758
758
|
};
|
|
759
759
|
/** Internal canonical projection; ownership comes from the ThreadStore read contract. */
|
|
760
760
|
const preparePromptHistory = (prompt) => prompt.content.length > MAX_ENTRIES ? void 0 : {
|
|
@@ -851,7 +851,12 @@ const makeCommittedPromptSuffix = (original) => {
|
|
|
851
851
|
}
|
|
852
852
|
try {
|
|
853
853
|
for (const fact of facts) {
|
|
854
|
-
const
|
|
854
|
+
const captured = captureRecord(fact);
|
|
855
|
+
if (Result.isFailure(captured)) {
|
|
856
|
+
discard();
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
const owned = captured.success;
|
|
855
860
|
const payload = owned.canonical.payload;
|
|
856
861
|
if (payload._tag !== "UserInputRecorded" && payload._tag !== "ModelResponseRecorded" && payload._tag !== "ToolCallSettled" && payload._tag !== "SubmissionSettled") {
|
|
857
862
|
discard();
|
|
@@ -2384,7 +2389,7 @@ const makeWorkerRuntime = Effect.fnUntraced(function* (options) {
|
|
|
2384
2389
|
ownerThreadId: context.source.threadId,
|
|
2385
2390
|
messageId
|
|
2386
2391
|
}).pipe(Effect.mapError(storageFailure("start")));
|
|
2387
|
-
const replay =
|
|
2392
|
+
const replay = Effect.fnUntraced(function* (saved) {
|
|
2388
2393
|
const currentPrevious = command.continuationOf === void 0 ? void 0 : yield* completedContinuation(context.source, command.continuationOf, command.target.id, command.delegationId, previous?.evidence);
|
|
2389
2394
|
const replayPrincipal = yield* authorize("start", "send", void 0, currentPrevious?.evidence);
|
|
2390
2395
|
yield* binding(command.target, "start");
|
|
@@ -2476,7 +2481,7 @@ const makeWorkerRuntime = Effect.fnUntraced(function* (options) {
|
|
|
2476
2481
|
ownerThreadId: context.source.threadId,
|
|
2477
2482
|
messageId
|
|
2478
2483
|
}).pipe(Effect.mapError(storageFailure("followUp")));
|
|
2479
|
-
const replay =
|
|
2484
|
+
const replay = Effect.fnUntraced(function* (saved) {
|
|
2480
2485
|
const replayPrincipal = yield* authorize("followUp", "send", command.worker);
|
|
2481
2486
|
yield* currentPolicy;
|
|
2482
2487
|
return yield* send(origin, messageId, saved.envelope.input, command.encodedParameters, replayPrincipal, "followUp");
|
|
@@ -3257,6 +3262,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
3257
3262
|
let context;
|
|
3258
3263
|
let progress;
|
|
3259
3264
|
let progressThrough;
|
|
3265
|
+
let operational = [];
|
|
3260
3266
|
const invalid = (message) => ThreadStoreError.make({
|
|
3261
3267
|
operation: "read Run continuation",
|
|
3262
3268
|
message
|
|
@@ -3325,20 +3331,20 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
3325
3331
|
context = saved;
|
|
3326
3332
|
progress = cursor;
|
|
3327
3333
|
progressThrough = envelope.throughSequence;
|
|
3334
|
+
operational = envelope.operational;
|
|
3328
3335
|
}
|
|
3329
3336
|
}
|
|
3330
|
-
const records = [...new Map([...identity.records.filter((entry) => entry.sequence <= throughSequence), ...selected].map((entry) => [entry.sequence, entry])).values()].sort((left, right) => left.sequence - right.sequence);
|
|
3331
3337
|
return {
|
|
3332
|
-
|
|
3338
|
+
records: [...new Map([...identity.records.filter((entry) => entry.sequence <= throughSequence), ...selected].map((entry) => [entry.sequence, entry])).values()].sort((left, right) => left.sequence - right.sequence),
|
|
3333
3339
|
context,
|
|
3334
3340
|
progress,
|
|
3335
|
-
progressThrough
|
|
3341
|
+
progressThrough,
|
|
3342
|
+
operational
|
|
3336
3343
|
};
|
|
3337
3344
|
});
|
|
3338
3345
|
const readControl = Effect.fnUntraced(function* (threadId, submissionIds) {
|
|
3339
3346
|
const tail = yield* store.inspectTail(ThreadTailRequest.make({ threadId }));
|
|
3340
|
-
|
|
3341
|
-
return yield* Stream.runCollect(view.canonical.pipe(Stream.filter(controlRecords(submissionIds))));
|
|
3347
|
+
return (yield* recoveryView(threadId, tail.tailSequence, submissionIds)).records.filter(controlRecords(submissionIds));
|
|
3342
3348
|
});
|
|
3343
3349
|
const readAllTolerant = (threadId, submissionIds) => Effect.suspend(() => readControl(threadId, submissionIds).pipe(Effect.map((records) => ({
|
|
3344
3350
|
records,
|
|
@@ -3360,7 +3366,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
3360
3366
|
submissionIds
|
|
3361
3367
|
};
|
|
3362
3368
|
return {
|
|
3363
|
-
records: yield* recoveryView(threadId, tail.value.tailSequence, submissionIds).pipe(Effect.
|
|
3369
|
+
records: yield* recoveryView(threadId, tail.value.tailSequence, submissionIds).pipe(Effect.map((view) => view.records.filter(controlRecords(submissionIds))), Effect.catchTag("ThreadNotMaterialized", (error) => ThreadStoreError.make({
|
|
3364
3370
|
operation: "read recovery history",
|
|
3365
3371
|
message: `Thread ${threadId} disappeared after its recovery tail was captured`,
|
|
3366
3372
|
cause: error
|
|
@@ -3747,7 +3753,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
3747
3753
|
});
|
|
3748
3754
|
const progressStore = ThreadStore.of({
|
|
3749
3755
|
...store,
|
|
3750
|
-
append:
|
|
3756
|
+
append: Effect.fnUntraced(function* (request) {
|
|
3751
3757
|
const progress = activeProgress.get(request.threadId)?.writer ?? (yield* makeProgressWriter(request.threadId, config.deploymentId).pipe(Effect.provideService(ThreadReader, reader), Effect.provideService(Crypto.Crypto, crypto)));
|
|
3752
3758
|
let tail = { sequence: request.expectedTailSequence };
|
|
3753
3759
|
return yield* progress.commit(request.batch).pipe(Effect.provideService(CurrentRunWriter, {
|
|
@@ -3776,7 +3782,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
3776
3782
|
threadId: ctx.threadId,
|
|
3777
3783
|
tail: ctx.tail,
|
|
3778
3784
|
withProgress: ctx.withProgress,
|
|
3779
|
-
publishSettlement:
|
|
3785
|
+
publishSettlement: Effect.fnUntraced(function* (prepared, executions) {
|
|
3780
3786
|
let tail = yield* ctx.tail;
|
|
3781
3787
|
for (let retries = 0;; retries++) {
|
|
3782
3788
|
const result = yield* runStorage.publishSettlement(SettlementPublication.make({
|
|
@@ -4079,23 +4085,26 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
4079
4085
|
sequence: result.firstSequence
|
|
4080
4086
|
});
|
|
4081
4087
|
});
|
|
4082
|
-
const readRunStart = Effect.fnUntraced(function* (threadId, runId) {
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
+
const readRunStart = Effect.fnUntraced(function* (threadId, runId, operational) {
|
|
4089
|
+
if (operational === void 0) {
|
|
4090
|
+
const loaded = yield* reader.readExecution({
|
|
4091
|
+
threadId,
|
|
4092
|
+
runId
|
|
4093
|
+
}).pipe(Effect.catchTag("ThreadNotMaterialized", () => Effect.succeed(Option.none())));
|
|
4094
|
+
if (Option.isNone(loaded)) return void 0;
|
|
4095
|
+
operational = loaded.value.operational;
|
|
4096
|
+
}
|
|
4088
4097
|
const recordId = runStartedRecordId(runId);
|
|
4089
|
-
const starts =
|
|
4090
|
-
const existing =
|
|
4098
|
+
const starts = operational.filter(({ payload }) => payload._tag === "RunStarted");
|
|
4099
|
+
const existing = operational.find((record) => record.recordId === recordId);
|
|
4091
4100
|
if (starts.length > 1 || starts.length === 1 && starts[0]?.recordId !== recordId || existing !== void 0 && (existing.payload._tag !== "RunStarted" || existing.payload.runId !== runId)) return yield* RunJournalError.make({ message: `Run ${runId} has conflicting active start state` });
|
|
4092
4101
|
return existing;
|
|
4093
4102
|
});
|
|
4094
|
-
const makeRunStart = Effect.fnUntraced(function* (submission, maxDurationMillis, records) {
|
|
4103
|
+
const makeRunStart = Effect.fnUntraced(function* (submission, maxDurationMillis, records, operational) {
|
|
4095
4104
|
const writer = yield* CurrentRunWriter;
|
|
4096
4105
|
const runId = runIdForSubmission(submission.submissionId);
|
|
4097
4106
|
const recordId = runStartedRecordId(runId);
|
|
4098
|
-
const existing = yield* readRunStart(submission.threadId, runId);
|
|
4107
|
+
const existing = yield* readRunStart(submission.threadId, runId, operational);
|
|
4099
4108
|
let start;
|
|
4100
4109
|
let allowance = maxDurationMillis;
|
|
4101
4110
|
let committed = existing !== void 0;
|
|
@@ -4942,1474 +4951,1476 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
4942
4951
|
})).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
|
|
4943
4952
|
knownIds.add(recordId);
|
|
4944
4953
|
});
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
let journal = cached !== void 0 && cached.threadId === ctx.threadId && cached.through === projectionThrough && cached.runId === runId && cached.contextRecordId === priorContext?.recordId ? (boundaries.push(...cached.boundaries), cached.contextEvidence.forEach(retainHistory), cached.journal) : yield* projectRunJournalStream(canonical, runId, (boundary) => boundaries.push(boundary), priorContext, journalMetadata, priorContext === void 0 ? retainHistory : void 0);
|
|
4970
|
-
if (initialJournal?.prefix !== void 0) {
|
|
4971
|
-
const prompt = initialJournal.prefix.prompt;
|
|
4972
|
-
journal = {
|
|
4973
|
-
...journal,
|
|
4974
|
-
prompt,
|
|
4975
|
-
historyBefore: prompt
|
|
4954
|
+
const runModel = Effect.fnUntraced(
|
|
4955
|
+
/**
|
|
4956
|
+
* Drive the shared interpreter Effect with history rebuilt by the run journal, commit
|
|
4957
|
+
* each Turn under the local owner, and watch for durable abort intent. Engine Run failures settle `failed`; coordinator failures abort the
|
|
4958
|
+
* Attempt cleanly with the obligation still owed.
|
|
4959
|
+
*
|
|
4960
|
+
* The interpreter supplies validated response, closed Tool-result, and completion facts.
|
|
4961
|
+
* Responses precede approval and effectful dispatch; readonly responses may join their closed
|
|
4962
|
+
* results. Tool results precede input drains and the next Turn. A no-tool response and Run
|
|
4963
|
+
* completion share one batch. A completion Tool's result
|
|
4964
|
+
* precedes its terminal-only completion batch, so recovery can repeat a pure output projection
|
|
4965
|
+
* without replaying the handler. Pending batches resume from their canonical declarations.
|
|
4966
|
+
*/
|
|
4967
|
+
function* (agent, ctx, submission, session, records, canonical, initialJournal, canonicalThrough, progressThrough, continuation, priorContext, journalMetadata, lineage, approvalDecisions, currentContracts, runTiming, yieldAfter) {
|
|
4968
|
+
const submissionId = submission.submissionId;
|
|
4969
|
+
const runId = runIdForSubmission(submissionId);
|
|
4970
|
+
const boundaries = [];
|
|
4971
|
+
const cached = projectedJournal;
|
|
4972
|
+
const projectionThrough = Math.max(progressThrough ?? 0, records.at(-1)?.sequence ?? 0);
|
|
4973
|
+
const originalInput = records.find(({ record: { payload } }) => payload._tag === "UserInputRecorded" && payload.kind === "user" && payload.submissionId === submissionId);
|
|
4974
|
+
if (originalInput === void 0) return yield* RunJournalError.make({ message: "Run has no original context boundary" });
|
|
4975
|
+
const historyEvidence = /* @__PURE__ */ new Map();
|
|
4976
|
+
const retainHistory = (entry) => {
|
|
4977
|
+
if (priorContext === void 0 && entry.sequence < originalInput.sequence) historyEvidence.set(entry.record.recordId, entry);
|
|
4976
4978
|
};
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
runId,
|
|
4986
|
-
contextRecordId: priorContext?.recordId,
|
|
4987
|
-
contextEvidence: [...historyEvidence.values()],
|
|
4988
|
-
journal,
|
|
4989
|
-
boundaries
|
|
4990
|
-
};
|
|
4991
|
-
if (continuation !== void 0) {
|
|
4992
|
-
const accounting = continuation.accounting;
|
|
4993
|
-
if ([
|
|
4994
|
-
"committedTurns",
|
|
4995
|
-
"toolCalls",
|
|
4996
|
-
"programmaticToolCalls",
|
|
4997
|
-
"consecutiveToolFailures",
|
|
4998
|
-
"finalizationUsed",
|
|
4999
|
-
"modelRestarts"
|
|
5000
|
-
].some((field) => (journal.policyUsage[field] ?? 0) !== accounting[field]) || [
|
|
5001
|
-
"modelCalls",
|
|
5002
|
-
"inputTokens",
|
|
5003
|
-
"outputTokens",
|
|
5004
|
-
"lastInputTokens",
|
|
5005
|
-
"lastOutputTokens",
|
|
5006
|
-
"costMicrousd"
|
|
5007
|
-
].some((field) => journal.usage[field] !== accounting[field]) || (journal.usage.unobservedModelCalls ?? 0) !== accounting.unobservedModelCalls) return yield* RunJournalError.make({ message: "Canonical continuation accounting differs from its exact execution evidence" });
|
|
5008
|
-
}
|
|
5009
|
-
const childLineage = records.find(({ record }) => record.recordId === subagentLineageRecordId(submission.threadId))?.record.payload;
|
|
5010
|
-
const inheritedGrant = submission.workerAdmission?.origin.grant ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.grant : void 0);
|
|
5011
|
-
const delegationDepth = submission.workerAdmission?.origin.depth ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.parentLink.depth : 0);
|
|
5012
|
-
const inheritedBudget = submission.workerAdmission?.origin.budget ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.budget : void 0);
|
|
5013
|
-
if (submission.parentLinkage !== void 0 && (childLineage?._tag !== "SubagentLineageRecorded" || childLineage.parentSubmissionId !== submission.parentLinkage.parentSubmissionId || childLineage.parentLink.parentToolCallId !== submission.parentLinkage.parentToolCallId || !definitionDigestsEqual(childLineage.childDefinitionDigests, submission.agentDigests) || childLineage.childInputDigest !== submission.inputDigest)) return yield* RunJournalError.make({ message: "The child Run has no matching canonical lineage and execution bounds" });
|
|
5014
|
-
const completionTools = [...agent.definition.completion === void 0 ? [] : [agent.definition.completion.tool], ...agent.definition.completionFromTools?.map((declaration) => declaration.tool) ?? []];
|
|
5015
|
-
const pending = yield* pendingToolBatchFor(records, runId, completionTools);
|
|
5016
|
-
const resumeProjection = pending === void 0 ? journal : yield* projectRunJournalStream(withoutPendingBatch(canonical, pending, runId), runId, void 0, priorContext);
|
|
5017
|
-
if (initialJournal !== void 0 && (journal.committedTurns !== 0 || journal.historyFrom !== 1 || journal.contextWindowId !== void 0 || historyEvidence.size !== 0 || pending !== void 0 || boundaries.some((boundary) => boundary.incomplete))) initialJournal.cacheable = false;
|
|
5018
|
-
if (initialJournal?.cacheable) initialJournal.history = initialJournal.prefix ?? preparePromptHistory(journal.historyBefore);
|
|
5019
|
-
if (initialJournal !== void 0) initialJournal.records = void 0;
|
|
5020
|
-
const rolloverOperation = journal.pendingContextToolCallId === void 0 ? void 0 : operationsFor(records, runId).get(journal.pendingContextToolCallId);
|
|
5021
|
-
const rolloverTool = rolloverOperation === void 0 ? void 0 : agent.definition.toolkit.tools[rolloverOperation.toolName];
|
|
5022
|
-
const pendingContextToolCallId = rolloverOperation !== void 0 && rolloverTool !== void 0 && Context.get(rolloverTool.annotations, ContextRolloverTool) && currentContracts[rolloverOperation.toolName] === rolloverOperation.replay ? journal.pendingContextToolCallId : void 0;
|
|
5023
|
-
const applicationCalls = pending?.calls.filter((call) => !call.providerExecuted);
|
|
5024
|
-
const completionCandidate = applicationCalls?.length === 1 && completionTools.some((tool) => tool === applicationCalls[0]?.name) && pending?.settled.some((result) => result.id === applicationCalls[0]?.id && !result.isFailure) ? applicationCalls[0] : void 0;
|
|
5025
|
-
const settledCompletion = pending !== void 0 && completionCandidate !== void 0 && supportsOperation(OpenToolCallEvidence.make({
|
|
5026
|
-
toolCallId: Schema.decodeSync(ToolCallId)(completionCandidate.id),
|
|
5027
|
-
toolName: completionCandidate.name,
|
|
5028
|
-
turn: pending.turn
|
|
5029
|
-
}), pending.toolOperations.find((operation) => operation.toolCallId === completionCandidate.id), {
|
|
5030
|
-
definition: agent.definition,
|
|
5031
|
-
contracts: currentContracts
|
|
5032
|
-
}) ? Schema.decodeSync(ToolCallId)(completionCandidate.id) : void 0;
|
|
5033
|
-
const knownIds = knownRecordIdsOf(records);
|
|
5034
|
-
const stepOutputs = /* @__PURE__ */ new Map();
|
|
5035
|
-
for (const envelope of records) {
|
|
5036
|
-
const payload = envelope.record.payload;
|
|
5037
|
-
if (payload._tag === "ToolStepSettled" && payload.runId === runId) stepOutputs.set(toolStepSettledRecordId(runId, payload.toolCallId, payload.stepName), payload.output);
|
|
5038
|
-
}
|
|
5039
|
-
const canonicalApprovalDecisions = /* @__PURE__ */ new Map();
|
|
5040
|
-
const approvalRequestedTurns = /* @__PURE__ */ new Set();
|
|
5041
|
-
for (const envelope of records) {
|
|
5042
|
-
const payload = envelope.record.payload;
|
|
5043
|
-
if (payload._tag === "ToolApprovalDecided" && payload.runId === runId) canonicalApprovalDecisions.set(payload.toolCallId, payload.decision);
|
|
5044
|
-
else if (payload._tag === "ToolApprovalRequested" && payload.runId === runId) approvalRequestedTurns.add(payload.turn);
|
|
5045
|
-
}
|
|
5046
|
-
const approvalIntents = /* @__PURE__ */ new Map();
|
|
5047
|
-
for (const intent of approvalDecisions) approvalIntents.set(intent.toolCallId, intent);
|
|
5048
|
-
const joinedInputEnvelopes = /* @__PURE__ */ new Map();
|
|
5049
|
-
let lastHostResponseSequence;
|
|
5050
|
-
for (const envelope of records) {
|
|
5051
|
-
const payload = envelope.record.payload;
|
|
5052
|
-
if (payload._tag === "UserInputRecorded" && payload.runId === runId && payload.submissionId !== void 0 && payload.submissionId !== submissionId) joinedInputEnvelopes.set(payload.submissionId, envelope);
|
|
5053
|
-
else if (payload._tag === "ModelResponseRecorded" && payload.runId === runId) {
|
|
5054
|
-
if (lastHostResponseSequence === void 0 || envelope.sequence > lastHostResponseSequence) lastHostResponseSequence = envelope.sequence;
|
|
4979
|
+
let journal = cached !== void 0 && cached.threadId === ctx.threadId && cached.through === projectionThrough && cached.runId === runId && cached.contextRecordId === priorContext?.recordId ? (boundaries.push(...cached.boundaries), cached.contextEvidence.forEach(retainHistory), cached.journal) : yield* projectRunJournalStream(canonical, runId, (boundary) => boundaries.push(boundary), priorContext, journalMetadata, priorContext === void 0 ? retainHistory : void 0);
|
|
4980
|
+
if (initialJournal?.prefix !== void 0) {
|
|
4981
|
+
const prompt = initialJournal.prefix.prompt;
|
|
4982
|
+
journal = {
|
|
4983
|
+
...journal,
|
|
4984
|
+
prompt,
|
|
4985
|
+
historyBefore: prompt
|
|
4986
|
+
};
|
|
5055
4987
|
}
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
outputTokens: modelUsage.reduce((sum, call) => sum + call.outputTokens.total, 0),
|
|
5069
|
-
costMicrousd: modelUsage.reduce((sum, call) => sum + call.costMicrousd, 0)
|
|
4988
|
+
journalMetadata = void 0;
|
|
4989
|
+
historyEvidence.forEach((entry, id) => {
|
|
4990
|
+
if (entry.sequence >= journal.historyFrom) historyEvidence.delete(id);
|
|
4991
|
+
});
|
|
4992
|
+
projectedJournal = {
|
|
4993
|
+
threadId: ctx.threadId,
|
|
4994
|
+
through: CanonicalSequence.make(projectionThrough),
|
|
4995
|
+
runId,
|
|
4996
|
+
contextRecordId: priorContext?.recordId,
|
|
4997
|
+
contextEvidence: [...historyEvidence.values()],
|
|
4998
|
+
journal,
|
|
4999
|
+
boundaries
|
|
5070
5000
|
};
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5001
|
+
if (continuation !== void 0) {
|
|
5002
|
+
const accounting = continuation.accounting;
|
|
5003
|
+
if ([
|
|
5004
|
+
"committedTurns",
|
|
5005
|
+
"toolCalls",
|
|
5006
|
+
"programmaticToolCalls",
|
|
5007
|
+
"consecutiveToolFailures",
|
|
5008
|
+
"finalizationUsed",
|
|
5009
|
+
"modelRestarts"
|
|
5010
|
+
].some((field) => (journal.policyUsage[field] ?? 0) !== accounting[field]) || [
|
|
5011
|
+
"modelCalls",
|
|
5012
|
+
"inputTokens",
|
|
5013
|
+
"outputTokens",
|
|
5014
|
+
"lastInputTokens",
|
|
5015
|
+
"lastOutputTokens",
|
|
5016
|
+
"costMicrousd"
|
|
5017
|
+
].some((field) => journal.usage[field] !== accounting[field]) || (journal.usage.unobservedModelCalls ?? 0) !== accounting.unobservedModelCalls) return yield* RunJournalError.make({ message: "Canonical continuation accounting differs from its exact execution evidence" });
|
|
5079
5018
|
}
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
const
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
const
|
|
5096
|
-
const
|
|
5097
|
-
|
|
5019
|
+
const childLineage = records.find(({ record }) => record.recordId === subagentLineageRecordId(submission.threadId))?.record.payload;
|
|
5020
|
+
const inheritedGrant = submission.workerAdmission?.origin.grant ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.grant : void 0);
|
|
5021
|
+
const delegationDepth = submission.workerAdmission?.origin.depth ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.parentLink.depth : 0);
|
|
5022
|
+
const inheritedBudget = submission.workerAdmission?.origin.budget ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.budget : void 0);
|
|
5023
|
+
if (submission.parentLinkage !== void 0 && (childLineage?._tag !== "SubagentLineageRecorded" || childLineage.parentSubmissionId !== submission.parentLinkage.parentSubmissionId || childLineage.parentLink.parentToolCallId !== submission.parentLinkage.parentToolCallId || !definitionDigestsEqual(childLineage.childDefinitionDigests, submission.agentDigests) || childLineage.childInputDigest !== submission.inputDigest)) return yield* RunJournalError.make({ message: "The child Run has no matching canonical lineage and execution bounds" });
|
|
5024
|
+
const completionTools = [...agent.definition.completion === void 0 ? [] : [agent.definition.completion.tool], ...agent.definition.completionFromTools?.map((declaration) => declaration.tool) ?? []];
|
|
5025
|
+
const pending = yield* pendingToolBatchFor(records, runId, completionTools);
|
|
5026
|
+
const resumeProjection = pending === void 0 ? journal : yield* projectRunJournalStream(withoutPendingBatch(canonical, pending, runId), runId, void 0, priorContext);
|
|
5027
|
+
if (initialJournal !== void 0 && (journal.committedTurns !== 0 || journal.historyFrom !== 1 || journal.contextWindowId !== void 0 || historyEvidence.size !== 0 || pending !== void 0 || boundaries.some((boundary) => boundary.incomplete))) initialJournal.cacheable = false;
|
|
5028
|
+
if (initialJournal?.cacheable) initialJournal.history = initialJournal.prefix ?? preparePromptHistory(journal.historyBefore);
|
|
5029
|
+
if (initialJournal !== void 0) initialJournal.records = void 0;
|
|
5030
|
+
const rolloverOperation = journal.pendingContextToolCallId === void 0 ? void 0 : operationsFor(records, runId).get(journal.pendingContextToolCallId);
|
|
5031
|
+
const rolloverTool = rolloverOperation === void 0 ? void 0 : agent.definition.toolkit.tools[rolloverOperation.toolName];
|
|
5032
|
+
const pendingContextToolCallId = rolloverOperation !== void 0 && rolloverTool !== void 0 && Context.get(rolloverTool.annotations, ContextRolloverTool) && currentContracts[rolloverOperation.toolName] === rolloverOperation.replay ? journal.pendingContextToolCallId : void 0;
|
|
5033
|
+
const applicationCalls = pending?.calls.filter((call) => !call.providerExecuted);
|
|
5034
|
+
const completionCandidate = applicationCalls?.length === 1 && completionTools.some((tool) => tool === applicationCalls[0]?.name) && pending?.settled.some((result) => result.id === applicationCalls[0]?.id && !result.isFailure) ? applicationCalls[0] : void 0;
|
|
5035
|
+
const settledCompletion = pending !== void 0 && completionCandidate !== void 0 && supportsOperation(OpenToolCallEvidence.make({
|
|
5036
|
+
toolCallId: Schema.decodeSync(ToolCallId)(completionCandidate.id),
|
|
5037
|
+
toolName: completionCandidate.name,
|
|
5038
|
+
turn: pending.turn
|
|
5039
|
+
}), pending.toolOperations.find((operation) => operation.toolCallId === completionCandidate.id), {
|
|
5040
|
+
definition: agent.definition,
|
|
5041
|
+
contracts: currentContracts
|
|
5042
|
+
}) ? Schema.decodeSync(ToolCallId)(completionCandidate.id) : void 0;
|
|
5043
|
+
const knownIds = knownRecordIdsOf(records);
|
|
5044
|
+
const stepOutputs = /* @__PURE__ */ new Map();
|
|
5045
|
+
for (const envelope of records) {
|
|
5046
|
+
const payload = envelope.record.payload;
|
|
5047
|
+
if (payload._tag === "ToolStepSettled" && payload.runId === runId) stepOutputs.set(toolStepSettledRecordId(runId, payload.toolCallId, payload.stepName), payload.output);
|
|
5048
|
+
}
|
|
5049
|
+
const canonicalApprovalDecisions = /* @__PURE__ */ new Map();
|
|
5050
|
+
const approvalRequestedTurns = /* @__PURE__ */ new Set();
|
|
5051
|
+
for (const envelope of records) {
|
|
5052
|
+
const payload = envelope.record.payload;
|
|
5053
|
+
if (payload._tag === "ToolApprovalDecided" && payload.runId === runId) canonicalApprovalDecisions.set(payload.toolCallId, payload.decision);
|
|
5054
|
+
else if (payload._tag === "ToolApprovalRequested" && payload.runId === runId) approvalRequestedTurns.add(payload.turn);
|
|
5055
|
+
}
|
|
5056
|
+
const approvalIntents = /* @__PURE__ */ new Map();
|
|
5057
|
+
for (const intent of approvalDecisions) approvalIntents.set(intent.toolCallId, intent);
|
|
5058
|
+
const joinedInputEnvelopes = /* @__PURE__ */ new Map();
|
|
5059
|
+
let lastHostResponseSequence;
|
|
5060
|
+
for (const envelope of records) {
|
|
5061
|
+
const payload = envelope.record.payload;
|
|
5062
|
+
if (payload._tag === "UserInputRecorded" && payload.runId === runId && payload.submissionId !== void 0 && payload.submissionId !== submissionId) joinedInputEnvelopes.set(payload.submissionId, envelope);
|
|
5063
|
+
else if (payload._tag === "ModelResponseRecorded" && payload.runId === runId) {
|
|
5064
|
+
if (lastHostResponseSequence === void 0 || envelope.sequence > lastHostResponseSequence) lastHostResponseSequence = envelope.sequence;
|
|
5065
|
+
}
|
|
5066
|
+
}
|
|
5067
|
+
const stagedUsage = /* @__PURE__ */ new Map();
|
|
5068
|
+
const committedUsageLengths = /* @__PURE__ */ new Map();
|
|
5069
|
+
const committedUnobservedCalls = /* @__PURE__ */ new Map();
|
|
5070
|
+
const usageForCommit = (turn) => {
|
|
5071
|
+
const staged = stagedUsage.get(turn);
|
|
5072
|
+
if (staged === void 0) return void 0;
|
|
5073
|
+
const modelUsage = staged.modelUsage.slice(committedUsageLengths.get(turn) ?? 0);
|
|
5074
|
+
if (modelUsage.length === 0) return void 0;
|
|
5075
|
+
return {
|
|
5076
|
+
modelUsage,
|
|
5077
|
+
inputTokens: modelUsage.reduce((sum, call) => sum + call.inputTokens.total, 0),
|
|
5078
|
+
outputTokens: modelUsage.reduce((sum, call) => sum + call.outputTokens.total, 0),
|
|
5079
|
+
costMicrousd: modelUsage.reduce((sum, call) => sum + call.costMicrousd, 0)
|
|
5080
|
+
};
|
|
5081
|
+
};
|
|
5082
|
+
const unobservedForCommit = (turn) => (stagedUnobservedCalls.get(turn) ?? 0) - (committedUnobservedCalls.get(turn) ?? 0);
|
|
5083
|
+
const recordCommittedUsage = (batch) => {
|
|
5084
|
+
for (const record of batch.records) {
|
|
5085
|
+
if (record.payload._tag !== "ModelResponseRecorded" && record.payload._tag !== "ModelCallAborted") continue;
|
|
5086
|
+
const payload = record.payload;
|
|
5087
|
+
committedUsageLengths.set(payload.turn, (committedUsageLengths.get(payload.turn) ?? 0) + (payload.modelUsage?.length ?? 0));
|
|
5088
|
+
committedUnobservedCalls.set(payload.turn, (committedUnobservedCalls.get(payload.turn) ?? 0) + (payload.unobservedModelCalls ?? 0));
|
|
5089
|
+
}
|
|
5090
|
+
progressWriters.get(ctx)?.stageUsage(runId, terminalUsageCharge(uncommittedModelUsage()));
|
|
5091
|
+
};
|
|
5092
|
+
const uncommittedModelUsage = () => [...stagedUsage.entries()].flatMap(([turn, usage]) => usage.modelUsage.slice(committedUsageLengths.get(turn) ?? 0));
|
|
5093
|
+
const stagedUnobservedCalls = /* @__PURE__ */ new Map();
|
|
5094
|
+
let interruptedUsage = records.some(({ record }) => record.payload._tag === "ModelResponseInterrupted" && record.payload.runId === runId);
|
|
5095
|
+
const checkedUsageTotal = (field, value) => decodeUsageTotal(value).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
5096
|
+
message: `Run usage summary exceeds safe-integer bounds at ${field}`,
|
|
5098
5097
|
cause
|
|
5099
5098
|
})));
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5099
|
+
const addUsageTotal = (field, left, right) => checkedUsageTotal(field, left + right);
|
|
5100
|
+
const subtractUsageTotal = (field, left, right) => checkedUsageTotal(field, left - right);
|
|
5101
|
+
const currentUsageSummary = () => Effect.gen(function* () {
|
|
5102
|
+
const stagedCalls = [...stagedUsage.values()].flatMap((usage) => usage.modelUsage);
|
|
5103
|
+
let unobservedModelCalls = journal.usage.unobservedModelCalls ?? 0;
|
|
5104
|
+
for (const count of stagedUnobservedCalls.values()) unobservedModelCalls = yield* addUsageTotal("unobservedModelCalls", unobservedModelCalls, count);
|
|
5105
|
+
const detailedCalls = [...journal.usage.modelUsage, ...stagedCalls];
|
|
5106
|
+
const detailed = yield* summarizeModelUsage(detailedCalls, journal.usage.summarizedModelUsage).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
5107
|
+
message: "Run detailed usage exceeds safe-integer accounting bounds",
|
|
5108
|
+
cause
|
|
5109
|
+
})));
|
|
5110
|
+
let inputTokens = journal.usage.inputTokens;
|
|
5111
|
+
let outputTokens = journal.usage.outputTokens;
|
|
5112
|
+
let costMicrousd = journal.usage.costMicrousd;
|
|
5113
|
+
for (const usage of stagedUsage.values()) {
|
|
5114
|
+
inputTokens = yield* addUsageTotal("inputTokens", inputTokens, usage.inputTokens);
|
|
5115
|
+
outputTokens = yield* addUsageTotal("outputTokens", outputTokens, usage.outputTokens);
|
|
5116
|
+
costMicrousd = yield* addUsageTotal("costMicrousd", costMicrousd, usage.costMicrousd);
|
|
5117
|
+
}
|
|
5118
|
+
const modelCalls = yield* addUsageTotal("modelCalls", journal.usage.modelCalls, stagedCalls.length);
|
|
5119
|
+
const legacyCalls = yield* subtractUsageTotal("legacy.modelCalls", modelCalls, detailed.modelCalls);
|
|
5120
|
+
const legacyInput = yield* subtractUsageTotal("legacy.inputTokens", inputTokens, detailed.inputTokens.total);
|
|
5121
|
+
const legacyOutput = yield* subtractUsageTotal("legacy.outputTokens", outputTokens, detailed.outputTokens.total);
|
|
5122
|
+
const legacyCost = yield* subtractUsageTotal("legacy.costMicrousd", costMicrousd, detailed.costMicrousd);
|
|
5123
|
+
if (legacyCalls === 0 && (legacyInput !== 0 || legacyOutput !== 0 || legacyCost !== 0)) return yield* RunJournalError.make({ message: "Run aggregate usage has legacy totals without a legacy model call" });
|
|
5124
|
+
const byModel = [...detailed.byModel];
|
|
5125
|
+
if (legacyCalls > 0) {
|
|
5126
|
+
const existingIndex = byModel.findIndex((group) => group.provider === "unknown" && group.model === "legacy-record" && group.responseModel === void 0 && group.serviceTier === void 0 && group.pricingVersion === void 0);
|
|
5127
|
+
const existing = existingIndex < 0 ? void 0 : byModel[existingIndex];
|
|
5128
|
+
const legacyGroup = ModelUsageGroup.make({
|
|
5129
|
+
provider: "unknown",
|
|
5130
|
+
model: "legacy-record",
|
|
5131
|
+
modelCalls: yield* addUsageTotal("byModel.modelCalls", existing?.modelCalls ?? 0, legacyCalls),
|
|
5132
|
+
inputTokens: InputTokenUsage.make({
|
|
5133
|
+
total: yield* addUsageTotal("byModel.inputTokens.total", existing?.inputTokens.total ?? 0, legacyInput),
|
|
5134
|
+
uncached: yield* addUsageTotal("byModel.inputTokens.uncached", existing?.inputTokens.uncached ?? 0, legacyInput),
|
|
5135
|
+
cacheRead: existing?.inputTokens.cacheRead ?? 0,
|
|
5136
|
+
cacheWrite: existing?.inputTokens.cacheWrite ?? 0
|
|
5137
|
+
}),
|
|
5138
|
+
outputTokens: OutputTokenUsage.make({
|
|
5139
|
+
total: yield* addUsageTotal("byModel.outputTokens.total", existing?.outputTokens.total ?? 0, legacyOutput),
|
|
5140
|
+
text: yield* addUsageTotal("byModel.outputTokens.text", existing?.outputTokens.text ?? 0, legacyOutput),
|
|
5141
|
+
reasoning: existing?.outputTokens.reasoning ?? 0
|
|
5142
|
+
}),
|
|
5143
|
+
costMicrousd: yield* addUsageTotal("byModel.costMicrousd", existing?.costMicrousd ?? 0, legacyCost)
|
|
5144
|
+
});
|
|
5145
|
+
if (existingIndex < 0) byModel.push(legacyGroup);
|
|
5146
|
+
else byModel[existingIndex] = legacyGroup;
|
|
5147
|
+
}
|
|
5148
|
+
const uncached = yield* addUsageTotal("inputTokens.uncached", detailed.inputTokens.uncached, legacyInput);
|
|
5149
|
+
const text = yield* addUsageTotal("outputTokens.text", detailed.outputTokens.text, legacyOutput);
|
|
5150
|
+
return RunUsageSummary.make({
|
|
5151
|
+
...legacyCalls === 0 && detailed.webSearchCalls !== void 0 ? { webSearchCalls: detailed.webSearchCalls } : {},
|
|
5152
|
+
modelCalls,
|
|
5122
5153
|
inputTokens: InputTokenUsage.make({
|
|
5123
|
-
total:
|
|
5124
|
-
uncached
|
|
5125
|
-
cacheRead:
|
|
5126
|
-
cacheWrite:
|
|
5154
|
+
total: inputTokens,
|
|
5155
|
+
uncached,
|
|
5156
|
+
cacheRead: detailed.inputTokens.cacheRead,
|
|
5157
|
+
cacheWrite: detailed.inputTokens.cacheWrite
|
|
5127
5158
|
}),
|
|
5128
5159
|
outputTokens: OutputTokenUsage.make({
|
|
5129
|
-
total:
|
|
5130
|
-
text
|
|
5131
|
-
reasoning:
|
|
5160
|
+
total: outputTokens,
|
|
5161
|
+
text,
|
|
5162
|
+
reasoning: detailed.outputTokens.reasoning
|
|
5132
5163
|
}),
|
|
5133
|
-
costMicrousd
|
|
5164
|
+
costMicrousd,
|
|
5165
|
+
byModel,
|
|
5166
|
+
unobservedModelCalls,
|
|
5167
|
+
usageStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.usageStatus === "unknown" ? "unknown" : "partial" : detailed.usageStatus,
|
|
5168
|
+
pricingStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.pricingStatus === "unknown" ? "unknown" : "partial" : detailed.pricingStatus
|
|
5134
5169
|
});
|
|
5135
|
-
if (existingIndex < 0) byModel.push(legacyGroup);
|
|
5136
|
-
else byModel[existingIndex] = legacyGroup;
|
|
5137
|
-
}
|
|
5138
|
-
const uncached = yield* addUsageTotal("inputTokens.uncached", detailed.inputTokens.uncached, legacyInput);
|
|
5139
|
-
const text = yield* addUsageTotal("outputTokens.text", detailed.outputTokens.text, legacyOutput);
|
|
5140
|
-
return RunUsageSummary.make({
|
|
5141
|
-
...legacyCalls === 0 && detailed.webSearchCalls !== void 0 ? { webSearchCalls: detailed.webSearchCalls } : {},
|
|
5142
|
-
modelCalls,
|
|
5143
|
-
inputTokens: InputTokenUsage.make({
|
|
5144
|
-
total: inputTokens,
|
|
5145
|
-
uncached,
|
|
5146
|
-
cacheRead: detailed.inputTokens.cacheRead,
|
|
5147
|
-
cacheWrite: detailed.inputTokens.cacheWrite
|
|
5148
|
-
}),
|
|
5149
|
-
outputTokens: OutputTokenUsage.make({
|
|
5150
|
-
total: outputTokens,
|
|
5151
|
-
text,
|
|
5152
|
-
reasoning: detailed.outputTokens.reasoning
|
|
5153
|
-
}),
|
|
5154
|
-
costMicrousd,
|
|
5155
|
-
byModel,
|
|
5156
|
-
unobservedModelCalls,
|
|
5157
|
-
usageStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.usageStatus === "unknown" ? "unknown" : "partial" : detailed.usageStatus,
|
|
5158
|
-
pricingStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.pricingStatus === "unknown" ? "unknown" : "partial" : detailed.pricingStatus
|
|
5159
5170
|
});
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
};
|
|
5184
|
-
}
|
|
5185
|
-
let ownerFirstSequence;
|
|
5186
|
-
for (const envelope of records) {
|
|
5187
|
-
const payload = envelope.record.payload;
|
|
5188
|
-
if ("runId" in payload && payload.runId === runId) {
|
|
5189
|
-
ownerFirstSequence = envelope.sequence;
|
|
5190
|
-
break;
|
|
5171
|
+
const activeExecution = yield* reader.readExecution({
|
|
5172
|
+
threadId: ctx.threadId,
|
|
5173
|
+
runId
|
|
5174
|
+
});
|
|
5175
|
+
const recordedCompletion = Option.isSome(activeExecution) ? activeExecution.value.operational.find((record) => record.recordId === runCompletedRecordId(runId))?.payload : void 0;
|
|
5176
|
+
if (recordedCompletion !== void 0) {
|
|
5177
|
+
if (recordedCompletion._tag !== "RunCompleted" || recordedCompletion.runId !== runId) return yield* RunJournalError.make({ message: `Run ${runId} has an invalid terminal completion marker` });
|
|
5178
|
+
const response = [...records].reverse().find((envelope) => envelope.record.payload._tag === "ModelResponseRecorded" && envelope.record.payload.runId === runId)?.record.payload;
|
|
5179
|
+
if (response?._tag !== "ModelResponseRecorded") return yield* RunJournalError.make({ message: `Run ${runId} has a terminal completion marker without a response` });
|
|
5180
|
+
const calls = (yield* declaredToolCalls(response.messages)).application;
|
|
5181
|
+
if (calls.length > 0) {
|
|
5182
|
+
const call = calls[0];
|
|
5183
|
+
const settled = call === void 0 ? void 0 : records.find(({ record }) => record.payload._tag === "ToolCallSettled" && record.payload.runId === runId && record.payload.toolCallId === call.id)?.record.payload;
|
|
5184
|
+
if (calls.length !== 1 || call === void 0 || settled?._tag !== "ToolCallSettled" || settled.toolName !== call.name || settled.isFailure) return yield* RunJournalError.make({ message: `Run ${runId} has a terminal completion marker without one successful declared Tool result` });
|
|
5185
|
+
}
|
|
5186
|
+
return {
|
|
5187
|
+
_tag: "completed",
|
|
5188
|
+
result: recordedCompletion.output,
|
|
5189
|
+
...recordedCompletion.runDisposition === void 0 ? {} : { runDisposition: recordedCompletion.runDisposition },
|
|
5190
|
+
...recordedCompletion.finishReason === void 0 ? {} : { finishReason: recordedCompletion.finishReason },
|
|
5191
|
+
...recordedCompletion.exhausted === void 0 ? {} : { exhausted: recordedCompletion.exhausted },
|
|
5192
|
+
usageSummary: yield* currentUsageSummary()
|
|
5193
|
+
};
|
|
5191
5194
|
}
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
const declaredNamesByCallId = /* @__PURE__ */ new Map();
|
|
5199
|
-
const subagentState = subagentRecordsOf(records, runId);
|
|
5200
|
-
const declaredToolIds = new Set(subagentState.declaredNames.keys());
|
|
5201
|
-
if (declaredToolIds.size > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
|
|
5202
|
-
for (const [callId, name] of subagentState.declaredNames) declaredNamesByCallId.set(callId, name);
|
|
5203
|
-
if (pending !== void 0) for (const call of pending.calls) {
|
|
5204
|
-
encodedParamsByCallId.set(call.id, call.params);
|
|
5205
|
-
declaredNamesByCallId.set(call.id, call.name);
|
|
5206
|
-
}
|
|
5207
|
-
let resumeLeadingMessages;
|
|
5208
|
-
let resumeResponseMessages;
|
|
5209
|
-
if (pending !== void 0) {
|
|
5210
|
-
const pendingMessages = yield* decodePrompt(pending.messages).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
5211
|
-
message: "Pending ModelResponseRecorded messages are not Schema-encoded Prompt messages",
|
|
5212
|
-
cause
|
|
5213
|
-
})));
|
|
5214
|
-
const firstAssistant = pendingMessages.content.findIndex((message) => message.role === "assistant");
|
|
5215
|
-
if (firstAssistant > 0) resumeLeadingMessages = Prompt.fromMessages(pendingMessages.content.slice(0, firstAssistant).filter((message) => message.role !== "system"));
|
|
5216
|
-
if (firstAssistant >= 0) resumeResponseMessages = Prompt.fromMessages(pendingMessages.content.slice(firstAssistant));
|
|
5217
|
-
}
|
|
5218
|
-
const initialDispatchProofTurns = new Set(initialDispatchBlockedTurns(records, runId));
|
|
5219
|
-
let currentToolTurn = pending === void 0 ? void 0 : {
|
|
5220
|
-
turn: pending.turn,
|
|
5221
|
-
turnId: pending.turnId
|
|
5222
|
-
};
|
|
5223
|
-
const haltRef = yield* Ref.make(void 0);
|
|
5224
|
-
const yieldSignal = yield* Deferred.make();
|
|
5225
|
-
const recordHalt = (effect) => effect.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, (failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? failure.cause : new CoordinatorHalt(failure)))));
|
|
5226
|
-
const checkpoint = recordHalt(Effect.gen(function* () {
|
|
5227
|
-
const failure = yield* Ref.get(haltRef);
|
|
5228
|
-
if (failure !== void 0) return yield* failure;
|
|
5229
|
-
const progress = progressWriters.get(ctx);
|
|
5230
|
-
if (progress !== void 0) yield* progress.check(runId).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
5231
|
-
}));
|
|
5232
|
-
const responseGate = yield* Semaphore.make(1);
|
|
5233
|
-
let deferredResponse;
|
|
5234
|
-
const acceptResponseDeclarations = (batch) => {
|
|
5235
|
-
for (const record of batch.records) {
|
|
5236
|
-
if (record.payload._tag !== "ModelResponseRecorded") continue;
|
|
5237
|
-
for (const call of record.payload.toolOperations) {
|
|
5238
|
-
declaredToolIds.add(call.toolCallId);
|
|
5239
|
-
declaredNamesByCallId.set(call.toolCallId, call.toolName);
|
|
5195
|
+
let ownerFirstSequence;
|
|
5196
|
+
for (const envelope of records) {
|
|
5197
|
+
const payload = envelope.record.payload;
|
|
5198
|
+
if ("runId" in payload && payload.runId === runId) {
|
|
5199
|
+
ownerFirstSequence = envelope.sequence;
|
|
5200
|
+
break;
|
|
5240
5201
|
}
|
|
5241
5202
|
}
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
const
|
|
5247
|
-
|
|
5248
|
-
const
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
const
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
yield* appendBatch(ctx, batch);
|
|
5256
|
-
acceptResponseDeclarations(batch);
|
|
5257
|
-
for (const call of calls.application) encodedParamsByCallId.set(call.id, call.params);
|
|
5258
|
-
recordCommittedUsage(batch);
|
|
5259
|
-
for (const entry of batch.records) knownIds.add(entry.recordId);
|
|
5260
|
-
deferredResponse = void 0;
|
|
5261
|
-
yield* hit("turn:after-response-append");
|
|
5262
|
-
});
|
|
5263
|
-
const flushDeferredResponse = promoteResponse.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), responseGate.withPermits(1));
|
|
5264
|
-
let initialHistoryLength = 0;
|
|
5265
|
-
let initialInstructions = [];
|
|
5266
|
-
const completionState = {};
|
|
5267
|
-
const turnCounter = yield* Ref.make(journal.committedTurns + (journal.policyUsage.modelRestarts ?? 0));
|
|
5268
|
-
const idGenerator = {
|
|
5269
|
-
nextThreadId: Effect.succeed(submission.threadId),
|
|
5270
|
-
nextRunId: Effect.succeed(runId),
|
|
5271
|
-
nextTurnId: Ref.modify(turnCounter, (turn) => [turnIdForRun(runId, turn + 1), turn + 1])
|
|
5272
|
-
};
|
|
5273
|
-
const instructionView = (messages, instructions, insertWhenAbsent, priorRunPrefixLength) => {
|
|
5274
|
-
const projected = [];
|
|
5275
|
-
const lengths = [0];
|
|
5276
|
-
let inserted = false;
|
|
5277
|
-
for (const [index, message] of messages.entries()) {
|
|
5278
|
-
if (index >= priorRunPrefixLength && message.role === "system") {
|
|
5279
|
-
if (!inserted) projected.push(...instructions);
|
|
5280
|
-
inserted = true;
|
|
5281
|
-
} else projected.push(message);
|
|
5282
|
-
lengths.push(projected.length);
|
|
5203
|
+
/** Only canonical joined inputs can require restoration from an earlier Attempt. */
|
|
5204
|
+
let joinBacklog = joinedInputEnvelopes.size === 0 ? [] : void 0;
|
|
5205
|
+
/** Joined inputs already handed to the engine during THIS Attempt (never re-deliver). */
|
|
5206
|
+
const deliveredJoinInputs = /* @__PURE__ */ new Set();
|
|
5207
|
+
const encodedParamsByCallId = /* @__PURE__ */ new Map();
|
|
5208
|
+
const declaredNamesByCallId = /* @__PURE__ */ new Map();
|
|
5209
|
+
const subagentState = subagentRecordsOf(records, runId);
|
|
5210
|
+
const declaredToolIds = new Set(subagentState.declaredNames.keys());
|
|
5211
|
+
if (declaredToolIds.size > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
|
|
5212
|
+
for (const [callId, name] of subagentState.declaredNames) declaredNamesByCallId.set(callId, name);
|
|
5213
|
+
if (pending !== void 0) for (const call of pending.calls) {
|
|
5214
|
+
encodedParamsByCallId.set(call.id, call.params);
|
|
5215
|
+
declaredNamesByCallId.set(call.id, call.name);
|
|
5283
5216
|
}
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
};
|
|
5290
|
-
const resumeContext = { prepare: ({ source }) => Effect.sync(() => {
|
|
5291
|
-
const prefix = journal.committedTurns === 0 && priorContext !== void 0 ? priorContext.prompt.content.slice(priorContext.priorHistoryLength) : [];
|
|
5292
|
-
const priorRunPrefixLength = journal.committedTurns === 0 ? resumeProjection.prompt.content.length : resumeProjection.historyBefore.content.length;
|
|
5293
|
-
const view = instructionView(prefix.length === 0 ? resumeProjection.prompt.content : [...resumeProjection.prompt.content, ...prefix], initialInstructions, true, priorRunPrefixLength);
|
|
5294
|
-
return {
|
|
5295
|
-
prompt: Prompt.fromMessages([...view.messages, ...source.content.slice(initialHistoryLength)]),
|
|
5296
|
-
priorRunPrefixLength: view.prefixLength(priorRunPrefixLength)
|
|
5297
|
-
};
|
|
5298
|
-
}) };
|
|
5299
|
-
const externalContext = runContextPreparation.hook;
|
|
5300
|
-
const needsContextReplay = priorContext !== void 0 || journal.committedTurns > 0;
|
|
5301
|
-
const preparedContext = externalContext === void 0 ? needsContextReplay ? resumeContext : void 0 : { prepare: (request) => (needsContextReplay ? resumeContext.prepare(request) : Effect.succeed({
|
|
5302
|
-
prompt: request.source,
|
|
5303
|
-
priorRunPrefixLength: journal.historyBefore.content.length
|
|
5304
|
-
})).pipe(Effect.flatMap(({ prompt, priorRunPrefixLength }) => externalContext.prepare({
|
|
5305
|
-
...request,
|
|
5306
|
-
source: prompt,
|
|
5307
|
-
priorRunPrefixLength
|
|
5308
|
-
})), Effect.map((prepared) => {
|
|
5309
|
-
if (prepared.rollover === void 0 || !knownIds.has(compactionRecordId(runId, request.turn, "rollover"))) return prepared;
|
|
5310
|
-
const { rollover: _, ...retained } = prepared;
|
|
5311
|
-
return retained;
|
|
5312
|
-
})) };
|
|
5313
|
-
const durability = {
|
|
5314
|
-
toolResultMaxBytes: MAX_PERSISTED_JSON_BYTES,
|
|
5315
|
-
checkpoint,
|
|
5316
|
-
initialize: ({ initialHistory, priorHistoryLength }) => recordHalt(Effect.gen(function* () {
|
|
5317
|
-
initialHistoryLength = initialHistory.content.length;
|
|
5318
|
-
initialInstructions = initialHistory.content.slice(priorHistoryLength).filter((message) => message.role === "system");
|
|
5319
|
-
if (priorContext !== void 0) return;
|
|
5320
|
-
const recordId = decodeRecordIdSync(JSON.stringify(["run-context@1", runId]));
|
|
5321
|
-
const prompt = yield* Schema.encodeEffect(Prompt.Prompt)(Prompt.fromMessages(initialHistory.content.slice(priorHistoryLength))).pipe(Effect.flatMap(decodePersisted), Effect.mapError((cause) => RunJournalError.make({
|
|
5322
|
-
message: "Original Run context exceeds persistence bounds",
|
|
5323
|
-
cause
|
|
5324
|
-
})));
|
|
5325
|
-
const history = Prompt.fromMessages(initialHistory.content.slice(0, priorHistoryLength));
|
|
5326
|
-
const historyDigest = yield* withCrypto(digestPromptHistory(history, initialJournal?.history));
|
|
5327
|
-
const retained = yield* Effect.forEach([...historyEvidence.values()].filter((entry) => entry.sequence < journal.historyFrom).sort((left, right) => left.sequence - right.sequence), (entry) => Effect.gen(function* () {
|
|
5328
|
-
const full = yield* getRecord({
|
|
5329
|
-
threadId: ctx.threadId,
|
|
5330
|
-
recordId: entry.record.recordId
|
|
5331
|
-
});
|
|
5332
|
-
if (Option.isNone(full) || full.value.sequence !== entry.sequence) return yield* RunJournalError.make({ message: "Retained history has no exact canonical fact" });
|
|
5333
|
-
return {
|
|
5334
|
-
...yield* withCrypto(reference(full.value.record)),
|
|
5335
|
-
sequence: entry.sequence
|
|
5336
|
-
};
|
|
5337
|
-
}).pipe(Effect.provideService(ThreadReader, reader)));
|
|
5338
|
-
const payload = yield* RunContextRecorded.makeEffect({
|
|
5339
|
-
version: 1,
|
|
5340
|
-
runId,
|
|
5341
|
-
runScopedInput: prompt,
|
|
5342
|
-
historyFrom: journal.historyFrom,
|
|
5343
|
-
historyThrough: CanonicalSequence.make(originalInput.sequence - 1),
|
|
5344
|
-
retained,
|
|
5345
|
-
historyDigest,
|
|
5346
|
-
priorHistoryLength,
|
|
5347
|
-
...journal.contextWindowId === void 0 ? {} : { contextWindowId: journal.contextWindowId }
|
|
5348
|
-
}).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
5349
|
-
message: "Original Run context mapping exceeds its bounds",
|
|
5217
|
+
let resumeLeadingMessages;
|
|
5218
|
+
let resumeResponseMessages;
|
|
5219
|
+
if (pending !== void 0) {
|
|
5220
|
+
const pendingMessages = yield* decodePrompt(pending.messages).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
5221
|
+
message: "Pending ModelResponseRecorded messages are not Schema-encoded Prompt messages",
|
|
5350
5222
|
cause
|
|
5351
5223
|
})));
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5224
|
+
const firstAssistant = pendingMessages.content.findIndex((message) => message.role === "assistant");
|
|
5225
|
+
if (firstAssistant > 0) resumeLeadingMessages = Prompt.fromMessages(pendingMessages.content.slice(0, firstAssistant).filter((message) => message.role !== "system"));
|
|
5226
|
+
if (firstAssistant >= 0) resumeResponseMessages = Prompt.fromMessages(pendingMessages.content.slice(firstAssistant));
|
|
5227
|
+
}
|
|
5228
|
+
const initialDispatchProofTurns = new Set(initialDispatchBlockedTurns(records, runId));
|
|
5229
|
+
let currentToolTurn = pending === void 0 ? void 0 : {
|
|
5230
|
+
turn: pending.turn,
|
|
5231
|
+
turnId: pending.turnId
|
|
5232
|
+
};
|
|
5233
|
+
const haltRef = yield* Ref.make(void 0);
|
|
5234
|
+
const yieldSignal = yield* Deferred.make();
|
|
5235
|
+
const recordHalt = (effect) => effect.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, (failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? failure.cause : new CoordinatorHalt(failure)))));
|
|
5236
|
+
const checkpoint = recordHalt(Effect.gen(function* () {
|
|
5237
|
+
const failure = yield* Ref.get(haltRef);
|
|
5238
|
+
if (failure !== void 0) return yield* failure;
|
|
5239
|
+
const progress = progressWriters.get(ctx);
|
|
5240
|
+
if (progress !== void 0) yield* progress.check(runId).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
5241
|
+
}));
|
|
5242
|
+
const responseGate = yield* Semaphore.make(1);
|
|
5243
|
+
let deferredResponse;
|
|
5244
|
+
const acceptResponseDeclarations = (batch) => {
|
|
5245
|
+
for (const record of batch.records) {
|
|
5246
|
+
if (record.payload._tag !== "ModelResponseRecorded") continue;
|
|
5247
|
+
for (const call of record.payload.toolOperations) {
|
|
5248
|
+
declaredToolIds.add(call.toolCallId);
|
|
5249
|
+
declaredNamesByCallId.set(call.toolCallId, call.toolName);
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
5252
|
+
};
|
|
5253
|
+
const promoteResponse = Effect.gen(function* () {
|
|
5254
|
+
const halted = yield* Ref.get(haltRef);
|
|
5255
|
+
if (halted !== void 0) return yield* halted;
|
|
5256
|
+
const deferred = deferredResponse;
|
|
5257
|
+
if (deferred === void 0) return;
|
|
5258
|
+
const record = deferred.batch.records[0];
|
|
5259
|
+
if (record?.payload._tag !== "ModelResponseRecorded") return yield* RunJournalError.make({ message: "Deferred Turn has no owned response" });
|
|
5260
|
+
const calls = yield* declaredToolCalls(record.payload.messages);
|
|
5368
5261
|
const batch = CanonicalBatch.make({
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
records: [record]
|
|
5262
|
+
...deferred.batch,
|
|
5263
|
+
batchId: turnResponseBatchId(runId, deferred.turn)
|
|
5372
5264
|
});
|
|
5373
5265
|
yield* appendBatch(ctx, batch);
|
|
5266
|
+
acceptResponseDeclarations(batch);
|
|
5267
|
+
for (const call of calls.application) encodedParamsByCallId.set(call.id, call.params);
|
|
5374
5268
|
recordCommittedUsage(batch);
|
|
5375
|
-
knownIds.add(recordId);
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
const deferred = deferredResponse;
|
|
5400
|
-
if (commit._tag === "Response" && deferred !== void 0) return yield* RunJournalError.make({ message: "Turn response was already deferred" });
|
|
5401
|
-
const responseId = modelResponseRecordId(runId, commit.turn);
|
|
5402
|
-
const suppliedResponse = commit._tag === "Partial" ? void 0 : commit.response;
|
|
5403
|
-
const response = knownIds.has(responseId) || deferred !== void 0 ? void 0 : suppliedResponse;
|
|
5404
|
-
if (suppliedResponse !== void 0) currentToolTurn = {
|
|
5405
|
-
turn: commit.turn,
|
|
5406
|
-
turnId: commit.turnId
|
|
5407
|
-
};
|
|
5408
|
-
if (commit._tag === "Response" && response === void 0) return "committed";
|
|
5409
|
-
const toolOperations = [];
|
|
5410
|
-
const responseToolIds = /* @__PURE__ */ new Set();
|
|
5411
|
-
for (const call of response?.calls ?? []) {
|
|
5412
|
-
if (declaredToolIds.has(call.toolCallId) || responseToolIds.has(call.toolCallId)) return yield* RunJournalError.make({ message: "Tool Call identity is reused within a Run" });
|
|
5413
|
-
if (declaredToolIds.size + responseToolIds.size + 1 > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
|
|
5414
|
-
const replay = currentContracts[call.toolName];
|
|
5415
|
-
if (replay === void 0) return yield* RunJournalError.make({ message: "Canonical Tool declaration has no original operation contract" });
|
|
5416
|
-
toolOperations.push(ToolOperation.make({
|
|
5417
|
-
toolCallId: call.toolCallId,
|
|
5418
|
-
toolName: call.toolName,
|
|
5419
|
-
executionClass: call.executionClass,
|
|
5420
|
-
executionKind: call.executionKind,
|
|
5421
|
-
replay
|
|
5422
|
-
}));
|
|
5423
|
-
responseToolIds.add(call.toolCallId);
|
|
5269
|
+
for (const entry of batch.records) knownIds.add(entry.recordId);
|
|
5270
|
+
deferredResponse = void 0;
|
|
5271
|
+
yield* hit("turn:after-response-append");
|
|
5272
|
+
});
|
|
5273
|
+
const flushDeferredResponse = promoteResponse.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), responseGate.withPermits(1));
|
|
5274
|
+
let initialHistoryLength = 0;
|
|
5275
|
+
let initialInstructions = [];
|
|
5276
|
+
const completionState = {};
|
|
5277
|
+
const turnCounter = yield* Ref.make(journal.committedTurns + (journal.policyUsage.modelRestarts ?? 0));
|
|
5278
|
+
const idGenerator = {
|
|
5279
|
+
nextThreadId: Effect.succeed(submission.threadId),
|
|
5280
|
+
nextRunId: Effect.succeed(runId),
|
|
5281
|
+
nextTurnId: Ref.modify(turnCounter, (turn) => [turnIdForRun(runId, turn + 1), turn + 1])
|
|
5282
|
+
};
|
|
5283
|
+
const instructionView = (messages, instructions, insertWhenAbsent, priorRunPrefixLength) => {
|
|
5284
|
+
const projected = [];
|
|
5285
|
+
const lengths = [0];
|
|
5286
|
+
let inserted = false;
|
|
5287
|
+
for (const [index, message] of messages.entries()) {
|
|
5288
|
+
if (index >= priorRunPrefixLength && message.role === "system") {
|
|
5289
|
+
if (!inserted) projected.push(...instructions);
|
|
5290
|
+
inserted = true;
|
|
5291
|
+
} else projected.push(message);
|
|
5292
|
+
lengths.push(projected.length);
|
|
5424
5293
|
}
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5294
|
+
if (!inserted && insertWhenAbsent) projected.push(...instructions);
|
|
5295
|
+
return {
|
|
5296
|
+
messages: projected,
|
|
5297
|
+
prefixLength: (length) => lengths[length] ?? projected.length
|
|
5298
|
+
};
|
|
5299
|
+
};
|
|
5300
|
+
const resumeContext = { prepare: ({ source }) => Effect.sync(() => {
|
|
5301
|
+
const prefix = journal.committedTurns === 0 && priorContext !== void 0 ? priorContext.prompt.content.slice(priorContext.priorHistoryLength) : [];
|
|
5302
|
+
const priorRunPrefixLength = journal.committedTurns === 0 ? resumeProjection.prompt.content.length : resumeProjection.historyBefore.content.length;
|
|
5303
|
+
const view = instructionView(prefix.length === 0 ? resumeProjection.prompt.content : [...resumeProjection.prompt.content, ...prefix], initialInstructions, true, priorRunPrefixLength);
|
|
5304
|
+
return {
|
|
5305
|
+
prompt: Prompt.fromMessages([...view.messages, ...source.content.slice(initialHistoryLength)]),
|
|
5306
|
+
priorRunPrefixLength: view.prefixLength(priorRunPrefixLength)
|
|
5307
|
+
};
|
|
5308
|
+
}) };
|
|
5309
|
+
const externalContext = runContextPreparation.hook;
|
|
5310
|
+
const needsContextReplay = priorContext !== void 0 || journal.committedTurns > 0;
|
|
5311
|
+
const preparedContext = externalContext === void 0 ? needsContextReplay ? resumeContext : void 0 : { prepare: (request) => (needsContextReplay ? resumeContext.prepare(request) : Effect.succeed({
|
|
5312
|
+
prompt: request.source,
|
|
5313
|
+
priorRunPrefixLength: journal.historyBefore.content.length
|
|
5314
|
+
})).pipe(Effect.flatMap(({ prompt, priorRunPrefixLength }) => externalContext.prepare({
|
|
5315
|
+
...request,
|
|
5316
|
+
source: prompt,
|
|
5317
|
+
priorRunPrefixLength
|
|
5318
|
+
})), Effect.map((prepared) => {
|
|
5319
|
+
if (prepared.rollover === void 0 || !knownIds.has(compactionRecordId(runId, request.turn, "rollover"))) return prepared;
|
|
5320
|
+
const { rollover: _, ...retained } = prepared;
|
|
5321
|
+
return retained;
|
|
5322
|
+
})) };
|
|
5323
|
+
const durability = {
|
|
5324
|
+
toolResultMaxBytes: MAX_PERSISTED_JSON_BYTES,
|
|
5325
|
+
checkpoint,
|
|
5326
|
+
initialize: ({ initialHistory, priorHistoryLength }) => recordHalt(Effect.gen(function* () {
|
|
5327
|
+
initialHistoryLength = initialHistory.content.length;
|
|
5328
|
+
initialInstructions = initialHistory.content.slice(priorHistoryLength).filter((message) => message.role === "system");
|
|
5329
|
+
if (priorContext !== void 0) return;
|
|
5330
|
+
const recordId = decodeRecordIdSync(JSON.stringify(["run-context@1", runId]));
|
|
5331
|
+
const prompt = yield* Schema.encodeEffect(Prompt.Prompt)(Prompt.fromMessages(initialHistory.content.slice(priorHistoryLength))).pipe(Effect.flatMap(decodePersisted), Effect.mapError((cause) => RunJournalError.make({
|
|
5332
|
+
message: "Original Run context exceeds persistence bounds",
|
|
5432
5333
|
cause
|
|
5433
5334
|
})));
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5335
|
+
const history = Prompt.fromMessages(initialHistory.content.slice(0, priorHistoryLength));
|
|
5336
|
+
const historyDigest = yield* withCrypto(digestPromptHistory(history, initialJournal?.history));
|
|
5337
|
+
const retained = yield* Effect.forEach([...historyEvidence.values()].filter((entry) => entry.sequence < journal.historyFrom).sort((left, right) => left.sequence - right.sequence), (entry) => Effect.gen(function* () {
|
|
5338
|
+
const full = yield* getRecord({
|
|
5339
|
+
threadId: ctx.threadId,
|
|
5340
|
+
recordId: entry.record.recordId
|
|
5341
|
+
});
|
|
5342
|
+
if (Option.isNone(full) || full.value.sequence !== entry.sequence) return yield* RunJournalError.make({ message: "Retained history has no exact canonical fact" });
|
|
5343
|
+
return {
|
|
5344
|
+
...yield* withCrypto(reference(full.value.record)),
|
|
5345
|
+
sequence: entry.sequence
|
|
5346
|
+
};
|
|
5347
|
+
}).pipe(Effect.provideService(ThreadReader, reader)));
|
|
5348
|
+
const payload = yield* RunContextRecorded.makeEffect({
|
|
5349
|
+
version: 1,
|
|
5350
|
+
runId,
|
|
5351
|
+
runScopedInput: prompt,
|
|
5352
|
+
historyFrom: journal.historyFrom,
|
|
5353
|
+
historyThrough: CanonicalSequence.make(originalInput.sequence - 1),
|
|
5354
|
+
retained,
|
|
5355
|
+
historyDigest,
|
|
5356
|
+
priorHistoryLength,
|
|
5357
|
+
...journal.contextWindowId === void 0 ? {} : { contextWindowId: journal.contextWindowId }
|
|
5358
|
+
}).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
5359
|
+
message: "Original Run context mapping exceeds its bounds",
|
|
5441
5360
|
cause
|
|
5442
5361
|
})));
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
...completion.exhausted === void 0 ? {} : { exhausted: completion.exhausted }
|
|
5449
|
-
} : {}
|
|
5450
|
-
};
|
|
5451
|
-
}
|
|
5452
|
-
if (response === void 0 && deferred === void 0 && toolResults.length === 0 && runCompletion === void 0) return "committed";
|
|
5453
|
-
if (response === void 0 && deferred === void 0 && !knownIds.has(responseId)) return yield* RunJournalError.make({ message: "Tool results or completion preceded the canonical response" });
|
|
5454
|
-
const input = {
|
|
5455
|
-
toolResultMaxBytes: Math.min(agent.definition.policy.toolResultBounds.maxBytes, MAX_PERSISTED_JSON_BYTES),
|
|
5456
|
-
toolSelectionMaxBytes: utf8ByteLength(JSON.stringify({ toolSelection: { toolNames: Object.keys(currentContracts) } })),
|
|
5457
|
-
runId,
|
|
5458
|
-
turn: commit.turn,
|
|
5459
|
-
turnId: commit.turnId,
|
|
5460
|
-
responseMessages: response?.messages ?? [],
|
|
5461
|
-
toolResults,
|
|
5462
|
-
toolOperations,
|
|
5463
|
-
toolExposure: response?.toolExposure,
|
|
5464
|
-
toolParameterRejections: response?.toolParameterRejections,
|
|
5465
|
-
runScopedPrefixLength: response?.runScopedPrefixLength,
|
|
5466
|
-
producerId: config.producerId,
|
|
5467
|
-
deploymentId: config.deploymentId,
|
|
5468
|
-
createdAt: yield* nowUtc,
|
|
5469
|
-
runCompletion,
|
|
5470
|
-
usage: usageForCommit(commit.turn),
|
|
5471
|
-
unobservedModelCalls: unobservedForCommit(commit.turn)
|
|
5472
|
-
};
|
|
5473
|
-
if (commit._tag === "Partial") {
|
|
5474
|
-
for (const result of toolResults) {
|
|
5475
|
-
const batch = yield* withCrypto(turnResultsBatch({
|
|
5476
|
-
...input,
|
|
5477
|
-
toolResults: [result]
|
|
5478
|
-
}));
|
|
5479
|
-
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5480
|
-
...batch,
|
|
5481
|
-
batchId: toolCallResultBatchId(runId, commit.turn, result.toolCallId)
|
|
5482
|
-
}));
|
|
5483
|
-
for (const record of batch.records) knownIds.add(record.recordId);
|
|
5484
|
-
yield* hit("subagent:after-sibling-settle");
|
|
5485
|
-
}
|
|
5486
|
-
return "committed";
|
|
5487
|
-
}
|
|
5488
|
-
if (commit._tag === "Response" && commit.defer === true) {
|
|
5489
|
-
if (toolOperations.length === 0 || toolOperations.some((call) => call.executionClass !== "readonly" || call.executionKind !== "ordinary")) return yield* RunJournalError.make({ message: "Only ordinary readonly Tool responses may be deferred" });
|
|
5490
|
-
const candidate = {
|
|
5491
|
-
turn: commit.turn,
|
|
5492
|
-
turnId: commit.turnId,
|
|
5493
|
-
batch: yield* withCrypto(turnCanonicalBatch({
|
|
5494
|
-
...input,
|
|
5495
|
-
toolParameterRejections: input.toolParameterRejections?.map((rejection) => ({
|
|
5496
|
-
...rejection,
|
|
5497
|
-
parameters: copyJson(rejection.parameters),
|
|
5498
|
-
error: {
|
|
5499
|
-
...rejection.error,
|
|
5500
|
-
reason: { ...rejection.error.reason }
|
|
5501
|
-
}
|
|
5502
|
-
})),
|
|
5503
|
-
toolExposure: input.toolExposure === void 0 ? void 0 : Snapshot.make({
|
|
5504
|
-
exposedToolNames: [...input.toolExposure.exposedToolNames],
|
|
5505
|
-
...input.toolExposure.selection === void 0 ? {} : { selection: Selection.make({ toolNames: [...input.toolExposure.selection.toolNames] }) }
|
|
5506
|
-
}),
|
|
5507
|
-
usage: input.usage === void 0 ? void 0 : {
|
|
5508
|
-
...input.usage,
|
|
5509
|
-
modelUsage: input.usage.modelUsage?.map((usage) => ModelCallUsage.make({
|
|
5510
|
-
...usage,
|
|
5511
|
-
...usage.response === void 0 ? {} : { response: ModelResponseIdentity.make({ ...usage.response }) },
|
|
5512
|
-
inputTokens: InputTokenUsage.make({ ...usage.inputTokens }),
|
|
5513
|
-
outputTokens: OutputTokenUsage.make({ ...usage.outputTokens })
|
|
5514
|
-
}))
|
|
5515
|
-
}
|
|
5516
|
-
}))
|
|
5517
|
-
};
|
|
5518
|
-
const progress = progressWriters.get(ctx);
|
|
5519
|
-
if (progress === void 0) return yield* ThreadStoreError.make({
|
|
5520
|
-
operation: "reserve readonly dispatch",
|
|
5521
|
-
message: "Dispatch has no scoped progress writer"
|
|
5522
|
-
});
|
|
5523
|
-
const batch = yield* progress.defer(candidate.batch).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
5524
|
-
deferredResponse = {
|
|
5525
|
-
...candidate,
|
|
5526
|
-
batch
|
|
5527
|
-
};
|
|
5528
|
-
return "deferred";
|
|
5529
|
-
}
|
|
5530
|
-
let batch;
|
|
5531
|
-
if (deferred === void 0) batch = yield* withCrypto(commit._tag === "Response" ? turnResponseBatch(input) : response === void 0 ? turnResultsBatch(input) : turnCanonicalBatch(input));
|
|
5532
|
-
else if (toolResults.length === 0 && runCompletion === void 0) batch = deferred.batch;
|
|
5533
|
-
else {
|
|
5534
|
-
const results = yield* withCrypto(turnResultsBatch(input));
|
|
5535
|
-
batch = CanonicalBatch.make({
|
|
5536
|
-
...deferred.batch,
|
|
5537
|
-
records: [...deferred.batch.records, ...results.records]
|
|
5538
|
-
});
|
|
5539
|
-
}
|
|
5540
|
-
yield* appendBatch(ctx, batch);
|
|
5541
|
-
for (const call of response?.calls ?? []) {
|
|
5542
|
-
declaredToolIds.add(call.toolCallId);
|
|
5543
|
-
encodedParamsByCallId.set(call.toolCallId, call.parameters);
|
|
5544
|
-
declaredNamesByCallId.set(call.toolCallId, call.toolName);
|
|
5545
|
-
}
|
|
5546
|
-
if (deferred !== void 0) {
|
|
5547
|
-
acceptResponseDeclarations(batch);
|
|
5548
|
-
deferredResponse = void 0;
|
|
5549
|
-
}
|
|
5550
|
-
if (commit._tag === "Response") initialDispatchProofTurns.add(commit.turn);
|
|
5551
|
-
recordCommittedUsage(batch);
|
|
5552
|
-
for (const record of batch.records) knownIds.add(record.recordId);
|
|
5553
|
-
if (runCompletion !== void 0) completionState.committed = runCompletion;
|
|
5554
|
-
yield* hit(commit._tag === "Response" ? "turn:after-response-append" : response === void 0 && deferred === void 0 ? "turn:after-results-append" : "turn:after-canonical-append");
|
|
5555
|
-
return "committed";
|
|
5556
|
-
}).pipe(responseGate.withPermits(1))),
|
|
5557
|
-
checkToolDispatch: recordHalt(Effect.gen(function* () {
|
|
5558
|
-
if (currentToolTurn === void 0) return yield* RunJournalError.make({ message: "Tool dispatch preceded its canonical response" });
|
|
5559
|
-
yield* hit("tools:before-dispatch-fence");
|
|
5560
|
-
yield* ctx.checkActive;
|
|
5561
|
-
initialDispatchProofTurns.delete(currentToolTurn.turn);
|
|
5562
|
-
yield* hit("tools:after-dispatch-fence");
|
|
5563
|
-
})),
|
|
5564
|
-
step: {
|
|
5565
|
-
lookup: (key) => recordHalt(Effect.gen(function* () {
|
|
5566
|
-
yield* flushDeferredResponse;
|
|
5567
|
-
const output = stepOutputs.get(toolStepSettledRecordId(runId, key.toolCallId, key.stepName));
|
|
5568
|
-
return output === void 0 ? Option.none() : Option.some({ encodedOutput: output });
|
|
5362
|
+
yield* (yield* CurrentRunStart).commit(yield* makeEnvelope(recordId, payload));
|
|
5363
|
+
knownIds.add(runStartedRecordId(runId));
|
|
5364
|
+
knownIds.add(recordId);
|
|
5365
|
+
historyEvidence.clear();
|
|
5366
|
+
projectedJournal = void 0;
|
|
5569
5367
|
})),
|
|
5570
|
-
|
|
5571
|
-
yield*
|
|
5572
|
-
const recordId =
|
|
5573
|
-
const
|
|
5368
|
+
commitModelRestart: (restart) => recordHalt(Effect.gen(function* () {
|
|
5369
|
+
if (knownIds.has(modelResponseRecordId(runId, restart.turn))) return yield* RunJournalError.make({ message: "Cannot restart a canonical model response" });
|
|
5370
|
+
const recordId = decodeRecordIdSync(`model-aborted:${runId}:${restart.restart}`);
|
|
5371
|
+
const record = yield* makeEnvelope(recordId, ModelCallAborted.make({
|
|
5574
5372
|
runId,
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
})
|
|
5580
|
-
|
|
5581
|
-
message: "Durable Step identity exceeds canonical persistence bounds",
|
|
5582
|
-
cause: AgentPersistenceCapacityError.make({ message: "Durable Step identity exceeds canonical persistence bounds" })
|
|
5583
|
-
}))));
|
|
5584
|
-
const progress = progressWriters.get(ctx);
|
|
5585
|
-
if (progress === void 0) return yield* ThreadStoreError.make({
|
|
5586
|
-
operation: "reserve Step dispatch",
|
|
5587
|
-
message: "Dispatch has no scoped progress writer"
|
|
5588
|
-
});
|
|
5589
|
-
return yield* progress.reserve(runId, CanonicalBatch.make({
|
|
5373
|
+
...restart,
|
|
5374
|
+
reason: "joined-input",
|
|
5375
|
+
modelUsage: usageForCommit(restart.turn)?.modelUsage ?? [],
|
|
5376
|
+
unobservedModelCalls: unobservedForCommit(restart.turn)
|
|
5377
|
+
}));
|
|
5378
|
+
const batch = CanonicalBatch.make({
|
|
5590
5379
|
batchId: decodeBatchIdSync(recordId),
|
|
5591
5380
|
producerId: config.producerId,
|
|
5592
|
-
records: [
|
|
5593
|
-
})
|
|
5381
|
+
records: [record]
|
|
5382
|
+
});
|
|
5383
|
+
yield* appendBatch(ctx, batch);
|
|
5384
|
+
recordCommittedUsage(batch);
|
|
5385
|
+
knownIds.add(recordId);
|
|
5594
5386
|
})),
|
|
5595
|
-
|
|
5387
|
+
reservePolicyUsage: (usage) => recordHalt(Effect.gen(function* () {
|
|
5596
5388
|
yield* flushDeferredResponse;
|
|
5597
|
-
const recordId =
|
|
5389
|
+
const recordId = decodeRecordIdSync(`policy:${runId}:${usage.programmaticToolCalls}:${usage.finalizationUsed}`);
|
|
5598
5390
|
if (knownIds.has(recordId)) return;
|
|
5599
|
-
const
|
|
5600
|
-
operation: "commit Step result",
|
|
5601
|
-
message: "Durable Step output exceeds canonical persistence bounds",
|
|
5602
|
-
cause: AgentPersistenceCapacityError.make({ message: "Durable Step output exceeds canonical persistence bounds" })
|
|
5603
|
-
})));
|
|
5604
|
-
const outputDigest = yield* withCrypto(digestJson(output));
|
|
5605
|
-
const envelope = yield* makeEnvelope(recordId, ToolStepSettled.make({
|
|
5391
|
+
const record = yield* makeEnvelope(recordId, RunPolicyUsageReserved.make({
|
|
5606
5392
|
runId,
|
|
5607
|
-
|
|
5608
|
-
stepName: key.stepName,
|
|
5609
|
-
output,
|
|
5610
|
-
outputDigest
|
|
5393
|
+
...usage
|
|
5611
5394
|
}));
|
|
5395
|
+
yield* hit("policy:before-reservation-append");
|
|
5612
5396
|
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5613
|
-
batchId:
|
|
5397
|
+
batchId: decodeBatchIdSync(recordId),
|
|
5614
5398
|
producerId: config.producerId,
|
|
5615
|
-
records: [
|
|
5399
|
+
records: [record]
|
|
5616
5400
|
}));
|
|
5617
5401
|
knownIds.add(recordId);
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5402
|
+
yield* hit("policy:after-reservation-append");
|
|
5403
|
+
})),
|
|
5404
|
+
commitTurn: (commit) => recordHalt(Effect.gen(function* () {
|
|
5405
|
+
const halted = yield* Ref.get(haltRef);
|
|
5406
|
+
if (halted !== void 0) return yield* halted;
|
|
5407
|
+
if (deferredResponse !== void 0 && (deferredResponse.turn !== commit.turn || deferredResponse.turnId !== commit.turnId)) return yield* RunJournalError.make({ message: "A new Turn preceded settlement of its deferred response" });
|
|
5408
|
+
if (commit._tag === "Partial") yield* promoteResponse;
|
|
5409
|
+
const deferred = deferredResponse;
|
|
5410
|
+
if (commit._tag === "Response" && deferred !== void 0) return yield* RunJournalError.make({ message: "Turn response was already deferred" });
|
|
5411
|
+
const responseId = modelResponseRecordId(runId, commit.turn);
|
|
5412
|
+
const suppliedResponse = commit._tag === "Partial" ? void 0 : commit.response;
|
|
5413
|
+
const response = knownIds.has(responseId) || deferred !== void 0 ? void 0 : suppliedResponse;
|
|
5414
|
+
if (suppliedResponse !== void 0) currentToolTurn = {
|
|
5415
|
+
turn: commit.turn,
|
|
5416
|
+
turnId: commit.turnId
|
|
5417
|
+
};
|
|
5418
|
+
if (commit._tag === "Response" && response === void 0) return "committed";
|
|
5419
|
+
const toolOperations = [];
|
|
5420
|
+
const responseToolIds = /* @__PURE__ */ new Set();
|
|
5421
|
+
for (const call of response?.calls ?? []) {
|
|
5422
|
+
if (declaredToolIds.has(call.toolCallId) || responseToolIds.has(call.toolCallId)) return yield* RunJournalError.make({ message: "Tool Call identity is reused within a Run" });
|
|
5423
|
+
if (declaredToolIds.size + responseToolIds.size + 1 > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
|
|
5424
|
+
const replay = currentContracts[call.toolName];
|
|
5425
|
+
if (replay === void 0) return yield* RunJournalError.make({ message: "Canonical Tool declaration has no original operation contract" });
|
|
5426
|
+
toolOperations.push(ToolOperation.make({
|
|
5427
|
+
toolCallId: call.toolCallId,
|
|
5428
|
+
toolName: call.toolName,
|
|
5429
|
+
executionClass: call.executionClass,
|
|
5430
|
+
executionKind: call.executionKind,
|
|
5431
|
+
replay
|
|
5432
|
+
}));
|
|
5433
|
+
responseToolIds.add(call.toolCallId);
|
|
5434
|
+
}
|
|
5435
|
+
const toolResults = commit._tag === "Response" ? [] : commit.results.filter((result) => !knownIds.has(toolCallSettledRecordId(runId, commit.turn, result.toolCallId)));
|
|
5436
|
+
let runCompletion;
|
|
5437
|
+
if (commit._tag === "Settled" && commit.completion !== void 0) {
|
|
5438
|
+
const completion = commit.completion;
|
|
5439
|
+
const output = yield* decodePersisted(completion.output).pipe(Effect.mapError((cause) => LedgerError.make({
|
|
5440
|
+
operation: "recordCompleted",
|
|
5441
|
+
message: "Run output exceeds canonical persistence bounds",
|
|
5442
|
+
cause
|
|
5443
|
+
})));
|
|
5444
|
+
if (completion.finishReason === "budget-exhausted" && completion.runDisposition !== void 0) return yield* LedgerError.make({
|
|
5445
|
+
operation: "recordCompleted",
|
|
5446
|
+
message: "A budget-exhausted Run cannot declare an application run disposition"
|
|
5447
|
+
});
|
|
5448
|
+
const runDisposition = completion.runDisposition === void 0 ? void 0 : yield* decodePersisted(completion.runDisposition).pipe(Effect.mapError((cause) => LedgerError.make({
|
|
5449
|
+
operation: "recordCompleted",
|
|
5450
|
+
message: "Run disposition exceeds canonical persistence bounds",
|
|
5451
|
+
cause
|
|
5452
|
+
})));
|
|
5453
|
+
runCompletion = {
|
|
5454
|
+
output,
|
|
5455
|
+
...runDisposition === void 0 ? {} : { runDisposition },
|
|
5456
|
+
...completion.finishReason === "budget-exhausted" ? {
|
|
5457
|
+
finishReason: completion.finishReason,
|
|
5458
|
+
...completion.exhausted === void 0 ? {} : { exhausted: completion.exhausted }
|
|
5459
|
+
} : {}
|
|
5460
|
+
};
|
|
5461
|
+
}
|
|
5462
|
+
if (response === void 0 && deferred === void 0 && toolResults.length === 0 && runCompletion === void 0) return "committed";
|
|
5463
|
+
if (response === void 0 && deferred === void 0 && !knownIds.has(responseId)) return yield* RunJournalError.make({ message: "Tool results or completion preceded the canonical response" });
|
|
5464
|
+
const input = {
|
|
5465
|
+
toolResultMaxBytes: Math.min(agent.definition.policy.toolResultBounds.maxBytes, MAX_PERSISTED_JSON_BYTES),
|
|
5466
|
+
toolSelectionMaxBytes: utf8ByteLength(JSON.stringify({ toolSelection: { toolNames: Object.keys(currentContracts) } })),
|
|
5467
|
+
runId,
|
|
5468
|
+
turn: commit.turn,
|
|
5469
|
+
turnId: commit.turnId,
|
|
5470
|
+
responseMessages: response?.messages ?? [],
|
|
5471
|
+
toolResults,
|
|
5472
|
+
toolOperations,
|
|
5473
|
+
toolExposure: response?.toolExposure,
|
|
5474
|
+
toolParameterRejections: response?.toolParameterRejections,
|
|
5475
|
+
runScopedPrefixLength: response?.runScopedPrefixLength,
|
|
5476
|
+
producerId: config.producerId,
|
|
5477
|
+
deploymentId: config.deploymentId,
|
|
5478
|
+
createdAt: yield* nowUtc,
|
|
5479
|
+
runCompletion,
|
|
5480
|
+
usage: usageForCommit(commit.turn),
|
|
5481
|
+
unobservedModelCalls: unobservedForCommit(commit.turn)
|
|
5482
|
+
};
|
|
5483
|
+
if (commit._tag === "Partial") {
|
|
5484
|
+
for (const result of toolResults) {
|
|
5485
|
+
const batch = yield* turnResultsBatch({
|
|
5486
|
+
...input,
|
|
5487
|
+
toolResults: [result]
|
|
5488
|
+
});
|
|
5489
|
+
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5490
|
+
...batch,
|
|
5491
|
+
batchId: toolCallResultBatchId(runId, commit.turn, result.toolCallId)
|
|
5492
|
+
}));
|
|
5493
|
+
for (const record of batch.records) knownIds.add(record.recordId);
|
|
5494
|
+
yield* hit("subagent:after-sibling-settle");
|
|
5495
|
+
}
|
|
5496
|
+
return "committed";
|
|
5497
|
+
}
|
|
5498
|
+
if (commit._tag === "Response" && commit.defer === true) {
|
|
5499
|
+
if (toolOperations.length === 0 || toolOperations.some((call) => call.executionClass !== "readonly" || call.executionKind !== "ordinary")) return yield* RunJournalError.make({ message: "Only ordinary readonly Tool responses may be deferred" });
|
|
5500
|
+
const candidate = {
|
|
5501
|
+
turn: commit.turn,
|
|
5502
|
+
turnId: commit.turnId,
|
|
5503
|
+
batch: yield* turnCanonicalBatch({
|
|
5504
|
+
...input,
|
|
5505
|
+
toolParameterRejections: input.toolParameterRejections?.map((rejection) => ({
|
|
5506
|
+
...rejection,
|
|
5507
|
+
parameters: copyJson(rejection.parameters),
|
|
5508
|
+
error: {
|
|
5509
|
+
...rejection.error,
|
|
5510
|
+
reason: { ...rejection.error.reason }
|
|
5511
|
+
}
|
|
5512
|
+
})),
|
|
5513
|
+
toolExposure: input.toolExposure === void 0 ? void 0 : Snapshot.make({
|
|
5514
|
+
exposedToolNames: [...input.toolExposure.exposedToolNames],
|
|
5515
|
+
...input.toolExposure.selection === void 0 ? {} : { selection: Selection.make({ toolNames: [...input.toolExposure.selection.toolNames] }) }
|
|
5516
|
+
}),
|
|
5517
|
+
usage: input.usage === void 0 ? void 0 : {
|
|
5518
|
+
...input.usage,
|
|
5519
|
+
modelUsage: input.usage.modelUsage?.map((usage) => ModelCallUsage.make({
|
|
5520
|
+
...usage,
|
|
5521
|
+
...usage.response === void 0 ? {} : { response: ModelResponseIdentity.make({ ...usage.response }) },
|
|
5522
|
+
inputTokens: InputTokenUsage.make({ ...usage.inputTokens }),
|
|
5523
|
+
outputTokens: OutputTokenUsage.make({ ...usage.outputTokens })
|
|
5524
|
+
}))
|
|
5525
|
+
}
|
|
5526
|
+
})
|
|
5527
|
+
};
|
|
5528
|
+
const progress = progressWriters.get(ctx);
|
|
5529
|
+
if (progress === void 0) return yield* ThreadStoreError.make({
|
|
5530
|
+
operation: "reserve readonly dispatch",
|
|
5531
|
+
message: "Dispatch has no scoped progress writer"
|
|
5532
|
+
});
|
|
5533
|
+
const batch = yield* progress.defer(candidate.batch).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
5534
|
+
deferredResponse = {
|
|
5535
|
+
...candidate,
|
|
5536
|
+
batch
|
|
5537
|
+
};
|
|
5538
|
+
return "deferred";
|
|
5539
|
+
}
|
|
5540
|
+
let batch;
|
|
5541
|
+
if (deferred === void 0) batch = yield* commit._tag === "Response" ? turnResponseBatch(input) : response === void 0 ? turnResultsBatch(input) : turnCanonicalBatch(input);
|
|
5542
|
+
else if (toolResults.length === 0 && runCompletion === void 0) batch = deferred.batch;
|
|
5543
|
+
else {
|
|
5544
|
+
const results = yield* turnResultsBatch(input);
|
|
5545
|
+
batch = CanonicalBatch.make({
|
|
5546
|
+
...deferred.batch,
|
|
5547
|
+
records: [...deferred.batch.records, ...results.records]
|
|
5548
|
+
});
|
|
5549
|
+
}
|
|
5550
|
+
yield* appendBatch(ctx, batch);
|
|
5551
|
+
for (const call of response?.calls ?? []) {
|
|
5552
|
+
declaredToolIds.add(call.toolCallId);
|
|
5553
|
+
encodedParamsByCallId.set(call.toolCallId, call.parameters);
|
|
5554
|
+
declaredNamesByCallId.set(call.toolCallId, call.toolName);
|
|
5555
|
+
}
|
|
5556
|
+
if (deferred !== void 0) {
|
|
5557
|
+
acceptResponseDeclarations(batch);
|
|
5558
|
+
deferredResponse = void 0;
|
|
5559
|
+
}
|
|
5560
|
+
if (commit._tag === "Response") initialDispatchProofTurns.add(commit.turn);
|
|
5561
|
+
recordCommittedUsage(batch);
|
|
5562
|
+
for (const record of batch.records) knownIds.add(record.recordId);
|
|
5563
|
+
if (runCompletion !== void 0) completionState.committed = runCompletion;
|
|
5564
|
+
yield* hit(commit._tag === "Response" ? "turn:after-response-append" : response === void 0 && deferred === void 0 ? "turn:after-results-append" : "turn:after-canonical-append");
|
|
5565
|
+
return "committed";
|
|
5566
|
+
}).pipe(responseGate.withPermits(1))),
|
|
5567
|
+
checkToolDispatch: recordHalt(Effect.gen(function* () {
|
|
5568
|
+
if (currentToolTurn === void 0) return yield* RunJournalError.make({ message: "Tool dispatch preceded its canonical response" });
|
|
5569
|
+
yield* hit("tools:before-dispatch-fence");
|
|
5570
|
+
yield* ctx.checkActive;
|
|
5571
|
+
initialDispatchProofTurns.delete(currentToolTurn.turn);
|
|
5572
|
+
yield* hit("tools:after-dispatch-fence");
|
|
5573
|
+
})),
|
|
5574
|
+
step: {
|
|
5575
|
+
lookup: (key) => recordHalt(Effect.gen(function* () {
|
|
5576
|
+
yield* flushDeferredResponse;
|
|
5577
|
+
const output = stepOutputs.get(toolStepSettledRecordId(runId, key.toolCallId, key.stepName));
|
|
5578
|
+
return output === void 0 ? Option.none() : Option.some({ encodedOutput: output });
|
|
5579
|
+
})),
|
|
5580
|
+
reserve: (key) => recordHalt(Effect.gen(function* () {
|
|
5581
|
+
yield* flushDeferredResponse;
|
|
5582
|
+
const recordId = toolStepSettledRecordId(runId, key.toolCallId, key.stepName);
|
|
5583
|
+
const template = yield* makeEnvelope(recordId, yield* ToolStepSettled.makeEffect({
|
|
5584
|
+
runId,
|
|
5585
|
+
toolCallId: key.toolCallId,
|
|
5586
|
+
stepName: key.stepName,
|
|
5587
|
+
output: null,
|
|
5588
|
+
outputDigest: yield* withCrypto(digestJson(null))
|
|
5589
|
+
}).pipe(Effect.mapError(() => ThreadStoreError.make({
|
|
5590
|
+
operation: "reserve Step dispatch",
|
|
5591
|
+
message: "Durable Step identity exceeds canonical persistence bounds",
|
|
5592
|
+
cause: AgentPersistenceCapacityError.make({ message: "Durable Step identity exceeds canonical persistence bounds" })
|
|
5593
|
+
}))));
|
|
5594
|
+
const progress = progressWriters.get(ctx);
|
|
5595
|
+
if (progress === void 0) return yield* ThreadStoreError.make({
|
|
5596
|
+
operation: "reserve Step dispatch",
|
|
5597
|
+
message: "Dispatch has no scoped progress writer"
|
|
5598
|
+
});
|
|
5599
|
+
return yield* progress.reserve(runId, CanonicalBatch.make({
|
|
5600
|
+
batchId: decodeBatchIdSync(recordId),
|
|
5601
|
+
producerId: config.producerId,
|
|
5602
|
+
records: [template]
|
|
5603
|
+
}), canonicalRecordBytes(template) + MAX_PERSISTED_JSON_BYTES + MAX_RUN_CONTINUATION_BYTES).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
5604
|
+
})),
|
|
5605
|
+
commit: (key, encodedOutput) => recordHalt(Effect.gen(function* () {
|
|
5606
|
+
yield* flushDeferredResponse;
|
|
5607
|
+
const recordId = toolStepSettledRecordId(runId, key.toolCallId, key.stepName);
|
|
5608
|
+
if (knownIds.has(recordId)) return;
|
|
5609
|
+
const output = yield* decodePersisted(encodedOutput).pipe(Effect.mapError(() => ThreadStoreError.make({
|
|
5610
|
+
operation: "commit Step result",
|
|
5611
|
+
message: "Durable Step output exceeds canonical persistence bounds",
|
|
5612
|
+
cause: AgentPersistenceCapacityError.make({ message: "Durable Step output exceeds canonical persistence bounds" })
|
|
5613
|
+
})));
|
|
5614
|
+
const outputDigest = yield* withCrypto(digestJson(output));
|
|
5615
|
+
const envelope = yield* makeEnvelope(recordId, ToolStepSettled.make({
|
|
5616
|
+
runId,
|
|
5617
|
+
toolCallId: key.toolCallId,
|
|
5618
|
+
stepName: key.stepName,
|
|
5619
|
+
output,
|
|
5620
|
+
outputDigest
|
|
5621
|
+
}));
|
|
5622
|
+
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5623
|
+
batchId: toolStepSettledBatchId(runId, key.toolCallId, key.stepName),
|
|
5624
|
+
producerId: config.producerId,
|
|
5625
|
+
records: [envelope]
|
|
5626
|
+
}));
|
|
5627
|
+
knownIds.add(recordId);
|
|
5628
|
+
stepOutputs.set(recordId, output);
|
|
5629
|
+
yield* hit("step:after-step-append");
|
|
5630
|
+
}))
|
|
5631
|
+
},
|
|
5632
|
+
noteTurnUsage: (usage) => Effect.sync(() => {
|
|
5633
|
+
const key = usage.turn;
|
|
5634
|
+
const prior = stagedUsage.get(key);
|
|
5635
|
+
stagedUsage.set(key, {
|
|
5636
|
+
inputTokens: (prior?.inputTokens ?? 0) + usage.usage.inputTokens.total,
|
|
5637
|
+
outputTokens: (prior?.outputTokens ?? 0) + usage.usage.outputTokens.total,
|
|
5638
|
+
costMicrousd: (prior?.costMicrousd ?? 0) + usage.usage.costMicrousd,
|
|
5639
|
+
modelUsage: [...prior?.modelUsage ?? [], usage.usage]
|
|
5640
|
+
});
|
|
5641
|
+
progressWriters.get(ctx)?.stageUsage(runId, terminalUsageCharge(uncommittedModelUsage()));
|
|
5642
|
+
}),
|
|
5643
|
+
commitCompaction: Effect.fnUntraced(function* (commit) {
|
|
5644
|
+
const canonicalTurn = commit.turn;
|
|
5645
|
+
const recordId = compactionRecordId(runId, canonicalTurn, commit.kind);
|
|
5646
|
+
if (knownIds.has(recordId)) return yield* CompactionError.make({ message: "Compaction is already committed for this Turn and kind" });
|
|
5647
|
+
let sourceJournal = journal;
|
|
5648
|
+
let sourceBoundaries = boundaries;
|
|
5649
|
+
if (initialJournal !== void 0) {
|
|
5650
|
+
initialJournal.cacheable = false;
|
|
5651
|
+
initialJournal.history = void 0;
|
|
5652
|
+
}
|
|
5653
|
+
if (commit.kind !== "summarize" || initialJournal?.prefix !== void 0) {
|
|
5654
|
+
const tail = yield* ctx.tail;
|
|
5655
|
+
const source = initialJournal === void 0 ? canonical : Stream.fromIterable(yield* recordHalt(readInitialJournal(initialJournal.original, initialJournal.suffix)));
|
|
5656
|
+
sourceBoundaries = [];
|
|
5657
|
+
sourceJournal = yield* recordHalt(projectRunJournalStream(Stream.concat(source, Stream.fromIterable(yield* recordHalt(selectedRange(ctx.threadId, [submissionId], tail.sequence, canonicalThrough)))).pipe(Stream.filter((envelope) => envelope.record.payload._tag !== "CompactionCreated" || envelope.sequence <= canonicalThrough)), runId, (boundary) => sourceBoundaries.push(boundary), priorContext));
|
|
5658
|
+
}
|
|
5659
|
+
const coverable = sourceBoundaries.filter((boundary) => commit.kind !== "summarize" || ownerFirstSequence === void 0 || boundary.sequence < ownerFirstSequence);
|
|
5660
|
+
if (coverable.length === 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Durable rollover requires complete canonical records" : "Durable compaction requires eligible canonical records" });
|
|
5661
|
+
const comparisonView = instructionView(sourceJournal.prompt.content, initialInstructions, false, sourceJournal.historyBefore.content.length);
|
|
5662
|
+
let matchingPrefix = 0;
|
|
5663
|
+
let requiredThrough = 0;
|
|
5664
|
+
const comparisonLimit = Math.min(comparisonView.messages.length, commit.through);
|
|
5665
|
+
for (let index = 0; index < commit.through; index += 1) {
|
|
5666
|
+
const message = commit.source.content[index];
|
|
5667
|
+
if (message !== void 0 && (commit.kind === "clear-tool-results" ? message.role === "tool" : message.role !== "system")) requiredThrough = index + 1;
|
|
5668
|
+
if (index >= comparisonLimit || index !== matchingPrefix || message === void 0) continue;
|
|
5669
|
+
const canonicalMessage = comparisonView.messages[index];
|
|
5670
|
+
if (canonicalMessage === void 0) continue;
|
|
5671
|
+
const encode = (entry) => encodeCompactionMessageJson(entry).pipe(Effect.flatMap(decodeCompactionMessageJson), Effect.map(canonicalJson), Effect.mapError((cause) => CompactionError.make({
|
|
5672
|
+
message: "Could not encode the canonical compaction prefix",
|
|
5673
|
+
cause
|
|
5674
|
+
})));
|
|
5675
|
+
if ((yield* encode(canonicalMessage)) === (yield* encode(message))) matchingPrefix += 1;
|
|
5676
|
+
}
|
|
5677
|
+
let lastCovered;
|
|
5678
|
+
for (let index = 0; index < coverable.length; index += 1) {
|
|
5679
|
+
const candidate = coverable[index];
|
|
5680
|
+
if (candidate === void 0) continue;
|
|
5681
|
+
if (coverable[index + 1]?.tag === "ToolCallSettled") continue;
|
|
5682
|
+
const length = comparisonView.prefixLength(candidate.promptLength);
|
|
5683
|
+
if (length === 0 || length > commit.through) continue;
|
|
5684
|
+
if (length < requiredThrough || length > matchingPrefix) continue;
|
|
5685
|
+
lastCovered = candidate;
|
|
5686
|
+
}
|
|
5687
|
+
if (lastCovered === void 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Rollover coverage cannot be mapped to complete canonical records" : "Compaction coverage cannot be mapped to complete canonical records" });
|
|
5688
|
+
const coveredSequence = lastCovered.sequence;
|
|
5689
|
+
if (commit.kind !== "summarize" && sourceBoundaries.some((boundary) => boundary.incomplete === true && boundary.terminalPriorRun !== true && boundary.sequence <= coveredSequence)) return yield* CompactionError.make({ message: "Compaction cannot cover an incomplete Tool batch" });
|
|
5690
|
+
if (commit.kind === "summarize" && (commit.summary ?? "").trim().length === 0) return yield* CompactionError.make({ message: "A summarize compaction commit carried no summary" });
|
|
5691
|
+
const payload = yield* Schema.decodeEffect(CompactionCreated)({
|
|
5692
|
+
_tag: "CompactionCreated",
|
|
5693
|
+
runId,
|
|
5694
|
+
turn: canonicalTurn,
|
|
5695
|
+
kind: commit.kind,
|
|
5696
|
+
coversThrough: lastCovered.sequence,
|
|
5697
|
+
...commit.kind === "summarize" ? { summary: commit.summary } : {},
|
|
5698
|
+
...commit.kind === "rollover" && commit.handoff !== void 0 ? { handoff: commit.handoff } : {}
|
|
5699
|
+
}).pipe(Effect.mapError((cause) => CompactionError.make({
|
|
5700
|
+
message: "Compaction decision exceeds canonical persistence bounds",
|
|
5663
5701
|
cause
|
|
5664
5702
|
})));
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
const payload = yield* Schema.decodeEffect(CompactionCreated)({
|
|
5682
|
-
_tag: "CompactionCreated",
|
|
5683
|
-
runId,
|
|
5684
|
-
turn: canonicalTurn,
|
|
5685
|
-
kind: commit.kind,
|
|
5686
|
-
coversThrough: lastCovered.sequence,
|
|
5687
|
-
...commit.kind === "summarize" ? { summary: commit.summary } : {},
|
|
5688
|
-
...commit.kind === "rollover" && commit.handoff !== void 0 ? { handoff: commit.handoff } : {}
|
|
5689
|
-
}).pipe(Effect.mapError((cause) => CompactionError.make({
|
|
5690
|
-
message: "Compaction decision exceeds canonical persistence bounds",
|
|
5703
|
+
const envelope = yield* recordHalt(makeEnvelope(recordId, payload));
|
|
5704
|
+
yield* recordHalt(hit("compaction:before-canonical-append"));
|
|
5705
|
+
yield* recordHalt(appendBatch(ctx, CanonicalBatch.make({
|
|
5706
|
+
batchId: compactionBatchId(runId, canonicalTurn, commit.kind),
|
|
5707
|
+
producerId: config.producerId,
|
|
5708
|
+
records: [envelope]
|
|
5709
|
+
})));
|
|
5710
|
+
knownIds.add(recordId);
|
|
5711
|
+
yield* recordHalt(hit("compaction:after-canonical-append"));
|
|
5712
|
+
})
|
|
5713
|
+
};
|
|
5714
|
+
/** Digest of one declared call's canonical encoded parameters (the original normalized wire). */
|
|
5715
|
+
const approvalParametersDigest = (toolCallId) => Effect.gen(function* () {
|
|
5716
|
+
if (!encodedParamsByCallId.has(toolCallId)) return yield* RunJournalError.make({ message: `Tool Call ${toolCallId} requested approval before its response commit` });
|
|
5717
|
+
const parameters = yield* decodePersisted(encodedParamsByCallId.get(toolCallId)).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
5718
|
+
message: `Tool Call ${toolCallId} parameters exceed canonical persistence bounds`,
|
|
5691
5719
|
cause
|
|
5692
5720
|
})));
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
}
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
const appendApprovalRecords = (turnInfo, toolCallId, toolName, decided) => Effect.gen(function* () {
|
|
5725
|
-
const requestRecordId = toolApprovalRequestRecordId(runId, turnInfo.turn, toolCallId);
|
|
5726
|
-
const decisionRecordId = toolApprovalDecisionRecordId(runId, turnInfo.turn, toolCallId);
|
|
5727
|
-
const envelopes = [];
|
|
5728
|
-
const appendRequest = !knownIds.has(requestRecordId);
|
|
5729
|
-
if (appendRequest) {
|
|
5730
|
-
const parametersDigest = yield* approvalParametersDigest(toolCallId);
|
|
5731
|
-
envelopes.push(yield* makeEnvelope(requestRecordId, ToolApprovalRequested.make({
|
|
5732
|
-
blocksInitialDispatch: initialDispatchProofTurns.has(turnInfo.turn),
|
|
5721
|
+
return yield* withCrypto(digestJson(parameters));
|
|
5722
|
+
});
|
|
5723
|
+
/**
|
|
5724
|
+
* Append the canonical approval records for one declared call: the `ToolApprovalRequested`
|
|
5725
|
+
* record — plus the immediate `ToolApprovalDecided` for a policy-auto or intent-backed
|
|
5726
|
+
* decision, one atomic batch — or the decision alone when the request is already canonical.
|
|
5727
|
+
* Batch identity: the Turn's FIRST canonical approval append owns
|
|
5728
|
+
* `turn-approvals:{runId}:{turn}`; later appends of the same Turn (across suspension
|
|
5729
|
+
* cycles) use deterministic per-call batches so committed batch content is never
|
|
5730
|
+
* contradicted; decision-only appends use `approval-decision:{sid}:{toolCallId}`. Record
|
|
5731
|
+
* identity dedupes every replay; an identity conflict means another pass already committed
|
|
5732
|
+
* the same records.
|
|
5733
|
+
*/
|
|
5734
|
+
const appendApprovalRecords = (turnInfo, toolCallId, toolName, decided) => Effect.gen(function* () {
|
|
5735
|
+
const requestRecordId = toolApprovalRequestRecordId(runId, turnInfo.turn, toolCallId);
|
|
5736
|
+
const decisionRecordId = toolApprovalDecisionRecordId(runId, turnInfo.turn, toolCallId);
|
|
5737
|
+
const envelopes = [];
|
|
5738
|
+
const appendRequest = !knownIds.has(requestRecordId);
|
|
5739
|
+
if (appendRequest) {
|
|
5740
|
+
const parametersDigest = yield* approvalParametersDigest(toolCallId);
|
|
5741
|
+
envelopes.push(yield* makeEnvelope(requestRecordId, ToolApprovalRequested.make({
|
|
5742
|
+
blocksInitialDispatch: initialDispatchProofTurns.has(turnInfo.turn),
|
|
5743
|
+
runId,
|
|
5744
|
+
turnId: turnInfo.turnId,
|
|
5745
|
+
turn: turnInfo.turn,
|
|
5746
|
+
toolCallId,
|
|
5747
|
+
toolName,
|
|
5748
|
+
parametersDigest
|
|
5749
|
+
})));
|
|
5750
|
+
}
|
|
5751
|
+
if (decided !== void 0 && !knownIds.has(decisionRecordId)) envelopes.push(yield* makeEnvelope(decisionRecordId, ToolApprovalDecided.make({
|
|
5733
5752
|
runId,
|
|
5734
|
-
turnId: turnInfo.turnId,
|
|
5735
5753
|
turn: turnInfo.turn,
|
|
5736
5754
|
toolCallId,
|
|
5737
|
-
|
|
5738
|
-
|
|
5755
|
+
decision: decided.decision,
|
|
5756
|
+
resolver: decided.resolver,
|
|
5757
|
+
reason: decided.reason
|
|
5739
5758
|
})));
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
const head = envelopes[0];
|
|
5750
|
-
if (head !== void 0) {
|
|
5751
|
-
const batchId = appendRequest ? approvalRequestedTurns.has(turnInfo.turn) ? decodeBatchId(`approval-request:${runId}:${turnInfo.turn}:${toolCallId}`) : turnApprovalsBatchId(runId, turnInfo.turn) : approvalDecisionBatchId(submissionId, toolCallId);
|
|
5752
|
-
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5753
|
-
batchId,
|
|
5754
|
-
producerId: config.producerId,
|
|
5755
|
-
records: [head, ...envelopes.slice(1)]
|
|
5756
|
-
})).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
|
|
5757
|
-
for (const record of envelopes) knownIds.add(record.recordId);
|
|
5758
|
-
}
|
|
5759
|
-
if (appendRequest) {
|
|
5760
|
-
approvalRequestedTurns.add(turnInfo.turn);
|
|
5761
|
-
yield* hit("approval:after-request-append");
|
|
5762
|
-
}
|
|
5763
|
-
if (decided !== void 0) canonicalApprovalDecisions.set(toolCallId, decided.decision);
|
|
5764
|
-
});
|
|
5765
|
-
/**
|
|
5766
|
-
* Retain every required request before any decision can remove initial-dispatch proof.
|
|
5767
|
-
* Policy preparation shares the engine deadline; canonical acceptance is a separate,
|
|
5768
|
-
* fenced commit. Canonical decisions and accepted resolver intents keep their audit.
|
|
5769
|
-
*/
|
|
5770
|
-
const approval = {
|
|
5771
|
-
prepareBatch: (requests) => recordHalt(Effect.gen(function* () {
|
|
5772
|
-
if (requests.length === 0) return;
|
|
5773
|
-
yield* flushDeferredResponse;
|
|
5774
|
-
const turnInfo = currentToolTurn;
|
|
5775
|
-
if (turnInfo === void 0) return yield* RunJournalError.make({ message: "Approval preparation preceded its canonical response" });
|
|
5776
|
-
for (const request of requests) {
|
|
5777
|
-
if (request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval preparation does not match its original declaration" });
|
|
5778
|
-
yield* appendApprovalRecords(turnInfo, request.toolCallId, request.toolName, void 0);
|
|
5779
|
-
}
|
|
5780
|
-
})),
|
|
5781
|
-
request: (request) => recordHalt(Effect.gen(function* () {
|
|
5782
|
-
const canonical = canonicalApprovalDecisions.get(request.toolCallId);
|
|
5783
|
-
if (canonical !== void 0) return canonical === "approved" ? { _tag: "approved" } : { _tag: "denied" };
|
|
5784
|
-
const intent = approvalIntents.get(request.toolCallId);
|
|
5785
|
-
if (intent !== void 0) return intent.decision === "approved" ? {
|
|
5786
|
-
_tag: "approved",
|
|
5787
|
-
reason: intent.reason
|
|
5788
|
-
} : {
|
|
5789
|
-
_tag: "denied",
|
|
5790
|
-
reason: intent.reason
|
|
5791
|
-
};
|
|
5792
|
-
return approvalResolver === void 0 ? { _tag: "unresolved" } : yield* approvalResolver.request(request);
|
|
5793
|
-
})),
|
|
5794
|
-
commit: (request, decision) => recordHalt(Effect.gen(function* () {
|
|
5795
|
-
const turnInfo = currentToolTurn;
|
|
5796
|
-
if (turnInfo === void 0 || request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval acceptance does not match its original declaration" });
|
|
5797
|
-
const canonical = canonicalApprovalDecisions.get(request.toolCallId);
|
|
5798
|
-
if (canonical !== void 0) {
|
|
5799
|
-
if (decision._tag !== canonical) return yield* RunJournalError.make({ message: "Approval preparation disagrees with its canonical decision" });
|
|
5800
|
-
return;
|
|
5759
|
+
const head = envelopes[0];
|
|
5760
|
+
if (head !== void 0) {
|
|
5761
|
+
const batchId = appendRequest ? approvalRequestedTurns.has(turnInfo.turn) ? decodeBatchId(`approval-request:${runId}:${turnInfo.turn}:${toolCallId}`) : turnApprovalsBatchId(runId, turnInfo.turn) : approvalDecisionBatchId(submissionId, toolCallId);
|
|
5762
|
+
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5763
|
+
batchId,
|
|
5764
|
+
producerId: config.producerId,
|
|
5765
|
+
records: [head, ...envelopes.slice(1)]
|
|
5766
|
+
})).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
|
|
5767
|
+
for (const record of envelopes) knownIds.add(record.recordId);
|
|
5801
5768
|
}
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
decision: intent.decision,
|
|
5806
|
-
resolver: intent.resolver,
|
|
5807
|
-
reason: intent.reason
|
|
5808
|
-
} : decision._tag === "unresolved" ? void 0 : {
|
|
5809
|
-
decision: decision._tag,
|
|
5810
|
-
resolver: APPROVAL_POLICY_RESOLVER,
|
|
5811
|
-
reason: boundedApprovalReason(decision.reason, "The configured approval policy decided immediately")
|
|
5812
|
-
});
|
|
5813
|
-
}))
|
|
5814
|
-
};
|
|
5815
|
-
/**
|
|
5816
|
-
* Joining/Joined queued input hook (plan §2.5, DUR-016). At every engine drain seam:
|
|
5817
|
-
*
|
|
5818
|
-
* 1. Reattach first — pre-existing joins whose canonical `input:{sid}` record is not yet
|
|
5819
|
-
* prompt-covered re-deliver WITHOUT re-appending (record identity is the dedupe);
|
|
5820
|
-
* covered inputs are already inside the journal prompt. A `joining` row whose input is
|
|
5821
|
-
* canonical only lost its marker: it is repaired from history under the host's live
|
|
5822
|
-
* ownership (DUR-015). A `joining` row WITHOUT canonical input was never consumed and
|
|
5823
|
-
* is recovery's to revert — the hook never guesses at it (fail-closed).
|
|
5824
|
-
* 2. Claim fresh — `claimJoining` atomically transitions the contiguous ready prefix of
|
|
5825
|
-
* strictly-later queue sequences to `joining` under the host's local generation (an
|
|
5826
|
-
* admitted-not-ready row breaks the prefix). Per fresh claim: honor a
|
|
5827
|
-
* pre-consumption abort intent by reverting (revert-then-abort), else append the
|
|
5828
|
-
* deterministic `UserInputRecorded` (batch `submission-input:{sid}`, record
|
|
5829
|
-
* `input:{sid}`, `runId` = host Run, kind `steering`) → `join:after-canonical-append`
|
|
5830
|
-
* → `markJoined` → hand the engine the `RunInputCommand`.
|
|
5831
|
-
*
|
|
5832
|
-
* Delivered input is `steering`: the engine appends it to official history at the seam,
|
|
5833
|
-
* so the next Turn's response commit makes it model-visible canonically — exactly the
|
|
5834
|
-
* prompt-coverage rule recovery relies on.
|
|
5835
|
-
*/
|
|
5836
|
-
const renderJoinedInput = ({ input: encodedInput, messageAdmission }) => Effect.gen(function* () {
|
|
5837
|
-
if (Schema.is(FrameworkMessage)(messageAdmission)) return yield* Schema.encodeEffect(Schema.fromJsonString(FrameworkMessage))(messageAdmission).pipe(Effect.mapError(() => AgentInputError.make({ message: "Invalid worker completion message" })));
|
|
5838
|
-
const inputPrompt = agent.definition.inputPrompt;
|
|
5839
|
-
if (inputPrompt === void 0) return yield* renderInputPrompt(void 0, encodedInput, encodedInput);
|
|
5840
|
-
const decodedInput = yield* Schema.decodeEffect(agent.definition.input)(encodedInput).pipe(Effect.mapError((cause) => AgentInputDecodeError.make({ message: cause.message })));
|
|
5841
|
-
return yield* renderInputPrompt(inputPrompt, decodedInput, encodedInput);
|
|
5842
|
-
});
|
|
5843
|
-
const pendingJoinClaims = [];
|
|
5844
|
-
const claimInputs = Effect.fnUntraced(function* (maxCount) {
|
|
5845
|
-
const claims = yield* session.claimJoining(maxCount);
|
|
5846
|
-
pendingJoinClaims.push(...claims.map((claim) => ({ claim })));
|
|
5847
|
-
return claims.length;
|
|
5848
|
-
}, Effect.uninterruptible);
|
|
5849
|
-
const revertClaims = Effect.fnUntraced(function* (claims) {
|
|
5850
|
-
for (const pending of claims) {
|
|
5851
|
-
yield* session.revertJoining(pending.claim.submissionId);
|
|
5852
|
-
pendingJoinClaims.splice(pendingJoinClaims.indexOf(pending), 1);
|
|
5853
|
-
}
|
|
5854
|
-
}, Effect.uninterruptible);
|
|
5855
|
-
const prepareInputs = Effect.fnUntraced(function* (limit, firstReady = false) {
|
|
5856
|
-
if (pendingJoinClaims.length < limit && (yield* claimInputs(limit - pendingJoinClaims.length)) > 0) yield* hit("join:after-claim");
|
|
5857
|
-
const prepared = [];
|
|
5858
|
-
for (const pending of pendingJoinClaims.slice(0, limit)) {
|
|
5859
|
-
const claim = pending.claim;
|
|
5860
|
-
const snapshot = yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId: claim.submissionId }));
|
|
5861
|
-
if (snapshot.abortIntent !== void 0) {
|
|
5862
|
-
yield* revertClaims([pending]);
|
|
5863
|
-
continue;
|
|
5769
|
+
if (appendRequest) {
|
|
5770
|
+
approvalRequestedTurns.add(turnInfo.turn);
|
|
5771
|
+
yield* hit("approval:after-request-append");
|
|
5864
5772
|
}
|
|
5865
|
-
if (
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5773
|
+
if (decided !== void 0) canonicalApprovalDecisions.set(toolCallId, decided.decision);
|
|
5774
|
+
});
|
|
5775
|
+
/**
|
|
5776
|
+
* Retain every required request before any decision can remove initial-dispatch proof.
|
|
5777
|
+
* Policy preparation shares the engine deadline; canonical acceptance is a separate,
|
|
5778
|
+
* fenced commit. Canonical decisions and accepted resolver intents keep their audit.
|
|
5779
|
+
*/
|
|
5780
|
+
const approval = {
|
|
5781
|
+
prepareBatch: (requests) => recordHalt(Effect.gen(function* () {
|
|
5782
|
+
if (requests.length === 0) return;
|
|
5783
|
+
yield* flushDeferredResponse;
|
|
5784
|
+
const turnInfo = currentToolTurn;
|
|
5785
|
+
if (turnInfo === void 0) return yield* RunJournalError.make({ message: "Approval preparation preceded its canonical response" });
|
|
5786
|
+
for (const request of requests) {
|
|
5787
|
+
if (request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval preparation does not match its original declaration" });
|
|
5788
|
+
yield* appendApprovalRecords(turnInfo, request.toolCallId, request.toolName, void 0);
|
|
5874
5789
|
}
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5790
|
+
})),
|
|
5791
|
+
request: (request) => recordHalt(Effect.gen(function* () {
|
|
5792
|
+
const canonical = canonicalApprovalDecisions.get(request.toolCallId);
|
|
5793
|
+
if (canonical !== void 0) return canonical === "approved" ? { _tag: "approved" } : { _tag: "denied" };
|
|
5794
|
+
const intent = approvalIntents.get(request.toolCallId);
|
|
5795
|
+
if (intent !== void 0) return intent.decision === "approved" ? {
|
|
5796
|
+
_tag: "approved",
|
|
5797
|
+
reason: intent.reason
|
|
5798
|
+
} : {
|
|
5799
|
+
_tag: "denied",
|
|
5800
|
+
reason: intent.reason
|
|
5879
5801
|
};
|
|
5802
|
+
return approvalResolver === void 0 ? { _tag: "unresolved" } : yield* approvalResolver.request(request);
|
|
5803
|
+
})),
|
|
5804
|
+
commit: (request, decision) => recordHalt(Effect.gen(function* () {
|
|
5805
|
+
const turnInfo = currentToolTurn;
|
|
5806
|
+
if (turnInfo === void 0 || request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval acceptance does not match its original declaration" });
|
|
5807
|
+
const canonical = canonicalApprovalDecisions.get(request.toolCallId);
|
|
5808
|
+
if (canonical !== void 0) {
|
|
5809
|
+
if (decision._tag !== canonical) return yield* RunJournalError.make({ message: "Approval preparation disagrees with its canonical decision" });
|
|
5810
|
+
return;
|
|
5811
|
+
}
|
|
5812
|
+
const intent = approvalIntents.get(request.toolCallId);
|
|
5813
|
+
if (intent !== void 0 && decision._tag !== intent.decision) return yield* RunJournalError.make({ message: "Approval preparation disagrees with its accepted intent" });
|
|
5814
|
+
yield* appendApprovalRecords(turnInfo, request.toolCallId, request.toolName, intent !== void 0 ? {
|
|
5815
|
+
decision: intent.decision,
|
|
5816
|
+
resolver: intent.resolver,
|
|
5817
|
+
reason: intent.reason
|
|
5818
|
+
} : decision._tag === "unresolved" ? void 0 : {
|
|
5819
|
+
decision: decision._tag,
|
|
5820
|
+
resolver: APPROVAL_POLICY_RESOLVER,
|
|
5821
|
+
reason: boundedApprovalReason(decision.reason, "The configured approval policy decided immediately")
|
|
5822
|
+
});
|
|
5823
|
+
}))
|
|
5824
|
+
};
|
|
5825
|
+
/**
|
|
5826
|
+
* Joining/Joined queued input hook (plan §2.5, DUR-016). At every engine drain seam:
|
|
5827
|
+
*
|
|
5828
|
+
* 1. Reattach first — pre-existing joins whose canonical `input:{sid}` record is not yet
|
|
5829
|
+
* prompt-covered re-deliver WITHOUT re-appending (record identity is the dedupe);
|
|
5830
|
+
* covered inputs are already inside the journal prompt. A `joining` row whose input is
|
|
5831
|
+
* canonical only lost its marker: it is repaired from history under the host's live
|
|
5832
|
+
* ownership (DUR-015). A `joining` row WITHOUT canonical input was never consumed and
|
|
5833
|
+
* is recovery's to revert — the hook never guesses at it (fail-closed).
|
|
5834
|
+
* 2. Claim fresh — `claimJoining` atomically transitions the contiguous ready prefix of
|
|
5835
|
+
* strictly-later queue sequences to `joining` under the host's local generation (an
|
|
5836
|
+
* admitted-not-ready row breaks the prefix). Per fresh claim: honor a
|
|
5837
|
+
* pre-consumption abort intent by reverting (revert-then-abort), else append the
|
|
5838
|
+
* deterministic `UserInputRecorded` (batch `submission-input:{sid}`, record
|
|
5839
|
+
* `input:{sid}`, `runId` = host Run, kind `steering`) → `join:after-canonical-append`
|
|
5840
|
+
* → `markJoined` → hand the engine the `RunInputCommand`.
|
|
5841
|
+
*
|
|
5842
|
+
* Delivered input is `steering`: the engine appends it to official history at the seam,
|
|
5843
|
+
* so the next Turn's response commit makes it model-visible canonically — exactly the
|
|
5844
|
+
* prompt-coverage rule recovery relies on.
|
|
5845
|
+
*/
|
|
5846
|
+
const renderJoinedInput = Effect.fnUntraced(function* (encodedInput, messageAdmission) {
|
|
5847
|
+
if (Schema.is(FrameworkMessage)(messageAdmission)) return yield* Schema.encodeEffect(Schema.fromJsonString(FrameworkMessage))(messageAdmission).pipe(Effect.mapError(() => AgentInputError.make({ message: "Invalid worker completion message" })));
|
|
5848
|
+
const inputPrompt = agent.definition.inputPrompt;
|
|
5849
|
+
if (inputPrompt === void 0) return yield* renderInputPrompt(void 0, encodedInput, encodedInput);
|
|
5850
|
+
const decodedInput = yield* Schema.decodeEffect(agent.definition.input)(encodedInput).pipe(Effect.mapError((cause) => AgentInputDecodeError.make({ message: cause.message })));
|
|
5851
|
+
return yield* renderInputPrompt(inputPrompt, decodedInput, encodedInput);
|
|
5852
|
+
});
|
|
5853
|
+
const pendingJoinClaims = [];
|
|
5854
|
+
const claimInputs = Effect.fnUntraced(function* (maxCount) {
|
|
5855
|
+
const claims = yield* session.claimJoining(maxCount);
|
|
5856
|
+
pendingJoinClaims.push(...claims.map((claim) => ({ claim })));
|
|
5857
|
+
return claims.length;
|
|
5858
|
+
}, Effect.uninterruptible);
|
|
5859
|
+
const revertClaims = Effect.fnUntraced(function* (claims) {
|
|
5860
|
+
for (const pending of claims) {
|
|
5861
|
+
yield* session.revertJoining(pending.claim.submissionId);
|
|
5862
|
+
pendingJoinClaims.splice(pendingJoinClaims.indexOf(pending), 1);
|
|
5880
5863
|
}
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
yield* notified;
|
|
5892
|
-
return false;
|
|
5893
|
-
}))) return;
|
|
5894
|
-
})),
|
|
5895
|
-
drain: (policy) => Effect.gen(function* () {
|
|
5896
|
-
const joinedInputs = yield* recordHalt(Effect.gen(function* () {
|
|
5897
|
-
const limit = policy === "one" ? 1 : MAX_JOIN_DRAIN;
|
|
5898
|
-
const joinedInputs = [];
|
|
5899
|
-
if (joinBacklog === void 0) joinBacklog = (yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId }))).joins;
|
|
5900
|
-
for (const join of joinBacklog) {
|
|
5901
|
-
const joinId = join.submissionId;
|
|
5902
|
-
if (deliveredJoinInputs.has(joinId)) continue;
|
|
5903
|
-
if (join.state !== "joining" && join.state !== "joined") continue;
|
|
5904
|
-
const existing = joinedInputEnvelopes.get(joinId);
|
|
5905
|
-
if (existing === void 0) continue;
|
|
5906
|
-
if (join.state === "joining") yield* session.markJoined(joinId, {
|
|
5907
|
-
recordId: existing.record.recordId,
|
|
5908
|
-
sequence: existing.sequence
|
|
5909
|
-
});
|
|
5910
|
-
deliveredJoinInputs.add(joinId);
|
|
5911
|
-
if (lastHostResponseSequence !== void 0 && lastHostResponseSequence > existing.sequence) continue;
|
|
5912
|
-
const payload = existing.record.payload;
|
|
5913
|
-
if (payload._tag !== "UserInputRecorded") continue;
|
|
5914
|
-
joinedInputs.push(payload);
|
|
5864
|
+
}, Effect.uninterruptible);
|
|
5865
|
+
const prepareInputs = Effect.fnUntraced(function* (limit, firstReady = false) {
|
|
5866
|
+
if (pendingJoinClaims.length < limit && (yield* claimInputs(limit - pendingJoinClaims.length)) > 0) yield* hit("join:after-claim");
|
|
5867
|
+
const prepared = [];
|
|
5868
|
+
for (const pending of pendingJoinClaims.slice(0, limit)) {
|
|
5869
|
+
const claim = pending.claim;
|
|
5870
|
+
const snapshot = yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId: claim.submissionId }));
|
|
5871
|
+
if (snapshot.abortIntent !== void 0) {
|
|
5872
|
+
yield* revertClaims([pending]);
|
|
5873
|
+
continue;
|
|
5915
5874
|
}
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
const
|
|
5922
|
-
if (
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
submissionId: claim.submissionId,
|
|
5926
|
-
kind: "steering",
|
|
5927
|
-
runId,
|
|
5928
|
-
input: claim.inputPayload,
|
|
5929
|
-
...payload.messageAdmission === void 0 ? {} : { messageAdmission: payload.messageAdmission }
|
|
5930
|
-
}));
|
|
5931
|
-
sequence = (yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5932
|
-
batchId: submissionInputBatchId(claim.submissionId),
|
|
5933
|
-
producerId: config.producerId,
|
|
5934
|
-
records: [envelope]
|
|
5935
|
-
}))).firstSequence;
|
|
5936
|
-
knownIds.add(recordId);
|
|
5937
|
-
yield* hit("join:after-canonical-append");
|
|
5875
|
+
if (pending.prepared === void 0) {
|
|
5876
|
+
const input = {
|
|
5877
|
+
input: claim.inputPayload,
|
|
5878
|
+
...snapshot.submission.messageAdmission === void 0 ? {} : { messageAdmission: snapshot.submission.messageAdmission }
|
|
5879
|
+
};
|
|
5880
|
+
const rendered = yield* Effect.result(renderJoinedInput(input.input, input.messageAdmission));
|
|
5881
|
+
if (Result.isFailure(rendered)) {
|
|
5882
|
+
yield* revertClaims(pendingJoinClaims.slice(pendingJoinClaims.indexOf(pending)));
|
|
5883
|
+
break;
|
|
5938
5884
|
}
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
joinedInputs.push({
|
|
5945
|
-
...payload,
|
|
5946
|
-
rendered
|
|
5947
|
-
});
|
|
5885
|
+
pending.prepared = {
|
|
5886
|
+
claim,
|
|
5887
|
+
input,
|
|
5888
|
+
rendered: rendered.success
|
|
5889
|
+
};
|
|
5948
5890
|
}
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
return yield* Effect.forEach(joinedInputs, (joinedInput) => (joinedInput.rendered === void 0 ? renderJoinedInput(joinedInput) : Effect.succeed(joinedInput.rendered)).pipe(Effect.map((input) => ({
|
|
5952
|
-
kind: "steering",
|
|
5953
|
-
input
|
|
5954
|
-
}))));
|
|
5955
|
-
})
|
|
5956
|
-
};
|
|
5957
|
-
/**
|
|
5958
|
-
* Durable child establishment: `establish` performs or replays
|
|
5959
|
-
* the idempotent get-or-create establishment protocol under the
|
|
5960
|
-
* parent's ownership fence and reports where the one child stands; `join` appends the
|
|
5961
|
-
* atomic `[SubagentJoined, ToolCallSettled]` settlement batch (SUB-019) and applies the
|
|
5962
|
-
* reservation release. Both use the halt side channel exactly like the durability/step
|
|
5963
|
-
* hooks: the engine wraps a `CoordinatorHalt` into `SubagentDurabilityError` in the
|
|
5964
|
-
* handler channel while the Attempt aborts with the original infrastructure failure.
|
|
5965
|
-
*/
|
|
5966
|
-
const establishmentGate = yield* Semaphore.make(1);
|
|
5967
|
-
const establishSubagent = (request) => recordHalt(Effect.gen(function* () {
|
|
5968
|
-
const toolCallId = request.toolCallId;
|
|
5969
|
-
const turnInfo = currentToolTurn;
|
|
5970
|
-
if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} established before any canonical response commit` });
|
|
5971
|
-
const denied = (errorTag, message) => ({
|
|
5972
|
-
_tag: "denied",
|
|
5973
|
-
errorTag,
|
|
5974
|
-
message: boundedText(message)
|
|
5975
|
-
});
|
|
5976
|
-
let requestedPayload = subagentState.requested.get(toolCallId);
|
|
5977
|
-
if (requestedPayload === void 0) {
|
|
5978
|
-
if (request.depth !== delegationDepth + 1) return denied("SubagentDepthUnsupported", `The child depth must be exactly one greater than its source depth ${delegationDepth}`);
|
|
5979
|
-
let targetDigests = request.targetDigests;
|
|
5980
|
-
if (request.target !== void 0) {
|
|
5981
|
-
if (request.target.id !== request.targetAgentId) return denied("SubagentBindingUnavailable", "The child target identity differs from its Definition");
|
|
5982
|
-
const binding = yield* resolveDefinitionBinding(registeredBindings, request.target).pipe(Effect.result);
|
|
5983
|
-
if (binding._tag === "Failure") return denied("SubagentBindingUnavailable", binding.failure.message);
|
|
5984
|
-
if (targetDigests !== void 0 && (targetDigests.agent !== binding.success.digests.agent || targetDigests.model !== binding.success.digests.model || targetDigests.tools !== binding.success.digests.tools)) return denied("SubagentDigestsInvalid", "The explicit child digests differ from its exact registration");
|
|
5985
|
-
targetDigests = binding.success.digests;
|
|
5891
|
+
prepared.push(pending.prepared);
|
|
5892
|
+
if (firstReady) break;
|
|
5986
5893
|
}
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
const
|
|
6025
|
-
|
|
6026
|
-
|
|
5894
|
+
return prepared;
|
|
5895
|
+
});
|
|
5896
|
+
const input = {
|
|
5897
|
+
awaitJoin: recordHalt(Effect.gen(function* () {
|
|
5898
|
+
while (true) if (yield* Effect.scoped(Effect.gen(function* () {
|
|
5899
|
+
const notified = yield* wake.subscribe(submission.threadId);
|
|
5900
|
+
if ((yield* prepareInputs(MAX_JOIN_DRAIN, true)).length > 0) return true;
|
|
5901
|
+
yield* notified;
|
|
5902
|
+
return false;
|
|
5903
|
+
}))) return;
|
|
5904
|
+
})),
|
|
5905
|
+
drain: Effect.fnUntraced(function* (policy) {
|
|
5906
|
+
const joinedInputs = yield* recordHalt(Effect.gen(function* () {
|
|
5907
|
+
const limit = policy === "one" ? 1 : MAX_JOIN_DRAIN;
|
|
5908
|
+
const joinedInputs = [];
|
|
5909
|
+
if (joinBacklog === void 0) joinBacklog = (yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId }))).joins;
|
|
5910
|
+
for (const join of joinBacklog) {
|
|
5911
|
+
const joinId = join.submissionId;
|
|
5912
|
+
if (deliveredJoinInputs.has(joinId)) continue;
|
|
5913
|
+
if (join.state !== "joining" && join.state !== "joined") continue;
|
|
5914
|
+
const existing = joinedInputEnvelopes.get(joinId);
|
|
5915
|
+
if (existing === void 0) continue;
|
|
5916
|
+
if (join.state === "joining") yield* session.markJoined(joinId, {
|
|
5917
|
+
recordId: existing.record.recordId,
|
|
5918
|
+
sequence: existing.sequence
|
|
5919
|
+
});
|
|
5920
|
+
deliveredJoinInputs.add(joinId);
|
|
5921
|
+
if (lastHostResponseSequence !== void 0 && lastHostResponseSequence > existing.sequence) continue;
|
|
5922
|
+
const payload = existing.record.payload;
|
|
5923
|
+
if (payload._tag !== "UserInputRecorded") continue;
|
|
5924
|
+
joinedInputs.push(payload);
|
|
5925
|
+
}
|
|
5926
|
+
const claims = yield* prepareInputs(limit);
|
|
5927
|
+
pendingJoinClaims.splice(0, claims.length);
|
|
5928
|
+
for (const { claim, input: payload, rendered } of claims) {
|
|
5929
|
+
const recordId = submissionInputRecordId(claim.submissionId);
|
|
5930
|
+
let sequence;
|
|
5931
|
+
const existing = joinedInputEnvelopes.get(claim.submissionId);
|
|
5932
|
+
if (existing !== void 0) sequence = existing.sequence;
|
|
5933
|
+
else {
|
|
5934
|
+
const envelope = yield* makeEnvelope(recordId, UserInputRecorded.make({
|
|
5935
|
+
submissionId: claim.submissionId,
|
|
5936
|
+
kind: "steering",
|
|
5937
|
+
runId,
|
|
5938
|
+
input: claim.inputPayload,
|
|
5939
|
+
...payload.messageAdmission === void 0 ? {} : { messageAdmission: payload.messageAdmission }
|
|
5940
|
+
}));
|
|
5941
|
+
sequence = (yield* appendBatch(ctx, CanonicalBatch.make({
|
|
5942
|
+
batchId: submissionInputBatchId(claim.submissionId),
|
|
5943
|
+
producerId: config.producerId,
|
|
5944
|
+
records: [envelope]
|
|
5945
|
+
}))).firstSequence;
|
|
5946
|
+
knownIds.add(recordId);
|
|
5947
|
+
yield* hit("join:after-canonical-append");
|
|
5948
|
+
}
|
|
5949
|
+
yield* session.markJoined(claim.submissionId, {
|
|
5950
|
+
recordId,
|
|
5951
|
+
sequence
|
|
5952
|
+
});
|
|
5953
|
+
deliveredJoinInputs.add(claim.submissionId);
|
|
5954
|
+
joinedInputs.push({
|
|
5955
|
+
...payload,
|
|
5956
|
+
rendered
|
|
5957
|
+
});
|
|
5958
|
+
}
|
|
5959
|
+
return joinedInputs;
|
|
5960
|
+
}));
|
|
5961
|
+
return yield* Effect.forEach(joinedInputs, (joinedInput) => (joinedInput.rendered === void 0 ? renderJoinedInput(joinedInput.input, joinedInput.messageAdmission) : Effect.succeed(joinedInput.rendered)).pipe(Effect.map((input) => ({
|
|
5962
|
+
kind: "steering",
|
|
5963
|
+
input
|
|
5964
|
+
}))));
|
|
5965
|
+
})
|
|
5966
|
+
};
|
|
5967
|
+
/**
|
|
5968
|
+
* Durable child establishment: `establish` performs or replays
|
|
5969
|
+
* the idempotent get-or-create establishment protocol under the
|
|
5970
|
+
* parent's ownership fence and reports where the one child stands; `join` appends the
|
|
5971
|
+
* atomic `[SubagentJoined, ToolCallSettled]` settlement batch (SUB-019) and applies the
|
|
5972
|
+
* reservation release. Both use the halt side channel exactly like the durability/step
|
|
5973
|
+
* hooks: the engine wraps a `CoordinatorHalt` into `SubagentDurabilityError` in the
|
|
5974
|
+
* handler channel while the Attempt aborts with the original infrastructure failure.
|
|
5975
|
+
*/
|
|
5976
|
+
const establishmentGate = yield* Semaphore.make(1);
|
|
5977
|
+
const establishSubagent = (request) => recordHalt(Effect.gen(function* () {
|
|
5978
|
+
const toolCallId = request.toolCallId;
|
|
5979
|
+
const turnInfo = currentToolTurn;
|
|
5980
|
+
if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} established before any canonical response commit` });
|
|
5981
|
+
const denied = (errorTag, message) => ({
|
|
5982
|
+
_tag: "denied",
|
|
5983
|
+
errorTag,
|
|
5984
|
+
message: boundedText(message)
|
|
5985
|
+
});
|
|
5986
|
+
let requestedPayload = subagentState.requested.get(toolCallId);
|
|
5987
|
+
if (requestedPayload === void 0) {
|
|
5988
|
+
if (request.depth !== delegationDepth + 1) return denied("SubagentDepthUnsupported", `The child depth must be exactly one greater than its source depth ${delegationDepth}`);
|
|
5989
|
+
let targetDigests = request.targetDigests;
|
|
5990
|
+
if (request.target !== void 0) {
|
|
5991
|
+
if (request.target.id !== request.targetAgentId) return denied("SubagentBindingUnavailable", "The child target identity differs from its Definition");
|
|
5992
|
+
const binding = yield* resolveDefinitionBinding(registeredBindings, request.target).pipe(Effect.result);
|
|
5993
|
+
if (binding._tag === "Failure") return denied("SubagentBindingUnavailable", binding.failure.message);
|
|
5994
|
+
if (targetDigests !== void 0 && (targetDigests.agent !== binding.success.digests.agent || targetDigests.model !== binding.success.digests.model || targetDigests.tools !== binding.success.digests.tools)) return denied("SubagentDigestsInvalid", "The explicit child digests differ from its exact registration");
|
|
5995
|
+
targetDigests = binding.success.digests;
|
|
5996
|
+
}
|
|
5997
|
+
const decodedDigests = yield* decodeDefinitionDigests(targetDigests).pipe(Effect.option);
|
|
5998
|
+
if (Option.isNone(decodedDigests)) return denied("SubagentDigestsInvalid", "The declared child Binding digests are not valid stored digests");
|
|
5999
|
+
const childInput = yield* decodePersisted(request.encodedChildInput).pipe(Effect.option);
|
|
6000
|
+
if (Option.isNone(childInput)) return denied("SubagentInputUnpersistable", "The prepared child input does not satisfy the canonical persistence bounds");
|
|
6001
|
+
const grant = yield* decodePersisted(request.encodedGrant).pipe(Effect.option);
|
|
6002
|
+
const allocation = yield* decodePersisted(request.encodedAllocation).pipe(Effect.option);
|
|
6003
|
+
if (Option.isNone(grant) || Option.isNone(allocation)) return denied("SubagentDeclarationUnpersistable", "The delegation grant or allocation does not satisfy the canonical persistence bounds");
|
|
6004
|
+
const decodedGrant = Schema.decodeUnknownOption(SubagentGrant)(grant.value);
|
|
6005
|
+
if (Option.isNone(decodedGrant)) return denied("SubagentGrantInvalid", "The child authority grant is invalid");
|
|
6006
|
+
if (request.policy === void 0 || request.budget === void 0) return denied("SubagentBudgetInvalid", "New durable children require their full execution policy and subtree allocation");
|
|
6007
|
+
if (request.toolCallAllowance !== void 0 && !Schema.is(SubagentRequested.fields.toolCallAllowance)(request.toolCallAllowance)) return denied("SubagentAllowanceInvalid", "The child Tool Call allowance must be a positive integer");
|
|
6008
|
+
if (request.policy !== void 0 && !Schema.is(AgentPolicy)(request.policy)) return denied("SubagentPolicyInvalid", "The resolved child policy is invalid");
|
|
6009
|
+
if (request.budget !== void 0) {
|
|
6010
|
+
if (!Schema.is(SubagentBudgetReservation)(request.budget)) return denied("SubagentBudgetInvalid", "The shared delegation budget is invalid");
|
|
6011
|
+
const decodedAllocation = Schema.decodeUnknownOption(SubagentReservationAmounts)(allocation.value);
|
|
6012
|
+
if (Option.isNone(decodedAllocation) || !Equal.equals(decodedAllocation.value, request.budget.allocation)) return denied("SubagentBudgetInvalid", "The reserved allocation differs from its budget declaration");
|
|
6013
|
+
const { caps, allocation: requested } = request.budget;
|
|
6014
|
+
const prior = [...subagentState.requested.values()];
|
|
6015
|
+
if (prior.some((entry) => entry.budget === void 0 || !Equal.equals(entry.budget.caps, caps))) return denied("SubagentParentBudgetConflict", "Delegations in one parent Run must share the same caps");
|
|
6016
|
+
if (caps.maxTotalChildInvocations !== void 0 && prior.reduce((sum, entry) => sum + 1 + (entry.budget?.descendantInvocations ?? 0), 1 + (request.budget.descendantInvocations ?? 0)) > caps.maxTotalChildInvocations) return denied("SubagentBudgetExhausted", "The parent Run exhausted its child invocation budget");
|
|
6017
|
+
const active = prior.filter((entry) => !subagentState.joined.has(entry.toolCallId));
|
|
6018
|
+
if (caps.maxConcurrentChildren !== void 0 && active.length >= caps.maxConcurrentChildren) return denied("SubagentBudgetExhausted", "The parent Run exhausted its concurrent child budget");
|
|
6019
|
+
const dimensions = [
|
|
6020
|
+
["turns", "maxTurns"],
|
|
6021
|
+
["toolCalls", "maxToolCalls"],
|
|
6022
|
+
["durationMillis", "maxDurationMillis"],
|
|
6023
|
+
["inputTokens", "maxInputTokens"],
|
|
6024
|
+
["outputTokens", "maxOutputTokens"],
|
|
6025
|
+
["costMicrousd", "maxCostMicrousd"],
|
|
6026
|
+
["resultBytes", "maxResultBytes"]
|
|
6027
|
+
];
|
|
6028
|
+
const accounting = Schema.Struct({ consumed: SubagentReservationAmounts });
|
|
6029
|
+
for (const [amount, cap] of dimensions) {
|
|
6030
|
+
const limit = caps[cap];
|
|
6031
|
+
if (limit === void 0) continue;
|
|
6032
|
+
let consumed = requested[amount];
|
|
6033
|
+
for (const entry of prior) {
|
|
6034
|
+
const joined = subagentState.joined.get(entry.toolCallId);
|
|
6035
|
+
const observed = joined === void 0 ? Option.none() : Schema.decodeUnknownOption(accounting)(joined.finalAccounting);
|
|
6036
|
+
consumed += Option.isSome(observed) ? observed.value.consumed[amount] : entry.budget?.allocation[amount] ?? limit;
|
|
6037
|
+
}
|
|
6038
|
+
if (consumed > limit) return denied("SubagentBudgetExhausted", `The parent Run exhausted its shared ${amount} budget`);
|
|
6027
6039
|
}
|
|
6028
|
-
if (consumed > limit) return denied("SubagentBudgetExhausted", `The parent Run exhausted its shared ${amount} budget`);
|
|
6029
6040
|
}
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6041
|
+
const childInputDigest = yield* withCrypto(digestJson(childInput.value));
|
|
6042
|
+
const grantDigest = yield* withCrypto(digestJson(grant.value));
|
|
6043
|
+
const allocationDigest = yield* withCrypto(digestJson(allocation.value));
|
|
6044
|
+
const reservationId = childReservationIdFor(runId, toolCallId);
|
|
6045
|
+
const subtree = delegationDepth === 0 ? void 0 : yield* workerRuntime.reserveSubtree(submission.threadId, SubtreeBudgetReserved.make({
|
|
6046
|
+
reservationId,
|
|
6047
|
+
executionRunId: runId,
|
|
6048
|
+
sourceSubmissionId: submissionId,
|
|
6049
|
+
childThreadId: childThreadIdFor(submissionId, toolCallId),
|
|
6050
|
+
lifetime: "attached",
|
|
6051
|
+
depth: request.depth,
|
|
6052
|
+
policy: request.policy,
|
|
6053
|
+
grant: decodedGrant.value,
|
|
6054
|
+
budget: request.budget
|
|
6055
|
+
})).pipe(Effect.result);
|
|
6056
|
+
if (subtree?._tag === "Failure") {
|
|
6057
|
+
if (subtree.failure.reason === "storage") return yield* LedgerError.make({
|
|
6058
|
+
operation: "reserve-subtree",
|
|
6059
|
+
message: "Subtree reservation is unavailable"
|
|
6060
|
+
});
|
|
6061
|
+
return denied("SubagentBudgetExhausted", `The subtree reservation was refused: ${subtree.failure.reason}`);
|
|
6062
|
+
}
|
|
6063
|
+
yield* session.reserveChildBudget({
|
|
6064
|
+
reservationId,
|
|
6065
|
+
parentToolCallId: toolCallId,
|
|
6066
|
+
allocation: allocation.value,
|
|
6067
|
+
allocationDigest
|
|
6068
|
+
}).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("reserveChildBudget")));
|
|
6069
|
+
yield* hit("subagent:after-reserve");
|
|
6070
|
+
requestedPayload = SubagentRequested.make({
|
|
6071
|
+
runId,
|
|
6072
|
+
turnId: turnInfo.turnId,
|
|
6073
|
+
turn: turnInfo.turn,
|
|
6074
|
+
toolCallId,
|
|
6075
|
+
delegationId: request.delegationId,
|
|
6076
|
+
targetAgentId: request.targetAgentId,
|
|
6077
|
+
targetDigests: decodedDigests.value,
|
|
6078
|
+
childInput: childInput.value,
|
|
6079
|
+
childInputDigest,
|
|
6080
|
+
grantDigest,
|
|
6081
|
+
grant: decodedGrant.value,
|
|
6082
|
+
depth: request.depth,
|
|
6083
|
+
reservationId,
|
|
6084
|
+
reservationDigest: allocationDigest,
|
|
6085
|
+
childThreadId: childThreadIdFor(submissionId, toolCallId),
|
|
6086
|
+
childPrincipal: submission.principal,
|
|
6087
|
+
childIdempotencyKey: childIdempotencyKeyFor(runId, toolCallId),
|
|
6088
|
+
...request.toolCallAllowance === void 0 ? {} : { toolCallAllowance: request.toolCallAllowance },
|
|
6089
|
+
...request.policy === void 0 ? {} : { policy: request.policy },
|
|
6090
|
+
...request.budget === void 0 ? {} : { budget: request.budget }
|
|
6050
6091
|
});
|
|
6051
|
-
|
|
6092
|
+
const requestRecordId = subagentRequestedRecordId(runId, toolCallId);
|
|
6093
|
+
if (!knownIds.has(requestRecordId)) {
|
|
6094
|
+
const envelope = yield* makeEnvelope(requestRecordId, requestedPayload);
|
|
6095
|
+
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
6096
|
+
batchId: subagentRequestedBatchId(runId, toolCallId),
|
|
6097
|
+
producerId: config.producerId,
|
|
6098
|
+
records: [envelope]
|
|
6099
|
+
})).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
|
|
6100
|
+
knownIds.add(requestRecordId);
|
|
6101
|
+
}
|
|
6102
|
+
subagentState.requested.set(toolCallId, requestedPayload);
|
|
6103
|
+
yield* hit("subagent:after-request-append");
|
|
6052
6104
|
}
|
|
6053
|
-
yield*
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
allocationDigest
|
|
6058
|
-
}).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("reserveChildBudget")));
|
|
6059
|
-
yield* hit("subagent:after-reserve");
|
|
6060
|
-
requestedPayload = SubagentRequested.make({
|
|
6061
|
-
runId,
|
|
6062
|
-
turnId: turnInfo.turnId,
|
|
6063
|
-
turn: turnInfo.turn,
|
|
6064
|
-
toolCallId,
|
|
6065
|
-
delegationId: request.delegationId,
|
|
6066
|
-
targetAgentId: request.targetAgentId,
|
|
6067
|
-
targetDigests: decodedDigests.value,
|
|
6068
|
-
childInput: childInput.value,
|
|
6069
|
-
childInputDigest,
|
|
6070
|
-
grantDigest,
|
|
6071
|
-
grant: decodedGrant.value,
|
|
6072
|
-
depth: request.depth,
|
|
6073
|
-
reservationId,
|
|
6074
|
-
reservationDigest: allocationDigest,
|
|
6075
|
-
childThreadId: childThreadIdFor(submissionId, toolCallId),
|
|
6076
|
-
childPrincipal: submission.principal,
|
|
6077
|
-
childIdempotencyKey: childIdempotencyKeyFor(runId, toolCallId),
|
|
6078
|
-
...request.toolCallAllowance === void 0 ? {} : { toolCallAllowance: request.toolCallAllowance },
|
|
6079
|
-
...request.policy === void 0 ? {} : { policy: request.policy },
|
|
6080
|
-
...request.budget === void 0 ? {} : { budget: request.budget }
|
|
6105
|
+
const admission = yield* establishChildFromRequest(submission, requestedPayload);
|
|
6106
|
+
if (admission._tag === "indeterminate") return yield* LedgerError.make({
|
|
6107
|
+
operation: "establishSubagent",
|
|
6108
|
+
message: `Child admission for Tool Call ${toolCallId} is indeterminate (${admission.reason}); retrying without a second admission (SUB-031)`
|
|
6081
6109
|
});
|
|
6082
|
-
const
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
childReceiptId: admission.receiptId,
|
|
6109
|
-
childRunId
|
|
6110
|
+
const childRunId = runIdForSubmission(admission.childSubmissionId);
|
|
6111
|
+
let startedPayload = subagentState.started.get(toolCallId);
|
|
6112
|
+
if (startedPayload === void 0) {
|
|
6113
|
+
startedPayload = SubagentStarted.make({
|
|
6114
|
+
runId,
|
|
6115
|
+
toolCallId,
|
|
6116
|
+
childThreadId: requestedPayload.childThreadId,
|
|
6117
|
+
childSubmissionId: admission.childSubmissionId,
|
|
6118
|
+
childReceiptId: admission.receiptId,
|
|
6119
|
+
childRunId
|
|
6120
|
+
});
|
|
6121
|
+
const startRecordId = subagentStartedRecordId(runId, toolCallId);
|
|
6122
|
+
if (!knownIds.has(startRecordId)) {
|
|
6123
|
+
const envelope = yield* makeEnvelope(startRecordId, startedPayload);
|
|
6124
|
+
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
6125
|
+
batchId: subagentStartedBatchId(runId, toolCallId),
|
|
6126
|
+
producerId: config.producerId,
|
|
6127
|
+
records: [envelope]
|
|
6128
|
+
})).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
|
|
6129
|
+
knownIds.add(startRecordId);
|
|
6130
|
+
}
|
|
6131
|
+
subagentState.started.set(toolCallId, startedPayload);
|
|
6132
|
+
yield* hit("subagent:after-start-append");
|
|
6133
|
+
} else if (startedPayload.childSubmissionId !== admission.childSubmissionId) return yield* LedgerError.make({
|
|
6134
|
+
operation: "establishSubagent",
|
|
6135
|
+
message: `The canonical SubagentStarted record names child ${startedPayload.childSubmissionId} but admission resolved ${admission.childSubmissionId}; establishment fails closed (SUB-016)`
|
|
6110
6136
|
});
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6137
|
+
yield* session.attachChildToReservation({
|
|
6138
|
+
reservationId: decodeChildReservationIdSync(requestedPayload.reservationId),
|
|
6139
|
+
childSubmissionId: startedPayload.childSubmissionId
|
|
6140
|
+
}).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("attachChildToReservation")));
|
|
6141
|
+
const identity = {
|
|
6142
|
+
childThreadId: startedPayload.childThreadId,
|
|
6143
|
+
childSubmissionId: startedPayload.childSubmissionId,
|
|
6144
|
+
childRunId: startedPayload.childRunId,
|
|
6145
|
+
receiptId: startedPayload.childReceiptId
|
|
6146
|
+
};
|
|
6147
|
+
const child = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: startedPayload.childSubmissionId }));
|
|
6148
|
+
if (Option.isNone(child)) return yield* LedgerError.make({
|
|
6149
|
+
operation: "establishSubagent",
|
|
6150
|
+
message: `Established child ${startedPayload.childSubmissionId} is unknown to the ledger`
|
|
6151
|
+
});
|
|
6152
|
+
if (child.value.state !== "settled") return {
|
|
6153
|
+
_tag: "waiting",
|
|
6154
|
+
...identity
|
|
6155
|
+
};
|
|
6156
|
+
const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
|
|
6157
|
+
if (verification._tag === "mismatch") return denied("SubagentVerificationFailed", verification.message);
|
|
6158
|
+
return {
|
|
6159
|
+
_tag: "settled",
|
|
6160
|
+
...identity,
|
|
6161
|
+
outcome: verification.value.outcome,
|
|
6162
|
+
encodedResult: verification.value.encodedResult,
|
|
6163
|
+
...yield* verifiedChildUsage(verification.value, startedPayload.childRunId),
|
|
6164
|
+
...verification.value.settlement.finishReason === void 0 ? {} : { finishReason: verification.value.settlement.finishReason }
|
|
6165
|
+
};
|
|
6166
|
+
}).pipe(establishmentGate.withPermits(1)));
|
|
6167
|
+
const joinSubagent = (request) => recordHalt(Effect.gen(function* () {
|
|
6168
|
+
const toolCallId = request.toolCallId;
|
|
6169
|
+
const turnInfo = currentToolTurn;
|
|
6170
|
+
if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined before any canonical response commit` });
|
|
6171
|
+
const requestedPayload = subagentState.requested.get(toolCallId);
|
|
6172
|
+
const startedPayload = subagentState.started.get(toolCallId);
|
|
6173
|
+
if (requestedPayload === void 0 || startedPayload === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without canonical establishment records` });
|
|
6174
|
+
const reservationId = decodeChildReservationIdSync(requestedPayload.reservationId);
|
|
6175
|
+
const joinedRecordId = subagentJoinedRecordId(runId, toolCallId);
|
|
6176
|
+
let finalAccounting;
|
|
6177
|
+
const existingJoined = subagentState.joined.get(toolCallId);
|
|
6178
|
+
if (existingJoined !== void 0) finalAccounting = existingJoined.finalAccounting;
|
|
6179
|
+
else {
|
|
6180
|
+
const encodedResult = yield* decodePersisted(request.encodedResult).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
6181
|
+
message: `The projected result of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
|
|
6182
|
+
cause
|
|
6183
|
+
})));
|
|
6184
|
+
const accounting = yield* decodePersisted(request.encodedAccounting).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
6185
|
+
message: `The join accounting of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
|
|
6186
|
+
cause
|
|
6187
|
+
})));
|
|
6188
|
+
const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
|
|
6189
|
+
if (verification._tag === "mismatch") return yield* LedgerError.make({
|
|
6190
|
+
operation: "joinSubagent",
|
|
6191
|
+
message: `Child Settlement verification failed for Tool Call ${toolCallId}: ${verification.message}`
|
|
6192
|
+
});
|
|
6193
|
+
const verified = verification.value;
|
|
6194
|
+
const toolName = declaredNamesByCallId.get(toolCallId);
|
|
6195
|
+
if (toolName === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without a declared Tool name` });
|
|
6196
|
+
yield* hit("subagent:before-join-append");
|
|
6197
|
+
const joinedPayload = SubagentJoined.make({
|
|
6198
|
+
runId,
|
|
6199
|
+
toolCallId,
|
|
6200
|
+
childSubmissionId: startedPayload.childSubmissionId,
|
|
6201
|
+
childSettlementId: verified.settlement.settlementId,
|
|
6202
|
+
childOutcome: verified.outcome,
|
|
6203
|
+
usageSummary: yield* childUsageSummaryOf(verified.childRecords, startedPayload.childRunId),
|
|
6204
|
+
...yield* verifiedChildUsage(verified, startedPayload.childRunId),
|
|
6205
|
+
reservationId: requestedPayload.reservationId,
|
|
6206
|
+
finalAccounting: accounting
|
|
6207
|
+
});
|
|
6208
|
+
const settledRecordId = toolCallSettledRecordId(runId, turnInfo.turn, toolCallId);
|
|
6209
|
+
const joinedEnvelope = yield* makeEnvelope(joinedRecordId, joinedPayload);
|
|
6210
|
+
const settledEnvelope = yield* makeEnvelope(settledRecordId, ToolCallSettled.make({
|
|
6211
|
+
runId,
|
|
6212
|
+
toolCallId,
|
|
6213
|
+
toolName,
|
|
6214
|
+
result: encodedResult,
|
|
6215
|
+
isFailure: request.isFailure
|
|
6216
|
+
}));
|
|
6114
6217
|
yield* appendBatch(ctx, CanonicalBatch.make({
|
|
6115
|
-
batchId:
|
|
6218
|
+
batchId: subagentJoinBatchId(runId, toolCallId),
|
|
6116
6219
|
producerId: config.producerId,
|
|
6117
|
-
records: [
|
|
6220
|
+
records: [joinedEnvelope, settledEnvelope]
|
|
6118
6221
|
})).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
|
|
6119
|
-
knownIds.add(
|
|
6222
|
+
knownIds.add(joinedRecordId);
|
|
6223
|
+
knownIds.add(settledRecordId);
|
|
6224
|
+
subagentState.joined.set(toolCallId, joinedPayload);
|
|
6225
|
+
finalAccounting = accounting;
|
|
6226
|
+
yield* hit("subagent:after-join-append");
|
|
6120
6227
|
}
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
} else if (startedPayload.childSubmissionId !== admission.childSubmissionId) return yield* LedgerError.make({
|
|
6124
|
-
operation: "establishSubagent",
|
|
6125
|
-
message: `The canonical SubagentStarted record names child ${startedPayload.childSubmissionId} but admission resolved ${admission.childSubmissionId}; establishment fails closed (SUB-016)`
|
|
6126
|
-
});
|
|
6127
|
-
yield* session.attachChildToReservation({
|
|
6128
|
-
reservationId: decodeChildReservationIdSync(requestedPayload.reservationId),
|
|
6129
|
-
childSubmissionId: startedPayload.childSubmissionId
|
|
6130
|
-
}).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("attachChildToReservation")));
|
|
6131
|
-
const identity = {
|
|
6132
|
-
childThreadId: startedPayload.childThreadId,
|
|
6133
|
-
childSubmissionId: startedPayload.childSubmissionId,
|
|
6134
|
-
childRunId: startedPayload.childRunId,
|
|
6135
|
-
receiptId: startedPayload.childReceiptId
|
|
6136
|
-
};
|
|
6137
|
-
const child = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: startedPayload.childSubmissionId }));
|
|
6138
|
-
if (Option.isNone(child)) return yield* LedgerError.make({
|
|
6139
|
-
operation: "establishSubagent",
|
|
6140
|
-
message: `Established child ${startedPayload.childSubmissionId} is unknown to the ledger`
|
|
6141
|
-
});
|
|
6142
|
-
if (child.value.state !== "settled") return {
|
|
6143
|
-
_tag: "waiting",
|
|
6144
|
-
...identity
|
|
6145
|
-
};
|
|
6146
|
-
const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
|
|
6147
|
-
if (verification._tag === "mismatch") return denied("SubagentVerificationFailed", verification.message);
|
|
6148
|
-
return {
|
|
6149
|
-
_tag: "settled",
|
|
6150
|
-
...identity,
|
|
6151
|
-
outcome: verification.value.outcome,
|
|
6152
|
-
encodedResult: verification.value.encodedResult,
|
|
6153
|
-
...yield* verifiedChildUsage(verification.value, startedPayload.childRunId),
|
|
6154
|
-
...verification.value.settlement.finishReason === void 0 ? {} : { finishReason: verification.value.settlement.finishReason }
|
|
6155
|
-
};
|
|
6156
|
-
}).pipe(establishmentGate.withPermits(1)));
|
|
6157
|
-
const joinSubagent = (request) => recordHalt(Effect.gen(function* () {
|
|
6158
|
-
const toolCallId = request.toolCallId;
|
|
6159
|
-
const turnInfo = currentToolTurn;
|
|
6160
|
-
if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined before any canonical response commit` });
|
|
6161
|
-
const requestedPayload = subagentState.requested.get(toolCallId);
|
|
6162
|
-
const startedPayload = subagentState.started.get(toolCallId);
|
|
6163
|
-
if (requestedPayload === void 0 || startedPayload === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without canonical establishment records` });
|
|
6164
|
-
const reservationId = decodeChildReservationIdSync(requestedPayload.reservationId);
|
|
6165
|
-
const joinedRecordId = subagentJoinedRecordId(runId, toolCallId);
|
|
6166
|
-
let finalAccounting;
|
|
6167
|
-
const existingJoined = subagentState.joined.get(toolCallId);
|
|
6168
|
-
if (existingJoined !== void 0) finalAccounting = existingJoined.finalAccounting;
|
|
6169
|
-
else {
|
|
6170
|
-
const encodedResult = yield* decodePersisted(request.encodedResult).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
6171
|
-
message: `The projected result of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
|
|
6172
|
-
cause
|
|
6173
|
-
})));
|
|
6174
|
-
const accounting = yield* decodePersisted(request.encodedAccounting).pipe(Effect.mapError((cause) => RunJournalError.make({
|
|
6175
|
-
message: `The join accounting of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
|
|
6176
|
-
cause
|
|
6177
|
-
})));
|
|
6178
|
-
const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
|
|
6179
|
-
if (verification._tag === "mismatch") return yield* LedgerError.make({
|
|
6180
|
-
operation: "joinSubagent",
|
|
6181
|
-
message: `Child Settlement verification failed for Tool Call ${toolCallId}: ${verification.message}`
|
|
6182
|
-
});
|
|
6183
|
-
const verified = verification.value;
|
|
6184
|
-
const toolName = declaredNamesByCallId.get(toolCallId);
|
|
6185
|
-
if (toolName === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without a declared Tool name` });
|
|
6186
|
-
yield* hit("subagent:before-join-append");
|
|
6187
|
-
const joinedPayload = SubagentJoined.make({
|
|
6228
|
+
yield* applyReservationRelease(reservationId, finalAccounting, {
|
|
6229
|
+
threadId: submission.threadId,
|
|
6188
6230
|
runId,
|
|
6189
|
-
toolCallId
|
|
6190
|
-
childSubmissionId: startedPayload.childSubmissionId,
|
|
6191
|
-
childSettlementId: verified.settlement.settlementId,
|
|
6192
|
-
childOutcome: verified.outcome,
|
|
6193
|
-
usageSummary: yield* childUsageSummaryOf(verified.childRecords, startedPayload.childRunId),
|
|
6194
|
-
...yield* verifiedChildUsage(verified, startedPayload.childRunId),
|
|
6195
|
-
reservationId: requestedPayload.reservationId,
|
|
6196
|
-
finalAccounting: accounting
|
|
6231
|
+
toolCallId
|
|
6197
6232
|
});
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
knownIds.add(joinedRecordId);
|
|
6213
|
-
knownIds.add(settledRecordId);
|
|
6214
|
-
subagentState.joined.set(toolCallId, joinedPayload);
|
|
6215
|
-
finalAccounting = accounting;
|
|
6216
|
-
yield* hit("subagent:after-join-append");
|
|
6217
|
-
}
|
|
6218
|
-
yield* applyReservationRelease(reservationId, finalAccounting, {
|
|
6233
|
+
}));
|
|
6234
|
+
const subagent = {
|
|
6235
|
+
establish: establishSubagent,
|
|
6236
|
+
join: joinSubagent
|
|
6237
|
+
};
|
|
6238
|
+
const toolAuthorization = inheritedGrant === void 0 && runToolAuthorization === RunToolAuthorization.allowAllPolicy ? runToolAuthorization : { authorize: (request) => inheritedGrant !== void 0 && !inheritedGrant.allowedToolNames.includes(request.call.toolName) ? Effect.succeed({
|
|
6239
|
+
_tag: "denied",
|
|
6240
|
+
reason: "Tool exceeds the worker's immutable grant"
|
|
6241
|
+
}) : runToolAuthorization.authorize({
|
|
6242
|
+
...request,
|
|
6243
|
+
input: submission.inputPayload,
|
|
6244
|
+
...Schema.is(FrameworkMessage)(submission.messageAdmission) ? { frameworkMessage: submission.messageAdmission } : {}
|
|
6245
|
+
}) };
|
|
6246
|
+
const options = {
|
|
6219
6247
|
threadId: submission.threadId,
|
|
6220
6248
|
runId,
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
} },
|
|
6270
|
-
...preparedContext === void 0 ? {} : { context: preparedContext },
|
|
6271
|
-
beforeTurn: () => Effect.gen(function* () {
|
|
6272
|
-
if (yieldAfter !== void 0 && (yield* Clock.currentTimeMillis) >= DateTime.toEpochMillis(yieldAfter)) {
|
|
6273
|
-
yield* Deferred.succeed(yieldSignal, void 0);
|
|
6274
|
-
return yield* Effect.never;
|
|
6275
|
-
}
|
|
6276
|
-
if (submissionScheduling.yieldTo !== void 0 && (yield* Ref.get(turnCounter)) > 0) {
|
|
6277
|
-
const candidate = yield* recordHalt(eligibleThreadHead(submission.threadId, submission.queueSequence));
|
|
6278
|
-
if (Option.isSome(candidate) && (candidate.value.state === "ready" || candidate.value.state === "input-applied")) {
|
|
6279
|
-
const next = yield* recordHalt(ledger.lookup(SubmissionLookupById.make({ submissionId: candidate.value.submissionId })));
|
|
6280
|
-
if (Option.isSome(next) && next.value.agentId === submission.agentId && (next.value.state === "ready" || next.value.state === "input-applied") && (yield* recordHalt(submissionScheduling.yieldTo({
|
|
6281
|
-
active: submission,
|
|
6282
|
-
next: next.value
|
|
6283
|
-
})))) {
|
|
6284
|
-
yield* Deferred.succeed(yieldSignal, next.value.submissionId);
|
|
6285
|
-
return yield* Effect.never;
|
|
6249
|
+
history: pending === void 0 ? journal.historyBefore : resumeProjection.historyBefore,
|
|
6250
|
+
input,
|
|
6251
|
+
commandDrainPolicy: "all",
|
|
6252
|
+
...priorContext !== void 0 || journal.committedTurns > 0 || Schema.is(FrameworkMessage)(submission.messageAdmission) ? { retainedInput: submission.inputPayload } : {},
|
|
6253
|
+
...priorContext === void 0 ? {} : { retainedContext: Prompt.fromMessages(priorContext.prompt.content.slice(priorContext.priorHistoryLength)) },
|
|
6254
|
+
...Schema.is(FrameworkMessage)(submission.messageAdmission) ? { frameworkMessage: submission.messageAdmission } : {},
|
|
6255
|
+
approval,
|
|
6256
|
+
toolAuthorization,
|
|
6257
|
+
...journal.toolSelection === void 0 ? {} : { toolSelection: { toolNames: journal.toolSelection.toolNames.filter((name) => Object.hasOwn(agent.definition.toolkit.tools, name)) } },
|
|
6258
|
+
durability,
|
|
6259
|
+
subagent,
|
|
6260
|
+
delegationDepth,
|
|
6261
|
+
...inheritedGrant === void 0 ? {} : { subagentGrant: inheritedGrant },
|
|
6262
|
+
...inheritedBudget === void 0 ? {} : { subagentBudget: inheritedBudget },
|
|
6263
|
+
...submission.workerAdmission?.origin.budgetScope === void 0 ? {} : { subagentBudgetScope: submission.workerAdmission.origin.budgetScope },
|
|
6264
|
+
runStartedAt: runTiming.startedAt,
|
|
6265
|
+
durationDeadline: runTiming.deadline,
|
|
6266
|
+
...submission.workerAdmission === void 0 ? {} : { toolCallAllowance: submission.workerAdmission.origin.toolCallAllowance },
|
|
6267
|
+
...submission.parentLinkage !== void 0 && childLineage?._tag === "SubagentLineageRecorded" ? { toolCallAllowance: childLineage.toolCallAllowance } : {},
|
|
6268
|
+
...pending === void 0 ? {} : { resume: {
|
|
6269
|
+
...settledCompletion === void 0 ? {} : { settledCompletion },
|
|
6270
|
+
turn: pending.turn,
|
|
6271
|
+
toolResultMaxBytes: pending.toolResultMaxBytes,
|
|
6272
|
+
turnId: pending.turnId,
|
|
6273
|
+
calls: pending.calls,
|
|
6274
|
+
toolParameterRejections: pending.toolParameterRejections,
|
|
6275
|
+
settled: pending.settled,
|
|
6276
|
+
toolExposure: pending.toolExposure ?? Snapshot.make({ exposedToolNames: [...new Set(pending.calls.map((call) => call.name))] }),
|
|
6277
|
+
...resumeLeadingMessages === void 0 ? {} : { leadingMessages: resumeLeadingMessages },
|
|
6278
|
+
...resumeResponseMessages === void 0 ? {} : { responseMessages: resumeResponseMessages }
|
|
6279
|
+
} },
|
|
6280
|
+
...preparedContext === void 0 ? {} : { context: preparedContext },
|
|
6281
|
+
beforeTurn: Effect.fnUntraced(function* () {
|
|
6282
|
+
if (yieldAfter !== void 0 && (yield* Clock.currentTimeMillis) >= DateTime.toEpochMillis(yieldAfter)) {
|
|
6283
|
+
yield* Deferred.succeed(yieldSignal, void 0);
|
|
6284
|
+
return yield* Effect.never;
|
|
6285
|
+
}
|
|
6286
|
+
if (submissionScheduling.yieldTo !== void 0 && (yield* Ref.get(turnCounter)) > 0) {
|
|
6287
|
+
const candidate = yield* recordHalt(eligibleThreadHead(submission.threadId, submission.queueSequence));
|
|
6288
|
+
if (Option.isSome(candidate) && (candidate.value.state === "ready" || candidate.value.state === "input-applied")) {
|
|
6289
|
+
const next = yield* recordHalt(ledger.lookup(SubmissionLookupById.make({ submissionId: candidate.value.submissionId })));
|
|
6290
|
+
if (Option.isSome(next) && next.value.agentId === submission.agentId && (next.value.state === "ready" || next.value.state === "input-applied") && (yield* recordHalt(submissionScheduling.yieldTo({
|
|
6291
|
+
active: submission,
|
|
6292
|
+
next: next.value
|
|
6293
|
+
})))) {
|
|
6294
|
+
yield* Deferred.succeed(yieldSignal, next.value.submissionId);
|
|
6295
|
+
return yield* Effect.never;
|
|
6296
|
+
}
|
|
6286
6297
|
}
|
|
6287
6298
|
}
|
|
6288
|
-
}
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
interruptedUsage = true;
|
|
6305
|
-
}
|
|
6306
|
-
const consume = executeWithUsageAccountingUnknown(agent, submission.inputPayload, options).pipe(Effect.provideService(AgentUpdateAcceptance, { accept: (update) => flushDeferredResponse.pipe(Effect.catch((failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" }))))), Effect.andThen(() => updateRuntime.emit({
|
|
6307
|
-
updateId: update.updateId,
|
|
6308
|
-
value: update.value,
|
|
6309
|
-
submission,
|
|
6310
|
-
runId,
|
|
6311
|
-
definitions: submission.agentDigests
|
|
6312
|
-
}).pipe(Effect.provideService(CurrentRunWriter, ctx))), Effect.catchTag(["LedgerError", "DurableRuntimeFailpointError"], (failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" })))))) }), Effect.provideService(ModelUsageAccounting, { noteIncompleteUsage: (turn) => Effect.sync(() => {
|
|
6313
|
-
stagedUnobservedCalls.set(turn, (stagedUnobservedCalls.get(turn) ?? 0) + 1);
|
|
6314
|
-
}) }), Effect.provide(ThreadHistory.layer), Effect.provideService(SubagentHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? SubagentHost.unavailable : workerRuntime.facet({
|
|
6315
|
-
source,
|
|
6316
|
-
policy: agent.definition.policy,
|
|
6317
|
-
depth: delegationDepth,
|
|
6318
|
-
...inheritedGrant === void 0 ? {} : { grant: inheritedGrant }
|
|
6319
|
-
}, submission.principal, submission.submissionId)), Effect.provideService(MessagingHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? MessagingHost.unavailable : messagingRuntime.forTool(source, submission.principal)), Effect.provideService(CurrentToolFailureObserver, toolFailureObserver), Effect.provideService(RunToolVisibility, runToolVisibility), Effect.provideService(RunToolScheduling, runToolScheduling), Effect.provideService(ContextCompactor, compactor), Effect.provideService(RunContextPreparation, runContextPreparation), Effect.andThen(checkpoint), Effect.catchCause((cause) => Ref.get(haltRef).pipe(Effect.flatMap((failure) => failure === void 0 ? Effect.failCause(cause) : Effect.failCause(Cause.map(cause, (error) => error instanceof CoordinatorHalt ? error : new CoordinatorHalt(failure)))))), Effect.tapCause((cause) => Option.isSome(agentApprovalPendingOption(cause)) && cause.reasons.every(Cause.isFailReason) ? Effect.flatMap(DurableApprovalSuspension, (retain) => retain === void 0 ? Effect.void : halt(retain)) : Effect.void), Effect.as({ _tag: "run" }));
|
|
6320
|
-
const abortWatcher = halt(Effect.gen(function* () {
|
|
6321
|
-
while (true) {
|
|
6322
|
-
yield* Effect.sleep(config.abortPollInterval);
|
|
6323
|
-
const intent = yield* ledger.readAbortIntent(AbortIntentRequest.make({ submissionId }));
|
|
6324
|
-
if (intent === void 0) continue;
|
|
6325
|
-
yield* appendAbortRecord(ctx, intent);
|
|
6326
|
-
return { _tag: "aborted" };
|
|
6327
|
-
}
|
|
6328
|
-
}));
|
|
6329
|
-
const execution = Effect.raceFirst(consume, abortWatcher);
|
|
6330
|
-
const result = yield* (yieldAfter === void 0 && submissionScheduling.yieldTo === void 0 ? execution : Effect.raceFirst(execution, Deferred.await(yieldSignal).pipe(Effect.map((nextSubmissionId) => ({
|
|
6331
|
-
_tag: "yielded",
|
|
6332
|
-
...nextSubmissionId === void 0 ? {} : { nextSubmissionId }
|
|
6333
|
-
}))))).pipe(Effect.provideService(IdGenerator$1, idGenerator)).pipe(Effect.catchCauseFilter(Cause.findError, (error, cause) => {
|
|
6334
|
-
if (isCoordinatorHaltCause(cause)) return Effect.failCause(Cause.map(cause, (halt) => halt.failure));
|
|
6335
|
-
if (cause.reasons.some((reason) => reason._tag === "Fail" && reason.error instanceof AgentInputDecodeError)) return Effect.failCause(Cause.map(cause, () => BindingUnavailable.make({
|
|
6336
|
-
agentId: agent.definition.id,
|
|
6337
|
-
message: "The current Binding cannot decode accepted input"
|
|
6338
|
-
})));
|
|
6339
|
-
const approvalPending = agentApprovalPendingOption(cause);
|
|
6340
|
-
if (Option.isSome(approvalPending)) {
|
|
6341
|
-
const residual = Cause.fromReasons(cause.reasons.filter((reason) => reason._tag !== "Fail"));
|
|
6342
|
-
if (residual.reasons.length > 0) return Effect.failCause(residual);
|
|
6343
|
-
return decodeToolCallIdUnknown(approvalPending.value.toolCallId).pipe(Effect.orDie, Effect.map((toolCallId) => ({
|
|
6344
|
-
_tag: "suspendedRun",
|
|
6345
|
-
toolCallId
|
|
6346
|
-
})));
|
|
6299
|
+
}),
|
|
6300
|
+
...runContextPreparation.transientContext === void 0 ? {} : { transientContext: runContextPreparation.transientContext },
|
|
6301
|
+
...config.estimateCostMicrousd === void 0 ? {} : { estimateCostMicrousd: config.estimateCostMicrousd },
|
|
6302
|
+
resumeUsage: {
|
|
6303
|
+
...journal.usage,
|
|
6304
|
+
...journal.policyUsage,
|
|
6305
|
+
...journal.usage.modelCalls === 0 && (journal.usage.unobservedModelCalls ?? 0) === 0 && !records.some(({ record }) => record.payload._tag === "ModelResponseInterrupted" && record.payload.runId === runId) ? emptyRunTotals() : runTotalsFromSummary(yield* currentUsageSummary()),
|
|
6306
|
+
children: childUsageReportsOf(subagentState)
|
|
6307
|
+
},
|
|
6308
|
+
...journal.contextWindowId === void 0 ? {} : { initialContextWindowId: journal.contextWindowId },
|
|
6309
|
+
...journal.protectedContext === void 0 ? {} : { protectedContext: journal.protectedContext },
|
|
6310
|
+
...pendingContextToolCallId === void 0 ? {} : { pendingContextToolCallId }
|
|
6311
|
+
};
|
|
6312
|
+
if (pending === void 0 && lineage.inputWasRecorded) {
|
|
6313
|
+
yield* appendInterruptedAudit(ctx, runId, knownIds);
|
|
6314
|
+
interruptedUsage = true;
|
|
6347
6315
|
}
|
|
6348
|
-
const
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6316
|
+
const consume = executeWithUsageAccountingUnknown(agent, submission.inputPayload, options).pipe(Effect.provideService(AgentUpdateAcceptance, { accept: (update) => flushDeferredResponse.pipe(Effect.catch((failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" }))))), Effect.andThen(() => updateRuntime.emit({
|
|
6317
|
+
updateId: update.updateId,
|
|
6318
|
+
value: update.value,
|
|
6319
|
+
submission,
|
|
6320
|
+
runId,
|
|
6321
|
+
definitions: submission.agentDigests
|
|
6322
|
+
}).pipe(Effect.provideService(CurrentRunWriter, ctx))), Effect.catchTag(["LedgerError", "DurableRuntimeFailpointError"], (failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" })))))) }), Effect.provideService(ModelUsageAccounting, { noteIncompleteUsage: (turn) => Effect.sync(() => {
|
|
6323
|
+
stagedUnobservedCalls.set(turn, (stagedUnobservedCalls.get(turn) ?? 0) + 1);
|
|
6324
|
+
}) }), Effect.provide(ThreadHistory.layer), Effect.provideService(SubagentHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? SubagentHost.unavailable : workerRuntime.facet({
|
|
6325
|
+
source,
|
|
6326
|
+
policy: agent.definition.policy,
|
|
6327
|
+
depth: delegationDepth,
|
|
6328
|
+
...inheritedGrant === void 0 ? {} : { grant: inheritedGrant }
|
|
6329
|
+
}, submission.principal, submission.submissionId)), Effect.provideService(MessagingHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? MessagingHost.unavailable : messagingRuntime.forTool(source, submission.principal)), Effect.provideService(CurrentToolFailureObserver, toolFailureObserver), Effect.provideService(RunToolVisibility, runToolVisibility), Effect.provideService(RunToolScheduling, runToolScheduling), Effect.provideService(ContextCompactor, compactor), Effect.provideService(RunContextPreparation, runContextPreparation), Effect.andThen(checkpoint), Effect.catchCause((cause) => Ref.get(haltRef).pipe(Effect.flatMap((failure) => failure === void 0 ? Effect.failCause(cause) : Effect.failCause(Cause.map(cause, (error) => error instanceof CoordinatorHalt ? error : new CoordinatorHalt(failure)))))), Effect.tapCause((cause) => Option.isSome(agentApprovalPendingOption(cause)) && cause.reasons.every(Cause.isFailReason) ? Effect.flatMap(DurableApprovalSuspension, (retain) => retain === void 0 ? Effect.void : halt(retain)) : Effect.void), Effect.as({ _tag: "run" }));
|
|
6330
|
+
const abortWatcher = halt(Effect.gen(function* () {
|
|
6331
|
+
while (true) {
|
|
6332
|
+
yield* Effect.sleep(config.abortPollInterval);
|
|
6358
6333
|
const intent = yield* ledger.readAbortIntent(AbortIntentRequest.make({ submissionId }));
|
|
6359
|
-
if (intent
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
}
|
|
6334
|
+
if (intent === void 0) continue;
|
|
6335
|
+
yield* appendAbortRecord(ctx, intent);
|
|
6336
|
+
return { _tag: "aborted" };
|
|
6363
6337
|
}
|
|
6364
|
-
|
|
6338
|
+
}));
|
|
6339
|
+
const execution = Effect.raceFirst(consume, abortWatcher);
|
|
6340
|
+
const result = yield* (yieldAfter === void 0 && submissionScheduling.yieldTo === void 0 ? execution : Effect.raceFirst(execution, Deferred.await(yieldSignal).pipe(Effect.map((nextSubmissionId) => ({
|
|
6341
|
+
_tag: "yielded",
|
|
6342
|
+
...nextSubmissionId === void 0 ? {} : { nextSubmissionId }
|
|
6343
|
+
}))))).pipe(Effect.provideService(IdGenerator$1, idGenerator)).pipe(Effect.catchCauseFilter(Cause.findError, (error, cause) => {
|
|
6344
|
+
if (isCoordinatorHaltCause(cause)) return Effect.failCause(Cause.map(cause, (halt) => halt.failure));
|
|
6345
|
+
if (cause.reasons.some((reason) => reason._tag === "Fail" && reason.error instanceof AgentInputDecodeError)) return Effect.failCause(Cause.map(cause, () => BindingUnavailable.make({
|
|
6365
6346
|
agentId: agent.definition.id,
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6347
|
+
message: "The current Binding cannot decode accepted input"
|
|
6348
|
+
})));
|
|
6349
|
+
const approvalPending = agentApprovalPendingOption(cause);
|
|
6350
|
+
if (Option.isSome(approvalPending)) {
|
|
6351
|
+
const residual = Cause.fromReasons(cause.reasons.filter((reason) => reason._tag !== "Fail"));
|
|
6352
|
+
if (residual.reasons.length > 0) return Effect.failCause(residual);
|
|
6353
|
+
return decodeToolCallIdUnknown(approvalPending.value.toolCallId).pipe(Effect.orDie, Effect.map((toolCallId) => ({
|
|
6354
|
+
_tag: "suspendedRun",
|
|
6355
|
+
toolCallId
|
|
6356
|
+
})));
|
|
6357
|
+
}
|
|
6358
|
+
const childPending = agentChildPendingOption(error);
|
|
6359
|
+
if (Option.isSome(childPending)) return Effect.succeed({
|
|
6360
|
+
_tag: "suspendedChildRun",
|
|
6361
|
+
children: childPending.value.children
|
|
6362
|
+
});
|
|
6363
|
+
return Effect.gen(function* () {
|
|
6364
|
+
const halted = yield* Ref.get(haltRef);
|
|
6365
|
+
if (halted !== void 0) return yield* halted;
|
|
6366
|
+
yield* flushDeferredResponse;
|
|
6367
|
+
if (error instanceof AgentToolAuthorizationDenied) {
|
|
6368
|
+
const intent = yield* ledger.readAbortIntent(AbortIntentRequest.make({ submissionId }));
|
|
6369
|
+
if (intent !== void 0) {
|
|
6370
|
+
yield* appendAbortRecord(ctx, intent);
|
|
6371
|
+
return { _tag: "aborted" };
|
|
6372
|
+
}
|
|
6373
|
+
}
|
|
6374
|
+
if (cause.reasons.some((reason) => reason._tag === "Die" || reason._tag === "Fail" && !(reason.error instanceof AgentApprovalDenied) && !(reason.error instanceof AgentToolAuthorizationDenied))) yield* Effect.logError("Agent run failed", cause).pipe(Effect.annotateLogs({
|
|
6374
6375
|
agentId: agent.definition.id,
|
|
6375
6376
|
runId,
|
|
6376
6377
|
threadId: ctx.threadId,
|
|
6377
6378
|
submissionId,
|
|
6378
6379
|
attemptId: lineage.attemptId
|
|
6379
|
-
})
|
|
6380
|
+
}));
|
|
6381
|
+
return {
|
|
6382
|
+
_tag: "failedRun",
|
|
6383
|
+
outcome: yield* failureOutcome(error, cause, {
|
|
6384
|
+
agentId: agent.definition.id,
|
|
6385
|
+
runId,
|
|
6386
|
+
threadId: ctx.threadId,
|
|
6387
|
+
submissionId,
|
|
6388
|
+
attemptId: lineage.attemptId
|
|
6389
|
+
})
|
|
6390
|
+
};
|
|
6391
|
+
});
|
|
6392
|
+
}));
|
|
6393
|
+
if (result._tag === "yielded") return result;
|
|
6394
|
+
if (result._tag === "suspendedRun") return approvalSuspension(result.toolCallId);
|
|
6395
|
+
if (result._tag === "suspendedChildRun") return childSuspension(result.children);
|
|
6396
|
+
if (result._tag === "aborted") {
|
|
6397
|
+
yield* flushDeferredResponse;
|
|
6398
|
+
return {
|
|
6399
|
+
...abortedRunPhase(yield* currentUsageSummary()),
|
|
6400
|
+
uncommittedModelUsage: uncommittedModelUsage()
|
|
6380
6401
|
};
|
|
6402
|
+
}
|
|
6403
|
+
if (result._tag === "failedRun") return {
|
|
6404
|
+
...result.outcome,
|
|
6405
|
+
usageSummary: yield* currentUsageSummary(),
|
|
6406
|
+
uncommittedModelUsage: uncommittedModelUsage()
|
|
6407
|
+
};
|
|
6408
|
+
const committedCompletion = completionState.committed;
|
|
6409
|
+
if (committedCompletion === void 0) return yield* LedgerError.make({
|
|
6410
|
+
operation: "runModel",
|
|
6411
|
+
message: "Agent Run ended without a committed completion"
|
|
6381
6412
|
});
|
|
6382
|
-
}));
|
|
6383
|
-
if (result._tag === "yielded") return result;
|
|
6384
|
-
if (result._tag === "suspendedRun") return approvalSuspension(result.toolCallId);
|
|
6385
|
-
if (result._tag === "suspendedChildRun") return childSuspension(result.children);
|
|
6386
|
-
if (result._tag === "aborted") {
|
|
6387
|
-
yield* flushDeferredResponse;
|
|
6388
6413
|
return {
|
|
6389
|
-
|
|
6414
|
+
_tag: "completed",
|
|
6415
|
+
result: committedCompletion.output,
|
|
6416
|
+
...committedCompletion.runDisposition === void 0 ? {} : { runDisposition: committedCompletion.runDisposition },
|
|
6417
|
+
...committedCompletion.finishReason === void 0 ? {} : { finishReason: committedCompletion.finishReason },
|
|
6418
|
+
...committedCompletion.exhausted === void 0 ? {} : { exhausted: committedCompletion.exhausted },
|
|
6419
|
+
usageSummary: yield* currentUsageSummary(),
|
|
6390
6420
|
uncommittedModelUsage: uncommittedModelUsage()
|
|
6391
6421
|
};
|
|
6392
6422
|
}
|
|
6393
|
-
|
|
6394
|
-
...result.outcome,
|
|
6395
|
-
usageSummary: yield* currentUsageSummary(),
|
|
6396
|
-
uncommittedModelUsage: uncommittedModelUsage()
|
|
6397
|
-
};
|
|
6398
|
-
const committedCompletion = completionState.committed;
|
|
6399
|
-
if (committedCompletion === void 0) return yield* LedgerError.make({
|
|
6400
|
-
operation: "runModel",
|
|
6401
|
-
message: "Agent Run ended without a committed completion"
|
|
6402
|
-
});
|
|
6403
|
-
return {
|
|
6404
|
-
_tag: "completed",
|
|
6405
|
-
result: committedCompletion.output,
|
|
6406
|
-
...committedCompletion.runDisposition === void 0 ? {} : { runDisposition: committedCompletion.runDisposition },
|
|
6407
|
-
...committedCompletion.finishReason === void 0 ? {} : { finishReason: committedCompletion.finishReason },
|
|
6408
|
-
...committedCompletion.exhausted === void 0 ? {} : { exhausted: committedCompletion.exhausted },
|
|
6409
|
-
usageSummary: yield* currentUsageSummary(),
|
|
6410
|
-
uncommittedModelUsage: uncommittedModelUsage()
|
|
6411
|
-
};
|
|
6412
|
-
});
|
|
6423
|
+
);
|
|
6413
6424
|
/**
|
|
6414
6425
|
* One ownership period over the claimed lane head. The step order mirrors the pure recovery
|
|
6415
6426
|
* classifier's decision table, so a fresh Attempt and a recovering Attempt take the same path
|
|
@@ -6417,7 +6428,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
6417
6428
|
* (Unknown Outcomes, or a durable approval suspension) — no settlement occurs and the
|
|
6418
6429
|
* obligation stays owed.
|
|
6419
6430
|
*/
|
|
6420
|
-
const runAttempt = (registeredAgent, session, resumeAfterRetention, onHandoff, yieldAfter)
|
|
6431
|
+
const runAttempt = Effect.fnUntraced(function* (registeredAgent, session, resumeAfterRetention, onHandoff, yieldAfter) {
|
|
6421
6432
|
yield* session.checkActive;
|
|
6422
6433
|
const checkpointPrompt = yield* promptHistory.take({ threadId: session.threadId }).pipe(Effect.provideService(ThreadStore, store), Effect.provideService(ThreadReader, reader), Effect.provideService(Crypto.Crypto, crypto));
|
|
6423
6434
|
let committedPromptSuffix;
|
|
@@ -6473,7 +6484,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
6473
6484
|
journalMetadata = void 0;
|
|
6474
6485
|
return metadata;
|
|
6475
6486
|
};
|
|
6476
|
-
let records =
|
|
6487
|
+
let records = initialView.records.filter(collectControl);
|
|
6477
6488
|
const refreshControl = Effect.fnUntraced(function* (throughSequence) {
|
|
6478
6489
|
const through = throughSequence ?? (yield* store.inspectTail(ThreadTailRequest.make({ threadId }))).tailSequence;
|
|
6479
6490
|
if (through > controlThrough) {
|
|
@@ -6513,7 +6524,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
6513
6524
|
return Option.some(yield* settleAborted(ctx, submission, session.publishSettlement, snapshot.abortIntent, evidence, knownIds));
|
|
6514
6525
|
}
|
|
6515
6526
|
yield* applyCanonicalInput(ctx, submission, session, records, snapshot.inputApplied);
|
|
6516
|
-
const start = yield* makeRunStart(submission, Duration.toMillis(agent.definition.policy.maxDuration), yield* refreshControl()).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
6527
|
+
const start = yield* makeRunStart(submission, Duration.toMillis(agent.definition.policy.maxDuration), yield* refreshControl(), initialView.operational).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
6517
6528
|
const savedRunTiming = start.timing;
|
|
6518
6529
|
const commitStart = Effect.flatMap(CurrentRunStart, (publication) => publication.commit()).pipe(Effect.provideService(CurrentRunStart, start.publication));
|
|
6519
6530
|
const runTiming = workerOrigin === void 0 ? savedRunTiming : {
|
|
@@ -6623,7 +6634,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
6623
6634
|
const tail = yield* session.tail;
|
|
6624
6635
|
const currentRecords = yield* refreshControl(tail.sequence);
|
|
6625
6636
|
const view = yield* recoveryView(threadId, tail.sequence, [submissionId], runIdForSubmission(submissionId), currentRecords);
|
|
6626
|
-
let canonical = view.
|
|
6637
|
+
let canonical = Stream.fromIterable(view.records);
|
|
6627
6638
|
let initialJournal;
|
|
6628
6639
|
if (view.context === void 0) {
|
|
6629
6640
|
const original = currentRecords.find(({ record }) => record.payload._tag === "UserInputRecorded" && record.payload.kind === "user" && record.payload.submissionId === submissionId);
|
|
@@ -6733,7 +6744,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
6733
6744
|
if (outcome._tag === "completed" && initialJournal?.cacheable && initialJournal.history !== void 0) yield* promptHistory.complete({ threadId: session.threadId }, initialJournal.original, initialJournal.history, committedPromptSuffix).pipe(Effect.provideService(CurrentRunWriter, session), Effect.provideService(ThreadStore, store), Effect.provideService(ThreadReader, reader));
|
|
6734
6745
|
return Option.some(settlement);
|
|
6735
6746
|
}
|
|
6736
|
-
}).pipe(Effect.scoped);
|
|
6747
|
+
}, (effect) => effect.pipe(Effect.scoped));
|
|
6737
6748
|
const acquireAdministrativeClaim = (threadId, handoff) => runStorage.claim(ClaimRequest.make({
|
|
6738
6749
|
threadId,
|
|
6739
6750
|
...handoff === void 0 ? {} : { handoff }
|
|
@@ -6819,7 +6830,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
6819
6830
|
settlements.push(settlement.value);
|
|
6820
6831
|
}
|
|
6821
6832
|
}).pipe((body) => withProcessing(threadId, body));
|
|
6822
|
-
const processThreadImpl =
|
|
6833
|
+
const processThreadImpl = Effect.fnUntraced(function* (agent, threadId) {
|
|
6823
6834
|
const binding = yield* makeLegacyWorkerBinding(agent);
|
|
6824
6835
|
return yield* drainThread((submission) => submission.agentId === binding.agentId ? Effect.succeed(binding) : Effect.fail(BindingUnavailable.make({
|
|
6825
6836
|
agentId: submission.agentId,
|
|
@@ -7221,8 +7232,7 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
7221
7232
|
const snapshot = yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId: submission.submissionId }));
|
|
7222
7233
|
if (snapshot.hostSubmissionId !== void 0 && !history.submissionIds.includes(snapshot.hostSubmissionId)) {
|
|
7223
7234
|
const hostId = snapshot.hostSubmissionId;
|
|
7224
|
-
const
|
|
7225
|
-
const hostRecords = yield* Stream.runCollect(hostView.canonical.pipe(Stream.filter(controlRecords([hostId]))));
|
|
7235
|
+
const hostRecords = (yield* recoveryView(submission.threadId, history.throughSequence, [hostId])).records.filter(controlRecords([hostId]));
|
|
7226
7236
|
const merged = new Map(history.records.map((entry) => [entry.sequence, entry]));
|
|
7227
7237
|
for (const entry of hostRecords) merged.set(entry.sequence, entry);
|
|
7228
7238
|
history = {
|
|
@@ -7776,10 +7786,6 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
7776
7786
|
submissionId: receipt.submissionId
|
|
7777
7787
|
});
|
|
7778
7788
|
if (snapshot.value.state !== "settled") return Option.none();
|
|
7779
|
-
const settlement = yield* ledger.finalizeSettlement(SettlementFinalization.make({
|
|
7780
|
-
submissionId: receipt.submissionId,
|
|
7781
|
-
settlementId: submissionSettlementId(receipt.submissionId)
|
|
7782
|
-
}));
|
|
7783
7789
|
const canonical = yield* getRecord({
|
|
7784
7790
|
threadId: receipt.threadId,
|
|
7785
7791
|
recordId: submissionSettlementRecordId(receipt.submissionId)
|
|
@@ -7793,6 +7799,23 @@ const make = Effect.fnUntraced(function* (bindings) {
|
|
|
7793
7799
|
message: "Finalized Submission has no canonical Settlement"
|
|
7794
7800
|
});
|
|
7795
7801
|
const record = yield* settlementPayloadFromRecord(canonical.value.record, receipt.submissionId);
|
|
7802
|
+
const finalized = snapshot.value;
|
|
7803
|
+
const retainedFinalization = finalized.settledAt !== void 0 && finalized.settledRecordId !== void 0 && finalized.settledOutcome !== void 0;
|
|
7804
|
+
if (retainedFinalization && (finalized.settledRecordId !== canonical.value.record.recordId || finalized.settledOutcome !== record.outcome || canonical.value.batchId !== submissionSettlementBatchId(receipt.submissionId))) return yield* LedgerError.make({
|
|
7805
|
+
operation: "awaitSettlement",
|
|
7806
|
+
message: "Settled projection disagrees with its canonical Settlement"
|
|
7807
|
+
});
|
|
7808
|
+
const settlement = retainedFinalization ? Settlement.make({
|
|
7809
|
+
submissionId: receipt.submissionId,
|
|
7810
|
+
settlementId: record.settlementId,
|
|
7811
|
+
receiptId: record.receiptId,
|
|
7812
|
+
outcome: record.outcome,
|
|
7813
|
+
...record.outcome === "failed" ? { failure: record.result } : {},
|
|
7814
|
+
settledAt: finalized.settledAt
|
|
7815
|
+
}) : yield* ledger.finalizeSettlement(SettlementFinalization.make({
|
|
7816
|
+
submissionId: receipt.submissionId,
|
|
7817
|
+
settlementId: submissionSettlementId(receipt.submissionId)
|
|
7818
|
+
}));
|
|
7796
7819
|
if (record.receiptId !== receipt.receiptId || record.settlementId !== settlement.settlementId || record.outcome !== settlement.outcome) return yield* LedgerError.make({
|
|
7797
7820
|
operation: "awaitSettlement",
|
|
7798
7821
|
message: "Canonical Settlement disagrees with the receipt or finalized outcome"
|
|
@@ -8348,4 +8371,4 @@ var DurableAgentRuntime = class DurableAgentRuntime extends Context.Service()("@
|
|
|
8348
8371
|
//#endregion
|
|
8349
8372
|
export { DurableApprovalSuspension as a, RecoveryFailure as c, WorkRecoveryReport as d, WorkRecoveryRequest as f, recoveryRepairRecordId as g, recoveryRepairBatchId as h, DurableApprovalResolver as i, RecoveryReport as l, isolateRecovery as m, DurableAgentRuntime as n, DurableRuntimeConfig as o, childReservationIdFor as p, DurableAgentRuntime_exports as r, RecoveryBlocked as s, ApprovalSuspensionError as t, RecoverySweepResult as u };
|
|
8350
8373
|
|
|
8351
|
-
//# sourceMappingURL=DurableAgentRuntime-
|
|
8374
|
+
//# sourceMappingURL=DurableAgentRuntime-CBBjRNJN.mjs.map
|