@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,464 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The deterministic script sandbox port.
|
|
3
|
+
*
|
|
4
|
+
* A cell is arbitrary agent-authored JavaScript, so it never runs in the host
|
|
5
|
+
* realm. It runs behind this port, which grants exactly one effectful
|
|
6
|
+
* primitive — flow invocation against the capability-narrowed catalog the run
|
|
7
|
+
* was given — and returns a serializable {@link Cell.Outcome}.
|
|
8
|
+
*
|
|
9
|
+
* The port opens a {@link Realm}, and a realm is the whole surface: it is
|
|
10
|
+
* acquired once per run and every cell of that run is evaluated in it, so a
|
|
11
|
+
* name one cell binds is still bound in the next. There is no per-cell
|
|
12
|
+
* evaluation beside it. One binding ships — `QuickJSSandbox`, the QuickJS-WASM
|
|
13
|
+
* binding that isolates a real separate realm in both Node and browsers — and a
|
|
14
|
+
* composition that offers none is refused with {@link realmUnsupported}.
|
|
15
|
+
*
|
|
16
|
+
* Cancellation is fiber interruption and teardown is scope finalization; a
|
|
17
|
+
* sandbox never installs a host abort signal.
|
|
18
|
+
*
|
|
19
|
+
* @since 0.1.0
|
|
20
|
+
*/
|
|
21
|
+
import * as Fault from "@smthrs/flow/Fault";
|
|
22
|
+
import { Context, Effect, Exit, Layer, Schema } from "effect";
|
|
23
|
+
import * as Cell from "./Cell.js";
|
|
24
|
+
import * as CellValidation from "./CellValidation.js";
|
|
25
|
+
import { refusal, timedOut } from "./internal/refusal.js";
|
|
26
|
+
/**
|
|
27
|
+
* Stable failures raised by a sandbox binding itself, as opposed to failures
|
|
28
|
+
* of the cell it was asked to run.
|
|
29
|
+
*
|
|
30
|
+
* A cell that throws is a {@link Cell.Raised} outcome, not a sandbox error.
|
|
31
|
+
* These codes describe the sandbox being unable to do its job at all.
|
|
32
|
+
*
|
|
33
|
+
* @category models
|
|
34
|
+
* @since 0.1.0
|
|
35
|
+
* @slop
|
|
36
|
+
*/
|
|
37
|
+
export const SandboxErrorCode = Schema.Literals([
|
|
38
|
+
"unavailable",
|
|
39
|
+
"unsupported",
|
|
40
|
+
"runtime_failed"
|
|
41
|
+
]);
|
|
42
|
+
/**
|
|
43
|
+
* A failure of the sandbox binding.
|
|
44
|
+
*
|
|
45
|
+
* @category errors
|
|
46
|
+
* @since 0.1.0
|
|
47
|
+
* @slop
|
|
48
|
+
*/
|
|
49
|
+
export class SandboxError extends Schema.TaggedError()("flows/harness/SandboxError", {
|
|
50
|
+
code: SandboxErrorCode,
|
|
51
|
+
message: Schema.String,
|
|
52
|
+
cause: Schema.optional(Schema.Defect())
|
|
53
|
+
}) {
|
|
54
|
+
}
|
|
55
|
+
Fault.register("flows/harness/SandboxError", {
|
|
56
|
+
unavailable: "infra",
|
|
57
|
+
runtime_failed: "infra",
|
|
58
|
+
unsupported: "bug"
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* The refusal a binding answers `ctx.checkpoint()` with when the caller wired
|
|
62
|
+
* no minter.
|
|
63
|
+
*
|
|
64
|
+
* @category constructors
|
|
65
|
+
* @since 0.1.0
|
|
66
|
+
*/
|
|
67
|
+
export const mintUnavailable = () => Effect.succeed(refusal("checkpoint_unavailable", "This run pins no checkpoints."));
|
|
68
|
+
/**
|
|
69
|
+
* The execution ceilings a cell runs under when the caller declares none.
|
|
70
|
+
*
|
|
71
|
+
* Agent-authored source must never acquire an unbounded frame merely because a
|
|
72
|
+
* host omitted configuration. These values are deliberately generous for a
|
|
73
|
+
* cell, whose work is choosing flow calls and shaping JSON between them. There
|
|
74
|
+
* is no spelling for "no ceiling": a host that needs more raises the relevant
|
|
75
|
+
* finite value explicitly.
|
|
76
|
+
*
|
|
77
|
+
* @category constants
|
|
78
|
+
* @since 0.1.0
|
|
79
|
+
* @slop
|
|
80
|
+
*/
|
|
81
|
+
export const defaultLimits = Object.freeze({
|
|
82
|
+
calls: 64,
|
|
83
|
+
memoryBytes: 128 * 1024 * 1024,
|
|
84
|
+
steps: 1000,
|
|
85
|
+
timeMs: 30_000,
|
|
86
|
+
totalMs: 900_000,
|
|
87
|
+
callMs: 120_000
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* Smallest interpreter-step budget a binding can enter a realm under.
|
|
91
|
+
*
|
|
92
|
+
* A zero budget interrupts the binding's own scaffolding before any cell source
|
|
93
|
+
* runs, which escapes as a crash rather than a ceiling report, so the sandbox
|
|
94
|
+
* boundary refuses it as `unsupported`.
|
|
95
|
+
*
|
|
96
|
+
* @category constants
|
|
97
|
+
* @since 1.0.0-rc.0
|
|
98
|
+
*/
|
|
99
|
+
export const minimumSteps = 1;
|
|
100
|
+
/**
|
|
101
|
+
* Smallest wall-clock budget, in milliseconds, a binding can enter a realm under.
|
|
102
|
+
*
|
|
103
|
+
* A zero budget interrupts the binding's own scaffolding before any cell source
|
|
104
|
+
* runs, which escapes as a crash rather than a ceiling report, so the sandbox
|
|
105
|
+
* boundary refuses it as `unsupported`.
|
|
106
|
+
*
|
|
107
|
+
* @category constants
|
|
108
|
+
* @since 1.0.0-rc.0
|
|
109
|
+
*/
|
|
110
|
+
export const minimumTimeMs = 1;
|
|
111
|
+
/**
|
|
112
|
+
* Smallest heap ceiling the QuickJS binding can initialize and tear down
|
|
113
|
+
* safely.
|
|
114
|
+
*
|
|
115
|
+
* QuickJS needs space for its runtime and context before cell source runs.
|
|
116
|
+
* Lower ceilings can leave a partially initialized context that aborts during
|
|
117
|
+
* disposal, so they are refused at the sandbox boundary.
|
|
118
|
+
*
|
|
119
|
+
* @category constants
|
|
120
|
+
* @since 0.1.0
|
|
121
|
+
* @slop
|
|
122
|
+
*/
|
|
123
|
+
export const minimumMemoryBytes = 1024 * 1024;
|
|
124
|
+
// The print-channel budgets live with the channel that spends them, and are
|
|
125
|
+
// re-exported here because a host reads them to size what it prints.
|
|
126
|
+
export { printFrameBytes, printRetainedBytes, printStatementFloor } from "./internal/printChannel.js";
|
|
127
|
+
const invalidLimit = (name, requirement) => new SandboxError({
|
|
128
|
+
code: "unsupported",
|
|
129
|
+
message: `The ${name} limit must be ${requirement}`
|
|
130
|
+
});
|
|
131
|
+
/** Validates caller-supplied numeric limits before a binding is entered. */
|
|
132
|
+
const validateLimits = (limits) => {
|
|
133
|
+
if (limits === undefined)
|
|
134
|
+
return undefined;
|
|
135
|
+
for (const name of ["calls", "totalMs", "callMs"]) {
|
|
136
|
+
const value = limits[name];
|
|
137
|
+
if (value !== undefined && (!Number.isSafeInteger(value) || value < 0)) {
|
|
138
|
+
return invalidLimit(name, "a non-negative safe integer");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
for (const [name, minimum] of [["steps", minimumSteps], ["timeMs", minimumTimeMs]]) {
|
|
142
|
+
const value = limits[name];
|
|
143
|
+
if (value !== undefined && (!Number.isSafeInteger(value) || value < minimum)) {
|
|
144
|
+
return invalidLimit(name, `a safe integer of at least ${minimum}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (limits.memoryBytes !== undefined &&
|
|
148
|
+
(!Number.isSafeInteger(limits.memoryBytes) || limits.memoryBytes < minimumMemoryBytes)) {
|
|
149
|
+
return invalidLimit("memoryBytes", `a safe integer of at least ${minimumMemoryBytes} bytes`);
|
|
150
|
+
}
|
|
151
|
+
if (limits.pauseTotalMsFor !== undefined &&
|
|
152
|
+
(!Array.isArray(limits.pauseTotalMsFor) ||
|
|
153
|
+
limits.pauseTotalMsFor.some((name) => typeof name !== "string" || name.trim().length === 0))) {
|
|
154
|
+
return invalidLimit("pauseTotalMsFor", "an array of non-empty flow names");
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Fills omitted ceilings from {@link defaultLimits} for limits a binding can
|
|
160
|
+
* enforce.
|
|
161
|
+
*
|
|
162
|
+
* Capability gating applies only to defaults. An explicit unsupported limit is
|
|
163
|
+
* passed through so the binding can refuse it instead of silently widening the
|
|
164
|
+
* caller's authority.
|
|
165
|
+
*
|
|
166
|
+
* @category constructors
|
|
167
|
+
* @since 0.1.0
|
|
168
|
+
* @slop
|
|
169
|
+
*/
|
|
170
|
+
export const withDefaults = (capabilities, limits) => ({
|
|
171
|
+
...limits,
|
|
172
|
+
...(capabilities.memoryBytes && limits?.memoryBytes === undefined
|
|
173
|
+
? { memoryBytes: defaultLimits.memoryBytes }
|
|
174
|
+
: {}),
|
|
175
|
+
...(capabilities.steps && limits?.steps === undefined ? { steps: defaultLimits.steps } : {}),
|
|
176
|
+
...(capabilities.calls && limits?.calls === undefined ? { calls: defaultLimits.calls } : {}),
|
|
177
|
+
...(capabilities.timeMs && limits?.timeMs === undefined ? { timeMs: defaultLimits.timeMs } : {}),
|
|
178
|
+
...(capabilities.timeMs && limits?.totalMs === undefined ? { totalMs: defaultLimits.totalMs } : {}),
|
|
179
|
+
// Gated on `calls` rather than on `timeMs`: the per-call budget is enforced
|
|
180
|
+
// by the shared drive loop, which is exactly the loop a binding that queues
|
|
181
|
+
// flow calls runs, and not by the interpreter clock `timeMs` describes.
|
|
182
|
+
...(capabilities.calls && limits?.callMs === undefined ? { callMs: defaultLimits.callMs } : {})
|
|
183
|
+
});
|
|
184
|
+
/**
|
|
185
|
+
* Merges and validates one frame's limits without changing the realm defaults.
|
|
186
|
+
* Only per-frame ceilings can be overridden; memory belongs to the realm.
|
|
187
|
+
*
|
|
188
|
+
* @category constructors
|
|
189
|
+
* @since 0.1.0
|
|
190
|
+
*/
|
|
191
|
+
export const evaluationLimits = (defaults, overrides) => {
|
|
192
|
+
const limits = {
|
|
193
|
+
calls: overrides?.calls ?? defaults.calls,
|
|
194
|
+
steps: overrides?.steps ?? defaults.steps,
|
|
195
|
+
timeMs: overrides?.timeMs ?? defaults.timeMs,
|
|
196
|
+
totalMs: overrides?.totalMs ?? defaults.totalMs,
|
|
197
|
+
pauseTotalMsFor: overrides?.pauseTotalMsFor ?? defaults.pauseTotalMsFor,
|
|
198
|
+
callMs: overrides?.callMs ?? defaults.callMs
|
|
199
|
+
};
|
|
200
|
+
const invalid = validateLimits(limits);
|
|
201
|
+
return invalid === undefined ? Effect.succeed(limits) : Effect.fail(invalid);
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Builds the durable transition one cell settled.
|
|
205
|
+
*
|
|
206
|
+
* A cell states its intent by calling, so this is the only place a
|
|
207
|
+
* {@link Cell.Transition} is constructed. The realm is the run's memory and the
|
|
208
|
+
* print buffer is what the next turn reads, so nothing is filed on the way out:
|
|
209
|
+
* the transition carries only the current intent.
|
|
210
|
+
*
|
|
211
|
+
* @category constructors
|
|
212
|
+
* @since 0.1.0
|
|
213
|
+
*/
|
|
214
|
+
export const replTransition = (intent, justification) => {
|
|
215
|
+
if (intent === undefined)
|
|
216
|
+
return new Cell.Continue({ justification });
|
|
217
|
+
return intent._tag === "Done"
|
|
218
|
+
? new Cell.Complete({ output: intent.output, value: intent.value })
|
|
219
|
+
: new Cell.Park({ reason: intent.reason, message: intent.message });
|
|
220
|
+
};
|
|
221
|
+
/**
|
|
222
|
+
* The bridge frontier at a frame limit. Ordinals are zero-based;
|
|
223
|
+
* minus one means no dispatch or settlement occurred. A dispatched call may
|
|
224
|
+
* have been interrupted before its settlement was delivered to JavaScript.
|
|
225
|
+
* `timeout` requires truncating replay; `settled` identifies a limit the
|
|
226
|
+
* interpreter completed itself, such as its step or call budget.
|
|
227
|
+
*
|
|
228
|
+
* @category schemas
|
|
229
|
+
* @since 0.1.0
|
|
230
|
+
*/
|
|
231
|
+
export const FrameBoundary = Schema.Struct({
|
|
232
|
+
terminal: Schema.Literals(["timeout", "settled"]),
|
|
233
|
+
dispatched: Schema.Int.check(Schema.isGreaterThanOrEqualTo(-1)),
|
|
234
|
+
settled: Schema.Int.check(Schema.isGreaterThanOrEqualTo(-1))
|
|
235
|
+
});
|
|
236
|
+
/**
|
|
237
|
+
* Context service for the selected sandbox binding.
|
|
238
|
+
*
|
|
239
|
+
* @category services
|
|
240
|
+
* @since 0.1.0
|
|
241
|
+
* @slop
|
|
242
|
+
*/
|
|
243
|
+
export const Sandbox = Context.Service("@smthrs/harness/Sandbox");
|
|
244
|
+
/**
|
|
245
|
+
* Constructs a sandbox from an implementation.
|
|
246
|
+
*
|
|
247
|
+
* @category constructors
|
|
248
|
+
* @since 0.1.0
|
|
249
|
+
* @slop
|
|
250
|
+
*/
|
|
251
|
+
export const make = (implementation) => {
|
|
252
|
+
const openRealm = implementation.openRealm;
|
|
253
|
+
return Sandbox.of({
|
|
254
|
+
...implementation,
|
|
255
|
+
...(openRealm === undefined ? {} : {
|
|
256
|
+
openRealm: (options) => {
|
|
257
|
+
const invalid = validateLimits(options.limits);
|
|
258
|
+
return invalid !== undefined ? Effect.fail(invalid) : openRealm({
|
|
259
|
+
...options,
|
|
260
|
+
limits: withDefaults(implementation.capabilities, options.limits)
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* Provides a sandbox implementation.
|
|
268
|
+
*
|
|
269
|
+
* @category layers
|
|
270
|
+
* @since 0.1.0
|
|
271
|
+
* @slop
|
|
272
|
+
*/
|
|
273
|
+
export const layer = (implementation) => Layer.succeed(Sandbox)(make(implementation));
|
|
274
|
+
/**
|
|
275
|
+
* Constructs an unavailable sandbox stub, optionally overriding operations.
|
|
276
|
+
*
|
|
277
|
+
* It offers no realm, which is what a run composed against it is told: see
|
|
278
|
+
* {@link realmUnsupported}.
|
|
279
|
+
*
|
|
280
|
+
* @category constructors
|
|
281
|
+
* @since 0.1.0
|
|
282
|
+
* @slop
|
|
283
|
+
*/
|
|
284
|
+
export const makeNoop = (overrides = {}) => Sandbox.of({
|
|
285
|
+
capabilities: { calls: false, memoryBytes: false, steps: false, timeMs: false },
|
|
286
|
+
...overrides
|
|
287
|
+
});
|
|
288
|
+
/**
|
|
289
|
+
* Provides an unavailable sandbox stub.
|
|
290
|
+
*
|
|
291
|
+
* @category layers
|
|
292
|
+
* @since 0.1.0
|
|
293
|
+
* @slop
|
|
294
|
+
*/
|
|
295
|
+
export const layerNoop = (overrides = {}) => Layer.succeed(Sandbox)(makeNoop(overrides));
|
|
296
|
+
/**
|
|
297
|
+
* Refuses a run on a binding that has no persistent realm.
|
|
298
|
+
*
|
|
299
|
+
* Stated rather than silently downgraded: a realm is the whole surface, so a
|
|
300
|
+
* binding without one cannot run a cell at all and saying so at the open is the
|
|
301
|
+
* only honest answer.
|
|
302
|
+
*
|
|
303
|
+
* @category constructors
|
|
304
|
+
* @since 0.1.0
|
|
305
|
+
*/
|
|
306
|
+
export const realmUnsupported = new SandboxError({
|
|
307
|
+
code: "unsupported",
|
|
308
|
+
message: "This sandbox has no persistent realm, so it cannot run a cell loop; select the QuickJS binding"
|
|
309
|
+
});
|
|
310
|
+
const seconds = (milliseconds) => {
|
|
311
|
+
const value = milliseconds / 1_000;
|
|
312
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/, "");
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* Settles one overrunning flow call as a resolved failure envelope in the cell.
|
|
316
|
+
*
|
|
317
|
+
* The message is written for the model, because the model is who reads it: it
|
|
318
|
+
* names the flow, the budget it spent, and the one action that recovers the
|
|
319
|
+
* frame. A rejection at the whole-evaluation ceiling teaches the model nothing
|
|
320
|
+
* — the frame is already gone by the time it could act.
|
|
321
|
+
*
|
|
322
|
+
* Exported so a caller that bounds its own settlements
|
|
323
|
+
* ({@link RealmEvaluation.bounded}) synthesizes the same refusal the loop would
|
|
324
|
+
* have: one ceiling means one sentence, whichever clock enforced it.
|
|
325
|
+
*
|
|
326
|
+
* @category constructors
|
|
327
|
+
* @since 0.1.0
|
|
328
|
+
*/
|
|
329
|
+
export const callTimedOut = (flow, callMs) => timedOut(`Flow ${flow} timed out after ${seconds(callMs)} seconds.`, callMs);
|
|
330
|
+
/**
|
|
331
|
+
* Erases type-only syntax from a cell without evaluating or resolving modules.
|
|
332
|
+
*
|
|
333
|
+
* Only Node's strip-safe TypeScript subset is accepted. Constructs that need
|
|
334
|
+
* JavaScript emit are refused instead of being silently transformed into new
|
|
335
|
+
* runtime behaviour.
|
|
336
|
+
*
|
|
337
|
+
* The parse itself belongs to `CellValidation`, which the controller already
|
|
338
|
+
* runs at the boundary before it commits a frame; this is the same answer, for
|
|
339
|
+
* a binding that only needs the program or the reason there is none.
|
|
340
|
+
*
|
|
341
|
+
* @category conversions
|
|
342
|
+
* @since 0.1.0
|
|
343
|
+
* @slop
|
|
344
|
+
*/
|
|
345
|
+
export const compile = (cell) => {
|
|
346
|
+
const validation = CellValidation.validate(cell);
|
|
347
|
+
/* v8 ignore next -- `validate` returns exactly one of the two, so the coalesce never reaches its fallback; it only discharges the optional types the interface declares */
|
|
348
|
+
return validation.rejected ?? validation.compiled ?? cell.text;
|
|
349
|
+
};
|
|
350
|
+
/**
|
|
351
|
+
* Renders a thrown non-`Error` as the value it is.
|
|
352
|
+
*
|
|
353
|
+
* `String(value)` on an object is `[object Object]`, which is the single
|
|
354
|
+
* defect PROGRAM change 1 names verbatim: a run that threw a structured value
|
|
355
|
+
* was told nothing about it and spent a frame going back for the same value.
|
|
356
|
+
* Anything JSON can hold is rendered as JSON; anything it cannot — a symbol, a
|
|
357
|
+
* function — keeps `String`, which is the only faithful thing left.
|
|
358
|
+
*
|
|
359
|
+
* @private
|
|
360
|
+
*/
|
|
361
|
+
const describe = (value) => {
|
|
362
|
+
const decoded = Schema.decodeUnknownResult(Schema.Json)(value);
|
|
363
|
+
return decoded._tag === "Success" ? Cell.renderText(decoded.success) : String(value);
|
|
364
|
+
};
|
|
365
|
+
/**
|
|
366
|
+
* Drives one externally compiled cell to settlement: settle queued calls one at
|
|
367
|
+
* a time, in the order the cell issued them, until the cell settles.
|
|
368
|
+
*
|
|
369
|
+
* One at a time is deliberate. Data-dependent calls are the normal case, and a
|
|
370
|
+
* deterministic execution ordinal is what makes a mid-cell crash replayable.
|
|
371
|
+
*
|
|
372
|
+
* Bindings differ only in how a cell is compiled and how its promises are
|
|
373
|
+
* settled, so the interleaving lives here once rather than in each of them.
|
|
374
|
+
*
|
|
375
|
+
* @category constructors
|
|
376
|
+
* @since 0.1.0
|
|
377
|
+
* @slop
|
|
378
|
+
*/
|
|
379
|
+
export const driveCell = (options) => Effect.gen(function* () {
|
|
380
|
+
let calls = 0;
|
|
381
|
+
let settledOrdinal = -1;
|
|
382
|
+
for (;;) {
|
|
383
|
+
const next = options.pending.shift();
|
|
384
|
+
if (next !== undefined) {
|
|
385
|
+
if (options.replay !== undefined &&
|
|
386
|
+
(next.ordinal > options.replay.boundary.settled || next.ordinal > options.replay.boundary.dispatched)) {
|
|
387
|
+
// Match interruption cleanup without delivering an answer that the
|
|
388
|
+
// original cell never received. This also covers queued checkpoints.
|
|
389
|
+
next.abort("The cell was interrupted");
|
|
390
|
+
options.abort("The cell was interrupted");
|
|
391
|
+
options.flush();
|
|
392
|
+
return options.replay.outcome;
|
|
393
|
+
}
|
|
394
|
+
if (options.limits?.calls !== undefined && calls >= options.limits.calls) {
|
|
395
|
+
const message = `This cell exceeded its limit of ${options.limits.calls} flow calls`;
|
|
396
|
+
next.abort(message);
|
|
397
|
+
options.abort(message);
|
|
398
|
+
options.flush();
|
|
399
|
+
return new Cell.Rejected({ code: "limit_exceeded", message });
|
|
400
|
+
}
|
|
401
|
+
calls = calls + 1;
|
|
402
|
+
options.progress?.(next.ordinal, settledOrdinal);
|
|
403
|
+
const callMs = options.limits?.callMs ?? defaultLimits.callMs;
|
|
404
|
+
// A mint is settled here rather than on a channel of its own so that it
|
|
405
|
+
// is ordered against the calls around it. See `Minter`.
|
|
406
|
+
const settling = next.kind === "checkpoint"
|
|
407
|
+
? (options.mint ?? mintUnavailable)({ ordinal: next.ordinal })
|
|
408
|
+
: options.handler({
|
|
409
|
+
ordinal: next.ordinal,
|
|
410
|
+
flow: next.flow,
|
|
411
|
+
input: next.input,
|
|
412
|
+
...(next.at === undefined ? {} : { at: next.at })
|
|
413
|
+
});
|
|
414
|
+
const result = yield* (options.bounded === true
|
|
415
|
+
// The caller bounds its own settlements, inside the boundary it
|
|
416
|
+
// journals them under. Racing a second clock here would settle the
|
|
417
|
+
// call from the one reading nothing records. See `bounded`.
|
|
418
|
+
? settling
|
|
419
|
+
: settling.pipe(
|
|
420
|
+
// The per-call ceiling, ahead of the interrupt cleanup below: a call
|
|
421
|
+
// that overruns is answered, not abandoned, so the cell sees a
|
|
422
|
+
// resolved failure and the frame keeps its remaining budget.
|
|
423
|
+
Effect.timeoutOrElse({
|
|
424
|
+
duration: callMs,
|
|
425
|
+
orElse: () => Effect.succeed(callTimedOut(next.flow, callMs))
|
|
426
|
+
}))).pipe(Effect.flatMap(Cell.decodeCallResult), Effect.onExit((exit) => Exit.isSuccess(exit)
|
|
427
|
+
? Effect.void
|
|
428
|
+
: Effect.sync(() => {
|
|
429
|
+
// `next` was shifted out of `pending` before the handler ran.
|
|
430
|
+
// Settle that active bridge as well as calls queued behind it,
|
|
431
|
+
// then flush the VM so a scoped runtime has no live promise
|
|
432
|
+
// handles when a permission park or engine failure unwinds it.
|
|
433
|
+
next.abort("The cell was interrupted");
|
|
434
|
+
options.abort("The cell was interrupted");
|
|
435
|
+
options.flush();
|
|
436
|
+
})));
|
|
437
|
+
next.settle(result);
|
|
438
|
+
settledOrdinal = next.ordinal;
|
|
439
|
+
options.progress?.(next.ordinal, settledOrdinal);
|
|
440
|
+
options.flush();
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
const outcome = options.finished();
|
|
444
|
+
if (outcome !== undefined)
|
|
445
|
+
return yield* Cell.decodeOutcome(outcome);
|
|
446
|
+
// Nothing is queued and the cell has not settled: hand the runtime a
|
|
447
|
+
// yield point so a peer fiber and an interrupt are both still observable.
|
|
448
|
+
yield* Effect.yieldNow;
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
/**
|
|
452
|
+
* Projects a thrown value into a stable serializable cell outcome.
|
|
453
|
+
*
|
|
454
|
+
* @category conversions
|
|
455
|
+
* @since 0.1.0
|
|
456
|
+
* @slop
|
|
457
|
+
*/
|
|
458
|
+
export const raisedOutcome = (error) => {
|
|
459
|
+
if (error instanceof Error) {
|
|
460
|
+
return new Cell.Raised({ name: error.name, message: error.message });
|
|
461
|
+
}
|
|
462
|
+
return new Cell.Raised({ name: "Error", message: describe(error) });
|
|
463
|
+
};
|
|
464
|
+
//# sourceMappingURL=Sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sandbox.js","sourceRoot":"","sources":["../../src/Sandbox.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The deterministic script sandbox port.\n *\n * A cell is arbitrary agent-authored JavaScript, so it never runs in the host\n * realm. It runs behind this port, which grants exactly one effectful\n * primitive — flow invocation against the capability-narrowed catalog the run\n * was given — and returns a serializable {@link Cell.Outcome}.\n *\n * The port opens a {@link Realm}, and a realm is the whole surface: it is\n * acquired once per run and every cell of that run is evaluated in it, so a\n * name one cell binds is still bound in the next. There is no per-cell\n * evaluation beside it. One binding ships — `QuickJSSandbox`, the QuickJS-WASM\n * binding that isolates a real separate realm in both Node and browsers — and a\n * composition that offers none is refused with {@link realmUnsupported}.\n *\n * Cancellation is fiber interruption and teardown is scope finalization; a\n * sandbox never installs a host abort signal.\n *\n * @since 0.1.0\n */\n\nimport * as Fault from \"@smthrs/flow/Fault\"\nimport { Context, Effect, Exit, Layer, Schema, type Scope } from \"effect\"\nimport * as Cell from \"./Cell.ts\"\nimport * as CellValidation from \"./CellValidation.ts\"\nimport type { HarnessError } from \"./HarnessError.ts\"\nimport { refusal, timedOut } from \"./internal/refusal.ts\"\nimport type * as VariablesPanel from \"./VariablesPanel.ts\"\n\n/**\n * Stable failures raised by a sandbox binding itself, as opposed to failures\n * of the cell it was asked to run.\n *\n * A cell that throws is a {@link Cell.Raised} outcome, not a sandbox error.\n * These codes describe the sandbox being unable to do its job at all.\n *\n * @category models\n * @since 0.1.0\n * @slop\n */\nexport const SandboxErrorCode = Schema.Literals([\n \"unavailable\",\n \"unsupported\",\n \"runtime_failed\"\n])\n\n/**\n * Stable failures raised by a sandbox binding itself.\n *\n * @category models\n * @since 0.1.0\n * @slop\n */\nexport type SandboxErrorCode = typeof SandboxErrorCode.Type\n\n/**\n * A failure of the sandbox binding.\n *\n * @category errors\n * @since 0.1.0\n * @slop\n */\nexport class SandboxError extends Schema.TaggedError<SandboxError>()(\"flows/harness/SandboxError\", {\n code: SandboxErrorCode,\n message: Schema.String,\n cause: Schema.optional(Schema.Defect())\n}) {}\nFault.register(\n \"flows/harness/SandboxError\",\n {\n unavailable: \"infra\",\n runtime_failed: \"infra\",\n unsupported: \"bug\"\n } satisfies Fault.Rows<SandboxErrorCode>\n)\n\n/**\n * One flow invocation requested from inside a running cell.\n *\n * `ordinal` is the zero-based execution order of the call within the cell. It\n * is the replay anchor: re-executing the same source reaches the same ordinal\n * with the same declaration, which is what lets a settled boundary replay\n * instead of re-running.\n *\n * @category models\n * @since 0.1.0\n * @slop\n */\nexport interface Invocation {\n readonly ordinal: number\n readonly flow: string\n readonly input: Schema.Json\n /**\n * Whatever the cell passed as the call's `at` option, undecoded.\n *\n * It arrives as the raw JSON the cell wrote rather than as an id because the\n * boundary, not the realm, decides whether it is a checkpoint: a cell that\n * passes a string, a failure envelope, or last frame's result gets an\n * resolved `invalid_input` failure naming what `at` takes. Throwing from inside\n * the sandbox would lose the calls the cell had already paid for.\n */\n readonly at?: Schema.Json | undefined\n}\n\n/**\n * One request to pin the workspace, issued from inside a running cell.\n *\n * It carries only its ordinal because that is the whole of its identity: the\n * cell source and the frame are the boundary's, and the ordinal is what makes\n * the pin land where the cell wrote it. See {@link Minter}.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Mint {\n readonly ordinal: number\n}\n\n/**\n * Pins the workspace on behalf of a running cell.\n *\n * A mint travels the same queue as a flow call and is settled by the same drive\n * loop, in issue order, one at a time. That ordering is the whole contract:\n * `ctx.checkpoint()` promises the tree as it stands *at the line it is written\n * on*, and the only way a cell can move the tree is by issuing a call, so a\n * queue that settles in issue order pins exactly the tree the cell was looking\n * at. A mint that runs on its own schedule — a side channel, a host callback,\n * anything the queue does not order — would pin whichever tree happened to be\n * there when it got round to it.\n *\n * The result is a {@link Cell.CallResult} like any other, so a host with no\n * store, a run past its checkpoint bound, and a store that failed are all\n * resolved `{ ok: false, error }` refusals rather than teardown.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Minter = (mint: Mint) => Effect.Effect<Cell.CallResult, HarnessError>\n\n/**\n * The refusal a binding answers `ctx.checkpoint()` with when the caller wired\n * no minter.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const mintUnavailable: Minter = () =>\n Effect.succeed(\n refusal(\"checkpoint_unavailable\", \"This run pins no checkpoints.\")\n )\n\n/**\n * Resolves one invocation on behalf of a running cell.\n *\n * A {@link Cell.CallResult} of `failure` resolves in the cell as\n * `{ ok: false, error }`, where `error` contains `code`, `message`, and `hint`;\n * it does not throw. Success resolves with the flow's own value, unwrapped.\n * Branch on `.ok === false` and `.error.code` to recover. For a flow whose\n * successful result has a `stdout` field, a cell can retry a timed-out call:\n *\n * ```ts\n * let result = await ctx.call(\"bash\", { command: \"find . -name '*.ts'\" })\n * if (result.ok === false && result.error.code === \"timeout\") {\n * result = await ctx.call(\"bash\", { command: \"find src -name '*.ts'\" })\n * }\n * console.log(result.ok === false ? result.error.code : result.stdout)\n * ```\n *\n * Anything the cell must not observe, such as a permission park, an abort,\n * or an engine failure, travels in the effect's error channel and tears the\n * cell down.\n *\n * @category models\n * @since 0.1.0\n * @slop\n */\nexport type Handler = (\n invocation: Invocation\n) => Effect.Effect<Cell.CallResult, HarnessError>\n\n/**\n * Realm memory ceiling and default execution limits for its evaluations.\n *\n * Bindings fill every ceiling they can enforce from {@link defaultLimits} when\n * the caller omits it. A binding that cannot honour an explicitly requested\n * limit fails with `unsupported` rather than silently ignoring it.\n *\n * @category models\n * @since 0.1.0\n * @slop\n */\nexport interface Limits {\n /**\n * Maximum number of flow calls one cell may make; a non-negative safe integer.\n * A checkpoint mint settles on the same channel and counts against this budget.\n */\n readonly calls?: number | undefined\n /** Maximum sandbox heap, in bytes; at least {@link minimumMemoryBytes}. */\n readonly memoryBytes?: number | undefined\n /**\n * Maximum interpreter steps before the cell is stopped.\n *\n * A step is one interrupt check, not one bytecode operation: an interpreter\n * polls its budget periodically, so this bounds work rather than counting\n * individual operations. The limit is a safe integer of at least\n * {@link minimumSteps}.\n */\n readonly steps?: number | undefined\n /**\n * Maximum cell-compute time in milliseconds; a safe integer of at least\n * {@link minimumTimeMs}.\n *\n * This bounds the cell's own JavaScript execution. Time spent suspended in\n * an outstanding `ctx.call` or `ctx.checkpoint()` does not count: host work\n * belongs to the boundary that runs it, and charging it here rejected every cell that\n * awaited a real test run — 57 of the 62 rejected frames in the first\n * SWE-bench benchmark were legitimate long `bash` calls hitting this clock.\n */\n readonly timeMs?: number | undefined\n /**\n * Maximum whole-evaluation time in milliseconds, host calls included; a\n * non-negative safe integer.\n *\n * The backstop for a host call that never settles. Generous on purpose: a\n * cell awaiting a ten-minute test suite is working, not stuck.\n */\n readonly totalMs?: number | undefined\n /** Flow names whose pending call time does not spend the frame backstop. */\n readonly pauseTotalMsFor?: ReadonlyArray<string> | undefined\n /**\n * Maximum wall-clock time one flow call may take, in milliseconds; a\n * non-negative safe integer.\n *\n * The per-call budget {@link totalMs} cannot supply. `totalMs` is the frame's\n * last resort, and a call that overruns it takes the whole frame down with a\n * `limit_exceeded` rejection the model never sees as an answer: on the\n * SWE-bench django instance one broad `grep` held its cell for the entire\n * 900,000 ms ceiling, 75% of a 1,204-second run. This ceiling settles that\n * same call as an ordinary resolved failure instead, so the cell observes a\n * timeout it can narrow and retry inside the frame it is already in.\n */\n readonly callMs?: number | undefined\n}\n\n/**\n * Per-frame overrides of a realm's opening limits. Omitted or undefined fields\n * inherit the realm defaults. The memory ceiling remains fixed for the run.\n *\n * @category models\n * @since 0.1.0\n */\nexport type EvaluationLimits = Omit<Limits, \"memoryBytes\">\n\n/**\n * Which limits a binding can actually enforce.\n *\n * @category models\n * @since 0.1.0\n * @slop\n */\nexport interface Capabilities {\n readonly calls: boolean\n readonly memoryBytes: boolean\n readonly steps: boolean\n readonly timeMs: boolean\n}\n\n/**\n * The execution ceilings a cell runs under when the caller declares none.\n *\n * Agent-authored source must never acquire an unbounded frame merely because a\n * host omitted configuration. These values are deliberately generous for a\n * cell, whose work is choosing flow calls and shaping JSON between them. There\n * is no spelling for \"no ceiling\": a host that needs more raises the relevant\n * finite value explicitly.\n *\n * @category constants\n * @since 0.1.0\n * @slop\n */\nexport const defaultLimits = Object.freeze({\n calls: 64,\n memoryBytes: 128 * 1024 * 1024,\n steps: 1000,\n timeMs: 30_000,\n totalMs: 900_000,\n callMs: 120_000\n})\n\n/**\n * Smallest interpreter-step budget a binding can enter a realm under.\n *\n * A zero budget interrupts the binding's own scaffolding before any cell source\n * runs, which escapes as a crash rather than a ceiling report, so the sandbox\n * boundary refuses it as `unsupported`.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const minimumSteps = 1\n\n/**\n * Smallest wall-clock budget, in milliseconds, a binding can enter a realm under.\n *\n * A zero budget interrupts the binding's own scaffolding before any cell source\n * runs, which escapes as a crash rather than a ceiling report, so the sandbox\n * boundary refuses it as `unsupported`.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const minimumTimeMs = 1\n\n/**\n * Smallest heap ceiling the QuickJS binding can initialize and tear down\n * safely.\n *\n * QuickJS needs space for its runtime and context before cell source runs.\n * Lower ceilings can leave a partially initialized context that aborts during\n * disposal, so they are refused at the sandbox boundary.\n *\n * @category constants\n * @since 0.1.0\n * @slop\n */\nexport const minimumMemoryBytes = 1024 * 1024\n\n// The print-channel budgets live with the channel that spends them, and are\n// re-exported here because a host reads them to size what it prints.\nexport { printFrameBytes, printRetainedBytes, printStatementFloor } from \"./internal/printChannel.ts\"\n\nconst invalidLimit = (name: keyof Limits, requirement: string): SandboxError =>\n new SandboxError({\n code: \"unsupported\",\n message: `The ${name} limit must be ${requirement}`\n })\n\n/** Validates caller-supplied numeric limits before a binding is entered. */\nconst validateLimits = (limits: Limits | undefined): SandboxError | undefined => {\n if (limits === undefined) return undefined\n\n for (const name of [\"calls\", \"totalMs\", \"callMs\"] as const) {\n const value = limits[name]\n if (value !== undefined && (!Number.isSafeInteger(value) || value < 0)) {\n return invalidLimit(name, \"a non-negative safe integer\")\n }\n }\n\n for (const [name, minimum] of [[\"steps\", minimumSteps], [\"timeMs\", minimumTimeMs]] as const) {\n const value = limits[name]\n if (value !== undefined && (!Number.isSafeInteger(value) || value < minimum)) {\n return invalidLimit(name, `a safe integer of at least ${minimum}`)\n }\n }\n\n if (\n limits.memoryBytes !== undefined &&\n (!Number.isSafeInteger(limits.memoryBytes) || limits.memoryBytes < minimumMemoryBytes)\n ) {\n return invalidLimit(\n \"memoryBytes\",\n `a safe integer of at least ${minimumMemoryBytes} bytes`\n )\n }\n\n if (\n limits.pauseTotalMsFor !== undefined &&\n (!Array.isArray(limits.pauseTotalMsFor) ||\n limits.pauseTotalMsFor.some((name) => typeof name !== \"string\" || name.trim().length === 0))\n ) {\n return invalidLimit(\"pauseTotalMsFor\", \"an array of non-empty flow names\")\n }\n\n return undefined\n}\n\n/**\n * Fills omitted ceilings from {@link defaultLimits} for limits a binding can\n * enforce.\n *\n * Capability gating applies only to defaults. An explicit unsupported limit is\n * passed through so the binding can refuse it instead of silently widening the\n * caller's authority.\n *\n * @category constructors\n * @since 0.1.0\n * @slop\n */\nexport const withDefaults = (\n capabilities: Capabilities,\n limits: Limits | undefined\n): Limits => ({\n ...limits,\n ...(capabilities.memoryBytes && limits?.memoryBytes === undefined\n ? { memoryBytes: defaultLimits.memoryBytes }\n : {}),\n ...(capabilities.steps && limits?.steps === undefined ? { steps: defaultLimits.steps } : {}),\n ...(capabilities.calls && limits?.calls === undefined ? { calls: defaultLimits.calls } : {}),\n ...(capabilities.timeMs && limits?.timeMs === undefined ? { timeMs: defaultLimits.timeMs } : {}),\n ...(capabilities.timeMs && limits?.totalMs === undefined ? { totalMs: defaultLimits.totalMs } : {}),\n // Gated on `calls` rather than on `timeMs`: the per-call budget is enforced\n // by the shared drive loop, which is exactly the loop a binding that queues\n // flow calls runs, and not by the interpreter clock `timeMs` describes.\n ...(capabilities.calls && limits?.callMs === undefined ? { callMs: defaultLimits.callMs } : {})\n})\n\n/**\n * Merges and validates one frame's limits without changing the realm defaults.\n * Only per-frame ceilings can be overridden; memory belongs to the realm.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const evaluationLimits = (\n defaults: Limits,\n overrides: EvaluationLimits | undefined\n): Effect.Effect<EvaluationLimits, SandboxError> => {\n const limits: EvaluationLimits = {\n calls: overrides?.calls ?? defaults.calls,\n steps: overrides?.steps ?? defaults.steps,\n timeMs: overrides?.timeMs ?? defaults.timeMs,\n totalMs: overrides?.totalMs ?? defaults.totalMs,\n pauseTotalMsFor: overrides?.pauseTotalMsFor ?? defaults.pauseTotalMsFor,\n callMs: overrides?.callMs ?? defaults.callMs\n }\n const invalid = validateLimits(limits)\n return invalid === undefined ? Effect.succeed(limits) : Effect.fail(invalid)\n}\n\n/**\n * What a REPL cell asked the controller to do.\n *\n * A cell runs as a global async script in a persistent realm. Top-level\n * `await` is supported; top-level `return` is invalid. The first `ctx.done`\n * or `ctx.park` that records an intent seals the frame. Later `ctx.done` and\n * `ctx.park` calls do nothing. Ordinary JavaScript continues running, but later\n * `ctx.call` and `ctx.checkpoint` calls resolve with a `run_completed` failure\n * envelope without dispatching host work.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Intent =\n | { readonly _tag: \"Done\"; readonly output: string; readonly value?: Schema.Json | undefined }\n | {\n readonly _tag: \"Park\"\n readonly reason: \"waiting-input\" | \"waiting-event\" | \"waiting-quota\"\n readonly message: string\n }\n\n/**\n * Builds the durable transition one cell settled.\n *\n * A cell states its intent by calling, so this is the only place a\n * {@link Cell.Transition} is constructed. The realm is the run's memory and the\n * print buffer is what the next turn reads, so nothing is filed on the way out:\n * the transition carries only the current intent.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const replTransition = (\n intent: Intent | undefined,\n justification: string | undefined\n): Cell.Transition => {\n if (intent === undefined) return new Cell.Continue({ justification })\n return intent._tag === \"Done\"\n ? new Cell.Complete({ output: intent.output, value: intent.value })\n : new Cell.Park({ reason: intent.reason, message: intent.message })\n}\n\n/**\n * One cell evaluated inside a realm that outlives it.\n *\n * `frame` names the evaluation for the realm's own stack traces, so a throw\n * reported in frame 7 says which cell threw.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface RealmEvaluation {\n /** Reconstruct a timed-out frame only through its recorded bridge prefix. */\n readonly replay?: { readonly boundary: typeof FrameBoundary.Type; readonly outcome: Cell.Outcome } | undefined\n /** Replaces ctx.flows with this frame's frozen catalog; omitted keeps the current catalog. */\n readonly flows?: Readonly<Record<string, Cell.FlowProjection>> | undefined\n readonly cell: Cell.Source\n /**\n * The program the controller's boundary parse already compiled from `cell`.\n *\n * A binding evaluates this verbatim when it is present, because the parse it\n * would do is the parse the boundary already did: a controller runs\n * {@link compile} before it commits a frame, so a binding that parses the\n * cell again parses every cell of the run twice. Omitted means the binding\n * compiles the cell itself, which is what a host driving a realm directly\n * does.\n */\n readonly program?: string | undefined\n readonly frame: number\n readonly call: Handler\n /**\n * Settles a `ctx.checkpoint()` issued by this cell.\n *\n * Optional, and absent means the caller pins no trees — which the cell is\n * told through a resolved failure envelope at the line it asked. It is a\n * separate collaborator from `call` because a checkpoint is not a flow:\n * it is neither in the catalog nor\n * subject to the capability envelope, and the run's own bound on how many\n * trees it may pin is the controller's, not any flow's.\n */\n readonly mint?: Minter | undefined\n /**\n * Whether the caller bounds each settlement itself.\n *\n * The loop's own {@link Limits.callMs} ceiling is a clock race it synthesizes\n * a failure from, and that failure is journaled nowhere: the call it\n * interrupted never settled, so nothing downstream holds a result for it. A\n * re-executed cell runs the same call again against a world that has moved\n * on, gets an answer this time, and takes a branch the original attempt never\n * took — with every irreversible effect below the fork bought twice.\n *\n * A caller that journals its settlements applies the same ceiling itself, in\n * front of the boundary that records what the ceiling produced, and sets this\n * so the loop adds none of its own — because two clocks racing one call means\n * the unrecorded one wins: the loop's starts first.\n */\n readonly bounded?: boolean | undefined\n /** Validated overrides for this frame only; memory is fixed when the realm opens. */\n readonly limits?: EvaluationLimits | undefined\n}\n\n/**\n * The bridge frontier at a frame limit. Ordinals are zero-based;\n * minus one means no dispatch or settlement occurred. A dispatched call may\n * have been interrupted before its settlement was delivered to JavaScript.\n * `timeout` requires truncating replay; `settled` identifies a limit the\n * interpreter completed itself, such as its step or call budget.\n *\n * @category schemas\n * @since 0.1.0\n */\nexport const FrameBoundary = Schema.Struct({\n terminal: Schema.Literals([\"timeout\", \"settled\"]),\n dispatched: Schema.Int.check(Schema.isGreaterThanOrEqualTo(-1)),\n settled: Schema.Int.check(Schema.isGreaterThanOrEqualTo(-1))\n})\n\n/**\n * Everything one REPL frame produced.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface RealmFrame {\n /** Present when evaluation ended at a frame limit. */\n readonly boundary?: typeof FrameBoundary.Type | undefined\n readonly outcome: Cell.Outcome\n /** What the cell printed, already bounded; empty when it printed nothing. */\n readonly prints: string\n /** Every name the realm holds after the cell ran. */\n readonly bindings: ReadonlyArray<VariablesPanel.Binding>\n}\n\n/**\n * A JavaScript realm that persists across the cells of one run.\n *\n * Teardown is scope closure, so a realm is acquired by the loop that uses it and\n * cancellation is still fiber interruption.\n *\n * @category services\n * @since 0.1.0\n */\nexport interface Realm {\n readonly evaluate: (\n evaluation: RealmEvaluation\n ) => Effect.Effect<RealmFrame, SandboxError | HarnessError>\n}\n\n/**\n * The initial catalog and limits a realm is opened with.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface RealmOptions {\n readonly flows: Readonly<Record<string, Cell.FlowProjection>>\n /**\n * The ceilings the realm enforces. `memoryBytes` becomes a **run** budget once\n * a realm outlives a cell, judged at each frame's start against what the\n * realm's own names weigh; a frame that opens over it runs nothing and is told\n * which names to free. Every other ceiling stays per-frame, because they are\n * counters the interrupt handler reads rather than properties of the runtime.\n */\n readonly limits?: Limits | undefined\n}\n\n/**\n * The deterministic script sandbox.\n *\n * @category services\n * @since 0.1.0\n * @slop\n */\nexport interface Sandbox {\n readonly capabilities: Capabilities\n /**\n * Opens the realm the run's cells share.\n *\n * Absent on a binding that has no persistent realm to offer, which is what a\n * host composing such a binding is told when the run opens rather than in the\n * middle of a frame. A realm is the only way a cell runs: there is no\n * per-frame evaluation beside it, because a cell that could not see what the\n * cell before it bound was the surface this harness deleted.\n */\n readonly openRealm?: (\n options: RealmOptions\n ) => Effect.Effect<Realm, SandboxError, Scope.Scope>\n}\n\n/**\n * Context service for the selected sandbox binding.\n *\n * @category services\n * @since 0.1.0\n * @slop\n */\nexport const Sandbox: Context.Service<Sandbox, Sandbox> = Context.Service(\"@smthrs/harness/Sandbox\")\n\n/**\n * Constructs a sandbox from an implementation.\n *\n * @category constructors\n * @since 0.1.0\n * @slop\n */\nexport const make = (implementation: Sandbox): Sandbox => {\n const openRealm = implementation.openRealm\n return Sandbox.of({\n ...implementation,\n ...(openRealm === undefined ? {} : {\n openRealm: (options: RealmOptions) => {\n const invalid = validateLimits(options.limits)\n return invalid !== undefined ? Effect.fail(invalid) : openRealm({\n ...options,\n limits: withDefaults(implementation.capabilities, options.limits)\n })\n }\n })\n })\n}\n\n/**\n * Provides a sandbox implementation.\n *\n * @category layers\n * @since 0.1.0\n * @slop\n */\nexport const layer = (implementation: Sandbox): Layer.Layer<Sandbox> => Layer.succeed(Sandbox)(make(implementation))\n\n/**\n * Constructs an unavailable sandbox stub, optionally overriding operations.\n *\n * It offers no realm, which is what a run composed against it is told: see\n * {@link realmUnsupported}.\n *\n * @category constructors\n * @since 0.1.0\n * @slop\n */\nexport const makeNoop = (overrides: Partial<Sandbox> = {}): Sandbox =>\n Sandbox.of({\n capabilities: { calls: false, memoryBytes: false, steps: false, timeMs: false },\n ...overrides\n })\n\n/**\n * Provides an unavailable sandbox stub.\n *\n * @category layers\n * @since 0.1.0\n * @slop\n */\nexport const layerNoop = (overrides: Partial<Sandbox> = {}): Layer.Layer<Sandbox> =>\n Layer.succeed(Sandbox)(makeNoop(overrides))\n\n/**\n * Refuses a run on a binding that has no persistent realm.\n *\n * Stated rather than silently downgraded: a realm is the whole surface, so a\n * binding without one cannot run a cell at all and saying so at the open is the\n * only honest answer.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const realmUnsupported: SandboxError = new SandboxError({\n code: \"unsupported\",\n message: \"This sandbox has no persistent realm, so it cannot run a cell loop; select the QuickJS binding\"\n})\n\nconst seconds = (milliseconds: number): string => {\n const value = milliseconds / 1_000\n return Number.isInteger(value) ? String(value) : value.toFixed(3).replace(/0+$/, \"\")\n}\n\n/**\n * Settles one overrunning flow call as a resolved failure envelope in the cell.\n *\n * The message is written for the model, because the model is who reads it: it\n * names the flow, the budget it spent, and the one action that recovers the\n * frame. A rejection at the whole-evaluation ceiling teaches the model nothing\n * — the frame is already gone by the time it could act.\n *\n * Exported so a caller that bounds its own settlements\n * ({@link RealmEvaluation.bounded}) synthesizes the same refusal the loop would\n * have: one ceiling means one sentence, whichever clock enforced it.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const callTimedOut = (flow: string, callMs: number): Cell.CallResult =>\n timedOut(`Flow ${flow} timed out after ${seconds(callMs)} seconds.`, callMs)\n\n/**\n * Erases type-only syntax from a cell without evaluating or resolving modules.\n *\n * Only Node's strip-safe TypeScript subset is accepted. Constructs that need\n * JavaScript emit are refused instead of being silently transformed into new\n * runtime behaviour.\n *\n * The parse itself belongs to `CellValidation`, which the controller already\n * runs at the boundary before it commits a frame; this is the same answer, for\n * a binding that only needs the program or the reason there is none.\n *\n * @category conversions\n * @since 0.1.0\n * @slop\n */\nexport const compile = (cell: Cell.Source): string | Cell.Rejected => {\n const validation = CellValidation.validate(cell)\n /* v8 ignore next -- `validate` returns exactly one of the two, so the coalesce never reaches its fallback; it only discharges the optional types the interface declares */\n return validation.rejected ?? validation.compiled ?? cell.text\n}\n\n/**\n * Renders a thrown non-`Error` as the value it is.\n *\n * `String(value)` on an object is `[object Object]`, which is the single\n * defect PROGRAM change 1 names verbatim: a run that threw a structured value\n * was told nothing about it and spent a frame going back for the same value.\n * Anything JSON can hold is rendered as JSON; anything it cannot — a symbol, a\n * function — keeps `String`, which is the only faithful thing left.\n *\n * @private\n */\nconst describe = (value: unknown): string => {\n const decoded = Schema.decodeUnknownResult(Schema.Json)(value)\n return decoded._tag === \"Success\" ? Cell.renderText(decoded.success) : String(value)\n}\n\n/**\n * A queued call awaiting resolution by a binding's driver.\n *\n * @category models\n * @since 0.1.0\n * @slop\n */\nexport interface PendingCall {\n readonly ordinal: number\n readonly flow: string\n readonly input: Schema.Json\n /** Undecoded `at` option; see {@link Invocation.at}. */\n readonly at?: Schema.Json | undefined\n /**\n * Whether this entry is a flow call or a request to pin the tree.\n *\n * Both ride one queue because both have to be ordered against each other: a\n * mint that overtook an edit, or an edit that overtook a mint, would pin the\n * wrong tree. Absent means `call`, so every binding that queues an ordinary\n * call is unchanged.\n */\n readonly kind?: \"call\" | \"checkpoint\" | undefined\n readonly settle: (result: Cell.CallResult) => void\n readonly abort: (message: string) => void\n}\n\n/**\n * Drives one externally compiled cell to settlement: settle queued calls one at\n * a time, in the order the cell issued them, until the cell settles.\n *\n * One at a time is deliberate. Data-dependent calls are the normal case, and a\n * deterministic execution ordinal is what makes a mid-cell crash replayable.\n *\n * Bindings differ only in how a cell is compiled and how its promises are\n * settled, so the interleaving lives here once rather than in each of them.\n *\n * @category constructors\n * @since 0.1.0\n * @slop\n */\nexport const driveCell = (options: {\n readonly replay?: RealmEvaluation[\"replay\"]\n readonly progress?: ((dispatched: number, settled: number) => void) | undefined\n readonly pending: Array<PendingCall>\n /** Called after each resolved call so a binding may flush its job queue. */\n readonly flush: () => void\n readonly finished: () => Cell.Outcome | undefined\n readonly abort: (message: string) => void\n readonly handler: Handler\n /** Settles a `ctx.checkpoint()`; omitted means the run pins none. */\n readonly mint?: Minter | undefined\n /** Whether the caller bounds each settlement itself; see {@link RealmEvaluation.bounded}. */\n readonly bounded?: boolean | undefined\n readonly limits?: Limits | undefined\n}): Effect.Effect<Cell.Outcome, SandboxError | HarnessError> =>\n Effect.gen(function*() {\n let calls = 0\n let settledOrdinal = -1\n for (;;) {\n const next = options.pending.shift()\n if (next !== undefined) {\n if (\n options.replay !== undefined &&\n (next.ordinal > options.replay.boundary.settled || next.ordinal > options.replay.boundary.dispatched)\n ) {\n // Match interruption cleanup without delivering an answer that the\n // original cell never received. This also covers queued checkpoints.\n next.abort(\"The cell was interrupted\")\n options.abort(\"The cell was interrupted\")\n options.flush()\n return options.replay.outcome\n }\n if (options.limits?.calls !== undefined && calls >= options.limits.calls) {\n const message = `This cell exceeded its limit of ${options.limits.calls} flow calls`\n next.abort(message)\n options.abort(message)\n options.flush()\n return new Cell.Rejected({ code: \"limit_exceeded\", message })\n }\n calls = calls + 1\n options.progress?.(next.ordinal, settledOrdinal)\n const callMs = options.limits?.callMs ?? defaultLimits.callMs\n // A mint is settled here rather than on a channel of its own so that it\n // is ordered against the calls around it. See `Minter`.\n const settling = next.kind === \"checkpoint\"\n ? (options.mint ?? mintUnavailable)({ ordinal: next.ordinal })\n : options.handler({\n ordinal: next.ordinal,\n flow: next.flow,\n input: next.input,\n ...(next.at === undefined ? {} : { at: next.at })\n })\n const result = yield* (options.bounded === true\n // The caller bounds its own settlements, inside the boundary it\n // journals them under. Racing a second clock here would settle the\n // call from the one reading nothing records. See `bounded`.\n ? settling\n : settling.pipe(\n // The per-call ceiling, ahead of the interrupt cleanup below: a call\n // that overruns is answered, not abandoned, so the cell sees a\n // resolved failure and the frame keeps its remaining budget.\n Effect.timeoutOrElse({\n duration: callMs,\n orElse: () => Effect.succeed(callTimedOut(next.flow, callMs))\n })\n )).pipe(\n Effect.flatMap(Cell.decodeCallResult),\n Effect.onExit((exit) =>\n Exit.isSuccess(exit)\n ? Effect.void\n : Effect.sync(() => {\n // `next` was shifted out of `pending` before the handler ran.\n // Settle that active bridge as well as calls queued behind it,\n // then flush the VM so a scoped runtime has no live promise\n // handles when a permission park or engine failure unwinds it.\n next.abort(\"The cell was interrupted\")\n options.abort(\"The cell was interrupted\")\n options.flush()\n })\n )\n )\n next.settle(result)\n settledOrdinal = next.ordinal\n options.progress?.(next.ordinal, settledOrdinal)\n options.flush()\n continue\n }\n const outcome = options.finished()\n if (outcome !== undefined) return yield* Cell.decodeOutcome(outcome)\n // Nothing is queued and the cell has not settled: hand the runtime a\n // yield point so a peer fiber and an interrupt are both still observable.\n yield* Effect.yieldNow\n }\n })\n\n/**\n * Projects a thrown value into a stable serializable cell outcome.\n *\n * @category conversions\n * @since 0.1.0\n * @slop\n */\nexport const raisedOutcome = (error: unknown): Cell.Raised => {\n if (error instanceof Error) {\n return new Cell.Raised({ name: error.name, message: error.message })\n }\n return new Cell.Raised({ name: \"Error\", message: describe(error) })\n}\n"]}
|