@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
@@ -1,12 +1,14 @@
1
1
  import { z } from 'zod';
2
+ import { errorMessage } from '../../guards.js';
2
3
  import { argvToObject, isObjectSchema, objectProps, walkCommands } from './cli-argv.js';
3
4
  export function buildSchemaAnnotation(schema) {
4
5
  const resourceEffects = schema['x-resource-effects'];
5
6
  return (argv) => {
6
7
  const first = argv[0];
7
8
  if (resourceEffects && typeof first === 'string') {
8
- if (resourceEffects[basename(first)] === 'read')
9
+ if (resourceEffects[basename(first)] === 'read') {
9
10
  return 'read';
11
+ }
10
12
  }
11
13
  return walkCommands(argv, schema).node['x-effect'] === 'read' ? 'read' : 'write';
12
14
  };
@@ -15,38 +17,46 @@ function basename(p) {
15
17
  return p.slice(Math.max(p.lastIndexOf('/'), p.lastIndexOf('\\')) + 1);
16
18
  }
17
19
  export function buildSchemaCheck(schema, resourcePaths) {
20
+ const source = schema;
18
21
  let zodSchema;
19
22
  try {
20
- zodSchema = z.fromJSONSchema(schema);
23
+ zodSchema = z.fromJSONSchema(source);
21
24
  }
22
25
  catch (err) {
23
- const msg = err instanceof Error ? err.message : String(err);
26
+ const msg = errorMessage(err);
24
27
  return () => `invalid skill cli JSON Schema: ${msg}`;
25
28
  }
26
29
  return (argv) => {
27
30
  const built = argvToObject(argv, schema);
28
- if (typeof built === 'string')
31
+ if (typeof built === 'string') {
29
32
  return built;
33
+ }
30
34
  const cmdErr = assertSingleCommand(built, schema);
31
- if (cmdErr)
35
+ if (cmdErr) {
32
36
  return cmdErr;
37
+ }
33
38
  const resourceErr = assertResourcePath(built, resourcePaths);
34
- if (resourceErr)
39
+ if (resourceErr) {
35
40
  return resourceErr;
41
+ }
36
42
  const result = zodSchema.safeParse(built);
37
- if (result.success)
43
+ if (result.success) {
38
44
  return null;
45
+ }
39
46
  return formatZod(result.error);
40
47
  };
41
48
  }
42
49
  function assertResourcePath(obj, resourcePaths) {
43
- if (!resourcePaths || resourcePaths.length === 0 || typeof obj.script !== 'string')
50
+ if (!resourcePaths || resourcePaths.length === 0 || typeof obj.script !== 'string') {
44
51
  return null;
52
+ }
45
53
  return resourcePaths.includes(obj.script) ? null : 'script must be a bundled skill resource';
46
54
  }
47
55
  function assertSingleCommand(obj, schema) {
48
56
  const props = objectProps(schema);
49
- const commandKeys = Object.keys(props).filter((k) => isObjectSchema(props[k]));
57
+ const commandKeys = Object.entries(props)
58
+ .filter(([, prop]) => isObjectSchema(prop))
59
+ .map(([k]) => k);
50
60
  const present = commandKeys.filter((k) => k in obj);
51
61
  if (present.length > 1) {
52
62
  return `only one command allowed (got ${present.join(', ')})`;
@@ -55,8 +65,9 @@ function assertSingleCommand(obj, schema) {
55
65
  }
56
66
  function formatZod(err) {
57
67
  const issue = err.issues[0];
58
- if (!issue)
68
+ if (!issue) {
59
69
  return 'invalid parameters';
70
+ }
60
71
  const where = issue.path.length ? `${issue.path.join('.')}: ` : '';
61
72
  return `${where}${issue.message}`;
62
73
  }
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
+ import { isRecord } from '../../guards.js';
3
4
  import { CLI_SCHEMA_FILENAME } from './cli-schema-types.js';
4
5
  export async function resolveCliSchema(skillDir, bin, readFile = (p) => fs.promises.readFile(p, 'utf8')) {
5
6
  const full = path.join(skillDir, CLI_SCHEMA_FILENAME);
@@ -8,27 +9,31 @@ export async function resolveCliSchema(skillDir, bin, readFile = (p) => fs.promi
8
9
  raw = await readFile(full);
9
10
  }
10
11
  catch (err) {
11
- if (isEnoent(err))
12
+ if (isEnoent(err)) {
12
13
  return { bin };
14
+ }
13
15
  return { bin, schemaFile: CLI_SCHEMA_FILENAME };
14
16
  }
15
17
  try {
16
- const parsed = JSON.parse(raw);
17
- if (!isObj(parsed))
18
+ const schema = JSON.parse(raw);
19
+ if (!isSchemaObject(schema)) {
18
20
  return { bin, schemaFile: CLI_SCHEMA_FILENAME };
19
- const schema = parsed;
20
- if (!resourceGuardConsistent(schema))
21
+ }
22
+ if (!resourceGuardConsistent(schema)) {
21
23
  return { bin, schemaFile: CLI_SCHEMA_FILENAME };
22
- if (!effectAnnotationsValid(schema))
24
+ }
25
+ if (!effectAnnotationsValid(schema)) {
23
26
  return { bin, schemaFile: CLI_SCHEMA_FILENAME };
24
- if (!resourceEffectsValid(schema))
27
+ }
28
+ if (!resourceEffectsValid(schema)) {
25
29
  return { bin, schemaFile: CLI_SCHEMA_FILENAME };
30
+ }
26
31
  const resourcePaths = resolveResourcePaths(skillDir, schema);
27
32
  return {
28
33
  bin,
29
34
  schema,
30
35
  schemaFile: CLI_SCHEMA_FILENAME,
31
- ...(resourcePaths.length ? { resourcePaths } : {})
36
+ resourcePaths: resourcePaths.length ? resourcePaths : undefined
32
37
  };
33
38
  }
34
39
  catch {
@@ -37,8 +42,9 @@ export async function resolveCliSchema(skillDir, bin, readFile = (p) => fs.promi
37
42
  }
38
43
  function resourceGuardConsistent(schema) {
39
44
  const resources = schema['x-resource-files'];
40
- if (!resources || resources.length === 0)
45
+ if (!resources || resources.length === 0) {
41
46
  return true;
47
+ }
42
48
  return schema.properties?.script?.type === 'string';
43
49
  }
44
50
  function effectAnnotationsValid(schema) {
@@ -48,10 +54,12 @@ function effectAnnotationsValid(schema) {
48
54
  }
49
55
  function resourceEffectsValid(schema) {
50
56
  const effects = schema['x-resource-effects'];
51
- if (effects === undefined)
57
+ if (effects === undefined) {
52
58
  return true;
53
- if (typeof effects !== 'object' || effects === null || Array.isArray(effects))
59
+ }
60
+ if (typeof effects !== 'object' || effects === null || Array.isArray(effects)) {
54
61
  return false;
62
+ }
55
63
  const files = new Set(schema['x-resource-files'] ?? []);
56
64
  return Object.entries(effects).every(([file, effect]) => effect === 'read' && files.has(file));
57
65
  }
@@ -65,26 +73,26 @@ export function execBinFromTools(tools) {
65
73
  for (const entry of tools) {
66
74
  const m = /^exec\((.+)\)$/i.exec(entry.trim());
67
75
  const scope = m?.[1]?.trim();
68
- if (scope)
76
+ if (scope) {
69
77
  return scope;
78
+ }
70
79
  }
71
80
  return undefined;
72
81
  }
73
82
  export async function loadSkillCli(skillDir, tools, readFile) {
74
83
  const bin = execBinFromTools(tools);
75
- if (!bin)
84
+ if (!bin) {
76
85
  return undefined;
86
+ }
77
87
  const resolved = await resolveCliSchema(skillDir, bin, readFile);
78
- if (resolved.schema || resolved.schemaFile)
88
+ if (resolved.schema || resolved.schemaFile) {
79
89
  return resolved;
90
+ }
80
91
  return undefined;
81
92
  }
82
93
  function isEnoent(err) {
83
- return (typeof err === 'object' &&
84
- err !== null &&
85
- 'code' in err &&
86
- err.code === 'ENOENT');
94
+ return isRecord(err) && 'code' in err && err.code === 'ENOENT';
87
95
  }
88
- function isObj(v) {
89
- return typeof v === 'object' && v !== null && !Array.isArray(v);
96
+ function isSchemaObject(v) {
97
+ return isRecord(v) && !Array.isArray(v);
90
98
  }
@@ -1,4 +1,4 @@
1
- export type JsonSchema = {
1
+ export interface JsonSchema {
2
2
  readonly type?: string;
3
3
  readonly properties?: Readonly<Record<string, JsonSchema>>;
4
4
  readonly required?: readonly string[];
@@ -14,17 +14,17 @@ export type JsonSchema = {
14
14
  readonly 'x-resource-effects'?: Readonly<Record<string, string>>;
15
15
  readonly 'x-effect'?: string;
16
16
  readonly [key: string]: unknown;
17
- };
18
- export type SkillCli = {
17
+ }
18
+ export interface SkillCli {
19
19
  readonly bin: string;
20
20
  readonly schema?: JsonSchema;
21
21
  readonly schemaFile?: string;
22
22
  readonly resourcePaths?: readonly string[];
23
- };
23
+ }
24
24
  export declare const CLI_SCHEMA_FILENAME = "cli.schema.json";
25
- export type CliValidator = {
25
+ export interface CliValidator {
26
26
  readonly bin: string;
27
27
  readonly check: (argv: readonly string[]) => string | null;
28
28
  readonly annotation: (argv: readonly string[]) => 'read' | 'write';
29
29
  readonly effect: (argv: readonly string[]) => 'read' | 'write';
30
- };
30
+ }
@@ -27,8 +27,9 @@ export function checkCliOps(argv, compiled) {
27
27
  let lastErr = null;
28
28
  for (const c of compiled) {
29
29
  const err = c.check(argv);
30
- if (err === null)
30
+ if (err === null) {
31
31
  return null;
32
+ }
32
33
  lastErr = err;
33
34
  }
34
35
  return lastErr ?? 'command does not match any allowed skill operation';
@@ -2,19 +2,22 @@ import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
2
2
  import { type CredentialStoreFn } from './auth-resolver.ts';
3
3
  import type { SkillCatalogEntry } from './catalog.ts';
4
4
  export declare const CREDENTIAL_CHECK_TTL_MS = 45000;
5
- type CredentialCheckResponse = {
5
+ interface CredentialCheckResponse {
6
6
  readonly status: number;
7
7
  text?: () => Promise<string>;
8
- };
8
+ }
9
9
  export type CredentialCheckFetch = (input: string, init: {
10
10
  method: string;
11
11
  headers: Headers;
12
12
  signal: BareAbortSignal;
13
13
  }) => Promise<CredentialCheckResponse>;
14
14
  export interface ValidateCredentialChecksOptions {
15
+ credentialStore?: CredentialStoreFn;
16
+ agentId?: string | null;
17
+ fetchImpl?: CredentialCheckFetch;
15
18
  refresh?: boolean | undefined;
16
19
  now?: () => number;
17
20
  ttlMs?: number;
18
21
  }
19
- export declare function validateCredentialChecks(catalog: readonly SkillCatalogEntry[], credentialStore: CredentialStoreFn | undefined, agentId?: string | null, fetchImpl?: CredentialCheckFetch, { refresh, now, ttlMs }?: ValidateCredentialChecksOptions): Promise<void>;
22
+ export declare function validateCredentialChecks(catalog: readonly SkillCatalogEntry[], { credentialStore, agentId, fetchImpl, refresh, now, ttlMs }?: ValidateCredentialChecksOptions): Promise<void>;
20
23
  export {};
@@ -2,6 +2,7 @@ import fetch from '#fetch';
2
2
  import { Headers } from '#headers';
3
3
  import { AbortController } from 'bare-abort-controller';
4
4
  import { DEFAULT_USER_AGENT } from '../../user-agent.js';
5
+ import { isRecord } from '../../guards.js';
5
6
  import { credentialRecord, isCredentialUrlAllowed } from './auth-resolver.js';
6
7
  import { credentialLastProbedAt, markCredentialRejected, markCredentialValid, setCredentialLastProbedAt } from './credential-health.js';
7
8
  const TIMEOUT_MS = 5_000;
@@ -10,7 +11,7 @@ const inflight = new Map();
10
11
  function scopedKey(key, agentId) {
11
12
  return agentId ? `${agentId}\0${key}` : key;
12
13
  }
13
- export async function validateCredentialChecks(catalog, credentialStore, agentId, fetchImpl, { refresh = false, now = Date.now, ttlMs = CREDENTIAL_CHECK_TTL_MS } = {}) {
14
+ export async function validateCredentialChecks(catalog, { credentialStore, agentId, fetchImpl, refresh = false, now = Date.now, ttlMs = CREDENTIAL_CHECK_TTL_MS } = {}) {
14
15
  if (!credentialStore)
15
16
  return;
16
17
  const doFetch = fetchImpl ?? fetch;
@@ -19,16 +20,18 @@ export async function validateCredentialChecks(catalog, credentialStore, agentId
19
20
  for (const [key, check] of Object.entries(skill.requires?.credentialChecks ?? {})) {
20
21
  if (!isCredentialUrlAllowed(check.url, skill.allowList))
21
22
  continue;
22
- if (!checks.has(key))
23
+ if (!checks.has(key)) {
23
24
  checks.set(key, { check, skill: skill.name });
25
+ }
24
26
  }
25
27
  }
26
28
  const at = now();
27
29
  await Promise.all([...checks].map(async ([key, { check, skill }]) => {
28
30
  if (!refresh) {
29
31
  const last = credentialLastProbedAt(key, agentId);
30
- if (last !== undefined && at - last < ttlMs)
32
+ if (last !== undefined && at - last < ttlMs) {
31
33
  return;
34
+ }
32
35
  }
33
36
  const sk = scopedKey(key, agentId);
34
37
  const pending = inflight.get(sk);
@@ -36,22 +39,28 @@ export async function validateCredentialChecks(catalog, credentialStore, agentId
36
39
  await pending;
37
40
  return;
38
41
  }
39
- const probe = runCheck(key, check, skill, credentialStore, agentId, doFetch).finally(() => {
42
+ const probe = runCheck(key, check, {
43
+ skill,
44
+ credentialStore,
45
+ agentId,
46
+ fetchImpl: doFetch
47
+ }).finally(() => {
40
48
  inflight.delete(sk);
41
49
  });
42
50
  inflight.set(sk, probe);
43
51
  await probe;
44
- setCredentialLastProbedAt(key, now(), agentId);
52
+ setCredentialLastProbedAt(key, now(), { agentId });
45
53
  }));
46
54
  }
47
- async function runCheck(key, check, skill, credentialStore, agentId, fetchImpl) {
55
+ async function runCheck(key, check, { skill, credentialStore, agentId, fetchImpl }) {
48
56
  const record = credentialRecord(await credentialStore(key, { agentId, skills: [skill] }));
49
- if (!record)
57
+ if (!record) {
50
58
  return;
59
+ }
51
60
  const controller = new AbortController();
52
61
  const timer = setTimeout(() => controller.abort('credential check timed out'), TIMEOUT_MS);
53
62
  try {
54
- const headers = new Headers({ ...(check.headers ?? {}) });
63
+ const headers = new Headers(check.headers);
55
64
  if (!headers.has('user-agent')) {
56
65
  headers.set('user-agent', DEFAULT_USER_AGENT);
57
66
  }
@@ -76,15 +85,18 @@ async function runCheck(key, check, skill, credentialStore, agentId, fetchImpl)
76
85
  }
77
86
  }
78
87
  async function hasMcpAuthError(response) {
79
- if (response.status < 200 || response.status >= 300 || !response.text)
88
+ if (response.status < 200 || response.status >= 300 || !response.text) {
80
89
  return false;
90
+ }
81
91
  try {
82
92
  const body = JSON.parse(await response.text());
83
- const error = body.error;
84
- if (!error)
93
+ const error = isRecord(body) ? body.error : undefined;
94
+ if (!isRecord(error)) {
85
95
  return false;
86
- if (error.code === 401 || error.code === 403)
96
+ }
97
+ if (error.code === 401 || error.code === 403) {
87
98
  return true;
99
+ }
88
100
  return (typeof error.message === 'string' &&
89
101
  /unauthori[sz]ed|forbidden|token.*expired/i.test(error.message));
90
102
  }
@@ -10,12 +10,7 @@ export function credentialGrants(catalog, skills) {
10
10
  if (!loaded.has(entry.name) || entry.allowList.length === 0)
11
11
  continue;
12
12
  for (const key of credentialSlots(entry).flat()) {
13
- const list = map[key] ?? [];
14
- for (const host of entry.allowList) {
15
- if (!list.includes(host))
16
- list.push(host);
17
- }
18
- map[key] = list;
13
+ map[key] = [...new Set([...(map[key] ?? []), ...entry.allowList])];
19
14
  }
20
15
  }
21
16
  return map;
@@ -3,6 +3,10 @@ export declare function markCredentialValid(key: string, agentId?: string | null
3
3
  export declare function recordCredentialHealth(key: string, status: number, agentId?: string | null): void;
4
4
  export declare function isCredentialRejected(key: string, agentId?: string | null, skill?: string | null): boolean;
5
5
  export declare function credentialLastProbedAt(key: string, agentId?: string | null, skill?: string | null): number | undefined;
6
- export declare function setCredentialLastProbedAt(key: string, at: number, agentId?: string | null, skill?: string | null): void;
6
+ export interface CredentialScope {
7
+ readonly agentId?: string | null;
8
+ readonly skill?: string | null;
9
+ }
10
+ export declare function setCredentialLastProbedAt(key: string, at: number, { agentId, skill }?: CredentialScope): void;
7
11
  export declare function resetCredentialHealth(key: string, agentId?: string | null, skill?: string | null): void;
8
12
  export declare function resetAllCredentialHealth(): void;
@@ -10,8 +10,9 @@ export function markCredentialRejected(key, agentId, skill) {
10
10
  }
11
11
  export function markCredentialValid(key, agentId, skill) {
12
12
  rejected.delete(scopedKey(key, agentId, skill));
13
- if (skill)
13
+ if (skill) {
14
14
  rejected.delete(scopedKey(key, agentId));
15
+ }
15
16
  }
16
17
  export function recordCredentialHealth(key, status, agentId) {
17
18
  if (status === 401 || status === 403) {
@@ -19,8 +20,9 @@ export function recordCredentialHealth(key, status, agentId) {
19
20
  markCredentialRejected(key, agentId);
20
21
  }
21
22
  else if (status < 400) {
22
- if (isCredentialRejected(key, agentId))
23
+ if (isCredentialRejected(key, agentId)) {
23
24
  hlog('credential recovered', { key });
25
+ }
24
26
  markCredentialValid(key, agentId);
25
27
  }
26
28
  }
@@ -32,7 +34,7 @@ export function isCredentialRejected(key, agentId, skill) {
32
34
  export function credentialLastProbedAt(key, agentId, skill) {
33
35
  return lastProbedAt.get(scopedKey(key, agentId, skill));
34
36
  }
35
- export function setCredentialLastProbedAt(key, at, agentId, skill) {
37
+ export function setCredentialLastProbedAt(key, at, { agentId, skill } = {}) {
36
38
  lastProbedAt.set(scopedKey(key, agentId, skill), at);
37
39
  }
38
40
  export function resetCredentialHealth(key, agentId, skill) {
@@ -1,12 +1,12 @@
1
1
  import { parseManifestBlock } from './manifest-parse.js';
2
2
  const FRONT_MATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
3
3
  const FIELD_RE = /^([A-Za-z_][\w-]*):(.*)$/;
4
- const LIST_FIELDS = new Set(['tools', 'platform', 'credentials', 'allow_list', 'aliases']);
5
4
  export function parseSkillFrontMatter(raw) {
6
5
  try {
7
6
  const match = FRONT_MATTER_RE.exec(raw);
8
- if (!match)
7
+ if (!match) {
9
8
  return { meta: {}, body: raw };
9
+ }
10
10
  const block = match[1] ?? '';
11
11
  const meta = { ...parseFields(block), ...parseManifestBlock(block) };
12
12
  return { meta, body: (match[2] ?? '').trim() };
@@ -31,19 +31,24 @@ function parseFields(block) {
31
31
  const meta = {};
32
32
  for (const line of unwrap(block.split(/\r?\n/))) {
33
33
  const field = FIELD_RE.exec(line);
34
- if (!field)
34
+ if (!field) {
35
35
  continue;
36
+ }
36
37
  const key = field[1] ?? '';
37
38
  const value = (field[2] ?? '').trim();
38
- if (!value)
39
+ if (!value) {
39
40
  continue;
41
+ }
40
42
  if (key === 'allow_list') {
41
43
  meta.allowList = parseList(value);
42
44
  }
43
45
  else if (key === 'mcp_reads') {
44
46
  meta.mcpReads = parseList(value);
45
47
  }
46
- else if (LIST_FIELDS.has(key)) {
48
+ else if (key === 'tools' ||
49
+ key === 'platform' ||
50
+ key === 'credentials' ||
51
+ key === 'aliases') {
47
52
  meta[key] = parseList(value);
48
53
  }
49
54
  else if (key === 'name' || key === 'description') {