@qvac/harness 1.0.0-rc.0 → 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 +5 -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 +262 -485
  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/CHANGELOG.md CHANGED
@@ -8,6 +8,1169 @@ While the major version is `0`, a breaking change bumps the minor version.
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ### Added
12
+
13
+ - `slots` (and `llm.slots` through `spawnHarness`) lets one loaded chat model
14
+ decode that many completions at once, each with its own context: on the
15
+ 2B, four requests at `slots: 4` decode about 30% more tokens a second in all
16
+ and each starts in about 0.2 s instead of queueing. At `parallel` 2 or more,
17
+ `@qvac/llm-llamacpp` 0.53 to 0.56 re-sends every reply as one last chunk,
18
+ doubling the text and the tool calls; the harness drops that repeat in the
19
+ stream and in the SDK's final result. (#316)
20
+
21
+ - A spawned harness takes plugin options. `spawnHarness` and `harnessChild`
22
+ accept `pluginOptions: { speech?, mcp?: { servers? } }`, sent to the sidecar
23
+ as JSON in one argv slot. The sidecar builds `Speech` with
24
+ `pluginOptions.speech` (`tts: 'moss'`, `voice`, `dialogue`) and `McpPlugin`
25
+ with `pluginOptions.mcp.servers` (each may set `defer`), so a host that
26
+ spawns the harness reaches MOSS and deferred MCP tools. (#322)
27
+
28
+ - `Parakeet-TDT-1.1B-Q8_0` is a curated transcription model: it lists in
29
+ `/models` and `transcribe({ model: 'Parakeet-TDT-1.1B-Q8_0' })` loads it. It
30
+ transcribes English only, lowercase and without punctuation, so
31
+ `Parakeet-TDT-0.6B-v3-Q8_0` stays the default on every profile. It runs
32
+ without Core ML: SDK 0.21 does not fetch its encoder bundle yet.
33
+ `infraModelsFor` still keeps only the default transcription model.
34
+ - The `base` music choice runs the undistilled ACE-Step 1.5 base DiT (Q4_K_M)
35
+ on the shared text encoder, LM and VAE, at 50 steps by default. It needs a
36
+ GPU. Pick it with `modelChoice: 'base'` in the `generate_music` tool-config.
37
+ (#315)
38
+ - A loaded model reports the engine's own fit probe. `LoadedModel.fit`, in
39
+ `diagnostics().models` and `model-event.loaded`, carries the probe's verdict
40
+ (`fit`, `does-not-fit` or `unknown`), its reason, the plan (`nCtx`,
41
+ `nGpuLayers`, `nGpuDevices`) and the projected `deviceBytes` and `hostBytes`.
42
+ The pool reads it with `getLoadedModelInfo` after each load; it is report
43
+ only, and a failed read never fails the load. The harness now writes
44
+ `fitStubBudgetMs: 10000` into `qvac.config.json`, so an offline registry
45
+ falls back to the calibrated estimate in 10 s instead of the SDK's 40 s.
46
+ (#314)
47
+ - Deferred tools. A `ToolDefinition` with `defer: true` (and an optional `group`)
48
+ is listed by name in the SDK's `tool_search` instead of sending its schema;
49
+ the model loads it with `tool_search`, whose result appends to the history,
50
+ so the tool block and the prompt prefix stay fixed. A call to a tool not
51
+ loaded yet is refused with a reply to search first, and a re-ask after a load
52
+ is not forced. `McpServerConfig.defer` defers a server's tools under its name.
53
+ A tool named `tool_search` is refused while anything defers. (#311)
54
+ - MOSS text-to-speech, opt-in with `new Speech({ tts: 'moss' })`. It streams,
55
+ clones a voice from `voice` (a 24 kHz wav), or speaks a dialogue of up to five
56
+ `speakers` on a local MOSS-TTSD backbone; a dialogue does not stream. No device
57
+ profile picks MOSS. Its load evicts the idle chat model first, and a chat load
58
+ frees an idle MOSS. Downloading `MOSS-TTS-8B-F16` fetches its codec decoder
59
+ too. `SpeakResult.sampleRate` is the rate the SDK reports.
60
+ `SpeechService.defaultModel(profile)` names the model an unnamed `speak` loads.
61
+ (#312)
62
+
63
+ - An agent may run on its own model. `AgentConfig.model` (and `model` on the
64
+ wire's agent knobs) names it; absent, the agent runs on the request's
65
+ `model`. It applies to a single run, to every hop of a chain including the
66
+ entry agent, and to `delegate` children through `base.agent`, so triage on
67
+ one model can hand a health question to an agent on `MEDPSY_1_7B`. A resume
68
+ still matches on the `model` the host first sent.
69
+
70
+ - An external agent target can run on the user's own login. `login: 'user'`
71
+ on an `ExternalAgents` target keeps the user's `HOME`, sets no
72
+ `CODEX_HOME` or `CLAUDE_CONFIG_DIR`, and runs `claude` without `--bare`, so
73
+ a CLI the user signed in to works with no API key. It then runs with the
74
+ user's own settings and plugins, and bills their subscription.
75
+ `claude` also gets `--setting-sources user --strict-mcp-config`, so the
76
+ workdir's own settings and MCP config never load. The default,
77
+ `'isolated'`, is unchanged. `DelegateTarget.policyVersion` folds into the
78
+ `delegate` tool's, so changing a target's login refuses a resume; every
79
+ existing `delegate` `policyVersion` changes once with this, so a durable run
80
+ with external targets saved before the upgrade refuses to resume.
81
+
82
+ - `CodingPlugin` runs on macOS. `SeatbeltSandbox` provides the `sandbox`
83
+ service: each line runs under `sandbox-exec` with the project as its write
84
+ root and a `TMPDIR` that lasts until the workspace closes. It is not
85
+ isolated, so every coding call asks. `shell_jobs` stops a job from the host:
86
+ SIGTERM to its group, then SIGKILL, and a job runs as long as what its line
87
+ started. The coding state moves under the provider's `TMPDIR`.
88
+ - **Breaking:** `SandboxWorkspace` gains `start(command, { cwd? })`, a
89
+ background line the provider holds, returning `{ exited, stop() }`. A
90
+ custom `SandboxService` must implement it. `SeatbeltSandbox` now declares
91
+ `provides: ['sandbox']`, so composing it beside another sandbox provider
92
+ fails at construction; leave one out.
93
+
94
+ - MCP servers as a plugin. `./plugins/mcp` exports `McpPlugin`, named `mcp`.
95
+ `servers: [{ name, url, auth? }]` lists each server's tools when the harness
96
+ opens and adds them as `<server>__<tool>` tools with the server's schema;
97
+ each asks for approval. A server that fails or does not answer within
98
+ `setupTimeoutMs` (10 s) adds no tools, and the harness still opens.
99
+ `auth: { tokenCredentialKey }` sends that credential to that server only.
100
+ `generic: true` adds `mcp_call` and the skill catalog's mcp operations.
101
+ `PluginContext.fetch` is a guarded fetch for a plugin's setup, and
102
+ `Tools.operations(catalog, transports)` compiles a catalog's operations over
103
+ the transport tools given. (#277)
104
+
105
+ - `@qvac/harness/tools` exports `Tools`. `Tools.product(options)` returns the
106
+ product tool list the sidecar serves, in the same order, with the fs tools
107
+ fenced off the storage root it derives from `options.sdkHome`; it throws
108
+ without one. The options also take `skillsDir`, `skillCatalog` and
109
+ `credentialStore`. Operation tools and
110
+ credentials need `skillCatalog`, and `skill` needs `skillsDir`.
111
+ `Tools.deniedRoots(sdkHome)` is the deny list. (#273)
112
+ - `PluginContext.deniedRoots` hands every plugin setup the folders the host
113
+ fences: the storage root and spill dir a harness derives from `sdkHome`, or
114
+ `PluginRegistryOptions.deniedRoots` for a registry built directly; frozen,
115
+ canonical at setup like `ExecutionContext.deniedRoots`, so a symlinked
116
+ storage root matches the real path a plugin resolves, and empty when none is
117
+ known. (#296, #299)
118
+
119
+ - `Tools.bundledSkillsDir()` from `@qvac/harness/tools` writes the bundled
120
+ skills to a private dir named by their content hash, and returns its path,
121
+ for an in-process host such as the mobile worklet. `@qvac/harness/skill-manifest`
122
+ exports `credentialSlots(entry)`, which unions an entry's `credentials` and
123
+ `requires.credentials` into any-of slots (`a|b`). (#283)
124
+
125
+ - Claude Code hook files. `./plugins/command-hooks` exports `CommandHooks`,
126
+ a plugin whose config is the `hooks` object of a `settings.json`. Each
127
+ `type: "command"` hook runs under `/bin/sh -c` on its harness phase
128
+ (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `UserPromptSubmit`,
129
+ `Stop`, `PreCompact`, `SubagentStart`, `SubagentStop`), reads the event as
130
+ JSON on stdin, and answers by exit code (2 blocks) or stdout JSON
131
+ (`permissionDecision`, `updatedInput`, `additionalContext`,
132
+ `decision: block`, `continue: false`). The default timeout is 60 s, and a
133
+ timeout kills the command's process group. Other exit codes fail closed.
134
+ `SessionStart`, `SessionEnd`, `Notification` and `PermissionRequest`
135
+ entries load but never run. A `PreToolUse`, `PostToolUse` or
136
+ `PostToolUseFailure` matcher that is not a valid regex fails `validate()`.
137
+ A config with a `Stop` command also registers `command-hooks:Stop:end` on
138
+ `runEnd`; when no other `runEnd` hook is loaded, this adds a `hook:runEnd`
139
+ step to the run log of each run that started. (#261)
140
+
141
+ - Hooks reach further on the same fold. `HarnessHook.matcher` scopes a tool
142
+ hook to tool names (full-match regex) and `timeoutMs` bounds a hook (no
143
+ default). New phases: `promptSubmit` (the prompt and each mid-run input; a
144
+ rejected input emits `input-rejected` and the run goes on), `toolFailure`
145
+ (every call that did not succeed), `stop` (`{ continue }` takes one more
146
+ round within the round limit) and `preFold` (`{ instructions }` for the
147
+ summary). New results: `{ permission: 'allow' | 'deny' | 'ask' }` on
148
+ `preToolCall` (a plugin's `allow` is dropped, and no `allow` gets past plan
149
+ mode or the outbound guard), `{ context }` for the model, and `{ halt }`,
150
+ which ends the run as a `HookHalt` failure (on a mid-run input it rejects
151
+ the input instead). Each new phase is journaled, so a
152
+ resume replays the decision. (#260)
153
+
154
+ - macOS sandbox. `./plugins/sandbox-macos` exports `SeatbeltSandbox`
155
+ (`{ preset: 'read-only' | 'workspace-write', network }`). Its `.shell` runs
156
+ exec's shell under `sandbox-exec`, writing only to the run's local write
157
+ roots and a temp dir. Its `.plugin` checks the platform and the profile at
158
+ start, and provides no `sandbox` service yet. Exec passes the write roots to
159
+ a composed shell as `ExecutionContext.writeRoots`, and `createShellAdapter`
160
+ takes a `name`. Linux and Windows follow. (#254)
161
+ - Approval quote. `ToolDefinition.quote(args, ctx)` returns the confirmation a
162
+ person reads before an approvable call runs, such as its cost, or null for
163
+ none, and `ApproveFn` receives it as `quote`. Over the wire, `approval-ask`
164
+ carries it in its existing `question` field, and `connectHarness` hands it
165
+ back as `quote`; no schema field is added. For qvac-core: no API break. (#183)
166
+ - Plugins pack as their own packages. `image`, `knowledge`, `music`,
167
+ `obsidian`, `sandbox-vm`, `speech` and `weather` each have a
168
+ `qvac-plugin-<name>` manifest in `plugins/<name>/`, and
169
+ `prepare-publish --plugin <name>` points it at its `dist-lib/`, rewrites
170
+ its imports of the core to `@qvac/harness/...` and sets its `@qvac/harness`
171
+ peer to `^<root version>`.
172
+ Nothing is published yet. The root `exports` map gains the 11 keys the
173
+ plugins import: `./lib/contract/index.ts`, `./lib/contract/knowledge.ts`,
174
+ `./lib/contract/models.ts`, `./lib/contract/speech.ts`, `./lib/guards.ts`,
175
+ `./lib/helpers/load-stall.ts`, `./lib/helpers/retry-memo.ts`,
176
+ `./lib/helpers/spawn-path.ts`, `./lib/log.ts`, `./lib/models/context.ts` and
177
+ `./lib/models/model-source.ts`. They are internals for the plugins, not a
178
+ stable API, and can change in a minor release. (#187)
179
+ - A run with `agents` takes `CompletionContext.input`. `Agent.follow` gives each
180
+ hop its own queue, so a steer or follow-up reaches the running hop, and input a
181
+ hop leaves unacked at a transfer goes to the next hop first. (#247)
182
+ - `@qvac/harness/addon-externals` exports `scripts/addon-externals.cjs` and its
183
+ types, so a host seeds `copyAddonExternals` with `deferredAddonPackages(bundle)`
184
+ instead of keeping its own copy of the script. (#228)
185
+ - `QuickJs` from `./plugins/quickjs` runs `language: "javascript"` in QuickJS
186
+ WASM as an exec language: compose `quickjs.language` into
187
+ `createExecTool({ languages })` and pass `quickjs.plugin`. A run has no files,
188
+ network, modules or tools, only `console`, so it is a read. Each call gets a
189
+ fresh runtime with memory and stack limits, and its deadline is the smallest
190
+ of `timeoutMs`, the run budget and 30 s. It runs on the harness thread and is
191
+ desktop-only until mobile is verified. Code mode runs on `QuickJs.run` beside
192
+ it. (#232)
193
+ - The harness folds a chat when its window runs short (what `@qvac/core` called
194
+ compaction). `lib/fold/` holds the trigger tiers on `cacheTokens / ctxSize`,
195
+ the 4,096 floor, the summary turn and the summarizer prompt. A run folds
196
+ before its first round when the last reading for its `cacheKey` is past its
197
+ tier, and on an overflow of the whole history before the ladder drops turns,
198
+ then retries the round. After text was shown, an overflow still folds and
199
+ deletes the key, and the run fails as before. The fold keeps the last user
200
+ turn and this run's own rounds, deletes the chat key once, records the
201
+ summarizer request in the run log, and emits `fold` `{ phase: 'start' }` and
202
+ `{ phase: 'done', summary, throughId, foldedTurns }`. `ChatMessage.id` (and
203
+ `id` on the wire message) is a new optional opaque field: `throughId` is the
204
+ id of the last folded message, and a history without it does not fold. For
205
+ qvac-core: send each message's last chunk id, store the fold from the `done`
206
+ event, and turn its own fold off in the same release; the decision record
207
+ lists what core deletes and keeps. (#241)
208
+ - `@qvac/harness/plugins/coding`: `CodingPlugin` adds `shell`, `shell_jobs` and
209
+ `write_file` in a new `coding` toolset, run in a sandbox provider. `shell` keeps
210
+ the cwd and exported variables between calls of a run, allows pipes and
211
+ redirects, waits 300 s by default (1800 s at most, cut to the run budget) and
212
+ starts background jobs that `shell_jobs` lists, reads from an offset and stops;
213
+ a run's jobs stop when it ends. `write_file` creates or overwrites a file in the
214
+ run's single write root. The plugin needs the new `sandbox` service
215
+ (`SandboxService` in `lib/contract/sandbox.ts`, exported as
216
+ `./lib/contract/sandbox.ts`); no provider ships yet. A tool is a read only on an
217
+ isolated provider under the host's `read: CodingPlugin.TOOLS` grant and outside
218
+ plan mode, which refuses it. qvac-core: opt in by passing a provider and the
219
+ plugin, grant one writable directory, pass `maxToolRounds`, and label the
220
+ `coding` toolset. A harness given `sdkHome` makes `shell` and `write_file`
221
+ refuse a workspace that holds the storage root or sits inside it, since the
222
+ provider mounts the whole workspace; `deniedRoots` adds folders to that
223
+ list. (#179, #279, #296)
224
+ - Code mode: `new CodeMode({ quickjs })` from `./plugins/code-mode` adds
225
+ `run_code`, a script that calls the run's other tools as
226
+ `await tools.<name>(args)`. Compose it as `{ plugin, read: ['run_code'] }`
227
+ beside `quickjs.plugin`. Each inner call takes the same hooks, policy checks,
228
+ plan-mode refusal and approval as a direct call, one at a time, at most 16 per
229
+ script. `QuickJs.run` is the runtime under it. New `ToolDefinition.callsTools`
230
+ and `minCapabilityProfile`; `run_code` is offered from `mid` models only. For
231
+ qvac-core: no API break; an inner approval carries the call id `<outer>.<n>`.
232
+ (#237)
233
+ - `CompletionContext.goal` keeps a run going across answers until the goal is
234
+ met: `{ objective, rounds?, ms?, tokens? }`. A goal is met when every step of
235
+ the run's plan is done, and a goal run is always offered `update_plan`. While
236
+ it is unmet, the run adds a goal turn after each answer and continues: the
237
+ goal nudge (`wording.goalContinuation`), the objective and the open plan.
238
+ Queued input still comes first. The run stops when its round budget
239
+ (`rounds`, 40 by default), its deadline (`ms`) or its generated tokens
240
+ (`tokens`, checked when an answer ends) run out. Each continuation and the
241
+ end emit a `goal` event `{ status, turn, round, text? }`, with `status` one of
242
+ `open`, `met`, `rounds`, `time` or `tokens`; `text` is the turn the run
243
+ added. A resume keeps the run's own goal. A run seeds its plan from the last
244
+ `update_plan` call in `messages`, unless that plan was finished. Single runs
245
+ only: a run with `agents` drops the goal, and a goal with a `responseFormat`
246
+ is refused, since a structured answer has no `update_plan`. The goal crosses the wire in the
247
+ start payload, and the event as `goal`. For qvac-core: no API break; a goal
248
+ run has several answers, which a host splits on `goal` events, and it stores
249
+ each goal turn from the event's `text` so that the next request replays it.
250
+ (#240)
251
+ - `update_plan` keeps a plan in the run: a list of up to 12 steps, each
252
+ `pending`, `in_progress` or `done`, that the model replaces on each call. The
253
+ run keeps the plan in its machine context, so a pause, resume or replay
254
+ keeps it. The plan is shown to the model on the continuation nudge while a
255
+ step is open, and is never put in the system prompt. Turn it on with the
256
+ agent knob `plan`, which is off by default. `CompletionContext.planMode`
257
+ starts a run in plan mode. Plan mode refuses every write except
258
+ `update_plan` with `submit: true`, which goes to the approver with the
259
+ numbered steps as its `quote`. Once the submit is approved, or auto-approved
260
+ under `skip-all`, writes run. With no approver, the run stays plan-only.
261
+ Outside plan mode a submit is an ordinary update and asks no one.
262
+ `planMode` crosses the wire in the start payload, and `plan` crosses it in
263
+ the agent frame. For qvac-core: no API break. The continuation nudge in a
264
+ captured inference call can now end in a `Plan:` block. (#234)
265
+ - Oversized host shell output spills to a run-scoped file the model reads back.
266
+ When a run has `read_files`, an exec stream over `maxOutputChars` is written
267
+ whole to `<tmp>/qvac-harness-spill-<user>/<runId>/`, and its marker carries a
268
+ locator: `…[N chars omitted; read_files path=<abs> startLine=<n>]…`. The
269
+ directory is removed when the run ends, except after a durable pause, and a
270
+ boot sweep reclaims what a crash left. For qvac-core: no API break, but stored
271
+ exec `stdout` and `stderr` can now carry the locator, and `deniedRootsFor`
272
+ returns two roots, the storage root and the spill root. With no `read_files`
273
+ the marker is unchanged. (#238)
274
+ - `CompletionContext.input` sends turns to a running run. A `steer` is
275
+ delivered at the next tool boundary, in place of the continuation nudge; a
276
+ `follow-up` continues the same run after its answer, under the run's round
277
+ budget and deadline. Each delivery emits an `input` event with the input's
278
+ `id`, `text` and the `round` it precedes; input with no such event was not
279
+ delivered. Over the wire it travels as `steer` and `follow-up` frames and an
280
+ `input` event. Text only, and for single runs: a run with `agents` ignores it. (#186)
281
+ - `RunLog.watch()` follows a run live from the steps the host commits. Feed it
282
+ with `watch.step(step)` after an in-process `onStep` commit, or wrap a
283
+ spawned run's `HostRunLog` with `watch.host(runLog)`. `views()` streams one
284
+ view per record: the state, the transition trace with its guards, the
285
+ approval, `pendingCall`, `currentCall`, `toolQueue`, `outcome` and the
286
+ inspector's lines. `html()` streams the inspector page, with the current
287
+ state highlighted and no script. A bad step becomes an error view and never
288
+ fails the run. `step()` follows a single run, so an in-process host makes a
289
+ new watcher per run. Through `host()` one watcher follows runs one after
290
+ another, such as a handoff's hops; concurrent runs need one watcher each.
291
+ `RunLog.renderHtml` now tags each graph node with `data-state`.
292
+ `examples/run-log/live.ts` replaces `examples/run-log/tail.ts`. (#236)
293
+ - **Breaking:** the run log records every model request. Before each send,
294
+ the engine appends a `request` record (`round`, `attempt`, `droppedTurns`,
295
+ `keep`, `messages`, `tools`, `params`) and waits for the host to take it, so
296
+ the log holds every request the model saw, overflow steps and grammar or
297
+ forced-call retries included. A record carries the messages the previous
298
+ request did not (`keep` counts the ones it shares), messages identical to the
299
+ run request's point at them by index, and the tool block is written once per
300
+ process under its sha256 `ref`. The messages are redacted as the
301
+ checkpoint history is; the tool block and generation params are kept as
302
+ sent. `RunLog.requests(core)` rebuilds each request, byte for byte where
303
+ redaction changed nothing, with its `index`, `round`, `attempt` and
304
+ `droppedTurns`, and `RunLog.inspect` and
305
+ `renderHtml` list them; `requestRecord` (`--request` in
306
+ `examples/run-log/inspect.ts`) prints one in full. `EngineOperationPort`
307
+ gains `recordRequest`. For qvac-core: a host run-log codec that allows only
308
+ known record types must accept `request` before it moves to this version;
309
+ `RUN_LOG_VERSION` stays 1. (#235)
310
+ - `ToolDefinition.concurrent` lets a read tool run alongside the round's other
311
+ opted-in reads. Up to four that need no approval run together; a write, a
312
+ call that needs approval and any tool that does not opt in run alone. Results
313
+ land and events go out in the model's order, each event with its own
314
+ `callId`. `read_files`, `grep` and `file_glob` opt in. (#193)
315
+ - A completion follows an agent's handoffs. `CompletionContext.agents`, in
316
+ `index.ts` and `./lib/contract-types.ts`, holds the agents `agent` may hand
317
+ to, by id. When a run ends with `transfer_to_agent`, the completion emits a
318
+ `transfer` event (`from`, `to`, `reason`, the new `TransferEvent`) and goes on
319
+ as the next agent's run, with the reason noted on the last user turn. Each
320
+ hop is a run of its own: hop k runs as `<runId>/<k>-<agent>` with cache key
321
+ `<cacheKey>/a-<agent>`. After three transfers the last agent must answer.
322
+ Every event in a chained run carries `agent`. Over the wire, `agent-knobs`
323
+ carries `handoffs` (a new `agent-handoff` struct), and the client runs each
324
+ hop as its own wire completion with its own `HostRunLog` lease. In process,
325
+ `agents` with `boot` or `onStep` throws. The loop is `Agent.follow`. For
326
+ qvac-core: pass `agents` to `harness.completion()` to hand a run on, and
327
+ resume a hop with its own `runId`. (#233)
328
+ - `LspPlugin` from `./plugins/lsp` gives a run one read tool, `lsp`, over
329
+ the language servers a host configures: `definition`, `references`,
330
+ `hover`, `symbols` (a file's outline, or a project search with `query`)
331
+ and `diagnostics`. A position is a 1-based `line` and the `symbol` on it.
332
+ Paths are scoped like the file tools: a harness given `sdkHome` fences the
333
+ storage root (#296) and the config's `deniedRoots` adds to it;
334
+ locations and hover text from a denied root are not shown. The server
335
+ starts through `/bin/sh`, so a bad command is an error and never a failed
336
+ spawn. One server runs per language and granted root, is shared, stops after
337
+ `idleMs` and on close, and restarts after a crash. Add
338
+ `{ plugin: new LspPlugin(), config: { servers }, read: ['lsp'] }` to
339
+ `HarnessOptions.plugins`, with absolute commands; TypeScript 7's
340
+ `tsc --lsp --stdio` is the tested server. Nothing wires it yet (#179).
341
+ (#202)
342
+ - `HarnessOptions.llmLoad` (and `llm.llmLoad` for a spawned harness) passes
343
+ llama.cpp load knobs to every completion load: `threads`, `batch-size`,
344
+ `ubatch-size`, `kv-offload` (`false` only) and `n-cpu-moe`. Each one keys
345
+ the model pool. Unset, the SDK defaults apply; the harness sets none until
346
+ they are measured (#184). (#194)
347
+ - Plugin services share one context per harness. A plugin reads the services
348
+ it names in `needs` or `provides` through `ctx.services`; the core keeps the
349
+ context private. The framework lives in `lib/plugins/`, with concrete
350
+ implementations in `plugins/`. `@qvac/harness/plugins` exports the framework,
351
+ `PluginRegistry`, with `PluginRegistry.API_VERSION` and
352
+ `PluginRegistry.loadAddons` as statics; augment `Services` through
353
+ `@qvac/harness/plugins/context`. Plugins can register cleanup immediately
354
+ with `ctx.onDispose`, including during partial setup that later fails. Startup rolls back before rejecting, and close waits
355
+ for active setup while skipping later plugins. The context stays local to
356
+ the process and survives runs and suspend/resume. (#171) `./plugins` does
357
+ not export the contract types: import `AddonLoaders` from the root or
358
+ `./lib/contract/index.ts`, and `ExecLanguage`, `ExecRoute` and `ExecShell`
359
+ from the root or `./lib/contract/exec.ts`. (#284)
360
+
361
+ - Knowledge is a plugin: `knowledgePlugin` from `./plugins/knowledge` keeps
362
+ one TurboVec index for the harness, fed by the host through
363
+ `knowledgeUpsert`, `knowledgeRemove`, `knowledgeSearch` and
364
+ `knowledgeStatus` (also over hrpc). An artifact whose vectors name the
365
+ local embedder is indexed with no re-embedding; any other is re-embedded
366
+ and its vectors handed back. `CompletionContext.knowledge = { scopes }`
367
+ grants a run its scopes: the hits are injected into the last user turn
368
+ before the first round, and with `tool: true` the plugin adds
369
+ `knowledge_search`. Absent, a run retrieves nothing. A hit scoring under
370
+ `minScore` (cosine, default 0.4) is dropped, so a run with no related
371
+ knowledge injects nothing and keeps its cache key. The core lends plugins
372
+ a second service, `embed`. `spawnHarness({ knowledge: { dir, model } })`
373
+ adds the plugin to the bundled sidecar. (#197)
374
+ - `createExecTool({ shell })` takes an `ExecShell`, where shell lines run
375
+ after every exec check; the default is the host shell (`name: 'host'`). The
376
+ shell name folds into exec's `policyVersion`. `VmShell` from
377
+ `./plugins/sandbox-vm` runs the shell in a barevisor VM with no network, no
378
+ disk and no mounts, from a prebuilt guest image the host ships: pass `shell`
379
+ to `createExecTool` and `plugin` in `HarnessOptions.plugins`. It is opt-in,
380
+ nothing wires it, and it is not a sandbox for untrusted code. **Upgrade:**
381
+ `bare-process` moves to 4.5.1 (barevisor needs it), which adds the native
382
+ addon `bare-posix`; a host that pins `bare-process` or audits its addons
383
+ follows. Exec's `policyVersion` changes once, so a run paused before the
384
+ upgrade does not resume. (#178)
385
+ - Python is a plugin. `createPython({ loadPyodide, network })` from
386
+ `./plugins/python` returns `{ language, plugin }`: pass `language` to
387
+ `createExecTool({ languages })` and `plugin` in `HarnessOptions.plugins`,
388
+ whose teardown closes the python worker. The entry also exports
389
+ `stageInputs`, `runPython` and `closePythonWorker`. (#174)
390
+ - Plugins: `HarnessOptions.plugins` takes `{ plugin, config, read }` entries. A
391
+ `HarnessPlugin` declares its `name`, `api` (`PLUGIN_API_VERSION`), the
392
+ services it `provides` and `needs`, an optional `validate(config)`, and a
393
+ `setup(ctx, config)` that returns tools, hooks, services and a `teardown`.
394
+ The list is checked when the `Harness` is constructed; plugins start on open
395
+ in dependency order and are torn down in reverse on close. A plugin tool is a
396
+ write unless the host lists it in `read`, it keeps `autoApprove` only then, its
397
+ toolset must be one of `TOOLSETS` and its name may not repeat another tool on
398
+ the harness, `transfer_to_agent` included. A granted tool with
399
+ `autoApprove: true` runs unasked whatever its classifier says, so grant
400
+ `read` only to a tool you would let run unasked. A plugin's `preToolCall`
401
+ hooks run before the harness's hooks, so the gates check its arg rewrites; its other
402
+ hooks run after them. `tools()` now waits for `ready()`, as `describe()`
403
+ does, and `toolNames` and `diagnostics()` list plugin tools only after it,
404
+ which a `spawnHarness` host never sees. With no plugins nothing changes. (#171)
405
+ - A tool declares that it reaches the network with `egress(args)`, which
406
+ returns the URL a call targets, or `null` when that is not known before the
407
+ call. `HookPipeline.EgressGuardHook` now checks every tool that declares it,
408
+ whatever its name, and no tool that does not: `http_request`, `web_fetch` and
409
+ `mcp_call` declare it. A host tool named `http_request` built by hand must
410
+ declare `egress` to keep the pre-call check. A plugin tool that declares
411
+ `egress` gets `ctx.fetch`, a guarded fetch that reaches only the host its
412
+ call's `egress` returned (none when that is `null`), refuses private hosts on
413
+ every hop, stops with the call and refuses everything in sandbox mode. (#172,
414
+ #224)
415
+ - A run sets its tool-round limit with `maxToolRounds` (an integer of 1 or
416
+ more, default 10), in process and on the wire. In process it also sets the
417
+ model-facing text with `wording: { toolContinuation, toolDenied, toolCutOff }`:
418
+ the nudge after a tool round, the result a declined call returns and the
419
+ result of a call refused because the response hit the length limit. A resume
420
+ keeps the values the run started with. An invalid `maxToolRounds` throws, in
421
+ process and from `connectHarness` before the frame is sent; 0 on the wire
422
+ means unset. (#159)
423
+ - The `metrics` event reports speed per round and per run: `rounds[]` with
424
+ each round's tokens, prefill and decode rates, time to first token, wall
425
+ time and stop reason; `tools[]` with each tool's wall time; and `modelMs`
426
+ and `toolMs`, the wall time spent in rounds and in tools. An in-process run
427
+ without `onStep` that is stopped by its `signal` now sends `metrics` for the
428
+ rounds it finished; a durable run or one over the wire sends none. The
429
+ README's "Speed stats" section describes each field. (#195)
430
+ - A host can replay an earlier turn's tool work: an assistant message may carry
431
+ `toolCalls: { id, name, arguments }[]`, and a `tool` message `toolCallId` and
432
+ `name`, with the result as JSON in `content`. A round's calls go in one
433
+ assistant turn, grouped by the events' `round`, then one `tool` message per
434
+ call. The harness renders them as the run that made the calls sent them, so a
435
+ follow-up question is answered from the earlier result and the KV cache's
436
+ message count still lines up. A replayed `skill` result becomes the reload
437
+ stub; a replayed preload goes back into its user turn, and a replayed direct
438
+ web search gets no nudge. In process and on the wire. It is opt-in: a host
439
+ that sends plain turns and the `skillLoadedTurn` stub, as qvac-core does,
440
+ works as before. **Upgrade:** switching rewrites history before the tail,
441
+ which a warm cache ignores and mis-slices, so delete each chat's KV cache
442
+ when it switches, as after a fold; that chat's next turn cold-primes once.
443
+ (#169)
444
+ - `CompletionEngine` takes an optional `outbound` guard
445
+ (`new CompletionEngine(sdk, { outbound })` or
446
+ `CompletionEngine.run(sdk, args, { outbound })`), defaulting to the built-in
447
+ one. (#166)
448
+ - `list()` rows for curated chat models that are not loaded carry `fit`,
449
+ `fitBasis` and `fitEvidence`, from one batched SDK `assessModelFit` ask that
450
+ is kept until a model loads or unloads, or the harness resumes. The
451
+ `model-info` wire fields are new and optional. qvac-core can show "fits" for
452
+ `likely-fits`, "too large" for `likely-too-large` and nothing for `unknown`,
453
+ and suggest the largest `likely-fits` row; none of them blocks a download. (#196)
454
+ - A curated chat model with no context set by the agent or `contextSize` steps
455
+ down from today's tier to 32768, 16384 or 8192 on its first load when the
456
+ SDK says the tier would not fit and confirms a lower one from calibration or
457
+ the engine's fitter. The choice is kept for the process, and the load, the
458
+ run's budget and the fit ask read it from one function. A cold run's
459
+ `metrics.ctxSize` is the context the model loaded with. A manual `loadModel`
460
+ steps down the same way and refuses only when no rung is confirmed. (#196)
461
+ - The load decision for a curated chat model passes its registry coordinates,
462
+ so the SDK runs the engine's own fitter (`native-fit`) once per load. Pin
463
+ re-checks and list rows stay on the cheap calibrated estimate. (#196)
464
+ - An embedding load that the SDK says would not fit unloads idle chat models
465
+ that are not pinned and that no reply is using. (#196)
466
+
467
+ - Ternary Bonsai 2 27B joins the curated catalog in two builds,
468
+ `Ternary-Bonsai-2-27B-PQ2_0` (7.2 GB) and `Ternary-Bonsai-2-27B-PTQ1_0`
469
+ (5.9 GB), each with its vision projection. Both sit in the `high` tier, by
470
+ their memory footprint rather than their parameter count. As a Qwen3.8-27B
471
+ fine-tune whose name the SDK's dialect router does not recognise, it parses
472
+ tool calls as `qwen35`; a catalog entry can now name its tool dialect.
473
+
474
+ ### Changed
475
+
476
+ - **Breaking:** `@qvac/harness/plugins/speech` exports `Speech` and the types
477
+ it takes (`SpeechOptions`, `SpeechDialogue`, `SpeechSpeaker`, `TtsEngine`)
478
+ and nothing else. `buildWavBuffer`, `packSamples`, `speakOnce`,
479
+ `speakStreamOnce`, `transcribeStreaming`, `normalizeForSpeech`,
480
+ `SPEECH_LEXICON`, `needsResample`, `resampleForTranscription`, `wavFormat` and
481
+ `TARGET_SAMPLE_RATE` are internal; qvac-core imports none of them. (#312,
482
+ #217)
483
+
484
+ - **Breaking:** translation is a plugin. The translate runtime, the NMT
485
+ catalog and the `translation` and `translation-nmtcpp` addon loaders moved
486
+ from `lib/` to `plugins/translation/`, exported as
487
+ `@qvac/harness/plugins/translation` (`TranslationPlugin`, package
488
+ `qvac-plugin-translation`). A `Harness` built without it answers
489
+ `invoke({ capability: 'translate' })` with
490
+ `translate is not available on this device` and loads no NMT model or
491
+ binding. `translate` is still never
492
+ in `toolNames`, `tools()` or an agent's tool list: it comes from the new
493
+ `PluginSetup.capabilities`, tools that only `invoke` reaches, whose names
494
+ the registry checks like a tool's and which keep their own `effect`.
495
+ `ModelHost.completionModel(model, signal)` loads a GGUF through the chat
496
+ pool and returns `{ modelId, release }`; the core never leases a model
497
+ borrowed this way as the resident chat model, which retires the
498
+ `TranslatePsy-` name check from the core. The bundled sidecar passes the
499
+ plugin, so a `spawnHarness` host is unchanged. **Upgrade:** a host that
500
+ constructs `Harness` itself adds `new TranslationPlugin()` to `plugins`,
501
+ with `import { TranslationPlugin } from '@qvac/harness/plugins/translation'`.
502
+ The root exports `./lib/helpers/clean-answer.ts` and
503
+ `./lib/capabilities/detect-language.ts` for the packed plugin. (#275)
504
+ - **Breaking:** the translation catalog is `TranslationPlugin` statics. The
505
+ root no longer exports them: `NMT_TO_ENGLISH`, `NMT_FROM_ENGLISH`,
506
+ `EURONANO_LANGUAGES`, `SLM_LANGUAGE_CODES` and `SLM_LANGUAGE_NAMES` are
507
+ `TranslationPlugin.NMT_TO_ENGLISH` and so on, `translationPlanFor(from, to)`
508
+ is `TranslationPlugin.planFor(from, to)`, and the `TranslationPlan` type
509
+ (with `TranslationRefusal`) comes from `@qvac/harness/plugins/translation`.
510
+ There are no deprecated aliases. (#275)
511
+ - A translation pack no longer stays resident across chat turns:
512
+ `TranslationPlugin` frees it on the same idle sweeps as the image and music
513
+ models, when a chat turn ends and when a chat model loads, and never while
514
+ a translation is running or waiting. The next translation reloads it. (#275)
515
+ - **Breaking:** `web_search` is a plugin. `Tools.product` no longer includes it;
516
+ `WebSearchPlugin` from `@qvac/harness/plugins/web-search` provides it, with
517
+ the same name, toolset, description and schema. Its options are `engines`
518
+ (a subset, in tie-break order; default all seven), `maxResults` (overrides
519
+ the 8 or 12 the context window picks) and `read`. `validate()` refuses an
520
+ unknown engine, an empty list and a `maxResults` that is not a positive
521
+ integer. The engines now fetch through the plugin `ctx.fetch`, so each
522
+ request is checked for a private address, and a redirect to a host the call
523
+ did not declare is refused: an engine that redirects to a consent or region
524
+ page fails for that call. `ToolDefinition.egress` may return a list of URLs;
525
+ the egress hook checks each one, and the plugin fetch admits the hosts they
526
+ name. The tool moves after `exec` in the prompt prefix, which changes cache
527
+ keys and bench comparability. `lib/web-search/html-helpers.ts` and
528
+ `user-agents.ts` move to `lib/helpers/`. **Upgrade:** qvac-core and the
529
+ mobile worklet add `new WebSearchPlugin({ read: ['web_search'] })` to
530
+ `plugins`, next to the `Tools.product` list; without the read grant every
531
+ search asks for approval. Hosts that use `spawnHarness` get it from the
532
+ sidecar. A run paused on a `web_search` call does not resume across the
533
+ upgrade. (#276)
534
+
535
+ - **Breaking:** plugins are an array of instances, and the harness builds `exec`
536
+ from what they declare. `HarnessOptions.plugins` is `readonly HarnessPlugin[]`;
537
+ `PluginEntry` and `{ plugin, config, read }` are gone, and so are the `config`
538
+ arguments of `validate` and `setup`. A plugin's options go to its constructor
539
+ and the host's read grant is a constructor option carried as
540
+ `HarnessPlugin.read`. Every shipped plugin is a class: `Speech`, `Weather`,
541
+ `Image`, `Music` and `Knowledge` replace the object constants, `Python`
542
+ replaces `createPython()`, and `ObsidianRoute`, `VmShell`, `SeatbeltSandbox`,
543
+ `QuickJs` and `CodeMode` implement `HarnessPlugin` with no `.plugin` pair;
544
+ `SeatbeltSandbox.name` is now the plugin name `sandbox-macos`, and the
545
+ `seatbelt:<preset>:<network>` label is `.shell.name`.
546
+ `CommandHooks` takes the hooks object first, `new CommandHooks(hooks, { cwd })`;
547
+ `LspPlugin` and `ExternalAgents` take their options in the constructor.
548
+ `PluginSetup.exec` declares the languages, routes and shell a plugin adds;
549
+ with `HarnessOptions.exec` (`true` or
550
+ `{ spawn, killProcess, realpath, policyVersion }`) the harness builds the
551
+ `exec` tool from them, with its own `skillsDir` and skill settings, and
552
+ rebuilds it on every dynamic swap. Two
553
+ shells fail the start naming both; a host `exec` tool beside a contributing
554
+ plugin fails the start naming the plugin. `HarnessOptions.sdkHome` is the SDK
555
+ home, from which the harness derives the denied roots of the exec it builds.
556
+ `ExecLanguage`, `ExecRoute`, `ExecShell` and the exec adapter and runner types
557
+ live in `lib/contract/exec.ts` (export `./lib/contract/exec.ts`); the root
558
+ exports the three. The `./docx` export is gone; `./office` keeps its functions.
559
+ (#269) For qvac-core: `desktop/electron/assistant-sidecar.mjs` and the mobile
560
+ worklet pass instances, `new Weather({ read: ['weather_lookup'] })`,
561
+ `new Image({ model, clamps, read: ['generate_image'] })`; the sidecar drops
562
+ `createExecTool`, `createPython` and the obsidian route from `tools` and passes
563
+ `exec: true` with `sdkHome: sdkStorage.home`; `extractDocxText` callers move to
564
+ `@qvac/harness/office`; the three `@qvac/harness` pins move to 0.9.0, the release after 0.8.5. The
565
+ `./lib` keys stay this release; `./lib/tools/*` is gone (#273).
566
+
567
+ - **Breaking:** `CompletionEvent` gains `input-rejected`, and `HookPhase` and
568
+ `HookRejection.phase` each gain `promptSubmit`, `toolFailure`, `stop` and
569
+ `preFold`; a host that switches on them exhaustively must handle the new
570
+ members. Every steer and follow-up now passes `promptSubmit` hooks. The hrpc
571
+ `completion-event-type` enum now has `input-rejected`: before, a harness
572
+ served over hrpc died when it emitted one. An older host decodes it with a
573
+ `null` type. (#260, #264)
574
+
575
+ - **Breaking:** `PreToolCallPayload.effect` and `.resource` are now required,
576
+ so a pre-tool hook can single out writes and the resource a call touches. A
577
+ host that calls `HookPipeline#runPreToolFold` itself passes both; a hook that
578
+ only reads the payload is unaffected. The `hook:runPreToolFold` operation now
579
+ records both in its arguments, so a run paused after a pre-tool hook ran
580
+ before the upgrade does not resume (`Operation identity mismatch`). (#183)
581
+ - `exec` refuses a `language` that no composed language claims, other than
582
+ `shell`, instead of running `command` as a shell line. `python` keeps its own
583
+ message. The language a call names reads it first, so Python's source
584
+ inference no longer takes a call named for another language. (#232)
585
+ - Long tool output keeps its start and end. Exec, python, the sandbox VM and
586
+ obsidian keep the first and last `maxOutputChars` of each stream, joined by
587
+ a marker that counts the chars dropped (`…[N chars omitted]…`), so errors
588
+ and tracebacks at the end survive. The output no longer ends in
589
+ `… [truncated]`, and the marker counts against `maxOutputChars`; a host that
590
+ matched the old suffix follows. A result whose payload is over 65536 chars
591
+ is trimmed the same way when it is rendered for the model, each long string
592
+ field cut so the payload still parses; the `tool-result` event and the run
593
+ log keep the full result, and the `skill` tool is exempt. (#180)
594
+
595
+ - **Breaking:** a plugin can own a skill's readiness. `PluginSetup.skills`
596
+ takes `SkillReadiness` entries: `skill`, `state(ctx)`, and optional
597
+ `probeVersions` and `deviceSharedKeys`. The registry collects them into
598
+ `StartedPlugins.skills`, and two plugins claiming one skill fail. `state()`
599
+ runs after the platform, stub and model gates and before the bin gate; a
600
+ state settles the skill, `null` defers. The obsidian readiness, the
601
+ version-probe exclusion, the device-shared `obsidian_vault_path` and the
602
+ vault-mode note moved from the core into `ObsidianRoute#plugin`, and
603
+ `ObsidianRoute` takes `probe` for its filesystem checks.
604
+ `SkillStateInputs.obsidianProbe` and the `credentialStore` option of
605
+ `createSkillTool` are gone, and the core shares no credential key by default. `versionProbeSkills` takes
606
+ `{ installedTools, platform, readiness }` after the catalog. The bundled
607
+ sidecar wires the plugin; its hook joins the hook manifest, so a run paused
608
+ before the upgrade does not resume. **Upgrade:** a host
609
+ that builds its own tools, such as qvac-app, passes the route's plugin too:
610
+ `const obsidian = new ObsidianRoute({ credentialStore })`, then
611
+ `routes: [obsidian]` and `plugins: [{ plugin: obsidian.plugin }]`. A host that
612
+ ships the obsidian skill without the plugin gets the generic gates: the vault
613
+ path is per agent and no longer stands in for the bin, the load has no vault
614
+ note, and `skills()` probes `obsidian version`, which opens the desktop app.
615
+ (#227)
616
+
617
+ - **Breaking:** every module's entry exports one class as its API, plus the
618
+ types it takes and returns. (#217, #216, #218 to #221) For qvac-core:
619
+ - The root no longer exports `completion()`: call
620
+ `CompletionEngine.run(sdk, args, options)`, which takes the same arguments
621
+ and defaults. `new CompletionEngine(sdk, options).run(args)` is the
622
+ instance form. The `./lib/capabilities/completion.ts` subpath is gone: its
623
+ `imageSettingsFrom`, `skillInContext`, `unreadySkillState`, `toSdkTool`,
624
+ `loadedSkillsFrom`, `skillLoadedTurn` and `CONTEXT_OVERFLOW_MESSAGE` are
625
+ root exports, and its types (`CompletionArgs`, `CompletionRun`,
626
+ `CompletionSkillEntry` and the contract types) are root types.
627
+ `trustedSourcesFrom` is no longer exported.
628
+ - `defaultHooks()` is `HookPipeline.defaults()`, and `EgressGuardHook` and
629
+ `SkillCatalogGuardHook` are `HookPipeline.EgressGuardHook` and
630
+ `HookPipeline.SkillCatalogGuardHook`. The root exports `HookPipeline`. The
631
+ hook types live in the contract, so the root also exports the hook payload
632
+ types.
633
+ - The contract type `Agent` is `AgentConfig`. `./agent` exports the `Agent`
634
+ class: `resolveAgent`, `agentPolicy`, `parseToolGrant`, `enabledTools`,
635
+ `permittedTools`, `collectToolGrants` and `skillIsActive` are its statics
636
+ `resolve`, `policy` and the same names, and the tool-name constants and
637
+ `NETWORK_TOOLSETS` are statics too. `new Agent(config, ports)` binds one
638
+ agent.
639
+ - `./plugins` exports the `PluginRegistry` class in place of
640
+ `createPluginRegistry(entries, options)`: call
641
+ `new PluginRegistry(entries, options)`. Its checks, messages and lifecycle
642
+ are unchanged.
643
+ - `./run-log` and `./run-log-inspect` both export the `RunLog` class.
644
+ `createEngineBoot`, `buildEngineBoot`, `validateEngineBoot`,
645
+ `applyEngineStep`, `contextFromBoot` and `requestFromBoot` are its statics,
646
+ `RUN_LOG_VERSION` and `RUN_LOG_PROTOCOL_VERSION` are `RunLog.VERSION` and
647
+ `RunLog.PROTOCOL_VERSION`, and `inspectRun` and `renderRunLogHtml` are
648
+ `RunLog.inspect` and `RunLog.renderHtml`. `./run-log` now loads XState.
649
+ It no longer exports the `Operation` and `RunBudget` types; the root
650
+ still exports `Operation` and `RunBudget`.
651
+ - `lib/machine` exports `CompletionMachine` and no longer re-exports the run
652
+ log. `createCompletionMachine`, `completionMachineDefinition`,
653
+ `emptyCompletionContext` and `MACHINE_VERSION` are `create`, `definition`,
654
+ `emptyContext` and `VERSION`. `runEngine` moved to the completion engine,
655
+ and `stableStringify`, `raceDrain` and `didDrainTimeOut` to `lib/helpers`.
656
+ - The machine entry exports only `CompletionMachine` (`VERSION`, `create`,
657
+ `definition`, `emptyContext`, `transitionName`) and the types those take
658
+ and return. It no longer exports the error classes, `tagError`,
659
+ `rehydrateError`, the failure-result helpers or the stage payload types.
660
+ `AbortedError` stays on `./race-abort`. The shared run types (`Message`,
661
+ `Operation`, `ToolExecutionOutcome`, ...) moved to the contract, so the
662
+ root now also exports `Operation`, `RunOutcome`, `HistorySplice`,
663
+ `CompletionHistoryEntry`, `FailureResultReference`, `TrustedOrigin`,
664
+ `TrustedSource` and `TrustedSourceFacts`. The `./lib/tool-call-display.ts`
665
+ subpath is gone; `ToolCallDisplay` and `ToolExecutionOutcome` come from
666
+ the root. (#229)
667
+ - `@qvac/sdk` and `@qvac/inference` 0.20.1. Every `llamacpp-completion` load
668
+ now sends `system_prompt: ''`, so the SDK no longer seeds
669
+ `'You are a helpful assistant.'` in front of a history with no system
670
+ message. **For qvac-core:** no API break, but every completion modelId
671
+ changes once, so each chat cold primes once after the upgrade. `fit` is left
672
+ out: a 2B load with `fit: true` showed no fitting, and the SDK sends it as
673
+ `'true'` where fabric's `--fit` takes `on` or `off`. (#194)
674
+ - `@qvac/sdk` and `@qvac/inference` 0.21.0, with `@qvac/llm-llamacpp` 0.55.0,
675
+ and the addons the plugins load directly at the SDK's peer ranges
676
+ (`@qvac/asr-ggml` 0.7, `@qvac/tts-ggml` 0.10, `@qvac/audiogen-ggml` 0.5,
677
+ `@qvac/diffusion-cpp` 0.26, `@qvac/embed-llamacpp` 0.43.0,
678
+ `@qvac/translation-nmtcpp` 0.18.0). The SDK fits models itself, so
679
+ `@qvac/model-fit` leaves the dependencies, `SdkLoader.addons` and
680
+ `NATIVE_ADDON_PACKAGES`. `@qvac/fabric` ships its prebuilds as per-platform
681
+ packages (`@qvac/fabric-<os>-<cpu>`); `collectRuntimeClosure` now follows a
682
+ dependency's `#host-addon` package as well as a seed's, and a host that
683
+ packages the addons exempts those names from any install age gate. The fit
684
+ check asks the SDK's `loadModel`-shaped `assessModelFit` input with the
685
+ model's source, and an embedding model is assessed as one. (#302)
686
+ - **Breaking:** the chat-file staging and output policy the office, pdf and
687
+ Python paths share move from `./plugins/python` into the core:
688
+ `Tools.stageInputs` and the `ExecInput` type come from `@qvac/harness/tools`,
689
+ and `./plugins/python` no longer exports them. `ExecLanguage.validate` takes
690
+ an `ExecValidateScope`, which adds the round's `toolNames`, and
691
+ `ResidentPoolSpec.modelConfigFor` lays a model's own config over the pool's,
692
+ as the speech plugin does for Supertonic's steps. `wording.fileDelivered`
693
+ replaces the nudge after a round that attached a file, and a run that wraps
694
+ up one round after a delivered file ends with the `delivered` outcome.
695
+ - The `pdf` tool declares `bare-pdfium` in its `addons`, so a sealed sidecar has
696
+ it loaded before the first PDF call, and `NATIVE_ADDON_PACKAGES` names it.
697
+ - **Breaking:** the sidecar seals native addon loading once the harness is ready
698
+ (`Bare.Addon.seal()` through `#addon-seal`, a no-op on Node), so nothing a run
699
+ does can load a new native addon. Whatever loads one declares it:
700
+ `HarnessPlugin.addons`, `ToolDefinition.addons` and `SdkLoader.addons`, each a
701
+ name and a literal `import()`. On Bare the harness loads them all as it opens,
702
+ each plugin's before its `setup`. A failure rejects `ready()` naming the
703
+ plugin or tool and the addon, and rolls the started plugins back. The build
704
+ fails on a native addon `NATIVE_ADDON_PACKAGES` does not name. **Upgrade:** a
705
+ host-written plugin or tool that imports a native addon lazily declares it in
706
+ `addons`, or it fails under the seal. An entry set in
707
+ `QVAC_PYODIDE_WORKER_ENTRY` must exit when `workerData.preload` is true, as
708
+ the real entry does, or `ready()` waits on it. Opening a harness on Bare now loads the
709
+ SDK's addons up front, not on the first call. (#177)
710
+ - Plugin service registration rejects `undefined` and names reserved by the
711
+ context, such as `get`, `provide` and `onDispose`. Rename conflicting services
712
+ and return an initialized value. A failed registry cannot restart; construct
713
+ another harness to retry. `HarnessPlugin` entries are the only plugin shape;
714
+ the lower-level runtime is not exported. Model unload callbacks, tool grants
715
+ and wire APIs keep their contracts. No qvac-core migration is
716
+ needed for this framework integration. (#171)
717
+ - **Breaking:** a tool declares that it reaches the network with
718
+ `egress(args)`, which returns the URL a call targets, or `null` when that is
719
+ not known before the call. `HookPipeline.EgressGuardHook` now checks every
720
+ tool that declares it, whatever its name, and no tool that does not:
721
+ `http_request`, `web_fetch` and `mcp_call` declare it. A plugin tool that
722
+ declares `egress` gets `ctx.fetch`, a guarded fetch that refuses private
723
+ hosts on every hop, stops with the call and refuses everything in sandbox
724
+ mode. The v0.7.3 names `createGuardedFetch`, `GuardedResponse`,
725
+ `GuardedResponseInit`, `GuardedFetchOptions`, `MAX_RESPONSE_BYTES`,
726
+ `ConnectPolicy`, `setConnectPolicy` and `isGuardedFetch` from
727
+ `./lib/tools/exec/adapters/python/guarded-fetch.ts` have no public path; a
728
+ plugin tool uses `ctx.fetch`. **Upgrade:** a host tool that reaches the
729
+ network declares `egress(args)`; one named `http_request`, `web_fetch` or
730
+ `mcp_call` without it loses the pre-call check. `createHttpRequestTool`,
731
+ `createWebFetchTool` and `createMcpCallTool` declare it, so qvac-core and
732
+ qvac-app's mobile worklet are unchanged. (#172)
733
+
734
+ - **Breaking:** speech is a plugin. Transcription, text-to-speech and the
735
+ `bare-ffmpeg` audio decoding moved from `lib/` to `plugins/speech/`,
736
+ exported as `@qvac/harness/plugins/speech` (`speechPlugin`). A `Harness`
737
+ built without it rejects `transcribe`, `speak`, `speakStream` and a
738
+ `loadModel` or `unloadModel` of a voice model with `speech needs the speech plugin`, before
739
+ loading anything. The bundled sidecar passes the plugin, so a host that uses
740
+ `spawnHarness` (qvac-core) is unchanged. **Upgrade:** a host that constructs
741
+ `Harness` itself, such as qvac-app's `mobile/worker/harness-worklet.mjs`,
742
+ adds `plugins: [{ plugin: speechPlugin }]` with
743
+ `import { speechPlugin } from '@qvac/harness/plugins/speech'`. `SpeechService`, `SpeakResult` and the voice context types
744
+ are exported from `index.ts`, and `SpeakResult` from
745
+ `./lib/contract-types.ts`. (#173)
746
+ - **Breaking:** `weather_lookup` is a plugin. It moved from
747
+ `lib/tools/weather-lookup.ts` to `plugins/weather/`, exported as
748
+ `@qvac/harness/plugins/weather` (`weatherPlugin`, and the tool as
749
+ `weatherLookupTool`); `createWeatherLookupTool` and its `fetch` and
750
+ `resolveHost` options are gone. The tool declares `egress` and fetches with
751
+ the guarded `ctx.fetch`; a refused fetch is a plain `{ error }` with no
752
+ `transport` code, and the 400 KB body cap is dropped. Granted read, it keeps
753
+ `autoApprove`, so its schema still has no `intent` argument. The bundled
754
+ sidecar passes the plugin, so `spawnHarness` hosts are unchanged. **Upgrade:** a host that constructs `Harness` itself, such as
755
+ qvac-app's mobile worklet, adds
756
+ `{ plugin: weatherPlugin, read: ['weather_lookup'] }` to `plugins` with
757
+ `import { weatherPlugin } from '@qvac/harness/plugins/weather'`. Without it
758
+ there is no `weather_lookup` and the bundled `weather` skill is unsupported.
759
+ (#176)
760
+ - **Breaking:** Obsidian is an exec route in `plugins/obsidian/`, exported as
761
+ `@qvac/harness/plugins/obsidian` (`ObsidianRoute`). The modules under
762
+ `lib/tools/exec/obsidian/` leave the package, and
763
+ `ExecToolOptions.credentialStore` is gone: the route takes the store.
764
+ `createExecTool({ routes })` takes `ExecRoute`s; the first route that claims a
765
+ shell command runs it instead of the shell, after the shell checks. Route
766
+ names fold into exec's `policyVersion`, so a run paused on an exec call does
767
+ not resume. The bundled sidecar passes the route, so `spawnHarness` hosts are
768
+ unchanged. **Upgrade:** a host that builds `exec` itself, such as qvac-app's
769
+ mobile worklet, passes
770
+ `routes: [new ObsidianRoute({ credentialStore })]` with
771
+ `import { ObsidianRoute } from '@qvac/harness/plugins/obsidian'`. Without it
772
+ `obsidian …` goes to the shell (on a phone, instead of the desktop-agent
773
+ guidance), and the obsidian skill should be left out, since its readiness
774
+ still reads `ready` when a vault path is set (#227). (#223)
775
+ - **Breaking:** image and music generation are plugins. `generate_image`,
776
+ `edit_image`, `generate_music`, their runtimes, the SDK diffusion and
777
+ audiogen plugin registration, and the `bare-media` and `bare-image-resample`
778
+ imports moved from `lib/` to `plugins/image/` and `plugins/music/`, exported
779
+ as `@qvac/harness/plugins/image` (`imagePlugin`) and
780
+ `@qvac/harness/plugins/music` (`musicPlugin`). `HarnessOptions` loses
781
+ `imageModel`, `imageClamps`, `musicModel` and `musicClamps`, and the root
782
+ loses `ImageModelOptions`, `MusicModelOptions`, `settingsDimension` and
783
+ `settingsSteps`; the last two are exported from `@qvac/harness/plugins/image`.
784
+ The three tools sit in two new toolsets, `image` and `music`, at the end of
785
+ `TOOLSETS`, so an agent can switch each off. A plugin may now `need` the
786
+ core's `models` service (`ModelHost`) and return `unload()` and
787
+ `unloadIdle()`, which the harness calls on suspend, close, idle unload and
788
+ before a chat model loads. `spawnHarness` and `harnessChild` keep their
789
+ options and the bundled sidecar passes both plugins, granting
790
+ `generate_image` and `generate_music` read. **Upgrade:** a host that
791
+ constructs `Harness` itself passes
792
+ `{ plugin: imagePlugin, config: { model, clamps }, read: ['generate_image'] }`
793
+ and `{ plugin: musicPlugin, config: { model: musicModelSet(choice), clamps }, read: ['generate_music'] }`;
794
+ music takes resolved stages, not a choice name. qvac-core's TUI imports
795
+ `settingsDimension` from `@qvac/harness/plugins/image` instead of
796
+ `@qvac/harness/lib/tools/generate-image.ts`, and adds `TOOLSET_HINTS` for
797
+ `image` and `music`. (#175)
798
+ - **Breaking:** `MAX_TOOL_ROUNDS`, `TOOL_CONTINUATION_NUDGE`,
799
+ `TOOL_DENIED_MESSAGE` and `TOOL_CUT_OFF_MESSAGE` are no longer exported from
800
+ `lib/machine`. All four are defaults now, exported from
801
+ `lib/capabilities/tool-turns.ts`.
802
+ `toolDeniedResult` takes its message, `contextCandidates` and
803
+ `lastFailedToolAnswer` take the run's nudge, and
804
+ `CompletionMachine.emptyContext` requires a `policy`. (#159)
805
+ - **Breaking:** `skillPreloadMessage` is exported from
806
+ `./lib/capabilities/tool-turns.ts`, no longer from
807
+ `./lib/tools/skills/mention.ts`. (#166)
808
+ - **Breaking:** `metrics.durationMs`, and `stats.durationMs` on the `runEnd`
809
+ hook, are the run's wall time, as they already were for a capability
810
+ invoke. They were an estimate of decode time. `promptTokensPerSecond` is
811
+ weighted by every round's prompt tokens instead of being the first round's.
812
+ (#195)
813
+ - **Breaking:** `MACHINE_VERSION` and `RUN_LOG_VERSION` are both 1, and stay
814
+ at 1 until 1.0.0 ships. A run saved with `1.0.0-rc.0` or `1.0.0-rc.1` does
815
+ not resume, and `./run-log-inspect` no longer reads v4 or rc logs. (#205)
816
+ - **Breaking:** the completion graph no longer has skill states. A turn's
817
+ skill preload runs as a generic prepare step (`prepareChecking` and
818
+ `prepareRunning`, actors `inspectPrepare` and `runPrepare`), and a skill call
819
+ in a round runs in `executing`, so `tools.loadingSkill` is gone. Context
820
+ `skills` is now `activated: string[]` and `skillPreload` is
821
+ `prepareStep: { id, tool, args, facts? }`. `lib/machine` no longer exports
822
+ `SkillLoadOutput`, `SkillPreloadState`, `PreloadInspectionOutput`,
823
+ `SkillReadyPayload` or `SkillFailedPayload`; it exports `PrepareStep`,
824
+ `PrepareStepProposal`, `PrepareInspectionOutput`, `PrepareRunOutput`,
825
+ `PrepareResult` and `PrepareFailure`. `PreparingOutput` carries `step`,
826
+ `InspectingOutput` only `call`, `execution` and `rejection`, and
827
+ `ToolExecutionSnapshot` has `origin` in place of `kind: 'skill'` and
828
+ `skillName`. Events, call ids (`preload-<name>`) and their order are
829
+ unchanged. A run saved paused in a removed state does not resume. (#170)
830
+ - A response cut off by the length limit no longer runs its tool calls. Each
831
+ call gets a `tool-call` and then an error `tool-result` carrying the run's
832
+ `wording.toolCutOff` text (#159), which asks for a shorter re-issue. Nothing
833
+ runs, no approval is asked for, and the next round starts. A complete re-send
834
+ in a later round still runs. (#155)
835
+ - Arg repair converts a string argument to the schema's scalar type when the
836
+ conversion is lossless: a JSON number that does not underflow, a whole one
837
+ only within the safe-integer range (`"1e20"` stays a string), `true`/`false`
838
+ in any case, `"null"` where null is allowed, and an enum value matched
839
+ ignoring case. Nested fields count too. An optional field sent as `"null"`
840
+ is dropped only when its schema allows neither string nor null: an optional
841
+ string field keeps `"null"`, and a nullable one becomes `null`. A tool may now
842
+ receive `3` where it used to get `"3"`. (#156)
843
+ - A tool description spells out a parameter's nested and defaulted fields
844
+ (`Each item: {…}`), which the SDK strips from the schema. The prompt bytes of
845
+ `read_files`, `create_documents`, `edit_documents`, `grep` and `edit_image`
846
+ change, so each chat's first turn after the upgrade misses the prefix cache
847
+ once. A tool with only flat parameters is unchanged. (#157)
848
+ - exec labels a Pyodide run of inline Python, source pasted into `script`
849
+ included, as `python[ · network: …]: …` in the approval; a bundled script
850
+ keeps `python script <skill>/<script>`. `command` together with `script` is
851
+ rejected. Pasted source classifies like the same source in `command`. (#163)
852
+ - **Breaking:** `resolveScriptRun` returns `{ args, trusted: false }` instead
853
+ of `null` for a call that is not a script run (#163). It moved out of
854
+ `./lib/tools/exec.ts` into the python plugin and is no longer exported
855
+ (#174).
856
+ - **Breaking:** `createExecTool()` runs shell commands only unless it is given
857
+ `languages`. Without Python its schema has no `language`, `packages`,
858
+ `inputs`, `outputs`, `script`, `skill` or `scriptArgs`, and a
859
+ `language: "python"`, interpreter or pip call is refused with a message that
860
+ says no call runs it. Without a language, `packages`, `inputs`, `outputs` or
861
+ `script` on a shell call is refused too, as before. `disablePyodide`, `loadPyodide` and `pythonNetwork` are
862
+ gone: pass `loadPyodide` and `network` to `createPython()`. The harness no
863
+ longer closes the python worker itself; the plugin's teardown does. The
864
+ modules under `./lib/tools/exec/adapters/python/` moved to
865
+ `plugins/python/` and are no longer exported one by one; take `stageInputs`
866
+ from `./plugins/python`. With Python, the exec schema lists
867
+ `script`, `skill` and `scriptArgs` before `workdir`, so each chat's first
868
+ turn after the upgrade misses the prefix cache once, and a run paused on an
869
+ exec call does not resume. (#174)
870
+ - A round whose only tool calls the SDK could not parse or validate
871
+ (`final.toolErrors`) gets a re-ask on its first stall: the failed markup as
872
+ the assistant turn, a `call-malformed` tool turn with each error's code and
873
+ message, then the continuation nudge. A round cut off at the length limit
874
+ gets `wording.toolCutOff` in the tool turn instead. Once that re-ask is spent
875
+ or no round is left, the round answers in prose as before, or takes the
876
+ narrated re-ask when its prose narrates a call. The re-ask has its own
877
+ one-retry budget, separate from the narrated re-ask, and a round that runs a
878
+ call resets it. The run log keeps `toolErrors` with `raw` and `message`
879
+ redacted, and redacts the malformed assistant turn and the `call-malformed`
880
+ tool turn wholesale. Nothing changes on the wire or in `RunPolicy`. (#190)
881
+ - The re-ask after a round that narrated a call, and the re-ask after a
882
+ malformed call, demand a call: they send `tool_choice: 'required'` and
883
+ `reasoning_budget: 0` over the session's params. A malformed round cut off at
884
+ `length` is re-asked unforced. A mute retry of a re-ask is forced too, even
885
+ after a cut-off. A run with no tools or with a response format is never
886
+ forced. Every other round, the wrap-up included, keeps the session's params.
887
+ When the addon refuses the forced call, the round runs again unforced on a
888
+ fresh KV session. A grammar fault still falls back to
889
+ `tool_choice: 'none'`. Each forced round resends the tool block into the
890
+ chat's cache; #212 measures the cost. `LlmGenerationParams.tool_choice` now
891
+ admits `'required'`. **Upgrade:** do not set it for a whole run, in process
892
+ or in the wire's `generationParams`. The wrap-up sends no tools, and the SDK
893
+ rejects `required` with none, so the run fails. qvac-core sends no
894
+ `tool_choice` and is unchanged. (#191, #213)
895
+
896
+ ### Removed
897
+
898
+ - **Breaking:** `Tools.product` no longer lists `mcp_call` or compiles the
899
+ skill catalog's mcp operations (notion's `notion_create_page` and
900
+ `notion_insert_content`). Add
901
+ `new McpPlugin({ generic: true, skillCatalog, credentialStore, read: ['mcp_call'] })`
902
+ from `@qvac/harness/plugins/mcp`; without `read`, every `mcp_reads` method
903
+ asks. `mcp_call` now follows the exec tools in the prompt, so every cached
904
+ prompt changes. (#277)
905
+ - **Breaking:** the `./lib/tools/*` wildcard and five tool factory exports.
906
+ Build the product list with `Tools.product` from `@qvac/harness/tools`:
907
+ - `./lib/tools/http-request.ts` (`createHttpRequestTool`): `Tools.product`.
908
+ - `./lib/tools/mcp-call.ts` (`createMcpCallTool`): `new McpPlugin({ generic: true })`
909
+ from `@qvac/harness/plugins/mcp`.
910
+ - `./lib/tools/web-search.ts` (`createWebSearchTool`): `WebSearchPlugin` from
911
+ `./plugins/web-search` (#276).
912
+ - `./lib/tools/web-fetch.ts` (`createWebFetchTool`): `Tools.product`.
913
+ - `./lib/tools/skill.ts` (`createSkillTool`): `Tools.product` with `skillsDir`.
914
+ - `./lib/tools/read-files.ts`, `file-glob.ts`, `grep.ts`,
915
+ `create-documents.ts`, `edit-documents.ts`, `operations/compile.ts`:
916
+ `Tools.product`, which passes them the denied roots.
917
+ - `./lib/tools/skills/credential-slots.ts` (`credentialSlots`):
918
+ `credentialSlots` from `@qvac/harness/skill-manifest` (#283).
919
+ - `./lib/tools/skills/scope-key.ts` (`isDeviceSharedCredentialKey`, which
920
+ #227 removed; `scopeKey` and `deviceSharedKeys` are harness-internal): no
921
+ replacement. Plugins now declare their device-shared keys in
922
+ `SkillReadiness.deviceSharedKeys`. A host that picks a credential's
923
+ storage key outside the harness keeps its own list of device-shared keys,
924
+ matching the plugins it composes. Today that is `obsidian_vault_path`,
925
+ from `ObsidianRoute`. A mismatch fails closed: a key the host stores
926
+ device-wide that no plugin shares reads as unset for an agent, and the
927
+ skill shows needs-setup. (#283)
928
+ - `./lib/tools/skills/bundled-dir.ts` (`ensureBundledSkillsDir`):
929
+ `Tools.bundledSkillsDir()` from `@qvac/harness/tools` (#283).
930
+ - `./lib/tools/skills/catalog.ts`: `./lib/tools/skills/index.ts` or the root
931
+ `@qvac/harness`, which both re-export it.
932
+ - `./lib/tools/skills/auth-resolver.ts`, `cli-schema.ts` and
933
+ `credential-grants.ts`: `./lib/tools/skills/index.ts`, which re-exports
934
+ them.
935
+ - `./lib/tools/skills/frontmatter-parser.ts`: `./skill-manifest` or
936
+ `./lib/tools/skills/index.ts`.
937
+ - `./lib/tools/skills/skill-state-constants.ts`: `./skill-state`.
938
+ - `./lib/tools/skills/tool-grants.ts` (`parseToolGrant`, already gone this
939
+ release): `Agent.parseToolGrant` from `@qvac/harness/agent`.
940
+ - Any other `./lib/tools/...` path: no replacement.
941
+
942
+ Only `./lib/tools/exec.ts`, `./lib/tools/toolsets.ts`,
943
+ `./lib/tools/skills/index.ts`, `./lib/tools/skills/mention.ts` and
944
+ `./lib/tools/skills/mention-name.ts` keep their keys, and the packed plugins
945
+ reach `exec/runner.ts`, `exec/shell-argv.ts`,
946
+ `exec/adapters/shell/shell-adapter.ts`, `fs/scope.ts` and `fs/write.ts`
947
+ through their own keys. (#273)
948
+
949
+ - **Breaking:** `lib/team` and `Team`, with `TeamConfig`, `TeamRequest`,
950
+ `TeamHost` and `TeamEvent`. `harness.completion({ agent, agents, messages })`
951
+ replaces `Team.run(host, { entry, agents }, request)`; `TransferEvent` is a
952
+ contract type now. (#233)
953
+ - The sidecar bundle no longer ships `@qvac/ocr-ggml`: no harness code imports
954
+ it, and the shipped addon closure is now seeded from the `@qvac` packages the
955
+ bundle defers (`deferredAddonPackages`), so a host bundling neither image nor
956
+ music ships neither `@qvac/diffusion-cpp` nor `@qvac/audiogen-ggml`. (#226)
957
+
958
+ - **Breaking:** `rag_search`, the `ragSearch` host callback and its types.
959
+ `CompletionArgs.ragSearch`, `CompletionContext.ragSearch` (`index.ts` and
960
+ `./lib/contract-types.ts`), `ToolExecuteContext.ragSearch` (a root type),
961
+ `RagSearchFn`, `RagSearchResult` and the `./lib/tools/rag-search.ts` export
962
+ are gone. The callback was bound onto every tool's execute context, so a
963
+ host's own tool could call `ctx.ragSearch`; no harness tool did. A host drops
964
+ the field, and knowledge still reaches the model by injection. The `rag-ask`
965
+ and `rag-result` wire values stay in the schema. (#162)
966
+ - **Breaking:** `harnessHooks`. Hooks belong to a `Harness`:
967
+ `new Harness({ hooks })` replaces the built-ins, and
968
+ `HookPipeline.defaults()` returns fresh instances of them (arg-repair,
969
+ egress-guard, sandbox, skill-catalog). To add a hook, pass
970
+ `[...HookPipeline.defaults(), mine]`. `CompletionEngine` takes a `hooks`
971
+ option and defaults to `HookPipeline.defaults()`, so a host that passes
972
+ nothing runs the same four as before. (#158)
973
+ - **Breaking:** the agent's tool selection and tool names are exported as
974
+ `@qvac/harness/agent`, which replaces `./lib/capabilities/tool-selection.ts`
975
+ and `./lib/capabilities/tool-names.ts` (and the unreleased
976
+ `./lib/agent/tool-selection.ts` and `./lib/agent/tool-names.ts`). It exports
977
+ the `Agent` class, with the statics `resolve`, `policy`, `parseToolGrant`,
978
+ `enabledTools`, `permittedTools`, `collectToolGrants`, `skillIsActive`,
979
+ `follow`, `NETWORK_TOOLSETS`, `SKILL_TOOL_NAME`, `WEB_SEARCH_TOOL_NAME`,
980
+ `TRANSFER_TOOL_NAME` and `MAX_TRANSFERS`.
981
+ `isSelected`, `skillsAreSelected`, `MCP_CALL_TOOL_NAME` and the types
982
+ `ToolGrantSource`, `ToolGrants`, `SelectableTool` and `ToolGateInputs` are no
983
+ longer exported; `SkillActivation` is a root type.
984
+ `parseToolGrant` left `./lib/tools/skills/tool-grants.ts` (gone), and
985
+ `NETWORK_TOOLSETS` and `permittedTools` left `./lib/tools/toolsets.ts`,
986
+ which keeps `TOOLSETS`, `Toolset`, `asToolset` and `toolsetEnabled`.
987
+ `ToolGrant` is no longer exported; `ToolsetScoped`, and `SystemPromptParts`
988
+ from `./lib/prompt.ts`, are root types. (#165, #206)
989
+ - **Breaking:** `./lib/tools/model-args.ts` (`unquoteArg`) is no longer
990
+ exported. (#166)
991
+
992
+ ### Fixed
993
+
994
+ - A reply that said it would act ("I'll …", "Let me …") but asked the user
995
+ something got the narrated re-ask, and the forced round called a tool with
996
+ the input the user was asked for made up. Such a reply is now the answer,
997
+ and the turn ends there: a question mark outside code and outside a URL
998
+ query, or a request for the user's input such as "tell me", "show me",
999
+ "send me", "give me …", "please provide …" or "let me know". A request for
1000
+ time, such as "give me a moment, I'll check", still gets the re-ask.
1001
+ Nothing changes on the wire or in `RunPolicy`. (#252, #272, #292)
1002
+ - Under `SeatbeltSandbox` (`./plugins/sandbox-macos`), a shell line could read
1003
+ and write the app storage root when a write root held it, for example a home
1004
+ grant: `cat <storage>/sdk-home/key` worked under both presets. Exec now passes
1005
+ its canonical `deniedRoots` to the shell as `ExecutionContext.deniedRoots`,
1006
+ and the Seatbelt profile denies reads and writes under each one, plus the
1007
+ rename or removal of each folder above a denied root, up to and including
1008
+ `/`. `SeatbeltSandbox.profile` takes `{ roots, denied, ancestors }`. (#293)
1009
+ - On Node, exec's default shell runtime failed every command with
1010
+ `require.addon is not a function`: it imported `bare-subprocess` and
1011
+ `bare-process` directly. It now imports `child_process` and `process`, which
1012
+ resolve to the Bare modules on Bare. The skill bin probe and the capability
1013
+ probe share this runtime. (#274)
1014
+ - On Node, a shell line run through `SeatbeltSandbox` (`./plugins/sandbox-macos`)
1015
+ failed with `require.addon is not a function`: the plugin imported
1016
+ `bare-subprocess` directly. It now imports `child_process`, which resolves to
1017
+ `bare-subprocess` on Bare. (#281)
1018
+ - A completion event the hrpc schema could not encode (a cycle in a tool
1019
+ result, a negative number such as `progress({ percentage: -1 })`) killed the
1020
+ harness process: hrpc encodes in a deferred write, outside any try/catch.
1021
+ `serve` now encodes each event before it sends it. When that fails, the run
1022
+ ends with an `error` event `cannot encode <type> event: <reason>`, and a later
1023
+ run on the same connection still completes. (#267)
1024
+ - The other wire writes no longer kill the process on a value the hrpc schema
1025
+ cannot encode. `modelEvents` sends
1026
+ `{ status: 'error', message: 'cannot encode model event: <reason>' }` with no
1027
+ `model` and keeps the subscription open. `download` ends with an `error`
1028
+ event `cannot encode <type> event: <reason>`. `speakStream` rejects with
1029
+ `cannot encode speak frame: <reason>`, for a worker frame and for a host
1030
+ fragment; before, it ended cleanly but cut short. A host `completion` frame that cannot encode destroys the stream and
1031
+ rejects with `cannot encode <type> frame: <reason>`, with no `HARNESS_DIED`
1032
+ code. The generated `spec/bind.js` turns a non-Error throw from a stream
1033
+ handler into an `Error` and destroys `writeStream` with it. (#278)
1034
+ - `copyAddonExternals` ships a dependency nested under a package because the
1035
+ root copy is out of its range (`@qvac/tts-ggml`'s `bare-subprocess` ^5). (#228)
1036
+ - On the last tool round, a response with no answer and no tool call re-asked
1037
+ the model one round past `maxToolRounds`, and tool calls from that extra
1038
+ round still ran. The run now wraps up instead. (#167)
1039
+ - A `FAIL` sent while a run was finishing ran the finishing step again, and
1040
+ with it the `runEnd` hook. The run now fails at once, as it does when the
1041
+ finishing step itself throws. `runEnd` does not fire for that failure, so a
1042
+ host hook does not see it. (#167)
1043
+
1044
+ ## [0.8.5] - 2026-10-06
1045
+
1046
+ ### Added
1047
+
1048
+ - Skill-gated `pptx`, `docx` and `xlsx` tools on the office engine. A call takes
1049
+ an `attachmentId` (or `create` options), `ops` that name engine methods with
1050
+ named arguments, and an `output` file name; with an `attachmentId` alone it
1051
+ returns the file's contents. The first failing op saves nothing and returns
1052
+ the engine's error. An edit is never saved under the attached file's own
1053
+ name. Saving the same file again in one turn answers with the one already
1054
+ attached, and a changed file under that name is refused. The one-line answer
1055
+ comes back as `reply`. These are the tools the presentations, word and excel
1056
+ skills in `@qvac/skills` 0.1.12 call. (#286)
1057
+
1058
+ ### Changed
1059
+
1060
+ - **Breaking:** `@qvac/skills` is now 0.1.12, whose office and pdf skills run on
1061
+ the `pptx`, `docx`, `xlsx` and `pdf` tools instead of Python. A host that
1062
+ passes its own `skillsDir` needs 0.1.12 as well: older office skills import
1063
+ Python libraries this release no longer ships. (#286)
1064
+ - `extractOfficeText` and `extractDocxText` read .docx, .xlsx and .pptx in
1065
+ process on the engine instead of starting Pyodide, and read at most 1M cells
1066
+ across a workbook. Extracted workbook booleans read `true`/`false` instead of
1067
+ `True`/`False`. `closeOfficeWorker` and `closeDocxWorker` remain as no-ops.
1068
+ (#286)
1069
+ - `exec` refuses Python that imports `pptx`, `docx` or `openpyxl`, or declares
1070
+ their packages, before it runs, and names the tool (or the skill that grants
1071
+ it) to use instead. (#287)
1072
+ - **Breaking:** Python run through `exec` asks for approval like any other
1073
+ write, including a run that only builds a new PDF. (#289)
1074
+
1075
+ ### Removed
1076
+
1077
+ - **Breaking:** the vendored Python wheels for python-pptx, python-docx,
1078
+ openpyxl, fpdf2 and pypdf, and their dependencies. Only micropip is still
1079
+ seeded; any other package installs from PyPI, which sandbox mode refuses.
1080
+ Use the office and `pdf` tools. (#286, #289)
1081
+ - The `exec` guidance written for python-pptx, python-docx and fpdf2 code:
1082
+ their error hints and source checks, and the shrink-to-fit pass on saved
1083
+ decks. (#288, #289)
1084
+
1085
+ ## [0.8.0] - 2026-10-05
1086
+
1087
+ ### Added
1088
+
1089
+ - A skill-gated `pdf` tool on `bare-pdfium` 1.6.0. With an `attachmentId` and
1090
+ no `action` it reads a PDF: the page count, each page's text and the form
1091
+ fields. With an `action` it saves a new file named `output` and attaches it:
1092
+ `create` from Markdown (chat images placed with `![caption](attachmentId)`),
1093
+ `merge`, `split`, `rotate`, `watermark`, `fill`, `encrypt`, `decrypt` and
1094
+ `text`. Errors name what exists, a locked PDF takes its password on any
1095
+ action, and the one-line answer comes back as `reply`. On Node it reports
1096
+ that the device cannot open PDFs. The pdf skill in the next `@qvac/skills`
1097
+ release uses it instead of Python. (#256)
1098
+ - An office engine in `lib/office/engine/` that reads, edits and creates `.pptx`,
1099
+ `.docx` and `.xlsx` files in TypeScript on Bare and Node, so office editing no
1100
+ longer needs Python and can run on mobile. It keeps untouched parts byte for
1101
+ byte, fails with a `DocsError` whose code names the problem, and moves Excel
1102
+ references when rows and columns change. It adds `@xmldom/xmldom`, makes
1103
+ `bare-zlib` a direct dependency and maps `#zlib` to `bare-zlib` or `zlib`.
1104
+
1105
+ ### Fixed
1106
+
1107
+ - Qwen3.5-family models: a tool call that ran goes back into the chat history
1108
+ in the Qwen3.5 template's own format (`<tool_call>` wrapper, one line per tag,
1109
+ string values as written) instead of a compact `<function=…>` line. A model
1110
+ several calls into a turn copied the compact form, the tool grammar rejected
1111
+ it, and the run ended in "This didn't finish". Models with another tool format
1112
+ (e.g. MedPsy) still get a format that is not their own, until the SDK accepts
1113
+ structured tool calls in history. (QVAC-23092, #146)
1114
+ - A skill loaded with a `file` it does not have, before its instructions were
1115
+ loaded, now returns those instructions with a line naming the files it has,
1116
+ so the skill counts as loaded and its skill-gated tools appear. Before, a
1117
+ one-file skill answered that the model already had its instructions, and its
1118
+ tools stayed hidden. (#257)
1119
+ - After a tool attaches a file, the loop tells the model the file is shown and
1120
+ to answer, allows one more tool round, then writes the answer in a tool-less
1121
+ round. Small models no longer keep calling tools on their own output until
1122
+ the round cap. (#258)
1123
+ - `exec`: a `$` before a digit, a space or punctuation in a shell command is
1124
+ escaped instead of rejected, so text like `$1,299` runs on the first try. Real
1125
+ shell expansion is still refused, now with a hint to single-quote the text.
1126
+ (#208)
1127
+
1128
+ ## [0.7.3] - 2026-10-01
1129
+
1130
+ ### Added
1131
+
1132
+ - A tool result may carry `answer: true` beside its `content` to end the turn
1133
+ with that content as the reply, without another round through the model.
1134
+ The `tool-result` event still fires. `weather_lookup` uses it for an
1135
+ ambiguous or unknown place: the question that lists the namesakes, or the
1136
+ not-found line, is the reply.
1137
+
1138
+ ### Fixed
1139
+
1140
+ - `weather_lookup` finds the place before it asks for the weather. It looks the
1141
+ city up on Open-Meteo's geocoder, `geocoding-api.open-meteo.com`, a new
1142
+ outbound host, and asks wttr.in for the forecast at the coordinates of the
1143
+ place it picked, which leads the report. A bare "Nassau" now reports Nassau,
1144
+ Bahamas. It used to ask wttr.in by name, whose own geocoder put it in
1145
+ Westbury, New York. A name that places of a similar size share, such as
1146
+ Springfield, gets a question listing up to four of them instead of a
1147
+ forecast: any namesake with a tenth of the largest one's population counts.
1148
+ A country or state in the request picks among them. When the geocoder is
1149
+ blocked, slow or failing, or knows no such place, the lookup asks wttr.in by
1150
+ name, as before. The resource label names both hosts.
1151
+
1152
+ ## [0.7.2] - 2026-10-01
1153
+
1154
+ ### Added
1155
+
1156
+ - `web_fetch` attaches a plain-text file (.txt, .csv, .json…) to the chat
1157
+ besides returning its text, so the user can open or save it and `exec` can
1158
+ stage it to read past the returned text. The result carries its
1159
+ `attachmentId`, `fileName` and `byteLength`. A body cut at the fetch cap is
1160
+ not attached, and a host that cannot store files gets the text alone, as
1161
+ with page images. (#147, #148)
1162
+
1163
+ ### Changed
1164
+
1165
+ - Speech sounds cleaner on desktops. Devices on the `mid` profile and up now
1166
+ speak with Supertonic 3 FP16 (`Supertonic3-FP16`, 207 MB) instead of Q8_0
1167
+ (127 MB), at 16 inference steps instead of 5, which removes the artifacts
1168
+ the 5-step output had. Synthesis takes about 2.7× as long, still around 7×
1169
+ faster than real time on an M-series Mac. Phones (`low`) and `tiny` devices
1170
+ keep Q4_0 at 5 steps. A host that prefetches `infraModelsFor` downloads the
1171
+ FP16 model once; `Supertonic3-Q8_0` stays in the catalog, and now also runs
1172
+ at 16 steps when a host asks for it by name. (#149)
1173
+
11
1174
  ## [0.7.1] - 2026-09-30
12
1175
 
13
1176
  ### Added
@@ -1019,7 +2182,11 @@ Tagged but never published to npm; these changes first shipped in 0.2.12.
1019
2182
  - GPU stats are read through `bare-gpu-info`, so every dependency installs from
1020
2183
  the public npm registry. (#12)
1021
2184
 
1022
- [Unreleased]: https://github.com/tetherto/qvac-harness/compare/v0.7.1...HEAD
2185
+ [Unreleased]: https://github.com/tetherto/qvac-harness/compare/v0.8.5...HEAD
2186
+ [0.8.5]: https://github.com/tetherto/qvac-harness/compare/v0.8.0...v0.8.5
2187
+ [0.8.0]: https://github.com/tetherto/qvac-harness/compare/v0.7.3...v0.8.0
2188
+ [0.7.3]: https://github.com/tetherto/qvac-harness/compare/v0.7.2...v0.7.3
2189
+ [0.7.2]: https://github.com/tetherto/qvac-harness/compare/v0.7.1...v0.7.2
1023
2190
  [0.7.1]: https://github.com/tetherto/qvac-harness/compare/v0.7.0...v0.7.1
1024
2191
  [0.7.0]: https://github.com/tetherto/qvac-harness/compare/v0.6.0...v0.7.0
1025
2192
  [0.6.0]: https://github.com/tetherto/qvac-harness/compare/v0.5.0...v0.6.0