@plurnk/plurnk-service 1.14.2 → 1.16.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.
Files changed (308) hide show
  1. package/.env.defaults +2 -2
  2. package/SPEC.md +243 -173
  3. package/digest-sql/curation/curation.sql +1 -1
  4. package/dist/build-info.json +1 -1
  5. package/dist/content/byte-view.d.ts +14 -0
  6. package/dist/content/byte-view.d.ts.map +1 -0
  7. package/dist/content/byte-view.js +33 -0
  8. package/dist/content/byte-view.js.map +1 -0
  9. package/dist/content/edit-receipt.d.ts.map +1 -1
  10. package/dist/content/edit-receipt.js +12 -1
  11. package/dist/content/edit-receipt.js.map +1 -1
  12. package/dist/content/line-marker.d.ts +2 -1
  13. package/dist/content/line-marker.d.ts.map +1 -1
  14. package/dist/content/line-marker.js +1 -0
  15. package/dist/content/line-marker.js.map +1 -1
  16. package/dist/content/matcher.d.ts +1 -0
  17. package/dist/content/matcher.d.ts.map +1 -1
  18. package/dist/content/matcher.js +1 -0
  19. package/dist/content/matcher.js.map +1 -1
  20. package/dist/content/read-projector.d.ts +4 -1
  21. package/dist/content/read-projector.d.ts.map +1 -1
  22. package/dist/content/read-projector.js +80 -3
  23. package/dist/content/read-projector.js.map +1 -1
  24. package/dist/core/AdmittedTurnExecutor.d.ts +43 -0
  25. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -0
  26. package/dist/core/AdmittedTurnExecutor.js +245 -0
  27. package/dist/core/AdmittedTurnExecutor.js.map +1 -0
  28. package/dist/core/BareBatchRunner.d.ts +26 -0
  29. package/dist/core/BareBatchRunner.d.ts.map +1 -0
  30. package/dist/core/BareBatchRunner.js +104 -0
  31. package/dist/core/BareBatchRunner.js.map +1 -0
  32. package/dist/core/BudgetReadout.d.ts +1 -1
  33. package/dist/core/BudgetReadout.d.ts.map +1 -1
  34. package/dist/core/BudgetReadout.js +42 -47
  35. package/dist/core/BudgetReadout.js.map +1 -1
  36. package/dist/core/CapabilityResolver.d.ts +2 -1
  37. package/dist/core/CapabilityResolver.d.ts.map +1 -1
  38. package/dist/core/CapabilityResolver.js +8 -9
  39. package/dist/core/CapabilityResolver.js.map +1 -1
  40. package/dist/core/ChannelWrite.d.ts +1 -1
  41. package/dist/core/ChannelWrite.d.ts.map +1 -1
  42. package/dist/core/DataStatementRunner.d.ts +35 -0
  43. package/dist/core/DataStatementRunner.d.ts.map +1 -0
  44. package/dist/core/DataStatementRunner.js +252 -0
  45. package/dist/core/DataStatementRunner.js.map +1 -0
  46. package/dist/core/Dispatcher.d.ts +8 -3
  47. package/dist/core/Dispatcher.d.ts.map +1 -1
  48. package/dist/core/Dispatcher.js +88 -738
  49. package/dist/core/Dispatcher.js.map +1 -1
  50. package/dist/core/EditMutations.d.ts +39 -0
  51. package/dist/core/EditMutations.d.ts.map +1 -0
  52. package/dist/core/EditMutations.js +418 -0
  53. package/dist/core/EditMutations.js.map +1 -0
  54. package/dist/core/Engine.d.ts +2 -23
  55. package/dist/core/Engine.d.ts.map +1 -1
  56. package/dist/core/Engine.js +18 -240
  57. package/dist/core/Engine.js.map +1 -1
  58. package/dist/core/Engine.sql +24 -23
  59. package/dist/core/KillHandler.d.ts +32 -0
  60. package/dist/core/KillHandler.d.ts.map +1 -0
  61. package/dist/core/KillHandler.js +179 -0
  62. package/dist/core/KillHandler.js.map +1 -0
  63. package/dist/core/LogVisibility.d.ts +1 -1
  64. package/dist/core/LogVisibility.d.ts.map +1 -1
  65. package/dist/core/LogVisibility.js +3 -4
  66. package/dist/core/LogVisibility.js.map +1 -1
  67. package/dist/core/LogWriter.d.ts +42 -0
  68. package/dist/core/LogWriter.d.ts.map +1 -0
  69. package/dist/core/LogWriter.js +136 -0
  70. package/dist/core/LogWriter.js.map +1 -0
  71. package/dist/core/LoopDriver.d.ts +46 -0
  72. package/dist/core/LoopDriver.d.ts.map +1 -0
  73. package/dist/core/LoopDriver.js +263 -0
  74. package/dist/core/LoopDriver.js.map +1 -0
  75. package/dist/core/LoopLifecycle.d.ts +2 -1
  76. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  77. package/dist/core/MembershipMaterialization.d.ts +7 -0
  78. package/dist/core/MembershipMaterialization.d.ts.map +1 -0
  79. package/dist/core/MembershipMaterialization.js +283 -0
  80. package/dist/core/MembershipMaterialization.js.map +1 -0
  81. package/dist/core/MutationEffects.d.ts +29 -0
  82. package/dist/core/MutationEffects.d.ts.map +1 -0
  83. package/dist/core/MutationEffects.js +318 -0
  84. package/dist/core/MutationEffects.js.map +1 -0
  85. package/dist/core/OverflowTurn.d.ts +4 -4
  86. package/dist/core/OverflowTurn.d.ts.map +1 -1
  87. package/dist/core/OverflowTurn.js +6 -7
  88. package/dist/core/OverflowTurn.js.map +1 -1
  89. package/dist/core/PacketBuilder.d.ts.map +1 -1
  90. package/dist/core/PacketBuilder.js +31 -9
  91. package/dist/core/PacketBuilder.js.map +1 -1
  92. package/dist/core/ResourceMutations.d.ts +12 -36
  93. package/dist/core/ResourceMutations.d.ts.map +1 -1
  94. package/dist/core/ResourceMutations.js +27 -1351
  95. package/dist/core/ResourceMutations.js.map +1 -1
  96. package/dist/core/ResourceSelector.d.ts +21 -0
  97. package/dist/core/ResourceSelector.d.ts.map +1 -0
  98. package/dist/core/ResourceSelector.js +233 -0
  99. package/dist/core/ResourceSelector.js.map +1 -0
  100. package/dist/core/ResourceTransfers.d.ts +55 -0
  101. package/dist/core/ResourceTransfers.d.ts.map +1 -0
  102. package/dist/core/ResourceTransfers.js +525 -0
  103. package/dist/core/ResourceTransfers.js.map +1 -0
  104. package/dist/core/SchemeRegistry.js +2 -2
  105. package/dist/core/SchemeRegistry.js.map +1 -1
  106. package/dist/core/SendBroadcastHandler.d.ts +40 -0
  107. package/dist/core/SendBroadcastHandler.d.ts.map +1 -0
  108. package/dist/core/SendBroadcastHandler.js +159 -0
  109. package/dist/core/SendBroadcastHandler.js.map +1 -0
  110. package/dist/core/StoredPacket.d.ts +11 -0
  111. package/dist/core/StoredPacket.d.ts.map +1 -1
  112. package/dist/core/StoredPacket.js +22 -1
  113. package/dist/core/StoredPacket.js.map +1 -1
  114. package/dist/core/StrikeRail.d.ts.map +1 -1
  115. package/dist/core/StrikeRail.js +19 -9
  116. package/dist/core/StrikeRail.js.map +1 -1
  117. package/dist/core/TokenCalibration.d.ts +16 -0
  118. package/dist/core/TokenCalibration.d.ts.map +1 -0
  119. package/dist/core/TokenCalibration.js +35 -0
  120. package/dist/core/TokenCalibration.js.map +1 -0
  121. package/dist/core/ToolResources.d.ts.map +1 -1
  122. package/dist/core/ToolResources.js +15 -12
  123. package/dist/core/ToolResources.js.map +1 -1
  124. package/dist/core/TurnMaterialization.d.ts +37 -0
  125. package/dist/core/TurnMaterialization.d.ts.map +1 -0
  126. package/dist/core/TurnMaterialization.js +296 -0
  127. package/dist/core/TurnMaterialization.js.map +1 -0
  128. package/dist/core/TurnOps.d.ts.map +1 -1
  129. package/dist/core/TurnOps.js +6 -8
  130. package/dist/core/TurnOps.js.map +1 -1
  131. package/dist/core/TurnRunner.d.ts +15 -27
  132. package/dist/core/TurnRunner.d.ts.map +1 -1
  133. package/dist/core/TurnRunner.js +76 -670
  134. package/dist/core/TurnRunner.js.map +1 -1
  135. package/dist/core/WorkerControlHandler.d.ts +15 -0
  136. package/dist/core/WorkerControlHandler.d.ts.map +1 -0
  137. package/dist/core/WorkerControlHandler.js +89 -0
  138. package/dist/core/WorkerControlHandler.js.map +1 -0
  139. package/dist/core/attachments.d.ts +14 -0
  140. package/dist/core/attachments.d.ts.map +1 -0
  141. package/dist/core/attachments.js +18 -0
  142. package/dist/core/attachments.js.map +1 -0
  143. package/dist/core/fork.d.ts.map +1 -1
  144. package/dist/core/fork.js +0 -4
  145. package/dist/core/fork.js.map +1 -1
  146. package/dist/core/fork.sql +5 -16
  147. package/dist/core/git-membership.d.ts +15 -0
  148. package/dist/core/git-membership.d.ts.map +1 -1
  149. package/dist/core/git-membership.js +4 -273
  150. package/dist/core/git-membership.js.map +1 -1
  151. package/dist/core/git-state.d.ts +2 -1
  152. package/dist/core/git-state.d.ts.map +1 -1
  153. package/dist/core/mutation-types.d.ts +102 -0
  154. package/dist/core/mutation-types.d.ts.map +1 -0
  155. package/dist/core/mutation-types.js +2 -0
  156. package/dist/core/mutation-types.js.map +1 -0
  157. package/dist/core/operation-target-groups.js +1 -1
  158. package/dist/core/operation-target-groups.js.map +1 -1
  159. package/dist/core/packet-wire.d.ts +7 -6
  160. package/dist/core/packet-wire.d.ts.map +1 -1
  161. package/dist/core/packet-wire.js +96 -68
  162. package/dist/core/packet-wire.js.map +1 -1
  163. package/dist/core/plurnk-uri.d.ts +0 -1
  164. package/dist/core/plurnk-uri.d.ts.map +1 -1
  165. package/dist/core/plurnk-uri.js +1 -1
  166. package/dist/core/plurnk-uri.js.map +1 -1
  167. package/dist/core/statement-primary.d.ts +4 -0
  168. package/dist/core/statement-primary.d.ts.map +1 -0
  169. package/dist/core/statement-primary.js +3 -0
  170. package/dist/core/statement-primary.js.map +1 -0
  171. package/dist/core/teaching-corpus.d.ts +0 -1
  172. package/dist/core/teaching-corpus.d.ts.map +1 -1
  173. package/dist/core/teaching-corpus.js +0 -9
  174. package/dist/core/teaching-corpus.js.map +1 -1
  175. package/dist/core/turn-scheduler.js +3 -3
  176. package/dist/core/turn-scheduler.js.map +1 -1
  177. package/dist/core/turn-signals.d.ts +15 -0
  178. package/dist/core/turn-signals.d.ts.map +1 -0
  179. package/dist/core/turn-signals.js +19 -0
  180. package/dist/core/turn-signals.js.map +1 -0
  181. package/dist/core/worker-settings.d.ts +0 -1
  182. package/dist/core/worker-settings.d.ts.map +1 -1
  183. package/dist/core/worker-settings.js +1 -1
  184. package/dist/core/worker-settings.js.map +1 -1
  185. package/dist/digest/Digest.d.ts +3 -16
  186. package/dist/digest/Digest.d.ts.map +1 -1
  187. package/dist/digest/Digest.js +10 -958
  188. package/dist/digest/Digest.js.map +1 -1
  189. package/dist/digest/DigestRender.d.ts +12 -0
  190. package/dist/digest/DigestRender.d.ts.map +1 -0
  191. package/dist/digest/DigestRender.js +641 -0
  192. package/dist/digest/DigestRender.js.map +1 -0
  193. package/dist/digest/DigestRequiem.d.ts +13 -0
  194. package/dist/digest/DigestRequiem.d.ts.map +1 -0
  195. package/dist/digest/DigestRequiem.js +332 -0
  196. package/dist/digest/DigestRequiem.js.map +1 -0
  197. package/dist/digest/digest-rows.d.ts +303 -0
  198. package/dist/digest/digest-rows.d.ts.map +1 -0
  199. package/dist/digest/digest-rows.js +2 -0
  200. package/dist/digest/digest-rows.js.map +1 -0
  201. package/dist/digest/digest.sql +1 -7
  202. package/dist/observe/api.d.ts +0 -2
  203. package/dist/observe/api.d.ts.map +1 -1
  204. package/dist/observe/api.js +2 -2
  205. package/dist/observe/api.js.map +1 -1
  206. package/dist/observe/metrics.d.ts +0 -1
  207. package/dist/observe/metrics.d.ts.map +1 -1
  208. package/dist/observe/metrics.js +0 -1
  209. package/dist/observe/metrics.js.map +1 -1
  210. package/dist/schemes/Exec.d.ts +4 -1
  211. package/dist/schemes/Exec.d.ts.map +1 -1
  212. package/dist/schemes/Exec.js +89 -48
  213. package/dist/schemes/Exec.js.map +1 -1
  214. package/dist/schemes/ExecOutputScheme.d.ts +2 -1
  215. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  216. package/dist/schemes/ExecOutputScheme.js +3 -3
  217. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  218. package/dist/schemes/File.d.ts +4 -1
  219. package/dist/schemes/File.d.ts.map +1 -1
  220. package/dist/schemes/File.js +100 -13
  221. package/dist/schemes/File.js.map +1 -1
  222. package/dist/schemes/Log.d.ts +4 -5
  223. package/dist/schemes/Log.d.ts.map +1 -1
  224. package/dist/schemes/Log.js +26 -118
  225. package/dist/schemes/Log.js.map +1 -1
  226. package/dist/schemes/Log.sql +1 -66
  227. package/dist/schemes/Prompt.js +1 -1
  228. package/dist/schemes/Prompt.js.map +1 -1
  229. package/dist/schemes/Worker.d.ts.map +1 -1
  230. package/dist/schemes/Worker.js +1 -13
  231. package/dist/schemes/Worker.js.map +1 -1
  232. package/dist/schemes/_entry-crud.d.ts +3 -1
  233. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  234. package/dist/schemes/_entry-crud.js +18 -3
  235. package/dist/schemes/_entry-crud.js.map +1 -1
  236. package/dist/schemes/_entry-find.d.ts +4 -2
  237. package/dist/schemes/_entry-find.d.ts.map +1 -1
  238. package/dist/schemes/_entry-find.js +79 -10
  239. package/dist/schemes/_entry-find.js.map +1 -1
  240. package/dist/schemes/_entry-manifest.d.ts +1 -2
  241. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  242. package/dist/schemes/_entry-ops.d.ts +2 -1
  243. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  244. package/dist/schemes/_entry-ops.js +20 -2
  245. package/dist/schemes/_entry-ops.js.map +1 -1
  246. package/dist/schemes/_entry-semantic.d.ts +1 -0
  247. package/dist/schemes/_entry-semantic.d.ts.map +1 -1
  248. package/dist/schemes/_entry-semantic.js +3 -0
  249. package/dist/schemes/_entry-semantic.js.map +1 -1
  250. package/dist/schemes/_entry-semantic.sql +2 -2
  251. package/dist/schemes/_entry-send.d.ts +0 -1
  252. package/dist/schemes/_entry-send.d.ts.map +1 -1
  253. package/dist/schemes/_entry-send.js +5 -80
  254. package/dist/schemes/_entry-send.js.map +1 -1
  255. package/dist/schemes/exec-runtime.d.ts +7 -0
  256. package/dist/schemes/exec-runtime.d.ts.map +1 -0
  257. package/dist/schemes/exec-runtime.js +2 -0
  258. package/dist/schemes/exec-runtime.js.map +1 -0
  259. package/dist/server/ClientReads.d.ts +34 -0
  260. package/dist/server/ClientReads.d.ts.map +1 -0
  261. package/dist/server/ClientReads.js +210 -0
  262. package/dist/server/ClientReads.js.map +1 -0
  263. package/dist/server/Daemon.d.ts +12 -22
  264. package/dist/server/Daemon.d.ts.map +1 -1
  265. package/dist/server/Daemon.js +31 -362
  266. package/dist/server/Daemon.js.map +1 -1
  267. package/dist/server/DaemonModule.d.ts +6 -5
  268. package/dist/server/DaemonModule.d.ts.map +1 -1
  269. package/dist/server/DrainSupervisor.d.ts +3 -2
  270. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  271. package/dist/server/DrainSupervisor.js +7 -3
  272. package/dist/server/DrainSupervisor.js.map +1 -1
  273. package/dist/server/Functionality.d.ts +0 -12
  274. package/dist/server/Functionality.d.ts.map +1 -1
  275. package/dist/server/Functionality.js.map +1 -1
  276. package/dist/server/FunctionalityManager.d.ts +0 -1
  277. package/dist/server/FunctionalityManager.d.ts.map +1 -1
  278. package/dist/server/FunctionalityManager.js +3 -3
  279. package/dist/server/FunctionalityManager.js.map +1 -1
  280. package/dist/server/MembersFunctionality.d.ts +2 -13
  281. package/dist/server/MembersFunctionality.d.ts.map +1 -1
  282. package/dist/server/MembersFunctionality.js +4 -4
  283. package/dist/server/MembersFunctionality.js.map +1 -1
  284. package/dist/server/SkillsFunctionality.d.ts +1 -7
  285. package/dist/server/SkillsFunctionality.d.ts.map +1 -1
  286. package/dist/server/SkillsFunctionality.js +3 -3
  287. package/dist/server/SkillsFunctionality.js.map +1 -1
  288. package/dist/server/WorkerModelResolver.d.ts +17 -0
  289. package/dist/server/WorkerModelResolver.d.ts.map +1 -0
  290. package/dist/server/WorkerModelResolver.js +166 -0
  291. package/dist/server/WorkerModelResolver.js.map +1 -0
  292. package/dist/server/daemon-results.d.ts +5 -0
  293. package/dist/server/daemon-results.d.ts.map +1 -0
  294. package/dist/server/daemon-results.js +7 -0
  295. package/dist/server/daemon-results.js.map +1 -0
  296. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  297. package/dist/server/dispatch-as-plurnk.js +4 -6
  298. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  299. package/dist/server/logEntry.d.ts +0 -1
  300. package/dist/server/logEntry.d.ts.map +1 -1
  301. package/dist/server/logEntry.js +1 -13
  302. package/dist/server/logEntry.js.map +1 -1
  303. package/dist/server/logEntry.sql +1 -5
  304. package/dist/server/loopDocs.d.ts.map +1 -1
  305. package/dist/server/loopDocs.js +11 -2
  306. package/dist/server/loopDocs.js.map +1 -1
  307. package/migrations/001_schema.sql +30 -347
  308. package/package.json +30 -30
@@ -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 } from "@plurnk/plurnk-contracts";
18
+ import { 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";
@@ -27,9 +27,8 @@ import WorkerControlAddress from "../core/WorkerControlAddress.js";
27
27
  import LoopLifecycle from "../core/LoopLifecycle.js";
28
28
  import { promptLoopPrefix } from "../core/plurnk-uri.js";
29
29
  import { contentWeight } from "../core/content-weight.js";
30
- import { parseAliasesFromEnv, resolveActiveRoute, UnsupportedReasoningPolicyError } from "@plurnk/plurnk-providers";
30
+ import { parseAliasesFromEnv, resolveActiveRoute } from "@plurnk/plurnk-providers";
31
31
  import ProviderInstantiate from "../core/ProviderInstantiate.js";
32
- import { resolveLoopRoute } from "./loop-model.js";
33
32
  import LoopPolicyReader from "../core/LoopPolicyReader.js";
34
33
  import CapabilityPolicies from "../core/CapabilityPolicies.js";
35
34
  import Results, { OperationFailureError } from "../core/results.js";
@@ -38,6 +37,9 @@ import WorkerResidency from "./WorkerResidency.js";
38
37
  import Functionality from "./Functionality.js";
39
38
  import { observed, observedSync } from "../observe/spans.js";
40
39
  import { listModelCatalog } from "./model-catalog.js";
40
+ import { daemonFailure, modelRouteLabel } from "./daemon-results.js";
41
+ import WorkerModelResolver from "./WorkerModelResolver.js";
42
+ import ClientReads from "./ClientReads.js";
41
43
  const clientActionFailure = (error) => {
42
44
  if (error instanceof OperationFailureError)
43
45
  return error.result;
@@ -47,11 +49,6 @@ const clientActionFailure = (error) => {
47
49
  retryable: false
48
50
  });
49
51
  };
50
- const daemonFailure = (owner, code, status, detail, extensions = {}) => new OperationFailureError(Results.failure(owner, code, status, detail, {}, extensions));
51
- const entryReadResult = (result) => Validator.assertEntryReadResult(result);
52
- const modelRouteLabel = (route) => route.alias === undefined
53
- ? `model route '${route.provider}/${route.model}'`
54
- : `provider alias '${route.alias}' (${route.provider}/${route.model})`;
55
52
  export default class Daemon {
56
53
  #db;
57
54
  #engine;
@@ -76,6 +73,8 @@ export default class Daemon {
76
73
  // module (plurnk-agui) subscribes and fans out to its OWN clients; core emits, never owns
77
74
  // client transport or connection state.
78
75
  #eventSubscribers = new Set();
76
+ #workerModels;
77
+ #reads;
79
78
  constructor({ db, schemes, mimetypes, provider, nodeModulesPath, skills }) {
80
79
  this.#db = db;
81
80
  this.#lifecycle = new LoopLifecycle(db);
@@ -156,13 +155,13 @@ export default class Daemon {
156
155
  // existing worker. Its own durable generation policy is the
157
156
  // receiver's identity; the daemon default and sender do not
158
157
  // overwrite it merely because a new loop must be minted.
159
- const targetPolicy = await this.#resolveWorkerModel(workerId, undefined);
158
+ const targetPolicy = await this.#workerModels.resolveWorkerModel(workerId, undefined);
160
159
  if (targetPolicy === null) {
161
160
  throw new Error(`injectWorker: worker ${workerId} has no resolvable model route`);
162
161
  }
163
162
  providerSpec = targetPolicy.providerSpec;
164
163
  reasoningPolicy = targetPolicy.reasoningPolicy;
165
- childProviderSpec = await this.#resolveWorkerSpawnModel(workerId, undefined);
164
+ childProviderSpec = await this.#workerModels.resolveWorkerSpawnModel(workerId, undefined);
166
165
  }
167
166
  else {
168
167
  const parentPolicy = await this.#providerPolicyForLoop(parentLoopId);
@@ -265,6 +264,8 @@ export default class Daemon {
265
264
  },
266
265
  cancelSubscription: (subscriptionId) => this.#engine.cancelSubscription(subscriptionId),
267
266
  hasActiveStreams: (workerId) => this.#workerHasActiveStreams(workerId),
267
+ // {§exec-timeout} — a `<-1>` spawn is nobody's obligation.
268
+ isDetachedSubscription: (subscriptionId) => this.#schemes.get("exec")?.isDetachedSpawn?.(subscriptionId) === true,
268
269
  readSystemPrompt: () => readFile(Paths.instructionsSystem, "utf8"),
269
270
  emitLogEntry: async (workspaceId, logEntryId) => {
270
271
  const entry = await LogEntry.fetchLogEntry(this.#db, logEntryId);
@@ -282,6 +283,8 @@ export default class Daemon {
282
283
  const { workspaceId, ...interaction } = event;
283
284
  this.#broadcast({ workspaceId }, "loop/interaction", interaction);
284
285
  });
286
+ this.#workerModels = new WorkerModelResolver({ db: this.#db, provider: this.#provider });
287
+ this.#reads = new ClientReads({ db: this.#db, engine: this.#engine, workspaceGate: this.#workspaceGate, residency: this.#residency });
285
288
  }
286
289
  // {§methods-event-subscribe}. A transport module subscribes to the daemon's in-process
287
290
  // event source: it receives every workspace-scoped engine event as `(workspaceId, method, params)`
@@ -336,7 +339,7 @@ export default class Daemon {
336
339
  // (seeded once from the daemon default). The loop then snapshots the resolved route.
337
340
  // A continuation's omitted selector must still keep the loop's durable provider.
338
341
  const selectorExplicit = selector !== undefined;
339
- const generationPolicy = await this.#resolveWorkerModel(workerId, selector);
342
+ const generationPolicy = await this.#workerModels.resolveWorkerModel(workerId, selector);
340
343
  if (generationPolicy === null) {
341
344
  throw new OperationFailureError(Results.failure("daemon:provider", "not-configured", 501, "No provider is configured for this worker.", {}, {
342
345
  stage: "provider-selection",
@@ -346,7 +349,7 @@ export default class Daemon {
346
349
  }
347
350
  const { providerSpec: selection, reasoningPolicy } = generationPolicy;
348
351
  // {§methods-loop-run-child-provider} — the worker's persistent spawn override.
349
- const childSelection = await this.#resolveWorkerSpawnModel(workerId, childSelector);
352
+ const childSelection = await this.#workerModels.resolveWorkerSpawnModel(workerId, childSelector);
350
353
  const systemPrompt = await readFile(Paths.instructionsSystem, "utf8");
351
354
  // {§operator-config-max-turns-ceiling} — the operator ceiling clamps a per-call maxTurns; a
352
355
  // seam caller must not bypass operator policy (inject only DEFAULTS from env, never clamps).
@@ -373,157 +376,6 @@ export default class Daemon {
373
376
  });
374
377
  return { status: 100, action, loopId, ...(turnSeq !== undefined ? { turnSeq } : {}) };
375
378
  }
376
- // {§methods-loop-run-model} — resolve one alias-or-route selector to a cached
377
- // Provider; absent uses the boot default. An unknown alias or malformed exact
378
- // route throws legibly rather than silently running the wrong model.
379
- async #resolveLoopProvider(selector, reasoningPolicy) {
380
- const requested = resolveLoopRoute(selector, parseAliasesFromEnv());
381
- if (requested === null && this.#provider === null)
382
- return null;
383
- const spec = requested ?? resolveActiveRoute();
384
- if (spec === null) {
385
- throw daemonFailure("daemon:provider", "active-model-unresolved", 500, "The active provider has no resolvable model route.", { stage: "provider-selection", retryable: false });
386
- }
387
- await this.#providerForPolicy(spec, reasoningPolicy);
388
- return spec;
389
- }
390
- // Resolve eagerly so runLoop fails before enqueue when the selected route
391
- // and durable reasoning policy cannot compose. The drain later retrieves
392
- // this cached handle from the loop's immutable snapshot.
393
- async #providerForPolicy(spec, reasoningPolicy) {
394
- try {
395
- const provider = await ProviderInstantiate.instantiateProvider(spec, process.env, reasoningPolicy);
396
- ProviderInstantiate.validateGrammarConfiguration(provider, process.env, reasoningPolicy);
397
- return provider;
398
- }
399
- catch (cause) {
400
- if (cause instanceof OperationFailureError)
401
- throw cause;
402
- if (cause instanceof UnsupportedReasoningPolicyError) {
403
- throw daemonFailure("daemon:provider", "reasoning-policy-unsupported", 409, `${modelRouteLabel(spec)} does not support reasoning policy '${cause.policy}'.`, {
404
- ...(spec.alias === undefined ? {} : { alias: spec.alias }),
405
- provider: spec.provider,
406
- model: spec.model,
407
- reasoningPolicy: cause.policy,
408
- supportedReasoningPolicies: cause.supported,
409
- stage: "provider-selection",
410
- recovery: "Select one of the provider's supported reasoning policies.",
411
- retryable: false
412
- });
413
- }
414
- console.error(`${modelRouteLabel(spec)} could not be instantiated:`, cause);
415
- throw daemonFailure("daemon:provider", "provider-unavailable", 503, `${modelRouteLabel(spec)} is unavailable.`, {
416
- ...(spec.alias === undefined ? {} : { alias: spec.alias }),
417
- provider: spec.provider,
418
- model: spec.model,
419
- stage: "provider-selection",
420
- retryable: false
421
- });
422
- }
423
- }
424
- // {§worker-model-selection} — a model worker owns one durable model. An explicit
425
- // selector persists onto the worker; an omitted selector resolves the worker's
426
- // durable model, seeded once from the daemon default. A deliberately modelless
427
- // daemon leaves the worker unset until an explicit selection arrives.
428
- async #resolveWorkerModel(workerId, selector) {
429
- const worker = await this.#db.worker_generation_policy_read.get({ id: workerId });
430
- if (worker === undefined)
431
- throw new Error(`worker ${workerId}: model route row missing`);
432
- if (selector !== undefined) {
433
- const spec = await this.#resolveLoopProvider(selector, worker.reasoning_policy ?? undefined);
434
- if (spec === null)
435
- return null;
436
- const reasoningPolicy = worker.reasoning_policy
437
- ?? ProviderInstantiate.configuredReasoningPolicy(spec);
438
- if (worker.spawn_model_route_id !== null) {
439
- const spawnSpec = await specForRoute(this.#db, worker.spawn_model_route_id);
440
- if (spawnSpec === null)
441
- throw new Error(`worker ${workerId}: spawn model route is missing`);
442
- await this.#providerForPolicy(spawnSpec, reasoningPolicy);
443
- }
444
- await this.#db.worker_generation_policy_update.run({
445
- id: workerId,
446
- model_route_id: await routeForSpec(this.#db, spec),
447
- spawn_model_route_id: worker.spawn_model_route_id,
448
- reasoning_policy: reasoningPolicy
449
- });
450
- return { providerSpec: spec, reasoningPolicy };
451
- }
452
- if (worker.model_route_id !== null) {
453
- if (worker.reasoning_policy === null) {
454
- throw new Error(`worker ${workerId}: durable model has no reasoning policy`);
455
- }
456
- const spec = await specForRoute(this.#db, worker.model_route_id);
457
- if (spec === null)
458
- throw new Error(`worker ${workerId}: model route is missing`);
459
- await this.#providerForPolicy(spec, worker.reasoning_policy);
460
- return { providerSpec: spec, reasoningPolicy: worker.reasoning_policy };
461
- }
462
- if (this.#provider === null)
463
- return null;
464
- const spec = resolveActiveRoute();
465
- if (spec !== null) {
466
- const reasoningPolicy = ProviderInstantiate.configuredReasoningPolicy(spec);
467
- await this.#providerForPolicy(spec, reasoningPolicy);
468
- if (worker.spawn_model_route_id !== null) {
469
- const spawnSpec = await specForRoute(this.#db, worker.spawn_model_route_id);
470
- if (spawnSpec === null)
471
- throw new Error(`worker ${workerId}: spawn model route is missing`);
472
- await this.#providerForPolicy(spawnSpec, reasoningPolicy);
473
- }
474
- await this.#db.worker_generation_policy_update.run({
475
- id: workerId,
476
- model_route_id: await routeForSpec(this.#db, spec),
477
- spawn_model_route_id: worker.spawn_model_route_id,
478
- reasoning_policy: reasoningPolicy
479
- });
480
- return { providerSpec: spec, reasoningPolicy };
481
- }
482
- return null;
483
- }
484
- // {§worker-model-selection} — the persistent spawn override. An explicit child
485
- // selector persists onto the worker (null clears it back to inherit); an omitted
486
- // selector resolves the persisted override, seeded once from the operator's
487
- // PLURNK_MODEL_CHILD default.
488
- async #resolveWorkerSpawnModel(workerId, childSelector) {
489
- const worker = await this.#db.worker_generation_policy_read.get({ id: workerId });
490
- if (worker === undefined)
491
- throw new Error(`worker ${workerId}: model route row missing`);
492
- if (childSelector !== undefined) {
493
- const spec = childSelector === null
494
- ? null
495
- : await this.#resolveLoopProvider(childSelector, worker.reasoning_policy ?? undefined);
496
- await this.#db.worker_generation_policy_update.run({
497
- id: workerId,
498
- model_route_id: worker.model_route_id,
499
- spawn_model_route_id: spec === null ? null : await routeForSpec(this.#db, spec),
500
- reasoning_policy: worker.reasoning_policy
501
- });
502
- return spec;
503
- }
504
- if (worker.spawn_model_route_id !== null) {
505
- const spec = await specForRoute(this.#db, worker.spawn_model_route_id);
506
- if (spec === null)
507
- throw new Error(`worker ${workerId}: spawn model route is missing`);
508
- if (worker.reasoning_policy !== null) {
509
- await this.#providerForPolicy(spec, worker.reasoning_policy);
510
- }
511
- return spec;
512
- }
513
- const configured = process.env.PLURNK_MODEL_CHILD;
514
- if (configured === undefined || configured.length === 0)
515
- return null;
516
- const spec = await this.#resolveLoopProvider(configured, worker.reasoning_policy ?? undefined);
517
- if (spec !== null) {
518
- await this.#db.worker_generation_policy_update.run({
519
- id: workerId,
520
- model_route_id: worker.model_route_id,
521
- spawn_model_route_id: await routeForSpec(this.#db, spec),
522
- reasoning_policy: worker.reasoning_policy
523
- });
524
- }
525
- return spec;
526
- }
527
379
  // {§worker-model-selection} — the loop's durable snapshot is the immutable route ids,
528
380
  // resolved through model_routes at the claim boundary; never re-resolved through the
529
381
  // alias cascade (a changed alias declaration must not rewrite history).
@@ -549,10 +401,10 @@ export default class Daemon {
549
401
  }
550
402
  async #providersForLoop(loopId) {
551
403
  const policy = await this.#providerPolicyForLoop(loopId);
552
- const provider = await this.#providerForPolicy(policy.providerSpec, policy.reasoningPolicy);
404
+ const provider = await this.#workerModels.providerForPolicy(policy.providerSpec, policy.reasoningPolicy);
553
405
  const childProvider = policy.childProviderSpec === null
554
406
  ? provider
555
- : await this.#providerForPolicy(policy.childProviderSpec, policy.reasoningPolicy);
407
+ : await this.#workerModels.providerForPolicy(policy.childProviderSpec, policy.reasoningPolicy);
556
408
  return { provider, childProvider };
557
409
  }
558
410
  async #assertLoopProvider(loopId, requested) {
@@ -679,20 +531,20 @@ export default class Daemon {
679
531
  await this.#assertWorkerOwned(workspaceId, workerId);
680
532
  await this.#assertWorkerSelectable(workerId);
681
533
  const selector = ClientInput.assertSelector("worker.model.set", "selector", args.selector);
682
- const policy = await this.#resolveWorkerModel(workerId, selector);
534
+ const policy = await this.#workerModels.resolveWorkerModel(workerId, selector);
683
535
  if (policy === null) {
684
536
  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 }));
685
537
  }
686
538
  return projectModelRoute(policy.providerSpec, policy.reasoningPolicy);
687
539
  }
688
540
  async #reasoningSupportForWorker(workerId, row, providerSpec, policy) {
689
- const provider = await this.#providerForPolicy(providerSpec, policy);
541
+ const provider = await this.#workerModels.providerForPolicy(providerSpec, policy);
690
542
  if (row.spawn_model_route_id === null)
691
543
  return provider.supportedReasoningPolicies;
692
544
  const spawnSpec = await specForRoute(this.#db, row.spawn_model_route_id);
693
545
  if (spawnSpec === null)
694
546
  throw new Error(`worker ${workerId}: spawn model route is missing`);
695
- const spawnProvider = await this.#providerForPolicy(spawnSpec, policy);
547
+ const spawnProvider = await this.#workerModels.providerForPolicy(spawnSpec, policy);
696
548
  return provider.supportedReasoningPolicies.filter((candidate) => spawnProvider.supportedReasoningPolicies.includes(candidate));
697
549
  }
698
550
  // {§worker-reasoning-policy} — the worker's reasoning policy is durable and
@@ -701,7 +553,7 @@ export default class Daemon {
701
553
  const workspaceId = ClientInput.assertId("worker.reasoning.get", "workspaceId", args.workspaceId);
702
554
  const workerId = ClientInput.assertId("worker.reasoning.get", "workerId", args.workerId);
703
555
  await this.#assertWorkerOwned(workspaceId, workerId);
704
- await this.#resolveWorkerModel(workerId, undefined);
556
+ await this.#workerModels.resolveWorkerModel(workerId, undefined);
705
557
  const row = await this.#db.worker_generation_policy_read.get({ id: workerId });
706
558
  if (row === undefined)
707
559
  throw new Error(`worker ${workerId}: generation policy row missing`);
@@ -736,7 +588,7 @@ export default class Daemon {
736
588
  }
737
589
  await this.#assertWorkerOwned(workspaceId, workerId);
738
590
  await this.#assertWorkerSelectable(workerId);
739
- await this.#resolveWorkerModel(workerId, undefined);
591
+ await this.#workerModels.resolveWorkerModel(workerId, undefined);
740
592
  const row = await this.#db.worker_generation_policy_read.get({ id: workerId });
741
593
  if (row === undefined)
742
594
  throw new Error(`worker ${workerId}: generation policy row missing`);
@@ -766,7 +618,7 @@ export default class Daemon {
766
618
  await this.#assertWorkerOwned(workspaceId, workerId);
767
619
  await this.#assertWorkerSelectable(workerId);
768
620
  const selector = ClientInput.assertChildSelector("worker.child.set", args.selector);
769
- const spec = await this.#resolveWorkerSpawnModel(workerId, selector);
621
+ const spec = await this.#workerModels.resolveWorkerSpawnModel(workerId, selector);
770
622
  if (spec === null)
771
623
  return null;
772
624
  const row = await this.#db.worker_generation_policy_read.get({ id: workerId });
@@ -970,64 +822,6 @@ export default class Daemon {
970
822
  releaseCapabilities();
971
823
  }
972
824
  }
973
- // {§methods-log-read} — a workspace's journal, the module's primary render input. The worker is
974
- // ownership-verified against the workspace (a workspace reads only its own workers — the model worker included,
975
- // {§methods-log-coordinate}); entries filter by loop/turn/since-id or the full L/T/S display coordinate. Core owns the
976
- // journal + the invariant; the module shapes the entries into AG-UI messages at its edge.
977
- async readLog(args) {
978
- const workspaceId = ClientInput.assertId("log.read", "workspaceId", args.workspaceId);
979
- const workerId = ClientInput.assertId("log.read", "workerId", args.workerId);
980
- const target = await this.#db.envelope_get_worker_by_id.get({ id: workerId });
981
- if (target === undefined) {
982
- throw daemonFailure("daemon:worker", "worker-not-found", 404, `Worker ${workerId} does not exist.`, { workerId });
983
- }
984
- if (target.workspace_id !== workspaceId) {
985
- throw daemonFailure("daemon:worker", "workspace-mismatch", 409, `Worker ${workerId} does not belong to workspace ${workspaceId}.`, {
986
- workerId,
987
- workspaceId,
988
- actualWorkspaceId: target.workspace_id,
989
- retryable: false
990
- });
991
- }
992
- const coordinateFields = {
993
- loopId: args.loopId,
994
- turnId: args.turnId,
995
- sinceId: args.sinceId,
996
- loopSeq: args.loopSeq,
997
- turnSeq: args.turnSeq,
998
- sequence: args.sequence
999
- };
1000
- for (const [field, value] of Object.entries(coordinateFields)) {
1001
- if (value !== undefined && (!Number.isSafeInteger(value) || value < 0)) {
1002
- throw daemonFailure("daemon:log", "coordinate-invalid", 400, `Log coordinate field '${field}' is not a non-negative safe integer.`, {
1003
- field,
1004
- value,
1005
- stage: "log-read",
1006
- recovery: "Use a non-negative integer coordinate.",
1007
- retryable: false
1008
- });
1009
- }
1010
- }
1011
- if (args.limit !== undefined && (!Number.isSafeInteger(args.limit) || args.limit < 1)) {
1012
- throw daemonFailure("daemon:log", "limit-invalid", 400, `Log limit ${args.limit} is not a positive safe integer.`, {
1013
- field: "limit",
1014
- value: args.limit,
1015
- stage: "log-read",
1016
- recovery: "Use a positive integer log limit.",
1017
- retryable: false
1018
- });
1019
- }
1020
- const rows = await this.#db.log_read_recent_ids.all({
1021
- worker_id: workerId,
1022
- loop_id: args.loopId ?? null, turn_id: args.turnId ?? null, since_id: args.sinceId ?? null,
1023
- loop_seq: args.loopSeq ?? null, turn_seq: args.turnSeq ?? null, sequence: args.sequence ?? null,
1024
- limit: Math.min(args.limit ?? 100, 1000)
1025
- });
1026
- const entries = [];
1027
- for (const r of rows)
1028
- entries.push(await LogEntry.fetchLogEntry(this.#db, r.id));
1029
- return entries;
1030
- }
1031
825
  // {§methods} — the module's render surface beyond the journal. Thin delegations
1032
826
  // into core's envelope / membership / provider machinery; the module fans the results into its own views.
1033
827
  listProviders() {
@@ -1170,139 +964,6 @@ export default class Daemon {
1170
964
  throw new Error("ClientInput.assertOptionalName accepted a required name as undefined");
1171
965
  return { id: checkedWorkspaceId, name: await Envelope.updateWorkspaceName(this.#db, checkedWorkspaceId, checkedName) };
1172
966
  }
1173
- // Contracts {§entry-read-result}: resolve through the scheme's address law,
1174
- // then project one owner-scoped entry without exposing persistence columns.
1175
- async readEntry(args) {
1176
- const workspaceId = ClientInput.assertId("entry.read", "workspaceId", args.workspaceId);
1177
- const workerId = ClientInput.assertId("entry.read", "workerId", args.workerId);
1178
- if (typeof args.target !== "string" || args.target.length === 0) {
1179
- throw daemonFailure("daemon:input", "target-invalid", 400, "target is not a non-empty string.", {
1180
- context: "entry.read",
1181
- field: "target",
1182
- stage: "input-validation",
1183
- recovery: "Provide an entry URI.",
1184
- retryable: false
1185
- });
1186
- }
1187
- const channel = ClientInput.assertOptionalChannel("entry.read", args.channel);
1188
- const worker = await this.#db.envelope_get_worker_by_id.get({ id: workerId });
1189
- if (worker === undefined) {
1190
- throw daemonFailure("daemon:worker", "worker-not-found", 404, `Worker ${workerId} does not exist.`, { workerId });
1191
- }
1192
- if (worker.workspace_id !== workspaceId) {
1193
- throw daemonFailure("daemon:worker", "workspace-mismatch", 409, `Worker ${workerId} does not belong to workspace ${workspaceId}.`, {
1194
- workerId,
1195
- workspaceId,
1196
- actualWorkspaceId: worker.workspace_id,
1197
- retryable: false
1198
- });
1199
- }
1200
- const releaseCapabilities = await this.#residency.acquire(workspaceId, workerId);
1201
- let releaseWorkspace;
1202
- try {
1203
- releaseWorkspace = await this.#workspaceGate.acquireTurn(workspaceId, workerId);
1204
- let parsed;
1205
- try {
1206
- parsed = parsePath(args.target);
1207
- }
1208
- catch {
1209
- parsed = null;
1210
- }
1211
- if (parsed === null || parsed.kind !== "url") {
1212
- return entryReadResult(Results.failure("daemon:entry", "target-invalid", 400, `The entry target '${args.target}' is not URL-shaped.`, { entry: null }, {
1213
- target: args.target,
1214
- stage: "entry-read",
1215
- recovery: "Use a scheme://path target.",
1216
- retryable: false
1217
- }));
1218
- }
1219
- if (args.offset !== undefined && channel === undefined) {
1220
- return entryReadResult(Results.failure("daemon:entry", "offset-channel-required", 400, "An entry offset requires a channel.", { entry: null }, {
1221
- offset: args.offset,
1222
- stage: "entry-read",
1223
- recovery: "Select the channel to read from the offset.",
1224
- retryable: false
1225
- }));
1226
- }
1227
- if (args.offset !== undefined && (!Number.isSafeInteger(args.offset) || args.offset < 0)) {
1228
- return entryReadResult(Results.failure("daemon:entry", "offset-invalid", 400, `Entry offset ${args.offset} is not a non-negative safe integer.`, { entry: null }, {
1229
- offset: args.offset,
1230
- stage: "entry-read",
1231
- recovery: "Use a non-negative integer offset.",
1232
- retryable: false
1233
- }));
1234
- }
1235
- if (parsed.username !== null || parsed.password !== null) {
1236
- return entryReadResult(Results.failure("daemon:entry", "userinfo-not-allowed", 400, "Entry target URL userinfo is not allowed.", { entry: null }, {
1237
- stage: "entry-read",
1238
- recovery: "Remove credentials from the entry URL.",
1239
- retryable: false
1240
- }));
1241
- }
1242
- const location = await this.#engine.resolveEntryAddress({
1243
- workspaceId,
1244
- workerId,
1245
- target: parsed
1246
- });
1247
- if (location === null) {
1248
- return entryReadResult(Results.failure("daemon:entry", "entry-not-found", 404, "No visible entry exists at the requested target.", { entry: null }, { target: args.target }));
1249
- }
1250
- const row = await this.#db.entry_read_lookup.get({
1251
- workspace_id: workspaceId,
1252
- owner_id: location.ownerId,
1253
- scheme: location.scheme,
1254
- authority: location.authority,
1255
- pathname: location.pathname
1256
- });
1257
- if (row === undefined) {
1258
- return entryReadResult(Results.failure("daemon:entry", "entry-not-found", 404, `No visible entry exists at ${location.target}.`, { entry: null }, { target: location.target }));
1259
- }
1260
- let channelRows;
1261
- if (channel === undefined) {
1262
- channelRows = await this.#db.entry_read_channels.all({ entry_id: row.id });
1263
- }
1264
- else {
1265
- const r = await this.#db.entry_read_channel_slice.get({ entry_id: row.id, channel, offset: args.offset ?? 0 });
1266
- if (r === undefined) {
1267
- const availableChannels = (await this.#db.entry_read_channels.all({ entry_id: row.id }))
1268
- .map(({ name }) => name);
1269
- return entryReadResult(Results.failure("daemon:entry", "channel-not-found", 404, `Channel #${channel} does not exist at ${location.target}.`, { entry: null }, {
1270
- target: location.target,
1271
- requestedChannel: channel,
1272
- availableChannels,
1273
- ...(availableChannels.length === 0
1274
- ? {}
1275
- : { recovery: `Use one of the available channels: ${availableChannels.map((channel) => `#${channel}`).join(", ")}.` }),
1276
- retryable: false
1277
- }));
1278
- }
1279
- channelRows = [r];
1280
- }
1281
- const channels = {};
1282
- for (const c of channelRows) {
1283
- channels[c.name] = {
1284
- content: c.content,
1285
- contentOffset: c.contentOffset,
1286
- contentLength: c.contentLength,
1287
- mimetype: c.mimetype,
1288
- weight: c.weight,
1289
- state: c.state
1290
- };
1291
- }
1292
- return entryReadResult({
1293
- status: 200,
1294
- entry: {
1295
- entryId: row.id,
1296
- target: location.target,
1297
- channels
1298
- }
1299
- });
1300
- }
1301
- finally {
1302
- releaseWorkspace?.();
1303
- releaseCapabilities();
1304
- }
1305
- }
1306
967
  // {§methods-conversation-worker}: a fresh conversation is a model-origin root worker with an empty private log.
1307
968
  // AG-UI threads map to these workers while the workspace world remains shared ({§machine-processes}).
1308
969
  async createConversationWorker(args) {
@@ -1688,6 +1349,8 @@ export default class Daemon {
1688
1349
  // (SSE, WS) add themselves here as they land.
1689
1350
  async #drainStreamingSchemes() {
1690
1351
  const exec = this.#schemes.get("exec");
1352
+ // {§exec-timeout} — a `<-1>` spawn ends with the daemon: nothing else ever aborts it.
1353
+ exec?.abortDetached?.();
1691
1354
  if (exec?.idle !== undefined)
1692
1355
  await exec.idle();
1693
1356
  }
@@ -1821,5 +1484,11 @@ export default class Daemon {
1821
1484
  this.#emitTo(target.workspaceId, method, params);
1822
1485
  });
1823
1486
  }
1487
+ async readEntry(...args) {
1488
+ return this.#reads.readEntry(...args);
1489
+ }
1490
+ async readLog(...args) {
1491
+ return this.#reads.readLog(...args);
1492
+ }
1824
1493
  }
1825
1494
  //# sourceMappingURL=Daemon.js.map