@plurnk/plurnk-service 1.29.0 → 3.0.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 +14 -33
- package/INSTALL.md +68 -17
- package/README.md +9 -7
- package/SPEC.md +503 -741
- package/dist/build-info.json +1 -1
- package/dist/content/body-preview.d.ts.map +1 -1
- package/dist/content/body-preview.js +11 -2
- package/dist/content/body-preview.js.map +1 -1
- package/dist/content/edit-receipt.d.ts +1 -1
- package/dist/content/edit-receipt.d.ts.map +1 -1
- package/dist/content/edit-receipt.js +1 -1
- package/dist/content/edit-receipt.js.map +1 -1
- package/dist/content/line-marker.js +1 -1
- package/dist/content/line-marker.js.map +1 -1
- package/dist/content/path-mimetype.js +1 -1
- package/dist/content/path-mimetype.js.map +1 -1
- package/dist/content/read-projector.d.ts.map +1 -1
- package/dist/content/read-projector.js +3 -12
- package/dist/content/read-projector.js.map +1 -1
- package/dist/core/AdministrativeLoop.d.ts +1 -1
- package/dist/core/AdministrativeLoop.d.ts.map +1 -1
- package/dist/core/AdministrativeLoop.js +2 -6
- package/dist/core/AdministrativeLoop.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts +4 -3
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +19 -17
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/BareBatchRunner.d.ts +2 -2
- package/dist/core/BareBatchRunner.d.ts.map +1 -1
- package/dist/core/BareBatchRunner.js.map +1 -1
- package/dist/core/BudgetReadout.d.ts +1 -0
- package/dist/core/BudgetReadout.d.ts.map +1 -1
- package/dist/core/BudgetReadout.js +12 -0
- package/dist/core/BudgetReadout.js.map +1 -1
- package/dist/core/CapabilityPolicies.d.ts +2 -4
- package/dist/core/CapabilityPolicies.d.ts.map +1 -1
- package/dist/core/CapabilityPolicies.js +3 -23
- package/dist/core/CapabilityPolicies.js.map +1 -1
- package/dist/core/CapabilityResolver.d.ts +9 -2
- package/dist/core/CapabilityResolver.d.ts.map +1 -1
- package/dist/core/CapabilityResolver.js +34 -5
- package/dist/core/CapabilityResolver.js.map +1 -1
- package/dist/core/ChannelWrite.d.ts +0 -2
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js.map +1 -1
- package/dist/core/ClientInteractions.d.ts +3 -2
- package/dist/core/ClientInteractions.d.ts.map +1 -1
- package/dist/core/ClientInteractions.js +21 -12
- package/dist/core/ClientInteractions.js.map +1 -1
- package/dist/core/ClientInteractions.sql +8 -2
- package/dist/core/CoreSchemeServices.d.ts +1 -0
- 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 +1 -1
- package/dist/core/DataStatementRunner.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +3 -2
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +15 -21
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Engine.d.ts +2 -2
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +4 -3
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/EnvFlags.d.ts.map +1 -1
- package/dist/core/EnvFlags.js +4 -3
- package/dist/core/EnvFlags.js.map +1 -1
- package/dist/core/ExecutorRegistry.d.ts +3 -17
- package/dist/core/ExecutorRegistry.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.js +6 -6
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/FabricatedLog.js +1 -1
- package/dist/core/FabricatedLog.js.map +1 -1
- package/dist/core/HostPaths.d.ts +2 -1
- package/dist/core/HostPaths.d.ts.map +1 -1
- package/dist/core/HostPaths.js +14 -2
- package/dist/core/HostPaths.js.map +1 -1
- package/dist/core/KillHandler.js +1 -1
- package/dist/core/KillHandler.js.map +1 -1
- package/dist/core/LogVisibility.d.ts.map +1 -1
- package/dist/core/LogVisibility.js +8 -17
- package/dist/core/LogVisibility.js.map +1 -1
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +4 -6
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopLifecycle.d.ts.map +1 -1
- package/dist/core/LoopLifecycle.js +4 -9
- package/dist/core/LoopLifecycle.js.map +1 -1
- package/dist/core/LoopLifecycle.sql +6 -6
- package/dist/core/OperatorConfig.d.ts +1 -0
- package/dist/core/OperatorConfig.d.ts.map +1 -1
- package/dist/core/OperatorConfig.js +10 -2
- package/dist/core/OperatorConfig.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts +5 -7
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +49 -119
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PacketBuilder.sql +15 -0
- package/dist/core/ProposalLifecycle.d.ts +1 -1
- package/dist/core/ProposalLifecycle.d.ts.map +1 -1
- package/dist/core/ProposalLifecycle.js +18 -20
- package/dist/core/ProposalLifecycle.js.map +1 -1
- package/dist/core/ProposalPolicies.d.ts +6 -0
- package/dist/core/ProposalPolicies.d.ts.map +1 -0
- package/dist/core/ProposalPolicies.js +28 -0
- package/dist/core/ProposalPolicies.js.map +1 -0
- package/dist/core/ProviderInstantiate.d.ts.map +1 -1
- package/dist/core/ProviderInstantiate.js +3 -4
- package/dist/core/ProviderInstantiate.js.map +1 -1
- package/dist/core/ResourceSelector.js +2 -2
- package/dist/core/ResourceSelector.js.map +1 -1
- package/dist/core/ResourceTransfers.js +3 -3
- package/dist/core/ResourceTransfers.js.map +1 -1
- package/dist/core/RuntimeWorker.sql +1 -2
- package/dist/core/SchemeRegistry.d.ts +5 -4
- package/dist/core/SchemeRegistry.d.ts.map +1 -1
- package/dist/core/SchemeRegistry.js +11 -12
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/ToolInputSchema.d.ts +1 -0
- package/dist/core/ToolInputSchema.d.ts.map +1 -1
- package/dist/core/ToolInputSchema.js +8 -2
- 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 +12 -6
- package/dist/core/ToolResources.js.map +1 -1
- package/dist/core/Turn.js +1 -1
- package/dist/core/Turn.js.map +1 -1
- package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
- package/dist/core/TurnDispositionHandler.js +1 -7
- package/dist/core/TurnDispositionHandler.js.map +1 -1
- package/dist/core/TurnMaterialization.js +1 -1
- package/dist/core/TurnMaterialization.js.map +1 -1
- package/dist/core/TurnOps.d.ts +1 -1
- package/dist/core/TurnOps.d.ts.map +1 -1
- package/dist/core/TurnOps.js +4 -12
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts +1 -2
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +85 -81
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/WorkerControlHandler.d.ts.map +1 -1
- package/dist/core/WorkerControlHandler.js +1 -8
- package/dist/core/WorkerControlHandler.js.map +1 -1
- package/dist/core/WorkerName.d.ts +1 -0
- package/dist/core/WorkerName.d.ts.map +1 -1
- package/dist/core/WorkerName.js +2 -0
- package/dist/core/WorkerName.js.map +1 -1
- package/dist/core/WorkerName.sql +2 -2
- package/dist/core/WorkerOwners.d.ts +13 -0
- package/dist/core/WorkerOwners.d.ts.map +1 -0
- package/dist/core/WorkerOwners.js +44 -0
- package/dist/core/WorkerOwners.js.map +1 -0
- package/dist/core/WorkerOwners.sql +55 -0
- package/dist/core/caps/DbNotifyCaps.js +2 -2
- package/dist/core/caps/DbNotifyCaps.js.map +1 -1
- package/dist/core/caps/DbProjectionCaps.js +1 -1
- package/dist/core/caps/DbProjectionCaps.js.map +1 -1
- package/dist/core/env-catalog.d.ts +3 -0
- package/dist/core/env-catalog.d.ts.map +1 -1
- package/dist/core/env-catalog.js +44 -9
- package/dist/core/env-catalog.js.map +1 -1
- package/dist/core/env-defaults.d.ts +2 -1
- package/dist/core/env-defaults.d.ts.map +1 -1
- package/dist/core/env-defaults.js +17 -9
- package/dist/core/env-defaults.js.map +1 -1
- package/dist/core/fork.sql +3 -4
- package/dist/core/packet-inject.js +0 -2
- package/dist/core/packet-inject.js.map +1 -1
- package/dist/core/packet-wire.d.ts +2 -11
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +31 -111
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/plurnk-uri.d.ts +1 -1
- package/dist/core/plurnk-uri.d.ts.map +1 -1
- package/dist/core/plurnk-uri.js +4 -4
- package/dist/core/plurnk-uri.js.map +1 -1
- package/dist/core/scheme-types.d.ts +2 -1
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/core/types.d.ts +0 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/unregistered-scheme.d.ts +1 -3
- package/dist/core/unregistered-scheme.d.ts.map +1 -1
- package/dist/core/unregistered-scheme.js +3 -11
- package/dist/core/unregistered-scheme.js.map +1 -1
- package/dist/evidence/EvidenceReader.d.ts +14 -0
- package/dist/evidence/EvidenceReader.d.ts.map +1 -0
- package/dist/evidence/EvidenceReader.js +137 -0
- package/dist/evidence/EvidenceReader.js.map +1 -0
- package/dist/{digest → evidence}/digest.sql +1 -2
- package/dist/schemes/EffectPolicy.d.ts.map +1 -1
- package/dist/schemes/EffectPolicy.js +1 -10
- package/dist/schemes/EffectPolicy.js.map +1 -1
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +19 -26
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts +1 -1
- package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +11 -17
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +14 -11
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/QuestionTool.d.ts.map +1 -1
- package/dist/schemes/QuestionTool.js +1 -3
- package/dist/schemes/QuestionTool.js.map +1 -1
- package/dist/schemes/{Skill.d.ts → ResourceTreeScheme.d.ts} +5 -6
- package/dist/schemes/ResourceTreeScheme.d.ts.map +1 -0
- package/dist/schemes/{Skill.js → ResourceTreeScheme.js} +63 -43
- package/dist/schemes/ResourceTreeScheme.js.map +1 -0
- package/dist/schemes/Worker.d.ts.map +1 -1
- package/dist/schemes/Worker.js +7 -9
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-crud.sql +1 -1
- package/dist/schemes/_entry-find.js +2 -2
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_entry-find.sql +1 -1
- package/dist/schemes/_entry-fts.d.ts.map +1 -1
- package/dist/schemes/_entry-fts.js +3 -9
- package/dist/schemes/_entry-fts.js.map +1 -1
- package/dist/schemes/_entry-manifest.js +1 -1
- package/dist/schemes/_entry-manifest.js.map +1 -1
- package/dist/schemes/_entry-ops.js +1 -1
- package/dist/schemes/_entry-ops.js.map +1 -1
- package/dist/server/AgentRoots.d.ts +2 -1
- package/dist/server/AgentRoots.d.ts.map +1 -1
- package/dist/server/AgentRoots.js +13 -10
- package/dist/server/AgentRoots.js.map +1 -1
- package/dist/server/ConfigurationDiagnostics.d.ts +5 -3
- package/dist/server/ConfigurationDiagnostics.d.ts.map +1 -1
- package/dist/server/ConfigurationDiagnostics.js +24 -8
- package/dist/server/ConfigurationDiagnostics.js.map +1 -1
- package/dist/server/Daemon.d.ts +25 -16
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +137 -96
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DrainSupervisor.d.ts +1 -4
- package/dist/server/DrainSupervisor.d.ts.map +1 -1
- package/dist/server/DrainSupervisor.js +1 -11
- package/dist/server/DrainSupervisor.js.map +1 -1
- package/dist/server/EnvFunctionality.d.ts +3 -5
- package/dist/server/EnvFunctionality.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.js +5 -7
- package/dist/server/EnvFunctionality.js.map +1 -1
- package/dist/server/Functionality.d.ts +3 -2
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +43 -14
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/FunctionalityManager.d.ts +3 -4
- package/dist/server/FunctionalityManager.d.ts.map +1 -1
- package/dist/server/FunctionalityManager.js +17 -9
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/HttpListener.d.ts +2 -0
- package/dist/server/HttpListener.d.ts.map +1 -1
- package/dist/server/HttpListener.js +23 -9
- package/dist/server/HttpListener.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts +2 -5
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +5 -3
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/ModuleHost.d.ts +33 -0
- package/dist/server/ModuleHost.d.ts.map +1 -0
- package/dist/server/ModuleHost.js +2 -0
- package/dist/server/ModuleHost.js.map +1 -0
- package/dist/server/PlurnkSkill.d.ts.map +1 -1
- package/dist/server/PlurnkSkill.js +54 -6
- package/dist/server/PlurnkSkill.js.map +1 -1
- package/dist/server/ServiceModules.d.ts +0 -2
- package/dist/server/ServiceModules.d.ts.map +1 -1
- package/dist/server/ServiceModules.js +5 -9
- package/dist/server/ServiceModules.js.map +1 -1
- package/dist/server/WorkspacePlugins.d.ts +2 -11
- package/dist/server/WorkspacePlugins.d.ts.map +1 -1
- package/dist/server/WorkspacePlugins.js.map +1 -1
- package/dist/server/WorkspaceResidency.d.ts +2 -1
- package/dist/server/WorkspaceResidency.d.ts.map +1 -1
- package/dist/server/WorkspaceStorage.d.ts.map +1 -1
- package/dist/server/WorkspaceStorage.js +7 -4
- package/dist/server/WorkspaceStorage.js.map +1 -1
- package/dist/server/client-input.d.ts +1 -2
- package/dist/server/client-input.d.ts.map +1 -1
- package/dist/server/client-input.js +2 -13
- package/dist/server/client-input.js.map +1 -1
- package/dist/server/dispatch-as-plurnk.js +1 -1
- package/dist/server/dispatch-as-plurnk.js.map +1 -1
- package/dist/server/drain.sql +6 -6
- package/dist/server/envelope.d.ts +2 -1
- package/dist/server/envelope.d.ts.map +1 -1
- package/dist/server/envelope.js +7 -17
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/envelope.sql +5 -5
- package/dist/server/module-discovery.d.ts +11 -3
- package/dist/server/module-discovery.d.ts.map +1 -1
- package/dist/server/module-discovery.js +32 -18
- package/dist/server/module-discovery.js.map +1 -1
- package/dist/server/seam-proposal-list.sql +6 -4
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +58 -65
- package/dist/service.js.map +1 -1
- package/migrations/003_loops.sql +2 -2
- package/migrations/006_log.sql +1 -1
- package/migrations/016_selection_statements.sql +44 -0
- package/migrations/017_skills_module.sql +6 -0
- package/migrations/018_worker_owners.sql +102 -0
- package/migrations/019_interactive_owners.sql +6 -0
- package/migrations/020_log_projection.sql +143 -0
- package/package.json +71 -76
- package/dist/core/EmissionHead.d.ts +0 -8
- package/dist/core/EmissionHead.d.ts.map +0 -1
- package/dist/core/EmissionHead.js +0 -29
- package/dist/core/EmissionHead.js.map +0 -1
- package/dist/core/LegacyHome.d.ts +0 -10
- package/dist/core/LegacyHome.d.ts.map +0 -1
- package/dist/core/LegacyHome.js +0 -170
- package/dist/core/LegacyHome.js.map +0 -1
- package/dist/core/LoopPolicies.d.ts +0 -7
- package/dist/core/LoopPolicies.d.ts.map +0 -1
- package/dist/core/LoopPolicies.js +0 -42
- package/dist/core/LoopPolicies.js.map +0 -1
- package/dist/core/LoopPolicyReader.d.ts +0 -7
- package/dist/core/LoopPolicyReader.d.ts.map +0 -1
- package/dist/core/LoopPolicyReader.js +0 -33
- package/dist/core/LoopPolicyReader.js.map +0 -1
- package/dist/core/LoopPolicyReader.sql +0 -6
- package/dist/core/operation-target-groups.d.ts +0 -3
- package/dist/core/operation-target-groups.d.ts.map +0 -1
- package/dist/core/operation-target-groups.js +0 -77
- package/dist/core/operation-target-groups.js.map +0 -1
- package/dist/digest/Digest.d.ts +0 -10
- package/dist/digest/Digest.d.ts.map +0 -1
- package/dist/digest/Digest.js +0 -252
- package/dist/digest/Digest.js.map +0 -1
- package/dist/digest/DigestEvidence.d.ts +0 -11
- package/dist/digest/DigestEvidence.d.ts.map +0 -1
- package/dist/digest/DigestEvidence.js +0 -66
- package/dist/digest/DigestEvidence.js.map +0 -1
- package/dist/digest/DigestRender.d.ts +0 -18
- package/dist/digest/DigestRender.d.ts.map +0 -1
- package/dist/digest/DigestRender.js +0 -1044
- package/dist/digest/DigestRender.js.map +0 -1
- package/dist/digest/DigestRequiem.d.ts +0 -13
- package/dist/digest/DigestRequiem.d.ts.map +0 -1
- package/dist/digest/DigestRequiem.js +0 -337
- package/dist/digest/DigestRequiem.js.map +0 -1
- package/dist/digest/digest-db.d.ts +0 -3
- package/dist/digest/digest-db.d.ts.map +0 -1
- package/dist/digest/digest-db.js +0 -68
- package/dist/digest/digest-db.js.map +0 -1
- package/dist/digest/digest-paths.d.ts +0 -6
- package/dist/digest/digest-paths.d.ts.map +0 -1
- package/dist/digest/digest-paths.js +0 -14
- package/dist/digest/digest-paths.js.map +0 -1
- package/dist/digest/digest-rows.d.ts +0 -346
- package/dist/digest/digest-rows.d.ts.map +0 -1
- package/dist/digest/digest-rows.js +0 -2
- package/dist/digest/digest-rows.js.map +0 -1
- package/dist/index.d.ts +0 -15
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -23
- package/dist/index.js.map +0 -1
- package/dist/schemes/Skill.d.ts.map +0 -1
- package/dist/schemes/Skill.js.map +0 -1
- package/dist/server/DaemonModule.d.ts +0 -101
- package/dist/server/DaemonModule.d.ts.map +0 -1
- package/dist/server/DaemonModule.js +0 -2
- package/dist/server/DaemonModule.js.map +0 -1
- package/dist/server/SkillSource.d.ts +0 -37
- package/dist/server/SkillSource.d.ts.map +0 -1
- package/dist/server/SkillSource.js +0 -267
- package/dist/server/SkillSource.js.map +0 -1
- package/dist/server/SkillsFunctionality.d.ts +0 -45
- package/dist/server/SkillsFunctionality.d.ts.map +0 -1
- package/dist/server/SkillsFunctionality.js +0 -405
- package/dist/server/SkillsFunctionality.js.map +0 -1
- package/dist/server/skills-problems.d.ts +0 -8
- package/dist/server/skills-problems.d.ts.map +0 -1
- package/dist/server/skills-problems.js +0 -18
- package/dist/server/skills-problems.js.map +0 -1
- package/dist/share/Share.d.ts +0 -15
- package/dist/share/Share.d.ts.map +0 -1
- package/dist/share/Share.js +0 -106
- package/dist/share/Share.js.map +0 -1
- package/dist/share/share.sql +0 -6
- package/docs/skills.md +0 -73
package/dist/server/Daemon.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Top-level daemon orchestrator. Owns the DB connection, engine, registries,
|
|
2
|
-
// the transport-free
|
|
2
|
+
// the transport-free module seam ({§rpc}).
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { resolve, dirname } from "node:path";
|
|
5
|
-
import Share from "
|
|
5
|
+
import { Share } from "@plurnk/plurnk-digest";
|
|
6
|
+
import EvidenceReader from "@plurnk/plurnk-service/evidence";
|
|
6
7
|
import Paths from "../Paths.js";
|
|
7
8
|
import Engine from "../core/Engine.js";
|
|
8
9
|
import ExecutorRegistry from "../core/ExecutorRegistry.js";
|
|
@@ -16,20 +17,18 @@ import EffectPolicy from "../schemes/EffectPolicy.js";
|
|
|
16
17
|
import QuestionTool, { questionRuntimeDecl } from "../schemes/QuestionTool.js";
|
|
17
18
|
import DrainSupervisor from "./DrainSupervisor.js";
|
|
18
19
|
import Retention, { retentionPolicy } from "./Retention.js";
|
|
19
|
-
import PacketBuilder from "../core/PacketBuilder.js";
|
|
20
20
|
import TurnDispositionHandler from "../core/TurnDispositionHandler.js";
|
|
21
21
|
import { Validator } from "@plurnk/plurnk-contracts";
|
|
22
22
|
import LogEntry from "./logEntry.js";
|
|
23
|
+
import HttpListener from "./HttpListener.js";
|
|
23
24
|
import Envelope, { projectWorkerRow } from "./envelope.js";
|
|
24
25
|
import ClientInput from "./client-input.js";
|
|
25
26
|
import Turn from "../core/Turn.js";
|
|
26
|
-
import { expandTargetGroup } from "../core/operation-target-groups.js";
|
|
27
|
-
import SkillsFunctionality from "./SkillsFunctionality.js";
|
|
28
27
|
import WorkspacePlugins from "./WorkspacePlugins.js";
|
|
29
|
-
import { agentRootScopes,
|
|
28
|
+
import { agentRootScopes, workspacePaths } from "./AgentRoots.js";
|
|
30
29
|
import ExecEnv from "../schemes/exec-env.js";
|
|
31
30
|
import PlurnkSkill from "./PlurnkSkill.js";
|
|
32
|
-
import
|
|
31
|
+
import ResourceTreeScheme from "../schemes/ResourceTreeScheme.js";
|
|
33
32
|
import MembersFunctionality, { modelScope, serviceMembers } from "./MembersFunctionality.js";
|
|
34
33
|
import FileCreationPolicy from "../core/file-creation-policy.js";
|
|
35
34
|
import EnvFunctionality, { ENV_OWNER } from "./EnvFunctionality.js";
|
|
@@ -39,8 +38,9 @@ import Fork from "../core/fork.js";
|
|
|
39
38
|
import WorkerControlAddress from "../core/WorkerControlAddress.js";
|
|
40
39
|
import LoopLifecycle from "../core/LoopLifecycle.js";
|
|
41
40
|
import { ConfigurationError, Knob } from "@plurnk/plurnk-meta";
|
|
42
|
-
import
|
|
43
|
-
import
|
|
41
|
+
import ProposalPolicies from "../core/ProposalPolicies.js";
|
|
42
|
+
import WorkerOwners from "../core/WorkerOwners.js";
|
|
43
|
+
import RuntimeWorker from "../core/RuntimeWorker.js";
|
|
44
44
|
import { contentWeight } from "../core/content-weight.js";
|
|
45
45
|
import MessageResources from "../core/MessageResources.js";
|
|
46
46
|
import { parseAliasesFromEnv, resolveActiveRoute } from "@plurnk/plurnk-providers";
|
|
@@ -69,15 +69,13 @@ export default class Daemon {
|
|
|
69
69
|
static validateConfiguration() {
|
|
70
70
|
FileCreationPolicy.serviceScope();
|
|
71
71
|
EffectPolicy.validateConfiguration();
|
|
72
|
-
|
|
72
|
+
ProposalPolicies.read();
|
|
73
73
|
TurnDispositionHandler.configuredWaitSeconds();
|
|
74
74
|
retentionPolicy();
|
|
75
|
-
PacketBuilder.validateConfiguration();
|
|
76
75
|
Exec.validateConfiguration();
|
|
77
76
|
ExecutorRegistry.validateConfiguration();
|
|
78
77
|
}
|
|
79
78
|
static validateWorkspaceConfiguration() {
|
|
80
|
-
SkillsFunctionality.validateConfiguration();
|
|
81
79
|
agentRootScopes();
|
|
82
80
|
serviceMembers();
|
|
83
81
|
modelScope();
|
|
@@ -100,13 +98,15 @@ export default class Daemon {
|
|
|
100
98
|
#discoveryCwd;
|
|
101
99
|
#started = false; // {§module-lifecycle}: one discovery/module boot; no listener
|
|
102
100
|
#modules = [];
|
|
101
|
+
// {§module-http-mounts} — each claimed prefix's owner, and the claims mounted at start.
|
|
102
|
+
#mountClaims = new Map();
|
|
103
|
+
#mounted = new Set();
|
|
103
104
|
#moduleLifetimes = [];
|
|
104
105
|
#moduleActions = new Map();
|
|
105
106
|
#residency;
|
|
106
107
|
#functionality;
|
|
107
108
|
// {§retention-policy} — the operator's retention, run on a cadence and at shutdown.
|
|
108
109
|
#retention = null;
|
|
109
|
-
#skills;
|
|
110
110
|
#plugins;
|
|
111
111
|
#members;
|
|
112
112
|
// {§methods-event-subscribe} — the broadcast's in-process event source. A transport
|
|
@@ -127,9 +127,9 @@ export default class Daemon {
|
|
|
127
127
|
this.#lifecycle = new LoopLifecycle(db);
|
|
128
128
|
this.#schemes = schemes ?? new SchemeRegistry();
|
|
129
129
|
this.#provider = provider ?? null;
|
|
130
|
-
//
|
|
130
|
+
// Extension discovery resolves from the SERVICE's node_modules (its exec/scheme/mimetype
|
|
131
131
|
// deps), NOT process.cwd() — else a globally-installed daemon started from a project dir
|
|
132
|
-
// finds no
|
|
132
|
+
// finds no extensions. The bin passes the package-relative path; cwd default holds for
|
|
133
133
|
// in-repo tests. discover() takes a cwd and joins node_modules, so derive the parent.
|
|
134
134
|
this.#nodeModulesPath = nodeModulesPath ?? resolve(process.cwd(), "node_modules");
|
|
135
135
|
this.#discoveryCwd = dirname(this.#nodeModulesPath);
|
|
@@ -174,20 +174,7 @@ export default class Daemon {
|
|
|
174
174
|
retainWorkspace: (workspaceId) => this.#residency.retain(workspaceId),
|
|
175
175
|
preparationChanged: (workspaceId, preparation) => this.#broadcast({ workspaceId }, "workspace/preparation", { workspaceId, preparation })
|
|
176
176
|
});
|
|
177
|
-
// {§skills-functionality} — Core's own family: standard Agent Skills.
|
|
178
177
|
this.#plugins = new WorkspacePlugins({ db, hostPaths, nodeModules: this.#nodeModulesPath });
|
|
179
|
-
this.#skills = new SkillsFunctionality({
|
|
180
|
-
db,
|
|
181
|
-
plugins: this.#plugins,
|
|
182
|
-
storage: this.#storage,
|
|
183
|
-
hostPaths,
|
|
184
|
-
provided: async () => {
|
|
185
|
-
const tree = await PlurnkSkill.load(this.#nodeModulesPath);
|
|
186
|
-
return new Map([[tree.document.name, tree]]);
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
this.#skills.attach(this.#functionality.register(this.#skills));
|
|
190
|
-
this.#schemes.register("skill", new Skill((workspaceId) => this.#skills.trees(workspaceId)));
|
|
191
178
|
// {§members-functionality} — Core's own family: file membership on the same surface.
|
|
192
179
|
this.#members = new MembersFunctionality({ db, engine: () => this.#engine });
|
|
193
180
|
this.#functionality.register(this.#members);
|
|
@@ -210,7 +197,7 @@ export default class Daemon {
|
|
|
210
197
|
// daemon owns provider + the law-file system prompt; the worker scheme
|
|
211
198
|
// handler carries neither. Fire-and-forget: the returned drain runs
|
|
212
199
|
// independently (the sister is its own worker). {§machine-processes}
|
|
213
|
-
injectWorker: async ({ workspaceId, workerId, sourceLoopId, prompt,
|
|
200
|
+
injectWorker: async ({ workspaceId, workerId, sourceLoopId, prompt, spawn, environment, attachments }) => {
|
|
214
201
|
await this.#assertModelWorker(workspaceId, workerId);
|
|
215
202
|
const sender = await this.#db.drain_message_source.get({ loop_id: sourceLoopId });
|
|
216
203
|
if (sender === undefined || sender.workspace_id !== workspaceId) {
|
|
@@ -267,8 +254,7 @@ export default class Daemon {
|
|
|
267
254
|
providerSpec,
|
|
268
255
|
effort,
|
|
269
256
|
childProviderSpec,
|
|
270
|
-
systemPrompt
|
|
271
|
-
...(freshLoopPolicy === undefined ? {} : { freshLoopPolicy })
|
|
257
|
+
systemPrompt
|
|
272
258
|
});
|
|
273
259
|
return { action, loopId };
|
|
274
260
|
},
|
|
@@ -292,8 +278,7 @@ export default class Daemon {
|
|
|
292
278
|
db,
|
|
293
279
|
lifecycle: this.#lifecycle,
|
|
294
280
|
injectPrompt: (loopId, prompt, openPaths, source, evidence, messageAddress) => this.#engine.injectIntoLoop(loopId, prompt, openPaths, source, evidence, messageAddress),
|
|
295
|
-
assertInjectionCompatibility: async ({ workerId, loopId, providerSpec, providerSpecExplicit, effort, childProviderSpec, turnCeiling
|
|
296
|
-
await this.#assertFoldPosture(workerId, policy, loopId);
|
|
281
|
+
assertInjectionCompatibility: async ({ workerId, loopId, providerSpec, providerSpecExplicit, effort, childProviderSpec, turnCeiling }) => {
|
|
297
282
|
// An omitted selector keeps the loop's durable provider; only an
|
|
298
283
|
// explicit selection is checked against it (a deliberate switch).
|
|
299
284
|
if (providerSpecExplicit !== false) {
|
|
@@ -371,6 +356,18 @@ export default class Daemon {
|
|
|
371
356
|
this.#eventSubscribers.add(handler);
|
|
372
357
|
return () => { this.#eventSubscribers.delete(handler); };
|
|
373
358
|
}
|
|
359
|
+
async registerWorkerOwner(workspaceId, owner) {
|
|
360
|
+
const id = ClientInput.assertId("registerWorkerOwner", "workspaceId", workspaceId);
|
|
361
|
+
await WorkerOwners.register(this.#db, id, owner);
|
|
362
|
+
}
|
|
363
|
+
async claimWorkerOwner(args) {
|
|
364
|
+
const workspaceId = ClientInput.assertId("claimWorkerOwner", "workspaceId", args.workspaceId);
|
|
365
|
+
const workerId = ClientInput.assertId("claimWorkerOwner", "workerId", args.workerId);
|
|
366
|
+
const worker = await this.readWorker({ workspaceId, identity: { id: workerId } });
|
|
367
|
+
if (worker === null)
|
|
368
|
+
throw daemonFailure("worker:owner", "worker-not-found", 404, `Worker ${workerId} does not belong to workspace ${workspaceId}.`, { workspaceId, workerId });
|
|
369
|
+
return WorkerOwners.claim(this.#db, workspaceId, workerId, args.owner);
|
|
370
|
+
}
|
|
374
371
|
// {§methods-proposal-resolve} — proposal HITL. A transport module reads the stopped-world
|
|
375
372
|
// proposals for a workspace (rendering each as a TOOL_CALL) and feeds back the human's decision. The
|
|
376
373
|
// gate, validation, and applyResolution stay core (Engine.resolveProposal); the seam is the read +
|
|
@@ -379,23 +376,29 @@ export default class Daemon {
|
|
|
379
376
|
const checkedWorkspaceId = ClientInput.assertId("pendingProposals", "workspaceId", workspaceId);
|
|
380
377
|
return this.#engine.pendingProposals(checkedWorkspaceId);
|
|
381
378
|
}
|
|
382
|
-
resolveProposal(logEntryId, resolution) {
|
|
379
|
+
async resolveProposal(logEntryId, resolution, owner) {
|
|
383
380
|
const checkedLogEntryId = ClientInput.assertId("resolveProposal", "logEntryId", logEntryId);
|
|
384
381
|
const checkedResolution = ClientInput.assertProposalResolution("resolveProposal", resolution);
|
|
382
|
+
const workspaceId = ClientInput.assertId("resolveProposal", "workspaceId", owner.workspaceId);
|
|
383
|
+
const pending = await this.#db.worker_owner_for_proposal.get({ log_entry_id: checkedLogEntryId });
|
|
384
|
+
if (pending !== undefined && (pending.workspaceId !== workspaceId || pending.owner !== owner.address)) {
|
|
385
|
+
throw daemonFailure("proposal:resolution", "owner-mismatch", 403, "Only the worker's owner may resolve this proposal.", { logEntryId: checkedLogEntryId });
|
|
386
|
+
}
|
|
385
387
|
this.#engine.resolveProposal(checkedLogEntryId, checkedResolution);
|
|
386
388
|
}
|
|
387
389
|
async pendingClientInteractions(workspaceId) {
|
|
388
390
|
const checkedWorkspaceId = ClientInput.assertId("pendingClientInteractions", "workspaceId", workspaceId);
|
|
389
391
|
return this.#engine.pendingClientInteractions(checkedWorkspaceId);
|
|
390
392
|
}
|
|
391
|
-
async resolveClientInteraction(interactionId, resolution, message) {
|
|
393
|
+
async resolveClientInteraction(interactionId, resolution, respondent, message) {
|
|
392
394
|
const checkedInteractionId = ClientInput.assertId("resolveClientInteraction", "interactionId", interactionId);
|
|
393
395
|
const checkedResolution = ClientInput.assertClientInteractionResolution("resolveClientInteraction", resolution);
|
|
394
396
|
if (message !== undefined) {
|
|
395
397
|
ClientInput.assertPrompt("resolveClientInteraction", message.body);
|
|
396
398
|
ClientInput.assertOptionalSource("resolveClientInteraction", message.source);
|
|
397
399
|
}
|
|
398
|
-
|
|
400
|
+
ClientInput.assertId("resolveClientInteraction", "workspaceId", respondent.workspaceId);
|
|
401
|
+
await this.#engine.resolveClientInteraction(checkedInteractionId, checkedResolution, respondent, message);
|
|
399
402
|
}
|
|
400
403
|
async #prepareMessage(workspaceId, workerId, body, attachments = [], envelope) {
|
|
401
404
|
const published = await MessageResources.publish(body, attachments, {
|
|
@@ -427,9 +430,6 @@ export default class Daemon {
|
|
|
427
430
|
const openPaths = ClientInput.assertOpenPaths("runLoop", args.openPaths);
|
|
428
431
|
const selector = ClientInput.assertOptionalSelector("runLoop", "selector", args.selector);
|
|
429
432
|
const childSelector = ClientInput.assertOptionalChildSelector("runLoop", args.childSelector);
|
|
430
|
-
const policy = args.policy === undefined
|
|
431
|
-
? undefined
|
|
432
|
-
: ClientInput.normalizeLoopPolicy("runLoop", args.policy);
|
|
433
433
|
// {§worker-model-selection} — the worker owns the model. An explicit selector
|
|
434
434
|
// persists onto the worker; an omitted selector resolves the worker's durable model
|
|
435
435
|
// (seeded once from the daemon default). The loop then snapshots the resolved route.
|
|
@@ -464,7 +464,6 @@ export default class Daemon {
|
|
|
464
464
|
evidence: delivered.evidence,
|
|
465
465
|
...(messageAddress === undefined ? {} : { messageAddress }),
|
|
466
466
|
...(source === undefined ? {} : { source }),
|
|
467
|
-
...(policy !== undefined ? { policy } : {}),
|
|
468
467
|
...(openPaths !== undefined ? { openPaths } : {}),
|
|
469
468
|
turnCeiling,
|
|
470
469
|
providerSpec: selection,
|
|
@@ -572,6 +571,13 @@ export default class Daemon {
|
|
|
572
571
|
const checked = ClientInput.assertId("worker.ensure-model", "workspaceId", workspaceId);
|
|
573
572
|
return await Envelope.ensureModelWorker(this.#db, checked);
|
|
574
573
|
}
|
|
574
|
+
async ensureRuntimeWorker(workspaceId) {
|
|
575
|
+
const checked = ClientInput.assertId("worker.ensure-runtime", "workspaceId", workspaceId);
|
|
576
|
+
if (await this.#db.envelope_get_workspace.get({ id: checked }) === undefined) {
|
|
577
|
+
throw daemonFailure("worker:owner", "workspace-not-found", 404, `Workspace ${checked} does not exist.`);
|
|
578
|
+
}
|
|
579
|
+
return RuntimeWorker.ensure(this.#db, checked);
|
|
580
|
+
}
|
|
575
581
|
async readWorkspaceCapabilities(args) {
|
|
576
582
|
const workspaceId = ClientInput.assertId("workspace.capabilities.get", "workspaceId", args.workspaceId);
|
|
577
583
|
return this.#engine.capabilityProjection(workspaceId);
|
|
@@ -769,14 +775,7 @@ export default class Daemon {
|
|
|
769
775
|
try {
|
|
770
776
|
const clientLoopId = await Envelope.ensureClientLoop(this.#db, workerId);
|
|
771
777
|
try {
|
|
772
|
-
|
|
773
|
-
// result: the first failure, otherwise the last outcome.
|
|
774
|
-
let result;
|
|
775
|
-
for (const member of expandTargetGroup(statement)) {
|
|
776
|
-
const outcome = await this.#dispatchClientStatement({ workspaceId, workerId, loopId: clientLoopId, statement: member });
|
|
777
|
-
if (result === undefined || result.status < 400)
|
|
778
|
-
result = outcome;
|
|
779
|
-
}
|
|
778
|
+
const result = await this.#dispatchClientStatement({ workspaceId, workerId, loopId: clientLoopId, statement });
|
|
780
779
|
await Envelope.closeClientLoop(this.#db, clientLoopId, { status: 200 });
|
|
781
780
|
return result;
|
|
782
781
|
}
|
|
@@ -813,8 +812,7 @@ export default class Daemon {
|
|
|
813
812
|
const clientLoopId = await Envelope.ensureClientLoop(this.#db, workerId);
|
|
814
813
|
try {
|
|
815
814
|
const results = [];
|
|
816
|
-
|
|
817
|
-
for (const statement of statements.flatMap(expandTargetGroup)) {
|
|
815
|
+
for (const statement of statements) {
|
|
818
816
|
results.push(await this.#dispatchClientStatement({ workspaceId, workerId, loopId: clientLoopId, statement }));
|
|
819
817
|
}
|
|
820
818
|
await Envelope.closeClientLoop(this.#db, clientLoopId, { status: 200 });
|
|
@@ -874,7 +872,7 @@ export default class Daemon {
|
|
|
874
872
|
// full scheme resolver and return its content, writing NO log row — the client's out-of-band
|
|
875
873
|
// inspection primitive (the module rewrites LOOK→READ and parses at its edge, exactly like
|
|
876
874
|
// dispatchClientAction). Its closed observation segment supplies the numeric loop coordinate
|
|
877
|
-
// required by
|
|
875
|
+
// required by extension context and relative log:/// addresses without impersonating an active
|
|
878
876
|
// client lifecycle. It creates no turn or log row. Engine.look enforces READ-only.
|
|
879
877
|
// {§op-look} — the segment is the acting worker's; the READ resolves as the perspective worker.
|
|
880
878
|
async look(args) {
|
|
@@ -1034,7 +1032,7 @@ export default class Daemon {
|
|
|
1034
1032
|
const checkedFolder = ClientInput.assertShareFolder("workspace.share", folder);
|
|
1035
1033
|
if (this.#dbPath === undefined)
|
|
1036
1034
|
throw new Error("share: this daemon was started without its database path");
|
|
1037
|
-
return await Share.write({ dbPath: this.#dbPath, folder: checkedFolder, workspaceId: checkedWorkspaceId });
|
|
1035
|
+
return await Share.write({ openEvidence: EvidenceReader.open, dbPath: this.#dbPath, folder: checkedFolder, workspaceId: checkedWorkspaceId });
|
|
1038
1036
|
}
|
|
1039
1037
|
listPrompts(workspaceId, limit, workerId) {
|
|
1040
1038
|
const checkedWorkspaceId = ClientInput.assertId("workspace.prompts", "workspaceId", workspaceId);
|
|
@@ -1082,7 +1080,7 @@ export default class Daemon {
|
|
|
1082
1080
|
throw new Error("ClientInput.assertOptionalName accepted a required name as undefined");
|
|
1083
1081
|
return { id: checkedWorkspaceId, name: await Envelope.updateWorkspaceName(this.#db, checkedWorkspaceId, checkedName) };
|
|
1084
1082
|
}
|
|
1085
|
-
// {§methods-conversation-worker}: a fresh conversation is a model-origin
|
|
1083
|
+
// {§methods-conversation-worker}: a fresh conversation is a model-origin worker with an empty private log.
|
|
1086
1084
|
// AG-UI threads map to these workers while the workspace world remains shared ({§machine-processes}).
|
|
1087
1085
|
async createConversationWorker(args) {
|
|
1088
1086
|
const workspaceId = ClientInput.assertId("worker.create", "workspaceId", args.workspaceId);
|
|
@@ -1091,13 +1089,24 @@ export default class Daemon {
|
|
|
1091
1089
|
if (workspace === undefined) {
|
|
1092
1090
|
throw daemonFailure("daemon:workspace", "workspace-not-found", 404, `Workspace ${workspaceId} does not exist.`, { workspaceId });
|
|
1093
1091
|
}
|
|
1092
|
+
const parentWorkerId = args.parentWorkerId === undefined ? undefined : ClientInput.assertId("worker.create", "parentWorkerId", args.parentWorkerId);
|
|
1093
|
+
if (parentWorkerId !== undefined) {
|
|
1094
|
+
if (args.owner !== undefined)
|
|
1095
|
+
throw daemonFailure("worker:owner", "child-owner-inherited", 400, "A child inherits its parent's owner.", { workspaceId, parentWorkerId });
|
|
1096
|
+
const parent = await this.readWorker({ workspaceId, identity: { id: parentWorkerId } });
|
|
1097
|
+
if (parent === null)
|
|
1098
|
+
throw daemonFailure("worker:owner", "worker-not-found", 404, `Parent worker ${parentWorkerId} does not belong to workspace ${workspaceId}.`, { workspaceId, parentWorkerId });
|
|
1099
|
+
}
|
|
1100
|
+
else if (args.owner !== undefined) {
|
|
1101
|
+
await WorkerOwners.registered(this.#db, workspaceId, args.owner);
|
|
1102
|
+
}
|
|
1094
1103
|
if (name !== undefined) {
|
|
1095
1104
|
const taken = await this.#db.envelope_get_worker_by_name.get({ workspace_id: workspaceId, name });
|
|
1096
1105
|
if (taken !== undefined) {
|
|
1097
1106
|
throw daemonFailure("daemon:worker", "name-conflict", 409, `Worker name '${name}' is already in use in workspace ${workspaceId} by a ${taken.origin} worker.`, { workspaceId, name, actualOrigin: taken.origin, recovery: "Choose another worker name.", retryable: false });
|
|
1098
1107
|
}
|
|
1099
1108
|
}
|
|
1100
|
-
const worker = await Envelope.createModelWorker(this.#db, workspaceId, name);
|
|
1109
|
+
const worker = await Envelope.createModelWorker(this.#db, workspaceId, name, parentWorkerId, args.owner);
|
|
1101
1110
|
return { workerId: worker.id, workerName: worker.name };
|
|
1102
1111
|
}
|
|
1103
1112
|
// {§worker-scheme-fork} — branch a worker's log while sharing the workspace world.
|
|
@@ -1142,6 +1151,9 @@ export default class Daemon {
|
|
|
1142
1151
|
await this.#schemes.ready();
|
|
1143
1152
|
await this.#residency.rematerializeActive();
|
|
1144
1153
|
}
|
|
1154
|
+
registerResourceTreeScheme(name, source) {
|
|
1155
|
+
return this.registerScheme(name, new ResourceTreeScheme(name, source));
|
|
1156
|
+
}
|
|
1145
1157
|
#normalizeRuntime({ namespaceOwner, decl, executor, availability, scheme }) {
|
|
1146
1158
|
if (typeof namespaceOwner !== "string" || namespaceOwner.trim().length === 0) {
|
|
1147
1159
|
throw new Error("runtime registration namespaceOwner must be a non-empty string");
|
|
@@ -1169,7 +1181,11 @@ export default class Daemon {
|
|
|
1169
1181
|
registerHttpRoute(prefix, handler) {
|
|
1170
1182
|
if (this.#http === null)
|
|
1171
1183
|
throw new Error(`registerHttpRoute: this daemon has no HTTP listener to mount '${prefix}' on`);
|
|
1184
|
+
// {§module-http-mounts} — a module mounts exactly what it claimed.
|
|
1185
|
+
if (!this.#mountClaims.has(prefix))
|
|
1186
|
+
throw new Error(`registerHttpRoute: no module declared '${prefix}' among its mounts`);
|
|
1172
1187
|
this.#http.registerHttpRoute(prefix, handler);
|
|
1188
|
+
this.#mounted.add(prefix);
|
|
1173
1189
|
}
|
|
1174
1190
|
httpAddress() {
|
|
1175
1191
|
if (this.#http === null)
|
|
@@ -1271,14 +1287,18 @@ export default class Daemon {
|
|
|
1271
1287
|
workspaceStateDirectory(workspaceId, namespaceOwner) {
|
|
1272
1288
|
return this.#storage.directory(workspaceId, namespaceOwner);
|
|
1273
1289
|
}
|
|
1274
|
-
async
|
|
1290
|
+
async workspacePaths(workspaceId) {
|
|
1275
1291
|
const workspace = await this.#db.envelope_get_workspace.get({ id: workspaceId });
|
|
1276
|
-
return
|
|
1292
|
+
return workspacePaths(this.#hostPaths, workspace?.project_root ?? null);
|
|
1277
1293
|
}
|
|
1278
1294
|
// {§agent-plugins-hosting}
|
|
1279
1295
|
readWorkspacePlugins(workspaceId) {
|
|
1280
1296
|
return this.#plugins.read(workspaceId);
|
|
1281
1297
|
}
|
|
1298
|
+
async readProvidedSkills() {
|
|
1299
|
+
const tree = await PlurnkSkill.load(this.#nodeModulesPath);
|
|
1300
|
+
return new Map([[tree.document.name, tree]]);
|
|
1301
|
+
}
|
|
1282
1302
|
// {§mcp-launch-environment}
|
|
1283
1303
|
operatorEnvironment() {
|
|
1284
1304
|
return ExecEnv.withoutOwnSecrets();
|
|
@@ -1301,19 +1321,19 @@ export default class Daemon {
|
|
|
1301
1321
|
get provider() { return this.#provider; }
|
|
1302
1322
|
get schemes() { return this.#schemes; }
|
|
1303
1323
|
get mimetypes() { return this.#mimetypes; }
|
|
1304
|
-
|
|
1324
|
+
// {§module-discovery} — `owner` is the module's package name; diagnostics name it.
|
|
1325
|
+
registerModule(module, owner) {
|
|
1305
1326
|
if (this.#started)
|
|
1306
1327
|
throw new Error("registerModule: modules must be registered before daemon start");
|
|
1307
|
-
this.#modules.push(module);
|
|
1328
|
+
this.#modules.push({ module, owner });
|
|
1308
1329
|
}
|
|
1309
1330
|
async start() {
|
|
1310
1331
|
if (this.#started)
|
|
1311
1332
|
throw new Error("daemon already started");
|
|
1312
1333
|
await this.#configuration.capture("file-creation", () => FileCreationPolicy.serviceScope());
|
|
1313
1334
|
await this.#configuration.capture("effect-policy", () => EffectPolicy.validateConfiguration());
|
|
1314
|
-
await this.#configuration.capture("
|
|
1335
|
+
await this.#configuration.capture("proposal-policy", () => ProposalPolicies.read());
|
|
1315
1336
|
await this.#configuration.capture("wait", () => TurnDispositionHandler.configuredWaitSeconds());
|
|
1316
|
-
await this.#configuration.capture("packet", () => PacketBuilder.validateConfiguration());
|
|
1317
1337
|
await this.#configuration.capture("execution", () => Exec.validateConfiguration());
|
|
1318
1338
|
this.#retention = await this.#configuration.capture("retention", () => new Retention(this.#db, retentionPolicy()));
|
|
1319
1339
|
this.#started = true;
|
|
@@ -1330,7 +1350,7 @@ export default class Daemon {
|
|
|
1330
1350
|
// packages; pre-warm it so first index render doesn't pay the cost.
|
|
1331
1351
|
await this.#mimetypes.ready();
|
|
1332
1352
|
for (const name of await this.#mimetypes.skippedPackages()) {
|
|
1333
|
-
console.warn(`mimetype discovery: '${name}' is discovered but untrusted (
|
|
1353
|
+
console.warn(`mimetype discovery: '${name}' is discovered but untrusted (PLURNK_EXTENSIONS_TRUSTED_ONLY); not registered`);
|
|
1334
1354
|
}
|
|
1335
1355
|
// Discover + probe the installed executor siblings, then hand the
|
|
1336
1356
|
// registry to the engine for exec dispatch ({§exec-registry-resolves}).
|
|
@@ -1360,23 +1380,42 @@ export default class Daemon {
|
|
|
1360
1380
|
this.#schemes.registerRuntimeSchemes(executors);
|
|
1361
1381
|
// Discover external @plurnk/plurnk-schemes-* siblings + register them
|
|
1362
1382
|
// (agnostic, by plurnk.kind:"scheme"). They light up http://, etc. with
|
|
1363
|
-
// no further engine change — #run wraps their context in SchemeCtxImpl ({§
|
|
1383
|
+
// no further engine change — #run wraps their context in SchemeCtxImpl ({§extension-discovery}).
|
|
1364
1384
|
await this.#schemes.discoverExternal(this.#discoveryCwd);
|
|
1365
1385
|
// {§module-discovery} — third-party daemon-module composition: trusted
|
|
1366
1386
|
// packages declaring `plurnk.kind: "module"` register beside the
|
|
1367
1387
|
// service's explicit composition before any module setup runs.
|
|
1368
|
-
const discoveredModules = await discoverDaemonModules({
|
|
1369
|
-
|
|
1370
|
-
|
|
1388
|
+
const discoveredModules = await discoverDaemonModules({
|
|
1389
|
+
cwd: this.#discoveryCwd, hostPaths: this.#hostPaths, registered: new Set(this.#modules.map(({ owner }) => owner)),
|
|
1390
|
+
});
|
|
1391
|
+
for (const { owner, cause } of discoveredModules.configurationErrors)
|
|
1392
|
+
this.#configuration.record(owner, cause);
|
|
1371
1393
|
this.#configuration.pluginReports(discoveredModules.reports);
|
|
1372
1394
|
for (const packageName of discoveredModules.skipped) {
|
|
1373
|
-
console.warn(`module discovery: '${packageName}' is discovered but untrusted (
|
|
1395
|
+
console.warn(`module discovery: '${packageName}' is discovered but untrusted (PLURNK_EXTENSIONS_TRUSTED_ONLY); not registered`);
|
|
1396
|
+
}
|
|
1397
|
+
for (const { module, owner } of discoveredModules.modules) {
|
|
1398
|
+
this.#modules.push({ module, owner });
|
|
1399
|
+
}
|
|
1400
|
+
// {§module-http-mounts} — a daemon without a listener has nothing to serve a mount on: it
|
|
1401
|
+
// leaves out every module that declares one, and says so.
|
|
1402
|
+
if (this.#http === null) {
|
|
1403
|
+
this.#modules = this.#modules.filter(({ module, owner }) => {
|
|
1404
|
+
const mounts = module.mounts ?? [];
|
|
1405
|
+
if (mounts.length === 0)
|
|
1406
|
+
return true;
|
|
1407
|
+
this.#configuration.leftOut(`module:${owner}`, `module '${owner}' mounts ${mounts.map((prefix) => `'${prefix}'`).join(", ")} and this daemon has no HTTP listener: left out`);
|
|
1408
|
+
return false;
|
|
1409
|
+
});
|
|
1374
1410
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1411
|
+
// {§module-contained-configuration} — what a module contained is its own configuration diagnostic.
|
|
1412
|
+
for (const { module, owner } of this.#modules) {
|
|
1413
|
+
for (const { key, message } of module.contained ?? [])
|
|
1414
|
+
this.#configuration.record(`module:${owner}`, new ConfigurationError(key, message));
|
|
1377
1415
|
}
|
|
1416
|
+
this.#claimMounts();
|
|
1378
1417
|
const setupSeam = this;
|
|
1379
|
-
for (const module of this.#modules) {
|
|
1418
|
+
for (const { module } of this.#modules) {
|
|
1380
1419
|
if (module.stop !== undefined || module.close !== undefined)
|
|
1381
1420
|
this.#moduleLifetimes.push(module);
|
|
1382
1421
|
await module.setup?.(setupSeam);
|
|
@@ -1387,12 +1426,39 @@ export default class Daemon {
|
|
|
1387
1426
|
// {§module-lifecycle} — the daemon opened its one transport before admission ({§http-host});
|
|
1388
1427
|
// modules mount their routes on it here, only after capability publication and durable
|
|
1389
1428
|
// lifecycle recovery are complete. None opens a listener of its own.
|
|
1390
|
-
for (const module of this.#modules) {
|
|
1429
|
+
for (const { module } of this.#modules) {
|
|
1391
1430
|
const started = await module.start?.(this);
|
|
1392
1431
|
if (started !== undefined && !this.#moduleLifetimes.includes(started)) {
|
|
1393
1432
|
this.#moduleLifetimes.push(started);
|
|
1394
1433
|
}
|
|
1395
1434
|
}
|
|
1435
|
+
this.#admitMounts();
|
|
1436
|
+
}
|
|
1437
|
+
// {§module-http-mounts} — every prefix is claimed before any module sets up: one owner per
|
|
1438
|
+
// prefix, including the optional root mount.
|
|
1439
|
+
#claimMounts() {
|
|
1440
|
+
for (const { module, owner } of this.#modules) {
|
|
1441
|
+
for (const prefix of module.mounts ?? []) {
|
|
1442
|
+
if (!HttpListener.isPrefix(prefix)) {
|
|
1443
|
+
throw new Error(`module '${owner}' declares HTTP mount '${prefix}', which is not an absolute pathname prefix`);
|
|
1444
|
+
}
|
|
1445
|
+
const holder = this.#mountClaims.get(prefix);
|
|
1446
|
+
if (holder !== undefined)
|
|
1447
|
+
throw new Error(`HTTP mount '${prefix}' is claimed by both '${holder}' and '${owner}'`);
|
|
1448
|
+
this.#mountClaims.set(prefix, owner);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
// {§module-http-mounts} — the listener is admitted once every module has started and every
|
|
1453
|
+
// claim is mounted, so readiness never depends on registration order.
|
|
1454
|
+
#admitMounts() {
|
|
1455
|
+
if (this.#http === null)
|
|
1456
|
+
return;
|
|
1457
|
+
for (const [prefix, owner] of this.#mountClaims) {
|
|
1458
|
+
if (!this.#mounted.has(prefix))
|
|
1459
|
+
throw new Error(`module '${owner}' claimed HTTP mount '${prefix}' but did not mount it at start`);
|
|
1460
|
+
}
|
|
1461
|
+
this.#http.admit();
|
|
1396
1462
|
}
|
|
1397
1463
|
async #recoverLifecycle() {
|
|
1398
1464
|
await this.#db.recovery_fail_active_loops.run({});
|
|
@@ -1554,30 +1620,6 @@ export default class Daemon {
|
|
|
1554
1620
|
notifyNotice(workspaceId, payload) {
|
|
1555
1621
|
this.#broadcast({ workspaceId }, "notice/event", payload);
|
|
1556
1622
|
}
|
|
1557
|
-
// {§methods-loop-run-fold-consistency} — a folded prompt cannot reconfigure its loop.
|
|
1558
|
-
async #assertFoldPosture(workerId, policy, loopId) {
|
|
1559
|
-
if (policy === undefined || Object.keys(policy).length === 0)
|
|
1560
|
-
return;
|
|
1561
|
-
const effective = await LoopPolicyReader.read(this.#db, loopId);
|
|
1562
|
-
const requested = Object.entries(policy);
|
|
1563
|
-
const conflicts = requested
|
|
1564
|
-
.filter(([key, value]) => {
|
|
1565
|
-
if (value === undefined)
|
|
1566
|
-
return false;
|
|
1567
|
-
return effective[key] !== value;
|
|
1568
|
-
})
|
|
1569
|
-
.map(([key, value]) => `${key}: ${JSON.stringify(effective[key])} -> ${JSON.stringify(value)}`);
|
|
1570
|
-
if (conflicts.length > 0) {
|
|
1571
|
-
throw daemonFailure("daemon:loop", "loop-policy-conflict", 409, "The requested loop policy differs from the active loop policy.", {
|
|
1572
|
-
workerId,
|
|
1573
|
-
loopId,
|
|
1574
|
-
conflicts,
|
|
1575
|
-
stage: "loop-injection",
|
|
1576
|
-
recovery: "Cancel the active loop before changing policy, or omit policy to keep its current posture.",
|
|
1577
|
-
retryable: false
|
|
1578
|
-
});
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
1623
|
inject(args) {
|
|
1582
1624
|
return this.#drains.inject(args);
|
|
1583
1625
|
}
|
|
@@ -1592,7 +1634,6 @@ export default class Daemon {
|
|
|
1592
1634
|
worker_id: workerId,
|
|
1593
1635
|
prompt: first.body,
|
|
1594
1636
|
prompt_source: first.source,
|
|
1595
|
-
policy: first.policy,
|
|
1596
1637
|
model_route_id: first.model_route_id,
|
|
1597
1638
|
spawn_model_route_id: first.spawn_model_route_id,
|
|
1598
1639
|
effort: first.effort,
|
|
@@ -1649,7 +1690,7 @@ export default class Daemon {
|
|
|
1649
1690
|
// {§methods-event-subscribe}: publish to the in-process source; transport modules subscribe
|
|
1650
1691
|
// here (plurnk-agui renders to AG-UI+). Each subscriber owns its own fan-out; core just emits.
|
|
1651
1692
|
// Scope-stamping onto the notification envelope ({§notifications-envelope-carries-workspaceid})
|
|
1652
|
-
// is each subscriber's edge concern
|
|
1693
|
+
// is each subscriber's edge concern; the seam hands (workspaceId, method, params) raw.
|
|
1653
1694
|
this.#emitTo(target.workspaceId, method, params);
|
|
1654
1695
|
});
|
|
1655
1696
|
}
|