@plurnk/plurnk-service 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.defaults +76 -13
- package/README.md +5 -3
- package/SPEC.md +924 -689
- package/dist/Paths.js +3 -3
- package/dist/build-info.json +1 -1
- package/dist/content/body-preview.d.ts +1 -0
- package/dist/content/body-preview.d.ts.map +1 -1
- package/dist/content/body-preview.js +8 -10
- package/dist/content/body-preview.js.map +1 -1
- package/dist/content/edit-receipt.d.ts.map +1 -1
- package/dist/content/edit-receipt.js +30 -29
- package/dist/content/edit-receipt.js.map +1 -1
- package/dist/content/line-anchors.d.ts.map +1 -1
- package/dist/content/line-anchors.js +17 -5
- package/dist/content/line-anchors.js.map +1 -1
- package/dist/content/read-projector.d.ts +2 -2
- package/dist/content/read-projector.d.ts.map +1 -1
- package/dist/content/read-projector.js +79 -37
- package/dist/content/read-projector.js.map +1 -1
- package/dist/content/scope-format.d.ts +9 -0
- package/dist/content/scope-format.d.ts.map +1 -0
- package/dist/content/scope-format.js +28 -0
- package/dist/content/scope-format.js.map +1 -0
- package/dist/core/AdministrativeLoop.d.ts +8 -0
- package/dist/core/AdministrativeLoop.d.ts.map +1 -0
- package/dist/core/AdministrativeLoop.js +16 -0
- package/dist/core/AdministrativeLoop.js.map +1 -0
- package/dist/core/AdmittedTurnExecutor.d.ts +2 -1
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +19 -19
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BareBatchRunner.d.ts +1 -2
- package/dist/core/BareBatchRunner.d.ts.map +1 -1
- package/dist/core/BareBatchRunner.js +7 -12
- package/dist/core/BareBatchRunner.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +3 -4
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/CapabilityPolicies.d.ts +4 -2
- package/dist/core/CapabilityPolicies.d.ts.map +1 -1
- package/dist/core/CapabilityPolicies.js +23 -2
- package/dist/core/CapabilityPolicies.js.map +1 -1
- package/dist/core/CapabilityResolver.d.ts +2 -2
- package/dist/core/CapabilityResolver.d.ts.map +1 -1
- package/dist/core/CapabilityResolver.js +6 -3
- package/dist/core/CapabilityResolver.js.map +1 -1
- package/dist/core/ChannelWrite.d.ts +3 -6
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js +8 -8
- package/dist/core/ChannelWrite.js.map +1 -1
- package/dist/core/ChannelWrite.sql +17 -11
- package/dist/core/ClientInteractions.d.ts +11 -1
- package/dist/core/ClientInteractions.d.ts.map +1 -1
- package/dist/core/ClientInteractions.js +26 -2
- package/dist/core/ClientInteractions.js.map +1 -1
- package/dist/core/CoreSchemeServices.d.ts.map +1 -1
- package/dist/core/CoreSchemeServices.js +1 -0
- package/dist/core/CoreSchemeServices.js.map +1 -1
- package/dist/core/DataStatementRunner.js +6 -6
- package/dist/core/DataStatementRunner.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +12 -4
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +112 -90
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Dispatcher.sql +11 -26
- package/dist/core/DurableStatement.d.ts +4 -1
- package/dist/core/DurableStatement.d.ts.map +1 -1
- package/dist/core/DurableStatement.js +4 -4
- package/dist/core/DurableStatement.js.map +1 -1
- package/dist/core/EditMutations.d.ts.map +1 -1
- package/dist/core/EditMutations.js +5 -2
- package/dist/core/EditMutations.js.map +1 -1
- package/dist/core/Engine.d.ts +11 -9
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +27 -65
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +2 -22
- package/dist/core/EnvFlags.d.ts.map +1 -1
- package/dist/core/EnvFlags.js +4 -2
- package/dist/core/EnvFlags.js.map +1 -1
- package/dist/core/ExecutorRegistry.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.js +2 -1
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/KillHandler.d.ts.map +1 -1
- package/dist/core/KillHandler.js +7 -12
- package/dist/core/KillHandler.js.map +1 -1
- package/dist/core/Knob.d.ts +9 -0
- package/dist/core/Knob.d.ts.map +1 -0
- package/dist/core/Knob.js +50 -0
- package/dist/core/Knob.js.map +1 -0
- package/dist/core/LogBody.d.ts.map +1 -1
- package/dist/core/LogBody.js +6 -35
- package/dist/core/LogBody.js.map +1 -1
- package/dist/core/LogEntryProjection.d.ts.map +1 -1
- package/dist/core/LogEntryProjection.js +4 -0
- package/dist/core/LogEntryProjection.js.map +1 -1
- package/dist/core/LogVisibility.d.ts.map +1 -1
- package/dist/core/LogVisibility.js +2 -1
- package/dist/core/LogVisibility.js.map +1 -1
- package/dist/core/LogWriter.js +2 -2
- package/dist/core/LogWriter.js.map +1 -1
- package/dist/core/LoopDriver.d.ts +1 -1
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +23 -29
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopLifecycle.d.ts +4 -17
- package/dist/core/LoopLifecycle.d.ts.map +1 -1
- package/dist/core/LoopLifecycle.js +20 -22
- package/dist/core/LoopLifecycle.js.map +1 -1
- package/dist/core/LoopLifecycle.sql +36 -49
- package/dist/core/LoopOutcome.d.ts +10 -0
- package/dist/core/LoopOutcome.d.ts.map +1 -0
- package/dist/core/LoopOutcome.js +28 -0
- package/dist/core/LoopOutcome.js.map +1 -0
- package/dist/core/LoopPolicies.d.ts +7 -0
- package/dist/core/LoopPolicies.d.ts.map +1 -0
- package/dist/core/LoopPolicies.js +37 -0
- package/dist/core/LoopPolicies.js.map +1 -0
- package/dist/core/MessageResources.d.ts +15 -0
- package/dist/core/MessageResources.d.ts.map +1 -0
- package/dist/core/MessageResources.js +46 -0
- package/dist/core/MessageResources.js.map +1 -0
- package/dist/core/MessageResources.sql +36 -0
- package/dist/core/OperatorConfig.d.ts +2 -1
- package/dist/core/OperatorConfig.d.ts.map +1 -1
- package/dist/core/OperatorConfig.js +14 -6
- package/dist/core/OperatorConfig.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +20 -35
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PacketBuilder.sql +24 -6
- package/dist/core/PatternSelection.d.ts +1 -1
- package/dist/core/PatternSelection.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.d.ts +3 -1
- package/dist/core/ProposalLifecycle.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.js +85 -22
- package/dist/core/ProposalLifecycle.js.map +1 -1
- package/dist/core/ProviderInstantiate.d.ts +1 -0
- package/dist/core/ProviderInstantiate.d.ts.map +1 -1
- package/dist/core/ProviderInstantiate.js +12 -7
- package/dist/core/ProviderInstantiate.js.map +1 -1
- package/dist/core/ReasoningView.d.ts +1 -2
- package/dist/core/ReasoningView.d.ts.map +1 -1
- package/dist/core/ReasoningView.js +9 -20
- package/dist/core/ReasoningView.js.map +1 -1
- package/dist/core/ResourceBindings.d.ts.map +1 -1
- package/dist/core/ResourceBindings.js +5 -4
- package/dist/core/ResourceBindings.js.map +1 -1
- package/dist/core/ResourceMutations.d.ts +4 -4
- package/dist/core/ResourceMutations.d.ts.map +1 -1
- package/dist/core/ResourceMutations.js +2 -3
- package/dist/core/ResourceMutations.js.map +1 -1
- package/dist/core/ResourceSelector.d.ts +10 -3
- package/dist/core/ResourceSelector.d.ts.map +1 -1
- package/dist/core/ResourceSelector.js +52 -13
- package/dist/core/ResourceSelector.js.map +1 -1
- package/dist/core/ResourceTransfers.d.ts.map +1 -1
- package/dist/core/ResourceTransfers.js +4 -2
- package/dist/core/ResourceTransfers.js.map +1 -1
- package/dist/core/SchemeRegistry.d.ts +2 -0
- package/dist/core/SchemeRegistry.d.ts.map +1 -1
- package/dist/core/SchemeRegistry.js +11 -5
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/StoredPacket.d.ts +3 -1
- package/dist/core/StoredPacket.d.ts.map +1 -1
- package/dist/core/StoredPacket.js +7 -3
- package/dist/core/StoredPacket.js.map +1 -1
- package/dist/core/StrikeRail.d.ts.map +1 -1
- package/dist/core/StrikeRail.js +9 -3
- package/dist/core/StrikeRail.js.map +1 -1
- package/dist/core/TerminalResult.d.ts +2 -2
- package/dist/core/TerminalResult.d.ts.map +1 -1
- package/dist/core/TerminalResult.js +15 -8
- package/dist/core/TerminalResult.js.map +1 -1
- package/dist/core/ToolInputSchema.d.ts.map +1 -1
- package/dist/core/ToolInputSchema.js +24 -8
- package/dist/core/ToolInputSchema.js.map +1 -1
- package/dist/core/ToolResources.d.ts +1 -0
- package/dist/core/ToolResources.d.ts.map +1 -1
- package/dist/core/ToolResources.js +45 -23
- package/dist/core/ToolResources.js.map +1 -1
- package/dist/core/Turn.d.ts +3 -1
- package/dist/core/Turn.d.ts.map +1 -1
- package/dist/core/Turn.js +4 -1
- package/dist/core/Turn.js.map +1 -1
- package/dist/core/Turn.sql +14 -2
- package/dist/core/TurnDispositionHandler.d.ts +13 -21
- package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
- package/dist/core/TurnDispositionHandler.js +32 -190
- package/dist/core/TurnDispositionHandler.js.map +1 -1
- package/dist/core/TurnMaterialization.d.ts +9 -7
- package/dist/core/TurnMaterialization.d.ts.map +1 -1
- package/dist/core/TurnMaterialization.js +63 -41
- package/dist/core/TurnMaterialization.js.map +1 -1
- package/dist/core/TurnMaterialization.sql +23 -6
- package/dist/core/TurnOps.js +1 -1
- package/dist/core/TurnRunner.d.ts +1 -3
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +148 -189
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/TurnRunner.sql +1 -24
- package/dist/core/TurnSources.sql +42 -11
- package/dist/core/WorkerName.d.ts +1 -1
- package/dist/core/WorkerName.d.ts.map +1 -1
- package/dist/core/WorkerName.js +3 -3
- package/dist/core/WorkerName.js.map +1 -1
- package/dist/core/ambient.sql +45 -19
- package/dist/core/attachments.d.ts +3 -1
- package/dist/core/attachments.d.ts.map +1 -1
- package/dist/core/attachments.js +4 -0
- package/dist/core/attachments.js.map +1 -1
- package/dist/core/caps/CoreInteractionCaps.d.ts +1 -1
- package/dist/core/caps/CoreInteractionCaps.d.ts.map +1 -1
- package/dist/core/caps/CoreInteractionCaps.js +4 -2
- package/dist/core/caps/CoreInteractionCaps.js.map +1 -1
- package/dist/core/caps/DbChannelCaps.js +6 -6
- package/dist/core/caps/DbChannelCaps.js.map +1 -1
- package/dist/core/caps/DbEntryCaps.js +1 -1
- package/dist/core/caps/DbEntryCaps.js.map +1 -1
- package/dist/core/caps/DbMessageCaps.d.ts +10 -0
- package/dist/core/caps/DbMessageCaps.d.ts.map +1 -0
- package/dist/core/caps/DbMessageCaps.js +39 -0
- package/dist/core/caps/DbMessageCaps.js.map +1 -0
- package/dist/core/caps/DbProjectionCaps.d.ts +2 -2
- package/dist/core/caps/DbProjectionCaps.d.ts.map +1 -1
- package/dist/core/caps/DbProjectionCaps.js +10 -4
- package/dist/core/caps/DbProjectionCaps.js.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.d.ts +3 -1
- package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
- package/dist/core/caps/SchemeCtxImpl.js +11 -0
- package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
- package/dist/core/fork.sql +7 -6
- package/dist/core/git-state.d.ts +3 -2
- package/dist/core/git-state.d.ts.map +1 -1
- package/dist/core/git-state.js +37 -20
- package/dist/core/git-state.js.map +1 -1
- package/dist/core/packet-inject.js +1 -1
- package/dist/core/packet-wire.d.ts +11 -0
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +112 -88
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/plurnk-uri.d.ts +4 -5
- package/dist/core/plurnk-uri.d.ts.map +1 -1
- package/dist/core/plurnk-uri.js +10 -31
- package/dist/core/plurnk-uri.js.map +1 -1
- package/dist/core/scheme-types.d.ts +3 -1
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/core/scheme-types.js +1 -1
- package/dist/core/scheme-types.js.map +1 -1
- package/dist/core/teaching.d.ts.map +1 -1
- package/dist/core/teaching.js +2 -1
- package/dist/core/teaching.js.map +1 -1
- package/dist/core/types.d.ts +1 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-ops.sql +3 -8
- package/dist/digest/Digest.d.ts.map +1 -1
- package/dist/digest/Digest.js +35 -30
- package/dist/digest/Digest.js.map +1 -1
- package/dist/digest/DigestRender.d.ts +1 -0
- package/dist/digest/DigestRender.d.ts.map +1 -1
- package/dist/digest/DigestRender.js +53 -1
- package/dist/digest/DigestRender.js.map +1 -1
- package/dist/digest/DigestRequiem.d.ts.map +1 -1
- package/dist/digest/DigestRequiem.js +13 -15
- package/dist/digest/DigestRequiem.js.map +1 -1
- package/dist/digest/digest-db.d.ts +3 -0
- package/dist/digest/digest-db.d.ts.map +1 -0
- package/dist/digest/digest-db.js +68 -0
- package/dist/digest/digest-db.js.map +1 -0
- package/dist/digest/digest-paths.d.ts +6 -0
- package/dist/digest/digest-paths.d.ts.map +1 -0
- package/dist/digest/digest-paths.js +23 -0
- package/dist/digest/digest-paths.js.map +1 -0
- package/dist/digest/digest-rows.d.ts +15 -0
- package/dist/digest/digest-rows.d.ts.map +1 -1
- package/dist/digest/digest.sql +13 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/observe/genai.d.ts +2 -2
- package/dist/observe/genai.d.ts.map +1 -1
- package/dist/observe/genai.js +15 -5
- package/dist/observe/genai.js.map +1 -1
- package/dist/schemes/EffectPolicy.d.ts +0 -2
- package/dist/schemes/EffectPolicy.d.ts.map +1 -1
- package/dist/schemes/EffectPolicy.js +25 -36
- package/dist/schemes/EffectPolicy.js.map +1 -1
- package/dist/schemes/Exec.d.ts +4 -5
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +74 -62
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts +6 -5
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
- package/dist/schemes/ExecOutputScheme.js +49 -16
- package/dist/schemes/ExecOutputScheme.js.map +1 -1
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +28 -20
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts +4 -4
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +29 -9
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/QuestionTool.d.ts.map +1 -1
- package/dist/schemes/QuestionTool.js +14 -1
- package/dist/schemes/QuestionTool.js.map +1 -1
- package/dist/schemes/TurnSource.d.ts +3 -2
- package/dist/schemes/TurnSource.d.ts.map +1 -1
- package/dist/schemes/TurnSource.js +80 -35
- package/dist/schemes/TurnSource.js.map +1 -1
- package/dist/schemes/Worker.d.ts.map +1 -1
- package/dist/schemes/Worker.js +22 -56
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.js +6 -6
- package/dist/schemes/_entry-crud.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +19 -17
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +6 -5
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-fts.d.ts.map +1 -1
- package/dist/schemes/_entry-fts.js +6 -3
- package/dist/schemes/_entry-fts.js.map +1 -1
- package/dist/schemes/_entry-fts.sql +25 -6
- package/dist/schemes/_entry-manifest.d.ts +1 -1
- package/dist/schemes/_entry-manifest.d.ts.map +1 -1
- package/dist/schemes/_entry-manifest.js +5 -3
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_entry-ops.js +4 -4
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/schemes/_entry-ops.sql +2 -2
- package/dist/schemes/_entry-readable.d.ts.map +1 -1
- package/dist/schemes/_entry-readable.js +5 -4
- package/dist/schemes/_entry-readable.js.map +1 -1
- package/dist/schemes/_entry-send.js +2 -2
- package/dist/schemes/_entry-send.js.map +1 -1
- package/dist/schemes/_search-exclusion.d.ts +1 -0
- package/dist/schemes/_search-exclusion.d.ts.map +1 -1
- package/dist/schemes/_search-exclusion.js +12 -0
- package/dist/schemes/_search-exclusion.js.map +1 -1
- package/dist/schemes/_search-index.js +4 -4
- package/dist/schemes/_search-index.js.map +1 -1
- package/dist/schemes/exec-abort.d.ts.map +1 -1
- package/dist/schemes/exec-abort.js +4 -3
- package/dist/schemes/exec-abort.js.map +1 -1
- package/dist/schemes/exec-lifetime.d.ts +11 -0
- package/dist/schemes/exec-lifetime.d.ts.map +1 -0
- package/dist/schemes/exec-lifetime.js +29 -0
- package/dist/schemes/exec-lifetime.js.map +1 -0
- package/dist/server/ClientReads.d.ts.map +1 -1
- package/dist/server/ClientReads.js +3 -1
- package/dist/server/ClientReads.js.map +1 -1
- package/dist/server/Daemon.d.ts +30 -7
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +107 -48
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DaemonModule.d.ts +19 -5
- package/dist/server/DaemonModule.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.d.ts +13 -11
- package/dist/server/DrainSupervisor.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.js +87 -98
- package/dist/server/DrainSupervisor.js.map +1 -1
- package/dist/server/EnvFunctionality.d.ts +12 -3
- package/dist/server/EnvFunctionality.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.js +19 -14
- package/dist/server/EnvFunctionality.js.map +1 -1
- package/dist/server/Functionality.d.ts +2 -2
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +97 -62
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/FunctionalityManager.d.ts +3 -1
- package/dist/server/FunctionalityManager.d.ts.map +1 -1
- package/dist/server/FunctionalityManager.js +11 -5
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/HttpListener.d.ts +16 -0
- package/dist/server/HttpListener.d.ts.map +1 -0
- package/dist/server/HttpListener.js +81 -0
- package/dist/server/HttpListener.js.map +1 -0
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +12 -16
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/PlurnkSkill.d.ts.map +1 -1
- package/dist/server/PlurnkSkill.js +1 -0
- package/dist/server/PlurnkSkill.js.map +1 -1
- package/dist/server/Retention.d.ts +11 -0
- package/dist/server/Retention.d.ts.map +1 -1
- package/dist/server/Retention.js +47 -2
- package/dist/server/Retention.js.map +1 -1
- package/dist/server/Retention.sql +32 -1
- package/dist/server/ServiceModules.d.ts.map +1 -1
- package/dist/server/ServiceModules.js +2 -0
- package/dist/server/ServiceModules.js.map +1 -1
- package/dist/server/SkillsFunctionality.d.ts +2 -0
- package/dist/server/SkillsFunctionality.d.ts.map +1 -1
- package/dist/server/SkillsFunctionality.js +22 -15
- package/dist/server/SkillsFunctionality.js.map +1 -1
- package/dist/server/WorkspaceCapabilities.d.ts.map +1 -1
- package/dist/server/WorkspaceCapabilities.js +1 -0
- package/dist/server/WorkspaceCapabilities.js.map +1 -1
- package/dist/server/WorkspaceStorage.d.ts +8 -0
- package/dist/server/WorkspaceStorage.d.ts.map +1 -0
- package/dist/server/WorkspaceStorage.js +26 -0
- package/dist/server/WorkspaceStorage.js.map +1 -0
- package/dist/server/client-input.d.ts +4 -3
- package/dist/server/client-input.d.ts.map +1 -1
- package/dist/server/client-input.js +24 -26
- package/dist/server/client-input.js.map +1 -1
- package/dist/server/dispatch-as-plurnk.js +2 -2
- package/dist/server/dispatch-as-plurnk.js.map +1 -1
- package/dist/server/drain.sql +69 -132
- package/dist/server/envelope.d.ts +2 -2
- package/dist/server/envelope.d.ts.map +1 -1
- package/dist/server/envelope.js +7 -9
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/envelope.sql +10 -6
- package/dist/server/exec-poll-backoff.js +3 -3
- package/dist/server/exec-poll-backoff.js.map +1 -1
- package/dist/server/lifecycle-recovery.sql +8 -35
- package/dist/server/logEntry.sql +2 -2
- package/dist/server/loopDocs.js +3 -3
- package/dist/server/loopDocs.sql +4 -2
- package/dist/server/model-catalog.d.ts.map +1 -1
- package/dist/server/model-catalog.js +2 -2
- package/dist/server/model-catalog.js.map +1 -1
- package/dist/server/seam-loop.sql +0 -1
- package/dist/server/workspace-storage.sql +8 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +21 -10
- package/dist/service.js.map +1 -1
- package/docs/copy-move.md +31 -0
- package/docs/env.md +19 -7
- package/docs/skills.md +2 -2
- package/migrations/002_workers.sql +26 -17
- package/migrations/003_loops.sql +82 -28
- package/migrations/005_entries.sql +135 -22
- package/migrations/006_log.sql +77 -25
- package/migrations/007_subscriptions.sql +10 -15
- package/package.json +35 -36
- package/dist/core/PromptFrames.d.ts +0 -12
- package/dist/core/PromptFrames.d.ts.map +0 -1
- package/dist/core/PromptFrames.js +0 -28
- package/dist/core/PromptFrames.js.map +0 -1
- package/dist/schemes/Prompt.d.ts +0 -8
- package/dist/schemes/Prompt.d.ts.map +0 -1
- package/dist/schemes/Prompt.js +0 -25
- package/dist/schemes/Prompt.js.map +0 -1
package/dist/core/TurnRunner.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
var _a;
|
|
2
|
-
import { TurnDisposition } from "@plurnk/plurnk-contracts";
|
|
3
2
|
import NativeContent from "./NativeContent.js";
|
|
4
3
|
import { PlurnkParser } from "@plurnk/plurnk-parser";
|
|
5
4
|
import { PathSyntax, PlurnkParseError, UNKNOWN_POSITION } from "@plurnk/plurnk-contracts";
|
|
5
|
+
import LoopPolicyReader from "./LoopPolicyReader.js";
|
|
6
6
|
import { setTimeout as delay } from "node:timers/promises";
|
|
7
7
|
import { aggregateProviderAccounting } from "@plurnk/plurnk-providers";
|
|
8
8
|
const comparePosition = (a, b) => a.line - b.line || a.column - b.column;
|
|
@@ -11,9 +11,7 @@ import GitMembership from "./git-membership.js";
|
|
|
11
11
|
import { acceptedKinds } from "./attachments.js";
|
|
12
12
|
import GitState from "./git-state.js";
|
|
13
13
|
import WorkspaceSettings from "./workspace-settings.js";
|
|
14
|
-
import {
|
|
15
|
-
import { generatedPathname, promptLoopPrefix } from "./plurnk-uri.js";
|
|
16
|
-
import PromptFrames from "./PromptFrames.js";
|
|
14
|
+
import { generatedPathname } from "./plurnk-uri.js";
|
|
17
15
|
import { readFile } from "node:fs/promises";
|
|
18
16
|
import { resolve as resolvePath } from "node:path";
|
|
19
17
|
import { homedir } from "node:os";
|
|
@@ -36,22 +34,13 @@ import Results, { OperationFailureError } from "./results.js";
|
|
|
36
34
|
import Turn from "./Turn.js";
|
|
37
35
|
import StoredPacket from "./StoredPacket.js";
|
|
38
36
|
import { observed, observedSync } from "../observe/spans.js";
|
|
39
|
-
import {
|
|
37
|
+
import { genAiRequestName, genAiRequestOptions, settleGenAiResponse } from "../observe/genai.js";
|
|
40
38
|
import { PROVIDER_CALLS, recordCounter } from "../observe/metrics.js";
|
|
41
39
|
import ModelCall, { ModelCallPersistenceError, ProviderAccountingIntegrityError } from "./ModelCall.js";
|
|
42
40
|
import WorkerName from "./WorkerName.js";
|
|
43
41
|
import TurnOps from "./TurnOps.js";
|
|
44
42
|
import CapabilityPolicies from "./CapabilityPolicies.js";
|
|
45
43
|
import CapabilityResolver from "./CapabilityResolver.js";
|
|
46
|
-
// {§prompt-address}: the same literal address in every observer's packet.
|
|
47
|
-
const promptTarget = (workerName, storage) => {
|
|
48
|
-
return {
|
|
49
|
-
kind: "url", raw: `prompt://${workerName}${storage}`,
|
|
50
|
-
scheme: "prompt", username: null, password: null,
|
|
51
|
-
hostname: workerName, port: null,
|
|
52
|
-
pathname: storage, query: null, fragment: null,
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
44
|
const regexLiteral = (value) => value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
56
45
|
const workerCatalogTarget = (namespace) => {
|
|
57
46
|
const pathname = generatedPathname(`/${namespace}/*.md`);
|
|
@@ -74,22 +63,6 @@ const assertOpenPaths = (value, source) => {
|
|
|
74
63
|
}
|
|
75
64
|
return value;
|
|
76
65
|
};
|
|
77
|
-
const parsePromptAttributes = (encoded, source) => {
|
|
78
|
-
const attributes = JSON.parse(encoded);
|
|
79
|
-
if (attributes === null || typeof attributes !== "object" || Array.isArray(attributes)) {
|
|
80
|
-
throw new TypeError(`${source}: expected a JSON object`);
|
|
81
|
-
}
|
|
82
|
-
return attributes;
|
|
83
|
-
};
|
|
84
|
-
const promptSourceFromAttributes = (attributes, source) => {
|
|
85
|
-
const value = attributes.source;
|
|
86
|
-
if (value === undefined)
|
|
87
|
-
return null;
|
|
88
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
89
|
-
throw new TypeError(`${source}: source must be a non-empty string when present`);
|
|
90
|
-
}
|
|
91
|
-
return value;
|
|
92
|
-
};
|
|
93
66
|
// Per-emission action ceiling — OFF by default. `-1` (or unset/non-positive) = no cap:
|
|
94
67
|
// every generated op dispatches. Runaway degeneration is a sampler concern (repetition penalty),
|
|
95
68
|
// not grounds to drop already-generated work. A positive value is an operator ceiling a
|
|
@@ -149,10 +122,11 @@ const readMilliseconds = (key) => {
|
|
|
149
122
|
return value;
|
|
150
123
|
};
|
|
151
124
|
// {§provider-recovery} — how long one turn keeps re-issuing its provider call after a
|
|
152
|
-
// recoverable failure before the loop parks (0 parks at once),
|
|
153
|
-
//
|
|
125
|
+
// recoverable failure before the loop parks (0 parks at once), the first backoff delay, which
|
|
126
|
+
// doubles per failure, and that delay's ceiling.
|
|
154
127
|
const readProviderRecovery = () => readMilliseconds("PLURNK_SERVICE_PROVIDER_RECOVERY");
|
|
155
128
|
const readProviderRecoveryBackoff = () => readMilliseconds("PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF");
|
|
129
|
+
const readProviderRecoveryBackoffMax = () => readMilliseconds("PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF_MAX");
|
|
156
130
|
const RECOVERABLE_PROVIDER_FAILURES = new Set(["rate_limit", "network_failure", "deadline_exceeded", "resource_interrupted"]);
|
|
157
131
|
// The wall's abort reason — runLoop branches a mid-turn teardown to the 504 terminal on it.
|
|
158
132
|
export const LOOP_TIMEOUT_REASON = "loop_timeout";
|
|
@@ -221,7 +195,7 @@ class TurnRunner {
|
|
|
221
195
|
this.#warmWorkspace = warmWorkspace;
|
|
222
196
|
this.#dispatch = dispatch;
|
|
223
197
|
this.#resolveWorkerProviderIdentity = resolveWorkerProviderIdentity;
|
|
224
|
-
this.#materialization = new TurnMaterialization({ db: this.#db, weighContent: this.#weighContent });
|
|
198
|
+
this.#materialization = new TurnMaterialization({ db: this.#db, weighContent: this.#weighContent, mimetypes: this.#mimetypes });
|
|
225
199
|
this.#bareBatch = new BareBatchRunner({ db: this.#db, providerAttributions: this.#providerAttributions.bind(this), providerFailure: _a.#providerFailure });
|
|
226
200
|
this.#admitted = new AdmittedTurnExecutor({ db: this.#db, schemes: this.#schemes, notices: this.#notices, problems: this.#problems, dispatcher: this.#dispatcher, bareBatch: this.#bareBatch });
|
|
227
201
|
}
|
|
@@ -236,7 +210,6 @@ class TurnRunner {
|
|
|
236
210
|
workerId: args.workerId,
|
|
237
211
|
loopId: args.loopId,
|
|
238
212
|
packetCount: packetCount.count,
|
|
239
|
-
...taskTiming(packetCount),
|
|
240
213
|
});
|
|
241
214
|
}
|
|
242
215
|
// {§operator-grammar} — the operator's grammar text for this provider, or undefined when
|
|
@@ -262,8 +235,6 @@ class TurnRunner {
|
|
|
262
235
|
process.stderr.write(`plurnk-engine: operator grammar: ${alias || "(bare)"} → ${path} (${text.length} chars)\n`);
|
|
263
236
|
return text;
|
|
264
237
|
}
|
|
265
|
-
// A lineage's no-parent root; a root worker resolves to itself. Fail hard
|
|
266
|
-
// when corruption leaves a worker without one. {§worker-primary}
|
|
267
238
|
async #attemptAttributions(provider, context) {
|
|
268
239
|
const tags = Meta.composeAttributions(this.#schemes.attributions(context), this.#executors()?.attributions(context) ?? [], await this.#mimetypes.attributions(context), provider.attributions?.(context) ?? []);
|
|
269
240
|
return [...tags];
|
|
@@ -370,7 +341,7 @@ class TurnRunner {
|
|
|
370
341
|
// durable turn and completes it only after its ordered operations settle; model
|
|
371
342
|
// packets and provider metadata are optional inference evidence, not turn identity.
|
|
372
343
|
async #openTurnContainer(args, createdTurnIds) {
|
|
373
|
-
const { workspaceId, workerId, loopId,
|
|
344
|
+
const { workspaceId, workerId, loopId, invalidEmissionRecoveryEntryId } = args;
|
|
374
345
|
const workerName = await WorkerName.forId(this.#db, workerId);
|
|
375
346
|
const transientOpenLogEntryId = typeof invalidEmissionRecoveryEntryId === "number"
|
|
376
347
|
? invalidEmissionRecoveryEntryId
|
|
@@ -381,11 +352,11 @@ class TurnRunner {
|
|
|
381
352
|
// Turn-0 foists that belong to the Worker (catalog preview, AGENTS) gate
|
|
382
353
|
// on its first inference history, not on loop sequence: honest client or
|
|
383
354
|
// runtime administrative turns may precede the first provider exchange.
|
|
384
|
-
// Per-loop foists such as
|
|
385
|
-
// {§
|
|
386
|
-
// rather than the model-turn ordinal, prevents an overflow diversion
|
|
387
|
-
//
|
|
388
|
-
const
|
|
355
|
+
// Per-loop foists such as the initial message's publication
|
|
356
|
+
// ({§message-arrival}) fire once per loop: the inbox row's publication state,
|
|
357
|
+
// rather than the model-turn ordinal, prevents an overflow diversion from
|
|
358
|
+
// replaying a message and its automatic path READs.
|
|
359
|
+
const loopSequence = (await this.#db.engine_loop_sequence.get({ loop_id: loopId }))?.sequence ?? loopId;
|
|
389
360
|
const priorInference = await this.#db.engine_worker_has_inference_history.get({
|
|
390
361
|
worker_id: workerId,
|
|
391
362
|
});
|
|
@@ -400,7 +371,7 @@ class TurnRunner {
|
|
|
400
371
|
createdTurnIds.push(initializationTurn.id);
|
|
401
372
|
const initializationPolicies = initializationTurn === null
|
|
402
373
|
? []
|
|
403
|
-
: (await CapabilityPolicies.layers(this.#db, workspaceId)).map((layer) => layer.policy);
|
|
374
|
+
: (await CapabilityPolicies.layers(this.#db, workspaceId, loopId)).map((layer) => layer.policy);
|
|
404
375
|
const modelTurn = initializationTurn === null
|
|
405
376
|
? await Turn.open(this.#db, { loopId, producer: "model", kind: "inference" })
|
|
406
377
|
: null;
|
|
@@ -414,41 +385,29 @@ class TurnRunner {
|
|
|
414
385
|
throw new Error(`worker ${workerId} has no durable ambient observation boundary`);
|
|
415
386
|
}
|
|
416
387
|
const systemCtx = this.#schemeContext(args, initializationTurn?.id ?? modelTurn.id);
|
|
417
|
-
// {§prompt-entry} — the prompt entry exists before any turn of the loop
|
|
418
|
-
// runs; its `prompt` log row is published to the model turn below (one
|
|
419
|
-
// durable publication per loop, decided by that row).
|
|
420
|
-
const promptPublication = turnNumber === 1 && loopRow?.prompt_published === 0
|
|
421
|
-
&& typeof loopRow.prompt === "string" && loopRow.prompt.length > 0
|
|
422
|
-
? {
|
|
423
|
-
content: loopRow.prompt,
|
|
424
|
-
source: loopRow.prompt_source,
|
|
425
|
-
path: promptTarget(workerName, await PromptFrames.write(systemCtx, {
|
|
426
|
-
loopSequence: loopRow.sequence, ordinal: 1, content: loopRow.prompt,
|
|
427
|
-
source: loopRow.prompt_source, pathname: loopRow.prompt_pathname,
|
|
428
|
-
openPaths: assertOpenPaths(JSON.parse(loopRow.open_paths), `Loop ${loopId} open_paths`),
|
|
429
|
-
})),
|
|
430
|
-
openPaths: assertOpenPaths(JSON.parse(loopRow.open_paths), `Loop ${loopId} open_paths`),
|
|
431
|
-
}
|
|
432
|
-
: null;
|
|
433
388
|
const initializationStatements = [];
|
|
434
389
|
// {§worker-initialization-entry} — the worker's first turn is the worked
|
|
435
|
-
// example itself: the actual orienting operations and
|
|
390
|
+
// example itself: the actual orienting operations and ordinary NOTEs.
|
|
436
391
|
// {§turn0-agents-stunt} — the project AGENTS.md (materialized by LoopDocs as
|
|
437
|
-
// worker:///_plurnk/
|
|
392
|
+
// worker:///_plurnk/AGENTS.md) gets one foisted READ on the worker's first
|
|
438
393
|
// loop, so local repo guidance is visible turn-0 content. Global policy
|
|
439
394
|
// stays in the system prompt; nothing else is force-read.
|
|
440
395
|
if (initializationTurn !== null) {
|
|
396
|
+
initializationStatements.push({
|
|
397
|
+
op: "NOTE", aside: null, metadata: null, target: null, lineMarker: null,
|
|
398
|
+
body: `This turn surveys tooling and environment. The log records results; ops://${workerName}/${loopSequence}/${initializationTurn.sequence} contains the submitted OPs.`, position: UNKNOWN_POSITION,
|
|
399
|
+
});
|
|
441
400
|
const agentsEntry = await this.#db.crud_find_workspace_entry.get({
|
|
442
401
|
workspace_id: workspaceId,
|
|
443
402
|
scheme: "worker",
|
|
444
403
|
authority: "",
|
|
445
|
-
pathname: generatedPathname("/
|
|
404
|
+
pathname: generatedPathname("/AGENTS.md"),
|
|
446
405
|
});
|
|
447
406
|
if (agentsEntry !== undefined) {
|
|
448
407
|
const agentsTarget = {
|
|
449
|
-
kind: "url", raw: "worker:///_plurnk/
|
|
408
|
+
kind: "url", raw: "worker:///_plurnk/AGENTS.md", scheme: "worker",
|
|
450
409
|
username: null, password: null, hostname: null, port: null,
|
|
451
|
-
pathname: generatedPathname("/
|
|
410
|
+
pathname: generatedPathname("/AGENTS.md"), query: null, fragment: null,
|
|
452
411
|
};
|
|
453
412
|
const agentsRead = {
|
|
454
413
|
op: "READ", aside: null, target: agentsTarget,
|
|
@@ -458,9 +417,9 @@ class TurnRunner {
|
|
|
458
417
|
}
|
|
459
418
|
}
|
|
460
419
|
return {
|
|
461
|
-
workerName, transientOpenLogEntryId,
|
|
420
|
+
workerName, transientOpenLogEntryId, loopSequence, createdTurnIds,
|
|
462
421
|
initializationTurn, initializationPolicies, initializationStatements,
|
|
463
|
-
modelTurn, systemCtx,
|
|
422
|
+
modelTurn, systemCtx,
|
|
464
423
|
};
|
|
465
424
|
}
|
|
466
425
|
// The `_plurnk` scheme context for one turn. Threaded per turn, never engine
|
|
@@ -514,11 +473,11 @@ class TurnRunner {
|
|
|
514
473
|
return gitStatus;
|
|
515
474
|
}
|
|
516
475
|
// {§worker-initialization-entry} — the worker's first turn is the worked example
|
|
517
|
-
// itself: the actual orienting operations and
|
|
476
|
+
// itself: the actual orienting operations and ordinary NOTEs, executed as a
|
|
518
477
|
// complete turn before the model boundary.
|
|
519
478
|
async #runInitializationTurn(args, container, initializationTurn) {
|
|
520
479
|
const { provider, workspaceId, workerId, loopId, onDispatch, onSettled } = args;
|
|
521
|
-
const {
|
|
480
|
+
const { workerName, loopSequence, initializationStatements, initializationPolicies } = container;
|
|
522
481
|
// Turn-0 catalog preview (PLURNK_SERVICE_FILES_ITEMS, {§actor-boundary-catalog-preview}):
|
|
523
482
|
// Eight bodyless FIND surveys in the worker's packetless initialization turn establish the Agent
|
|
524
483
|
// Skills, the plurnk references, the enabled tools, agents, and members, then the project, commons,
|
|
@@ -530,32 +489,25 @@ class TurnRunner {
|
|
|
530
489
|
if (filesItems !== null) { // {§actor-boundary-catalog-preview} — once per worker
|
|
531
490
|
initializationStatements.push(...await this.#catalogSurveys(args, container, filesItems));
|
|
532
491
|
}
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
};
|
|
538
|
-
const pathname = `/${loopRow.sequence}/${initializationTurn.sequence}`;
|
|
539
|
-
await Turn.recordSource(this.#db, initializationTurn.id, "reasoning", ReasoningView.initialSource());
|
|
540
|
-
// {§reasoning-initial-read} — the pattern READ needs a text/plain projection to run the regex.
|
|
541
|
-
const pluck = await this.#mimetypes.getHandler("text/plain") !== null;
|
|
542
|
-
const reasoningRead = ReasoningView.initialRead(provider, loopRow.sequence, initializationTurn.sequence, pluck);
|
|
492
|
+
const pathname = `/${loopSequence}/${initializationTurn.sequence}`;
|
|
493
|
+
const reasoning = ReasoningView.initialSource();
|
|
494
|
+
await Turn.recordSource(this.#db, initializationTurn.id, "reasoning", reasoning);
|
|
495
|
+
const reasoningRead = ReasoningView.initialRead(provider, workerName, loopSequence, initializationTurn.sequence);
|
|
543
496
|
if (reasoningRead !== null)
|
|
544
497
|
initializationStatements.push(reasoningRead);
|
|
545
498
|
initializationStatements.push({
|
|
546
499
|
op: "READ", aside: "inspect this turn's emission", matcher: null, body: null, metadata: null,
|
|
547
500
|
target: {
|
|
548
|
-
kind: "url", raw: `ops://${pathname}`, scheme: "ops", pathname,
|
|
549
|
-
username: null, password: null, hostname:
|
|
501
|
+
kind: "url", raw: `ops://${workerName}${pathname}`, scheme: "ops", pathname,
|
|
502
|
+
username: null, password: null, hostname: workerName, port: null, query: null, fragment: null,
|
|
550
503
|
},
|
|
551
504
|
lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
|
|
552
505
|
});
|
|
553
|
-
// {§
|
|
506
|
+
// {§message-arrival} — the message reaches the model as an inbound SEND in the first
|
|
554
507
|
// model turn; initialization does not READ it a second time.
|
|
555
|
-
initializationStatements.push(task);
|
|
556
508
|
const admittedInitializationStatements = initializationStatements.filter((statement) => this.#capabilities.allowsAcross(statement, workspaceId, initializationPolicies));
|
|
557
|
-
const source = TurnOps.renderInternal(admittedInitializationStatements);
|
|
558
|
-
const admitted = TurnOps.parseInternal(source);
|
|
509
|
+
const source = admittedInitializationStatements.length === 0 ? "" : TurnOps.renderInternal(admittedInitializationStatements);
|
|
510
|
+
const admitted = [...PlurnkParser.parseReasoningNotes(reasoning), ...(source.length === 0 ? [] : TurnOps.parseInternal(source))];
|
|
559
511
|
const result = await this.executeAdmittedTurn({
|
|
560
512
|
statements: admitted,
|
|
561
513
|
source,
|
|
@@ -570,8 +522,8 @@ class TurnRunner {
|
|
|
570
522
|
onDispatch,
|
|
571
523
|
onSettled,
|
|
572
524
|
});
|
|
573
|
-
if (result.status !==
|
|
574
|
-
throw new Error(`initialization
|
|
525
|
+
if (result.status !== 200) {
|
|
526
|
+
throw new Error(`initialization returned ${result.status}; expected 200`);
|
|
575
527
|
}
|
|
576
528
|
}
|
|
577
529
|
// {§actor-boundary-catalog-preview} — the opening surveys, each admitted only when
|
|
@@ -608,11 +560,11 @@ class TurnRunner {
|
|
|
608
560
|
},
|
|
609
561
|
...this.#toolExpansions(workspaceId, initializationPolicies),
|
|
610
562
|
{
|
|
611
|
-
// {§a2a-
|
|
563
|
+
// {§a2a-catalog} — enabled outbound agents survey at
|
|
612
564
|
// alias level; each row's summary is the agent's identity line,
|
|
613
565
|
// the exact card stays pullable through READ a2a://<alias>.
|
|
614
566
|
op: "FIND", aside: null,
|
|
615
|
-
target: { kind: "url", raw: "worker:///_plurnk/
|
|
567
|
+
target: { kind: "url", raw: "worker:///_plurnk/a2a/*.md", scheme: "worker", username: null, password: null, hostname: null, port: null, pathname: generatedPathname("/a2a/*.md"), query: null, fragment: null },
|
|
616
568
|
metadata: null,
|
|
617
569
|
matcher: null, body: null, lineMarker: { marks: [1, -1] }, position: UNKNOWN_POSITION,
|
|
618
570
|
},
|
|
@@ -634,13 +586,13 @@ class TurnRunner {
|
|
|
634
586
|
position: UNKNOWN_POSITION,
|
|
635
587
|
},
|
|
636
588
|
{
|
|
637
|
-
op: "FIND", aside: "
|
|
589
|
+
op: "FIND", aside: "workspace knowledgebase entries",
|
|
638
590
|
target: { kind: "url", raw: "worker:///*", scheme: "worker", username: null, password: null, hostname: null, port: null, pathname: "/*", query: null, fragment: null },
|
|
639
591
|
metadata: null,
|
|
640
592
|
matcher: null, body: null, lineMarker: null, position: UNKNOWN_POSITION,
|
|
641
593
|
},
|
|
642
594
|
{
|
|
643
|
-
op: "FIND", aside: "
|
|
595
|
+
op: "FIND", aside: "worker knowledgebase entries",
|
|
644
596
|
target: { kind: "url", raw: `worker://${workerName}/*`, scheme: "worker", username: null, password: null, hostname: workerName, port: null, pathname: "/*", query: null, fragment: null },
|
|
645
597
|
metadata: null,
|
|
646
598
|
matcher: null, body: null, lineMarker: null, position: UNKNOWN_POSITION,
|
|
@@ -689,18 +641,26 @@ class TurnRunner {
|
|
|
689
641
|
container.createdTurnIds.push(modelTurn.id);
|
|
690
642
|
const { id: turnId, sequence: seq } = modelTurn;
|
|
691
643
|
const systemCtx = this.#schemeContext(args, turnId);
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
let nextActionIndex = await this.#readOpenPaths(args, turnId, prompts.openPaths, prompts.nextActionIndex);
|
|
644
|
+
const messages = await this.#publishMessages(args, turnId);
|
|
645
|
+
let nextActionIndex = await this.#readOpenPaths(args, turnId, messages.openPaths, messages.nextActionIndex);
|
|
695
646
|
// {§env-delta-log-pull} — materialize ambient observations before packet
|
|
696
647
|
// composition and reserve their action indices. {§exec-stream} owns the
|
|
697
648
|
// distinct byte-cursor path for this worker's streams.
|
|
698
|
-
// {§exec-
|
|
649
|
+
// {§exec-lifetime} — a `"turn"` lifetime: reap the worker's open turn-scoped streams (necessarily
|
|
699
650
|
// from a prior turn — this runs before the turn's own spawns) so a `<0>` never survives into
|
|
700
651
|
// the subsequent turn. The terminal output then surfaces initially visible via the stream-delta path.
|
|
701
652
|
await this.#reapTurnScopedStreams(workerId);
|
|
702
|
-
|
|
703
|
-
nextActionIndex +=
|
|
653
|
+
const ambientEntries = await this.#materialization.materializeEnvironmentDeltas({ workspaceId, workerId, loopId, turnId, fromSequence: nextActionIndex });
|
|
654
|
+
nextActionIndex += ambientEntries.length;
|
|
655
|
+
const streamEntries = await this.#materialization.materializeStreamDeltas({ workspaceId, workerId, loopId, turnId, fromSequence: nextActionIndex });
|
|
656
|
+
nextActionIndex += streamEntries.length;
|
|
657
|
+
await Turn.observeCompletions(this.#db, turnId);
|
|
658
|
+
// {§notifications-log-entry-notify}: materialized observations are
|
|
659
|
+
// ordinary committed log rows, not packet-only content.
|
|
660
|
+
for (const id of [...ambientEntries, ...streamEntries]) {
|
|
661
|
+
args.onDispatch?.(id);
|
|
662
|
+
await args.onSettled?.(id);
|
|
663
|
+
}
|
|
704
664
|
// The post-reconciliation Git snapshot above is threaded into the packet
|
|
705
665
|
// and every budget rebuild; overflow never shells again.
|
|
706
666
|
// Notices are non-terminal observations, never operation-failure truth.
|
|
@@ -708,68 +668,42 @@ class TurnRunner {
|
|
|
708
668
|
const notices = this.#notices.drain(loopId)
|
|
709
669
|
.filter((event) => event.level !== "info");
|
|
710
670
|
// Build the model request packet ({§packet-stored-shape}). The log build
|
|
711
|
-
// queries log_entries scoped to the worker
|
|
712
|
-
//
|
|
671
|
+
// queries log_entries scoped to the worker, including this turn's newly
|
|
672
|
+
// published message arrivals.
|
|
713
673
|
const facts = { turnId, seq, gitStatus, notices, transientOpenLogEntryId: container.transientOpenLogEntryId, promptProjection: "automatic" };
|
|
714
674
|
let packet = await this.#buildPacket(args, facts);
|
|
715
675
|
// {§context-output-admission} — output admission changes no operation
|
|
716
|
-
// outcome, authored
|
|
676
|
+
// outcome, authored memory, or turn identity.
|
|
717
677
|
if (await this.#packets.admitOutput(packet, turnId))
|
|
718
678
|
packet = await this.#buildPacket(args, facts);
|
|
719
|
-
return { ...facts, createdTurnIds: container.createdTurnIds, loopSeq, systemCtx, nextActionIndex, packet };
|
|
679
|
+
return { ...facts, createdTurnIds: container.createdTurnIds, loopSeq: container.loopSequence, systemCtx, nextActionIndex, packet };
|
|
720
680
|
}
|
|
721
|
-
// Pre-model writes. Each
|
|
722
|
-
//
|
|
723
|
-
//
|
|
724
|
-
//
|
|
725
|
-
|
|
681
|
+
// Pre-model writes. Each message the model has not seen yet becomes an inbound `SEND`
|
|
682
|
+
// row; model operations continue the same turn sequence after these rows. Returns the
|
|
683
|
+
// next action index and the messages' open paths.
|
|
684
|
+
// {§message-loop-containment}: the loop contains every message that arrived before this
|
|
685
|
+
// boundary. Publish each unpublished inbox row oldest-first, exactly once, as an inbound
|
|
686
|
+
// SEND row ({§message-arrival}); its selected paths ride along for the READs that follow.
|
|
687
|
+
async #publishMessages({ workerId, loopId, onDispatch, onSettled }, turnId) {
|
|
726
688
|
let nextActionIndex = 1;
|
|
727
689
|
const openPaths = [];
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
loopId,
|
|
733
|
-
|
|
734
|
-
sequence: nextActionIndex++,
|
|
735
|
-
target: promptPublication.path,
|
|
736
|
-
content: promptPublication.content,
|
|
737
|
-
source: promptPublication.source,
|
|
738
|
-
});
|
|
739
|
-
onDispatch?.(promptLogId);
|
|
740
|
-
await onSettled?.(promptLogId);
|
|
741
|
-
}
|
|
742
|
-
// {§prompt-loop-containment}: the loop contains every prompt that arrived
|
|
743
|
-
// while it ran. Publish each undelivered frame oldest-first exactly once.
|
|
744
|
-
const prefix = promptLoopPrefix(loopSeq);
|
|
745
|
-
const undelivered = (await this.#db.drain_undelivered_prompts_for_loop.all({
|
|
746
|
-
worker_id: workerId,
|
|
747
|
-
pattern: `${prefix}%`,
|
|
748
|
-
prefix_len: prefix.length,
|
|
749
|
-
loop_id: loopId,
|
|
750
|
-
}))
|
|
751
|
-
.filter((row) => typeof row.content === "string" && row.content.length > 0);
|
|
752
|
-
for (const injectedRow of undelivered) {
|
|
753
|
-
const attributes = parsePromptAttributes(injectedRow.attributes, `Prompt ${injectedRow.pathname} attributes`);
|
|
754
|
-
if (attributes.openPaths !== undefined) {
|
|
755
|
-
openPaths.push(...assertOpenPaths(attributes.openPaths, `Prompt ${injectedRow.pathname} openPaths`));
|
|
756
|
-
}
|
|
757
|
-
const promptLogId = await this.#materialization.writePromptLog({
|
|
758
|
-
workerId,
|
|
759
|
-
loopId,
|
|
760
|
-
turnId,
|
|
761
|
-
sequence: nextActionIndex++,
|
|
762
|
-
target: promptTarget(workerName, injectedRow.pathname),
|
|
763
|
-
content: injectedRow.content,
|
|
764
|
-
source: promptSourceFromAttributes(attributes, `Prompt ${injectedRow.pathname} attributes`),
|
|
690
|
+
const unpublished = await this.#db.drain_unpublished_messages_for_loop.all({ loop_id: loopId });
|
|
691
|
+
for (const message of unpublished) {
|
|
692
|
+
openPaths.push(...assertOpenPaths(JSON.parse(message.open_paths), `Message ${message.id} open_paths`));
|
|
693
|
+
const logEntryId = await this.#materialization.writeArrivalLog({
|
|
694
|
+
workerId, loopId, turnId, sequence: nextActionIndex++, body: message.body, source: message.source, resource: message.path,
|
|
695
|
+
selfAddressed: message.source !== null && message.source === message.durable_path,
|
|
765
696
|
});
|
|
766
|
-
|
|
767
|
-
|
|
697
|
+
const published = await this.#db.drain_publish_message.get({ id: message.id, log_entry_id: logEntryId });
|
|
698
|
+
if (published === undefined)
|
|
699
|
+
throw new Error(`TurnRunner.#publishMessages: message ${message.id} was already published`);
|
|
700
|
+
onDispatch?.(logEntryId);
|
|
701
|
+
await onSettled?.(logEntryId);
|
|
768
702
|
}
|
|
769
703
|
return { nextActionIndex, openPaths };
|
|
770
704
|
}
|
|
771
|
-
// {§methods-loop-run-open-paths}: selected workspace paths belong to the
|
|
772
|
-
//
|
|
705
|
+
// {§methods-loop-run-open-paths}: selected workspace paths belong to the message.
|
|
706
|
+
// Publish it, then dispatch ordinary core READs in that same turn;
|
|
773
707
|
// missing/non-member paths retain their normal 4xx. Returns the next action index.
|
|
774
708
|
async #readOpenPaths({ workspaceId, workerId, loopId, onDispatch, onSettled }, turnId, openPaths, fromSequence) {
|
|
775
709
|
let nextActionIndex = fromSequence;
|
|
@@ -825,9 +759,7 @@ class TurnRunner {
|
|
|
825
759
|
const recoveryBudget = readProviderRecovery();
|
|
826
760
|
const recoveryBackoff = readProviderRecoveryBackoff();
|
|
827
761
|
const providerSignal = this.#loopSignal(loopId) ?? signal;
|
|
828
|
-
|
|
829
|
-
const { client } = await WorkspaceSettings.read(this.#db, workspaceId);
|
|
830
|
-
const { workerId: providerWorkerId, primaryWorkerId } = await this.#resolveWorkerProviderIdentity(workerId);
|
|
762
|
+
const { workerId: providerWorkerId } = await this.#resolveWorkerProviderIdentity(workerId);
|
|
831
763
|
return {
|
|
832
764
|
wire,
|
|
833
765
|
response: undefined,
|
|
@@ -847,9 +779,7 @@ class TurnRunner {
|
|
|
847
779
|
recoveryBudget,
|
|
848
780
|
recoveryBackoff,
|
|
849
781
|
signal: providerSignal,
|
|
850
|
-
client,
|
|
851
782
|
providerWorkerId,
|
|
852
|
-
primaryWorkerId,
|
|
853
783
|
turnWireAccounting: [],
|
|
854
784
|
};
|
|
855
785
|
}
|
|
@@ -902,7 +832,6 @@ class TurnRunner {
|
|
|
902
832
|
railEvidence: attempts.railEvidence,
|
|
903
833
|
emissionAttempts: attempts.emissionAttempts,
|
|
904
834
|
signal: attempts.signal,
|
|
905
|
-
primaryWorkerId: attempts.primaryWorkerId,
|
|
906
835
|
};
|
|
907
836
|
if (emission.split.packetAssistant.reasoning?.length) {
|
|
908
837
|
await Turn.recordSource(this.#db, request.turnId, "reasoning", emission.split.packetAssistant.reasoning, { modelCallId: emission.modelCallId });
|
|
@@ -923,7 +852,6 @@ class TurnRunner {
|
|
|
923
852
|
const attributionContext = Object.freeze({
|
|
924
853
|
workspaceId: String(workspaceId),
|
|
925
854
|
workerId: attempts.providerWorkerId,
|
|
926
|
-
primaryWorkerId: attempts.primaryWorkerId,
|
|
927
855
|
loop: request.loopSeq,
|
|
928
856
|
turn: request.seq,
|
|
929
857
|
attempt: attempts.modelCallSequence,
|
|
@@ -1047,27 +975,19 @@ class TurnRunner {
|
|
|
1047
975
|
// asserted whether it resolved or failed.
|
|
1048
976
|
async #generate({ provider, workspaceId }, request, attempts, modelCall, reasoning, strikeStreak) {
|
|
1049
977
|
return await observed(// {§observability-boundary}
|
|
1050
|
-
|
|
978
|
+
genAiRequestName(provider.model), { model: provider.model, attempt: attempts.modelCallSequence }, async (span) => {
|
|
1051
979
|
try {
|
|
1052
980
|
await this.#packets.recordObservations(request.packet);
|
|
1053
981
|
const generated = await provider.generate({
|
|
1054
982
|
messages: attempts.wire.messages,
|
|
1055
983
|
workerId: attempts.providerWorkerId,
|
|
1056
|
-
|
|
984
|
+
workspaceId: String(workspaceId),
|
|
1057
985
|
signal: attempts.signal,
|
|
1058
986
|
grammar: attempts.railGrammar,
|
|
1059
|
-
strikes: strikeStreak,
|
|
1060
|
-
attributions: attempts.attributions.length > 0
|
|
1061
|
-
? attempts.attributions
|
|
1062
|
-
: undefined,
|
|
1063
|
-
client: attempts.client ?? undefined,
|
|
1064
|
-
workspaceId: String(workspaceId),
|
|
1065
|
-
loop: request.loopSeq,
|
|
1066
|
-
turn: request.seq,
|
|
1067
987
|
observeRequest: reasoning.observeRequest,
|
|
1068
988
|
observeReasoning: reasoning.observeReasoning,
|
|
1069
989
|
callKind: "emission",
|
|
1070
|
-
}); // {§provider-surface-generate} {§provider-guarantees-signal-wired} {§provider-guarantees-serial-attempts} {§attribution}
|
|
990
|
+
}); // {§provider-surface-generate} {§provider-guarantees-signal-wired} {§provider-guarantees-serial-attempts} {§attribution}
|
|
1071
991
|
modelCall.assertAccounting(generated.accounting);
|
|
1072
992
|
attempts.callInFlight = false;
|
|
1073
993
|
recordCounter(PROVIDER_CALLS, {
|
|
@@ -1086,7 +1006,7 @@ class TurnRunner {
|
|
|
1086
1006
|
}
|
|
1087
1007
|
throw error;
|
|
1088
1008
|
}
|
|
1089
|
-
}, genAiRequestOptions(ProviderInstantiate.
|
|
1009
|
+
}, genAiRequestOptions(ProviderInstantiate.providerIdOf(provider) ?? "other", provider.model));
|
|
1090
1010
|
}
|
|
1091
1011
|
// {§provider-recovery} — a transient provider failure never ends the loop: record
|
|
1092
1012
|
// it, wait, and re-issue the same turn; once the budget is spent the failure
|
|
@@ -1119,7 +1039,7 @@ class TurnRunner {
|
|
|
1119
1039
|
source: "provider",
|
|
1120
1040
|
result: failure,
|
|
1121
1041
|
});
|
|
1122
|
-
const wait = Math.min(attempts.recoveryBackoff * 2 ** (attempts.recoveryFailures - 1),
|
|
1042
|
+
const wait = Math.min(attempts.recoveryBackoff * 2 ** (attempts.recoveryFailures - 1), readProviderRecoveryBackoffMax());
|
|
1123
1043
|
this.#notices.push(workspaceId, workerId, loopId, {
|
|
1124
1044
|
source: "engine:provider",
|
|
1125
1045
|
kind: "provider_unavailable",
|
|
@@ -1242,11 +1162,14 @@ class TurnRunner {
|
|
|
1242
1162
|
if (attempts.parked) {
|
|
1243
1163
|
// {§provider-recovery} — the recovery budget is spent: the loop parks exactly like a
|
|
1244
1164
|
// [202] wait and resumes on the next prompt or wake; the failure stays durable.
|
|
1165
|
+
// {§loop-attendance} — unattended, nothing will wake it, so LoopDriver concludes instead
|
|
1166
|
+
// and the notice says that rather than promising a resumption nobody can deliver.
|
|
1167
|
+
const { attended } = await LoopPolicyReader.read(this.#db, loopId);
|
|
1245
1168
|
this.#notices.push(workspaceId, workerId, loopId, {
|
|
1246
1169
|
source: "engine:provider",
|
|
1247
1170
|
kind: "provider_unavailable",
|
|
1248
1171
|
level: "error",
|
|
1249
|
-
message: `${recorded.result.problem?.title ?? "Provider failure"}: the ${Math.round(attempts.recoveryBudget / 1000)}s recovery budget is spent; the loop is parked and resumes on the next prompt or wake.`,
|
|
1172
|
+
message: `${recorded.result.problem?.title ?? "Provider failure"}: the ${Math.round(attempts.recoveryBudget / 1000)}s recovery budget is spent; ${attended ? "the loop is parked and resumes on the next prompt or wake" : "this run is unattended, so the loop ends here"}.`,
|
|
1250
1173
|
});
|
|
1251
1174
|
return turnResult(request, 202, { providerParked: true, providerFailure: recorded.result, emissionAttempts });
|
|
1252
1175
|
}
|
|
@@ -1349,7 +1272,7 @@ class TurnRunner {
|
|
|
1349
1272
|
}
|
|
1350
1273
|
// Non-fatal provider transport notices on an accepted turn. Forward each
|
|
1351
1274
|
// Notice with a content-offset `line:col`;
|
|
1352
|
-
// the model resolves it against its own emission — READ ops
|
|
1275
|
+
// the model resolves it against its own emission — READ ops://<worker>/<loop>/<turn> at the
|
|
1353
1276
|
// cited lines ({§turn-ops-entry}) — not an embedded snippet that would duplicate the emission.
|
|
1354
1277
|
for (const notice of response.notices ?? []) {
|
|
1355
1278
|
const located = typeof notice.position === "number"
|
|
@@ -1419,9 +1342,9 @@ class TurnRunner {
|
|
|
1419
1342
|
maxCommands,
|
|
1420
1343
|
recoverableParseErrors: split.recoverableParseErrors,
|
|
1421
1344
|
emptyTurn: split.emptyTurn,
|
|
1345
|
+
proseAnswer: split.proseAnswer,
|
|
1422
1346
|
bare: {
|
|
1423
1347
|
provider: childProvider,
|
|
1424
|
-
primaryWorkerId: emission.primaryWorkerId,
|
|
1425
1348
|
loopSequence: request.loopSeq,
|
|
1426
1349
|
turnSequence: request.seq,
|
|
1427
1350
|
signal: emission.signal,
|
|
@@ -1494,7 +1417,7 @@ class TurnRunner {
|
|
|
1494
1417
|
});
|
|
1495
1418
|
}
|
|
1496
1419
|
else {
|
|
1497
|
-
parseErrors.push({ message: err.message, line: err.line, column: err.column, source: err.source
|
|
1420
|
+
parseErrors.push({ message: err.message, line: err.line, column: err.column, source: err.source });
|
|
1498
1421
|
}
|
|
1499
1422
|
}
|
|
1500
1423
|
else {
|
|
@@ -1503,34 +1426,69 @@ class TurnRunner {
|
|
|
1503
1426
|
}
|
|
1504
1427
|
}
|
|
1505
1428
|
}
|
|
1506
|
-
//
|
|
1507
|
-
//
|
|
1429
|
+
// {§unparsed-tail-boundary} — the lexer's one boundary fact: from `unparsedTail.from` on,
|
|
1430
|
+
// nothing was read. The statements that closed before it are ordinary facts and run; the
|
|
1431
|
+
// loss itself is one more hard diagnostic, a failed row the model sees. An emission that
|
|
1432
|
+
// lost its boundary before any statement closed has nothing admissible and is resampled.
|
|
1508
1433
|
const tail = parsed.unparsedTail;
|
|
1509
1434
|
if (tail !== undefined) {
|
|
1510
1435
|
hasUnparsedTail = true;
|
|
1511
1436
|
parseErrors.push({ message: tail.reason, line: tail.from.line, column: tail.from.column, source: "grammar" });
|
|
1512
1437
|
}
|
|
1513
1438
|
}
|
|
1439
|
+
// {§prose-conclusion} — a response whose content is prose (no operation, no attempt at one,
|
|
1440
|
+
// not cut at the output allowance) is the model's answer: a SEND to the open messages.
|
|
1441
|
+
// {§quotation} a reply wrapped whole in one markdown fence is delivered as its content.
|
|
1442
|
+
const wrapped = /^(`{3,}|~{3,})(?:markdown|md)[ \t]*\n([\s\S]*?)\n\1[ \t]*$/u.exec(assistant.content.trim());
|
|
1443
|
+
const prose = (wrapped?.[2] ?? assistant.content).trim();
|
|
1444
|
+
const concludes = preParsedOps === undefined
|
|
1445
|
+
&& ops.length === 0
|
|
1446
|
+
&& !hasUnparsedTail
|
|
1447
|
+
&& prose.length > 0
|
|
1448
|
+
&& assistant.finishReason !== "length"
|
|
1449
|
+
&& parseErrors.every((error) => error.message === PlurnkParser.NO_VALID_OPERATION)
|
|
1450
|
+
&& PlurnkParser.operationAttempt(assistant.content, executors) === null
|
|
1451
|
+
// {§quotation} an answer says something of its own: a reply that is nothing but quoted
|
|
1452
|
+
// material is a misfenced program, not prose (operator, 2026-09-18).
|
|
1453
|
+
&& PlurnkParser.unquoted(prose, executors).trim().length > 0
|
|
1454
|
+
// {§quotation} an operation fence that merely missed column zero is a misplaced program,
|
|
1455
|
+
// never an answer: the loop continues and the next packet carries the parser's word.
|
|
1456
|
+
&& !parseNotices.some(({ message }) => (message ?? "").includes("must start its line to run"));
|
|
1457
|
+
const proseAnswer = concludes
|
|
1458
|
+
? { op: "SEND", aside: null, target: null, metadata: null, lineMarker: null, body: { raw: prose, json: null }, position: { line: 1, column: 0 } }
|
|
1459
|
+
: null;
|
|
1460
|
+
if (proseAnswer !== null) {
|
|
1461
|
+
parseErrors.length = 0;
|
|
1462
|
+
ops.push(proseAnswer);
|
|
1463
|
+
}
|
|
1464
|
+
// The statements the content itself closed: a lost boundary is admissible only behind one
|
|
1465
|
+
// of these, never behind a reasoning NOTE alone ({§reasoning-notes}).
|
|
1466
|
+
const contentStatementCount = ops.filter(({ position }) => position.line > 0).length;
|
|
1467
|
+
const reasoning = assistant.reasoning ?? null;
|
|
1468
|
+
const notes = reasoning === null ? [] : PlurnkParser.parseReasoningNotes(reasoning);
|
|
1469
|
+
ops.unshift(...notes);
|
|
1470
|
+
if (notes.length > 0) {
|
|
1471
|
+
// A reasoned NOTE is an operation even when the content contains no program.
|
|
1472
|
+
for (let index = parseErrors.length - 1; index >= 0; index--) {
|
|
1473
|
+
if (parseErrors[index].message === PlurnkParser.NO_VALID_OPERATION)
|
|
1474
|
+
parseErrors.splice(index, 1);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1514
1477
|
const sourceStatementCount = ops.filter(({ position }) => position.line > 0).length;
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
//
|
|
1518
|
-
|
|
1519
|
-
const recoverableParseErrors = trustworthyBoundary
|
|
1520
|
-
? parseErrors.filter((error) => error.code !== "invalid-turn-structure").toSorted(comparePosition)
|
|
1521
|
-
: [];
|
|
1478
|
+
// {§turn-shape} — every hard diagnostic is recoverable and rides with the admitted program
|
|
1479
|
+
// as a failed row; a lost boundary refuses only what follows it. The harness admits every
|
|
1480
|
+
// program whose meaning it can determine and reports what it could not read.
|
|
1481
|
+
const recoverableParseErrors = [...parseErrors].toSorted(comparePosition);
|
|
1522
1482
|
// {§empty-turn} — no operation and no other hard error: admitted as an empty turn, never
|
|
1523
|
-
// resampled; its advisories ({§bare-heading-advisory}) ride as notices.
|
|
1483
|
+
// resampled; its advisories ({§bare-heading-advisory}) ride as notices. A boundary lost
|
|
1484
|
+
// before any statement closed is not an empty turn: the model tried, and is resampled.
|
|
1524
1485
|
const emptyTurn = preParsedOps === undefined
|
|
1525
|
-
&&
|
|
1486
|
+
&& !hasUnparsedTail
|
|
1526
1487
|
&& sourceStatementCount === 0
|
|
1527
1488
|
&& parseErrors.every((error) => error.message === PlurnkParser.NO_VALID_OPERATION);
|
|
1528
1489
|
const emissionValid = preParsedOps !== undefined
|
|
1529
1490
|
|| emptyTurn
|
|
1530
|
-
|| (
|
|
1531
|
-
&& sourceStatementCount > 0
|
|
1532
|
-
&& recoverableParseErrors.length === parseErrors.length);
|
|
1533
|
-
const reasoning = assistant.reasoning ?? null;
|
|
1491
|
+
|| (hasUnparsedTail ? contentStatementCount > 0 : sourceStatementCount > 0);
|
|
1534
1492
|
return {
|
|
1535
1493
|
packetAssistant: { content: assistant.content, ops, reasoning },
|
|
1536
1494
|
sourceBacked: preParsedOps === undefined,
|
|
@@ -1538,18 +1496,19 @@ class TurnRunner {
|
|
|
1538
1496
|
parseErrors,
|
|
1539
1497
|
recoverableParseErrors: emissionValid && !emptyTurn ? recoverableParseErrors : [],
|
|
1540
1498
|
emptyTurn,
|
|
1499
|
+
proseAnswer,
|
|
1541
1500
|
parseNotices,
|
|
1542
1501
|
// The ANTLR model-turn parser is authoritative. At least one source
|
|
1543
|
-
// operation is required;
|
|
1502
|
+
// operation is required; lifecycle omission continues silently. Bounded
|
|
1544
1503
|
// statement failures become durable operation results.
|
|
1545
|
-
//
|
|
1546
|
-
//
|
|
1504
|
+
// A boundary lost before any statement closed rejects; after one, the
|
|
1505
|
+
// statements run and the loss is a row. Pre-parsed ops are Mock's trusted test seam.
|
|
1547
1506
|
emissionValid,
|
|
1548
1507
|
};
|
|
1549
1508
|
}
|
|
1550
1509
|
// #note12 — plugin reference docs are materialized beneath
|
|
1551
1510
|
// worker:///_plurnk/plurnk/ by LoopDocs.
|
|
1552
|
-
// {§exec-
|
|
1511
|
+
// {§exec-lifetime} — a `"turn"` lifetime: abort the worker's open turn-scoped streams via their
|
|
1553
1512
|
// owning scheme (the same registry-routed abort the total reap uses). Called at each pre-turn
|
|
1554
1513
|
// before the turn's own spawns, so every open turn-scoped sub here is from a prior turn — it
|
|
1555
1514
|
// never survives into the subsequent turn. Fire-and-forget: the spawn finalizes async and its
|