@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
@@ -1,6 +1,7 @@
1
1
  import type { AbortSignal } from 'bare-abort-controller';
2
2
  export { closePythonWorker as closeOfficeWorker } from '../tools/exec/adapters/python/worker/client.ts';
3
- export declare function extractOfficeText(bytes: Uint8Array, fileName: string, options?: {
3
+ export interface OfficeExtractOptions {
4
4
  readonly signal?: AbortSignal | undefined;
5
5
  readonly mimeType?: string | undefined;
6
- }): Promise<string>;
6
+ }
7
+ export declare function extractOfficeText(bytes: Uint8Array, fileName: string, options?: OfficeExtractOptions): Promise<string>;
@@ -1,7 +1,8 @@
1
1
  import type { AbortSignal } from 'bare-abort-controller';
2
- export declare function extractWithPython(bytes: Uint8Array, fileName: string, { format, packages, source, signal }: {
2
+ export interface PythonExtractOptions {
3
3
  readonly format: string;
4
4
  readonly packages: readonly string[];
5
5
  readonly source: string;
6
6
  readonly signal?: AbortSignal | undefined;
7
- }): Promise<string>;
7
+ }
8
+ export declare function extractWithPython(bytes: Uint8Array, fileName: string, { format, packages, source, signal }: PythonExtractOptions): Promise<string>;
@@ -22,8 +22,9 @@ export async function extractWithPython(bytes, fileName, { format, packages, sou
22
22
  outputs: ['extracted.txt'],
23
23
  signal
24
24
  });
25
- if (result.exitCode !== 0)
25
+ if (result.exitCode !== 0) {
26
26
  throw new Error(`${fileName}: ${result.stderr.trim()}`);
27
+ }
27
28
  const output = result.files?.get('extracted.txt');
28
29
  if (!output) {
29
30
  throw new Error(result.rejected?.[0]?.reason ?? `${format} extraction produced no text file`);
@@ -16,7 +16,8 @@ export interface SystemPromptParts {
16
16
  }
17
17
  export declare function systemPromptParts({ bio, toolNames, skillsSection }: SystemPromptInput): SystemPromptParts;
18
18
  export declare function buildSystemPrompt(input: SystemPromptInput): string;
19
- export declare function skillsPromptSection(activeSkills: ReadonlyArray<{
20
- name: string;
21
- description: string;
22
- }>): string | null;
19
+ export interface PromptSkill {
20
+ readonly name: string;
21
+ readonly description: string;
22
+ }
23
+ export declare function skillsPromptSection(activeSkills: ReadonlyArray<PromptSkill>): string | null;
@@ -34,8 +34,9 @@ export function annotateLastUserTime(turns, now) {
34
34
  const result = [...turns];
35
35
  for (let i = result.length - 1; i >= 0; i--) {
36
36
  const turn = result[i];
37
- if (!turn || turn.role !== 'user')
37
+ if (!turn || turn.role !== 'user') {
38
38
  continue;
39
+ }
39
40
  result[i] = { ...turn, content: `${currentTimeAnnotation(now)}\n\n${turn.content}` };
40
41
  break;
41
42
  }
@@ -43,12 +44,15 @@ export function annotateLastUserTime(turns, now) {
43
44
  }
44
45
  function buildGuidelines(active) {
45
46
  const lines = [...BASE_GUIDELINES];
46
- if (active.size > 0)
47
+ if (active.size > 0) {
47
48
  lines.push(...TOOL_GUIDELINES);
48
- if (active.has('exec'))
49
+ }
50
+ if (active.has('exec')) {
49
51
  lines.push(EXEC_FILE_GUIDELINE, EXEC_ATTACHED_IMAGE_GUIDELINE);
50
- if (active.has('skill'))
52
+ }
53
+ if (active.has('skill')) {
51
54
  lines.push(...SKILL_GUIDELINES);
55
+ }
52
56
  if (active.has('web_search') || active.has('web_fetch')) {
53
57
  lines.push(CITATION_GUIDELINE);
54
58
  }
@@ -16,12 +16,14 @@ export function pushQueue({ highWaterMark = 0 } = {}) {
16
16
  return items.length;
17
17
  },
18
18
  push(item) {
19
- if (ended)
19
+ if (ended) {
20
20
  return Promise.resolve();
21
+ }
21
22
  items.push(item);
22
23
  wakeConsumer();
23
- if (highWaterMark <= 0 || items.length < highWaterMark)
24
+ if (highWaterMark <= 0 || items.length < highWaterMark) {
24
25
  return Promise.resolve();
26
+ }
25
27
  drain ??= Promise.withResolvers();
26
28
  return drain.promise;
27
29
  },
@@ -33,13 +35,16 @@ export function pushQueue({ highWaterMark = 0 } = {}) {
33
35
  async *[Symbol.asyncIterator]() {
34
36
  while (true) {
35
37
  while (items.length) {
36
- const item = items.shift();
37
- if (highWaterMark > 0 && items.length < highWaterMark)
38
+ const item = items[0];
39
+ items.shift();
40
+ if (highWaterMark > 0 && items.length < highWaterMark) {
38
41
  wakeProducer();
42
+ }
39
43
  yield item;
40
44
  }
41
- if (ended)
45
+ if (ended) {
42
46
  return;
47
+ }
43
48
  wake = Promise.withResolvers();
44
49
  await wake.promise;
45
50
  }
@@ -1,3 +1,4 @@
1
+ import { errorMessage, isRecord } from './guards.js';
1
2
  import { hlog } from './log.js';
2
3
  function readValue(value, key) {
3
4
  if (value === null)
@@ -12,29 +13,34 @@ function readString(value, key) {
12
13
  }
13
14
  function readCandidates(err) {
14
15
  const found = readValue(err, 'candidates');
15
- if (!Array.isArray(found))
16
+ if (!Array.isArray(found)) {
16
17
  return undefined;
18
+ }
17
19
  return found.map((candidate) => readString(candidate, 'href') ?? String(candidate));
18
20
  }
19
21
  export function resolutionDetail(err) {
20
22
  const detail = {};
21
23
  const code = readString(err, 'code');
22
- if (code !== null)
24
+ if (code !== null) {
23
25
  detail.code = code;
26
+ }
24
27
  const specifier = readString(err, 'specifier');
25
- if (specifier !== null)
28
+ if (specifier !== null) {
26
29
  detail.specifier = specifier;
30
+ }
27
31
  const referrer = readString(readValue(err, 'referrer'), 'href');
28
- if (referrer !== null)
32
+ if (referrer !== null) {
29
33
  detail.referrer = referrer;
34
+ }
30
35
  const candidates = readCandidates(err);
31
- if (candidates !== undefined)
36
+ if (candidates !== undefined) {
32
37
  detail.candidates = candidates;
38
+ }
33
39
  return detail;
34
40
  }
35
41
  function readCache(meta) {
36
42
  const cache = readValue(meta, 'cache');
37
- return typeof cache === 'object' && cache !== null ? cache : null;
43
+ return isRecord(cache) ? cache : null;
38
44
  }
39
45
  export function isReferrerLost(referrer, parent, cache) {
40
46
  if (referrer !== null && referrer !== undefined)
@@ -48,23 +54,27 @@ export function resolutionFailure(specifier, parent, err) {
48
54
  specifier,
49
55
  parent,
50
56
  ...resolutionDetail(err),
51
- err: err instanceof Error ? err.message : String(err)
57
+ err: errorMessage(err)
52
58
  };
53
59
  }
54
60
  let uninstall = null;
55
61
  export function installResolutionDetector(meta) {
56
62
  const cacheRecord = readCache(meta);
57
- if (cacheRecord === null)
63
+ if (cacheRecord === null) {
58
64
  return noop;
59
- if (uninstall !== null)
65
+ }
66
+ if (uninstall !== null) {
60
67
  return noop;
68
+ }
61
69
  const self = Reflect.get(cacheRecord, meta.url);
62
70
  const Module = readValue(self, 'constructor');
63
- if (typeof Module !== 'function')
71
+ if (typeof Module !== 'function') {
64
72
  return noop;
73
+ }
65
74
  const resolve = readValue(Module, 'resolve');
66
- if (typeof resolve !== 'function')
75
+ if (typeof resolve !== 'function') {
67
76
  return noop;
77
+ }
68
78
  const startedAt = Date.now();
69
79
  const original = resolve.bind(Module);
70
80
  const wrapped = (specifier, parentURL, opts = {}) => {
@@ -14,7 +14,8 @@ export function settleOnClose(hrpc) {
14
14
  };
15
15
  session._stream.on('error', (err) => dead(err));
16
16
  session._stream.on('close', () => dead(null));
17
- if (session._stream.destroyed)
17
+ if (session._stream.destroyed) {
18
18
  dead(null);
19
+ }
19
20
  return hrpc;
20
21
  }
@@ -1,3 +1,4 @@
1
+ import { errorMessage } from './guards.js';
1
2
  import { retryMemo } from './helpers/retry-memo.js';
2
3
  import { hlog } from './log.js';
3
4
  const defaultImports = {
@@ -15,7 +16,7 @@ function register(registry, name, plugin) {
15
16
  catch (err) {
16
17
  hlog('plugin registration skipped', {
17
18
  plugin: name,
18
- err: err instanceof Error ? err.message : String(err)
19
+ err: errorMessage(err)
19
20
  });
20
21
  }
21
22
  }
@@ -14,10 +14,12 @@ export function configureSdkStorage(storage, channels = {}) {
14
14
  writeFileSync(configPath, `${JSON.stringify({ cacheDirectory: storage.models }, null, 2)}\n`);
15
15
  const openclCacheDir = join(storage.home, 'opencl-cache');
16
16
  mkdirSync(openclCacheDir, { recursive: true });
17
- if (argv)
17
+ if (argv) {
18
18
  argv[0] = storage.home;
19
- else
19
+ }
20
+ else {
20
21
  env[SDK_HOME_ENV] = storage.home;
22
+ }
21
23
  env[SDK_CONFIG_PATH_ENV] = configPath;
22
24
  env[OPENCL_CACHE_DIR_ENV] = openclCacheDir;
23
25
  return configPath;
@@ -1,4 +1,5 @@
1
1
  import { AbortController } from 'bare-abort-controller';
2
+ import b4a from 'b4a';
2
3
  import fs from 'fs';
3
4
  import { settleOnClose } from './rpc-session.js';
4
5
  import { pipeline, Readable } from 'streamx';
@@ -7,7 +8,7 @@ import HRPC from '../spec/hrpc/index.js';
7
8
  import { isCapability } from './capabilities/invoke.js';
8
9
  import { CUSTOM_TASK_TYPES } from './models/model-catalog.js';
9
10
  import { unsupportedKvCacheDeletion } from './capabilities/kv-cache.js';
10
- import { errorMessage } from './error-fields.js';
11
+ import { errorMessage } from './guards.js';
11
12
  import { hlog } from './log.js';
12
13
  import { pushQueue } from './queue.js';
13
14
  import { TextCoalescer } from './helpers/text-coalescer.js';
@@ -45,6 +46,10 @@ export function serveHarness(stream, harness) {
45
46
  await harness.setSkillSettings?.(entries ?? []);
46
47
  return { ok: true };
47
48
  },
49
+ setModelIdleTimeout: async ({ ms }) => {
50
+ await harness.setModelIdleTimeout?.(ms);
51
+ return { ok: true };
52
+ },
48
53
  listManagedSkills: async () => ({
49
54
  skills: (await harness.listManagedSkills?.()) ?? []
50
55
  }),
@@ -55,8 +60,9 @@ export function serveHarness(stream, harness) {
55
60
  : { found: false, content: '', origin: '' };
56
61
  },
57
62
  writeSkillFile: async ({ name, content }) => {
58
- if (!harness.writeSkillFile)
63
+ if (!harness.writeSkillFile) {
59
64
  return { ok: false };
65
+ }
60
66
  return harness.writeSkillFile(name, content);
61
67
  },
62
68
  copySkillForEdit: async ({ name }) => ({
@@ -66,17 +72,21 @@ export function serveHarness(stream, harness) {
66
72
  removed: (await harness.deleteOverlaySkill?.(name))?.removed ?? false
67
73
  }),
68
74
  setCustomModels: async ({ models }) => {
69
- await harness.setCustomModels?.((models ?? []).flatMap(({ name, src, projectionSrc, taskType, expectedSize }) => {
75
+ await harness.setCustomModels?.((models ?? []).flatMap((model) => {
76
+ const { name, src, projectionSrc, taskType, expectedSize, label, contextLength } = model;
70
77
  const known = CUSTOM_TASK_TYPES.find((task) => task === taskType);
71
- if (taskType && !known)
78
+ if (taskType && !known) {
72
79
  return [];
80
+ }
73
81
  return [
74
82
  {
75
83
  name,
76
84
  src,
77
85
  projectionSrc: projectionSrc ?? undefined,
78
86
  taskType: known,
79
- expectedSize: expectedSize || undefined
87
+ expectedSize: expectedSize || undefined,
88
+ label: label || undefined,
89
+ contextLength: contextLength || undefined
80
90
  }
81
91
  ];
82
92
  }));
@@ -107,15 +117,17 @@ export function serveHarness(stream, harness) {
107
117
  return packVectors(await harness.embed({ model, texts: texts ?? [] }));
108
118
  },
109
119
  transcribe: async ({ model, audio }) => {
110
- if (!harness.transcribe)
120
+ if (!harness.transcribe) {
111
121
  throw new Error('harness does not support transcribe');
122
+ }
112
123
  return {
113
- text: await harness.transcribe({ model: model ?? '', audio: audio ?? Buffer.alloc(0) })
124
+ text: await harness.transcribe({ model: model ?? '', audio: audio ?? b4a.alloc(0) })
114
125
  };
115
126
  },
116
127
  detectLanguage: async ({ text, topK }) => {
117
- if (!harness.detectLanguage)
128
+ if (!harness.detectLanguage) {
118
129
  throw new Error('harness does not support detectLanguage');
130
+ }
119
131
  const languages = await harness.detectLanguage({
120
132
  text: text ?? '',
121
133
  topK: topK ?? undefined
@@ -129,13 +141,15 @@ export function serveHarness(stream, harness) {
129
141
  },
130
142
  speakStream: speakStream(harness),
131
143
  getEmbeddingDevice: async () => {
132
- if (!harness.getEmbeddingDevice)
144
+ if (!harness.getEmbeddingDevice) {
133
145
  throw unsupportedEmbeddingDeviceControl();
146
+ }
134
147
  return { device: await harness.getEmbeddingDevice() };
135
148
  },
136
149
  setEmbeddingDevice: async ({ device }) => {
137
- if (!harness.setEmbeddingDevice)
150
+ if (!harness.setEmbeddingDevice) {
138
151
  throw unsupportedEmbeddingDeviceControl();
152
+ }
139
153
  await harness.setEmbeddingDevice(device);
140
154
  return { ok: true };
141
155
  },
@@ -150,7 +164,7 @@ export function serveHarness(stream, harness) {
150
164
  }),
151
165
  listModels: async (req) => ({
152
166
  models: (await harness.list?.({
153
- type: (req?.type || undefined),
167
+ type: req?.type || undefined,
154
168
  cachedOnly: req?.cachedOnly ?? undefined,
155
169
  fullRegistry: req?.fullRegistry ?? undefined
156
170
  })) ?? []
@@ -165,13 +179,15 @@ export function serveHarness(stream, harness) {
165
179
  models: (await harness.infraModels?.(profile ?? '')) ?? []
166
180
  }),
167
181
  capability: async () => {
168
- if (!harness.capability)
182
+ if (!harness.capability) {
169
183
  throw new Error('harness does not support capability');
184
+ }
170
185
  return harness.capability();
171
186
  },
172
187
  warmModel: async ({ model, agent }) => {
173
- if (!harness.warmModel)
188
+ if (!harness.warmModel) {
174
189
  throw new Error('harness does not support warmModel');
190
+ }
175
191
  await harness.warmModel({ model, agent: agent ?? {} });
176
192
  return { ok: true };
177
193
  },
@@ -199,19 +215,15 @@ function toWireSkill(skill) {
199
215
  allowList: skill.allowList,
200
216
  platforms: skill.platform,
201
217
  status: skill.status,
202
- ...(skill.requires
203
- ? {
204
- requirements: {
205
- binaries,
206
- credentials: skill.requires.credentials ?? []
207
- }
208
- }
209
- : {}),
210
- ...(skill.install ? { install: skill.install } : {}),
211
- ...(skill.setup ? { setup: skill.setup, ...(setupV2 ? { setupV2 } : {}) } : {}),
212
- ...(skill.stub !== undefined ? { stub: skill.stub } : {}),
213
- ...(skill.minCapabilityProfile ? { minCapabilityProfile: skill.minCapabilityProfile } : {}),
214
- ...(skill.emoji ? { emoji: skill.emoji } : {})
218
+ requirements: skill.requires
219
+ ? { binaries, credentials: skill.requires.credentials ?? [] }
220
+ : undefined,
221
+ install: skill.install || undefined,
222
+ setup: skill.setup || undefined,
223
+ setupV2,
224
+ stub: skill.stub,
225
+ minCapabilityProfile: skill.minCapabilityProfile || undefined,
226
+ emoji: skill.emoji || undefined
215
227
  };
216
228
  }
217
229
  function unsupportedEmbeddingDeviceControl() {
@@ -246,8 +258,9 @@ function modelEvents(harness) {
246
258
  catalogChanged,
247
259
  ...loaded.map((entry) => `${entry.model}:${entry.refs}`)
248
260
  ].join('\0');
249
- if (key === last)
261
+ if (key === last) {
250
262
  return;
263
+ }
251
264
  last = key;
252
265
  const frame = {
253
266
  status: state.status,
@@ -285,16 +298,18 @@ function modelEvents(harness) {
285
298
  }
286
299
  function speakStream(harness) {
287
300
  return async function* (duplex) {
288
- if (!harness.speakStream)
301
+ if (!harness.speakStream) {
289
302
  throw new Error('harness does not support speakStream');
303
+ }
290
304
  const text = pushQueue();
291
305
  const end = () => text.end();
292
306
  duplex.on('close', end);
293
307
  duplex.on('end', end);
294
308
  duplex.readStream?.on('close', end);
295
309
  duplex.on('data', (frame) => {
296
- if (frame.text)
310
+ if (frame.text) {
297
311
  text.push(frame.text);
312
+ }
298
313
  });
299
314
  for await (const chunk of harness.speakStream({ model: '', text })) {
300
315
  yield { audio: chunk.audio, sampleRate: chunk.sampleRate };
@@ -302,13 +317,15 @@ function speakStream(harness) {
302
317
  };
303
318
  }
304
319
  function runFrame(harness, frame, context) {
305
- if (frame.type !== 'invoke')
320
+ if (frame.type !== 'invoke') {
306
321
  return harness.completion(context);
322
+ }
307
323
  if (!harness.invoke)
308
324
  throw new Error('harness does not support invoke');
309
325
  const capability = frame.capability ?? '';
310
- if (!isCapability(capability))
326
+ if (!isCapability(capability)) {
311
327
  throw new Error(`unknown capability: ${capability}`);
328
+ }
312
329
  return harness.invoke({
313
330
  capability,
314
331
  args: frame.arguments ?? {},
@@ -334,26 +351,31 @@ function completion(harness) {
334
351
  let started = false;
335
352
  const gone = () => {
336
353
  controller.abort('client gone');
337
- for (const resolve of pending.values())
354
+ for (const resolve of pending.values()) {
338
355
  resolve(false);
356
+ }
339
357
  pending.clear();
340
358
  for (const { reject, staged } of pendingAttach.values()) {
341
359
  void fs.promises.unlink(staged).catch(noop);
342
360
  reject(new Error('client gone'));
343
361
  }
344
362
  pendingAttach.clear();
345
- for (const { reject } of pendingFetch.values())
363
+ for (const { reject } of pendingFetch.values()) {
346
364
  reject(new Error('client gone'));
365
+ }
347
366
  pendingFetch.clear();
348
- for (const { reject } of pendingRag.values())
367
+ for (const { reject } of pendingRag.values()) {
349
368
  reject(new Error('client gone'));
369
+ }
350
370
  pendingRag.clear();
351
- for (const { resolve } of pendingQuestion.values())
371
+ for (const { resolve } of pendingQuestion.values()) {
352
372
  resolve(null);
373
+ }
353
374
  pendingQuestion.clear();
354
375
  for (const { reject, path } of pendingDrive.values()) {
355
- if (path)
376
+ if (path) {
356
377
  void fs.promises.unlink(path).catch(noop);
378
+ }
357
379
  reject(new Error('client gone'));
358
380
  }
359
381
  pendingDrive.clear();
@@ -364,35 +386,43 @@ function completion(harness) {
364
386
  duplex.readStream?.on('close', gone);
365
387
  duplex.on('data', (frame) => {
366
388
  if (frame.type === 'decision') {
367
- if (typeof frame.callId !== 'string')
389
+ if (typeof frame.callId !== 'string') {
368
390
  return;
391
+ }
369
392
  pending.get(frame.callId)?.(frame.approved === true);
370
393
  pending.delete(frame.callId);
371
394
  return;
372
395
  }
373
396
  if (frame.type === 'attach-result') {
374
- if (typeof frame.callId !== 'string')
397
+ if (typeof frame.callId !== 'string') {
375
398
  return;
399
+ }
376
400
  const waiter = pendingAttach.get(frame.callId);
377
401
  pendingAttach.delete(frame.callId);
378
- if (!waiter)
402
+ if (!waiter) {
379
403
  return;
404
+ }
380
405
  void fs.promises.unlink(waiter.staged).catch(noop);
381
- if (frame.attachment)
406
+ if (frame.attachment) {
382
407
  waiter.resolve(frame.attachment);
383
- else
408
+ }
409
+ else {
384
410
  waiter.reject(new Error(frame.message || 'the host failed to store the attachment'));
411
+ }
385
412
  return;
386
413
  }
387
414
  if (frame.type === 'fetch-result') {
388
- if (typeof frame.callId !== 'string')
415
+ if (typeof frame.callId !== 'string') {
389
416
  return;
417
+ }
390
418
  const waiter = pendingFetch.get(frame.callId);
391
419
  pendingFetch.delete(frame.callId);
392
- if (!waiter)
420
+ if (!waiter) {
393
421
  return;
394
- if (frame.message)
422
+ }
423
+ if (frame.message) {
395
424
  return waiter.reject(new Error(frame.message));
425
+ }
396
426
  const staged = frame.path;
397
427
  const { fileName, mimeType, attachmentId, size } = frame;
398
428
  if (frame.meta === true) {
@@ -403,8 +433,9 @@ function completion(harness) {
403
433
  byteLength: typeof size === 'number' ? size : 0
404
434
  });
405
435
  }
406
- if (!staged)
436
+ if (!staged) {
407
437
  return waiter.resolve(null);
438
+ }
408
439
  fs.promises.readFile(staged).then((bytes) => waiter.resolve({
409
440
  id: attachmentId ?? '',
410
441
  fileName: fileName ?? '',
@@ -415,42 +446,52 @@ function completion(harness) {
415
446
  return;
416
447
  }
417
448
  if (frame.type === 'rag-result') {
418
- if (typeof frame.callId !== 'string')
449
+ if (typeof frame.callId !== 'string') {
419
450
  return;
451
+ }
420
452
  const waiter = pendingRag.get(frame.callId);
421
453
  pendingRag.delete(frame.callId);
422
- if (!waiter)
454
+ if (!waiter) {
423
455
  return;
424
- if (frame.message)
456
+ }
457
+ if (frame.message) {
425
458
  return waiter.reject(new Error(frame.message));
459
+ }
426
460
  waiter.resolve(frame.result ?? { enabled: false, indexEmpty: true, hasKnowledge: false, hits: [] });
427
461
  }
428
462
  if (frame.type === 'question-result') {
429
- if (typeof frame.callId !== 'string')
463
+ if (typeof frame.callId !== 'string') {
430
464
  return;
465
+ }
431
466
  const waiter = pendingQuestion.get(frame.callId);
432
467
  pendingQuestion.delete(frame.callId);
433
- if (!waiter)
468
+ if (!waiter) {
434
469
  return;
435
- if (frame.message)
470
+ }
471
+ if (frame.message) {
436
472
  hlog('question failed', { callId: frame.callId, message: frame.message });
473
+ }
437
474
  waiter.resolve(frame.answer || null);
438
475
  return;
439
476
  }
440
477
  if (frame.type === 'drive-result') {
441
- if (typeof frame.callId !== 'string')
478
+ if (typeof frame.callId !== 'string') {
442
479
  return;
480
+ }
443
481
  const waiter = pendingDrive.get(frame.callId);
444
482
  pendingDrive.delete(frame.callId);
445
- if (!waiter)
483
+ if (!waiter) {
446
484
  return;
447
- if (frame.message)
485
+ }
486
+ if (frame.message) {
448
487
  return waiter.reject(new Error(frame.message));
449
- waiter.resolve((frame.payload ?? {}));
488
+ }
489
+ waiter.resolve(frame.payload ?? {});
450
490
  return;
451
491
  }
452
- if (started || (frame.type !== 'start' && frame.type !== 'invoke'))
492
+ if (started || (frame.type !== 'start' && frame.type !== 'invoke')) {
453
493
  return;
494
+ }
454
495
  started = true;
455
496
  const context = {
456
497
  model: frame.model ?? '',
@@ -463,9 +504,9 @@ function completion(harness) {
463
504
  messages: (frame.messages ?? []).map(({ role, content, attachments }) => ({
464
505
  role,
465
506
  content,
466
- ...(attachments?.length
467
- ? { attachments: attachments.map(({ path: file }) => ({ path: file })) }
468
- : {})
507
+ attachments: attachments?.length
508
+ ? attachments.map(({ path: file }) => ({ path: file }))
509
+ : undefined
469
510
  })),
470
511
  toolConfigs: frame.toolConfigs ?? undefined,
471
512
  grantedDirs: frame.grantedDirs ?? undefined,
@@ -483,7 +524,7 @@ function completion(harness) {
483
524
  pendingDrive.set(callId, {
484
525
  resolve,
485
526
  reject,
486
- ...(request.op === 'write' ? { path: request.path } : {})
527
+ path: request.op === 'write' ? request.path : undefined
487
528
  });
488
529
  events.push({ type: 'drive-ask', callId, op: request.op, payload: request });
489
530
  })
@@ -532,7 +573,7 @@ function completion(harness) {
532
573
  type: 'fetch-ask',
533
574
  callId,
534
575
  attachmentId,
535
- ...(meta === true ? { meta: true } : {})
576
+ meta: meta === true ? true : undefined
536
577
  });
537
578
  }),
538
579
  ragSearch: ({ query, limit }) => controller.signal.aborted
@@ -627,6 +668,13 @@ function downloadStream(harness, req) {
627
668
  pendingProgress = null;
628
669
  lastProgressAt = at;
629
670
  };
671
+ const queueProgress = (wire) => {
672
+ const now = Date.now();
673
+ pendingProgress = wire;
674
+ if (lastProgressAt === 0 || now - lastProgressAt >= DOWNLOAD_PROGRESS_INTERVAL_MS) {
675
+ flushProgress(now);
676
+ }
677
+ };
630
678
  try {
631
679
  for await (const event of harness.download({
632
680
  model: req.model,
@@ -636,11 +684,7 @@ function downloadStream(harness, req) {
636
684
  })) {
637
685
  const wire = toDownloadWire(event);
638
686
  if (wire.type === 'progress') {
639
- const now = Date.now();
640
- pendingProgress = wire;
641
- if (lastProgressAt === 0 || now - lastProgressAt >= DOWNLOAD_PROGRESS_INTERVAL_MS) {
642
- flushProgress(now);
643
- }
687
+ queueProgress(wire);
644
688
  continue;
645
689
  }
646
690
  flushProgress();