@qvac/harness 1.0.0-rc.1 → 1.0.0-rc.2

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 (796) hide show
  1. package/CHANGELOG.md +1168 -1
  2. package/NOTICE.md +16 -0
  3. package/README.md +278 -471
  4. package/dist-lib/index.d.ts +101 -169
  5. package/dist-lib/index.js +423 -1506
  6. package/dist-lib/lib/addon-seal.bare.d.ts +1 -0
  7. package/dist-lib/lib/addon-seal.bare.js +3 -0
  8. package/dist-lib/lib/addon-seal.node.d.ts +1 -0
  9. package/dist-lib/lib/addon-seal.node.js +1 -0
  10. package/dist-lib/lib/agent/delegate.d.ts +83 -0
  11. package/dist-lib/lib/agent/delegate.js +261 -0
  12. package/dist-lib/lib/agent/follow.d.ts +32 -0
  13. package/dist-lib/lib/agent/follow.js +162 -0
  14. package/dist-lib/lib/agent/index.d.ts +37 -0
  15. package/dist-lib/lib/agent/index.js +42 -0
  16. package/dist-lib/lib/agent/plan.d.ts +6 -0
  17. package/dist-lib/lib/agent/plan.js +74 -0
  18. package/dist-lib/lib/agent/resolve.d.ts +3 -0
  19. package/dist-lib/lib/agent/resolve.js +78 -0
  20. package/dist-lib/lib/{capabilities → agent}/tool-names.d.ts +0 -1
  21. package/dist-lib/lib/{capabilities → agent}/tool-names.js +0 -1
  22. package/dist-lib/lib/{capabilities → agent}/tool-selection.d.ts +3 -6
  23. package/dist-lib/lib/{capabilities → agent}/tool-selection.js +9 -1
  24. package/dist-lib/lib/agent/tools.d.ts +14 -0
  25. package/dist-lib/lib/agent/tools.js +16 -0
  26. package/dist-lib/lib/agent/transfer.d.ts +7 -0
  27. package/dist-lib/lib/agent/transfer.js +26 -0
  28. package/dist-lib/lib/capabilities/agent-ports.d.ts +3 -0
  29. package/dist-lib/lib/capabilities/agent-ports.js +9 -0
  30. package/dist-lib/lib/capabilities/completion-engine/actors/answering.d.ts +1 -1
  31. package/dist-lib/lib/capabilities/completion-engine/actors/answering.js +25 -9
  32. package/dist-lib/lib/capabilities/completion-engine/actors/batching.d.ts +3 -0
  33. package/dist-lib/lib/capabilities/completion-engine/actors/batching.js +90 -0
  34. package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.d.ts +2 -1
  35. package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.js +14 -5
  36. package/dist-lib/lib/capabilities/completion-engine/actors/execute.d.ts +5 -3
  37. package/dist-lib/lib/capabilities/completion-engine/actors/execute.js +8 -3
  38. package/dist-lib/lib/capabilities/completion-engine/actors/executing.d.ts +29 -2
  39. package/dist-lib/lib/capabilities/completion-engine/actors/executing.js +100 -40
  40. package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.d.ts +11 -10
  41. package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.js +28 -21
  42. package/dist-lib/lib/capabilities/completion-engine/actors/finishing.js +2 -2
  43. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-prepare.d.ts +4 -0
  44. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-prepare.js +67 -0
  45. package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.d.ts +10 -3
  46. package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.js +14 -11
  47. package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.d.ts +7 -3
  48. package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.js +30 -31
  49. package/dist-lib/lib/capabilities/completion-engine/actors/preparing.d.ts +3 -2
  50. package/dist-lib/lib/capabilities/completion-engine/actors/preparing.js +86 -102
  51. package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.d.ts +1 -1
  52. package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.js +24 -7
  53. package/dist-lib/lib/capabilities/completion-engine/actors/rejection.d.ts +4 -2
  54. package/dist-lib/lib/capabilities/completion-engine/actors/rejection.js +8 -8
  55. package/dist-lib/lib/capabilities/completion-engine/actors/resolving.d.ts +1 -1
  56. package/dist-lib/lib/capabilities/completion-engine/actors/resolving.js +73 -15
  57. package/dist-lib/lib/capabilities/completion-engine/actors/retrieving.d.ts +10 -0
  58. package/dist-lib/lib/capabilities/completion-engine/actors/retrieving.js +56 -0
  59. package/dist-lib/lib/capabilities/completion-engine/actors/run-prepare.d.ts +4 -0
  60. package/dist-lib/lib/capabilities/completion-engine/actors/run-prepare.js +74 -0
  61. package/dist-lib/lib/capabilities/completion-engine/actors/skill-step.d.ts +2 -0
  62. package/dist-lib/lib/capabilities/completion-engine/actors/skill-step.js +76 -0
  63. package/dist-lib/lib/capabilities/completion-engine/actors/stream.d.ts +2 -2
  64. package/dist-lib/lib/capabilities/completion-engine/actors/stream.js +2 -1
  65. package/dist-lib/lib/capabilities/completion-engine/actors/streaming.d.ts +1 -1
  66. package/dist-lib/lib/capabilities/completion-engine/actors/streaming.js +84 -26
  67. package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.d.ts +1 -1
  68. package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.js +16 -6
  69. package/dist-lib/lib/capabilities/completion-engine/actors.d.ts +11 -0
  70. package/dist-lib/lib/capabilities/completion-engine/actors.js +216 -0
  71. package/dist-lib/lib/capabilities/completion-engine/driver.d.ts +12 -5
  72. package/dist-lib/lib/capabilities/completion-engine/driver.js +118 -33
  73. package/dist-lib/lib/capabilities/completion-engine/durable.d.ts +2 -1
  74. package/dist-lib/lib/capabilities/completion-engine/durable.js +6 -4
  75. package/dist-lib/lib/capabilities/completion-engine/engine.d.ts +65 -0
  76. package/dist-lib/lib/{machine → capabilities/completion-engine}/engine.js +67 -130
  77. package/dist-lib/lib/capabilities/completion-engine/index.d.ts +30 -0
  78. package/dist-lib/lib/capabilities/completion-engine/index.js +44 -0
  79. package/dist-lib/lib/capabilities/completion-engine/loop.d.ts +58 -0
  80. package/dist-lib/lib/capabilities/completion-engine/loop.js +62 -0
  81. package/dist-lib/lib/capabilities/completion-engine/metrics.d.ts +4 -0
  82. package/dist-lib/lib/capabilities/completion-engine/metrics.js +46 -0
  83. package/dist-lib/lib/capabilities/completion-engine/operations.d.ts +5 -2
  84. package/dist-lib/lib/capabilities/completion-engine/operations.js +84 -15
  85. package/dist-lib/lib/capabilities/completion-engine/ports.d.ts +25 -2
  86. package/dist-lib/lib/capabilities/completion-engine/ports.js +25 -16
  87. package/dist-lib/lib/capabilities/completion-engine/prepare-step.d.ts +26 -0
  88. package/dist-lib/lib/{machine → capabilities/completion-engine}/replay-output.d.ts +1 -1
  89. package/dist-lib/lib/{machine → capabilities/completion-engine}/replay-output.js +1 -1
  90. package/dist-lib/lib/capabilities/{completion-loop → completion-engine}/round.d.ts +24 -4
  91. package/dist-lib/lib/capabilities/{completion-loop → completion-engine}/round.js +242 -27
  92. package/dist-lib/lib/capabilities/completion-engine/session.d.ts +19 -12
  93. package/dist-lib/lib/capabilities/completion-engine/session.js +12 -6
  94. package/dist-lib/lib/capabilities/completion-engine/splice.d.ts +2 -0
  95. package/dist-lib/lib/capabilities/completion-engine/splice.js +7 -0
  96. package/dist-lib/lib/capabilities/completion-engine/stages.d.ts +23 -0
  97. package/dist-lib/lib/capabilities/completion-engine/tool-caller.d.ts +10 -0
  98. package/dist-lib/lib/capabilities/completion-engine/tool-caller.js +151 -0
  99. package/dist-lib/lib/capabilities/completion-engine/tool-execution.d.ts +77 -0
  100. package/dist-lib/lib/capabilities/{completion-loop → completion-engine}/tool-execution.js +74 -25
  101. package/dist-lib/lib/capabilities/{completion-loop → completion-engine}/turns.d.ts +8 -4
  102. package/dist-lib/lib/capabilities/completion-engine/turns.js +225 -0
  103. package/dist-lib/lib/capabilities/enhance.d.ts +1 -1
  104. package/dist-lib/lib/capabilities/enhance.js +3 -2
  105. package/dist-lib/lib/capabilities/invoke.d.ts +1 -1
  106. package/dist-lib/lib/capabilities/preview-model-source.d.ts +1 -10
  107. package/dist-lib/lib/capabilities/preview-model-source.js +3 -1
  108. package/dist-lib/lib/capabilities/sdk-tool.d.ts +10 -0
  109. package/dist-lib/lib/capabilities/sdk-tool.js +130 -0
  110. package/dist-lib/lib/capabilities/skill-entry.d.ts +8 -0
  111. package/dist-lib/lib/capabilities/skill-entry.js +14 -0
  112. package/dist-lib/lib/capabilities/tool-plan.d.ts +6 -5
  113. package/dist-lib/lib/capabilities/tool-plan.js +16 -10
  114. package/dist-lib/lib/capabilities/tool-turns.d.ts +29 -4
  115. package/dist-lib/lib/capabilities/tool-turns.js +120 -10
  116. package/dist-lib/lib/capabilities/usage-breakdown.d.ts +1 -1
  117. package/dist-lib/lib/capabilities/usage-breakdown.js +4 -1
  118. package/dist-lib/lib/connect.d.ts +6 -0
  119. package/dist-lib/lib/connect.js +153 -65
  120. package/dist-lib/lib/context-window.d.ts +4 -2
  121. package/dist-lib/lib/context-window.js +27 -16
  122. package/dist-lib/lib/contract/agent.d.ts +65 -0
  123. package/dist-lib/lib/{capabilities/types.d.ts → contract/completion.d.ts} +140 -26
  124. package/dist-lib/lib/contract/exec.d.ts +134 -0
  125. package/dist-lib/lib/{hooks/types.d.ts → contract/hooks.d.ts} +62 -10
  126. package/dist-lib/lib/contract/index.d.ts +5 -0
  127. package/dist-lib/lib/contract/knowledge.d.ts +60 -0
  128. package/dist-lib/lib/contract/knowledge.js +1 -0
  129. package/dist-lib/lib/contract/models.d.ts +56 -0
  130. package/dist-lib/lib/contract/models.js +1 -0
  131. package/dist-lib/lib/contract/run.d.ts +142 -0
  132. package/dist-lib/lib/contract/run.js +1 -0
  133. package/dist-lib/lib/contract/sandbox.d.ts +29 -0
  134. package/dist-lib/lib/contract/sandbox.js +1 -0
  135. package/dist-lib/lib/contract/skill-readiness.d.ts +14 -0
  136. package/dist-lib/lib/contract/skill-readiness.js +1 -0
  137. package/dist-lib/lib/{capabilities/voice.d.ts → contract/speech.d.ts} +11 -16
  138. package/dist-lib/lib/contract/speech.js +1 -0
  139. package/dist-lib/lib/contract-types.d.ts +43 -16
  140. package/dist-lib/lib/docx/index.d.ts +0 -1
  141. package/dist-lib/lib/docx/index.js +15 -24
  142. package/dist-lib/lib/embeddings/index.d.ts +63 -0
  143. package/dist-lib/lib/embeddings/index.js +267 -0
  144. package/dist-lib/lib/fold/index.d.ts +50 -0
  145. package/dist-lib/lib/fold/index.js +123 -0
  146. package/dist-lib/lib/{tools/exec/adapters/python/guarded-fetch.d.ts → guarded-fetch.d.ts} +5 -12
  147. package/dist-lib/lib/{tools/exec/adapters/python/guarded-fetch.js → guarded-fetch.js} +12 -34
  148. package/dist-lib/lib/helpers/completion-params.d.ts +3 -0
  149. package/dist-lib/lib/helpers/completion-params.js +12 -0
  150. package/dist-lib/lib/helpers/copy.d.ts +1 -0
  151. package/dist-lib/lib/helpers/copy.js +5 -0
  152. package/dist-lib/lib/helpers/drain.d.ts +5 -0
  153. package/dist-lib/lib/helpers/drain.js +19 -0
  154. package/dist-lib/lib/{machine/errors.d.ts → helpers/engine-error.d.ts} +6 -9
  155. package/dist-lib/lib/{machine/errors.js → helpers/engine-error.js} +9 -25
  156. package/dist-lib/lib/helpers/failure-result.d.ts +21 -0
  157. package/dist-lib/lib/helpers/failure-result.js +39 -0
  158. package/dist-lib/lib/helpers/head-tail.d.ts +7 -0
  159. package/dist-lib/lib/helpers/head-tail.js +19 -0
  160. package/dist-lib/lib/helpers/image-settings.d.ts +2 -0
  161. package/dist-lib/lib/helpers/image-settings.js +19 -0
  162. package/dist-lib/lib/helpers/mcp-methods.d.ts +2 -0
  163. package/dist-lib/lib/helpers/mcp-methods.js +14 -0
  164. package/dist-lib/lib/helpers/race-abort.d.ts +1 -1
  165. package/dist-lib/lib/helpers/race-abort.js +1 -1
  166. package/dist-lib/lib/helpers/repeated-reply.d.ts +2 -0
  167. package/dist-lib/lib/helpers/repeated-reply.js +63 -0
  168. package/dist-lib/lib/helpers/run-outcome.d.ts +5 -4
  169. package/dist-lib/lib/helpers/run-outcome.js +11 -9
  170. package/dist-lib/lib/{machine → helpers}/stable-stringify.js +1 -1
  171. package/dist-lib/lib/helpers/tool-call-markup.d.ts +1 -0
  172. package/dist-lib/lib/helpers/tool-call-markup.js +9 -5
  173. package/dist-lib/lib/helpers/tool-label.d.ts +2 -2
  174. package/dist-lib/lib/helpers/tool-label.js +3 -3
  175. package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -1
  176. package/dist-lib/lib/hooks/built-in/arg-repair.js +109 -19
  177. package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -1
  178. package/dist-lib/lib/hooks/built-in/egress.js +13 -21
  179. package/dist-lib/lib/hooks/built-in/sandbox.d.ts +1 -1
  180. package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -1
  181. package/dist-lib/lib/hooks/index.d.ts +48 -0
  182. package/dist-lib/lib/hooks/index.js +130 -0
  183. package/dist-lib/lib/hooks/run.d.ts +9 -6
  184. package/dist-lib/lib/hooks/run.js +113 -48
  185. package/dist-lib/lib/{completion-lifecycle.d.ts → lifecycle/completion-run.d.ts} +1 -1
  186. package/dist-lib/lib/{completion-lifecycle.js → lifecycle/completion-run.js} +1 -1
  187. package/dist-lib/lib/lifecycle/index.d.ts +83 -0
  188. package/dist-lib/lib/lifecycle/index.js +335 -0
  189. package/dist-lib/lib/{harness-lifecycle.js → lifecycle/machine.js} +2 -2
  190. package/dist-lib/lib/machine/completion/actions/completion.d.ts +11 -2
  191. package/dist-lib/lib/machine/completion/actions/completion.js +98 -14
  192. package/dist-lib/lib/machine/completion/actions/prepare.d.ts +9 -0
  193. package/dist-lib/lib/machine/completion/actions/prepare.js +30 -0
  194. package/dist-lib/lib/machine/completion/actions/tools.d.ts +10 -1
  195. package/dist-lib/lib/machine/completion/actions/tools.js +79 -7
  196. package/dist-lib/lib/machine/completion/context.d.ts +7 -2
  197. package/dist-lib/lib/machine/completion/context.js +29 -5
  198. package/dist-lib/lib/machine/completion/guards/retry.d.ts +1 -0
  199. package/dist-lib/lib/machine/completion/guards/retry.js +6 -3
  200. package/dist-lib/lib/machine/completion/implementations.d.ts +38 -12
  201. package/dist-lib/lib/machine/completion/implementations.js +81 -31
  202. package/dist-lib/lib/machine/completion/machine.d.ts +140 -63
  203. package/dist-lib/lib/machine/completion/machine.js +194 -58
  204. package/dist-lib/lib/machine/completion/ports.d.ts +7 -55
  205. package/dist-lib/lib/machine/completion/ports.js +1 -224
  206. package/dist-lib/lib/machine/completion/rules.d.ts +20 -19
  207. package/dist-lib/lib/machine/completion/rules.js +73 -52
  208. package/dist-lib/lib/machine/completion/types.d.ts +110 -187
  209. package/dist-lib/lib/machine/completion/version.d.ts +1 -0
  210. package/dist-lib/lib/machine/completion/version.js +1 -0
  211. package/dist-lib/lib/machine/definition.d.ts +23 -0
  212. package/dist-lib/lib/machine/definition.js +76 -0
  213. package/dist-lib/lib/machine/index.d.ts +463 -20
  214. package/dist-lib/lib/machine/index.js +15 -11
  215. package/dist-lib/lib/models/llm-presets.d.ts +1 -0
  216. package/dist-lib/lib/models/model-catalog-constants.d.ts +3 -1
  217. package/dist-lib/lib/models/model-catalog-constants.js +9 -1
  218. package/dist-lib/lib/models/model-catalog.d.ts +31 -4
  219. package/dist-lib/lib/models/model-catalog.js +89 -8
  220. package/dist-lib/lib/models/model-fit.d.ts +55 -0
  221. package/dist-lib/lib/models/model-fit.js +102 -0
  222. package/dist-lib/lib/models/model-handle.d.ts +4 -0
  223. package/dist-lib/lib/models/model-handle.js +8 -1
  224. package/dist-lib/lib/models/model-list.d.ts +4 -0
  225. package/dist-lib/lib/models/model-pool.d.ts +35 -10
  226. package/dist-lib/lib/models/model-pool.js +63 -14
  227. package/dist-lib/lib/models/music-catalog.d.ts +1 -1
  228. package/dist-lib/lib/models/music-catalog.js +8 -1
  229. package/dist-lib/lib/models/sdk-faults.d.ts +2 -0
  230. package/dist-lib/lib/models/sdk-faults.js +18 -0
  231. package/dist-lib/lib/models/tts-model-default.js +3 -3
  232. package/dist-lib/lib/office/engine/codes.d.ts +62 -0
  233. package/dist-lib/lib/office/engine/codes.js +61 -0
  234. package/dist-lib/lib/office/engine/docx/document.d.ts +216 -0
  235. package/dist-lib/lib/office/engine/docx/document.js +1152 -0
  236. package/dist-lib/lib/office/engine/docx/index.d.ts +7 -0
  237. package/dist-lib/lib/office/engine/docx/index.js +8 -0
  238. package/dist-lib/lib/office/engine/docx/styles.d.ts +31 -0
  239. package/dist-lib/lib/office/engine/docx/styles.js +173 -0
  240. package/dist-lib/lib/office/engine/docx/template.d.ts +18 -0
  241. package/dist-lib/lib/office/engine/docx/template.js +133 -0
  242. package/dist-lib/lib/office/engine/docx/text.d.ts +55 -0
  243. package/dist-lib/lib/office/engine/docx/text.js +538 -0
  244. package/dist-lib/lib/office/engine/drawingml/chart.d.ts +63 -0
  245. package/dist-lib/lib/office/engine/drawingml/chart.js +539 -0
  246. package/dist-lib/lib/office/engine/drawingml/text.d.ts +35 -0
  247. package/dist-lib/lib/office/engine/drawingml/text.js +352 -0
  248. package/dist-lib/lib/office/engine/errors.d.ts +6 -0
  249. package/dist-lib/lib/office/engine/errors.js +12 -0
  250. package/dist-lib/lib/office/engine/image.d.ts +8 -0
  251. package/dist-lib/lib/office/engine/image.js +48 -0
  252. package/dist-lib/lib/office/engine/index.d.ts +12 -0
  253. package/dist-lib/lib/office/engine/index.js +7 -0
  254. package/dist-lib/lib/office/engine/opc/content-types.d.ts +17 -0
  255. package/dist-lib/lib/office/engine/opc/content-types.js +74 -0
  256. package/dist-lib/lib/office/engine/opc/media.d.ts +13 -0
  257. package/dist-lib/lib/office/engine/opc/media.js +11 -0
  258. package/dist-lib/lib/office/engine/opc/package.d.ts +51 -0
  259. package/dist-lib/lib/office/engine/opc/package.js +324 -0
  260. package/dist-lib/lib/office/engine/opc/paths.d.ts +7 -0
  261. package/dist-lib/lib/office/engine/opc/paths.js +46 -0
  262. package/dist-lib/lib/office/engine/opc/properties.d.ts +7 -0
  263. package/dist-lib/lib/office/engine/opc/properties.js +75 -0
  264. package/dist-lib/lib/office/engine/opc/relationships.d.ts +23 -0
  265. package/dist-lib/lib/office/engine/opc/relationships.js +65 -0
  266. package/dist-lib/lib/office/engine/opc/zip.d.ts +15 -0
  267. package/dist-lib/lib/office/engine/opc/zip.js +264 -0
  268. package/dist-lib/lib/office/engine/pptx/fit.d.ts +12 -0
  269. package/dist-lib/lib/office/engine/pptx/fit.js +37 -0
  270. package/dist-lib/lib/office/engine/pptx/index.d.ts +8 -0
  271. package/dist-lib/lib/office/engine/pptx/index.js +8 -0
  272. package/dist-lib/lib/office/engine/pptx/inherit.d.ts +29 -0
  273. package/dist-lib/lib/office/engine/pptx/inherit.js +155 -0
  274. package/dist-lib/lib/office/engine/pptx/notes.d.ts +5 -0
  275. package/dist-lib/lib/office/engine/pptx/notes.js +85 -0
  276. package/dist-lib/lib/office/engine/pptx/presentation.d.ts +54 -0
  277. package/dist-lib/lib/office/engine/pptx/presentation.js +749 -0
  278. package/dist-lib/lib/office/engine/pptx/read.d.ts +9 -0
  279. package/dist-lib/lib/office/engine/pptx/read.js +66 -0
  280. package/dist-lib/lib/office/engine/pptx/shapes.d.ts +52 -0
  281. package/dist-lib/lib/office/engine/pptx/shapes.js +276 -0
  282. package/dist-lib/lib/office/engine/pptx/slides.d.ts +27 -0
  283. package/dist-lib/lib/office/engine/pptx/slides.js +123 -0
  284. package/dist-lib/lib/office/engine/pptx/template.d.ts +20 -0
  285. package/dist-lib/lib/office/engine/pptx/template.js +391 -0
  286. package/dist-lib/lib/office/engine/pptx/types.d.ts +120 -0
  287. package/dist-lib/lib/office/engine/pptx/types.js +1 -0
  288. package/dist-lib/lib/office/engine/units.d.ts +3 -0
  289. package/dist-lib/lib/office/engine/units.js +12 -0
  290. package/dist-lib/lib/office/engine/utf8.d.ts +2 -0
  291. package/dist-lib/lib/office/engine/utf8.js +103 -0
  292. package/dist-lib/lib/office/engine/xlsx/formula.d.ts +49 -0
  293. package/dist-lib/lib/office/engine/xlsx/formula.js +381 -0
  294. package/dist-lib/lib/office/engine/xlsx/index.d.ts +8 -0
  295. package/dist-lib/lib/office/engine/xlsx/index.js +8 -0
  296. package/dist-lib/lib/office/engine/xlsx/refs.d.ts +22 -0
  297. package/dist-lib/lib/office/engine/xlsx/refs.js +82 -0
  298. package/dist-lib/lib/office/engine/xlsx/reshape.d.ts +21 -0
  299. package/dist-lib/lib/office/engine/xlsx/reshape.js +424 -0
  300. package/dist-lib/lib/office/engine/xlsx/sheet.d.ts +108 -0
  301. package/dist-lib/lib/office/engine/xlsx/sheet.js +662 -0
  302. package/dist-lib/lib/office/engine/xlsx/strings.d.ts +15 -0
  303. package/dist-lib/lib/office/engine/xlsx/strings.js +93 -0
  304. package/dist-lib/lib/office/engine/xlsx/styles.d.ts +38 -0
  305. package/dist-lib/lib/office/engine/xlsx/styles.js +369 -0
  306. package/dist-lib/lib/office/engine/xlsx/template.d.ts +7 -0
  307. package/dist-lib/lib/office/engine/xlsx/template.js +54 -0
  308. package/dist-lib/lib/office/engine/xlsx/workbook.d.ts +161 -0
  309. package/dist-lib/lib/office/engine/xlsx/workbook.js +850 -0
  310. package/dist-lib/lib/office/engine/xlsx/write.d.ts +2 -0
  311. package/dist-lib/lib/office/engine/xlsx/write.js +42 -0
  312. package/dist-lib/lib/office/engine/xml.d.ts +45 -0
  313. package/dist-lib/lib/office/engine/xml.js +258 -0
  314. package/dist-lib/lib/office/extract.d.ts +9 -0
  315. package/dist-lib/lib/office/extract.js +19 -0
  316. package/dist-lib/lib/office/index.d.ts +1 -1
  317. package/dist-lib/lib/office/index.js +74 -19
  318. package/dist-lib/lib/plugins/addons.d.ts +2 -0
  319. package/dist-lib/lib/plugins/addons.js +12 -0
  320. package/dist-lib/lib/plugins/context.d.ts +16 -0
  321. package/dist-lib/lib/plugins/context.js +48 -0
  322. package/dist-lib/lib/plugins/index.d.ts +3 -0
  323. package/dist-lib/lib/plugins/index.js +1 -0
  324. package/dist-lib/lib/plugins/registry.d.ts +116 -0
  325. package/dist-lib/lib/plugins/registry.js +505 -0
  326. package/dist-lib/lib/plugins/runtime.d.ts +27 -0
  327. package/dist-lib/lib/plugins/runtime.js +143 -0
  328. package/dist-lib/lib/plugins/scope.d.ts +17 -0
  329. package/dist-lib/lib/plugins/scope.js +55 -0
  330. package/dist-lib/lib/prompt.d.ts +2 -5
  331. package/dist-lib/lib/prompt.js +9 -0
  332. package/dist-lib/lib/residency/completion-runtime.d.ts +52 -0
  333. package/dist-lib/lib/{capabilities → residency}/completion-runtime.js +22 -15
  334. package/dist-lib/lib/residency/index.d.ts +148 -0
  335. package/dist-lib/lib/residency/index.js +539 -0
  336. package/dist-lib/lib/run-log/boundary.d.ts +17 -0
  337. package/dist-lib/lib/run-log/boundary.js +58 -0
  338. package/dist-lib/lib/run-log/history-codec.d.ts +7 -6
  339. package/dist-lib/lib/run-log/history-codec.js +175 -46
  340. package/dist-lib/lib/run-log/index.d.ts +46 -0
  341. package/dist-lib/lib/run-log/index.js +40 -0
  342. package/dist-lib/lib/run-log/inspect.d.ts +53 -0
  343. package/dist-lib/lib/{run-log-inspect.js → run-log/inspect.js} +196 -139
  344. package/dist-lib/lib/run-log/live.d.ts +37 -0
  345. package/dist-lib/lib/run-log/live.js +195 -0
  346. package/dist-lib/lib/run-log/persisted-actor.d.ts +1 -6
  347. package/dist-lib/lib/run-log/persisted-actor.js +4 -3
  348. package/dist-lib/lib/run-log/protocol-types.d.ts +37 -14
  349. package/dist-lib/lib/run-log/protocol.d.ts +1 -2
  350. package/dist-lib/lib/run-log/protocol.js +45 -40
  351. package/dist-lib/lib/{run-log-redact.d.ts → run-log/redact.d.ts} +3 -2
  352. package/dist-lib/lib/{run-log-redact.js → run-log/redact.js} +101 -16
  353. package/dist-lib/lib/run-log/replay.d.ts +3 -2
  354. package/dist-lib/lib/run-log/replay.js +7 -6
  355. package/dist-lib/lib/run-log/request-codec.d.ts +17 -0
  356. package/dist-lib/lib/run-log/request-codec.js +87 -0
  357. package/dist-lib/lib/run-log/run-journal.d.ts +14 -8
  358. package/dist-lib/lib/run-log/run-journal.js +100 -75
  359. package/dist-lib/lib/sdk-loader.d.ts +2 -7
  360. package/dist-lib/lib/sdk-loader.js +8 -15
  361. package/dist-lib/lib/sdk-storage.js +3 -1
  362. package/dist-lib/lib/serve.js +139 -38
  363. package/dist-lib/lib/skills-host/index.d.ts +59 -0
  364. package/dist-lib/lib/skills-host/index.js +268 -0
  365. package/dist-lib/lib/spawn.d.ts +37 -3
  366. package/dist-lib/lib/spawn.js +7 -3
  367. package/dist-lib/lib/spill.d.ts +11 -0
  368. package/dist-lib/lib/spill.js +82 -0
  369. package/dist-lib/lib/tools/{exec/adapters/python → attachments}/output-policy.d.ts +2 -3
  370. package/dist-lib/lib/tools/{exec/adapters/python/attachments.d.ts → attachments/staging.d.ts} +2 -2
  371. package/dist-lib/lib/tools/{exec/adapters/python/attachments.js → attachments/staging.js} +3 -3
  372. package/dist-lib/lib/tools/catalog.d.ts +1 -1
  373. package/dist-lib/lib/tools/catalog.js +1 -1
  374. package/dist-lib/lib/tools/create-documents.d.ts +1 -1
  375. package/dist-lib/lib/tools/edit-documents.d.ts +1 -1
  376. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +5 -7
  377. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +3 -2
  378. package/dist-lib/lib/tools/exec/bare-runtime.js +2 -4
  379. package/dist-lib/lib/tools/exec/python-source.d.ts +6 -0
  380. package/dist-lib/lib/tools/exec/python-source.js +243 -0
  381. package/dist-lib/lib/tools/exec/runner.d.ts +24 -45
  382. package/dist-lib/lib/tools/exec/runner.js +68 -34
  383. package/dist-lib/lib/tools/exec/scope.d.ts +2 -0
  384. package/dist-lib/lib/tools/exec/scope.js +33 -2
  385. package/dist-lib/lib/tools/exec/shell-guidance.d.ts +11 -9
  386. package/dist-lib/lib/tools/exec/shell-guidance.js +28 -57
  387. package/dist-lib/lib/tools/exec/video-tools.d.ts +0 -1
  388. package/dist-lib/lib/tools/exec/video-tools.js +0 -5
  389. package/dist-lib/lib/tools/exec.d.ts +7 -14
  390. package/dist-lib/lib/tools/exec.js +181 -457
  391. package/dist-lib/lib/tools/file-glob.d.ts +1 -1
  392. package/dist-lib/lib/tools/file-glob.js +1 -0
  393. package/dist-lib/lib/tools/fs/scope.d.ts +1 -0
  394. package/dist-lib/lib/tools/fs/scope.js +8 -3
  395. package/dist-lib/lib/tools/grep.d.ts +1 -1
  396. package/dist-lib/lib/tools/grep.js +1 -0
  397. package/dist-lib/lib/tools/http-request.d.ts +1 -1
  398. package/dist-lib/lib/tools/http-request.js +1 -0
  399. package/dist-lib/lib/tools/index.d.ts +21 -0
  400. package/dist-lib/lib/tools/index.js +46 -0
  401. package/dist-lib/lib/tools/office/ops.d.ts +13 -0
  402. package/dist-lib/lib/tools/office/ops.js +100 -0
  403. package/dist-lib/lib/tools/office.d.ts +12 -0
  404. package/dist-lib/lib/tools/office.js +486 -0
  405. package/dist-lib/lib/tools/operations/compile.d.ts +3 -3
  406. package/dist-lib/lib/tools/operations/compile.js +2 -1
  407. package/dist-lib/lib/tools/operations/decoders.js +1 -1
  408. package/dist-lib/lib/tools/operations/manifest.d.ts +1 -1
  409. package/dist-lib/lib/tools/outbound-guard.d.ts +3 -1
  410. package/dist-lib/lib/tools/outbound-guard.js +4 -0
  411. package/dist-lib/lib/tools/pdf/build.d.ts +43 -0
  412. package/dist-lib/lib/tools/pdf/build.js +150 -0
  413. package/dist-lib/lib/tools/pdf/images.d.ts +7 -0
  414. package/dist-lib/lib/tools/pdf/images.js +82 -0
  415. package/dist-lib/lib/tools/pdf/request.d.ts +63 -0
  416. package/dist-lib/lib/tools/pdf/request.js +335 -0
  417. package/dist-lib/lib/tools/pdf.d.ts +6 -0
  418. package/dist-lib/lib/tools/pdf.js +303 -0
  419. package/dist-lib/lib/tools/read-files.d.ts +1 -1
  420. package/dist-lib/lib/tools/read-files.js +5 -1
  421. package/dist-lib/lib/tools/skill.d.ts +2 -4
  422. package/dist-lib/lib/tools/skill.js +20 -22
  423. package/dist-lib/lib/tools/skills/auth-resolver.d.ts +1 -1
  424. package/dist-lib/lib/tools/skills/catalog.d.ts +9 -2
  425. package/dist-lib/lib/tools/skills/catalog.js +7 -7
  426. package/dist-lib/lib/tools/skills/cli-schema.js +1 -1
  427. package/dist-lib/lib/tools/skills/frontmatter-parser.d.ts +1 -0
  428. package/dist-lib/lib/tools/skills/frontmatter-parser.js +1 -0
  429. package/dist-lib/lib/tools/skills/mention.d.ts +1 -2
  430. package/dist-lib/lib/tools/skills/mention.js +0 -3
  431. package/dist-lib/lib/tools/skills/scope-key.d.ts +2 -1
  432. package/dist-lib/lib/tools/skills/scope-key.js +2 -3
  433. package/dist-lib/lib/tools/skills/skill-state.d.ts +2 -2
  434. package/dist-lib/lib/tools/skills/skill-state.js +11 -28
  435. package/dist-lib/lib/tools/toolsets.d.ts +3 -7
  436. package/dist-lib/lib/tools/toolsets.js +5 -9
  437. package/dist-lib/lib/tools/web-fetch.d.ts +1 -1
  438. package/dist-lib/lib/tools/web-fetch.js +42 -6
  439. package/dist-lib/lib/web-fetch/embedded-state.js +1 -1
  440. package/dist-lib/lib/web-fetch/extract.js +1 -1
  441. package/dist-lib/lib/web-fetch/images.js +1 -1
  442. package/dist-lib/lib/web-fetch/video.js +1 -1
  443. package/dist-lib/lib/wire.d.ts +8 -0
  444. package/dist-lib/lib/wire.js +112 -2
  445. package/dist-lib/plugins/code-mode/index.d.ts +16 -0
  446. package/dist-lib/plugins/code-mode/index.js +43 -0
  447. package/dist-lib/plugins/coding/index.d.ts +15 -0
  448. package/dist-lib/plugins/coding/index.js +42 -0
  449. package/dist-lib/plugins/coding/jobs.d.ts +24 -0
  450. package/dist-lib/plugins/coding/jobs.js +144 -0
  451. package/dist-lib/plugins/coding/session.d.ts +51 -0
  452. package/dist-lib/plugins/coding/session.js +263 -0
  453. package/dist-lib/plugins/coding/write-file.d.ts +3 -0
  454. package/dist-lib/plugins/coding/write-file.js +52 -0
  455. package/dist-lib/plugins/command-hooks/index.d.ts +88 -0
  456. package/dist-lib/plugins/command-hooks/index.js +338 -0
  457. package/dist-lib/plugins/external-agents/acp.d.ts +27 -0
  458. package/dist-lib/plugins/external-agents/acp.js +264 -0
  459. package/dist-lib/plugins/external-agents/cli.d.ts +3 -0
  460. package/dist-lib/plugins/external-agents/cli.js +199 -0
  461. package/dist-lib/plugins/external-agents/index.d.ts +25 -0
  462. package/dist-lib/plugins/external-agents/index.js +54 -0
  463. package/dist-lib/plugins/external-agents/process.d.ts +19 -0
  464. package/dist-lib/plugins/external-agents/process.js +92 -0
  465. package/dist-lib/plugins/external-agents/targets.d.ts +32 -0
  466. package/dist-lib/plugins/external-agents/targets.js +66 -0
  467. package/dist-lib/{lib/tools → plugins/image}/edit-image.d.ts +3 -2
  468. package/dist-lib/{lib/tools → plugins/image}/edit-image.js +7 -2
  469. package/dist-lib/{lib/tools → plugins/image}/generate-image.d.ts +6 -12
  470. package/dist-lib/{lib/tools → plugins/image}/generate-image.js +6 -7
  471. package/dist-lib/plugins/image/index.d.ts +25 -0
  472. package/dist-lib/plugins/image/index.js +76 -0
  473. package/dist-lib/plugins/knowledge/index.d.ts +21 -0
  474. package/dist-lib/plugins/knowledge/index.js +47 -0
  475. package/dist-lib/plugins/knowledge/search-tool.d.ts +4 -0
  476. package/dist-lib/plugins/knowledge/search-tool.js +38 -0
  477. package/dist-lib/plugins/knowledge/store.d.ts +42 -0
  478. package/dist-lib/plugins/knowledge/store.js +332 -0
  479. package/dist-lib/plugins/lsp/index.d.ts +32 -0
  480. package/dist-lib/plugins/lsp/index.js +77 -0
  481. package/dist-lib/plugins/lsp/pool.d.ts +24 -0
  482. package/dist-lib/plugins/lsp/pool.js +73 -0
  483. package/dist-lib/plugins/lsp/rpc.d.ts +37 -0
  484. package/dist-lib/plugins/lsp/rpc.js +145 -0
  485. package/dist-lib/plugins/lsp/server.d.ts +55 -0
  486. package/dist-lib/plugins/lsp/server.js +192 -0
  487. package/dist-lib/plugins/lsp/tool.d.ts +12 -0
  488. package/dist-lib/plugins/lsp/tool.js +366 -0
  489. package/dist-lib/plugins/mcp/call.d.ts +17 -0
  490. package/dist-lib/{lib/tools/mcp-call.js → plugins/mcp/call.js} +92 -84
  491. package/dist-lib/plugins/mcp/index.d.ts +21 -0
  492. package/dist-lib/plugins/mcp/index.js +85 -0
  493. package/dist-lib/{lib/tools → plugins}/mcp/protocol.d.ts +9 -16
  494. package/dist-lib/{lib/tools → plugins}/mcp/protocol.js +3 -16
  495. package/dist-lib/plugins/mcp/server.d.ts +23 -0
  496. package/dist-lib/plugins/mcp/server.js +108 -0
  497. package/dist-lib/{lib/tools → plugins/music}/generate-music.d.ts +6 -15
  498. package/dist-lib/{lib/tools → plugins/music}/generate-music.js +7 -8
  499. package/dist-lib/plugins/music/index.d.ts +24 -0
  500. package/dist-lib/plugins/music/index.js +48 -0
  501. package/dist-lib/{lib/tools/exec → plugins}/obsidian/cli-process.d.ts +2 -2
  502. package/dist-lib/{lib/tools/exec → plugins}/obsidian/cli-process.js +2 -2
  503. package/dist-lib/{lib/tools/exec → plugins}/obsidian/cli.d.ts +1 -1
  504. package/dist-lib/{lib/tools/exec → plugins}/obsidian/cli.js +7 -7
  505. package/dist-lib/{lib/tools/exec → plugins}/obsidian/command.js +1 -1
  506. package/dist-lib/{lib/tools/exec → plugins}/obsidian/guidance.d.ts +0 -1
  507. package/dist-lib/{lib/tools/exec → plugins}/obsidian/guidance.js +0 -7
  508. package/dist-lib/plugins/obsidian/index.d.ts +26 -0
  509. package/dist-lib/plugins/obsidian/index.js +138 -0
  510. package/dist-lib/{lib/tools/skills/obsidian-readiness.d.ts → plugins/obsidian/readiness.d.ts} +1 -0
  511. package/dist-lib/{lib/tools/skills/obsidian-readiness.js → plugins/obsidian/readiness.js} +7 -0
  512. package/dist-lib/plugins/python/guarded-fetch.d.ts +13 -0
  513. package/dist-lib/plugins/python/guarded-fetch.js +32 -0
  514. package/dist-lib/plugins/python/index.d.ts +18 -0
  515. package/dist-lib/plugins/python/index.js +19 -0
  516. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/interrupt-timer.js +2 -2
  517. package/dist-lib/plugins/python/language.d.ts +8 -0
  518. package/dist-lib/plugins/python/language.js +377 -0
  519. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/loader.d.ts +1 -0
  520. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/loader.js +8 -1
  521. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/memfs.js +3 -3
  522. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/module-distributions.js +0 -3
  523. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/pyodide.js +4 -4
  524. package/dist-lib/plugins/python/python-adapter.d.ts +41 -0
  525. package/dist-lib/plugins/python/python-adapter.js +515 -0
  526. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/run-session.d.ts +1 -2
  527. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/run-session.js +10 -99
  528. package/dist-lib/plugins/python/shell-redirect.d.ts +8 -0
  529. package/dist-lib/plugins/python/shell-redirect.js +25 -0
  530. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/wheels.js +4 -3
  531. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/active.js +1 -1
  532. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/client.d.ts +1 -0
  533. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/client.js +6 -3
  534. package/dist-lib/plugins/python/worker/entry.d.ts +1 -0
  535. package/dist-lib/plugins/python/worker/entry.js +9 -0
  536. package/dist-lib/plugins/python/worker/interrupt-deadline.d.ts +1 -0
  537. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/interrupt-deadline.js +1 -1
  538. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/serve.js +2 -2
  539. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/spawn.d.ts +1 -0
  540. package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/spawn.js +7 -0
  541. package/dist-lib/plugins/quickjs/index.d.ts +20 -0
  542. package/dist-lib/plugins/quickjs/index.js +25 -0
  543. package/dist-lib/plugins/quickjs/language.d.ts +3 -0
  544. package/dist-lib/plugins/quickjs/language.js +59 -0
  545. package/dist-lib/plugins/quickjs/runtime.d.ts +38 -0
  546. package/dist-lib/plugins/quickjs/runtime.js +421 -0
  547. package/dist-lib/plugins/quickjs/text-decoder.d.ts +1 -0
  548. package/dist-lib/plugins/quickjs/text-decoder.js +15 -0
  549. package/dist-lib/plugins/run-report/brand.d.ts +1 -0
  550. package/dist-lib/plugins/run-report/brand.js +1 -0
  551. package/dist-lib/plugins/run-report/flow-view.d.ts +6 -0
  552. package/dist-lib/plugins/run-report/flow-view.js +53 -0
  553. package/dist-lib/plugins/run-report/flow.d.ts +33 -0
  554. package/dist-lib/plugins/run-report/flow.js +201 -0
  555. package/dist-lib/plugins/run-report/index.d.ts +17 -0
  556. package/dist-lib/plugins/run-report/index.js +27 -0
  557. package/dist-lib/plugins/run-report/layout.d.ts +39 -0
  558. package/dist-lib/plugins/run-report/layout.js +175 -0
  559. package/dist-lib/plugins/run-report/meaning.d.ts +6 -0
  560. package/dist-lib/plugins/run-report/meaning.js +43 -0
  561. package/dist-lib/plugins/run-report/model.d.ts +86 -0
  562. package/dist-lib/plugins/run-report/model.js +387 -0
  563. package/dist-lib/plugins/run-report/page.d.ts +13 -0
  564. package/dist-lib/plugins/run-report/page.js +234 -0
  565. package/dist-lib/plugins/run-report/script.d.ts +1 -0
  566. package/dist-lib/plugins/run-report/script.js +661 -0
  567. package/dist-lib/plugins/run-report/story.d.ts +48 -0
  568. package/dist-lib/plugins/run-report/story.js +188 -0
  569. package/dist-lib/plugins/run-report/style.d.ts +1 -0
  570. package/dist-lib/plugins/run-report/style.js +410 -0
  571. package/dist-lib/plugins/run-report/why.d.ts +28 -0
  572. package/dist-lib/plugins/run-report/why.js +170 -0
  573. package/dist-lib/plugins/sandbox-macos/index.d.ts +48 -0
  574. package/dist-lib/plugins/sandbox-macos/index.js +175 -0
  575. package/dist-lib/plugins/sandbox-vm/index.d.ts +24 -0
  576. package/dist-lib/plugins/sandbox-vm/index.js +27 -0
  577. package/dist-lib/plugins/sandbox-vm/vm-shell.d.ts +46 -0
  578. package/dist-lib/plugins/sandbox-vm/vm-shell.js +106 -0
  579. package/dist-lib/{lib → plugins/speech}/audio-transcode-bare.js +2 -2
  580. package/dist-lib/plugins/speech/index.d.ts +17 -0
  581. package/dist-lib/plugins/speech/index.js +24 -0
  582. package/dist-lib/plugins/speech/speech-engine.d.ts +23 -0
  583. package/dist-lib/plugins/speech/speech-engine.js +55 -0
  584. package/dist-lib/plugins/speech/speech-runtime.d.ts +22 -0
  585. package/dist-lib/plugins/speech/speech-runtime.js +212 -0
  586. package/dist-lib/{lib/capabilities → plugins/speech}/speech-text.d.ts +1 -0
  587. package/dist-lib/{lib/capabilities → plugins/speech}/speech-text.js +10 -3
  588. package/dist-lib/plugins/speech/voice-lane.d.ts +2 -0
  589. package/dist-lib/plugins/speech/voice-lane.js +9 -0
  590. package/dist-lib/plugins/speech/voice.d.ts +17 -0
  591. package/dist-lib/{lib/capabilities → plugins/speech}/voice.js +27 -25
  592. package/dist-lib/plugins/translation/index.d.ts +22 -0
  593. package/dist-lib/plugins/translation/index.js +63 -0
  594. package/dist-lib/{lib/models → plugins/translation}/nmt-catalog.d.ts +0 -1
  595. package/dist-lib/{lib/models → plugins/translation}/nmt-catalog.js +0 -3
  596. package/dist-lib/{lib/tools → plugins/translation}/translate.d.ts +14 -6
  597. package/dist-lib/{lib/tools → plugins/translation}/translate.js +14 -8
  598. package/dist-lib/plugins/walkie-talkie/crew.d.ts +27 -0
  599. package/dist-lib/plugins/walkie-talkie/crew.js +103 -0
  600. package/dist-lib/plugins/walkie-talkie/index.d.ts +127 -0
  601. package/dist-lib/plugins/walkie-talkie/index.js +340 -0
  602. package/dist-lib/plugins/walkie-talkie/wire.d.ts +67 -0
  603. package/dist-lib/plugins/walkie-talkie/wire.js +136 -0
  604. package/dist-lib/plugins/weather/geocode.d.ts +25 -0
  605. package/dist-lib/plugins/weather/geocode.js +101 -0
  606. package/dist-lib/plugins/weather/index.d.ts +15 -0
  607. package/dist-lib/plugins/weather/index.js +17 -0
  608. package/dist-lib/plugins/weather/lookup.d.ts +6 -0
  609. package/dist-lib/plugins/weather/lookup.js +169 -0
  610. package/dist-lib/{lib/tools/weather-lookup → plugins/weather}/place.js +5 -1
  611. package/dist-lib/plugins/web-search/engine-registry.d.ts +44 -0
  612. package/dist-lib/plugins/web-search/engine-registry.js +17 -0
  613. package/dist-lib/{lib → plugins}/web-search/engines/aol.d.ts +1 -0
  614. package/dist-lib/{lib → plugins}/web-search/engines/aol.js +5 -3
  615. package/dist-lib/{lib → plugins}/web-search/engines/bing.d.ts +1 -0
  616. package/dist-lib/{lib → plugins}/web-search/engines/bing.js +9 -4
  617. package/dist-lib/{lib → plugins}/web-search/engines/brave.d.ts +1 -0
  618. package/dist-lib/{lib → plugins}/web-search/engines/brave.js +5 -3
  619. package/dist-lib/{lib → plugins}/web-search/engines/duckduckgo.d.ts +1 -0
  620. package/dist-lib/{lib → plugins}/web-search/engines/duckduckgo.js +5 -2
  621. package/dist-lib/{lib → plugins}/web-search/engines/google.d.ts +1 -0
  622. package/dist-lib/{lib → plugins}/web-search/engines/google.js +6 -4
  623. package/dist-lib/{lib → plugins}/web-search/engines/wikipedia.d.ts +1 -0
  624. package/dist-lib/{lib → plugins}/web-search/engines/wikipedia.js +5 -3
  625. package/dist-lib/{lib → plugins}/web-search/engines/yahoo.d.ts +1 -0
  626. package/dist-lib/{lib → plugins}/web-search/engines/yahoo.js +5 -3
  627. package/dist-lib/{lib → plugins}/web-search/fetch-html.js +1 -1
  628. package/dist-lib/plugins/web-search/index.d.ts +18 -0
  629. package/dist-lib/plugins/web-search/index.js +33 -0
  630. package/dist-lib/{lib → plugins}/web-search/orchestrator.d.ts +3 -1
  631. package/dist-lib/{lib → plugins}/web-search/orchestrator.js +5 -5
  632. package/dist-lib/plugins/web-search/tool.d.ts +3 -0
  633. package/dist-lib/{lib/tools/web-search.js → plugins/web-search/tool.js} +18 -14
  634. package/dist-lib/plugins/web-search/types.js +1 -0
  635. package/dist-lib/schema/generate.js +5 -2
  636. package/dist-lib/schema/harness.js +158 -7
  637. package/dist-lib/spec/bind.js +20 -4
  638. package/dist-lib/spec/calls.js +4 -0
  639. package/dist-lib/spec/hrpc/hrpc.json +52 -0
  640. package/dist-lib/spec/hrpc/index.js +51 -3
  641. package/dist-lib/spec/hrpc/messages.js +595 -17
  642. package/dist-lib/spec/hyperschema/index.js +595 -17
  643. package/dist-lib/spec/hyperschema/schema.json +464 -1
  644. package/dist-lib/spec/hyperschema/types.d.ts +113 -2
  645. package/package.json +261 -484
  646. package/patches/{@qvac%2Finference@0.20.0.patch → @qvac%2Finference@0.21.0.patch} +8 -8
  647. package/scripts/addon-externals.cjs +386 -0
  648. package/scripts/addon-externals.d.ts +30 -0
  649. package/wheels/manifest.json +1 -160
  650. package/worker/harness-sidecar.mjs +80 -59
  651. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.d.ts +0 -3
  652. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.js +0 -75
  653. package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.d.ts +0 -9
  654. package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.js +0 -11
  655. package/dist-lib/lib/capabilities/completion-engine/actors/preloading.d.ts +0 -3
  656. package/dist-lib/lib/capabilities/completion-engine/actors/preloading.js +0 -114
  657. package/dist-lib/lib/capabilities/completion-loop/index.d.ts +0 -80
  658. package/dist-lib/lib/capabilities/completion-loop/index.js +0 -158
  659. package/dist-lib/lib/capabilities/completion-loop/metrics.d.ts +0 -5
  660. package/dist-lib/lib/capabilities/completion-loop/metrics.js +0 -29
  661. package/dist-lib/lib/capabilities/completion-loop/tool-execution.d.ts +0 -60
  662. package/dist-lib/lib/capabilities/completion-loop/turns.js +0 -112
  663. package/dist-lib/lib/capabilities/completion-runtime.d.ts +0 -46
  664. package/dist-lib/lib/capabilities/completion.d.ts +0 -18
  665. package/dist-lib/lib/capabilities/completion.js +0 -22
  666. package/dist-lib/lib/helpers/recovery-required.d.ts +0 -1
  667. package/dist-lib/lib/helpers/recovery-required.js +0 -1
  668. package/dist-lib/lib/hooks/built-in/index.d.ts +0 -4
  669. package/dist-lib/lib/hooks/built-in/index.js +0 -4
  670. package/dist-lib/lib/hooks/pipeline.d.ts +0 -24
  671. package/dist-lib/lib/hooks/pipeline.js +0 -74
  672. package/dist-lib/lib/hooks/registry.d.ts +0 -2
  673. package/dist-lib/lib/hooks/registry.js +0 -7
  674. package/dist-lib/lib/machine/completion/actions/skills.d.ts +0 -9
  675. package/dist-lib/lib/machine/completion/actions/skills.js +0 -83
  676. package/dist-lib/lib/machine/engine.d.ts +0 -93
  677. package/dist-lib/lib/machine/guards.d.ts +0 -2
  678. package/dist-lib/lib/machine/guards.js +0 -6
  679. package/dist-lib/lib/office/pptx.d.ts +0 -1
  680. package/dist-lib/lib/office/pptx.js +0 -26
  681. package/dist-lib/lib/office/python.d.ts +0 -8
  682. package/dist-lib/lib/office/python.js +0 -32
  683. package/dist-lib/lib/office/xlsx.d.ts +0 -1
  684. package/dist-lib/lib/office/xlsx.js +0 -26
  685. package/dist-lib/lib/run-log-inspect.d.ts +0 -25
  686. package/dist-lib/lib/run-log-protocol.d.ts +0 -2
  687. package/dist-lib/lib/run-log-protocol.js +0 -1
  688. package/dist-lib/lib/tool-call-display.d.ts +0 -1
  689. package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +0 -31
  690. package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +0 -7
  691. package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +0 -318
  692. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +0 -89
  693. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +0 -1371
  694. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +0 -3
  695. package/dist-lib/lib/tools/exec/obsidian/route.d.ts +0 -17
  696. package/dist-lib/lib/tools/exec/obsidian/route.js +0 -91
  697. package/dist-lib/lib/tools/mcp-call.d.ts +0 -14
  698. package/dist-lib/lib/tools/rag-search.d.ts +0 -2
  699. package/dist-lib/lib/tools/rag-search.js +0 -105
  700. package/dist-lib/lib/tools/weather-lookup.d.ts +0 -8
  701. package/dist-lib/lib/tools/weather-lookup.js +0 -122
  702. package/dist-lib/lib/tools/web-search.d.ts +0 -6
  703. package/dist-lib/lib/web-search/engine-registry.d.ts +0 -7
  704. package/dist-lib/lib/web-search/engine-registry.js +0 -17
  705. package/wheels/cffi-2.0.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl +0 -0
  706. package/wheels/cryptography-47.0.0-cp314-abi3-pyemscripten_2026_0_wasm32.whl +0 -0
  707. package/wheels/defusedxml-0.7.1-py2.py3-none-any.whl +0 -0
  708. package/wheels/et_xmlfile-2.0.0-py3-none-any.whl +0 -0
  709. package/wheels/fonttools-4.62.1-py3-none-any.whl +0 -0
  710. package/wheels/fpdf2-2.8.8-py3-none-any.whl +0 -0
  711. package/wheels/lxml-6.0.2-cp314-cp314-pyemscripten_2026_0_wasm32.whl +0 -0
  712. package/wheels/openpyxl-3.1.5-py2.py3-none-any.whl +0 -0
  713. package/wheels/pillow-12.2.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl +0 -0
  714. package/wheels/pycparser-3.0-py3-none-any.whl +0 -0
  715. package/wheels/pypdf-6.15.0-py3-none-any.whl +0 -0
  716. package/wheels/python_docx-1.2.0-py3-none-any.whl +0 -0
  717. package/wheels/python_pptx-1.0.2-py3-none-any.whl +0 -0
  718. package/wheels/six-1.17.0-py2.py3-none-any.whl +0 -0
  719. package/wheels/typing_extensions-4.15.0-py3-none-any.whl +0 -0
  720. package/wheels/xlsxwriter-3.2.9-py3-none-any.whl +0 -0
  721. /package/dist-lib/lib/{tools/skills → agent}/tool-grants.d.ts +0 -0
  722. /package/dist-lib/lib/{tools/skills → agent}/tool-grants.js +0 -0
  723. /package/dist-lib/lib/capabilities/{types.js → completion-engine/prepare-step.js} +0 -0
  724. /package/dist-lib/lib/{hooks/types.js → capabilities/completion-engine/stages.js} +0 -0
  725. /package/dist-lib/lib/{tool-call-display.js → contract/agent.js} +0 -0
  726. /package/dist-lib/lib/{tools/exec/adapters/adapter.js → contract/completion.js} +0 -0
  727. /package/dist-lib/lib/{tools/exec/adapters/python/worker/entry.d.ts → contract/exec.js} +0 -0
  728. /package/dist-lib/lib/{tools/exec/adapters/python/worker/interrupt-deadline.d.ts → contract/hooks.js} +0 -0
  729. /package/dist-lib/lib/{web-search/types.js → contract/index.js} +0 -0
  730. /package/dist-lib/lib/{capabilities/completion-engine → helpers}/abort-polyfill.d.ts +0 -0
  731. /package/dist-lib/lib/{capabilities/completion-engine → helpers}/abort-polyfill.js +0 -0
  732. /package/dist-lib/lib/{web-search → helpers}/html-helpers.d.ts +0 -0
  733. /package/dist-lib/lib/{web-search → helpers}/html-helpers.js +0 -0
  734. /package/dist-lib/lib/{tools → helpers}/model-args.d.ts +0 -0
  735. /package/dist-lib/lib/{tools → helpers}/model-args.js +0 -0
  736. /package/dist-lib/lib/{machine → helpers}/stable-stringify.d.ts +0 -0
  737. /package/dist-lib/lib/{web-search → helpers}/user-agents.d.ts +0 -0
  738. /package/dist-lib/lib/{web-search → helpers}/user-agents.js +0 -0
  739. /package/dist-lib/lib/{harness-lifecycle.d.ts → lifecycle/machine.d.ts} +0 -0
  740. /package/dist-lib/lib/tools/{exec/adapters/python → attachments}/output-policy.js +0 -0
  741. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/command.d.ts +0 -0
  742. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/note-name.d.ts +0 -0
  743. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/note-name.js +0 -0
  744. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/output.d.ts +0 -0
  745. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/output.js +0 -0
  746. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/safe-path.d.ts +0 -0
  747. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/safe-path.js +0 -0
  748. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-create.d.ts +0 -0
  749. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-create.js +0 -0
  750. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-fs.d.ts +0 -0
  751. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-fs.js +0 -0
  752. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-paths.d.ts +0 -0
  753. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-paths.js +0 -0
  754. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-read.d.ts +0 -0
  755. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-read.js +0 -0
  756. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-write.d.ts +0 -0
  757. /package/dist-lib/{lib/tools/exec → plugins}/obsidian/vault-write.js +0 -0
  758. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/deadline-state.d.ts +0 -0
  759. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/deadline-state.js +0 -0
  760. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/distributions.d.ts +0 -0
  761. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/distributions.js +0 -0
  762. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/interrupt-timer.d.ts +0 -0
  763. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/memfs.d.ts +0 -0
  764. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/module-distributions.d.ts +0 -0
  765. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/named-hosts.d.ts +0 -0
  766. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/named-hosts.js +0 -0
  767. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/net-shim.d.ts +0 -0
  768. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/net-shim.js +0 -0
  769. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/pyodide.d.ts +0 -0
  770. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/wheels.d.ts +0 -0
  771. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/active.d.ts +0 -0
  772. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/protocol.d.ts +0 -0
  773. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/protocol.js +0 -0
  774. /package/dist-lib/{lib/tools/exec/adapters → plugins}/python/worker/serve.d.ts +0 -0
  775. /package/dist-lib/{lib/capabilities → plugins/speech}/audio-resample.d.ts +0 -0
  776. /package/dist-lib/{lib/capabilities → plugins/speech}/audio-resample.js +0 -0
  777. /package/dist-lib/{lib → plugins/speech}/audio-transcode-bare.d.ts +0 -0
  778. /package/dist-lib/{lib → plugins/speech}/audio-transcode-node.d.ts +0 -0
  779. /package/dist-lib/{lib → plugins/speech}/audio-transcode-node.js +0 -0
  780. /package/dist-lib/{lib/capabilities → plugins/speech}/speech-lexicon.d.ts +0 -0
  781. /package/dist-lib/{lib/capabilities → plugins/speech}/speech-lexicon.js +0 -0
  782. /package/dist-lib/{lib → plugins/speech}/wav-encode.d.ts +0 -0
  783. /package/dist-lib/{lib → plugins/speech}/wav-encode.js +0 -0
  784. /package/dist-lib/{lib/tools/weather-lookup → plugins/weather}/place.d.ts +0 -0
  785. /package/dist-lib/{lib/tools/weather-lookup → plugins/weather}/report.d.ts +0 -0
  786. /package/dist-lib/{lib/tools/weather-lookup → plugins/weather}/report.js +0 -0
  787. /package/dist-lib/{lib → plugins}/web-search/fetch-html.d.ts +0 -0
  788. /package/dist-lib/{lib → plugins}/web-search/format-results.d.ts +0 -0
  789. /package/dist-lib/{lib → plugins}/web-search/format-results.js +0 -0
  790. /package/dist-lib/{lib → plugins}/web-search/merge-results.d.ts +0 -0
  791. /package/dist-lib/{lib → plugins}/web-search/merge-results.js +0 -0
  792. /package/dist-lib/{lib → plugins}/web-search/types.d.ts +0 -0
  793. /package/dist-lib/{lib → plugins}/web-search/url-helpers.d.ts +0 -0
  794. /package/dist-lib/{lib → plugins}/web-search/url-helpers.js +0 -0
  795. /package/dist-lib/{lib → plugins}/web-search/url-normalize.d.ts +0 -0
  796. /package/dist-lib/{lib → plugins}/web-search/url-normalize.js +0 -0
package/dist-lib/index.js CHANGED
@@ -4,69 +4,49 @@ import process from 'process';
4
4
  import ReadyResource from 'ready-resource';
5
5
  import { probeGpuStats } from './lib/hardware/gpu-probe.js';
6
6
  import { probeCapabilityProfile } from './lib/hardware/capability-probe.js';
7
- import { closePythonWorker } from './lib/tools/exec/adapters/python/worker/active.js';
8
- import { trackCompletion } from './lib/completion-lifecycle.js';
9
- import { createHarnessLifecycle } from './lib/harness-lifecycle.js';
10
- import { didDrainTimeOut, raceDrain } from './lib/machine/index.js';
11
- import { completion, imageSettingsFrom } from './lib/capabilities/completion.js';
7
+ import { Lifecycle } from './lib/lifecycle/index.js';
8
+ import { didDrainTimeOut, raceDrain } from './lib/helpers/drain.js';
9
+ import { CompletionEngine } from './lib/capabilities/completion-engine/index.js';
10
+ import { imageSettingsFrom } from './lib/helpers/image-settings.js';
12
11
  import { detectLanguage } from './lib/capabilities/detect-language.js';
13
12
  import { invoke } from './lib/capabilities/invoke.js';
14
13
  import { previewModelSource } from './lib/capabilities/preview-model-source.js';
15
14
  import { expandImagePrompt } from './lib/capabilities/enhance.js';
16
- import { cleanAnswer } from './lib/helpers/clean-answer.js';
17
- import { isTranslationModel } from './lib/models/nmt-catalog.js';
18
- import { createTranslateTool, createTranslationRuntime } from './lib/tools/translate.js';
19
15
  import { download } from './lib/capabilities/download.js';
20
- import { createEmbedLane } from './lib/capabilities/embed.js';
16
+ import { Embeddings } from './lib/embeddings/index.js';
21
17
  import { deleteAllKvCaches, deleteKvCacheKey } from './lib/capabilities/kv-cache.js';
22
- import { pcmForTranscription } from './lib/capabilities/audio-resample.js';
23
- import { buildWavBuffer } from './lib/wav-encode.js';
24
- import { createVoiceLane, packSamples, speakOnce, speakStreamOnce, transcribeOnce, transcribeStreaming, SUPERTONIC_SAMPLE_RATE } from './lib/capabilities/voice.js';
25
18
  import { pushQueue } from './lib/queue.js';
26
- import { AbortedError, raceAbort } from './lib/helpers/race-abort.js';
27
- import { audioGenDownloadMetadata, customProjectionMap, defaultProjectionMap, defaultTtsFor, defaultVoiceModel, diffusionDownloadMetadata, curatedModelAsset, infraModelsFor, modelAddonOf, modelNameToCapabilityProfile, musicModelSet, residentSrc, setCustomModels } from './lib/models/model-catalog.js';
28
- import { createModelStatusCache, customModelRows, invalidateModelStatusCache, mergeCustomRows, listModels } from './lib/models/model-list.js';
19
+ import { AbortedError } from './lib/helpers/race-abort.js';
20
+ import { audioGenDownloadMetadata, categoryDownloadMetadata, customProjectionMap, defaultProjectionMap, defaultVoiceModel, diffusionDownloadMetadata, infraModelsFor, modelNameToCapabilityProfile, residentSrc, setCustomModels } from './lib/models/model-catalog.js';
21
+ import { customModelRows, mergeCustomRows, listModels } from './lib/models/model-list.js';
29
22
  import { deleteModelFiles, summarizeDelete } from './lib/models/model-delete.js';
30
- import { createEmbedPool, createLoadTracker, createModelPool, createVoicePool, ModelUnloadError, awaitModelCapacity, evictIdle, evictIdleWhere, evictModel, evictModelWithin, isResident, leaseResidentModel, leaseCount, loadedModels, loadingModels, settledModels, modelKey, modelOf, releaseModel, resolveCtxSize, resolveLoadOptions, progressState } from './lib/models/model-pool.js';
31
- import { defaultContextSize } from './lib/models/context.js';
32
- import { resolveMainGpu } from './lib/models/gpu-selection.js';
33
- import { createIdleReaper } from './lib/models/idle-unload.js';
23
+ import { createLoadTracker, createVoicePool, evictIdle, evictIdleWhere, isResident, leaseResidentModel, loadedModels, releaseModel, progressState } from './lib/models/model-pool.js';
34
24
  import { openclCacheDir } from './lib/models/opencl-cache.js';
35
- import { assertEmbedDevice, createEmbedConfig } from './lib/models/embed-config.js';
36
- import { createGpuFaultState, isSdkGpuDeviceLostError, isSdkModelWedgedError } from './lib/models/sdk-faults.js';
25
+ import { isSdkModelWedgedError } from './lib/models/sdk-faults.js';
37
26
  import { createSdkLoader } from './lib/sdk-loader.js';
38
- import { installAbortControllerPolyfill } from './lib/capabilities/completion-engine/abort-polyfill.js';
39
- import { prepareCompletionRuntime } from './lib/capabilities/completion-runtime.js';
40
- import { createEditImageTool } from './lib/tools/edit-image.js';
27
+ import { installAbortControllerPolyfill } from './lib/helpers/abort-polyfill.js';
28
+ import { Residency } from './lib/residency/index.js';
41
29
  import { toolCatalog } from './lib/tools/catalog.js';
42
- import { createDiffusionRuntime, createGenerateImageTool } from './lib/tools/generate-image.js';
43
- import { createGenerateMusicTool, createMusicRuntime } from './lib/tools/generate-music.js';
44
- import { availableSkills, detectPlatform, loadSkillCatalog, resolveSkillStatuses, skillSupportsPlatform, versionProbeSkills } from './lib/tools/skills/catalog.js';
45
- import { ensureBundledSkillsDir } from './lib/tools/skills/bundled-dir.js';
46
- import { ensureSkillsOverlayDir } from './lib/tools/skills/overlay-dir.js';
47
- import { copyBaseForEdit, deleteOverlaySkill, listManagedSkills, readSkillFile, writeSkillFile } from './lib/tools/skills/overlay-crud.js';
48
- import { watchSkillsOverlay } from './lib/tools/skills/overlay-watch.js';
30
+ import { SkillsHost } from './lib/skills-host/index.js';
49
31
  import { errorMessage, isRecord } from './lib/guards.js';
50
32
  import { redactedRecoveryFields } from './lib/wire.js';
51
33
  import { hlog } from './lib/log.js';
52
34
  import { installResolutionDetector, resolutionDetail } from './lib/resolution-detector.js';
53
- import { probeBinVersions } from './lib/tools/skills/bin-check.js';
54
35
  import { bareRuntime } from './lib/tools/exec/bare-runtime.js';
55
36
  import { runCommand } from './lib/tools/exec/runner.js';
56
37
  import { createLocalRoots } from './lib/tools/fs/local.js';
57
38
  import { createRemoteRoots } from './lib/tools/fs/remote.js';
58
- import { resetCredentialHealth as resetCredentialHealthAfterSnapshot } from './lib/tools/skills/credential-health.js';
59
- import { isDeviceSharedCredentialKey, scopeKey } from './lib/tools/skills/scope-key.js';
60
- import { settingsScopeKey } from './lib/tools/skills/skill-settings.js';
61
- export * from './lib/capabilities/completion.js';
39
+ export { CompletionEngine } from './lib/capabilities/completion-engine/index.js';
40
+ export const CONTEXT_OVERFLOW_MESSAGE = CompletionEngine.CONTEXT_OVERFLOW_MESSAGE;
41
+ export { imageSettingsFrom } from './lib/helpers/image-settings.js';
42
+ export { skillInContext, unreadySkillState } from './lib/capabilities/skill-entry.js';
43
+ export { toSdkTool } from './lib/capabilities/sdk-tool.js';
62
44
  export { attachmentTurn, loadedSkillsFrom, skillLoadedTurn } from './lib/capabilities/tool-turns.js';
63
45
  export { CAPABILITIES, isCapability } from './lib/capabilities/invoke.js';
64
- export { EURONANO_LANGUAGES, NMT_FROM_ENGLISH, NMT_TO_ENGLISH, SLM_LANGUAGE_CODES, SLM_LANGUAGE_NAMES, translationPlanFor } from './lib/models/nmt-catalog.js';
65
46
  export * from './lib/capabilities/download.js';
66
47
  export * from './lib/models/model-catalog.js';
67
48
  export * from './lib/models/model-list.js';
68
49
  export { harnessChild, spawnHarness } from './lib/spawn.js';
69
- export { settingsDimension, settingsSteps } from './lib/tools/generate-image.js';
70
50
  export * from './lib/tools/skills/catalog.js';
71
51
  export { requiredSettings, settingEnvName } from './lib/tools/skills/skill-settings.js';
72
52
  export { TOOLSETS, toolsetEnabled } from './lib/tools/toolsets.js';
@@ -76,455 +56,337 @@ export { isAvailableState, SKILL_STATE } from './lib/tools/skills/skill-state.js
76
56
  export { connectHarness, HARNESS_DIED, RemoteHarness } from './lib/connect.js';
77
57
  export { serveHarness } from './lib/serve.js';
78
58
  export { hlog, setHarnessLog, setHarnessLogSink } from './lib/log.js';
79
- export { harnessHooks } from './lib/hooks/registry.js';
80
- export { EgressGuardHook, SkillCatalogGuardHook } from './lib/hooks/built-in/index.js';
81
- const BIN_VERSION_PROBE_TTL_MS = 45_000;
59
+ import { HookPipeline } from './lib/hooks/index.js';
60
+ import { Agent } from './lib/agent/index.js';
61
+ export { HookPipeline };
62
+ import { createGuardedFetch } from './lib/guarded-fetch.js';
63
+ import { PluginRegistry } from './lib/plugins/index.js';
64
+ import { createExecTool } from './lib/tools/exec.js';
65
+ import { deniedRootsFor } from './lib/tools/fs/scope.js';
66
+ export const PLUGIN_API_VERSION = PluginRegistry.API_VERSION;
82
67
  const SUSPEND_SETTLE_MS = 500;
83
- const TRANSCRIBE_STREAM_MIN_BYTES = 16_000 * 2 * 60;
84
- const TRANSCRIPTION_MODEL_LABEL = 'transcription model';
85
- const DIFFUSION_EVICT_WAIT_MS = 15_000;
86
- const MUSIC_EVICT_WAIT_MS = 15_000;
87
- const WEDGED_EVICT_WAIT_MS = 10_000;
88
- const MODEL_ROOM_WAIT_MS = 300_000;
89
- const WARM_ROOM_WAIT_MS = 2_000;
90
- const UNLOAD_LEASE_WAIT_MS = 10_000;
91
- const DEFAULT_COMPLETION_MODEL_CAP = 1;
92
- const WEDGED_EVICT_LEASED_MS = 120_000;
93
- const TTS_MODEL_CONFIG = {
94
- ttsEngine: 'supertonic',
95
- language: 'en',
96
- ttsSpeed: 1.175,
97
- ttsNumInferenceSteps: 5
98
- };
68
+ const SPEECH_PLUGIN_MISSING = 'speech needs the speech plugin';
69
+ const KNOWLEDGE_PLUGIN_MISSING = 'knowledge needs the knowledge plugin';
70
+ function execOptions(exec) {
71
+ if (!exec)
72
+ return null;
73
+ return exec === true ? {} : exec;
74
+ }
99
75
  export class Harness extends ReadyResource {
76
+ _hostTools;
100
77
  _tools;
78
+ _capabilities = [];
101
79
  _sdk;
102
80
  _loads = createLoadTracker();
103
- _pinned = new Set();
104
- _replying = [];
105
- _modelStatus = createModelStatusCache();
106
- _models;
107
- _embedModels;
108
- _retiredEmbedModels;
109
- _faultedEmbedKeys = new WeakMap();
110
- _embedLane = createEmbedLane();
111
- _embedFaults;
112
- _embedGpuLayers;
113
- _embedBatchSize;
114
- _embedControl;
115
- _ttsModels;
116
- _transcriptionModels;
117
- _voiceLane = createVoiceLane();
118
- _lifecycle = createHarnessLifecycle({
119
- suspend: () => this._suspendRuntimes(),
120
- resume: () => this._resumeRuntimes()
121
- });
122
- _detachedRuns = new Set();
123
- _effectDrainWaiters = new Set();
124
- _activeWork = 0;
125
- _workDrainWaiters = new Set();
126
- _runtimeDraining = false;
127
- _runtimeUnloadFailed = false;
128
- _poolUnloadFailed = false;
129
- _poolCleanupFailed = false;
130
- _failedModelUnloads = new Set();
131
- _sdkClosed = false;
132
- _runtimesReleased = false;
81
+ _residency;
82
+ _embeddings;
83
+ _voicePools = new Map();
84
+ _skills;
85
+ _lifecycle;
133
86
  _closeRetryNeeded = false;
134
- _closeRequested = false;
135
- _skillsDir;
136
87
  _modelsDir;
137
- _overlayWatcher = null;
138
- _supportedSkills;
88
+ _skillsDir;
89
+ _exec;
90
+ _deniedRoots;
139
91
  _projectionModel;
140
92
  _customProjection = {};
141
- _llmDevice;
142
- _llmGpuLayers;
143
- _contextSize;
144
- _kvCacheK;
145
- _kvCacheV;
146
- _transcriptionDevice;
147
93
  _gpuStats;
148
- _completionModelCap;
149
- _allSkills;
150
- _credentialStore;
151
- _credentials = new Map();
152
- _settings = new Map();
153
- _platform;
154
- _diffusionSdk;
155
- _imageRuntime;
156
- _musicSdk;
157
- _translationSdk;
158
- _musicRuntime;
159
- _completionRuns;
160
- _translationRuntime;
161
- _capabilityTools;
162
94
  _capability = null;
163
95
  _capabilityInflight = null;
164
- _modelFaults = new Map();
165
- _idle;
166
- constructor({ tools = [], sdkLoader, skillsDir, modelsDir, projectionModel, imageModel, imageClamps, musicModel, musicClamps, llmDevice, llmGpuLayers, contextSize, kvCacheK, kvCacheV, embedDevice, embedGpuLayers, embedBatchSize, transcriptionDevice, completionModelCap, credentialStore, platform, gpuStats } = {}) {
96
+ _hostHooks;
97
+ _hooks;
98
+ _plugins;
99
+ _pluginMode;
100
+ _pluginsStarted = null;
101
+ constructor({ tools = [], sdkLoader, skillsDir, modelsDir, sdkHome, exec, projectionModel, llmDevice, llmGpuLayers, contextSize, kvCacheK, kvCacheV, llmLoad, slots, embedDevice, embedGpuLayers, embedBatchSize, transcriptionDevice, completionModelCap, credentialStore, platform, gpuStats, hooks, plugins = [], pluginMode = 'frozen' } = {}) {
167
102
  super();
103
+ this._exec = execOptions(exec);
104
+ if (this._exec && tools.some((tool) => tool.name === PluginRegistry.EXEC_TOOL)) {
105
+ throw new Error(`tools has '${PluginRegistry.EXEC_TOOL}', which the harness builds when exec is set`);
106
+ }
107
+ this._deniedRoots = sdkHome === undefined ? undefined : deniedRootsFor(sdkHome);
108
+ this._plugins = new PluginRegistry(plugins, {
109
+ services: { models: this._modelHost(transcriptionDevice), embed: this._embedHost() },
110
+ exec: this._exec !== null,
111
+ deniedRoots: this._deniedRoots ?? []
112
+ });
113
+ this._pluginMode = pluginMode;
168
114
  installAbortControllerPolyfill();
115
+ this._hostHooks = Object.freeze([...(hooks ?? HookPipeline.defaults())]);
116
+ this._hooks = this._hostHooks;
169
117
  this._sdk = sdkLoader ?? createSdkLoader();
170
- this._llmDevice = llmDevice;
171
- this._gpuStats = gpuStats;
172
- this._llmGpuLayers = llmGpuLayers;
173
- this._contextSize = contextSize;
174
- this._kvCacheK = kvCacheK;
175
- this._kvCacheV = kvCacheV;
176
- this._transcriptionDevice = transcriptionDevice;
177
- this._completionModelCap = completionModelCap ?? DEFAULT_COMPLETION_MODEL_CAP;
178
- const embedConfig = createEmbedConfig({
179
- device: embedDevice,
180
- gpuLayers: embedGpuLayers,
181
- batchSize: embedBatchSize
118
+ this._lifecycle = new Lifecycle({
119
+ resource: this,
120
+ sdk: { peek: () => this._sdk.peek() },
121
+ loads: this._loads,
122
+ releases: {
123
+ pools: () => [
124
+ this._residency.destroy(),
125
+ this._embeddings.destroy(),
126
+ ...[...this._voicePools.values()].map((entry) => entry.pool.destroy())
127
+ ],
128
+ runtimes: () => [],
129
+ plugins: () => this._plugins.unload()
130
+ },
131
+ models: () => loadedModels(this._residency.pool).map((entry) => entry.model),
132
+ recreate: () => {
133
+ this._residency.recreate();
134
+ this._embeddings.recreate();
135
+ for (const entry of this._voicePools.values()) {
136
+ entry.pool = this._createVoicePool(entry.spec);
137
+ }
138
+ },
139
+ statusChanged: () => this._residency.invalidateStatus(),
140
+ teardown: async () => {
141
+ this._skills.close();
142
+ await this._teardownPlugins();
143
+ }
182
144
  });
183
- this._embedGpuLayers = embedConfig.gpuLayers;
184
- this._embedBatchSize = embedConfig.batchSize;
185
- this._retiredEmbedModels = new Set();
186
- this._embedControl = Promise.resolve();
187
- this._embedFaults = createGpuFaultState({
188
- device: embedConfig.device,
189
- gpuLayers: embedConfig.gpuLayers
145
+ this._gpuStats = gpuStats;
146
+ this._hostTools = tools;
147
+ this._tools = tools;
148
+ this._projectionModel = projectionModel ?? defaultProjectionMap();
149
+ this._modelsDir = modelsDir;
150
+ this._skillsDir = skillsDir;
151
+ this._skills = new SkillsHost({
152
+ skillsDir,
153
+ platform,
154
+ credentialStore,
155
+ tools: () => this._tools,
156
+ startPlugins: () => this._startPlugins()
190
157
  });
191
- const imageTransfers = new Map();
192
- const image = typeof imageModel === 'string' ? { model: imageModel } : imageModel;
193
- this._imageRuntime = image
194
- ? createDiffusionRuntime({
195
- ...image,
196
- loads: this._loads,
197
- loadSdk: () => this._loadDiffusionSdk(),
198
- onProgress: (model, progress) => {
199
- const state = progressState(model, progress);
200
- if (state.status === 'downloading' &&
201
- typeof progress.percentage === 'number' &&
202
- progress.percentage < 100) {
203
- imageTransfers.set(model, state);
204
- }
205
- this.emit('model', state.status === 'downloading' && !imageTransfers.has(model)
206
- ? { ...state, status: 'loading' }
207
- : state);
208
- },
209
- onLoaded: (model) => {
210
- const transfer = imageTransfers.get(model);
211
- if (!transfer) {
212
- return;
213
- }
214
- imageTransfers.delete(model);
215
- invalidateModelStatusCache(this._modelStatus);
216
- this.emit('model', { ...transfer, status: 'downloaded' });
217
- },
218
- onBeforeLoad: async (signal) => {
219
- if (this._models.destroyed)
220
- return;
221
- const evicted = await awaitModelCapacity(this._models, {
222
- cap: 1,
223
- deadlineMs: DIFFUSION_EVICT_WAIT_MS,
224
- signal
225
- });
226
- if (signal?.aborted) {
227
- throw new AbortedError();
228
- }
229
- if (!evicted) {
230
- throw new Error('the chat model is busy; try the image again once the current reply finishes');
231
- }
158
+ this._residency = new Residency({
159
+ llmDevice,
160
+ llmGpuLayers,
161
+ contextSize,
162
+ kvCacheK,
163
+ kvCacheV,
164
+ llmLoad,
165
+ slots,
166
+ completionModelCap,
167
+ sdk: { load: () => this._sdk.load() },
168
+ loads: this._loads,
169
+ gate: this._lifecycle,
170
+ emit: (state) => this.emit('model', state),
171
+ projectionFor: (model) => this._projectionFor(model),
172
+ pools: () => [
173
+ ...this._embeddings.pools(),
174
+ ...[...this._voicePools.values()].map((entry) => entry.pool)
175
+ ],
176
+ poolFor: (addon, model) => {
177
+ if (addon === 'embeddings') {
178
+ return this._embeddings.target(model);
232
179
  }
233
- })
234
- : null;
235
- const music = typeof musicModel === 'string' ? (musicModelSet(musicModel) ?? undefined) : musicModel;
236
- this._musicRuntime = music
237
- ? createMusicRuntime({
238
- ...music,
239
- loads: this._loads,
240
- loadSdk: () => this._loadMusicSdk(),
241
- onProgress: (model, progress) => {
242
- const state = progressState(model, progress);
243
- this.emit('model', state);
244
- },
245
- onBeforeLoad: async (signal) => {
246
- if (this._models.destroyed)
247
- return;
248
- const evicted = await awaitModelCapacity(this._models, {
249
- cap: 1,
250
- deadlineMs: MUSIC_EVICT_WAIT_MS,
251
- signal
252
- });
253
- if (signal?.aborted) {
254
- throw new AbortedError();
255
- }
256
- if (!evicted) {
257
- throw new Error('the chat model is busy; try the music again once the current reply finishes');
258
- }
180
+ const entry = this._voicePools.get(addon);
181
+ if (!entry) {
182
+ throw new Error(SPEECH_PLUGIN_MISSING);
259
183
  }
260
- })
261
- : null;
262
- this._translationRuntime = createTranslationRuntime({
263
- loads: this._loads,
264
- loadSdk: () => this._loadTranslationSdk(),
265
- onProgress: (model, progress) => this.emit('model', progressState(model, progress))
184
+ const key = residentSrc(model, addon);
185
+ return {
186
+ pool: entry.pool,
187
+ key,
188
+ needsRoom: entry.spec.needsRoom?.(key) ?? false,
189
+ open: () => entry.pool.open(key, key)
190
+ };
191
+ },
192
+ embedRoom: (model, target) => this._embeddings.makeRoom(model, target),
193
+ evictIdle: () => [
194
+ ...this._embeddings.evictIdle(),
195
+ ...[...this._voicePools.values()].map((entry) => evictIdle(entry.pool))
196
+ ],
197
+ unloadIdlePlugins: () => this._plugins.unloadIdle(),
198
+ tools: () => this._tools,
199
+ skills: (agentId, model) => this._skills.completionSkills(agentId, model)
266
200
  });
267
- this._capabilityTools = [
268
- createTranslateTool(this._translationRuntime, {
269
- slm: (...args) => this._slmTranslate(...args)
270
- })
271
- ];
272
- this._tools = [
273
- ...tools,
274
- ...(this._imageRuntime
275
- ? [
276
- createGenerateImageTool(this._imageRuntime, imageClamps),
277
- createEditImageTool(this._imageRuntime, {}, imageClamps)
278
- ]
279
- : []),
280
- ...(this._musicRuntime ? [createGenerateMusicTool(this._musicRuntime, musicClamps)] : [])
281
- ];
282
- this._projectionModel = projectionModel ?? defaultProjectionMap();
283
- this._skillsDir = skillsDir;
284
- this._modelsDir = modelsDir;
285
- this._supportedSkills = [];
286
- this._allSkills = [];
287
- this._credentialStore = credentialStore;
288
- this._platform = platform;
289
- this._diffusionSdk = null;
290
- this._musicSdk = null;
291
- this._completionRuns = new Set();
292
- this._translationSdk = null;
293
- this._models = this._createPool();
294
- this._embedModels = this._createEmbedPool();
295
- this._ttsModels = this._createTtsPool();
296
- this._transcriptionModels = this._createTranscriptionPool();
297
- this._idle = createIdleReaper({
298
- sweep: () => this._unloadIdleModels(),
299
- waitMs: WEDGED_EVICT_WAIT_MS,
300
- onError: (err) => hlog('idle unload failed', { err: errorMessage(err) })
201
+ this._embeddings = new Embeddings({
202
+ device: embedDevice,
203
+ gpuLayers: embedGpuLayers,
204
+ batchSize: embedBatchSize,
205
+ sdk: { loadEmbed: () => this._sdk.loadEmbed() },
206
+ loads: this._loads,
207
+ gate: this._lifecycle,
208
+ notify: (state) => this._residency.notify(state),
209
+ settleFit: (query) => this._residency.fit.settle(query),
210
+ evictIdleChat: () => this._residency.evictIdleChat()
301
211
  });
302
212
  }
303
213
  async _open() {
304
214
  try {
305
215
  installResolutionDetector(import.meta);
306
- await this._reloadSkills();
307
- await this._startOverlayWatch();
308
- hlog('open', { skills: this._supportedSkills.length, tools: this._tools.length });
216
+ await this._startPlugins();
217
+ await this._loadAddons();
218
+ await this._skills.open();
219
+ hlog('open', { skills: this._skills.names.length, tools: this._tools.length });
309
220
  }
310
221
  catch (error) {
222
+ await this._teardownPlugins();
311
223
  throw error;
312
224
  }
313
225
  }
226
+ _startPlugins() {
227
+ this._pluginsStarted ??= this._runPluginStart();
228
+ return this._pluginsStarted;
229
+ }
230
+ async _runPluginStart() {
231
+ const reserved = this._hostTools.map((tool) => tool.name);
232
+ if (this._exec) {
233
+ reserved.push(PluginRegistry.EXEC_TOOL);
234
+ }
235
+ const started = await this._plugins.start([...reserved, Agent.TRANSFER_TOOL_NAME, Agent.DELEGATE_TOOL_NAME], {
236
+ fetch: (signal, mayConnect) => createGuardedFetch({ signal, mayConnect }),
237
+ publish: (swapped) => this._publishPlugins(swapped)
238
+ });
239
+ this._publishPlugins(started);
240
+ }
241
+ _publishPlugins({ tools, capabilities, hooks, skills, exec }) {
242
+ const pre = hooks.filter((hook) => hook.phase === 'preToolCall');
243
+ const rest = hooks.filter((hook) => hook.phase !== 'preToolCall');
244
+ this._tools = Object.freeze([...this._hostTools, ...this._execTools(exec), ...tools]);
245
+ this._capabilities = Object.freeze(capabilities);
246
+ this._hooks = Object.freeze([...pre, ...this._hostHooks, ...rest]);
247
+ this._skills.publish(skills);
248
+ }
249
+ _execTools(exec) {
250
+ if (!this._exec) {
251
+ return [];
252
+ }
253
+ return [
254
+ createExecTool({
255
+ ...this._exec,
256
+ ...exec,
257
+ deniedRoots: this._deniedRoots,
258
+ skillsDir: this._skillsDir,
259
+ skillSettings: (skill, agentId) => this._skills.skillSettings(skill, agentId)
260
+ })
261
+ ];
262
+ }
263
+ async addPlugin(plugin) {
264
+ await this._dynamicPlugins();
265
+ await this._plugins.add(plugin);
266
+ }
267
+ async removePlugin(name) {
268
+ await this._dynamicPlugins();
269
+ await this._plugins.remove(name);
270
+ }
271
+ async reloadPlugin(name, plugin) {
272
+ await this._dynamicPlugins();
273
+ await this._plugins.reload(name, plugin);
274
+ }
275
+ async _dynamicPlugins() {
276
+ if (this._pluginMode !== 'dynamic') {
277
+ throw new Error("plugins are frozen: construct the harness with pluginMode 'dynamic'");
278
+ }
279
+ if (!this.opened)
280
+ await this.ready();
281
+ this._lifecycle.assertNotClosing();
282
+ }
283
+ _modelHost(transcriptionDevice) {
284
+ return {
285
+ transcriptionDevice,
286
+ sdk: () => this._sdk.load(),
287
+ track: (load, sdk) => this._loads.track(load, sdk),
288
+ makeRoom: (signal, busyMessage) => this._residency.makeRoomForPlugin(signal, busyMessage),
289
+ completionModel: (model, signal) => this._residency.borrow(model, signal),
290
+ emit: (state) => this.emit('model', state),
291
+ progressState,
292
+ statusChanged: () => this._residency.statusChanged(),
293
+ registerPool: (spec) => this._registerPool(spec),
294
+ enterWork: () => {
295
+ if (this._lifecycle.suspended) {
296
+ throw new Error('harness is suspended');
297
+ }
298
+ return this._lifecycle.enterWork();
299
+ }
300
+ };
301
+ }
302
+ _registerPool(spec) {
303
+ const entry = { spec, pool: this._createVoicePool(spec) };
304
+ this._voicePools.set(spec.addon, entry);
305
+ return {
306
+ open: (model) => {
307
+ const pool = entry.pool;
308
+ const handle = pool.open(model, model);
309
+ return {
310
+ load: async () => {
311
+ const { modelId } = await handle.load();
312
+ this._lifecycle.assertNotClosing();
313
+ return { modelId };
314
+ },
315
+ peek: () => handle.peek(),
316
+ release: () => releaseModel(pool, model)
317
+ };
318
+ },
319
+ resident: (model) => isResident(entry.pool, model),
320
+ evictIdle: (wanted) => evictIdleWhere(entry.pool, wanted)
321
+ };
322
+ }
323
+ _createVoicePool({ sdk, label, openclCache, ...spec }) {
324
+ return createVoicePool(() => sdk(), (state) => this._residency.notify(label ? { ...state, model: label } : state), {
325
+ ...spec,
326
+ openclCacheDir: openclCache ? openclCacheDir : undefined,
327
+ loads: this._loads,
328
+ onUnloadFailure: (modelId, error) => this._lifecycle.recordModelUnloadFailure(modelId, error)
329
+ });
330
+ }
331
+ _embedHost() {
332
+ return {
333
+ embed: (request) => this.embed(request),
334
+ sdk: () => this._sdk.loadEmbed()
335
+ };
336
+ }
337
+ async _loadAddons() {
338
+ await Promise.all([
339
+ PluginRegistry.loadAddons('the harness', this._sdk.addons),
340
+ ...this._tools.map((tool) => PluginRegistry.loadAddons(`tool '${tool.name}'`, tool.addons))
341
+ ]);
342
+ }
343
+ _teardownPlugins() {
344
+ return this._plugins.teardown((plugin, error) => hlog('plugin teardown failed', { plugin, err: errorMessage(error) }));
345
+ }
314
346
  get suspended() {
315
347
  return this._lifecycle.suspended;
316
348
  }
317
349
  get skillNames() {
318
- return this._supportedSkills.map((skill) => skill.name);
350
+ return this._skills.names;
319
351
  }
320
352
  setCredentials(entries) {
321
- const previous = this._credentials;
322
- const next = new Map();
323
- for (const { key, token, expiresAt, agentId, skill } of entries) {
324
- if (!token)
325
- continue;
326
- const storeKey = scopeKey({ agentId, skill, key });
327
- const record = typeof expiresAt === 'number' && expiresAt > 0 ? { token, expiresAt } : { token };
328
- const current = previous.get(storeKey);
329
- if (!current || current.token !== record.token || current.expiresAt !== record.expiresAt) {
330
- resetCredentialHealthAfterSnapshot(key, agentId, skill);
331
- }
332
- next.set(storeKey, record);
333
- }
334
- this._credentials = next;
353
+ this._skills.setCredentials(entries);
335
354
  }
336
355
  setSkillSettings(entries) {
337
- const next = new Map();
338
- for (const { skill, key, value, agentId } of entries) {
339
- if (!skill || !key || typeof value !== 'string')
340
- continue;
341
- const scope = settingsScopeKey(skill, agentId);
342
- const bucket = next.get(scope) ?? {};
343
- bucket[key] = value;
344
- next.set(scope, bucket);
345
- }
346
- this._settings = next;
356
+ this._skills.setSkillSettings(entries);
347
357
  }
348
358
  skillSettings(skill, agentId) {
349
- return {
350
- ...this._settings.get(settingsScopeKey(skill, null)),
351
- ...(agentId ? this._settings.get(settingsScopeKey(skill, agentId)) : undefined)
352
- };
359
+ return this._skills.skillSettings(skill, agentId);
353
360
  }
354
- async _baseSkillsDir() {
355
- return this._skillsDir ?? (await ensureBundledSkillsDir());
361
+ listManagedSkills() {
362
+ return this._skills.listManagedSkills();
356
363
  }
357
- async listManagedSkills() {
358
- return listManagedSkills(await this._baseSkillsDir(), await ensureSkillsOverlayDir());
364
+ readSkillFile(name) {
365
+ return this._skills.readSkillFile(name);
359
366
  }
360
- async readSkillFile(name) {
361
- return readSkillFile(await this._baseSkillsDir(), await ensureSkillsOverlayDir(), name);
367
+ writeSkillFile(name, content) {
368
+ return this._skills.writeSkillFile(name, content);
362
369
  }
363
- async writeSkillFile(name, content) {
364
- const overlay = await ensureSkillsOverlayDir();
365
- if (!overlay) {
366
- throw new Error('no writable skills overlay is configured');
367
- }
368
- await writeSkillFile(overlay, name, content);
369
- await this._reloadSkills();
370
- return { ok: true };
371
- }
372
- async copyBaseForEdit(name) {
373
- const overlay = await ensureSkillsOverlayDir();
374
- if (!overlay) {
375
- throw new Error('no writable skills overlay is configured');
376
- }
377
- const result = await copyBaseForEdit(await this._baseSkillsDir(), overlay, name);
378
- if (result.copied) {
379
- await this._reloadSkills();
380
- }
381
- return result;
370
+ copyBaseForEdit(name) {
371
+ return this._skills.copyBaseForEdit(name);
382
372
  }
383
- async deleteOverlaySkill(name) {
384
- const overlay = await ensureSkillsOverlayDir();
385
- if (!overlay) {
386
- throw new Error('no writable skills overlay is configured');
387
- }
388
- const result = await deleteOverlaySkill(overlay, name);
389
- if (result.removed) {
390
- await this._reloadSkills();
391
- }
392
- return result;
373
+ deleteOverlaySkill(name) {
374
+ return this._skills.deleteOverlaySkill(name);
393
375
  }
394
376
  resolveCredential(key, ctx) {
395
- if (this._credentialStore) {
396
- return this._credentialStore(key, ctx);
397
- }
398
- const agentId = ctx?.agentId ?? null;
399
- const deviceShared = isDeviceSharedCredentialKey(key);
400
- for (const skill of ctx?.skills ?? []) {
401
- const owned = this._credentials.get(scopeKey({ agentId, skill, key })) ??
402
- (agentId && deviceShared ? this._credentials.get(scopeKey({ skill, key })) : undefined);
403
- if (owned) {
404
- return owned;
405
- }
406
- }
407
- if (agentId) {
408
- const scoped = this._credentials.get(scopeKey({ agentId, key }));
409
- if (scoped) {
410
- return scoped;
411
- }
412
- }
413
- if (!agentId || deviceShared) {
414
- return this._credentials.get(scopeKey({ key })) ?? null;
415
- }
416
- return null;
417
- }
418
- async _completionSkills(agentId, model) {
419
- const statuses = new Map((await this.skills(agentId, model, { skipCredentialProbe: true, skipBinProbe: true })).map((entry) => [entry.name, entry.status]));
420
- return availableSkills(this._supportedSkills, new Set(this._tools.map((tool) => tool.name)), modelNameToCapabilityProfile(model)).map((entry) => ({
421
- ...entry,
422
- status: statuses.get(entry.name)
423
- }));
377
+ return this._skills.resolveCredential(key, ctx);
424
378
  }
425
379
  async skills(agentId, modelName, options) {
426
380
  if (!this.opened)
427
381
  await this.ready();
428
- this._assertNotClosing();
429
- const platform = this._platform ?? detectPlatform();
430
- const refresh = options?.refresh === true;
431
- return resolveSkillStatuses(this._allSkills, {
432
- installedTools: new Set(this._tools.map((tool) => tool.name)),
433
- credentialStore: (key, ctx) => this.resolveCredential(key, ctx),
434
- settingsStore: (skill, agentId) => this.skillSettings(skill, agentId),
435
- platform,
436
- agentId,
437
- binVersions: options?.skipBinProbe === true
438
- ? (this._binVersionCache?.bySkill ?? new Map())
439
- : await this._probeBinVersions(platform, refresh),
440
- refresh,
441
- skipCredentialProbe: options?.skipCredentialProbe === true,
442
- activeProfile: modelName ? modelNameToCapabilityProfile(modelName) : undefined
443
- });
444
- }
445
- async _reloadSkills() {
446
- const skillsDir = this._skillsDir ?? (await ensureBundledSkillsDir());
447
- this._allSkills = await loadSkillCatalog(skillsDir, { platform: null });
448
- const platform = this._platform ?? detectPlatform();
449
- const supported = this._allSkills.filter((skill) => skillSupportsPlatform(skill, platform));
450
- this._supportedSkills = availableSkills(supported, new Set(this._tools.map((t) => t.name)));
451
- }
452
- async _startOverlayWatch() {
453
- if (this._overlayWatcher)
454
- return;
455
- try {
456
- const overlay = await ensureSkillsOverlayDir();
457
- if (!overlay) {
458
- return;
459
- }
460
- this._overlayWatcher = watchSkillsOverlay(overlay, () => {
461
- this._reloadSkills().catch((err) => hlog('overlay reload failed', { err: errorMessage(err) }));
462
- });
463
- }
464
- catch (err) {
465
- hlog('overlay watch unavailable', { err: errorMessage(err) });
466
- }
382
+ this._lifecycle.assertNotClosing();
383
+ return this._skills.statuses(agentId, modelName, options);
467
384
  }
468
385
  async tools() {
386
+ if (!this.opened)
387
+ await this.ready();
469
388
  return toolCatalog(this._tools);
470
389
  }
471
- _binVersionCache = null;
472
- _binVersionInflight = null;
473
- async _probeBinVersions(platform, refresh = false) {
474
- const now = Date.now();
475
- if (!refresh && this._binVersionCache && this._binVersionCache.expiresAt > now) {
476
- return this._binVersionCache.bySkill;
477
- }
478
- if (this._binVersionInflight) {
479
- return this._binVersionInflight;
480
- }
481
- this._binVersionInflight = this._runBinVersionProbes(platform)
482
- .then((bySkill) => {
483
- this._binVersionCache = {
484
- expiresAt: Date.now() + BIN_VERSION_PROBE_TTL_MS,
485
- bySkill
486
- };
487
- return bySkill;
488
- })
489
- .finally(() => {
490
- this._binVersionInflight = null;
491
- });
492
- return this._binVersionInflight;
493
- }
494
- async _runBinVersionProbes(platform) {
495
- if (process.env.QVAC_NO_SKILL_BIN_PROBE) {
496
- return new Map();
497
- }
498
- const installed = new Set(this._tools.map((tool) => tool.name));
499
- const candidates = versionProbeSkills(this._allSkills, installed, platform);
500
- if (candidates.length === 0) {
501
- return new Map();
502
- }
503
- let runtime;
504
- try {
505
- runtime = await bareRuntime();
506
- }
507
- catch {
508
- return new Map();
509
- }
510
- const run = async (command) => {
511
- try {
512
- const result = await runCommand(command, { ...runtime, timeoutMs: 5_000 });
513
- return result.exitCode === 0 ? result.stdout : null;
514
- }
515
- catch {
516
- return null;
517
- }
518
- };
519
- const bySkill = new Map();
520
- for (const skill of candidates) {
521
- const states = await probeBinVersions(skill.requires, { platform, run });
522
- if (states.size > 0) {
523
- bySkill.set(skill.name, states);
524
- }
525
- }
526
- return bySkill;
527
- }
528
390
  get toolNames() {
529
391
  return this._tools.map((tool) => tool.name);
530
392
  }
@@ -554,550 +416,65 @@ export class Harness extends ReadyResource {
554
416
  this._customProjection = customProjectionMap();
555
417
  }
556
418
  setModelIdleTimeout(ms) {
557
- this._idle.configure(ms);
419
+ this._residency.setIdleTimeout(ms);
558
420
  }
559
421
  previewModelSource(context) {
560
- return previewModelSource(context, { assessFit: (query) => this._assessFit(query) });
561
- }
562
- async _assessFit({ sha256Checksum, name, contextTokens }) {
563
- const sdk = await this._sdk.load();
564
- const result = await sdk.assessModelFit({
565
- models: [{ model: { sha256Checksum, name }, workload: { kind: 'llm', contextTokens } }]
566
- });
567
- const model = result.models[0];
568
- return {
569
- fit: model?.verdict ?? result.verdict,
570
- fitReasons: [...(model?.reasons ?? result.reasons)]
571
- };
422
+ return previewModelSource(context, { assessFit: (query) => this._residency.fit.assess(query) });
572
423
  }
573
424
  async describe() {
574
425
  if (!this.opened)
575
426
  await this.ready();
576
427
  return {
577
428
  toolNames: this.toolNames,
578
- skills: this._supportedSkills.map((skill) => skill.name),
429
+ skills: this._skills.names,
579
430
  supportsImages: this.supportsImages,
580
431
  supportsKvCacheDeletion: true
581
432
  };
582
433
  }
583
434
  diagnostics() {
584
435
  return {
585
- models: this.opened ? this._loadedModels() : [],
436
+ models: this.opened ? this._residency.loaded() : [],
586
437
  suspended: this.suspended,
587
438
  sdkLoaded: this._sdk.peek() !== null,
588
439
  toolNames: this.toolNames,
589
- skills: this._supportedSkills.map((skill) => skill.name),
590
- device: this._llmDevice
591
- };
592
- }
593
- _loadedModels() {
594
- return this._pools().flatMap((pool) => loadedModels(pool));
595
- }
596
- _loadingModels() {
597
- return new Set(this._pools().flatMap((pool) => loadingModels(pool)));
598
- }
599
- _settledModels() {
600
- return new Set(this._pools().flatMap((pool) => settledModels(pool)));
601
- }
602
- _pools() {
603
- return [
604
- this._models,
605
- this._embedModels,
606
- ...this._retiredEmbedModels,
607
- this._ttsModels,
608
- this._transcriptionModels
609
- ];
610
- }
611
- _loadPluginSdk(current, store, importPlugin) {
612
- let pending = current();
613
- if (!pending) {
614
- pending = (async () => {
615
- const sdk = await this._sdk.load();
616
- const [plugin, { registerPlugin }] = await Promise.all([
617
- importPlugin(),
618
- import('@qvac/sdk/plugins')
619
- ]);
620
- try {
621
- registerPlugin(plugin);
622
- }
623
- catch { }
624
- return sdk;
625
- })().catch((err) => {
626
- store(null);
627
- throw err;
628
- });
629
- store(pending);
630
- }
631
- return pending;
632
- }
633
- _loadDiffusionSdk() {
634
- return this._loadPluginSdk(() => this._diffusionSdk, (sdk) => {
635
- this._diffusionSdk = sdk;
636
- }, () => import('@qvac/sdk/sdcpp-generation/plugin').then((m) => m.diffusionPlugin));
637
- }
638
- async _slmTranslate(model, { text, from, to }, signal) {
639
- const loadOpts = resolveLoadOptions({}, this._deviceConfig());
640
- const key = modelKey(model, loadOpts);
641
- const pool = this._models;
642
- if (!isResident(pool, key)) {
643
- await this._makeRoomForCompletion(model, { ctxSize: loadOpts.ctxSize, signal });
644
- }
645
- try {
646
- const { modelId } = await raceAbort(pool.open(key, model, loadOpts).load(), signal);
647
- const sdk = await this._sdk.load();
648
- const answer = await raceAbort(sdk.translate({ modelId, text, from, to, stream: false, modelType: 'llm' }).text, signal);
649
- return cleanAnswer(answer, text);
650
- }
651
- finally {
652
- releaseModel(pool, key);
653
- }
654
- }
655
- _loadTranslationSdk() {
656
- return this._loadPluginSdk(() => this._translationSdk, (sdk) => {
657
- this._translationSdk = sdk;
658
- }, () => import('@qvac/sdk/nmtcpp-translation/plugin').then((m) => m.nmtPlugin));
659
- }
660
- _loadMusicSdk() {
661
- return this._loadPluginSdk(() => this._musicSdk, (sdk) => {
662
- this._musicSdk = sdk;
663
- }, () => import('@qvac/sdk/audiogen-ggml/plugin').then((m) => m.audioGenPlugin));
664
- }
665
- _deviceConfig() {
666
- return {
667
- device: this._llmDevice,
668
- gpuLayers: this._llmGpuLayers,
669
- contextSize: this._contextSize,
670
- kvCacheK: this._kvCacheK,
671
- kvCacheV: this._kvCacheV,
672
- mainGpu: resolveMainGpu,
673
- openclCacheDir
674
- };
675
- }
676
- _createPool() {
677
- const loadSdk = () => this._loadModelLifecycleSdk();
678
- return createModelPool(loadSdk, (state) => this._notifyModel(state), {
679
- deviceConfig: this._deviceConfig(),
680
- loads: this._loads,
681
- onUnloadFailure: (modelId, error) => this._recordModelUnloadFailure(modelId, error)
682
- });
683
- }
684
- _loadModelLifecycleSdk() {
685
- return this._sdk.load();
686
- }
687
- _createEmbedPool() {
688
- const loadSdk = () => this._sdk.loadEmbed();
689
- return createEmbedPool(loadSdk, (state) => this._notifyModel(state), {
690
- faults: this._embedFaults,
691
- batchSize: this._embedBatchSize,
692
- openclCacheDir,
693
- loads: this._loads,
694
- onUnloadFailure: (modelId, error) => this._recordModelUnloadFailure(modelId, error)
695
- });
696
- }
697
- _createTtsPool() {
698
- const loadSdk = () => this._sdk.loadVoice();
699
- return createVoicePool(loadSdk, (state) => this._notifyModel(state), {
700
- modelType: 'tts-ggml',
701
- addon: 'tts',
702
- modelConfig: TTS_MODEL_CONFIG,
703
- loads: this._loads,
704
- onUnloadFailure: (modelId, error) => this._recordModelUnloadFailure(modelId, error)
705
- });
706
- }
707
- _createTranscriptionPool() {
708
- const loadSdk = () => this._sdk.loadVoice();
709
- return createVoicePool(loadSdk, (state) => this._notifyModel({ ...state, model: TRANSCRIPTION_MODEL_LABEL }), {
710
- modelType: 'parakeet-transcription',
711
- addon: 'parakeet',
712
- modelConfig: { useGPU: this._transcriptionDevice !== 'cpu' },
713
- openclCacheDir,
714
- loads: this._loads,
715
- onUnloadFailure: (modelId, error) => this._recordModelUnloadFailure(modelId, error)
716
- });
717
- }
718
- _recordModelUnloadFailure(modelId, error) {
719
- this._failedModelUnloads.add(modelId);
720
- this._poolUnloadFailed = true;
721
- this._runtimeUnloadFailed = true;
722
- hlog('model unload failed', { modelId, err: errorMessage(error) });
723
- }
724
- _notifyModel(state) {
725
- if (state.status === 'ready' || state.status === 'unloaded' || state.status === 'error') {
726
- invalidateModelStatusCache(this._modelStatus);
727
- }
728
- if (state.status === 'unloaded') {
729
- for (const key of this._pinned) {
730
- if (!isResident(this._models, key)) {
731
- this._pinned.delete(key);
732
- }
733
- }
734
- }
735
- this.emit('model', {
736
- ...state,
737
- catalogChanged: state.catalogChanged === true,
738
- loaded: this._loadedModels()
739
- });
740
- }
741
- async _collectRetiredEmbedPool(pool) {
742
- if (!this._retiredEmbedModels.has(pool) || pool.idle !== pool.size)
743
- return;
744
- try {
745
- await pool.destroy();
746
- }
747
- catch (error) {
748
- if (!(error instanceof ModelUnloadError)) {
749
- this._poolCleanupFailed = true;
750
- this._poolUnloadFailed = true;
751
- this._runtimeUnloadFailed = true;
752
- }
753
- throw error;
754
- }
755
- this._retiredEmbedModels.delete(pool);
756
- }
757
- async _releaseEmbedResource(pool, key) {
758
- releaseModel(pool, key);
759
- const faulted = this._faultedEmbedKeys.get(pool);
760
- if (faulted?.has(key)) {
761
- await evictIdle(pool);
762
- if (!isResident(pool, key)) {
763
- faulted.delete(key);
764
- }
765
- }
766
- await this._collectRetiredEmbedPool(pool);
767
- }
768
- async _releaseEmbedResourceBeforeWork(releasing, releaseWork) {
769
- try {
770
- await releasing;
771
- }
772
- finally {
773
- releaseWork();
774
- }
775
- }
776
- _markEmbedFault({ pool, key, faults, generation }) {
777
- faults.recordFault(generation);
778
- let faulted = this._faultedEmbedKeys.get(pool);
779
- if (!faulted) {
780
- faulted = new Set();
781
- this._faultedEmbedKeys.set(pool, faulted);
782
- }
783
- faulted.add(key);
784
- }
785
- _releaseEmbedResourceAfter(settled, fault) {
786
- return settled
787
- .then(() => this._releaseEmbedResource(fault.pool, fault.key), (error) => {
788
- if (isSdkGpuDeviceLostError(error)) {
789
- this._markEmbedFault(fault);
790
- }
791
- return this._releaseEmbedResource(fault.pool, fault.key);
792
- })
793
- .catch(noop);
794
- }
795
- async _destroyEmbedPools() {
796
- const pools = [this._embedModels, ...this._retiredEmbedModels].filter((pool) => Boolean(pool));
797
- const outcomes = await Promise.allSettled(pools.map(async (pool) => {
798
- await pool.destroy();
799
- this._retiredEmbedModels.delete(pool);
800
- }));
801
- const generic = outcomes.find((outcome) => outcome.status === 'rejected' && !(outcome.reason instanceof ModelUnloadError));
802
- if (generic?.status === 'rejected') {
803
- throw generic.reason;
804
- }
805
- const failed = outcomes.find((outcome) => outcome.status === 'rejected');
806
- if (failed?.status === 'rejected') {
807
- throw failed.reason;
808
- }
809
- }
810
- _enqueueEmbedControl(run) {
811
- const next = this._embedControl.then(run, run);
812
- this._embedControl = next.catch(noop);
813
- return next;
814
- }
815
- async _runLifecycle(type, { open = true } = {}) {
816
- if (!this.opened) {
817
- if (open) {
818
- await this.ready();
819
- }
820
- }
821
- if (this._closeRequested || this.closing) {
822
- return;
823
- }
824
- await this._lifecycle.send(type);
825
- }
826
- _abortCompletions() {
827
- for (const run of this._completionRuns) {
828
- run.abort();
829
- }
830
- }
831
- _assertNotClosing() {
832
- if (this._closeRequested || this.closing || this.closed) {
833
- throw new Error('harness is closing');
834
- }
835
- }
836
- _enterWork() {
837
- this._assertNotClosing();
838
- if (this._runtimeDraining) {
839
- throw new Error('harness is suspended');
840
- }
841
- if (this._runtimeUnloadFailed) {
842
- throw new Error('Runtime unload failed; close the harness before loading models again');
843
- }
844
- this._activeWork++;
845
- let released = false;
846
- return () => {
847
- if (released)
848
- return;
849
- released = true;
850
- if (--this._activeWork !== 0) {
851
- return;
852
- }
853
- for (const resolve of this._workDrainWaiters) {
854
- resolve();
855
- }
856
- this._workDrainWaiters.clear();
440
+ skills: this._skills.names,
441
+ device: this._residency.deviceConfig().device
857
442
  };
858
443
  }
859
- _waitForWorkDrain() {
860
- if (!this._activeWork) {
861
- return Promise.resolve();
862
- }
863
- return new Promise((resolve) => this._workDrainWaiters.add(resolve));
864
- }
865
- _effectsSettled() {
866
- return !this._detachedRuns.size && ![...this._completionRuns].some((run) => run.started);
867
- }
868
- _notifyEffectDrain() {
869
- if (!this._effectsSettled())
870
- return;
871
- for (const resolve of this._effectDrainWaiters) {
872
- resolve();
873
- }
874
- this._effectDrainWaiters.clear();
875
- }
876
- _waitForEffectDrain() {
877
- if (this._effectsSettled()) {
878
- return Promise.resolve();
879
- }
880
- return new Promise((resolve) => this._effectDrainWaiters.add(resolve));
881
- }
882
- _trackDetachedRun(pending, runId) {
883
- const tracked = pending.catch((error) => {
884
- hlog('detached completion effect failed', { runId, err: errorMessage(error) });
885
- });
886
- this._detachedRuns.add(tracked);
887
- void tracked
888
- .finally(() => {
889
- this._detachedRuns.delete(tracked);
890
- this._notifyEffectDrain();
891
- })
892
- .catch(noop);
893
- }
894
- async _closeCompletions(runs = this._completionRuns) {
895
- const closed = await Promise.allSettled([...runs].map((run) => run.close()));
896
- for (const outcome of closed) {
897
- if (outcome.status === 'rejected') {
898
- hlog('completion close failed', {
899
- err: errorMessage(outcome.reason)
900
- });
901
- }
902
- }
903
- }
904
444
  getEmbeddingDevice() {
905
- return this._embedFaults.device;
445
+ return this._embeddings.device;
906
446
  }
907
447
  setEmbeddingDevice(device) {
908
- assertEmbedDevice(device);
909
- return this._enqueueEmbedControl(() => this._setEmbeddingDevice(device));
910
- }
911
- async _setEmbeddingDevice(device) {
912
- if (!this.opened)
913
- await this.ready();
914
- if (this.suspended) {
915
- this._assertNotClosing();
916
- if (this._embedFaults.device === device) {
917
- return;
918
- }
919
- this._embedFaults = createGpuFaultState({ device, gpuLayers: this._embedGpuLayers });
920
- return;
921
- }
922
- const releaseWork = this._enterWork();
923
- try {
924
- if (this._embedFaults.device === device) {
925
- return;
926
- }
927
- this._embedFaults = createGpuFaultState({ device, gpuLayers: this._embedGpuLayers });
928
- if (this.suspended) {
929
- return;
930
- }
931
- const retired = this._embedModels;
932
- this._retiredEmbedModels.add(retired);
933
- this._embedModels = this._createEmbedPool();
934
- await this._collectRetiredEmbedPool(retired);
935
- }
936
- finally {
937
- releaseWork();
938
- }
448
+ return this._embeddings.setDevice(device);
939
449
  }
940
450
  async presuspend() {
941
- await this._runLifecycle('PRESUSPEND', { open: false });
451
+ await this._lifecycle.send('PRESUSPEND', { open: false });
942
452
  }
943
453
  async suspend() {
944
- const result = await raceDrain(this._runLifecycle('SUSPEND'), SUSPEND_SETTLE_MS);
454
+ const result = await raceDrain(this._lifecycle.send('SUSPEND'), SUSPEND_SETTLE_MS);
945
455
  if (didDrainTimeOut(result)) {
946
456
  throw new Error('Harness suspend is still waiting for active work to settle');
947
457
  }
948
458
  }
949
- async _suspendRuntimes() {
950
- this._runtimeDraining = true;
951
- hlog('suspending', { models: loadedModels(this._models).map((entry) => entry.model) });
952
- this._abortCompletions();
953
- this._loads.drain();
954
- await this._closeCompletions([...this._completionRuns].filter((run) => run.started));
955
- await this._waitForEffectDrain();
956
- const pending = this._sdk.peek();
957
- if (pending) {
958
- const sdk = await pending.catch(noop);
959
- if (sdk) {
960
- this._loads.drain(sdk);
961
- }
962
- }
963
- await this._waitForWorkDrain();
964
- if (!(await this._releaseRuntimes())) {
965
- throw new Error('Runtime unload failed; close the harness before loading models again');
966
- }
967
- invalidateModelStatusCache(this._modelStatus);
968
- await this._sdkLifecycle('suspend');
969
- hlog('suspended');
970
- }
971
- async _sdkLifecycle(op) {
972
- const sdk = await this._sdk.peek()?.catch(noop);
973
- if (!sdk) {
974
- return;
975
- }
976
- try {
977
- await sdk[op]();
978
- }
979
- catch (err) {
980
- hlog(`sdk ${op} failed`, { err: errorMessage(err) });
981
- if (op === 'suspend') {
982
- throw err;
983
- }
984
- await sdk.resume().catch((retryErr) => {
985
- hlog('sdk resume retry failed', {
986
- err: errorMessage(retryErr)
987
- });
988
- throw retryErr;
989
- });
990
- }
991
- }
992
- async _releaseRuntimes() {
993
- const released = await Promise.allSettled([
994
- this._models?.destroy(),
995
- this._destroyEmbedPools(),
996
- this._ttsModels?.destroy(),
997
- this._transcriptionModels?.destroy(),
998
- this._imageRuntime?.unload(),
999
- this._musicRuntime?.unload(),
1000
- this._translationRuntime.unload()
1001
- ]);
1002
- for (const [index, outcome] of released.entries()) {
1003
- if (outcome.status !== 'rejected')
1004
- continue;
1005
- if (index < 4 && !(outcome.reason instanceof ModelUnloadError)) {
1006
- this._poolCleanupFailed = true;
1007
- }
1008
- const err = outcome.reason;
1009
- hlog('unload failed', { err: errorMessage(err) });
1010
- }
1011
- const sdk = await this._sdk.peek()?.catch(noop);
1012
- if (sdk) {
1013
- for (const modelId of this._failedModelUnloads) {
1014
- try {
1015
- await sdk.unloadModel({ modelId });
1016
- this._failedModelUnloads.delete(modelId);
1017
- invalidateModelStatusCache(this._modelStatus);
1018
- }
1019
- catch (error) {
1020
- hlog('model unload retry failed', {
1021
- modelId,
1022
- err: errorMessage(error)
1023
- });
1024
- }
1025
- }
1026
- }
1027
- this._poolUnloadFailed = this._poolCleanupFailed || this._failedModelUnloads.size > 0;
1028
- this._runtimeUnloadFailed =
1029
- this._poolUnloadFailed || released.slice(4).some((outcome) => outcome.status === 'rejected');
1030
- return !this._runtimeUnloadFailed;
1031
- }
1032
- async _unloadIdleModels() {
1033
- if (!this.opened || this.closing || this.suspended || this._runtimeDraining) {
1034
- return;
1035
- }
1036
- hlog('idle unload', { models: this._loadedModels().map((entry) => entry.model) });
1037
- const released = await Promise.allSettled([
1038
- evictIdle(this._models),
1039
- evictIdle(this._embedModels),
1040
- ...[...this._retiredEmbedModels].map((pool) => this._collectRetiredEmbedPool(pool)),
1041
- evictIdle(this._ttsModels),
1042
- evictIdle(this._transcriptionModels),
1043
- this._imageRuntime?.unloadIdle(),
1044
- this._musicRuntime?.unloadIdle(),
1045
- this._translationRuntime.unload()
1046
- ]);
1047
- for (const outcome of released) {
1048
- if (outcome.status !== 'rejected')
1049
- continue;
1050
- hlog('idle unload failed', { err: errorMessage(outcome.reason) });
1051
- }
1052
- invalidateModelStatusCache(this._modelStatus);
1053
- }
1054
459
  async resume() {
1055
- await this._runLifecycle('RESUME');
1056
- }
1057
- async _resumeRuntimes() {
1058
- this._assertNotClosing();
1059
- if (this._runtimeUnloadFailed) {
1060
- throw new Error('Runtime unload failed; close the harness before loading models again');
1061
- }
1062
- hlog('resuming', { pools: 'recreated' });
1063
- this._loads.undrain();
1064
- this._models = this._createPool();
1065
- this._embedModels = this._createEmbedPool();
1066
- this._ttsModels = this._createTtsPool();
1067
- this._transcriptionModels = this._createTranscriptionPool();
1068
- try {
1069
- await this._sdkLifecycle('resume');
1070
- this._runtimeDraining = false;
1071
- }
1072
- catch (error) {
1073
- const sdk = await this._sdk.peek()?.catch(noop);
1074
- if (sdk) {
1075
- this._loads.drain(sdk);
1076
- }
1077
- await this._releaseRuntimes();
1078
- throw error;
1079
- }
460
+ await this._lifecycle.send('RESUME');
1080
461
  }
1081
462
  async wakeup() {
1082
- await this._runLifecycle('WAKEUP');
463
+ await this._lifecycle.send('WAKEUP');
1083
464
  }
1084
465
  ready() {
1085
- if (this._closeRequested || this.closing || this.closed) {
466
+ if (this._lifecycle.closeRequested || this.closing || this.closed) {
1086
467
  return Promise.reject(new Error('harness is closing'));
1087
468
  }
1088
469
  return super.ready();
1089
470
  }
1090
471
  async _close() {
1091
472
  hlog('closing');
1092
- this._idle.close();
1093
- this._lifecycle.cancelPending();
1094
- this._abortCompletions();
1095
- this._loads.drain();
1096
- await this._lifecycle.settled();
1097
- await this._finishClose();
473
+ this._residency.closeIdle();
474
+ await this._lifecycle.close();
1098
475
  }
1099
476
  close() {
1100
- this._closeRequested = true;
477
+ this._lifecycle.requestClose();
1101
478
  if (this._closeRetryNeeded) {
1102
479
  this.closing = null;
1103
480
  this._closeRetryNeeded = false;
@@ -1120,80 +497,33 @@ export class Harness extends ReadyResource {
1120
497
  if (this.closing)
1121
498
  return this.closing;
1122
499
  const opening = this.opening;
500
+ const pluginsClosing = this._teardownPlugins();
1123
501
  const pending = (async () => {
1124
502
  await opening?.catch(noop);
1125
- this._abortCompletions();
503
+ await pluginsClosing;
504
+ this._lifecycle.abortCompletions();
1126
505
  this._loads.drain();
1127
- await this._finishClose();
506
+ await this._lifecycle.finishClose();
1128
507
  this.closed = true;
1129
508
  this.emit('close');
1130
509
  })();
1131
510
  this.closing = pending;
1132
511
  return pending;
1133
512
  }
1134
- async _finishClose() {
1135
- let completed = false;
1136
- try {
1137
- const pending = this._sdk.peek();
1138
- if (pending) {
1139
- const sdk = await pending.catch(noop);
1140
- if (sdk) {
1141
- this._loads.drain(sdk);
1142
- }
1143
- }
1144
- await this._closeCompletions();
1145
- await this._waitForEffectDrain();
1146
- await this._waitForWorkDrain();
1147
- this._overlayWatcher?.stop();
1148
- this._overlayWatcher = null;
1149
- if (!this._runtimesReleased) {
1150
- let [released] = await Promise.all([this._releaseRuntimes(), closePythonWorker()]);
1151
- if (!released && !this._poolUnloadFailed) {
1152
- released = await this._releaseRuntimes();
1153
- }
1154
- this._runtimesReleased = released;
1155
- }
1156
- let sdkCloseFailed = false;
1157
- let sdkCloseError;
1158
- const sdk = !this._sdkClosed && !this._runtimeUnloadFailed ? await this._sdk.peek()?.catch(noop) : null;
1159
- if (sdk) {
1160
- try {
1161
- await sdk.close();
1162
- this._sdkClosed = true;
1163
- }
1164
- catch (error) {
1165
- sdkCloseFailed = true;
1166
- sdkCloseError = error;
1167
- hlog('sdk close failed', { err: errorMessage(error) });
1168
- }
1169
- }
1170
- if (sdkCloseFailed) {
1171
- throw sdkCloseError;
1172
- }
1173
- if (this._runtimeUnloadFailed) {
1174
- throw new Error('Runtime unload failed; model cleanup could not be confirmed');
1175
- }
1176
- completed = true;
1177
- }
1178
- finally {
1179
- if (completed) {
1180
- this._lifecycle.stop();
1181
- }
1182
- }
1183
- }
1184
513
  download(args) {
1185
- this._assertNotClosing();
514
+ this._lifecycle.assertNotClosing();
1186
515
  let releaseWork = null;
1187
516
  const projection = (args.addon ?? 'llm') === 'llm' ? this._projectionFor(args.model) : undefined;
1188
517
  const multiFile = diffusionDownloadMetadata(args.model, args.addon) ??
1189
- audioGenDownloadMetadata(args.model, args.addon);
518
+ audioGenDownloadMetadata(args.model, args.addon) ??
519
+ categoryDownloadMetadata(args.model, args.addon);
1190
520
  return download(async () => {
1191
521
  if (!this.opened)
1192
522
  await this.ready();
1193
- releaseWork = this._enterWork();
523
+ releaseWork = this._lifecycle.enterWork();
1194
524
  try {
1195
525
  const sdk = await this._sdk.load();
1196
- this._assertNotClosing();
526
+ this._lifecycle.assertNotClosing();
1197
527
  return sdk;
1198
528
  }
1199
529
  catch (error) {
@@ -1206,264 +536,100 @@ export class Harness extends ReadyResource {
1206
536
  projection,
1207
537
  companions: multiFile?.companions,
1208
538
  assetSizes: multiFile?.assetSizes
1209
- }, () => invalidateModelStatusCache(this._modelStatus), () => {
539
+ }, () => this._residency.invalidateStatus(), () => {
1210
540
  releaseWork?.();
1211
541
  releaseWork = null;
1212
542
  });
1213
543
  }
1214
544
  embed(context) {
1215
- return this._busy(() => this._embed(context));
545
+ return this._residency.busy(() => this._embeddings.embed(context));
1216
546
  }
1217
- async _embed({ model, texts, signal }) {
547
+ async _speechService() {
1218
548
  if (!this.opened)
1219
549
  await this.ready();
1220
- this._assertNotClosing();
1221
- if (this.suspended) {
1222
- throw new Error('harness is suspended');
1223
- }
1224
- if (texts.length === 0) {
1225
- return [];
1226
- }
1227
- const pool = this._embedModels;
1228
- const faults = this._embedFaults;
1229
- const generation = faults.generation;
1230
- const key = faults.key(residentSrc(model, 'embeddings'));
1231
- const releaseWork = this._enterWork();
1232
- let handle;
1233
- try {
1234
- handle = pool.open(key, model);
1235
- }
1236
- catch (error) {
1237
- releaseWork();
1238
- throw error;
1239
- }
1240
- let loaded = null;
1241
- let job = null;
1242
- let releaseAfter = null;
1243
- let drainWorkAfter = null;
1244
- try {
1245
- loaded = await raceAbort(handle.load(), signal);
1246
- const sdk = await this._sdk.loadEmbed();
1247
- this._assertNotClosing();
1248
- job = this._embedLane(sdk, { modelId: loaded.modelId, texts });
1249
- const vectors = await raceAbort(job, signal);
1250
- faults.reset();
1251
- return vectors;
1252
- }
1253
- catch (err) {
1254
- if (err instanceof AbortedError) {
1255
- if (job || this._retiredEmbedModels.has(pool)) {
1256
- releaseAfter = job ?? handle.peek();
1257
- }
1258
- else {
1259
- drainWorkAfter = handle.peek();
1260
- }
1261
- }
1262
- if (isSdkGpuDeviceLostError(err)) {
1263
- this._markEmbedFault({ pool, key, faults, generation });
1264
- }
1265
- throw err;
1266
- }
1267
- finally {
1268
- if (releaseAfter) {
1269
- void this._releaseEmbedResourceAfter(releaseAfter, {
1270
- pool,
1271
- key,
1272
- faults,
1273
- generation
1274
- }).finally(releaseWork);
1275
- }
1276
- else {
1277
- const releasing = this._releaseEmbedResource(pool, key);
1278
- if (drainWorkAfter) {
1279
- void Promise.allSettled([releasing, drainWorkAfter]).then(releaseWork);
1280
- }
1281
- else {
1282
- await this._releaseEmbedResourceBeforeWork(releasing, releaseWork);
1283
- }
1284
- }
550
+ if (!this._plugins.ctx.speech) {
551
+ throw new Error(SPEECH_PLUGIN_MISSING);
1285
552
  }
553
+ return this._plugins.ctx.speech;
1286
554
  }
1287
- async _defaultVoiceSrc(category) {
1288
- if (category !== 'tts') {
1289
- return defaultVoiceModel(category);
1290
- }
1291
- try {
1292
- const { capabilityProfile } = await this.capability();
1293
- return defaultTtsFor(capabilityProfile).asset.src;
1294
- }
1295
- catch {
1296
- return defaultVoiceModel('tts');
1297
- }
1298
- }
1299
- async _voiceJob(pool, { category, model, signal }, run) {
555
+ async _knowledgeService() {
1300
556
  if (!this.opened)
1301
557
  await this.ready();
1302
- if (this.suspended)
1303
- throw new Error('harness is suspended');
1304
- const addon = category === 'tts' ? 'tts' : 'parakeet';
1305
- const name = residentSrc(model || (await this._defaultVoiceSrc(category)), addon);
1306
- this._assertNotClosing();
1307
- const releaseWork = this._enterWork();
1308
- let handle;
1309
- try {
1310
- handle = pool.open(name, name);
1311
- }
1312
- catch (error) {
1313
- releaseWork();
1314
- throw error;
1315
- }
1316
- let job = null;
1317
- let releaseAfter = null;
1318
- let sdk = null;
1319
- let modelId = null;
1320
- try {
1321
- modelId = (await raceAbort(handle.load(), signal)).modelId;
1322
- sdk = (await this._sdk.loadVoice());
1323
- this._assertNotClosing();
1324
- const boundSdk = sdk;
1325
- const boundId = modelId;
1326
- job = this._voiceLane(() => run(boundSdk, boundId));
1327
- return await raceAbort(job, signal);
1328
- }
1329
- catch (err) {
1330
- if (err instanceof AbortedError) {
1331
- if (sdk && modelId) {
1332
- void sdk.cancel({ modelId, operation: 'inference' }).catch(noop);
1333
- }
1334
- releaseAfter = job ?? handle.peek();
1335
- }
1336
- throw err;
1337
- }
1338
- finally {
1339
- const release = () => {
1340
- releaseModel(pool, name);
1341
- };
1342
- if (releaseAfter) {
1343
- void releaseAfter.then(release, release).finally(releaseWork).catch(noop);
1344
- }
1345
- else {
1346
- try {
1347
- release();
1348
- }
1349
- finally {
1350
- releaseWork();
1351
- }
1352
- }
558
+ if (!this._plugins.ctx.knowledge) {
559
+ throw new Error(KNOWLEDGE_PLUGIN_MISSING);
1353
560
  }
561
+ return this._plugins.ctx.knowledge;
562
+ }
563
+ async knowledgeUpsert(artifact) {
564
+ return (await this._knowledgeService()).upsert(artifact);
565
+ }
566
+ async knowledgeRemove(artifactId) {
567
+ return (await this._knowledgeService()).remove(artifactId);
568
+ }
569
+ async knowledgeSearch(query) {
570
+ return (await this._knowledgeService()).search(query);
571
+ }
572
+ async knowledgeStatus() {
573
+ return (await this._knowledgeService()).status();
1354
574
  }
1355
575
  transcribe(context) {
1356
- return this._busy(() => this._transcribe(context));
576
+ return this._residency.busy(() => this._transcribe(context));
1357
577
  }
1358
578
  async _transcribe({ model, audio, signal }) {
1359
- return this._voiceJob(this._transcriptionModels, { category: 'transcription', model, signal }, async (sdk, id) => {
1360
- const pcm = await pcmForTranscription(audio);
1361
- if (signal?.aborted) {
1362
- throw new AbortedError();
1363
- }
1364
- if (pcm && pcm.length >= TRANSCRIBE_STREAM_MIN_BYTES) {
1365
- return transcribeStreaming(sdk, pcm, { modelId: id, signal });
1366
- }
1367
- return transcribeOnce(sdk, id, pcm ? buildWavBuffer(pcm) : audio);
579
+ const speech = await this._speechService();
580
+ return speech.transcribe({
581
+ model: model || defaultVoiceModel('transcription'),
582
+ audio,
583
+ signal
1368
584
  });
1369
585
  }
1370
586
  detectLanguage(context) {
1371
587
  return detectLanguage(context);
1372
588
  }
1373
589
  speak(context) {
1374
- return this._busy(() => this._speak(context));
590
+ return this._residency.busy(() => this._speak(context));
1375
591
  }
1376
592
  async _speak({ model, text, signal }) {
1377
- const samples = await this._voiceJob(this._ttsModels, { category: 'tts', model, signal }, (sdk, id) => speakOnce(sdk, id, text));
1378
- return { audio: packSamples(samples), sampleRate: SUPERTONIC_SAMPLE_RATE };
593
+ const speech = await this._speechService();
594
+ return speech.speak({ model: model || (await this._defaultTts(speech)), text, signal });
1379
595
  }
1380
596
  speakStream(context) {
1381
- return this._busyStream(() => this._speakStream(context));
597
+ return this._residency.busyStream(() => this._speakStream(context));
1382
598
  }
1383
599
  async *_speakStream({ model, text, signal }) {
1384
- if (!this.opened)
1385
- await this.ready();
1386
- if (this.suspended)
1387
- throw new Error('harness is suspended');
1388
- const name = residentSrc(model || (await this._defaultVoiceSrc('tts')), 'tts');
1389
- this._assertNotClosing();
1390
- const pool = this._ttsModels;
1391
- const chunks = pushQueue();
1392
- const releaseWork = this._enterWork();
1393
- let handle;
1394
- try {
1395
- handle = pool.open(name, name);
1396
- }
1397
- catch (error) {
1398
- releaseWork();
1399
- throw error;
1400
- }
1401
- let sdk = null;
1402
- let modelId = null;
1403
- const cancel = () => {
1404
- if (sdk && modelId) {
1405
- void sdk.cancel({ modelId, operation: 'inference' }).catch(noop);
1406
- }
1407
- };
1408
- signal?.addEventListener('abort', cancel, { once: true });
1409
- const job = this._voiceLane(async () => {
1410
- try {
1411
- modelId = (await handle.load()).modelId;
1412
- sdk = (await this._sdk.loadVoice());
1413
- this._assertNotClosing();
1414
- if (signal?.aborted) {
1415
- return;
1416
- }
1417
- for await (const chunk of speakStreamOnce(sdk, modelId, text)) {
1418
- chunks.push(chunk);
1419
- }
1420
- }
1421
- finally {
1422
- chunks.end();
1423
- }
1424
- });
1425
- let settled = false;
1426
- try {
1427
- yield* chunks;
1428
- await job;
1429
- settled = true;
1430
- }
1431
- finally {
1432
- signal?.removeEventListener('abort', cancel);
1433
- if (!settled) {
1434
- cancel();
1435
- }
1436
- void job
1437
- .catch(noop)
1438
- .finally(() => {
1439
- try {
1440
- releaseModel(pool, name);
1441
- }
1442
- finally {
1443
- releaseWork();
1444
- }
1445
- })
1446
- .catch(noop);
1447
- }
600
+ const speech = await this._speechService();
601
+ yield* speech.speakStream({ model: model || (await this._defaultTts(speech)), text, signal });
602
+ }
603
+ async _defaultTts(speech) {
604
+ const profile = await this.capability().then((capability) => capability.capabilityProfile, () => null);
605
+ return speech.defaultModel(profile);
1448
606
  }
1449
607
  async list(options = {}) {
1450
608
  if (!this.opened)
1451
609
  await this.ready();
1452
- const releaseWork = this._enterWork();
610
+ const releaseWork = this._lifecycle.enterWork();
1453
611
  try {
1454
612
  const sdk = await this._sdk.load();
1455
- this._assertNotClosing();
613
+ this._lifecycle.assertNotClosing();
1456
614
  const rows = await listModels(sdk, options, {
1457
- cache: this._modelStatus,
615
+ cache: this._residency.status,
1458
616
  projectionFor: (name) => this._projectionFor(name)
1459
617
  });
1460
- const loaded = this._settledModels();
1461
- const loading = this._loadingModels();
618
+ const loaded = this._residency.settled();
619
+ const loading = this._residency.loading();
1462
620
  const custom = await customModelRows(options, { modelsDir: this._modelsDir, loaded });
1463
- return mergeCustomRows(rows, custom).map((row) => ({
1464
- ...row,
1465
- isLoading: loading.has(row.name)
1466
- }));
621
+ const merged = mergeCustomRows(rows, custom);
622
+ const fits = await this._residency.rowFits(merged);
623
+ return merged.map((row) => {
624
+ const fit = row.isLoaded || loaded.has(row.name) ? undefined : fits.get(row.registryPath);
625
+ return {
626
+ ...row,
627
+ isLoading: loading.has(row.name),
628
+ fit: fit?.verdict,
629
+ fitBasis: fit?.basis,
630
+ fitEvidence: fit?.evidence
631
+ };
632
+ });
1467
633
  }
1468
634
  finally {
1469
635
  releaseWork();
@@ -1472,12 +638,12 @@ export class Harness extends ReadyResource {
1472
638
  async deleteModel(name) {
1473
639
  if (!this.opened)
1474
640
  await this.ready();
1475
- const releaseWork = this._enterWork();
641
+ const releaseWork = this._lifecycle.enterWork();
1476
642
  try {
1477
643
  const sdk = await this._sdk.load();
1478
- this._assertNotClosing();
644
+ this._lifecycle.assertNotClosing();
1479
645
  const result = await deleteModelFiles(sdk, name, { modelsDir: this._modelsDir });
1480
- invalidateModelStatusCache(this._modelStatus);
646
+ this._residency.invalidateStatus();
1481
647
  return summarizeDelete(result);
1482
648
  }
1483
649
  finally {
@@ -1487,10 +653,10 @@ export class Harness extends ReadyResource {
1487
653
  async clearKvCache() {
1488
654
  if (!this.opened)
1489
655
  await this.ready();
1490
- const releaseWork = this._enterWork();
656
+ const releaseWork = this._lifecycle.enterWork();
1491
657
  try {
1492
658
  return await deleteAllKvCaches(() => {
1493
- this._assertNotClosing();
659
+ this._lifecycle.assertNotClosing();
1494
660
  return this._sdk.load();
1495
661
  });
1496
662
  }
@@ -1501,10 +667,10 @@ export class Harness extends ReadyResource {
1501
667
  async deleteKvCache(kvCacheKey) {
1502
668
  if (!this.opened)
1503
669
  await this.ready();
1504
- const releaseWork = this._enterWork();
670
+ const releaseWork = this._lifecycle.enterWork();
1505
671
  try {
1506
672
  return await deleteKvCacheKey(() => {
1507
- this._assertNotClosing();
673
+ this._lifecycle.assertNotClosing();
1508
674
  return this._sdk.load();
1509
675
  }, kvCacheKey);
1510
676
  }
@@ -1518,7 +684,7 @@ export class Harness extends ReadyResource {
1518
684
  async capability() {
1519
685
  if (!this.opened)
1520
686
  await this.ready();
1521
- this._assertNotClosing();
687
+ this._lifecycle.assertNotClosing();
1522
688
  if (this._capability) {
1523
689
  return this._capability;
1524
690
  }
@@ -1560,211 +726,25 @@ export class Harness extends ReadyResource {
1560
726
  return this._capabilityInflight;
1561
727
  }
1562
728
  warmModel(context) {
1563
- return this._busy(() => this._warmModel(context));
1564
- }
1565
- async _warmModel({ model, agent, signal }) {
1566
- if (!this.opened)
1567
- await this.ready();
1568
- this._assertNotClosing();
1569
- if (this.suspended) {
1570
- return;
1571
- }
1572
- const target = this._residency(model, agent);
1573
- hlog('warm model', { model, resident: isResident(target.pool, target.key) });
1574
- await this._loadAndRelease(target, signal, async () => {
1575
- if (target.pool !== this._models || isResident(target.pool, target.key)) {
1576
- return true;
1577
- }
1578
- const roomed = await this._makeRoomForCompletion(model, {
1579
- ctxSize: target.ctxSize,
1580
- signal,
1581
- deadlineMs: WARM_ROOM_WAIT_MS
1582
- });
1583
- if (roomed) {
1584
- await this._unloadIdleGenerators();
1585
- }
1586
- return roomed;
1587
- });
729
+ return this._residency.busy(() => this._residency.warm(context));
1588
730
  }
1589
731
  loadModel(context) {
1590
- return this._busy(() => this._loadModel(context));
1591
- }
1592
- async _loadModel({ model, agent, signal }) {
1593
- if (!this.opened)
1594
- await this.ready();
1595
- if (this.suspended) {
1596
- throw new Error('harness is suspended');
1597
- }
1598
- const target = this._residency(model, agent);
1599
- const resident = isResident(target.pool, target.key);
1600
- hlog('load model', { model, resident });
1601
- if (target.pool !== this._models) {
1602
- await this._loadAndRelease(target, signal);
1603
- return { loaded: true };
1604
- }
1605
- if (!resident) {
1606
- if (!(await this._fits(model, target.ctxSize))) {
1607
- return { loaded: false, reason: 'memory' };
1608
- }
1609
- await evictIdleWhere(this._models, (key) => modelOf(key) === model && !this._replying.includes(key));
1610
- await this._unloadIdleGenerators();
1611
- }
1612
- this._pinned.add(target.key);
1613
- try {
1614
- await this._loadAndRelease(target, signal);
1615
- }
1616
- catch (err) {
1617
- this._pinned.delete(target.key);
1618
- throw err;
1619
- }
1620
- return { loaded: true };
732
+ return this._residency.busy(() => this._residency.load(context));
1621
733
  }
1622
734
  unloadModel(context) {
1623
- return this._busy(() => this._unloadModel(context));
1624
- }
1625
- async _unloadModel({ model }) {
1626
- if (!this.opened)
1627
- await this.ready();
1628
- const target = this._residency(model);
1629
- const name = modelOf(target.key);
1630
- const unloaded = await evictModel(target.pool, name, { deadlineMs: UNLOAD_LEASE_WAIT_MS });
1631
- hlog('unload model', { model, unloaded });
1632
- if (unloaded) {
1633
- for (const key of this._pinned) {
1634
- if (modelOf(key) === name) {
1635
- this._pinned.delete(key);
1636
- }
1637
- }
1638
- }
1639
- return { unloaded };
1640
- }
1641
- async _loadAndRelease({ pool, key, open }, signal, prepare = async () => true) {
1642
- const lease = await this._acquireModelLease({ pool, key, open, signal, prepare });
1643
- lease?.release();
1644
- }
1645
- async _unloadIdleGenerators() {
1646
- await this._imageRuntime?.unloadIdle().catch(noop);
1647
- await this._musicRuntime?.unloadIdle().catch(noop);
1648
- }
1649
- async _fits(model, ctxSize) {
1650
- const asset = curatedModelAsset(model, 'llm');
1651
- if (!asset) {
1652
- return true;
1653
- }
1654
- const assessed = await this._assessFit({
1655
- sha256Checksum: asset.sha256Checksum,
1656
- name: asset.name,
1657
- contextTokens: ctxSize || defaultContextSize(asset)
1658
- }).catch((err) => {
1659
- hlog('fit estimate failed', { model, err: errorMessage(err) });
1660
- return null;
1661
- });
1662
- return assessed?.fit !== 'likely-too-large';
1663
- }
1664
- async _yieldPins(model, ctxSize) {
1665
- for (const key of this._pinned) {
1666
- if (leaseCount(this._models, key) > 0 || this._replying.includes(key)) {
1667
- continue;
1668
- }
1669
- if (await this._fits(model, ctxSize))
1670
- return;
1671
- this._pinned.delete(key);
1672
- await evictModelWithin(this._models, key, { deadlineMs: WEDGED_EVICT_WAIT_MS });
1673
- }
1674
- }
1675
- _residency(model, agent) {
1676
- const addon = modelAddonOf(model);
1677
- if (addon === 'llm') {
1678
- const loadOpts = this._completionLoadOptions(model, agent);
1679
- const key = modelKey(model, loadOpts);
1680
- return {
1681
- pool: this._models,
1682
- key,
1683
- ctxSize: loadOpts.ctxSize,
1684
- open: () => this._models.open(key, model, loadOpts)
1685
- };
1686
- }
1687
- if (addon === 'embeddings') {
1688
- const key = this._embedFaults.key(residentSrc(model, addon));
1689
- return { pool: this._embedModels, key, open: () => this._embedModels.open(key, model) };
1690
- }
1691
- if (addon === 'tts' || addon === 'parakeet') {
1692
- const pool = addon === 'tts' ? this._ttsModels : this._transcriptionModels;
1693
- const key = residentSrc(model, addon);
1694
- return { pool, key, open: () => pool.open(key, key) };
1695
- }
1696
- throw new Error(`${model} loads for each generation and is not kept in memory`);
1697
- }
1698
- _completionLoadOptions(model, agent) {
1699
- return resolveLoadOptions({
1700
- ctxSize: agent?.ctxSize ?? undefined,
1701
- kvCacheK: agent?.kvCacheK ?? undefined,
1702
- kvCacheV: agent?.kvCacheV ?? undefined,
1703
- projectionModel: this._projectionFor(model)
1704
- }, this._deviceConfig());
1705
- }
1706
- async _acquireModelLease({ pool, key, open, signal, prepare }) {
1707
- const releaseWork = this._enterWork();
1708
- let pendingLoad = null;
1709
- let opened = false;
1710
- let released = false;
1711
- const release = () => {
1712
- if (released) {
1713
- return;
1714
- }
1715
- released = true;
1716
- try {
1717
- if (opened) {
1718
- releaseModel(pool, key);
1719
- }
1720
- }
1721
- finally {
1722
- releaseWork();
1723
- }
1724
- };
1725
- try {
1726
- if (!(await prepare())) {
1727
- release();
1728
- return null;
1729
- }
1730
- if (signal?.aborted) {
1731
- throw new AbortedError();
1732
- }
1733
- if (this.suspended || this._runtimeDraining) {
1734
- throw new Error('harness is suspended');
1735
- }
1736
- this._assertNotClosing();
1737
- if (this._runtimeUnloadFailed) {
1738
- throw new Error('Runtime unload failed; close the harness before loading models again');
1739
- }
1740
- const handle = open();
1741
- opened = true;
1742
- const loading = handle.load();
1743
- pendingLoad = loading;
1744
- const loaded = await raceAbort(loading, signal);
1745
- return { modelId: loaded.modelId, release };
1746
- }
1747
- catch (error) {
1748
- if (pendingLoad) {
1749
- void pendingLoad.then(release, release).catch(noop);
1750
- }
1751
- else {
1752
- release();
1753
- }
1754
- throw error;
1755
- }
735
+ return this._residency.busy(() => this._residency.unload(context));
1756
736
  }
1757
737
  invoke(context) {
1758
- return this._busyStream(() => this._invoke(context));
738
+ return this._residency.busyStream(() => this._invoke(context));
1759
739
  }
1760
740
  async *_invoke({ capability, args, enhance, agent, attach, fetchAttachment, progress, signal }) {
1761
741
  if (!this.opened)
1762
742
  await this.ready();
1763
743
  if (this.suspended) {
1764
- this._assertNotClosing();
744
+ this._lifecycle.assertNotClosing();
1765
745
  return yield { type: 'aborted' };
1766
746
  }
1767
- const releaseWork = this._enterWork();
747
+ const releaseWork = this._lifecycle.enterWork();
1768
748
  hlog('invoke start', { capability, enhance });
1769
749
  try {
1770
750
  yield* invoke({
@@ -1772,7 +752,7 @@ export class Harness extends ReadyResource {
1772
752
  args,
1773
753
  enhance,
1774
754
  enhancer: this._residentEnhancer(),
1775
- tools: [...this._tools, ...this._capabilityTools],
755
+ tools: [...this._tools, ...this._capabilities],
1776
756
  ctx: {
1777
757
  image: imageSettingsFrom(agent),
1778
758
  attach,
@@ -1788,56 +768,65 @@ export class Harness extends ReadyResource {
1788
768
  }
1789
769
  }
1790
770
  completion(context) {
1791
- this._assertNotClosing();
1792
- if (this._runtimeDraining) {
771
+ if (!context.agents) {
772
+ return this._completion(context);
773
+ }
774
+ if (context.boot || context.onStep) {
775
+ throw new TypeError('A run that follows handoffs cannot take boot or onStep; run it over the wire with a HostRunLog');
776
+ }
777
+ return Agent.follow({ completion: (hop) => this._completion(hop) }, { ...context, goal: undefined });
778
+ }
779
+ _completion(context) {
780
+ this._lifecycle.assertNotClosing();
781
+ if (this._lifecycle.draining) {
1793
782
  throw new Error('harness is suspended');
1794
783
  }
1795
- if (this._runtimeUnloadFailed) {
784
+ if (this._lifecycle.unloadFailed) {
1796
785
  throw new Error('Runtime unload failed; close the harness before loading models again');
1797
786
  }
1798
- const tracked = trackCompletion((signal) => this._busyStream(() => this._runCompletion({ ...context, signal })), context.signal, (run) => {
1799
- this._completionRuns.delete(run);
1800
- this._notifyEffectDrain();
1801
- });
1802
- const { iterator, run } = tracked;
1803
- this._completionRuns.add(run);
1804
- return iterator;
787
+ return this._lifecycle.trackCompletion((signal) => this._residency.busyStream(() => this._runCompletion({ ...context, signal })), context.signal);
1805
788
  }
1806
789
  async *_runCompletion(request) {
1807
790
  if (!this.opened)
1808
791
  await this.ready();
1809
- this._assertNotClosing();
1810
- if (this.suspended || this._runtimeDraining) {
792
+ this._lifecycle.assertNotClosing();
793
+ if (this.suspended || this._lifecycle.draining) {
1811
794
  yield { type: 'aborted' };
1812
795
  return;
1813
796
  }
1814
797
  const { boot, onStep, hostAppendTimeoutMs, requestDigestKey, ...provided } = request;
1815
798
  let modelId = request.model ?? '';
1816
799
  let key = null;
800
+ const releasePlugins = await this._plugins.hold(request.parentRunId !== undefined);
801
+ const detached = [];
1817
802
  try {
1818
803
  const runtime = async (run) => {
1819
804
  modelId = run.model ?? run.modelId;
1820
805
  const runContext = { ...run, model: run.model ?? run.modelId };
1821
- const lease = await this._completionRuntime(runContext);
806
+ const lease = await this._residency.completionRuntime(runContext);
1822
807
  if (!key) {
1823
- this._replying.push(lease.key);
808
+ this._residency.reply(lease.key);
1824
809
  }
1825
810
  key = lease.key;
1826
- return lease;
811
+ return { ...lease, services: this._plugins.ctx };
1827
812
  };
1828
813
  const args = { ...provided, lockOwner: this };
1829
- for await (const event of completion(runtime, args, {
814
+ for await (const event of CompletionEngine.run(runtime, args, {
815
+ hooks: this._hooks,
1830
816
  boot,
1831
817
  onStep,
1832
818
  hostAppendTimeoutMs,
1833
819
  requestDigestKey,
1834
820
  resumeRequest: provided,
1835
- onDetached: (pending, runId) => this._trackDetachedRun(pending, runId)
821
+ onDetached: (pending, runId) => {
822
+ detached.push(pending);
823
+ this._lifecycle.trackDetachedRun(pending, runId);
824
+ }
1836
825
  })) {
1837
826
  yield event;
1838
827
  }
1839
828
  if (key) {
1840
- this._modelFaults.delete(modelId);
829
+ this._residency.clearFaults(modelId);
1841
830
  }
1842
831
  }
1843
832
  catch (error) {
@@ -1846,15 +835,15 @@ export class Harness extends ReadyResource {
1846
835
  finally {
1847
836
  if (key) {
1848
837
  hlog('completion end', { model: modelId });
1849
- this._replying.splice(this._replying.indexOf(key), 1);
1850
- void this._imageRuntime?.unloadIdle().catch(noop);
1851
- void this._musicRuntime?.unloadIdle().catch(noop);
838
+ this._residency.replied(key);
839
+ void this._plugins.unloadIdle();
1852
840
  }
841
+ void Promise.allSettled(detached).then(releasePlugins);
1853
842
  }
1854
843
  }
1855
844
  async *_completionFailed(err, model, key) {
1856
- if (err instanceof AbortedError || this.suspended || this._runtimeDraining) {
1857
- hlog('completion aborted', { model, suspended: this.suspended || this._runtimeDraining });
845
+ if (err instanceof AbortedError || this.suspended || this._lifecycle.draining) {
846
+ hlog('completion aborted', { model, suspended: this.suspended || this._lifecycle.draining });
1858
847
  yield { type: 'aborted' };
1859
848
  return;
1860
849
  }
@@ -1862,7 +851,7 @@ export class Harness extends ReadyResource {
1862
851
  const name = err instanceof Error ? err.name : undefined;
1863
852
  hlog('completion failed', { model, ...resolutionDetail(err), err: message });
1864
853
  if (key && isSdkModelWedgedError(err)) {
1865
- const wedged = await this._evictWedgedModel(model, key);
854
+ const wedged = await this._residency.evictWedged(model, key);
1866
855
  yield completionErrorEvent(wedged.message, name, err);
1867
856
  if (wedged.fatal) {
1868
857
  process.exit(1);
@@ -1872,18 +861,9 @@ export class Harness extends ReadyResource {
1872
861
  yield completionErrorEvent(message, name, err);
1873
862
  }
1874
863
  }
1875
- async _completionRuntime(request) {
1876
- const releaseWork = this._enterWork();
1877
- try {
1878
- return await prepareCompletionRuntime(this, request);
1879
- }
1880
- finally {
1881
- releaseWork();
1882
- }
1883
- }
1884
864
  _residentEnhancer() {
1885
865
  return async (prompt, signal) => {
1886
- const lease = await leaseResidentModel(this._models, (model) => !isTranslationModel(model));
866
+ const lease = await leaseResidentModel(this._residency.pool, (model) => !this._residency.borrowed(model));
1887
867
  if (!lease) {
1888
868
  return null;
1889
869
  }
@@ -1904,69 +884,6 @@ export class Harness extends ReadyResource {
1904
884
  }
1905
885
  };
1906
886
  }
1907
- async _makeRoomForCompletion(model, { ctxSize, signal, deadlineMs = MODEL_ROOM_WAIT_MS } = {}) {
1908
- const roomed = await awaitModelCapacity(this._models, {
1909
- cap: this._completionModelCap,
1910
- deadlineMs,
1911
- signal,
1912
- evictable: (key) => !this._pinned.has(key) || modelOf(key) === model
1913
- });
1914
- if (!roomed) {
1915
- hlog('model room wait gave up', {
1916
- cap: this._completionModelCap,
1917
- loaded: loadedModels(this._models).length
1918
- });
1919
- }
1920
- await this._yieldPins(model, ctxSize);
1921
- return roomed;
1922
- }
1923
- async _evictWedgedModel(model, key) {
1924
- const faults = (this._modelFaults.get(model) ?? 0) + 1;
1925
- this._modelFaults.set(model, faults);
1926
- const leased = leaseCount(this._models, key) > 0;
1927
- const evicted = leased
1928
- ? false
1929
- : await evictModelWithin(this._models, key, { deadlineMs: WEDGED_EVICT_WAIT_MS });
1930
- hlog('wedged model evicted', { model, faults, evicted, leased });
1931
- if (leased) {
1932
- this._evictAfterLeases(model, key);
1933
- }
1934
- if (!evicted && !leased) {
1935
- return {
1936
- message: `${model} is stuck in device memory — restarting the model runtime`,
1937
- fatal: true
1938
- };
1939
- }
1940
- return {
1941
- message: faults > 1
1942
- ? `${model} keeps failing during inference on this device — it may need more memory than is available`
1943
- : `${model} failed during inference and was unloaded — try again`,
1944
- fatal: false
1945
- };
1946
- }
1947
- _evictAfterLeases(model, key) {
1948
- void evictModelWithin(this._models, key, { deadlineMs: WEDGED_EVICT_LEASED_MS })
1949
- .then((evicted) => hlog('wedged model evicted after leases', { model, evicted }))
1950
- .catch(noop);
1951
- }
1952
- async _busy(run) {
1953
- await this._idle.enter();
1954
- try {
1955
- return await run();
1956
- }
1957
- finally {
1958
- this._idle.exit();
1959
- }
1960
- }
1961
- async *_busyStream(run) {
1962
- await this._idle.enter();
1963
- try {
1964
- yield* run();
1965
- }
1966
- finally {
1967
- this._idle.exit();
1968
- }
1969
- }
1970
887
  }
1971
888
  function completionErrorEvent(message, name, error) {
1972
889
  const event = { type: 'error', message, ...completionErrorDetails(error) };