@plurnk/plurnk-service 1.24.0 → 1.26.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 +17 -15
- package/INSTALL.md +96 -20
- package/README.md +2 -2
- package/SPEC.md +517 -193
- package/dist/Paths.d.ts +1 -0
- package/dist/Paths.d.ts.map +1 -1
- package/dist/Paths.js +1 -0
- package/dist/Paths.js.map +1 -1
- package/dist/build-info.json +1 -1
- package/dist/content/read-projector.d.ts.map +1 -1
- package/dist/content/read-projector.js +19 -0
- 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 +5 -5
- package/dist/core/AdministrativeLoop.js.map +1 -1
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +1 -0
- package/dist/core/AdmittedTurnExecutor.js.map +1 -1
- package/dist/core/CapabilityResolver.js +1 -1
- package/dist/core/CapabilityResolver.js.map +1 -1
- package/dist/core/DataStatementRunner.d.ts.map +1 -1
- package/dist/core/DataStatementRunner.js +1 -3
- package/dist/core/DataStatementRunner.js.map +1 -1
- package/dist/core/Dispatcher.d.ts +1 -1
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +76 -21
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Dispatcher.sql +0 -7
- package/dist/core/Engine.d.ts +2 -2
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.d.ts +16 -4
- package/dist/core/ExecutorRegistry.d.ts.map +1 -1
- package/dist/core/ExecutorRegistry.js +31 -31
- package/dist/core/ExecutorRegistry.js.map +1 -1
- package/dist/core/HostPaths.d.ts +7 -1
- package/dist/core/HostPaths.d.ts.map +1 -1
- package/dist/core/HostPaths.js +25 -12
- package/dist/core/HostPaths.js.map +1 -1
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +11 -2
- package/dist/core/LoopDriver.js.map +1 -1
- package/dist/core/LoopLifecycle.d.ts +1 -1
- package/dist/core/LoopLifecycle.js +1 -1
- package/dist/core/LoopLifecycle.sql +2 -2
- package/dist/core/LoopPolicies.d.ts.map +1 -1
- package/dist/core/LoopPolicies.js +12 -7
- package/dist/core/LoopPolicies.js.map +1 -1
- package/dist/core/MembershipMaterialization.js +1 -1
- package/dist/core/MembershipMaterialization.js.map +1 -1
- package/dist/core/OperatorConfig.d.ts.map +1 -1
- package/dist/core/OperatorConfig.js +97 -51
- package/dist/core/OperatorConfig.js.map +1 -1
- package/dist/core/PacketBuilder.d.ts +1 -0
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +27 -25
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/ReasoningView.d.ts +1 -1
- package/dist/core/ReasoningView.d.ts.map +1 -1
- package/dist/core/ReasoningView.js +4 -5
- package/dist/core/ReasoningView.js.map +1 -1
- package/dist/core/SchemeRegistry.d.ts.map +1 -1
- package/dist/core/SchemeRegistry.js +3 -2
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/Turn.d.ts +1 -1
- package/dist/core/Turn.d.ts.map +1 -1
- package/dist/core/Turn.js +2 -2
- package/dist/core/Turn.js.map +1 -1
- package/dist/core/Turn.sql +1 -1
- package/dist/core/TurnDispositionHandler.d.ts +1 -1
- package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
- package/dist/core/TurnDispositionHandler.js +6 -15
- 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 -0
- package/dist/core/TurnOps.d.ts.map +1 -1
- package/dist/core/TurnOps.js +18 -0
- package/dist/core/TurnOps.js.map +1 -1
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +53 -32
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/env-defaults.d.ts +12 -1
- package/dist/core/env-defaults.d.ts.map +1 -1
- package/dist/core/env-defaults.js +50 -7
- package/dist/core/env-defaults.js.map +1 -1
- package/dist/core/file-creation-policy.d.ts.map +1 -1
- package/dist/core/file-creation-policy.js +2 -1
- package/dist/core/file-creation-policy.js.map +1 -1
- package/dist/core/git-membership.d.ts.map +1 -1
- package/dist/core/git-membership.js +0 -3
- package/dist/core/git-membership.js.map +1 -1
- package/dist/core/namespace.d.ts +1 -0
- package/dist/core/namespace.d.ts.map +1 -1
- package/dist/core/namespace.js +21 -75
- package/dist/core/namespace.js.map +1 -1
- package/dist/core/notifications.d.ts +2 -0
- package/dist/core/notifications.d.ts.map +1 -1
- package/dist/core/packet-wire.d.ts +1 -0
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +28 -7
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/results.d.ts +2 -0
- package/dist/core/results.d.ts.map +1 -1
- package/dist/core/results.js +7 -0
- package/dist/core/results.js.map +1 -1
- package/dist/digest/Digest.d.ts.map +1 -1
- package/dist/digest/Digest.js +1 -2
- package/dist/digest/Digest.js.map +1 -1
- package/dist/digest/DigestEvidence.d.ts +1 -0
- package/dist/digest/DigestEvidence.d.ts.map +1 -1
- package/dist/digest/DigestEvidence.js +8 -0
- package/dist/digest/DigestEvidence.js.map +1 -1
- package/dist/digest/DigestRender.d.ts.map +1 -1
- package/dist/digest/DigestRender.js +23 -21
- package/dist/digest/DigestRender.js.map +1 -1
- package/dist/digest/digest-rows.d.ts +2 -1
- package/dist/digest/digest-rows.d.ts.map +1 -1
- package/dist/digest/digest.sql +4 -0
- package/dist/observe/init.d.ts +1 -0
- package/dist/observe/init.d.ts.map +1 -1
- package/dist/observe/init.js +5 -1
- package/dist/observe/init.js.map +1 -1
- package/dist/schemes/EffectPolicy.d.ts.map +1 -1
- package/dist/schemes/EffectPolicy.js +4 -4
- package/dist/schemes/EffectPolicy.js.map +1 -1
- package/dist/schemes/Exec.d.ts +1 -0
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +30 -14
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/ExecScheduler.d.ts.map +1 -1
- package/dist/schemes/ExecScheduler.js +4 -3
- package/dist/schemes/ExecScheduler.js.map +1 -1
- package/dist/schemes/ExecScratch.d.ts.map +1 -1
- package/dist/schemes/ExecScratch.js +2 -1
- package/dist/schemes/ExecScratch.js.map +1 -1
- package/dist/schemes/File.d.ts.map +1 -1
- package/dist/schemes/File.js +21 -22
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/_entry-find.d.ts +1 -0
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +4 -3
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/schemes/_path-scope.d.ts +2 -2
- package/dist/schemes/_path-scope.d.ts.map +1 -1
- package/dist/schemes/_path-scope.js +23 -2
- package/dist/schemes/_path-scope.js.map +1 -1
- package/dist/server/AgentRoots.d.ts +6 -0
- package/dist/server/AgentRoots.d.ts.map +1 -0
- package/dist/server/AgentRoots.js +25 -0
- package/dist/server/AgentRoots.js.map +1 -0
- package/dist/server/ConfigurationDiagnostics.d.ts +12 -0
- package/dist/server/ConfigurationDiagnostics.d.ts.map +1 -0
- package/dist/server/ConfigurationDiagnostics.js +40 -0
- package/dist/server/ConfigurationDiagnostics.js.map +1 -0
- package/dist/server/Daemon.d.ts +11 -5
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +125 -48
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/DaemonModule.d.ts +11 -4
- package/dist/server/DaemonModule.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.d.ts.map +1 -1
- package/dist/server/EnvFunctionality.js +5 -2
- package/dist/server/EnvFunctionality.js.map +1 -1
- package/dist/server/Functionality.d.ts +6 -0
- package/dist/server/Functionality.d.ts.map +1 -1
- package/dist/server/Functionality.js +173 -37
- package/dist/server/Functionality.js.map +1 -1
- package/dist/server/FunctionalityManager.js +6 -6
- package/dist/server/FunctionalityManager.js.map +1 -1
- package/dist/server/MembersFunctionality.d.ts.map +1 -1
- package/dist/server/MembersFunctionality.js +13 -41
- package/dist/server/MembersFunctionality.js.map +1 -1
- package/dist/server/PluginSources.d.ts +20 -0
- package/dist/server/PluginSources.d.ts.map +1 -0
- package/dist/server/PluginSources.js +52 -0
- package/dist/server/PluginSources.js.map +1 -0
- package/dist/server/PlurnkSkill.js +1 -1
- package/dist/server/PlurnkSkill.js.map +1 -1
- package/dist/server/Retention.d.ts.map +1 -1
- package/dist/server/Retention.js +11 -30
- package/dist/server/Retention.js.map +1 -1
- package/dist/server/ServiceModules.d.ts +1 -0
- package/dist/server/ServiceModules.d.ts.map +1 -1
- package/dist/server/ServiceModules.js +9 -3
- package/dist/server/ServiceModules.js.map +1 -1
- package/dist/server/SkillSource.d.ts +37 -0
- package/dist/server/SkillSource.d.ts.map +1 -0
- package/dist/server/SkillSource.js +267 -0
- package/dist/server/SkillSource.js.map +1 -0
- package/dist/server/SkillsFunctionality.d.ts +8 -27
- package/dist/server/SkillsFunctionality.d.ts.map +1 -1
- package/dist/server/SkillsFunctionality.js +218 -270
- package/dist/server/SkillsFunctionality.js.map +1 -1
- package/dist/server/WorkerModelResolver.d.ts +1 -2
- package/dist/server/WorkerModelResolver.d.ts.map +1 -1
- package/dist/server/WorkerModelResolver.js +18 -19
- package/dist/server/WorkerModelResolver.js.map +1 -1
- package/dist/server/WorkspacePlugins.d.ts +25 -0
- package/dist/server/WorkspacePlugins.d.ts.map +1 -0
- package/dist/server/WorkspacePlugins.js +43 -0
- package/dist/server/WorkspacePlugins.js.map +1 -0
- package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
- package/dist/server/dispatch-as-plurnk.js +2 -1
- package/dist/server/dispatch-as-plurnk.js.map +1 -1
- package/dist/server/envelope.js +1 -1
- package/dist/server/envelope.js.map +1 -1
- package/dist/server/loop-model.d.ts.map +1 -1
- package/dist/server/loop-model.js +1 -2
- package/dist/server/loop-model.js.map +1 -1
- package/dist/server/module-discovery.d.ts +6 -0
- package/dist/server/module-discovery.d.ts.map +1 -1
- package/dist/server/module-discovery.js +46 -24
- package/dist/server/module-discovery.js.map +1 -1
- package/dist/server/skills-problems.d.ts +8 -0
- package/dist/server/skills-problems.d.ts.map +1 -0
- package/dist/server/skills-problems.js +18 -0
- package/dist/server/skills-problems.js.map +1 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +55 -45
- package/dist/service.js.map +1 -1
- package/docs/env.md +7 -8
- package/docs/members.md +4 -3
- package/docs/skills.md +45 -22
- package/package.json +37 -35
- package/plurnk.service +29 -0
package/dist/server/Daemon.js
CHANGED
|
@@ -6,6 +6,7 @@ import Share from "../share/Share.js";
|
|
|
6
6
|
import Paths from "../Paths.js";
|
|
7
7
|
import Engine from "../core/Engine.js";
|
|
8
8
|
import ExecutorRegistry from "../core/ExecutorRegistry.js";
|
|
9
|
+
import Exec from "../schemes/Exec.js";
|
|
9
10
|
import SchemeRegistry from "../core/SchemeRegistry.js";
|
|
10
11
|
import { Mimetypes } from "@plurnk/plurnk-mimetypes";
|
|
11
12
|
import { RuntimeDeclaration } from "@plurnk/plurnk-execs";
|
|
@@ -15,22 +16,27 @@ import EffectPolicy from "../schemes/EffectPolicy.js";
|
|
|
15
16
|
import QuestionTool, { questionRuntimeDecl } from "../schemes/QuestionTool.js";
|
|
16
17
|
import DrainSupervisor from "./DrainSupervisor.js";
|
|
17
18
|
import Retention, { retentionPolicy } from "./Retention.js";
|
|
19
|
+
import PacketBuilder from "../core/PacketBuilder.js";
|
|
18
20
|
import { Validator } from "@plurnk/plurnk-contracts";
|
|
19
21
|
import LogEntry from "./logEntry.js";
|
|
20
22
|
import Envelope, { projectWorkerRow } from "./envelope.js";
|
|
21
23
|
import ClientInput from "./client-input.js";
|
|
22
24
|
import Turn from "../core/Turn.js";
|
|
23
25
|
import SkillsFunctionality from "./SkillsFunctionality.js";
|
|
26
|
+
import WorkspacePlugins from "./WorkspacePlugins.js";
|
|
27
|
+
import { agentRootScopes, configurationDirectories } from "./AgentRoots.js";
|
|
28
|
+
import ExecEnv from "../schemes/exec-env.js";
|
|
24
29
|
import PlurnkSkill from "./PlurnkSkill.js";
|
|
25
30
|
import Skill from "../schemes/Skill.js";
|
|
26
|
-
import MembersFunctionality from "./MembersFunctionality.js";
|
|
31
|
+
import MembersFunctionality, { modelScope, serviceMembers } from "./MembersFunctionality.js";
|
|
32
|
+
import FileCreationPolicy from "../core/file-creation-policy.js";
|
|
27
33
|
import EnvFunctionality, { ENV_OWNER } from "./EnvFunctionality.js";
|
|
28
34
|
import HostPaths from "../core/HostPaths.js";
|
|
29
35
|
import WorkspaceStorage from "./WorkspaceStorage.js";
|
|
30
36
|
import Fork from "../core/fork.js";
|
|
31
37
|
import WorkerControlAddress from "../core/WorkerControlAddress.js";
|
|
32
38
|
import LoopLifecycle from "../core/LoopLifecycle.js";
|
|
33
|
-
import { Knob } from "@plurnk/plurnk-meta";
|
|
39
|
+
import { ConfigurationError, Knob } from "@plurnk/plurnk-meta";
|
|
34
40
|
import LoopPolicies from "../core/LoopPolicies.js";
|
|
35
41
|
import LoopPolicyReader from "../core/LoopPolicyReader.js";
|
|
36
42
|
import { contentWeight } from "../core/content-weight.js";
|
|
@@ -46,6 +52,7 @@ import { listModelCatalog } from "./model-catalog.js";
|
|
|
46
52
|
import { daemonFailure, modelRouteLabel } from "./daemon-results.js";
|
|
47
53
|
import WorkerModelResolver from "./WorkerModelResolver.js";
|
|
48
54
|
import ClientReads from "./ClientReads.js";
|
|
55
|
+
import ConfigurationDiagnostics from "./ConfigurationDiagnostics.js";
|
|
49
56
|
const clientActionFailure = (error) => {
|
|
50
57
|
if (error instanceof OperationFailureError)
|
|
51
58
|
return error.result;
|
|
@@ -56,8 +63,24 @@ const clientActionFailure = (error) => {
|
|
|
56
63
|
});
|
|
57
64
|
};
|
|
58
65
|
export default class Daemon {
|
|
66
|
+
static validateConfiguration() {
|
|
67
|
+
FileCreationPolicy.serviceScope();
|
|
68
|
+
EffectPolicy.validateConfiguration();
|
|
69
|
+
LoopPolicies.validateConfiguration();
|
|
70
|
+
retentionPolicy();
|
|
71
|
+
PacketBuilder.validateConfiguration();
|
|
72
|
+
Exec.validateConfiguration();
|
|
73
|
+
ExecutorRegistry.validateConfiguration();
|
|
74
|
+
}
|
|
75
|
+
static validateWorkspaceConfiguration() {
|
|
76
|
+
SkillsFunctionality.validateConfiguration();
|
|
77
|
+
agentRootScopes();
|
|
78
|
+
serviceMembers();
|
|
79
|
+
modelScope();
|
|
80
|
+
}
|
|
59
81
|
#db;
|
|
60
82
|
#dbPath;
|
|
83
|
+
#hostPaths;
|
|
61
84
|
#engine;
|
|
62
85
|
#workspaceGate;
|
|
63
86
|
#lifecycle;
|
|
@@ -73,13 +96,14 @@ export default class Daemon {
|
|
|
73
96
|
#discoveryCwd;
|
|
74
97
|
#started = false; // {§module-lifecycle}: one discovery/module boot; no listener
|
|
75
98
|
#modules = [];
|
|
76
|
-
#
|
|
99
|
+
#moduleLifetimes = [];
|
|
77
100
|
#moduleActions = new Map();
|
|
78
101
|
#residency;
|
|
79
102
|
#functionality;
|
|
80
103
|
// {§retention-policy} — the operator's retention, run on a cadence and at shutdown.
|
|
81
|
-
#retention;
|
|
104
|
+
#retention = null;
|
|
82
105
|
#skills;
|
|
106
|
+
#plugins;
|
|
83
107
|
#members;
|
|
84
108
|
// {§methods-event-subscribe} — the broadcast's in-process event source. A transport
|
|
85
109
|
// module (plurnk-agui) subscribes and fans out to its OWN clients; core emits, never owns
|
|
@@ -88,10 +112,13 @@ export default class Daemon {
|
|
|
88
112
|
#workerModels;
|
|
89
113
|
#reads;
|
|
90
114
|
#storage;
|
|
91
|
-
|
|
115
|
+
#configuration;
|
|
116
|
+
constructor({ db, schemes, mimetypes, provider, nodeModulesPath, hostPaths = new HostPaths(), http = null, dbPath, configuration = new ConfigurationDiagnostics() }) {
|
|
92
117
|
this.#db = db;
|
|
118
|
+
this.#hostPaths = hostPaths;
|
|
93
119
|
this.#dbPath = dbPath;
|
|
94
120
|
this.#http = http;
|
|
121
|
+
this.#configuration = configuration;
|
|
95
122
|
this.#storage = new WorkspaceStorage(db, hostPaths);
|
|
96
123
|
this.#lifecycle = new LoopLifecycle(db);
|
|
97
124
|
this.#schemes = schemes ?? new SchemeRegistry();
|
|
@@ -111,7 +138,7 @@ export default class Daemon {
|
|
|
111
138
|
defaultMimetype: "text/markdown",
|
|
112
139
|
discoverOptions: { cwd: this.#discoveryCwd }
|
|
113
140
|
});
|
|
114
|
-
const bootSpec = resolveActiveRoute();
|
|
141
|
+
const bootSpec = this.#provider === null ? null : resolveActiveRoute();
|
|
115
142
|
if (this.#provider !== null && bootSpec !== null) {
|
|
116
143
|
ProviderInstantiate.registerInstance(this.#provider, bootSpec);
|
|
117
144
|
}
|
|
@@ -140,13 +167,16 @@ export default class Daemon {
|
|
|
140
167
|
readWorkerModuleState: (workerId, owner) => this.#residency.readWorkerModuleState(workerId, owner),
|
|
141
168
|
replaceWorkerModuleState: (workerId, owner, state) => this.#residency.replaceWorkerModuleState(workerId, owner, state),
|
|
142
169
|
mutateWorkspace: (workspaceId, owner, caller, run) => this.#residency.exclusively(workspaceId, owner, caller === "operation" ? "wait" : "try", run),
|
|
143
|
-
retainWorkspace: (workspaceId) => this.#residency.retain(workspaceId)
|
|
170
|
+
retainWorkspace: (workspaceId) => this.#residency.retain(workspaceId),
|
|
171
|
+
preparationChanged: (workspaceId, preparation) => this.#broadcast({ workspaceId }, "workspace/preparation", { workspaceId, preparation })
|
|
144
172
|
});
|
|
145
173
|
// {§skills-functionality} — Core's own family: standard Agent Skills.
|
|
174
|
+
this.#plugins = new WorkspacePlugins({ db, hostPaths, nodeModules: this.#nodeModulesPath });
|
|
146
175
|
this.#skills = new SkillsFunctionality({
|
|
147
176
|
db,
|
|
177
|
+
plugins: this.#plugins,
|
|
178
|
+
storage: this.#storage,
|
|
148
179
|
hostPaths,
|
|
149
|
-
...skills,
|
|
150
180
|
provided: async () => {
|
|
151
181
|
const tree = await PlurnkSkill.load(this.#nodeModulesPath);
|
|
152
182
|
return new Map([[tree.document.name, tree]]);
|
|
@@ -167,6 +197,7 @@ export default class Daemon {
|
|
|
167
197
|
weigh: contentWeight,
|
|
168
198
|
streamEventNotify: (workspaceId, event) => this.notifyStreamEvent(workspaceId, event),
|
|
169
199
|
operationSettledNotify: (workspaceId, logEntryId) => this.#drains.operationSettled(workspaceId, logEntryId),
|
|
200
|
+
operationEventNotify: (workspaceId, event) => this.#broadcast({ workspaceId }, "operation/event", event),
|
|
170
201
|
reasoningEventNotify: (workspaceId, event) => this.notifyReasoningEvent(workspaceId, event),
|
|
171
202
|
outsideEventNotify: (workspaceId, event) => this.notifyOutsideEvent(workspaceId, event),
|
|
172
203
|
wakeWorkerNotify: (payload) => this.#drains.notifyWakeWorker(payload),
|
|
@@ -238,11 +269,12 @@ export default class Daemon {
|
|
|
238
269
|
return { action, loopId };
|
|
239
270
|
},
|
|
240
271
|
acquireWorkspaceTurn: async (workspaceId, workerId, signal) => this.#workspaceGate.acquireTurn(workspaceId, workerId, signal),
|
|
241
|
-
// {§
|
|
272
|
+
// {§functionality-hotload} — skills and plugins change out of band.
|
|
242
273
|
// Republish under the workspace turn gate before packet assembly so
|
|
243
274
|
// the first subsequent model turn sees their exact result.
|
|
244
275
|
workspaceTurnStarting: async ({ workspaceId }) => {
|
|
245
|
-
await this.#
|
|
276
|
+
await this.#functionality.refreshChanged({ workspaceId });
|
|
277
|
+
return [...this.configurationNotices(), ...this.#functionality.configurationNotices(workspaceId), ...this.#plugins.notices(workspaceId)];
|
|
246
278
|
},
|
|
247
279
|
// worker:// KILL (terminate) — cancel the addressed worker subtree and
|
|
248
280
|
// tear down its held streams before the operation completes.
|
|
@@ -252,7 +284,6 @@ export default class Daemon {
|
|
|
252
284
|
this.#broadcast({ workspaceId }, "loop/packet", payload);
|
|
253
285
|
}
|
|
254
286
|
});
|
|
255
|
-
this.#retention = new Retention(db, retentionPolicy());
|
|
256
287
|
this.#drains = new DrainSupervisor({
|
|
257
288
|
db,
|
|
258
289
|
lifecycle: this.#lifecycle,
|
|
@@ -323,7 +354,7 @@ export default class Daemon {
|
|
|
323
354
|
const { workspaceId, ...interaction } = event;
|
|
324
355
|
this.#broadcast({ workspaceId }, "loop/interaction", interaction);
|
|
325
356
|
});
|
|
326
|
-
this.#workerModels = new WorkerModelResolver({ db: this.#db
|
|
357
|
+
this.#workerModels = new WorkerModelResolver({ db: this.#db });
|
|
327
358
|
this.#reads = new ClientReads({ db: this.#db, engine: this.#engine, workspaceGate: this.#workspaceGate, residency: this.#residency });
|
|
328
359
|
}
|
|
329
360
|
// {§methods-event-subscribe}. A transport module subscribes to the daemon's in-process
|
|
@@ -870,10 +901,19 @@ export default class Daemon {
|
|
|
870
901
|
// {§methods} — the module's render surface beyond the journal. Thin delegations
|
|
871
902
|
// into core's envelope / membership / provider machinery; the module fans the results into its own views.
|
|
872
903
|
listProviders() {
|
|
873
|
-
const active =
|
|
904
|
+
const active = process.env.PLURNK_MODEL?.toLowerCase();
|
|
905
|
+
let aliases;
|
|
906
|
+
try {
|
|
907
|
+
aliases = parseAliasesFromEnv();
|
|
908
|
+
}
|
|
909
|
+
catch (cause) {
|
|
910
|
+
if (!(cause instanceof ConfigurationError))
|
|
911
|
+
throw cause;
|
|
912
|
+
throw new OperationFailureError(Results.configurationFailure(cause), { cause });
|
|
913
|
+
}
|
|
874
914
|
return {
|
|
875
|
-
aliases:
|
|
876
|
-
const isActive = active
|
|
915
|
+
aliases: aliases.map((a) => {
|
|
916
|
+
const isActive = active === a.alias;
|
|
877
917
|
return {
|
|
878
918
|
alias: a.alias, provider: a.provider, model: a.model, active: isActive,
|
|
879
919
|
inputCapacity: isActive && this.#provider !== null ? this.#provider.inputCapacity : null
|
|
@@ -988,6 +1028,9 @@ export default class Daemon {
|
|
|
988
1028
|
const checkedWorkerId = workerId === undefined ? null : ClientInput.assertId("workspace.prompts", "workerId", workerId);
|
|
989
1029
|
return Envelope.listPromptsForWorkspace(this.#db, checkedWorkspaceId, checkedLimit ?? Knob.integer("PLURNK_SERVICE_PROMPTS_PAGE", 1), checkedWorkerId);
|
|
990
1030
|
}
|
|
1031
|
+
workspacePreparationStatus(workspaceId) {
|
|
1032
|
+
return this.#functionality.preparationStatus(ClientInput.assertId("workspace preparation", "workspaceId", workspaceId));
|
|
1033
|
+
}
|
|
991
1034
|
workspaceDerivationStatus(workspaceId) {
|
|
992
1035
|
return this.#engine.workspaceDerivationStatus(ClientInput.assertId("workspace.derivation", "workspaceId", workspaceId));
|
|
993
1036
|
}
|
|
@@ -1142,6 +1185,12 @@ export default class Daemon {
|
|
|
1142
1185
|
}
|
|
1143
1186
|
if (typeof handler !== "function")
|
|
1144
1187
|
throw new Error(`module action '${name}' has no handler`);
|
|
1188
|
+
if (registration.residency !== "required" && registration.residency !== "none") {
|
|
1189
|
+
throw new Error(`module action '${name}' must declare its residency requirement`);
|
|
1190
|
+
}
|
|
1191
|
+
if (scope === "worldless" && registration.residency !== "none") {
|
|
1192
|
+
throw new Error(`worldless module action '${name}' cannot require workspace residency`);
|
|
1193
|
+
}
|
|
1145
1194
|
if (this.#moduleActions.has(name))
|
|
1146
1195
|
throw new Error(`module action '${name}' is already registered`);
|
|
1147
1196
|
this.#moduleActions.set(name, registration);
|
|
@@ -1164,20 +1213,22 @@ export default class Daemon {
|
|
|
1164
1213
|
throw new Error(`module action '${name}' requires ${registration.scope} context, not ${context.scope}`);
|
|
1165
1214
|
}
|
|
1166
1215
|
let releaseCapabilities;
|
|
1167
|
-
if (context.scope === "
|
|
1168
|
-
releaseCapabilities = await this.#residency.acquire(context.workspaceId);
|
|
1169
|
-
}
|
|
1170
|
-
else if (context.scope === "worker") {
|
|
1216
|
+
if (context.scope === "worker") {
|
|
1171
1217
|
const workspaceId = ClientInput.assertId(`module action '${name}'`, "workspaceId", context.workspaceId);
|
|
1172
1218
|
const workerId = ClientInput.assertId(`module action '${name}'`, "workerId", context.workerId);
|
|
1173
1219
|
const worker = await this.#db.envelope_get_worker_by_id.get({ id: workerId });
|
|
1174
1220
|
if (worker === undefined || worker.workspace_id !== workspaceId) {
|
|
1175
1221
|
throw daemonFailure("daemon:module-action", "worker-not-found", 404, `Worker ${workerId} does not exist in workspace ${workspaceId}.`, { workspaceId, workerId, retryable: false });
|
|
1176
1222
|
}
|
|
1177
|
-
|
|
1223
|
+
}
|
|
1224
|
+
if (registration.residency === "required" && context.scope !== "worldless") {
|
|
1225
|
+
releaseCapabilities = await this.#residency.acquire(context.workspaceId);
|
|
1226
|
+
}
|
|
1227
|
+
else if (context.scope === "workspace") {
|
|
1228
|
+
await this.#residency.identity(context.workspaceId);
|
|
1178
1229
|
}
|
|
1179
1230
|
try {
|
|
1180
|
-
if (context.scope === "worker") {
|
|
1231
|
+
if (registration.residency === "required" && context.scope === "worker") {
|
|
1181
1232
|
const release = await this.#workspaceGate.acquireTurn(context.workspaceId, context.workerId);
|
|
1182
1233
|
try {
|
|
1183
1234
|
await this.#residency.reconcile(context.workspaceId);
|
|
@@ -1206,6 +1257,18 @@ export default class Daemon {
|
|
|
1206
1257
|
workspaceStateDirectory(workspaceId, namespaceOwner) {
|
|
1207
1258
|
return this.#storage.directory(workspaceId, namespaceOwner);
|
|
1208
1259
|
}
|
|
1260
|
+
async workspaceConfigurationDirectories(workspaceId) {
|
|
1261
|
+
const workspace = await this.#db.envelope_get_workspace.get({ id: workspaceId });
|
|
1262
|
+
return configurationDirectories(this.#hostPaths, workspace?.project_root ?? null);
|
|
1263
|
+
}
|
|
1264
|
+
// {§agent-plugins-hosting}
|
|
1265
|
+
readWorkspacePlugins(workspaceId) {
|
|
1266
|
+
return this.#plugins.read(workspaceId);
|
|
1267
|
+
}
|
|
1268
|
+
// {§mcp-launch-environment}
|
|
1269
|
+
operatorEnvironment() {
|
|
1270
|
+
return ExecEnv.withoutOwnSecrets();
|
|
1271
|
+
}
|
|
1209
1272
|
async readWorkerEnvironment(workspaceId, workerId) {
|
|
1210
1273
|
await this.#assertWorkerOwned(workspaceId, workerId);
|
|
1211
1274
|
const shared = await EnvFunctionality.workspace(this.#db, workspaceId);
|
|
@@ -1220,6 +1283,7 @@ export default class Daemon {
|
|
|
1220
1283
|
await this.#residency.replace(replacement, options);
|
|
1221
1284
|
}
|
|
1222
1285
|
get engine() { return this.#engine; }
|
|
1286
|
+
configurationNotices() { return this.#configuration.notices(); }
|
|
1223
1287
|
get provider() { return this.#provider; }
|
|
1224
1288
|
get schemes() { return this.#schemes; }
|
|
1225
1289
|
get mimetypes() { return this.#mimetypes; }
|
|
@@ -1231,14 +1295,22 @@ export default class Daemon {
|
|
|
1231
1295
|
async start() {
|
|
1232
1296
|
if (this.#started)
|
|
1233
1297
|
throw new Error("daemon already started");
|
|
1298
|
+
await this.#configuration.capture("file-creation", () => FileCreationPolicy.serviceScope());
|
|
1299
|
+
await this.#configuration.capture("effect-policy", () => EffectPolicy.validateConfiguration());
|
|
1300
|
+
await this.#configuration.capture("loop-policy", () => LoopPolicies.validateConfiguration());
|
|
1301
|
+
await this.#configuration.capture("packet", () => PacketBuilder.validateConfiguration());
|
|
1302
|
+
await this.#configuration.capture("execution", () => Exec.validateConfiguration());
|
|
1303
|
+
this.#retention = await this.#configuration.capture("retention", () => new Retention(this.#db, retentionPolicy()));
|
|
1234
1304
|
this.#started = true;
|
|
1235
1305
|
// {§db-space-reclamation} — the file is brought to the policy's auto-vacuum mode before any work.
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1306
|
+
if (this.#retention !== null) {
|
|
1307
|
+
const storage = await this.#retention.prepareStorage();
|
|
1308
|
+
if (storage.converted) {
|
|
1309
|
+
console.error(`database: converted to auto_vacuum=${this.#retention.policy.autoVacuum} (${storage.pagesBefore} → ${storage.pagesAfter} pages)`);
|
|
1310
|
+
}
|
|
1239
1311
|
}
|
|
1240
1312
|
this.#drains.start();
|
|
1241
|
-
this.#retention
|
|
1313
|
+
this.#retention?.start((cause) => { console.error("retention pass failed:", cause instanceof Error ? cause.message : String(cause)); });
|
|
1242
1314
|
// Mimetypes owns its own discovery scan over @plurnk/plurnk-mimetypes-*
|
|
1243
1315
|
// packages; pre-warm it so first index render doesn't pay the cost.
|
|
1244
1316
|
await this.#mimetypes.ready();
|
|
@@ -1246,9 +1318,11 @@ export default class Daemon {
|
|
|
1246
1318
|
console.warn(`mimetype discovery: '${name}' is discovered but untrusted (PLURNK_PLUGINS_TRUSTED_ONLY); not registered`);
|
|
1247
1319
|
}
|
|
1248
1320
|
// Discover + probe the installed executor siblings, then hand the
|
|
1249
|
-
// registry to the engine for exec dispatch ({§exec-registry-resolves}).
|
|
1250
|
-
|
|
1251
|
-
const
|
|
1321
|
+
// registry to the engine for exec dispatch ({§exec-registry-resolves}).
|
|
1322
|
+
const executors = await ExecutorRegistry.build({ cwd: this.#discoveryCwd });
|
|
1323
|
+
for (const { runtime, error } of executors.configurationErrors()) {
|
|
1324
|
+
this.#configuration.record(`executor:${runtime}`, error);
|
|
1325
|
+
}
|
|
1252
1326
|
this.#engine.setExecutors(executors);
|
|
1253
1327
|
this.#engine.setFunctionalityDocuments((workspaceId) => this.#functionality.documents(workspaceId));
|
|
1254
1328
|
// {§question-tool} — the native request-user-input runtime, process-wide;
|
|
@@ -1266,9 +1340,6 @@ export default class Daemon {
|
|
|
1266
1340
|
detail: "in-process"
|
|
1267
1341
|
}
|
|
1268
1342
|
}]);
|
|
1269
|
-
// {§effect-policy-tunable} — invalid operator policy fails boot, not the first execution.
|
|
1270
|
-
EffectPolicy.validateConfiguration();
|
|
1271
|
-
LoopPolicies.validateConfiguration();
|
|
1272
1343
|
// {§exec} — mint a scheme per runtime tag so exec output entries address by tag
|
|
1273
1344
|
// authority (sh:///l/t/s). The "exec" scheme stays for execution dispatch.
|
|
1274
1345
|
this.#schemes.registerRuntimeSchemes(executors);
|
|
@@ -1279,7 +1350,10 @@ export default class Daemon {
|
|
|
1279
1350
|
// {§module-discovery} — third-party daemon-module composition: trusted
|
|
1280
1351
|
// packages declaring `plurnk.kind: "module"` register beside the
|
|
1281
1352
|
// service's explicit composition before any module setup runs.
|
|
1282
|
-
const discoveredModules = await discoverDaemonModules({ cwd: this.#discoveryCwd });
|
|
1353
|
+
const discoveredModules = await discoverDaemonModules({ cwd: this.#discoveryCwd, hostPaths: this.#hostPaths });
|
|
1354
|
+
for (const cause of discoveredModules.configurationErrors)
|
|
1355
|
+
this.#configuration.record("native-plugins", cause);
|
|
1356
|
+
this.#configuration.pluginReports(discoveredModules.reports);
|
|
1283
1357
|
for (const packageName of discoveredModules.skipped) {
|
|
1284
1358
|
console.warn(`module discovery: '${packageName}' is discovered but untrusted (PLURNK_PLUGINS_TRUSTED_ONLY); not registered`);
|
|
1285
1359
|
}
|
|
@@ -1288,8 +1362,8 @@ export default class Daemon {
|
|
|
1288
1362
|
}
|
|
1289
1363
|
const setupSeam = this;
|
|
1290
1364
|
for (const module of this.#modules) {
|
|
1291
|
-
if (module.close !== undefined)
|
|
1292
|
-
this.#
|
|
1365
|
+
if (module.stop !== undefined || module.close !== undefined)
|
|
1366
|
+
this.#moduleLifetimes.push(module);
|
|
1293
1367
|
await module.setup?.(setupSeam);
|
|
1294
1368
|
}
|
|
1295
1369
|
await this.#schemes.ready();
|
|
@@ -1300,8 +1374,8 @@ export default class Daemon {
|
|
|
1300
1374
|
// lifecycle recovery are complete. None opens a listener of its own.
|
|
1301
1375
|
for (const module of this.#modules) {
|
|
1302
1376
|
const started = await module.start?.(this);
|
|
1303
|
-
if (started !== undefined && !this.#
|
|
1304
|
-
this.#
|
|
1377
|
+
if (started !== undefined && !this.#moduleLifetimes.includes(started)) {
|
|
1378
|
+
this.#moduleLifetimes.push(started);
|
|
1305
1379
|
}
|
|
1306
1380
|
}
|
|
1307
1381
|
}
|
|
@@ -1364,7 +1438,7 @@ export default class Daemon {
|
|
|
1364
1438
|
// already between queue claim and activation must observe its own abort,
|
|
1365
1439
|
// not misclassify orderly shutdown as a capability failure.
|
|
1366
1440
|
const derivationAbort = new DOMException("daemon stopping", "AbortError");
|
|
1367
|
-
this.#retention
|
|
1441
|
+
this.#retention?.stop();
|
|
1368
1442
|
this.#engine.cancelAllProposals("daemon_stopping");
|
|
1369
1443
|
this.#engine.cancelDerivations(derivationAbort);
|
|
1370
1444
|
this.#drains.beginStop("daemon_stopping");
|
|
@@ -1386,10 +1460,15 @@ export default class Daemon {
|
|
|
1386
1460
|
// Stop accepting external work immediately, but do not await listener
|
|
1387
1461
|
// closure before cancelling active workers: an SSE connection may itself be
|
|
1388
1462
|
// waiting for the worker cancellation that follows.
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1463
|
+
const modules = this.#moduleLifetimes.toReversed();
|
|
1464
|
+
this.#moduleLifetimes = [];
|
|
1465
|
+
const modulePhase = async (phase) => {
|
|
1466
|
+
const results = await Promise.allSettled(modules.map((module) => Promise.resolve().then(() => module[phase]?.())));
|
|
1467
|
+
const errors = results.filter((result) => result.status === "rejected").map(({ reason }) => reason);
|
|
1468
|
+
if (errors.length > 0)
|
|
1469
|
+
throw new AggregateError(errors, `module ${phase} failed`);
|
|
1470
|
+
};
|
|
1471
|
+
const moduleStop = settle("modules stop", () => modulePhase("stop"));
|
|
1393
1472
|
// Drain order: (1) tell the supervisor to abort worker scopes so
|
|
1394
1473
|
// strike paths don't keep going, (2) await its active drains
|
|
1395
1474
|
// to completion, (3) drain streaming schemes' background work
|
|
@@ -1411,11 +1490,7 @@ export default class Daemon {
|
|
|
1411
1490
|
// A boundary publication queued behind the last turn settles before
|
|
1412
1491
|
// modules close and before the DB goes away ({§functionality-publication}).
|
|
1413
1492
|
const functionalityResult = await settle("functionality publications", () => this.#functionality.settle());
|
|
1414
|
-
const
|
|
1415
|
-
const results = await moduleClose;
|
|
1416
|
-
if (results.some((r) => r.status === "rejected"))
|
|
1417
|
-
throw new AggregateError(results.filter((r) => r.status === "rejected").map((r) => r.reason), "module close failed");
|
|
1418
|
-
});
|
|
1493
|
+
const moduleStopResult = await moduleStop;
|
|
1419
1494
|
const streamingResult = await settle("streaming schemes idle", () => this.#drainStreamingSchemes());
|
|
1420
1495
|
const derivationResult = await settle("derivation drain", () => this.#engine.drainDerivations(derivationAbort));
|
|
1421
1496
|
const mimetypeResult = this.#ownsMimetypes
|
|
@@ -1426,13 +1501,15 @@ export default class Daemon {
|
|
|
1426
1501
|
// conclusion notifications. Join the supervisor-owned async tails only
|
|
1427
1502
|
// after those producers settle, before the caller may close SQLite.
|
|
1428
1503
|
const wakeResult = await settle("drains idle (wake)", () => this.#drains.idle());
|
|
1504
|
+
const moduleCloseResult = await settle("modules close", () => modulePhase("close"));
|
|
1429
1505
|
// {§db-maintenance-optimize} — the last database step before the caller closes SQLite:
|
|
1430
1506
|
// planner statistics refreshed on the writer, bounded by SQLite's own analysis limit.
|
|
1431
1507
|
// {§retention-policy} — the operator's retention runs once more before the statistics.
|
|
1432
|
-
const collectResult = await settle("retention", () => this.#retention
|
|
1508
|
+
const collectResult = await settle("retention", async () => this.#retention?.run());
|
|
1433
1509
|
const optimizeResult = await settle("database optimize", () => this.#db.maintenance_optimize.run({}));
|
|
1434
1510
|
const closeErrors = [
|
|
1435
|
-
|
|
1511
|
+
moduleStopResult,
|
|
1512
|
+
moduleCloseResult,
|
|
1436
1513
|
functionalityResult,
|
|
1437
1514
|
drainResult,
|
|
1438
1515
|
streamingResult,
|