@qvac/harness 0.4.0 → 0.6.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 +740 -141
  2. package/README.md +75 -7
  3. package/dist/harness.bundle +72 -50
  4. package/dist-lib/index.d.ts +49 -39
  5. package/dist-lib/index.js +448 -161
  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 +13 -32
  29. package/dist-lib/lib/connect.js +170 -112
  30. package/dist-lib/lib/context-window.js +25 -21
  31. package/dist-lib/lib/contract-types.d.ts +35 -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 +15 -20
  84. package/dist-lib/lib/models/model-catalog.js +66 -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 +48 -10
  90. package/dist-lib/lib/models/model-pool.js +106 -45
  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 +122 -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 +39 -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 +9 -0
  288. package/dist-lib/spec/calls.js +3 -0
  289. package/dist-lib/spec/hrpc/hrpc.json +39 -0
  290. package/dist-lib/spec/hrpc/index.js +39 -3
  291. package/dist-lib/spec/hrpc/messages.js +105 -8
  292. package/dist-lib/spec/hyperschema/index.js +105 -8
  293. package/dist-lib/spec/hyperschema/schema.json +77 -1
  294. package/dist-lib/spec/hyperschema/types.d.ts +25 -1
  295. package/package.json +14 -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
@@ -13,8 +13,9 @@ export function resolveNotePath(vaultPath, args) {
13
13
  const name = fileArg.slice('file='.length);
14
14
  const withExt = name.endsWith('.md') ? name : `${name}.md`;
15
15
  const direct = ensureWithinRoot(vaultPath, withExt);
16
- if (fs.existsSync(direct))
16
+ if (fs.existsSync(direct)) {
17
17
  return direct;
18
+ }
18
19
  return findFileRecursive(vaultPath, withExt);
19
20
  }
20
21
  return null;
@@ -32,8 +33,9 @@ function readDirEntries(dir) {
32
33
  if (name.startsWith('.'))
33
34
  continue;
34
35
  const full = path.join(dir, name);
35
- if (isSymlink(full))
36
+ if (isSymlink(full)) {
36
37
  continue;
38
+ }
37
39
  let stat;
38
40
  try {
39
41
  stat = fs.statSync(full);
@@ -52,8 +54,9 @@ function findFileRecursive(dir, target) {
52
54
  for (const entry of readDirEntries(dir)) {
53
55
  if (entry.isDir) {
54
56
  const found = findFileRecursive(entry.full, target);
55
- if (found)
57
+ if (found) {
56
58
  return found;
59
+ }
57
60
  }
58
61
  else if (namesMatch(entry.name, target)) {
59
62
  return entry.full;
@@ -72,8 +75,9 @@ export function readFileSnapshot(filePath) {
72
75
  catch {
73
76
  return null;
74
77
  }
75
- if (!stat.isFile())
78
+ if (!stat.isFile()) {
76
79
  return null;
80
+ }
77
81
  return { text: fs.readFileSync(filePath, 'utf8'), mtimeMs: stat.mtimeMs };
78
82
  }
79
83
  export function writeIfUnchanged(filePath, content, expectedMtimeMs) {
@@ -116,10 +120,12 @@ export function listMarkdownFiles(dir, prefix = '') {
116
120
  const results = [];
117
121
  for (const entry of readDirEntries(dir)) {
118
122
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
119
- if (entry.isDir)
123
+ if (entry.isDir) {
120
124
  results.push(...listMarkdownFiles(entry.full, rel));
121
- else if (entry.name.endsWith('.md'))
125
+ }
126
+ else if (entry.name.endsWith('.md')) {
122
127
  results.push(rel);
128
+ }
123
129
  }
124
130
  return results;
125
131
  }
@@ -136,24 +142,28 @@ export function listFolders(dir, prefix = '') {
136
142
  }
137
143
  export function parseFrontmatter(content) {
138
144
  const match = content.match(FRONTMATTER_RE);
139
- if (!match?.[1])
145
+ if (!match?.[1]) {
140
146
  return {};
147
+ }
141
148
  const props = {};
142
149
  for (const line of match[1].split('\n')) {
143
150
  const colonIdx = line.indexOf(':');
144
- if (colonIdx === -1)
151
+ if (colonIdx === -1) {
145
152
  continue;
153
+ }
146
154
  const key = line.slice(0, colonIdx).trim();
147
155
  const value = line.slice(colonIdx + 1).trim();
148
- if (key)
156
+ if (key) {
149
157
  props[key] = value;
158
+ }
150
159
  }
151
160
  return props;
152
161
  }
153
162
  export function getContentArg(args) {
154
163
  const arg = args.find((a) => a.startsWith('content='));
155
- if (!arg)
164
+ if (!arg) {
156
165
  return '';
166
+ }
157
167
  return arg.slice('content='.length).replace(/\\n/g, '\n');
158
168
  }
159
169
  export function getArg(args, key) {
@@ -35,14 +35,16 @@ const SEARCH_LIMIT_MAX = 200;
35
35
  function parseLimit(args) {
36
36
  const raw = getArg(args, 'limit');
37
37
  const n = raw ? Number.parseInt(raw, 10) : Number.NaN;
38
- if (!Number.isFinite(n) || n <= 0)
38
+ if (!Number.isFinite(n) || n <= 0) {
39
39
  return SEARCH_LIMIT_DEFAULT;
40
+ }
40
41
  return Math.min(n, SEARCH_LIMIT_MAX);
41
42
  }
42
43
  export function handleSearch(vaultPath, args) {
43
44
  const query = getArg(args, 'query');
44
- if (!query)
45
+ if (!query) {
45
46
  throw new Error('Missing required argument: query=');
47
+ }
46
48
  const limit = parseLimit(args);
47
49
  const lowerQuery = query.toLowerCase();
48
50
  const files = listMarkdownFiles(path.resolve(vaultPath));
@@ -52,14 +54,16 @@ export function handleSearch(vaultPath, args) {
52
54
  break;
53
55
  const fullPath = path.join(path.resolve(vaultPath), relPath);
54
56
  try {
55
- if (readFileText(fullPath).toLowerCase().includes(lowerQuery))
57
+ if (readFileText(fullPath).toLowerCase().includes(lowerQuery)) {
56
58
  matches.push(relPath);
59
+ }
57
60
  }
58
61
  catch {
59
62
  }
60
63
  }
61
- if (matches.length === 0)
64
+ if (matches.length === 0) {
62
65
  return `No results for "${query}"`;
66
+ }
63
67
  const truncated = matches.length >= limit ? `\n(showing first ${limit}; narrow query for more)` : '';
64
68
  return matches.join('\n') + truncated;
65
69
  }
@@ -70,19 +74,21 @@ export function handleProperties(vaultPath, args) {
70
74
  }
71
75
  return JSON.stringify(parseFrontmatter(readFileText(notePath)), null, 2);
72
76
  }
77
+ function countTags(tagCounts, content) {
78
+ for (const match of content.matchAll(/#([a-zA-Z0-9_/-]+)/g)) {
79
+ const tag = match[1];
80
+ if (tag === undefined) {
81
+ continue;
82
+ }
83
+ tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
84
+ }
85
+ }
73
86
  export function handleTags(vaultPath) {
74
87
  const files = listMarkdownFiles(path.resolve(vaultPath));
75
88
  const tagCounts = new Map();
76
- const tagRe = /#([a-zA-Z0-9_/-]+)/g;
77
89
  for (const relPath of files) {
78
90
  try {
79
- const content = readFileText(path.join(path.resolve(vaultPath), relPath));
80
- for (const match of content.matchAll(tagRe)) {
81
- const tag = match[1];
82
- if (tag === undefined)
83
- continue;
84
- tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
85
- }
91
+ countTags(tagCounts, readFileText(path.join(path.resolve(vaultPath), relPath)));
86
92
  }
87
93
  catch {
88
94
  }
@@ -112,8 +118,9 @@ export function handleOutline(vaultPath, args) {
112
118
  export function handleDailyRead(vaultPath) {
113
119
  const dateStr = todayStamp();
114
120
  for (const p of dailyCandidates(vaultPath, dateStr)) {
115
- if (fs.existsSync(p))
121
+ if (fs.existsSync(p)) {
116
122
  return readFileText(p);
123
+ }
117
124
  }
118
125
  return `No daily note found for ${dateStr}`;
119
126
  }
@@ -8,8 +8,9 @@ export function handleAppend(vaultPath, args) {
8
8
  throw new Error(`Note not found. Args: ${args.join(', ')}`);
9
9
  }
10
10
  const content = getContentArg(args);
11
- if (!content)
11
+ if (!content) {
12
12
  throw new Error('Missing required argument: content=');
13
+ }
13
14
  appendToFile(notePath, content);
14
15
  return `Appended to: ${path.relative(vaultPath, notePath)}`;
15
16
  }
@@ -19,8 +20,9 @@ export function handlePrepend(vaultPath, args) {
19
20
  throw new Error(`Note not found. Args: ${args.join(', ')}`);
20
21
  }
21
22
  const content = getContentArg(args);
22
- if (!content)
23
+ if (!content) {
23
24
  throw new Error('Missing required argument: content=');
25
+ }
24
26
  updateFileText(notePath, (existing) => content + existing);
25
27
  return `Prepended to: ${path.relative(vaultPath, notePath)}`;
26
28
  }
@@ -30,8 +32,9 @@ function uniqueTrashPath(base) {
30
32
  const ext = base.endsWith('.md') ? '.md' : '';
31
33
  const stem = ext ? base.slice(0, -ext.length) : base;
32
34
  let n = 1;
33
- while (fs.existsSync(`${stem} (${n})${ext}`))
35
+ while (fs.existsSync(`${stem} (${n})${ext}`)) {
34
36
  n += 1;
37
+ }
35
38
  return `${stem} (${n})${ext}`;
36
39
  }
37
40
  export function handleDelete(vaultPath, args) {
@@ -51,11 +54,13 @@ export function handleMove(vaultPath, args) {
51
54
  throw new Error(`Note not found. Args: ${args.join(', ')}`);
52
55
  }
53
56
  const to = getArg(args, 'to');
54
- if (!to)
57
+ if (!to) {
55
58
  throw new Error('Missing required argument: to=');
59
+ }
56
60
  const destDir = ensureWithinRoot(vaultPath, to);
57
- if (!fs.existsSync(destDir))
61
+ if (!fs.existsSync(destDir)) {
58
62
  fs.mkdirSync(destDir, { recursive: true });
63
+ }
59
64
  const destPath = path.join(destDir, path.basename(notePath));
60
65
  moveFile(notePath, destPath);
61
66
  return `Moved to: ${path.relative(vaultPath, destPath)}`;
@@ -66,8 +71,9 @@ export function handleRename(vaultPath, args) {
66
71
  throw new Error(`Note not found. Args: ${args.join(', ')}`);
67
72
  }
68
73
  const newName = getArg(args, 'name');
69
- if (!newName)
74
+ if (!newName) {
70
75
  throw new Error('Missing required argument: name=');
76
+ }
71
77
  const fileName = markdownFileName(newName);
72
78
  const relativeDir = path.relative(path.resolve(vaultPath), path.dirname(notePath));
73
79
  const destPath = ensureWithinRoot(vaultPath, path.join(relativeDir, fileName));
@@ -78,10 +84,12 @@ function mergeIntoFrontmatter(fmBlock, newProps) {
78
84
  let result = fmBlock;
79
85
  for (const { key, value } of newProps) {
80
86
  const lineRe = new RegExp(`^${key}:.*$`, 'm');
81
- if (lineRe.test(result))
87
+ if (lineRe.test(result)) {
82
88
  result = result.replace(lineRe, `${key}: ${value}`);
83
- else
89
+ }
90
+ else {
84
91
  result += `\n${key}: ${value}`;
92
+ }
85
93
  }
86
94
  return result;
87
95
  }
@@ -91,8 +99,9 @@ export function handlePropertySet(vaultPath, args) {
91
99
  throw new Error(`Note not found. Args: ${args.join(', ')}`);
92
100
  }
93
101
  const propArgs = args.filter((a) => !a.startsWith('file=') && !a.startsWith('path=') && a.includes('='));
94
- if (propArgs.length === 0)
102
+ if (propArgs.length === 0) {
95
103
  throw new Error('No property key=value pairs provided.');
104
+ }
96
105
  const newProps = propArgs.map((a) => {
97
106
  const eqIdx = a.indexOf('=');
98
107
  return { key: a.slice(0, eqIdx), value: a.slice(eqIdx + 1) };
@@ -110,8 +119,9 @@ export function handlePropertySet(vaultPath, args) {
110
119
  }
111
120
  export function handleDailyAppend(vaultPath, args) {
112
121
  const content = getContentArg(args);
113
- if (!content)
122
+ if (!content) {
114
123
  throw new Error('Missing required argument: content=');
124
+ }
115
125
  const dateStr = todayStamp();
116
126
  let target = null;
117
127
  for (const candidate of dailyCandidates(vaultPath, dateStr)) {
@@ -122,12 +132,14 @@ export function handleDailyAppend(vaultPath, args) {
122
132
  }
123
133
  if (!target) {
124
134
  const dailyDir = ensureWithinRoot(vaultPath, 'Daily Notes');
125
- if (!fs.existsSync(dailyDir))
135
+ if (!fs.existsSync(dailyDir)) {
126
136
  fs.mkdirSync(dailyDir, { recursive: true });
137
+ }
127
138
  target = ensureWithinRoot(vaultPath, path.join('Daily Notes', `${dateStr}.md`));
128
139
  const snap = readFileSnapshot(target);
129
- if (!snap)
140
+ if (!snap) {
130
141
  writeIfUnchanged(target, '', null);
142
+ }
131
143
  }
132
144
  appendToFile(target, content);
133
145
  return `Appended to daily note: ${dateStr}`;
@@ -1,29 +1,29 @@
1
1
  import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
2
- export type ExecAttachment = {
2
+ export interface ExecAttachment {
3
3
  readonly attachmentId: string;
4
4
  readonly fileName: string;
5
5
  readonly byteLength: number;
6
- };
7
- export type RejectedOutput = {
6
+ }
7
+ export interface RejectedOutput {
8
8
  readonly name: string;
9
9
  readonly reason: string;
10
- };
11
- export type ExecResult = {
10
+ }
11
+ export interface ExecResult {
12
12
  readonly stdout: string;
13
13
  readonly stderr: string;
14
14
  readonly exitCode: number;
15
15
  readonly attachments?: readonly ExecAttachment[];
16
16
  readonly missingOutputs?: readonly string[];
17
17
  readonly rejectedOutputs?: readonly RejectedOutput[];
18
- };
19
- export type SpawnOptions = {
18
+ }
19
+ export interface SpawnOptions {
20
20
  cwd?: string;
21
21
  shell?: boolean;
22
22
  detached?: boolean;
23
23
  stdio?: [string, string, string] | string;
24
24
  env?: Record<string, string>;
25
- };
26
- export type Child = {
25
+ }
26
+ export interface Child {
27
27
  readonly pid?: number;
28
28
  readonly stdout: {
29
29
  on(event: 'data', handler: (chunk: Buffer | string) => void): void;
@@ -34,9 +34,9 @@ export type Child = {
34
34
  kill(signum?: number | string): void;
35
35
  on(event: 'exit', handler: (code: number | null, signal?: string | null) => void): void;
36
36
  on(event: 'error', handler: (err: Error) => void): void;
37
- };
37
+ }
38
38
  export type SpawnFn = (command: string, opts?: SpawnOptions) => Child;
39
- export type RunCommandOptions = {
39
+ export interface RunCommandOptions {
40
40
  readonly cwd?: string;
41
41
  readonly env?: Readonly<Record<string, string>>;
42
42
  readonly timeoutMs?: number;
@@ -45,15 +45,15 @@ export type RunCommandOptions = {
45
45
  readonly spawn: SpawnFn;
46
46
  readonly killProcess?: KillProcess;
47
47
  readonly platform?: string;
48
- };
48
+ }
49
49
  export declare const MAX_OUTPUT_CHARS = 8192;
50
50
  export declare const MAX_OUTPUT_CHARS_LIMIT = 65536;
51
51
  export declare const TRUNCATED_OUTPUT_SUFFIX = "\u2026 [truncated]";
52
52
  export type KillProcess = (pid: number, signal: string) => void;
53
- type CapturedOutput = {
53
+ interface CapturedOutput {
54
54
  value: string;
55
55
  truncated: boolean;
56
- };
56
+ }
57
57
  export declare function capOutput(text: string, limit: number): string;
58
58
  export declare function appendOutput(output: CapturedOutput, chunk: Buffer | string, limit: number): void;
59
59
  export declare function formatOutput(output: CapturedOutput): string;
@@ -1,3 +1,4 @@
1
+ import b4a from 'b4a';
1
2
  import process from 'process';
2
3
  import { AbortedError } from '../../helpers/race-abort.js';
3
4
  const DEFAULT_TIMEOUT_MS = 120_000;
@@ -21,7 +22,7 @@ export function appendOutput(output, chunk, limit) {
21
22
  output.truncated = true;
22
23
  return;
23
24
  }
24
- const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
25
+ const text = typeof chunk === 'string' ? chunk : b4a.toString(chunk, 'utf8');
25
26
  output.value += text.slice(0, available);
26
27
  output.truncated = text.length > available;
27
28
  }
@@ -45,8 +46,9 @@ function terminateProcessTree(child, killProcess) {
45
46
  export function runCommand(command, options) {
46
47
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
47
48
  const maxOutputChars = options.maxOutputChars ?? MAX_OUTPUT_CHARS;
48
- if (options.signal?.aborted)
49
+ if (options.signal?.aborted) {
49
50
  return Promise.reject(new AbortedError());
51
+ }
50
52
  return new Promise((resolve, reject) => {
51
53
  const stdout = { value: '', truncated: false };
52
54
  const stderr = { value: '', truncated: false };
@@ -56,7 +58,7 @@ export function runCommand(command, options) {
56
58
  detached: (options.platform ?? process.platform) !== 'win32',
57
59
  stdio: ['ignore', 'pipe', 'pipe'],
58
60
  cwd: options.cwd,
59
- ...(options.env ? { env: { ...options.env } } : {})
61
+ env: options.env ? { ...options.env } : undefined
60
62
  });
61
63
  const finish = (fn) => {
62
64
  if (settled)
@@ -6,8 +6,9 @@ export function bareBin(token) {
6
6
  export function firstCommandToken(command) {
7
7
  const chars = [...command];
8
8
  let i = 0;
9
- while (i < chars.length && (chars[i] === ' ' || chars[i] === '\t'))
9
+ while (i < chars.length && (chars[i] === ' ' || chars[i] === '\t')) {
10
10
  i++;
11
+ }
11
12
  let token = '';
12
13
  while (i < chars.length) {
13
14
  const c = chars[i];
@@ -21,10 +22,12 @@ export function firstCommandToken(command) {
21
22
  i++;
22
23
  continue;
23
24
  }
24
- if (c === ' ' || c === '\t' || c === '\n')
25
+ if (c === ' ' || c === '\t' || c === '\n') {
25
26
  break;
26
- if (c === ';' || c === '&' || c === '|' || c === '>' || c === '<' || c === '`')
27
+ }
28
+ if (c === ';' || c === '&' || c === '|' || c === '>' || c === '<' || c === '`') {
27
29
  break;
30
+ }
28
31
  token += c;
29
32
  i++;
30
33
  }
@@ -33,6 +36,26 @@ export function firstCommandToken(command) {
33
36
  function isPad(c) {
34
37
  return c === ' ' || c === '\t' || c === '\n';
35
38
  }
39
+ function skipDoubleQuoted(chars, open) {
40
+ let i = open + 1;
41
+ while (i < chars.length && chars[i] !== '"') {
42
+ if (chars[i] === '\\') {
43
+ if (chars[i + 1] === '\n') {
44
+ return 'command must not use line continuations';
45
+ }
46
+ i += 2;
47
+ continue;
48
+ }
49
+ if (chars[i] === '`') {
50
+ return 'command must not use backtick substitution';
51
+ }
52
+ if (chars[i] === '$') {
53
+ return 'command must not use shell expansion';
54
+ }
55
+ i++;
56
+ }
57
+ return i + 1;
58
+ }
36
59
  export function sanitizeCommand(command) {
37
60
  const chars = [...command];
38
61
  let i = 0;
@@ -40,57 +63,58 @@ export function sanitizeCommand(command) {
40
63
  const c = chars[i];
41
64
  if (c === '\n') {
42
65
  i++;
43
- while (i < chars.length && isPad(chars[i]))
66
+ while (i < chars.length && isPad(chars[i])) {
44
67
  i++;
45
- if (i < chars.length)
68
+ }
69
+ if (i < chars.length) {
46
70
  return 'command must not span multiple lines';
71
+ }
47
72
  return null;
48
73
  }
49
74
  if (c === "'") {
50
75
  i++;
51
- while (i < chars.length && chars[i] !== "'")
76
+ while (i < chars.length && chars[i] !== "'") {
52
77
  i++;
78
+ }
53
79
  i++;
54
80
  continue;
55
81
  }
56
82
  if (c === '"') {
57
- i++;
58
- while (i < chars.length && chars[i] !== '"') {
59
- if (chars[i] === '\\') {
60
- if (chars[i + 1] === '\n')
61
- return 'command must not use line continuations';
62
- i += 2;
63
- continue;
64
- }
65
- if (chars[i] === '`')
66
- return 'command must not use backtick substitution';
67
- if (chars[i] === '$')
68
- return 'command must not use shell expansion';
69
- i++;
83
+ const end = skipDoubleQuoted(chars, i);
84
+ if (typeof end === 'string') {
85
+ return end;
70
86
  }
71
- i++;
87
+ i = end;
72
88
  continue;
73
89
  }
74
90
  if (c === '\\') {
75
- if (chars[i + 1] === '\n')
91
+ if (chars[i + 1] === '\n') {
76
92
  return 'command must not use line continuations';
93
+ }
77
94
  i += 2;
78
95
  continue;
79
96
  }
80
- if (c === '`')
97
+ if (c === '`') {
81
98
  return 'command must not use backtick substitution';
82
- if (c === '$')
99
+ }
100
+ if (c === '$') {
83
101
  return 'command must not use shell expansion';
84
- if (c === ';')
102
+ }
103
+ if (c === ';') {
85
104
  return 'command must not chain with ;';
86
- if (c === '&')
105
+ }
106
+ if (c === '&') {
87
107
  return 'command must not use & or &&';
88
- if (c === '|')
108
+ }
109
+ if (c === '|') {
89
110
  return 'command must not use pipes';
90
- if (c === '>')
111
+ }
112
+ if (c === '>') {
91
113
  return 'command must not redirect output';
92
- if (c === '<')
114
+ }
115
+ if (c === '<') {
93
116
  return 'command must not redirect input';
117
+ }
94
118
  i++;
95
119
  }
96
120
  return null;
@@ -1,36 +1,48 @@
1
1
  export function shellEscapeArg(value) {
2
2
  return value.replace(/[\\'" \t\n]/g, '\\$&');
3
3
  }
4
+ function readQuoted(chars, open) {
5
+ const quote = chars[open];
6
+ let text = '';
7
+ let i = open + 1;
8
+ while (i < chars.length && chars[i] !== quote) {
9
+ if (quote === '"' && chars[i] === '\\' && i + 1 < chars.length) {
10
+ text += chars[i + 1];
11
+ i += 2;
12
+ continue;
13
+ }
14
+ text += chars[i];
15
+ i++;
16
+ }
17
+ if (i < chars.length) {
18
+ i++;
19
+ }
20
+ return { text, end: i };
21
+ }
4
22
  export function shellArgv(command) {
5
23
  const chars = [...command];
6
24
  const out = [];
7
25
  let i = 0;
8
26
  while (i < chars.length) {
9
- while (i < chars.length && (chars[i] === ' ' || chars[i] === '\t'))
27
+ while (i < chars.length && (chars[i] === ' ' || chars[i] === '\t')) {
10
28
  i++;
11
- if (i >= chars.length)
29
+ }
30
+ if (i >= chars.length) {
12
31
  break;
13
- if (chars[i] === '\n')
32
+ }
33
+ if (chars[i] === '\n') {
14
34
  break;
35
+ }
15
36
  let token = '';
16
37
  while (i < chars.length) {
17
38
  const c = chars[i];
18
- if (c === ' ' || c === '\t' || c === '\n')
39
+ if (c === ' ' || c === '\t' || c === '\n') {
19
40
  break;
41
+ }
20
42
  if (c === "'" || c === '"') {
21
- const quote = c;
22
- i++;
23
- while (i < chars.length && chars[i] !== quote) {
24
- if (quote === '"' && chars[i] === '\\' && i + 1 < chars.length) {
25
- token += chars[i + 1];
26
- i += 2;
27
- continue;
28
- }
29
- token += chars[i];
30
- i++;
31
- }
32
- if (i < chars.length)
33
- i++;
43
+ const quoted = readQuoted(chars, i);
44
+ token += quoted.text;
45
+ i = quoted.end;
34
46
  continue;
35
47
  }
36
48
  if (c === '\\' && i + 1 < chars.length) {
@@ -41,8 +53,9 @@ export function shellArgv(command) {
41
53
  token += c;
42
54
  i++;
43
55
  }
44
- if (token.length > 0 || out.length > 0)
56
+ if (token.length > 0 || out.length > 0) {
45
57
  out.push(token);
58
+ }
46
59
  }
47
60
  return out;
48
61
  }
@@ -1,7 +1,12 @@
1
1
  export declare const PYTHON_BIN_ERROR: string;
2
2
  export declare const PACKAGES_NEED_PYTHON_ERROR: string;
3
3
  export declare const FILES_NEED_PYTHON_ERROR: string;
4
- export declare function videoToolError(command: string, packages: readonly string[] | undefined, python: boolean, network?: boolean): string | null;
4
+ export interface VideoToolCall {
5
+ packages?: readonly string[] | undefined;
6
+ python: boolean;
7
+ network?: boolean;
8
+ }
9
+ export declare function videoToolError(command: string, { packages, python, network }: VideoToolCall): string | null;
5
10
  export declare const SHELL_DOWNLOAD_NOTE: string;
6
11
  export declare function shellDownloadNote(command: string): string | null;
7
12
  export declare function pipError(command: string, sandbox?: boolean): string | null;