@qvac/harness 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/CHANGELOG.md +689 -141
  2. package/README.md +29 -7
  3. package/dist/harness.bundle +71 -50
  4. package/dist-lib/index.d.ts +36 -39
  5. package/dist-lib/index.js +279 -114
  6. package/dist-lib/lib/audio-transcode-bare.d.ts +2 -2
  7. package/dist-lib/lib/audio-transcode-bare.js +28 -18
  8. package/dist-lib/lib/audio-transcode-node.d.ts +2 -2
  9. package/dist-lib/lib/capabilities/audio-resample.d.ts +7 -6
  10. package/dist-lib/lib/capabilities/audio-resample.js +30 -18
  11. package/dist-lib/lib/capabilities/completion.d.ts +20 -19
  12. package/dist-lib/lib/capabilities/completion.js +193 -132
  13. package/dist-lib/lib/capabilities/download.d.ts +6 -6
  14. package/dist-lib/lib/capabilities/download.js +15 -8
  15. package/dist-lib/lib/capabilities/embed.js +2 -1
  16. package/dist-lib/lib/capabilities/enhance.d.ts +6 -1
  17. package/dist-lib/lib/capabilities/enhance.js +7 -4
  18. package/dist-lib/lib/capabilities/invoke.js +7 -4
  19. package/dist-lib/lib/capabilities/kv-cache.js +2 -1
  20. package/dist-lib/lib/capabilities/preview-model-source.d.ts +9 -7
  21. package/dist-lib/lib/capabilities/preview-model-source.js +80 -28
  22. package/dist-lib/lib/capabilities/speech-text.js +5 -4
  23. package/dist-lib/lib/capabilities/tool-selection.js +10 -9
  24. package/dist-lib/lib/capabilities/tool-turns.js +30 -16
  25. package/dist-lib/lib/capabilities/usage-breakdown.js +2 -1
  26. package/dist-lib/lib/capabilities/voice.d.ts +5 -1
  27. package/dist-lib/lib/capabilities/voice.js +22 -12
  28. package/dist-lib/lib/connect.d.ts +11 -32
  29. package/dist-lib/lib/connect.js +152 -112
  30. package/dist-lib/lib/context-window.js +25 -21
  31. package/dist-lib/lib/contract-types.d.ts +22 -15
  32. package/dist-lib/lib/diagram-repair.d.ts +4 -4
  33. package/dist-lib/lib/diagram-repair.js +6 -3
  34. package/dist-lib/lib/docx/index.d.ts +3 -2
  35. package/dist-lib/lib/{error-fields.d.ts → guards.d.ts} +1 -0
  36. package/dist-lib/lib/{error-fields.js → guards.js} +3 -0
  37. package/dist-lib/lib/hardware/capability-probe.js +20 -10
  38. package/dist-lib/lib/hardware/gpu-classify.js +6 -3
  39. package/dist-lib/lib/hardware/gpu-probe-addon.js +8 -4
  40. package/dist-lib/lib/hardware/gpu-probe.js +4 -2
  41. package/dist-lib/lib/hardware/gpu-stats.native.cjs +8 -9
  42. package/dist-lib/lib/hardware/parsers.js +8 -4
  43. package/dist-lib/lib/helpers/buffer-burst.js +4 -2
  44. package/dist-lib/lib/helpers/control-tokens.js +4 -2
  45. package/dist-lib/lib/helpers/join-guard.d.ts +2 -2
  46. package/dist-lib/lib/helpers/join-guard.js +4 -2
  47. package/dist-lib/lib/helpers/load-stall.js +4 -2
  48. package/dist-lib/lib/helpers/markup-stream-filter.d.ts +2 -2
  49. package/dist-lib/lib/helpers/markup-stream-filter.js +6 -3
  50. package/dist-lib/lib/helpers/race-abort.js +2 -1
  51. package/dist-lib/lib/helpers/race-timeout.d.ts +5 -0
  52. package/dist-lib/lib/helpers/race-timeout.js +14 -0
  53. package/dist-lib/lib/helpers/run-outcome.d.ts +6 -8
  54. package/dist-lib/lib/helpers/run-outcome.js +36 -20
  55. package/dist-lib/lib/helpers/spawn-path.js +6 -3
  56. package/dist-lib/lib/helpers/text-coalescer.js +6 -3
  57. package/dist-lib/lib/helpers/thinking.js +38 -45
  58. package/dist-lib/lib/helpers/tool-call-markup.d.ts +9 -7
  59. package/dist-lib/lib/helpers/tool-call-markup.js +36 -20
  60. package/dist-lib/lib/helpers/tool-intent.d.ts +3 -2
  61. package/dist-lib/lib/helpers/tool-intent.js +4 -2
  62. package/dist-lib/lib/helpers/tool-label.js +18 -9
  63. package/dist-lib/lib/hooks/built-in/arg-repair.js +23 -13
  64. package/dist-lib/lib/hooks/built-in/egress.js +2 -1
  65. package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
  66. package/dist-lib/lib/hooks/pipeline.d.ts +5 -4
  67. package/dist-lib/lib/hooks/pipeline.js +6 -3
  68. package/dist-lib/lib/hooks/run.js +12 -8
  69. package/dist-lib/lib/model-download-progress.js +10 -8
  70. package/dist-lib/lib/models/context.d.ts +1 -1
  71. package/dist-lib/lib/models/context.js +5 -1
  72. package/dist-lib/lib/models/custom-model-cache.d.ts +10 -1
  73. package/dist-lib/lib/models/custom-model-cache.js +43 -15
  74. package/dist-lib/lib/models/gguf-header.d.ts +3 -2
  75. package/dist-lib/lib/models/gguf-header.js +44 -22
  76. package/dist-lib/lib/models/idle-unload.d.ts +14 -0
  77. package/dist-lib/lib/models/idle-unload.js +51 -0
  78. package/dist-lib/lib/models/kv-cache.d.ts +3 -2
  79. package/dist-lib/lib/models/kv-cache.js +4 -3
  80. package/dist-lib/lib/models/llm-presets.d.ts +2 -2
  81. package/dist-lib/lib/models/llm-presets.js +4 -2
  82. package/dist-lib/lib/models/model-catalog-constants.js +3 -2
  83. package/dist-lib/lib/models/model-catalog.d.ts +13 -20
  84. package/dist-lib/lib/models/model-catalog.js +59 -31
  85. package/dist-lib/lib/models/model-delete.js +18 -8
  86. package/dist-lib/lib/models/model-handle.js +2 -1
  87. package/dist-lib/lib/models/model-list.d.ts +8 -3
  88. package/dist-lib/lib/models/model-list.js +11 -6
  89. package/dist-lib/lib/models/model-pool.d.ts +44 -10
  90. package/dist-lib/lib/models/model-pool.js +47 -42
  91. package/dist-lib/lib/models/model-source.js +10 -5
  92. package/dist-lib/lib/models/music-catalog.d.ts +2 -2
  93. package/dist-lib/lib/models/nmt-catalog.d.ts +4 -3
  94. package/dist-lib/lib/models/nmt-catalog.js +10 -5
  95. package/dist-lib/lib/models/opencl-cache.d.ts +6 -1
  96. package/dist-lib/lib/models/opencl-cache.js +5 -3
  97. package/dist-lib/lib/models/sdk-faults.d.ts +11 -8
  98. package/dist-lib/lib/models/sdk-faults.js +9 -6
  99. package/dist-lib/lib/models/shards.d.ts +11 -0
  100. package/dist-lib/lib/models/shards.js +15 -0
  101. package/dist-lib/lib/models/tool-dialect.js +10 -5
  102. package/dist-lib/lib/no-redirect-fetch-bare.d.ts +3 -3
  103. package/dist-lib/lib/no-redirect-fetch-bare.js +1 -1
  104. package/dist-lib/lib/no-redirect-fetch-impl.js +6 -3
  105. package/dist-lib/lib/no-redirect-fetch-node.d.ts +1 -1
  106. package/dist-lib/lib/no-redirect-fetch-node.js +9 -9
  107. package/dist-lib/lib/office/index.d.ts +3 -2
  108. package/dist-lib/lib/office/python.d.ts +3 -2
  109. package/dist-lib/lib/office/python.js +2 -1
  110. package/dist-lib/lib/prompt.d.ts +5 -4
  111. package/dist-lib/lib/prompt.js +8 -4
  112. package/dist-lib/lib/queue.js +10 -5
  113. package/dist-lib/lib/resolution-detector.js +21 -11
  114. package/dist-lib/lib/rpc-session.js +2 -1
  115. package/dist-lib/lib/sdk-loader.js +2 -1
  116. package/dist-lib/lib/sdk-storage.js +4 -2
  117. package/dist-lib/lib/serve.js +110 -66
  118. package/dist-lib/lib/spawn.js +7 -4
  119. package/dist-lib/lib/tmp-path.d.ts +7 -6
  120. package/dist-lib/lib/tool-call-display.d.ts +2 -2
  121. package/dist-lib/lib/tools/create-documents.js +18 -10
  122. package/dist-lib/lib/tools/edit-documents.js +23 -13
  123. package/dist-lib/lib/tools/edit-image.d.ts +2 -2
  124. package/dist-lib/lib/tools/edit-image.js +60 -36
  125. package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +10 -10
  126. package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +17 -11
  127. package/dist-lib/lib/tools/exec/adapters/python/attachments.js +53 -40
  128. package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +2 -2
  129. package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +60 -32
  130. package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.d.ts +33 -22
  131. package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.js +58 -29
  132. package/dist-lib/lib/tools/exec/adapters/python/interrupt-timer.d.ts +2 -2
  133. package/dist-lib/lib/tools/exec/adapters/python/loader.js +23 -12
  134. package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +13 -11
  135. package/dist-lib/lib/tools/exec/adapters/python/memfs.js +10 -5
  136. package/dist-lib/lib/tools/exec/adapters/python/net-shim.js +3 -1
  137. package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +6 -4
  138. package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +20 -10
  139. package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +2 -2
  140. package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +14 -7
  141. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +41 -34
  142. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +316 -166
  143. package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +9 -8
  144. package/dist-lib/lib/tools/exec/adapters/python/run-session.js +56 -28
  145. package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +8 -10
  146. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +22 -11
  147. package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +3 -2
  148. package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +41 -26
  149. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +27 -18
  150. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +2 -2
  151. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +14 -13
  152. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +4 -4
  153. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +10 -5
  154. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +4 -4
  155. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +2 -1
  156. package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +6 -1
  157. package/dist-lib/lib/tools/exec/obsidian/cli-process.js +8 -5
  158. package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +6 -6
  159. package/dist-lib/lib/tools/exec/obsidian/cli.js +4 -4
  160. package/dist-lib/lib/tools/exec/obsidian/command.d.ts +3 -2
  161. package/dist-lib/lib/tools/exec/obsidian/command.js +6 -3
  162. package/dist-lib/lib/tools/exec/obsidian/output.js +2 -1
  163. package/dist-lib/lib/tools/exec/obsidian/route.d.ts +4 -6
  164. package/dist-lib/lib/tools/exec/obsidian/route.js +17 -11
  165. package/dist-lib/lib/tools/exec/obsidian/safe-path.js +2 -1
  166. package/dist-lib/lib/tools/exec/obsidian/vault-create.js +15 -7
  167. package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +2 -2
  168. package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +20 -10
  169. package/dist-lib/lib/tools/exec/obsidian/vault-read.js +20 -13
  170. package/dist-lib/lib/tools/exec/obsidian/vault-write.js +24 -12
  171. package/dist-lib/lib/tools/exec/runner.d.ts +14 -14
  172. package/dist-lib/lib/tools/exec/runner.js +5 -3
  173. package/dist-lib/lib/tools/exec/scope.js +52 -28
  174. package/dist-lib/lib/tools/exec/shell-argv.js +31 -18
  175. package/dist-lib/lib/tools/exec/shell-guidance.d.ts +6 -1
  176. package/dist-lib/lib/tools/exec/shell-guidance.js +35 -20
  177. package/dist-lib/lib/tools/exec/video-tools.js +2 -2
  178. package/dist-lib/lib/tools/exec.d.ts +6 -8
  179. package/dist-lib/lib/tools/exec.js +113 -54
  180. package/dist-lib/lib/tools/file-glob.d.ts +4 -5
  181. package/dist-lib/lib/tools/file-glob.js +16 -11
  182. package/dist-lib/lib/tools/fs/glob.js +13 -18
  183. package/dist-lib/lib/tools/fs/remote-protocol.d.ts +10 -10
  184. package/dist-lib/lib/tools/fs/remote.d.ts +3 -2
  185. package/dist-lib/lib/tools/fs/remote.js +13 -7
  186. package/dist-lib/lib/tools/fs/scope.d.ts +8 -3
  187. package/dist-lib/lib/tools/fs/scope.js +20 -12
  188. package/dist-lib/lib/tools/fs/walk.js +6 -3
  189. package/dist-lib/lib/tools/fs/write.d.ts +3 -2
  190. package/dist-lib/lib/tools/generate-image.d.ts +11 -9
  191. package/dist-lib/lib/tools/generate-image.js +73 -37
  192. package/dist-lib/lib/tools/generate-music.d.ts +22 -11
  193. package/dist-lib/lib/tools/generate-music.js +79 -48
  194. package/dist-lib/lib/tools/grep.js +66 -41
  195. package/dist-lib/lib/tools/http-request/encode-fields.js +18 -9
  196. package/dist-lib/lib/tools/http-request/{utils.js → request.js} +20 -11
  197. package/dist-lib/lib/tools/http-request/truncate-response.js +57 -46
  198. package/dist-lib/lib/tools/http-request.d.ts +1 -1
  199. package/dist-lib/lib/tools/http-request.js +33 -18
  200. package/dist-lib/lib/tools/mcp/protocol.d.ts +53 -0
  201. package/dist-lib/lib/tools/mcp/{utils.js → protocol.js} +45 -23
  202. package/dist-lib/lib/tools/mcp-call.d.ts +1 -1
  203. package/dist-lib/lib/tools/mcp-call.js +37 -16
  204. package/dist-lib/lib/tools/operations/builders.js +10 -6
  205. package/dist-lib/lib/tools/operations/compile.js +20 -10
  206. package/dist-lib/lib/tools/operations/decoders.js +12 -6
  207. package/dist-lib/lib/tools/operations/gmail-message.js +3 -2
  208. package/dist-lib/lib/tools/outbound-guard.d.ts +4 -3
  209. package/dist-lib/lib/tools/outbound-guard.js +14 -8
  210. package/dist-lib/lib/tools/private-ip.js +8 -7
  211. package/dist-lib/lib/tools/rag-search.js +14 -7
  212. package/dist-lib/lib/tools/read-files.js +23 -20
  213. package/dist-lib/lib/tools/skill.js +19 -10
  214. package/dist-lib/lib/tools/skills/auth-resolver.d.ts +11 -18
  215. package/dist-lib/lib/tools/skills/auth-resolver.js +30 -18
  216. package/dist-lib/lib/tools/skills/bin-check.d.ts +3 -2
  217. package/dist-lib/lib/tools/skills/bin-check.js +10 -3
  218. package/dist-lib/lib/tools/skills/bundled-dir.js +20 -10
  219. package/dist-lib/lib/tools/skills/bundled-hash.d.ts +3 -2
  220. package/dist-lib/lib/tools/skills/bundled-hash.js +6 -1
  221. package/dist-lib/lib/tools/skills/catalog.d.ts +3 -2
  222. package/dist-lib/lib/tools/skills/catalog.js +33 -28
  223. package/dist-lib/lib/tools/skills/cli-argv.d.ts +3 -2
  224. package/dist-lib/lib/tools/skills/cli-argv.js +55 -52
  225. package/dist-lib/lib/tools/skills/cli-schema-check.js +21 -10
  226. package/dist-lib/lib/tools/skills/cli-schema-load.js +28 -20
  227. package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +6 -6
  228. package/dist-lib/lib/tools/skills/cli-schema.js +2 -1
  229. package/dist-lib/lib/tools/skills/credential-check.d.ts +6 -3
  230. package/dist-lib/lib/tools/skills/credential-check.js +24 -12
  231. package/dist-lib/lib/tools/skills/credential-grants.js +1 -6
  232. package/dist-lib/lib/tools/skills/credential-health.d.ts +5 -1
  233. package/dist-lib/lib/tools/skills/credential-health.js +5 -3
  234. package/dist-lib/lib/tools/skills/frontmatter-parser.js +10 -5
  235. package/dist-lib/lib/tools/skills/manifest-parse.js +84 -64
  236. package/dist-lib/lib/tools/skills/mention.js +7 -6
  237. package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +2 -2
  238. package/dist-lib/lib/tools/skills/obsidian-readiness.js +11 -3
  239. package/dist-lib/lib/tools/skills/overlay-crud.d.ts +6 -4
  240. package/dist-lib/lib/tools/skills/overlay-crud.js +12 -6
  241. package/dist-lib/lib/tools/skills/overlay-dir.js +4 -2
  242. package/dist-lib/lib/tools/skills/overlay-watch.d.ts +3 -2
  243. package/dist-lib/lib/tools/skills/overlay-watch.js +8 -4
  244. package/dist-lib/lib/tools/skills/setup-routes.js +1 -3
  245. package/dist-lib/lib/tools/skills/skill-settings.js +4 -1
  246. package/dist-lib/lib/tools/skills/skill-state.d.ts +6 -11
  247. package/dist-lib/lib/tools/skills/skill-state.js +48 -29
  248. package/dist-lib/lib/tools/skills/tool-grants.js +6 -3
  249. package/dist-lib/lib/tools/toolsets.js +2 -1
  250. package/dist-lib/lib/tools/translate.d.ts +4 -5
  251. package/dist-lib/lib/tools/translate.js +31 -14
  252. package/dist-lib/lib/tools/url-guard.js +2 -1
  253. package/dist-lib/lib/tools/weather-lookup/place.js +8 -4
  254. package/dist-lib/lib/tools/weather-lookup/report.d.ts +7 -1
  255. package/dist-lib/lib/tools/weather-lookup/report.js +46 -9
  256. package/dist-lib/lib/tools/weather-lookup.js +18 -12
  257. package/dist-lib/lib/tools/web-fetch.js +47 -24
  258. package/dist-lib/lib/tools/web-search.js +8 -3
  259. package/dist-lib/lib/validating-lookup.d.ts +4 -4
  260. package/dist-lib/lib/wav-encode.d.ts +1 -1
  261. package/dist-lib/lib/wav-encode.js +11 -10
  262. package/dist-lib/lib/web-fetch/embedded-state.js +24 -12
  263. package/dist-lib/lib/web-fetch/extract.js +4 -2
  264. package/dist-lib/lib/web-fetch/images.js +8 -4
  265. package/dist-lib/lib/web-fetch/video.d.ts +2 -2
  266. package/dist-lib/lib/web-fetch/video.js +8 -4
  267. package/dist-lib/lib/web-search/engine-registry.d.ts +2 -2
  268. package/dist-lib/lib/web-search/engines/aol.js +1 -1
  269. package/dist-lib/lib/web-search/engines/bing.js +1 -1
  270. package/dist-lib/lib/web-search/engines/brave.js +4 -1
  271. package/dist-lib/lib/web-search/engines/duckduckgo.js +3 -2
  272. package/dist-lib/lib/web-search/engines/google.js +7 -3
  273. package/dist-lib/lib/web-search/engines/wikipedia.js +5 -4
  274. package/dist-lib/lib/web-search/engines/yahoo.js +1 -1
  275. package/dist-lib/lib/web-search/fetch-html.d.ts +5 -4
  276. package/dist-lib/lib/web-search/fetch-html.js +13 -7
  277. package/dist-lib/lib/web-search/orchestrator.d.ts +9 -5
  278. package/dist-lib/lib/web-search/orchestrator.js +3 -3
  279. package/dist-lib/lib/wire.d.ts +3 -2
  280. package/dist-lib/lib/wire.js +23 -15
  281. package/dist-lib/schema/baseline.js +10 -5
  282. package/dist-lib/schema/build.js +2 -1
  283. package/dist-lib/schema/harness.d.ts +15 -2
  284. package/dist-lib/schema/harness.js +14 -2
  285. package/dist-lib/schema/release-tags.d.ts +3 -2
  286. package/dist-lib/schema/release-tags.js +6 -3
  287. package/dist-lib/spec/bind.js +3 -0
  288. package/dist-lib/spec/calls.js +1 -0
  289. package/dist-lib/spec/hrpc/hrpc.json +13 -0
  290. package/dist-lib/spec/hrpc/index.js +15 -3
  291. package/dist-lib/spec/hrpc/messages.js +39 -8
  292. package/dist-lib/spec/hyperschema/index.js +39 -8
  293. package/dist-lib/spec/hyperschema/schema.json +30 -1
  294. package/dist-lib/spec/hyperschema/types.d.ts +9 -1
  295. package/package.json +13 -14
  296. package/worker/harness-sidecar.mjs +15 -22
  297. package/worker/stow-entry.mjs +7 -4
  298. package/dist-lib/lib/tools/mcp/utils.d.ts +0 -47
  299. /package/dist-lib/lib/tools/http-request/{utils.d.ts → request.d.ts} +0 -0
@@ -3,8 +3,9 @@ import { connectHarness } from './connect.js';
3
3
  import { setHarnessLog } from './log.js';
4
4
  import { createEmbedConfig } from './models/embed-config.js';
5
5
  export function harnessChild(entry, opts) {
6
- if (opts.logger)
6
+ if (opts.logger) {
7
7
  setHarnessLog(true);
8
+ }
8
9
  const { runner, skillsDir, gpuStats, wheelsDir, sdkStorage, embedDevice, embedGpuLayers, embedBatchSize, imageModel, imageClamps, musicModel, musicClamps, llm, onIpc, logger = null, ...spec } = opts;
9
10
  const embedConfig = createEmbedConfig({
10
11
  device: embedDevice,
@@ -36,8 +37,9 @@ export function harnessChild(entry, opts) {
36
37
  }
37
38
  export function spawnHarness(opts) {
38
39
  const logger = opts.logger ?? null;
39
- if (logger)
40
+ if (logger) {
40
41
  setHarnessLog(true);
42
+ }
41
43
  const embedConfig = createEmbedConfig({
42
44
  device: opts.embedDevice,
43
45
  gpuLayers: opts.embedGpuLayers,
@@ -45,7 +47,7 @@ export function spawnHarness(opts) {
45
47
  });
46
48
  return connectHarness(async () => {
47
49
  const { default: Sidecar } = await import('bare-sidecar');
48
- const { wrap } = (await import('bare-stow/host'));
50
+ const { wrap } = await import('bare-stow/host');
49
51
  const sidecar = new Sidecar(opts.entry, [
50
52
  opts.skillsDir ?? '',
51
53
  JSON.stringify(opts.sdkStorage),
@@ -66,8 +68,9 @@ export function spawnHarness(opts) {
66
68
  sidecar.once('exit', (code) => resolve(`harness exited (${code}) before ready`));
67
69
  });
68
70
  const failure = await Promise.race([ipc.ready.then(() => null), died]);
69
- if (failure)
71
+ if (failure) {
70
72
  throw new Error(failure);
73
+ }
71
74
  return ipc;
72
75
  });
73
76
  }
@@ -1,7 +1,8 @@
1
- export type UserTmpOptions = {
2
- readonly readOwner?: () => {
3
- uid: number;
4
- username: string;
5
- };
6
- };
1
+ export interface TmpOwner {
2
+ uid: number;
3
+ username: string;
4
+ }
5
+ export interface UserTmpOptions {
6
+ readonly readOwner?: () => TmpOwner;
7
+ }
7
8
  export declare function userTmpPath(name: string, opts?: UserTmpOptions): string;
@@ -1,8 +1,8 @@
1
- export type ToolCallDisplay = {
1
+ export interface ToolCallDisplay {
2
2
  readonly label: string;
3
3
  readonly description?: string;
4
4
  readonly iconEmoji?: string;
5
- };
5
+ }
6
6
  export type ToolExecutionOutcome = {
7
7
  readonly kind: 'success';
8
8
  } | {
@@ -1,19 +1,25 @@
1
1
  import { canonicalDenyRoots, defaultRealpath, resolveKey } from './fs/scope.js';
2
2
  import { writeText } from './fs/write.js';
3
+ import { errorMessage } from '../guards.js';
3
4
  function documentRequests(raw) {
4
5
  if (!Array.isArray(raw) || raw.length === 0)
5
6
  return null;
6
7
  const documents = [];
7
8
  for (const entry of raw) {
8
- const record = entry;
9
- if (typeof record?.path !== 'string' || !record.path.trim())
9
+ if (!isDocumentRequest(entry))
10
10
  return null;
11
- if (typeof record.content !== 'string')
12
- return null;
13
- documents.push({ path: record.path, content: record.content });
11
+ documents.push({ path: entry.path, content: entry.content });
14
12
  }
15
13
  return documents;
16
14
  }
15
+ function isDocumentRequest(value) {
16
+ if (typeof value !== 'object' || value === null)
17
+ return false;
18
+ if (!('path' in value) || typeof value.path !== 'string' || !value.path.trim()) {
19
+ return false;
20
+ }
21
+ return 'content' in value && typeof value.content === 'string';
22
+ }
17
23
  export function createCreateDocumentsTool({ realpath = defaultRealpath, deniedRoots } = {}) {
18
24
  return {
19
25
  name: 'create_documents',
@@ -48,8 +54,9 @@ export function createCreateDocumentsTool({ realpath = defaultRealpath, deniedRo
48
54
  },
49
55
  resource(args) {
50
56
  const documents = documentRequests(args.documents);
51
- if (!documents)
57
+ if (!documents) {
52
58
  return null;
59
+ }
53
60
  const bytes = documents.reduce((sum, doc) => sum + doc.content.length, 0);
54
61
  const first = documents[0];
55
62
  const suffix = documents.length > 1 ? ` (+${documents.length - 1} more)` : '';
@@ -58,13 +65,14 @@ export function createCreateDocumentsTool({ realpath = defaultRealpath, deniedRo
58
65
  async execute(rawArgs, ctx) {
59
66
  const roots = ctx?.fsWriteRoots ?? [];
60
67
  const documents = documentRequests(rawArgs.documents);
61
- if (!documents)
68
+ if (!documents) {
62
69
  return { error: 'documents must be a non-empty array of { path, content }' };
70
+ }
63
71
  const created = [];
64
72
  const failed = [];
65
73
  const deny = await canonicalDenyRoots(deniedRoots, realpath);
66
74
  for (const doc of documents) {
67
- const resolved = await resolveKey(doc.path, roots, realpath, deny);
75
+ const resolved = await resolveKey(doc.path, roots, { realpath, deny });
68
76
  if ('error' in resolved) {
69
77
  failed.push({ path: doc.path, error: resolved.error });
70
78
  continue;
@@ -78,10 +86,10 @@ export function createCreateDocumentsTool({ realpath = defaultRealpath, deniedRo
78
86
  created.push(doc.path);
79
87
  }
80
88
  catch (err) {
81
- failed.push({ path: doc.path, error: err.message });
89
+ failed.push({ path: doc.path, error: errorMessage(err) });
82
90
  }
83
91
  }
84
- return { created, ...(failed.length ? { failed } : {}) };
92
+ return { created, failed: failed.length ? failed : undefined };
85
93
  }
86
94
  };
87
95
  }
@@ -1,28 +1,36 @@
1
1
  import b4a from 'b4a';
2
2
  import { canonicalDenyRoots, defaultRealpath, resolveKey } from './fs/scope.js';
3
3
  import { writeText } from './fs/write.js';
4
+ import { errorMessage } from '../guards.js';
4
5
  function editRequests(raw) {
5
6
  if (!Array.isArray(raw) || raw.length === 0)
6
7
  return null;
7
8
  const edits = [];
8
9
  for (const entry of raw) {
9
- const record = entry;
10
- if (typeof record?.path !== 'string' || !record.path.trim())
10
+ if (!isEditRequest(entry))
11
11
  return null;
12
- if (typeof record.search !== 'string' || record.search.length === 0)
13
- return null;
14
- if (typeof record.replace !== 'string')
15
- return null;
16
- edits.push({ path: record.path, search: record.search, replace: record.replace });
12
+ edits.push({ path: entry.path, search: entry.search, replace: entry.replace });
17
13
  }
18
14
  return edits;
19
15
  }
16
+ function isEditRequest(value) {
17
+ if (typeof value !== 'object' || value === null)
18
+ return false;
19
+ if (!('path' in value) || typeof value.path !== 'string' || !value.path.trim()) {
20
+ return false;
21
+ }
22
+ if (!('search' in value) || typeof value.search !== 'string' || !value.search) {
23
+ return false;
24
+ }
25
+ return 'replace' in value && typeof value.replace === 'string';
26
+ }
20
27
  function applyEdits(content, edits) {
21
28
  let next = content;
22
29
  for (const edit of edits) {
23
30
  const first = next.indexOf(edit.search);
24
- if (first === -1)
31
+ if (first === -1) {
25
32
  return { error: 'search text not found' };
33
+ }
26
34
  if (next.indexOf(edit.search, first + edit.search.length) !== -1) {
27
35
  return { error: 'search text is ambiguous (matches more than once)' };
28
36
  }
@@ -66,8 +74,9 @@ export function createEditDocumentsTool({ realpath = defaultRealpath, deniedRoot
66
74
  },
67
75
  resource(args) {
68
76
  const edits = editRequests(args.edits);
69
- if (!edits)
77
+ if (!edits) {
70
78
  return null;
79
+ }
71
80
  const paths = [...new Set(edits.map((edit) => edit.path))];
72
81
  const label = paths.slice(0, 3).join(', ');
73
82
  return {
@@ -78,8 +87,9 @@ export function createEditDocumentsTool({ realpath = defaultRealpath, deniedRoot
78
87
  async execute(rawArgs, ctx) {
79
88
  const roots = ctx?.fsWriteRoots ?? [];
80
89
  const edits = editRequests(rawArgs.edits);
81
- if (!edits)
90
+ if (!edits) {
82
91
  return { error: 'edits must be a non-empty array of { path, search, replace }' };
92
+ }
83
93
  const byPath = new Map();
84
94
  for (const edit of edits) {
85
95
  const list = byPath.get(edit.path) ?? [];
@@ -90,7 +100,7 @@ export function createEditDocumentsTool({ realpath = defaultRealpath, deniedRoot
90
100
  const failed = [];
91
101
  const deny = await canonicalDenyRoots(deniedRoots, realpath);
92
102
  for (const [file, fileEdits] of byPath) {
93
- const resolved = await resolveKey(file, roots, realpath, deny);
103
+ const resolved = await resolveKey(file, roots, { realpath, deny });
94
104
  if ('error' in resolved) {
95
105
  failed.push({ path: file, error: resolved.error });
96
106
  continue;
@@ -113,10 +123,10 @@ export function createEditDocumentsTool({ realpath = defaultRealpath, deniedRoot
113
123
  edited.push(file);
114
124
  }
115
125
  catch (err) {
116
- failed.push({ path: file, error: err.message });
126
+ failed.push({ path: file, error: errorMessage(err) });
117
127
  }
118
128
  }
119
- return { edited, ...(failed.length ? { failed } : {}) };
129
+ return { edited, failed: failed.length ? failed : undefined };
120
130
  }
121
131
  };
122
132
  }
@@ -4,12 +4,12 @@ import { type DiffusionRuntime } from './generate-image.ts';
4
4
  interface Rgba {
5
5
  width: number;
6
6
  height: number;
7
- data: Buffer;
7
+ data: Uint8Array;
8
8
  frames?: Rgba[];
9
9
  }
10
10
  interface Media {
11
11
  image: {
12
- decode(input: Buffer, opts?: {
12
+ decode(input: Uint8Array, opts?: {
13
13
  maxFrames?: number;
14
14
  }): Promise<Rgba>;
15
15
  encode(rgba: Rgba, opts: {
@@ -1,3 +1,4 @@
1
+ import b4a from 'b4a';
1
2
  import fs from 'fs';
2
3
  import path from 'path';
3
4
  import { AbortedError } from '../helpers/race-abort.js';
@@ -11,13 +12,14 @@ async function turnSources(turnImages) {
11
12
  const sources = [];
12
13
  for (const image of turnImages) {
13
14
  const bytes = await fs.promises.readFile(image.path).catch(toNull);
14
- if (!bytes)
15
+ if (!bytes) {
15
16
  return { error: `could not read attached image ${path.basename(image.path)}` };
17
+ }
16
18
  sources.push({ bytes, fileName: path.basename(image.path) });
17
19
  }
18
20
  return sources;
19
21
  }
20
- async function resolveSources(fetchAttachment, ids, turnImages, signal) {
22
+ async function resolveSources(fetchAttachment, { ids, turnImages, signal }) {
21
23
  if (!ids.length) {
22
24
  if (turnImages.length) {
23
25
  const sources = await turnSources(turnImages);
@@ -33,13 +35,16 @@ async function resolveSources(fetchAttachment, ids, turnImages, signal) {
33
35
  const missing = [];
34
36
  for (const id of ids) {
35
37
  const found = await fetchAttachment({ attachmentId: id, signal });
36
- if (found && 'bytes' in found && found.bytes)
38
+ if (found && 'bytes' in found && found.bytes) {
37
39
  sources.push(found);
38
- else
40
+ }
41
+ else {
39
42
  missing.push(id);
43
+ }
40
44
  }
41
- if (!missing.length)
45
+ if (!missing.length) {
42
46
  return { sources };
47
+ }
43
48
  if (sources.length) {
44
49
  return {
45
50
  sources,
@@ -48,8 +53,9 @@ async function resolveSources(fetchAttachment, ids, turnImages, signal) {
48
53
  }
49
54
  if (turnImages.length) {
50
55
  const fallback = await turnSources(turnImages);
51
- if ('error' in fallback)
56
+ if ('error' in fallback) {
52
57
  return fallback;
58
+ }
53
59
  return {
54
60
  sources: fallback,
55
61
  note: `ignored unknown attachment id(s) ${missing.join(', ')} — edited the image(s) from the user's latest message`
@@ -62,7 +68,7 @@ async function resolveSources(fetchAttachment, ids, turnImages, signal) {
62
68
  }
63
69
  async function defaultLoadMedia() {
64
70
  try {
65
- return (await import('bare-media'));
71
+ return await import('bare-media');
66
72
  }
67
73
  catch {
68
74
  return null;
@@ -129,8 +135,9 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
129
135
  }),
130
136
  execute: async (args, ctx) => {
131
137
  const common = parseCommonArgs(args, cap.maxSteps);
132
- if ('error' in common)
138
+ if ('error' in common) {
133
139
  return common;
140
+ }
134
141
  let strength = DEFAULT_STRENGTH;
135
142
  if (args.strength !== undefined && args.strength !== null) {
136
143
  strength = Number(args.strength);
@@ -144,15 +151,17 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
144
151
  const attachmentIds = [];
145
152
  if (Array.isArray(args.attachment_ids)) {
146
153
  for (const id of args.attachment_ids) {
147
- if (typeof id === 'string' && id)
154
+ if (typeof id === 'string' && id) {
148
155
  attachmentIds.push(id);
156
+ }
149
157
  }
150
158
  }
151
159
  if (attachmentId && attachmentIds.length) {
152
160
  return { error: 'pass attachment_id or attachment_ids, not both' };
153
161
  }
154
- if (attachmentId)
162
+ if (attachmentId) {
155
163
  attachmentIds.push(attachmentId);
164
+ }
156
165
  if (!ctx?.attach || !ctx.fetchAttachment) {
157
166
  return { error: 'this device cannot edit chat images' };
158
167
  }
@@ -161,16 +170,24 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
161
170
  if (!attachmentIds.length && turnImages.length > 1 && !inContext) {
162
171
  return { error: MULTI_SOURCE_UNSUPPORTED };
163
172
  }
164
- const resolved = await resolveSources(ctx.fetchAttachment, attachmentIds, turnImages, ctx.signal);
165
- if (ctx.signal?.aborted)
173
+ const resolved = await resolveSources(ctx.fetchAttachment, {
174
+ ids: attachmentIds,
175
+ turnImages,
176
+ signal: ctx.signal
177
+ });
178
+ if (ctx.signal?.aborted) {
166
179
  return { error: 'image generation canceled' };
167
- if ('error' in resolved)
180
+ }
181
+ if ('error' in resolved) {
168
182
  return resolved;
183
+ }
169
184
  const { sources, note } = resolved;
170
- if (sources.length > 1 && !inContext)
185
+ if (sources.length > 1 && !inContext) {
171
186
  return { error: MULTI_SOURCE_UNSUPPORTED };
172
- if (!runtime.acquire())
187
+ }
188
+ if (!runtime.acquire()) {
173
189
  return { error: BUSY_ERROR, code: 'busy' };
190
+ }
174
191
  const report = ctx.progress;
175
192
  const onTick = report && generationPercentTick((percentage) => report({ percentage }), sources.length);
176
193
  try {
@@ -186,7 +203,7 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
186
203
  for (const source of sources) {
187
204
  let decoded;
188
205
  try {
189
- decoded = await media.image.decode(Buffer.from(source.bytes), { maxFrames: 1 });
206
+ decoded = await media.image.decode(b4a.from(source.bytes), { maxFrames: 1 });
190
207
  }
191
208
  catch {
192
209
  return { error: `could not decode ${source.fileName} as an image` };
@@ -198,7 +215,7 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
198
215
  const fitted = frame.width === fitWidth && frame.height === fitHeight
199
216
  ? frame
200
217
  : await resample(frame, fitWidth, fitHeight);
201
- inits.push(Buffer.from(await media.image.encode(fitted, { mimetype: 'image/png' })));
218
+ inits.push(b4a.from(await media.image.encode(fitted, { mimetype: 'image/png' })));
202
219
  if (!width) {
203
220
  width = fitWidth;
204
221
  height = fitHeight;
@@ -207,24 +224,30 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
207
224
  const sdk = await runtime.loadSdk();
208
225
  const { modelId } = await runtime.ensureLoaded(sdk, ctx.signal, ctx.image?.modelChoice);
209
226
  const fusion = inits.length > 1;
210
- const image = await runDiffusion(sdk, modelId, {
211
- prompt: common.prompt,
212
- width,
213
- height,
214
- steps: effectiveSteps(common.steps, ctx.image?.steps, stepsCap),
215
- seed: common.seed,
216
- negative_prompt: common.negativePrompt,
217
- ...(inContext
218
- ? {
219
- init_images: inits,
220
- auto_resize_ref_image: true,
221
- guidance: FLUX2_GUIDANCE,
222
- cfg_scale: FLUX2_CFG_SCALE
223
- }
224
- : { init_image: inits[0], strength })
225
- }, ctx.signal, onTick);
226
- if (!(image instanceof Uint8Array))
227
+ const image = await runDiffusion(sdk, {
228
+ modelId,
229
+ params: {
230
+ prompt: common.prompt,
231
+ width,
232
+ height,
233
+ steps: effectiveSteps(common.steps, ctx.image?.steps, stepsCap),
234
+ seed: common.seed,
235
+ negative_prompt: common.negativePrompt,
236
+ ...(inContext
237
+ ? {
238
+ init_images: inits,
239
+ auto_resize_ref_image: true,
240
+ guidance: FLUX2_GUIDANCE,
241
+ cfg_scale: FLUX2_CFG_SCALE
242
+ }
243
+ : { init_image: inits[0], strength })
244
+ },
245
+ signal: ctx.signal,
246
+ onTick
247
+ });
248
+ if (!(image instanceof Uint8Array)) {
227
249
  return image;
250
+ }
228
251
  const record = await ctx.attach({
229
252
  fileName: `edited-${Date.now()}.png`,
230
253
  mimeType: 'image/png',
@@ -244,7 +267,7 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
244
267
  ...(sources.length === 1 && sources[0].id
245
268
  ? { sourceAttachmentId: sources[0].id }
246
269
  : { sourceFileNames: sources.map((source) => source.fileName) }),
247
- ...(notes.length ? { note: notes.join('; ') } : {}),
270
+ note: notes.length ? notes.join('; ') : undefined,
248
271
  fileName: record.fileName,
249
272
  byteLength: record.byteLength,
250
273
  width,
@@ -252,8 +275,9 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
252
275
  };
253
276
  }
254
277
  catch (err) {
255
- if (err instanceof AbortedError)
278
+ if (err instanceof AbortedError) {
256
279
  return { error: 'image generation canceled' };
280
+ }
257
281
  if (err instanceof Error && err.message === IMAGE_LOAD_STALL_ERROR) {
258
282
  return { error: IMAGE_LOAD_STALL_ERROR };
259
283
  }
@@ -1,14 +1,14 @@
1
1
  import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
2
2
  import type { AttachFn, FetchAttachmentFn, RunBudget, ToolDecision } from '../../../capabilities/completion.ts';
3
3
  import type { ExecResult } from '../runner.ts';
4
- export type ExecutionOptions = {
4
+ export interface ExecutionOptions {
5
5
  readonly cwd?: string;
6
6
  readonly env?: Readonly<Record<string, string>>;
7
7
  readonly timeoutMs?: number;
8
8
  readonly maxOutputChars?: number;
9
9
  readonly signal?: BareAbortSignal;
10
- };
11
- export type ExecutionContext = {
10
+ }
11
+ export interface ExecutionContext {
12
12
  readonly attach?: AttachFn;
13
13
  readonly fetchAttachment?: FetchAttachmentFn;
14
14
  readonly turnImages?: readonly {
@@ -19,13 +19,13 @@ export type ExecutionContext = {
19
19
  readonly toolNames?: readonly string[];
20
20
  readonly approval?: ToolDecision;
21
21
  readonly confirmConnect?: (host: string) => Promise<boolean>;
22
- };
23
- export type ExecutionPlan = {
22
+ }
23
+ export interface ExecutionPlan {
24
24
  run(options: ExecutionOptions): Promise<ExecResult> | ExecResult;
25
- };
26
- export type ExecutionAdapter = {
25
+ }
26
+ export interface ExecutionAdapter {
27
27
  resolve(args: Record<string, unknown>, ctx?: ExecutionContext): ExecutionPlan | null;
28
- };
29
- export type FallbackExecutionAdapter = {
28
+ }
29
+ export interface FallbackExecutionAdapter {
30
30
  resolve(args: Record<string, unknown>, ctx?: ExecutionContext): ExecutionPlan;
31
- };
31
+ }
@@ -1,26 +1,32 @@
1
1
  import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
2
2
  import type { AttachFn, FetchAttachmentFn, RunBudget } from '../../../../capabilities/completion.ts';
3
3
  import type { ExecAttachment, RejectedOutput } from '../../runner.ts';
4
- export type ExecInput = {
4
+ import { type ExecError } from './output-policy.ts';
5
+ export interface ExecInput {
5
6
  readonly attachmentId?: string;
6
7
  readonly path: string;
7
- };
8
- export type StagedInput = {
8
+ }
9
+ export interface StagedInput {
9
10
  readonly path: string;
10
11
  readonly bytes: Uint8Array;
11
- };
12
- export declare function stageInputs(fetchAttachment: FetchAttachmentFn, inputs: readonly ExecInput[], opts?: {
12
+ }
13
+ export interface StageInputsOptions {
13
14
  turnImages?: readonly {
14
15
  path: string;
15
16
  }[];
16
17
  signal?: BareAbortSignal;
17
- }): Promise<{
18
+ }
19
+ export interface StagedInputs {
18
20
  files: readonly StagedInput[];
19
- } | {
20
- error: string;
21
- }>;
22
- export declare function attachOutputs(attach: AttachFn, files: ReadonlyMap<string, Uint8Array>, declared: readonly string[], runBudget?: RunBudget): Promise<{
21
+ }
22
+ export declare function stageInputs(fetchAttachment: FetchAttachmentFn, inputs: readonly ExecInput[], opts?: StageInputsOptions): Promise<StagedInputs | ExecError>;
23
+ export interface AttachOutputsOptions {
24
+ readonly declared: readonly string[];
25
+ readonly runBudget?: RunBudget | undefined;
26
+ }
27
+ export interface AttachedOutputs {
23
28
  attachments: readonly ExecAttachment[];
24
29
  missingOutputs: readonly string[];
25
30
  rejectedOutputs: readonly RejectedOutput[];
26
- }>;
31
+ }
32
+ export declare function attachOutputs(attach: AttachFn, files: ReadonlyMap<string, Uint8Array>, { declared, runBudget }: AttachOutputsOptions): Promise<AttachedOutputs>;