@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,8 +1,9 @@
1
1
  import { raceAbort } from '../../helpers/race-abort.js';
2
- import { parseObjectArg } from '../http-request/utils.js';
2
+ import { parseObjectArg } from '../http-request/request.js';
3
3
  export function credentialRecord(value) {
4
- if (typeof value === 'string')
4
+ if (typeof value === 'string') {
5
5
  return value ? { token: value } : null;
6
+ }
6
7
  return value?.token ? value : null;
7
8
  }
8
9
  export function isCredentialExpired(record, now = Date.now()) {
@@ -23,8 +24,9 @@ function matchesPattern(url, pattern) {
23
24
  catch {
24
25
  return url.href.startsWith(raw);
25
26
  }
26
- if (url.protocol !== base.protocol || url.host !== base.host)
27
+ if (url.protocol !== base.protocol || url.host !== base.host) {
27
28
  return false;
29
+ }
28
30
  return glob ? url.pathname.startsWith(base.pathname) : pathAllowed(url.pathname, base.pathname);
29
31
  }
30
32
  export function urlAllowed(url, patterns) {
@@ -40,10 +42,12 @@ export function isCredentialUrlAllowed(target, patterns) {
40
42
  }
41
43
  export function parseAuth(v) {
42
44
  const parsed = parseObjectArg(v, 'auth');
43
- if (!parsed.ok)
45
+ if (!parsed.ok) {
44
46
  return parsed;
45
- if (!parsed.value)
47
+ }
48
+ if (!parsed.value) {
46
49
  return { ok: true, value: undefined };
50
+ }
47
51
  const { type, tokenCredentialKey } = parsed.value;
48
52
  if (type !== undefined && type !== 'bearer') {
49
53
  return { ok: false, error: `unsupported auth type: ${String(type)}` };
@@ -69,8 +73,9 @@ async function connectedCredentials(keys, credentialStore, ctx) {
69
73
  const connected = [];
70
74
  for (const key of keys) {
71
75
  const record = credentialRecord(await credentialStore(key, ctx));
72
- if (record)
76
+ if (record) {
73
77
  connected.push({ token: record.token, key });
78
+ }
74
79
  }
75
80
  return connected;
76
81
  }
@@ -79,7 +84,7 @@ function ambiguous(keys) {
79
84
  error: `multiple credentials match this URL; set auth.tokenCredentialKey to one of ${keys.join(', ')}`
80
85
  };
81
86
  }
82
- async function resolveGuessedKey(key, url, credentialStore, credentialAllowList, ctx) {
87
+ async function resolveGuessedKey(key, url, { credentialStore, credentialAllowList = {}, ctx }) {
83
88
  const granted = grantedKeys(url, credentialAllowList);
84
89
  if (granted.length === 0) {
85
90
  return {
@@ -92,14 +97,16 @@ async function resolveGuessedKey(key, url, credentialStore, credentialAllowList,
92
97
  error: `unknown credential key ${key}; no connected credential for ${url.host} (${granted.join(', ')}). Tell the user to connect it in Skills; do not retry`
93
98
  };
94
99
  }
95
- if (rest.length > 0)
100
+ if (rest.length > 0) {
96
101
  return ambiguous([first, ...rest].map((c) => c.key));
102
+ }
97
103
  return first;
98
104
  }
99
- async function resolveDeclaredKey(key, url, credentialStore, credentialAllowList, ctx) {
105
+ async function resolveDeclaredKey(key, url, { credentialStore, credentialAllowList, ctx }) {
100
106
  const entry = credentialAllowList?.[key];
101
- if (!entry)
107
+ if (!entry) {
102
108
  return null;
109
+ }
103
110
  const patterns = Array.isArray(entry) ? entry : [entry];
104
111
  if (!urlAllowed(url, patterns)) {
105
112
  return { error: `credential ${key} is not allowed for URL ${url.href}` };
@@ -114,37 +121,42 @@ async function resolveDeclaredKey(key, url, credentialStore, credentialAllowList
114
121
  }
115
122
  export async function resolveAuth(auth, url, credentialStore, credentialAllowList, ctx) {
116
123
  const key = auth.tokenCredentialKey;
117
- if (!credentialStore)
124
+ if (!credentialStore) {
118
125
  return { error: 'credentials not configured' };
119
- return ((await resolveDeclaredKey(key, url, credentialStore, credentialAllowList, ctx)) ??
120
- resolveGuessedKey(key, url, credentialStore, credentialAllowList ?? {}, ctx));
126
+ }
127
+ const access = { credentialStore, credentialAllowList, ctx };
128
+ return (await resolveDeclaredKey(key, url, access)) ?? resolveGuessedKey(key, url, access);
121
129
  }
122
130
  export async function resolveAutoAuth(url, credentialStore, credentialAllowList, ctx) {
123
131
  if (!credentialStore || !credentialAllowList)
124
132
  return null;
125
133
  const connected = await connectedCredentials(grantedKeys(url, credentialAllowList), credentialStore, ctx);
126
- if (connected.length > 1)
134
+ if (connected.length > 1) {
127
135
  return ambiguous(connected.map((c) => c.key));
136
+ }
128
137
  return connected[0] ?? null;
129
138
  }
130
139
  export async function resolveBearerHeader(auth, url, credentialStore, credentialAllowList, ctx, signal) {
131
140
  if (auth) {
132
141
  const resolved = await raceAbort(resolveAuth(auth, url, credentialStore, credentialAllowList, ctx), signal);
133
- if ('error' in resolved)
142
+ if ('error' in resolved) {
134
143
  return { error: resolved.error };
144
+ }
135
145
  return { header: `Bearer ${resolved.token}`, credentialKey: resolved.key };
136
146
  }
137
147
  const resolved = await raceAbort(resolveAutoAuth(url, credentialStore, credentialAllowList, ctx), signal);
138
- if (resolved && 'error' in resolved)
148
+ if (resolved && 'error' in resolved) {
139
149
  return resolved;
150
+ }
140
151
  return resolved
141
152
  ? { header: `Bearer ${resolved.token}`, credentialKey: resolved.key }
142
153
  : { header: null };
143
154
  }
144
155
  export async function resolveRedirectBearerHeader(auth, url, credentialStore, credentialAllowList, ctx, signal) {
145
- if (!auth || !credentialStore)
156
+ if (!auth || !credentialStore) {
146
157
  return { header: null };
147
- const resolved = await raceAbort(resolveDeclaredKey(auth.tokenCredentialKey, url, credentialStore, credentialAllowList, ctx), signal);
158
+ }
159
+ const resolved = await raceAbort(resolveDeclaredKey(auth.tokenCredentialKey, url, { credentialStore, credentialAllowList, ctx }), signal);
148
160
  return !resolved || 'error' in resolved
149
161
  ? { header: null }
150
162
  : { header: `Bearer ${resolved.token}`, credentialKey: resolved.key };
@@ -2,8 +2,9 @@ import type { SkillRequires } from './manifest.ts';
2
2
  export type BinVersionState = 'ok' | 'too-old' | 'unknown';
3
3
  export declare function binOnPath(bin: string, platform?: string): boolean;
4
4
  export declare function missingBins(bins: readonly string[], platform?: string, probe?: (bin: string, platform?: string) => boolean): string[];
5
- export declare function probeBinVersions(requires: SkillRequires | undefined, opts: {
5
+ export interface ProbeBinVersionsOptions {
6
6
  platform?: string;
7
7
  run: (command: string) => Promise<string | null>;
8
8
  binPresent?: (bin: string) => boolean | Promise<boolean>;
9
- }): Promise<Map<string, BinVersionState>>;
9
+ }
10
+ export declare function probeBinVersions(requires: SkillRequires | undefined, opts: ProbeBinVersionsOptions): Promise<Map<string, BinVersionState>>;
@@ -29,20 +29,27 @@ function parseVersion(text) {
29
29
  const m = text.match(/(\d+)\.(\d+)(?:\.(\d+))?/);
30
30
  return m ? [Number(m[1]), Number(m[2]), Number(m[3] ?? 0)] : null;
31
31
  }
32
+ function versionState(found, min) {
33
+ if (!found || !min)
34
+ return 'unknown';
35
+ return isBelow(found, min) ? 'too-old' : 'ok';
36
+ }
32
37
  function isBelow(found, min) {
33
38
  for (let i = 0; i < Math.max(found.length, min.length); i++) {
34
39
  const f = found[i] ?? 0;
35
40
  const m = min[i] ?? 0;
36
- if (f !== m)
41
+ if (f !== m) {
37
42
  return f < m;
43
+ }
38
44
  }
39
45
  return false;
40
46
  }
41
47
  export async function probeBinVersions(requires, opts) {
42
48
  const states = new Map();
43
49
  const mins = requires?.binMinVersions;
44
- if (!mins)
50
+ if (!mins) {
45
51
  return states;
52
+ }
46
53
  const binPresent = opts.binPresent ?? ((bin) => binOnPath(bin, opts.platform));
47
54
  for (const [bin, spec] of Object.entries(mins)) {
48
55
  if (!spec.command || !(await binPresent(bin)))
@@ -50,7 +57,7 @@ export async function probeBinVersions(requires, opts) {
50
57
  const output = await opts.run(spec.command);
51
58
  const found = output === null ? null : parseVersion(output);
52
59
  const min = parseVersion(spec.min);
53
- states.set(bin, found && min ? (isBelow(found, min) ? 'too-old' : 'ok') : 'unknown');
60
+ states.set(bin, versionState(found, min));
54
61
  }
55
62
  return states;
56
63
  }
@@ -15,35 +15,42 @@ export function ensureBundledSkillsDir() {
15
15
  }
16
16
  async function materialize() {
17
17
  const dir = userTmpPath('qvac-harness-skills-' + BUNDLED_SKILLS_HASH);
18
- if (await validTree(dir))
18
+ if (await validTree(dir)) {
19
19
  return dir;
20
+ }
20
21
  const staging = `${dir}-staging-${process.pid}-${randomSuffix()}`;
21
22
  await fs.promises.mkdir(staging, { recursive: true });
22
- if (os.platform() !== 'win32')
23
+ if (os.platform() !== 'win32') {
23
24
  await fs.promises.chmod(staging, 0o700);
25
+ }
24
26
  try {
25
27
  await writeTree(staging);
26
28
  if (!(await validTree(staging))) {
27
29
  throw new Error(`bundled skills staging dir ${staging} failed validation`);
28
30
  }
29
- if (await tryRename(staging, dir))
31
+ if (await tryRename(staging, dir)) {
30
32
  return dir;
31
- if (await validTree(dir))
33
+ }
34
+ if (await validTree(dir)) {
32
35
  return dir;
36
+ }
33
37
  const trash = `${dir}.trash-${process.pid}-${randomSuffix()}`;
34
38
  try {
35
39
  await fs.promises.rename(dir, trash);
36
40
  }
37
41
  catch (err) {
38
- if (await validTree(dir))
42
+ if (await validTree(dir)) {
39
43
  return dir;
44
+ }
40
45
  throw occupiedError(dir, err);
41
46
  }
42
47
  void fs.promises.rm(trash, { recursive: true, force: true });
43
- if (await tryRename(staging, dir))
48
+ if (await tryRename(staging, dir)) {
44
49
  return dir;
45
- if (await validTree(dir))
50
+ }
51
+ if (await validTree(dir)) {
46
52
  return dir;
53
+ }
47
54
  throw tamperError(dir);
48
55
  }
49
56
  finally {
@@ -81,12 +88,14 @@ async function validTree(dir) {
81
88
  try {
82
89
  if (os.platform() !== 'win32') {
83
90
  const stat = await fs.promises.lstat(dir);
84
- if (!stat.isDirectory() || (stat.mode & 0o077) !== 0)
91
+ if (!stat.isDirectory() || (stat.mode & 0o077) !== 0) {
85
92
  return false;
93
+ }
86
94
  }
87
95
  const files = await collect(dir, '');
88
- if (files === null)
96
+ if (files === null) {
89
97
  return false;
98
+ }
90
99
  return hashBundledSkills(files) === BUNDLED_SKILLS_HASH;
91
100
  }
92
101
  catch {
@@ -99,8 +108,9 @@ async function collect(dir, prefix) {
99
108
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
100
109
  if (entry.isDirectory()) {
101
110
  const nested = await collect(path.join(dir, entry.name), rel);
102
- if (nested === null)
111
+ if (nested === null) {
103
112
  return null;
113
+ }
104
114
  files.push(...nested);
105
115
  }
106
116
  else if (entry.isFile()) {
@@ -1,4 +1,5 @@
1
- export declare function hashBundledSkills(files: ReadonlyArray<{
1
+ export interface BundledFile {
2
2
  path: string;
3
3
  content: string;
4
- }>): string;
4
+ }
5
+ export declare function hashBundledSkills(files: ReadonlyArray<BundledFile>): string;
@@ -1,7 +1,7 @@
1
1
  import crypto from 'crypto';
2
2
  export function hashBundledSkills(files) {
3
3
  const hash = crypto.createHash('sha256');
4
- const sorted = [...files].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
4
+ const sorted = [...files].sort(byPath);
5
5
  for (const file of sorted) {
6
6
  hash.update(file.path);
7
7
  hash.update('\0');
@@ -10,3 +10,8 @@ export function hashBundledSkills(files) {
10
10
  }
11
11
  return hash.digest('hex').slice(0, 16);
12
12
  }
13
+ function byPath(a, b) {
14
+ if (a.path < b.path)
15
+ return -1;
16
+ return a.path > b.path ? 1 : 0;
17
+ }
@@ -46,10 +46,11 @@ export interface ResolveSkillStatusOptions {
46
46
  skipCredentialProbe?: boolean;
47
47
  fetchImpl?: CredentialCheckFetch;
48
48
  }
49
- export declare function skillsEligibleForCredentialProbe(catalog: readonly SkillCatalogEntry[], { platform, installedTools }?: {
49
+ export interface CredentialProbeEligibilityOptions {
50
50
  platform?: string | undefined;
51
51
  installedTools?: ReadonlySet<string> | undefined;
52
- }): SkillCatalogEntry[];
52
+ }
53
+ export declare function skillsEligibleForCredentialProbe(catalog: readonly SkillCatalogEntry[], { platform, installedTools }?: CredentialProbeEligibilityOptions): SkillCatalogEntry[];
53
54
  export declare function resolveSkillStatuses(catalog: readonly SkillCatalogEntry[], { installedTools, credentialStore, settingsStore, platform, agentId, activeProfile, binVersions, refresh, skipCredentialProbe, fetchImpl }?: ResolveSkillStatusOptions): Promise<ResolvedSkillCatalogEntry[]>;
54
55
  export interface LoadSkillCatalogOptions {
55
56
  platform?: string | null;
@@ -35,7 +35,7 @@ export function resolveSkillStatuses(catalog, { installedTools, credentialStore,
35
35
  const probeCatalog = skillsEligibleForCredentialProbe(catalog, { platform, installedTools });
36
36
  const checked = skipCredentialProbe
37
37
  ? Promise.resolve()
38
- : validateCredentialChecks(probeCatalog, credentialStore, agentId, fetchImpl, { refresh });
38
+ : validateCredentialChecks(probeCatalog, { credentialStore, agentId, fetchImpl, refresh });
39
39
  return checked.then(() => Promise.all(catalog.map(async (entry) => withSetup(entry, installedTools && !isToolSupported(entry, installedTools)
40
40
  ? SKILL_STATE.unsupported
41
41
  : await resolveSkillState(entry, {
@@ -52,9 +52,9 @@ function withSetup(entry, state) {
52
52
  const setup = deriveSetup(entry, state);
53
53
  return {
54
54
  ...rest,
55
- ...(requires ? { requires: stripCredentialChecks(requires) } : {}),
56
- ...(install ? { install } : {}),
57
- ...(setup ? { setup } : {}),
55
+ requires: requires ? stripCredentialChecks(requires) : undefined,
56
+ install,
57
+ setup,
58
58
  status: state
59
59
  };
60
60
  }
@@ -82,8 +82,8 @@ function mergeOverlay(base, overlay) {
82
82
  credentials: base.credentials,
83
83
  allowList: base.allowList,
84
84
  platform: base.platform,
85
- ...(base.operations ? { operations: base.operations } : {}),
86
- ...(base.mcpReads ? { mcpReads: base.mcpReads } : {})
85
+ operations: base.operations,
86
+ mcpReads: base.mcpReads
87
87
  };
88
88
  }
89
89
  const OVERLAY_DEFAULT_PLATFORMS = ['darwin', 'linux', 'win32', 'ios', 'android'];
@@ -99,9 +99,11 @@ async function loadRoot(skillsDir, origin) {
99
99
  }
100
100
  const loaded = await Promise.all(dirs.map((dir) => loadEntry(skillsDir, dir, origin)));
101
101
  const byName = new Map();
102
- for (const entry of loaded)
103
- if (entry)
102
+ for (const entry of loaded) {
103
+ if (entry) {
104
104
  byName.set(entry.name, entry);
105
+ }
106
+ }
105
107
  return byName;
106
108
  }
107
109
  export function mcpReadMethods(catalog) {
@@ -113,11 +115,13 @@ export function mcpReadMethods(catalog) {
113
115
  continue;
114
116
  for (const url of entry.allowList) {
115
117
  const host = hostnameOf(url);
116
- if (!host)
118
+ if (!host) {
117
119
  continue;
120
+ }
118
121
  const methods = byHost.get(host) ?? new Set();
119
- for (const method of entry.mcpReads)
122
+ for (const method of entry.mcpReads) {
120
123
  methods.add(method);
124
+ }
121
125
  byHost.set(host, methods);
122
126
  }
123
127
  }
@@ -134,6 +138,11 @@ function hostnameOf(url) {
134
138
  export function detectPlatform() {
135
139
  return platform();
136
140
  }
141
+ function platformsOf(declared, origin) {
142
+ if (declared && declared.length > 0)
143
+ return declared;
144
+ return origin === 'overlay' ? OVERLAY_DEFAULT_PLATFORMS : [];
145
+ }
137
146
  async function loadEntry(skillsDir, dir, origin) {
138
147
  try {
139
148
  const skillDir = path.join(skillsDir, dir);
@@ -143,31 +152,27 @@ async function loadEntry(skillsDir, dir, origin) {
143
152
  const cli = await loadSkillCli(skillDir, tools);
144
153
  const referenceFiles = await loadReferenceFiles(skillDir);
145
154
  const operations = origin === 'overlay' ? [] : await loadOperations(skillDir, dir);
146
- const platform = meta.platform && meta.platform.length > 0
147
- ? meta.platform
148
- : origin === 'overlay'
149
- ? OVERLAY_DEFAULT_PLATFORMS
150
- : [];
155
+ const platform = platformsOf(meta.platform, origin);
151
156
  return {
152
157
  name: dir,
153
158
  description: meta.description ?? '',
154
- ...(meta.aliases ? { aliases: meta.aliases } : {}),
155
- ...(meta.preloadOnName === false ? { preloadOnName: false } : {}),
159
+ aliases: meta.aliases,
160
+ preloadOnName: meta.preloadOnName === false ? false : undefined,
156
161
  tools,
157
162
  credentials: meta.credentials ?? [],
158
163
  allowList: meta.allowList ?? [],
159
- ...(meta.mcpReads ? { mcpReads: meta.mcpReads } : {}),
164
+ mcpReads: meta.mcpReads,
160
165
  platform,
161
- ...(meta.requires ? { requires: meta.requires } : {}),
162
- ...(meta.install ? { install: meta.install } : {}),
163
- ...(meta.setup ? { setup: meta.setup } : {}),
164
- ...(cli ? { cliValidator: buildCliValidator(cli) } : {}),
165
- ...(meta.stub !== undefined ? { stub: meta.stub } : {}),
166
- ...(meta.minCapabilityProfile ? { minCapabilityProfile: meta.minCapabilityProfile } : {}),
167
- ...(meta.emoji ? { emoji: meta.emoji } : {}),
168
- ...(referenceFiles.length ? { referenceFiles } : {}),
169
- ...(operations.length ? { operations } : {}),
170
- ...(origin ? { origin } : {})
166
+ requires: meta.requires,
167
+ install: meta.install,
168
+ setup: meta.setup,
169
+ cliValidator: cli ? buildCliValidator(cli) : undefined,
170
+ stub: meta.stub,
171
+ minCapabilityProfile: meta.minCapabilityProfile || undefined,
172
+ emoji: meta.emoji || undefined,
173
+ referenceFiles: referenceFiles.length ? referenceFiles : undefined,
174
+ operations: operations.length ? operations : undefined,
175
+ origin
171
176
  };
172
177
  }
173
178
  catch {
@@ -1,9 +1,10 @@
1
1
  import type { JsonSchema } from './cli-schema-types.ts';
2
- export declare function walkCommands(argv: readonly string[], schema: JsonSchema): {
2
+ export interface CommandWalk {
3
3
  node: JsonSchema;
4
4
  pathSegs: string[];
5
5
  index: number;
6
- };
6
+ }
7
+ export declare function walkCommands(argv: readonly string[], schema: JsonSchema): CommandWalk;
7
8
  export declare function argvToObject(argv: readonly string[], schema: JsonSchema): Record<string, unknown> | string;
8
9
  export declare function objectProps(schema: JsonSchema): Readonly<Record<string, JsonSchema>>;
9
10
  export declare function isObjectSchema(schema: JsonSchema): boolean;
@@ -4,11 +4,13 @@ export function walkCommands(argv, schema) {
4
4
  let i = 0;
5
5
  while (i < argv.length) {
6
6
  const tok = argv[i] ?? '';
7
- if (isParamToken(tok))
7
+ if (isParamToken(tok)) {
8
8
  break;
9
+ }
9
10
  const child = objectProps(node)[tok];
10
- if (!child || !isObjectSchema(child))
11
+ if (!child || !isObjectSchema(child)) {
11
12
  break;
13
+ }
12
14
  pathSegs.push(tok);
13
15
  node = child;
14
16
  i++;
@@ -18,13 +20,10 @@ export function walkCommands(argv, schema) {
18
20
  export function argvToObject(argv, schema) {
19
21
  const { node, pathSegs, index } = walkCommands(argv, schema);
20
22
  const leaf = parseParams(argv.slice(index), node);
21
- if (typeof leaf === 'string')
23
+ if (typeof leaf === 'string') {
22
24
  return leaf;
23
- let out = leaf;
24
- for (let p = pathSegs.length - 1; p >= 0; p--) {
25
- out = { [pathSegs[p]]: out };
26
25
  }
27
- return out;
26
+ return pathSegs.reduceRight((inner, seg) => ({ [seg]: inner }), leaf);
28
27
  }
29
28
  export function objectProps(schema) {
30
29
  return schema.properties ?? {};
@@ -37,13 +36,25 @@ function isParamToken(tok) {
37
36
  return false;
38
37
  if (tok.startsWith('-'))
39
38
  return true;
40
- if (tok.includes('='))
39
+ if (tok.includes('=')) {
41
40
  return true;
41
+ }
42
42
  return false;
43
43
  }
44
+ function flagParts(tok) {
45
+ if (!tok.startsWith('--')) {
46
+ return { key: tok.slice(1), inline: undefined };
47
+ }
48
+ const body = tok.slice(2);
49
+ const ieq = body.indexOf('=');
50
+ if (ieq < 0) {
51
+ return { key: body, inline: undefined };
52
+ }
53
+ return { key: body.slice(0, ieq), inline: body.slice(ieq + 1) };
54
+ }
44
55
  function parseParams(tokens, schema) {
45
56
  const props = objectProps(schema);
46
- const propKeys = new Set(Object.keys(props));
57
+ const propSchemas = new Map(Object.entries(props));
47
58
  const boolKeys = new Set(Object.entries(props)
48
59
  .filter(([, s]) => s.type === 'boolean')
49
60
  .map(([k]) => k));
@@ -59,67 +70,58 @@ function parseParams(tokens, schema) {
59
70
  const eq = tok.indexOf('=');
60
71
  if (eq > 0 && !tok.startsWith('-')) {
61
72
  const key = tok.slice(0, eq);
62
- if (propKeys.has(key)) {
63
- out[key] = coerce(tok.slice(eq + 1), props[key]);
73
+ const keySchema = propSchemas.get(key);
74
+ if (keySchema !== undefined) {
75
+ out[key] = coerce(tok.slice(eq + 1), keySchema);
64
76
  i++;
65
77
  continue;
66
78
  }
67
- if (!canAbsorb)
79
+ if (!canAbsorb) {
68
80
  return `unknown parameter "${key}"`;
69
- }
70
- if (tok.startsWith('-')) {
71
- let key;
72
- let inline;
73
- if (tok.startsWith('--')) {
74
- const body = tok.slice(2);
75
- const ieq = body.indexOf('=');
76
- if (ieq >= 0) {
77
- key = body.slice(0, ieq);
78
- inline = body.slice(ieq + 1);
79
- }
80
- else
81
- key = body;
82
81
  }
83
- else {
84
- key = tok.slice(1);
82
+ }
83
+ const flag = tok.startsWith('-') ? flagParts(tok) : null;
84
+ const flagSchema = flag ? propSchemas.get(flag.key) : undefined;
85
+ if (flag && flagSchema !== undefined) {
86
+ const { key, inline } = flag;
87
+ if (boolKeys.has(key)) {
88
+ out[key] = inline !== undefined ? inline !== 'false' && inline !== '0' : true;
89
+ i++;
90
+ continue;
85
91
  }
86
- if (propKeys.has(key)) {
87
- if (boolKeys.has(key)) {
88
- out[key] = inline !== undefined ? inline !== 'false' && inline !== '0' : true;
89
- i++;
90
- continue;
91
- }
92
- if (inline !== undefined) {
93
- out[key] = coerce(inline, props[key]);
94
- i++;
95
- continue;
96
- }
97
- const next = tokens[i + 1];
98
- if (next === undefined || next.startsWith('-')) {
99
- return `flag --${key} requires a value`;
100
- }
101
- out[key] = coerce(next, props[key]);
102
- i += 2;
92
+ if (inline !== undefined) {
93
+ out[key] = coerce(inline, flagSchema);
94
+ i++;
103
95
  continue;
104
96
  }
105
- if (!canAbsorb)
106
- return `unknown flag "--${key}"`;
97
+ const next = tokens[i + 1];
98
+ if (next === undefined || next.startsWith('-')) {
99
+ return `flag --${key} requires a value`;
100
+ }
101
+ out[key] = coerce(next, flagSchema);
102
+ i += 2;
103
+ continue;
104
+ }
105
+ if (flag && !canAbsorb) {
106
+ return `unknown flag "--${flag.key}"`;
107
107
  }
108
108
  if (boolKeys.has(tok)) {
109
109
  out[tok] = true;
110
110
  i++;
111
111
  continue;
112
112
  }
113
- if (propKeys.has(tok) && props[tok]?.type === 'string' && !canAbsorb) {
113
+ if (propSchemas.get(tok)?.type === 'string' && !canAbsorb) {
114
114
  out[tok] = '';
115
115
  i++;
116
116
  continue;
117
117
  }
118
- if (posIdx < positionals.length) {
119
- const name = positionals[posIdx];
120
- if (!propKeys.has(name))
118
+ const name = positionals[posIdx];
119
+ if (name !== undefined) {
120
+ const nameSchema = propSchemas.get(name);
121
+ if (nameSchema === undefined) {
121
122
  return `x-positionals names unknown property "${name}"`;
122
- out[name] = coerce(tok, props[name]);
123
+ }
124
+ out[name] = coerce(tok, nameSchema);
123
125
  posIdx++;
124
126
  i++;
125
127
  continue;
@@ -131,8 +133,9 @@ function parseParams(tokens, schema) {
131
133
  }
132
134
  return `unexpected argument "${tok}"`;
133
135
  }
134
- if (restName && restVals.length > 0)
136
+ if (restName && restVals.length > 0) {
135
137
  out[restName] = restVals;
138
+ }
136
139
  return out;
137
140
  }
138
141
  function coerce(value, schema) {