@qvac/harness 0.1.0 → 0.1.1

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 (460) hide show
  1. package/dist/harness.bundle +8 -59
  2. package/dist/prebuilds-manifest.json +0 -8
  3. package/dist-lib/index.d.ts +240 -0
  4. package/dist-lib/index.js +1063 -0
  5. package/dist-lib/lib/audio-transcode-bare.d.ts +2 -0
  6. package/dist-lib/lib/audio-transcode-bare.js +145 -0
  7. package/dist-lib/lib/audio-transcode-node.d.ts +2 -0
  8. package/dist-lib/lib/audio-transcode-node.js +6 -0
  9. package/dist-lib/lib/capabilities/audio-resample.d.ts +14 -0
  10. package/dist-lib/lib/capabilities/audio-resample.js +72 -0
  11. package/dist-lib/lib/capabilities/completion.d.ts +288 -0
  12. package/dist-lib/lib/capabilities/completion.js +1077 -0
  13. package/dist-lib/lib/capabilities/download.d.ts +46 -0
  14. package/dist-lib/lib/capabilities/download.js +124 -0
  15. package/dist-lib/lib/capabilities/embed.d.ts +20 -0
  16. package/dist-lib/lib/capabilities/embed.js +13 -0
  17. package/dist-lib/lib/capabilities/kv-cache.d.ts +13 -0
  18. package/dist-lib/lib/capabilities/kv-cache.js +21 -0
  19. package/dist-lib/lib/capabilities/prompt-prefix.d.ts +6 -0
  20. package/dist-lib/lib/capabilities/prompt-prefix.js +10 -0
  21. package/dist-lib/lib/capabilities/speech-lexicon.d.ts +5 -0
  22. package/dist-lib/lib/capabilities/speech-lexicon.js +32 -0
  23. package/dist-lib/lib/capabilities/speech-text.d.ts +6 -0
  24. package/dist-lib/lib/capabilities/speech-text.js +79 -0
  25. package/dist-lib/lib/capabilities/tool-names.d.ts +3 -0
  26. package/dist-lib/lib/capabilities/tool-names.js +3 -0
  27. package/dist-lib/lib/capabilities/tool-selection.d.ts +43 -0
  28. package/dist-lib/lib/capabilities/tool-selection.js +60 -0
  29. package/dist-lib/lib/capabilities/tool-turns.d.ts +9 -0
  30. package/dist-lib/lib/capabilities/tool-turns.js +101 -0
  31. package/dist-lib/lib/capabilities/usage-breakdown.d.ts +27 -0
  32. package/dist-lib/lib/capabilities/usage-breakdown.js +44 -0
  33. package/dist-lib/lib/capabilities/vision-history.d.ts +3 -0
  34. package/dist-lib/lib/capabilities/vision-history.js +21 -0
  35. package/dist-lib/lib/capabilities/voice.d.ts +78 -0
  36. package/dist-lib/lib/capabilities/voice.js +189 -0
  37. package/dist-lib/lib/connect.d.ts +76 -0
  38. package/dist-lib/lib/connect.js +789 -0
  39. package/dist-lib/lib/context-window.d.ts +7 -0
  40. package/dist-lib/lib/context-window.js +90 -0
  41. package/dist-lib/lib/contract-types.d.ts +210 -0
  42. package/dist-lib/lib/contract-types.js +1 -0
  43. package/dist-lib/lib/diagram-repair.d.ts +21 -0
  44. package/dist-lib/lib/diagram-repair.js +58 -0
  45. package/dist-lib/lib/dns-lookup.d.ts +1 -0
  46. package/dist-lib/lib/dns-lookup.js +13 -0
  47. package/dist-lib/lib/error-fields.d.ts +2 -0
  48. package/dist-lib/lib/error-fields.js +8 -0
  49. package/dist-lib/lib/fetch-node.d.ts +1 -0
  50. package/dist-lib/lib/fetch-node.js +1 -0
  51. package/dist-lib/lib/hardware/capability-probe.d.ts +9 -0
  52. package/dist-lib/lib/hardware/capability-probe.js +99 -0
  53. package/dist-lib/lib/hardware/gpu-classify.d.ts +2 -0
  54. package/dist-lib/lib/hardware/gpu-classify.js +32 -0
  55. package/dist-lib/lib/hardware/gpu-probe-addon.d.ts +2 -0
  56. package/dist-lib/lib/hardware/gpu-probe-addon.js +42 -0
  57. package/dist-lib/lib/hardware/gpu-stats.bare.d.ts +1 -0
  58. package/dist-lib/lib/hardware/gpu-stats.bare.js +24 -0
  59. package/dist-lib/lib/hardware/gpu-stats.stub.d.ts +1 -0
  60. package/dist-lib/lib/hardware/gpu-stats.stub.js +3 -0
  61. package/dist-lib/lib/hardware/memory-budget.d.ts +8 -0
  62. package/dist-lib/lib/hardware/memory-budget.js +1 -0
  63. package/dist-lib/lib/hardware/parsers.d.ts +7 -0
  64. package/dist-lib/lib/hardware/parsers.js +41 -0
  65. package/dist-lib/lib/headers-bare.d.ts +1 -0
  66. package/dist-lib/lib/headers-bare.js +1 -0
  67. package/dist-lib/lib/headers-node.d.ts +4 -0
  68. package/dist-lib/lib/headers-node.js +1 -0
  69. package/dist-lib/lib/helpers/buffer-burst.d.ts +1 -0
  70. package/dist-lib/lib/helpers/buffer-burst.js +20 -0
  71. package/dist-lib/lib/helpers/control-tokens.d.ts +7 -0
  72. package/dist-lib/lib/helpers/control-tokens.js +32 -0
  73. package/dist-lib/lib/helpers/join-guard.d.ts +6 -0
  74. package/dist-lib/lib/helpers/join-guard.js +46 -0
  75. package/dist-lib/lib/helpers/markup-stream-filter.d.ts +5 -0
  76. package/dist-lib/lib/helpers/markup-stream-filter.js +75 -0
  77. package/dist-lib/lib/helpers/race-abort.d.ts +5 -0
  78. package/dist-lib/lib/helpers/race-abort.js +18 -0
  79. package/dist-lib/lib/helpers/retry-memo.d.ts +5 -0
  80. package/dist-lib/lib/helpers/retry-memo.js +12 -0
  81. package/dist-lib/lib/helpers/run-outcome.d.ts +33 -0
  82. package/dist-lib/lib/helpers/run-outcome.js +204 -0
  83. package/dist-lib/lib/helpers/spawn-path.d.ts +5 -0
  84. package/dist-lib/lib/helpers/spawn-path.js +57 -0
  85. package/dist-lib/lib/helpers/text-coalescer.d.ts +15 -0
  86. package/dist-lib/lib/helpers/text-coalescer.js +34 -0
  87. package/dist-lib/lib/helpers/thinking.d.ts +8 -0
  88. package/dist-lib/lib/helpers/thinking.js +95 -0
  89. package/dist-lib/lib/helpers/tool-call-markup.d.ts +20 -0
  90. package/dist-lib/lib/helpers/tool-call-markup.js +201 -0
  91. package/dist-lib/lib/helpers/tool-intent.d.ts +7 -0
  92. package/dist-lib/lib/helpers/tool-intent.js +21 -0
  93. package/dist-lib/lib/helpers/tool-label.d.ts +8 -0
  94. package/dist-lib/lib/helpers/tool-label.js +131 -0
  95. package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +5 -0
  96. package/dist-lib/lib/hooks/built-in/arg-repair.js +88 -0
  97. package/dist-lib/lib/hooks/built-in/egress.d.ts +5 -0
  98. package/dist-lib/lib/hooks/built-in/egress.js +29 -0
  99. package/dist-lib/lib/hooks/built-in/index.d.ts +3 -0
  100. package/dist-lib/lib/hooks/built-in/index.js +3 -0
  101. package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +10 -0
  102. package/dist-lib/lib/hooks/built-in/skill-catalog.js +17 -0
  103. package/dist-lib/lib/hooks/pipeline.d.ts +20 -0
  104. package/dist-lib/lib/hooks/pipeline.js +49 -0
  105. package/dist-lib/lib/hooks/registry.d.ts +2 -0
  106. package/dist-lib/lib/hooks/registry.js +6 -0
  107. package/dist-lib/lib/hooks/run.d.ts +5 -0
  108. package/dist-lib/lib/hooks/run.js +83 -0
  109. package/dist-lib/lib/hooks/types.d.ts +57 -0
  110. package/dist-lib/lib/hooks/types.js +1 -0
  111. package/dist-lib/lib/log.d.ts +5 -0
  112. package/dist-lib/lib/log.js +37 -0
  113. package/dist-lib/lib/model-download-progress.d.ts +22 -0
  114. package/dist-lib/lib/model-download-progress.js +95 -0
  115. package/dist-lib/lib/models/context.d.ts +5 -0
  116. package/dist-lib/lib/models/context.js +12 -0
  117. package/dist-lib/lib/models/embed-config.d.ts +14 -0
  118. package/dist-lib/lib/models/embed-config.js +31 -0
  119. package/dist-lib/lib/models/gpu-selection.d.ts +3 -0
  120. package/dist-lib/lib/models/gpu-selection.js +26 -0
  121. package/dist-lib/lib/models/kv-cache.d.ts +4 -0
  122. package/dist-lib/lib/models/kv-cache.js +6 -0
  123. package/dist-lib/lib/models/llm-presets.d.ts +10 -0
  124. package/dist-lib/lib/models/llm-presets.js +58 -0
  125. package/dist-lib/lib/models/model-catalog-constants.d.ts +29 -0
  126. package/dist-lib/lib/models/model-catalog-constants.js +103 -0
  127. package/dist-lib/lib/models/model-catalog.d.ts +125 -0
  128. package/dist-lib/lib/models/model-catalog.js +371 -0
  129. package/dist-lib/lib/models/model-delete.d.ts +18 -0
  130. package/dist-lib/lib/models/model-delete.js +47 -0
  131. package/dist-lib/lib/models/model-handle.d.ts +18 -0
  132. package/dist-lib/lib/models/model-handle.js +33 -0
  133. package/dist-lib/lib/models/model-list.d.ts +42 -0
  134. package/dist-lib/lib/models/model-list.js +123 -0
  135. package/dist-lib/lib/models/model-pool.d.ts +116 -0
  136. package/dist-lib/lib/models/model-pool.js +356 -0
  137. package/dist-lib/lib/models/model-source.d.ts +6 -0
  138. package/dist-lib/lib/models/model-source.js +21 -0
  139. package/dist-lib/lib/models/music-catalog.d.ts +12 -0
  140. package/dist-lib/lib/models/music-catalog.js +26 -0
  141. package/dist-lib/lib/models/opencl-cache.d.ts +5 -0
  142. package/dist-lib/lib/models/opencl-cache.js +50 -0
  143. package/dist-lib/lib/models/sdk-faults.d.ts +21 -0
  144. package/dist-lib/lib/models/sdk-faults.js +66 -0
  145. package/dist-lib/lib/models/tool-dialect.d.ts +2 -0
  146. package/dist-lib/lib/models/tool-dialect.js +19 -0
  147. package/dist-lib/lib/models/tts-model-default.d.ts +3 -0
  148. package/dist-lib/lib/models/tts-model-default.js +13 -0
  149. package/dist-lib/lib/no-redirect-fetch-bare.d.ts +15 -0
  150. package/dist-lib/lib/no-redirect-fetch-bare.js +59 -0
  151. package/dist-lib/lib/no-redirect-fetch-impl.d.ts +39 -0
  152. package/dist-lib/lib/no-redirect-fetch-impl.js +80 -0
  153. package/dist-lib/lib/no-redirect-fetch-node.d.ts +4 -0
  154. package/dist-lib/lib/no-redirect-fetch-node.js +52 -0
  155. package/dist-lib/lib/prompt.d.ts +22 -0
  156. package/dist-lib/lib/prompt.js +77 -0
  157. package/dist-lib/lib/queue.d.ts +9 -0
  158. package/dist-lib/lib/queue.js +48 -0
  159. package/dist-lib/lib/resolution-detector.d.ts +5 -0
  160. package/dist-lib/lib/resolution-detector.js +100 -0
  161. package/dist-lib/lib/rpc-session.d.ts +8 -0
  162. package/dist-lib/lib/rpc-session.js +20 -0
  163. package/dist-lib/lib/sdk-config-loader.node.d.ts +1 -0
  164. package/dist-lib/lib/sdk-config-loader.node.js +1 -0
  165. package/dist-lib/lib/sdk-loader.d.ts +30 -0
  166. package/dist-lib/lib/sdk-loader.js +53 -0
  167. package/dist-lib/lib/sdk-storage.d.ts +8 -0
  168. package/dist-lib/lib/sdk-storage.js +24 -0
  169. package/dist-lib/lib/serve.d.ts +3 -0
  170. package/dist-lib/lib/serve.js +612 -0
  171. package/dist-lib/lib/spawn.d.ts +62 -0
  172. package/dist-lib/lib/spawn.js +71 -0
  173. package/dist-lib/lib/staging.d.ts +4 -0
  174. package/dist-lib/lib/staging.js +28 -0
  175. package/dist-lib/lib/storage.d.ts +18 -0
  176. package/dist-lib/lib/storage.js +26 -0
  177. package/dist-lib/lib/tmp-path.d.ts +7 -0
  178. package/dist-lib/lib/tmp-path.js +17 -0
  179. package/dist-lib/lib/tool-call-display.d.ts +21 -0
  180. package/dist-lib/lib/tool-call-display.js +1 -0
  181. package/dist-lib/lib/tools/catalog.d.ts +13 -0
  182. package/dist-lib/lib/tools/catalog.js +13 -0
  183. package/dist-lib/lib/tools/create-documents.d.ts +3 -0
  184. package/dist-lib/lib/tools/create-documents.js +87 -0
  185. package/dist-lib/lib/tools/edit-documents.d.ts +3 -0
  186. package/dist-lib/lib/tools/edit-documents.js +122 -0
  187. package/dist-lib/lib/tools/edit-image.d.ts +25 -0
  188. package/dist-lib/lib/tools/edit-image.js +271 -0
  189. package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +27 -0
  190. package/dist-lib/lib/tools/exec/adapters/adapter.js +1 -0
  191. package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +26 -0
  192. package/dist-lib/lib/tools/exec/adapters/python/attachments.js +160 -0
  193. package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +7 -0
  194. package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +290 -0
  195. package/dist-lib/lib/tools/exec/adapters/python/loader.d.ts +11 -0
  196. package/dist-lib/lib/tools/exec/adapters/python/loader.js +94 -0
  197. package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +47 -0
  198. package/dist-lib/lib/tools/exec/adapters/python/memfs.js +85 -0
  199. package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +13 -0
  200. package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +129 -0
  201. package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +19 -0
  202. package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +107 -0
  203. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +75 -0
  204. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +1094 -0
  205. package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +75 -0
  206. package/dist-lib/lib/tools/exec/adapters/python/run-session.js +273 -0
  207. package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +38 -0
  208. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +102 -0
  209. package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +7 -0
  210. package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +188 -0
  211. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.d.ts +1 -0
  212. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +105 -0
  213. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +38 -0
  214. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +41 -0
  215. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.d.ts +2 -0
  216. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.js +30 -0
  217. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +13 -0
  218. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +45 -0
  219. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +12 -0
  220. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +20 -0
  221. package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +8 -0
  222. package/dist-lib/lib/tools/exec/obsidian/cli-process.js +74 -0
  223. package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +18 -0
  224. package/dist-lib/lib/tools/exec/obsidian/cli.js +153 -0
  225. package/dist-lib/lib/tools/exec/obsidian/command.d.ts +5 -0
  226. package/dist-lib/lib/tools/exec/obsidian/command.js +18 -0
  227. package/dist-lib/lib/tools/exec/obsidian/guidance.d.ts +5 -0
  228. package/dist-lib/lib/tools/exec/obsidian/guidance.js +18 -0
  229. package/dist-lib/lib/tools/exec/obsidian/note-name.d.ts +1 -0
  230. package/dist-lib/lib/tools/exec/obsidian/note-name.js +6 -0
  231. package/dist-lib/lib/tools/exec/obsidian/output.d.ts +1 -0
  232. package/dist-lib/lib/tools/exec/obsidian/output.js +31 -0
  233. package/dist-lib/lib/tools/exec/obsidian/route.d.ts +19 -0
  234. package/dist-lib/lib/tools/exec/obsidian/route.js +85 -0
  235. package/dist-lib/lib/tools/exec/obsidian/safe-path.d.ts +3 -0
  236. package/dist-lib/lib/tools/exec/obsidian/safe-path.js +56 -0
  237. package/dist-lib/lib/tools/exec/obsidian/vault-create.d.ts +1 -0
  238. package/dist-lib/lib/tools/exec/obsidian/vault-create.js +40 -0
  239. package/dist-lib/lib/tools/exec/obsidian/vault-fs.d.ts +3 -0
  240. package/dist-lib/lib/tools/exec/obsidian/vault-fs.js +57 -0
  241. package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +20 -0
  242. package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +171 -0
  243. package/dist-lib/lib/tools/exec/obsidian/vault-read.d.ts +11 -0
  244. package/dist-lib/lib/tools/exec/obsidian/vault-read.js +119 -0
  245. package/dist-lib/lib/tools/exec/obsidian/vault-write.d.ts +7 -0
  246. package/dist-lib/lib/tools/exec/obsidian/vault-write.js +134 -0
  247. package/dist-lib/lib/tools/exec/runner.d.ts +62 -0
  248. package/dist-lib/lib/tools/exec/runner.js +87 -0
  249. package/dist-lib/lib/tools/exec/scope.d.ts +3 -0
  250. package/dist-lib/lib/tools/exec/scope.js +97 -0
  251. package/dist-lib/lib/tools/exec/shell-argv.d.ts +2 -0
  252. package/dist-lib/lib/tools/exec/shell-argv.js +48 -0
  253. package/dist-lib/lib/tools/exec.d.ts +29 -0
  254. package/dist-lib/lib/tools/exec.js +459 -0
  255. package/dist-lib/lib/tools/file-glob.d.ts +15 -0
  256. package/dist-lib/lib/tools/file-glob.js +112 -0
  257. package/dist-lib/lib/tools/fs/drive.d.ts +26 -0
  258. package/dist-lib/lib/tools/fs/drive.js +1 -0
  259. package/dist-lib/lib/tools/fs/glob.d.ts +1 -0
  260. package/dist-lib/lib/tools/fs/glob.js +34 -0
  261. package/dist-lib/lib/tools/fs/local.d.ts +2 -0
  262. package/dist-lib/lib/tools/fs/local.js +29 -0
  263. package/dist-lib/lib/tools/fs/read.d.ts +2 -0
  264. package/dist-lib/lib/tools/fs/read.js +17 -0
  265. package/dist-lib/lib/tools/fs/remote-protocol.d.ts +40 -0
  266. package/dist-lib/lib/tools/fs/remote-protocol.js +1 -0
  267. package/dist-lib/lib/tools/fs/remote.d.ts +17 -0
  268. package/dist-lib/lib/tools/fs/remote.js +131 -0
  269. package/dist-lib/lib/tools/fs/scope.d.ts +37 -0
  270. package/dist-lib/lib/tools/fs/scope.js +130 -0
  271. package/dist-lib/lib/tools/fs/walk.d.ts +15 -0
  272. package/dist-lib/lib/tools/fs/walk.js +38 -0
  273. package/dist-lib/lib/tools/fs/write.d.ts +4 -0
  274. package/dist-lib/lib/tools/fs/write.js +5 -0
  275. package/dist-lib/lib/tools/generate-image.d.ts +111 -0
  276. package/dist-lib/lib/tools/generate-image.js +369 -0
  277. package/dist-lib/lib/tools/generate-music.d.ts +124 -0
  278. package/dist-lib/lib/tools/generate-music.js +522 -0
  279. package/dist-lib/lib/tools/grep.d.ts +5 -0
  280. package/dist-lib/lib/tools/grep.js +158 -0
  281. package/dist-lib/lib/tools/http-methods.d.ts +1 -0
  282. package/dist-lib/lib/tools/http-methods.js +1 -0
  283. package/dist-lib/lib/tools/http-request/encode-fields.d.ts +2 -0
  284. package/dist-lib/lib/tools/http-request/encode-fields.js +69 -0
  285. package/dist-lib/lib/tools/http-request/truncate-response.d.ts +1 -0
  286. package/dist-lib/lib/tools/http-request/truncate-response.js +83 -0
  287. package/dist-lib/lib/tools/http-request/utils.d.ts +27 -0
  288. package/dist-lib/lib/tools/http-request/utils.js +84 -0
  289. package/dist-lib/lib/tools/http-request.d.ts +20 -0
  290. package/dist-lib/lib/tools/http-request.js +177 -0
  291. package/dist-lib/lib/tools/mcp/utils.d.ts +47 -0
  292. package/dist-lib/lib/tools/mcp/utils.js +172 -0
  293. package/dist-lib/lib/tools/mcp-call.d.ts +14 -0
  294. package/dist-lib/lib/tools/mcp-call.js +155 -0
  295. package/dist-lib/lib/tools/model-args.d.ts +1 -0
  296. package/dist-lib/lib/tools/model-args.js +4 -0
  297. package/dist-lib/lib/tools/operations/builders.d.ts +17 -0
  298. package/dist-lib/lib/tools/operations/builders.js +179 -0
  299. package/dist-lib/lib/tools/operations/compile.d.ts +7 -0
  300. package/dist-lib/lib/tools/operations/compile.js +92 -0
  301. package/dist-lib/lib/tools/operations/gmail-message.d.ts +15 -0
  302. package/dist-lib/lib/tools/operations/gmail-message.js +62 -0
  303. package/dist-lib/lib/tools/operations/manifest.d.ts +60 -0
  304. package/dist-lib/lib/tools/operations/manifest.js +50 -0
  305. package/dist-lib/lib/tools/outbound-guard.d.ts +10 -0
  306. package/dist-lib/lib/tools/outbound-guard.js +127 -0
  307. package/dist-lib/lib/tools/private-ip.d.ts +4 -0
  308. package/dist-lib/lib/tools/private-ip.js +126 -0
  309. package/dist-lib/lib/tools/rag-search.d.ts +2 -0
  310. package/dist-lib/lib/tools/rag-search.js +98 -0
  311. package/dist-lib/lib/tools/read-files.d.ts +5 -0
  312. package/dist-lib/lib/tools/read-files.js +153 -0
  313. package/dist-lib/lib/tools/skill.d.ts +10 -0
  314. package/dist-lib/lib/tools/skill.js +123 -0
  315. package/dist-lib/lib/tools/skills/auth-resolver.d.ts +43 -0
  316. package/dist-lib/lib/tools/skills/auth-resolver.js +121 -0
  317. package/dist-lib/lib/tools/skills/bin-check.d.ts +9 -0
  318. package/dist-lib/lib/tools/skills/bin-check.js +56 -0
  319. package/dist-lib/lib/tools/skills/bundled-dir.d.ts +2 -0
  320. package/dist-lib/lib/tools/skills/bundled-dir.js +117 -0
  321. package/dist-lib/lib/tools/skills/bundled-hash.d.ts +4 -0
  322. package/dist-lib/lib/tools/skills/bundled-hash.js +12 -0
  323. package/dist-lib/lib/tools/skills/catalog.d.ts +60 -0
  324. package/dist-lib/lib/tools/skills/catalog.js +203 -0
  325. package/dist-lib/lib/tools/skills/cli-argv.d.ts +9 -0
  326. package/dist-lib/lib/tools/skills/cli-argv.js +147 -0
  327. package/dist-lib/lib/tools/skills/cli-schema-check.d.ts +3 -0
  328. package/dist-lib/lib/tools/skills/cli-schema-check.js +62 -0
  329. package/dist-lib/lib/tools/skills/cli-schema-load.d.ts +4 -0
  330. package/dist-lib/lib/tools/skills/cli-schema-load.js +90 -0
  331. package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +30 -0
  332. package/dist-lib/lib/tools/skills/cli-schema-types.js +1 -0
  333. package/dist-lib/lib/tools/skills/cli-schema.d.ts +7 -0
  334. package/dist-lib/lib/tools/skills/cli-schema.js +35 -0
  335. package/dist-lib/lib/tools/skills/credential-check.d.ts +20 -0
  336. package/dist-lib/lib/tools/skills/credential-check.js +94 -0
  337. package/dist-lib/lib/tools/skills/credential-grants.d.ts +9 -0
  338. package/dist-lib/lib/tools/skills/credential-grants.js +25 -0
  339. package/dist-lib/lib/tools/skills/credential-health.d.ts +8 -0
  340. package/dist-lib/lib/tools/skills/credential-health.js +51 -0
  341. package/dist-lib/lib/tools/skills/credential-slots.d.ts +7 -0
  342. package/dist-lib/lib/tools/skills/credential-slots.js +8 -0
  343. package/dist-lib/lib/tools/skills/frontmatter-parser.d.ts +23 -0
  344. package/dist-lib/lib/tools/skills/frontmatter-parser.js +68 -0
  345. package/dist-lib/lib/tools/skills/index.d.ts +5 -0
  346. package/dist-lib/lib/tools/skills/index.js +5 -0
  347. package/dist-lib/lib/tools/skills/manifest-parse.d.ts +12 -0
  348. package/dist-lib/lib/tools/skills/manifest-parse.js +199 -0
  349. package/dist-lib/lib/tools/skills/manifest.d.ts +47 -0
  350. package/dist-lib/lib/tools/skills/manifest.js +1 -0
  351. package/dist-lib/lib/tools/skills/mention-name.d.ts +1 -0
  352. package/dist-lib/lib/tools/skills/mention-name.js +4 -0
  353. package/dist-lib/lib/tools/skills/mention.d.ts +6 -0
  354. package/dist-lib/lib/tools/skills/mention.js +42 -0
  355. package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +16 -0
  356. package/dist-lib/lib/tools/skills/obsidian-readiness.js +95 -0
  357. package/dist-lib/lib/tools/skills/overlay-crud.d.ts +18 -0
  358. package/dist-lib/lib/tools/skills/overlay-crud.js +98 -0
  359. package/dist-lib/lib/tools/skills/overlay-dir.d.ts +2 -0
  360. package/dist-lib/lib/tools/skills/overlay-dir.js +22 -0
  361. package/dist-lib/lib/tools/skills/overlay-watch.d.ts +13 -0
  362. package/dist-lib/lib/tools/skills/overlay-watch.js +44 -0
  363. package/dist-lib/lib/tools/skills/scope-key.d.ts +7 -0
  364. package/dist-lib/lib/tools/skills/scope-key.js +7 -0
  365. package/dist-lib/lib/tools/skills/setup-routes.d.ts +4 -0
  366. package/dist-lib/lib/tools/skills/setup-routes.js +14 -0
  367. package/dist-lib/lib/tools/skills/skill-settings.d.ts +16 -0
  368. package/dist-lib/lib/tools/skills/skill-settings.js +33 -0
  369. package/dist-lib/lib/tools/skills/skill-state-constants.d.ts +12 -0
  370. package/dist-lib/lib/tools/skills/skill-state-constants.js +14 -0
  371. package/dist-lib/lib/tools/skills/skill-state.d.ts +40 -0
  372. package/dist-lib/lib/tools/skills/skill-state.js +117 -0
  373. package/dist-lib/lib/tools/skills/tool-grants.d.ts +5 -0
  374. package/dist-lib/lib/tools/skills/tool-grants.js +14 -0
  375. package/dist-lib/lib/tools/toolsets.d.ts +8 -0
  376. package/dist-lib/lib/tools/toolsets.js +20 -0
  377. package/dist-lib/lib/tools/url-guard.d.ts +8 -0
  378. package/dist-lib/lib/tools/url-guard.js +40 -0
  379. package/dist-lib/lib/tools/web-fetch.d.ts +8 -0
  380. package/dist-lib/lib/tools/web-fetch.js +302 -0
  381. package/dist-lib/lib/tools/web-search.d.ts +6 -0
  382. package/dist-lib/lib/tools/web-search.js +55 -0
  383. package/dist-lib/lib/transport.d.ts +12 -0
  384. package/dist-lib/lib/transport.js +59 -0
  385. package/dist-lib/lib/user-agent.d.ts +1 -0
  386. package/dist-lib/lib/user-agent.js +1 -0
  387. package/dist-lib/lib/validating-lookup.d.ts +17 -0
  388. package/dist-lib/lib/validating-lookup.js +25 -0
  389. package/dist-lib/lib/wav-encode.d.ts +5 -0
  390. package/dist-lib/lib/wav-encode.js +24 -0
  391. package/dist-lib/lib/web-fetch/embedded-state.d.ts +1 -0
  392. package/dist-lib/lib/web-fetch/embedded-state.js +131 -0
  393. package/dist-lib/lib/web-fetch/extract.d.ts +6 -0
  394. package/dist-lib/lib/web-fetch/extract.js +65 -0
  395. package/dist-lib/lib/web-fetch/images.d.ts +3 -0
  396. package/dist-lib/lib/web-fetch/images.js +43 -0
  397. package/dist-lib/lib/web-fetch/video.d.ts +5 -0
  398. package/dist-lib/lib/web-fetch/video.js +42 -0
  399. package/dist-lib/lib/web-search/engine-registry.d.ts +7 -0
  400. package/dist-lib/lib/web-search/engine-registry.js +17 -0
  401. package/dist-lib/lib/web-search/engines/aol.d.ts +3 -0
  402. package/dist-lib/lib/web-search/engines/aol.js +81 -0
  403. package/dist-lib/lib/web-search/engines/bing.d.ts +3 -0
  404. package/dist-lib/lib/web-search/engines/bing.js +111 -0
  405. package/dist-lib/lib/web-search/engines/brave.d.ts +3 -0
  406. package/dist-lib/lib/web-search/engines/brave.js +59 -0
  407. package/dist-lib/lib/web-search/engines/duckduckgo.d.ts +3 -0
  408. package/dist-lib/lib/web-search/engines/duckduckgo.js +112 -0
  409. package/dist-lib/lib/web-search/engines/google.d.ts +3 -0
  410. package/dist-lib/lib/web-search/engines/google.js +92 -0
  411. package/dist-lib/lib/web-search/engines/wikipedia.d.ts +3 -0
  412. package/dist-lib/lib/web-search/engines/wikipedia.js +37 -0
  413. package/dist-lib/lib/web-search/engines/yahoo.d.ts +3 -0
  414. package/dist-lib/lib/web-search/engines/yahoo.js +81 -0
  415. package/dist-lib/lib/web-search/fetch-html.d.ts +25 -0
  416. package/dist-lib/lib/web-search/fetch-html.js +97 -0
  417. package/dist-lib/lib/web-search/format-results.d.ts +3 -0
  418. package/dist-lib/lib/web-search/format-results.js +14 -0
  419. package/dist-lib/lib/web-search/html-helpers.d.ts +3 -0
  420. package/dist-lib/lib/web-search/html-helpers.js +24 -0
  421. package/dist-lib/lib/web-search/merge-results.d.ts +2 -0
  422. package/dist-lib/lib/web-search/merge-results.js +53 -0
  423. package/dist-lib/lib/web-search/orchestrator.d.ts +14 -0
  424. package/dist-lib/lib/web-search/orchestrator.js +50 -0
  425. package/dist-lib/lib/web-search/types.d.ts +34 -0
  426. package/dist-lib/lib/web-search/types.js +1 -0
  427. package/dist-lib/lib/web-search/url-helpers.d.ts +1 -0
  428. package/dist-lib/lib/web-search/url-helpers.js +11 -0
  429. package/dist-lib/lib/web-search/url-normalize.d.ts +1 -0
  430. package/dist-lib/lib/web-search/url-normalize.js +25 -0
  431. package/dist-lib/lib/web-search/user-agents.d.ts +3 -0
  432. package/dist-lib/lib/web-search/user-agents.js +3 -0
  433. package/dist-lib/lib/wire.d.ts +50 -0
  434. package/dist-lib/lib/wire.js +145 -0
  435. package/dist-lib/schema/baseline.d.ts +8 -0
  436. package/dist-lib/schema/baseline.js +35 -0
  437. package/dist-lib/schema/build.d.ts +1 -0
  438. package/dist-lib/schema/build.js +39 -0
  439. package/dist-lib/schema/generate.d.ts +20 -0
  440. package/dist-lib/schema/generate.js +149 -0
  441. package/dist-lib/schema/harness.d.ts +2 -0
  442. package/dist-lib/schema/harness.js +745 -0
  443. package/dist-lib/schema/release-tags.d.ts +5 -0
  444. package/dist-lib/schema/release-tags.js +58 -0
  445. package/dist-lib/spec/bind.d.ts +2 -0
  446. package/dist-lib/spec/bind.js +124 -0
  447. package/dist-lib/spec/calls.d.ts +3 -0
  448. package/dist-lib/spec/calls.js +41 -0
  449. package/dist-lib/spec/hrpc/hrpc.json +356 -0
  450. package/dist-lib/spec/hrpc/index.d.ts +3 -0
  451. package/dist-lib/spec/hrpc/index.js +463 -0
  452. package/dist-lib/spec/hrpc/messages.d.ts +4 -0
  453. package/dist-lib/spec/hrpc/messages.js +3102 -0
  454. package/dist-lib/spec/hyperschema/index.js +3102 -0
  455. package/dist-lib/spec/hyperschema/schema.json +2290 -0
  456. package/dist-lib/spec/hyperschema/types.d.ts +554 -0
  457. package/dist-lib/spec/index.d.ts +8 -0
  458. package/dist-lib/spec/index.js +1 -0
  459. package/package.json +239 -64
  460. package/.gitattributes +0 -1
@@ -0,0 +1,1063 @@
1
+ import fs from 'fs';
2
+ import { platform, totalmem } from 'os';
3
+ import process from 'process';
4
+ import ReadyResource from 'ready-resource';
5
+ import { readSystemStats } from '#hw-gpu-stats';
6
+ import { probeCapabilityProfile } from "./lib/hardware/capability-probe.js";
7
+ import { closePythonWorker } from "./lib/tools/exec/adapters/python/worker/client.js";
8
+ import { completion } from "./lib/capabilities/completion.js";
9
+ import { download } from "./lib/capabilities/download.js";
10
+ import { createEmbedLane } from "./lib/capabilities/embed.js";
11
+ import { deleteAllKvCaches } from "./lib/capabilities/kv-cache.js";
12
+ import { pcmForTranscription } from "./lib/capabilities/audio-resample.js";
13
+ import { buildWavBuffer } from "./lib/wav-encode.js";
14
+ import { createVoiceLane, packSamples, speakOnce, speakStreamOnce, transcribeOnce, transcribeStreaming, SUPERTONIC_SAMPLE_RATE } from "./lib/capabilities/voice.js";
15
+ import { pushQueue } from "./lib/queue.js";
16
+ import { AbortedError, raceAbort } from "./lib/helpers/race-abort.js";
17
+ import { audioGenDownloadMetadata, customProjectionMap, defaultProjectionMap, defaultTtsFor, defaultVoiceModel, diffusionDownloadMetadata, infraModelsFor, modelNameToCapabilityProfile, musicModelSet, setCustomModels } from "./lib/models/model-catalog.js";
18
+ import { createModelStatusCache, invalidateModelStatusCache, listModels } from "./lib/models/model-list.js";
19
+ import { deleteModelFiles, summarizeDelete } from "./lib/models/model-delete.js";
20
+ import { createEmbedPool, createLoadTracker, createModelPool, createVoicePool, evictAllWithin, evictIdle, evictModelWithin, isResident, leaseCount, loadedModels, modelKey, releaseModel, resolveLoadOptions, progressState } from "./lib/models/model-pool.js";
21
+ import { resolveMainGpu } from "./lib/models/gpu-selection.js";
22
+ import { openclCacheDir } from "./lib/models/opencl-cache.js";
23
+ import { assertEmbedDevice, createEmbedConfig } from "./lib/models/embed-config.js";
24
+ import { createGpuFaultState, isSdkGpuDeviceLostError, isSdkModelWedgedError } from "./lib/models/sdk-faults.js";
25
+ import { createSdkLoader } from "./lib/sdk-loader.js";
26
+ import { createEditImageTool } from "./lib/tools/edit-image.js";
27
+ import { toolCatalog } from "./lib/tools/catalog.js";
28
+ import { createDiffusionRuntime, createGenerateImageTool } from "./lib/tools/generate-image.js";
29
+ import { createGenerateMusicTool, createMusicRuntime } from "./lib/tools/generate-music.js";
30
+ import { availableSkills, detectPlatform, loadSkillCatalog, resolveSkillStatuses, skillSupportsPlatform, versionProbeSkills } from "./lib/tools/skills/catalog.js";
31
+ import { ensureBundledSkillsDir } from "./lib/tools/skills/bundled-dir.js";
32
+ import { ensureSkillsOverlayDir } from "./lib/tools/skills/overlay-dir.js";
33
+ import { copyBaseForEdit, deleteOverlaySkill, listManagedSkills, readSkillFile, writeSkillFile } from "./lib/tools/skills/overlay-crud.js";
34
+ import { watchSkillsOverlay } from "./lib/tools/skills/overlay-watch.js";
35
+ import { hlog } from "./lib/log.js";
36
+ import { harness } from './spec/index.js';
37
+ import { installResolutionDetector, resolutionDetail } from "./lib/resolution-detector.js";
38
+ import { probeBinVersions } from "./lib/tools/skills/bin-check.js";
39
+ import { bareRuntime } from "./lib/tools/exec.js";
40
+ import { runCommand } from "./lib/tools/exec/runner.js";
41
+ import { createLocalRoots } from "./lib/tools/fs/local.js";
42
+ import { createRemoteRoots } from "./lib/tools/fs/remote.js";
43
+ import { resetCredentialHealth as resetCredentialHealthAfterSnapshot } from "./lib/tools/skills/credential-health.js";
44
+ import { isDeviceSharedCredentialKey, scopeKey } from "./lib/tools/skills/scope-key.js";
45
+ import { settingsScopeKey } from "./lib/tools/skills/skill-settings.js";
46
+ export * from "./lib/capabilities/completion.js";
47
+ export { attachmentTurn, loadedSkillsFrom, skillLoadedTurn } from "./lib/capabilities/tool-turns.js";
48
+ export * from "./lib/capabilities/download.js";
49
+ export * from "./lib/models/model-catalog.js";
50
+ export * from "./lib/models/model-list.js";
51
+ export { harnessChild, spawnHarness } from "./lib/spawn.js";
52
+ export { settingsDimension, settingsSteps } from "./lib/tools/generate-image.js";
53
+ export * from "./lib/tools/skills/catalog.js";
54
+ export { requiredSettings, settingEnvName } from "./lib/tools/skills/skill-settings.js";
55
+ export { TOOLSETS, toolsetEnabled } from "./lib/tools/toolsets.js";
56
+ export { markCredentialRejected, markCredentialValid, recordCredentialHealth, resetAllCredentialHealth, resetCredentialHealth } from "./lib/tools/skills/credential-health.js";
57
+ export { readSetup as normalizeSkillSetup } from "./lib/tools/skills/manifest-parse.js";
58
+ export { isAvailableState, SKILL_STATE } from "./lib/tools/skills/skill-state.js";
59
+ export { connectHarness, HARNESS_DIED, RemoteHarness } from "./lib/connect.js";
60
+ export { serveHarness } from "./lib/serve.js";
61
+ export { hlog, setHarnessLog, setHarnessLogSink } from "./lib/log.js";
62
+ export { harnessHooks } from "./lib/hooks/registry.js";
63
+ export { EgressGuardHook, SkillCatalogGuardHook } from "./lib/hooks/built-in/index.js";
64
+ const HarnessState = harness.getEnum('@harness/state');
65
+ const BIN_VERSION_PROBE_TTL_MS = 45_000;
66
+ const TRANSCRIBE_STREAM_MIN_BYTES = 16_000 * 2 * 60;
67
+ const TRANSCRIPTION_MODEL_LABEL = 'transcription model';
68
+ const DIFFUSION_EVICT_WAIT_MS = 15_000;
69
+ const MUSIC_EVICT_WAIT_MS = 15_000;
70
+ const WEDGED_EVICT_WAIT_MS = 10_000;
71
+ const WEDGED_EVICT_LEASED_MS = 120_000;
72
+ const TTS_MODEL_CONFIG = {
73
+ ttsEngine: 'supertonic',
74
+ language: 'en',
75
+ ttsSpeed: 1.175,
76
+ ttsNumInferenceSteps: 5
77
+ };
78
+ export class Harness extends ReadyResource {
79
+ _tools;
80
+ _sdk;
81
+ _loads = createLoadTracker();
82
+ _modelStatus = createModelStatusCache();
83
+ _models;
84
+ _embedModels;
85
+ _retiredEmbedModels;
86
+ _embedLane = createEmbedLane();
87
+ _embedFaults;
88
+ _embedGpuLayers;
89
+ _embedBatchSize;
90
+ _embedControl;
91
+ _ttsModels;
92
+ _transcriptionModels;
93
+ _voiceLane = createVoiceLane();
94
+ _state;
95
+ _skillsDir;
96
+ _overlayWatcher = null;
97
+ _supportedSkills;
98
+ _projectionModel;
99
+ _customProjection = {};
100
+ _llmDevice;
101
+ _llmGpuLayers;
102
+ _contextSize;
103
+ _kvCacheK;
104
+ _kvCacheV;
105
+ _transcriptionDevice;
106
+ _allSkills;
107
+ _credentialStore;
108
+ _credentials = new Map();
109
+ _settings = new Map();
110
+ _platform;
111
+ _diffusionSdk;
112
+ _imageRuntime;
113
+ _musicSdk;
114
+ _musicRuntime;
115
+ _capability = null;
116
+ _capabilityInflight = null;
117
+ _modelFaults = new Map();
118
+ constructor({ tools = [], sdkLoader, skillsDir, projectionModel, imageModel, imageClamps, musicModel, musicClamps, llmDevice, llmGpuLayers, contextSize, kvCacheK, kvCacheV, embedDevice, embedGpuLayers, embedBatchSize, transcriptionDevice, credentialStore, platform } = {}) {
119
+ super();
120
+ this._sdk = sdkLoader ?? createSdkLoader();
121
+ this._llmDevice = llmDevice;
122
+ this._llmGpuLayers = llmGpuLayers;
123
+ this._contextSize = contextSize;
124
+ this._kvCacheK = kvCacheK;
125
+ this._kvCacheV = kvCacheV;
126
+ this._transcriptionDevice = transcriptionDevice;
127
+ const embedConfig = createEmbedConfig({
128
+ device: embedDevice,
129
+ gpuLayers: embedGpuLayers,
130
+ batchSize: embedBatchSize
131
+ });
132
+ this._embedGpuLayers = embedConfig.gpuLayers;
133
+ this._embedBatchSize = embedConfig.batchSize;
134
+ this._retiredEmbedModels = new Set();
135
+ this._embedControl = Promise.resolve();
136
+ this._embedFaults = createGpuFaultState({
137
+ device: embedConfig.device,
138
+ gpuLayers: embedConfig.gpuLayers
139
+ });
140
+ const image = typeof imageModel === 'string' ? { model: imageModel } : imageModel;
141
+ this._imageRuntime = image
142
+ ? createDiffusionRuntime({
143
+ ...image,
144
+ loads: this._loads,
145
+ loadSdk: () => this._loadDiffusionSdk(),
146
+ onProgress: (model, progress) => {
147
+ const state = progressState(model, progress);
148
+ if (state.status === 'loading' && state.percentage === 100) {
149
+ invalidateModelStatusCache(this._modelStatus);
150
+ }
151
+ this.emit('model', state);
152
+ },
153
+ onBeforeLoad: async (signal) => {
154
+ if (this._models.destroyed)
155
+ return;
156
+ const evicted = await evictAllWithin(this._models, DIFFUSION_EVICT_WAIT_MS, undefined, signal);
157
+ if (signal?.aborted)
158
+ throw new AbortedError();
159
+ if (!evicted) {
160
+ throw new Error('the chat model is busy; try the image again once the current reply finishes');
161
+ }
162
+ }
163
+ })
164
+ : null;
165
+ const music = typeof musicModel === 'string' ? (musicModelSet(musicModel) ?? undefined) : musicModel;
166
+ this._musicRuntime = music
167
+ ? createMusicRuntime({
168
+ ...music,
169
+ loads: this._loads,
170
+ loadSdk: () => this._loadMusicSdk(),
171
+ onProgress: (model, progress) => this.emit('model', progressState(model, progress)),
172
+ onBeforeLoad: async (signal) => {
173
+ if (this._models.destroyed)
174
+ return;
175
+ const evicted = await evictAllWithin(this._models, MUSIC_EVICT_WAIT_MS, undefined, signal);
176
+ if (signal?.aborted)
177
+ throw new AbortedError();
178
+ if (!evicted) {
179
+ throw new Error('the chat model is busy; try the music again once the current reply finishes');
180
+ }
181
+ }
182
+ })
183
+ : null;
184
+ this._tools = [
185
+ ...tools,
186
+ ...(this._imageRuntime
187
+ ? [
188
+ createGenerateImageTool(this._imageRuntime, imageClamps),
189
+ createEditImageTool(this._imageRuntime, {}, imageClamps)
190
+ ]
191
+ : []),
192
+ ...(this._musicRuntime ? [createGenerateMusicTool(this._musicRuntime, musicClamps)] : [])
193
+ ];
194
+ this._projectionModel = projectionModel ?? defaultProjectionMap();
195
+ this._state = HarnessState.RESUME;
196
+ this._skillsDir = skillsDir;
197
+ this._supportedSkills = [];
198
+ this._allSkills = [];
199
+ this._credentialStore = credentialStore;
200
+ this._platform = platform;
201
+ this._diffusionSdk = null;
202
+ this._musicSdk = null;
203
+ }
204
+ async _open() {
205
+ installResolutionDetector(import.meta);
206
+ this._models = this._createPool();
207
+ this._embedModels = this._createEmbedPool();
208
+ this._ttsModels = this._createTtsPool();
209
+ this._transcriptionModels = this._createTranscriptionPool();
210
+ await this._reloadSkills();
211
+ await this._startOverlayWatch();
212
+ hlog('open', { skills: this._supportedSkills.length, tools: this._tools.length });
213
+ }
214
+ get suspended() {
215
+ return this._state === HarnessState.SUSPEND;
216
+ }
217
+ get skillNames() {
218
+ return this._supportedSkills.map((skill) => skill.name);
219
+ }
220
+ setCredentials(entries) {
221
+ const previous = this._credentials;
222
+ const next = new Map();
223
+ for (const { key, token, expiresAt, agentId, skill } of entries) {
224
+ if (!token)
225
+ continue;
226
+ const storeKey = scopeKey({ agentId, skill, key });
227
+ const record = {
228
+ token,
229
+ ...(typeof expiresAt === 'number' && expiresAt > 0 ? { expiresAt } : {})
230
+ };
231
+ const current = previous.get(storeKey);
232
+ if (!current || current.token !== record.token || current.expiresAt !== record.expiresAt) {
233
+ resetCredentialHealthAfterSnapshot(key, agentId, skill);
234
+ }
235
+ next.set(storeKey, record);
236
+ }
237
+ this._credentials = next;
238
+ }
239
+ setSkillSettings(entries) {
240
+ const next = new Map();
241
+ for (const { skill, key, value, agentId } of entries) {
242
+ if (!skill || !key || typeof value !== 'string')
243
+ continue;
244
+ const scope = settingsScopeKey(skill, agentId);
245
+ const bucket = next.get(scope) ?? {};
246
+ bucket[key] = value;
247
+ next.set(scope, bucket);
248
+ }
249
+ this._settings = next;
250
+ }
251
+ skillSettings(skill, agentId) {
252
+ return {
253
+ ...this._settings.get(settingsScopeKey(skill, null)),
254
+ ...(agentId ? this._settings.get(settingsScopeKey(skill, agentId)) : undefined)
255
+ };
256
+ }
257
+ async _baseSkillsDir() {
258
+ return this._skillsDir ?? (await ensureBundledSkillsDir());
259
+ }
260
+ async listManagedSkills() {
261
+ return listManagedSkills(await this._baseSkillsDir(), await ensureSkillsOverlayDir());
262
+ }
263
+ async readSkillFile(name) {
264
+ return readSkillFile(await this._baseSkillsDir(), await ensureSkillsOverlayDir(), name);
265
+ }
266
+ async writeSkillFile(name, content) {
267
+ const overlay = await ensureSkillsOverlayDir();
268
+ if (!overlay)
269
+ throw new Error('no writable skills overlay is configured');
270
+ await writeSkillFile(overlay, name, content);
271
+ await this._reloadSkills();
272
+ return { ok: true };
273
+ }
274
+ async copyBaseForEdit(name) {
275
+ const overlay = await ensureSkillsOverlayDir();
276
+ if (!overlay)
277
+ throw new Error('no writable skills overlay is configured');
278
+ const result = await copyBaseForEdit(await this._baseSkillsDir(), overlay, name);
279
+ if (result.copied)
280
+ await this._reloadSkills();
281
+ return result;
282
+ }
283
+ async deleteOverlaySkill(name) {
284
+ const overlay = await ensureSkillsOverlayDir();
285
+ if (!overlay)
286
+ throw new Error('no writable skills overlay is configured');
287
+ const result = await deleteOverlaySkill(overlay, name);
288
+ if (result.removed)
289
+ await this._reloadSkills();
290
+ return result;
291
+ }
292
+ resolveCredential(key, ctx) {
293
+ if (this._credentialStore)
294
+ return this._credentialStore(key, ctx);
295
+ const agentId = ctx?.agentId ?? null;
296
+ const deviceShared = isDeviceSharedCredentialKey(key);
297
+ for (const skill of ctx?.skills ?? []) {
298
+ const owned = this._credentials.get(scopeKey({ agentId, skill, key })) ??
299
+ (agentId && deviceShared ? this._credentials.get(scopeKey({ skill, key })) : undefined);
300
+ if (owned)
301
+ return owned;
302
+ }
303
+ if (agentId) {
304
+ const scoped = this._credentials.get(scopeKey({ agentId, key }));
305
+ if (scoped)
306
+ return scoped;
307
+ }
308
+ if (!agentId || deviceShared)
309
+ return this._credentials.get(scopeKey({ key })) ?? null;
310
+ return null;
311
+ }
312
+ async _completionSkills(agentId, model) {
313
+ const statuses = new Map((await this.skills(agentId, model, { skipCredentialProbe: true, skipBinProbe: true })).map((entry) => [entry.name, entry.status]));
314
+ return availableSkills(this._supportedSkills, new Set(this._tools.map((tool) => tool.name)), modelNameToCapabilityProfile(model)).map((entry) => ({
315
+ ...entry,
316
+ status: statuses.get(entry.name)
317
+ }));
318
+ }
319
+ async skills(agentId, modelName, options) {
320
+ await this.ready();
321
+ const platform = this._platform ?? detectPlatform();
322
+ const refresh = options?.refresh === true;
323
+ return resolveSkillStatuses(this._allSkills, {
324
+ installedTools: new Set(this._tools.map((tool) => tool.name)),
325
+ credentialStore: (key, ctx) => this.resolveCredential(key, ctx),
326
+ settingsStore: (skill, agentId) => this.skillSettings(skill, agentId),
327
+ platform,
328
+ agentId,
329
+ binVersions: options?.skipBinProbe === true
330
+ ? (this._binVersionCache?.bySkill ?? new Map())
331
+ : await this._probeBinVersions(platform, refresh),
332
+ refresh,
333
+ skipCredentialProbe: options?.skipCredentialProbe === true,
334
+ ...(modelName ? { activeProfile: modelNameToCapabilityProfile(modelName) } : {})
335
+ });
336
+ }
337
+ async _reloadSkills() {
338
+ const skillsDir = this._skillsDir ?? (await ensureBundledSkillsDir());
339
+ this._allSkills = await loadSkillCatalog(skillsDir, { platform: null });
340
+ const platform = this._platform ?? detectPlatform();
341
+ const supported = this._allSkills.filter((skill) => skillSupportsPlatform(skill, platform));
342
+ this._supportedSkills = availableSkills(supported, new Set(this._tools.map((t) => t.name)));
343
+ }
344
+ async _startOverlayWatch() {
345
+ if (this._overlayWatcher)
346
+ return;
347
+ try {
348
+ const overlay = await ensureSkillsOverlayDir();
349
+ if (!overlay)
350
+ return;
351
+ this._overlayWatcher = watchSkillsOverlay(overlay, () => {
352
+ this._reloadSkills().catch((err) => hlog('overlay reload failed', { err: err instanceof Error ? err.message : String(err) }));
353
+ });
354
+ }
355
+ catch (err) {
356
+ hlog('overlay watch unavailable', { err: err instanceof Error ? err.message : String(err) });
357
+ }
358
+ }
359
+ async tools() {
360
+ return toolCatalog(this._tools);
361
+ }
362
+ _binVersionCache = null;
363
+ _binVersionInflight = null;
364
+ async _probeBinVersions(platform, refresh = false) {
365
+ const now = Date.now();
366
+ if (!refresh && this._binVersionCache && this._binVersionCache.expiresAt > now) {
367
+ return this._binVersionCache.bySkill;
368
+ }
369
+ if (this._binVersionInflight)
370
+ return this._binVersionInflight;
371
+ this._binVersionInflight = this._runBinVersionProbes(platform)
372
+ .then((bySkill) => {
373
+ this._binVersionCache = {
374
+ expiresAt: Date.now() + BIN_VERSION_PROBE_TTL_MS,
375
+ bySkill
376
+ };
377
+ return bySkill;
378
+ })
379
+ .finally(() => {
380
+ this._binVersionInflight = null;
381
+ });
382
+ return this._binVersionInflight;
383
+ }
384
+ async _runBinVersionProbes(platform) {
385
+ if (process.env.QVAC_NO_SKILL_BIN_PROBE)
386
+ return new Map();
387
+ const installed = new Set(this._tools.map((tool) => tool.name));
388
+ const candidates = versionProbeSkills(this._allSkills, installed, platform);
389
+ if (candidates.length === 0)
390
+ return new Map();
391
+ let runtime;
392
+ try {
393
+ runtime = await bareRuntime();
394
+ }
395
+ catch {
396
+ return new Map();
397
+ }
398
+ const run = async (command) => {
399
+ try {
400
+ const result = await runCommand(command, { ...runtime, timeoutMs: 5_000 });
401
+ return result.exitCode === 0 ? result.stdout : null;
402
+ }
403
+ catch {
404
+ return null;
405
+ }
406
+ };
407
+ const bySkill = new Map();
408
+ for (const skill of candidates) {
409
+ const states = await probeBinVersions(skill.requires, { platform, run });
410
+ if (states.size > 0)
411
+ bySkill.set(skill.name, states);
412
+ }
413
+ return bySkill;
414
+ }
415
+ get toolNames() {
416
+ return this._tools.map((tool) => tool.name);
417
+ }
418
+ get supportsImages() {
419
+ if (!this._projectionModel)
420
+ return false;
421
+ if (typeof this._projectionModel === 'string')
422
+ return true;
423
+ return Object.keys(this._projectionModel).length > 0;
424
+ }
425
+ supportsImagesFor(model) {
426
+ return Boolean(this._projectionFor(model));
427
+ }
428
+ _projectionFor(model) {
429
+ const custom = this._customProjection[model];
430
+ if (custom)
431
+ return custom;
432
+ const projection = this._projectionModel;
433
+ if (!projection)
434
+ return undefined;
435
+ return typeof projection === 'string' ? projection : projection[model];
436
+ }
437
+ setCustomModels(entries) {
438
+ setCustomModels(entries);
439
+ this._customProjection = customProjectionMap();
440
+ }
441
+ async describe() {
442
+ if (!this.opened)
443
+ await this.ready();
444
+ return {
445
+ toolNames: this.toolNames,
446
+ skills: this._supportedSkills.map((skill) => skill.name),
447
+ supportsImages: this.supportsImages,
448
+ supportsKvCacheDeletion: true
449
+ };
450
+ }
451
+ diagnostics() {
452
+ return {
453
+ models: this.opened ? this._loadedModels() : [],
454
+ suspended: this.suspended,
455
+ sdkLoaded: this._sdk.peek() !== null,
456
+ toolNames: this.toolNames,
457
+ skills: this._supportedSkills.map((skill) => skill.name),
458
+ device: this._llmDevice
459
+ };
460
+ }
461
+ _loadedModels() {
462
+ const pools = [this._embedModels, ...this._retiredEmbedModels];
463
+ if (this._ttsModels)
464
+ pools.push(this._ttsModels);
465
+ if (this._transcriptionModels)
466
+ pools.push(this._transcriptionModels);
467
+ return [...loadedModels(this._models), ...pools.flatMap((pool) => loadedModels(pool))];
468
+ }
469
+ _loadPluginSdk(current, store, importPlugin) {
470
+ let pending = current();
471
+ if (!pending) {
472
+ pending = (async () => {
473
+ const sdk = await this._sdk.load();
474
+ const [plugin, { registerPlugin }] = await Promise.all([
475
+ importPlugin(),
476
+ import('@qvac/sdk/plugins')
477
+ ]);
478
+ try {
479
+ registerPlugin(plugin);
480
+ }
481
+ catch { }
482
+ return sdk;
483
+ })().catch((err) => {
484
+ store(null);
485
+ throw err;
486
+ });
487
+ store(pending);
488
+ }
489
+ return pending;
490
+ }
491
+ _loadDiffusionSdk() {
492
+ return this._loadPluginSdk(() => this._diffusionSdk, (sdk) => {
493
+ this._diffusionSdk = sdk;
494
+ }, () => import('@qvac/sdk/sdcpp-generation/plugin').then((m) => m.diffusionPlugin));
495
+ }
496
+ _loadMusicSdk() {
497
+ return this._loadPluginSdk(() => this._musicSdk, (sdk) => {
498
+ this._musicSdk = sdk;
499
+ }, () => import('@qvac/sdk/audiogen-ggml/plugin').then((m) => m.audioGenPlugin));
500
+ }
501
+ _deviceConfig() {
502
+ return {
503
+ device: this._llmDevice,
504
+ gpuLayers: this._llmGpuLayers,
505
+ contextSize: this._contextSize,
506
+ kvCacheK: this._kvCacheK,
507
+ kvCacheV: this._kvCacheV,
508
+ mainGpu: resolveMainGpu,
509
+ openclCacheDir
510
+ };
511
+ }
512
+ _createPool() {
513
+ const loadSdk = this._sdk.load;
514
+ return createModelPool(loadSdk, (state) => this._notifyModel(state, true), this._deviceConfig(), this._loads);
515
+ }
516
+ _createEmbedPool() {
517
+ const loadSdk = () => this._sdk.loadEmbed();
518
+ return createEmbedPool(loadSdk, (state) => this._notifyModel(state, false), this._embedFaults, this._embedBatchSize, openclCacheDir, this._loads);
519
+ }
520
+ _createTtsPool() {
521
+ const loadSdk = () => this._sdk.loadVoice();
522
+ return createVoicePool(loadSdk, (state) => this._notifyModel(state, false), 'tts-ggml', 'tts', TTS_MODEL_CONFIG, undefined, this._loads);
523
+ }
524
+ _createTranscriptionPool() {
525
+ const loadSdk = () => this._sdk.loadVoice();
526
+ return createVoicePool(loadSdk, (state) => this._notifyModel({ ...state, model: TRANSCRIPTION_MODEL_LABEL }, false), 'parakeet-transcription', 'parakeet', { useGPU: this._transcriptionDevice !== 'cpu' }, openclCacheDir, this._loads);
527
+ }
528
+ _notifyModel(state, languageModel) {
529
+ const catalogChanged = languageModel && (state.status === 'ready' || state.status === 'unloaded');
530
+ if (catalogChanged) {
531
+ invalidateModelStatusCache(this._modelStatus);
532
+ }
533
+ this.emit('model', { ...state, catalogChanged, loaded: this._loadedModels() });
534
+ }
535
+ async _collectRetiredEmbedPool(pool) {
536
+ if (!this._retiredEmbedModels.has(pool) || pool.idle !== pool.size)
537
+ return;
538
+ this._retiredEmbedModels.delete(pool);
539
+ await pool.destroy();
540
+ }
541
+ async _releaseEmbedResource(pool, key) {
542
+ releaseModel(pool, key);
543
+ await this._collectRetiredEmbedPool(pool);
544
+ }
545
+ _releaseEmbedResourceAfter(settled, pool, key) {
546
+ settled
547
+ .then(() => this._releaseEmbedResource(pool, key), () => this._releaseEmbedResource(pool, key))
548
+ .catch(noop);
549
+ }
550
+ async _destroyEmbedPools() {
551
+ const pools = [this._embedModels, ...this._retiredEmbedModels];
552
+ this._retiredEmbedModels.clear();
553
+ await Promise.all(pools.map((pool) => pool.destroy()));
554
+ }
555
+ _enqueueEmbedControl(run) {
556
+ const next = this._embedControl.then(run, run);
557
+ this._embedControl = next.catch(noop);
558
+ return next;
559
+ }
560
+ getEmbeddingDevice() {
561
+ return this._embedFaults.device;
562
+ }
563
+ setEmbeddingDevice(device) {
564
+ assertEmbedDevice(device);
565
+ return this._enqueueEmbedControl(() => this._setEmbeddingDevice(device));
566
+ }
567
+ async _setEmbeddingDevice(device) {
568
+ await this.ready();
569
+ if (this.closing)
570
+ throw new Error('harness is closing');
571
+ if (this._embedFaults.device === device)
572
+ return;
573
+ this._embedFaults = createGpuFaultState({ device, gpuLayers: this._embedGpuLayers });
574
+ if (this.suspended)
575
+ return;
576
+ const retired = this._embedModels;
577
+ this._retiredEmbedModels.add(retired);
578
+ this._embedModels = this._createEmbedPool();
579
+ await this._collectRetiredEmbedPool(retired);
580
+ }
581
+ async presuspend() {
582
+ if (this.closing)
583
+ return;
584
+ this._state = HarnessState.PRESUSPEND;
585
+ hlog('presuspend');
586
+ }
587
+ async suspend() {
588
+ hlog('suspend called');
589
+ if (this._state === HarnessState.SUSPEND)
590
+ return;
591
+ if (this.closing)
592
+ return;
593
+ this._state = HarnessState.SUSPEND;
594
+ hlog('suspending', { models: loadedModels(this._models).map((entry) => entry.model) });
595
+ const pending = this._sdk.peek();
596
+ if (pending)
597
+ this._loads.drain(await pending);
598
+ await this._releaseRuntimes();
599
+ await this._sdkLifecycle('suspend');
600
+ invalidateModelStatusCache(this._modelStatus);
601
+ hlog('suspended');
602
+ }
603
+ async _sdkLifecycle(op) {
604
+ const sdk = await this._sdk.peek()?.catch(noop);
605
+ if (!sdk)
606
+ return;
607
+ try {
608
+ await sdk[op]();
609
+ }
610
+ catch (err) {
611
+ hlog(`sdk ${op} failed`, { err: err instanceof Error ? err.message : String(err) });
612
+ if (op === 'suspend')
613
+ return;
614
+ await sdk.resume().catch((retryErr) => {
615
+ hlog('sdk resume retry failed', {
616
+ err: retryErr instanceof Error ? retryErr.message : String(retryErr)
617
+ });
618
+ });
619
+ }
620
+ }
621
+ async _releaseRuntimes() {
622
+ const released = await Promise.allSettled([
623
+ this._models.destroy(),
624
+ this._destroyEmbedPools(),
625
+ this._ttsModels.destroy(),
626
+ this._transcriptionModels.destroy(),
627
+ this._imageRuntime?.unload(),
628
+ this._musicRuntime?.unload()
629
+ ]);
630
+ for (const outcome of released) {
631
+ if (outcome.status !== 'rejected')
632
+ continue;
633
+ const err = outcome.reason;
634
+ hlog('unload failed', { err: err instanceof Error ? err.message : String(err) });
635
+ }
636
+ }
637
+ async resume() {
638
+ hlog('resume called');
639
+ if (this._state === HarnessState.RESUME)
640
+ return;
641
+ if (this.closing)
642
+ return;
643
+ if (this._state === HarnessState.PRESUSPEND) {
644
+ this._state = HarnessState.RESUME;
645
+ return;
646
+ }
647
+ this._state = HarnessState.RESUME;
648
+ hlog('resuming', { pools: 'recreated' });
649
+ this._loads.undrain();
650
+ this._models = this._createPool();
651
+ this._embedModels = this._createEmbedPool();
652
+ this._ttsModels = this._createTtsPool();
653
+ this._transcriptionModels = this._createTranscriptionPool();
654
+ await this._sdkLifecycle('resume');
655
+ }
656
+ async wakeup() {
657
+ if (this.closing)
658
+ return;
659
+ this._state = HarnessState.WAKEUP;
660
+ hlog('wakeup');
661
+ await this.resume();
662
+ }
663
+ async _close() {
664
+ hlog('closing');
665
+ this._overlayWatcher?.stop();
666
+ this._overlayWatcher = null;
667
+ const pending = this._sdk.peek();
668
+ if (pending)
669
+ this._loads.drain(await pending);
670
+ await Promise.all([this._releaseRuntimes(), closePythonWorker()]);
671
+ const sdk = await this._sdk.peek()?.catch(noop);
672
+ if (sdk)
673
+ await sdk.close();
674
+ }
675
+ download(args) {
676
+ const projection = (args.addon ?? 'llm') === 'llm' ? this._projectionFor(args.model) : undefined;
677
+ const multiFile = diffusionDownloadMetadata(args.model, args.addon) ??
678
+ audioGenDownloadMetadata(args.model, args.addon);
679
+ return download(async () => {
680
+ await this.ready();
681
+ return this._sdk.load();
682
+ }, {
683
+ ...args,
684
+ projection,
685
+ companions: multiFile?.companions,
686
+ assetSizes: multiFile?.assetSizes
687
+ }, () => invalidateModelStatusCache(this._modelStatus));
688
+ }
689
+ async embed({ model, texts, signal }) {
690
+ await this.ready();
691
+ if (this.suspended)
692
+ throw new Error('harness is suspended');
693
+ if (texts.length === 0)
694
+ return [];
695
+ const pool = this._embedModels;
696
+ const faults = this._embedFaults;
697
+ const generation = faults.generation;
698
+ const key = faults.key(model);
699
+ const handle = pool.open(key, model);
700
+ let loaded = null;
701
+ let job = null;
702
+ let releaseAfter = null;
703
+ try {
704
+ loaded = await raceAbort(handle.load(), signal);
705
+ const sdk = (await this._sdk.loadEmbed());
706
+ job = this._embedLane(sdk, { modelId: loaded.modelId, texts });
707
+ const vectors = await raceAbort(job, signal);
708
+ faults.reset();
709
+ return vectors;
710
+ }
711
+ catch (err) {
712
+ if (err instanceof AbortedError) {
713
+ releaseAfter = job ?? (this._retiredEmbedModels.has(pool) ? handle.peek() : null);
714
+ }
715
+ if (isSdkGpuDeviceLostError(err)) {
716
+ faults.recordFault(generation);
717
+ if (loaded) {
718
+ const dead = loaded.modelId;
719
+ await this._sdk
720
+ .loadEmbed()
721
+ .then((sdk) => sdk.unloadModel({ modelId: dead }))
722
+ .catch(noop);
723
+ }
724
+ }
725
+ throw err;
726
+ }
727
+ finally {
728
+ if (releaseAfter)
729
+ this._releaseEmbedResourceAfter(releaseAfter, pool, key);
730
+ else
731
+ await this._releaseEmbedResource(pool, key);
732
+ }
733
+ }
734
+ async _defaultVoiceSrc(category) {
735
+ if (category !== 'tts')
736
+ return defaultVoiceModel(category);
737
+ try {
738
+ const { capabilityProfile } = await this.capability();
739
+ return defaultTtsFor(capabilityProfile).asset.src;
740
+ }
741
+ catch {
742
+ return defaultVoiceModel('tts');
743
+ }
744
+ }
745
+ async _voiceJob(pool, category, model, signal, run) {
746
+ await this.ready();
747
+ if (this.suspended)
748
+ throw new Error('harness is suspended');
749
+ const name = model || (await this._defaultVoiceSrc(category));
750
+ const handle = pool.open(name, name);
751
+ let job = null;
752
+ let releaseAfter = null;
753
+ let sdk = null;
754
+ let modelId = null;
755
+ try {
756
+ modelId = (await raceAbort(handle.load(), signal)).modelId;
757
+ sdk = (await this._sdk.loadVoice());
758
+ const boundSdk = sdk;
759
+ const boundId = modelId;
760
+ job = this._voiceLane(() => run(boundSdk, boundId));
761
+ return await raceAbort(job, signal);
762
+ }
763
+ catch (err) {
764
+ if (err instanceof AbortedError) {
765
+ if (sdk && modelId)
766
+ void sdk.cancel({ modelId, operation: 'inference' }).catch(noop);
767
+ releaseAfter = job;
768
+ }
769
+ throw err;
770
+ }
771
+ finally {
772
+ const release = () => {
773
+ releaseModel(pool, name);
774
+ };
775
+ if (releaseAfter)
776
+ void releaseAfter.then(release, release);
777
+ else
778
+ release();
779
+ }
780
+ }
781
+ async transcribe({ model, audio, signal }) {
782
+ return this._voiceJob(this._transcriptionModels, 'transcription', model, signal, async (sdk, id) => {
783
+ const pcm = await pcmForTranscription(audio);
784
+ if (signal?.aborted)
785
+ throw new AbortedError();
786
+ if (pcm && pcm.length >= TRANSCRIBE_STREAM_MIN_BYTES) {
787
+ return transcribeStreaming(sdk, id, pcm, signal);
788
+ }
789
+ return transcribeOnce(sdk, id, pcm ? buildWavBuffer(pcm) : audio);
790
+ });
791
+ }
792
+ async speak({ model, text, signal }) {
793
+ const samples = await this._voiceJob(this._ttsModels, 'tts', model, signal, (sdk, id) => speakOnce(sdk, id, text));
794
+ return { audio: packSamples(samples), sampleRate: SUPERTONIC_SAMPLE_RATE };
795
+ }
796
+ async *speakStream({ model, text, signal }) {
797
+ await this.ready();
798
+ if (this.suspended)
799
+ throw new Error('harness is suspended');
800
+ const name = model || (await this._defaultVoiceSrc('tts'));
801
+ const pool = this._ttsModels;
802
+ const handle = pool.open(name, name);
803
+ const chunks = pushQueue();
804
+ let sdk = null;
805
+ let modelId = null;
806
+ const cancel = () => {
807
+ if (sdk && modelId)
808
+ void sdk.cancel({ modelId, operation: 'inference' }).catch(() => { });
809
+ };
810
+ signal?.addEventListener('abort', cancel, { once: true });
811
+ const job = this._voiceLane(async () => {
812
+ try {
813
+ modelId = (await handle.load()).modelId;
814
+ sdk = (await this._sdk.loadVoice());
815
+ if (signal?.aborted)
816
+ return;
817
+ for await (const chunk of speakStreamOnce(sdk, modelId, text))
818
+ chunks.push(chunk);
819
+ }
820
+ finally {
821
+ chunks.end();
822
+ }
823
+ });
824
+ let settled = false;
825
+ try {
826
+ yield* chunks;
827
+ await job;
828
+ settled = true;
829
+ }
830
+ finally {
831
+ signal?.removeEventListener('abort', cancel);
832
+ if (!settled)
833
+ cancel();
834
+ void job.catch(noop).finally(() => {
835
+ releaseModel(pool, name);
836
+ });
837
+ }
838
+ }
839
+ async list(options = {}) {
840
+ await this.ready();
841
+ const sdk = (await this._sdk.load());
842
+ return listModels(sdk, options, this._modelStatus, (name) => this._projectionFor(name));
843
+ }
844
+ async deleteModel(name) {
845
+ await this.ready();
846
+ const sdk = (await this._sdk.load());
847
+ const result = await deleteModelFiles(sdk, name);
848
+ invalidateModelStatusCache(this._modelStatus);
849
+ return summarizeDelete(result);
850
+ }
851
+ async clearKvCache() {
852
+ await this.ready();
853
+ return deleteAllKvCaches(() => this._sdk.load());
854
+ }
855
+ async infraModels(profile) {
856
+ return infraModelsFor(profile);
857
+ }
858
+ async capability() {
859
+ if (this._capability)
860
+ return this._capability;
861
+ if (this._capabilityInflight)
862
+ return this._capabilityInflight;
863
+ const reads = {
864
+ totalmem,
865
+ platform,
866
+ readFile: async (path) => {
867
+ try {
868
+ return String(await fs.promises.readFile(path, 'utf8'));
869
+ }
870
+ catch {
871
+ return null;
872
+ }
873
+ },
874
+ run: async (command) => {
875
+ try {
876
+ const runtime = await bareRuntime();
877
+ const result = await runCommand(command, { ...runtime, timeoutMs: 5_000 });
878
+ return result.exitCode === 0 ? result.stdout : null;
879
+ }
880
+ catch {
881
+ return null;
882
+ }
883
+ },
884
+ readGpuStats: () => readSystemStats()
885
+ };
886
+ this._capabilityInflight = probeCapabilityProfile(reads)
887
+ .then((capability) => {
888
+ this._capability = capability;
889
+ return capability;
890
+ })
891
+ .finally(() => {
892
+ this._capabilityInflight = null;
893
+ });
894
+ return this._capabilityInflight;
895
+ }
896
+ async warmModel({ model, agent, signal }) {
897
+ await this.ready();
898
+ if (this.suspended)
899
+ return;
900
+ const projectionModel = this._projectionFor(model);
901
+ const loadOpts = resolveLoadOptions({
902
+ ctxSize: agent?.ctxSize ?? undefined,
903
+ kvCacheK: agent?.kvCacheK ?? undefined,
904
+ kvCacheV: agent?.kvCacheV ?? undefined,
905
+ projectionModel
906
+ }, this._deviceConfig());
907
+ const key = modelKey(model, loadOpts);
908
+ const pool = this._models;
909
+ hlog('warm model', { model, resident: isResident(pool, key) });
910
+ if (!isResident(pool, key)) {
911
+ await evictIdle(pool);
912
+ await this._imageRuntime?.unloadIdle().catch(noop);
913
+ }
914
+ try {
915
+ await raceAbort(pool.open(key, model, loadOpts).load(), signal);
916
+ }
917
+ finally {
918
+ releaseModel(pool, key);
919
+ }
920
+ }
921
+ async *completion({ model, agent, messages, cacheKey, thinkingDefault, toolConfigs, generationParams, responseFormat, grantedDirs, grantedDrives, driveOp, grantedWriteDirs, approve, attach, fetchAttachment, ragSearch, progress, askUser, signal }) {
922
+ await this.ready();
923
+ if (this.suspended)
924
+ throw new Error('harness is suspended');
925
+ const projectionModel = this._projectionFor(model);
926
+ const loadOpts = resolveLoadOptions({
927
+ ctxSize: agent?.ctxSize ?? undefined,
928
+ kvCacheK: agent?.kvCacheK ?? undefined,
929
+ kvCacheV: agent?.kvCacheV ?? undefined,
930
+ projectionModel
931
+ }, this._deviceConfig());
932
+ const key = modelKey(model, loadOpts);
933
+ const pool = this._models;
934
+ const resident = isResident(pool, key);
935
+ hlog('completion start', { model, resident, projection: Boolean(projectionModel) });
936
+ if (!resident) {
937
+ await evictIdle(pool);
938
+ await this._imageRuntime?.unloadIdle().catch(noop);
939
+ await this._musicRuntime?.unloadIdle().catch(noop);
940
+ }
941
+ const acquireRound = async () => {
942
+ if (!isResident(pool, key)) {
943
+ await evictIdle(pool);
944
+ await this._imageRuntime?.unloadIdle().catch(noop);
945
+ await this._musicRuntime?.unloadIdle().catch(noop);
946
+ }
947
+ try {
948
+ const { modelId } = await raceAbort(pool.open(key, model, loadOpts).load(), signal);
949
+ return {
950
+ modelId,
951
+ release: () => {
952
+ releaseModel(pool, key);
953
+ }
954
+ };
955
+ }
956
+ catch (err) {
957
+ releaseModel(pool, key);
958
+ throw err;
959
+ }
960
+ };
961
+ const handle = pool.open(key, model, loadOpts);
962
+ let held = true;
963
+ const releaseHeld = () => {
964
+ if (!held)
965
+ return;
966
+ held = false;
967
+ releaseModel(pool, key);
968
+ };
969
+ try {
970
+ const { modelId, ctxSize } = await raceAbort(handle.load(), signal);
971
+ hlog('model ready', { model });
972
+ const sdk = await this._sdk.load();
973
+ const turns = projectionModel ? messages : messages.map(({ attachments, ...turn }) => turn);
974
+ const remoteRoots = driveOp && grantedDrives?.length ? createRemoteRoots(grantedDrives, driveOp) : [];
975
+ const fsRoots = [
976
+ ...(grantedDirs?.length ? await createLocalRoots(grantedDirs) : []),
977
+ ...remoteRoots
978
+ ];
979
+ const fsWriteRoots = [
980
+ ...(grantedWriteDirs?.length ? await createLocalRoots(grantedWriteDirs) : []),
981
+ ...remoteRoots.filter((root) => root.writable)
982
+ ];
983
+ releaseHeld();
984
+ yield* completion(sdk, {
985
+ modelId,
986
+ acquireRound,
987
+ model,
988
+ agent,
989
+ ctxSize,
990
+ cacheKey,
991
+ thinkingDefault,
992
+ generationParams,
993
+ responseFormat,
994
+ messages: turns,
995
+ tools: this._tools,
996
+ skillCatalog: await this._completionSkills(agent?.id ?? null, model),
997
+ toolConfigs,
998
+ fsRoots,
999
+ fsWriteRoots,
1000
+ approve,
1001
+ attach,
1002
+ fetchAttachment,
1003
+ ragSearch,
1004
+ progress,
1005
+ askUser,
1006
+ signal
1007
+ });
1008
+ this._modelFaults.delete(model);
1009
+ }
1010
+ catch (err) {
1011
+ if (err instanceof AbortedError || this.suspended) {
1012
+ hlog('completion aborted', { model, suspended: this.suspended });
1013
+ yield { type: 'aborted' };
1014
+ }
1015
+ else {
1016
+ const message = err instanceof Error ? err.message : String(err);
1017
+ hlog('completion failed', { model, ...resolutionDetail(err), err: message });
1018
+ if (isSdkModelWedgedError(err)) {
1019
+ const wedged = await this._evictWedgedModel(model, key);
1020
+ yield { type: 'error', message: wedged.message };
1021
+ if (wedged.fatal)
1022
+ process.exit(1);
1023
+ }
1024
+ else {
1025
+ yield { type: 'error', message };
1026
+ }
1027
+ }
1028
+ }
1029
+ finally {
1030
+ hlog('completion end', { model });
1031
+ releaseHeld();
1032
+ void this._imageRuntime?.unloadIdle().catch(noop);
1033
+ void this._musicRuntime?.unloadIdle().catch(noop);
1034
+ }
1035
+ }
1036
+ async _evictWedgedModel(model, key) {
1037
+ const faults = (this._modelFaults.get(model) ?? 0) + 1;
1038
+ this._modelFaults.set(model, faults);
1039
+ const leased = leaseCount(this._models, key) > 0;
1040
+ const evicted = leased ? false : await evictModelWithin(this._models, key, WEDGED_EVICT_WAIT_MS);
1041
+ hlog('wedged model evicted', { model, faults, evicted, leased });
1042
+ if (leased)
1043
+ this._evictAfterLeases(model, key);
1044
+ if (!evicted && !leased) {
1045
+ return {
1046
+ message: `${model} is stuck in device memory — restarting the model runtime`,
1047
+ fatal: true
1048
+ };
1049
+ }
1050
+ return {
1051
+ message: faults > 1
1052
+ ? `${model} keeps failing during inference on this device — it may need more memory than is available`
1053
+ : `${model} failed during inference and was unloaded — try again`,
1054
+ fatal: false
1055
+ };
1056
+ }
1057
+ _evictAfterLeases(model, key) {
1058
+ void evictModelWithin(this._models, key, WEDGED_EVICT_LEASED_MS)
1059
+ .then((evicted) => hlog('wedged model evicted after leases', { model, evicted }))
1060
+ .catch(noop);
1061
+ }
1062
+ }
1063
+ function noop() { }