@plurnk/plurnk-service 1.23.0 → 1.25.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 +519 -206
- 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/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 +3 -2
- package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
- package/dist/core/AdmittedTurnExecutor.js +14 -1
- 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 +10 -0
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +71 -18
- 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/FabricatedLog.d.ts +2 -0
- package/dist/core/FabricatedLog.d.ts.map +1 -1
- package/dist/core/FabricatedLog.js +18 -7
- package/dist/core/FabricatedLog.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/LogEntryProjection.d.ts +1 -0
- package/dist/core/LogEntryProjection.d.ts.map +1 -1
- package/dist/core/LogEntryProjection.js +10 -0
- package/dist/core/LogEntryProjection.js.map +1 -1
- package/dist/core/LoopDriver.d.ts.map +1 -1
- package/dist/core/LoopDriver.js +8 -1
- 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/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 +2 -0
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +44 -32
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/PacketBuilder.sql +3 -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/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 +6 -0
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +18 -8
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/TurnSources.sql +0 -15
- 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 +46 -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/packet-wire.d.ts +10 -2
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +87 -69
- 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 +10 -4
- package/dist/digest/Digest.js.map +1 -1
- package/dist/digest/DigestRender.d.ts.map +1 -1
- package/dist/digest/DigestRender.js +51 -22
- package/dist/digest/DigestRender.js.map +1 -1
- package/dist/digest/DigestRequiem.d.ts.map +1 -1
- package/dist/digest/DigestRequiem.js +10 -4
- package/dist/digest/DigestRequiem.js.map +1 -1
- package/dist/digest/digest-rows.d.ts +9 -1
- package/dist/digest/digest-rows.d.ts.map +1 -1
- package/dist/digest/digest-rows.js.map +1 -1
- package/dist/digest/digest.sql +16 -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 +15 -10
- package/dist/schemes/File.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +25 -3
- package/dist/schemes/Log.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 +124 -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 +3 -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/migrations/012_emission.sql +77 -0
- package/package.json +38 -36
- package/plurnk.service +29 -0
- package/dist/core/PreviousEmission.d.ts +0 -14
- package/dist/core/PreviousEmission.d.ts.map +0 -1
- package/dist/core/PreviousEmission.js +0 -24
- package/dist/core/PreviousEmission.js.map +0 -1
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]]);
|
|
@@ -238,11 +268,12 @@ export default class Daemon {
|
|
|
238
268
|
return { action, loopId };
|
|
239
269
|
},
|
|
240
270
|
acquireWorkspaceTurn: async (workspaceId, workerId, signal) => this.#workspaceGate.acquireTurn(workspaceId, workerId, signal),
|
|
241
|
-
// {§
|
|
271
|
+
// {§functionality-hotload} — skills and plugins change out of band.
|
|
242
272
|
// Republish under the workspace turn gate before packet assembly so
|
|
243
273
|
// the first subsequent model turn sees their exact result.
|
|
244
274
|
workspaceTurnStarting: async ({ workspaceId }) => {
|
|
245
|
-
await this.#
|
|
275
|
+
await this.#functionality.refreshChanged({ workspaceId });
|
|
276
|
+
return [...this.configurationNotices(), ...this.#functionality.configurationNotices(workspaceId), ...this.#plugins.notices(workspaceId)];
|
|
246
277
|
},
|
|
247
278
|
// worker:// KILL (terminate) — cancel the addressed worker subtree and
|
|
248
279
|
// tear down its held streams before the operation completes.
|
|
@@ -252,7 +283,6 @@ export default class Daemon {
|
|
|
252
283
|
this.#broadcast({ workspaceId }, "loop/packet", payload);
|
|
253
284
|
}
|
|
254
285
|
});
|
|
255
|
-
this.#retention = new Retention(db, retentionPolicy());
|
|
256
286
|
this.#drains = new DrainSupervisor({
|
|
257
287
|
db,
|
|
258
288
|
lifecycle: this.#lifecycle,
|
|
@@ -323,7 +353,7 @@ export default class Daemon {
|
|
|
323
353
|
const { workspaceId, ...interaction } = event;
|
|
324
354
|
this.#broadcast({ workspaceId }, "loop/interaction", interaction);
|
|
325
355
|
});
|
|
326
|
-
this.#workerModels = new WorkerModelResolver({ db: this.#db
|
|
356
|
+
this.#workerModels = new WorkerModelResolver({ db: this.#db });
|
|
327
357
|
this.#reads = new ClientReads({ db: this.#db, engine: this.#engine, workspaceGate: this.#workspaceGate, residency: this.#residency });
|
|
328
358
|
}
|
|
329
359
|
// {§methods-event-subscribe}. A transport module subscribes to the daemon's in-process
|
|
@@ -870,10 +900,19 @@ export default class Daemon {
|
|
|
870
900
|
// {§methods} — the module's render surface beyond the journal. Thin delegations
|
|
871
901
|
// into core's envelope / membership / provider machinery; the module fans the results into its own views.
|
|
872
902
|
listProviders() {
|
|
873
|
-
const active =
|
|
903
|
+
const active = process.env.PLURNK_MODEL?.toLowerCase();
|
|
904
|
+
let aliases;
|
|
905
|
+
try {
|
|
906
|
+
aliases = parseAliasesFromEnv();
|
|
907
|
+
}
|
|
908
|
+
catch (cause) {
|
|
909
|
+
if (!(cause instanceof ConfigurationError))
|
|
910
|
+
throw cause;
|
|
911
|
+
throw new OperationFailureError(Results.configurationFailure(cause), { cause });
|
|
912
|
+
}
|
|
874
913
|
return {
|
|
875
|
-
aliases:
|
|
876
|
-
const isActive = active
|
|
914
|
+
aliases: aliases.map((a) => {
|
|
915
|
+
const isActive = active === a.alias;
|
|
877
916
|
return {
|
|
878
917
|
alias: a.alias, provider: a.provider, model: a.model, active: isActive,
|
|
879
918
|
inputCapacity: isActive && this.#provider !== null ? this.#provider.inputCapacity : null
|
|
@@ -988,6 +1027,9 @@ export default class Daemon {
|
|
|
988
1027
|
const checkedWorkerId = workerId === undefined ? null : ClientInput.assertId("workspace.prompts", "workerId", workerId);
|
|
989
1028
|
return Envelope.listPromptsForWorkspace(this.#db, checkedWorkspaceId, checkedLimit ?? Knob.integer("PLURNK_SERVICE_PROMPTS_PAGE", 1), checkedWorkerId);
|
|
990
1029
|
}
|
|
1030
|
+
workspacePreparationStatus(workspaceId) {
|
|
1031
|
+
return this.#functionality.preparationStatus(ClientInput.assertId("workspace preparation", "workspaceId", workspaceId));
|
|
1032
|
+
}
|
|
991
1033
|
workspaceDerivationStatus(workspaceId) {
|
|
992
1034
|
return this.#engine.workspaceDerivationStatus(ClientInput.assertId("workspace.derivation", "workspaceId", workspaceId));
|
|
993
1035
|
}
|
|
@@ -1142,6 +1184,12 @@ export default class Daemon {
|
|
|
1142
1184
|
}
|
|
1143
1185
|
if (typeof handler !== "function")
|
|
1144
1186
|
throw new Error(`module action '${name}' has no handler`);
|
|
1187
|
+
if (registration.residency !== "required" && registration.residency !== "none") {
|
|
1188
|
+
throw new Error(`module action '${name}' must declare its residency requirement`);
|
|
1189
|
+
}
|
|
1190
|
+
if (scope === "worldless" && registration.residency !== "none") {
|
|
1191
|
+
throw new Error(`worldless module action '${name}' cannot require workspace residency`);
|
|
1192
|
+
}
|
|
1145
1193
|
if (this.#moduleActions.has(name))
|
|
1146
1194
|
throw new Error(`module action '${name}' is already registered`);
|
|
1147
1195
|
this.#moduleActions.set(name, registration);
|
|
@@ -1164,20 +1212,22 @@ export default class Daemon {
|
|
|
1164
1212
|
throw new Error(`module action '${name}' requires ${registration.scope} context, not ${context.scope}`);
|
|
1165
1213
|
}
|
|
1166
1214
|
let releaseCapabilities;
|
|
1167
|
-
if (context.scope === "
|
|
1168
|
-
releaseCapabilities = await this.#residency.acquire(context.workspaceId);
|
|
1169
|
-
}
|
|
1170
|
-
else if (context.scope === "worker") {
|
|
1215
|
+
if (context.scope === "worker") {
|
|
1171
1216
|
const workspaceId = ClientInput.assertId(`module action '${name}'`, "workspaceId", context.workspaceId);
|
|
1172
1217
|
const workerId = ClientInput.assertId(`module action '${name}'`, "workerId", context.workerId);
|
|
1173
1218
|
const worker = await this.#db.envelope_get_worker_by_id.get({ id: workerId });
|
|
1174
1219
|
if (worker === undefined || worker.workspace_id !== workspaceId) {
|
|
1175
1220
|
throw daemonFailure("daemon:module-action", "worker-not-found", 404, `Worker ${workerId} does not exist in workspace ${workspaceId}.`, { workspaceId, workerId, retryable: false });
|
|
1176
1221
|
}
|
|
1177
|
-
|
|
1222
|
+
}
|
|
1223
|
+
if (registration.residency === "required" && context.scope !== "worldless") {
|
|
1224
|
+
releaseCapabilities = await this.#residency.acquire(context.workspaceId);
|
|
1225
|
+
}
|
|
1226
|
+
else if (context.scope === "workspace") {
|
|
1227
|
+
await this.#residency.identity(context.workspaceId);
|
|
1178
1228
|
}
|
|
1179
1229
|
try {
|
|
1180
|
-
if (context.scope === "worker") {
|
|
1230
|
+
if (registration.residency === "required" && context.scope === "worker") {
|
|
1181
1231
|
const release = await this.#workspaceGate.acquireTurn(context.workspaceId, context.workerId);
|
|
1182
1232
|
try {
|
|
1183
1233
|
await this.#residency.reconcile(context.workspaceId);
|
|
@@ -1206,6 +1256,18 @@ export default class Daemon {
|
|
|
1206
1256
|
workspaceStateDirectory(workspaceId, namespaceOwner) {
|
|
1207
1257
|
return this.#storage.directory(workspaceId, namespaceOwner);
|
|
1208
1258
|
}
|
|
1259
|
+
async workspaceConfigurationDirectories(workspaceId) {
|
|
1260
|
+
const workspace = await this.#db.envelope_get_workspace.get({ id: workspaceId });
|
|
1261
|
+
return configurationDirectories(this.#hostPaths, workspace?.project_root ?? null);
|
|
1262
|
+
}
|
|
1263
|
+
// {§agent-plugins-hosting}
|
|
1264
|
+
readWorkspacePlugins(workspaceId) {
|
|
1265
|
+
return this.#plugins.read(workspaceId);
|
|
1266
|
+
}
|
|
1267
|
+
// {§mcp-launch-environment}
|
|
1268
|
+
operatorEnvironment() {
|
|
1269
|
+
return ExecEnv.withoutOwnSecrets();
|
|
1270
|
+
}
|
|
1209
1271
|
async readWorkerEnvironment(workspaceId, workerId) {
|
|
1210
1272
|
await this.#assertWorkerOwned(workspaceId, workerId);
|
|
1211
1273
|
const shared = await EnvFunctionality.workspace(this.#db, workspaceId);
|
|
@@ -1220,6 +1282,7 @@ export default class Daemon {
|
|
|
1220
1282
|
await this.#residency.replace(replacement, options);
|
|
1221
1283
|
}
|
|
1222
1284
|
get engine() { return this.#engine; }
|
|
1285
|
+
configurationNotices() { return this.#configuration.notices(); }
|
|
1223
1286
|
get provider() { return this.#provider; }
|
|
1224
1287
|
get schemes() { return this.#schemes; }
|
|
1225
1288
|
get mimetypes() { return this.#mimetypes; }
|
|
@@ -1231,14 +1294,22 @@ export default class Daemon {
|
|
|
1231
1294
|
async start() {
|
|
1232
1295
|
if (this.#started)
|
|
1233
1296
|
throw new Error("daemon already started");
|
|
1297
|
+
await this.#configuration.capture("file-creation", () => FileCreationPolicy.serviceScope());
|
|
1298
|
+
await this.#configuration.capture("effect-policy", () => EffectPolicy.validateConfiguration());
|
|
1299
|
+
await this.#configuration.capture("loop-policy", () => LoopPolicies.validateConfiguration());
|
|
1300
|
+
await this.#configuration.capture("packet", () => PacketBuilder.validateConfiguration());
|
|
1301
|
+
await this.#configuration.capture("execution", () => Exec.validateConfiguration());
|
|
1302
|
+
this.#retention = await this.#configuration.capture("retention", () => new Retention(this.#db, retentionPolicy()));
|
|
1234
1303
|
this.#started = true;
|
|
1235
1304
|
// {§db-space-reclamation} — the file is brought to the policy's auto-vacuum mode before any work.
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1305
|
+
if (this.#retention !== null) {
|
|
1306
|
+
const storage = await this.#retention.prepareStorage();
|
|
1307
|
+
if (storage.converted) {
|
|
1308
|
+
console.error(`database: converted to auto_vacuum=${this.#retention.policy.autoVacuum} (${storage.pagesBefore} → ${storage.pagesAfter} pages)`);
|
|
1309
|
+
}
|
|
1239
1310
|
}
|
|
1240
1311
|
this.#drains.start();
|
|
1241
|
-
this.#retention
|
|
1312
|
+
this.#retention?.start((cause) => { console.error("retention pass failed:", cause instanceof Error ? cause.message : String(cause)); });
|
|
1242
1313
|
// Mimetypes owns its own discovery scan over @plurnk/plurnk-mimetypes-*
|
|
1243
1314
|
// packages; pre-warm it so first index render doesn't pay the cost.
|
|
1244
1315
|
await this.#mimetypes.ready();
|
|
@@ -1246,9 +1317,11 @@ export default class Daemon {
|
|
|
1246
1317
|
console.warn(`mimetype discovery: '${name}' is discovered but untrusted (PLURNK_PLUGINS_TRUSTED_ONLY); not registered`);
|
|
1247
1318
|
}
|
|
1248
1319
|
// Discover + probe the installed executor siblings, then hand the
|
|
1249
|
-
// registry to the engine for exec dispatch ({§exec-registry-resolves}).
|
|
1250
|
-
|
|
1251
|
-
const
|
|
1320
|
+
// registry to the engine for exec dispatch ({§exec-registry-resolves}).
|
|
1321
|
+
const executors = await ExecutorRegistry.build({ cwd: this.#discoveryCwd });
|
|
1322
|
+
for (const { runtime, error } of executors.configurationErrors()) {
|
|
1323
|
+
this.#configuration.record(`executor:${runtime}`, error);
|
|
1324
|
+
}
|
|
1252
1325
|
this.#engine.setExecutors(executors);
|
|
1253
1326
|
this.#engine.setFunctionalityDocuments((workspaceId) => this.#functionality.documents(workspaceId));
|
|
1254
1327
|
// {§question-tool} — the native request-user-input runtime, process-wide;
|
|
@@ -1266,9 +1339,6 @@ export default class Daemon {
|
|
|
1266
1339
|
detail: "in-process"
|
|
1267
1340
|
}
|
|
1268
1341
|
}]);
|
|
1269
|
-
// {§effect-policy-tunable} — invalid operator policy fails boot, not the first execution.
|
|
1270
|
-
EffectPolicy.validateConfiguration();
|
|
1271
|
-
LoopPolicies.validateConfiguration();
|
|
1272
1342
|
// {§exec} — mint a scheme per runtime tag so exec output entries address by tag
|
|
1273
1343
|
// authority (sh:///l/t/s). The "exec" scheme stays for execution dispatch.
|
|
1274
1344
|
this.#schemes.registerRuntimeSchemes(executors);
|
|
@@ -1279,7 +1349,10 @@ export default class Daemon {
|
|
|
1279
1349
|
// {§module-discovery} — third-party daemon-module composition: trusted
|
|
1280
1350
|
// packages declaring `plurnk.kind: "module"` register beside the
|
|
1281
1351
|
// service's explicit composition before any module setup runs.
|
|
1282
|
-
const discoveredModules = await discoverDaemonModules({ cwd: this.#discoveryCwd });
|
|
1352
|
+
const discoveredModules = await discoverDaemonModules({ cwd: this.#discoveryCwd, hostPaths: this.#hostPaths });
|
|
1353
|
+
for (const cause of discoveredModules.configurationErrors)
|
|
1354
|
+
this.#configuration.record("native-plugins", cause);
|
|
1355
|
+
this.#configuration.pluginReports(discoveredModules.reports);
|
|
1283
1356
|
for (const packageName of discoveredModules.skipped) {
|
|
1284
1357
|
console.warn(`module discovery: '${packageName}' is discovered but untrusted (PLURNK_PLUGINS_TRUSTED_ONLY); not registered`);
|
|
1285
1358
|
}
|
|
@@ -1288,8 +1361,8 @@ export default class Daemon {
|
|
|
1288
1361
|
}
|
|
1289
1362
|
const setupSeam = this;
|
|
1290
1363
|
for (const module of this.#modules) {
|
|
1291
|
-
if (module.close !== undefined)
|
|
1292
|
-
this.#
|
|
1364
|
+
if (module.stop !== undefined || module.close !== undefined)
|
|
1365
|
+
this.#moduleLifetimes.push(module);
|
|
1293
1366
|
await module.setup?.(setupSeam);
|
|
1294
1367
|
}
|
|
1295
1368
|
await this.#schemes.ready();
|
|
@@ -1300,8 +1373,8 @@ export default class Daemon {
|
|
|
1300
1373
|
// lifecycle recovery are complete. None opens a listener of its own.
|
|
1301
1374
|
for (const module of this.#modules) {
|
|
1302
1375
|
const started = await module.start?.(this);
|
|
1303
|
-
if (started !== undefined && !this.#
|
|
1304
|
-
this.#
|
|
1376
|
+
if (started !== undefined && !this.#moduleLifetimes.includes(started)) {
|
|
1377
|
+
this.#moduleLifetimes.push(started);
|
|
1305
1378
|
}
|
|
1306
1379
|
}
|
|
1307
1380
|
}
|
|
@@ -1364,7 +1437,7 @@ export default class Daemon {
|
|
|
1364
1437
|
// already between queue claim and activation must observe its own abort,
|
|
1365
1438
|
// not misclassify orderly shutdown as a capability failure.
|
|
1366
1439
|
const derivationAbort = new DOMException("daemon stopping", "AbortError");
|
|
1367
|
-
this.#retention
|
|
1440
|
+
this.#retention?.stop();
|
|
1368
1441
|
this.#engine.cancelAllProposals("daemon_stopping");
|
|
1369
1442
|
this.#engine.cancelDerivations(derivationAbort);
|
|
1370
1443
|
this.#drains.beginStop("daemon_stopping");
|
|
@@ -1386,10 +1459,15 @@ export default class Daemon {
|
|
|
1386
1459
|
// Stop accepting external work immediately, but do not await listener
|
|
1387
1460
|
// closure before cancelling active workers: an SSE connection may itself be
|
|
1388
1461
|
// waiting for the worker cancellation that follows.
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1462
|
+
const modules = this.#moduleLifetimes.toReversed();
|
|
1463
|
+
this.#moduleLifetimes = [];
|
|
1464
|
+
const modulePhase = async (phase) => {
|
|
1465
|
+
const results = await Promise.allSettled(modules.map((module) => Promise.resolve().then(() => module[phase]?.())));
|
|
1466
|
+
const errors = results.filter((result) => result.status === "rejected").map(({ reason }) => reason);
|
|
1467
|
+
if (errors.length > 0)
|
|
1468
|
+
throw new AggregateError(errors, `module ${phase} failed`);
|
|
1469
|
+
};
|
|
1470
|
+
const moduleStop = settle("modules stop", () => modulePhase("stop"));
|
|
1393
1471
|
// Drain order: (1) tell the supervisor to abort worker scopes so
|
|
1394
1472
|
// strike paths don't keep going, (2) await its active drains
|
|
1395
1473
|
// to completion, (3) drain streaming schemes' background work
|
|
@@ -1411,11 +1489,7 @@ export default class Daemon {
|
|
|
1411
1489
|
// A boundary publication queued behind the last turn settles before
|
|
1412
1490
|
// modules close and before the DB goes away ({§functionality-publication}).
|
|
1413
1491
|
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
|
-
});
|
|
1492
|
+
const moduleStopResult = await moduleStop;
|
|
1419
1493
|
const streamingResult = await settle("streaming schemes idle", () => this.#drainStreamingSchemes());
|
|
1420
1494
|
const derivationResult = await settle("derivation drain", () => this.#engine.drainDerivations(derivationAbort));
|
|
1421
1495
|
const mimetypeResult = this.#ownsMimetypes
|
|
@@ -1426,13 +1500,15 @@ export default class Daemon {
|
|
|
1426
1500
|
// conclusion notifications. Join the supervisor-owned async tails only
|
|
1427
1501
|
// after those producers settle, before the caller may close SQLite.
|
|
1428
1502
|
const wakeResult = await settle("drains idle (wake)", () => this.#drains.idle());
|
|
1503
|
+
const moduleCloseResult = await settle("modules close", () => modulePhase("close"));
|
|
1429
1504
|
// {§db-maintenance-optimize} — the last database step before the caller closes SQLite:
|
|
1430
1505
|
// planner statistics refreshed on the writer, bounded by SQLite's own analysis limit.
|
|
1431
1506
|
// {§retention-policy} — the operator's retention runs once more before the statistics.
|
|
1432
|
-
const collectResult = await settle("retention", () => this.#retention
|
|
1507
|
+
const collectResult = await settle("retention", async () => this.#retention?.run());
|
|
1433
1508
|
const optimizeResult = await settle("database optimize", () => this.#db.maintenance_optimize.run({}));
|
|
1434
1509
|
const closeErrors = [
|
|
1435
|
-
|
|
1510
|
+
moduleStopResult,
|
|
1511
|
+
moduleCloseResult,
|
|
1436
1512
|
functionalityResult,
|
|
1437
1513
|
drainResult,
|
|
1438
1514
|
streamingResult,
|