@smthrs/harness 0.0.0-stage → 1.0.0-rc.3
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/CHANGELOG.md +387 -0
- package/LICENSE +21 -0
- package/README.md +138 -2
- package/dist/cjs/AgentEvent.d.ts +3092 -0
- package/dist/cjs/AgentEvent.d.ts.map +1 -0
- package/dist/cjs/AgentEvent.js +1116 -0
- package/dist/cjs/AgentEvent.js.map +7 -0
- package/dist/cjs/CallLedger.d.ts +378 -0
- package/dist/cjs/CallLedger.d.ts.map +1 -0
- package/dist/cjs/CallLedger.js +240 -0
- package/dist/cjs/CallLedger.js.map +7 -0
- package/dist/cjs/Cell.d.ts +774 -0
- package/dist/cjs/Cell.d.ts.map +1 -0
- package/dist/cjs/Cell.js +431 -0
- package/dist/cjs/Cell.js.map +7 -0
- package/dist/cjs/CellCalls.d.ts +115 -0
- package/dist/cjs/CellCalls.d.ts.map +1 -0
- package/dist/cjs/CellCalls.js +98 -0
- package/dist/cjs/CellCalls.js.map +7 -0
- package/dist/cjs/CellHistory.d.ts +102 -0
- package/dist/cjs/CellHistory.d.ts.map +1 -0
- package/dist/cjs/CellHistory.js +54 -0
- package/dist/cjs/CellHistory.js.map +7 -0
- package/dist/cjs/CellTurn.d.ts +1071 -0
- package/dist/cjs/CellTurn.d.ts.map +1 -0
- package/dist/cjs/CellTurn.js +2618 -0
- package/dist/cjs/CellTurn.js.map +7 -0
- package/dist/cjs/CellValidation.d.ts +94 -0
- package/dist/cjs/CellValidation.d.ts.map +1 -0
- package/dist/cjs/CellValidation.js +218 -0
- package/dist/cjs/CellValidation.js.map +7 -0
- package/dist/cjs/Compaction.d.ts +158 -0
- package/dist/cjs/Compaction.d.ts.map +1 -0
- package/dist/cjs/Compaction.js +189 -0
- package/dist/cjs/Compaction.js.map +7 -0
- package/dist/cjs/CompletionClaim.d.ts +801 -0
- package/dist/cjs/CompletionClaim.d.ts.map +1 -0
- package/dist/cjs/CompletionClaim.js +303 -0
- package/dist/cjs/CompletionClaim.js.map +7 -0
- package/dist/cjs/ContextWindow.d.ts +435 -0
- package/dist/cjs/ContextWindow.d.ts.map +1 -0
- package/dist/cjs/ContextWindow.js +319 -0
- package/dist/cjs/ContextWindow.js.map +7 -0
- package/dist/cjs/EngineLike.d.ts +546 -0
- package/dist/cjs/EngineLike.d.ts.map +1 -0
- package/dist/cjs/EngineLike.js +114 -0
- package/dist/cjs/EngineLike.js.map +7 -0
- package/dist/cjs/ExternalTranscript.d.ts +349 -0
- package/dist/cjs/ExternalTranscript.d.ts.map +1 -0
- package/dist/cjs/ExternalTranscript.js +826 -0
- package/dist/cjs/ExternalTranscript.js.map +7 -0
- package/dist/cjs/FailedCall.d.ts +132 -0
- package/dist/cjs/FailedCall.d.ts.map +1 -0
- package/dist/cjs/FailedCall.js +53 -0
- package/dist/cjs/FailedCall.js.map +7 -0
- package/dist/cjs/FlowBinding.d.ts +289 -0
- package/dist/cjs/FlowBinding.d.ts.map +1 -0
- package/dist/cjs/FlowBinding.js +251 -0
- package/dist/cjs/FlowBinding.js.map +7 -0
- package/dist/cjs/HarnessError.d.ts +57 -0
- package/dist/cjs/HarnessError.d.ts.map +1 -0
- package/dist/cjs/HarnessError.js +75 -0
- package/dist/cjs/HarnessError.js.map +7 -0
- package/dist/cjs/Judgement.d.ts +289 -0
- package/dist/cjs/Judgement.d.ts.map +1 -0
- package/dist/cjs/Judgement.js +240 -0
- package/dist/cjs/Judgement.js.map +7 -0
- package/dist/cjs/Monitor.d.ts +374 -0
- package/dist/cjs/Monitor.d.ts.map +1 -0
- package/dist/cjs/Monitor.js +233 -0
- package/dist/cjs/Monitor.js.map +7 -0
- package/dist/cjs/NarrowedCheck.d.ts +523 -0
- package/dist/cjs/NarrowedCheck.d.ts.map +1 -0
- package/dist/cjs/NarrowedCheck.js +263 -0
- package/dist/cjs/NarrowedCheck.js.map +7 -0
- package/dist/cjs/Notifications.d.ts +42 -0
- package/dist/cjs/Notifications.d.ts.map +1 -0
- package/dist/cjs/Notifications.js +177 -0
- package/dist/cjs/Notifications.js.map +7 -0
- package/dist/cjs/Plan.d.ts +127 -0
- package/dist/cjs/Plan.d.ts.map +1 -0
- package/dist/cjs/Plan.js +77 -0
- package/dist/cjs/Plan.js.map +7 -0
- package/dist/cjs/QuickJSSandbox.d.ts +151 -0
- package/dist/cjs/QuickJSSandbox.d.ts.map +1 -0
- package/dist/cjs/QuickJSSandbox.js +987 -0
- package/dist/cjs/QuickJSSandbox.js.map +7 -0
- package/dist/cjs/Relevance.d.ts +213 -0
- package/dist/cjs/Relevance.d.ts.map +1 -0
- package/dist/cjs/Relevance.js +183 -0
- package/dist/cjs/Relevance.js.map +7 -0
- package/dist/cjs/Sandbox.d.ts +637 -0
- package/dist/cjs/Sandbox.d.ts.map +1 -0
- package/dist/cjs/Sandbox.js +260 -0
- package/dist/cjs/Sandbox.js.map +7 -0
- package/dist/cjs/Steering.d.ts +464 -0
- package/dist/cjs/Steering.d.ts.map +1 -0
- package/dist/cjs/Steering.js +153 -0
- package/dist/cjs/Steering.js.map +7 -0
- package/dist/cjs/StructuredOutput.d.ts +252 -0
- package/dist/cjs/StructuredOutput.d.ts.map +1 -0
- package/dist/cjs/StructuredOutput.js +266 -0
- package/dist/cjs/StructuredOutput.js.map +7 -0
- package/dist/cjs/Sufficiency.d.ts +195 -0
- package/dist/cjs/Sufficiency.d.ts.map +1 -0
- package/dist/cjs/Sufficiency.js +110 -0
- package/dist/cjs/Sufficiency.js.map +7 -0
- package/dist/cjs/Supervisor.d.ts +719 -0
- package/dist/cjs/Supervisor.d.ts.map +1 -0
- package/dist/cjs/Supervisor.js +313 -0
- package/dist/cjs/Supervisor.js.map +7 -0
- package/dist/cjs/Tokens.d.ts +86 -0
- package/dist/cjs/Tokens.d.ts.map +1 -0
- package/dist/cjs/Tokens.js +72 -0
- package/dist/cjs/Tokens.js.map +7 -0
- package/dist/cjs/Transcript.d.ts +171 -0
- package/dist/cjs/Transcript.d.ts.map +1 -0
- package/dist/cjs/Transcript.js +342 -0
- package/dist/cjs/Transcript.js.map +7 -0
- package/dist/cjs/TruncatedOutput.d.ts +186 -0
- package/dist/cjs/TruncatedOutput.d.ts.map +1 -0
- package/dist/cjs/TruncatedOutput.js +143 -0
- package/dist/cjs/TruncatedOutput.js.map +7 -0
- package/dist/cjs/UnmovedTree.d.ts +113 -0
- package/dist/cjs/UnmovedTree.d.ts.map +1 -0
- package/dist/cjs/UnmovedTree.js +38 -0
- package/dist/cjs/UnmovedTree.js.map +7 -0
- package/dist/cjs/UnresolvedFailure.d.ts +196 -0
- package/dist/cjs/UnresolvedFailure.d.ts.map +1 -0
- package/dist/cjs/UnresolvedFailure.js +77 -0
- package/dist/cjs/UnresolvedFailure.js.map +7 -0
- package/dist/cjs/VacuousVerification.d.ts +237 -0
- package/dist/cjs/VacuousVerification.d.ts.map +1 -0
- package/dist/cjs/VacuousVerification.js +91 -0
- package/dist/cjs/VacuousVerification.js.map +7 -0
- package/dist/cjs/VariablesPanel.d.ts +117 -0
- package/dist/cjs/VariablesPanel.d.ts.map +1 -0
- package/dist/cjs/VariablesPanel.js +108 -0
- package/dist/cjs/VariablesPanel.js.map +7 -0
- package/dist/cjs/index.d.ts +172 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +99 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/bytes.d.ts +36 -0
- package/dist/cjs/internal/bytes.d.ts.map +1 -0
- package/dist/cjs/internal/bytes.js +57 -0
- package/dist/cjs/internal/bytes.js.map +7 -0
- package/dist/cjs/internal/cellPrompt.d.ts +122 -0
- package/dist/cjs/internal/cellPrompt.d.ts.map +1 -0
- package/dist/cjs/internal/cellPrompt.js +146 -0
- package/dist/cjs/internal/cellPrompt.js.map +7 -0
- package/dist/cjs/internal/compactable.d.ts +44 -0
- package/dist/cjs/internal/compactable.d.ts.map +1 -0
- package/dist/cjs/internal/compactable.js +56 -0
- package/dist/cjs/internal/compactable.js.map +7 -0
- package/dist/cjs/internal/compactionMarks.d.ts +278 -0
- package/dist/cjs/internal/compactionMarks.d.ts.map +1 -0
- package/dist/cjs/internal/compactionMarks.js +212 -0
- package/dist/cjs/internal/compactionMarks.js.map +7 -0
- package/dist/cjs/internal/demandText.d.ts +95 -0
- package/dist/cjs/internal/demandText.d.ts.map +1 -0
- package/dist/cjs/internal/demandText.js +70 -0
- package/dist/cjs/internal/demandText.js.map +7 -0
- package/dist/cjs/internal/elide.d.ts +109 -0
- package/dist/cjs/internal/elide.d.ts.map +1 -0
- package/dist/cjs/internal/elide.js +59 -0
- package/dist/cjs/internal/elide.js.map +7 -0
- package/dist/cjs/internal/frame.d.ts +463 -0
- package/dist/cjs/internal/frame.d.ts.map +1 -0
- package/dist/cjs/internal/frame.js +514 -0
- package/dist/cjs/internal/frame.js.map +7 -0
- package/dist/cjs/internal/nonNegativeSafeInt.d.ts +20 -0
- package/dist/cjs/internal/nonNegativeSafeInt.d.ts.map +1 -0
- package/dist/cjs/internal/nonNegativeSafeInt.js +29 -0
- package/dist/cjs/internal/nonNegativeSafeInt.js.map +7 -0
- package/dist/cjs/internal/paidUsage.d.ts +52 -0
- package/dist/cjs/internal/paidUsage.d.ts.map +1 -0
- package/dist/cjs/internal/paidUsage.js +70 -0
- package/dist/cjs/internal/paidUsage.js.map +7 -0
- package/dist/cjs/internal/printChannel.d.ts +233 -0
- package/dist/cjs/internal/printChannel.d.ts.map +1 -0
- package/dist/cjs/internal/printChannel.js +165 -0
- package/dist/cjs/internal/printChannel.js.map +7 -0
- package/dist/cjs/internal/printsObservation.d.ts +26 -0
- package/dist/cjs/internal/printsObservation.d.ts.map +1 -0
- package/dist/cjs/internal/printsObservation.js +27 -0
- package/dist/cjs/internal/printsObservation.js.map +7 -0
- package/dist/cjs/internal/refusal.d.ts +40 -0
- package/dist/cjs/internal/refusal.d.ts.map +1 -0
- package/dist/cjs/internal/refusal.js +45 -0
- package/dist/cjs/internal/refusal.js.map +7 -0
- package/dist/cjs/internal/supervision.d.ts +174 -0
- package/dist/cjs/internal/supervision.d.ts.map +1 -0
- package/dist/cjs/internal/supervision.js +402 -0
- package/dist/cjs/internal/supervision.js.map +7 -0
- package/dist/cjs/internal/unfinishedWork.d.ts +99 -0
- package/dist/cjs/internal/unfinishedWork.d.ts.map +1 -0
- package/dist/cjs/internal/unfinishedWork.js +80 -0
- package/dist/cjs/internal/unfinishedWork.js.map +7 -0
- package/dist/cjs/internal/unobservedCall.d.ts +112 -0
- package/dist/cjs/internal/unobservedCall.d.ts.map +1 -0
- package/dist/cjs/internal/unobservedCall.js +345 -0
- package/dist/cjs/internal/unobservedCall.js.map +7 -0
- package/dist/cjs/internal/untrustedData.d.ts +14 -0
- package/dist/cjs/internal/untrustedData.d.ts.map +1 -0
- package/dist/cjs/internal/untrustedData.js +30 -0
- package/dist/cjs/internal/untrustedData.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/AgentEvent.d.ts +3092 -0
- package/dist/esm/AgentEvent.d.ts.map +1 -0
- package/dist/esm/AgentEvent.js +1610 -0
- package/dist/esm/AgentEvent.js.map +1 -0
- package/dist/esm/CallLedger.d.ts +378 -0
- package/dist/esm/CallLedger.d.ts.map +1 -0
- package/dist/esm/CallLedger.js +506 -0
- package/dist/esm/CallLedger.js.map +1 -0
- package/dist/esm/Cell.d.ts +774 -0
- package/dist/esm/Cell.d.ts.map +1 -0
- package/dist/esm/Cell.js +772 -0
- package/dist/esm/Cell.js.map +1 -0
- package/dist/esm/CellCalls.d.ts +115 -0
- package/dist/esm/CellCalls.d.ts.map +1 -0
- package/dist/esm/CellCalls.js +97 -0
- package/dist/esm/CellCalls.js.map +1 -0
- package/dist/esm/CellHistory.d.ts +102 -0
- package/dist/esm/CellHistory.d.ts.map +1 -0
- package/dist/esm/CellHistory.js +91 -0
- package/dist/esm/CellHistory.js.map +1 -0
- package/dist/esm/CellTurn.d.ts +1071 -0
- package/dist/esm/CellTurn.d.ts.map +1 -0
- package/dist/esm/CellTurn.js +3410 -0
- package/dist/esm/CellTurn.js.map +1 -0
- package/dist/esm/CellValidation.d.ts +94 -0
- package/dist/esm/CellValidation.d.ts.map +1 -0
- package/dist/esm/CellValidation.js +335 -0
- package/dist/esm/CellValidation.js.map +1 -0
- package/dist/esm/Compaction.d.ts +158 -0
- package/dist/esm/Compaction.d.ts.map +1 -0
- package/dist/esm/Compaction.js +216 -0
- package/dist/esm/Compaction.js.map +1 -0
- package/dist/esm/CompletionClaim.d.ts +801 -0
- package/dist/esm/CompletionClaim.d.ts.map +1 -0
- package/dist/esm/CompletionClaim.js +833 -0
- package/dist/esm/CompletionClaim.js.map +1 -0
- package/dist/esm/ContextWindow.d.ts +435 -0
- package/dist/esm/ContextWindow.d.ts.map +1 -0
- package/dist/esm/ContextWindow.js +427 -0
- package/dist/esm/ContextWindow.js.map +1 -0
- package/dist/esm/EngineLike.d.ts +546 -0
- package/dist/esm/EngineLike.d.ts.map +1 -0
- package/dist/esm/EngineLike.js +218 -0
- package/dist/esm/EngineLike.js.map +1 -0
- package/dist/esm/ExternalTranscript.d.ts +349 -0
- package/dist/esm/ExternalTranscript.d.ts.map +1 -0
- package/dist/esm/ExternalTranscript.js +987 -0
- package/dist/esm/ExternalTranscript.js.map +1 -0
- package/dist/esm/FailedCall.d.ts +132 -0
- package/dist/esm/FailedCall.d.ts.map +1 -0
- package/dist/esm/FailedCall.js +131 -0
- package/dist/esm/FailedCall.js.map +1 -0
- package/dist/esm/FlowBinding.d.ts +289 -0
- package/dist/esm/FlowBinding.d.ts.map +1 -0
- package/dist/esm/FlowBinding.js +376 -0
- package/dist/esm/FlowBinding.js.map +1 -0
- package/dist/esm/HarnessError.d.ts +57 -0
- package/dist/esm/HarnessError.d.ts.map +1 -0
- package/dist/esm/HarnessError.js +85 -0
- package/dist/esm/HarnessError.js.map +1 -0
- package/dist/esm/Judgement.d.ts +289 -0
- package/dist/esm/Judgement.d.ts.map +1 -0
- package/dist/esm/Judgement.js +305 -0
- package/dist/esm/Judgement.js.map +1 -0
- package/dist/esm/Monitor.d.ts +374 -0
- package/dist/esm/Monitor.d.ts.map +1 -0
- package/dist/esm/Monitor.js +370 -0
- package/dist/esm/Monitor.js.map +1 -0
- package/dist/esm/NarrowedCheck.d.ts +523 -0
- package/dist/esm/NarrowedCheck.d.ts.map +1 -0
- package/dist/esm/NarrowedCheck.js +612 -0
- package/dist/esm/NarrowedCheck.js.map +1 -0
- package/dist/esm/Notifications.d.ts +42 -0
- package/dist/esm/Notifications.d.ts.map +1 -0
- package/dist/esm/Notifications.js +215 -0
- package/dist/esm/Notifications.js.map +1 -0
- package/dist/esm/Plan.d.ts +127 -0
- package/dist/esm/Plan.d.ts.map +1 -0
- package/dist/esm/Plan.js +97 -0
- package/dist/esm/Plan.js.map +1 -0
- package/dist/esm/QuickJSSandbox.d.ts +151 -0
- package/dist/esm/QuickJSSandbox.d.ts.map +1 -0
- package/dist/esm/QuickJSSandbox.js +1364 -0
- package/dist/esm/QuickJSSandbox.js.map +1 -0
- package/dist/esm/Relevance.d.ts +213 -0
- package/dist/esm/Relevance.d.ts.map +1 -0
- package/dist/esm/Relevance.js +254 -0
- package/dist/esm/Relevance.js.map +1 -0
- package/dist/esm/Sandbox.d.ts +637 -0
- package/dist/esm/Sandbox.d.ts.map +1 -0
- package/dist/esm/Sandbox.js +464 -0
- package/dist/esm/Sandbox.js.map +1 -0
- package/dist/esm/Steering.d.ts +464 -0
- package/dist/esm/Steering.d.ts.map +1 -0
- package/dist/esm/Steering.js +193 -0
- package/dist/esm/Steering.js.map +1 -0
- package/dist/esm/StructuredOutput.d.ts +252 -0
- package/dist/esm/StructuredOutput.d.ts.map +1 -0
- package/dist/esm/StructuredOutput.js +430 -0
- package/dist/esm/StructuredOutput.js.map +1 -0
- package/dist/esm/Sufficiency.d.ts +195 -0
- package/dist/esm/Sufficiency.d.ts.map +1 -0
- package/dist/esm/Sufficiency.js +207 -0
- package/dist/esm/Sufficiency.js.map +1 -0
- package/dist/esm/Supervisor.d.ts +719 -0
- package/dist/esm/Supervisor.d.ts.map +1 -0
- package/dist/esm/Supervisor.js +575 -0
- package/dist/esm/Supervisor.js.map +1 -0
- package/dist/esm/Tokens.d.ts +86 -0
- package/dist/esm/Tokens.d.ts.map +1 -0
- package/dist/esm/Tokens.js +92 -0
- package/dist/esm/Tokens.js.map +1 -0
- package/dist/esm/Transcript.d.ts +171 -0
- package/dist/esm/Transcript.d.ts.map +1 -0
- package/dist/esm/Transcript.js +424 -0
- package/dist/esm/Transcript.js.map +1 -0
- package/dist/esm/TruncatedOutput.d.ts +186 -0
- package/dist/esm/TruncatedOutput.d.ts.map +1 -0
- package/dist/esm/TruncatedOutput.js +257 -0
- package/dist/esm/TruncatedOutput.js.map +1 -0
- package/dist/esm/UnmovedTree.d.ts +113 -0
- package/dist/esm/UnmovedTree.d.ts.map +1 -0
- package/dist/esm/UnmovedTree.js +90 -0
- package/dist/esm/UnmovedTree.js.map +1 -0
- package/dist/esm/UnresolvedFailure.d.ts +196 -0
- package/dist/esm/UnresolvedFailure.d.ts.map +1 -0
- package/dist/esm/UnresolvedFailure.js +218 -0
- package/dist/esm/UnresolvedFailure.js.map +1 -0
- package/dist/esm/VacuousVerification.d.ts +237 -0
- package/dist/esm/VacuousVerification.d.ts.map +1 -0
- package/dist/esm/VacuousVerification.js +245 -0
- package/dist/esm/VacuousVerification.js.map +1 -0
- package/dist/esm/VariablesPanel.d.ts +117 -0
- package/dist/esm/VariablesPanel.d.ts.map +1 -0
- package/dist/esm/VariablesPanel.js +142 -0
- package/dist/esm/VariablesPanel.js.map +1 -0
- package/dist/esm/index.d.ts +172 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +172 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/bytes.d.ts +36 -0
- package/dist/esm/internal/bytes.d.ts.map +1 -0
- package/dist/esm/internal/bytes.js +70 -0
- package/dist/esm/internal/bytes.js.map +1 -0
- package/dist/esm/internal/cellPrompt.d.ts +122 -0
- package/dist/esm/internal/cellPrompt.d.ts.map +1 -0
- package/dist/esm/internal/cellPrompt.js +276 -0
- package/dist/esm/internal/cellPrompt.js.map +1 -0
- package/dist/esm/internal/compactable.d.ts +44 -0
- package/dist/esm/internal/compactable.d.ts.map +1 -0
- package/dist/esm/internal/compactable.js +71 -0
- package/dist/esm/internal/compactable.js.map +1 -0
- package/dist/esm/internal/compactionMarks.d.ts +278 -0
- package/dist/esm/internal/compactionMarks.d.ts.map +1 -0
- package/dist/esm/internal/compactionMarks.js +317 -0
- package/dist/esm/internal/compactionMarks.js.map +1 -0
- package/dist/esm/internal/demandText.d.ts +95 -0
- package/dist/esm/internal/demandText.d.ts.map +1 -0
- package/dist/esm/internal/demandText.js +128 -0
- package/dist/esm/internal/demandText.js.map +1 -0
- package/dist/esm/internal/elide.d.ts +109 -0
- package/dist/esm/internal/elide.d.ts.map +1 -0
- package/dist/esm/internal/elide.js +123 -0
- package/dist/esm/internal/elide.js.map +1 -0
- package/dist/esm/internal/frame.d.ts +463 -0
- package/dist/esm/internal/frame.d.ts.map +1 -0
- package/dist/esm/internal/frame.js +861 -0
- package/dist/esm/internal/frame.js.map +1 -0
- package/dist/esm/internal/nonNegativeSafeInt.d.ts +20 -0
- package/dist/esm/internal/nonNegativeSafeInt.d.ts.map +1 -0
- package/dist/esm/internal/nonNegativeSafeInt.js +20 -0
- package/dist/esm/internal/nonNegativeSafeInt.js.map +1 -0
- package/dist/esm/internal/paidUsage.d.ts +52 -0
- package/dist/esm/internal/paidUsage.d.ts.map +1 -0
- package/dist/esm/internal/paidUsage.js +72 -0
- package/dist/esm/internal/paidUsage.js.map +1 -0
- package/dist/esm/internal/printChannel.d.ts +233 -0
- package/dist/esm/internal/printChannel.d.ts.map +1 -0
- package/dist/esm/internal/printChannel.js +376 -0
- package/dist/esm/internal/printChannel.js.map +1 -0
- package/dist/esm/internal/printsObservation.d.ts +26 -0
- package/dist/esm/internal/printsObservation.d.ts.map +1 -0
- package/dist/esm/internal/printsObservation.js +29 -0
- package/dist/esm/internal/printsObservation.js.map +1 -0
- package/dist/esm/internal/refusal.d.ts +40 -0
- package/dist/esm/internal/refusal.d.ts.map +1 -0
- package/dist/esm/internal/refusal.js +47 -0
- package/dist/esm/internal/refusal.js.map +1 -0
- package/dist/esm/internal/supervision.d.ts +174 -0
- package/dist/esm/internal/supervision.d.ts.map +1 -0
- package/dist/esm/internal/supervision.js +485 -0
- package/dist/esm/internal/supervision.js.map +1 -0
- package/dist/esm/internal/unfinishedWork.d.ts +99 -0
- package/dist/esm/internal/unfinishedWork.d.ts.map +1 -0
- package/dist/esm/internal/unfinishedWork.js +85 -0
- package/dist/esm/internal/unfinishedWork.js.map +1 -0
- package/dist/esm/internal/unobservedCall.d.ts +112 -0
- package/dist/esm/internal/unobservedCall.d.ts.map +1 -0
- package/dist/esm/internal/unobservedCall.js +501 -0
- package/dist/esm/internal/unobservedCall.js.map +1 -0
- package/dist/esm/internal/untrustedData.d.ts +14 -0
- package/dist/esm/internal/untrustedData.d.ts.map +1 -0
- package/dist/esm/internal/untrustedData.js +15 -0
- package/dist/esm/internal/untrustedData.js.map +1 -0
- package/docs/README.md +129 -0
- package/docs/api.md +1869 -0
- package/docs/concepts.md +238 -0
- package/docs/external-transcripts.md +245 -0
- package/docs/guides/bind-flows.md +167 -0
- package/docs/guides/drive-the-loop.md +265 -0
- package/docs/guides/run-cells.md +262 -0
- package/docs/guides/workerd.md +144 -0
- package/docs/installation.md +69 -0
- package/docs/quickstart.md +121 -0
- package/docs/reference.md +954 -0
- package/docs/troubleshooting.md +177 -0
- package/package.json +463 -3
- package/src/AgentEvent.ts +1772 -0
- package/src/CallLedger.ts +560 -0
- package/src/Cell.ts +926 -0
- package/src/CellCalls.ts +198 -0
- package/src/CellHistory.ts +128 -0
- package/src/CellTurn.ts +4450 -0
- package/src/CellValidation.ts +382 -0
- package/src/Compaction.ts +330 -0
- package/src/CompletionClaim.ts +1013 -0
- package/src/ContextWindow.ts +669 -0
- package/src/EngineLike.ts +614 -0
- package/src/ExternalTranscript.ts +1143 -0
- package/src/FailedCall.ts +163 -0
- package/src/FlowBinding.ts +603 -0
- package/src/HarnessError.ts +98 -0
- package/src/Judgement.ts +526 -0
- package/src/Monitor.ts +579 -0
- package/src/NarrowedCheck.ts +694 -0
- package/src/Notifications.ts +262 -0
- package/src/Plan.ts +113 -0
- package/src/QuickJSSandbox.ts +1557 -0
- package/src/Relevance.ts +352 -0
- package/src/Sandbox.ts +908 -0
- package/src/Steering.ts +405 -0
- package/src/StructuredOutput.ts +484 -0
- package/src/Sufficiency.ts +247 -0
- package/src/Supervisor.ts +798 -0
- package/src/Tokens.ts +108 -0
- package/src/Transcript.ts +513 -0
- package/src/TruncatedOutput.ts +297 -0
- package/src/UnmovedTree.ts +121 -0
- package/src/UnresolvedFailure.ts +240 -0
- package/src/VacuousVerification.ts +280 -0
- package/src/VariablesPanel.ts +165 -0
- package/src/index.ts +204 -0
- package/src/internal/bytes.ts +70 -0
- package/src/internal/cellPrompt.ts +337 -0
- package/src/internal/compactable.ts +76 -0
- package/src/internal/compactionMarks.ts +454 -0
- package/src/internal/demandText.ts +145 -0
- package/src/internal/elide.ts +130 -0
- package/src/internal/frame.ts +1178 -0
- package/src/internal/nonNegativeSafeInt.ts +24 -0
- package/src/internal/paidUsage.ts +90 -0
- package/src/internal/printChannel.ts +434 -0
- package/src/internal/printsObservation.ts +31 -0
- package/src/internal/refusal.ts +53 -0
- package/src/internal/supervision.ts +652 -0
- package/src/internal/unfinishedWork.ts +123 -0
- package/src/internal/unobservedCall.ts +536 -0
- package/src/internal/untrustedData.ts +19 -0
|
@@ -0,0 +1,2618 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var CellTurn_exports = {};
|
|
30
|
+
__export(CellTurn_exports, {
|
|
31
|
+
State: () => State,
|
|
32
|
+
defaultClaimDemands: () => defaultClaimDemands,
|
|
33
|
+
defaultMaxCheckpoints: () => defaultMaxCheckpoints,
|
|
34
|
+
defaultMaxFrames: () => defaultMaxFrames,
|
|
35
|
+
defaultModelCallMs: () => defaultModelCallMs,
|
|
36
|
+
defaultNarrowingDemands: () => defaultNarrowingDemands,
|
|
37
|
+
defaultReadOnlyFrames: () => defaultReadOnlyFrames,
|
|
38
|
+
defaultRepeatFrames: () => defaultRepeatFrames,
|
|
39
|
+
defaultRevalidations: () => defaultRevalidations,
|
|
40
|
+
defaultUnmovedDemands: () => defaultUnmovedDemands,
|
|
41
|
+
defaultUnresolvedDemands: () => defaultUnresolvedDemands,
|
|
42
|
+
instructionsSegment: () => instructionsSegment,
|
|
43
|
+
make: () => make,
|
|
44
|
+
memorySegment: () => memorySegment,
|
|
45
|
+
modelCallMsFor: () => modelCallMsFor,
|
|
46
|
+
run: () => run,
|
|
47
|
+
teach: () => teach
|
|
48
|
+
});
|
|
49
|
+
module.exports = __toCommonJS(CellTurn_exports);
|
|
50
|
+
var import_core = require("@smthrs/core");
|
|
51
|
+
var Digest = __toESM(require("@smthrs/core/Digest"), 1);
|
|
52
|
+
var Fault = __toESM(require("@smthrs/flow/Fault"), 1);
|
|
53
|
+
var import_kernel = require("@smthrs/kernel");
|
|
54
|
+
var import_model = require("@smthrs/model");
|
|
55
|
+
var Pricing = __toESM(require("@smthrs/model/Pricing"), 1);
|
|
56
|
+
var import_registry = require("@smthrs/registry");
|
|
57
|
+
var import_effect = require("effect");
|
|
58
|
+
var AgentEvent = __toESM(require("./AgentEvent.js"), 1);
|
|
59
|
+
var CallLedger = __toESM(require("./CallLedger.js"), 1);
|
|
60
|
+
var Cell = __toESM(require("./Cell.js"), 1);
|
|
61
|
+
var CellHistory = __toESM(require("./CellHistory.js"), 1);
|
|
62
|
+
var CellValidation = __toESM(require("./CellValidation.js"), 1);
|
|
63
|
+
var Compaction = __toESM(require("./Compaction.js"), 1);
|
|
64
|
+
var CompletionClaim = __toESM(require("./CompletionClaim.js"), 1);
|
|
65
|
+
var ContextWindow = __toESM(require("./ContextWindow.js"), 1);
|
|
66
|
+
var EngineLike = __toESM(require("./EngineLike.js"), 1);
|
|
67
|
+
var FailedCall = __toESM(require("./FailedCall.js"), 1);
|
|
68
|
+
var import_HarnessError = require("./HarnessError.js");
|
|
69
|
+
var cellPrompt = __toESM(require("./internal/cellPrompt.js"), 1);
|
|
70
|
+
var import_compactable = require("./internal/compactable.js");
|
|
71
|
+
var compactionMarks = __toESM(require("./internal/compactionMarks.js"), 1);
|
|
72
|
+
var elide = __toESM(require("./internal/elide.js"), 1);
|
|
73
|
+
var Frame = __toESM(require("./internal/frame.js"), 1);
|
|
74
|
+
var import_nonNegativeSafeInt = require("./internal/nonNegativeSafeInt.js");
|
|
75
|
+
var import_paidUsage = require("./internal/paidUsage.js");
|
|
76
|
+
var import_printsObservation = require("./internal/printsObservation.js");
|
|
77
|
+
var import_refusal = require("./internal/refusal.js");
|
|
78
|
+
var Supervision = __toESM(require("./internal/supervision.js"), 1);
|
|
79
|
+
var import_untrustedData = require("./internal/untrustedData.js");
|
|
80
|
+
var Judgement = __toESM(require("./Judgement.js"), 1);
|
|
81
|
+
var Monitor = __toESM(require("./Monitor.js"), 1);
|
|
82
|
+
var NarrowedCheck = __toESM(require("./NarrowedCheck.js"), 1);
|
|
83
|
+
var Relevance = __toESM(require("./Relevance.js"), 1);
|
|
84
|
+
var Sandbox = __toESM(require("./Sandbox.js"), 1);
|
|
85
|
+
var Steering = __toESM(require("./Steering.js"), 1);
|
|
86
|
+
var Sufficiency = __toESM(require("./Sufficiency.js"), 1);
|
|
87
|
+
var Supervisor = __toESM(require("./Supervisor.js"), 1);
|
|
88
|
+
var import_Transcript = require("./Transcript.js");
|
|
89
|
+
var TruncatedOutput = __toESM(require("./TruncatedOutput.js"), 1);
|
|
90
|
+
var UnresolvedFailure = __toESM(require("./UnresolvedFailure.js"), 1);
|
|
91
|
+
var VariablesPanel = __toESM(require("./VariablesPanel.js"), 1);
|
|
92
|
+
const repeatedFailureTag = "/harness/CellTurn/RepeatedFailure";
|
|
93
|
+
Fault.register(repeatedFailureTag, "factory");
|
|
94
|
+
const defaultMaxFrames = 100;
|
|
95
|
+
const defaultReadOnlyFrames = 12;
|
|
96
|
+
const defaultModelCallMs = 3e5;
|
|
97
|
+
const modelCallMsFor = (effort) => {
|
|
98
|
+
switch (effort) {
|
|
99
|
+
case "xhigh":
|
|
100
|
+
case "max":
|
|
101
|
+
return 18e5;
|
|
102
|
+
case "high":
|
|
103
|
+
return 9e5;
|
|
104
|
+
default:
|
|
105
|
+
return defaultModelCallMs;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const defaultRepeatFrames = 4;
|
|
109
|
+
const defaultNarrowingDemands = 1;
|
|
110
|
+
const defaultUnmovedDemands = 1;
|
|
111
|
+
const defaultUnresolvedDemands = 1;
|
|
112
|
+
const defaultClaimDemands = 3;
|
|
113
|
+
const defaultRevalidations = 1;
|
|
114
|
+
const defaultMaxCheckpoints = 8;
|
|
115
|
+
const MaxFrames = import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
116
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultMaxFrames)),
|
|
117
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultMaxFrames))
|
|
118
|
+
);
|
|
119
|
+
const ContextWindowTokens = import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
120
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
121
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
122
|
+
);
|
|
123
|
+
const eventType = AgentEvent.eventType;
|
|
124
|
+
class State extends import_effect.Schema.Class("flows/harness/CellTurn/State")({
|
|
125
|
+
session: import_effect.Schema.String,
|
|
126
|
+
/** Missing versions decode as legacy so resume refuses before any model call. */
|
|
127
|
+
journalVersion: import_effect.Schema.Number.pipe(
|
|
128
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(import_Transcript.journalVersion)),
|
|
129
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(1))
|
|
130
|
+
),
|
|
131
|
+
frame: import_nonNegativeSafeInt.NonNegativeSafeInt,
|
|
132
|
+
maxFrames: MaxFrames,
|
|
133
|
+
/**
|
|
134
|
+
* Every name the realm holds, with the frame that last bound it.
|
|
135
|
+
*
|
|
136
|
+
* Freshness is a property of the run: the frame that reads a name is rarely
|
|
137
|
+
* the frame that bound it, and "how old is this" cannot be recovered from the
|
|
138
|
+
* realm itself. See `VariablesPanel`.
|
|
139
|
+
*/
|
|
140
|
+
panel: VariablesPanel.Ledger,
|
|
141
|
+
seat: import_effect.Schema.String,
|
|
142
|
+
modelParams: import_model.ModelRequest.GenerationParams,
|
|
143
|
+
layers: import_effect.Schema.Array(import_effect.Schema.String),
|
|
144
|
+
capabilityEnvelope: import_effect.Schema.Array(import_kernel.Capability.CapabilityPattern),
|
|
145
|
+
placement: import_effect.Schema.Option(import_registry.Descriptor.Placement),
|
|
146
|
+
contextWindow: ContextWindow.ContextWindow,
|
|
147
|
+
contextWindowTokens: ContextWindowTokens,
|
|
148
|
+
/**
|
|
149
|
+
* Consecutive read-only frames this run may spend before the controller
|
|
150
|
+
* intervenes. Zero disarms the cap, which is what a conversational run gets.
|
|
151
|
+
*/
|
|
152
|
+
readOnlyCap: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
153
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
154
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
155
|
+
),
|
|
156
|
+
/**
|
|
157
|
+
* Wall-clock milliseconds one model call may spend. Zero disarms the budget.
|
|
158
|
+
*
|
|
159
|
+
* Carried in controller state, and handed to the engine on every sealed
|
|
160
|
+
* step, so the value journaled in `discipline-armed` is the value enforced.
|
|
161
|
+
* See {@link defaultModelCallMs} for where the number comes from.
|
|
162
|
+
*/
|
|
163
|
+
modelCallMs: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
164
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultModelCallMs)),
|
|
165
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultModelCallMs))
|
|
166
|
+
),
|
|
167
|
+
/**
|
|
168
|
+
* Whether {@link State.modelCallMs} was left to the effort's default, so a
|
|
169
|
+
* steered effort moves it. A ceiling the host chose stays through every
|
|
170
|
+
* steer, even one numerically equal to some effort's default. A state
|
|
171
|
+
* decoded from a journal that predates the flag keeps its ceiling.
|
|
172
|
+
*/
|
|
173
|
+
modelCallMsFollowsEffort: import_effect.Schema.Boolean.pipe(
|
|
174
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(false)),
|
|
175
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(false))
|
|
176
|
+
),
|
|
177
|
+
/**
|
|
178
|
+
* Stalled frames settled since the last frame that changed the workspace.
|
|
179
|
+
*
|
|
180
|
+
* Before the run's first write every read-only frame counts: the instance
|
|
181
|
+
* the cap was built for read for 100 frames, made 132 calls and edited
|
|
182
|
+
* nothing. After it, a read-only frame counts only when it stalls, settling
|
|
183
|
+
* no call this run had not already issued: a cell that only printed what the
|
|
184
|
+
* realm holds, a raise, a rejected cell, or a frame that re-asked old
|
|
185
|
+
* questions. A frame that settled a new call holds the count where it was,
|
|
186
|
+
* because a probe of work that exists is debugging. Terminal-Bench 4.0's
|
|
187
|
+
* mp-checkpoint-consolidation needed 36 read-only probes in a row after its
|
|
188
|
+
* first write, and counting them stopped the run at 24 (2026-09-24).
|
|
189
|
+
* Re-asking is still bounded, by {@link State.repeatFrames}.
|
|
190
|
+
*
|
|
191
|
+
* Changed-ness is measured as well as declared: the controller compares the
|
|
192
|
+
* observation the previous frame closed on ({@link State.workspace}) against
|
|
193
|
+
* the one this frame closes on, and a difference is a mutation whoever
|
|
194
|
+
* performed it. The measurement is what a frame's calls cannot say; it is
|
|
195
|
+
* never what overrules them. A frame is read-only when nothing declared a
|
|
196
|
+
* write *and* no complete measurement saw one, because a measurement is
|
|
197
|
+
* rooted, pruned and bounded, and the paths it does not cover are not
|
|
198
|
+
* evidence that a run stopped working.
|
|
199
|
+
*
|
|
200
|
+
* It used to count frames since the last call that *declared* a write, and
|
|
201
|
+
* the difference is not academic. `bash` declares no write set at all — its
|
|
202
|
+
* registry envelope is the conservative empty one and an unhermetic
|
|
203
|
+
* invocation carries no `writes` key, because a shell command's effects do
|
|
204
|
+
* not travel through any boundary the harness can read. On the SWE-bench
|
|
205
|
+
* pytest instance a frame ran `git show <base>:src/_pytest/python.py >
|
|
206
|
+
* src/_pytest/python.py`, destroyed the fix the run had landed six frames
|
|
207
|
+
* earlier, and was counted as read-only; the whole wave made 41 shell calls
|
|
208
|
+
* and not one of them declared a write, so nothing in the harness saw a
|
|
209
|
+
* single one of them.
|
|
210
|
+
*
|
|
211
|
+
* Declared writes are still what the capability envelope is enforced
|
|
212
|
+
* against, still what decides whether the truncated-write refusal applies to
|
|
213
|
+
* a call, still enough on their own to clear this counter, and still
|
|
214
|
+
* journaled beside the measured answer as `declaredWrites`. This is
|
|
215
|
+
* accounting, not permission. A host that measures nothing, or measures only
|
|
216
|
+
* a prefix of its tree, keeps the old rule, and `MutationObserved.basis`
|
|
217
|
+
* says which.
|
|
218
|
+
*/
|
|
219
|
+
readOnlyFrames: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
220
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
221
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
222
|
+
),
|
|
223
|
+
/**
|
|
224
|
+
* Frames the demand stays silent for, bought by an accepted justification.
|
|
225
|
+
*
|
|
226
|
+
* A justification is an escape hatch with a price: it buys `readOnlyCap`
|
|
227
|
+
* quiet frames and never resets {@link State.readOnlyFrames}, so a run that
|
|
228
|
+
* keeps justifying still reaches the hard stop at twice the cap.
|
|
229
|
+
*
|
|
230
|
+
* Only an *answer* buys it. A justification is accepted when the frame that
|
|
231
|
+
* wrote it was handed the demand — {@link State.pendingReadOnlyDemand} is
|
|
232
|
+
* set — and a justification volunteered by a frame that was asked nothing is
|
|
233
|
+
* recorded on its transition and buys zero frames. Otherwise a run can spend
|
|
234
|
+
* the whole allowance without the demand ever being issued: see the
|
|
235
|
+
* read-only intervention in `internal/frame.ts` `discipline`.
|
|
236
|
+
*/
|
|
237
|
+
readOnlyGrace: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
238
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
239
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
240
|
+
),
|
|
241
|
+
/** Intervention waiting to be resolved by the next frame. */
|
|
242
|
+
pendingReadOnlyDemand: import_effect.Schema.optional(import_effect.Schema.Struct({
|
|
243
|
+
streak: import_nonNegativeSafeInt.NonNegativeSafeInt,
|
|
244
|
+
cap: import_nonNegativeSafeInt.NonNegativeSafeInt
|
|
245
|
+
})),
|
|
246
|
+
/**
|
|
247
|
+
* The newest call ordinal a state section already in the window listed.
|
|
248
|
+
*
|
|
249
|
+
* Every frame's section stays in the window (see `frozen`), so the next one
|
|
250
|
+
* lists only calls settled after this. Zero after a compaction, which may
|
|
251
|
+
* have replaced the sections that listed them, and on a state decoded from
|
|
252
|
+
* an older journal, whose window holds none.
|
|
253
|
+
*/
|
|
254
|
+
ledgerShown: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
255
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
256
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
257
|
+
),
|
|
258
|
+
/**
|
|
259
|
+
* Whether the window already ends with this frame's state section.
|
|
260
|
+
*
|
|
261
|
+
* A frame that continues writes the next frame's section into the segment it
|
|
262
|
+
* just appended, so a supervisor reading of that segment reads it whole (see
|
|
263
|
+
* `frozen`). A run's first frame, and a state decoded from an older journal,
|
|
264
|
+
* has none yet, and the frame writes it when it opens.
|
|
265
|
+
*/
|
|
266
|
+
sectioned: import_effect.Schema.Boolean.pipe(
|
|
267
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(false)),
|
|
268
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(false))
|
|
269
|
+
),
|
|
270
|
+
/**
|
|
271
|
+
* How many messages at the end of the window are interventions the next
|
|
272
|
+
* frame is being asked to answer.
|
|
273
|
+
*
|
|
274
|
+
* The controller's own asks, which are the read-only demand, the repeat
|
|
275
|
+
* redirect, the sufficiency observation and the completion review, are
|
|
276
|
+
* appended to the transcript when the frame that earned them closes. The block of run memory
|
|
277
|
+
* is written into the window when the next frame opens, so without this count the ask
|
|
278
|
+
* was always the second-to-last message and a roster of variable names was
|
|
279
|
+
* always the last. {@link stateSection} says what that cost.
|
|
280
|
+
*
|
|
281
|
+
* It is a count rather than a flag because a frame can earn several asks at
|
|
282
|
+
* once, and it is state rather than something recomputed from the window
|
|
283
|
+
* because the messages carry no mark that says which of them is an ask.
|
|
284
|
+
* Zero on a state decoded from an older journal, which puts the block last
|
|
285
|
+
* exactly as that run had it.
|
|
286
|
+
*/
|
|
287
|
+
interventions: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
288
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
289
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
290
|
+
),
|
|
291
|
+
/**
|
|
292
|
+
* Consecutive repeat-observation frames this run may spend before the
|
|
293
|
+
* controller redirects it. Zero disarms the demand.
|
|
294
|
+
*
|
|
295
|
+
* Armed separately from {@link State.readOnlyCap} because the two answer
|
|
296
|
+
* different stalls. The read-only cap watches a run that has written
|
|
297
|
+
* nothing; this watches a run that has written something and keeps
|
|
298
|
+
* confirming it. A run can be in both states at once, and telling one that
|
|
299
|
+
* has already edited to "land an edit" sends it back to the file it is
|
|
300
|
+
* already staring at.
|
|
301
|
+
*/
|
|
302
|
+
repeatCap: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
303
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultRepeatFrames)),
|
|
304
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultRepeatFrames))
|
|
305
|
+
),
|
|
306
|
+
/** Consecutive frames with the same uncorrected cell or call failure. */
|
|
307
|
+
failureFrames: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
308
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
309
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
310
|
+
),
|
|
311
|
+
/** Bounded identity of the failure being retried. */
|
|
312
|
+
failureKey: import_effect.Schema.String.pipe(
|
|
313
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed("")),
|
|
314
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(""))
|
|
315
|
+
),
|
|
316
|
+
/**
|
|
317
|
+
* Consecutive frames that observed only what this run had already observed.
|
|
318
|
+
*
|
|
319
|
+
* A frame counts when it issued at least one call, issued no call whose
|
|
320
|
+
* signature this run had not already issued, and changed nothing. A frame
|
|
321
|
+
* that issued no call is neither a repeat nor a break: it made no
|
|
322
|
+
* observation, so the counter is carried across it rather than advanced or
|
|
323
|
+
* cleared — a run that thinks for a frame between two identical commands has
|
|
324
|
+
* not stopped repeating itself, and a run planning its next move has not
|
|
325
|
+
* started.
|
|
326
|
+
*/
|
|
327
|
+
repeatFrames: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
328
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
329
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
330
|
+
),
|
|
331
|
+
/**
|
|
332
|
+
* Signatures of the calls this run has issued, oldest first.
|
|
333
|
+
*
|
|
334
|
+
* State rather than a per-frame detail because repetition is a property of
|
|
335
|
+
* the run: the frame that re-runs a check is usually nowhere near the frame
|
|
336
|
+
* that first ran it. It carries digests and no inputs; see
|
|
337
|
+
* {@link signatureOf}.
|
|
338
|
+
*/
|
|
339
|
+
callSignatures: import_effect.Schema.Array(import_effect.Schema.String).pipe(
|
|
340
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed([])),
|
|
341
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed([]))
|
|
342
|
+
),
|
|
343
|
+
/**
|
|
344
|
+
* Completions this run may have bounced for narrowed evidence. Zero disarms
|
|
345
|
+
* the demand.
|
|
346
|
+
*
|
|
347
|
+
* Armed separately from every other cap because it watches a different
|
|
348
|
+
* moment. The read-only cap and the repeat demand watch a run that is still
|
|
349
|
+
* working and has stopped making progress; this watches the one frame a run
|
|
350
|
+
* gets wrong for free — the last one, where a narrowed check is presented as
|
|
351
|
+
* evidence for a change it never covered. See {@link defaultNarrowingDemands}.
|
|
352
|
+
*/
|
|
353
|
+
narrowingCap: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
354
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultNarrowingDemands)),
|
|
355
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultNarrowingDemands))
|
|
356
|
+
),
|
|
357
|
+
/**
|
|
358
|
+
* Completions this run has already had bounced for narrowed evidence.
|
|
359
|
+
*
|
|
360
|
+
* Counted rather than flagged so the cap reads like the others, and carried
|
|
361
|
+
* in state so a bounce survives the frame that answers it: the run stays
|
|
362
|
+
* responsible for the answer, and the loop stops asking once it has asked.
|
|
363
|
+
*/
|
|
364
|
+
narrowingDemands: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
365
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
366
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
367
|
+
),
|
|
368
|
+
/**
|
|
369
|
+
* Completions this run may have bounced for an unmoved tree. The demand is
|
|
370
|
+
* issued only for a completion the claim brake reads as unsupported, so a
|
|
371
|
+
* `claimCap` of zero disarms it too. Zero disarms the demand. See
|
|
372
|
+
* {@link defaultUnmovedDemands} and `UnmovedTree`.
|
|
373
|
+
*/
|
|
374
|
+
unmovedCap: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
375
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultUnmovedDemands)),
|
|
376
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultUnmovedDemands))
|
|
377
|
+
),
|
|
378
|
+
/** Completions this run has already had bounced for an unmoved tree. */
|
|
379
|
+
unmovedDemands: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
380
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
381
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
382
|
+
),
|
|
383
|
+
/**
|
|
384
|
+
* Completions this run may have bounced for a failing check it replaced
|
|
385
|
+
* rather than answered. Zero disarms the demand. See
|
|
386
|
+
* {@link defaultUnresolvedDemands} and `UnresolvedFailure`.
|
|
387
|
+
*/
|
|
388
|
+
unresolvedCap: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
389
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultUnresolvedDemands)),
|
|
390
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultUnresolvedDemands))
|
|
391
|
+
),
|
|
392
|
+
/** Completions this run has already had bounced for such a check. */
|
|
393
|
+
unresolvedDemands: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
394
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
395
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
396
|
+
),
|
|
397
|
+
/**
|
|
398
|
+
* Completions this run has already had bounced for a call their own cell
|
|
399
|
+
* failed before they were written. Capped at `FailedCall.cap`.
|
|
400
|
+
*/
|
|
401
|
+
failedCallDemands: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
402
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
403
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
404
|
+
),
|
|
405
|
+
/**
|
|
406
|
+
* Completions this run has already had bounced for calls their own cell
|
|
407
|
+
* made and never read before completing. Capped at `UnobservedCall.cap`.
|
|
408
|
+
*/
|
|
409
|
+
unobservedDemands: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
410
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
411
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
412
|
+
),
|
|
413
|
+
/**
|
|
414
|
+
* Completions this run has already had handed back for an output that did
|
|
415
|
+
* not fit the host's declared shape. Capped by `Input.output`.
|
|
416
|
+
*/
|
|
417
|
+
outputDemands: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
418
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
419
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
420
|
+
),
|
|
421
|
+
/**
|
|
422
|
+
* Frames this run may be given to prove a claim its own record does not
|
|
423
|
+
* support. Past it an unproven claim fails the run rather than standing.
|
|
424
|
+
* Zero disarms the brake. See {@link defaultClaimDemands} and
|
|
425
|
+
* `CompletionClaim`.
|
|
426
|
+
*/
|
|
427
|
+
claimCap: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
428
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultClaimDemands)),
|
|
429
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultClaimDemands))
|
|
430
|
+
),
|
|
431
|
+
/** Completions this run has already had bounced for such a claim. */
|
|
432
|
+
claimDemands: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
433
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
434
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
435
|
+
),
|
|
436
|
+
/**
|
|
437
|
+
* Trees this run may pin with `ctx.checkpoint()`. Zero disarms minting.
|
|
438
|
+
*
|
|
439
|
+
* See {@link defaultMaxCheckpoints}. `ctx.base` is not minted and is
|
|
440
|
+
* unaffected by this.
|
|
441
|
+
*/
|
|
442
|
+
checkpointCap: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
443
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultMaxCheckpoints)),
|
|
444
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultMaxCheckpoints))
|
|
445
|
+
),
|
|
446
|
+
/**
|
|
447
|
+
* Ids of the trees this run has already pinned, oldest first.
|
|
448
|
+
*
|
|
449
|
+
* Run state rather than a per-frame count because a checkpoint outlives the
|
|
450
|
+
* frame that minted it: the whole use is a frame taking a reading against a
|
|
451
|
+
* tree some earlier frame pinned, so the bound has to be the run's. The ids
|
|
452
|
+
* rather than a tally, because the one thing worth saying to a run that has
|
|
453
|
+
* reached the bound is which handles it is already holding.
|
|
454
|
+
*/
|
|
455
|
+
checkpointIds: import_effect.Schema.Array(import_effect.Schema.String).pipe(
|
|
456
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed([])),
|
|
457
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed([]))
|
|
458
|
+
),
|
|
459
|
+
/**
|
|
460
|
+
* Provider-run tools every frame's model call may use (see
|
|
461
|
+
* `ModelRequest.serverTools`). Absent means none.
|
|
462
|
+
*/
|
|
463
|
+
serverTools: import_effect.Schema.optionalKey(import_effect.Schema.Array(import_model.ModelRequest.ServerTool)),
|
|
464
|
+
/**
|
|
465
|
+
* Content address of the workspace this run opened on.
|
|
466
|
+
*
|
|
467
|
+
* Recorded once, from the first frame whose opening measurement covered the
|
|
468
|
+
* tree, and never restamped: the whole question `UnmovedTree` asks is whether
|
|
469
|
+
* the tree a completion describes is the tree the run was handed, and an
|
|
470
|
+
* origin that moved with the run could not answer it. Empty means no frame
|
|
471
|
+
* has produced a complete opening measurement, which makes the demand inert
|
|
472
|
+
* rather than wrong.
|
|
473
|
+
*/
|
|
474
|
+
openingDigest: import_effect.Schema.String.pipe(
|
|
475
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed("")),
|
|
476
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(""))
|
|
477
|
+
),
|
|
478
|
+
/**
|
|
479
|
+
* Checks this run has run, oldest first, each stamped with the tree it ran
|
|
480
|
+
* over.
|
|
481
|
+
*
|
|
482
|
+
* State rather than a per-frame detail for the same reason
|
|
483
|
+
* {@link State.callSignatures} is: the frame that narrows a check is nowhere
|
|
484
|
+
* near the frame that first ran it. It carries the terms of each input rather
|
|
485
|
+
* than the input, and only for calls that declared no write — a call that
|
|
486
|
+
* changes the workspace is not an observation of it. See `NarrowedCheck`.
|
|
487
|
+
*/
|
|
488
|
+
checks: NarrowedCheck.Ledger,
|
|
489
|
+
/**
|
|
490
|
+
* Every call this run has settled, bounded and rendered every frame.
|
|
491
|
+
*
|
|
492
|
+
* State rather than a per-frame detail because the frame that needs to see a
|
|
493
|
+
* result is rarely the frame that fetched it, and a cell is authored before
|
|
494
|
+
* any of its results exist. See `CallLedger`.
|
|
495
|
+
*/
|
|
496
|
+
callLedger: CallLedger.Ledger,
|
|
497
|
+
/**
|
|
498
|
+
* Every command this run ran that reported an exit status, as the claim
|
|
499
|
+
* brake lists it. See `CompletionClaim.record`.
|
|
500
|
+
*/
|
|
501
|
+
reported: CompletionClaim.Reported,
|
|
502
|
+
/**
|
|
503
|
+
* Checks this run has watched fail, each stamped with the epoch it failed in.
|
|
504
|
+
*
|
|
505
|
+
* Separate from {@link State.checks} because that ledger holds one entry per
|
|
506
|
+
* signature carrying its *latest* run: the moment a failing check is re-run
|
|
507
|
+
* and passes, the failure it reported is gone from it, and the failure is
|
|
508
|
+
* exactly half of what `Sufficiency` needs. See `Sufficiency`.
|
|
509
|
+
*/
|
|
510
|
+
failures: Sufficiency.Ledger,
|
|
511
|
+
/**
|
|
512
|
+
* Frames of this run that changed the workspace.
|
|
513
|
+
*
|
|
514
|
+
* The clock `Sufficiency` orders its two halves by. A count rather than a
|
|
515
|
+
* digest, because the fact being established is that something changed
|
|
516
|
+
* between two readings, and a count says that on a host that measures nothing
|
|
517
|
+
* and knows only what its calls declared.
|
|
518
|
+
*/
|
|
519
|
+
mutations: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
520
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
521
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
522
|
+
),
|
|
523
|
+
/**
|
|
524
|
+
* Settled writes this run recorded on trees the workspace walk never sees.
|
|
525
|
+
*
|
|
526
|
+
* A `bash` call routed into a container fingerprints that container's
|
|
527
|
+
* working directory either side of the command and reports a move under
|
|
528
|
+
* the reserved `mutated` key (`@smthrs/std/TreeFingerprint`). Counted apart
|
|
529
|
+
* from {@link State.mutations} because the unmoved-tree demand and the
|
|
530
|
+
* claim judge compare the host's two digests, and a container edit leaves
|
|
531
|
+
* those equal: without this count a run that did its whole task in a
|
|
532
|
+
* container was bounced as unmoved and then refused as "work this run never
|
|
533
|
+
* recorded". Measured on Terminal-Bench 4.0, 2026-09-22.
|
|
534
|
+
*/
|
|
535
|
+
remoteMutations: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
536
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(0)),
|
|
537
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(0))
|
|
538
|
+
),
|
|
539
|
+
/**
|
|
540
|
+
* Whether the sufficiency observation has already been written this run.
|
|
541
|
+
*
|
|
542
|
+
* Once, and only once: it is a statement about the record, the record only
|
|
543
|
+
* grows, and repeating it every frame would turn the one control that is not
|
|
544
|
+
* a demand into nagging. A run that is shown it and keeps working is a run
|
|
545
|
+
* that has decided the evidence is not enough, which is its decision to make.
|
|
546
|
+
*/
|
|
547
|
+
sufficiencyStated: import_effect.Schema.Boolean.pipe(
|
|
548
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(false)),
|
|
549
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(false))
|
|
550
|
+
),
|
|
551
|
+
/**
|
|
552
|
+
* How many times one frame may answer its own unparseable cell before the
|
|
553
|
+
* frame ends. Zero disarms the answer, which restores the old behaviour: a
|
|
554
|
+
* cell that does not parse settles the frame.
|
|
555
|
+
*
|
|
556
|
+
* One, because that is what the evidence asks for. A cell that does not parse
|
|
557
|
+
* is answered by a re-prompt whose whole prefix — teaching, catalog,
|
|
558
|
+
* transcript — is byte-identical to the one just sent, so the retry is paid
|
|
559
|
+
* for at cached-input price plus the output it writes. Two consecutive
|
|
560
|
+
* unparseable answers is a model that has lost the shape rather than
|
|
561
|
+
* mistyped, and that is worth a fresh frame with the failure on the record.
|
|
562
|
+
*/
|
|
563
|
+
revalidations: import_nonNegativeSafeInt.NonNegativeSafeInt.pipe(
|
|
564
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(defaultRevalidations)),
|
|
565
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(defaultRevalidations))
|
|
566
|
+
),
|
|
567
|
+
/**
|
|
568
|
+
* The output of the completion a completion demand handed back, if any.
|
|
569
|
+
*
|
|
570
|
+
* The demand takes a finished answer away and asks for one more frame. It is
|
|
571
|
+
* allowed to do that only because the run gets to answer again — so the one
|
|
572
|
+
* outcome it must never produce is a run that ends holding nothing. Between
|
|
573
|
+
* the bounce and the next completion the run can spend its last frame on a
|
|
574
|
+
* cell that raises, on a refused park, or on more work, and every one of
|
|
575
|
+
* those ends the run on {@link budgetMessage} rather than on a completion.
|
|
576
|
+
* Keeping the bounced output here is what makes the demand recoverable: the
|
|
577
|
+
* budget still ends the run, and the run's own words are still what it ends
|
|
578
|
+
* with. See `NarrowedCheck` for why the demand is issued at all.
|
|
579
|
+
*
|
|
580
|
+
* The measured demands and the unread-call demand keep it; the failed-call
|
|
581
|
+
* demand does not, and neither does a claim demand. The claim brake read the sentence
|
|
582
|
+
* itself and found the record against it, so restoring that sentence on the
|
|
583
|
+
* budget notice hands back the exact answer the brake refused: one live run
|
|
584
|
+
* finished `stop` with a bounced "the tests pass" over a repository whose
|
|
585
|
+
* test exits 1, by this route and no other. A claim demand therefore clears
|
|
586
|
+
* this. See `Frame.CompletionDemand.keeps`.
|
|
587
|
+
*/
|
|
588
|
+
bouncedCompletion: import_effect.Schema.optional(import_effect.Schema.String),
|
|
589
|
+
/**
|
|
590
|
+
* The frame a completion demand was handed to, if one is outstanding.
|
|
591
|
+
*
|
|
592
|
+
* The five measured demands end with the same promise: what you return next
|
|
593
|
+
* is the answer that stands. Three of them can fire on one `complete`
|
|
594
|
+
* transition and each carries its own cap, so without this the frame written
|
|
595
|
+
* to answer one demand is judged by the next — and a run that changed nothing and displaced a
|
|
596
|
+
* failing check is told "no" twice about one decision, spending two frames
|
|
597
|
+
* and two model calls on the argument. Recorded as the frame number rather
|
|
598
|
+
* than as a flag because it is then self-clearing: it names one frame, and
|
|
599
|
+
* every frame after that one is a frame the run chose to spend.
|
|
600
|
+
*
|
|
601
|
+
* It governs whether a demand may be *issued*, not whether the claim brake
|
|
602
|
+
* may read. A frame that answers a measured demand and completes is read by
|
|
603
|
+
* the claim brake like any other completion, because an unread completion is
|
|
604
|
+
* the silence this package refuses; what it cannot be handed is a second
|
|
605
|
+
* demand. See `Frame.judgeCompletion`.
|
|
606
|
+
*/
|
|
607
|
+
demandedFrame: import_effect.Schema.optional(import_nonNegativeSafeInt.NonNegativeSafeInt),
|
|
608
|
+
/**
|
|
609
|
+
* Whether a human can answer this run, which is what makes a park honorable.
|
|
610
|
+
*
|
|
611
|
+
* A park is durable waiting, and waiting only ends when somebody answers. A
|
|
612
|
+
* run with no approval channel has nobody to answer it, so a park there is
|
|
613
|
+
* not patience: it is the run abandoning a budget it still holds. False —
|
|
614
|
+
* the default — refuses the transition and answers it in the frame that
|
|
615
|
+
* returned it.
|
|
616
|
+
*/
|
|
617
|
+
approvalChannel: import_effect.Schema.Boolean.pipe(
|
|
618
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed(false)),
|
|
619
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed(false))
|
|
620
|
+
),
|
|
621
|
+
/**
|
|
622
|
+
* The workspace as the last measured frame left it.
|
|
623
|
+
*
|
|
624
|
+
* Carried in state rather than re-measured because one measurement serves
|
|
625
|
+
* two frames: what a frame closes on is what the next frame opens on, and
|
|
626
|
+
* nothing between them touches the tree — the sealed model step in between
|
|
627
|
+
* only produces text. So a run pays one walk per frame, not two, and a
|
|
628
|
+
* resumed run replays the recorded measurement instead of walking a tree
|
|
629
|
+
* that has moved on.
|
|
630
|
+
*
|
|
631
|
+
* Absent means no frame has measured yet; `None` means a frame measured and
|
|
632
|
+
* the host reported it has nothing to measure. The two are kept apart so an
|
|
633
|
+
* unobservable host is asked once and then left alone, instead of paying an
|
|
634
|
+
* opening boundary every frame for an answer that will not change.
|
|
635
|
+
*/
|
|
636
|
+
workspace: import_effect.Schema.optional(import_effect.Schema.Option(EngineLike.Observation)),
|
|
637
|
+
/**
|
|
638
|
+
* Catalog flows and skills the run-start relevance reading withheld, and
|
|
639
|
+
* that no call has restored since.
|
|
640
|
+
*
|
|
641
|
+
* State rather than a per-frame detail because the reading is taken once,
|
|
642
|
+
* at frame 0, and every later frame's `ctx.flows` is filtered by it. A call
|
|
643
|
+
* to one of these names is refused as `flow_withheld` and restores it from
|
|
644
|
+
* the next frame. See {@link Input.judged}.
|
|
645
|
+
*/
|
|
646
|
+
withheldFlows: import_effect.Schema.Array(import_effect.Schema.String).pipe(
|
|
647
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed([])),
|
|
648
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed([]))
|
|
649
|
+
),
|
|
650
|
+
/**
|
|
651
|
+
* Keys of the memory rows the supervisor has shown this run, oldest first,
|
|
652
|
+
* the newest 256 kept.
|
|
653
|
+
*
|
|
654
|
+
* State rather than a supervisor detail because it is folded in from each
|
|
655
|
+
* recorded drain, so a replay rebuilds it, and a row shown once is never
|
|
656
|
+
* asked about or delivered again. See `Supervisor`.
|
|
657
|
+
*/
|
|
658
|
+
memoryShown: import_effect.Schema.Array(import_effect.Schema.String).pipe(
|
|
659
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed([])),
|
|
660
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed([]))
|
|
661
|
+
),
|
|
662
|
+
/**
|
|
663
|
+
* Each supervisor monitor's streak, deliveries and last delivery, by id.
|
|
664
|
+
*
|
|
665
|
+
* State because it is folded in only from each recorded drain, the one
|
|
666
|
+
* place a reading is gated, so a replay rebuilds it and a resumed run
|
|
667
|
+
* keeps its cooldowns and limits. See `Monitor.gate`.
|
|
668
|
+
*/
|
|
669
|
+
monitorLedger: Monitor.Ledger.pipe(
|
|
670
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed({})),
|
|
671
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed({}))
|
|
672
|
+
),
|
|
673
|
+
/**
|
|
674
|
+
* What the run knows of its newest transcript segments, one entry each, in
|
|
675
|
+
* window order: the frame that wrote it, whether it carries the person's
|
|
676
|
+
* messages, whether that frame changed files, the checks it ran, and Jev's
|
|
677
|
+
* answer about it once a supervisor reading has marked it.
|
|
678
|
+
*
|
|
679
|
+
* State because a compaction's pins and marks read it long after the frame
|
|
680
|
+
* that wrote a segment; each compaction keeps the entries of the segments
|
|
681
|
+
* it keeps. Answers are folded in only from each recorded drain, so a
|
|
682
|
+
* replay rebuilds them. It is aligned when it describes every transcript
|
|
683
|
+
* segment; a run whose state predates it is not, and compacts every
|
|
684
|
+
* segment into the summary, as runs did before compaction marks.
|
|
685
|
+
*/
|
|
686
|
+
segmentFacts: import_effect.Schema.Array(compactionMarks.Facts).pipe(
|
|
687
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed([])),
|
|
688
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed([]))
|
|
689
|
+
),
|
|
690
|
+
/**
|
|
691
|
+
* The context triggers a drained supervisor reading fired, which compact the
|
|
692
|
+
* next frame's context whatever the budget says; empty once it has opened.
|
|
693
|
+
*
|
|
694
|
+
* State because it is folded in only from each recorded drain, so a replay
|
|
695
|
+
* compacts the same frame for the same cause.
|
|
696
|
+
*/
|
|
697
|
+
compactionDue: import_effect.Schema.Array(AgentEvent.CompactionCause).pipe(
|
|
698
|
+
import_effect.Schema.withConstructorDefault(import_effect.Effect.succeed([])),
|
|
699
|
+
import_effect.Schema.withDecodingDefaultKey(import_effect.Effect.succeed([]))
|
|
700
|
+
),
|
|
701
|
+
/**
|
|
702
|
+
* Output this run has been handed as a fragment, by digest.
|
|
703
|
+
*
|
|
704
|
+
* The ledger is state rather than a per-frame detail because a cell may store
|
|
705
|
+
* a truncated capture and write it a frame later. It carries no bytes; see
|
|
706
|
+
* `TruncatedOutput`.
|
|
707
|
+
*/
|
|
708
|
+
truncatedOutputs: TruncatedOutput.Ledger
|
|
709
|
+
}) {
|
|
710
|
+
}
|
|
711
|
+
const advance = (state, changes) => new State({ ...state, ...changes });
|
|
712
|
+
const memorySegment = (text, digest) => ({
|
|
713
|
+
kind: "system",
|
|
714
|
+
zone: "prefix",
|
|
715
|
+
declaredDigest: digest,
|
|
716
|
+
content: [import_model.ModelRequest.SystemPart.make({ text })]
|
|
717
|
+
});
|
|
718
|
+
const instructionsSegment = (documents, withheld2) => ({
|
|
719
|
+
kind: "system",
|
|
720
|
+
zone: "prefix",
|
|
721
|
+
content: [import_model.ModelRequest.SystemPart.make({ text: Relevance.render(documents, withheld2) })]
|
|
722
|
+
});
|
|
723
|
+
const make = (options) => new State({
|
|
724
|
+
session: options.session,
|
|
725
|
+
frame: options.frame ?? 0,
|
|
726
|
+
maxFrames: options.maxFrames ?? defaultMaxFrames,
|
|
727
|
+
panel: [],
|
|
728
|
+
seat: options.seat,
|
|
729
|
+
modelParams: options.modelParams,
|
|
730
|
+
layers: options.layers,
|
|
731
|
+
capabilityEnvelope: options.capabilityEnvelope,
|
|
732
|
+
placement: options.placement,
|
|
733
|
+
contextWindow: options.contextWindow,
|
|
734
|
+
// The opening transcript is the host's, written before any frame: no
|
|
735
|
+
// person's message, no change and no check.
|
|
736
|
+
segmentFacts: options.contextWindow.segments.flatMap(
|
|
737
|
+
(segment) => segment.kind === "transcript" ? [{ frame: options.frame ?? 0, person: false, mutated: false, checks: [] }] : []
|
|
738
|
+
),
|
|
739
|
+
contextWindowTokens: options.contextWindowTokens ?? 0,
|
|
740
|
+
readOnlyCap: options.readOnlyCap ?? 0,
|
|
741
|
+
modelCallMs: options.modelCallMs ?? modelCallMsFor(options.modelParams.reasoningEffort),
|
|
742
|
+
modelCallMsFollowsEffort: options.modelCallMs === void 0,
|
|
743
|
+
readOnlyFrames: 0,
|
|
744
|
+
readOnlyGrace: 0,
|
|
745
|
+
pendingReadOnlyDemand: void 0,
|
|
746
|
+
interventions: 0,
|
|
747
|
+
repeatCap: options.repeatCap ?? defaultRepeatFrames,
|
|
748
|
+
repeatFrames: 0,
|
|
749
|
+
failureFrames: 0,
|
|
750
|
+
failureKey: "",
|
|
751
|
+
callSignatures: [],
|
|
752
|
+
narrowingCap: options.narrowingCap ?? defaultNarrowingDemands,
|
|
753
|
+
narrowingDemands: 0,
|
|
754
|
+
unmovedCap: options.unmovedCap ?? defaultUnmovedDemands,
|
|
755
|
+
unmovedDemands: 0,
|
|
756
|
+
unresolvedCap: options.unresolvedCap ?? defaultUnresolvedDemands,
|
|
757
|
+
unresolvedDemands: 0,
|
|
758
|
+
failedCallDemands: 0,
|
|
759
|
+
unobservedDemands: 0,
|
|
760
|
+
outputDemands: 0,
|
|
761
|
+
claimCap: options.claimCap ?? defaultClaimDemands,
|
|
762
|
+
claimDemands: 0,
|
|
763
|
+
openingDigest: "",
|
|
764
|
+
checks: [],
|
|
765
|
+
callLedger: [],
|
|
766
|
+
reported: [],
|
|
767
|
+
failures: [],
|
|
768
|
+
mutations: 0,
|
|
769
|
+
remoteMutations: 0,
|
|
770
|
+
sufficiencyStated: false,
|
|
771
|
+
revalidations: options.revalidations ?? defaultRevalidations,
|
|
772
|
+
approvalChannel: options.approvalChannel ?? false,
|
|
773
|
+
workspace: void 0,
|
|
774
|
+
truncatedOutputs: [],
|
|
775
|
+
checkpointCap: options.checkpointCap ?? defaultMaxCheckpoints,
|
|
776
|
+
checkpointIds: [],
|
|
777
|
+
...options.serverTools === void 0 || options.serverTools.length === 0 ? {} : {
|
|
778
|
+
serverTools: [
|
|
779
|
+
...new Map(options.serverTools.map((tool) => [import_model.CanonicalJson.stringify(tool), tool])).values()
|
|
780
|
+
]
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
const teach = (contextWindow, flows, environment, stance) => {
|
|
784
|
+
const projections = {};
|
|
785
|
+
for (const descriptor of flows) {
|
|
786
|
+
projections[descriptor.name] = {
|
|
787
|
+
...Cell.project(descriptor),
|
|
788
|
+
provenance: descriptor.provenance,
|
|
789
|
+
path: descriptor.path
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
const taught = cellPrompt.make(projections, environment, stance).map(
|
|
793
|
+
(section) => ContextWindow.makeSegment({
|
|
794
|
+
kind: "system",
|
|
795
|
+
zone: "prefix",
|
|
796
|
+
declaredDigest: section.digest,
|
|
797
|
+
content: [import_model.ModelRequest.SystemPart.make({ text: section.text })]
|
|
798
|
+
})
|
|
799
|
+
);
|
|
800
|
+
return ContextWindow.make({
|
|
801
|
+
modelId: contextWindow.modelId,
|
|
802
|
+
segments: [...taught, ...contextWindow.segments],
|
|
803
|
+
activeTools: contextWindow.activeTools,
|
|
804
|
+
replaced: contextWindow.replaced
|
|
805
|
+
});
|
|
806
|
+
};
|
|
807
|
+
const modelIdFromSeat = (seat) => {
|
|
808
|
+
const separator = seat.indexOf(":");
|
|
809
|
+
return separator < 0 ? seat : seat.slice(separator + 1);
|
|
810
|
+
};
|
|
811
|
+
const placementFrom = (state) => import_effect.Option.match(state.placement, {
|
|
812
|
+
onNone: () => void 0,
|
|
813
|
+
onSome: (value) => {
|
|
814
|
+
switch (value) {
|
|
815
|
+
case "client":
|
|
816
|
+
return import_core.Placement.client();
|
|
817
|
+
case "local":
|
|
818
|
+
return import_core.Placement.local();
|
|
819
|
+
case "remote":
|
|
820
|
+
return import_core.Placement.remote();
|
|
821
|
+
case "sandbox":
|
|
822
|
+
return import_core.Placement.sandbox();
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
const keyMaterialFrom = (state, contextWindow, request) => ({
|
|
827
|
+
version: "flows/key-material/v2",
|
|
828
|
+
kind: "sealed",
|
|
829
|
+
body: { _tag: "ModelCall", request },
|
|
830
|
+
inputs: [{ _tag: "Literal", value: { contextDigest: contextWindow.digest, journalVersion: import_Transcript.journalVersion } }],
|
|
831
|
+
layers: [...new Set(state.layers)].sort(),
|
|
832
|
+
capabilities: [...new Set(state.capabilityEnvelope.map(import_kernel.Capability.format))].sort(),
|
|
833
|
+
effects: import_core.Effects.make({
|
|
834
|
+
reads: [],
|
|
835
|
+
writes: [],
|
|
836
|
+
mode: "hermetic",
|
|
837
|
+
onConflict: "serialize",
|
|
838
|
+
tier: "sealed"
|
|
839
|
+
}),
|
|
840
|
+
placement: placementFrom(state)
|
|
841
|
+
});
|
|
842
|
+
const stateSection = (state) => {
|
|
843
|
+
const settled = CallLedger.render(state.callLedger, state.ledgerShown);
|
|
844
|
+
return [
|
|
845
|
+
VariablesPanel.render({ ledger: state.panel, frame: state.frame - 1 }),
|
|
846
|
+
...settled === void 0 ? [] : [settled]
|
|
847
|
+
].join("\n\n");
|
|
848
|
+
};
|
|
849
|
+
const frozen = (contextWindow, state) => {
|
|
850
|
+
try {
|
|
851
|
+
ContextWindow.render(contextWindow);
|
|
852
|
+
return import_effect.Result.succeed(withSection(contextWindow, state));
|
|
853
|
+
} catch (cause) {
|
|
854
|
+
return import_effect.Result.fail(
|
|
855
|
+
new import_HarnessError.HarnessError({ code: "render_failed", message: "Unable to render the context window", cause })
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
const withSection = (contextWindow, state) => {
|
|
860
|
+
const section = import_model.ModelRequest.Message.user(stateSection(state));
|
|
861
|
+
const segments = [...contextWindow.segments];
|
|
862
|
+
let asks = state.interventions;
|
|
863
|
+
let index = segments.length - 1;
|
|
864
|
+
let position = index < 0 ? 0 : segments[index].content.length;
|
|
865
|
+
while (index >= 0 && asks > 0) {
|
|
866
|
+
const content = segments[index].content;
|
|
867
|
+
position = content.length;
|
|
868
|
+
for (let item = content.length - 1; item >= 0 && asks > 0; item--) {
|
|
869
|
+
if ("role" in content[item]) {
|
|
870
|
+
asks--;
|
|
871
|
+
position = item;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
if (asks > 0 && index > 0) {
|
|
875
|
+
index--;
|
|
876
|
+
} else break;
|
|
877
|
+
}
|
|
878
|
+
const holder = index < 0 ? void 0 : segments[index];
|
|
879
|
+
if (holder === void 0 || holder.zone !== "tail") {
|
|
880
|
+
segments.push(ContextWindow.makeSegment({ kind: "transcript", zone: "tail", content: [section] }));
|
|
881
|
+
} else {
|
|
882
|
+
segments[index] = ContextWindow.makeSegment({
|
|
883
|
+
kind: holder.kind,
|
|
884
|
+
zone: holder.zone,
|
|
885
|
+
content: [...holder.content.slice(0, position), section, ...holder.content.slice(position)]
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
return ContextWindow.make({
|
|
889
|
+
modelId: contextWindow.modelId,
|
|
890
|
+
segments,
|
|
891
|
+
activeTools: contextWindow.activeTools,
|
|
892
|
+
replaced: contextWindow.replaced
|
|
893
|
+
});
|
|
894
|
+
};
|
|
895
|
+
const requestFrom = (state, contextWindow) => {
|
|
896
|
+
let rendered;
|
|
897
|
+
try {
|
|
898
|
+
rendered = ContextWindow.render(contextWindow);
|
|
899
|
+
} catch (cause) {
|
|
900
|
+
return import_effect.Result.fail(
|
|
901
|
+
new import_HarnessError.HarnessError({
|
|
902
|
+
code: "render_failed",
|
|
903
|
+
message: "Unable to render the context window",
|
|
904
|
+
cause
|
|
905
|
+
})
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
return import_effect.Result.succeed(
|
|
909
|
+
import_model.ModelRequest.ModelRequest.make({
|
|
910
|
+
modelId: contextWindow.modelId,
|
|
911
|
+
system: rendered.system,
|
|
912
|
+
messages: rendered.messages,
|
|
913
|
+
// A cell-first frame never declares provider tools: the cell is the plan
|
|
914
|
+
// and `ctx.call` is the only invocation path.
|
|
915
|
+
tools: [],
|
|
916
|
+
toolChoice: "none",
|
|
917
|
+
params: state.modelParams,
|
|
918
|
+
// The window only grows between frames (see `frozen`), so the whole
|
|
919
|
+
// request is the next one's prefix and Anthropic's moving breakpoint
|
|
920
|
+
// sits at its end.
|
|
921
|
+
cacheKey: cacheKey(state, rendered.system),
|
|
922
|
+
// Provider-run tools are not declared tools: the model may search
|
|
923
|
+
// inside the call while `ctx.call` stays the only invocation path.
|
|
924
|
+
...state.serverTools === void 0 ? {} : { serverTools: state.serverTools }
|
|
925
|
+
})
|
|
926
|
+
);
|
|
927
|
+
};
|
|
928
|
+
const cacheKey = (state, system) => {
|
|
929
|
+
const task = system.findIndex((part) => part.text.startsWith("The task for this run:\n\n"));
|
|
930
|
+
const prefix = task < 0 ? system : system.slice(0, task);
|
|
931
|
+
return `smithers-${import_model.CanonicalJson.shortHash(`${state.session}
|
|
932
|
+
${prefix.map((part) => part.text).join("\n")}`)}`;
|
|
933
|
+
};
|
|
934
|
+
const assistantText = (message) => message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
935
|
+
const encodePermissionRequired = import_effect.Schema.encodeSync(import_kernel.Permission.PermissionRequired);
|
|
936
|
+
const permissionRequired = (error) => {
|
|
937
|
+
if (error instanceof import_kernel.Permission.PermissionRequired) return error;
|
|
938
|
+
if (error instanceof import_HarnessError.HarnessError && error.cause instanceof import_kernel.Permission.PermissionRequired) return error.cause;
|
|
939
|
+
return import_effect.Option.getOrUndefined(
|
|
940
|
+
import_effect.Schema.decodeUnknownOption(import_kernel.Permission.PermissionRequired)(
|
|
941
|
+
error instanceof import_HarnessError.HarnessError ? error.cause : error
|
|
942
|
+
)
|
|
943
|
+
);
|
|
944
|
+
};
|
|
945
|
+
const liveCellEcho = 8192;
|
|
946
|
+
const deadCellEcho = 1024;
|
|
947
|
+
const appended = (contextWindow, assistant, messages, echo) => ContextWindow.make({
|
|
948
|
+
modelId: contextWindow.modelId,
|
|
949
|
+
segments: [
|
|
950
|
+
...contextWindow.segments,
|
|
951
|
+
ContextWindow.makeSegment({
|
|
952
|
+
kind: "transcript",
|
|
953
|
+
zone: "tail",
|
|
954
|
+
content: [bounded(assistant, echo), ...messages]
|
|
955
|
+
})
|
|
956
|
+
],
|
|
957
|
+
activeTools: contextWindow.activeTools,
|
|
958
|
+
replaced: contextWindow.replaced
|
|
959
|
+
});
|
|
960
|
+
const observedOn = (contextWindow, assistant, observation, echo) => appended(contextWindow, assistant, [import_model.ModelRequest.Message.user(observation)], echo);
|
|
961
|
+
const memoryShownLimit = 256;
|
|
962
|
+
const shownAfter = (state, drained) => drained.memory === void 0 ? {} : { memoryShown: [...state.memoryShown, ...drained.memory].slice(-memoryShownLimit) };
|
|
963
|
+
const ledgerAfter = (drained) => drained.monitorLedger === void 0 ? {} : { monitorLedger: drained.monitorLedger };
|
|
964
|
+
const marksAfter = (state, drained) => {
|
|
965
|
+
const due = drained.compact === void 0 ? {} : { compactionDue: drained.compact };
|
|
966
|
+
if (drained.marks === void 0) return due;
|
|
967
|
+
const answers = new Map(drained.marks.map(({ digest, ...answer }) => [digest, answer]));
|
|
968
|
+
const transcripts = (0, import_compactable.compactable)(state.contextWindow.segments).filter((segment) => segment.kind === "transcript");
|
|
969
|
+
const missing = transcripts.length - state.segmentFacts.length;
|
|
970
|
+
return {
|
|
971
|
+
segmentFacts: state.segmentFacts.map((facts, at) => {
|
|
972
|
+
const answer = answers.get(transcripts[at + missing].digest);
|
|
973
|
+
return facts.answer !== void 0 || answer === void 0 ? facts : { ...facts, answer };
|
|
974
|
+
}),
|
|
975
|
+
...due
|
|
976
|
+
};
|
|
977
|
+
};
|
|
978
|
+
const carries = (drained) => drained.inserts.length > 0 || drained.seatChanges.length > 0;
|
|
979
|
+
const steered = (state, changes, resolve) => import_effect.Effect.gen(function* () {
|
|
980
|
+
let seat = state.seat;
|
|
981
|
+
let modelParams = state.modelParams;
|
|
982
|
+
for (const change of changes) {
|
|
983
|
+
if (change._tag === "SeatChange") seat = change.seat;
|
|
984
|
+
else {
|
|
985
|
+
modelParams = import_model.ModelRequest.GenerationParams.make({
|
|
986
|
+
maxTokens: modelParams.maxTokens,
|
|
987
|
+
temperature: modelParams.temperature,
|
|
988
|
+
topP: modelParams.topP,
|
|
989
|
+
topK: modelParams.topK,
|
|
990
|
+
stopSequences: modelParams.stopSequences,
|
|
991
|
+
thinkingBudget: modelParams.thinkingBudget,
|
|
992
|
+
reasoningEffort: change.thinking
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
return {
|
|
997
|
+
seat,
|
|
998
|
+
modelParams,
|
|
999
|
+
modelCallMs: state.modelCallMsFollowsEffort ? modelCallMsFor(modelParams.reasoningEffort) : state.modelCallMs,
|
|
1000
|
+
contextWindowTokens: seat === state.seat ? state.contextWindowTokens : resolve === void 0 ? import_model.ModelCatalog.contextWindowTokensFor(modelIdFromSeat(seat)) : yield* resolve(seat)
|
|
1001
|
+
};
|
|
1002
|
+
});
|
|
1003
|
+
const windowOn = (state, seat, context) => seat === state.seat ? context : ContextWindow.make({
|
|
1004
|
+
modelId: modelIdFromSeat(seat),
|
|
1005
|
+
segments: context.segments,
|
|
1006
|
+
activeTools: context.activeTools,
|
|
1007
|
+
replaced: context.replaced
|
|
1008
|
+
});
|
|
1009
|
+
const missedProperty = (message) => {
|
|
1010
|
+
const match = /reading '([^']+)'|read property '([^']+)'/i.exec(message);
|
|
1011
|
+
return match === null ? void 0 : match[1] ?? match[2];
|
|
1012
|
+
};
|
|
1013
|
+
const bindingPathMiss = (message, bindings) => {
|
|
1014
|
+
const property = missedProperty(message);
|
|
1015
|
+
if (property === void 0) return void 0;
|
|
1016
|
+
return bindings.length === 0 ? `If \`${property}\` was meant to come from a name an earlier cell bound: your realm holds no names yet.` : `If \`${property}\` was meant to come from a name an earlier cell bound, these are the names your realm holds: ${elide.head(
|
|
1017
|
+
bindings.map((binding) => binding.name).join(", "),
|
|
1018
|
+
CallLedger.width * 4,
|
|
1019
|
+
"the panel in the frame block lists them all"
|
|
1020
|
+
)}. The panel gives each one's type and size.`;
|
|
1021
|
+
};
|
|
1022
|
+
const revalidationNote = (rejection) => `${rejection.message}
|
|
1023
|
+
|
|
1024
|
+
This reply is not a frame. Nothing ran, nothing changed, and no call was made, so you are being asked again inside the same frame instead of losing it: everything above this line is already in the provider's cache, and only what you write next is paid for. Emit the corrected cell and nothing else.`;
|
|
1025
|
+
const bounded = (assistant, echo) => {
|
|
1026
|
+
const text = assistantText(assistant);
|
|
1027
|
+
const shortened = elide.middle(
|
|
1028
|
+
text,
|
|
1029
|
+
echo,
|
|
1030
|
+
"the reply is not re-read in full; the observation below names what went wrong"
|
|
1031
|
+
);
|
|
1032
|
+
if (shortened === text) return assistant;
|
|
1033
|
+
return import_model.ModelRequest.Message.assistant(shortened, { stopReason: assistant.stopReason });
|
|
1034
|
+
};
|
|
1035
|
+
const clip = (text, width) => elide.head(text, width, "clipped");
|
|
1036
|
+
const salvageSummary = 400;
|
|
1037
|
+
const salvageRecall = "the whole result is still under the name your cell bound it to";
|
|
1038
|
+
const signatureOf = (flow, input, at) => Digest.digest(import_model.CanonicalJson.stringify(at === void 0 ? [flow, input] : [flow, input, at]));
|
|
1039
|
+
const readOnlyCapFailure = (cap, frames) => new import_HarnessError.HarnessError({
|
|
1040
|
+
code: "read_only_cap",
|
|
1041
|
+
message: `The run spent ${frames} consecutive frames without one call that declares a write, twice its read-only budget of ${cap}. It is stopped here rather than allowed to report work it never did.`
|
|
1042
|
+
});
|
|
1043
|
+
const mutating = (descriptor, input) => {
|
|
1044
|
+
if (descriptor.effects.writes.length > 0) return true;
|
|
1045
|
+
const declared = input !== null && typeof input === "object" && !Array.isArray(input) ? input.writes : void 0;
|
|
1046
|
+
return Array.isArray(declared) && declared.length > 0;
|
|
1047
|
+
};
|
|
1048
|
+
const RecordedObservation = import_effect.Schema.Option(EngineLike.Observation);
|
|
1049
|
+
const RecordedCompletion = import_effect.Schema.Struct({
|
|
1050
|
+
observed: import_effect.Schema.NullOr(AgentEvent.ClaimDemanded),
|
|
1051
|
+
demand: import_effect.Schema.NullOr(import_effect.Schema.Struct({
|
|
1052
|
+
event: import_effect.Schema.Union([
|
|
1053
|
+
AgentEvent.UnmovedDemanded,
|
|
1054
|
+
AgentEvent.UnresolvedDemanded,
|
|
1055
|
+
AgentEvent.FailedCallDemanded,
|
|
1056
|
+
AgentEvent.UnobservedDemanded,
|
|
1057
|
+
AgentEvent.NarrowedDemanded,
|
|
1058
|
+
AgentEvent.NarrowOnlyDemanded,
|
|
1059
|
+
AgentEvent.ClaimDemanded
|
|
1060
|
+
]),
|
|
1061
|
+
note: import_effect.Schema.String,
|
|
1062
|
+
keeps: import_effect.Schema.Boolean,
|
|
1063
|
+
spent: import_effect.Schema.Struct({
|
|
1064
|
+
unmovedDemands: import_effect.Schema.optionalKey(import_nonNegativeSafeInt.NonNegativeSafeInt),
|
|
1065
|
+
unresolvedDemands: import_effect.Schema.optionalKey(import_nonNegativeSafeInt.NonNegativeSafeInt),
|
|
1066
|
+
failedCallDemands: import_effect.Schema.optionalKey(import_nonNegativeSafeInt.NonNegativeSafeInt),
|
|
1067
|
+
unobservedDemands: import_effect.Schema.optionalKey(import_nonNegativeSafeInt.NonNegativeSafeInt),
|
|
1068
|
+
narrowingDemands: import_effect.Schema.optionalKey(import_nonNegativeSafeInt.NonNegativeSafeInt),
|
|
1069
|
+
claimDemands: import_effect.Schema.optionalKey(import_nonNegativeSafeInt.NonNegativeSafeInt)
|
|
1070
|
+
})
|
|
1071
|
+
})),
|
|
1072
|
+
unproven: import_effect.Schema.NullOr(import_HarnessError.HarnessError),
|
|
1073
|
+
// An optional key, not a nullable one: a judgement recorded before decisions
|
|
1074
|
+
// existed has no such member, and it must replay as a judgement with no
|
|
1075
|
+
// decision to report rather than fail to decode.
|
|
1076
|
+
decision: import_effect.Schema.optionalKey(import_effect.Schema.NullOr(AgentEvent.DecisionSettled)),
|
|
1077
|
+
sentenceDecision: import_effect.Schema.optionalKey(import_effect.Schema.NullOr(AgentEvent.DecisionSettled)),
|
|
1078
|
+
unfinishedDecision: import_effect.Schema.optionalKey(import_effect.Schema.NullOr(AgentEvent.DecisionSettled))
|
|
1079
|
+
});
|
|
1080
|
+
const witness = (engine, state, boundary, phase) => engine.record({
|
|
1081
|
+
name: `workspace-${phase}`,
|
|
1082
|
+
// The purpose is folded into the boundary as well as carried in `name`.
|
|
1083
|
+
// `EngineLike.record` keys on `(name, identity)` together, and the
|
|
1084
|
+
// production engine does; an engine that read the contract as keying on
|
|
1085
|
+
// identity alone would replay this frame's opening measurement as its
|
|
1086
|
+
// closing one, and its cell outcome as its steering drain. Folding the
|
|
1087
|
+
// purpose in makes the controller correct under either reading. No released
|
|
1088
|
+
// run database exists at 1.0.0-rc.0, so the labels are free to change now
|
|
1089
|
+
// and will not be again.
|
|
1090
|
+
identity: { session: state.session, frame: state.frame, boundary: `workspace-${phase}:${boundary}` },
|
|
1091
|
+
success: RecordedObservation,
|
|
1092
|
+
execute: engine.observe
|
|
1093
|
+
});
|
|
1094
|
+
const RecordedSnapshot = import_effect.Schema.Option(EngineLike.Snapshot);
|
|
1095
|
+
const pin = (engine, state, cell, ordinal, id, callMs) => engine.record({
|
|
1096
|
+
name: "checkpoint",
|
|
1097
|
+
identity: { session: state.session, frame: state.frame, boundary: `checkpoint:${cell}:${ordinal}` },
|
|
1098
|
+
success: RecordedSnapshot,
|
|
1099
|
+
// The per-call ceiling, applied INSIDE the record for the reason
|
|
1100
|
+
// {@link settled} applies it inside its own: a store that hung past the
|
|
1101
|
+
// budget left the cell told nothing was pinned while the pin itself was
|
|
1102
|
+
// still in flight, so the resumed frame could be handed a snapshot the
|
|
1103
|
+
// original attempt was told it never got. Cut off here, "nothing was
|
|
1104
|
+
// pinned" is what the journal holds and what every later attempt reads.
|
|
1105
|
+
execute: engine.capture({
|
|
1106
|
+
id,
|
|
1107
|
+
identity: { session: state.session, frame: state.frame, boundary: `checkpoint-capture:${cell}` }
|
|
1108
|
+
}).pipe(
|
|
1109
|
+
import_effect.Effect.timeoutOrElse({ duration: callMs, orElse: () => import_effect.Effect.succeed(import_effect.Option.none()) })
|
|
1110
|
+
)
|
|
1111
|
+
});
|
|
1112
|
+
const issued = (engine, state, cell, ordinal, callMs, flow, issue, replaying, call) => import_effect.Effect.gen(function* () {
|
|
1113
|
+
if (replaying) {
|
|
1114
|
+
return yield* engine.record({
|
|
1115
|
+
name: "cell-call",
|
|
1116
|
+
call,
|
|
1117
|
+
identity: { session: state.session, frame: state.frame, boundary: `cell-call:${cell}:${ordinal}` },
|
|
1118
|
+
success: Cell.CallResultVariant,
|
|
1119
|
+
execute: import_effect.Effect.fail(
|
|
1120
|
+
new import_HarnessError.HarnessError({
|
|
1121
|
+
code: "incompatible_journal",
|
|
1122
|
+
message: `The timed-out frame is missing settlement ${ordinal}`
|
|
1123
|
+
})
|
|
1124
|
+
)
|
|
1125
|
+
}).pipe(import_effect.Effect.flatMap(Cell.decodeCallResult));
|
|
1126
|
+
}
|
|
1127
|
+
const refused = engine.admit === void 0 ? void 0 : yield* engine.admit(call);
|
|
1128
|
+
const identity = { session: state.session, frame: state.frame, boundary: `cell-call:${cell}:${ordinal}` };
|
|
1129
|
+
const subject = EngineLike.callSubject(call.identity);
|
|
1130
|
+
const guarded = refused === void 0 ? engine.guard : void 0;
|
|
1131
|
+
if (guarded !== void 0) yield* guarded.admit(subject);
|
|
1132
|
+
const settlement = refused ?? (yield* issue.pipe(
|
|
1133
|
+
import_effect.Effect.timeoutOrElse({ duration: callMs, orElse: () => import_effect.Effect.succeed(Sandbox.callTimedOut(flow, callMs)) }),
|
|
1134
|
+
import_effect.Effect.flatMap(Cell.decodeCallResult)
|
|
1135
|
+
));
|
|
1136
|
+
if (guarded !== void 0 && settlement.outcome === "failure" && settlement.code === "timeout") {
|
|
1137
|
+
yield* guarded.trip({
|
|
1138
|
+
source: "tool-call",
|
|
1139
|
+
subject,
|
|
1140
|
+
limitMillis: (0, import_refusal.limitOf)(settlement),
|
|
1141
|
+
message: settlement.message ?? `Flow ${flow} timed out.`
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
return yield* engine.record({
|
|
1145
|
+
name: "cell-call",
|
|
1146
|
+
call,
|
|
1147
|
+
identity,
|
|
1148
|
+
success: Cell.CallResultVariant,
|
|
1149
|
+
execute: import_effect.Effect.succeed(settlement)
|
|
1150
|
+
}).pipe(import_effect.Effect.flatMap(Cell.decodeCallResult));
|
|
1151
|
+
});
|
|
1152
|
+
const RecordedFrame = import_effect.Schema.Struct({
|
|
1153
|
+
boundary: import_effect.Schema.optional(Sandbox.FrameBoundary),
|
|
1154
|
+
outcome: Cell.Outcome,
|
|
1155
|
+
prints: import_effect.Schema.String,
|
|
1156
|
+
bindings: import_effect.Schema.Array(VariablesPanel.Binding)
|
|
1157
|
+
});
|
|
1158
|
+
const minter = (state, cell, engine, minted, callMs, emit) => (mint) => import_effect.Effect.gen(function* () {
|
|
1159
|
+
const held = state.checkpointIds.length + minted.length;
|
|
1160
|
+
if (held >= state.checkpointCap) {
|
|
1161
|
+
return (0, import_refusal.refusal)(
|
|
1162
|
+
"checkpoint_exhausted",
|
|
1163
|
+
`This run has pinned its ${state.checkpointCap} checkpoints and nothing was pinned here. ${held === 0 ? "" : `The ones you hold are ${[...state.checkpointIds, ...minted].join(", ")}, and `}ctx.base is always the tree this run opened on.`
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
const id = `cp-${state.frame}-${mint.ordinal}`;
|
|
1167
|
+
const snapshot = yield* pin(engine, state, cell.digest, mint.ordinal, id, callMs);
|
|
1168
|
+
if (import_effect.Option.isNone(snapshot)) {
|
|
1169
|
+
return (0, import_refusal.refusal)(
|
|
1170
|
+
"checkpoint_unavailable",
|
|
1171
|
+
"This host pins no trees, so nothing was checkpointed. For a baseline, run the check before your edit, then again after it."
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
minted.push(id);
|
|
1175
|
+
yield* emit(
|
|
1176
|
+
new AgentEvent.CheckpointMinted({
|
|
1177
|
+
eventType: eventType.checkpointMinted,
|
|
1178
|
+
id: snapshot.value.id,
|
|
1179
|
+
ref: snapshot.value.ref,
|
|
1180
|
+
cell: cell.digest,
|
|
1181
|
+
ordinal: mint.ordinal
|
|
1182
|
+
})
|
|
1183
|
+
);
|
|
1184
|
+
return new Cell.CallResult({ outcome: "success", value: Cell.checkpoint(snapshot.value.id) });
|
|
1185
|
+
});
|
|
1186
|
+
const emitModelProgress = (event, emit) => event.type === "retry" ? emit(
|
|
1187
|
+
new AgentEvent.ModelRetried({
|
|
1188
|
+
eventType: eventType.modelRetried,
|
|
1189
|
+
attempt: event.attempt,
|
|
1190
|
+
code: event.code,
|
|
1191
|
+
delayMillis: event.delayMillis
|
|
1192
|
+
})
|
|
1193
|
+
) : event.type === "settle" ? import_effect.Effect.void : emit(new AgentEvent.ModelDelta({ eventType: eventType.modelDelta, delta: event }));
|
|
1194
|
+
const invalidProbeKey = "invalidProbe";
|
|
1195
|
+
const invalidProbeOf = (value) => {
|
|
1196
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1197
|
+
const declared = value[invalidProbeKey];
|
|
1198
|
+
if (declared === null || typeof declared !== "object" || Array.isArray(declared)) return void 0;
|
|
1199
|
+
const { message, reason } = declared;
|
|
1200
|
+
return typeof reason === "string" && typeof message === "string" ? { reason, message } : void 0;
|
|
1201
|
+
};
|
|
1202
|
+
const mutatedKey = "mutated";
|
|
1203
|
+
const mutatedOf = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && value[mutatedKey] === true;
|
|
1204
|
+
const frameFailureMessage = (error) => {
|
|
1205
|
+
const row = typeof error === "object" && error !== null ? error : {};
|
|
1206
|
+
const said = typeof row["message"] === "string" ? row["message"].replace(/\s+/g, " ").trim() : "";
|
|
1207
|
+
if (said === "") return "The cell frame failed";
|
|
1208
|
+
const code = typeof row["code"] === "string" && row["code"] !== "" ? `${row["code"].slice(0, 64)}: ` : "";
|
|
1209
|
+
return `The cell frame failed: ${code}${said.slice(0, 1e3)}`;
|
|
1210
|
+
};
|
|
1211
|
+
const budgetMessage = (state) => state.bouncedCompletion === void 0 ? `The frame budget of ${state.maxFrames} is exhausted. The run stops here; the last transition was a request to continue.` : `The frame budget of ${state.maxFrames} is exhausted. This run completed once and had that completion handed back for another frame, so what it reported then stands here rather than being lost:
|
|
1212
|
+
|
|
1213
|
+
${state.bouncedCompletion}`;
|
|
1214
|
+
const callHandler = (state, cell, descriptors, engine, ledger, performed, restored, tree, live, callMs, replaying, emit) => (invocation) => import_effect.Effect.gen(function* () {
|
|
1215
|
+
if (state.withheldFlows.includes(invocation.flow)) {
|
|
1216
|
+
restored.add(invocation.flow);
|
|
1217
|
+
return (0, import_refusal.refusal)(
|
|
1218
|
+
"flow_withheld",
|
|
1219
|
+
`Flow ${invocation.flow} was withheld for this task. It is in ctx.flows from the next frame; reissue the call.`
|
|
1220
|
+
);
|
|
1221
|
+
}
|
|
1222
|
+
const descriptor = descriptors.get(invocation.flow);
|
|
1223
|
+
if (descriptor === void 0) {
|
|
1224
|
+
return (0, import_refusal.refusal)("unknown_flow", `Unknown flow ${invocation.flow}. Only the flows in ctx.flows are callable.`);
|
|
1225
|
+
}
|
|
1226
|
+
if (!descriptor.modelInvocable) {
|
|
1227
|
+
return (0, import_refusal.refusal)("capability_refused", `Flow ${invocation.flow} is not model-invocable.`);
|
|
1228
|
+
}
|
|
1229
|
+
const envelope = import_kernel.CapabilitySet.fromPatterns(state.capabilityEnvelope);
|
|
1230
|
+
const refused = descriptor.capabilities.filter(
|
|
1231
|
+
(declared) => import_effect.Option.match(import_kernel.Capability.parse(declared), {
|
|
1232
|
+
onNone: () => true,
|
|
1233
|
+
onSome: (capability) => !import_kernel.CapabilitySet.allows(envelope, capability)
|
|
1234
|
+
})
|
|
1235
|
+
);
|
|
1236
|
+
if (refused.length > 0) {
|
|
1237
|
+
return (0, import_refusal.refusal)(
|
|
1238
|
+
"capability_refused",
|
|
1239
|
+
`Flow ${invocation.flow} needs ${refused.join(", ")}, which is outside this run's capability envelope.`
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
const changes = mutating(descriptor, invocation.input);
|
|
1243
|
+
if (changes) {
|
|
1244
|
+
const found = TruncatedOutput.reuse(invocation.input, ledger);
|
|
1245
|
+
if (found !== void 0) {
|
|
1246
|
+
return (0, import_refusal.refusal)("truncated_write", TruncatedOutput.refusal(invocation.flow, found));
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
let at;
|
|
1250
|
+
if (invocation.at !== void 0) {
|
|
1251
|
+
at = Cell.checkpointOf(invocation.at);
|
|
1252
|
+
if (at === void 0) {
|
|
1253
|
+
return (0, import_refusal.refusal)(
|
|
1254
|
+
"invalid_input",
|
|
1255
|
+
`The at option takes a checkpoint, which is what ctx.checkpoint() resolves with and what ctx.base is. It was given ${elide.head(import_model.CanonicalJson.stringify(invocation.at), 120, "the rest is the same shape")}.`
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
if (changes) {
|
|
1259
|
+
return (0, import_refusal.refusal)(
|
|
1260
|
+
"checkpoint_readonly",
|
|
1261
|
+
`Flow ${invocation.flow} declares a write, and a checkpoint is a read-only view of a tree that has already been. Nothing was run. Make the change on the live tree, and keep at for the readings you take against ${at}.`
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
const sealed = descriptor.effects.tier === "sealed";
|
|
1266
|
+
const epoch = sealed && at === void 0 ? {
|
|
1267
|
+
frames: state.mutations,
|
|
1268
|
+
calls: tree.writes,
|
|
1269
|
+
...tree.chain === void 0 ? {} : { writes: tree.chain },
|
|
1270
|
+
...live
|
|
1271
|
+
} : void 0;
|
|
1272
|
+
const call = Cell.callOf(descriptor, {
|
|
1273
|
+
input: invocation.input,
|
|
1274
|
+
identity: new Cell.CallIdentity({
|
|
1275
|
+
session: state.session,
|
|
1276
|
+
frame: state.frame,
|
|
1277
|
+
cell: cell.digest,
|
|
1278
|
+
ordinal: invocation.ordinal,
|
|
1279
|
+
declaration: Cell.declarationDigest(descriptor),
|
|
1280
|
+
layers: [...new Set(state.layers)].sort()
|
|
1281
|
+
}),
|
|
1282
|
+
...at === void 0 ? {} : { at },
|
|
1283
|
+
...epoch === void 0 ? {} : { epoch }
|
|
1284
|
+
});
|
|
1285
|
+
performed.add(invocation.ordinal);
|
|
1286
|
+
if (!sealed) {
|
|
1287
|
+
tree.writes++;
|
|
1288
|
+
tree.chain = Digest.digest(
|
|
1289
|
+
import_model.CanonicalJson.stringify([tree.chain ?? null, signatureOf(invocation.flow, invocation.input, at)])
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
yield* emit(new AgentEvent.CellCallStarted({ eventType: eventType.cellCallStarted, call }));
|
|
1293
|
+
const result = yield* issued(
|
|
1294
|
+
engine,
|
|
1295
|
+
state,
|
|
1296
|
+
cell.digest,
|
|
1297
|
+
invocation.ordinal,
|
|
1298
|
+
callMs,
|
|
1299
|
+
invocation.flow,
|
|
1300
|
+
// A flow that asks Jev journals its receipts into this run.
|
|
1301
|
+
import_effect.Effect.suspend(() => engine.call(call)).pipe(import_effect.Effect.provideService(AgentEvent.Journal, emit)),
|
|
1302
|
+
replaying,
|
|
1303
|
+
call
|
|
1304
|
+
);
|
|
1305
|
+
if (result.outcome === "success") ledger.push(...TruncatedOutput.captures(call.flowName, result.value));
|
|
1306
|
+
yield* emit(
|
|
1307
|
+
new AgentEvent.CellCallSettled({
|
|
1308
|
+
eventType: eventType.cellCallSettled,
|
|
1309
|
+
flowName: call.flowName,
|
|
1310
|
+
identity: call.identity,
|
|
1311
|
+
result
|
|
1312
|
+
})
|
|
1313
|
+
);
|
|
1314
|
+
return result;
|
|
1315
|
+
});
|
|
1316
|
+
const requested = (state, engine, request, purpose, attempt, emit) => import_effect.Effect.gen(function* () {
|
|
1317
|
+
const resolved = yield* EngineLike.resolve(engine, request);
|
|
1318
|
+
if (import_effect.Option.isNone(resolved)) return;
|
|
1319
|
+
yield* emit(
|
|
1320
|
+
new AgentEvent.ModelRequested({
|
|
1321
|
+
eventType: eventType.modelRequested,
|
|
1322
|
+
scope: state.session,
|
|
1323
|
+
frame: state.frame,
|
|
1324
|
+
attempt,
|
|
1325
|
+
purpose,
|
|
1326
|
+
seat: state.seat,
|
|
1327
|
+
binding: import_effect.Option.getOrUndefined(resolved.value.binding),
|
|
1328
|
+
request: resolved.value.request
|
|
1329
|
+
})
|
|
1330
|
+
);
|
|
1331
|
+
});
|
|
1332
|
+
const summarized = (state, engine, emit, step) => import_effect.Effect.gen(function* () {
|
|
1333
|
+
const summaryRequest = yield* Compaction.summaryRequest(state.contextWindow, step).pipe(import_effect.Effect.orDie);
|
|
1334
|
+
const request = import_model.ModelRequest.ModelRequest.make({
|
|
1335
|
+
modelId: summaryRequest.modelId,
|
|
1336
|
+
system: summaryRequest.system,
|
|
1337
|
+
messages: summaryRequest.messages,
|
|
1338
|
+
tools: [],
|
|
1339
|
+
toolChoice: "none",
|
|
1340
|
+
params: summaryRequest.params
|
|
1341
|
+
});
|
|
1342
|
+
yield* requested(state, engine, request, "compaction", 1, emit);
|
|
1343
|
+
const events = yield* import_effect.Stream.runCollect(
|
|
1344
|
+
(engine.sealStepWithEvents?.({
|
|
1345
|
+
request,
|
|
1346
|
+
keyMaterial: keyMaterialFrom(state, state.contextWindow, request),
|
|
1347
|
+
modelCallMs: state.modelCallMs
|
|
1348
|
+
}, emit) ?? engine.sealStep({
|
|
1349
|
+
request,
|
|
1350
|
+
keyMaterial: keyMaterialFrom(state, state.contextWindow, request),
|
|
1351
|
+
modelCallMs: state.modelCallMs
|
|
1352
|
+
})).pipe(
|
|
1353
|
+
import_effect.Stream.tap((event) => emitModelProgress(event, emit))
|
|
1354
|
+
)
|
|
1355
|
+
).pipe(import_effect.Effect.map((collected) => Array.from(collected)));
|
|
1356
|
+
if (!events.some((event) => event.type === "settle")) {
|
|
1357
|
+
return yield* new import_HarnessError.HarnessError({
|
|
1358
|
+
code: "model_failed",
|
|
1359
|
+
message: "The sealed compaction step ended without a recorded settlement"
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
const settled = import_model.ModelEvent.ModelEvent.settledMessage(events);
|
|
1363
|
+
const text = settled.message.content.filter(
|
|
1364
|
+
(part) => part.type === "text"
|
|
1365
|
+
);
|
|
1366
|
+
if (text.length === 0) {
|
|
1367
|
+
return yield* new import_HarnessError.HarnessError({
|
|
1368
|
+
code: "model_failed",
|
|
1369
|
+
message: "The sealed compaction step returned no text summary"
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
return import_model.ModelRequest.Message.user(
|
|
1373
|
+
(0, import_untrustedData.untrustedData)(text.map((part) => part.text).join("\n"), "compaction summary of conversation and tool output")
|
|
1374
|
+
);
|
|
1375
|
+
});
|
|
1376
|
+
const messageText = (message) => message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
1377
|
+
const markItem = (segment) => {
|
|
1378
|
+
const messages = segment.content.filter((item) => "role" in item);
|
|
1379
|
+
const said = messages.filter((message) => message.role === "assistant").map(messageText).join("\n");
|
|
1380
|
+
const extracted = Cell.extract(said);
|
|
1381
|
+
return {
|
|
1382
|
+
tokens: segment.tokens.value,
|
|
1383
|
+
cell: extracted._tag === "Success" ? extracted.success.source.text : "",
|
|
1384
|
+
prose: Supervisor.prose(said),
|
|
1385
|
+
observed: messages.filter((message) => message.role !== "assistant").map(messageText).join("\n\n")
|
|
1386
|
+
};
|
|
1387
|
+
};
|
|
1388
|
+
const alignedFacts = (state, segments) => {
|
|
1389
|
+
const transcripts = segments.filter((segment) => segment.kind === "transcript").length;
|
|
1390
|
+
if (transcripts !== state.segmentFacts.length) return void 0;
|
|
1391
|
+
let next = 0;
|
|
1392
|
+
return segments.map((segment) => segment.kind === "transcript" ? state.segmentFacts[next++] : void 0);
|
|
1393
|
+
};
|
|
1394
|
+
const unmarked = (state) => {
|
|
1395
|
+
const segments = (0, import_compactable.compactable)(state.contextWindow.segments);
|
|
1396
|
+
const facts = alignedFacts(state, segments);
|
|
1397
|
+
if (facts === void 0) return [];
|
|
1398
|
+
const open = segments.flatMap((segment, index) => {
|
|
1399
|
+
const known = facts[index];
|
|
1400
|
+
return known === void 0 || known.person || known.answer !== void 0 ? [] : [segment];
|
|
1401
|
+
});
|
|
1402
|
+
return [...new Map(open.map((segment) => [segment.digest, segment])).values()].map((segment) => ({
|
|
1403
|
+
digest: segment.digest,
|
|
1404
|
+
item: markItem(segment)
|
|
1405
|
+
}));
|
|
1406
|
+
};
|
|
1407
|
+
const factsAfter = (state, prefixLength, marks) => {
|
|
1408
|
+
const transcripts = (0, import_compactable.compactable)(state.contextWindow.segments).flatMap(
|
|
1409
|
+
(segment, index) => segment.kind === "transcript" ? [index] : []
|
|
1410
|
+
);
|
|
1411
|
+
const missing = transcripts.length - state.segmentFacts.length;
|
|
1412
|
+
return transcripts.flatMap((index, at) => {
|
|
1413
|
+
const facts = state.segmentFacts[at - missing];
|
|
1414
|
+
return facts !== void 0 && (index >= prefixLength || marks?.[index] === "keep") ? [facts] : [];
|
|
1415
|
+
});
|
|
1416
|
+
};
|
|
1417
|
+
const MarksRecord = import_effect.Schema.Array(compactionMarks.Marked);
|
|
1418
|
+
const marked = (state, facts, prefixLength, engine, emit, taskOf) => import_effect.Effect.gen(function* () {
|
|
1419
|
+
const segments = (0, import_compactable.compactable)(state.contextWindow.segments);
|
|
1420
|
+
const failing = state.checks.filter((check) => check.failing).map((check) => check.label);
|
|
1421
|
+
const pinned = compactionMarks.pins(segments, prefixLength, facts, failing);
|
|
1422
|
+
const open = compactionMarks.unpinned(pinned);
|
|
1423
|
+
const missing = open.filter((index) => facts[index]?.answer === void 0);
|
|
1424
|
+
const budget = {
|
|
1425
|
+
contextWindow: state.contextWindowTokens,
|
|
1426
|
+
reserve: import_compactable.defaultReserve,
|
|
1427
|
+
keepRecent: import_compactable.defaultKeepRecent,
|
|
1428
|
+
suffix: segments.slice(prefixLength).reduce((sum, segment) => sum + segment.tokens.value, 0),
|
|
1429
|
+
tokens: segments.slice(0, prefixLength).map((segment) => segment.tokens.value)
|
|
1430
|
+
};
|
|
1431
|
+
const resolved = (answered) => import_effect.Effect.fromResult(compactionMarks.resolve(open.map((index) => answered.get(index)), pinned, budget)).pipe(
|
|
1432
|
+
import_effect.Effect.orDie
|
|
1433
|
+
);
|
|
1434
|
+
const stored = new Map(open.flatMap((index) => {
|
|
1435
|
+
const answer = facts[index]?.answer;
|
|
1436
|
+
return answer === void 0 ? [] : [[index, answer]];
|
|
1437
|
+
}));
|
|
1438
|
+
if (missing.length === 0) return yield* resolved(stored);
|
|
1439
|
+
const prefix = yield* import_effect.Effect.fromResult(ContextWindow.prefixDigest(state.contextWindow, prefixLength)).pipe(
|
|
1440
|
+
import_effect.Effect.orDie
|
|
1441
|
+
);
|
|
1442
|
+
const record = yield* Judgement.recorded(
|
|
1443
|
+
engine,
|
|
1444
|
+
{
|
|
1445
|
+
name: "compaction-marks",
|
|
1446
|
+
identity: { session: state.session, frame: state.frame, boundary: `compaction-marks:${prefix}` },
|
|
1447
|
+
classifier: "compaction/marks",
|
|
1448
|
+
value: MarksRecord,
|
|
1449
|
+
items: missing.length
|
|
1450
|
+
},
|
|
1451
|
+
compactionMarks.read(
|
|
1452
|
+
{ task: Judgement.task(taskOf(state.contextWindow)), failing },
|
|
1453
|
+
missing.map((index) => markItem(segments[index]))
|
|
1454
|
+
).pipe(import_effect.Effect.flatMap(
|
|
1455
|
+
(reading) => resolved(new Map([...stored, ...missing.map((index, at) => [index, reading.answers[at]])])).pipe(
|
|
1456
|
+
import_effect.Effect.map((value) => ({
|
|
1457
|
+
value,
|
|
1458
|
+
asked: reading.asked,
|
|
1459
|
+
acted: value.some((mark) => mark.mark !== "squash")
|
|
1460
|
+
}))
|
|
1461
|
+
)
|
|
1462
|
+
))
|
|
1463
|
+
);
|
|
1464
|
+
yield* Judgement.emitRecorded(emit, record);
|
|
1465
|
+
return record.value ?? void 0;
|
|
1466
|
+
});
|
|
1467
|
+
const compacted = (state, engine, emit, judged, taskOf) => import_effect.Effect.gen(function* () {
|
|
1468
|
+
const over = Compaction.shouldCompact({
|
|
1469
|
+
total: state.contextWindow.tokens.total,
|
|
1470
|
+
contextWindow: state.contextWindowTokens
|
|
1471
|
+
});
|
|
1472
|
+
const due = state.compactionDue;
|
|
1473
|
+
const opened = due.length === 0 ? state : advance(state, { compactionDue: [] });
|
|
1474
|
+
if (!over && due.length === 0) return opened;
|
|
1475
|
+
const prefixLength = Compaction.selectPrefix(state.contextWindow);
|
|
1476
|
+
if (prefixLength === 0) return opened;
|
|
1477
|
+
const causes = [...over ? ["budget"] : [], ...due];
|
|
1478
|
+
const facts = judged ? alignedFacts(state, (0, import_compactable.compactable)(state.contextWindow.segments)) : void 0;
|
|
1479
|
+
const unaligned = judged && facts === void 0;
|
|
1480
|
+
const marks = facts === void 0 ? void 0 : yield* marked(state, facts, prefixLength, engine, emit, taskOf);
|
|
1481
|
+
if (!over && marks !== void 0 && marks.every((mark) => mark.mark === "keep")) return opened;
|
|
1482
|
+
const step = yield* Compaction.declare(
|
|
1483
|
+
state.contextWindow,
|
|
1484
|
+
prefixLength,
|
|
1485
|
+
{
|
|
1486
|
+
identity: "flows/harness/CellTurn.compaction",
|
|
1487
|
+
modelId: state.contextWindow.modelId,
|
|
1488
|
+
params: state.modelParams
|
|
1489
|
+
},
|
|
1490
|
+
marks?.map((mark) => mark.mark)
|
|
1491
|
+
).pipe(import_effect.Effect.orDie);
|
|
1492
|
+
const summary = marks === void 0 || marks.some((mark) => mark.mark === "squash") ? yield* summarized(state, engine, emit, step) : void 0;
|
|
1493
|
+
const contextWindow = yield* Compaction.apply(state.contextWindow, step, summary).pipe(import_effect.Effect.orDie);
|
|
1494
|
+
const segments = (0, import_compactable.compactable)(state.contextWindow.segments);
|
|
1495
|
+
const replaced = segments.slice(0, prefixLength);
|
|
1496
|
+
yield* emit(
|
|
1497
|
+
new AgentEvent.CompactionSettled({
|
|
1498
|
+
eventType: eventType.compactionSettled,
|
|
1499
|
+
replacedPrefixDigest: step.replacedPrefixDigest,
|
|
1500
|
+
retainedMessageCount: segments.slice(prefixLength).flatMap((segment) => segment.content).filter((item) => "role" in item).length,
|
|
1501
|
+
...summary === void 0 ? {} : { summary },
|
|
1502
|
+
...unaligned ? { unaligned } : {},
|
|
1503
|
+
causes,
|
|
1504
|
+
...marks === void 0 ? {} : {
|
|
1505
|
+
kept: replaced.filter((_, index) => marks[index].mark === "keep").flatMap((segment) => segment.content.filter((item) => "role" in item)),
|
|
1506
|
+
marks: replaced.map((segment, index) => ({ digest: segment.digest, ...marks[index] })),
|
|
1507
|
+
removedTokens: replaced.filter((_, index) => marks[index].mark === "remove").reduce((sum, segment) => sum + segment.tokens.value, 0)
|
|
1508
|
+
}
|
|
1509
|
+
})
|
|
1510
|
+
);
|
|
1511
|
+
return advance(opened, {
|
|
1512
|
+
contextWindow,
|
|
1513
|
+
segmentFacts: factsAfter(state, prefixLength, marks?.map((mark) => mark.mark)),
|
|
1514
|
+
// The sections that listed earlier calls may be among what was replaced.
|
|
1515
|
+
ledgerShown: 0
|
|
1516
|
+
});
|
|
1517
|
+
});
|
|
1518
|
+
const parsed = (message) => {
|
|
1519
|
+
if (message.stopReason === "length") {
|
|
1520
|
+
return import_effect.Result.fail(
|
|
1521
|
+
new Cell.Rejected({
|
|
1522
|
+
code: "output_truncated",
|
|
1523
|
+
message: "The model reached its output limit (length) before finishing the response. No blocks ran. Emit a shorter, complete cell."
|
|
1524
|
+
})
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1527
|
+
const extracted = Cell.extract(assistantText(message));
|
|
1528
|
+
if (extracted._tag === "Failure") return import_effect.Result.fail(extracted.failure);
|
|
1529
|
+
const validation = CellValidation.validate(extracted.success.source);
|
|
1530
|
+
return validation.rejected === void 0 ? import_effect.Result.succeed({
|
|
1531
|
+
source: extracted.success.source,
|
|
1532
|
+
blocks: extracted.success.blocks,
|
|
1533
|
+
program: validation.compiled
|
|
1534
|
+
}) : import_effect.Result.fail(validation.rejected);
|
|
1535
|
+
};
|
|
1536
|
+
const seal = (state, engine, emit) => import_effect.Effect.gen(function* () {
|
|
1537
|
+
let contextWindow = state.contextWindow;
|
|
1538
|
+
for (let attempt = 0; ; attempt++) {
|
|
1539
|
+
const request = yield* import_effect.Effect.fromResult(requestFrom(state, contextWindow));
|
|
1540
|
+
yield* requested(state, engine, request, "frame", attempt + 1, emit);
|
|
1541
|
+
const startedAt = yield* import_effect.Clock.currentTimeMillis;
|
|
1542
|
+
const events = yield* import_effect.Stream.runCollect(
|
|
1543
|
+
(engine.sealStepWithEvents?.({
|
|
1544
|
+
request,
|
|
1545
|
+
keyMaterial: keyMaterialFrom(state, contextWindow, request),
|
|
1546
|
+
modelCallMs: state.modelCallMs
|
|
1547
|
+
}, emit) ?? engine.sealStep({
|
|
1548
|
+
request,
|
|
1549
|
+
keyMaterial: keyMaterialFrom(state, contextWindow, request),
|
|
1550
|
+
modelCallMs: state.modelCallMs
|
|
1551
|
+
})).pipe(
|
|
1552
|
+
import_effect.Stream.tap((event) => emitModelProgress(event, emit))
|
|
1553
|
+
)
|
|
1554
|
+
).pipe(import_effect.Effect.map((collected) => Array.from(collected)));
|
|
1555
|
+
const settledAt = yield* import_effect.Clock.currentTimeMillis;
|
|
1556
|
+
if (!events.some((event) => event.type === "settle")) {
|
|
1557
|
+
return yield* new import_HarnessError.HarnessError({
|
|
1558
|
+
code: "model_failed",
|
|
1559
|
+
message: "The sealed model step ended without a recorded settlement"
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
const settled = import_model.ModelEvent.ModelEvent.settledMessage(events);
|
|
1563
|
+
const sessionId = events.find((event) => event.type === "settle")?.sessionId;
|
|
1564
|
+
const cost = Pricing.cost(settled.usage, request.modelId, { at: settledAt });
|
|
1565
|
+
yield* emit(
|
|
1566
|
+
new AgentEvent.ModelSettled({
|
|
1567
|
+
eventType: eventType.modelSettled,
|
|
1568
|
+
message: settled.message,
|
|
1569
|
+
usage: settled.usage,
|
|
1570
|
+
...cost,
|
|
1571
|
+
...sessionId === void 0 ? {} : { sessionId },
|
|
1572
|
+
durationMillis: settledAt - startedAt
|
|
1573
|
+
})
|
|
1574
|
+
);
|
|
1575
|
+
const cell = parsed(settled.message);
|
|
1576
|
+
if (cell._tag === "Success" || attempt >= state.revalidations) {
|
|
1577
|
+
return { contextWindow, answer: settled.message, cell };
|
|
1578
|
+
}
|
|
1579
|
+
yield* emit(
|
|
1580
|
+
new AgentEvent.CellRejectedInFrame({
|
|
1581
|
+
eventType: eventType.cellRejectedInFrame,
|
|
1582
|
+
attempt: attempt + 1,
|
|
1583
|
+
code: cell.failure.code,
|
|
1584
|
+
message: cell.failure.message
|
|
1585
|
+
})
|
|
1586
|
+
);
|
|
1587
|
+
contextWindow = observedOn(
|
|
1588
|
+
contextWindow,
|
|
1589
|
+
settled.message,
|
|
1590
|
+
revalidationNote(cell.failure),
|
|
1591
|
+
deadCellEcho
|
|
1592
|
+
);
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1595
|
+
const evaluate = (input, state, produced, engine, sandbox, realm, opened, steering, emit) => import_effect.Effect.gen(function* () {
|
|
1596
|
+
const cell = produced.source;
|
|
1597
|
+
const descriptors = new Map(input.flows.map((descriptor) => [descriptor.name, descriptor]));
|
|
1598
|
+
const projections = {};
|
|
1599
|
+
for (const descriptor of input.flows) projections[descriptor.name] = Cell.project(descriptor);
|
|
1600
|
+
const captures = [...state.truncatedOutputs];
|
|
1601
|
+
const calls = [];
|
|
1602
|
+
const performed = /* @__PURE__ */ new Set();
|
|
1603
|
+
const restored = /* @__PURE__ */ new Set();
|
|
1604
|
+
const tree = { writes: 0, chain: void 0 };
|
|
1605
|
+
const live = import_effect.Option.isSome(opened) && opened.value.complete ? { tree: opened.value.digest } : { session: state.session, frame: state.frame };
|
|
1606
|
+
const callMs = Sandbox.withDefaults(sandbox.capabilities, input.limits).callMs ?? Sandbox.defaultLimits.callMs;
|
|
1607
|
+
const totalMs = Sandbox.withDefaults(sandbox.capabilities, input.limits).totalMs;
|
|
1608
|
+
let replaying = false;
|
|
1609
|
+
const observing = (invocation) => {
|
|
1610
|
+
const handle = callHandler(
|
|
1611
|
+
state,
|
|
1612
|
+
cell,
|
|
1613
|
+
descriptors,
|
|
1614
|
+
engine,
|
|
1615
|
+
captures,
|
|
1616
|
+
performed,
|
|
1617
|
+
restored,
|
|
1618
|
+
tree,
|
|
1619
|
+
live,
|
|
1620
|
+
callMs,
|
|
1621
|
+
replaying,
|
|
1622
|
+
emit
|
|
1623
|
+
);
|
|
1624
|
+
const pending = engine.record({
|
|
1625
|
+
name: "steering-before-call",
|
|
1626
|
+
identity: {
|
|
1627
|
+
session: state.session,
|
|
1628
|
+
frame: state.frame,
|
|
1629
|
+
boundary: `steering-before-call:${cell.digest}:${invocation.ordinal}`
|
|
1630
|
+
},
|
|
1631
|
+
success: import_effect.Schema.Boolean,
|
|
1632
|
+
execute: steering.read().pipe(import_effect.Effect.map((queue) => queue.items.some((item) => item.delivery === "steer")))
|
|
1633
|
+
});
|
|
1634
|
+
return pending.pipe(
|
|
1635
|
+
import_effect.Effect.flatMap(
|
|
1636
|
+
(blocked) => blocked ? import_effect.Effect.succeed(
|
|
1637
|
+
(0, import_refusal.refusal)(
|
|
1638
|
+
void 0,
|
|
1639
|
+
"Outside changes are pending; finish this cell and re-read the changed files in the next turn."
|
|
1640
|
+
)
|
|
1641
|
+
) : handle(invocation)
|
|
1642
|
+
),
|
|
1643
|
+
import_effect.Effect.tap(
|
|
1644
|
+
(result) => import_effect.Effect.sync(() => {
|
|
1645
|
+
const rendered = result.outcome === "success" ? JSON.stringify(result.value) : result.message ?? "failed";
|
|
1646
|
+
const ordinal = CallLedger.settled(state.callLedger) + calls.length + 1;
|
|
1647
|
+
const descriptor = descriptors.get(invocation.flow);
|
|
1648
|
+
const probe = result.outcome === "success" ? invalidProbeOf(result.value) : void 0;
|
|
1649
|
+
const measured = performed.has(invocation.ordinal) && result.outcome === "success" && mutatedOf(result.value);
|
|
1650
|
+
const ranAt = performed.has(invocation.ordinal) && invocation.at !== void 0 ? Cell.checkpointOf(invocation.at) : void 0;
|
|
1651
|
+
calls.push({
|
|
1652
|
+
flow: invocation.flow,
|
|
1653
|
+
ok: result.outcome === "success",
|
|
1654
|
+
summary: elide.head(rendered, salvageSummary, salvageRecall),
|
|
1655
|
+
ordinal,
|
|
1656
|
+
mutates: performed.has(invocation.ordinal) && descriptor !== void 0 && mutating(descriptor, invocation.input) || measured,
|
|
1657
|
+
remote: measured,
|
|
1658
|
+
// Every invocation the cell issued, refused ones included: a
|
|
1659
|
+
// refusal is still a question the run has already asked, and
|
|
1660
|
+
// asking it again learns nothing either.
|
|
1661
|
+
signature: signatureOf(invocation.flow, invocation.input, ranAt),
|
|
1662
|
+
subject: signatureOf(invocation.flow, invocation.input),
|
|
1663
|
+
at: ranAt,
|
|
1664
|
+
input: invocation.input,
|
|
1665
|
+
value: result.value,
|
|
1666
|
+
message: result.message,
|
|
1667
|
+
invalidProbe: probe,
|
|
1668
|
+
failing: result.outcome === "success" && probe === void 0 && UnresolvedFailure.failed(result.value),
|
|
1669
|
+
passing: result.outcome === "success" && probe === void 0 && UnresolvedFailure.passed(result.value)
|
|
1670
|
+
});
|
|
1671
|
+
})
|
|
1672
|
+
)
|
|
1673
|
+
);
|
|
1674
|
+
};
|
|
1675
|
+
const minted = [];
|
|
1676
|
+
const mint = minter(state, cell, engine, minted, callMs, emit);
|
|
1677
|
+
const history = yield* import_effect.Effect.serviceOption(CellHistory.CellHistory);
|
|
1678
|
+
yield* import_effect.Option.match(history, {
|
|
1679
|
+
onNone: () => import_effect.Effect.void,
|
|
1680
|
+
onSome: (recorder) => recorder.record(cell.text)
|
|
1681
|
+
});
|
|
1682
|
+
const settled = yield* import_effect.Effect.gen(function* () {
|
|
1683
|
+
for (let attempt = 0; ; attempt++) {
|
|
1684
|
+
const identity = (slot) => ({
|
|
1685
|
+
session: state.session,
|
|
1686
|
+
frame: state.frame,
|
|
1687
|
+
boundary: `cell-frame:${cell.digest}${slot === 0 ? "" : `:attempt:${slot}`}`
|
|
1688
|
+
});
|
|
1689
|
+
let fresh = false;
|
|
1690
|
+
const recorded = yield* engine.record({
|
|
1691
|
+
name: "cell-frame",
|
|
1692
|
+
identity: identity(attempt),
|
|
1693
|
+
success: import_effect.Schema.NullOr(RecordedFrame),
|
|
1694
|
+
execute: import_effect.Effect.sync(() => {
|
|
1695
|
+
fresh = true;
|
|
1696
|
+
return null;
|
|
1697
|
+
})
|
|
1698
|
+
});
|
|
1699
|
+
if (recorded === null && !fresh) continue;
|
|
1700
|
+
if (recorded !== null && recorded.boundary === void 0 && recorded.outcome._tag === "rejected" && recorded.outcome.code === "limit_exceeded") {
|
|
1701
|
+
return yield* import_effect.Effect.fail(
|
|
1702
|
+
new import_HarnessError.HarnessError({
|
|
1703
|
+
code: "incompatible_journal",
|
|
1704
|
+
message: "Cannot reconstruct a limited frame without its recorded execution frontier"
|
|
1705
|
+
})
|
|
1706
|
+
);
|
|
1707
|
+
}
|
|
1708
|
+
const replay = recorded !== null && recorded.boundary?.terminal === "timeout" ? { boundary: recorded.boundary, outcome: yield* Cell.decodeOutcome(recorded.outcome) } : void 0;
|
|
1709
|
+
replaying = replay !== void 0;
|
|
1710
|
+
const guarded = recorded === null && engine.guard !== void 0 ? engine.guard : void 0;
|
|
1711
|
+
const subject = JSON.stringify({
|
|
1712
|
+
session: state.session,
|
|
1713
|
+
frame: state.frame,
|
|
1714
|
+
boundary: `cell-frame:${cell.digest}`
|
|
1715
|
+
});
|
|
1716
|
+
if (guarded !== void 0) yield* guarded.admit(subject);
|
|
1717
|
+
const frame2 = yield* realm.evaluate({
|
|
1718
|
+
cell,
|
|
1719
|
+
// The boundary parse is the only one this cell gets: the realm runs
|
|
1720
|
+
// what it compiled rather than parsing the same text again.
|
|
1721
|
+
program: produced.program,
|
|
1722
|
+
frame: state.frame,
|
|
1723
|
+
// A judged run's catalog can change without a refresh: the run-start
|
|
1724
|
+
// relevance reading withholds flows and a call restores them.
|
|
1725
|
+
flows: input.refreshFlows === void 0 && input.judged !== true ? void 0 : projections,
|
|
1726
|
+
call: observing,
|
|
1727
|
+
mint,
|
|
1728
|
+
replay,
|
|
1729
|
+
// Settlements are bounded inside their recorded boundaries.
|
|
1730
|
+
bounded: true
|
|
1731
|
+
});
|
|
1732
|
+
if (recorded !== null) return recorded;
|
|
1733
|
+
const outcome = yield* Cell.decodeOutcome(frame2.outcome);
|
|
1734
|
+
if (guarded !== void 0 && frame2.boundary?.terminal === "timeout" && outcome._tag === "rejected" && outcome.code === "limit_exceeded") {
|
|
1735
|
+
yield* guarded.trip({ source: "cell", subject, limitMillis: totalMs, message: outcome.message });
|
|
1736
|
+
}
|
|
1737
|
+
return yield* engine.record({
|
|
1738
|
+
name: "cell-frame",
|
|
1739
|
+
identity: identity(attempt + 1),
|
|
1740
|
+
success: RecordedFrame,
|
|
1741
|
+
execute: import_effect.Effect.succeed({ ...frame2, outcome })
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
});
|
|
1745
|
+
return { frame: settled, calls, minted, captures, restored };
|
|
1746
|
+
});
|
|
1747
|
+
const completionTask = (task, instructions) => instructions === "" ? task : `${elide.middle(task, 3584, "the run record has the whole task")}
|
|
1748
|
+
|
|
1749
|
+
The person now says:
|
|
1750
|
+
|
|
1751
|
+
Later instructions accepted during this run, oldest first. Apply these changes to the task above; later changes take precedence:
|
|
1752
|
+
|
|
1753
|
+
${instructions}`;
|
|
1754
|
+
const drain = (settling, wouldIdle) => import_effect.Effect.gen(function* () {
|
|
1755
|
+
const { boundary, state } = settling;
|
|
1756
|
+
const drained = yield* settling.engine.record({
|
|
1757
|
+
name: "steering-drain",
|
|
1758
|
+
identity: { session: state.session, frame: state.frame, boundary: `steering-drain:${boundary}` },
|
|
1759
|
+
success: Steering.DrainRecord,
|
|
1760
|
+
execute: Frame.hasNextFrame(state) ? settling.steering.drain({ boundary: `${state.frame}:${boundary}`, wouldIdle }).pipe(
|
|
1761
|
+
import_effect.Effect.map(Steering.drainRecord),
|
|
1762
|
+
// The supervisor's nudge rides the same recorded drain, in a field
|
|
1763
|
+
// of its own and only at a boundary the run continues through: a
|
|
1764
|
+
// boundary that would idle is a completion or the last frame, and a
|
|
1765
|
+
// nudge there would turn a finished answer into a follow-up. Inside
|
|
1766
|
+
// the record, so a replayed boundary delivers what it delivered the
|
|
1767
|
+
// first time. Apart from `inserts`, because those are the person's
|
|
1768
|
+
// words and the completion brake reads them as the task; a nudge is
|
|
1769
|
+
// not. See `internal/supervision`.
|
|
1770
|
+
import_effect.Effect.flatMap(
|
|
1771
|
+
(record) => wouldIdle ? import_effect.Effect.succeed(record) : settling.supervision.take(state.frame, {
|
|
1772
|
+
ledger: state.monitorLedger,
|
|
1773
|
+
shown: state.memoryShown,
|
|
1774
|
+
deliver: settling.input.judged ?? false
|
|
1775
|
+
}).pipe(
|
|
1776
|
+
import_effect.Effect.map((taken) => ({
|
|
1777
|
+
...record,
|
|
1778
|
+
...taken.messages.length === 0 ? {} : { supervisor: taken.messages },
|
|
1779
|
+
...taken.memory.length === 0 ? {} : { memory: taken.memory },
|
|
1780
|
+
...taken.monitor === void 0 ? {} : { monitor: taken.monitor },
|
|
1781
|
+
...taken.suppressed.length === 0 ? {} : { suppressed: taken.suppressed },
|
|
1782
|
+
...taken.ledger === void 0 ? {} : { monitorLedger: taken.ledger },
|
|
1783
|
+
...taken.marks.length === 0 ? {} : { marks: taken.marks },
|
|
1784
|
+
...taken.compact.length === 0 ? {} : { compact: taken.compact }
|
|
1785
|
+
}))
|
|
1786
|
+
)
|
|
1787
|
+
),
|
|
1788
|
+
// Executed, not replayed: the one fact that says this frame is the
|
|
1789
|
+
// run's present rather than its past.
|
|
1790
|
+
import_effect.Effect.tap(() => import_effect.Effect.sync(() => void (settling.live.value = true)))
|
|
1791
|
+
) : import_effect.Effect.succeed({ inserts: [], seatChanges: [], queued: false })
|
|
1792
|
+
});
|
|
1793
|
+
yield* settling.emit(
|
|
1794
|
+
new AgentEvent.SteeringDrained({
|
|
1795
|
+
eventType: eventType.steeringDrained,
|
|
1796
|
+
messages: drained.inserts,
|
|
1797
|
+
...drained.supervisor === void 0 || drained.supervisor.length === 0 ? {} : { supervisor: drained.supervisor },
|
|
1798
|
+
...drained.monitor === void 0 ? {} : { monitor: drained.monitor },
|
|
1799
|
+
...drained.suppressed === void 0 ? {} : { suppressed: drained.suppressed },
|
|
1800
|
+
...drained.memory === void 0 ? {} : { memory: drained.memory }
|
|
1801
|
+
})
|
|
1802
|
+
);
|
|
1803
|
+
if (settling.live.value && !wouldIdle) yield* settling.offer;
|
|
1804
|
+
return drained;
|
|
1805
|
+
});
|
|
1806
|
+
const close = (settling, outcome, output = budgetMessage(settling.state)) => import_effect.Effect.gen(function* () {
|
|
1807
|
+
yield* settling.emit(
|
|
1808
|
+
new AgentEvent.TurnClosed({
|
|
1809
|
+
eventType: eventType.turnClosed,
|
|
1810
|
+
stopReason: settling.answer.stopReason,
|
|
1811
|
+
outcome
|
|
1812
|
+
})
|
|
1813
|
+
);
|
|
1814
|
+
if (outcome === "resolved") {
|
|
1815
|
+
yield* settling.emit(
|
|
1816
|
+
new AgentEvent.Resolved({
|
|
1817
|
+
eventType: eventType.resolved,
|
|
1818
|
+
message: import_model.ModelRequest.Message.assistant(output, { stopReason: "stop" })
|
|
1819
|
+
})
|
|
1820
|
+
);
|
|
1821
|
+
}
|
|
1822
|
+
});
|
|
1823
|
+
const finish = (settling, step) => close(settling, step._tag === "Done" ? "resolved" : step._tag === "Suspend" ? "suspended" : "continue").pipe(
|
|
1824
|
+
import_effect.Effect.as(step)
|
|
1825
|
+
);
|
|
1826
|
+
const continuing = (settling, contextWindow, person, changes) => {
|
|
1827
|
+
const transcripts = (window) => window.segments.filter((segment) => segment.kind === "transcript").length;
|
|
1828
|
+
const frame2 = settling.state.frame;
|
|
1829
|
+
const reasks = transcripts(contextWindow) - transcripts(settling.state.contextWindow) - 1;
|
|
1830
|
+
const { segmentFacts = settling.state.segmentFacts, ...rest } = changes;
|
|
1831
|
+
const next = advance(settling.state, {
|
|
1832
|
+
frame: frame2 + 1,
|
|
1833
|
+
interventions: 0,
|
|
1834
|
+
// What this frame's section listed; see `frozen`.
|
|
1835
|
+
ledgerShown: CallLedger.settled(settling.state.callLedger),
|
|
1836
|
+
...settling.facts,
|
|
1837
|
+
contextWindow,
|
|
1838
|
+
segmentFacts: [
|
|
1839
|
+
...segmentFacts,
|
|
1840
|
+
...new Array(reasks).fill({ frame: frame2, person: false, mutated: false, checks: [] }),
|
|
1841
|
+
{ frame: frame2, person, ...settling.written }
|
|
1842
|
+
],
|
|
1843
|
+
...rest
|
|
1844
|
+
});
|
|
1845
|
+
return {
|
|
1846
|
+
_tag: "Continue",
|
|
1847
|
+
state: advance(next, { contextWindow: withSection(next.contextWindow, next), sectioned: true })
|
|
1848
|
+
};
|
|
1849
|
+
};
|
|
1850
|
+
const delivered = (drained) => [
|
|
1851
|
+
...drained.supervisor ?? [],
|
|
1852
|
+
...drained.inserts
|
|
1853
|
+
];
|
|
1854
|
+
const resumed = (settling, drained, changes = {}, text = settling.printed, echo = liveCellEcho, ask) => import_effect.Effect.gen(function* () {
|
|
1855
|
+
const { state } = settling;
|
|
1856
|
+
const settings = yield* steered(state, drained.seatChanges, settling.input.contextWindowTokensFor);
|
|
1857
|
+
const inserts = delivered(drained);
|
|
1858
|
+
const messages = ask === void 0 ? [import_model.ModelRequest.Message.user(text), ...inserts] : inserts.length === 0 ? [import_model.ModelRequest.Message.user(text === "" ? ask : `${text}
|
|
1859
|
+
|
|
1860
|
+
${ask}`)] : [...text === "" ? [] : [import_model.ModelRequest.Message.user(text)], ...inserts, import_model.ModelRequest.Message.user(ask)];
|
|
1861
|
+
const context = appended(settling.contextWindow, settling.answer, messages, echo);
|
|
1862
|
+
return continuing(settling, windowOn(state, settings.seat, context), drained.inserts.length > 0, {
|
|
1863
|
+
...settings,
|
|
1864
|
+
...shownAfter(state, drained),
|
|
1865
|
+
...ledgerAfter(drained),
|
|
1866
|
+
...marksAfter(state, drained),
|
|
1867
|
+
...changes
|
|
1868
|
+
});
|
|
1869
|
+
});
|
|
1870
|
+
const observe = (settling, note, changes = {}, echo = liveCellEcho) => import_effect.Effect.gen(function* () {
|
|
1871
|
+
const next = Frame.hasNextFrame(settling.state);
|
|
1872
|
+
const drained = yield* drain(settling, !next);
|
|
1873
|
+
return next ? yield* resumed(settling, drained, changes, settling.printed, echo, note) : { _tag: "Done" };
|
|
1874
|
+
});
|
|
1875
|
+
const frame = (input, engine, sandbox, realm, steering, emit, readCompletion, supervision, taskOf) => import_effect.Effect.gen(function* () {
|
|
1876
|
+
const compactedState = yield* compacted(input.state, engine, emit, input.judged ?? false, taskOf);
|
|
1877
|
+
const sectioned = compactedState.sectioned ? import_effect.Result.succeed(compactedState.contextWindow) : frozen(compactedState.contextWindow, compactedState);
|
|
1878
|
+
const state = sectioned._tag === "Success" ? advance(compactedState, { contextWindow: sectioned.success, sectioned: true }) : compactedState;
|
|
1879
|
+
yield* emit(
|
|
1880
|
+
new AgentEvent.TurnOpened({
|
|
1881
|
+
eventType: eventType.turnOpened,
|
|
1882
|
+
seat: state.seat,
|
|
1883
|
+
modelParams: state.modelParams,
|
|
1884
|
+
activeToolNames: [],
|
|
1885
|
+
contextDigest: state.contextWindow.digest
|
|
1886
|
+
})
|
|
1887
|
+
);
|
|
1888
|
+
if (sectioned._tag === "Failure") return yield* import_effect.Effect.fail(sectioned.failure);
|
|
1889
|
+
const { answer, cell: sealed, contextWindow } = yield* seal(state, engine, emit);
|
|
1890
|
+
const settling = (boundary, printed2, facts2, written2, offer = import_effect.Effect.void) => ({
|
|
1891
|
+
input,
|
|
1892
|
+
state,
|
|
1893
|
+
engine,
|
|
1894
|
+
steering,
|
|
1895
|
+
supervision,
|
|
1896
|
+
offer,
|
|
1897
|
+
live: { value: false },
|
|
1898
|
+
emit,
|
|
1899
|
+
contextWindow,
|
|
1900
|
+
answer,
|
|
1901
|
+
boundary,
|
|
1902
|
+
printed: printed2,
|
|
1903
|
+
facts: facts2,
|
|
1904
|
+
written: written2
|
|
1905
|
+
});
|
|
1906
|
+
if (sealed._tag === "Failure") {
|
|
1907
|
+
const rejection = sealed.failure;
|
|
1908
|
+
yield* emit(
|
|
1909
|
+
new AgentEvent.CellSettled({
|
|
1910
|
+
eventType: eventType.cellSettled,
|
|
1911
|
+
cell: "",
|
|
1912
|
+
outcome: rejection
|
|
1913
|
+
})
|
|
1914
|
+
);
|
|
1915
|
+
const rejectedFrames = state.readOnlyFrames + 1;
|
|
1916
|
+
if (state.readOnlyCap > 0 && rejectedFrames >= state.readOnlyCap * 2) {
|
|
1917
|
+
return yield* readOnlyCapFailure(state.readOnlyCap, rejectedFrames);
|
|
1918
|
+
}
|
|
1919
|
+
const rejected = settling(contextWindow.digest, "", {
|
|
1920
|
+
truncatedOutputs: TruncatedOutput.retain(state.truncatedOutputs),
|
|
1921
|
+
readOnlyFrames: rejectedFrames
|
|
1922
|
+
}, { mutated: false, checks: [] });
|
|
1923
|
+
const step = yield* observe(rejected, rejection.message, {}, deadCellEcho);
|
|
1924
|
+
return yield* finish(rejected, step);
|
|
1925
|
+
}
|
|
1926
|
+
const cell = sealed.success.source;
|
|
1927
|
+
yield* emit(
|
|
1928
|
+
new AgentEvent.CellProduced({
|
|
1929
|
+
eventType: eventType.cellProduced,
|
|
1930
|
+
cell,
|
|
1931
|
+
blocks: sealed.success.blocks
|
|
1932
|
+
})
|
|
1933
|
+
);
|
|
1934
|
+
const pendingBeforeTool = yield* engine.record({
|
|
1935
|
+
name: "steering-before-tool",
|
|
1936
|
+
identity: { session: state.session, frame: state.frame, boundary: `steering-before-tool:${cell.digest}` },
|
|
1937
|
+
success: import_effect.Schema.Boolean,
|
|
1938
|
+
execute: steering.read().pipe(import_effect.Effect.map((queue) => queue.items.some((item) => item.delivery === "steer")))
|
|
1939
|
+
});
|
|
1940
|
+
if (pendingBeforeTool) {
|
|
1941
|
+
if (!Frame.hasNextFrame(state)) {
|
|
1942
|
+
return yield* new import_HarnessError.HarnessError({
|
|
1943
|
+
code: "engine_failed",
|
|
1944
|
+
message: "Outside changes require another model turn before tools can run"
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1947
|
+
const beforeTool = settling(`before-tool:${cell.digest}`, "", {}, { mutated: false, checks: [] });
|
|
1948
|
+
const drained2 = yield* drain(beforeTool, false);
|
|
1949
|
+
if (carries(drained2)) {
|
|
1950
|
+
const step = yield* resumed(beforeTool, drained2, {}, "", deadCellEcho);
|
|
1951
|
+
return yield* finish(beforeTool, step);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
const opened = state.workspace !== void 0 && (import_effect.Option.isNone(state.workspace) || !state.workspace.value.complete) ? state.workspace : yield* witness(engine, state, cell.digest, "open");
|
|
1955
|
+
const ran = yield* evaluate(
|
|
1956
|
+
input,
|
|
1957
|
+
state,
|
|
1958
|
+
sealed.success,
|
|
1959
|
+
engine,
|
|
1960
|
+
sandbox,
|
|
1961
|
+
realm,
|
|
1962
|
+
opened,
|
|
1963
|
+
steering,
|
|
1964
|
+
emit
|
|
1965
|
+
);
|
|
1966
|
+
const outcome = yield* Cell.decodeOutcome(ran.frame.outcome);
|
|
1967
|
+
const printed = (0, import_printsObservation.printsObservation)(ran.frame.prints);
|
|
1968
|
+
yield* emit(
|
|
1969
|
+
new AgentEvent.CellPrinted({
|
|
1970
|
+
eventType: eventType.cellPrinted,
|
|
1971
|
+
cell: cell.digest,
|
|
1972
|
+
text: ran.frame.prints
|
|
1973
|
+
})
|
|
1974
|
+
);
|
|
1975
|
+
const closed = import_effect.Option.isSome(opened) && !opened.value.complete ? opened : yield* witness(engine, state, cell.digest, "close");
|
|
1976
|
+
yield* emit(
|
|
1977
|
+
new AgentEvent.CellSettled({
|
|
1978
|
+
eventType: eventType.cellSettled,
|
|
1979
|
+
cell: cell.digest,
|
|
1980
|
+
outcome,
|
|
1981
|
+
...ran.frame.boundary === void 0 ? {} : { boundary: ran.frame.boundary }
|
|
1982
|
+
})
|
|
1983
|
+
);
|
|
1984
|
+
const accounting = Frame.account({
|
|
1985
|
+
state,
|
|
1986
|
+
calls: ran.calls,
|
|
1987
|
+
opened,
|
|
1988
|
+
closed,
|
|
1989
|
+
minted: ran.minted,
|
|
1990
|
+
bindings: ran.frame.bindings,
|
|
1991
|
+
captures: ran.captures,
|
|
1992
|
+
source: cell.text
|
|
1993
|
+
});
|
|
1994
|
+
yield* emit(accounting.observed);
|
|
1995
|
+
const written = Supervisor.prose(assistantText(answer));
|
|
1996
|
+
const { mutated } = accounting;
|
|
1997
|
+
const { readOnlyFrames } = accounting.facts;
|
|
1998
|
+
const failed = ran.calls.length > 0 && ran.calls.every((call) => !call.ok || call.failing);
|
|
1999
|
+
const failure = ran.calls.some((call) => call.ok && !call.failing) ? "" : outcome._tag === "raised" ? `cell threw ${outcome.name}: ${outcome.message}` : failed ? ran.calls.map((call) => `${call.flow}: ${call.summary}`).join("; ") : "";
|
|
2000
|
+
const failureKey = failure.slice(0, 1e3);
|
|
2001
|
+
const failureFrames = failureKey === "" ? 0 : failureKey === state.failureKey ? state.failureFrames + 1 : 1;
|
|
2002
|
+
const facts = ran.restored.size === 0 ? accounting.facts : {
|
|
2003
|
+
...accounting.facts,
|
|
2004
|
+
withheldFlows: state.withheldFlows.filter((name) => !ran.restored.has(name))
|
|
2005
|
+
};
|
|
2006
|
+
const { capped: skillsCapped, ...offered } = Supervision.catalog(input.flows, accounting.facts.callLedger);
|
|
2007
|
+
const exit = settling(
|
|
2008
|
+
cell.digest,
|
|
2009
|
+
printed,
|
|
2010
|
+
{ ...facts, failureFrames, failureKey },
|
|
2011
|
+
{ mutated, checks: accounting.frameChecks.map((check) => check.label) },
|
|
2012
|
+
supervision.offer({
|
|
2013
|
+
frame: state.frame,
|
|
2014
|
+
digest: cell.digest,
|
|
2015
|
+
current: {
|
|
2016
|
+
frame: state.frame,
|
|
2017
|
+
cell: Supervisor.head(cell.text),
|
|
2018
|
+
prose: Supervisor.head(written),
|
|
2019
|
+
printed: Supervisor.tail(ran.frame.prints),
|
|
2020
|
+
transition: outcome._tag === "settled" ? outcome.transition._tag : outcome._tag,
|
|
2021
|
+
mutated
|
|
2022
|
+
},
|
|
2023
|
+
snapshot: {
|
|
2024
|
+
task: Judgement.task(taskOf(contextWindow)),
|
|
2025
|
+
signals: Supervision.signals(state, accounting.facts, accounting.workspaceDigest, accounting.observed.paths),
|
|
2026
|
+
...offered
|
|
2027
|
+
},
|
|
2028
|
+
shown: state.memoryShown,
|
|
2029
|
+
recent: Supervisor.head(written),
|
|
2030
|
+
skillsCapped,
|
|
2031
|
+
unmarked: input.judged === true ? unmarked(state) : [],
|
|
2032
|
+
failing: accounting.facts.checks.filter((check) => check.failing).map((check) => check.label)
|
|
2033
|
+
})
|
|
2034
|
+
);
|
|
2035
|
+
const cap = state.readOnlyCap;
|
|
2036
|
+
if (outcome._tag !== "settled") {
|
|
2037
|
+
if (state.pendingReadOnlyDemand !== void 0 && mutated) {
|
|
2038
|
+
yield* emit(
|
|
2039
|
+
new AgentEvent.ReadOnlyDemanded({
|
|
2040
|
+
eventType: eventType.readOnlyDemanded,
|
|
2041
|
+
streak: state.pendingReadOnlyDemand.streak,
|
|
2042
|
+
cap: state.pendingReadOnlyDemand.cap,
|
|
2043
|
+
nextFrame: state.frame,
|
|
2044
|
+
nextAction: "write"
|
|
2045
|
+
})
|
|
2046
|
+
);
|
|
2047
|
+
}
|
|
2048
|
+
if (cap > 0 && readOnlyFrames >= cap * 2) {
|
|
2049
|
+
return yield* readOnlyCapFailure(cap, readOnlyFrames);
|
|
2050
|
+
}
|
|
2051
|
+
const salvage = ran.calls.length === 0 ? "" : `
|
|
2052
|
+
Calls this cell already completed (their results are durable, and each one is still under the name your cell bound it to \u2014 read the name instead of redoing the work):
|
|
2053
|
+
${ran.calls.map(
|
|
2054
|
+
(call) => `- ${call.ordinal}. ${clip(call.flow, CallLedger.width)} -> ${call.ok ? "ok" : "FAILED"}: ${call.summary}`
|
|
2055
|
+
).join("\n")}`;
|
|
2056
|
+
const alert = accounting.probeNotice === void 0 ? "" : `
|
|
2057
|
+
|
|
2058
|
+
${accounting.probeNotice}`;
|
|
2059
|
+
const missed = outcome._tag === "raised" ? bindingPathMiss(outcome.message, ran.frame.bindings) : void 0;
|
|
2060
|
+
const note = outcome._tag === "raised" ? `The cell threw ${outcome.name}: ${outcome.message}. Emit a corrected cell.${missed === void 0 ? "" : `
|
|
2061
|
+
${missed}`}${salvage}${alert}` : `${outcome.message}${salvage}${alert}`;
|
|
2062
|
+
const step = yield* observe(exit, note);
|
|
2063
|
+
return yield* finish(exit, step);
|
|
2064
|
+
}
|
|
2065
|
+
const transition = outcome.transition;
|
|
2066
|
+
yield* emit(
|
|
2067
|
+
new AgentEvent.TransitionApplied({
|
|
2068
|
+
eventType: eventType.transitionApplied,
|
|
2069
|
+
transition
|
|
2070
|
+
})
|
|
2071
|
+
);
|
|
2072
|
+
if (transition._tag === "park") {
|
|
2073
|
+
if (state.pendingReadOnlyDemand !== void 0) {
|
|
2074
|
+
yield* emit(
|
|
2075
|
+
new AgentEvent.ReadOnlyDemanded({
|
|
2076
|
+
eventType: eventType.readOnlyDemanded,
|
|
2077
|
+
streak: state.pendingReadOnlyDemand.streak,
|
|
2078
|
+
cap: state.pendingReadOnlyDemand.cap,
|
|
2079
|
+
nextFrame: state.frame,
|
|
2080
|
+
nextAction: mutated ? "write" : "park"
|
|
2081
|
+
})
|
|
2082
|
+
);
|
|
2083
|
+
}
|
|
2084
|
+
if (!state.approvalChannel) {
|
|
2085
|
+
return yield* new import_HarnessError.HarnessError({
|
|
2086
|
+
code: "approval_unavailable",
|
|
2087
|
+
message: `The run requires an answer but has no approval channel: ${transition.message}`
|
|
2088
|
+
});
|
|
2089
|
+
}
|
|
2090
|
+
if (!Frame.hasNextFrame(state)) {
|
|
2091
|
+
return yield* finish(exit, {
|
|
2092
|
+
_tag: "Suspend",
|
|
2093
|
+
reason: new EngineLike.SuspendReason({
|
|
2094
|
+
code: transition.reason,
|
|
2095
|
+
message: transition.message
|
|
2096
|
+
})
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
const answered = yield* import_effect.Effect.gen(function* () {
|
|
2100
|
+
for (let rung = 0; ; rung++) {
|
|
2101
|
+
const drained2 = yield* steering.drain({
|
|
2102
|
+
boundary: `${state.frame}:${cell.digest}:park:${rung}`,
|
|
2103
|
+
// A park IS the run going idle, which is the condition a queued
|
|
2104
|
+
// follow-up was admitted to wait for. The continue path passes
|
|
2105
|
+
// false because a continuing run is not idle; this is the boundary
|
|
2106
|
+
// that owes those messages their delivery.
|
|
2107
|
+
wouldIdle: true,
|
|
2108
|
+
// What the park asks, so a source with a person on the other end
|
|
2109
|
+
// can put the question to them and answer this drain.
|
|
2110
|
+
park: { reason: transition.reason, message: transition.message }
|
|
2111
|
+
});
|
|
2112
|
+
const record = Steering.drainRecord(drained2);
|
|
2113
|
+
if (carries(record) || !drained2.duplicate) return record;
|
|
2114
|
+
}
|
|
2115
|
+
});
|
|
2116
|
+
if (carries(answered)) {
|
|
2117
|
+
yield* emit(
|
|
2118
|
+
new AgentEvent.SteeringDrained({
|
|
2119
|
+
eventType: eventType.steeringDrained,
|
|
2120
|
+
messages: answered.inserts
|
|
2121
|
+
})
|
|
2122
|
+
);
|
|
2123
|
+
const step = yield* resumed(exit, answered, {
|
|
2124
|
+
pendingReadOnlyDemand: void 0,
|
|
2125
|
+
readOnlyFrames: state.readOnlyFrames
|
|
2126
|
+
});
|
|
2127
|
+
return yield* finish(exit, step);
|
|
2128
|
+
}
|
|
2129
|
+
return yield* finish(exit, {
|
|
2130
|
+
_tag: "Suspend",
|
|
2131
|
+
reason: new EngineLike.SuspendReason({
|
|
2132
|
+
code: transition.reason,
|
|
2133
|
+
message: transition.message
|
|
2134
|
+
})
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
if (state.pendingReadOnlyDemand !== void 0) {
|
|
2138
|
+
yield* emit(
|
|
2139
|
+
new AgentEvent.ReadOnlyDemanded({
|
|
2140
|
+
eventType: eventType.readOnlyDemanded,
|
|
2141
|
+
streak: state.pendingReadOnlyDemand.streak,
|
|
2142
|
+
cap: state.pendingReadOnlyDemand.cap,
|
|
2143
|
+
nextFrame: state.frame,
|
|
2144
|
+
nextAction: mutated ? "write" : transition._tag === "continue" && (transition.justification ?? "").trim().length > 0 ? "justification" : "read-only"
|
|
2145
|
+
})
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
if (cap > 0 && readOnlyFrames >= cap * 2) {
|
|
2149
|
+
return yield* readOnlyCapFailure(cap, readOnlyFrames);
|
|
2150
|
+
}
|
|
2151
|
+
const drained = yield* drain(exit, transition._tag === "complete" || !Frame.hasNextFrame(state));
|
|
2152
|
+
if (transition._tag === "complete" && carries(drained)) {
|
|
2153
|
+
const step = yield* resumed(
|
|
2154
|
+
exit,
|
|
2155
|
+
drained,
|
|
2156
|
+
{ bouncedCompletion: transition.output },
|
|
2157
|
+
`${printed}
|
|
2158
|
+
|
|
2159
|
+
The completed answer before this follow-up:
|
|
2160
|
+
${transition.output}`
|
|
2161
|
+
);
|
|
2162
|
+
return yield* finish(exit, step);
|
|
2163
|
+
}
|
|
2164
|
+
if (transition._tag === "complete" && input.output !== void 0 && state.outputDemands < input.output.cap && Frame.handBackRoom(state, readOnlyFrames)) {
|
|
2165
|
+
const check = input.output.check;
|
|
2166
|
+
const note = yield* engine.record({
|
|
2167
|
+
name: "output-judgement",
|
|
2168
|
+
identity: {
|
|
2169
|
+
session: state.session,
|
|
2170
|
+
frame: state.frame,
|
|
2171
|
+
boundary: `output-judgement:${cell.digest}`
|
|
2172
|
+
},
|
|
2173
|
+
success: import_effect.Schema.NullOr(import_effect.Schema.String),
|
|
2174
|
+
execute: import_effect.Effect.map(
|
|
2175
|
+
import_effect.Effect.suspend(() => check(transition.output, state.outputDemands, transition.value)),
|
|
2176
|
+
(refused) => refused ?? null
|
|
2177
|
+
)
|
|
2178
|
+
});
|
|
2179
|
+
if (note !== null) {
|
|
2180
|
+
if (exit.live.value) yield* exit.offer;
|
|
2181
|
+
yield* emit(
|
|
2182
|
+
new AgentEvent.OutputDemanded({
|
|
2183
|
+
eventType: eventType.outputDemanded,
|
|
2184
|
+
note,
|
|
2185
|
+
nextFrame: state.frame + 1
|
|
2186
|
+
})
|
|
2187
|
+
);
|
|
2188
|
+
yield* close(exit, "continue");
|
|
2189
|
+
return continuing(
|
|
2190
|
+
exit,
|
|
2191
|
+
appended(
|
|
2192
|
+
contextWindow,
|
|
2193
|
+
answer,
|
|
2194
|
+
[import_model.ModelRequest.Message.user(printed), import_model.ModelRequest.Message.user(note)],
|
|
2195
|
+
liveCellEcho
|
|
2196
|
+
),
|
|
2197
|
+
false,
|
|
2198
|
+
{
|
|
2199
|
+
interventions: 1,
|
|
2200
|
+
pendingReadOnlyDemand: void 0,
|
|
2201
|
+
outputDemands: state.outputDemands + 1,
|
|
2202
|
+
// An answer the host could not read is not worth restoring.
|
|
2203
|
+
bouncedCompletion: void 0
|
|
2204
|
+
}
|
|
2205
|
+
);
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
if (transition._tag === "complete") {
|
|
2209
|
+
const services = yield* import_effect.Effect.context();
|
|
2210
|
+
const judged = yield* engine.record({
|
|
2211
|
+
name: "completion-judgement",
|
|
2212
|
+
identity: {
|
|
2213
|
+
session: state.session,
|
|
2214
|
+
frame: state.frame,
|
|
2215
|
+
boundary: `completion-judgement:${cell.digest}`
|
|
2216
|
+
},
|
|
2217
|
+
success: RecordedCompletion,
|
|
2218
|
+
// The claim brake's reading, whole and by sentence, is paid model
|
|
2219
|
+
// work: the run's budget accounts it like any sealed step (#2681). A
|
|
2220
|
+
// bounce carries the reading as its demand and leaves `observed` empty.
|
|
2221
|
+
usage: (judgement) => (0, import_paidUsage.paidUsage)([
|
|
2222
|
+
(judgement.observed ?? (judgement.demand?.event._tag === "claim-demanded" ? judgement.demand.event : null))?.usage
|
|
2223
|
+
]),
|
|
2224
|
+
// A replay uses the entire original decision. Re-evaluating even an
|
|
2225
|
+
// accepted claim can invent a demand and execute additional work.
|
|
2226
|
+
execute: Frame.judgeCompletion(
|
|
2227
|
+
state,
|
|
2228
|
+
accounting,
|
|
2229
|
+
contextWindow,
|
|
2230
|
+
transition.output,
|
|
2231
|
+
readCompletion
|
|
2232
|
+
).pipe(
|
|
2233
|
+
import_effect.Effect.provideContext(services),
|
|
2234
|
+
import_effect.Effect.map((judgement) => ({
|
|
2235
|
+
observed: judgement.observed ?? null,
|
|
2236
|
+
demand: judgement.demand ?? null,
|
|
2237
|
+
unproven: judgement.unproven ?? null,
|
|
2238
|
+
decision: judgement.decision ?? null,
|
|
2239
|
+
sentenceDecision: judgement.sentenceDecision ?? null,
|
|
2240
|
+
unfinishedDecision: judgement.unfinishedDecision ?? null
|
|
2241
|
+
}))
|
|
2242
|
+
)
|
|
2243
|
+
}).pipe(import_effect.Effect.map((judgement) => ({
|
|
2244
|
+
observed: judgement.observed ?? void 0,
|
|
2245
|
+
demand: judgement.demand ?? void 0,
|
|
2246
|
+
unproven: judgement.unproven ?? void 0,
|
|
2247
|
+
decision: judgement.decision ?? void 0,
|
|
2248
|
+
sentenceDecision: judgement.sentenceDecision ?? void 0,
|
|
2249
|
+
unfinishedDecision: judgement.unfinishedDecision ?? void 0
|
|
2250
|
+
})));
|
|
2251
|
+
if (judged.observed !== void 0) yield* emit(judged.observed);
|
|
2252
|
+
if (judged.decision !== void 0) yield* emit(judged.decision);
|
|
2253
|
+
if (judged.sentenceDecision !== void 0) yield* emit(judged.sentenceDecision);
|
|
2254
|
+
if (judged.unfinishedDecision !== void 0) yield* emit(judged.unfinishedDecision);
|
|
2255
|
+
if (judged.unproven !== void 0) return yield* import_effect.Effect.fail(judged.unproven);
|
|
2256
|
+
const demanded = judged.demand;
|
|
2257
|
+
if (demanded !== void 0) {
|
|
2258
|
+
if (exit.live.value) yield* exit.offer;
|
|
2259
|
+
yield* emit(demanded.event);
|
|
2260
|
+
yield* close(exit, "continue");
|
|
2261
|
+
const demandedWindow = demanded.event._tag === "unobserved-demanded" ? appended(
|
|
2262
|
+
contextWindow,
|
|
2263
|
+
answer,
|
|
2264
|
+
[import_model.ModelRequest.Message.user(printed), import_model.ModelRequest.Message.user(demanded.note)],
|
|
2265
|
+
liveCellEcho
|
|
2266
|
+
) : observedOn(contextWindow, answer, demanded.note, liveCellEcho);
|
|
2267
|
+
return continuing(exit, demandedWindow, false, {
|
|
2268
|
+
// The note is the ask this frame appended; the run's memory goes
|
|
2269
|
+
// above it. See `frozen`.
|
|
2270
|
+
interventions: 1,
|
|
2271
|
+
pendingReadOnlyDemand: void 0,
|
|
2272
|
+
...demanded.spent,
|
|
2273
|
+
// The answer the demand is taking away, kept so it cannot be lost.
|
|
2274
|
+
// A frame was reserved for the run to answer in, but nothing makes
|
|
2275
|
+
// that frame end in a completion, and a run that spends it and
|
|
2276
|
+
// then runs out of budget would end on the budget notice with its
|
|
2277
|
+
// own answer discarded. See {@link budgetMessage}.
|
|
2278
|
+
//
|
|
2279
|
+
// A claim the brake read and found unsupported is not kept: the
|
|
2280
|
+
// budget notice would hand back the very sentence the brake
|
|
2281
|
+
// refused. See `Frame.CompletionDemand.keeps`.
|
|
2282
|
+
bouncedCompletion: demanded.keeps ? transition.output : void 0,
|
|
2283
|
+
// The frame this demand was handed to, which is the frame that
|
|
2284
|
+
// gets to answer it without being judged again. See
|
|
2285
|
+
// {@link State.demandedFrame}.
|
|
2286
|
+
demandedFrame: state.frame + 1
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
yield* close(
|
|
2290
|
+
exit,
|
|
2291
|
+
"resolved",
|
|
2292
|
+
FailedCall.state(
|
|
2293
|
+
transition.output,
|
|
2294
|
+
FailedCall.find(accounting.calls, transition.output, accounting.source)
|
|
2295
|
+
)
|
|
2296
|
+
);
|
|
2297
|
+
return { _tag: "Done" };
|
|
2298
|
+
}
|
|
2299
|
+
if (!Frame.hasNextFrame(state)) {
|
|
2300
|
+
yield* close(exit, "resolved");
|
|
2301
|
+
return { _tag: "Done" };
|
|
2302
|
+
}
|
|
2303
|
+
yield* close(exit, "continue");
|
|
2304
|
+
const { contextWindowTokens, modelCallMs, modelParams, seat } = yield* steered(
|
|
2305
|
+
state,
|
|
2306
|
+
drained.seatChanges,
|
|
2307
|
+
input.contextWindowTokensFor
|
|
2308
|
+
);
|
|
2309
|
+
const disciplined = Frame.discipline(state, accounting, transition.justification);
|
|
2310
|
+
for (const event of disciplined.events) yield* emit(event);
|
|
2311
|
+
const context = appended(
|
|
2312
|
+
contextWindow,
|
|
2313
|
+
answer,
|
|
2314
|
+
[import_model.ModelRequest.Message.user(printed), ...delivered(drained), ...disciplined.messages],
|
|
2315
|
+
liveCellEcho
|
|
2316
|
+
);
|
|
2317
|
+
return continuing(exit, windowOn(state, seat, context), drained.inserts.length > 0, {
|
|
2318
|
+
seat,
|
|
2319
|
+
modelParams,
|
|
2320
|
+
modelCallMs,
|
|
2321
|
+
contextWindowTokens,
|
|
2322
|
+
...shownAfter(state, drained),
|
|
2323
|
+
...ledgerAfter(drained),
|
|
2324
|
+
...marksAfter(state, drained),
|
|
2325
|
+
// Whatever this frame earned is what the next one answers, so the run's
|
|
2326
|
+
// memory goes above it. See `frozen`.
|
|
2327
|
+
interventions: disciplined.messages.length,
|
|
2328
|
+
...disciplined.changes
|
|
2329
|
+
});
|
|
2330
|
+
});
|
|
2331
|
+
const RelevanceRecord = import_effect.Schema.Struct({ settled: AgentEvent.RelevanceSettled });
|
|
2332
|
+
const withheld = (state, catalog, input, engine, emit, taskOf) => import_effect.Effect.gen(function* () {
|
|
2333
|
+
const pinned = input.pinned ?? [];
|
|
2334
|
+
const documents = input.instructions ?? [];
|
|
2335
|
+
const rows = input.memory?.rows ?? [];
|
|
2336
|
+
const items = [
|
|
2337
|
+
...catalog.filter((descriptor) => descriptor.modelInvocable && !pinned.includes(descriptor.name)).map(Relevance.flowItem).sort((left, right) => left.id < right.id ? -1 : 1),
|
|
2338
|
+
...Relevance.chunks(documents).map((chunk) => ({
|
|
2339
|
+
kind: "instruction",
|
|
2340
|
+
id: chunk.id,
|
|
2341
|
+
text: chunk.text
|
|
2342
|
+
})),
|
|
2343
|
+
...rows.map((row) => ({ kind: "memory", id: row.key, text: row.text }))
|
|
2344
|
+
];
|
|
2345
|
+
if (items.length === 0) return state;
|
|
2346
|
+
const record = yield* Judgement.recorded(
|
|
2347
|
+
engine,
|
|
2348
|
+
{
|
|
2349
|
+
name: "relevance",
|
|
2350
|
+
identity: { session: state.session, frame: 0, boundary: "relevance" },
|
|
2351
|
+
classifier: "relevance/unnecessary",
|
|
2352
|
+
value: RelevanceRecord,
|
|
2353
|
+
items: items.length
|
|
2354
|
+
},
|
|
2355
|
+
import_effect.Effect.map(Relevance.judge({ task: Judgement.task(taskOf(state.contextWindow)) }, items), (reading) => ({
|
|
2356
|
+
value: { settled: Relevance.settled(reading, { scope: state.session, frame: 0, source: "run" }) },
|
|
2357
|
+
asked: reading.asked,
|
|
2358
|
+
acted: reading.verdicts.some((verdict) => verdict.withheld)
|
|
2359
|
+
}))
|
|
2360
|
+
);
|
|
2361
|
+
yield* Judgement.emitRecorded(emit, record);
|
|
2362
|
+
if (record.value === null) return state;
|
|
2363
|
+
const { settled } = record.value;
|
|
2364
|
+
yield* emit(settled);
|
|
2365
|
+
const judgedChunks = new Set(
|
|
2366
|
+
settled.withheld.filter((item) => item.kind === "instruction").map((item) => `${item.id}\0${item.digest}`)
|
|
2367
|
+
);
|
|
2368
|
+
const chunks = new Set(
|
|
2369
|
+
Relevance.chunks(documents).flatMap(
|
|
2370
|
+
(chunk) => judgedChunks.has(`${chunk.id}\0${Digest.digest(chunk.text)}`) ? [chunk.id] : []
|
|
2371
|
+
)
|
|
2372
|
+
);
|
|
2373
|
+
const dropped = new Set(
|
|
2374
|
+
settled.withheld.filter((item) => item.kind === "memory").map((item) => `${item.id}\0${item.digest}`)
|
|
2375
|
+
);
|
|
2376
|
+
const replaced = /* @__PURE__ */ new Map();
|
|
2377
|
+
if (chunks.size > 0) {
|
|
2378
|
+
const text = Relevance.render(documents, chunks);
|
|
2379
|
+
replaced.set(
|
|
2380
|
+
ContextWindow.makeSegment(instructionsSegment(documents, /* @__PURE__ */ new Set())).digest,
|
|
2381
|
+
text === "" ? [] : [ContextWindow.makeSegment(instructionsSegment(documents, chunks))]
|
|
2382
|
+
);
|
|
2383
|
+
}
|
|
2384
|
+
if (input.memory !== void 0 && dropped.size > 0) {
|
|
2385
|
+
const { digest, render } = input.memory;
|
|
2386
|
+
const text = render(rows.filter((row) => !dropped.has(`${row.key}\0${Digest.digest(row.text)}`)));
|
|
2387
|
+
replaced.set(
|
|
2388
|
+
ContextWindow.makeSegment(memorySegment(render(rows), digest)).digest,
|
|
2389
|
+
text === "" ? [] : [ContextWindow.makeSegment(memorySegment(text, Digest.digest(text)))]
|
|
2390
|
+
);
|
|
2391
|
+
}
|
|
2392
|
+
return advance(state, {
|
|
2393
|
+
withheldFlows: settled.withheld.filter((item) => item.kind === "flow" || item.kind === "skill").map(
|
|
2394
|
+
(item) => item.id
|
|
2395
|
+
),
|
|
2396
|
+
...replaced.size === 0 ? {} : {
|
|
2397
|
+
contextWindow: ContextWindow.make({
|
|
2398
|
+
...state.contextWindow,
|
|
2399
|
+
segments: state.contextWindow.segments.flatMap((segment) => replaced.get(segment.digest) ?? [segment])
|
|
2400
|
+
})
|
|
2401
|
+
}
|
|
2402
|
+
});
|
|
2403
|
+
});
|
|
2404
|
+
const run = (input) => import_effect.Stream.callback((queue) => {
|
|
2405
|
+
let instructions = "";
|
|
2406
|
+
const emit = (event) => import_effect.Effect.flatMap(AgentEvent.Observer, (observe2) => observe2(event)).pipe(
|
|
2407
|
+
import_effect.Effect.andThen(import_effect.Effect.sync(() => {
|
|
2408
|
+
if (event._tag !== "steering-drained") return;
|
|
2409
|
+
const text = event.messages.flatMap((message) => message.content).filter((part) => part.type === "text").map((part) => part.text).join("\n\n");
|
|
2410
|
+
if (text !== "") instructions = CompletionClaim.newest(`${instructions}
|
|
2411
|
+
|
|
2412
|
+
${text}`.trim());
|
|
2413
|
+
})),
|
|
2414
|
+
import_effect.Effect.andThen(import_effect.Queue.offer(queue, event)),
|
|
2415
|
+
import_effect.Effect.asVoid
|
|
2416
|
+
);
|
|
2417
|
+
const readCompletion = (evidence) => CompletionClaim.read({ ...evidence, task: completionTask(evidence.task, instructions) });
|
|
2418
|
+
const taskOf = (window) => completionTask(Frame.taskText(window), instructions);
|
|
2419
|
+
const monitors = input.monitors ?? Monitor.defaults();
|
|
2420
|
+
const judged = input.judged ?? false;
|
|
2421
|
+
const pinned = input.pinned ?? [];
|
|
2422
|
+
const loop = import_effect.Effect.gen(function* () {
|
|
2423
|
+
const engine = yield* EngineLike.EngineLike;
|
|
2424
|
+
const sandbox = yield* Sandbox.Sandbox;
|
|
2425
|
+
const steering = yield* Steering.Source;
|
|
2426
|
+
let current = input.state;
|
|
2427
|
+
let flows = input.flows.filter((descriptor) => !current.withheldFlows.includes(descriptor.name));
|
|
2428
|
+
if (current.journalVersion !== import_Transcript.journalVersion) {
|
|
2429
|
+
return yield* new import_HarnessError.HarnessError({
|
|
2430
|
+
code: "incompatible_journal",
|
|
2431
|
+
message: `Controller state predates harness journal format ${import_Transcript.journalVersion}; start a new run.`
|
|
2432
|
+
});
|
|
2433
|
+
}
|
|
2434
|
+
if (current.frame === 0) {
|
|
2435
|
+
const limits = Sandbox.withDefaults(sandbox.capabilities, input.limits);
|
|
2436
|
+
yield* emit(
|
|
2437
|
+
new AgentEvent.DisciplineArmed({
|
|
2438
|
+
eventType: eventType.disciplineArmed,
|
|
2439
|
+
readOnlyCap: current.readOnlyCap,
|
|
2440
|
+
maxFrames: current.maxFrames,
|
|
2441
|
+
approvalChannel: current.approvalChannel,
|
|
2442
|
+
modelCallMs: current.modelCallMs,
|
|
2443
|
+
repeatCap: current.repeatCap,
|
|
2444
|
+
narrowingCap: current.narrowingCap,
|
|
2445
|
+
unmovedCap: current.unmovedCap,
|
|
2446
|
+
unresolvedCap: current.unresolvedCap,
|
|
2447
|
+
claimCap: current.claimCap,
|
|
2448
|
+
revalidations: current.revalidations,
|
|
2449
|
+
// Written only when armed, so an unjudged journal keeps the bytes
|
|
2450
|
+
// it had before the switch existed.
|
|
2451
|
+
...judged ? {
|
|
2452
|
+
judged,
|
|
2453
|
+
relevance: { withholdAt: Relevance.withholdAt, pinned: [...pinned] },
|
|
2454
|
+
monitors: monitors.map(({ at, consecutive, cooldownFrames, id, kind, limit }) => ({
|
|
2455
|
+
id,
|
|
2456
|
+
kind,
|
|
2457
|
+
at,
|
|
2458
|
+
consecutive,
|
|
2459
|
+
cooldownFrames,
|
|
2460
|
+
limit
|
|
2461
|
+
}))
|
|
2462
|
+
} : {},
|
|
2463
|
+
...input.stance === void 0 ? {} : { stance: input.stance },
|
|
2464
|
+
...limits
|
|
2465
|
+
})
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
const supervision = yield* Supervision.open({
|
|
2469
|
+
session: current.session,
|
|
2470
|
+
engine,
|
|
2471
|
+
emit,
|
|
2472
|
+
monitors,
|
|
2473
|
+
deliver: judged
|
|
2474
|
+
});
|
|
2475
|
+
const realm = yield* import_effect.Effect.suspend(() => {
|
|
2476
|
+
const projections = {};
|
|
2477
|
+
for (const descriptor of input.flows) {
|
|
2478
|
+
projections[descriptor.name] = Cell.project(descriptor);
|
|
2479
|
+
}
|
|
2480
|
+
return sandbox.openRealm === void 0 ? import_effect.Effect.fail(Sandbox.realmUnsupported) : sandbox.openRealm({ flows: projections, limits: input.limits });
|
|
2481
|
+
}).pipe(
|
|
2482
|
+
import_effect.Effect.mapError(
|
|
2483
|
+
(cause) => new import_HarnessError.HarnessError({
|
|
2484
|
+
code: "engine_failed",
|
|
2485
|
+
message: "The run's persistent realm could not be opened",
|
|
2486
|
+
cause
|
|
2487
|
+
})
|
|
2488
|
+
)
|
|
2489
|
+
);
|
|
2490
|
+
for (; ; ) {
|
|
2491
|
+
if (current.failureFrames >= 5) {
|
|
2492
|
+
return yield* new import_HarnessError.HarnessError({
|
|
2493
|
+
code: "model_failed",
|
|
2494
|
+
message: `Runaway guard: ${current.failureFrames} consecutive frames repeated the same failure: ${current.failureKey}`,
|
|
2495
|
+
cause: { _tag: repeatedFailureTag, frames: current.failureFrames }
|
|
2496
|
+
});
|
|
2497
|
+
}
|
|
2498
|
+
if (current.maxFrames > 0 && current.frame >= current.maxFrames) {
|
|
2499
|
+
yield* emit(
|
|
2500
|
+
new AgentEvent.Resolved({
|
|
2501
|
+
eventType: eventType.resolved,
|
|
2502
|
+
message: import_model.ModelRequest.Message.assistant(budgetMessage(current), { stopReason: "stop" })
|
|
2503
|
+
})
|
|
2504
|
+
);
|
|
2505
|
+
return;
|
|
2506
|
+
}
|
|
2507
|
+
const catalog = input.refreshFlows === void 0 ? input.flows : yield* engine.record({
|
|
2508
|
+
name: "flow-catalog",
|
|
2509
|
+
identity: { session: current.session, frame: current.frame, boundary: "flow-catalog" },
|
|
2510
|
+
success: import_effect.Schema.Array(import_registry.Descriptor.FlowDescriptor),
|
|
2511
|
+
execute: input.refreshFlows
|
|
2512
|
+
});
|
|
2513
|
+
current = judged && current.frame === 0 ? yield* withheld(current, catalog, input, engine, emit, taskOf) : current;
|
|
2514
|
+
const shown = catalog.filter((descriptor) => !current.withheldFlows.includes(descriptor.name));
|
|
2515
|
+
if (input.refreshFlows !== void 0 || shown.length !== flows.length) {
|
|
2516
|
+
const previous = teach(ContextWindow.empty(current.contextWindow.modelId), flows, void 0, input.stance);
|
|
2517
|
+
const digests = new Set(previous.segments.map((segment) => segment.digest));
|
|
2518
|
+
current = advance(current, {
|
|
2519
|
+
contextWindow: teach(
|
|
2520
|
+
ContextWindow.make({
|
|
2521
|
+
...current.contextWindow,
|
|
2522
|
+
segments: current.contextWindow.segments.filter((segment) => !digests.has(segment.digest))
|
|
2523
|
+
}),
|
|
2524
|
+
shown,
|
|
2525
|
+
void 0,
|
|
2526
|
+
input.stance
|
|
2527
|
+
)
|
|
2528
|
+
});
|
|
2529
|
+
flows = shown;
|
|
2530
|
+
}
|
|
2531
|
+
const step = yield* frame(
|
|
2532
|
+
{ ...input, state: current, flows },
|
|
2533
|
+
engine,
|
|
2534
|
+
sandbox,
|
|
2535
|
+
realm,
|
|
2536
|
+
steering,
|
|
2537
|
+
emit,
|
|
2538
|
+
readCompletion,
|
|
2539
|
+
supervision,
|
|
2540
|
+
taskOf
|
|
2541
|
+
).pipe(
|
|
2542
|
+
import_effect.Effect.catch((error) => {
|
|
2543
|
+
const request = permissionRequired(error);
|
|
2544
|
+
if (request === void 0) {
|
|
2545
|
+
return import_effect.Effect.fail(
|
|
2546
|
+
error instanceof import_HarnessError.HarnessError ? error : new import_HarnessError.HarnessError({
|
|
2547
|
+
code: error instanceof Sandbox.SandboxError ? "engine_failed" : "model_failed",
|
|
2548
|
+
message: frameFailureMessage(error),
|
|
2549
|
+
cause: error
|
|
2550
|
+
})
|
|
2551
|
+
);
|
|
2552
|
+
}
|
|
2553
|
+
return import_effect.Effect.gen(function* () {
|
|
2554
|
+
yield* emit(
|
|
2555
|
+
new AgentEvent.PermissionRequired({
|
|
2556
|
+
eventType: eventType.permissionRequired,
|
|
2557
|
+
request
|
|
2558
|
+
})
|
|
2559
|
+
);
|
|
2560
|
+
yield* emit(
|
|
2561
|
+
new AgentEvent.TurnClosed({
|
|
2562
|
+
eventType: eventType.turnClosed,
|
|
2563
|
+
stopReason: "error",
|
|
2564
|
+
outcome: "suspended"
|
|
2565
|
+
})
|
|
2566
|
+
);
|
|
2567
|
+
return {
|
|
2568
|
+
_tag: "Suspend",
|
|
2569
|
+
reason: new EngineLike.SuspendReason({
|
|
2570
|
+
code: "permission-required",
|
|
2571
|
+
message: `Permission ${request.requestId} is required`,
|
|
2572
|
+
// Encoded, not attached: `request` is a class that extends
|
|
2573
|
+
// `Error`, and this reason is journaled inside
|
|
2574
|
+
// `AgentEvent.Suspended`. A live Error there has no JSON form,
|
|
2575
|
+
// so encoding it dies with a schema failure that replaces the
|
|
2576
|
+
// park it was carrying.
|
|
2577
|
+
details: encodePermissionRequired(request)
|
|
2578
|
+
})
|
|
2579
|
+
};
|
|
2580
|
+
});
|
|
2581
|
+
}),
|
|
2582
|
+
import_effect.Effect.onInterrupt(
|
|
2583
|
+
() => import_effect.Effect.gen(function* () {
|
|
2584
|
+
yield* emit(new AgentEvent.Aborted({ eventType: eventType.aborted, reason: "Cell frame interrupted" }));
|
|
2585
|
+
yield* emit(
|
|
2586
|
+
new AgentEvent.TurnClosed({
|
|
2587
|
+
eventType: eventType.turnClosed,
|
|
2588
|
+
stopReason: "aborted",
|
|
2589
|
+
outcome: "aborted"
|
|
2590
|
+
})
|
|
2591
|
+
);
|
|
2592
|
+
})
|
|
2593
|
+
)
|
|
2594
|
+
);
|
|
2595
|
+
if (step._tag === "Done") return;
|
|
2596
|
+
if (step._tag === "Suspend") {
|
|
2597
|
+
yield* emit(new AgentEvent.Suspended({ eventType: eventType.suspended, reason: step.reason }));
|
|
2598
|
+
return yield* engine.suspend(step.reason);
|
|
2599
|
+
}
|
|
2600
|
+
for (const flow of current.withheldFlows) {
|
|
2601
|
+
if (step.state.withheldFlows.includes(flow)) continue;
|
|
2602
|
+
yield* emit(
|
|
2603
|
+
new AgentEvent.RelevanceRestored({
|
|
2604
|
+
eventType: eventType.relevanceRestored,
|
|
2605
|
+
scope: current.session,
|
|
2606
|
+
frame: current.frame,
|
|
2607
|
+
flow
|
|
2608
|
+
})
|
|
2609
|
+
);
|
|
2610
|
+
}
|
|
2611
|
+
current = step.state;
|
|
2612
|
+
}
|
|
2613
|
+
});
|
|
2614
|
+
return import_effect.Effect.onExit(import_effect.Effect.scoped(loop), (exit) => import_effect.Effect.asVoid(
|
|
2615
|
+
exit._tag === "Success" ? import_effect.Queue.end(queue) : import_effect.Queue.failCause(queue, exit.cause)
|
|
2616
|
+
));
|
|
2617
|
+
});
|
|
2618
|
+
//# sourceMappingURL=CellTurn.js.map
|