akm-cli 0.8.7 → 0.8.14

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 (324) hide show
  1. package/CHANGELOG.md +428 -0
  2. package/dist/assets/help/help-proposals.md +1 -2
  3. package/dist/assets/hints/cli-hints-full.md +34 -19
  4. package/dist/assets/hints/cli-hints-short.md +1 -1
  5. package/dist/assets/profiles/catchup.json +13 -0
  6. package/dist/assets/profiles/consolidate.json +13 -0
  7. package/dist/assets/profiles/frequent.json +13 -0
  8. package/dist/assets/tasks/core/backup.yml +4 -0
  9. package/dist/assets/tasks/core/extract.yml +4 -0
  10. package/dist/assets/tasks/core/improve.yml +4 -0
  11. package/dist/assets/tasks/core/index-refresh.yml +4 -0
  12. package/dist/assets/tasks/core/sync.yml +4 -0
  13. package/dist/assets/tasks/core/update-stashes.yml +4 -0
  14. package/dist/assets/tasks/core/version-check.yml +4 -0
  15. package/dist/assets/templates/html/default.html +78 -0
  16. package/dist/assets/templates/html/health.html +560 -0
  17. package/dist/assets/templates/html/vendor/echarts.min.js +45 -0
  18. package/dist/cli/config-migrate.js +6 -6
  19. package/dist/cli/config-validate.js +4 -4
  20. package/dist/cli/confirm.js +3 -3
  21. package/dist/cli/parse-args.js +1 -1
  22. package/dist/cli/shared.js +72 -19
  23. package/dist/cli-node.mjs +26 -0
  24. package/dist/cli.js +206 -3866
  25. package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
  26. package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
  27. package/dist/commands/agent/contribute-cli.js +200 -0
  28. package/dist/commands/completions.js +1 -1
  29. package/dist/commands/config-cli.js +230 -3
  30. package/dist/commands/db-cli.js +2 -2
  31. package/dist/commands/env/env-cli.js +529 -0
  32. package/dist/commands/env/env.js +410 -0
  33. package/dist/commands/env/secret-cli.js +259 -0
  34. package/dist/commands/{secret.js → env/secret.js} +6 -47
  35. package/dist/commands/events.js +4 -4
  36. package/dist/commands/feedback-cli.js +18 -34
  37. package/dist/commands/graph/graph-cli.js +132 -0
  38. package/dist/commands/{graph.js → graph/graph.js} +22 -16
  39. package/dist/commands/health/checks.js +279 -0
  40. package/dist/commands/health/html-report.js +448 -0
  41. package/dist/commands/health.js +189 -266
  42. package/dist/commands/{consolidate.js → improve/consolidate.js} +48 -36
  43. package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
  44. package/dist/commands/{distill.js → improve/distill.js} +39 -18
  45. package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
  46. package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
  47. package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
  48. package/dist/commands/{extract.js → improve/extract.js} +221 -26
  49. package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +30 -4
  50. package/dist/commands/{improve-cli.js → improve/improve-cli.js} +44 -22
  51. package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
  52. package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +1 -1
  53. package/dist/commands/{improve.js → improve/improve.js} +672 -292
  54. package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
  55. package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
  56. package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
  57. package/dist/commands/improve/reflect-noise.js +0 -0
  58. package/dist/commands/{reflect.js → improve/reflect.js} +58 -28
  59. package/dist/commands/improve/session-asset.js +248 -0
  60. package/dist/commands/lint/agent-linter.js +1 -1
  61. package/dist/commands/lint/base-linter.js +55 -37
  62. package/dist/commands/lint/command-linter.js +1 -1
  63. package/dist/commands/lint/default-linter.js +1 -1
  64. package/dist/commands/lint/env-key-rules.js +1 -1
  65. package/dist/commands/lint/index.js +19 -25
  66. package/dist/commands/lint/knowledge-linter.js +1 -1
  67. package/dist/commands/lint/memory-linter.js +1 -1
  68. package/dist/commands/lint/registry.js +8 -8
  69. package/dist/commands/lint/skill-linter.js +1 -1
  70. package/dist/commands/lint/task-linter.js +1 -1
  71. package/dist/commands/lint/workflow-linter.js +1 -1
  72. package/dist/commands/lint.js +1 -1
  73. package/dist/commands/observability-cli.js +244 -0
  74. package/dist/commands/proposal/drain-policies.js +3 -3
  75. package/dist/commands/proposal/drain.js +87 -15
  76. package/dist/commands/proposal/proposal-cli.js +490 -0
  77. package/dist/commands/{proposal.js → proposal/proposal.js} +17 -6
  78. package/dist/commands/{propose.js → proposal/propose.js} +11 -11
  79. package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
  80. package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
  81. package/dist/{core → commands/proposal/validators}/proposals.js +374 -345
  82. package/dist/commands/{curate.js → read/curate.js} +7 -7
  83. package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
  84. package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
  85. package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
  86. package/dist/commands/read/search-cli.js +207 -0
  87. package/dist/commands/{search.js → read/search.js} +22 -27
  88. package/dist/commands/{show.js → read/show.js} +31 -45
  89. package/dist/commands/registry-cli.js +8 -8
  90. package/dist/commands/remember.js +14 -10
  91. package/dist/commands/sources/add-cli.js +293 -0
  92. package/dist/commands/{history.js → sources/history.js} +27 -25
  93. package/dist/commands/{info.js → sources/info.js} +6 -6
  94. package/dist/commands/{init.js → sources/init.js} +6 -6
  95. package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
  96. package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
  97. package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
  98. package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
  99. package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
  100. package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
  101. package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
  102. package/dist/commands/sources/sources-cli.js +305 -0
  103. package/dist/commands/sources/stash-cli.js +219 -0
  104. package/dist/commands/{stash-skeleton.js → sources/stash-skeleton.js} +2 -1
  105. package/dist/commands/tasks/default-tasks.js +173 -0
  106. package/dist/commands/tasks/tasks-cli.js +210 -0
  107. package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
  108. package/dist/commands/wiki-cli.js +307 -0
  109. package/dist/commands/workflow-cli.js +329 -0
  110. package/dist/core/action-contributors.js +1 -1
  111. package/dist/core/assert.js +40 -0
  112. package/dist/core/asset/asset-create.js +54 -0
  113. package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
  114. package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
  115. package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
  116. package/dist/core/{markdown.js → asset/markdown.js} +1 -1
  117. package/dist/core/{stash-meta.js → asset/stash-meta.js} +1 -1
  118. package/dist/core/best-effort.js +64 -0
  119. package/dist/core/common.js +32 -18
  120. package/dist/core/{config-io.js → config/config-io.js} +29 -19
  121. package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
  122. package/dist/core/{config-schema.js → config/config-schema.js} +50 -7
  123. package/dist/core/config/config-types.js +16 -0
  124. package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
  125. package/dist/core/{config.js → config/config.js} +10 -8
  126. package/dist/core/env-secret-ref.js +90 -0
  127. package/dist/core/errors.js +13 -3
  128. package/dist/core/events.js +27 -4
  129. package/dist/core/file-lock.js +1 -1
  130. package/dist/core/improve-types.js +48 -0
  131. package/dist/core/lesson-lint.js +2 -2
  132. package/dist/core/logs-db.js +304 -0
  133. package/dist/core/paths.js +2 -2
  134. package/dist/core/ripgrep/install.js +2 -2
  135. package/dist/core/ripgrep/resolve.js +2 -2
  136. package/dist/core/state-db.js +195 -60
  137. package/dist/core/text-truncation.js +148 -0
  138. package/dist/core/time.js +1 -1
  139. package/dist/core/write-source.js +98 -85
  140. package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
  141. package/dist/indexer/{db.js → db/db.js} +128 -118
  142. package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
  143. package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
  144. package/dist/indexer/ensure-index.js +4 -4
  145. package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
  146. package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
  147. package/dist/indexer/indexer.js +37 -30
  148. package/dist/indexer/init.js +54 -0
  149. package/dist/indexer/manifest.js +10 -10
  150. package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +141 -33
  151. package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
  152. package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
  153. package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
  154. package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
  155. package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
  156. package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
  157. package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
  158. package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
  159. package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
  160. package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
  161. package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
  162. package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
  163. package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
  164. package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
  165. package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
  166. package/dist/indexer/{walker.js → walk/walker.js} +4 -3
  167. package/dist/integrations/agent/builder-shared.js +39 -0
  168. package/dist/integrations/agent/builders.js +14 -81
  169. package/dist/integrations/agent/config.js +6 -4
  170. package/dist/integrations/agent/detect.js +1 -1
  171. package/dist/integrations/agent/index.js +23 -8
  172. package/dist/integrations/agent/prompts.js +2 -3
  173. package/dist/integrations/agent/runner.js +22 -3
  174. package/dist/integrations/agent/spawn.js +9 -10
  175. package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
  176. package/dist/integrations/harnesses/claude/config-import.js +70 -0
  177. package/dist/integrations/harnesses/claude/index.js +64 -0
  178. package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +32 -5
  179. package/dist/integrations/harnesses/index.js +144 -0
  180. package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
  181. package/dist/integrations/harnesses/opencode/config-import.js +82 -0
  182. package/dist/integrations/harnesses/opencode/index.js +59 -0
  183. package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
  184. package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
  185. package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
  186. package/dist/integrations/harnesses/types.js +43 -0
  187. package/dist/integrations/lockfile.js +7 -16
  188. package/dist/integrations/session-logs/index.js +82 -9
  189. package/dist/llm/call-ai.js +4 -4
  190. package/dist/llm/client.js +146 -6
  191. package/dist/llm/embedder.js +6 -6
  192. package/dist/llm/embedders/local.js +9 -22
  193. package/dist/llm/embedders/remote.js +2 -2
  194. package/dist/llm/embedders/types.js +1 -1
  195. package/dist/llm/graph-extract.js +31 -12
  196. package/dist/llm/index-passes.js +1 -1
  197. package/dist/llm/memory-infer.js +12 -5
  198. package/dist/llm/metadata-enhance.js +2 -2
  199. package/dist/llm/usage-persist.js +77 -0
  200. package/dist/llm/usage-telemetry.js +103 -0
  201. package/dist/output/context.js +9 -46
  202. package/dist/output/html-render.js +73 -0
  203. package/dist/output/renderers.js +88 -58
  204. package/dist/output/shapes/curate.js +7 -3
  205. package/dist/output/shapes/distill.js +7 -3
  206. package/dist/output/shapes/env-list.js +18 -16
  207. package/dist/output/shapes/events.js +5 -4
  208. package/dist/output/shapes/helpers.js +19 -5
  209. package/dist/output/shapes/history.js +7 -3
  210. package/dist/output/shapes/passthrough.js +8 -11
  211. package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
  212. package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
  213. package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
  214. package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
  215. package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
  216. package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
  217. package/dist/output/shapes/registry-search.js +7 -3
  218. package/dist/output/shapes/registry.js +12 -0
  219. package/dist/output/shapes/search.js +7 -3
  220. package/dist/output/shapes/secret-list.js +18 -16
  221. package/dist/output/shapes/show.js +7 -3
  222. package/dist/output/shapes.js +55 -30
  223. package/dist/output/text/add.js +2 -3
  224. package/dist/output/text/clone.js +2 -3
  225. package/dist/output/text/config.js +2 -3
  226. package/dist/output/text/curate.js +4 -3
  227. package/dist/output/text/distill.js +2 -3
  228. package/dist/output/text/enable-disable.js +5 -4
  229. package/dist/output/text/env.js +13 -0
  230. package/dist/output/text/events.js +5 -4
  231. package/dist/output/text/feedback.js +4 -3
  232. package/dist/output/text/helpers.js +123 -40
  233. package/dist/output/text/history.js +2 -3
  234. package/dist/output/text/import.js +2 -3
  235. package/dist/output/text/index.js +2 -3
  236. package/dist/output/text/info.js +2 -3
  237. package/dist/output/text/init.js +2 -3
  238. package/dist/output/text/list.js +2 -3
  239. package/dist/output/text/proposal/producer.js +9 -0
  240. package/dist/output/text/proposal/proposal.js +13 -0
  241. package/dist/output/text/registry-commands.js +8 -7
  242. package/dist/output/text/registry.js +12 -0
  243. package/dist/output/text/remember.js +4 -3
  244. package/dist/output/text/remove.js +2 -3
  245. package/dist/output/text/save.js +2 -3
  246. package/dist/output/text/search.js +4 -3
  247. package/dist/output/text/show.js +4 -3
  248. package/dist/output/text/update.js +2 -3
  249. package/dist/output/text/upgrade.js +2 -3
  250. package/dist/output/text/wiki.js +12 -11
  251. package/dist/output/text/workflow.js +12 -10
  252. package/dist/output/text.js +66 -32
  253. package/dist/registry/build-index.js +11 -10
  254. package/dist/registry/factory.js +1 -1
  255. package/dist/registry/origin-resolve.js +1 -1
  256. package/dist/registry/providers/index.js +2 -2
  257. package/dist/registry/providers/skills-sh.js +91 -72
  258. package/dist/registry/providers/static-index.js +75 -52
  259. package/dist/registry/resolve.js +3 -3
  260. package/dist/runtime.js +242 -0
  261. package/dist/scripts/migrate-storage.js +1654 -683
  262. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +254 -168
  263. package/dist/setup/detect.js +311 -9
  264. package/dist/setup/harness-config-import.js +6 -120
  265. package/dist/setup/setup.js +454 -43
  266. package/dist/sources/include.js +1 -1
  267. package/dist/sources/provider-factory.js +2 -2
  268. package/dist/sources/providers/filesystem.js +3 -3
  269. package/dist/sources/providers/git.js +9 -9
  270. package/dist/sources/providers/index.js +4 -4
  271. package/dist/sources/providers/npm.js +6 -6
  272. package/dist/sources/providers/provider-utils.js +13 -20
  273. package/dist/sources/providers/sync-from-ref.js +5 -5
  274. package/dist/sources/providers/tar-utils.js +2 -2
  275. package/dist/sources/providers/website.js +2 -2
  276. package/dist/sources/resolve.js +5 -5
  277. package/dist/sources/website-ingest.js +5 -5
  278. package/dist/storage/database.js +102 -0
  279. package/dist/storage/engines/sqlite-migrations.js +42 -0
  280. package/dist/storage/locations.js +25 -0
  281. package/dist/storage/repositories/index-db.js +43 -0
  282. package/dist/storage/repositories/workflow-runs-repository.js +141 -0
  283. package/dist/tasks/backends/cron.js +4 -4
  284. package/dist/tasks/backends/exec-utils.js +32 -0
  285. package/dist/tasks/backends/index.js +3 -3
  286. package/dist/tasks/backends/launchd.js +7 -14
  287. package/dist/tasks/backends/schtasks.js +7 -16
  288. package/dist/tasks/embedded.js +71 -0
  289. package/dist/tasks/parser.js +2 -2
  290. package/dist/tasks/resolveAkmBin.js +1 -1
  291. package/dist/tasks/runner.js +127 -31
  292. package/dist/tasks/schedule.js +1 -1
  293. package/dist/tasks/validator.js +7 -7
  294. package/dist/text-import-hook.mjs +51 -0
  295. package/dist/version.js +2 -1
  296. package/dist/wiki/wiki.js +7 -7
  297. package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
  298. package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
  299. package/dist/workflows/cli.js +1 -1
  300. package/dist/workflows/db.js +54 -32
  301. package/dist/workflows/parser.js +4 -4
  302. package/dist/workflows/renderer.js +5 -5
  303. package/dist/workflows/runtime/agent-identity.js +56 -0
  304. package/dist/workflows/runtime/checkin.js +57 -0
  305. package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
  306. package/dist/workflows/validate-summary.js +82 -0
  307. package/docs/README.md +1 -1
  308. package/docs/data-and-telemetry.md +6 -6
  309. package/package.json +17 -8
  310. package/dist/commands/add-cli.js +0 -279
  311. package/dist/commands/env.js +0 -213
  312. package/dist/integrations/agent/sdk-runner.js +0 -126
  313. package/dist/output/shapes/vault-list.js +0 -19
  314. package/dist/output/text/proposal-producer.js +0 -8
  315. package/dist/output/text/proposal.js +0 -12
  316. package/dist/output/text/vault.js +0 -16
  317. /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
  318. /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
  319. /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
  320. /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
  321. /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
  322. /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
  323. /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
  324. /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
@@ -0,0 +1,242 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ /**
5
+ * Runtime boundary for non-SQLite host APIs.
6
+ *
7
+ * Single source of truth for every `Bun.*` API (and `import.meta.dir`) used
8
+ * outside the SQLite layer. The rest of the codebase imports these named
9
+ * helpers and NEVER touches `Bun.*` directly, so the application code is
10
+ * runtime-agnostic and the Node path is purely additive.
11
+ *
12
+ * Runtime selection: a single `isBun` flag (computed once at module load)
13
+ * branches each helper. On Bun (the primary/test runtime) the helpers delegate
14
+ * to the native `Bun.*` API so behaviour stays byte-identical; on Node they use
15
+ * the `node:*` equivalents. The Node-only deps (`semver`) are loaded lazily so
16
+ * Bun never resolves them.
17
+ *
18
+ * This is intentionally NOT an adapter/DI/ports-and-adapters layer — just a
19
+ * plain module of named function exports plus a couple of structural types.
20
+ *
21
+ * @module runtime
22
+ */
23
+ import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
24
+ import { createHash } from "node:crypto";
25
+ import { createWriteStream } from "node:fs";
26
+ import { createRequire } from "node:module";
27
+ import path from "node:path";
28
+ import { Readable } from "node:stream";
29
+ import { pipeline } from "node:stream/promises";
30
+ import { fileURLToPath } from "node:url";
31
+ /** True when running under the Bun runtime. Computed once at module load. */
32
+ const isBun = !!process.versions?.bun;
33
+ /** A CommonJS-style require usable from this ESM module on both runtimes. */
34
+ const nodeRequire = createRequire(import.meta.url);
35
+ // ── Subprocess ──────────────────────────────────────────────────────────────
36
+ /**
37
+ * Spawn a child process asynchronously. On Bun delegates to `Bun.spawn` (the
38
+ * returned native `Subprocess` is structurally identical to {@link Subprocess});
39
+ * on Node wraps `child_process.spawn` to expose the same Web-stream surface.
40
+ */
41
+ export function spawn(cmd, options = {}) {
42
+ if (isBun) {
43
+ return bunGlobal().spawn(cmd, options);
44
+ }
45
+ return nodeSpawnAdapter(cmd, options);
46
+ }
47
+ /**
48
+ * Spawn a child process synchronously, returning a Bun-shaped result (note
49
+ * `success` and the Buffer `stdout`/`stderr`). On Node `child_process.spawnSync`
50
+ * is normalised to that shape.
51
+ */
52
+ export function spawnSync(cmd, options = {}) {
53
+ if (isBun) {
54
+ const r = bunGlobal().spawnSync(cmd, options);
55
+ return {
56
+ success: r.success,
57
+ exitCode: r.exitCode ?? null,
58
+ stdout: toBuffer(r.stdout),
59
+ stderr: toBuffer(r.stderr),
60
+ };
61
+ }
62
+ const [bin, ...args] = cmd;
63
+ const r = nodeSpawnSync(bin, args, { cwd: options.cwd, env: options.env ?? process.env });
64
+ const exitCode = r.status;
65
+ return {
66
+ success: r.error === undefined && exitCode === 0,
67
+ exitCode: exitCode ?? null,
68
+ stdout: toBuffer(r.stdout),
69
+ stderr: toBuffer(r.stderr),
70
+ };
71
+ }
72
+ function nodeSpawnAdapter(cmd, options) {
73
+ const [bin, ...args] = cmd;
74
+ const child = nodeSpawn(bin, args, {
75
+ cwd: options.cwd,
76
+ env: options.env ?? process.env,
77
+ detached: options.detached,
78
+ stdio: [stdioFor(options.stdin), stdioFor(options.stdout), stdioFor(options.stderr)],
79
+ });
80
+ const exited = new Promise((resolve, reject) => {
81
+ child.once("exit", (code) => resolve(code ?? 0));
82
+ child.once("error", reject);
83
+ });
84
+ return {
85
+ get stdout() {
86
+ return child.stdout ? Readable.toWeb(child.stdout) : null;
87
+ },
88
+ get stderr() {
89
+ return child.stderr ? Readable.toWeb(child.stderr) : null;
90
+ },
91
+ get stdin() {
92
+ return child.stdin ? Writable_toWeb(child.stdin) : null;
93
+ },
94
+ exited,
95
+ get exitCode() {
96
+ return child.exitCode;
97
+ },
98
+ pid: child.pid,
99
+ kill(signal) {
100
+ child.kill(signal);
101
+ },
102
+ };
103
+ }
104
+ // `node:stream`'s Writable.toWeb is available on Node >=17; referenced via the
105
+ // class to avoid a static import that Bun's typings may not expose.
106
+ function Writable_toWeb(w) {
107
+ const { Writable } = nodeRequire("node:stream");
108
+ return Writable.toWeb(w);
109
+ }
110
+ function stdioFor(mode) {
111
+ return mode ?? "pipe";
112
+ }
113
+ // ── Stdin ───────────────────────────────────────────────────────────────────
114
+ /**
115
+ * Read all of stdin as a single `Buffer`, enforcing a byte limit. When more
116
+ * than `limitBytes` is read, `onLimitExceeded()` is invoked and its return (an
117
+ * Error) is thrown — callers supply their own message so behaviour is exact.
118
+ */
119
+ export async function readStdin(limitBytes, onLimitExceeded) {
120
+ const chunks = [];
121
+ let total = 0;
122
+ for await (const chunk of stdinIterator()) {
123
+ total += chunk.byteLength;
124
+ if (total > limitBytes)
125
+ throw onLimitExceeded();
126
+ chunks.push(chunk);
127
+ }
128
+ return Buffer.concat(chunks);
129
+ }
130
+ function stdinIterator() {
131
+ if (isBun) {
132
+ return bunGlobal().stdin.stream();
133
+ }
134
+ // process.stdin is an async iterable of Buffer on Node.
135
+ return process.stdin;
136
+ }
137
+ // ── File write ──────────────────────────────────────────────────────────────
138
+ /**
139
+ * Stream a `Response` (or its body) to `filePath`. On Bun uses `Bun.write`,
140
+ * which natively streams a `Response` to disk; on Node pipes the response body
141
+ * through `stream/promises.pipeline` so the archive is never fully buffered.
142
+ */
143
+ export async function writeResponseToFile(filePath, res) {
144
+ if (isBun) {
145
+ await bunGlobal().write(filePath, res);
146
+ return;
147
+ }
148
+ if (res.body) {
149
+ const readable = Readable.fromWeb(res.body);
150
+ await pipeline(readable, createWriteStream(filePath));
151
+ return;
152
+ }
153
+ const buf = Buffer.from(await res.arrayBuffer());
154
+ await pipeline(Readable.from(buf), createWriteStream(filePath));
155
+ }
156
+ // ── Hashing ─────────────────────────────────────────────────────────────────
157
+ /**
158
+ * Hex SHA-256 of `data`. Uses `node:crypto` on both runtimes (available in Bun
159
+ * and Node), which is simpler than `Bun.CryptoHasher` and produces identical
160
+ * digests.
161
+ */
162
+ export function sha256Hex(data) {
163
+ return createHash("sha256").update(data).digest("hex");
164
+ }
165
+ /** Hex MD5 of `data`. Uses `node:crypto` on both runtimes. */
166
+ export function md5Hex(data) {
167
+ return createHash("md5").update(data).digest("hex");
168
+ }
169
+ // ── Semver ──────────────────────────────────────────────────────────────────
170
+ /**
171
+ * Compare two semver strings, returning -1, 0, or 1 (the ordering contract of
172
+ * `Bun.semver.order`). On Bun uses the built-in; on Node uses the `semver`
173
+ * package's `compare`, loaded lazily.
174
+ */
175
+ export function semverOrder(a, b) {
176
+ if (isBun) {
177
+ return bunGlobal().semver.order(a, b);
178
+ }
179
+ const semver = nodeRequire("semver");
180
+ return semver.compare(a, b);
181
+ }
182
+ // ── Module resolution ───────────────────────────────────────────────────────
183
+ /**
184
+ * Resolve a module specifier without loading it, relative to `from`. On Bun
185
+ * uses `Bun.resolveSync`; on Node uses `require.resolve`. Throws when the
186
+ * specifier cannot be resolved (mirroring both underlying APIs).
187
+ */
188
+ export function resolveModule(spec, from) {
189
+ if (isBun) {
190
+ return bunGlobal().resolveSync(spec, from);
191
+ }
192
+ return nodeRequire.resolve(spec, { paths: [from] });
193
+ }
194
+ // ── Filesystem paths ────────────────────────────────────────────────────────
195
+ /**
196
+ * The directory of the module identified by `importMetaUrl`. Replaces
197
+ * `import.meta.dir` (Bun-only). Uses `fileURLToPath` + `dirname` on both
198
+ * runtimes — on Bun this is byte-identical to `import.meta.dir`.
199
+ */
200
+ export function getDirname(importMetaUrl) {
201
+ return path.dirname(fileURLToPath(importMetaUrl));
202
+ }
203
+ // ── Sleep ───────────────────────────────────────────────────────────────────
204
+ /**
205
+ * Block the current thread for `ms` without busy-spinning. On Bun uses the real
206
+ * blocking `Bun.sleepSync`; on Node uses `Atomics.wait` on a throwaway buffer,
207
+ * which yields the thread to the OS scheduler the same way.
208
+ */
209
+ export function sleepSync(ms) {
210
+ if (isBun) {
211
+ bunGlobal().sleepSync(ms);
212
+ return;
213
+ }
214
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
215
+ }
216
+ /** Async sleep for `ms`. On Bun uses `Bun.sleep`; on Node a `setTimeout` promise. */
217
+ export function sleep(ms) {
218
+ if (isBun) {
219
+ return bunGlobal().sleep(ms);
220
+ }
221
+ return new Promise((resolve) => setTimeout(resolve, ms));
222
+ }
223
+ // ── Main entrypoint ─────────────────────────────────────────────────────────
224
+ /**
225
+ * Path of the script that started the process. On Bun this is `Bun.main`
226
+ * (which, for compiled binaries, points at a virtual `/$bunfs/` path rather
227
+ * than `process.execPath`); on Node it is `process.argv[1]`.
228
+ */
229
+ export const mainPath = isBun ? bunGlobal().main : process.argv[1];
230
+ /** Access the `Bun` global. Only ever called when `isBun` is true. */
231
+ function bunGlobal() {
232
+ return globalThis.Bun;
233
+ }
234
+ function toBuffer(data) {
235
+ if (data == null)
236
+ return Buffer.alloc(0);
237
+ if (Buffer.isBuffer(data))
238
+ return data;
239
+ if (typeof data === "string")
240
+ return Buffer.from(data, "utf8");
241
+ return Buffer.from(data);
242
+ }