@qvac/harness 0.3.3 → 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 (301) hide show
  1. package/CHANGELOG.md +700 -126
  2. package/README.md +156 -0
  3. package/dist/harness.bundle +71 -103
  4. package/dist/prebuilds-manifest.json +0 -8
  5. package/dist-lib/index.d.ts +42 -40
  6. package/dist-lib/index.js +307 -117
  7. package/dist-lib/lib/audio-transcode-bare.d.ts +2 -2
  8. package/dist-lib/lib/audio-transcode-bare.js +28 -18
  9. package/dist-lib/lib/audio-transcode-node.d.ts +2 -2
  10. package/dist-lib/lib/capabilities/audio-resample.d.ts +7 -6
  11. package/dist-lib/lib/capabilities/audio-resample.js +30 -18
  12. package/dist-lib/lib/capabilities/completion.d.ts +20 -19
  13. package/dist-lib/lib/capabilities/completion.js +194 -135
  14. package/dist-lib/lib/capabilities/download.d.ts +6 -6
  15. package/dist-lib/lib/capabilities/download.js +15 -8
  16. package/dist-lib/lib/capabilities/embed.js +2 -1
  17. package/dist-lib/lib/capabilities/enhance.d.ts +6 -1
  18. package/dist-lib/lib/capabilities/enhance.js +7 -4
  19. package/dist-lib/lib/capabilities/invoke.js +7 -4
  20. package/dist-lib/lib/capabilities/kv-cache.js +2 -1
  21. package/dist-lib/lib/capabilities/preview-model-source.d.ts +69 -0
  22. package/dist-lib/lib/capabilities/preview-model-source.js +439 -0
  23. package/dist-lib/lib/capabilities/speech-text.js +5 -4
  24. package/dist-lib/lib/capabilities/tool-selection.js +10 -9
  25. package/dist-lib/lib/capabilities/tool-turns.js +30 -16
  26. package/dist-lib/lib/capabilities/usage-breakdown.js +2 -1
  27. package/dist-lib/lib/capabilities/voice.d.ts +5 -1
  28. package/dist-lib/lib/capabilities/voice.js +22 -12
  29. package/dist-lib/lib/connect.d.ts +15 -37
  30. package/dist-lib/lib/connect.js +161 -112
  31. package/dist-lib/lib/context-window.js +25 -21
  32. package/dist-lib/lib/contract-types.d.ts +26 -20
  33. package/dist-lib/lib/diagram-repair.d.ts +4 -4
  34. package/dist-lib/lib/diagram-repair.js +6 -3
  35. package/dist-lib/lib/docx/index.d.ts +3 -2
  36. package/dist-lib/lib/{error-fields.d.ts → guards.d.ts} +1 -0
  37. package/dist-lib/lib/{error-fields.js → guards.js} +3 -0
  38. package/dist-lib/lib/hardware/capability-probe.js +20 -10
  39. package/dist-lib/lib/hardware/gpu-classify.js +6 -3
  40. package/dist-lib/lib/hardware/gpu-probe-addon.js +8 -4
  41. package/dist-lib/lib/hardware/gpu-probe.js +4 -2
  42. package/dist-lib/lib/hardware/gpu-stats.native.cjs +8 -9
  43. package/dist-lib/lib/hardware/parsers.js +8 -4
  44. package/dist-lib/lib/helpers/buffer-burst.js +4 -2
  45. package/dist-lib/lib/helpers/control-tokens.js +4 -2
  46. package/dist-lib/lib/helpers/join-guard.d.ts +2 -2
  47. package/dist-lib/lib/helpers/join-guard.js +4 -2
  48. package/dist-lib/lib/helpers/load-stall.js +4 -2
  49. package/dist-lib/lib/helpers/markup-stream-filter.d.ts +2 -2
  50. package/dist-lib/lib/helpers/markup-stream-filter.js +6 -3
  51. package/dist-lib/lib/helpers/race-abort.js +2 -1
  52. package/dist-lib/lib/helpers/race-timeout.d.ts +5 -0
  53. package/dist-lib/lib/helpers/race-timeout.js +14 -0
  54. package/dist-lib/lib/helpers/run-outcome.d.ts +6 -8
  55. package/dist-lib/lib/helpers/run-outcome.js +36 -20
  56. package/dist-lib/lib/helpers/spawn-path.js +6 -3
  57. package/dist-lib/lib/helpers/text-coalescer.js +6 -3
  58. package/dist-lib/lib/helpers/thinking.js +38 -45
  59. package/dist-lib/lib/helpers/tool-call-markup.d.ts +9 -7
  60. package/dist-lib/lib/helpers/tool-call-markup.js +36 -20
  61. package/dist-lib/lib/helpers/tool-intent.d.ts +3 -2
  62. package/dist-lib/lib/helpers/tool-intent.js +4 -2
  63. package/dist-lib/lib/helpers/tool-label.js +18 -9
  64. package/dist-lib/lib/hooks/built-in/arg-repair.js +23 -13
  65. package/dist-lib/lib/hooks/built-in/egress.js +2 -1
  66. package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
  67. package/dist-lib/lib/hooks/pipeline.d.ts +5 -4
  68. package/dist-lib/lib/hooks/pipeline.js +6 -3
  69. package/dist-lib/lib/hooks/run.js +12 -8
  70. package/dist-lib/lib/model-download-progress.js +10 -8
  71. package/dist-lib/lib/models/context.d.ts +1 -1
  72. package/dist-lib/lib/models/context.js +5 -1
  73. package/dist-lib/lib/models/custom-model-cache.d.ts +13 -0
  74. package/dist-lib/lib/models/custom-model-cache.js +70 -0
  75. package/dist-lib/lib/models/gguf-header.d.ts +31 -0
  76. package/dist-lib/lib/models/gguf-header.js +230 -0
  77. package/dist-lib/lib/models/idle-unload.d.ts +14 -0
  78. package/dist-lib/lib/models/idle-unload.js +51 -0
  79. package/dist-lib/lib/models/kv-cache.d.ts +3 -2
  80. package/dist-lib/lib/models/kv-cache.js +4 -3
  81. package/dist-lib/lib/models/llm-presets.d.ts +2 -2
  82. package/dist-lib/lib/models/llm-presets.js +4 -2
  83. package/dist-lib/lib/models/model-catalog-constants.js +3 -2
  84. package/dist-lib/lib/models/model-catalog.d.ts +19 -21
  85. package/dist-lib/lib/models/model-catalog.js +66 -33
  86. package/dist-lib/lib/models/model-delete.d.ts +4 -1
  87. package/dist-lib/lib/models/model-delete.js +30 -15
  88. package/dist-lib/lib/models/model-handle.js +2 -1
  89. package/dist-lib/lib/models/model-list.d.ts +14 -3
  90. package/dist-lib/lib/models/model-list.js +33 -6
  91. package/dist-lib/lib/models/model-pool.d.ts +44 -10
  92. package/dist-lib/lib/models/model-pool.js +47 -42
  93. package/dist-lib/lib/models/model-source.js +11 -6
  94. package/dist-lib/lib/models/music-catalog.d.ts +2 -2
  95. package/dist-lib/lib/models/nmt-catalog.d.ts +4 -3
  96. package/dist-lib/lib/models/nmt-catalog.js +10 -5
  97. package/dist-lib/lib/models/opencl-cache.d.ts +6 -1
  98. package/dist-lib/lib/models/opencl-cache.js +5 -3
  99. package/dist-lib/lib/models/sdk-faults.d.ts +11 -8
  100. package/dist-lib/lib/models/sdk-faults.js +9 -6
  101. package/dist-lib/lib/models/shards.d.ts +11 -0
  102. package/dist-lib/lib/models/shards.js +15 -0
  103. package/dist-lib/lib/models/tool-dialect.js +10 -5
  104. package/dist-lib/lib/no-redirect-fetch-bare.d.ts +3 -3
  105. package/dist-lib/lib/no-redirect-fetch-bare.js +1 -1
  106. package/dist-lib/lib/no-redirect-fetch-impl.js +6 -3
  107. package/dist-lib/lib/no-redirect-fetch-node.d.ts +1 -1
  108. package/dist-lib/lib/no-redirect-fetch-node.js +9 -9
  109. package/dist-lib/lib/office/index.d.ts +3 -2
  110. package/dist-lib/lib/office/python.d.ts +3 -2
  111. package/dist-lib/lib/office/python.js +2 -1
  112. package/dist-lib/lib/prompt.d.ts +5 -4
  113. package/dist-lib/lib/prompt.js +8 -4
  114. package/dist-lib/lib/queue.js +10 -5
  115. package/dist-lib/lib/resolution-detector.js +21 -11
  116. package/dist-lib/lib/rpc-session.js +2 -1
  117. package/dist-lib/lib/sdk-loader.js +2 -1
  118. package/dist-lib/lib/sdk-storage.js +4 -2
  119. package/dist-lib/lib/serve.js +128 -68
  120. package/dist-lib/lib/spawn.js +7 -4
  121. package/dist-lib/lib/tmp-path.d.ts +7 -6
  122. package/dist-lib/lib/tool-call-display.d.ts +2 -2
  123. package/dist-lib/lib/tools/create-documents.js +18 -10
  124. package/dist-lib/lib/tools/edit-documents.js +23 -13
  125. package/dist-lib/lib/tools/edit-image.d.ts +2 -2
  126. package/dist-lib/lib/tools/edit-image.js +60 -36
  127. package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +10 -10
  128. package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +17 -11
  129. package/dist-lib/lib/tools/exec/adapters/python/attachments.js +53 -40
  130. package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +2 -2
  131. package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +60 -32
  132. package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.d.ts +33 -22
  133. package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.js +58 -29
  134. package/dist-lib/lib/tools/exec/adapters/python/interrupt-timer.d.ts +2 -2
  135. package/dist-lib/lib/tools/exec/adapters/python/loader.js +23 -12
  136. package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +13 -11
  137. package/dist-lib/lib/tools/exec/adapters/python/memfs.js +10 -5
  138. package/dist-lib/lib/tools/exec/adapters/python/net-shim.js +3 -1
  139. package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +6 -4
  140. package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +20 -10
  141. package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +2 -2
  142. package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +14 -7
  143. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +41 -34
  144. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +316 -166
  145. package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +9 -8
  146. package/dist-lib/lib/tools/exec/adapters/python/run-session.js +56 -28
  147. package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +8 -10
  148. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +22 -11
  149. package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +3 -2
  150. package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +41 -26
  151. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +27 -18
  152. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +2 -2
  153. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +14 -13
  154. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +4 -4
  155. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +10 -5
  156. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +4 -4
  157. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +2 -1
  158. package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +6 -1
  159. package/dist-lib/lib/tools/exec/obsidian/cli-process.js +8 -5
  160. package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +6 -6
  161. package/dist-lib/lib/tools/exec/obsidian/cli.js +4 -4
  162. package/dist-lib/lib/tools/exec/obsidian/command.d.ts +3 -2
  163. package/dist-lib/lib/tools/exec/obsidian/command.js +6 -3
  164. package/dist-lib/lib/tools/exec/obsidian/output.js +2 -1
  165. package/dist-lib/lib/tools/exec/obsidian/route.d.ts +4 -6
  166. package/dist-lib/lib/tools/exec/obsidian/route.js +17 -11
  167. package/dist-lib/lib/tools/exec/obsidian/safe-path.js +2 -1
  168. package/dist-lib/lib/tools/exec/obsidian/vault-create.js +15 -7
  169. package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +2 -2
  170. package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +20 -10
  171. package/dist-lib/lib/tools/exec/obsidian/vault-read.js +20 -13
  172. package/dist-lib/lib/tools/exec/obsidian/vault-write.js +24 -12
  173. package/dist-lib/lib/tools/exec/runner.d.ts +14 -14
  174. package/dist-lib/lib/tools/exec/runner.js +5 -3
  175. package/dist-lib/lib/tools/exec/scope.js +52 -28
  176. package/dist-lib/lib/tools/exec/shell-argv.js +31 -18
  177. package/dist-lib/lib/tools/exec/shell-guidance.d.ts +6 -1
  178. package/dist-lib/lib/tools/exec/shell-guidance.js +35 -20
  179. package/dist-lib/lib/tools/exec/video-tools.js +2 -2
  180. package/dist-lib/lib/tools/exec.d.ts +6 -8
  181. package/dist-lib/lib/tools/exec.js +113 -54
  182. package/dist-lib/lib/tools/file-glob.d.ts +4 -5
  183. package/dist-lib/lib/tools/file-glob.js +16 -11
  184. package/dist-lib/lib/tools/fs/glob.js +13 -18
  185. package/dist-lib/lib/tools/fs/remote-protocol.d.ts +10 -10
  186. package/dist-lib/lib/tools/fs/remote.d.ts +3 -2
  187. package/dist-lib/lib/tools/fs/remote.js +13 -7
  188. package/dist-lib/lib/tools/fs/scope.d.ts +8 -3
  189. package/dist-lib/lib/tools/fs/scope.js +20 -12
  190. package/dist-lib/lib/tools/fs/walk.js +6 -3
  191. package/dist-lib/lib/tools/fs/write.d.ts +3 -2
  192. package/dist-lib/lib/tools/generate-image.d.ts +11 -9
  193. package/dist-lib/lib/tools/generate-image.js +73 -37
  194. package/dist-lib/lib/tools/generate-music.d.ts +22 -11
  195. package/dist-lib/lib/tools/generate-music.js +79 -48
  196. package/dist-lib/lib/tools/grep.js +66 -41
  197. package/dist-lib/lib/tools/http-request/encode-fields.js +18 -9
  198. package/dist-lib/lib/tools/http-request/{utils.js → request.js} +20 -11
  199. package/dist-lib/lib/tools/http-request/truncate-response.js +57 -46
  200. package/dist-lib/lib/tools/http-request.d.ts +1 -1
  201. package/dist-lib/lib/tools/http-request.js +33 -18
  202. package/dist-lib/lib/tools/mcp/protocol.d.ts +53 -0
  203. package/dist-lib/lib/tools/mcp/{utils.js → protocol.js} +45 -23
  204. package/dist-lib/lib/tools/mcp-call.d.ts +1 -1
  205. package/dist-lib/lib/tools/mcp-call.js +37 -16
  206. package/dist-lib/lib/tools/operations/builders.js +10 -6
  207. package/dist-lib/lib/tools/operations/compile.js +20 -10
  208. package/dist-lib/lib/tools/operations/decoders.js +12 -6
  209. package/dist-lib/lib/tools/operations/gmail-message.js +3 -2
  210. package/dist-lib/lib/tools/outbound-guard.d.ts +4 -3
  211. package/dist-lib/lib/tools/outbound-guard.js +14 -8
  212. package/dist-lib/lib/tools/private-ip.js +8 -7
  213. package/dist-lib/lib/tools/rag-search.js +14 -7
  214. package/dist-lib/lib/tools/read-files.js +23 -20
  215. package/dist-lib/lib/tools/skill.js +19 -10
  216. package/dist-lib/lib/tools/skills/auth-resolver.d.ts +11 -18
  217. package/dist-lib/lib/tools/skills/auth-resolver.js +30 -18
  218. package/dist-lib/lib/tools/skills/bin-check.d.ts +3 -2
  219. package/dist-lib/lib/tools/skills/bin-check.js +10 -3
  220. package/dist-lib/lib/tools/skills/bundled-dir.js +20 -10
  221. package/dist-lib/lib/tools/skills/bundled-hash.d.ts +3 -2
  222. package/dist-lib/lib/tools/skills/bundled-hash.js +6 -1
  223. package/dist-lib/lib/tools/skills/catalog.d.ts +3 -2
  224. package/dist-lib/lib/tools/skills/catalog.js +33 -28
  225. package/dist-lib/lib/tools/skills/cli-argv.d.ts +3 -2
  226. package/dist-lib/lib/tools/skills/cli-argv.js +55 -52
  227. package/dist-lib/lib/tools/skills/cli-schema-check.js +21 -10
  228. package/dist-lib/lib/tools/skills/cli-schema-load.js +28 -20
  229. package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +6 -6
  230. package/dist-lib/lib/tools/skills/cli-schema.js +2 -1
  231. package/dist-lib/lib/tools/skills/credential-check.d.ts +6 -3
  232. package/dist-lib/lib/tools/skills/credential-check.js +24 -12
  233. package/dist-lib/lib/tools/skills/credential-grants.js +1 -6
  234. package/dist-lib/lib/tools/skills/credential-health.d.ts +5 -1
  235. package/dist-lib/lib/tools/skills/credential-health.js +5 -3
  236. package/dist-lib/lib/tools/skills/frontmatter-parser.js +10 -5
  237. package/dist-lib/lib/tools/skills/manifest-parse.js +84 -64
  238. package/dist-lib/lib/tools/skills/mention.js +7 -6
  239. package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +2 -2
  240. package/dist-lib/lib/tools/skills/obsidian-readiness.js +11 -3
  241. package/dist-lib/lib/tools/skills/overlay-crud.d.ts +6 -4
  242. package/dist-lib/lib/tools/skills/overlay-crud.js +12 -6
  243. package/dist-lib/lib/tools/skills/overlay-dir.js +4 -2
  244. package/dist-lib/lib/tools/skills/overlay-watch.d.ts +3 -2
  245. package/dist-lib/lib/tools/skills/overlay-watch.js +8 -4
  246. package/dist-lib/lib/tools/skills/setup-routes.js +1 -3
  247. package/dist-lib/lib/tools/skills/skill-settings.js +4 -1
  248. package/dist-lib/lib/tools/skills/skill-state.d.ts +6 -11
  249. package/dist-lib/lib/tools/skills/skill-state.js +48 -29
  250. package/dist-lib/lib/tools/skills/tool-grants.js +6 -3
  251. package/dist-lib/lib/tools/toolsets.js +2 -1
  252. package/dist-lib/lib/tools/translate.d.ts +4 -5
  253. package/dist-lib/lib/tools/translate.js +31 -14
  254. package/dist-lib/lib/tools/url-guard.js +2 -1
  255. package/dist-lib/lib/tools/weather-lookup/place.js +8 -4
  256. package/dist-lib/lib/tools/weather-lookup/report.d.ts +7 -1
  257. package/dist-lib/lib/tools/weather-lookup/report.js +46 -9
  258. package/dist-lib/lib/tools/weather-lookup.js +18 -12
  259. package/dist-lib/lib/tools/web-fetch.js +47 -24
  260. package/dist-lib/lib/tools/web-search.js +8 -3
  261. package/dist-lib/lib/validating-lookup.d.ts +4 -4
  262. package/dist-lib/lib/wav-encode.d.ts +1 -1
  263. package/dist-lib/lib/wav-encode.js +11 -10
  264. package/dist-lib/lib/web-fetch/embedded-state.js +24 -12
  265. package/dist-lib/lib/web-fetch/extract.js +4 -2
  266. package/dist-lib/lib/web-fetch/images.js +8 -4
  267. package/dist-lib/lib/web-fetch/video.d.ts +2 -2
  268. package/dist-lib/lib/web-fetch/video.js +8 -4
  269. package/dist-lib/lib/web-search/engine-registry.d.ts +2 -2
  270. package/dist-lib/lib/web-search/engines/aol.js +1 -1
  271. package/dist-lib/lib/web-search/engines/bing.js +1 -1
  272. package/dist-lib/lib/web-search/engines/brave.js +4 -1
  273. package/dist-lib/lib/web-search/engines/duckduckgo.js +3 -2
  274. package/dist-lib/lib/web-search/engines/google.js +7 -3
  275. package/dist-lib/lib/web-search/engines/wikipedia.js +5 -4
  276. package/dist-lib/lib/web-search/engines/yahoo.js +1 -1
  277. package/dist-lib/lib/web-search/fetch-html.d.ts +5 -4
  278. package/dist-lib/lib/web-search/fetch-html.js +13 -7
  279. package/dist-lib/lib/web-search/orchestrator.d.ts +9 -5
  280. package/dist-lib/lib/web-search/orchestrator.js +3 -3
  281. package/dist-lib/lib/wire.d.ts +3 -2
  282. package/dist-lib/lib/wire.js +23 -15
  283. package/dist-lib/schema/baseline.js +10 -5
  284. package/dist-lib/schema/build.js +2 -1
  285. package/dist-lib/schema/harness.d.ts +15 -2
  286. package/dist-lib/schema/harness.js +55 -2
  287. package/dist-lib/schema/release-tags.d.ts +3 -2
  288. package/dist-lib/schema/release-tags.js +6 -3
  289. package/dist-lib/spec/bind.js +6 -0
  290. package/dist-lib/spec/calls.js +2 -0
  291. package/dist-lib/spec/hrpc/hrpc.json +26 -0
  292. package/dist-lib/spec/hrpc/index.js +27 -3
  293. package/dist-lib/spec/hrpc/messages.js +207 -8
  294. package/dist-lib/spec/hyperschema/index.js +207 -8
  295. package/dist-lib/spec/hyperschema/schema.json +165 -1
  296. package/dist-lib/spec/hyperschema/types.d.ts +42 -1
  297. package/package.json +13 -14
  298. package/worker/harness-sidecar.mjs +16 -22
  299. package/worker/stow-entry.mjs +7 -4
  300. package/dist-lib/lib/tools/mcp/utils.d.ts +0 -47
  301. /package/dist-lib/lib/tools/http-request/{utils.d.ts → request.d.ts} +0 -0
@@ -5,8 +5,9 @@ function isTurnBoundary(message) {
5
5
  }
6
6
  export function contextCandidates(history) {
7
7
  const { prefix, turns } = splitTurns(history);
8
- if (!turns.length)
8
+ if (!turns.length) {
9
9
  return [{ history, droppedTurns: 0 }];
10
+ }
10
11
  const maxDropped = Math.max(0, turns.length - 1);
11
12
  const candidates = dropCounts(maxDropped).map((droppedTurns) => ({
12
13
  history: droppedTurns ? [...prefix, ...turns.slice(droppedTurns).flat()] : history,
@@ -17,57 +18,60 @@ export function contextCandidates(history) {
17
18
  }
18
19
  function splitTurns(history) {
19
20
  const firstUser = history.findIndex(isTurnBoundary);
20
- if (firstUser === -1)
21
+ if (firstUser === -1) {
21
22
  return { prefix: history, turns: [] };
23
+ }
22
24
  const prefix = history.slice(0, firstUser);
23
25
  const starts = [];
24
- for (let i = firstUser; i < history.length; i++) {
25
- if (isTurnBoundary(history[i]))
26
+ for (const [i, message] of history.entries()) {
27
+ if (i >= firstUser && isTurnBoundary(message)) {
26
28
  starts.push(i);
29
+ }
27
30
  }
28
31
  const turns = starts.map((start, index) => history.slice(start, starts[index + 1]));
29
32
  return { prefix, turns };
30
33
  }
31
34
  function dropCounts(max) {
32
35
  const counts = [0];
33
- for (let step = 1; counts[counts.length - 1] < max; step *= 2) {
36
+ let last = 0;
37
+ for (let step = 1; last < max; step *= 2) {
34
38
  const next = Math.min(max, step);
35
- if (next !== counts[counts.length - 1])
36
- counts.push(next);
39
+ if (next === last) {
40
+ continue;
41
+ }
42
+ counts.push(next);
43
+ last = next;
37
44
  }
38
45
  return counts;
39
46
  }
40
47
  function appendToolCompactions(candidates) {
41
48
  const last = candidates[candidates.length - 1];
42
- if (!last)
49
+ if (!last) {
43
50
  return;
51
+ }
44
52
  const tools = compactableTools(last.history);
45
53
  let history = last.history;
46
54
  while (true) {
47
55
  const selected = longestTool(tools);
48
- if (!selected)
56
+ if (!selected) {
49
57
  return;
58
+ }
50
59
  selected.target = Math.max(TOOL_RESULT_TRUNCATION_MARKER.length, Math.floor(selected.target / 2));
51
60
  history = history.map(compactTool.bind(null, selected));
52
61
  candidates.push({ history, droppedTurns: last.droppedTurns });
53
62
  }
54
63
  }
55
64
  function compactableTools(history) {
56
- let newestUser = -1;
57
- for (let index = history.length - 1; index >= 0; index--) {
58
- if (!isTurnBoundary(history[index]))
59
- continue;
60
- newestUser = index;
61
- break;
62
- }
63
- if (newestUser === -1)
65
+ const newestUser = history.findLastIndex(isTurnBoundary);
66
+ if (newestUser === -1) {
64
67
  return [];
68
+ }
65
69
  const tools = [];
66
- for (let index = newestUser + 1; index < history.length; index++) {
67
- const message = history[index];
68
- if (message.role !== 'tool' || message.content.length <= TOOL_RESULT_TRUNCATION_MARKER.length) {
70
+ for (const [index, message] of history.entries()) {
71
+ if (index <= newestUser || message.role !== 'tool')
72
+ continue;
73
+ if (message.content.length <= TOOL_RESULT_TRUNCATION_MARKER.length)
69
74
  continue;
70
- }
71
75
  tools.push({ index, original: message.content, target: message.content.length });
72
76
  }
73
77
  return tools;
@@ -1,9 +1,11 @@
1
1
  import type { HarnessCapabilityProfile } from '../spec/hyperschema/types.d.ts';
2
2
  import type { ApproveFn, AskUserFn, AttachFn, FetchAttachmentFn, ProgressFn, RagSearchFn, ResourceDescriptor, ResponseFormat } from './capabilities/completion.ts';
3
3
  import type { KvCacheDeletionResult } from './capabilities/kv-cache.ts';
4
+ import type { ModelSourcePreview, PreviewModelSourceContext } from './capabilities/preview-model-source.ts';
4
5
  import type { MemoryBudget } from './hardware/memory-budget.ts';
5
6
  import type { EmbedDevice } from './models/embed-config.ts';
6
7
  import type { LlmGenerationParams } from './models/llm-presets.ts';
8
+ import type { CustomModelEntry } from './models/model-catalog.ts';
7
9
  import type { DeleteModelSummary } from './models/model-delete.ts';
8
10
  import type { ListModelsOptions, ModelInfo } from './models/model-list.ts';
9
11
  import type { ToolCatalogEntry } from './tools/catalog.ts';
@@ -163,6 +165,24 @@ export interface CapabilityInfo {
163
165
  recommendedModelName: string;
164
166
  memoryBudget?: MemoryBudget;
165
167
  }
168
+ export interface CredentialEntry {
169
+ key: string;
170
+ token?: string | null;
171
+ expiresAt?: number | null;
172
+ agentId?: string | null;
173
+ skill?: string | null;
174
+ }
175
+ export interface SkillsOptions {
176
+ readonly refresh?: boolean;
177
+ readonly skipCredentialProbe?: boolean;
178
+ }
179
+ export interface SkillWriteResult {
180
+ ok: boolean;
181
+ }
182
+ export interface InfraModel {
183
+ name: string;
184
+ addon: string;
185
+ }
166
186
  export interface HarnessContract {
167
187
  completion(context: CompletionContext): AsyncIterable<HarnessEvent>;
168
188
  invoke?(context: InvokeContext): AsyncIterable<HarnessEvent>;
@@ -181,24 +201,16 @@ export interface HarnessContract {
181
201
  suspend?(): Promise<void> | void;
182
202
  wakeup?(): Promise<void> | void;
183
203
  resume?(): Promise<void> | void;
184
- skills?(agentId?: string | null, modelName?: string | null, options?: {
185
- readonly refresh?: boolean;
186
- readonly skipCredentialProbe?: boolean;
187
- }): Promise<ResolvedSkillCatalogEntry[]>;
204
+ skills?(agentId?: string | null, modelName?: string | null, options?: SkillsOptions): Promise<ResolvedSkillCatalogEntry[]>;
188
205
  tools?(): Promise<ToolCatalogEntry[]>;
189
- setCredentials?(entries: ReadonlyArray<{
190
- key: string;
191
- token?: string | null;
192
- expiresAt?: number | null;
193
- agentId?: string | null;
194
- skill?: string | null;
195
- }>): void | Promise<void>;
206
+ setCredentials?(entries: ReadonlyArray<CredentialEntry>): void | Promise<void>;
196
207
  setSkillSettings?(entries: ReadonlyArray<{
197
208
  skill: string;
198
209
  key: string;
199
210
  value: string;
200
211
  agentId?: string | null;
201
212
  }>): void | Promise<void>;
213
+ setModelIdleTimeout?(ms: number): void | Promise<void>;
202
214
  listManagedSkills?(): Promise<ManagedSkill[]>;
203
215
  readSkillFile?(name: string): Promise<SkillFileContent | null>;
204
216
  writeSkillFile?(name: string, content: string): Promise<{
@@ -215,15 +227,9 @@ export interface HarnessContract {
215
227
  deleteModel?(name: string): Promise<DeleteModelSummary>;
216
228
  clearKvCache?(): Promise<KvCacheDeletionResult>;
217
229
  deleteKvCache?(kvCacheKey: string): Promise<KvCacheDeletionResult>;
218
- infraModels?(profile: string): Promise<ReadonlyArray<{
219
- name: string;
220
- addon: string;
221
- }>>;
222
- setCustomModels?(entries: ReadonlyArray<{
223
- name: string;
224
- src: string;
225
- projectionSrc?: string;
226
- }>): void | Promise<void>;
230
+ infraModels?(profile: string): Promise<ReadonlyArray<InfraModel>>;
231
+ setCustomModels?(entries: ReadonlyArray<CustomModelEntry>): void | Promise<void>;
232
+ previewModelSource?(context: PreviewModelSourceContext): Promise<ModelSourcePreview>;
227
233
  capability?(): Promise<CapabilityInfo>;
228
234
  diagnostics?(): HarnessDiagnostics;
229
235
  }
@@ -4,18 +4,18 @@ export declare function diagramRepairPromptCount(content: string, parentRunId?:
4
4
  export declare function isDiagramRepairPrompt(content: string): boolean;
5
5
  export declare function completeMermaidDiagramCount(content: string): number;
6
6
  export declare function diagramRepairAccepted(text: string): boolean;
7
- type DiagramRepairRecord = {
7
+ interface DiagramRepairRecord {
8
8
  readonly id: string;
9
9
  readonly seq: number;
10
10
  readonly runId?: string | null;
11
11
  readonly parentId?: string | null;
12
- };
13
- export type DiagramRepairLink = {
12
+ }
13
+ export interface DiagramRepairLink {
14
14
  readonly expectedCount: number;
15
15
  readonly parentId: string;
16
16
  readonly promptId: string;
17
17
  readonly promptText: string;
18
18
  readonly runId: string;
19
- };
19
+ }
20
20
  export declare function diagramRepairLinks<T extends DiagramRepairRecord>(records: ReadonlyArray<T>, textOf: (record: T) => string | null): ReadonlyArray<DiagramRepairLink>;
21
21
  export {};
@@ -3,8 +3,9 @@ export const DIAGRAM_REPAIR_PROMPT_SUFFIX = 'Rewrite the complete previous answe
3
3
  'Common fixes: put every label with spaces or punctuation in double quotes like A["Send (HTTP)"]; never use lowercase end as a node label - write "End"; the first line inside the fence must be the diagram type; close the fence before any prose - never leave a sentence inside it; give every node a unique id.';
4
4
  export function diagramRepairPromptCount(content, parentRunId) {
5
5
  const match = /^<!-- qvac:diagram-repair:(\d+):([^\s>]+) -->\n(\d+) Mermaid diagram(?:s)? in your previous answer fail(?:s)? to render\.\n/.exec(content);
6
- if (!match || !content.endsWith(`\n\n${DIAGRAM_REPAIR_PROMPT_SUFFIX}`))
6
+ if (!match || !content.endsWith(`\n\n${DIAGRAM_REPAIR_PROMPT_SUFFIX}`)) {
7
7
  return null;
8
+ }
8
9
  const expected = Number(match[1]);
9
10
  return Number.isSafeInteger(expected) &&
10
11
  expected > 0 &&
@@ -31,8 +32,9 @@ export function diagramRepairLinks(records, textOf) {
31
32
  if (!child.runId || !child.parentId)
32
33
  return [];
33
34
  const parent = byId.get(child.parentId);
34
- if (!parent?.runId)
35
+ if (!parent?.runId) {
35
36
  return [];
37
+ }
36
38
  const prompt = [...ordered]
37
39
  .reverse()
38
40
  .find((candidate) => candidate.seq > parent.seq &&
@@ -41,8 +43,9 @@ export function diagramRepairLinks(records, textOf) {
41
43
  diagramRepairPromptCount(textOf(candidate) ?? '', parent.runId ?? undefined) !== null);
42
44
  const promptText = prompt ? textOf(prompt) : null;
43
45
  const expectedCount = diagramRepairPromptCount(promptText ?? '', parent.runId);
44
- if (prompt)
46
+ if (prompt) {
45
47
  used.add(prompt.id);
48
+ }
46
49
  return prompt && promptText && expectedCount
47
50
  ? [
48
51
  {
@@ -1,5 +1,6 @@
1
1
  import type { AbortSignal } from 'bare-abort-controller';
2
2
  export { closePythonWorker as closeDocxWorker } from '../tools/exec/adapters/python/worker/client.ts';
3
- export declare function extractDocxText(bytes: Uint8Array, fileName: string, options?: {
3
+ export interface DocxExtractOptions {
4
4
  readonly signal?: AbortSignal;
5
- }): Promise<string>;
5
+ }
6
+ export declare function extractDocxText(bytes: Uint8Array, fileName: string, options?: DocxExtractOptions): Promise<string>;
@@ -1,2 +1,3 @@
1
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
1
2
  export declare function errorMessage(err: unknown): string;
2
3
  export declare function errorCode(err: unknown): string | undefined;
@@ -1,3 +1,6 @@
1
+ export function isRecord(value) {
2
+ return typeof value === 'object' && value !== null;
3
+ }
1
4
  export function errorMessage(err) {
2
5
  return err instanceof Error ? err.message : String(err);
3
6
  }
@@ -13,8 +13,9 @@ function pickTier(availableBytes) {
13
13
  return 'xhigh';
14
14
  if (availableBytes >= 30 * GIB)
15
15
  return 'high';
16
- if (availableBytes >= 8 * GIB)
16
+ if (availableBytes >= 8 * GIB) {
17
17
  return 'mid';
18
+ }
18
19
  return 'low';
19
20
  }
20
21
  function tierProfile(budget) {
@@ -38,8 +39,9 @@ function recommend(budget) {
38
39
  async function probeSysfs(reads) {
39
40
  for (const path of SYSFS_VRAM_PATHS) {
40
41
  const raw = await reads.readFile(path);
41
- if (!raw)
42
+ if (!raw) {
42
43
  continue;
44
+ }
43
45
  const bytes = Number.parseInt(raw.trim(), 10);
44
46
  if (!Number.isNaN(bytes) && bytes > 0) {
45
47
  return { totalBytes: bytes, availableBytes: bytes, source: 'vram' };
@@ -50,25 +52,31 @@ async function probeSysfs(reads) {
50
52
  async function probeDesktop(reads) {
51
53
  const ram = reads.totalmem();
52
54
  const addon = probeWithAddon(await reads.readGpuStats(), ram);
53
- if (addon && addon.source === 'vram')
55
+ if (addon && addon.source === 'vram') {
54
56
  return addon;
57
+ }
55
58
  const nvidia = await reads.run('nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits');
56
59
  const nvidiaBudget = nvidia ? parseNvidiaSmiOutput(nvidia) : null;
57
- if (nvidiaBudget)
60
+ if (nvidiaBudget) {
58
61
  return nvidiaBudget;
62
+ }
59
63
  const rocm = await reads.run('rocm-smi --showmeminfo vram');
60
64
  const rocmBudget = rocm ? parseRocmSmiOutput(rocm) : null;
61
- if (rocmBudget)
65
+ if (rocmBudget) {
62
66
  return rocmBudget;
67
+ }
63
68
  const sysfs = await probeSysfs(reads);
64
- if (sysfs)
69
+ if (sysfs) {
65
70
  return sysfs;
71
+ }
66
72
  const registry = await reads.run(`powershell -Command "${WINDOWS_REGISTRY_QUERY}"`);
67
73
  const registryBudget = registry ? parseWindowsRegistryOutput(registry, ram) : null;
68
- if (registryBudget)
74
+ if (registryBudget) {
69
75
  return registryBudget;
70
- if (addon)
76
+ }
77
+ if (addon) {
71
78
  return addon;
79
+ }
72
80
  return { ...sharedRamBudget(ram), source: 'no-gpu' };
73
81
  }
74
82
  async function isPixel(reads) {
@@ -77,10 +85,12 @@ async function isPixel(reads) {
77
85
  }
78
86
  async function probeMemoryBudget(reads) {
79
87
  const os = reads.platform();
80
- if (os === 'android' || os === 'ios')
88
+ if (os === 'android' || os === 'ios') {
81
89
  return mobileBudget(reads.totalmem(), await isPixel(reads));
82
- if (os === 'darwin')
90
+ }
91
+ if (os === 'darwin') {
83
92
  return sharedRamBudget(reads.totalmem());
93
+ }
84
94
  return probeDesktop(reads);
85
95
  }
86
96
  function forcedProfile() {
@@ -19,14 +19,17 @@ const INTEGRATED_GPU = [
19
19
  ];
20
20
  const SOFTWARE_GPU = [/llvmpipe/i, /swrast/i, /mesa/i];
21
21
  export function classifyGpu(name) {
22
- for (const re of DISCRETE_GPU)
22
+ for (const re of DISCRETE_GPU) {
23
23
  if (re.test(name))
24
24
  return 'discrete';
25
- for (const re of INTEGRATED_GPU)
25
+ }
26
+ for (const re of INTEGRATED_GPU) {
26
27
  if (re.test(name))
27
28
  return 'integrated';
28
- for (const re of SOFTWARE_GPU)
29
+ }
30
+ for (const re of SOFTWARE_GPU) {
29
31
  if (re.test(name))
30
32
  return 'software';
33
+ }
31
34
  return 'integrated';
32
35
  }
@@ -12,8 +12,9 @@ const StatsSchema = z.object({
12
12
  function classifyBestDevice(devices, systemRamBytes) {
13
13
  for (const device of devices) {
14
14
  const cls = classifyGpu(device.name);
15
- if (cls === 'software')
15
+ if (cls === 'software') {
16
16
  continue;
17
+ }
17
18
  if (cls === 'discrete') {
18
19
  const vram = device.videoMemoryBytes;
19
20
  if (vram > systemRamBytes * IGPU_LIE_THRESHOLD) {
@@ -26,15 +27,18 @@ function classifyBestDevice(devices, systemRamBytes) {
26
27
  }
27
28
  export function probeWithAddon(rawStats, systemRamBytes) {
28
29
  const parsed = StatsSchema.safeParse(rawStats);
29
- if (!parsed.success)
30
+ if (!parsed.success) {
30
31
  return null;
32
+ }
31
33
  const devices = parsed.data.gpu?.devices ?? [];
32
- if (devices.length === 0)
34
+ if (devices.length === 0) {
33
35
  return null;
36
+ }
34
37
  const totalRamBytes = parsed.data.memory?.totalBytes ?? systemRamBytes;
35
38
  const best = classifyBestDevice(devices, totalRamBytes);
36
- if (best)
39
+ if (best) {
37
40
  return best;
41
+ }
38
42
  if (devices.every((device) => classifyGpu(device.name) === 'software')) {
39
43
  return { ...sharedRamBudget(totalRamBytes), source: 'software' };
40
44
  }
@@ -1,3 +1,4 @@
1
+ import b4a from 'b4a';
1
2
  import { spawn } from 'child_process';
2
3
  import os from 'os';
3
4
  import { readSystemStats } from '#hw-gpu-stats';
@@ -11,8 +12,9 @@ export function runGpuProbeIfRequested() {
11
12
  }
12
13
  export function parseGpuProbeOutput(output) {
13
14
  const line = output.trim().split('\n').at(-1) ?? '';
14
- if (line.length === 0)
15
+ if (line.length === 0) {
15
16
  return null;
17
+ }
16
18
  try {
17
19
  const parsed = JSON.parse(line);
18
20
  return typeof parsed === 'object' ? parsed : null;
@@ -32,7 +34,7 @@ export function spawnGpuProbe(entry = Bare.argv[1]) {
32
34
  resolve({ ok: false, stats: null });
33
35
  }, TIMEOUT_MS);
34
36
  child.stdout?.on('data', (chunk) => {
35
- output += Buffer.from(chunk).toString();
37
+ output += b4a.toString(chunk);
36
38
  });
37
39
  child.stderr?.on('data', () => { });
38
40
  child.on('error', () => {
@@ -1,22 +1,21 @@
1
1
  const os = require('os')
2
2
 
3
- // loaded on first read: the addon drags the graphics stack (and on Linux a
4
- // second LLVM) into whichever process imports it
3
+ // lazy: the addon drags the graphics stack (and on Linux a second LLVM) into its importer
5
4
  let GPUInfo
6
5
 
7
- // Shaped for probeWithAddon (gpu-probe-addon.ts): the probe only wants each
8
- // device's name and VRAM total, plus system RAM to catch integrated-GPU lies.
6
+ // system RAM is here to catch integrated-GPU lies
9
7
  exports.readSystemStats = function readSystemStats() {
10
8
  try {
11
9
  GPUInfo ??= require('bare-gpu-info')
12
10
  const info = new GPUInfo()
13
11
  try {
14
- const devices = []
15
- for (const gpu of info) {
16
- if (typeof gpu.memory !== 'number' || !gpu.name) continue
17
- devices.push({ name: gpu.name, videoMemoryBytes: gpu.memory })
12
+ const devices = [...info]
13
+ .filter((gpu) => typeof gpu.memory === 'number' && gpu.name)
14
+ .map((gpu) => ({ name: gpu.name, videoMemoryBytes: gpu.memory }))
15
+ if (devices.length === 0) {
16
+ return null
18
17
  }
19
- if (devices.length === 0) return null
18
+
20
19
  return { memory: { totalBytes: os.totalmem() }, gpu: { devices } }
21
20
  } finally {
22
21
  info.destroy()
@@ -7,25 +7,29 @@ export const IGPU_LIE_THRESHOLD = 0.9;
7
7
  export function parseNvidiaSmiOutput(stdout) {
8
8
  const firstLine = stdout.split('\n')[0] ?? '';
9
9
  const mib = Number.parseInt(firstLine, 10);
10
- if (Number.isNaN(mib) || mib <= 0)
10
+ if (Number.isNaN(mib) || mib <= 0) {
11
11
  return null;
12
+ }
12
13
  const bytes = mib * 1024 * 1024;
13
14
  return { totalBytes: bytes, availableBytes: bytes, source: 'vram', gpuClass: 'discrete' };
14
15
  }
15
16
  export function parseRocmSmiOutput(stdout) {
16
17
  const match = /Total.*?:\s*(\d+)/i.exec(stdout);
17
- if (!match)
18
+ if (!match) {
18
19
  return null;
20
+ }
19
21
  const bytes = Number.parseInt(match[1] ?? '', 10);
20
- if (Number.isNaN(bytes) || bytes <= 0)
22
+ if (Number.isNaN(bytes) || bytes <= 0) {
21
23
  return null;
24
+ }
22
25
  return { totalBytes: bytes, availableBytes: bytes, source: 'vram' };
23
26
  }
24
27
  export function parseWindowsRegistryOutput(stdout, systemRamBytes) {
25
28
  const firstLine = stdout.split('\n')[0] ?? '';
26
29
  const bytes = Number.parseInt(firstLine, 10);
27
- if (Number.isNaN(bytes) || bytes <= 0)
30
+ if (Number.isNaN(bytes) || bytes <= 0) {
28
31
  return null;
32
+ }
29
33
  if (bytes > systemRamBytes * IGPU_LIE_THRESHOLD) {
30
34
  return { ...sharedRamBudget(systemRamBytes), source: 'integrated' };
31
35
  }
@@ -7,14 +7,16 @@ export async function* bufferBurst(tokens, ms) {
7
7
  continue;
8
8
  }
9
9
  if (Date.now() >= deadline) {
10
- if (burst)
10
+ if (burst) {
11
11
  yield burst;
12
+ }
12
13
  burst = null;
13
14
  yield token;
14
15
  continue;
15
16
  }
16
17
  burst += token;
17
18
  }
18
- if (burst)
19
+ if (burst) {
19
20
  yield burst;
21
+ }
20
22
  }
@@ -19,14 +19,16 @@ export async function* stopAtControlToken(tokens, onStop) {
19
19
  const safe = scanner({ stop: STOP_MARKERS });
20
20
  for await (const token of tokens) {
21
21
  const shown = safe.push(token);
22
- if (shown)
22
+ if (shown) {
23
23
  yield shown;
24
+ }
24
25
  if (safe.stopped !== null) {
25
26
  onStop?.(safe.stopped);
26
27
  return;
27
28
  }
28
29
  }
29
30
  const rest = safe.flush();
30
- if (rest)
31
+ if (rest) {
31
32
  yield rest;
33
+ }
32
34
  }
@@ -1,6 +1,6 @@
1
- export type JoinGuard = {
1
+ export interface JoinGuard {
2
2
  readonly push: (text: string) => string;
3
3
  readonly cut: () => void;
4
4
  readonly flush: () => string;
5
- };
5
+ }
6
6
  export declare function createJoinGuard(markers: readonly string[]): JoinGuard;
@@ -30,8 +30,9 @@ export function createJoinGuard(markers) {
30
30
  function mend(text, at, markers) {
31
31
  for (;;) {
32
32
  const found = spanning(text, at, markers);
33
- if (found === null)
33
+ if (found === null) {
34
34
  return { text, at };
35
+ }
35
36
  text = text.slice(0, found.index) + text.slice(found.index + found.marker.length);
36
37
  at = found.index;
37
38
  }
@@ -39,8 +40,9 @@ function mend(text, at, markers) {
39
40
  function spanning(text, at, markers) {
40
41
  for (const marker of markers) {
41
42
  const index = text.indexOf(marker, Math.max(0, at - marker.length + 1));
42
- if (index !== -1 && index < at)
43
+ if (index !== -1 && index < at) {
43
44
  return { index, marker };
45
+ }
44
46
  }
45
47
  return null;
46
48
  }
@@ -5,8 +5,9 @@ export function createLoadStall(ms, message) {
5
5
  rejectStall = reject;
6
6
  });
7
7
  const arm = () => {
8
- if (timer !== null)
8
+ if (timer !== null) {
9
9
  clearTimeout(timer);
10
+ }
10
11
  timer = setTimeout(() => {
11
12
  rejectStall?.(new Error(message));
12
13
  }, ms);
@@ -15,8 +16,9 @@ export function createLoadStall(ms, message) {
15
16
  return {
16
17
  bump: arm,
17
18
  clear: () => {
18
- if (timer !== null)
19
+ if (timer !== null) {
19
20
  clearTimeout(timer);
21
+ }
20
22
  timer = null;
21
23
  },
22
24
  promise
@@ -1,5 +1,5 @@
1
- export type MarkupStreamFilter = {
1
+ export interface MarkupStreamFilter {
2
2
  readonly push: (token: string) => string;
3
3
  readonly flush: () => string;
4
- };
4
+ }
5
5
  export declare function createMarkupStreamFilter(): MarkupStreamFilter;
@@ -22,8 +22,9 @@ export function createMarkupStreamFilter() {
22
22
  for (;;) {
23
23
  const step = state.closer ? consumeSuppressed(state) : emitUntilOpener(state);
24
24
  out += step.out;
25
- if (step.done)
25
+ if (step.done) {
26
26
  return out;
27
+ }
27
28
  }
28
29
  },
29
30
  flush() {
@@ -52,8 +53,9 @@ function dropResumeNewline(state) {
52
53
  if (!state.stripNewline || state.buffer.length === 0)
53
54
  return;
54
55
  state.stripNewline = false;
55
- if (state.buffer[0] === '\n')
56
+ if (state.buffer[0] === '\n') {
56
57
  state.buffer = state.buffer.slice(1);
58
+ }
57
59
  }
58
60
  function emitUntilOpener(state) {
59
61
  dropResumeNewline(state);
@@ -63,8 +65,9 @@ function emitUntilOpener(state) {
63
65
  state.guard.cut();
64
66
  state.buffer = state.buffer.slice(marker.index + marker.marker.length);
65
67
  const closer = MARKUP_CLOSERS[marker.marker];
66
- if (closer === undefined)
68
+ if (closer === undefined) {
67
69
  state.stripNewline = true;
70
+ }
68
71
  state.closer = closer ?? null;
69
72
  return { out, done: false };
70
73
  }
@@ -8,8 +8,9 @@ export class AbortedError extends Error {
8
8
  export function raceAbort(promise, signal) {
9
9
  if (!signal)
10
10
  return promise;
11
- if (signal.aborted)
11
+ if (signal.aborted) {
12
12
  return Promise.reject(new AbortedError());
13
+ }
13
14
  return new Promise((resolve, reject) => {
14
15
  const onAbort = () => reject(new AbortedError());
15
16
  signal.addEventListener('abort', onAbort, { once: true });
@@ -0,0 +1,5 @@
1
+ export interface RaceTimeoutOptions<T> {
2
+ ms: number;
3
+ fallback: T;
4
+ }
5
+ export declare function raceTimeout<T>(pending: Promise<T>, { ms, fallback }: RaceTimeoutOptions<T>): Promise<T>;
@@ -0,0 +1,14 @@
1
+ export async function raceTimeout(pending, { ms, fallback }) {
2
+ let timer = null;
3
+ const expired = new Promise((resolve) => {
4
+ timer = setTimeout(() => resolve(fallback), ms);
5
+ });
6
+ try {
7
+ return await Promise.race([pending, expired]);
8
+ }
9
+ finally {
10
+ if (timer !== null) {
11
+ clearTimeout(timer);
12
+ }
13
+ }
14
+ }