@qvac/harness 0.1.0 → 0.1.1

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 (460) hide show
  1. package/dist/harness.bundle +8 -59
  2. package/dist/prebuilds-manifest.json +0 -8
  3. package/dist-lib/index.d.ts +240 -0
  4. package/dist-lib/index.js +1063 -0
  5. package/dist-lib/lib/audio-transcode-bare.d.ts +2 -0
  6. package/dist-lib/lib/audio-transcode-bare.js +145 -0
  7. package/dist-lib/lib/audio-transcode-node.d.ts +2 -0
  8. package/dist-lib/lib/audio-transcode-node.js +6 -0
  9. package/dist-lib/lib/capabilities/audio-resample.d.ts +14 -0
  10. package/dist-lib/lib/capabilities/audio-resample.js +72 -0
  11. package/dist-lib/lib/capabilities/completion.d.ts +288 -0
  12. package/dist-lib/lib/capabilities/completion.js +1077 -0
  13. package/dist-lib/lib/capabilities/download.d.ts +46 -0
  14. package/dist-lib/lib/capabilities/download.js +124 -0
  15. package/dist-lib/lib/capabilities/embed.d.ts +20 -0
  16. package/dist-lib/lib/capabilities/embed.js +13 -0
  17. package/dist-lib/lib/capabilities/kv-cache.d.ts +13 -0
  18. package/dist-lib/lib/capabilities/kv-cache.js +21 -0
  19. package/dist-lib/lib/capabilities/prompt-prefix.d.ts +6 -0
  20. package/dist-lib/lib/capabilities/prompt-prefix.js +10 -0
  21. package/dist-lib/lib/capabilities/speech-lexicon.d.ts +5 -0
  22. package/dist-lib/lib/capabilities/speech-lexicon.js +32 -0
  23. package/dist-lib/lib/capabilities/speech-text.d.ts +6 -0
  24. package/dist-lib/lib/capabilities/speech-text.js +79 -0
  25. package/dist-lib/lib/capabilities/tool-names.d.ts +3 -0
  26. package/dist-lib/lib/capabilities/tool-names.js +3 -0
  27. package/dist-lib/lib/capabilities/tool-selection.d.ts +43 -0
  28. package/dist-lib/lib/capabilities/tool-selection.js +60 -0
  29. package/dist-lib/lib/capabilities/tool-turns.d.ts +9 -0
  30. package/dist-lib/lib/capabilities/tool-turns.js +101 -0
  31. package/dist-lib/lib/capabilities/usage-breakdown.d.ts +27 -0
  32. package/dist-lib/lib/capabilities/usage-breakdown.js +44 -0
  33. package/dist-lib/lib/capabilities/vision-history.d.ts +3 -0
  34. package/dist-lib/lib/capabilities/vision-history.js +21 -0
  35. package/dist-lib/lib/capabilities/voice.d.ts +78 -0
  36. package/dist-lib/lib/capabilities/voice.js +189 -0
  37. package/dist-lib/lib/connect.d.ts +76 -0
  38. package/dist-lib/lib/connect.js +789 -0
  39. package/dist-lib/lib/context-window.d.ts +7 -0
  40. package/dist-lib/lib/context-window.js +90 -0
  41. package/dist-lib/lib/contract-types.d.ts +210 -0
  42. package/dist-lib/lib/contract-types.js +1 -0
  43. package/dist-lib/lib/diagram-repair.d.ts +21 -0
  44. package/dist-lib/lib/diagram-repair.js +58 -0
  45. package/dist-lib/lib/dns-lookup.d.ts +1 -0
  46. package/dist-lib/lib/dns-lookup.js +13 -0
  47. package/dist-lib/lib/error-fields.d.ts +2 -0
  48. package/dist-lib/lib/error-fields.js +8 -0
  49. package/dist-lib/lib/fetch-node.d.ts +1 -0
  50. package/dist-lib/lib/fetch-node.js +1 -0
  51. package/dist-lib/lib/hardware/capability-probe.d.ts +9 -0
  52. package/dist-lib/lib/hardware/capability-probe.js +99 -0
  53. package/dist-lib/lib/hardware/gpu-classify.d.ts +2 -0
  54. package/dist-lib/lib/hardware/gpu-classify.js +32 -0
  55. package/dist-lib/lib/hardware/gpu-probe-addon.d.ts +2 -0
  56. package/dist-lib/lib/hardware/gpu-probe-addon.js +42 -0
  57. package/dist-lib/lib/hardware/gpu-stats.bare.d.ts +1 -0
  58. package/dist-lib/lib/hardware/gpu-stats.bare.js +24 -0
  59. package/dist-lib/lib/hardware/gpu-stats.stub.d.ts +1 -0
  60. package/dist-lib/lib/hardware/gpu-stats.stub.js +3 -0
  61. package/dist-lib/lib/hardware/memory-budget.d.ts +8 -0
  62. package/dist-lib/lib/hardware/memory-budget.js +1 -0
  63. package/dist-lib/lib/hardware/parsers.d.ts +7 -0
  64. package/dist-lib/lib/hardware/parsers.js +41 -0
  65. package/dist-lib/lib/headers-bare.d.ts +1 -0
  66. package/dist-lib/lib/headers-bare.js +1 -0
  67. package/dist-lib/lib/headers-node.d.ts +4 -0
  68. package/dist-lib/lib/headers-node.js +1 -0
  69. package/dist-lib/lib/helpers/buffer-burst.d.ts +1 -0
  70. package/dist-lib/lib/helpers/buffer-burst.js +20 -0
  71. package/dist-lib/lib/helpers/control-tokens.d.ts +7 -0
  72. package/dist-lib/lib/helpers/control-tokens.js +32 -0
  73. package/dist-lib/lib/helpers/join-guard.d.ts +6 -0
  74. package/dist-lib/lib/helpers/join-guard.js +46 -0
  75. package/dist-lib/lib/helpers/markup-stream-filter.d.ts +5 -0
  76. package/dist-lib/lib/helpers/markup-stream-filter.js +75 -0
  77. package/dist-lib/lib/helpers/race-abort.d.ts +5 -0
  78. package/dist-lib/lib/helpers/race-abort.js +18 -0
  79. package/dist-lib/lib/helpers/retry-memo.d.ts +5 -0
  80. package/dist-lib/lib/helpers/retry-memo.js +12 -0
  81. package/dist-lib/lib/helpers/run-outcome.d.ts +33 -0
  82. package/dist-lib/lib/helpers/run-outcome.js +204 -0
  83. package/dist-lib/lib/helpers/spawn-path.d.ts +5 -0
  84. package/dist-lib/lib/helpers/spawn-path.js +57 -0
  85. package/dist-lib/lib/helpers/text-coalescer.d.ts +15 -0
  86. package/dist-lib/lib/helpers/text-coalescer.js +34 -0
  87. package/dist-lib/lib/helpers/thinking.d.ts +8 -0
  88. package/dist-lib/lib/helpers/thinking.js +95 -0
  89. package/dist-lib/lib/helpers/tool-call-markup.d.ts +20 -0
  90. package/dist-lib/lib/helpers/tool-call-markup.js +201 -0
  91. package/dist-lib/lib/helpers/tool-intent.d.ts +7 -0
  92. package/dist-lib/lib/helpers/tool-intent.js +21 -0
  93. package/dist-lib/lib/helpers/tool-label.d.ts +8 -0
  94. package/dist-lib/lib/helpers/tool-label.js +131 -0
  95. package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +5 -0
  96. package/dist-lib/lib/hooks/built-in/arg-repair.js +88 -0
  97. package/dist-lib/lib/hooks/built-in/egress.d.ts +5 -0
  98. package/dist-lib/lib/hooks/built-in/egress.js +29 -0
  99. package/dist-lib/lib/hooks/built-in/index.d.ts +3 -0
  100. package/dist-lib/lib/hooks/built-in/index.js +3 -0
  101. package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +10 -0
  102. package/dist-lib/lib/hooks/built-in/skill-catalog.js +17 -0
  103. package/dist-lib/lib/hooks/pipeline.d.ts +20 -0
  104. package/dist-lib/lib/hooks/pipeline.js +49 -0
  105. package/dist-lib/lib/hooks/registry.d.ts +2 -0
  106. package/dist-lib/lib/hooks/registry.js +6 -0
  107. package/dist-lib/lib/hooks/run.d.ts +5 -0
  108. package/dist-lib/lib/hooks/run.js +83 -0
  109. package/dist-lib/lib/hooks/types.d.ts +57 -0
  110. package/dist-lib/lib/hooks/types.js +1 -0
  111. package/dist-lib/lib/log.d.ts +5 -0
  112. package/dist-lib/lib/log.js +37 -0
  113. package/dist-lib/lib/model-download-progress.d.ts +22 -0
  114. package/dist-lib/lib/model-download-progress.js +95 -0
  115. package/dist-lib/lib/models/context.d.ts +5 -0
  116. package/dist-lib/lib/models/context.js +12 -0
  117. package/dist-lib/lib/models/embed-config.d.ts +14 -0
  118. package/dist-lib/lib/models/embed-config.js +31 -0
  119. package/dist-lib/lib/models/gpu-selection.d.ts +3 -0
  120. package/dist-lib/lib/models/gpu-selection.js +26 -0
  121. package/dist-lib/lib/models/kv-cache.d.ts +4 -0
  122. package/dist-lib/lib/models/kv-cache.js +6 -0
  123. package/dist-lib/lib/models/llm-presets.d.ts +10 -0
  124. package/dist-lib/lib/models/llm-presets.js +58 -0
  125. package/dist-lib/lib/models/model-catalog-constants.d.ts +29 -0
  126. package/dist-lib/lib/models/model-catalog-constants.js +103 -0
  127. package/dist-lib/lib/models/model-catalog.d.ts +125 -0
  128. package/dist-lib/lib/models/model-catalog.js +371 -0
  129. package/dist-lib/lib/models/model-delete.d.ts +18 -0
  130. package/dist-lib/lib/models/model-delete.js +47 -0
  131. package/dist-lib/lib/models/model-handle.d.ts +18 -0
  132. package/dist-lib/lib/models/model-handle.js +33 -0
  133. package/dist-lib/lib/models/model-list.d.ts +42 -0
  134. package/dist-lib/lib/models/model-list.js +123 -0
  135. package/dist-lib/lib/models/model-pool.d.ts +116 -0
  136. package/dist-lib/lib/models/model-pool.js +356 -0
  137. package/dist-lib/lib/models/model-source.d.ts +6 -0
  138. package/dist-lib/lib/models/model-source.js +21 -0
  139. package/dist-lib/lib/models/music-catalog.d.ts +12 -0
  140. package/dist-lib/lib/models/music-catalog.js +26 -0
  141. package/dist-lib/lib/models/opencl-cache.d.ts +5 -0
  142. package/dist-lib/lib/models/opencl-cache.js +50 -0
  143. package/dist-lib/lib/models/sdk-faults.d.ts +21 -0
  144. package/dist-lib/lib/models/sdk-faults.js +66 -0
  145. package/dist-lib/lib/models/tool-dialect.d.ts +2 -0
  146. package/dist-lib/lib/models/tool-dialect.js +19 -0
  147. package/dist-lib/lib/models/tts-model-default.d.ts +3 -0
  148. package/dist-lib/lib/models/tts-model-default.js +13 -0
  149. package/dist-lib/lib/no-redirect-fetch-bare.d.ts +15 -0
  150. package/dist-lib/lib/no-redirect-fetch-bare.js +59 -0
  151. package/dist-lib/lib/no-redirect-fetch-impl.d.ts +39 -0
  152. package/dist-lib/lib/no-redirect-fetch-impl.js +80 -0
  153. package/dist-lib/lib/no-redirect-fetch-node.d.ts +4 -0
  154. package/dist-lib/lib/no-redirect-fetch-node.js +52 -0
  155. package/dist-lib/lib/prompt.d.ts +22 -0
  156. package/dist-lib/lib/prompt.js +77 -0
  157. package/dist-lib/lib/queue.d.ts +9 -0
  158. package/dist-lib/lib/queue.js +48 -0
  159. package/dist-lib/lib/resolution-detector.d.ts +5 -0
  160. package/dist-lib/lib/resolution-detector.js +100 -0
  161. package/dist-lib/lib/rpc-session.d.ts +8 -0
  162. package/dist-lib/lib/rpc-session.js +20 -0
  163. package/dist-lib/lib/sdk-config-loader.node.d.ts +1 -0
  164. package/dist-lib/lib/sdk-config-loader.node.js +1 -0
  165. package/dist-lib/lib/sdk-loader.d.ts +30 -0
  166. package/dist-lib/lib/sdk-loader.js +53 -0
  167. package/dist-lib/lib/sdk-storage.d.ts +8 -0
  168. package/dist-lib/lib/sdk-storage.js +24 -0
  169. package/dist-lib/lib/serve.d.ts +3 -0
  170. package/dist-lib/lib/serve.js +612 -0
  171. package/dist-lib/lib/spawn.d.ts +62 -0
  172. package/dist-lib/lib/spawn.js +71 -0
  173. package/dist-lib/lib/staging.d.ts +4 -0
  174. package/dist-lib/lib/staging.js +28 -0
  175. package/dist-lib/lib/storage.d.ts +18 -0
  176. package/dist-lib/lib/storage.js +26 -0
  177. package/dist-lib/lib/tmp-path.d.ts +7 -0
  178. package/dist-lib/lib/tmp-path.js +17 -0
  179. package/dist-lib/lib/tool-call-display.d.ts +21 -0
  180. package/dist-lib/lib/tool-call-display.js +1 -0
  181. package/dist-lib/lib/tools/catalog.d.ts +13 -0
  182. package/dist-lib/lib/tools/catalog.js +13 -0
  183. package/dist-lib/lib/tools/create-documents.d.ts +3 -0
  184. package/dist-lib/lib/tools/create-documents.js +87 -0
  185. package/dist-lib/lib/tools/edit-documents.d.ts +3 -0
  186. package/dist-lib/lib/tools/edit-documents.js +122 -0
  187. package/dist-lib/lib/tools/edit-image.d.ts +25 -0
  188. package/dist-lib/lib/tools/edit-image.js +271 -0
  189. package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +27 -0
  190. package/dist-lib/lib/tools/exec/adapters/adapter.js +1 -0
  191. package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +26 -0
  192. package/dist-lib/lib/tools/exec/adapters/python/attachments.js +160 -0
  193. package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +7 -0
  194. package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +290 -0
  195. package/dist-lib/lib/tools/exec/adapters/python/loader.d.ts +11 -0
  196. package/dist-lib/lib/tools/exec/adapters/python/loader.js +94 -0
  197. package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +47 -0
  198. package/dist-lib/lib/tools/exec/adapters/python/memfs.js +85 -0
  199. package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +13 -0
  200. package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +129 -0
  201. package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +19 -0
  202. package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +107 -0
  203. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +75 -0
  204. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +1094 -0
  205. package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +75 -0
  206. package/dist-lib/lib/tools/exec/adapters/python/run-session.js +273 -0
  207. package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +38 -0
  208. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +102 -0
  209. package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +7 -0
  210. package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +188 -0
  211. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.d.ts +1 -0
  212. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +105 -0
  213. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +38 -0
  214. package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +41 -0
  215. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.d.ts +2 -0
  216. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.js +30 -0
  217. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +13 -0
  218. package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +45 -0
  219. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +12 -0
  220. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +20 -0
  221. package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +8 -0
  222. package/dist-lib/lib/tools/exec/obsidian/cli-process.js +74 -0
  223. package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +18 -0
  224. package/dist-lib/lib/tools/exec/obsidian/cli.js +153 -0
  225. package/dist-lib/lib/tools/exec/obsidian/command.d.ts +5 -0
  226. package/dist-lib/lib/tools/exec/obsidian/command.js +18 -0
  227. package/dist-lib/lib/tools/exec/obsidian/guidance.d.ts +5 -0
  228. package/dist-lib/lib/tools/exec/obsidian/guidance.js +18 -0
  229. package/dist-lib/lib/tools/exec/obsidian/note-name.d.ts +1 -0
  230. package/dist-lib/lib/tools/exec/obsidian/note-name.js +6 -0
  231. package/dist-lib/lib/tools/exec/obsidian/output.d.ts +1 -0
  232. package/dist-lib/lib/tools/exec/obsidian/output.js +31 -0
  233. package/dist-lib/lib/tools/exec/obsidian/route.d.ts +19 -0
  234. package/dist-lib/lib/tools/exec/obsidian/route.js +85 -0
  235. package/dist-lib/lib/tools/exec/obsidian/safe-path.d.ts +3 -0
  236. package/dist-lib/lib/tools/exec/obsidian/safe-path.js +56 -0
  237. package/dist-lib/lib/tools/exec/obsidian/vault-create.d.ts +1 -0
  238. package/dist-lib/lib/tools/exec/obsidian/vault-create.js +40 -0
  239. package/dist-lib/lib/tools/exec/obsidian/vault-fs.d.ts +3 -0
  240. package/dist-lib/lib/tools/exec/obsidian/vault-fs.js +57 -0
  241. package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +20 -0
  242. package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +171 -0
  243. package/dist-lib/lib/tools/exec/obsidian/vault-read.d.ts +11 -0
  244. package/dist-lib/lib/tools/exec/obsidian/vault-read.js +119 -0
  245. package/dist-lib/lib/tools/exec/obsidian/vault-write.d.ts +7 -0
  246. package/dist-lib/lib/tools/exec/obsidian/vault-write.js +134 -0
  247. package/dist-lib/lib/tools/exec/runner.d.ts +62 -0
  248. package/dist-lib/lib/tools/exec/runner.js +87 -0
  249. package/dist-lib/lib/tools/exec/scope.d.ts +3 -0
  250. package/dist-lib/lib/tools/exec/scope.js +97 -0
  251. package/dist-lib/lib/tools/exec/shell-argv.d.ts +2 -0
  252. package/dist-lib/lib/tools/exec/shell-argv.js +48 -0
  253. package/dist-lib/lib/tools/exec.d.ts +29 -0
  254. package/dist-lib/lib/tools/exec.js +459 -0
  255. package/dist-lib/lib/tools/file-glob.d.ts +15 -0
  256. package/dist-lib/lib/tools/file-glob.js +112 -0
  257. package/dist-lib/lib/tools/fs/drive.d.ts +26 -0
  258. package/dist-lib/lib/tools/fs/drive.js +1 -0
  259. package/dist-lib/lib/tools/fs/glob.d.ts +1 -0
  260. package/dist-lib/lib/tools/fs/glob.js +34 -0
  261. package/dist-lib/lib/tools/fs/local.d.ts +2 -0
  262. package/dist-lib/lib/tools/fs/local.js +29 -0
  263. package/dist-lib/lib/tools/fs/read.d.ts +2 -0
  264. package/dist-lib/lib/tools/fs/read.js +17 -0
  265. package/dist-lib/lib/tools/fs/remote-protocol.d.ts +40 -0
  266. package/dist-lib/lib/tools/fs/remote-protocol.js +1 -0
  267. package/dist-lib/lib/tools/fs/remote.d.ts +17 -0
  268. package/dist-lib/lib/tools/fs/remote.js +131 -0
  269. package/dist-lib/lib/tools/fs/scope.d.ts +37 -0
  270. package/dist-lib/lib/tools/fs/scope.js +130 -0
  271. package/dist-lib/lib/tools/fs/walk.d.ts +15 -0
  272. package/dist-lib/lib/tools/fs/walk.js +38 -0
  273. package/dist-lib/lib/tools/fs/write.d.ts +4 -0
  274. package/dist-lib/lib/tools/fs/write.js +5 -0
  275. package/dist-lib/lib/tools/generate-image.d.ts +111 -0
  276. package/dist-lib/lib/tools/generate-image.js +369 -0
  277. package/dist-lib/lib/tools/generate-music.d.ts +124 -0
  278. package/dist-lib/lib/tools/generate-music.js +522 -0
  279. package/dist-lib/lib/tools/grep.d.ts +5 -0
  280. package/dist-lib/lib/tools/grep.js +158 -0
  281. package/dist-lib/lib/tools/http-methods.d.ts +1 -0
  282. package/dist-lib/lib/tools/http-methods.js +1 -0
  283. package/dist-lib/lib/tools/http-request/encode-fields.d.ts +2 -0
  284. package/dist-lib/lib/tools/http-request/encode-fields.js +69 -0
  285. package/dist-lib/lib/tools/http-request/truncate-response.d.ts +1 -0
  286. package/dist-lib/lib/tools/http-request/truncate-response.js +83 -0
  287. package/dist-lib/lib/tools/http-request/utils.d.ts +27 -0
  288. package/dist-lib/lib/tools/http-request/utils.js +84 -0
  289. package/dist-lib/lib/tools/http-request.d.ts +20 -0
  290. package/dist-lib/lib/tools/http-request.js +177 -0
  291. package/dist-lib/lib/tools/mcp/utils.d.ts +47 -0
  292. package/dist-lib/lib/tools/mcp/utils.js +172 -0
  293. package/dist-lib/lib/tools/mcp-call.d.ts +14 -0
  294. package/dist-lib/lib/tools/mcp-call.js +155 -0
  295. package/dist-lib/lib/tools/model-args.d.ts +1 -0
  296. package/dist-lib/lib/tools/model-args.js +4 -0
  297. package/dist-lib/lib/tools/operations/builders.d.ts +17 -0
  298. package/dist-lib/lib/tools/operations/builders.js +179 -0
  299. package/dist-lib/lib/tools/operations/compile.d.ts +7 -0
  300. package/dist-lib/lib/tools/operations/compile.js +92 -0
  301. package/dist-lib/lib/tools/operations/gmail-message.d.ts +15 -0
  302. package/dist-lib/lib/tools/operations/gmail-message.js +62 -0
  303. package/dist-lib/lib/tools/operations/manifest.d.ts +60 -0
  304. package/dist-lib/lib/tools/operations/manifest.js +50 -0
  305. package/dist-lib/lib/tools/outbound-guard.d.ts +10 -0
  306. package/dist-lib/lib/tools/outbound-guard.js +127 -0
  307. package/dist-lib/lib/tools/private-ip.d.ts +4 -0
  308. package/dist-lib/lib/tools/private-ip.js +126 -0
  309. package/dist-lib/lib/tools/rag-search.d.ts +2 -0
  310. package/dist-lib/lib/tools/rag-search.js +98 -0
  311. package/dist-lib/lib/tools/read-files.d.ts +5 -0
  312. package/dist-lib/lib/tools/read-files.js +153 -0
  313. package/dist-lib/lib/tools/skill.d.ts +10 -0
  314. package/dist-lib/lib/tools/skill.js +123 -0
  315. package/dist-lib/lib/tools/skills/auth-resolver.d.ts +43 -0
  316. package/dist-lib/lib/tools/skills/auth-resolver.js +121 -0
  317. package/dist-lib/lib/tools/skills/bin-check.d.ts +9 -0
  318. package/dist-lib/lib/tools/skills/bin-check.js +56 -0
  319. package/dist-lib/lib/tools/skills/bundled-dir.d.ts +2 -0
  320. package/dist-lib/lib/tools/skills/bundled-dir.js +117 -0
  321. package/dist-lib/lib/tools/skills/bundled-hash.d.ts +4 -0
  322. package/dist-lib/lib/tools/skills/bundled-hash.js +12 -0
  323. package/dist-lib/lib/tools/skills/catalog.d.ts +60 -0
  324. package/dist-lib/lib/tools/skills/catalog.js +203 -0
  325. package/dist-lib/lib/tools/skills/cli-argv.d.ts +9 -0
  326. package/dist-lib/lib/tools/skills/cli-argv.js +147 -0
  327. package/dist-lib/lib/tools/skills/cli-schema-check.d.ts +3 -0
  328. package/dist-lib/lib/tools/skills/cli-schema-check.js +62 -0
  329. package/dist-lib/lib/tools/skills/cli-schema-load.d.ts +4 -0
  330. package/dist-lib/lib/tools/skills/cli-schema-load.js +90 -0
  331. package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +30 -0
  332. package/dist-lib/lib/tools/skills/cli-schema-types.js +1 -0
  333. package/dist-lib/lib/tools/skills/cli-schema.d.ts +7 -0
  334. package/dist-lib/lib/tools/skills/cli-schema.js +35 -0
  335. package/dist-lib/lib/tools/skills/credential-check.d.ts +20 -0
  336. package/dist-lib/lib/tools/skills/credential-check.js +94 -0
  337. package/dist-lib/lib/tools/skills/credential-grants.d.ts +9 -0
  338. package/dist-lib/lib/tools/skills/credential-grants.js +25 -0
  339. package/dist-lib/lib/tools/skills/credential-health.d.ts +8 -0
  340. package/dist-lib/lib/tools/skills/credential-health.js +51 -0
  341. package/dist-lib/lib/tools/skills/credential-slots.d.ts +7 -0
  342. package/dist-lib/lib/tools/skills/credential-slots.js +8 -0
  343. package/dist-lib/lib/tools/skills/frontmatter-parser.d.ts +23 -0
  344. package/dist-lib/lib/tools/skills/frontmatter-parser.js +68 -0
  345. package/dist-lib/lib/tools/skills/index.d.ts +5 -0
  346. package/dist-lib/lib/tools/skills/index.js +5 -0
  347. package/dist-lib/lib/tools/skills/manifest-parse.d.ts +12 -0
  348. package/dist-lib/lib/tools/skills/manifest-parse.js +199 -0
  349. package/dist-lib/lib/tools/skills/manifest.d.ts +47 -0
  350. package/dist-lib/lib/tools/skills/manifest.js +1 -0
  351. package/dist-lib/lib/tools/skills/mention-name.d.ts +1 -0
  352. package/dist-lib/lib/tools/skills/mention-name.js +4 -0
  353. package/dist-lib/lib/tools/skills/mention.d.ts +6 -0
  354. package/dist-lib/lib/tools/skills/mention.js +42 -0
  355. package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +16 -0
  356. package/dist-lib/lib/tools/skills/obsidian-readiness.js +95 -0
  357. package/dist-lib/lib/tools/skills/overlay-crud.d.ts +18 -0
  358. package/dist-lib/lib/tools/skills/overlay-crud.js +98 -0
  359. package/dist-lib/lib/tools/skills/overlay-dir.d.ts +2 -0
  360. package/dist-lib/lib/tools/skills/overlay-dir.js +22 -0
  361. package/dist-lib/lib/tools/skills/overlay-watch.d.ts +13 -0
  362. package/dist-lib/lib/tools/skills/overlay-watch.js +44 -0
  363. package/dist-lib/lib/tools/skills/scope-key.d.ts +7 -0
  364. package/dist-lib/lib/tools/skills/scope-key.js +7 -0
  365. package/dist-lib/lib/tools/skills/setup-routes.d.ts +4 -0
  366. package/dist-lib/lib/tools/skills/setup-routes.js +14 -0
  367. package/dist-lib/lib/tools/skills/skill-settings.d.ts +16 -0
  368. package/dist-lib/lib/tools/skills/skill-settings.js +33 -0
  369. package/dist-lib/lib/tools/skills/skill-state-constants.d.ts +12 -0
  370. package/dist-lib/lib/tools/skills/skill-state-constants.js +14 -0
  371. package/dist-lib/lib/tools/skills/skill-state.d.ts +40 -0
  372. package/dist-lib/lib/tools/skills/skill-state.js +117 -0
  373. package/dist-lib/lib/tools/skills/tool-grants.d.ts +5 -0
  374. package/dist-lib/lib/tools/skills/tool-grants.js +14 -0
  375. package/dist-lib/lib/tools/toolsets.d.ts +8 -0
  376. package/dist-lib/lib/tools/toolsets.js +20 -0
  377. package/dist-lib/lib/tools/url-guard.d.ts +8 -0
  378. package/dist-lib/lib/tools/url-guard.js +40 -0
  379. package/dist-lib/lib/tools/web-fetch.d.ts +8 -0
  380. package/dist-lib/lib/tools/web-fetch.js +302 -0
  381. package/dist-lib/lib/tools/web-search.d.ts +6 -0
  382. package/dist-lib/lib/tools/web-search.js +55 -0
  383. package/dist-lib/lib/transport.d.ts +12 -0
  384. package/dist-lib/lib/transport.js +59 -0
  385. package/dist-lib/lib/user-agent.d.ts +1 -0
  386. package/dist-lib/lib/user-agent.js +1 -0
  387. package/dist-lib/lib/validating-lookup.d.ts +17 -0
  388. package/dist-lib/lib/validating-lookup.js +25 -0
  389. package/dist-lib/lib/wav-encode.d.ts +5 -0
  390. package/dist-lib/lib/wav-encode.js +24 -0
  391. package/dist-lib/lib/web-fetch/embedded-state.d.ts +1 -0
  392. package/dist-lib/lib/web-fetch/embedded-state.js +131 -0
  393. package/dist-lib/lib/web-fetch/extract.d.ts +6 -0
  394. package/dist-lib/lib/web-fetch/extract.js +65 -0
  395. package/dist-lib/lib/web-fetch/images.d.ts +3 -0
  396. package/dist-lib/lib/web-fetch/images.js +43 -0
  397. package/dist-lib/lib/web-fetch/video.d.ts +5 -0
  398. package/dist-lib/lib/web-fetch/video.js +42 -0
  399. package/dist-lib/lib/web-search/engine-registry.d.ts +7 -0
  400. package/dist-lib/lib/web-search/engine-registry.js +17 -0
  401. package/dist-lib/lib/web-search/engines/aol.d.ts +3 -0
  402. package/dist-lib/lib/web-search/engines/aol.js +81 -0
  403. package/dist-lib/lib/web-search/engines/bing.d.ts +3 -0
  404. package/dist-lib/lib/web-search/engines/bing.js +111 -0
  405. package/dist-lib/lib/web-search/engines/brave.d.ts +3 -0
  406. package/dist-lib/lib/web-search/engines/brave.js +59 -0
  407. package/dist-lib/lib/web-search/engines/duckduckgo.d.ts +3 -0
  408. package/dist-lib/lib/web-search/engines/duckduckgo.js +112 -0
  409. package/dist-lib/lib/web-search/engines/google.d.ts +3 -0
  410. package/dist-lib/lib/web-search/engines/google.js +92 -0
  411. package/dist-lib/lib/web-search/engines/wikipedia.d.ts +3 -0
  412. package/dist-lib/lib/web-search/engines/wikipedia.js +37 -0
  413. package/dist-lib/lib/web-search/engines/yahoo.d.ts +3 -0
  414. package/dist-lib/lib/web-search/engines/yahoo.js +81 -0
  415. package/dist-lib/lib/web-search/fetch-html.d.ts +25 -0
  416. package/dist-lib/lib/web-search/fetch-html.js +97 -0
  417. package/dist-lib/lib/web-search/format-results.d.ts +3 -0
  418. package/dist-lib/lib/web-search/format-results.js +14 -0
  419. package/dist-lib/lib/web-search/html-helpers.d.ts +3 -0
  420. package/dist-lib/lib/web-search/html-helpers.js +24 -0
  421. package/dist-lib/lib/web-search/merge-results.d.ts +2 -0
  422. package/dist-lib/lib/web-search/merge-results.js +53 -0
  423. package/dist-lib/lib/web-search/orchestrator.d.ts +14 -0
  424. package/dist-lib/lib/web-search/orchestrator.js +50 -0
  425. package/dist-lib/lib/web-search/types.d.ts +34 -0
  426. package/dist-lib/lib/web-search/types.js +1 -0
  427. package/dist-lib/lib/web-search/url-helpers.d.ts +1 -0
  428. package/dist-lib/lib/web-search/url-helpers.js +11 -0
  429. package/dist-lib/lib/web-search/url-normalize.d.ts +1 -0
  430. package/dist-lib/lib/web-search/url-normalize.js +25 -0
  431. package/dist-lib/lib/web-search/user-agents.d.ts +3 -0
  432. package/dist-lib/lib/web-search/user-agents.js +3 -0
  433. package/dist-lib/lib/wire.d.ts +50 -0
  434. package/dist-lib/lib/wire.js +145 -0
  435. package/dist-lib/schema/baseline.d.ts +8 -0
  436. package/dist-lib/schema/baseline.js +35 -0
  437. package/dist-lib/schema/build.d.ts +1 -0
  438. package/dist-lib/schema/build.js +39 -0
  439. package/dist-lib/schema/generate.d.ts +20 -0
  440. package/dist-lib/schema/generate.js +149 -0
  441. package/dist-lib/schema/harness.d.ts +2 -0
  442. package/dist-lib/schema/harness.js +745 -0
  443. package/dist-lib/schema/release-tags.d.ts +5 -0
  444. package/dist-lib/schema/release-tags.js +58 -0
  445. package/dist-lib/spec/bind.d.ts +2 -0
  446. package/dist-lib/spec/bind.js +124 -0
  447. package/dist-lib/spec/calls.d.ts +3 -0
  448. package/dist-lib/spec/calls.js +41 -0
  449. package/dist-lib/spec/hrpc/hrpc.json +356 -0
  450. package/dist-lib/spec/hrpc/index.d.ts +3 -0
  451. package/dist-lib/spec/hrpc/index.js +463 -0
  452. package/dist-lib/spec/hrpc/messages.d.ts +4 -0
  453. package/dist-lib/spec/hrpc/messages.js +3102 -0
  454. package/dist-lib/spec/hyperschema/index.js +3102 -0
  455. package/dist-lib/spec/hyperschema/schema.json +2290 -0
  456. package/dist-lib/spec/hyperschema/types.d.ts +554 -0
  457. package/dist-lib/spec/index.d.ts +8 -0
  458. package/dist-lib/spec/index.js +1 -0
  459. package/package.json +239 -64
  460. package/.gitattributes +0 -1
@@ -0,0 +1,75 @@
1
+ import type { ExecResult } from '../../runner.ts';
2
+ export type PyodideLike = {
3
+ runPython(code: string, options?: {
4
+ filename?: string;
5
+ }): unknown;
6
+ runPythonAsync(code: string): Promise<unknown>;
7
+ loadPackage(name: string): Promise<unknown>;
8
+ setStdout(options: {
9
+ batched: (output: string) => void;
10
+ }): void;
11
+ setStderr(options: {
12
+ batched: (output: string) => void;
13
+ }): void;
14
+ setInterruptBuffer(buffer: Uint8Array): void;
15
+ globals: {
16
+ set(key: string, value: unknown): void;
17
+ get(key: string): unknown;
18
+ };
19
+ FS: {
20
+ mkdirTree(path: string): void;
21
+ chdir(path: string): void;
22
+ cwd(): string;
23
+ writeFile(path: string, data: Uint8Array): void;
24
+ readFile(path: string, opts: {
25
+ encoding: 'binary';
26
+ }): Uint8Array;
27
+ analyzePath(path: string): {
28
+ exists: boolean;
29
+ };
30
+ readdir(path: string): string[];
31
+ stat(path: string): {
32
+ mode: number;
33
+ size: number;
34
+ };
35
+ lstat(path: string): {
36
+ mode: number;
37
+ };
38
+ isDir(mode: number): boolean;
39
+ isLink(mode: number): boolean;
40
+ unlink(path: string): void;
41
+ rmdir(path: string): void;
42
+ };
43
+ };
44
+ export type LoadPyodideFn = () => Promise<PyodideLike>;
45
+ export type PythonRunResult = ExecResult & {
46
+ files?: ReadonlyMap<string, Uint8Array>;
47
+ missing?: readonly string[];
48
+ rejected?: readonly {
49
+ name: string;
50
+ reason: string;
51
+ }[];
52
+ undeclared?: readonly string[];
53
+ };
54
+ export type RunSpec = {
55
+ readonly code: string;
56
+ readonly packages?: readonly string[] | undefined;
57
+ readonly inputs?: readonly {
58
+ readonly path: string;
59
+ readonly bytes: Uint8Array;
60
+ }[] | undefined;
61
+ readonly outputs?: readonly string[] | undefined;
62
+ readonly workdir?: string | undefined;
63
+ readonly maxOutputChars: number;
64
+ readonly installTimeoutMs: number;
65
+ };
66
+ export type RunOutcome = {
67
+ readonly result: PythonRunResult;
68
+ readonly evict: boolean;
69
+ };
70
+ export declare function cap(text: string, limit: number): string;
71
+ export declare function isPyodideFatal(error: unknown): boolean;
72
+ export declare function repairDoubleEscapedSource(code: string, message: string): string | null;
73
+ export declare function performRun(py: PyodideLike, spec: RunSpec, opts?: {
74
+ readonly isCancelled?: () => boolean;
75
+ }): Promise<RunOutcome>;
@@ -0,0 +1,273 @@
1
+ import { AbortedError } from "../../../../helpers/race-abort.js";
2
+ import { hlog } from "../../../../log.js";
3
+ import { TRUNCATED_OUTPUT_SUFFIX } from "../../runner.js";
4
+ import { collectOutputs, openScratch, stageInputFiles } from "./memfs.js";
5
+ import { planVendoredInstall, stageVendoredWheels } from "./wheels.js";
6
+ export function cap(text, limit) {
7
+ if (text.length <= limit)
8
+ return text;
9
+ return `${text.slice(0, limit)}${TRUNCATED_OUTPUT_SUFFIX}`;
10
+ }
11
+ export function isPyodideFatal(error) {
12
+ if (typeof error !== 'object' || error === null)
13
+ return false;
14
+ if ('pyodide_fatal_error' in error && error.pyodide_fatal_error === true)
15
+ return true;
16
+ return error instanceof Error && error.message.includes('and can no longer be used');
17
+ }
18
+ const DOUBLE_ESCAPED = /\\[nt"']/;
19
+ function unescapeSource(code) {
20
+ return code.replace(/\\(n|t|r|"|'|\\)/g, (_, char) => {
21
+ if (char === 'n')
22
+ return '\n';
23
+ if (char === 't')
24
+ return '\t';
25
+ if (char === 'r')
26
+ return '\r';
27
+ return char;
28
+ });
29
+ }
30
+ export function repairDoubleEscapedSource(code, message) {
31
+ if (!message.includes('SyntaxError'))
32
+ return null;
33
+ if (code.includes('\n'))
34
+ return null;
35
+ if (!DOUBLE_ESCAPED.test(code))
36
+ return null;
37
+ const repaired = unescapeSource(code);
38
+ return repaired === code ? null : repaired;
39
+ }
40
+ function attempt(py, code, output, maxOutputChars) {
41
+ try {
42
+ py.runPython(code);
43
+ return {
44
+ result: {
45
+ stdout: cap(output.stdout, maxOutputChars),
46
+ stderr: cap(output.stderr, maxOutputChars),
47
+ exitCode: 0
48
+ },
49
+ error: null,
50
+ fatal: false
51
+ };
52
+ }
53
+ catch (error) {
54
+ const message = error instanceof Error ? error.message : String(error);
55
+ return {
56
+ result: {
57
+ stdout: cap(output.stdout, maxOutputChars),
58
+ stderr: cap(output.stderr || message, maxOutputChars),
59
+ exitCode: 1
60
+ },
61
+ error: message,
62
+ fatal: isPyodideFatal(error)
63
+ };
64
+ }
65
+ }
66
+ function runOnce(py, code, output, maxOutputChars) {
67
+ const first = attempt(py, code, output, maxOutputChars);
68
+ if (first.error === null)
69
+ return first;
70
+ const repaired = repairDoubleEscapedSource(code, first.error);
71
+ if (repaired === null)
72
+ return first;
73
+ const retry = attempt(py, repaired, output, maxOutputChars);
74
+ if (retry.error !== null && retry.error.includes('SyntaxError'))
75
+ return first;
76
+ return retry;
77
+ }
78
+ const FIT_DECKS = `
79
+ def _qvac_fit_decks(names):
80
+ try:
81
+ from pptx import Presentation
82
+ from pptx.oxml.ns import qn
83
+ except Exception:
84
+ return
85
+ for name in names:
86
+ if not name.lower().endswith('.pptx'):
87
+ continue
88
+ try:
89
+ prs = Presentation(name)
90
+ except Exception:
91
+ continue
92
+ slide_height = prs.slide_height
93
+ changed = False
94
+ for slide in prs.slides:
95
+ for shape in slide.shapes:
96
+ if not shape.has_text_frame:
97
+ continue
98
+ tf = shape.text_frame
99
+ text = tf.text or ''
100
+ if not text.strip():
101
+ continue
102
+ tf.word_wrap = True
103
+ # Estimated wrapped lines against the box: a character at N pt is
104
+ # about 0.5 N wide and a line about 1.2 N tall. Rough on purpose —
105
+ # it only has to pick a scale, and the renderer does the real layout.
106
+ width_pt = (shape.width or 0) / 12700.0
107
+ height_pt = (shape.height or slide_height) / 12700.0
108
+ lines = 0
109
+ tallest = 0.0
110
+ for p in tf.paragraphs:
111
+ # An unsized paragraph inherits from the layout, and the bundled
112
+ # template's body is 28pt — assuming something smaller here is
113
+ # what let a seven-bullet slide measure as fitting.
114
+ size = p.font.size.pt if p.font.size is not None else 28.0
115
+ tallest = max(tallest, size)
116
+ per_line = max(1.0, width_pt / (size * 0.5))
117
+ lines += max(1, int(len(p.text or '') / per_line) + 1)
118
+ needed = lines * max(tallest, 12.0) * 1.2
119
+ scale = 1.0 if needed <= height_pt or height_pt <= 0 else height_pt / needed
120
+ # 55% is the floor: below that the deck is unreadable from a room and
121
+ # the honest answer is fewer bullets, not smaller type.
122
+ scale = max(0.55, min(1.0, scale))
123
+ bodyPr = tf._txBody.bodyPr
124
+ for tag in ('a:normAutofit', 'a:spAutoFit', 'a:noAutofit'):
125
+ found = bodyPr.find(qn(tag))
126
+ if found is not None:
127
+ bodyPr.remove(found)
128
+ bodyPr.append(
129
+ bodyPr.makeelement(
130
+ qn('a:normAutofit'),
131
+ {
132
+ 'fontScale': str(int(scale * 100000)),
133
+ 'lnSpcReduction': '0' if scale >= 1.0 else '10000'
134
+ }
135
+ )
136
+ )
137
+ changed = True
138
+ if changed:
139
+ try:
140
+ prs.save(name)
141
+ except Exception:
142
+ pass
143
+ `;
144
+ class InstallTimeoutError extends Error {
145
+ }
146
+ function installSource(py, packages) {
147
+ const plan = planVendoredInstall(packages);
148
+ if (!plan)
149
+ return `import micropip\nawait micropip.install(${JSON.stringify(packages)})`;
150
+ const specs = [...stageVendoredWheels(py.FS, plan), ...plan.packages];
151
+ hlog('python: installing from vendored wheels', { specs });
152
+ return `import micropip\nawait micropip.install(${JSON.stringify(specs)}, deps=False)`;
153
+ }
154
+ async function installPackages(py, packages, timeoutMs, isCancelled) {
155
+ await py.loadPackage('micropip');
156
+ if (isCancelled())
157
+ throw new AbortedError();
158
+ const install = py.runPythonAsync(installSource(py, packages));
159
+ let timer;
160
+ const bound = new Promise((_, reject) => {
161
+ timer = setTimeout(() => reject(new InstallTimeoutError(`package install timed out after ${timeoutMs}ms`)), timeoutMs);
162
+ });
163
+ try {
164
+ await Promise.race([install, bound]);
165
+ }
166
+ finally {
167
+ if (timer)
168
+ clearTimeout(timer);
169
+ }
170
+ }
171
+ const DELIVERABLE = /\.(pptx|docx|xlsx|pdf|png|jpe?g|gif|webp|csv|json|txt|md|zip)$/i;
172
+ function listFiles(py, dir) {
173
+ try {
174
+ return new Set(py.FS.readdir(dir).filter((name) => name !== '.' && name !== '..'));
175
+ }
176
+ catch {
177
+ return new Set();
178
+ }
179
+ }
180
+ function newDeliverables(before, after) {
181
+ return [...after].filter((name) => !before.has(name) && DELIVERABLE.test(name));
182
+ }
183
+ function fitDecks(py, outputs) {
184
+ if (!outputs.some((name) => name.toLowerCase().endsWith('.pptx')))
185
+ return false;
186
+ try {
187
+ py.runPython(`${FIT_DECKS}\n_qvac_fit_decks(${JSON.stringify(outputs)})`);
188
+ return false;
189
+ }
190
+ catch (error) {
191
+ hlog('python: deck fit skipped', {
192
+ err: error instanceof Error ? error.message : String(error)
193
+ });
194
+ return isPyodideFatal(error);
195
+ }
196
+ }
197
+ export async function performRun(py, spec, opts = {}) {
198
+ const isCancelled = opts.isCancelled ?? (() => false);
199
+ const output = { stdout: '', stderr: '' };
200
+ py.setStdout({ batched: (chunk) => (output.stdout += chunk + '\n') });
201
+ py.setStderr({ batched: (chunk) => (output.stderr += chunk + '\n') });
202
+ if (spec.packages?.length) {
203
+ if (isCancelled())
204
+ throw new AbortedError();
205
+ hlog('python: installing packages', {
206
+ packages: [...spec.packages],
207
+ timeoutMs: spec.installTimeoutMs
208
+ });
209
+ try {
210
+ await installPackages(py, spec.packages, spec.installTimeoutMs, isCancelled);
211
+ hlog('python: packages ready', { packages: [...spec.packages] });
212
+ }
213
+ catch (error) {
214
+ if (error instanceof AbortedError)
215
+ throw error;
216
+ const message = error instanceof Error ? error.message : String(error);
217
+ const timedOut = error instanceof InstallTimeoutError;
218
+ const evict = timedOut || isPyodideFatal(error);
219
+ hlog(timedOut ? 'python: package install timed out' : 'python: package install failed', {
220
+ packages: [...spec.packages],
221
+ err: message,
222
+ evict
223
+ });
224
+ return {
225
+ result: { stdout: '', stderr: cap(message, spec.maxOutputChars), exitCode: 1 },
226
+ evict
227
+ };
228
+ }
229
+ output.stdout = '';
230
+ output.stderr = '';
231
+ }
232
+ if (isCancelled())
233
+ throw new AbortedError();
234
+ if (!spec.inputs?.length && !spec.outputs?.length && !spec.workdir) {
235
+ const cwd = py.FS.cwd();
236
+ const before = listFiles(py, cwd);
237
+ const { result, fatal } = runOnce(py, spec.code, output, spec.maxOutputChars);
238
+ if (result.exitCode !== 0)
239
+ return { result, evict: fatal };
240
+ const undeclared = newDeliverables(before, listFiles(py, cwd));
241
+ return { result: undeclared.length > 0 ? { ...result, undeclared } : result, evict: false };
242
+ }
243
+ const scratch = openScratch(py.FS, spec.workdir);
244
+ try {
245
+ py.FS.chdir(scratch.cwd);
246
+ stageInputFiles(py.FS, scratch.cwd, spec.inputs ?? []);
247
+ const before = listFiles(py, scratch.cwd);
248
+ const { result, fatal } = runOnce(py, spec.code, output, spec.maxOutputChars);
249
+ let evict = fatal;
250
+ if (result.exitCode === 0)
251
+ evict = fitDecks(py, spec.outputs ?? []);
252
+ if (evict)
253
+ return { result: { ...result, missing: spec.outputs ?? [] }, evict };
254
+ const outputs = collectOutputs(py.FS, scratch.cwd, spec.outputs ?? []);
255
+ const declared = new Set(spec.outputs ?? []);
256
+ const undeclared = result.exitCode === 0
257
+ ? newDeliverables(before, listFiles(py, scratch.cwd)).filter((name) => !declared.has(name))
258
+ : [];
259
+ return {
260
+ result: {
261
+ ...result,
262
+ files: outputs.files,
263
+ missing: outputs.missing,
264
+ rejected: outputs.rejected,
265
+ ...(undeclared.length > 0 && { undeclared })
266
+ },
267
+ evict: false
268
+ };
269
+ }
270
+ finally {
271
+ scratch[Symbol.dispose]();
272
+ }
273
+ }
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ declare const ManifestSchema: z.ZodObject<{
3
+ pyodide: z.ZodString;
4
+ packages: z.ZodRecord<z.ZodString, z.ZodObject<{
5
+ version: z.ZodOptional<z.ZodString>;
6
+ pypi: z.ZodArray<z.ZodString>;
7
+ pyodide: z.ZodArray<z.ZodString>;
8
+ }, z.core.$strip>>;
9
+ files: z.ZodRecord<z.ZodString, z.ZodObject<{
10
+ url: z.ZodString;
11
+ sha256: z.ZodString;
12
+ channel: z.ZodEnum<{
13
+ pyodide: "pyodide";
14
+ pypi: "pypi";
15
+ }>;
16
+ }, z.core.$strip>>;
17
+ }, z.core.$strip>;
18
+ export type WheelManifest = z.infer<typeof ManifestSchema>;
19
+ export type VendoredInstall = {
20
+ readonly wheels: readonly string[];
21
+ readonly packages: readonly string[];
22
+ };
23
+ type WheelFs = {
24
+ mkdirTree(path: string): void;
25
+ writeFile(path: string, data: Uint8Array): void;
26
+ analyzePath(path: string): {
27
+ exists: boolean;
28
+ };
29
+ };
30
+ export declare function wheelsDir(): string | undefined;
31
+ export declare function vendoredManifest(dir?: string | undefined): WheelManifest | null;
32
+ export declare function planVendoredInstall(specs: readonly string[], opts?: {
33
+ readonly dir?: string | undefined;
34
+ readonly manifest?: WheelManifest | null;
35
+ }): VendoredInstall | null;
36
+ export declare function stageVendoredWheels(target: WheelFs, install: VendoredInstall): string[];
37
+ export declare function seedPackageCache(cacheDir: string, dir?: string | undefined): void;
38
+ export {};
@@ -0,0 +1,102 @@
1
+ import fs from 'fs';
2
+ import process from 'process';
3
+ import { fileURLToPath } from 'url';
4
+ import { z } from 'zod';
5
+ import { hlog } from "../../../../log.js";
6
+ const ManifestSchema = z.object({
7
+ pyodide: z.string(),
8
+ packages: z.record(z.string(), z.object({
9
+ version: z.string().optional(),
10
+ pypi: z.array(z.string()),
11
+ pyodide: z.array(z.string())
12
+ })),
13
+ files: z.record(z.string(), z.object({ url: z.string(), sha256: z.string(), channel: z.enum(['pypi', 'pyodide']) }))
14
+ });
15
+ const STAGE_DIR = '/qvac-wheels';
16
+ export function wheelsDir() {
17
+ const fromHost = process.env.QVAC_PYTHON_WHEELS_DIR;
18
+ if (fromHost)
19
+ return fromHost;
20
+ const source = new URL('../../../../../wheels', import.meta.url);
21
+ if (source.href.includes('.bundle/'))
22
+ return undefined;
23
+ return fileURLToPath(source.href);
24
+ }
25
+ export function vendoredManifest(dir = wheelsDir()) {
26
+ if (!dir)
27
+ return null;
28
+ const file = `${dir}/manifest.json`;
29
+ if (!fs.existsSync(file)) {
30
+ hlog('python: no vendored wheels', { dir });
31
+ return null;
32
+ }
33
+ try {
34
+ return ManifestSchema.parse(JSON.parse(fs.readFileSync(file, 'utf8')));
35
+ }
36
+ catch (error) {
37
+ hlog('python: vendored wheel manifest unusable', {
38
+ file,
39
+ err: error instanceof Error ? error.message : String(error)
40
+ });
41
+ return null;
42
+ }
43
+ }
44
+ function normalize(name) {
45
+ return name.toLowerCase().replace(/[_.]+/g, '-');
46
+ }
47
+ function parseSpec(spec) {
48
+ const [name, version] = spec.split('==');
49
+ return { name: normalize((name ?? '').trim()), version: version?.trim() };
50
+ }
51
+ export function planVendoredInstall(specs, opts = {}) {
52
+ const dir = opts.dir ?? wheelsDir();
53
+ const manifest = opts.manifest === undefined ? vendoredManifest(dir) : opts.manifest;
54
+ if (!manifest || !dir || specs.length === 0)
55
+ return null;
56
+ const wheels = new Set();
57
+ const packages = new Set();
58
+ for (const spec of specs) {
59
+ const { name, version } = parseSpec(spec);
60
+ const entry = manifest.packages[name];
61
+ if (!entry || entry.version !== version)
62
+ return null;
63
+ for (const wheel of entry.pypi) {
64
+ if (!fs.existsSync(`${dir}/${wheel}`)) {
65
+ hlog('python: vendored wheel missing, installing from PyPI instead', { wheel });
66
+ return null;
67
+ }
68
+ wheels.add(`${dir}/${wheel}`);
69
+ }
70
+ for (const dependency of entry.pyodide)
71
+ packages.add(dependency);
72
+ }
73
+ return { wheels: [...wheels], packages: [...packages] };
74
+ }
75
+ export function stageVendoredWheels(target, install) {
76
+ if (install.wheels.length > 0)
77
+ target.mkdirTree(STAGE_DIR);
78
+ return install.wheels.map((wheel) => {
79
+ const staged = `${STAGE_DIR}/${wheel.slice(wheel.lastIndexOf('/') + 1)}`;
80
+ if (!target.analyzePath(staged).exists) {
81
+ target.writeFile(staged, new Uint8Array(fs.readFileSync(wheel)));
82
+ }
83
+ return `emfs:${staged}`;
84
+ });
85
+ }
86
+ export function seedPackageCache(cacheDir, dir = wheelsDir()) {
87
+ const manifest = vendoredManifest(dir);
88
+ if (!manifest || !dir)
89
+ return;
90
+ fs.mkdirSync(cacheDir, { recursive: true });
91
+ let seeded = 0;
92
+ for (const [file, entry] of Object.entries(manifest.files)) {
93
+ if (entry.channel !== 'pyodide' || fs.existsSync(`${cacheDir}/${file}`))
94
+ continue;
95
+ if (!fs.existsSync(`${dir}/${file}`))
96
+ continue;
97
+ fs.copyFileSync(`${dir}/${file}`, `${cacheDir}/${file}`);
98
+ seeded++;
99
+ }
100
+ if (seeded > 0)
101
+ hlog('python: seeded package cache', { cacheDir, wheels: seeded });
102
+ }
@@ -0,0 +1,7 @@
1
+ import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
2
+ import type { PythonRunResult, RunSpec } from '../run-session.ts';
3
+ export declare function runPythonInWorker(spec: RunSpec, opts: {
4
+ readonly timeoutMs: number;
5
+ readonly signal?: BareAbortSignal | undefined;
6
+ }): Promise<PythonRunResult>;
7
+ export declare function closePythonWorker(): Promise<void>;
@@ -0,0 +1,188 @@
1
+ import { spawnPythonWorker } from '#pyodide-worker-spawn';
2
+ import process from 'process';
3
+ import { fileURLToPath } from 'url';
4
+ import { AbortedError, raceAbort } from "../../../../../helpers/race-abort.js";
5
+ import { harnessLogEnabled, hlog } from "../../../../../log.js";
6
+ import { asWorkerMessage, fromWireResult } from "./protocol.js";
7
+ const SIGINT = 2;
8
+ function interruptGraceMs() {
9
+ const ms = Number(process.env.QVAC_PYODIDE_INTERRUPT_GRACE_MS);
10
+ return ms > 0 ? ms : 30_000;
11
+ }
12
+ const SHUTDOWN_GRACE_MS = 3_000;
13
+ let active = null;
14
+ function workerEntry() {
15
+ return (process.env.QVAC_PYODIDE_WORKER_ENTRY ??
16
+ fileURLToPath(new URL('./entry.ts', import.meta.url).href));
17
+ }
18
+ async function readMessage(link) {
19
+ for (;;) {
20
+ const message = asWorkerMessage(await link.read());
21
+ if (message?.type !== 'log')
22
+ return message;
23
+ hlog(`python worker: ${message.message}`);
24
+ }
25
+ }
26
+ async function awaitReady(link) {
27
+ const message = await readMessage(link);
28
+ if (message?.type === 'ready')
29
+ return;
30
+ if (message?.type === 'boot-error')
31
+ throw new Error(`python worker: ${message.message}`);
32
+ throw new Error('python worker sent an unexpected first message');
33
+ }
34
+ function boot() {
35
+ hlog('python: booting worker thread');
36
+ const sab = new SharedArrayBuffer(1);
37
+ const link = spawnPythonWorker(workerEntry(), { sab, log: harnessLogEnabled() });
38
+ const worker = {
39
+ link,
40
+ view: new Uint8Array(sab),
41
+ ready: awaitReady(link).then(() => hlog('python: worker ready')),
42
+ nextId: 1
43
+ };
44
+ worker.ready.catch(() => {
45
+ if (active === worker)
46
+ active = null;
47
+ link.kill();
48
+ });
49
+ return worker;
50
+ }
51
+ function destroy(worker) {
52
+ if (active === worker)
53
+ active = null;
54
+ worker.link.kill();
55
+ }
56
+ async function drainAndReap(worker) {
57
+ if (active === worker)
58
+ active = null;
59
+ const closed = readMessage(worker.link).then(() => 'message', () => 'closed');
60
+ const timer = grace(SHUTDOWN_GRACE_MS);
61
+ try {
62
+ const settled = await Promise.race([closed, timer.expired]);
63
+ if (settled === 'closed')
64
+ worker.link.reap();
65
+ else
66
+ worker.link.kill();
67
+ }
68
+ finally {
69
+ timer.clear();
70
+ }
71
+ }
72
+ async function resultFor(worker, id) {
73
+ const message = await readMessage(worker.link);
74
+ if (message?.type === 'result') {
75
+ if (message.id !== id)
76
+ throw new Error('python worker answered a different run');
77
+ return { result: fromWireResult(message.result), evict: message.evict };
78
+ }
79
+ if (message?.type === 'boot-error')
80
+ throw new Error(`python worker: ${message.message}`);
81
+ throw new Error('python worker sent an unexpected message');
82
+ }
83
+ function grace(ms) {
84
+ let timer;
85
+ const expired = new Promise((resolve) => {
86
+ timer = setTimeout(() => resolve('grace'), ms);
87
+ });
88
+ return { expired, clear: () => clearTimeout(timer) };
89
+ }
90
+ async function interrupt(worker, outcome) {
91
+ Atomics.store(worker.view, 0, SIGINT);
92
+ const graceMs = interruptGraceMs();
93
+ const timer = grace(graceMs);
94
+ try {
95
+ const settled = await Promise.race([
96
+ outcome.then(() => 'done', () => 'done'),
97
+ timer.expired
98
+ ]);
99
+ if (settled === 'grace') {
100
+ hlog('python: worker ignored interrupt; killing', { graceMs });
101
+ destroy(worker);
102
+ }
103
+ else {
104
+ Atomics.store(worker.view, 0, 0);
105
+ }
106
+ }
107
+ finally {
108
+ timer.clear();
109
+ }
110
+ }
111
+ export async function runPythonInWorker(spec, opts) {
112
+ const worker = (active ??= boot());
113
+ worker.link.ref();
114
+ try {
115
+ const id = worker.nextId++;
116
+ Atomics.store(worker.view, 0, 0);
117
+ let cancelled = false;
118
+ let sent = false;
119
+ const outcome = (async () => {
120
+ await worker.ready;
121
+ if (cancelled)
122
+ throw new AbortedError();
123
+ sent = true;
124
+ await worker.link.write({ type: 'run', id, spec });
125
+ return resultFor(worker, id);
126
+ })();
127
+ let timer;
128
+ const timeout = new Promise((resolve) => {
129
+ timer = setTimeout(() => resolve('timeout'), opts.timeoutMs);
130
+ });
131
+ let first;
132
+ try {
133
+ first = await raceAbort(Promise.race([outcome, timeout]), opts.signal);
134
+ }
135
+ catch (error) {
136
+ if (error instanceof AbortedError) {
137
+ cancelled = true;
138
+ if (sent)
139
+ await interrupt(worker, outcome);
140
+ else
141
+ outcome.catch(() => { });
142
+ throw error;
143
+ }
144
+ destroy(worker);
145
+ throw error;
146
+ }
147
+ finally {
148
+ if (timer)
149
+ clearTimeout(timer);
150
+ }
151
+ if (first === 'timeout') {
152
+ cancelled = true;
153
+ if (sent)
154
+ await interrupt(worker, outcome);
155
+ else
156
+ outcome.catch(() => { });
157
+ throw new Error(`Command timed out after ${opts.timeoutMs}ms`);
158
+ }
159
+ if (first.evict)
160
+ await drainAndReap(worker);
161
+ return first.result;
162
+ }
163
+ finally {
164
+ worker.link.unref();
165
+ }
166
+ }
167
+ export async function closePythonWorker() {
168
+ const worker = active;
169
+ if (!worker)
170
+ return;
171
+ active = null;
172
+ const timer = grace(SHUTDOWN_GRACE_MS);
173
+ try {
174
+ const booted = await Promise.race([worker.ready.then(() => 'ready'), timer.expired]);
175
+ if (booted === 'grace') {
176
+ worker.link.kill();
177
+ return;
178
+ }
179
+ await worker.link.write({ type: 'close' });
180
+ await drainAndReap(worker);
181
+ }
182
+ catch {
183
+ worker.link.kill();
184
+ }
185
+ finally {
186
+ timer.clear();
187
+ }
188
+ }