@plurnk/plurnk-service 1.12.0 → 1.14.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 +4 -6
- package/SPEC.md +62 -85
- package/dist/build-info.json +1 -1
- package/dist/content/matcher.d.ts.map +1 -1
- package/dist/content/matcher.js +21 -1
- package/dist/content/matcher.js.map +1 -1
- package/dist/core/ChannelWrite.d.ts +1 -17
- package/dist/core/ChannelWrite.d.ts.map +1 -1
- package/dist/core/ChannelWrite.js +5 -5
- package/dist/core/ChannelWrite.js.map +1 -1
- 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/Dispatcher.d.ts +3 -4
- package/dist/core/Dispatcher.d.ts.map +1 -1
- package/dist/core/Dispatcher.js +13 -43
- package/dist/core/Dispatcher.js.map +1 -1
- package/dist/core/Engine.d.ts +3 -12
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +103 -45
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +2 -0
- package/dist/core/PacketBuilder.d.ts.map +1 -1
- package/dist/core/PacketBuilder.js +1 -6
- package/dist/core/PacketBuilder.js.map +1 -1
- package/dist/core/TurnRunner.d.ts.map +1 -1
- package/dist/core/TurnRunner.js +26 -5
- package/dist/core/TurnRunner.js.map +1 -1
- package/dist/core/VectorPump.d.ts +28 -0
- package/dist/core/VectorPump.d.ts.map +1 -0
- package/dist/core/VectorPump.js +130 -0
- package/dist/core/VectorPump.js.map +1 -0
- package/dist/core/packet-wire.d.ts +1 -1
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +2 -5
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/scheme-types.d.ts +1 -0
- package/dist/core/scheme-types.d.ts.map +1 -1
- package/dist/digest/Digest.d.ts.map +1 -1
- package/dist/digest/Digest.js +69 -16
- package/dist/digest/Digest.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +14 -0
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Log.sql +3 -0
- package/dist/schemes/Worker.d.ts.map +1 -1
- package/dist/schemes/Worker.js +0 -2
- package/dist/schemes/Worker.js.map +1 -1
- package/dist/schemes/_entry-graph.sql +21 -1
- package/dist/schemes/_entry-semantic.d.ts.map +1 -1
- package/dist/schemes/_entry-semantic.js +5 -0
- package/dist/schemes/_entry-semantic.js.map +1 -1
- package/dist/schemes/_search-index.d.ts +5 -1
- package/dist/schemes/_search-index.d.ts.map +1 -1
- package/dist/schemes/_search-index.js +66 -24
- package/dist/schemes/_search-index.js.map +1 -1
- package/dist/server/Daemon.d.ts +1 -1
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +81 -149
- package/dist/server/Daemon.js.map +1 -1
- package/dist/server/drain.sql +16 -0
- package/dist/server/lifecycle-recovery.sql +0 -7
- package/dist/server/model-route.d.ts +2 -2
- package/dist/server/model-route.d.ts.map +1 -1
- package/dist/server/model-route.js +8 -1
- package/dist/server/model-route.js.map +1 -1
- package/migrations/001_schema.sql +0 -51
- package/package.json +37 -37
- package/dist/core/BranchReceipt.d.ts +0 -6
- package/dist/core/BranchReceipt.d.ts.map +0 -1
- package/dist/core/BranchReceipt.js +0 -29
- package/dist/core/BranchReceipt.js.map +0 -1
- package/dist/core/GitBranch.d.ts +0 -23
- package/dist/core/GitBranch.d.ts.map +0 -1
- package/dist/core/GitBranch.js +0 -120
- package/dist/core/GitBranch.js.map +0 -1
- package/dist/server/BranchBatches.d.ts +0 -49
- package/dist/server/BranchBatches.d.ts.map +0 -1
- package/dist/server/BranchBatches.js +0 -599
- package/dist/server/BranchBatches.js.map +0 -1
- package/dist/server/branch-batch.sql +0 -156
package/dist/server/Daemon.js
CHANGED
|
@@ -15,7 +15,7 @@ import WorkerSettingsReader from "../core/worker-settings.js";
|
|
|
15
15
|
import EffectPolicy from "../schemes/EffectPolicy.js";
|
|
16
16
|
import QuestionTool, { questionRuntimeDecl } from "../schemes/QuestionTool.js";
|
|
17
17
|
import DrainSupervisor from "./DrainSupervisor.js";
|
|
18
|
-
import { parsePath, CapabilityAdmission, Validator
|
|
18
|
+
import { parsePath, CapabilityAdmission, Validator } from "@plurnk/plurnk-contracts";
|
|
19
19
|
import LogEntry from "./logEntry.js";
|
|
20
20
|
import Envelope from "./envelope.js";
|
|
21
21
|
import ClientInput from "./client-input.js";
|
|
@@ -23,12 +23,11 @@ import Turn from "../core/Turn.js";
|
|
|
23
23
|
import SkillsFunctionality from "./SkillsFunctionality.js";
|
|
24
24
|
import MembersFunctionality from "./MembersFunctionality.js";
|
|
25
25
|
import Fork from "../core/fork.js";
|
|
26
|
-
import WorkerName from "../core/WorkerName.js";
|
|
27
26
|
import WorkerControlAddress from "../core/WorkerControlAddress.js";
|
|
28
27
|
import LoopLifecycle from "../core/LoopLifecycle.js";
|
|
29
28
|
import { promptLoopPrefix } from "../core/plurnk-uri.js";
|
|
30
29
|
import { contentWeight } from "../core/content-weight.js";
|
|
31
|
-
import { parseAliasesFromEnv, resolveActiveRoute, UnsupportedReasoningPolicyError
|
|
30
|
+
import { parseAliasesFromEnv, resolveActiveRoute, UnsupportedReasoningPolicyError } from "@plurnk/plurnk-providers";
|
|
32
31
|
import ProviderInstantiate from "../core/ProviderInstantiate.js";
|
|
33
32
|
import { resolveLoopRoute } from "./loop-model.js";
|
|
34
33
|
import LoopPolicyReader from "../core/LoopPolicyReader.js";
|
|
@@ -36,7 +35,6 @@ import CapabilityPolicies from "../core/CapabilityPolicies.js";
|
|
|
36
35
|
import Results, { OperationFailureError } from "../core/results.js";
|
|
37
36
|
import WorkspaceGate from "../core/WorkspaceGate.js";
|
|
38
37
|
import WorkerResidency from "./WorkerResidency.js";
|
|
39
|
-
import BranchBatches from "./BranchBatches.js";
|
|
40
38
|
import Functionality from "./Functionality.js";
|
|
41
39
|
import { observed, observedSync } from "../observe/spans.js";
|
|
42
40
|
import { listModelCatalog } from "./model-catalog.js";
|
|
@@ -46,7 +44,7 @@ const clientActionFailure = (error) => {
|
|
|
46
44
|
console.error("Client action failed outside its operation result contract:", error);
|
|
47
45
|
return Results.failure("daemon:client", "action-threw", 500, "The client action failed outside its operation result contract.", {}, {
|
|
48
46
|
stage: "client-action",
|
|
49
|
-
retryable: false
|
|
47
|
+
retryable: false
|
|
50
48
|
});
|
|
51
49
|
};
|
|
52
50
|
const daemonFailure = (owner, code, status, detail, extensions = {}) => new OperationFailureError(Results.failure(owner, code, status, detail, {}, extensions));
|
|
@@ -58,7 +56,6 @@ export default class Daemon {
|
|
|
58
56
|
#db;
|
|
59
57
|
#engine;
|
|
60
58
|
#workspaceGate;
|
|
61
|
-
#branchBatches;
|
|
62
59
|
#lifecycle;
|
|
63
60
|
#drains;
|
|
64
61
|
#schemes;
|
|
@@ -79,7 +76,7 @@ export default class Daemon {
|
|
|
79
76
|
// module (plurnk-agui) subscribes and fans out to its OWN clients; core emits, never owns
|
|
80
77
|
// client transport or connection state.
|
|
81
78
|
#eventSubscribers = new Set();
|
|
82
|
-
constructor({ db, schemes, mimetypes, provider, nodeModulesPath, skills
|
|
79
|
+
constructor({ db, schemes, mimetypes, provider, nodeModulesPath, skills }) {
|
|
83
80
|
this.#db = db;
|
|
84
81
|
this.#lifecycle = new LoopLifecycle(db);
|
|
85
82
|
this.#schemes = schemes ?? new SchemeRegistry();
|
|
@@ -97,16 +94,16 @@ export default class Daemon {
|
|
|
97
94
|
this.#ownsMimetypes = mimetypes === undefined;
|
|
98
95
|
this.#mimetypes = mimetypes ?? new Mimetypes({
|
|
99
96
|
defaultMimetype: "text/markdown",
|
|
100
|
-
discoverOptions: { cwd: this.#discoveryCwd }
|
|
97
|
+
discoverOptions: { cwd: this.#discoveryCwd }
|
|
101
98
|
});
|
|
102
99
|
const bootSpec = resolveActiveRoute();
|
|
103
100
|
if (this.#provider !== null && bootSpec !== null) {
|
|
104
101
|
ProviderInstantiate.registerInstance(this.#provider, bootSpec);
|
|
105
102
|
}
|
|
106
103
|
this.#workspaceGate = new WorkspaceGate(async (workerId, rootWorkerId) => {
|
|
107
|
-
const row = await this.#db.
|
|
104
|
+
const row = await this.#db.worker_lineage_contains.get({
|
|
108
105
|
worker_id: workerId,
|
|
109
|
-
root_worker_id: rootWorkerId
|
|
106
|
+
root_worker_id: rootWorkerId
|
|
110
107
|
});
|
|
111
108
|
return row !== undefined;
|
|
112
109
|
});
|
|
@@ -116,7 +113,7 @@ export default class Daemon {
|
|
|
116
113
|
db,
|
|
117
114
|
engine: () => this.#engine,
|
|
118
115
|
workspaceGate: this.#workspaceGate,
|
|
119
|
-
normalizeRuntime: (registration) => this.#normalizeRuntime(registration)
|
|
116
|
+
normalizeRuntime: (registration) => this.#normalizeRuntime(registration)
|
|
120
117
|
});
|
|
121
118
|
// {§functionality-coordinator} — the one owner above every family
|
|
122
119
|
// adapter; Core hosts it, modules register adapters through the seam.
|
|
@@ -125,7 +122,7 @@ export default class Daemon {
|
|
|
125
122
|
registerWorkerCapabilityProvider: (owner, provider) => this.registerWorkerCapabilityProvider(owner, provider),
|
|
126
123
|
readWorkerModuleState: (workerId, owner) => this.readWorkerModuleState(workerId, owner),
|
|
127
124
|
replaceWorkerCapabilities: (replacement, options) => this.replaceWorkerCapabilities(replacement, options),
|
|
128
|
-
retainWorker: (workerId) => this.#residency.retain(workerId)
|
|
125
|
+
retainWorker: (workerId) => this.#residency.retain(workerId)
|
|
129
126
|
});
|
|
130
127
|
// {§skills-functionality} — Core's own family: standard Agent Skills.
|
|
131
128
|
this.#skills = new SkillsFunctionality({ db, ...skills });
|
|
@@ -133,64 +130,6 @@ export default class Daemon {
|
|
|
133
130
|
// {§members-functionality} — Core's own family: file membership on the same surface.
|
|
134
131
|
this.#members = new MembersFunctionality({ db, engine: () => this.#engine });
|
|
135
132
|
this.#functionality.register(this.#members);
|
|
136
|
-
this.#branchBatches = new BranchBatches(db, this.#workspaceGate, {
|
|
137
|
-
settleWorkspace: async (workspaceId) => this.#engine.drainWorkspaceDerivations(workspaceId),
|
|
138
|
-
createChild: async ({ workspaceId, parentWorkerId, parentLoopId, op, name, prompt, policy, origin }) => {
|
|
139
|
-
const parentPolicy = await this.#providerPolicyForLoop(parentLoopId);
|
|
140
|
-
const providerSpec = parentPolicy.childProviderSpec ?? parentPolicy.providerSpec;
|
|
141
|
-
const workerName = WorkerName.assert(name);
|
|
142
|
-
const capabilityBound = await CapabilityPolicies.delegationBound(this.#db, workspaceId, parentWorkerId, policy);
|
|
143
|
-
const workerId = op === "FORK"
|
|
144
|
-
? await Fork.fork(this.#db, parentWorkerId, workerName, capabilityBound, (scheme) => this.#schemes.entryInheritanceForStoredScheme(scheme, parentWorkerId))
|
|
145
|
-
: (await this.#db.fork_insert_worker.get({
|
|
146
|
-
workspace_id: workspaceId,
|
|
147
|
-
name: workerName,
|
|
148
|
-
parent_worker_id: parentWorkerId,
|
|
149
|
-
origin,
|
|
150
|
-
fork_snapshot: 0,
|
|
151
|
-
capability_bound: JSON.stringify(capabilityBound),
|
|
152
|
-
}))?.id;
|
|
153
|
-
if (workerId === undefined)
|
|
154
|
-
throw new Error("Branch worker insert returned no row");
|
|
155
|
-
// {§worker-model-selection} — lineage inheritance by value: the branch
|
|
156
|
-
// child begins with the spawning loop's effective spawn model.
|
|
157
|
-
await this.#db.worker_generation_policy_update.run({
|
|
158
|
-
id: workerId,
|
|
159
|
-
model_route_id: await routeForSpec(this.#db, providerSpec),
|
|
160
|
-
spawn_model_route_id: null,
|
|
161
|
-
reasoning_policy: parentPolicy.reasoningPolicy,
|
|
162
|
-
});
|
|
163
|
-
const source = await this.#workerPromptSource(workspaceId, parentWorkerId, workerId);
|
|
164
|
-
const loopId = await this.#drains.enqueueFreshLoop({
|
|
165
|
-
workerId,
|
|
166
|
-
prompt,
|
|
167
|
-
...(source === undefined ? {} : { source }),
|
|
168
|
-
providerSpec,
|
|
169
|
-
reasoningPolicy: parentPolicy.reasoningPolicy,
|
|
170
|
-
childProviderSpec: parentPolicy.childProviderSpec,
|
|
171
|
-
policy,
|
|
172
|
-
});
|
|
173
|
-
return { workerId, loopId };
|
|
174
|
-
},
|
|
175
|
-
startChild: async (workspaceId, workerId, loopId) => {
|
|
176
|
-
const systemPrompt = await readFile(Paths.instructionsSystem, "utf8");
|
|
177
|
-
const started = await this.#drains.ensureDrain({ workspaceId, workerId, systemPrompt });
|
|
178
|
-
if (started === null)
|
|
179
|
-
throw new Error(`Branch worker ${workerId} already has a live drain`);
|
|
180
|
-
const result = await started.firstLoopPromise;
|
|
181
|
-
if (result.loopId !== loopId) {
|
|
182
|
-
throw new Error(`Branch worker ${workerId} drained loop ${result.loopId}, expected ${loopId}`);
|
|
183
|
-
}
|
|
184
|
-
return result.result;
|
|
185
|
-
},
|
|
186
|
-
wakeParent: async (workspaceId, workerId) => {
|
|
187
|
-
const systemPrompt = await readFile(Paths.instructionsSystem, "utf8");
|
|
188
|
-
await this.#drains.settleCompletionWake(workspaceId, workerId, systemPrompt, false);
|
|
189
|
-
},
|
|
190
|
-
notify: (workspaceId, payload) => {
|
|
191
|
-
this.#broadcast({ workspaceId }, "workspace/branch-batch", payload);
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
133
|
this.#engine = new Engine({
|
|
195
134
|
db, schemes: this.#schemes, mimetypes: this.#mimetypes,
|
|
196
135
|
// {§tokenomics-agnostic-ruler} — stored and catalog curation weights
|
|
@@ -237,7 +176,7 @@ export default class Daemon {
|
|
|
237
176
|
id: workerId,
|
|
238
177
|
model_route_id: await routeForSpec(this.#db, providerSpec),
|
|
239
178
|
spawn_model_route_id: null,
|
|
240
|
-
reasoning_policy: reasoningPolicy
|
|
179
|
+
reasoning_policy: reasoningPolicy
|
|
241
180
|
});
|
|
242
181
|
}
|
|
243
182
|
const { action, loopId } = await this.inject({
|
|
@@ -249,12 +188,10 @@ export default class Daemon {
|
|
|
249
188
|
reasoningPolicy,
|
|
250
189
|
childProviderSpec,
|
|
251
190
|
systemPrompt,
|
|
252
|
-
...(freshLoopPolicy === undefined ? {} : { freshLoopPolicy })
|
|
191
|
+
...(freshLoopPolicy === undefined ? {} : { freshLoopPolicy })
|
|
253
192
|
});
|
|
254
193
|
return { action, loopId };
|
|
255
194
|
},
|
|
256
|
-
branchWorker: async (args) => this.#branchBatches.enqueue(args),
|
|
257
|
-
branchCompletionGate: async (workerId) => this.#branchBatches.completionGate(workerId),
|
|
258
195
|
acquireWorkspaceTurn: async (workspaceId, workerId) => this.#workspaceGate.acquireTurn(workspaceId, workerId),
|
|
259
196
|
// {§skills-hotload} — filesystem installers operate out of band.
|
|
260
197
|
// Republish under the workspace turn gate before packet assembly so
|
|
@@ -262,9 +199,6 @@ export default class Daemon {
|
|
|
262
199
|
workspaceTurnStarting: async ({ workspaceId, workerId }) => {
|
|
263
200
|
await this.#skills.refreshIfChanged({ workspaceId, workerId });
|
|
264
201
|
},
|
|
265
|
-
workspaceTurnCompleted: async ({ turnId }) => {
|
|
266
|
-
await this.#branchBatches.sealTurn(turnId);
|
|
267
|
-
},
|
|
268
202
|
// worker:// KILL (terminate) — cancel the addressed worker subtree and
|
|
269
203
|
// tear down its held streams before the operation completes.
|
|
270
204
|
cancelWorker: async (workerId, reason) => this.#drains.cancelWorkerTree(workerId, reason),
|
|
@@ -272,13 +206,13 @@ export default class Daemon {
|
|
|
272
206
|
noticeNotify: (workspaceId, payload) => this.notifyNotice(workspaceId, payload),
|
|
273
207
|
loopPacketNotify: (workspaceId, payload) => {
|
|
274
208
|
this.#broadcast({ workspaceId }, "loop/packet", payload);
|
|
275
|
-
}
|
|
209
|
+
}
|
|
276
210
|
});
|
|
277
211
|
this.#drains = new DrainSupervisor({
|
|
278
212
|
db,
|
|
279
213
|
lifecycle: this.#lifecycle,
|
|
280
214
|
injectPrompt: (workerId, prompt, openPaths, source) => this.#engine.inject(workerId, prompt, openPaths, source),
|
|
281
|
-
assertInjectionCompatibility: async ({ workerId, loopId, providerSpec, providerSpecExplicit, reasoningPolicy, childProviderSpec, turnCeiling, policy
|
|
215
|
+
assertInjectionCompatibility: async ({ workerId, loopId, providerSpec, providerSpecExplicit, reasoningPolicy, childProviderSpec, turnCeiling, policy }) => {
|
|
282
216
|
await this.#assertFoldPosture(workerId, policy, loopId);
|
|
283
217
|
// An omitted selector keeps the loop's durable provider; only an
|
|
284
218
|
// explicit selection is checked against it (a deliberate switch).
|
|
@@ -292,7 +226,7 @@ export default class Daemon {
|
|
|
292
226
|
await this.#assertLoopMaxTurns(loopId, turnCeiling?.source === "explicit" ? turnCeiling.effective : undefined);
|
|
293
227
|
},
|
|
294
228
|
reconcilePrompts: (workerId, endedLoopId) => this.#reconcileOrphanedPrompts(workerId, endedLoopId),
|
|
295
|
-
runLoop: async ({ workspaceId, workerId, loopId, maxTurns, prompt, systemPrompt, signal, onSettled
|
|
229
|
+
runLoop: async ({ workspaceId, workerId, loopId, maxTurns, prompt, systemPrompt, signal, onSettled }) => {
|
|
296
230
|
// The drain callback is the final provider/model boundary. Every
|
|
297
231
|
// admission path, including boot recovery, terminates here.
|
|
298
232
|
await this.#assertModelWorker(workspaceId, workerId);
|
|
@@ -315,7 +249,7 @@ export default class Daemon {
|
|
|
315
249
|
{ role: "user", content: prompt },
|
|
316
250
|
],
|
|
317
251
|
signal,
|
|
318
|
-
onSettled
|
|
252
|
+
onSettled
|
|
319
253
|
});
|
|
320
254
|
}
|
|
321
255
|
finally {
|
|
@@ -336,7 +270,7 @@ export default class Daemon {
|
|
|
336
270
|
const entry = await LogEntry.fetchLogEntry(this.#db, logEntryId);
|
|
337
271
|
this.#broadcast({ workspaceId }, "log/entry", { entry });
|
|
338
272
|
},
|
|
339
|
-
emit: (workspaceId, method, params) => this.#broadcast({ workspaceId }, method, params)
|
|
273
|
+
emit: (workspaceId, method, params) => this.#broadcast({ workspaceId }, method, params)
|
|
340
274
|
});
|
|
341
275
|
// Wire proposal-pending events to the loop/proposal WS notification.
|
|
342
276
|
// Sessionid scopes the broadcast to clients on the same workspace.
|
|
@@ -407,7 +341,7 @@ export default class Daemon {
|
|
|
407
341
|
throw new OperationFailureError(Results.failure("daemon:provider", "not-configured", 501, "No provider is configured for this worker.", {}, {
|
|
408
342
|
stage: "provider-selection",
|
|
409
343
|
recovery: "Select a configured model provider.",
|
|
410
|
-
retryable: false
|
|
344
|
+
retryable: false
|
|
411
345
|
}));
|
|
412
346
|
}
|
|
413
347
|
const { providerSpec: selection, reasoningPolicy } = generationPolicy;
|
|
@@ -421,7 +355,7 @@ export default class Daemon {
|
|
|
421
355
|
const maxTurns = ceiling < 0 ? requested : (requested < 0 ? ceiling : Math.min(requested, ceiling));
|
|
422
356
|
const turnCeiling = {
|
|
423
357
|
effective: maxTurns,
|
|
424
|
-
source: requestedMaxTurns === undefined ? "implicit" : "explicit"
|
|
358
|
+
source: requestedMaxTurns === undefined ? "implicit" : "explicit"
|
|
425
359
|
};
|
|
426
360
|
const { action, loopId, turnSeq } = await this.inject({
|
|
427
361
|
workspaceId,
|
|
@@ -435,7 +369,7 @@ export default class Daemon {
|
|
|
435
369
|
providerSpecExplicit: selectorExplicit,
|
|
436
370
|
reasoningPolicy,
|
|
437
371
|
childProviderSpec: childSelection,
|
|
438
|
-
systemPrompt
|
|
372
|
+
systemPrompt
|
|
439
373
|
});
|
|
440
374
|
return { status: 100, action, loopId, ...(turnSeq !== undefined ? { turnSeq } : {}) };
|
|
441
375
|
}
|
|
@@ -474,7 +408,7 @@ export default class Daemon {
|
|
|
474
408
|
supportedReasoningPolicies: cause.supported,
|
|
475
409
|
stage: "provider-selection",
|
|
476
410
|
recovery: "Select one of the provider's supported reasoning policies.",
|
|
477
|
-
retryable: false
|
|
411
|
+
retryable: false
|
|
478
412
|
});
|
|
479
413
|
}
|
|
480
414
|
console.error(`${modelRouteLabel(spec)} could not be instantiated:`, cause);
|
|
@@ -483,7 +417,7 @@ export default class Daemon {
|
|
|
483
417
|
provider: spec.provider,
|
|
484
418
|
model: spec.model,
|
|
485
419
|
stage: "provider-selection",
|
|
486
|
-
retryable: false
|
|
420
|
+
retryable: false
|
|
487
421
|
});
|
|
488
422
|
}
|
|
489
423
|
}
|
|
@@ -511,7 +445,7 @@ export default class Daemon {
|
|
|
511
445
|
id: workerId,
|
|
512
446
|
model_route_id: await routeForSpec(this.#db, spec),
|
|
513
447
|
spawn_model_route_id: worker.spawn_model_route_id,
|
|
514
|
-
reasoning_policy: reasoningPolicy
|
|
448
|
+
reasoning_policy: reasoningPolicy
|
|
515
449
|
});
|
|
516
450
|
return { providerSpec: spec, reasoningPolicy };
|
|
517
451
|
}
|
|
@@ -541,7 +475,7 @@ export default class Daemon {
|
|
|
541
475
|
id: workerId,
|
|
542
476
|
model_route_id: await routeForSpec(this.#db, spec),
|
|
543
477
|
spawn_model_route_id: worker.spawn_model_route_id,
|
|
544
|
-
reasoning_policy: reasoningPolicy
|
|
478
|
+
reasoning_policy: reasoningPolicy
|
|
545
479
|
});
|
|
546
480
|
return { providerSpec: spec, reasoningPolicy };
|
|
547
481
|
}
|
|
@@ -563,7 +497,7 @@ export default class Daemon {
|
|
|
563
497
|
id: workerId,
|
|
564
498
|
model_route_id: worker.model_route_id,
|
|
565
499
|
spawn_model_route_id: spec === null ? null : await routeForSpec(this.#db, spec),
|
|
566
|
-
reasoning_policy: worker.reasoning_policy
|
|
500
|
+
reasoning_policy: worker.reasoning_policy
|
|
567
501
|
});
|
|
568
502
|
return spec;
|
|
569
503
|
}
|
|
@@ -585,7 +519,7 @@ export default class Daemon {
|
|
|
585
519
|
id: workerId,
|
|
586
520
|
model_route_id: worker.model_route_id,
|
|
587
521
|
spawn_model_route_id: await routeForSpec(this.#db, spec),
|
|
588
|
-
reasoning_policy: worker.reasoning_policy
|
|
522
|
+
reasoning_policy: worker.reasoning_policy
|
|
589
523
|
});
|
|
590
524
|
}
|
|
591
525
|
return spec;
|
|
@@ -607,7 +541,7 @@ export default class Daemon {
|
|
|
607
541
|
return {
|
|
608
542
|
providerSpec,
|
|
609
543
|
childProviderSpec: await specForRoute(this.#db, row.spawn_model_route_id),
|
|
610
|
-
reasoningPolicy: row.reasoning_policy
|
|
544
|
+
reasoningPolicy: row.reasoning_policy
|
|
611
545
|
};
|
|
612
546
|
}
|
|
613
547
|
async #providerSpecForLoop(loopId) {
|
|
@@ -632,7 +566,7 @@ export default class Daemon {
|
|
|
632
566
|
requestedModel: `${requested.provider}/${requested.model}`,
|
|
633
567
|
stage: "loop-injection",
|
|
634
568
|
recovery: "Cancel or conclude the loop before selecting another provider.",
|
|
635
|
-
retryable: false
|
|
569
|
+
retryable: false
|
|
636
570
|
});
|
|
637
571
|
}
|
|
638
572
|
}
|
|
@@ -645,7 +579,7 @@ export default class Daemon {
|
|
|
645
579
|
requestedReasoningPolicy: requested,
|
|
646
580
|
stage: "loop-injection",
|
|
647
581
|
recovery: "Cancel or conclude the loop before selecting another reasoning policy.",
|
|
648
|
-
retryable: false
|
|
582
|
+
retryable: false
|
|
649
583
|
});
|
|
650
584
|
}
|
|
651
585
|
}
|
|
@@ -660,7 +594,7 @@ export default class Daemon {
|
|
|
660
594
|
requestedChildModel: requested === null ? null : `${requested.provider}/${requested.model}`,
|
|
661
595
|
stage: "loop-injection",
|
|
662
596
|
recovery: "Cancel or conclude the loop before changing its child provider policy.",
|
|
663
|
-
retryable: false
|
|
597
|
+
retryable: false
|
|
664
598
|
});
|
|
665
599
|
}
|
|
666
600
|
}
|
|
@@ -677,7 +611,7 @@ export default class Daemon {
|
|
|
677
611
|
requestedMaximumTurns: requested,
|
|
678
612
|
stage: "loop-injection",
|
|
679
613
|
recovery: "Cancel or conclude the loop before selecting another turn ceiling.",
|
|
680
|
-
retryable: false
|
|
614
|
+
retryable: false
|
|
681
615
|
});
|
|
682
616
|
}
|
|
683
617
|
}
|
|
@@ -698,7 +632,7 @@ export default class Daemon {
|
|
|
698
632
|
const normalized = ClientInput.normalizeWorkerSettings(settings);
|
|
699
633
|
const current = await WorkerSettingsReader.read(this.#db, workerId);
|
|
700
634
|
const merged = {
|
|
701
|
-
capabilities: normalized.capabilities ?? current.capabilities
|
|
635
|
+
capabilities: normalized.capabilities ?? current.capabilities
|
|
702
636
|
};
|
|
703
637
|
await this.#db.worker_settings_update.run({ id: workerId, settings: JSON.stringify(merged) });
|
|
704
638
|
}
|
|
@@ -733,8 +667,8 @@ export default class Daemon {
|
|
|
733
667
|
const modelSpec = await specForRoute(this.#db, row.model_route_id);
|
|
734
668
|
const spawnModelSpec = await specForRoute(this.#db, row.spawn_model_route_id);
|
|
735
669
|
return {
|
|
736
|
-
model: modelSpec === null ? null : projectModelRoute(modelSpec),
|
|
737
|
-
spawnModel: spawnModelSpec === null ? null : projectModelRoute(spawnModelSpec)
|
|
670
|
+
model: modelSpec === null ? null : projectModelRoute(modelSpec, row.reasoning_policy),
|
|
671
|
+
spawnModel: spawnModelSpec === null ? null : projectModelRoute(spawnModelSpec, row.reasoning_policy)
|
|
738
672
|
};
|
|
739
673
|
}
|
|
740
674
|
// {§worker-model-selection} — persist an explicit model selection onto the worker
|
|
@@ -749,7 +683,7 @@ export default class Daemon {
|
|
|
749
683
|
if (policy === null) {
|
|
750
684
|
throw new OperationFailureError(Results.failure("daemon:provider", "not-configured", 501, "No provider is configured for this worker.", {}, { stage: "provider-selection", recovery: "Select a configured model provider.", retryable: false }));
|
|
751
685
|
}
|
|
752
|
-
return projectModelRoute(policy.providerSpec);
|
|
686
|
+
return projectModelRoute(policy.providerSpec, policy.reasoningPolicy);
|
|
753
687
|
}
|
|
754
688
|
async #reasoningSupportForWorker(workerId, row, providerSpec, policy) {
|
|
755
689
|
const provider = await this.#providerForPolicy(providerSpec, policy);
|
|
@@ -785,7 +719,7 @@ export default class Daemon {
|
|
|
785
719
|
throw new Error(`worker ${workerId}: model route is missing`);
|
|
786
720
|
return {
|
|
787
721
|
policy: row.reasoning_policy,
|
|
788
|
-
supportedPolicies: await this.#reasoningSupportForWorker(workerId, row, spec, row.reasoning_policy)
|
|
722
|
+
supportedPolicies: await this.#reasoningSupportForWorker(workerId, row, spec, row.reasoning_policy)
|
|
789
723
|
};
|
|
790
724
|
}
|
|
791
725
|
// {§worker-reasoning-policy} — mutate between loops, validate against both
|
|
@@ -812,7 +746,7 @@ export default class Daemon {
|
|
|
812
746
|
workerId,
|
|
813
747
|
stage: "provider-selection",
|
|
814
748
|
recovery: "Select a model before selecting its reasoning policy.",
|
|
815
|
-
retryable: false
|
|
749
|
+
retryable: false
|
|
816
750
|
});
|
|
817
751
|
}
|
|
818
752
|
const supportedPolicies = await this.#reasoningSupportForWorker(workerId, row, spec, policy);
|
|
@@ -820,7 +754,7 @@ export default class Daemon {
|
|
|
820
754
|
id: workerId,
|
|
821
755
|
model_route_id: row.model_route_id,
|
|
822
756
|
spawn_model_route_id: row.spawn_model_route_id,
|
|
823
|
-
reasoning_policy: policy
|
|
757
|
+
reasoning_policy: policy
|
|
824
758
|
});
|
|
825
759
|
return { policy, supportedPolicies };
|
|
826
760
|
}
|
|
@@ -833,7 +767,10 @@ export default class Daemon {
|
|
|
833
767
|
await this.#assertWorkerSelectable(workerId);
|
|
834
768
|
const selector = ClientInput.assertChildSelector("worker.child.set", args.selector);
|
|
835
769
|
const spec = await this.#resolveWorkerSpawnModel(workerId, selector);
|
|
836
|
-
|
|
770
|
+
if (spec === null)
|
|
771
|
+
return null;
|
|
772
|
+
const row = await this.#db.worker_generation_policy_read.get({ id: workerId });
|
|
773
|
+
return projectModelRoute(spec, row?.reasoning_policy ?? null);
|
|
837
774
|
}
|
|
838
775
|
// {§worker-model-selection} — a selection must not mutate underneath active
|
|
839
776
|
// work: a live or parked loop is a precise 409, never a silent retroactive
|
|
@@ -844,7 +781,7 @@ export default class Daemon {
|
|
|
844
781
|
workerId,
|
|
845
782
|
stage: "model-selection",
|
|
846
783
|
recovery: "Conclude or cancel the active loop before selecting a model.",
|
|
847
|
-
retryable: false
|
|
784
|
+
retryable: false
|
|
848
785
|
});
|
|
849
786
|
}
|
|
850
787
|
}
|
|
@@ -870,7 +807,7 @@ export default class Daemon {
|
|
|
870
807
|
workerId,
|
|
871
808
|
workspaceId,
|
|
872
809
|
actualWorkspaceId: worker.workspace_id,
|
|
873
|
-
retryable: false
|
|
810
|
+
retryable: false
|
|
874
811
|
});
|
|
875
812
|
}
|
|
876
813
|
if (worker.origin !== "model") {
|
|
@@ -878,7 +815,7 @@ export default class Daemon {
|
|
|
878
815
|
workerId,
|
|
879
816
|
actualOrigin: worker.origin,
|
|
880
817
|
recovery: "Select or create a model worker for this loop.",
|
|
881
|
-
retryable: false
|
|
818
|
+
retryable: false
|
|
882
819
|
});
|
|
883
820
|
}
|
|
884
821
|
}
|
|
@@ -965,18 +902,17 @@ export default class Daemon {
|
|
|
965
902
|
const { id: turnId } = await Turn.open(this.#db, {
|
|
966
903
|
loopId,
|
|
967
904
|
producer: "client",
|
|
968
|
-
kind: "operation"
|
|
905
|
+
kind: "operation"
|
|
969
906
|
});
|
|
970
907
|
let turnOpen = true;
|
|
971
908
|
try {
|
|
972
909
|
const entryIds = [];
|
|
973
910
|
const result = await this.#engine.dispatch({
|
|
974
911
|
statement, workspaceId, workerId, functionalityWorkerId, loopId, turnId, sequence: 1,
|
|
975
|
-
origin: "client", onDispatch: (logEntryId) => { entryIds.push(logEntryId); }
|
|
912
|
+
origin: "client", onDispatch: (logEntryId) => { entryIds.push(logEntryId); }
|
|
976
913
|
});
|
|
977
914
|
await Turn.complete(this.#db, turnId, result.status);
|
|
978
915
|
turnOpen = false;
|
|
979
|
-
await this.#branchBatches.sealTurn(turnId);
|
|
980
916
|
for (const logEntryId of entryIds) {
|
|
981
917
|
const entry = await LogEntry.fetchLogEntry(this.#db, logEntryId);
|
|
982
918
|
this.#broadcast({ workspaceId }, "log/entry", { entry });
|
|
@@ -1050,7 +986,7 @@ export default class Daemon {
|
|
|
1050
986
|
workerId,
|
|
1051
987
|
workspaceId,
|
|
1052
988
|
actualWorkspaceId: target.workspace_id,
|
|
1053
|
-
retryable: false
|
|
989
|
+
retryable: false
|
|
1054
990
|
});
|
|
1055
991
|
}
|
|
1056
992
|
const coordinateFields = {
|
|
@@ -1059,7 +995,7 @@ export default class Daemon {
|
|
|
1059
995
|
sinceId: args.sinceId,
|
|
1060
996
|
loopSeq: args.loopSeq,
|
|
1061
997
|
turnSeq: args.turnSeq,
|
|
1062
|
-
sequence: args.sequence
|
|
998
|
+
sequence: args.sequence
|
|
1063
999
|
};
|
|
1064
1000
|
for (const [field, value] of Object.entries(coordinateFields)) {
|
|
1065
1001
|
if (value !== undefined && (!Number.isSafeInteger(value) || value < 0)) {
|
|
@@ -1068,7 +1004,7 @@ export default class Daemon {
|
|
|
1068
1004
|
value,
|
|
1069
1005
|
stage: "log-read",
|
|
1070
1006
|
recovery: "Use a non-negative integer coordinate.",
|
|
1071
|
-
retryable: false
|
|
1007
|
+
retryable: false
|
|
1072
1008
|
});
|
|
1073
1009
|
}
|
|
1074
1010
|
}
|
|
@@ -1078,14 +1014,14 @@ export default class Daemon {
|
|
|
1078
1014
|
value: args.limit,
|
|
1079
1015
|
stage: "log-read",
|
|
1080
1016
|
recovery: "Use a positive integer log limit.",
|
|
1081
|
-
retryable: false
|
|
1017
|
+
retryable: false
|
|
1082
1018
|
});
|
|
1083
1019
|
}
|
|
1084
1020
|
const rows = await this.#db.log_read_recent_ids.all({
|
|
1085
1021
|
worker_id: workerId,
|
|
1086
1022
|
loop_id: args.loopId ?? null, turn_id: args.turnId ?? null, since_id: args.sinceId ?? null,
|
|
1087
1023
|
loop_seq: args.loopSeq ?? null, turn_seq: args.turnSeq ?? null, sequence: args.sequence ?? null,
|
|
1088
|
-
limit: Math.min(args.limit ?? 100, 1000)
|
|
1024
|
+
limit: Math.min(args.limit ?? 100, 1000)
|
|
1089
1025
|
});
|
|
1090
1026
|
const entries = [];
|
|
1091
1027
|
for (const r of rows)
|
|
@@ -1101,9 +1037,9 @@ export default class Daemon {
|
|
|
1101
1037
|
const isActive = active !== null && active.alias === a.alias;
|
|
1102
1038
|
return {
|
|
1103
1039
|
alias: a.alias, provider: a.provider, model: a.model, active: isActive,
|
|
1104
|
-
inputCapacity: isActive && this.#provider !== null ? this.#provider.inputCapacity : null
|
|
1040
|
+
inputCapacity: isActive && this.#provider !== null ? this.#provider.inputCapacity : null
|
|
1105
1041
|
};
|
|
1106
|
-
})
|
|
1042
|
+
})
|
|
1107
1043
|
};
|
|
1108
1044
|
}
|
|
1109
1045
|
// {§model-catalog} The catalog is a bounded, worldless local projection.
|
|
@@ -1123,14 +1059,14 @@ export default class Daemon {
|
|
|
1123
1059
|
return {
|
|
1124
1060
|
kind: "scheme",
|
|
1125
1061
|
scheme,
|
|
1126
|
-
display: glyph === undefined ? {} : { glyph }
|
|
1062
|
+
display: glyph === undefined ? {} : { glyph }
|
|
1127
1063
|
};
|
|
1128
1064
|
});
|
|
1129
1065
|
const mimetypes = (await this.#mimetypes.displayMetadata())
|
|
1130
1066
|
.map(({ mimetype, glyph }) => ({
|
|
1131
1067
|
kind: "mimetype",
|
|
1132
1068
|
mimetype,
|
|
1133
|
-
display: glyph.length === 0 ? {} : { glyph }
|
|
1069
|
+
display: glyph.length === 0 ? {} : { glyph }
|
|
1134
1070
|
}));
|
|
1135
1071
|
return Validator.assertClientDisplayCapabilities([...schemes, ...mimetypes]);
|
|
1136
1072
|
}
|
|
@@ -1149,7 +1085,7 @@ export default class Daemon {
|
|
|
1149
1085
|
// the envelope keys the filter on the property's presence, not its value.
|
|
1150
1086
|
return Envelope.listWorkersForWorkspace(this.#db, ClientInput.assertId("workspace.workers", "workspaceId", workspaceId), {
|
|
1151
1087
|
...(origin === undefined ? {} : { origin }),
|
|
1152
|
-
...(parentWorkerId === undefined ? {} : { parentWorkerId })
|
|
1088
|
+
...(parentWorkerId === undefined ? {} : { parentWorkerId })
|
|
1153
1089
|
});
|
|
1154
1090
|
}
|
|
1155
1091
|
async readWorker(args) {
|
|
@@ -1161,11 +1097,11 @@ export default class Daemon {
|
|
|
1161
1097
|
}
|
|
1162
1098
|
const row = hasId
|
|
1163
1099
|
? await this.#db.envelope_get_worker_by_id.get({
|
|
1164
|
-
id: ClientInput.assertId("worker.read", "id", args.identity.id)
|
|
1100
|
+
id: ClientInput.assertId("worker.read", "id", args.identity.id)
|
|
1165
1101
|
})
|
|
1166
1102
|
: await this.#db.envelope_get_worker_by_name.get({
|
|
1167
1103
|
workspace_id: workspaceId,
|
|
1168
|
-
name: ClientInput.assertOptionalWorkerName("worker.read", "name", args.identity.name)
|
|
1104
|
+
name: ClientInput.assertOptionalWorkerName("worker.read", "name", args.identity.name)
|
|
1169
1105
|
});
|
|
1170
1106
|
if (row === undefined || row.workspace_id !== workspaceId)
|
|
1171
1107
|
return null;
|
|
@@ -1188,7 +1124,7 @@ export default class Daemon {
|
|
|
1188
1124
|
packetCount: row.packetCount,
|
|
1189
1125
|
terminalResult: row.terminalResult === null
|
|
1190
1126
|
? null
|
|
1191
|
-
: Validator.assertOperationResult(JSON.parse(row.terminalResult))
|
|
1127
|
+
: Validator.assertOperationResult(JSON.parse(row.terminalResult))
|
|
1192
1128
|
}));
|
|
1193
1129
|
}
|
|
1194
1130
|
// {§methods-workspace-prompts}: root-conversation loop seeds, newest-first.
|
|
@@ -1245,7 +1181,7 @@ export default class Daemon {
|
|
|
1245
1181
|
field: "target",
|
|
1246
1182
|
stage: "input-validation",
|
|
1247
1183
|
recovery: "Provide an entry URI.",
|
|
1248
|
-
retryable: false
|
|
1184
|
+
retryable: false
|
|
1249
1185
|
});
|
|
1250
1186
|
}
|
|
1251
1187
|
const channel = ClientInput.assertOptionalChannel("entry.read", args.channel);
|
|
@@ -1258,7 +1194,7 @@ export default class Daemon {
|
|
|
1258
1194
|
workerId,
|
|
1259
1195
|
workspaceId,
|
|
1260
1196
|
actualWorkspaceId: worker.workspace_id,
|
|
1261
|
-
retryable: false
|
|
1197
|
+
retryable: false
|
|
1262
1198
|
});
|
|
1263
1199
|
}
|
|
1264
1200
|
const releaseCapabilities = await this.#residency.acquire(workspaceId, workerId);
|
|
@@ -1277,7 +1213,7 @@ export default class Daemon {
|
|
|
1277
1213
|
target: args.target,
|
|
1278
1214
|
stage: "entry-read",
|
|
1279
1215
|
recovery: "Use a scheme://path target.",
|
|
1280
|
-
retryable: false
|
|
1216
|
+
retryable: false
|
|
1281
1217
|
}));
|
|
1282
1218
|
}
|
|
1283
1219
|
if (args.offset !== undefined && channel === undefined) {
|
|
@@ -1285,7 +1221,7 @@ export default class Daemon {
|
|
|
1285
1221
|
offset: args.offset,
|
|
1286
1222
|
stage: "entry-read",
|
|
1287
1223
|
recovery: "Select the channel to read from the offset.",
|
|
1288
|
-
retryable: false
|
|
1224
|
+
retryable: false
|
|
1289
1225
|
}));
|
|
1290
1226
|
}
|
|
1291
1227
|
if (args.offset !== undefined && (!Number.isSafeInteger(args.offset) || args.offset < 0)) {
|
|
@@ -1293,20 +1229,20 @@ export default class Daemon {
|
|
|
1293
1229
|
offset: args.offset,
|
|
1294
1230
|
stage: "entry-read",
|
|
1295
1231
|
recovery: "Use a non-negative integer offset.",
|
|
1296
|
-
retryable: false
|
|
1232
|
+
retryable: false
|
|
1297
1233
|
}));
|
|
1298
1234
|
}
|
|
1299
1235
|
if (parsed.username !== null || parsed.password !== null) {
|
|
1300
1236
|
return entryReadResult(Results.failure("daemon:entry", "userinfo-not-allowed", 400, "Entry target URL userinfo is not allowed.", { entry: null }, {
|
|
1301
1237
|
stage: "entry-read",
|
|
1302
1238
|
recovery: "Remove credentials from the entry URL.",
|
|
1303
|
-
retryable: false
|
|
1239
|
+
retryable: false
|
|
1304
1240
|
}));
|
|
1305
1241
|
}
|
|
1306
1242
|
const location = await this.#engine.resolveEntryAddress({
|
|
1307
1243
|
workspaceId,
|
|
1308
1244
|
workerId,
|
|
1309
|
-
target: parsed
|
|
1245
|
+
target: parsed
|
|
1310
1246
|
});
|
|
1311
1247
|
if (location === null) {
|
|
1312
1248
|
return entryReadResult(Results.failure("daemon:entry", "entry-not-found", 404, "No visible entry exists at the requested target.", { entry: null }, { target: args.target }));
|
|
@@ -1316,7 +1252,7 @@ export default class Daemon {
|
|
|
1316
1252
|
owner_id: location.ownerId,
|
|
1317
1253
|
scheme: location.scheme,
|
|
1318
1254
|
authority: location.authority,
|
|
1319
|
-
pathname: location.pathname
|
|
1255
|
+
pathname: location.pathname
|
|
1320
1256
|
});
|
|
1321
1257
|
if (row === undefined) {
|
|
1322
1258
|
return entryReadResult(Results.failure("daemon:entry", "entry-not-found", 404, `No visible entry exists at ${location.target}.`, { entry: null }, { target: location.target }));
|
|
@@ -1337,7 +1273,7 @@ export default class Daemon {
|
|
|
1337
1273
|
...(availableChannels.length === 0
|
|
1338
1274
|
? {}
|
|
1339
1275
|
: { recovery: `Use one of the available channels: ${availableChannels.map((channel) => `#${channel}`).join(", ")}.` }),
|
|
1340
|
-
retryable: false
|
|
1276
|
+
retryable: false
|
|
1341
1277
|
}));
|
|
1342
1278
|
}
|
|
1343
1279
|
channelRows = [r];
|
|
@@ -1350,7 +1286,7 @@ export default class Daemon {
|
|
|
1350
1286
|
contentLength: c.contentLength,
|
|
1351
1287
|
mimetype: c.mimetype,
|
|
1352
1288
|
weight: c.weight,
|
|
1353
|
-
state: c.state
|
|
1289
|
+
state: c.state
|
|
1354
1290
|
};
|
|
1355
1291
|
}
|
|
1356
1292
|
return entryReadResult({
|
|
@@ -1358,8 +1294,8 @@ export default class Daemon {
|
|
|
1358
1294
|
entry: {
|
|
1359
1295
|
entryId: row.id,
|
|
1360
1296
|
target: location.target,
|
|
1361
|
-
channels
|
|
1362
|
-
}
|
|
1297
|
+
channels
|
|
1298
|
+
}
|
|
1363
1299
|
});
|
|
1364
1300
|
}
|
|
1365
1301
|
finally {
|
|
@@ -1403,7 +1339,7 @@ export default class Daemon {
|
|
|
1403
1339
|
workerId,
|
|
1404
1340
|
workspaceId,
|
|
1405
1341
|
actualWorkspaceId: owner.workspace_id,
|
|
1406
|
-
retryable: false
|
|
1342
|
+
retryable: false
|
|
1407
1343
|
});
|
|
1408
1344
|
}
|
|
1409
1345
|
if (name !== undefined) {
|
|
@@ -1447,9 +1383,9 @@ export default class Daemon {
|
|
|
1447
1383
|
...(runtime.resourcesPath === undefined ? {} : { resourcesPath: runtime.resourcesPath }),
|
|
1448
1384
|
...(runtime.expandTools === undefined ? {} : { expandTools: runtime.expandTools }),
|
|
1449
1385
|
available: availability.available,
|
|
1450
|
-
detail: availability.detail
|
|
1386
|
+
detail: availability.detail
|
|
1451
1387
|
},
|
|
1452
|
-
scheme
|
|
1388
|
+
scheme
|
|
1453
1389
|
};
|
|
1454
1390
|
}
|
|
1455
1391
|
registerModuleAction(registration) {
|
|
@@ -1485,7 +1421,7 @@ export default class Daemon {
|
|
|
1485
1421
|
name,
|
|
1486
1422
|
scope,
|
|
1487
1423
|
inputSchema,
|
|
1488
|
-
outputSchema
|
|
1424
|
+
outputSchema
|
|
1489
1425
|
}))
|
|
1490
1426
|
.toSorted((left, right) => left.name.localeCompare(right.name));
|
|
1491
1427
|
}
|
|
@@ -1566,8 +1502,8 @@ export default class Daemon {
|
|
|
1566
1502
|
invocation: questionRuntimeDecl.invocation,
|
|
1567
1503
|
details: questionRuntimeDecl.details ?? "",
|
|
1568
1504
|
available: true,
|
|
1569
|
-
detail: "in-process"
|
|
1570
|
-
}
|
|
1505
|
+
detail: "in-process"
|
|
1506
|
+
}
|
|
1571
1507
|
}]);
|
|
1572
1508
|
// {§effect-policy-tunable} — invalid operator policy fails boot, not the first EXEC.
|
|
1573
1509
|
EffectPolicy.validateConfiguration();
|
|
@@ -1617,7 +1553,6 @@ export default class Daemon {
|
|
|
1617
1553
|
await this.#db.recovery_error_orphan_subscription_channels.run({});
|
|
1618
1554
|
await this.#db.recovery_fail_orphan_subscriptions.run({});
|
|
1619
1555
|
await this.#db.recovery_resume_unblocked_parks.run({});
|
|
1620
|
-
await this.#branchBatches.recover();
|
|
1621
1556
|
const orphanSources = await this.#db.recovery_orphan_prompt_sources.all({});
|
|
1622
1557
|
const invalidOrphan = orphanSources.find(({ origin }) => origin !== "model");
|
|
1623
1558
|
if (invalidOrphan !== undefined) {
|
|
@@ -1641,7 +1576,7 @@ export default class Daemon {
|
|
|
1641
1576
|
const started = await this.#drains.ensureDrain({
|
|
1642
1577
|
workspaceId: row.workspace_id,
|
|
1643
1578
|
workerId: row.worker_id,
|
|
1644
|
-
systemPrompt
|
|
1579
|
+
systemPrompt
|
|
1645
1580
|
});
|
|
1646
1581
|
started?.drainPromise.catch((err) => {
|
|
1647
1582
|
if (this.#started) {
|
|
@@ -1673,7 +1608,6 @@ export default class Daemon {
|
|
|
1673
1608
|
const derivationAbort = new DOMException("daemon stopping", "AbortError");
|
|
1674
1609
|
this.#engine.cancelAllProposals("daemon_stopping");
|
|
1675
1610
|
this.#engine.cancelDerivations(derivationAbort);
|
|
1676
|
-
this.#branchBatches.beginStop();
|
|
1677
1611
|
this.#drains.beginStop("daemon_stopping");
|
|
1678
1612
|
this.#residency.beginStop();
|
|
1679
1613
|
const stopDeadlineMs = Daemon.#stopDeadlineMs();
|
|
@@ -1714,7 +1648,6 @@ export default class Daemon {
|
|
|
1714
1648
|
// the daemon forever. Past the deadline the waits are abandoned; the
|
|
1715
1649
|
// process may exit with the WAL in place (SQLite recovers) rather than
|
|
1716
1650
|
// leak as a live-but-wedged tree.
|
|
1717
|
-
const branchResult = await settle("branch batches idle", () => this.#branchBatches.idle());
|
|
1718
1651
|
const drainResult = await settle("drains idle", () => this.#drains.idle());
|
|
1719
1652
|
// A boundary publication queued behind the last turn settles before
|
|
1720
1653
|
// modules close and before the DB goes away ({§functionality-publication}).
|
|
@@ -1737,7 +1670,6 @@ export default class Daemon {
|
|
|
1737
1670
|
const closeErrors = [
|
|
1738
1671
|
moduleResult,
|
|
1739
1672
|
functionalityResult,
|
|
1740
|
-
branchResult,
|
|
1741
1673
|
drainResult,
|
|
1742
1674
|
streamingResult,
|
|
1743
1675
|
derivationResult,
|
|
@@ -1800,7 +1732,7 @@ export default class Daemon {
|
|
|
1800
1732
|
conflicts,
|
|
1801
1733
|
stage: "loop-injection",
|
|
1802
1734
|
recovery: "Cancel the active loop before changing policy, or omit policy to keep its current posture.",
|
|
1803
|
-
retryable: false
|
|
1735
|
+
retryable: false
|
|
1804
1736
|
});
|
|
1805
1737
|
}
|
|
1806
1738
|
}
|
|
@@ -1830,7 +1762,7 @@ export default class Daemon {
|
|
|
1830
1762
|
reasoning_policy: first.reasoning_policy,
|
|
1831
1763
|
max_turns: first.max_turns,
|
|
1832
1764
|
open_paths: first.open_paths ?? "[]",
|
|
1833
|
-
orphan_source_loop_id: endedLoopId
|
|
1765
|
+
orphan_source_loop_id: endedLoopId
|
|
1834
1766
|
});
|
|
1835
1767
|
if (recovery === undefined)
|
|
1836
1768
|
throw new Error("reconcileOrphanedPrompts: enqueue returned no row");
|
|
@@ -1841,7 +1773,7 @@ export default class Daemon {
|
|
|
1841
1773
|
source_loop_id: endedLoopId,
|
|
1842
1774
|
source_pattern: `${prefix}%`,
|
|
1843
1775
|
source_prefix_len: prefix.length,
|
|
1844
|
-
target_prefix: promptLoopPrefix(recovery.sequence)
|
|
1776
|
+
target_prefix: promptLoopPrefix(recovery.sequence)
|
|
1845
1777
|
});
|
|
1846
1778
|
if (moved.length !== frames.length) {
|
|
1847
1779
|
throw new Error(`reconcileOrphanedPrompts: expected to re-home ${frames.length} frames, moved ${moved.length}`);
|