allyhub 0.5.0 → 0.7.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 (632) hide show
  1. package/dist/audio-text.js +1 -1
  2. package/dist/commands/add.js +2 -2
  3. package/dist/commands/cloud-tools.js +5 -5
  4. package/dist/commands/dev.js +1 -1
  5. package/dist/commands/frames/piece.js +1 -1
  6. package/dist/commands/frames/sheet.js +1 -1
  7. package/dist/commands/frames.js +8 -8
  8. package/dist/commands/index.js +1 -1
  9. package/dist/commands/inspect/common.js +1 -1
  10. package/dist/commands/inspect/layout.js +1 -1
  11. package/dist/commands/render.js +1 -1
  12. package/dist/commands/sheet.js +7 -7
  13. package/dist/commands/site.js +3 -2
  14. package/dist/commands/skills.js +3 -3
  15. package/dist/commands/slides.js +2 -2
  16. package/dist/node_modules/@allyhub-next/audio/dist/node/index.js +1 -1
  17. package/dist/node_modules/@allyhub-next/audio/dist/node/master.js +1 -1
  18. package/dist/node_modules/@allyhub-next/audio/package.json +1 -1
  19. package/dist/node_modules/@allyhub-next/browser/dist/html.js +1 -1
  20. package/dist/node_modules/@allyhub-next/browser/package.json +1 -1
  21. package/dist/node_modules/@allyhub-next/build/dist/content.d.ts +4 -0
  22. package/dist/node_modules/@allyhub-next/build/dist/content.js +1 -1
  23. package/dist/node_modules/@allyhub-next/build/dist/index.d.ts +2 -2
  24. package/dist/node_modules/@allyhub-next/build/dist/index.js +1 -1
  25. package/dist/node_modules/@allyhub-next/build/dist/meta-worker.d.ts +2 -2
  26. package/dist/node_modules/@allyhub-next/build/dist/meta-worker.js +3 -3
  27. package/dist/node_modules/@allyhub-next/build/dist/move-refs.d.ts +1 -1
  28. package/dist/node_modules/@allyhub-next/build/dist/move-refs.js +1 -1
  29. package/dist/node_modules/@allyhub-next/build/dist/plugin.d.ts +12 -3
  30. package/dist/node_modules/@allyhub-next/build/dist/plugin.js +7 -6
  31. package/dist/node_modules/@allyhub-next/build/dist/prepare.d.ts +9 -5
  32. package/dist/node_modules/@allyhub-next/build/dist/prepare.js +2 -2
  33. package/dist/node_modules/@allyhub-next/build/dist/vite.d.ts +10 -0
  34. package/dist/node_modules/@allyhub-next/build/dist/vite.js +2 -2
  35. package/dist/node_modules/@allyhub-next/build/package.json +1 -1
  36. package/dist/node_modules/@allyhub-next/chart/dist/chart-xml.js +2 -2
  37. package/dist/node_modules/@allyhub-next/chart/dist/chart.d.ts +14 -5
  38. package/dist/node_modules/@allyhub-next/chart/dist/chart.js +1 -1
  39. package/dist/node_modules/@allyhub-next/chart/package.json +1 -1
  40. package/dist/node_modules/@allyhub-next/check/dist/check.js +3 -3
  41. package/dist/node_modules/@allyhub-next/check/package.json +1 -1
  42. package/dist/node_modules/@allyhub-next/cloud/dist/blobs.js +2 -0
  43. package/dist/node_modules/@allyhub-next/cloud/dist/call.js +4 -2
  44. package/dist/node_modules/@allyhub-next/cloud/dist/client.js +1 -1
  45. package/dist/node_modules/@allyhub-next/cloud/dist/errors.js +1 -1
  46. package/dist/node_modules/@allyhub-next/cloud/dist/hashes.js +2 -0
  47. package/dist/node_modules/@allyhub-next/cloud/dist/index.js +1 -1
  48. package/dist/node_modules/@allyhub-next/cloud/dist/sites.js +2 -0
  49. package/dist/node_modules/@allyhub-next/cloud/dist/voice.js +1 -1
  50. package/dist/node_modules/@allyhub-next/cloud/package.json +1 -1
  51. package/dist/node_modules/@allyhub-next/components/package.json +1 -1
  52. package/dist/node_modules/@allyhub-next/components/r/caption-subtitle.json +1 -1
  53. package/dist/node_modules/@allyhub-next/components/src/caption-subtitle.ts +54 -16
  54. package/dist/node_modules/@allyhub-next/dev-server/dist/background.js +1 -1
  55. package/dist/node_modules/@allyhub-next/dev-server/dist/exports.js +1 -1
  56. package/dist/node_modules/@allyhub-next/dev-server/dist/fonts.js +2 -0
  57. package/dist/node_modules/@allyhub-next/dev-server/dist/index.js +1 -1
  58. package/dist/node_modules/@allyhub-next/dev-server/dist/live.js +1 -1
  59. package/dist/node_modules/@allyhub-next/dev-server/dist/project.js +1 -1
  60. package/dist/node_modules/@allyhub-next/dev-server/dist/reach.js +2 -0
  61. package/dist/node_modules/@allyhub-next/dev-server/dist/record.js +2 -0
  62. package/dist/node_modules/@allyhub-next/dev-server/dist/server.js +2 -2
  63. package/dist/node_modules/@allyhub-next/dev-server/dist/tools.js +1 -1
  64. package/dist/node_modules/@allyhub-next/dev-server/dist/tree.js +2 -0
  65. package/dist/node_modules/@allyhub-next/dev-server/package.json +1 -1
  66. package/dist/node_modules/@allyhub-next/doc/package.json +1 -1
  67. package/dist/node_modules/@allyhub-next/export/dist/deck-pptx.js +1 -1
  68. package/dist/node_modules/@allyhub-next/export/dist/export.js +5 -5
  69. package/dist/node_modules/@allyhub-next/export/dist/index.js +1 -1
  70. package/dist/node_modules/@allyhub-next/export/package.json +1 -1
  71. package/dist/node_modules/@allyhub-next/formats/dist/data/deck-code.d.ts +205 -0
  72. package/dist/node_modules/@allyhub-next/formats/dist/data/deck-code.js +2 -0
  73. package/dist/node_modules/@allyhub-next/formats/dist/data/script.d.ts +4 -1
  74. package/dist/node_modules/@allyhub-next/formats/dist/data/script.js +1 -1
  75. package/dist/node_modules/@allyhub-next/formats/dist/data/sheet.d.ts +248 -18
  76. package/dist/node_modules/@allyhub-next/formats/dist/data/sheet.js +1 -1
  77. package/dist/node_modules/@allyhub-next/formats/dist/data/slides.d.ts +1114 -91
  78. package/dist/node_modules/@allyhub-next/formats/dist/data/slides.js +1 -1
  79. package/dist/node_modules/@allyhub-next/formats/dist/data/website.d.ts +20 -0
  80. package/dist/node_modules/@allyhub-next/formats/dist/data/website.js +2 -0
  81. package/dist/node_modules/@allyhub-next/formats/dist/index.d.ts +4 -0
  82. package/dist/node_modules/@allyhub-next/formats/dist/index.js +1 -1
  83. package/dist/node_modules/@allyhub-next/formats/dist/items.d.ts +1 -1
  84. package/dist/node_modules/@allyhub-next/formats/dist/items.js +1 -1
  85. package/dist/node_modules/@allyhub-next/formats/dist/media-type.d.ts +3 -0
  86. package/dist/node_modules/@allyhub-next/formats/dist/media-type.js +2 -0
  87. package/dist/node_modules/@allyhub-next/formats/dist/schemas.d.ts +625 -30
  88. package/dist/node_modules/@allyhub-next/formats/dist/schemas.js +1 -1
  89. package/dist/node_modules/@allyhub-next/formats/dist/strict.d.ts +2 -0
  90. package/dist/node_modules/@allyhub-next/formats/dist/strict.js +1 -1
  91. package/dist/node_modules/@allyhub-next/formats/dist/zip.d.ts +17 -0
  92. package/dist/node_modules/@allyhub-next/formats/dist/zip.js +2 -0
  93. package/dist/node_modules/@allyhub-next/formats/package.json +2 -1
  94. package/dist/node_modules/@allyhub-next/measure/package.json +1 -1
  95. package/dist/node_modules/@allyhub-next/media/dist/index.d.ts +1 -1
  96. package/dist/node_modules/@allyhub-next/media/dist/index.js +1 -1
  97. package/dist/node_modules/@allyhub-next/media/dist/sheet.d.ts +2 -0
  98. package/dist/node_modules/@allyhub-next/media/dist/sheet.js +7 -7
  99. package/dist/node_modules/@allyhub-next/media/package.json +1 -1
  100. package/dist/node_modules/@allyhub-next/model/package.json +1 -1
  101. package/dist/node_modules/@allyhub-next/ooxml/dist/brightness.d.ts +31 -0
  102. package/dist/node_modules/@allyhub-next/ooxml/dist/brightness.js +2 -0
  103. package/dist/node_modules/@allyhub-next/ooxml/dist/color.d.ts +33 -0
  104. package/dist/node_modules/@allyhub-next/ooxml/dist/color.js +2 -0
  105. package/dist/node_modules/@allyhub-next/ooxml/dist/enums.d.ts +13 -0
  106. package/dist/node_modules/@allyhub-next/ooxml/dist/enums.js +2 -0
  107. package/dist/node_modules/@allyhub-next/ooxml/dist/ext.d.ts +79 -0
  108. package/dist/node_modules/@allyhub-next/ooxml/dist/ext.js +2 -0
  109. package/dist/node_modules/@allyhub-next/ooxml/dist/generated/enums.d.ts +132 -0
  110. package/dist/node_modules/@allyhub-next/ooxml/dist/generated/enums.js +2 -0
  111. package/dist/node_modules/@allyhub-next/ooxml/dist/generated/presets.d.ts +28 -0
  112. package/dist/node_modules/@allyhub-next/ooxml/dist/generated/presets.js +2 -0
  113. package/dist/node_modules/@allyhub-next/ooxml/dist/generated/spec.d.ts +4708 -0
  114. package/dist/node_modules/@allyhub-next/ooxml/dist/generated/spec.js +2 -0
  115. package/dist/node_modules/@allyhub-next/ooxml/dist/geometry/index.d.ts +57 -0
  116. package/dist/node_modules/@allyhub-next/ooxml/dist/geometry/index.js +2 -0
  117. package/dist/node_modules/@allyhub-next/ooxml/dist/index.d.ts +10 -0
  118. package/dist/node_modules/@allyhub-next/ooxml/dist/index.js +2 -0
  119. package/dist/node_modules/@allyhub-next/ooxml/dist/mce.d.ts +12 -0
  120. package/dist/node_modules/@allyhub-next/ooxml/dist/mce.js +2 -0
  121. package/dist/node_modules/@allyhub-next/ooxml/dist/node.d.ts +111 -0
  122. package/dist/node_modules/@allyhub-next/ooxml/dist/node.js +2 -0
  123. package/dist/node_modules/@allyhub-next/ooxml/dist/ns.d.ts +45 -0
  124. package/dist/node_modules/@allyhub-next/ooxml/dist/ns.js +2 -0
  125. package/dist/node_modules/@allyhub-next/ooxml/dist/opc.d.ts +48 -0
  126. package/dist/node_modules/@allyhub-next/ooxml/dist/opc.js +2 -0
  127. package/dist/node_modules/@allyhub-next/ooxml/dist/report.d.ts +45 -0
  128. package/dist/node_modules/@allyhub-next/ooxml/dist/report.js +2 -0
  129. package/dist/node_modules/@allyhub-next/ooxml/dist/xml.d.ts +28 -0
  130. package/dist/node_modules/@allyhub-next/ooxml/dist/xml.js +2 -0
  131. package/dist/node_modules/@allyhub-next/ooxml/package.json +26 -0
  132. package/dist/node_modules/@allyhub-next/project/dist/deck-keys.js +2 -0
  133. package/dist/node_modules/@allyhub-next/project/dist/deck-measure.js +2 -0
  134. package/dist/node_modules/@allyhub-next/project/dist/deck-pool.js +2 -0
  135. package/dist/node_modules/@allyhub-next/project/dist/index.js +1 -1
  136. package/dist/node_modules/@allyhub-next/project/dist/session.js +1 -1
  137. package/dist/node_modules/@allyhub-next/project/dist/stills.js +2 -0
  138. package/dist/node_modules/@allyhub-next/project/package.json +1 -1
  139. package/dist/node_modules/@allyhub-next/protocol/dist/account.d.ts +338 -0
  140. package/dist/node_modules/@allyhub-next/protocol/dist/account.js +2 -0
  141. package/dist/node_modules/@allyhub-next/protocol/dist/auth.d.ts +12 -13
  142. package/dist/node_modules/@allyhub-next/protocol/dist/auth.js +1 -1
  143. package/dist/node_modules/@allyhub-next/protocol/dist/blobs.d.ts +35 -0
  144. package/dist/node_modules/@allyhub-next/protocol/dist/blobs.js +2 -0
  145. package/dist/node_modules/@allyhub-next/protocol/dist/cloud.d.ts +101 -32
  146. package/dist/node_modules/@allyhub-next/protocol/dist/cloud.js +1 -1
  147. package/dist/node_modules/@allyhub-next/protocol/dist/editor.d.ts +89 -5
  148. package/dist/node_modules/@allyhub-next/protocol/dist/editor.js +1 -1
  149. package/dist/node_modules/@allyhub-next/protocol/dist/files.d.ts +2 -2
  150. package/dist/node_modules/@allyhub-next/protocol/dist/index.d.ts +6 -0
  151. package/dist/node_modules/@allyhub-next/protocol/dist/index.js +1 -1
  152. package/dist/node_modules/@allyhub-next/protocol/dist/notes.d.ts +23 -0
  153. package/dist/node_modules/@allyhub-next/protocol/dist/notes.js +1 -1
  154. package/dist/node_modules/@allyhub-next/protocol/dist/open.d.ts +13 -0
  155. package/dist/node_modules/@allyhub-next/protocol/dist/open.js +2 -0
  156. package/dist/node_modules/@allyhub-next/protocol/dist/registry.d.ts +73 -59
  157. package/dist/node_modules/@allyhub-next/protocol/dist/registry.js +1 -1
  158. package/dist/node_modules/@allyhub-next/protocol/dist/routes.d.ts +1 -1
  159. package/dist/node_modules/@allyhub-next/protocol/dist/routes.js +1 -1
  160. package/dist/node_modules/@allyhub-next/protocol/dist/shares.d.ts +115 -0
  161. package/dist/node_modules/@allyhub-next/protocol/dist/shares.js +2 -0
  162. package/dist/node_modules/@allyhub-next/protocol/dist/sites.d.ts +293 -0
  163. package/dist/node_modules/@allyhub-next/protocol/dist/sites.js +2 -0
  164. package/dist/node_modules/@allyhub-next/protocol/dist/snapshots.d.ts +377 -0
  165. package/dist/node_modules/@allyhub-next/protocol/dist/snapshots.js +2 -0
  166. package/dist/node_modules/@allyhub-next/protocol/dist/teams.d.ts +27 -9
  167. package/dist/node_modules/@allyhub-next/protocol/dist/teams.js +1 -1
  168. package/dist/node_modules/@allyhub-next/protocol/dist/tools.d.ts +53 -14
  169. package/dist/node_modules/@allyhub-next/protocol/dist/tools.js +1 -1
  170. package/dist/node_modules/@allyhub-next/protocol/package.json +2 -1
  171. package/dist/node_modules/@allyhub-next/registry/package.json +1 -1
  172. package/dist/node_modules/@allyhub-next/render/dist/doc/fonts.js +3 -2
  173. package/dist/node_modules/@allyhub-next/render/dist/doc/index.js +1 -1
  174. package/dist/node_modules/@allyhub-next/render/dist/doc/pdf.js +34 -0
  175. package/dist/node_modules/@allyhub-next/render/dist/doc/print.js +4 -4
  176. package/dist/node_modules/@allyhub-next/render/dist/exports.js +2 -2
  177. package/dist/node_modules/@allyhub-next/render/dist/pdf.js +2 -0
  178. package/dist/node_modules/@allyhub-next/render/package.json +1 -1
  179. package/dist/node_modules/@allyhub-next/runtime/dist/fonts.js +1 -1
  180. package/dist/node_modules/@allyhub-next/runtime/dist/music.js +1 -1
  181. package/dist/node_modules/@allyhub-next/runtime/package.json +1 -1
  182. package/dist/node_modules/@allyhub-next/runtimes/package.json +1 -1
  183. package/dist/node_modules/@allyhub-next/runtimes/schemas/runtimes.schema.json +25 -5
  184. package/dist/node_modules/@allyhub-next/scaffold/dist/index.js +4 -4
  185. package/dist/node_modules/@allyhub-next/scaffold/package.json +1 -1
  186. package/dist/node_modules/@allyhub-next/scenery/package.json +1 -1
  187. package/dist/node_modules/@allyhub-next/scenery-host/dist/bundle.d.ts +10 -0
  188. package/dist/node_modules/@allyhub-next/scenery-host/dist/bundle.js +3 -3
  189. package/dist/node_modules/@allyhub-next/scenery-host/package.json +1 -1
  190. package/dist/node_modules/@allyhub-next/sheet/dist/api/capabilities.js +1 -1
  191. package/dist/node_modules/@allyhub-next/sheet/dist/api/index.d.ts +1 -0
  192. package/dist/node_modules/@allyhub-next/sheet/dist/api/index.js +1 -1
  193. package/dist/node_modules/@allyhub-next/sheet/dist/api/page.d.ts +83 -0
  194. package/dist/node_modules/@allyhub-next/sheet/dist/api/page.js +2 -0
  195. package/dist/node_modules/@allyhub-next/sheet/dist/api/workbook.d.ts +40 -1
  196. package/dist/node_modules/@allyhub-next/sheet/dist/api/workbook.js +1 -1
  197. package/dist/node_modules/@allyhub-next/sheet/dist/calc/analyse.d.ts +9 -3
  198. package/dist/node_modules/@allyhub-next/sheet/dist/calc/analyse.js +1 -1
  199. package/dist/node_modules/@allyhub-next/sheet/dist/calc/coerce.d.ts +5 -1
  200. package/dist/node_modules/@allyhub-next/sheet/dist/calc/coerce.js +1 -1
  201. package/dist/node_modules/@allyhub-next/sheet/dist/calc/engine.d.ts +60 -13
  202. package/dist/node_modules/@allyhub-next/sheet/dist/calc/engine.js +1 -1
  203. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/aggregate.js +1 -1
  204. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/convert.d.ts +4 -0
  205. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/convert.js +2 -0
  206. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/criteria.js +1 -1
  207. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/database.js +1 -1
  208. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/date.js +1 -1
  209. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/define.d.ts +27 -1
  210. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/define.js +1 -1
  211. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/delimiters.d.ts +16 -0
  212. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/delimiters.js +2 -0
  213. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/dynamic.d.ts +18 -1
  214. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/dynamic.js +1 -1
  215. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/finance.js +1 -1
  216. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/index.d.ts +2 -0
  217. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/index.js +1 -1
  218. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/info.js +1 -1
  219. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/kernels.js +1 -1
  220. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/logical.js +1 -1
  221. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/lookup.js +1 -1
  222. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/maths.js +1 -1
  223. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/modern.d.ts +2 -0
  224. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/modern.js +2 -0
  225. package/dist/node_modules/@allyhub-next/sheet/dist/calc/functions/text.js +1 -1
  226. package/dist/node_modules/@allyhub-next/sheet/dist/calc/graph.d.ts +38 -0
  227. package/dist/node_modules/@allyhub-next/sheet/dist/calc/graph.js +2 -0
  228. package/dist/node_modules/@allyhub-next/sheet/dist/calc/indexes.d.ts +19 -0
  229. package/dist/node_modules/@allyhub-next/sheet/dist/calc/indexes.js +2 -0
  230. package/dist/node_modules/@allyhub-next/sheet/dist/calc/remote.d.ts +49 -0
  231. package/dist/node_modules/@allyhub-next/sheet/dist/calc/remote.js +2 -0
  232. package/dist/node_modules/@allyhub-next/sheet/dist/calc/server.d.ts +82 -0
  233. package/dist/node_modules/@allyhub-next/sheet/dist/calc/server.js +2 -0
  234. package/dist/node_modules/@allyhub-next/sheet/dist/calc/types.d.ts +6 -1
  235. package/dist/node_modules/@allyhub-next/sheet/dist/calc/types.js +1 -1
  236. package/dist/node_modules/@allyhub-next/sheet/dist/chart.js +1 -1
  237. package/dist/node_modules/@allyhub-next/sheet/dist/check.js +1 -1
  238. package/dist/node_modules/@allyhub-next/sheet/dist/diff.d.ts +15 -0
  239. package/dist/node_modules/@allyhub-next/sheet/dist/diff.js +1 -1
  240. package/dist/node_modules/@allyhub-next/sheet/dist/export.d.ts +29 -8
  241. package/dist/node_modules/@allyhub-next/sheet/dist/export.js +3 -4
  242. package/dist/node_modules/@allyhub-next/sheet/dist/file.js +2 -2
  243. package/dist/node_modules/@allyhub-next/sheet/dist/format.d.ts +8 -2
  244. package/dist/node_modules/@allyhub-next/sheet/dist/format.js +1 -1
  245. package/dist/node_modules/@allyhub-next/sheet/dist/html.d.ts +52 -4
  246. package/dist/node_modules/@allyhub-next/sheet/dist/html.js +43 -11
  247. package/dist/node_modules/@allyhub-next/sheet/dist/index.d.ts +7 -3
  248. package/dist/node_modules/@allyhub-next/sheet/dist/index.js +1 -1
  249. package/dist/node_modules/@allyhub-next/sheet/dist/inspect.js +1 -1
  250. package/dist/node_modules/@allyhub-next/sheet/dist/paginate.d.ts +98 -0
  251. package/dist/node_modules/@allyhub-next/sheet/dist/paginate.js +2 -0
  252. package/dist/node_modules/@allyhub-next/sheet/dist/structure.js +1 -1
  253. package/dist/node_modules/@allyhub-next/sheet/dist/table-style.d.ts +32 -0
  254. package/dist/node_modules/@allyhub-next/sheet/dist/table-style.js +2 -0
  255. package/dist/node_modules/@allyhub-next/sheet/dist/table-styles.d.ts +3 -0
  256. package/dist/node_modules/@allyhub-next/sheet/dist/table-styles.js +2 -0
  257. package/dist/node_modules/@allyhub-next/sheet/dist/values.js +1 -1
  258. package/dist/node_modules/@allyhub-next/sheet/dist/workbook.d.ts +10 -1
  259. package/dist/node_modules/@allyhub-next/sheet/dist/workbook.js +1 -1
  260. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/charts.d.ts +12 -1
  261. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/charts.js +1 -1
  262. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/formula.d.ts +14 -4
  263. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/formula.js +2 -2
  264. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/functions.d.ts +11 -1
  265. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/functions.js +36 -16
  266. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/import.d.ts +6 -1
  267. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/import.js +1 -1
  268. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/read.d.ts +44 -2
  269. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/read.js +2 -1
  270. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/sax.d.ts +23 -0
  271. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/sax.js +2 -0
  272. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/styles.d.ts +2 -0
  273. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/styles.js +1 -1
  274. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/write.d.ts +6 -0
  275. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/write.js +1 -1
  276. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/zip.d.ts +40 -0
  277. package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/zip.js +2 -0
  278. package/dist/node_modules/@allyhub-next/sheet/package.json +1 -1
  279. package/dist/node_modules/@allyhub-next/slides-core/dist/animation.js +1 -1
  280. package/dist/node_modules/@allyhub-next/slides-core/dist/api.d.ts +121 -44
  281. package/dist/node_modules/@allyhub-next/slides-core/dist/api.js +2 -2
  282. package/dist/node_modules/@allyhub-next/slides-core/dist/capabilities.js +1 -1
  283. package/dist/node_modules/@allyhub-next/slides-core/dist/chart-api.d.ts +50 -13
  284. package/dist/node_modules/@allyhub-next/slides-core/dist/chart-api.js +1 -1
  285. package/dist/node_modules/@allyhub-next/slides-core/dist/chart-file.js +1 -1
  286. package/dist/node_modules/@allyhub-next/slides-core/dist/check.js +1 -1
  287. package/dist/node_modules/@allyhub-next/slides-core/dist/code.d.ts +33 -0
  288. package/dist/node_modules/@allyhub-next/slides-core/dist/code.js +2 -0
  289. package/dist/node_modules/@allyhub-next/slides-core/dist/components.d.ts +31 -0
  290. package/dist/node_modules/@allyhub-next/slides-core/dist/components.js +2 -0
  291. package/dist/node_modules/@allyhub-next/slides-core/dist/enums.d.ts +188 -5
  292. package/dist/node_modules/@allyhub-next/slides-core/dist/enums.js +1 -1
  293. package/dist/node_modules/@allyhub-next/slides-core/dist/file.d.ts +43 -21
  294. package/dist/node_modules/@allyhub-next/slides-core/dist/file.js +3 -3
  295. package/dist/node_modules/@allyhub-next/slides-core/dist/identity.d.ts +17 -0
  296. package/dist/node_modules/@allyhub-next/slides-core/dist/identity.js +2 -0
  297. package/dist/node_modules/@allyhub-next/slides-core/dist/index.d.ts +5 -0
  298. package/dist/node_modules/@allyhub-next/slides-core/dist/index.js +1 -1
  299. package/dist/node_modules/@allyhub-next/slides-core/dist/lang.d.ts +6 -0
  300. package/dist/node_modules/@allyhub-next/slides-core/dist/lang.js +2 -0
  301. package/dist/node_modules/@allyhub-next/slides-core/dist/measure.js +1 -1
  302. package/dist/node_modules/@allyhub-next/slides-core/dist/merge.d.ts +58 -0
  303. package/dist/node_modules/@allyhub-next/slides-core/dist/merge.js +2 -0
  304. package/dist/node_modules/@allyhub-next/slides-core/dist/model.d.ts +38 -4
  305. package/dist/node_modules/@allyhub-next/slides-core/dist/office.d.ts +27 -1
  306. package/dist/node_modules/@allyhub-next/slides-core/dist/office.js +1 -1
  307. package/dist/node_modules/@allyhub-next/slides-core/dist/resolve.d.ts +26 -5
  308. package/dist/node_modules/@allyhub-next/slides-core/dist/resolve.js +1 -1
  309. package/dist/node_modules/@allyhub-next/slides-core/dist/script.d.ts +18 -16
  310. package/dist/node_modules/@allyhub-next/slides-core/dist/script.js +2 -2
  311. package/dist/node_modules/@allyhub-next/slides-core/dist/stage.d.ts +51 -53
  312. package/dist/node_modules/@allyhub-next/slides-core/dist/strict.js +1 -1
  313. package/dist/node_modules/@allyhub-next/slides-core/dist/units.d.ts +27 -0
  314. package/dist/node_modules/@allyhub-next/slides-core/dist/units.js +1 -1
  315. package/dist/node_modules/@allyhub-next/slides-core/dist/values.d.ts +7 -0
  316. package/dist/node_modules/@allyhub-next/slides-core/dist/values.js +2 -0
  317. package/dist/node_modules/@allyhub-next/slides-core/package.json +1 -1
  318. package/dist/node_modules/@allyhub-next/slides-pptx/dist/charts.js +1 -1
  319. package/dist/node_modules/@allyhub-next/slides-pptx/dist/import/code.js +4 -0
  320. package/dist/node_modules/@allyhub-next/slides-pptx/dist/import/index.js +3 -0
  321. package/dist/node_modules/@allyhub-next/slides-pptx/dist/import/names.js +2 -0
  322. package/dist/node_modules/@allyhub-next/slides-pptx/dist/import/script.js +2 -0
  323. package/dist/node_modules/@allyhub-next/slides-pptx/dist/index.js +1 -1
  324. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read/chart.js +2 -0
  325. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read/common.js +2 -0
  326. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read/index.js +4 -0
  327. package/dist/{site.js → node_modules/@allyhub-next/slides-pptx/dist/read/model.js} +1 -1
  328. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read/shapes.js +2 -0
  329. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read/table.js +2 -0
  330. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read/text.js +2 -0
  331. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read/timing.js +2 -0
  332. package/dist/node_modules/@allyhub-next/slides-pptx/dist/shapes.js +1 -1
  333. package/dist/node_modules/@allyhub-next/slides-pptx/dist/text.js +1 -1
  334. package/dist/node_modules/@allyhub-next/slides-pptx/dist/theme.js +1 -1
  335. package/dist/node_modules/@allyhub-next/slides-pptx/dist/timing.js +1 -1
  336. package/dist/node_modules/@allyhub-next/slides-pptx/dist/write.js +2 -2
  337. package/dist/node_modules/@allyhub-next/slides-pptx/dist/xml.js +2 -2
  338. package/dist/node_modules/@allyhub-next/slides-pptx/package.json +1 -1
  339. package/dist/node_modules/@allyhub-next/slides-runtime/dist/component.js +2 -0
  340. package/dist/node_modules/@allyhub-next/slides-runtime/dist/draw.js +2 -2
  341. package/dist/node_modules/@allyhub-next/slides-runtime/dist/index.js +1 -1
  342. package/dist/node_modules/@allyhub-next/slides-runtime/dist/load.js +5 -5
  343. package/dist/node_modules/@allyhub-next/slides-runtime/package.json +5 -1
  344. package/dist/node_modules/@allyhub-next/stage/dist/graphics.js +1 -1
  345. package/dist/node_modules/@allyhub-next/stage/dist/index.js +1 -1
  346. package/dist/node_modules/@allyhub-next/stage/dist/page.js +22 -12
  347. package/dist/node_modules/@allyhub-next/stage/dist/scenery-page.js +5 -5
  348. package/dist/node_modules/@allyhub-next/stage/dist/server.js +1 -1
  349. package/dist/node_modules/@allyhub-next/stage/package.json +1 -1
  350. package/dist/node_modules/@allyhub-next/stage-page/dist/host.js +1 -20
  351. package/dist/node_modules/@allyhub-next/stage-page/dist/runtime/probe.html +8 -0
  352. package/dist/{astro.js → node_modules/@allyhub-next/stage-page/dist/runtime/probe.js} +1 -1
  353. package/dist/node_modules/@allyhub-next/stage-page/dist/runtime/runtime.js +79 -0
  354. package/dist/node_modules/@allyhub-next/stage-page/dist/runtime/stage.html +21 -0
  355. package/dist/node_modules/@allyhub-next/stage-page/dist/runtime/stage.js +3 -0
  356. package/dist/node_modules/@allyhub-next/stage-page/dist/runtime/viewer.html +9 -0
  357. package/dist/node_modules/@allyhub-next/stage-page/dist/runtime/viewer.js +3 -0
  358. package/dist/node_modules/@allyhub-next/stage-page/package.json +2 -3
  359. package/dist/node_modules/@allyhub-next/video-core/dist/captions.js +6 -6
  360. package/dist/node_modules/@allyhub-next/video-core/dist/fact.d.ts +47 -8
  361. package/dist/node_modules/@allyhub-next/video-core/dist/fact.js +1 -1
  362. package/dist/node_modules/@allyhub-next/video-core/dist/index.d.ts +1 -0
  363. package/dist/node_modules/@allyhub-next/video-core/dist/index.js +1 -1
  364. package/dist/node_modules/@allyhub-next/video-core/dist/marks.d.ts +14 -0
  365. package/dist/node_modules/@allyhub-next/video-core/dist/marks.js +1 -1
  366. package/dist/node_modules/@allyhub-next/video-core/dist/music.d.ts +2 -1
  367. package/dist/node_modules/@allyhub-next/video-core/dist/piece.d.ts +11 -2
  368. package/dist/node_modules/@allyhub-next/video-core/dist/problem.d.ts +4 -0
  369. package/dist/node_modules/@allyhub-next/video-core/dist/problem.js +1 -1
  370. package/dist/node_modules/@allyhub-next/video-core/dist/schema.d.ts +2 -2
  371. package/dist/node_modules/@allyhub-next/video-core/dist/schema.js +1 -1
  372. package/dist/node_modules/@allyhub-next/video-core/dist/script.d.ts +2 -1
  373. package/dist/node_modules/@allyhub-next/video-core/dist/script.js +1 -1
  374. package/dist/node_modules/@allyhub-next/video-core/dist/source.d.ts +7 -0
  375. package/dist/node_modules/@allyhub-next/video-core/dist/source.js +2 -0
  376. package/dist/node_modules/@allyhub-next/video-core/dist/timeline.d.ts +10 -33
  377. package/dist/node_modules/@allyhub-next/video-core/package.json +1 -1
  378. package/dist/node_modules/@allyhub-next/website/LICENSE +241 -0
  379. package/dist/node_modules/@allyhub-next/website/dist/index.js +2 -0
  380. package/dist/node_modules/@allyhub-next/website/dist/publish.js +3 -0
  381. package/dist/node_modules/@allyhub-next/website/dist/rules.js +2 -0
  382. package/dist/node_modules/@allyhub-next/website/dist/website.js +4 -0
  383. package/dist/node_modules/@allyhub-next/website/package.json +13 -0
  384. package/dist/text/facts-text.js +4 -4
  385. package/dist/works.js +1 -1
  386. package/editor-web/assets/calc-worker-Bz9r26p1.js +158 -0
  387. package/editor-web/assets/dist-0emakyZE.js +36 -0
  388. package/editor-web/assets/dist-B3UoDUa5.js +37 -0
  389. package/editor-web/assets/dist-B6KzR3pN.js +10 -0
  390. package/editor-web/assets/dist-Bc5iA5k1.js +1 -0
  391. package/editor-web/assets/dist-CTQIm8Im.js +10 -0
  392. package/editor-web/assets/dist-CiHNHwyq.js +2 -0
  393. package/editor-web/assets/dist-DNZ8PQ-E.js +224 -0
  394. package/editor-web/assets/index-CFt3ovRY.js +69 -0
  395. package/editor-web/assets/index-ujKjdu_s.css +2 -0
  396. package/editor-web/assets/minus-BhoPZC5P.js +1 -0
  397. package/editor-web/assets/react-C_-rEEBU.js +101 -0
  398. package/editor-web/assets/tabs-Den4gHrU.js +105 -0
  399. package/editor-web/assets/text-align-start-CsW4nqqL.js +1 -0
  400. package/editor-web/index.html +5 -5
  401. package/package.json +8 -14
  402. package/dist/astro.d.ts +0 -2
  403. package/dist/node_modules/@allyhub-next/audio/dist/at-cut.d.ts +0 -52
  404. package/dist/node_modules/@allyhub-next/audio/dist/decode.d.ts +0 -33
  405. package/dist/node_modules/@allyhub-next/audio/dist/envelope.d.ts +0 -37
  406. package/dist/node_modules/@allyhub-next/audio/dist/index.d.ts +0 -17
  407. package/dist/node_modules/@allyhub-next/audio/dist/levels.d.ts +0 -97
  408. package/dist/node_modules/@allyhub-next/audio/dist/master.d.ts +0 -29
  409. package/dist/node_modules/@allyhub-next/audio/dist/music.d.ts +0 -11
  410. package/dist/node_modules/@allyhub-next/audio/dist/node/decode.d.ts +0 -39
  411. package/dist/node_modules/@allyhub-next/audio/dist/node/ebur128.d.ts +0 -25
  412. package/dist/node_modules/@allyhub-next/audio/dist/node/ffmpeg.d.ts +0 -31
  413. package/dist/node_modules/@allyhub-next/audio/dist/node/index.d.ts +0 -8
  414. package/dist/node_modules/@allyhub-next/audio/dist/node/loudness.d.ts +0 -18
  415. package/dist/node_modules/@allyhub-next/audio/dist/node/master.d.ts +0 -42
  416. package/dist/node_modules/@allyhub-next/audio/dist/node/measure.d.ts +0 -60
  417. package/dist/node_modules/@allyhub-next/audio/dist/node/mix.d.ts +0 -31
  418. package/dist/node_modules/@allyhub-next/audio/dist/plan.d.ts +0 -143
  419. package/dist/node_modules/@allyhub-next/audio/dist/recorded.d.ts +0 -26
  420. package/dist/node_modules/@allyhub-next/audio/dist/recording/bandwidth.d.ts +0 -47
  421. package/dist/node_modules/@allyhub-next/audio/dist/recording/chain.d.ts +0 -89
  422. package/dist/node_modules/@allyhub-next/audio/dist/recording/dynamics.d.ts +0 -64
  423. package/dist/node_modules/@allyhub-next/audio/dist/recording/fft.d.ts +0 -26
  424. package/dist/node_modules/@allyhub-next/audio/dist/recording/filters.d.ts +0 -42
  425. package/dist/node_modules/@allyhub-next/audio/dist/recording/fit.d.ts +0 -56
  426. package/dist/node_modules/@allyhub-next/audio/dist/recording/index.d.ts +0 -10
  427. package/dist/node_modules/@allyhub-next/audio/dist/recording/loudness.d.ts +0 -12
  428. package/dist/node_modules/@allyhub-next/audio/dist/recording/measure.d.ts +0 -67
  429. package/dist/node_modules/@allyhub-next/audio/dist/recording/mic.d.ts +0 -32
  430. package/dist/node_modules/@allyhub-next/audio/dist/recording/noise.d.ts +0 -27
  431. package/dist/node_modules/@allyhub-next/audio/dist/recording/presets.d.ts +0 -64
  432. package/dist/node_modules/@allyhub-next/audio/dist/recording/room.d.ts +0 -78
  433. package/dist/node_modules/@allyhub-next/audio/dist/recording/setup.d.ts +0 -111
  434. package/dist/node_modules/@allyhub-next/audio/dist/recording/vec.d.ts +0 -3
  435. package/dist/node_modules/@allyhub-next/audio/dist/render.d.ts +0 -26
  436. package/dist/node_modules/@allyhub-next/audio/dist/sfx.d.ts +0 -10
  437. package/dist/node_modules/@allyhub-next/audio/dist/shape.d.ts +0 -118
  438. package/dist/node_modules/@allyhub-next/audio/dist/voice.d.ts +0 -45
  439. package/dist/node_modules/@allyhub-next/browser/dist/browser.d.ts +0 -24
  440. package/dist/node_modules/@allyhub-next/browser/dist/capture.d.ts +0 -61
  441. package/dist/node_modules/@allyhub-next/browser/dist/cdp.d.ts +0 -51
  442. package/dist/node_modules/@allyhub-next/browser/dist/flags.d.ts +0 -13
  443. package/dist/node_modules/@allyhub-next/browser/dist/frames.d.ts +0 -35
  444. package/dist/node_modules/@allyhub-next/browser/dist/html.d.ts +0 -19
  445. package/dist/node_modules/@allyhub-next/browser/dist/index.d.ts +0 -10
  446. package/dist/node_modules/@allyhub-next/browser/dist/launch.d.ts +0 -35
  447. package/dist/node_modules/@allyhub-next/browser/dist/page.d.ts +0 -67
  448. package/dist/node_modules/@allyhub-next/browser/dist/server.d.ts +0 -26
  449. package/dist/node_modules/@allyhub-next/check/dist/cache.d.ts +0 -46
  450. package/dist/node_modules/@allyhub-next/check/dist/check.d.ts +0 -142
  451. package/dist/node_modules/@allyhub-next/check/dist/generated.d.ts +0 -22
  452. package/dist/node_modules/@allyhub-next/check/dist/index.d.ts +0 -7
  453. package/dist/node_modules/@allyhub-next/check/dist/plans.d.ts +0 -111
  454. package/dist/node_modules/@allyhub-next/check/dist/result.d.ts +0 -12
  455. package/dist/node_modules/@allyhub-next/check/dist/scenery.d.ts +0 -23
  456. package/dist/node_modules/@allyhub-next/dev-server/dist/background.d.ts +0 -50
  457. package/dist/node_modules/@allyhub-next/dev-server/dist/card.d.ts +0 -17
  458. package/dist/node_modules/@allyhub-next/dev-server/dist/exports.d.ts +0 -18
  459. package/dist/node_modules/@allyhub-next/dev-server/dist/index.d.ts +0 -11
  460. package/dist/node_modules/@allyhub-next/dev-server/dist/live.d.ts +0 -77
  461. package/dist/node_modules/@allyhub-next/dev-server/dist/mime.d.ts +0 -2
  462. package/dist/node_modules/@allyhub-next/dev-server/dist/mime.js +0 -2
  463. package/dist/node_modules/@allyhub-next/dev-server/dist/paths.d.ts +0 -27
  464. package/dist/node_modules/@allyhub-next/dev-server/dist/project.d.ts +0 -153
  465. package/dist/node_modules/@allyhub-next/dev-server/dist/reveal.d.ts +0 -6
  466. package/dist/node_modules/@allyhub-next/dev-server/dist/server.d.ts +0 -47
  467. package/dist/node_modules/@allyhub-next/dev-server/dist/sound.d.ts +0 -21
  468. package/dist/node_modules/@allyhub-next/dev-server/dist/stage.d.ts +0 -82
  469. package/dist/node_modules/@allyhub-next/dev-server/dist/stage.js +0 -121
  470. package/dist/node_modules/@allyhub-next/dev-server/dist/tools.d.ts +0 -24
  471. package/dist/node_modules/@allyhub-next/dev-server/dist/validate.d.ts +0 -6
  472. package/dist/node_modules/@allyhub-next/dev-server/dist/watcher.d.ts +0 -47
  473. package/dist/node_modules/@allyhub-next/dev-server/dist/writer.d.ts +0 -51
  474. package/dist/node_modules/@allyhub-next/export/dist/batch.d.ts +0 -70
  475. package/dist/node_modules/@allyhub-next/export/dist/deck-fonts.d.ts +0 -24
  476. package/dist/node_modules/@allyhub-next/export/dist/deck-pptx.d.ts +0 -12
  477. package/dist/node_modules/@allyhub-next/export/dist/export.d.ts +0 -123
  478. package/dist/node_modules/@allyhub-next/export/dist/index.d.ts +0 -5
  479. package/dist/node_modules/@allyhub-next/export/dist/names.d.ts +0 -36
  480. package/dist/node_modules/@allyhub-next/measure/dist/compare.d.ts +0 -195
  481. package/dist/node_modules/@allyhub-next/measure/dist/contrast.d.ts +0 -14
  482. package/dist/node_modules/@allyhub-next/measure/dist/cut-sheet.d.ts +0 -90
  483. package/dist/node_modules/@allyhub-next/measure/dist/cuts.d.ts +0 -108
  484. package/dist/node_modules/@allyhub-next/measure/dist/facts.d.ts +0 -60
  485. package/dist/node_modules/@allyhub-next/measure/dist/fidelity.d.ts +0 -40
  486. package/dist/node_modules/@allyhub-next/measure/dist/flat.d.ts +0 -42
  487. package/dist/node_modules/@allyhub-next/measure/dist/index.d.ts +0 -24
  488. package/dist/node_modules/@allyhub-next/measure/dist/loop.d.ts +0 -22
  489. package/dist/node_modules/@allyhub-next/measure/dist/overlay.d.ts +0 -57
  490. package/dist/node_modules/@allyhub-next/measure/dist/recording-report.d.ts +0 -66
  491. package/dist/node_modules/@allyhub-next/measure/dist/reference/compare.d.ts +0 -118
  492. package/dist/node_modules/@allyhub-next/measure/dist/reference/folder.d.ts +0 -75
  493. package/dist/node_modules/@allyhub-next/measure/dist/reference/interpret.d.ts +0 -39
  494. package/dist/node_modules/@allyhub-next/measure/dist/reference/piece.d.ts +0 -53
  495. package/dist/node_modules/@allyhub-next/measure/dist/reference/sections.d.ts +0 -53
  496. package/dist/node_modules/@allyhub-next/measure/dist/reference/sets.d.ts +0 -84
  497. package/dist/node_modules/@allyhub-next/measure/dist/reference/text.d.ts +0 -27
  498. package/dist/node_modules/@allyhub-next/measure/dist/reference/video.d.ts +0 -55
  499. package/dist/node_modules/@allyhub-next/measure/dist/seams.d.ts +0 -46
  500. package/dist/node_modules/@allyhub-next/measure/dist/sound-measures.d.ts +0 -74
  501. package/dist/node_modules/@allyhub-next/measure/dist/sound-report.d.ts +0 -156
  502. package/dist/node_modules/@allyhub-next/measure/dist/still.d.ts +0 -58
  503. package/dist/node_modules/@allyhub-next/measure/dist/version-voice.d.ts +0 -12
  504. package/dist/node_modules/@allyhub-next/project/dist/console.d.ts +0 -34
  505. package/dist/node_modules/@allyhub-next/project/dist/digest.d.ts +0 -9
  506. package/dist/node_modules/@allyhub-next/project/dist/index.d.ts +0 -11
  507. package/dist/node_modules/@allyhub-next/project/dist/ledger.d.ts +0 -17
  508. package/dist/node_modules/@allyhub-next/project/dist/media-index.d.ts +0 -27
  509. package/dist/node_modules/@allyhub-next/project/dist/page.d.ts +0 -119
  510. package/dist/node_modules/@allyhub-next/project/dist/says.d.ts +0 -15
  511. package/dist/node_modules/@allyhub-next/project/dist/scenery.d.ts +0 -35
  512. package/dist/node_modules/@allyhub-next/project/dist/session.d.ts +0 -37
  513. package/dist/node_modules/@allyhub-next/project/dist/stretch.d.ts +0 -38
  514. package/dist/node_modules/@allyhub-next/project/dist/version.d.ts +0 -114
  515. package/dist/node_modules/@allyhub-next/render/dist/cap.d.ts +0 -41
  516. package/dist/node_modules/@allyhub-next/render/dist/capture.d.ts +0 -78
  517. package/dist/node_modules/@allyhub-next/render/dist/clip.d.ts +0 -27
  518. package/dist/node_modules/@allyhub-next/render/dist/composite.d.ts +0 -106
  519. package/dist/node_modules/@allyhub-next/render/dist/delivery.d.ts +0 -18
  520. package/dist/node_modules/@allyhub-next/render/dist/doc/fonts.d.ts +0 -3
  521. package/dist/node_modules/@allyhub-next/render/dist/doc/index.d.ts +0 -3
  522. package/dist/node_modules/@allyhub-next/render/dist/doc/print.d.ts +0 -51
  523. package/dist/node_modules/@allyhub-next/render/dist/encode.d.ts +0 -111
  524. package/dist/node_modules/@allyhub-next/render/dist/errors.d.ts +0 -15
  525. package/dist/node_modules/@allyhub-next/render/dist/exports.d.ts +0 -76
  526. package/dist/node_modules/@allyhub-next/render/dist/ffmpeg.d.ts +0 -75
  527. package/dist/node_modules/@allyhub-next/render/dist/footage.d.ts +0 -169
  528. package/dist/node_modules/@allyhub-next/render/dist/image.d.ts +0 -16
  529. package/dist/node_modules/@allyhub-next/render/dist/index.d.ts +0 -26
  530. package/dist/node_modules/@allyhub-next/render/dist/junction.d.ts +0 -70
  531. package/dist/node_modules/@allyhub-next/render/dist/look.d.ts +0 -21
  532. package/dist/node_modules/@allyhub-next/render/dist/page.d.ts +0 -186
  533. package/dist/node_modules/@allyhub-next/render/dist/parts.d.ts +0 -140
  534. package/dist/node_modules/@allyhub-next/render/dist/png.d.ts +0 -37
  535. package/dist/node_modules/@allyhub-next/render/dist/pool.d.ts +0 -54
  536. package/dist/node_modules/@allyhub-next/render/dist/post-probe.d.ts +0 -27
  537. package/dist/node_modules/@allyhub-next/render/dist/post.d.ts +0 -27
  538. package/dist/node_modules/@allyhub-next/render/dist/render.d.ts +0 -151
  539. package/dist/node_modules/@allyhub-next/render/dist/segments.d.ts +0 -40
  540. package/dist/node_modules/@allyhub-next/render/dist/sound.d.ts +0 -24
  541. package/dist/node_modules/@allyhub-next/render/dist/stills.d.ts +0 -41
  542. package/dist/node_modules/@allyhub-next/render/dist/tools.d.ts +0 -25
  543. package/dist/node_modules/@allyhub-next/render/dist/webp.d.ts +0 -17
  544. package/dist/node_modules/@allyhub-next/runtime/dist/bridge.d.ts +0 -211
  545. package/dist/node_modules/@allyhub-next/runtime/dist/captions.d.ts +0 -24
  546. package/dist/node_modules/@allyhub-next/runtime/dist/clock.d.ts +0 -32
  547. package/dist/node_modules/@allyhub-next/runtime/dist/compose.d.ts +0 -149
  548. package/dist/node_modules/@allyhub-next/runtime/dist/console.d.ts +0 -21
  549. package/dist/node_modules/@allyhub-next/runtime/dist/contrast.d.ts +0 -13
  550. package/dist/node_modules/@allyhub-next/runtime/dist/embed.d.ts +0 -50
  551. package/dist/node_modules/@allyhub-next/runtime/dist/env.d.ts +0 -101
  552. package/dist/node_modules/@allyhub-next/runtime/dist/errors.d.ts +0 -21
  553. package/dist/node_modules/@allyhub-next/runtime/dist/facade.d.ts +0 -42
  554. package/dist/node_modules/@allyhub-next/runtime/dist/fonts.d.ts +0 -110
  555. package/dist/node_modules/@allyhub-next/runtime/dist/footage.d.ts +0 -52
  556. package/dist/node_modules/@allyhub-next/runtime/dist/frame.d.ts +0 -61
  557. package/dist/node_modules/@allyhub-next/runtime/dist/guards.d.ts +0 -32
  558. package/dist/node_modules/@allyhub-next/runtime/dist/index.d.ts +0 -14
  559. package/dist/node_modules/@allyhub-next/runtime/dist/inspect.d.ts +0 -112
  560. package/dist/node_modules/@allyhub-next/runtime/dist/locate.d.ts +0 -11
  561. package/dist/node_modules/@allyhub-next/runtime/dist/measure.d.ts +0 -41
  562. package/dist/node_modules/@allyhub-next/runtime/dist/mix-plan.d.ts +0 -42
  563. package/dist/node_modules/@allyhub-next/runtime/dist/music.d.ts +0 -29
  564. package/dist/node_modules/@allyhub-next/runtime/dist/output.d.ts +0 -5
  565. package/dist/node_modules/@allyhub-next/runtime/dist/pictures.d.ts +0 -39
  566. package/dist/node_modules/@allyhub-next/runtime/dist/piece.d.ts +0 -34
  567. package/dist/node_modules/@allyhub-next/runtime/dist/player/clips.d.ts +0 -41
  568. package/dist/node_modules/@allyhub-next/runtime/dist/player/cutout.d.ts +0 -57
  569. package/dist/node_modules/@allyhub-next/runtime/dist/player/player.d.ts +0 -78
  570. package/dist/node_modules/@allyhub-next/runtime/dist/reads.d.ts +0 -132
  571. package/dist/node_modules/@allyhub-next/runtime/dist/sound.d.ts +0 -22
  572. package/dist/node_modules/@allyhub-next/runtime/dist/speech.d.ts +0 -107
  573. package/dist/node_modules/@allyhub-next/runtime/dist/stage-kit.d.ts +0 -12
  574. package/dist/node_modules/@allyhub-next/runtime/dist/stage.d.ts +0 -34
  575. package/dist/node_modules/@allyhub-next/runtime/dist/styles.d.ts +0 -35
  576. package/dist/node_modules/@allyhub-next/runtime/dist/takes.d.ts +0 -72
  577. package/dist/node_modules/@allyhub-next/runtime/dist/titles.d.ts +0 -10
  578. package/dist/node_modules/@allyhub-next/runtime/dist/transitions.d.ts +0 -26
  579. package/dist/node_modules/@allyhub-next/site/dist/assets.d.ts +0 -59
  580. package/dist/node_modules/@allyhub-next/site/dist/assets.js +0 -2
  581. package/dist/node_modules/@allyhub-next/site/dist/astro.d.ts +0 -22
  582. package/dist/node_modules/@allyhub-next/site/dist/astro.js +0 -3
  583. package/dist/node_modules/@allyhub-next/site/dist/lockfile.d.ts +0 -40
  584. package/dist/node_modules/@allyhub-next/site/dist/lockfile.js +0 -3
  585. package/dist/node_modules/@allyhub-next/site/dist/media.d.ts +0 -24
  586. package/dist/node_modules/@allyhub-next/site/dist/media.js +0 -4
  587. package/dist/node_modules/@allyhub-next/site/package.json +0 -25
  588. package/dist/node_modules/@allyhub-next/slides-pptx/dist/charts.d.ts +0 -6
  589. package/dist/node_modules/@allyhub-next/slides-pptx/dist/fonts.d.ts +0 -45
  590. package/dist/node_modules/@allyhub-next/slides-pptx/dist/import.d.ts +0 -18
  591. package/dist/node_modules/@allyhub-next/slides-pptx/dist/import.js +0 -3
  592. package/dist/node_modules/@allyhub-next/slides-pptx/dist/index.d.ts +0 -5
  593. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read.d.ts +0 -55
  594. package/dist/node_modules/@allyhub-next/slides-pptx/dist/read.js +0 -4
  595. package/dist/node_modules/@allyhub-next/slides-pptx/dist/shapes.d.ts +0 -67
  596. package/dist/node_modules/@allyhub-next/slides-pptx/dist/text.d.ts +0 -21
  597. package/dist/node_modules/@allyhub-next/slides-pptx/dist/theme.d.ts +0 -4
  598. package/dist/node_modules/@allyhub-next/slides-pptx/dist/timing.d.ts +0 -32
  599. package/dist/node_modules/@allyhub-next/slides-pptx/dist/write.d.ts +0 -32
  600. package/dist/node_modules/@allyhub-next/slides-pptx/dist/xml.d.ts +0 -26
  601. package/dist/node_modules/@allyhub-next/slides-runtime/dist/draw.d.ts +0 -40
  602. package/dist/node_modules/@allyhub-next/slides-runtime/dist/edit.d.ts +0 -4
  603. package/dist/node_modules/@allyhub-next/slides-runtime/dist/edit.js +0 -2
  604. package/dist/node_modules/@allyhub-next/slides-runtime/dist/index.d.ts +0 -4
  605. package/dist/node_modules/@allyhub-next/slides-runtime/dist/ink.d.ts +0 -10
  606. package/dist/node_modules/@allyhub-next/slides-runtime/dist/load.d.ts +0 -6
  607. package/dist/node_modules/@allyhub-next/stage/dist/bakes.d.ts +0 -42
  608. package/dist/node_modules/@allyhub-next/stage/dist/graphics.d.ts +0 -7
  609. package/dist/node_modules/@allyhub-next/stage/dist/identity.d.ts +0 -2
  610. package/dist/node_modules/@allyhub-next/stage/dist/index.d.ts +0 -9
  611. package/dist/node_modules/@allyhub-next/stage/dist/page.d.ts +0 -87
  612. package/dist/node_modules/@allyhub-next/stage/dist/scenery-page.d.ts +0 -69
  613. package/dist/node_modules/@allyhub-next/stage/dist/scenery-solve.d.ts +0 -49
  614. package/dist/node_modules/@allyhub-next/stage/dist/scenery.d.ts +0 -8
  615. package/dist/node_modules/@allyhub-next/stage/dist/server.d.ts +0 -21
  616. package/dist/node_modules/@allyhub-next/stage-page/dist/host.d.ts +0 -22
  617. package/dist/node_modules/@allyhub-next/stage-page/dist/page.js +0 -79
  618. package/dist/site.d.ts +0 -2
  619. package/editor-web/assets/dist-Cg2PdedY.js +0 -6
  620. package/editor-web/assets/dist-CuW84oPe.js +0 -233
  621. package/editor-web/assets/dist-CxAS_vp7.js +0 -2
  622. package/editor-web/assets/dist-DCVaj9i1.js +0 -4
  623. package/editor-web/assets/dist-DGVUuVPB.js +0 -33
  624. package/editor-web/assets/dist-Yi3sy7Ea.js +0 -1
  625. package/editor-web/assets/index-B7S9RZhL.css +0 -2
  626. package/editor-web/assets/index-pwRfZ2Jv.js +0 -69
  627. package/editor-web/assets/minus-BizJdinJ.js +0 -1
  628. package/editor-web/assets/react-D54s6gwK.js +0 -101
  629. package/editor-web/assets/textarea-CvxipnGW.js +0 -105
  630. package/editor-web/assets/trash-2-Bq1Dt8XG.js +0 -1
  631. package/editor-web/assets/undo-2-Djhvu4xt.js +0 -1
  632. /package/dist/node_modules/@allyhub-next/{site → ooxml}/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
2
  import{isAbsolute as U,relative as T}from"node:path";import{VOICE_FIT_DEFAULTS as E}from"@allyhub-next/audio";import{comboKey as S}from"@allyhub-next/video-core";const c=(e,t=1)=>e==null?"–":e.toFixed(t),p=(e,t=1)=>`${e>=0?"+":"−"}${Math.abs(e).toFixed(t)}`,b=(e,t)=>`${String(e)} ${t}${e===1?"":"s"}`;function x(e,t){const o=T(t,e);return o&&!o.startsWith("..")&&!U(o)?o:e}const P=e=>[...e].sort((t,o)=>o.strength-t.strength).slice(0,12).sort((t,o)=>t.t-o.t),g=e=>`${e.p10.toFixed(1)} / ${e.median.toFixed(1)} / ${e.p90.toFixed(1)}`,w=e=>e?`${e.bpm.toFixed(1)} BPM (confidence ${e.confidence.toFixed(2)})`:"no steady tempo";function v(e){const t=e.loudness,o=P(e.onsets);return[`Loudness ${c(t.integrated)} LUFS integrated · range ${c(t.range)} LU · true peak ${c(t.truePeak)} dBTP · sample peak ${c(t.samplePeak)} dBFS${e.clipped>0?` · ${b(e.clipped,"sample")} at full scale`:""}`,`Silence under ${String(e.options.silence.noise)} dBFS for ${String(e.options.silence.min)} s or longer: ${e.silences.length===0?"none":e.silences.map(i=>`${i.start.toFixed(2)}–${i.end.toFixed(2)} s (${i.duration.toFixed(2)} s${i.part?`, ${i.part}`:""})`).join(" · ")}`,`Onsets ${String(e.onsets.length)}${o.length>0?`; strongest at ${o.map(i=>i.t.toFixed(2)).join(" ")} s (all in --json)`:""}`]}export function fileAudioText(e,t){return[`${x(e.source.file,t)} · ${e.duration.toFixed(2)} s · measured alone, on its own clock`,...v(e),`Pace ${w(e.pace.tempo)} · ${e.pace.onsetsPerMinute.toFixed(1)} onsets a minute`,`Levels dBFS every 10 ms, 10th / median / 90th: whole ${g(e.sound.whole)} · floor ${e.sound.floor.toFixed(1)}`].join(`
3
- `)}function O(e){return e===null?"":"█".repeat(Math.round(Math.min(-6,Math.max(-36,e))+36))}const y=e=>e?[e.pitch===void 0?void 0:`${p(e.pitch)} st`,e.pace===void 0?void 0:`${p(e.pace*100,0)} %`,e.bright===void 0?void 0:`${p(e.bright)} dB`].filter(t=>t!==void 0).join(" "):"",k=e=>e.pitch?`${e.pitch.median.toFixed(0).padStart(4)} Hz (${e.pitch.low.toFixed(0)}–${e.pitch.high.toFixed(0)})`:" – Hz";export function versionAudioText(e,t,o){const i=t.master,s=[`${[e.piece,S(e.combo),e.format].join(" · ")} · ${t.duration.toFixed(2)} s · ${t.source.kind==="file"?`measured ${x(t.source.file,o)}`:"mixed now from its sources (no render)"}`,...v(t)];i&&s.splice(2,0,`Master ${i.target.lufs===!1?"the mix's own level":`${String(i.target.lufs)} LUFS`}, ceiling ${String(i.target.truePeak)} dBTP: ${i.gainDb===void 0?"silent":`gain ${p(i.gainDb,2)} dB`}${i.before?` on ${i.before.integrated.toFixed(1)} LUFS, range ${c(i.before.range)} LU, true peak ${c(i.before.truePeak)} dBTP`:""}${i.limited===void 0?"":` · the limiter took ${i.limited.toFixed(1)} dB off the loudest peak`}`);const a=t.pace;s.push(`Pace ${w(a.tempo)} · ${a.onsetsPerMinute.toFixed(1)} onsets a minute · ${a.wordsPerMinute.toFixed(1)} words a minute (${a.speakingRate.toFixed(1)} from the first word to the last) · speech ${(a.speechShare*100).toFixed(0)} % of the film${a.timeToFirstWord===null?"":` · first word at ${a.timeToFirstWord.toFixed(2)} s`}`);const r=t.sound;s.push(`Levels dBFS every 10 ms, 10th / median / 90th: whole ${g(r.whole)}${r.words?` · under words ${g(r.words)}`:""}${r.between?` · between them ${g(r.between)} (${r.between.seconds.toFixed(1)} s, ${(r.between.voicedShare*100).toFixed(0)} % voiced, ${r.between.onsetsPerMinute.toFixed(1)} onsets a minute)`:""} · floor ${r.floor.toFixed(1)}${t.bedUnderVoice===null?"":` · words over between ${t.bedUnderVoice.toFixed(1)} dB`}`),t.stems.length>0&&s.push(`Stems ${t.stems.map(n=>`${n.as} ${n.file} ${c(n.lufs)} LUFS${n.by==="level"?" (level over its length)":""}`).join(" · ")}`);const $=t.summary,f=n=>n.onset===void 0||n.offsetMs===void 0?"no onset":`onset ${n.onset.toFixed(2)} (${n.offsetMs>=0?"+":""}${String(n.offsetMs)} ms)${n.near?" ✓":""}`,l=Math.max(4,...t.cuts.map(n=>n.part.length),...t.cues.map(n=>n.sound.length));s.push(`Cuts ${String($.cutsOnOnset)} of ${String($.cuts)} within ±${String($.toleranceMs)} ms of an onset`);for(const n of t.cuts)s.push(` ${n.t.toFixed(2).padStart(6)} ${n.part.padEnd(l)} ${f(n)}`);if($.cues>0){s.push(`Cues ${String($.cuesOnOnset)} of ${String($.cues)} within ±${String($.toleranceMs)} ms of an onset`);for(const n of t.cues)s.push(` ${n.t.toFixed(2).padStart(6)} ${n.sound.padEnd(l)} ${f(n)} (${n.part})`)}const m=Math.max(4,...t.parts.map(n=>n.key.length));s.push("Parts momentary loudness, mean / max LUFS");for(const n of t.parts)s.push(` ${n.key.padEnd(m)} ${n.start.toFixed(2).padStart(6)}–${n.end.toFixed(2).padEnd(6)} ${c(n.loudness).padStart(5)} / ${c(n.peak).padStart(5)} ${O(n.loudness)}`);if(t.speech.length>0){const n=Math.max(4,...t.speech.map(d=>d.part.length));s.push(`Speech where each part speaks, mean LUFS; integrated LUFS before the recording and ${t.source.kind==="file"?"in the file":"in the mix"}; silences inside`);for(const d of t.speech){const u=d.levels.gainDb===void 0?"":` (speechGainDb ${p(d.levels.gainDb)})`;s.push(` ${d.part.padEnd(n)} ${d.start.toFixed(2).padStart(6)}–${d.end.toFixed(2).padEnd(6)} ${c(d.loudness).padStart(5)} ${c(d.levels.before).padStart(5)} → ${c(d.levels.after).padStart(5)}${u} ${d.gaps.length===0?"continuous":b(d.gaps.length,"gap")} ${d.file} @ ${d.from.toFixed(2)} s`)}t.speechSpread.before!==null&&t.speechSpread.after!==null&&s.push(` the parts' spread: ${t.speechSpread.before.toFixed(1)} LU before the recording, ${t.speechSpread.after.toFixed(1)} LU ${t.source.kind==="file"?"in the file":"in the mix"}`),s.push(`Voice each part's from its own file: median pitch (10–90 %), words a second, energy above ${String(t.options.voice.bright)} Hz; the step from the part before`);for(const d of t.speech){const u=d.voice;if(!u){s.push(` ${d.part.padEnd(n)} – (its file could not be read)`);continue}const h=y(d.step);s.push(` ${d.part.padEnd(n)} ${k(u).padEnd(22)} ${c(u.pace,2).padStart(5)} /s ${c(u.bright).padStart(6)} dB${h?` ${h}`:""}`)}if(t.speech.some(d=>d.fileVoice!==void 0)){s.push(`File the file's sound where each part speaks (what is under the voice counts too): median pitch (10–90 %), energy above ${String(t.options.voice.bright)} Hz; the file's less the video's`);for(const d of t.speech){const u=d.fileVoice;if(!u){s.push(` ${d.part.padEnd(n)} –`);continue}const h=y(d.fileStep);s.push(` ${d.part.padEnd(n)} ${k(u).padEnd(22)} ${c(u.bright).padStart(6)} dB${h?` ${h}`:""}`)}}}for(const n of t.notes)s.push(`! ${n}`);return s.join(`
3
+ `)}function O(e){return e===null?"":"█".repeat(Math.round(Math.min(-6,Math.max(-36,e))+36))}const y=e=>e?[e.pitch===void 0?void 0:`${p(e.pitch)} st`,e.pace===void 0?void 0:`${p(e.pace*100,0)} %`,e.bright===void 0?void 0:`${p(e.bright)} dB`].filter(t=>t!==void 0).join(" "):"",k=e=>e.pitch?`${e.pitch.median.toFixed(0).padStart(4)} Hz (${e.pitch.low.toFixed(0)}–${e.pitch.high.toFixed(0)})`:" – Hz";export function versionAudioText(e,t,o){const i=t.master,s=[`${[e.piece,S(e.combo),e.format].join(" · ")} · ${t.duration.toFixed(2)} s · ${t.source.kind==="file"?`measured ${x(t.source.file,o)}`:"mixed now from its sources (no render)"}`,...v(t)];i&&s.splice(2,0,`Master ${i.target.lufs===!1?"the mix's own level":`${String(i.target.lufs)} LUFS`}, ceiling ${String(i.target.truePeak)} dBTP: ${i.gainDb===void 0?"silent":`gain ${p(i.gainDb,2)} dB`}${i.before?` on ${i.before.integrated.toFixed(1)} LUFS, range ${c(i.before.range)} LU, true peak ${c(i.before.truePeak)} dBTP`:""}${i.limited===void 0?"":` · the limiter took ${i.limited.toFixed(1)} dB off the loudest peak${i.limitedAt===void 0?"":`, at ${i.limitedAt.toFixed(2)} s`}`}`);const a=t.pace;s.push(`Pace ${w(a.tempo)} · ${a.onsetsPerMinute.toFixed(1)} onsets a minute · ${a.wordsPerMinute.toFixed(1)} words a minute (${a.speakingRate.toFixed(1)} from the first word to the last) · speech ${(a.speechShare*100).toFixed(0)} % of the film${a.timeToFirstWord===null?"":` · first word at ${a.timeToFirstWord.toFixed(2)} s`}`);const r=t.sound;s.push(`Levels dBFS every 10 ms, 10th / median / 90th: whole ${g(r.whole)}${r.words?` · under words ${g(r.words)}`:""}${r.between?` · between them ${g(r.between)} (${r.between.seconds.toFixed(1)} s, ${(r.between.voicedShare*100).toFixed(0)} % voiced, ${r.between.onsetsPerMinute.toFixed(1)} onsets a minute)`:""} · floor ${r.floor.toFixed(1)}${t.bedUnderVoice===null?"":` · words over between ${t.bedUnderVoice.toFixed(1)} dB`}`),t.stems.length>0&&s.push(`Stems ${t.stems.map(n=>`${n.as} ${n.file} ${c(n.lufs)} LUFS${n.by==="level"?" (level over its length)":""}`).join(" · ")}`);const $=t.summary,f=n=>n.onset===void 0||n.offsetMs===void 0?"no onset":`onset ${n.onset.toFixed(2)} (${n.offsetMs>=0?"+":""}${String(n.offsetMs)} ms)${n.near?" ✓":""}`,l=Math.max(4,...t.cuts.map(n=>n.part.length),...t.cues.map(n=>n.sound.length));s.push(`Cuts ${String($.cutsOnOnset)} of ${String($.cuts)} within ±${String($.toleranceMs)} ms of an onset`);for(const n of t.cuts)s.push(` ${n.t.toFixed(2).padStart(6)} ${n.part.padEnd(l)} ${f(n)}`);if($.cues>0){s.push(`Cues ${String($.cuesOnOnset)} of ${String($.cues)} within ±${String($.toleranceMs)} ms of an onset`);for(const n of t.cues)s.push(` ${n.t.toFixed(2).padStart(6)} ${n.sound.padEnd(l)} ${f(n)} (${n.part})`)}const m=Math.max(4,...t.parts.map(n=>n.key.length));s.push("Parts momentary loudness, mean / max LUFS");for(const n of t.parts)s.push(` ${n.key.padEnd(m)} ${n.start.toFixed(2).padStart(6)}–${n.end.toFixed(2).padEnd(6)} ${c(n.loudness).padStart(5)} / ${c(n.peak).padStart(5)} ${O(n.loudness)}`);if(t.speech.length>0){const n=Math.max(4,...t.speech.map(d=>d.part.length));s.push(`Speech where each part speaks, mean LUFS; integrated LUFS before the recording and ${t.source.kind==="file"?"in the file":"in the mix"}; silences inside`);for(const d of t.speech){const u=d.levels.gainDb===void 0?"":` (speechGainDb ${p(d.levels.gainDb)})`;s.push(` ${d.part.padEnd(n)} ${d.start.toFixed(2).padStart(6)}–${d.end.toFixed(2).padEnd(6)} ${c(d.loudness).padStart(5)} ${c(d.levels.before).padStart(5)} → ${c(d.levels.after).padStart(5)}${u} ${d.gaps.length===0?"continuous":b(d.gaps.length,"gap")} ${d.file} @ ${d.from.toFixed(2)} s`)}t.speechSpread.before!==null&&t.speechSpread.after!==null&&s.push(` the parts' spread: ${t.speechSpread.before.toFixed(1)} LU before the recording, ${t.speechSpread.after.toFixed(1)} LU ${t.source.kind==="file"?"in the file":"in the mix"}`),s.push(`Voice each part's from its own file: median pitch (10–90 %), words a second, energy above ${String(t.options.voice.bright)} Hz; the step from the part before`);for(const d of t.speech){const u=d.voice;if(!u){s.push(` ${d.part.padEnd(n)} – (its file could not be read)`);continue}const h=y(d.step);s.push(` ${d.part.padEnd(n)} ${k(u).padEnd(22)} ${c(u.pace,2).padStart(5)} /s ${c(u.bright).padStart(6)} dB${h?` ${h}`:""}`)}if(t.speech.some(d=>d.fileVoice!==void 0)){s.push(`File the file's sound where each part speaks (what is under the voice counts too): median pitch (10–90 %), energy above ${String(t.options.voice.bright)} Hz; the file's less the video's`);for(const d of t.speech){const u=d.fileVoice;if(!u){s.push(` ${d.part.padEnd(n)} –`);continue}const h=y(d.fileStep);s.push(` ${d.part.padEnd(n)} ${k(u).padEnd(22)} ${c(u.bright).padStart(6)} dB${h?` ${h}`:""}`)}}}for(const n of t.notes)s.push(`! ${n}`);return s.join(`
4
4
  `)}const L=[63,125,250,500,1e3,2e3,4e3,8e3,16e3],j=e=>e>=1e3?`${String(e/1e3)}k`:String(e);function B(e){const t=e.decay,o=e.tone;return[`speech ${e.speech.toFixed(1)} s, pauses ${e.pauses.toFixed(1)} s`,"t60"in t?`decay ${t.t60.toFixed(2)} s (${t.low.toFixed(2)}–${t.high.toFixed(2)}, ${String(t.ends)} ends)`:`decay – (${t.missing})`,"below"in o?`room tone ${o.below.toFixed(1)} LU under, tilt ${p(o.tilt)} dB/oct`:`room tone – (${o.missing})`,`spread ${e.dynamics.spread.toFixed(1)} LU, crest ${e.dynamics.crest.toFixed(1)} dB`].join(" · ")}const F=e=>L.map(t=>{const o=e.find(i=>i.hz===t);return(o?p(o.db):"–").padStart(6)}).join("");export function versionRecordingText(e,t){return[[e.piece,S(e.combo),e.format].join(" · "),...M(t)].join(`
5
5
  `)}export function fileRecordingText(e,t,o){return[`${x(e,o)} · measured alone, whole`,...M({file:t})].join(`
6
6
  `)}function M(e){const t=[],o="piece"in e?e:void 0;if(o){const a=o.groups.map(r=>`${r.setup} (${r.parts.join(", ")})`).join(" · ");t.push(o.measured==="mix"?`Recording the video's whole mix, as mastered; video({ mic }): ${JSON.stringify(o.setting)}`:`Recording the voice as recorded: ${a||"played as it is"}; video({ mic }): ${JSON.stringify(o.setting)}`,` video ${B(o.piece)}`)}else t.push("Recording");e.file&&t.push(` file ${B(e.file)}`),t.push(` spectrum, dB against 1 kHz ${L.map(a=>j(a).padStart(6)).join("")} (third octaves in --json)`),o&&t.push(` video ${F(o.piece.spectrum)}`),e.file&&t.push(` file ${F(e.file.spectrum)}`);const i=o?.difference;i&&t.push(` file − video ${F(i.spectrum)}`,` file − video: ${[i.decay===void 0?"decay –":`decay ${p(i.decay,2)} s`,i.tone===void 0?"room tone –":`room tone ${p(i.tone)} LU under, tilt ${p(i.tilt??0)}`,`spread ${p(i.spread)} LU`,`crest ${p(i.crest)} dB`].join(" · ")}`);const s=o?.fit;if(s){const a=s.distance.before,r=s.distance.after,$=(f,l,m,n="")=>l===void 0||m===void 0?void 0:`${f} ${p(l)} → ${p(m)}${n}`;t.push(`Fit the video's voice moved (${s.moved.join(", ")||"nothing"}) until it measures as the file's; video − file: ${[`spectrum ${a.spectrum.toFixed(1)} → ${r.spectrum.toFixed(1)} dB RMS`,$("decay",a.decay,r.decay," s"),$("room tone",a.tone,r.tone," LU"),$("tilt",a.tilt,r.tilt)].filter(f=>f!==void 0).join(" · ")}`,` mic: ${JSON.stringify(s.setting)}`),s.limited.length>0&&t.push(` The response reached its limit at ${s.limited.map(j).join(", ")} Hz (it moves at most ${String(E.most)} dB at a band).`);for(const f of s.notes)t.push(`! ${f}`)}if(o)for(const a of o.notes)t.push(`! ${a}`);return t}
@@ -1,6 +1,6 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{readFile as Y}from"node:fs/promises";import{join as A,posix as B,relative as V}from"node:path";import{fileURLToPath as W}from"node:url";import{z as p}from"zod";import{modelInfo as q}from"@allyhub-next/build";import{COMPONENTS_DIR as I}from"@allyhub-next/formats";import{EXIT as f}from"@allyhub-next/protocol";import{ASSET_DEFAULTS as G,ASSET_TYPES as K,PolyHaven as X,PolyHavenError as Z,RegistryError as J,applyAdd as T,fetchBakes as Q,folderRegistry as D,planAdd as L,searchIndex as O}from"@allyhub-next/registry";import{cacheHome as ee}from"@allyhub-next/runtimes";import{CLI_VERSION as te}from"../cli-version.js";import{CommandError as S,defineCommand as C}from"../command.js";import{projectRoot as ne}from"../project.js";import{dir as oe}from"../fields.js";import{resourcesIndex as R}from"../resources.js";const _=W(new URL(".",import.meta.resolve("@allyhub-next/components/registry.json"))),se=Object.keys(K),x=["component","3d-model","scenery","skill","template","lib","@polyhaven"],ae={"allyhub:component":"component","allyhub:model":"3d-model","allyhub:scenery":"scenery","allyhub:skill":"skill","allyhub:template":"template","allyhub:lib":"lib"},H=e=>ae[e]??e.replace(/^allyhub:/u,""),E=e=>`${H(e.type)}/${e.name}`;function ie(e){const n=/^(@?[a-z0-9-]+)\/(.+)$/u.exec(e),i=x.find(d=>d===n?.[1]);if(i===void 0||n?.[2]===void 0)throw new S("usage",n===null?`Name what to add as <type>/<name>: ${e} has no type.`:`${n[1]??""} is not a type: name what to add as <type>/<name>.`,{exit:f.usage,hint:`Types: ${x.join(", ")} (3d-model/monitor, scenery/home-desk-demo-day, skill/product-demos, component/caption-line, @polyhaven/<id>). allyhub add lists every one.`});return{type:i,name:n[2]}}const le={"allyhub:model":"3D models","allyhub:scenery":"3D sceneries","allyhub:skill":"Skills","allyhub:template":"Templates","allyhub:component":"Components","allyhub:lib":"Libs (added with what uses them)"};function F(e,n){if(e.from==="none")return["AllyHub's resources (models, sceneries) could not be read: check the connection."];const i=n??e.index?.items??[],d=Math.max(0,...i.map(s=>E(s).length)),r=[`AllyHub's resources (allyhub add <type>/<name> copies one with what it needs, its Poly Haven assets and its baked light)${e.from==="stale"?", as last read (the registry cannot be read now)":""}:`];for(const[s,h]of Object.entries(le)){const c=i.filter(u=>u.type===s);c.length!==0&&r.push(` ${h}:`,...c.map(u=>` ${E(u).padEnd(d)} ${u.description}`))}return r}const N=20,z=e=>e.replace(/\.(?:ts|js)$/u,"").replaceAll(/[A-Z]/gu,n=>`-${n.toLowerCase()}`).replace(/^-/u,"");function M(e){return e instanceof J?new S(e.code,e.message,{exit:e.code==="conflict"?f.conflict:e.code==="no-item"?f.notFound:f.failed,...e.hint===void 0?{}:{hint:e.hint}}):e instanceof Z?new S(e.code,e.message,{exit:e.code==="network"?f.platform:e.code==="not-found"?f.notFound:e.code==="bad-choice"?f.usage:f.failed,...e.hint===void 0?{}:{hint:e.hint}}):e}const P=e=>new X({userAgent:`AllyHub/${te} (+https://allyhub.com)`,cacheDir:A(ee(e.env),"polyhaven"),...e.env.ALLYHUB_POLYHAVEN_API?{api:e.env.ALLYHUB_POLYHAVEN_API}:{}}),k=e=>`${e.toFixed(3)} m`;function de(e){const n=[e.type,e.category,e.size?`${k(e.size.width)} wide, ${k(e.size.depth)} deep, ${k(e.size.height)} tall`:void 0,e.covers?`one tile covers ${e.covers.map(k).join(" × ")}`:void 0,e.polycount!==void 0?`${e.polycount.toLocaleString("en")} polygons`:void 0,e.maxResolution?`up to ${String(e.maxResolution[0])} px`:void 0,e.authors.length>0?`by ${e.authors.join(", ")}`:void 0].filter(i=>i!==void 0);return` @polyhaven/${e.id}: ${e.name} (${n.join("; ")})
3
- found in ${e.matchedIn.join(", ")||"everything"}; tags ${e.tags.join(", ")}`}async function U(e,n){const i=[`${n.name} from Poly Haven (CC0, by ${n.source.authors.join(", ")||"its authors"}): ${String(n.files.length)} files in ${n.dir}/, ${n.fetched>0?`${String(n.fetched)} fetched`:"all already there"}. Records: ${n.records.join(", ")}.`];if(n.type==="model"){const r=n.main[0]??"",s=await q(e,r,await Y(A(e,r))),h=s.bounds;return i.push(h?`Measured: ${h.size.map(c=>c.toFixed(3)).join(" × ")} m along x, y (up), z; from ${h.min.map(c=>c.toFixed(3)).join(", ")} to ${h.max.map(c=>c.toFixed(3)).join(", ")}.`:`Not measured: ${s.contentsMissing??"no contents"}.`,...s.missing.length>0?[`Missing: ${s.missing.join(", ")}.`]:[],`In a scenery: const m = await w.load("${r}");`),{lines:i,model:s}}if(n.type==="hdri")return i.push(`In a scenery: await w.environment("${n.main[0]??""}", { background: true });`),{lines:i};const d=n.covers;return i.push(d&&d.length>=2?`One tile covers ${k(d[0]??0)} × ${k(d[1]??0)} (Poly Haven's dimensions): a surface's repeat is its size over that.`:"Poly Haven gives no size for one tile.",...n.main.map((r,s)=>{const h=n.maps?.[s]??"";return` ${h}: await w.texture("${r}"${h==="diffuse"?"":', { colorSpace: "linear" }'})`})),{lines:i}}export const add=C({name:"add",summary:"Adds to the project what AllyHub and Poly Haven have, each named <type>/<name>: a starter component, a 3D model, a 3D scenery, a skill or a template from AllyHub's registry, or a CC0 model, HDRI or texture from Poly Haven; alone it lists everything AllyHub has, by type",input:p.strictObject({name:p.array(p.string()).optional().describe("What to add, each <type>/<name>: component/caption-line, 3d-model/monitor, scenery/home-desk-demo-day, skill/product-demos (a skill goes in .agents/skills, linked from .claude/skills), template/<name>, lib/<name>, or @polyhaven/<id> (as allyhub add search prints it)"),to:p.string().optional().describe(`The folder the files go in, from the project (default ${I} for a component; for an asset, its kind's folder under assets/media/ and its id)`),force:p.boolean().default(!1).describe("Replace a component's copy the project changed (its changes are lost)"),res:p.string().optional().describe(`An asset's resolution, of its textures or of the HDRI (default ${G.resolution})`),dir:oe}),positional:["name"],output:p.looseObject({}),examples:["allyhub add","allyhub add component/caption-line","allyhub add 3d-model/monitor scenery/home-desk-demo-day","allyhub add @polyhaven/metal_office_desk --res 2k"]},async(e,n)=>{const i=D(_);try{const d=await i.index();if(!e.name||e.name.length===0){const t=Math.max(...d.items.map(y=>`component/${y.name}`.length)),l=await R(n);return{value:{components:d.items,resources:l.index?.items??[]},text:["Starter components (allyhub add component/<name> copies one into components/; allyhub add search <words> finds among everything, Poly Haven's models, HDRIs and textures too):",...d.items.map(y=>` ${`component/${y.name}`.padEnd(t)} ${y.description}`),"",...F(l,void 0)].join(`
2
+ import{readFile as Y}from"node:fs/promises";import{join as A,posix as B,relative as V}from"node:path";import{fileURLToPath as W}from"node:url";import{z as p}from"zod";import{modelInfo as q}from"@allyhub-next/build";import{COMPONENTS_DIR as I}from"@allyhub-next/formats";import{EXIT as f}from"@allyhub-next/protocol";import{ASSET_DEFAULTS as G,ASSET_TYPES as K,PolyHaven as X,PolyHavenError as Z,RegistryError as J,applyAdd as T,fetchBakes as Q,folderRegistry as D,planAdd as L,searchIndex as O}from"@allyhub-next/registry";import{cacheHome as ee}from"@allyhub-next/runtimes";import{CLI_VERSION as te}from"../cli-version.js";import{CommandError as S,defineCommand as C}from"../command.js";import{projectRoot as ne}from"../project.js";import{dir as oe}from"../fields.js";import{resourcesIndex as R}from"../resources.js";const _=W(new URL(".",import.meta.resolve("@allyhub-next/components/registry.json"))),se=Object.keys(K),x=["component","3d-model","scenery","skill","template","lib","@polyhaven"],ae={"allyhub:component":"component","allyhub:model":"3d-model","allyhub:scenery":"scenery","allyhub:skill":"skill","allyhub:template":"template","allyhub:lib":"lib"},H=e=>ae[e]??e.replace(/^allyhub:/u,""),E=e=>`${H(e.type)}/${e.name}`;function ie(e){const n=/^(@?[a-z0-9-]+)\/(.+)$/u.exec(e),i=x.find(d=>d===n?.[1]);if(i===void 0||n?.[2]===void 0)throw new S("usage",n===null?`Name what to add as <type>/<name>: ${e} has no type.`:`${n[1]??""} is not a type: name what to add as <type>/<name>.`,{exit:f.usage,hint:`Types: ${x.join(", ")} (3d-model/monitor, scenery/home-desk-demo-day, skill/web-product-demos, component/caption-line, @polyhaven/<id>). allyhub add lists every one.`});return{type:i,name:n[2]}}const le={"allyhub:model":"3D models","allyhub:scenery":"3D sceneries","allyhub:skill":"Skills","allyhub:template":"Templates","allyhub:component":"Components","allyhub:lib":"Libs (added with what uses them)"};function F(e,n){if(e.from==="none")return["AllyHub's resources (models, sceneries) could not be read: check the connection."];const i=n??e.index?.items??[],d=Math.max(0,...i.map(s=>E(s).length)),r=[`AllyHub's resources (allyhub add <type>/<name> copies one with what it needs, its Poly Haven assets and its baked light)${e.from==="stale"?", as last read (the registry cannot be read now)":""}:`];for(const[s,h]of Object.entries(le)){const c=i.filter(u=>u.type===s);c.length!==0&&r.push(` ${h}:`,...c.map(u=>` ${E(u).padEnd(d)} ${u.description}`))}return r}const N=20,z=e=>e.replace(/\.(?:ts|js)$/u,"").replaceAll(/[A-Z]/gu,n=>`-${n.toLowerCase()}`).replace(/^-/u,"");function M(e){return e instanceof J?new S(e.code,e.message,{exit:e.code==="conflict"?f.conflict:e.code==="no-item"?f.notFound:f.failed,...e.hint===void 0?{}:{hint:e.hint}}):e instanceof Z?new S(e.code,e.message,{exit:e.code==="network"?f.platform:e.code==="not-found"?f.notFound:e.code==="bad-choice"?f.usage:f.failed,...e.hint===void 0?{}:{hint:e.hint}}):e}const P=e=>new X({userAgent:`AllyHub/${te} (+https://allyhub.com)`,cacheDir:A(ee(e.env),"polyhaven"),...e.env.ALLYHUB_POLYHAVEN_API?{api:e.env.ALLYHUB_POLYHAVEN_API}:{}}),k=e=>`${e.toFixed(3)} m`;function de(e){const n=[e.type,e.category,e.size?`${k(e.size.width)} wide, ${k(e.size.depth)} deep, ${k(e.size.height)} tall`:void 0,e.covers?`one tile covers ${e.covers.map(k).join(" × ")}`:void 0,e.polycount!==void 0?`${e.polycount.toLocaleString("en")} polygons`:void 0,e.maxResolution?`up to ${String(e.maxResolution[0])} px`:void 0,e.authors.length>0?`by ${e.authors.join(", ")}`:void 0].filter(i=>i!==void 0);return` @polyhaven/${e.id}: ${e.name} (${n.join("; ")})
3
+ found in ${e.matchedIn.join(", ")||"everything"}; tags ${e.tags.join(", ")}`}async function U(e,n){const i=[`${n.name} from Poly Haven (CC0, by ${n.source.authors.join(", ")||"its authors"}): ${String(n.files.length)} files in ${n.dir}/, ${n.fetched>0?`${String(n.fetched)} fetched`:"all already there"}. Records: ${n.records.join(", ")}.`];if(n.type==="model"){const r=n.main[0]??"",s=await q(e,r,await Y(A(e,r))),h=s.bounds;return i.push(h?`Measured: ${h.size.map(c=>c.toFixed(3)).join(" × ")} m along x, y (up), z; from ${h.min.map(c=>c.toFixed(3)).join(", ")} to ${h.max.map(c=>c.toFixed(3)).join(", ")}.`:`Not measured: ${s.contentsMissing??"no contents"}.`,...s.missing.length>0?[`Missing: ${s.missing.join(", ")}.`]:[],`In a scenery: const m = await w.load("${r}");`),{lines:i,model:s}}if(n.type==="hdri")return i.push(`In a scenery: await w.environment("${n.main[0]??""}", { background: true });`),{lines:i};const d=n.covers;return i.push(d&&d.length>=2?`One tile covers ${k(d[0]??0)} × ${k(d[1]??0)} (Poly Haven's dimensions): a surface's repeat is its size over that.`:"Poly Haven gives no size for one tile.",...n.main.map((r,s)=>{const h=n.maps?.[s]??"";return` ${h}: await w.texture("${r}"${h==="diffuse"?"":', { colorSpace: "linear" }'})`})),{lines:i}}export const add=C({name:"add",summary:"Adds to the project what AllyHub and Poly Haven have, each named <type>/<name>: a starter component, a 3D model, a 3D scenery, a skill or a template from AllyHub's registry, or a CC0 model, HDRI or texture from Poly Haven; alone it lists everything AllyHub has, by type",input:p.strictObject({name:p.array(p.string()).optional().describe("What to add, each <type>/<name>: component/caption-line, 3d-model/monitor, scenery/home-desk-demo-day, skill/web-product-demos (a skill goes in .agents/skills, linked from .claude/skills), template/<name>, lib/<name>, or @polyhaven/<id> (as allyhub add search prints it)"),to:p.string().optional().describe(`The folder the files go in, from the project (default ${I} for a component; for an asset, its kind's folder under assets/media/ and its id)`),force:p.boolean().default(!1).describe("Replace a component's copy the project changed (its changes are lost)"),res:p.string().optional().describe(`An asset's resolution, of its textures or of the HDRI (default ${G.resolution})`),dir:oe}),positional:["name"],output:p.looseObject({}),examples:["allyhub add","allyhub add component/caption-line","allyhub add 3d-model/monitor scenery/home-desk-demo-day","allyhub add @polyhaven/metal_office_desk --res 2k"]},async(e,n)=>{const i=D(_);try{const d=await i.index();if(!e.name||e.name.length===0){const t=Math.max(...d.items.map(y=>`component/${y.name}`.length)),l=await R(n);return{value:{components:d.items,resources:l.index?.items??[]},text:["Starter components (allyhub add component/<name> copies one into components/; allyhub add search <words> finds among everything, Poly Haven's models, HDRIs and textures too):",...d.items.map(y=>` ${`component/${y.name}`.padEnd(t)} ${y.description}`),"",...F(l,void 0)].join(`
4
4
  `)}}const r=e.name.map(ie),s=await ne(n.cwd,e.dir),h=new Set(d.items.map(t=>t.name)),c=t=>t.type==="component"&&h.has(z(t.name)),u=r.filter(c).map(t=>z(t.name)),v=r.filter(t=>t.type==="@polyhaven").map(t=>t.name),g=r.filter(t=>t.type!=="@polyhaven"&&!c(t)),b=g.length>0?await R(n):void 0;for(const t of g){const l=b?.index?.items.find(y=>y.name===t.name);if(!l)throw new S("no-item",`There is no ${t.type}/${t.name}.`,{exit:f.notFound,hint:b?.from==="none"?"AllyHub's registry could not be read: check the connection.":`allyhub add search --type ${t.type} lists them.`});if(H(l.type)!==t.type)throw new S("usage",`${t.name} is a ${H(l.type)}, not a ${t.type}.`,{exit:f.usage,hint:`allyhub add ${E(l)}`})}const w=g.map(t=>t.name),a=[],j={};if(u.length>0){const t=e.to??I,l=await L(i,u,{root:s,dir:t,force:e.force});await T(s,l);const y=m=>m==="up to date"?"Up to date":m==="added"?"Added":"Replaced";a.push(...l.files.map(m=>`${y(m.status)} ${m.path}`));const $=l.items.find(m=>m.name===u[0]),o=$?.files[0]?.target.replaceAll("{dir}",t);if($&&o){const m=V(A(s,"name"),A(s,o)).split("\\").join("/").replace(/\.ts$/u,".js");a.push(`Import it from an item's entry file (<name>/video.ts): import { ${$.title} } from "${m.startsWith(".")?m:`./${m}`}"; one "../" more for each folder the item is deeper.`,"The file is the project's: change it as you like. allyhub add component/<name> --force puts the registry's back.")}l.missing.length>0&&a.push(`It needs packages the project does not declare: ${l.missing.join(", ")}.`),j.components=l.files.map(m=>({item:m.item,path:m.path,status:m.status})),j.missing=l.missing}if(b&&w.length>0){const t=await L(b.source,w,{root:s,dir:".",force:e.force});await T(s,t),a.length>0&&a.push(""),a.push(...t.files.map(o=>`${o.status==="up to date"?"Up to date":o.status==="added"?"Added":"Replaced"} ${o.path}`));const l=P(n);for(const o of t.assets){const m=await l.add(o.id,{root:s,...o.resolution===void 0?{}:{resolution:o.resolution},...o.maps===void 0?{}:{maps:o.maps}});a.push(...(await U(s,m)).lines)}const y=await Q(s,t.bakes);a.push(...y.map(o=>`${o.status==="added"?"Downloaded":"Up to date"} the baked light for ${o.bake.scenery}: ${o.path}`),"The files are the project's: change them as you like (a changed scenery is drawn unbaked until allyhub scenery bake bakes it again). allyhub add <type>/<name> --force puts the registry's back.");const $=t.files.filter(o=>o.path.endsWith("/README.md"));$.length>0&&a.push(`Read first, for its screens and cameras: ${$.map(o=>o.path).join(", ")}`),j.resources={files:t.files.map(o=>({item:o.item,path:o.path,status:o.status})),assets:t.assets,bakes:y.map(o=>({path:o.path,status:o.status}))}}if(v.length>0){const t=P(n),l=[];for(const y of v){const $=await t.add(y,{root:s,...e.to===void 0||u.length>0?{}:{to:B.normalize(e.to)},...e.res===void 0?{}:{resolution:e.res}}),o=await U(s,$);a.length>0&&a.push(""),a.push(...o.lines),l.push({...$,...o.model===void 0?{}:{model:o.model}})}j.assets=l}return{value:j,text:a.join(`
5
5
  `)}}catch(d){throw M(d)}}),addSearch=C({name:"add search",summary:"Finds the starter components, AllyHub's resources (models, sceneries) and Poly Haven's CC0 models, HDRIs and textures whose names, tags, categories or descriptions hold every word, each with where its words were found; with no words, lists every one",input:p.strictObject({words:p.array(p.string()).default([]).describe("The words to find (a word may start one of theirs); none lists every one"),type:p.array(p.enum(x)).optional().describe(`Only these types (default all): ${x.join(", ")} (@polyhaven: Poly Haven's models, HDRIs and textures)`),all:p.boolean().default(!1).describe(`Every match, not only the first ${String(N)} Poly Haven assets`)}),positional:["words"],output:p.looseObject({}),examples:["allyhub add search --type 3d-model",'allyhub add search "office desk" --type @polyhaven',"allyhub add search caption --type component"]},async(e,n)=>{const i=e.words.join(" ").trim(),d=i===""?"":` hold "${i}"`;try{const r=e.type??x,s=r.includes("component")?O(await D(_).index(),i):[],h=r.filter(a=>a!=="@polyhaven"),c=h.length>0?await R(n):void 0,u=c?.index?O(c.index,i).filter(a=>h.includes(H(a.type))):[],v=r.includes("@polyhaven")?se:[],{found:g,total:b}=v.length>0?await P(n).search(i,v):{found:[],total:0},w=e.all?g:g.slice(0,N);return{value:{query:i,components:s,resources:u,assets:{total:b,matches:g.length,found:w}},text:[...r.includes("component")?[`Starter components: ${String(s.length)}${d}.`,...s.map(a=>` component/${a.name} (${a.title}): ${a.description}`)]:[],...c?c.from==="none"?F(c,[]):[`AllyHub's resources: ${String(u.length)}${d}${c.from==="stale"?" (as last read)":""}.`,...u.map(a=>` ${E(a)} (${a.title}): ${a.description}`)]:[],...v.length>0?[`From Poly Haven (CC0): ${String(g.length)} of ${String(b)} assets${d}${w.length<g.length?`; the first ${String(w.length)} (--all for every one)`:""}.`,...w.map(de)]:[],"","Add one: allyhub add <type>/<name>"].join(`
6
6
  `)}}catch(r){throw M(r)}});
@@ -1,10 +1,10 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{readFile as C}from"node:fs/promises";import{join as J,resolve as v}from"node:path";import{z as o}from"zod";import{callTool as D,loadCatalog as m,resumeJob as E,uploadFiles as I}from"@allyhub-next/cloud";import{WORK_DIR as M}from"@allyhub-next/formats";import{EXIT as g}from"@allyhub-next/protocol";import{CommandError as w,defineCommand as N}from"../command.js";import{optionName as F}from"../args.js";import{requiredMissing as T,toolInput as L,toolOptions as U}from"../tool-options.js";import{cloudOf as f,cloudWork as $,placeFrom as H,plural as b}from"./cloud.js";const B=8e3,p={input:o.string().optional().describe("The input as JSON, or a file of it: the whole of it, or the fields no option gives; an option given beside it wins"),file:o.string().optional().describe("The path of the file it makes (without an extension it takes the result's); the same call with the same input then keeps it, calling nothing, and while its call works waits for that call; default a folder under .allyhub/work/"),force:o.boolean().default(!1).describe("With --file: call even when the file was made from this input, and replace a file that has no record"),wait:o.boolean().default(!0).describe("Wait for a long tool (an audit, a video model); --no-wait returns its call at once"),resume:o.string().optional().describe("Wait for a call of this tool this computer made (from --no-wait, or a call that stopped waiting), and download its file")},k=(e,a)=>new w("usage",e,{exit:g.usage,...a===void 0?{}:{hint:a}}),K=e=>{const a=e.reduce((i,r)=>r.map((s,n)=>Math.max(i[n]??0,s.length)),[]);return e.map(i=>` ${i.map((r,s)=>s===i.length-1?r:r.padEnd(a[s]??0)).join(" ")}`.trimEnd())};function _(e){return N({name:e.id,summary:`${e.title}: ${e.description} Lists the tools, each a command`,input:o.strictObject({fresh:o.boolean().default(!1).describe("Read the catalog from AllyHub again, not the copy kept an hour")}),output:o.looseObject({work:o.string(),tools:o.array(o.looseObject({name:o.string()}))}),examples:[`allyhub ${e.id}`,`allyhub ${e.id} --json`]},(a,i)=>$(async()=>{const s=(await m(f(i),{refresh:a.fresh})).tools.filter(n=>n.work===e.id).sort((n,t)=>n.name.localeCompare(t.name));return{value:{work:e.id,title:e.title,tools:s.map(n=>({name:n.name,title:n.title,description:n.description,long:n.long}))},text:[`${e.title} (${b(s.length,"tool")}):`,...K(s.map(n=>[n.name,n.title])),"",`Each costs credits when it worked; a failed call is free. allyhub help ${e.id} <tool> shows a tool's options and how its credits are counted.`].join(`
3
- `)}}))}function q(e,a=5,i=160){const r=n=>{const t=n===void 0?"undefined":JSON.stringify(n);return t.length>i?`${t.slice(0,i-1)}…`:t},s=(n,t)=>[`${n?`${n}: `:""}${b(t.length,"item")}${t.length>a?`, the first ${String(a)}:`:":"}`,...t.slice(0,a).map((l,d)=>` [${String(d)}] ${r(l)}`)];return Array.isArray(e)?s("",e):typeof e!="object"||e===null?[r(e)]:Object.entries(e).flatMap(([n,t])=>Array.isArray(t)?s(n,t):[`${n}: ${r(t)}`])}function R(e,a){if("jobId"in e)return[`${e.tool} is still working (call ${e.jobId}).`,`Wait for it: allyhub ${a} --resume ${e.jobId}${e.file===void 0?"":" (or the same command again: it waits for this call)"}`].join(`
2
+ import{readFile as x}from"node:fs/promises";import{join as J,resolve as v}from"node:path";import{z as o}from"zod";import{callTool as C,loadCatalog as m,resumeJob as D,uploadFiles as E}from"@allyhub-next/cloud";import{WORK_DIR as I}from"@allyhub-next/formats";import{EXIT as g}from"@allyhub-next/protocol";import{CommandError as w,defineCommand as N}from"../command.js";import{optionName as M}from"../args.js";import{requiredMissing as T,toolInput as L,toolOptions as U}from"../tool-options.js";import{cloudOf as f,cloudWork as $,placeFrom as H,plural as b}from"./cloud.js";const B=8e3,p={input:o.string().optional().describe("The input as JSON, or a file of it: the whole of it, or the fields no option gives; an option given beside it wins"),file:o.string().optional().describe("The path of the file it makes, or for a tool that returns data, of its output as JSON (without an extension it takes the result's, or .json); the same call with the same input then keeps it, calling nothing, and while its call works waits for that call; default a folder under .allyhub/work/"),force:o.boolean().default(!1).describe("With --file: call even when the file was made from this input, and replace a file that has no record"),wait:o.boolean().default(!0).describe("Wait for a long tool (an audit, a video model); --no-wait returns its call at once"),resume:o.string().optional().describe("Wait for a call of this tool this computer made (from --no-wait, or a call that stopped waiting), and download its file")},k=(e,a)=>new w("usage",e,{exit:g.usage,...a===void 0?{}:{hint:a}}),K=e=>{const a=e.reduce((i,r)=>r.map((s,n)=>Math.max(i[n]??0,s.length)),[]);return e.map(i=>` ${i.map((r,s)=>s===i.length-1?r:r.padEnd(a[s]??0)).join(" ")}`.trimEnd())};function _(e){return N({name:e.id,summary:`${e.title}: ${e.description} Lists the tools, each a command`,input:o.strictObject({fresh:o.boolean().default(!1).describe("Read the catalog from AllyHub again, not the copy kept an hour")}),output:o.looseObject({work:o.string(),tools:o.array(o.looseObject({name:o.string()}))}),examples:[`allyhub ${e.id}`,`allyhub ${e.id} --json`]},(a,i)=>$(async()=>{const s=(await m(f(i),{refresh:a.fresh})).tools.filter(n=>n.work===e.id).sort((n,t)=>n.name.localeCompare(t.name));return{value:{work:e.id,title:e.title,tools:s.map(n=>({name:n.name,title:n.title,description:n.description,long:n.long}))},text:[`${e.title} (${b(s.length,"tool")}):`,...K(s.map(n=>[n.name,n.title])),"",`Each costs credits when it worked; a failed call is free. allyhub help ${e.id} <tool> shows a tool's options and how its credits are counted.`].join(`
3
+ `)}}))}function q(e,a=5,i=160){const r=n=>{const t=n===void 0?"undefined":JSON.stringify(n);return t.length>i?`${t.slice(0,i-1)}…`:t},s=(n,t)=>[`${n?`${n}: `:""}${b(t.length,"item")}${t.length>a?`, the first ${String(a)}:`:":"}`,...t.slice(0,a).map((l,d)=>` [${String(d)}] ${r(l)}`)];return Array.isArray(e)?s("",e):typeof e!="object"||e===null?[r(e)]:Object.entries(e).flatMap(([n,t])=>Array.isArray(t)?s(n,t):[`${n}: ${r(t)}`])}function W(e,a){if("jobId"in e)return[`${e.tool} is still working (call ${e.jobId}).`,`Wait for it: allyhub ${a} --resume ${e.jobId}${e.file===void 0?"":" (or the same command again: it waits for this call)"}`].join(`
4
4
  `);if(e.kept)return[`Kept ${e.file??""}: ${e.tool} made it from this same input on ${e.kept.at} (${e.gen??""}).`,"Nothing was called or charged. --force makes it again."].join(`
5
- `);const i=JSON.stringify(e.output,null,2);return[i.length<=B?i:[`Output: ${String(Math.round(Buffer.byteLength(i)/1024))} KB of JSON, in short (--json prints it whole):`,...q(e.output)].join(`
6
- `),...e.file?[`File: ${e.file}${e.replaced?" (replaced: it was made from another input)":""}`]:[],...e.words?[`Words: ${e.words} (when each word is said: a part can say a stretch of the file)`]:[],...e.gen?[`Record: ${e.gen} (move it with the file)`]:[],`Credits used: ${e.credits===void 0?"not reported":String(e.credits)}`].join(`
7
- `)}const G=e=>{const a=Math.max(0,Math.round(e));return`${String(Math.floor(a/60))}:${String(a%60).padStart(2,"0")}`},z=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);async function X(e,a){const i=e.trim().startsWith("{"),r=i?e:await C(v(a.cwd,e),"utf8").catch(n=>{throw new w("not-found",`--input: cannot read ${e}: ${n.message}`,{exit:g.notFound,hint:"Give a JSON object, or a file of one."})});let s;try{s=JSON.parse(r)}catch{s=void 0}if(!z(s))throw k(`--input: ${i?"the text":e} is not a JSON object.`,`Give '{"field": …}', or a file of it.`);return s}export function toolCommand(e){const a=`${e.work} ${e.name}`,i=U(e.input,Object.keys(p)),r=o.strictObject({...i.shape,...p,input:p.input.describe(i.inputOnly.length?`${p.input.description??""}. Fields only it gives: ${i.inputOnly.join(", ")}`:p.input.description??"")}),s=[...i.fields].filter(([,n])=>i.required.includes(n)).map(([n,t])=>`--${F(n)} <${t}>`);return{spec:{name:a,summary:e.description,input:r,output:o.looseObject({tool:o.string(),output:o.record(o.string(),o.unknown()).optional(),credits:o.number().optional(),file:o.string().optional(),gen:o.string().optional(),words:o.string().optional(),jobId:o.string().optional()}),examples:[`allyhub ${[a,...s].join(" ")}`]},about:{lines:[e.title,"","A call is charged once, when it worked, as the description says; a failed call is free.",...e.long?["A long tool: the command waits for it (--no-wait returns its call, --resume waits again)."]:[]],value:{work:e.work,title:e.title,long:e.long,inputSchema:e.input,outputSchema:e.output}},run:(n,t)=>$(async()=>{const l=n,d=n,u=f(t),h=await H(t),y=L(i,d,l.input===void 0?{}:await X(l.input,t));let j=0;const O={base:h,signal:t.signal,onRunning:c=>{Date.now()-j<3e4||(j=Date.now(),t.progress(`${e.name}: working · ${G((Date.now()-Date.parse(c.createdAt))/1e3)} (call ${c.id})`))},onRetry:(c,W,x)=>{t.progress(`${e.name}: ${W.message}; reading call ${c} again in ${String(x)} s`)}};if(l.resume!==void 0){if(Object.keys(y).length>0||l.file!==void 0)throw k("--resume waits for a call as it was made: give it no input or --file.");const c=await E(u,l.resume,{...O,tool:e.name});return{value:{...c},text:R(c,a)}}const S=T(i,y);if(S.length>0)throw k(`${e.name} needs ${S.join(", ")}.`,`allyhub help ${a} shows its options.`);const A=await D(u,e.name,y,{...O,outDir:J(h,M,e.work,e.name),...l.file===void 0?{}:{file:v(t.cwd,l.file)},force:l.force,wait:l.wait});return{value:{...A},text:R(A,a)}})}}export const CLOUD_SOURCE={entries:[{name:"<work>",summary:"List a work's cloud tools (AllyHub's catalog), a line each; allyhub help lists the works"},{name:"<work> <tool>",summary:"Run a cloud tool with the account's credits, its input as options (allyhub help <work> <tool>, which says how its credits are counted)"}],async nouns(e){return(await m(f(e))).works.map(i=>({name:i.id,summary:`${i.title}: ${i.description}`}))},resolve:(e,a)=>$(async()=>{const[i,r]=e;if(i===void 0||i.startsWith("-"))return;let s;const n=(u,h)=>(s=u,h);let t=await m(f(a)).catch(n),l=t?.works.find(u=>u.id===i);if(l||(t=await m(f(a),{refresh:!0}).catch(u=>n(u,t)),l=t?.works.find(u=>u.id===i)),!t)throw new w("catalog-unreachable",`"${i}" is none of allyhub's own commands, and its cloud tools could not be read: ${s instanceof Error?s.message:String(s)}.`,{exit:g.failed,hint:"They need the network: run allyhub outside a sandbox that blocks it."});if(!l)return;if(r===void 0||r.startsWith("-"))return{command:_(l),rest:e.slice(1),list:!0};const d=t.tools.find(u=>u.name===r);if(d?.work!==l.id)throw new w("unknown-tool",d?`${r} is not a ${l.id} tool: it is in allyhub ${d.work}.`:`No ${l.id} tool ${r}.`,{exit:g.notFound,hint:d?`allyhub ${d.work} ${r}`:`allyhub ${l.id} lists its tools.`});return{command:toolCommand(d),rest:e.slice(2),list:!1}})},upload=N({name:"upload",summary:"Upload files from this computer for a cloud tool whose input takes a URL (a presenter photo, speech audio, a reference clip), and print a signed URL for each, which works for a few hours",input:o.strictObject({files:o.array(o.string()).min(1).describe("The files: images (.jpg, .png, .webp, .gif), sound (.mp3, .wav, .m4a, .aac, .ogg, .flac) or video (.mp4, .mov, .webm), 50 MB at most")}),positional:["files"],output:o.looseObject({files:o.array(o.looseObject({file:o.string(),ok:o.boolean(),url:o.string().optional()}))}),examples:["allyhub upload assets/media/presenter.jpg"]},(e,a)=>$(async()=>{const i=await I(f(a),e.files,{base:a.cwd}),r=i.filter(t=>!t.ok),s=i.map(t=>t.ok?`${t.file}
5
+ `);const i=JSON.stringify(e.output,null,2);return[i.length<=B?i:[`Output: ${String(Math.round(Buffer.byteLength(i)/1024))} KB of JSON, in short:`,...q(e.output)].join(`
6
+ `),...e.outputFile&&e.outputFile!==e.file?[`Whole output: ${e.outputFile}`]:[],...e.file?[`File: ${e.file}${e.replaced?" (replaced: it was made from another input)":""}`]:[],...e.words?[`Words: ${e.words} (when each word is said: a part can say a stretch of the file)`]:[],...e.gen?[`Record: ${e.gen} (move it with the file)`]:[],`Credits used: ${e.credits===void 0?"not reported":String(e.credits)}`].join(`
7
+ `)}const G=e=>{const a=Math.max(0,Math.round(e));return`${String(Math.floor(a/60))}:${String(a%60).padStart(2,"0")}`},z=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);async function X(e,a){const i=e.trim().startsWith("{"),r=i?e:await x(v(a.cwd,e),"utf8").catch(n=>{throw new w("not-found",`--input: cannot read ${e}: ${n.message}`,{exit:g.notFound,hint:"Give a JSON object, or a file of one."})});let s;try{s=JSON.parse(r)}catch{s=void 0}if(!z(s))throw k(`--input: ${i?"the text":e} is not a JSON object.`,`Give '{"field": …}', or a file of it.`);return s}export function toolCommand(e){const a=`${e.work} ${e.name}`,i=U(e.input,Object.keys(p)),r=o.strictObject({...i.shape,...p,input:p.input.describe(i.inputOnly.length?`${p.input.description??""}. Fields only it gives: ${i.inputOnly.join(", ")}`:p.input.description??"")}),s=[...i.fields].filter(([,n])=>i.required.includes(n)).map(([n,t])=>`--${M(n)} <${t}>`);return{spec:{name:a,summary:e.description,input:r,output:o.looseObject({tool:o.string(),output:o.record(o.string(),o.unknown()).optional(),outputFile:o.string().optional(),credits:o.number().optional(),file:o.string().optional(),gen:o.string().optional(),words:o.string().optional(),jobId:o.string().optional()}),examples:[`allyhub ${[a,...s].join(" ")}`]},about:{lines:[e.title,"","A call is charged once, when it worked, as the description says; a failed call is free.",...e.long?["A long tool: the command waits for it (--no-wait returns its call, --resume waits again)."]:[]],value:{work:e.work,title:e.title,long:e.long,inputSchema:e.input,outputSchema:e.output}},run:(n,t)=>$(async()=>{const l=n,d=n,u=f(t),h=await H(t),y=L(i,d,l.input===void 0?{}:await X(l.input,t));let j=0;const O={base:h,signal:t.signal,onRunning:c=>{Date.now()-j<3e4||(j=Date.now(),t.progress(`${e.name}: working · ${G((Date.now()-Date.parse(c.createdAt))/1e3)} (call ${c.id})`))},onRetry:(c,F,R)=>{t.progress(`${e.name}: ${F.message}; reading call ${c} again in ${String(R)} s`)}};if(l.resume!==void 0){if(Object.keys(y).length>0||l.file!==void 0)throw k("--resume waits for a call as it was made: give it no input or --file.");const c=await D(u,l.resume,{...O,tool:e.name});return{value:{...c},text:W(c,a)}}const S=T(i,y);if(S.length>0)throw k(`${e.name} needs ${S.join(", ")}.`,`allyhub help ${a} shows its options.`);const A=await C(u,e.name,y,{...O,outDir:J(h,I,e.work,e.name),...l.file===void 0?{}:{file:v(t.cwd,l.file)},force:l.force,wait:l.wait});return{value:{...A},text:W(A,a)}})}}export const CLOUD_SOURCE={entries:[{name:"<work>",summary:"List a work's cloud tools (AllyHub's catalog), a line each; allyhub help lists the works"},{name:"<work> <tool>",summary:"Run a cloud tool with the account's credits, its input as options (allyhub help <work> <tool>, which says how its credits are counted)"}],async nouns(e){return(await m(f(e))).works.map(i=>({name:i.id,summary:`${i.title}: ${i.description}`}))},resolve:(e,a)=>$(async()=>{const[i,r]=e;if(i===void 0||i.startsWith("-"))return;let s;const n=(u,h)=>(s=u,h);let t=await m(f(a)).catch(n),l=t?.works.find(u=>u.id===i);if(l||(t=await m(f(a),{refresh:!0}).catch(u=>n(u,t)),l=t?.works.find(u=>u.id===i)),!t)throw new w("catalog-unreachable",`"${i}" is none of allyhub's own commands, and its cloud tools could not be read: ${s instanceof Error?s.message:String(s)}.`,{exit:g.failed,hint:"They need the network: run allyhub outside a sandbox that blocks it."});if(!l)return;if(r===void 0||r.startsWith("-"))return{command:_(l),rest:e.slice(1),list:!0};const d=t.tools.find(u=>u.name===r);if(d?.work!==l.id)throw new w("unknown-tool",d?`${r} is not a ${l.id} tool: it is in allyhub ${d.work}.`:`No ${l.id} tool ${r}.`,{exit:g.notFound,hint:d?`allyhub ${d.work} ${r}`:`allyhub ${l.id} lists its tools.`});return{command:toolCommand(d),rest:e.slice(2),list:!1}})},upload=N({name:"upload",summary:"Upload files from this computer for a cloud tool whose input takes a URL (a presenter photo, speech audio, a reference clip), and print a signed URL for each, which works for a few hours",input:o.strictObject({files:o.array(o.string()).min(1).describe("The files: images (.jpg, .png, .webp, .gif), sound (.mp3, .wav, .m4a, .aac, .ogg, .flac) or video (.mp4, .mov, .webm), 50 MB at most")}),positional:["files"],output:o.looseObject({files:o.array(o.looseObject({file:o.string(),ok:o.boolean(),url:o.string().optional()}))}),examples:["allyhub upload assets/media/presenter.jpg"]},(e,a)=>$(async()=>{const i=await E(f(a),e.files,{base:a.cwd}),r=i.filter(t=>!t.ok),s=i.map(t=>t.ok?`${t.file}
8
8
  ${t.url}${t.expiresAt===void 0?"":` (works until ${t.expiresAt})`}`:`${t.file}
9
9
  failed: ${t.error.message}${t.error.hint?` ${t.error.hint}`:""}`);i.length>1&&s.push(r.length===0?`${b(i.length,"file")} uploaded.`:`${String(i.length-r.length)} of ${b(i.length,"file")} uploaded; ${String(r.length)} failed.`);const n=r[0];return{value:{files:i.map(t=>t.ok?{...t}:{file:t.file,ok:!1,error:{code:t.error.code,message:t.error.message,...t.error.hint?{hint:t.error.hint}:{}}})},text:s.join(`
10
10
  `),...n?{exit:n.error.exit}:{}}}));
@@ -1,3 +1,3 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{mkdir as y,readFile as f,rm as b,writeFile as S}from"node:fs/promises";import{dirname as m,join as p}from"node:path";import{fileURLToPath as E}from"node:url";import{z as a}from"zod";import{listFiles as R}from"@allyhub-next/build";import{openBrowser as h}from"@allyhub-next/cloud";import{startDevServer as u}from"@allyhub-next/dev-server";import{DEV_FILE as w,scanItems as T}from"@allyhub-next/formats";import{EXIT as I}from"@allyhub-next/protocol";import{CommandError as g,defineCommand as $}from"../command.js";import{dir as O,indexing as D}from"../fields.js";import{projectRoot as P}from"../project.js";export const PAGE=p(m(E(import.meta.url)),"../../editor-web");const l=4340,j=20;export async function start(r,e,n){const s={root:r,ui:PAGE,index:n};if(e!==void 0)return u({...s,port:e}).catch(t=>{throw t.code==="EADDRINUSE"?new g("port-in-use",`Port ${String(e)} is in use.`,{hint:"Choose another with --port, or leave it out."}):t});for(let t=l;t<l+j;t++)try{return await u({...s,port:t})}catch(o){if(o.code!=="EADDRINUSE")throw o}return u(s)}async function F(r){try{const e=JSON.parse(await f(p(r,w),"utf8"));return typeof e.url!="string"||typeof e.pid!="number"?void 0:(process.kill(e.pid,0),(await fetch(e.url,{signal:AbortSignal.timeout(2e3)})).ok?e.url:void 0)}catch{return}}async function v(r,e,n){if(n===void 0)return e;const{items:s}=T(await R(r)),t=n.replace(/^\.\//u,"").replace(/\/+$/u,""),o=s.find(i=>i.dir===t||i.entry===t);if(!o)throw new g("not-found",`There is no item ${n} in the project.`,{exit:I.notFound,hint:`Its items: ${s.map(i=>i.dir).join(", ")||"none"}.`});return`${e}?${new URLSearchParams({item:o.dir}).toString()}`}export const dev=$({name:"dev",summary:"The project's items in the browser, each in its editor (docs, sheets, videos, 3D sceneries), as their files change; runs until stopped, and run again while it runs, opens its page and ends",input:a.strictObject({item:a.string().optional().describe("Open the page on this item: its folder or its entry file"),dir:O,port:a.number().int().min(1).max(65535).optional().describe(`The port; default the first free one from ${String(l)}`),open:a.boolean().default(!0).describe("Open the page in the browser; --no-open only prints it")}),positional:["item"],output:a.strictObject({url:a.string()}),examples:["allyhub dev","allyhub dev launch/plan","allyhub dev --port 4400 --no-open"]},async(r,e)=>{const n=await P(e.cwd,r.dir),s=r.port===void 0?await F(n):void 0;if(s!==void 0){const i=await v(n,s,r.item);return e.progress(`allyhub dev is already running at ${i}`),r.open&&h(i,e.env),{value:{url:i},text:""}}const t=await start(n,r.port,D(e.env)),o=p(n,w);try{const i=await v(n,t.url,r.item);return await y(m(o),{recursive:!0}),await S(o,JSON.stringify({url:t.url,pid:process.pid})),e.progress(`allyhub dev is at ${i}
2
+ import{mkdir as y,readFile as f,rm as b,writeFile as S}from"node:fs/promises";import{dirname as m,join as p}from"node:path";import{fileURLToPath as E}from"node:url";import{z as a}from"zod";import{listFiles as R}from"@allyhub-next/build";import{openBrowser as h}from"@allyhub-next/cloud";import{startDevServer as u}from"@allyhub-next/dev-server";import{DEV_FILE as w,scanItems as T}from"@allyhub-next/formats";import{EXIT as I}from"@allyhub-next/protocol";import{CommandError as g,defineCommand as $}from"../command.js";import{dir as O,indexing as D}from"../fields.js";import{projectRoot as P}from"../project.js";export const PAGE=p(m(E(import.meta.url)),"../../editor-web");const l=4340,j=20;export async function start(r,e,n){const s={root:r,ui:PAGE,index:n};if(e!==void 0)return u({...s,port:e}).catch(t=>{throw t.code==="EADDRINUSE"?new g("port-in-use",`Port ${String(e)} is in use.`,{hint:"Choose another with --port, or leave it out."}):t});for(let t=l;t<l+j;t++)try{return await u({...s,port:t})}catch(o){if(o.code!=="EADDRINUSE")throw o}return u(s)}async function F(r){try{const e=JSON.parse(await f(p(r,w),"utf8"));return typeof e.url!="string"||typeof e.pid!="number"?void 0:(process.kill(e.pid,0),(await fetch(e.url,{signal:AbortSignal.timeout(2e3)})).ok?e.url:void 0)}catch{return}}async function v(r,e,n){if(n===void 0)return e;const{items:s}=T(await R(r)),t=n.replace(/^\.\//u,"").replace(/\/+$/u,""),o=s.find(i=>i.dir===t||i.entry===t);if(!o)throw new g("not-found",`There is no item ${n} in the project.`,{exit:I.notFound,hint:`Its items: ${s.map(i=>i.dir).join(", ")||"none"}.`});return`${e}?${new URLSearchParams({item:o.dir}).toString()}`}export const dev=$({name:"dev",summary:"The project's items in the browser, each in its editor (docs, sheets, videos, 3D sceneries; websites listed), as their files change; runs until stopped, and run again while it runs, opens its page and ends",input:a.strictObject({item:a.string().optional().describe("Open the page on this item: its folder or its entry file"),dir:O,port:a.number().int().min(1).max(65535).optional().describe(`The port; default the first free one from ${String(l)}`),open:a.boolean().default(!0).describe("Open the page in the browser; --no-open only prints it")}),positional:["item"],output:a.strictObject({url:a.string()}),examples:["allyhub dev","allyhub dev launch/plan","allyhub dev --port 4400 --no-open"]},async(r,e)=>{const n=await P(e.cwd,r.dir),s=r.port===void 0?await F(n):void 0;if(s!==void 0){const i=await v(n,s,r.item);return e.progress(`allyhub dev is already running at ${i}`),r.open&&h(i,e.env),{value:{url:i},text:""}}const t=await start(n,r.port,D(e.env)),o=p(n,w);try{const i=await v(n,t.url,r.item);return await y(m(o),{recursive:!0}),await S(o,JSON.stringify({url:t.url,pid:process.pid})),e.progress(`allyhub dev is at ${i}
3
3
  Press Ctrl+C to stop.`),r.open&&h(i,e.env),await new Promise(c=>{const d=()=>{process.off("SIGTERM",d),e.signal.removeEventListener("abort",d),c()};e.signal.aborted&&c(),e.signal.addEventListener("abort",d),process.once("SIGTERM",d)}),{value:{url:i},text:""}}finally{(await f(o,"utf8").catch(()=>"")).includes(`"pid":${String(process.pid)}`)&&await b(o,{force:!0}),await t.close()}});
@@ -1,2 +1,2 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{basename as q,resolve as x}from"node:path";import{Mattes as J,DECK_OVERLAY_KEY as Q,OVERLAY_KEY as Z,frameOverlay as v,overlaySvg as tt}from"@allyhub-next/measure";import{filmTimes as et,partOf as it}from"@allyhub-next/project";import{GRID_WIDTH as nt,MAX_TILES as H,defaultCols as st,gridHtml as ot,gridLayout as rt,labelSize as at,probeVideo as dt,sheetHtml as ct,stretchFrames as ft}from"@allyhub-next/media";import{clipTypeOf as lt,ffmpegOf as pt,hasFinalLook as ht,videoFrame as mt,writeClip as ut}from"@allyhub-next/render";import{EXIT as wt}from"@allyhub-next/protocol";import{CommandError as gt}from"../../command.js";import{drawPage as R,gridError as V,isFile as $t,looks as yt,momentOf as bt,pictureUrl as W,picturePath as L,save as _,secondsName as I,usage as F,withCombo as K,workPath as kt}from"./common.js";const T=e=>Math.round(e*1e3)/1e3,j=e=>({source:"piece",piece:e.target.piece,combo:e.target.combo,...e.target.id===void 0?{}:{id:e.target.id},format:e.target.format}),P=(e,t)=>kt(t,"frames",e.target.piece);function C(e,t){const i=e.at(-1);return e.find(s=>t>=s.start&&t<s.end)??(i&&t>=i.end?i:void 0)}export async function stillsSheet(e,t){const i=e.timeline,s=e.version.summary?.text??[],p=i.parts.flatMap((a,l)=>{const w=a.steps??[a.still];return w.map((y,d)=>({p:a,t:y,slide:l,step:d,of:w.length}))}),h=[];for(const a of p)h.push(await e.still(a.t));const m=i.width/i.height,$=m<1?4:3,r=m<1?1320:1600,b=e.piece.kind==="slides",o=[];for(let a=0;a<p.length;a+=$)o.push({cells:p.slice(a,a+$).map(({p:l,slide:w,step:y,of:d},S)=>{const k=s.find(g=>g.key===l.key);return{image:h[a+S]??Buffer.alloc(0),label:b?`${String(w+1)}${d>1?`.${String(y)}`:""} · ${l.key}${l.hidden?" · hidden":""}`:`${l.key} · ${l.still.toFixed(2)} s`,text:k?.notes??k?.spoken??k?.onScreen.join(" · ")??""}})});const E=await R(e.session.browser,{html:ct({title:b?`${e.target.piece} · ${i.parts.length===1?"1 slide":`${String(i.parts.length)} slides`}`:`${e.target.piece} · ${i.parts.length===1?"1 part":`${String(i.parts.length)} parts`} · ${i.duration.toFixed(2)} s`,rows:o,cols:$,width:r,aspect:m}),width:r}),M=await _(L(t.cwd,t.out,x(P(e,t.root),`${K("sheet",e.target)}.png`)),E);return{mode:"sheet",...b?{slides:!0}:{},...j(e),out:M,parts:i.parts.map(a=>({key:a.key,t:T(a.still)}))}}export function clipKind(e){const t=lt(e);if(!t)throw F("bad-clip",`Cannot tell what kind of video ${e} is.`,"End --clip with .gif, .mp4 or .webm.");return t}async function xt(e,t){if(!await $t(e))throw new gt("not-found",`There is no file ${e} (--beside).`,{exit:wt.notFound});const i=await dt(e),s=Math.max(1,Math.round(i.duration*i.fps)),p=[];for(const h of t){const m=Math.round(h*i.fps);p.push(h<0||m>s-1?void 0:await mt(e,m,i.fps))}return{info:i,shots:p}}export async function pieceMoments(e,t){const i=e.timeline,s=t.part===void 0?void 0:it(i,t.part),p=s?.start??0,h=t.from!==void 0||t.to!==void 0;if(h&&t.at!==void 0)throw F("bad-option","Give --at or --from and --to, not both.");if(h&&(t.from===void 0||t.to===void 0))throw F("bad-option","A stretch needs --from and --to.");if(t.clip!==void 0&&!h)throw F("bad-option","--clip needs --from and --to.","For example --from 3.2 --to 4.4 --clip move.gif.");const m=t.clip===void 0?void 0:clipKind(t.clip),$=t.clip===void 0||t.out!==void 0;let r;try{r=t.from!==void 0&&t.to!==void 0?ft({from:p+t.from,to:p+t.to},{fps:i.fps,duration:i.duration,grid:$}):void 0}catch(n){throw V(n)}const b=(t.at??[]).map(bt),o=r?r.times:b.length===0&&s?[s.still]:et(b,i.parts,s);if(o.length>H&&$)throw F("bad-time",`${String(o.length)} moments; one picture holds at most ${String(H)}.`);for(const n of o)if(n<0||n>i.duration+1/i.fps)throw F("bad-time",`${n.toFixed(2)} s is outside ${e.target.piece}, which is ${i.duration.toFixed(2)} s long.`,s?`With --part, --at counts from the part's start; ${s.key} runs ${s.start.toFixed(2)}–${s.end.toFixed(2)} s.`:`Parts: ${i.parts.map(c=>`${c.key} ${c.start.toFixed(2)}–${c.end.toFixed(2)}`).join(", ")}.`);const E=n=>Math.min(n,i.duration),M={...j(e),final:ht(e.look,i),...r?{stretch:{from:r.from,to:r.to,every:r.every,frames:r.times.length}}:{}};if(o.length===1&&!r&&!t.overlay&&t.beside===void 0){const n=o[0]??0,c=s?.key??C(i.parts,n)?.key??"",f=await _(L(t.cwd,t.out,x(P(e,t.root),`${K(t.at===void 0&&s?s.key:I(n),e.target)}.png`)),await e.still(E(n),{format:yt()}));return{mode:"frame",...M,out:f,t:T(n),part:c,width:i.width,height:i.height}}const l=[];for(const n of o)l.push(await e.still(E(n)));const w=t.clip!==void 0&&m?await ut(l,{file:x(t.cwd,t.clip),type:m,fps:i.fps/(r?.every??1)}):void 0;if(!$)return{mode:"clip",...M,clip:w};const y=[];if(t.overlay){const n=i.duration-1/i.fps,c=await e.version.measure(o.map(u=>Math.min(u,n))),f=new J({root:e.prepared.root,media:e.prepared.media,ffmpeg:await pt()});for(const u of o)y.push(await v(Math.min(u,n),i,c,e.prepared.media,f))}const d=t.beside===void 0?void 0:await xt(x(t.cwd,t.beside),o),S=d?2:1,k=i.width/i.height;let g;try{g=rt({count:o.length,cols:st(o.length,k*S),width:nt,aspect:k*S})}catch(n){throw V(n)}const Y=(g.tiles[0]?.width??i.width)/S,G=Math.max(11,at(Y)-4),A=[...l],X=d?q(t.beside??""):"",z=o.map((n,c)=>{const f=y[c],u={src:W(c),label:e.piece.kind==="slides"?C(i.parts,n)?.key??"":`${n.toFixed(r?3:2)} s · ${C(i.parts,n)?.key??""}`,...f?{over:tt(f,i.width,i.height,Y/i.width,G)}:{}};if(!d)return{pictures:[u]};const O=d.shots[c];return O&&A.push(O),{pictures:[{src:O?W(A.length-1):void 0,label:`${X} · ${n.toFixed(2)} s${O?"":" · past its end"}`},u]}}),B=await R(e.session.browser,{html:ot({layout:g,cells:z,...t.overlay?{legend:e.piece.kind==="slides"?Q:Z}:{}}),width:g.width,pictures:A}),D=o[0]??0,N=o.at(-1)??D,U=await _(L(t.cwd,t.out,x(P(e,t.root),`${K(`${r?"stretch":"moments"}-${I(D)}-${I(N)}`,e.target)}.png`)),B);return{mode:"grid",...M,out:U,cols:g.cols,tiles:o.map((n,c)=>{const f=g.tiles[c],u=y[c];return{t:T(n),part:C(i.parts,n)?.key??"",...f?{box:[f.x,f.y,f.width,f.height]}:{},...u?{overlay:u}:{},...d?{beside:{t:T(n),shown:d.shots[c]!==void 0}}:{}}}),...d?{beside:{file:x(t.cwd,t.beside??""),video:{duration:d.info.duration,width:d.info.width,height:d.info.height,fps:d.info.fps}}}:{},...w?{clip:w}:{}}}
2
+ import{basename as q,resolve as x}from"node:path";import{Mattes as J,DECK_OVERLAY_KEY as Q,OVERLAY_KEY as Z,frameOverlay as v,overlaySvg as tt}from"@allyhub-next/measure";import{DeckPool as et,filmTimes as it,partOf as st}from"@allyhub-next/project";import{GRID_WIDTH as nt,MAX_TILES as H,defaultCols as ot,gridHtml as rt,gridLayout as at,labelSize as dt,probeVideo as ct,sheetHtml as lt,sheetTile as ft,stretchFrames as pt}from"@allyhub-next/media";import{clipTypeOf as ht,ffmpegOf as mt,hasFinalLook as ut,videoFrame as wt,writeClip as gt}from"@allyhub-next/render";import{EXIT as yt}from"@allyhub-next/protocol";import{CommandError as $t}from"../../command.js";import{drawPage as R,gridError as V,isFile as bt,looks as kt,momentOf as xt,pictureUrl as W,picturePath as L,save as P,secondsName as _,usage as F,withCombo as D,workPath as Ft}from"./common.js";const T=t=>Math.round(t*1e3)/1e3,j=t=>({source:"piece",piece:t.target.piece,combo:t.target.combo,...t.target.id===void 0?{}:{id:t.target.id},format:t.target.format}),I=(t,e)=>Ft(e,"frames",t.target.piece);function C(t,e){const i=t.at(-1);return t.find(n=>e>=n.start&&e<n.end)??(i&&e>=i.end?i:void 0)}export async function stillsSheet(t,e){const i=t.timeline,n=t.version.summary?.text??[],h=i.parts.flatMap((a,l)=>{const p=a.steps??[a.still];return p.map(($,d)=>({p:a,t:$,slide:l,step:d,of:p.length}))}),m=i.width/i.height,u=m<1?4:3,y=m<1?1320:1600,r=t.piece.kind==="slides",b=[];if(r){const a=await et.on(t.session,t.piece,t.target,t.version.stage),l=ft({width:y,cols:u});b.push(...await a.stills(h.map(p=>({slide:p.p.key,step:p.step,width:l,format:"webp"}))))}else for(const a of h)b.push(await t.still(a.t));const o=[];for(let a=0;a<h.length;a+=u)o.push({cells:h.slice(a,a+u).map(({p:l,slide:p,step:$,of:d},S)=>{const k=n.find(g=>g.key===l.key);return{image:b[a+S]??Buffer.alloc(0),label:r?`${String(p+1)}${d>1?`.${String($)}`:""} · ${l.key}${l.hidden?" · hidden":""}`:`${l.key} · ${l.still.toFixed(2)} s`,text:k?.notes??k?.spoken??k?.onScreen.join(" · ")??""}})});const E=await R(t.session.browser,{html:lt({title:r?`${t.target.piece} · ${i.parts.length===1?"1 slide":`${String(i.parts.length)} slides`}`:`${t.target.piece} · ${i.parts.length===1?"1 part":`${String(i.parts.length)} parts`} · ${i.duration.toFixed(2)} s`,rows:o,cols:u,width:y,aspect:m}),width:y}),M=await P(L(e.cwd,e.out,x(I(t,e.root),`${D("sheet",t.target)}.png`)),E);return{mode:"sheet",...r?{slides:!0}:{},...j(t),out:M,parts:i.parts.map(a=>({key:a.key,t:T(a.still)}))}}export function clipKind(t){const e=ht(t);if(!e)throw F("bad-clip",`Cannot tell what kind of video ${t} is.`,"End --clip with .gif, .mp4 or .webm.");return e}async function Mt(t,e){if(!await bt(t))throw new $t("not-found",`There is no file ${t} (--beside).`,{exit:yt.notFound});const i=await ct(t),n=Math.max(1,Math.round(i.duration*i.fps)),h=[];for(const m of e){const u=Math.round(m*i.fps);h.push(m<0||u>n-1?void 0:await wt(t,u,i.fps))}return{info:i,shots:h}}export async function pieceMoments(t,e){const i=t.timeline,n=e.part===void 0?void 0:st(i,e.part),h=n?.start??0,m=e.from!==void 0||e.to!==void 0;if(m&&e.at!==void 0)throw F("bad-option","Give --at or --from and --to, not both.");if(m&&(e.from===void 0||e.to===void 0))throw F("bad-option","A stretch needs --from and --to.");if(e.clip!==void 0&&!m)throw F("bad-option","--clip needs --from and --to.","For example --from 3.2 --to 4.4 --clip move.gif.");const u=e.clip===void 0?void 0:clipKind(e.clip),y=e.clip===void 0||e.out!==void 0;let r;try{r=e.from!==void 0&&e.to!==void 0?pt({from:h+e.from,to:h+e.to},{fps:i.fps,duration:i.duration,grid:y}):void 0}catch(s){throw V(s)}const b=(e.at??[]).map(xt),o=r?r.times:b.length===0&&n?[n.still]:it(b,i.parts,n);if(o.length>H&&y)throw F("bad-time",`${String(o.length)} moments; one picture holds at most ${String(H)}.`);for(const s of o)if(s<0||s>i.duration+1/i.fps)throw F("bad-time",`${s.toFixed(2)} s is outside ${t.target.piece}, which is ${i.duration.toFixed(2)} s long.`,n?`With --part, --at counts from the part's start; ${n.key} runs ${n.start.toFixed(2)}–${n.end.toFixed(2)} s.`:`Parts: ${i.parts.map(c=>`${c.key} ${c.start.toFixed(2)}–${c.end.toFixed(2)}`).join(", ")}.`);const E=s=>Math.min(s,i.duration),M={...j(t),final:ut(t.look,i),...r?{stretch:{from:r.from,to:r.to,every:r.every,frames:r.times.length}}:{}};if(o.length===1&&!r&&!e.overlay&&e.beside===void 0){const s=o[0]??0,c=n?.key??C(i.parts,s)?.key??"",f=await P(L(e.cwd,e.out,x(I(t,e.root),`${D(e.at===void 0&&n?n.key:_(s),t.target)}.png`)),await t.still(E(s),{format:kt()}));return{mode:"frame",...M,out:f,t:T(s),part:c,width:i.width,height:i.height}}const l=[];for(const s of o)l.push(await t.still(E(s)));const p=e.clip!==void 0&&u?await gt(l,{file:x(e.cwd,e.clip),type:u,fps:i.fps/(r?.every??1)}):void 0;if(!y)return{mode:"clip",...M,clip:p};const $=[];if(e.overlay){const s=i.duration-1/i.fps,c=await t.version.measure(o.map(w=>Math.min(w,s))),f=new J({root:t.prepared.root,media:t.prepared.media,ffmpeg:await mt()});for(const w of o)$.push(await v(Math.min(w,s),i,c,t.prepared.media,f))}const d=e.beside===void 0?void 0:await Mt(x(e.cwd,e.beside),o),S=d?2:1,k=i.width/i.height;let g;try{g=at({count:o.length,cols:ot(o.length,k*S),width:nt,aspect:k*S})}catch(s){throw V(s)}const K=(g.tiles[0]?.width??i.width)/S,G=Math.max(11,dt(K)-4),A=[...l],X=d?q(e.beside??""):"",z=o.map((s,c)=>{const f=$[c],w={src:W(c),label:t.piece.kind==="slides"?C(i.parts,s)?.key??"":`${s.toFixed(r?3:2)} s · ${C(i.parts,s)?.key??""}`,...f?{over:tt(f,i.width,i.height,K/i.width,G)}:{}};if(!d)return{pictures:[w]};const O=d.shots[c];return O&&A.push(O),{pictures:[{src:O?W(A.length-1):void 0,label:`${X} · ${s.toFixed(2)} s${O?"":" · past its end"}`},w]}}),B=await R(t.session.browser,{html:rt({layout:g,cells:z,...e.overlay?{legend:t.piece.kind==="slides"?Q:Z}:{}}),width:g.width,pictures:A}),Y=o[0]??0,N=o.at(-1)??Y,U=await P(L(e.cwd,e.out,x(I(t,e.root),`${D(`${r?"stretch":"moments"}-${_(Y)}-${_(N)}`,t.target)}.png`)),B);return{mode:"grid",...M,out:U,cols:g.cols,tiles:o.map((s,c)=>{const f=g.tiles[c],w=$[c];return{t:T(s),part:C(i.parts,s)?.key??"",...f?{box:[f.x,f.y,f.width,f.height]}:{},...w?{overlay:w}:{},...d?{beside:{t:T(s),shown:d.shots[c]!==void 0}}:{}}}),...d?{beside:{file:x(e.cwd,e.beside??""),video:{duration:d.info.duration,width:d.info.width,height:d.info.height,fps:d.info.fps}}}:{},...p?{clip:p}:{}}}
@@ -1,2 +1,2 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{readFileSync as w}from"node:fs";import{dirname as $,join as l}from"node:path";import{startBrowser as b}from"@allyhub-next/browser";import{EXIT as x}from"@allyhub-next/protocol";import{docFontsCss as S}from"@allyhub-next/render/doc";import{columnIndex as p,readArea as y,sheetHtml as A}from"@allyhub-next/sheet";import{CommandError as E}from"../../command.js";import{openSheet as M}from"../sheet.js";import{drawPage as k,picturePath as C,save as I,workPath as N}from"./common.js";export const SHEET_ROWS=200,SHEET_COLUMNS=60;const g=12;function P(e,r){const c=e.used;if(!c)return;const u=/^\$?([A-Za-z]{1,3}):\$?([A-Za-z]{1,3})$/u.exec(r);if(u){const t=p(u[1]??""),s=p(u[2]??"");return t===void 0||s===void 0?void 0:{...c,left:Math.min(t,s),right:Math.max(t,s)}}const o=/^\$?(\d+):\$?(\d+)$/u.exec(r);if(!o)return;const m=Number(o[1])-1,a=Number(o[2])-1;return{...c,top:Math.min(m,a),bottom:Math.max(m,a)}}const B=e=>e.replace(/^'|'$/gu,"").replaceAll("''","'");export async function sheetPicture(e){const{workbook:r,calc:c,file:u}=await M(e.root,e.cwd,e.item),o=$(u),m=n=>{throw new E("not-found",`${n} is not a sheet or a range of this workbook.`,{exit:x.notFound,hint:`Sheets: ${r.sheets.map(i=>i.name).join(", ")}. A range is Summary!B3:D9, or B3:D9 on the first sheet.`})};let a,t;if(e.range!==void 0){const n=r.sheet(e.range);if(n)a=[n];else{const i=e.range.lastIndexOf("!"),d=i<0?r.sheets[0]:r.sheet(B(e.range.slice(0,i))),h=e.range.slice(i+1);if(!d||(t=y(h)??P(d,h),!t))return m(e.range);a=[d]}}const s=A(c,{...a?{sheets:a}:{},...t?{area:t}:{rows:SHEET_ROWS,columns:SHEET_COLUMNS},headings:!0,css:`${await S()}body{padding:${String(g)}px}`,font:"Commissioner Variable",file:n=>{try{return new Uint8Array(w(l(e.root,o,n)))}catch{return}}}),f=await b({gpu:!1,htmlInCanvas:!1});try{const n=await k(f,{html:s.html,width:s.width+2*g}),i=e.range===void 0?"sheet":e.range.replace(/[^\p{L}\p{N}]+/gu,"-").replace(/^-+|-+$/gu,""),d=await I(C(e.cwd,e.out,l(N(e.root,"frames",o),`${i||"sheet"}.png`)),n);return{mode:"frame",source:"sheet",sheet:o,out:d,...e.range===void 0?{}:{range:e.range},cut:s.cut}}finally{await f.close()}}
2
+ import{readFileSync as w}from"node:fs";import{dirname as $,join as l}from"node:path";import{startBrowser as x}from"@allyhub-next/browser";import{EXIT as b}from"@allyhub-next/protocol";import{SHEET_FONT as y,sheetFontsCss as S}from"@allyhub-next/render/doc";import{columnIndex as p,readArea as A,sheetHtml as E}from"@allyhub-next/sheet";import{CommandError as M}from"../../command.js";import{openSheet as N}from"../sheet.js";import{drawPage as k,picturePath as I,save as T,workPath as C}from"./common.js";export const SHEET_ROWS=200,SHEET_COLUMNS=60;const g=12;function F(e,a){const c=e.used;if(!c)return;const u=/^\$?([A-Za-z]{1,3}):\$?([A-Za-z]{1,3})$/u.exec(a);if(u){const t=p(u[1]??""),n=p(u[2]??"");return t===void 0||n===void 0?void 0:{...c,left:Math.min(t,n),right:Math.max(t,n)}}const o=/^\$?(\d+):\$?(\d+)$/u.exec(a);if(!o)return;const m=Number(o[1])-1,s=Number(o[2])-1;return{...c,top:Math.min(m,s),bottom:Math.max(m,s)}}const H=e=>e.replace(/^'|'$/gu,"").replaceAll("''","'");export async function sheetPicture(e){const{workbook:a,calc:c,file:u}=await N(e.root,e.cwd,e.item),o=$(u),m=r=>{throw new M("not-found",`${r} is not a sheet or a range of this workbook.`,{exit:b.notFound,hint:`Sheets: ${a.sheets.map(i=>i.name).join(", ")}. A range is Summary!B3:D9, or B3:D9 on the first sheet.`})};let s,t;if(e.range!==void 0){const r=a.sheet(e.range);if(r)s=[r];else{const i=e.range.lastIndexOf("!"),f=i<0?a.sheets[0]:a.sheet(H(e.range.slice(0,i))),h=e.range.slice(i+1);if(!f||(t=A(h)??F(f,h),!t))return m(e.range);s=[f]}}const n=E(c,{...s?{sheets:s}:{},...t?{area:t}:{rows:SHEET_ROWS,columns:SHEET_COLUMNS},headings:!0,css:`body{padding:${String(g)}px}`,font:y,file:r=>{try{return new Uint8Array(w(l(e.root,o,r)))}catch{return}}}),d=await x({gpu:!1,htmlInCanvas:!1});try{const r=await k(d,{html:n.html.replace("<style>",`<style>${await S(n.html)}`),width:n.width+2*g}),i=e.range===void 0?"sheet":e.range.replace(/[^\p{L}\p{N}]+/gu,"-").replace(/^-+|-+$/gu,""),f=await T(I(e.cwd,e.out,l(C(e.root,"frames",o),`${i||"sheet"}.png`)),r);return{mode:"frame",source:"sheet",sheet:o,out:f,...e.range===void 0?{}:{range:e.range},cut:n.cut}}finally{await d.close()}}
@@ -1,9 +1,9 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{z as t}from"zod";import{formatConsole as P,formatProblem as z}from"../text/index.js";import{COMPARE_DEFAULTS as W,CUT_REVIEW_DEFAULTS as M,cutLine as I,dbText as w,silenceText as L}from"@allyhub-next/measure";import{consoleJson as x}from"@allyhub-next/project";import{PAGE_CAPTURE_DEFAULTS as $}from"@allyhub-next/browser";import{EXIT as j}from"@allyhub-next/protocol";import{defineCommand as f}from"../command.js";import{dir as k}from"../fields.js";import{parameters as T}from"../parameters.js";import{projectRoot as u}from"../project.js";import{VERSION_FIELDS as y,commandError as F,withVersion as h}from"../version.js";import{compareText as A,comparePictures as O}from"./frames/compare.js";import{isPicture as _,isVideo as C,usage as p}from"./frames/common.js";import{cutSheets as R}from"./frames/cuts.js";import{fileFrames as B}from"./frames/file.js";import{pageShot as H}from"./frames/page.js";import{pieceMoments as N,stillsSheet as U}from"./frames/piece.js";import{sheetPicture as G}from"./frames/sheet.js";import{findSheet as V}from"./sheet.js";import{sizeOf as J}from"./scenery-input.js";function g(e){return[...e.problems.filter(s=>s.level==="error").map(z),...P(x(e.console))]}const b=e=>({problems:e.problems,...x(e.console)}),v=(e,i)=>u(e,i),q=t.strictObject({...y,item:t.string().optional().describe("The piece (its id, or a path into it; default the project's only one), a sheet, or a video file: a path ending in .mp4, .mov, .webm, .m4v, .qt, .mkv or .avi is a file"),range:t.string().optional().describe("A sheet's: what to draw, a sheet (Summary), a range (Summary!B3:D9, or B3:D9 on the first sheet), columns (A:C) or rows (1:20); default its sheets, from A1"),at:t.array(t.string()).optional().describe("Moments: seconds (from the start of --part when given) or anchors (@press, @/map a stretch's end, @press+0.2); a video file's are seconds. One is written as the frame itself, several are tiled. Without it, --part's still, or every part's still on one sheet"),part:t.string().optional().describe("The part --at, --from and --to count from; alone, its still"),from:t.number().optional().describe("A stretch of consecutive frames from this second (with --to), instead of --at"),to:t.number().optional().describe("The stretch's last second"),clip:t.string().optional().describe("Write the stretch as a small silent video, .gif, .mp4 or .webm by its extension; with --out, the grid too"),overlay:t.boolean().default(!1).describe("Draw over each tile the face boxes with ids, the person matte's outline, the covered areas and the text boxes; places nothing"),beside:t.string().optional().describe("Another video file (a reference) whose frame at the same time goes on each tile's left"),grid:t.number().int().min(4).optional().describe("A video file at one --at: the frame at its own size with numbered lines every this many pixels"),out:t.string().optional().describe("Where the picture goes (a WebP); default under .allyhub/work/frames/")});function X(e){const i=[["--combo",e.combo!==void 0],["--part",e.part!==void 0],["--beside",e.beside!==void 0],["--overlay",e.overlay]].filter(([,s])=>s).map(([s])=>s);if(i.length>0)throw p("bad-option",`${i.join(" and ")} ${i.length===1?"is":"are"} a piece's: a video file has no combos or parts.`)}export const frames=f({name:"frames",summary:"Pictures of a piece over time, drawn as the render draws them: every part's still on a sheet (default), a moment, a stretch tiled or as a clip, overlays; a sheet's cells, or a range of them; or any video file's frames",input:q,positional:["item"],output:t.looseObject({mode:t.enum(["sheet","frame","grid","clip"])}),examples:["allyhub frames launch/film","allyhub frames launch/film --at 2.5","allyhub frames launch/film --part hook --from 0 --to 1 --clip hook.gif","allyhub frames launch/film --at 1,2,3 --overlay","allyhub frames reference.mp4 --at 0,1,2","allyhub frames reference.mp4 --at 3 --grid 50","allyhub frames finance/budget --range 'Summary!A1:F20'"]},async(e,i)=>{const s=i.cwd;if(e.item!==void 0&&C(e.item)){X(e);const r=await B({cwd:s,root:await v(s,e.dir),file:e.item,at:e.at,from:e.from,to:e.to,clip:e.clip,out:e.out,grid:e.grid}).catch(D=>{throw F(D)}),a=r.video,m=`${r.file} · ${a.duration.toFixed(2)} s · ${String(a.width)}×${String(a.height)} · ${String(a.fps)} fps`,S="clip"in r&&r.clip?`${r.clip.out} (${r.clip.type}, ${String(r.clip.frames)} frames at ${String(r.clip.fps)} fps, no sound)`:void 0;return{value:r,text:[m,..."out"in r?[`${r.out}${"tiles"in r?` (${String(r.tiles.length)} moments in ${String(r.cols)} columns)`:""}`]:[],...S?[S]:[]].join(`
3
- `)}}if(e.grid!==void 0)throw p("bad-option","--grid draws a video file's frame at its own size: give the file.");const l=await u(s,e.dir);if(e.item!==void 0&&await V(l,s,e.item)!==void 0){const r=await G({cwd:s,root:l,item:e.item,range:e.range,out:e.out});return{value:r,text:[r.out,...r.cut].join(`
4
- `)}}if(e.range!==void 0)throw p("bad-option","--range is a sheet's: name the sheet.");if(!(e.at!==void 0||e.part!==void 0||e.from!==void 0||e.to!==void 0)){if(e.clip!==void 0||e.beside!==void 0||e.overlay)throw p("bad-option","--clip, --beside and --overlay draw moments: give --at, --part, or --from and --to.");const{result:r,...a}=await h(e,i,"render",m=>U(m,{cwd:s,root:l,out:e.out}));return{value:{...r,...b(a)},text:[`${r.out} (${r.piece} · ${r.format} · ${String(r.parts.length)} ${"slides"in r?"slide":"part"}${r.parts.length===1?"":"s"})`,...g(a)].join(`
5
- `)}}const{result:o,...d}=await h(e,i,"render",r=>N(r,{cwd:s,root:l,at:e.at,part:e.part,from:e.from,to:e.to,clip:e.clip,out:e.out,overlay:e.overlay,beside:e.beside})),c=[];if(o.mode==="frame"&&c.push(`${o.out} (${o.piece} · ${o.format} · ${o.part} · ${o.t.toFixed(2)} s)`),o.mode==="grid"){c.push(`${o.out} (${o.piece} · ${String(o.tiles.length)} moments in ${String(o.cols)} columns)`,` ${o.tiles.map(a=>`${a.t.toFixed(o.stretch?3:2)} ${a.part}`).join(" · ")}`);const r=[...new Set(o.tiles.flatMap(a=>a.overlay?.missing??[]))];r.length>0&&c.push(` Not measured: ${r.join(", ")}.`)}return o.stretch&&c.push(` Stretch ${o.stretch.from.toFixed(3)}–${o.stretch.to.toFixed(3)} s, one frame in ${String(o.stretch.every)}: ${String(o.stretch.frames)} frames.`),"clip"in o&&o.clip&&c.push(`${o.clip.out} (${o.clip.type}, ${String(o.clip.frames)} frames at ${String(o.clip.fps)} fps, no sound)`),{value:{...o,...b(d)},text:[...c,...g(d)].join(`
6
- `)}}),framesCuts=f({name:"frames cuts",summary:"A review sheet per cut of a video (a cut take's jumps, part joins, a scenery camera's cuts): frames around it, waveform and level, the words each side, the sound at it",input:t.strictObject({...y,part:t.string().optional().describe("Only this part's cuts and its joins"),out:t.string().optional().describe("The folder the sheets go in; default .allyhub/work/cuts/"),params:T({span:t.number().positive().max(10).default(M.span).describe("Seconds shown on each side of a cut")})}),positional:["item"],output:t.looseObject({out:t.string(),cuts:t.array(t.looseObject({sheet:t.string()}))}),examples:["allyhub frames cuts launch/film","allyhub frames cuts launch/film --part hook"]},async(e,i)=>{const s=i.cwd,l=await u(s,e.dir),{result:n,...o}=await h(e,i,"render",r=>R(r,{cwd:s,root:l,part:e.part,out:e.out,review:{span:e.params.span}})),d=n.part===void 0?`${String(n.cuts.length)} cut${n.cuts.length===1?"":"s"}`:`${String(n.cuts.length)} of ${String(n.total)} cuts (part ${n.part} and its joins)`,c=[`${n.piece} · ${n.format} · ${d}; silence is sound under ${String(n.threshold)} dBFS`];for(const r of n.cuts){const a=r.sound?`level ${w(r.sound.levelDb)} / around ${w(r.sound.aroundDb)} dBFS, peak ${w(r.sound.peakDb)}, step ${r.sound.jumpDb<0?"−":"+"}${Math.abs(r.sound.jumpDb).toFixed(1)} dB`:"no sound";c.push(`${String(r.index).padStart(3)} ${r.t.toFixed(3).padStart(7)} s ${r.kind.padEnd(6)} ${I(r)}`,` silence at the cut: ${L(r.silence)} · ${a}`,` “${r.said.before}” | “${r.said.after}”${r.across?` · across the cut: “${r.across}”`:""}`,` ${r.sheet}`)}return{value:{...n,...b(o)},text:[...c,...g(o)].join(`
7
- `)}});const E=W;export const framesCompare=f({name:"frames compare",summary:"How a candidate picture differs from a reference, as numbers (ΔE, channels, SSIM, levels, grain, edges, regions) with a heatmap and a side-by-side: a piece's moment, a picture file or a video file's frame",input:t.strictObject({reference:t.string().describe("The reference picture (PNG, WebP, JPEG…)"),candidate:t.string().optional().describe("A piece (its id, or a path into it; default the project's only one) at --at or --part's still; or a file by its extension: a picture (.png, .jpg, .webp…), or a video file's frame at --at (.mp4, .mov, .webm…)"),combo:y.combo,dir:k,at:t.string().optional().describe("The moment: seconds (from the start of --part when given) or an anchor of the piece; a video file's are seconds (default 0)"),part:t.string().optional().describe("The piece's part --at counts from; alone, its still"),refCrop:t.string().optional().describe("Cut the reference to x,y,width,height, or to an element of the elements.json beside it (frames web writes one)"),crop:t.string().optional().describe("Cut the candidate to x,y,width,height before any resize"),encode:t.string().optional().describe("Draw the candidate through this encode first, as a platform serves it: codec:kbps, h264 or hevc (hevc:618)"),out:t.string().optional().describe("Where its files go, a path without extension; default under .allyhub/work/compare/"),params:T({resize:t.enum(["stretch","width","none"]).default(E.resize).describe("When sizes differ: stretch the candidate to the reference, scale it to its width, or compare the common area"),shift:t.number().int().min(0).max(32).default(E.shift).describe("Search the best offset within this many pixels each way")})}),positional:["reference","candidate"],output:t.looseObject({reference:t.string(),files:t.looseObject({side:t.string(),heatmap:t.string()})}),examples:["allyhub frames compare reference.png launch/film --at 2.5 --encode hevc:618","allyhub frames compare reference.png shot.webp --ref-crop cta","allyhub frames compare reference.png theirs.mp4 --at 3"]},async(e,i)=>{const s=i.cwd,l=e.params,n=e.candidate!==void 0&&(_(e.candidate)||C(e.candidate))?e.candidate:void 0,o=a=>({cwd:s,root:a,reference:e.reference,file:n,at:e.at===void 0?void 0:[e.at],part:e.part,refCrop:e.refCrop,crop:e.crop,encode:e.encode,out:e.out,options:{shift:l.shift,resize:l.resize}});if(n!==void 0){if(e.combo!==void 0||e.part!==void 0)throw p("bad-option","--combo and --part are a piece's: the candidate is a file.");const a=await O(o(await v(s,e.dir)),void 0).catch(m=>{throw F(m)});return{value:a,text:A(a)}}const d=await u(s,e.dir),{result:c,...r}=await h({...e,item:e.candidate},i,"render",a=>O(o(d),a));return{value:{...c,...b(r)},text:[A(c),...g(r)].join(`
8
- `)}}),framesWeb=f({name:"frames web",summary:"A web page's screenshot with its named elements' boxes in the image's pixels, for a screen demo",input:t.strictObject({url:t.string().describe("The page: an address, or an HTML file on this computer"),el:t.array(t.string()).optional().describe("An element to locate, name=selector (CSS, or text=<words>); [data-el] elements are found too"),click:t.array(t.string()).optional().describe("Selectors clicked in order before the shot (close a banner, open a dialog)"),full:t.boolean().default(!1).describe("The whole page, not one viewport"),out:t.string().optional().describe("Where the picture goes (a WebP), its boxes in <out>.elements.json beside it; default under .allyhub/work/pages/"),dir:k,size:t.string().default(`${String($.width)}x${String($.height)}`).describe("The viewport, WIDTHxHEIGHT in CSS pixels"),scale:t.number().min(1).max(4).default($.scale).describe("Image pixels per CSS pixel; 2 draws a high-density screen, sharp when a camera goes in"),wait:t.number().int().min(0).optional().describe("Milliseconds to wait after loading and clicking")}),positional:["url"],output:t.looseObject({out:t.string(),elementsFile:t.string()}),examples:["allyhub frames web https://example.com --el cta=text=Sign\\ up --scale 2 --out assets/media/home","allyhub frames web page.html --click '#accept' --full"]},async(e,i)=>{const s=i.cwd,[l,n]=J(e.size),o=await H({cwd:s,root:await v(s,e.dir),url:e.url,out:e.out,el:e.el,click:e.click,width:l,height:n,scale:e.scale,full:e.full,wait:e.wait});return{value:o,text:[`${o.out}: ${String(o.width)}×${String(o.height)}${o.scale===1?"":` (${String(o.scale)} image pixels per CSS pixel)`}, ${String(Object.keys(o.elements).length)} elements (${Object.keys(o.elements).join(", ")||"none"}) in ${o.elementsFile}`,...o.missing.length>0?[`Not found: ${o.missing.join(", ")} (the selector is wrong, or something must be opened with --click first).`]:[]].join(`
9
- `),exit:o.missing.length>0?j.failed:j.ok}}),FRAMES_COMMANDS=[frames,framesCuts,framesCompare,framesWeb];
2
+ import{z as t}from"zod";import{formatConsole as z,formatProblem as W}from"../text/index.js";import{COMPARE_DEFAULTS as M,CUT_REVIEW_DEFAULTS as I,cutLine as L,dbText as $,silenceText as _}from"@allyhub-next/measure";import{consoleJson as j}from"@allyhub-next/project";import{PAGE_CAPTURE_DEFAULTS as y}from"@allyhub-next/browser";import{EXIT as k}from"@allyhub-next/protocol";import{defineCommand as f}from"../command.js";import{dir as T}from"../fields.js";import{parameters as A}from"../parameters.js";import{projectRoot as u}from"../project.js";import{VERSION_FIELDS as v,commandError as F,withVersion as h}from"../version.js";import{compareText as O,comparePictures as C}from"./frames/compare.js";import{isPicture as R,isVideo as E,usage as p}from"./frames/common.js";import{cutSheets as B}from"./frames/cuts.js";import{fileFrames as H}from"./frames/file.js";import{pageShot as N}from"./frames/page.js";import{pieceMoments as U,stillsSheet as G}from"./frames/piece.js";import{sheetPicture as V}from"./frames/sheet.js";import{findSheet as J}from"./sheet.js";import{sizeOf as q}from"./scenery-input.js";function g(e){return[...e.problems.filter(a=>a.level==="error").map(W),...z(j(e.console))]}const b=e=>({problems:e.problems,...j(e.console)}),S=(e,l)=>u(e,l),X=t.strictObject({...v,item:t.string().optional().describe("The piece (its id, or a path into it; default the project's only one), a sheet, or a video file: a path ending in .mp4, .mov, .webm, .m4v, .qt, .mkv or .avi is a file"),range:t.string().optional().describe("A sheet's: what to draw, a sheet (Summary), a range (Summary!B3:D9, or B3:D9 on the first sheet), columns (A:C) or rows (1:20); default its sheets, from A1"),at:t.array(t.string()).optional().describe("Moments: seconds (from the start of --part when given) or anchors (@press, @/map a stretch's end, @press+0.2); a video file's are seconds. One is written as the frame itself, several are tiled. Without it, --part's still, or every part's still on one sheet"),part:t.string().optional().describe("The part --at, --from and --to count from; alone, its still"),from:t.number().optional().describe("A stretch of consecutive frames from this second (with --to), instead of --at"),to:t.number().optional().describe("The stretch's last second"),clip:t.string().optional().describe("Write the stretch as a small silent video, .gif, .mp4 or .webm by its extension; with --out, the grid too"),overlay:t.boolean().default(!1).describe("Draw over each tile the face boxes with ids, the person matte's outline, the covered areas and the text boxes (a deck's: each shape's box and name, and the lines nearly in line); places nothing. Alone, over every part's still"),beside:t.string().optional().describe("Another video file (a reference) whose frame at the same time goes on each tile's left"),grid:t.number().int().min(4).optional().describe("A video file at one --at: the frame at its own size with numbered lines every this many pixels"),out:t.string().optional().describe("Where the picture goes, always a WebP whatever the extension; default under .allyhub/work/frames/")});function K(e){const l=[["--combo",e.combo!==void 0],["--part",e.part!==void 0],["--beside",e.beside!==void 0],["--overlay",e.overlay]].filter(([,a])=>a).map(([a])=>a);if(l.length>0)throw p("bad-option",`${l.join(" and ")} ${l.length===1?"is":"are"} a piece's: a video file has no combos or parts.`)}export const frames=f({name:"frames",summary:"Pictures of a piece over time, drawn as the render draws them: every part's still on a sheet (default), a moment, a stretch tiled or as a clip, overlays; a sheet's cells, or a range of them; or any video file's frames",input:X,positional:["item"],output:t.looseObject({mode:t.enum(["sheet","frame","grid","clip"])}),examples:["allyhub frames launch/film","allyhub frames launch/film --at 2.5","allyhub frames launch/film --part hook --from 0 --to 1 --clip hook.gif","allyhub frames launch/film --at 1,2,3 --overlay","allyhub frames reference.mp4 --at 0,1,2","allyhub frames reference.mp4 --at 3 --grid 50","allyhub frames finance/budget --range 'Summary!A1:F20'"]},async(e,l)=>{const a=l.cwd;if(e.item!==void 0&&E(e.item)){K(e);const r=await H({cwd:a,root:await S(a,e.dir),file:e.item,at:e.at,from:e.from,to:e.to,clip:e.clip,out:e.out,grid:e.grid}).catch(P=>{throw F(P)}),c=r.video,w=`${r.file} · ${c.duration.toFixed(2)} s · ${String(c.width)}×${String(c.height)} · ${String(c.fps)} fps`,x="clip"in r&&r.clip?`${r.clip.out} (${r.clip.type}, ${String(r.clip.frames)} frames at ${String(r.clip.fps)} fps, no sound)`:void 0;return{value:r,text:[w,..."out"in r?[`${r.out}${"tiles"in r?` (${String(r.tiles.length)} moments in ${String(r.cols)} columns)`:""}`]:[],...x?[x]:[]].join(`
3
+ `)}}if(e.grid!==void 0)throw p("bad-option","--grid draws a video file's frame at its own size: give the file.");const d=await u(a,e.dir);if(e.item!==void 0&&await J(d,a,e.item)!==void 0){const r=await V({cwd:a,root:d,item:e.item,range:e.range,out:e.out});return{value:r,text:[r.out,...r.cut].join(`
4
+ `)}}if(e.range!==void 0)throw p("bad-option","--range is a sheet's: name the sheet.");const i=e.at!==void 0||e.part!==void 0||e.from!==void 0||e.to!==void 0;if(!i&&(e.clip!==void 0||e.beside!==void 0))throw p("bad-option","--clip and --beside draw moments: give --at, --part, or --from and --to.");if(!i&&!e.overlay){const{result:r,...c}=await h(e,l,"render",w=>G(w,{cwd:a,root:d,out:e.out}));return{value:{...r,...b(c)},text:[`${r.out} (${r.piece} · ${r.format} · ${String(r.parts.length)} ${"slides"in r?"slide":"part"}${r.parts.length===1?"":"s"})`,...g(c)].join(`
5
+ `)}}const n=!i&&e.overlay,{result:o,...m}=await h(e,l,"render",r=>U(r,{cwd:a,root:d,at:n?r.timeline.parts.map(c=>String(c.still)):e.at,part:e.part,from:e.from,to:e.to,clip:e.clip,out:e.out,overlay:e.overlay,beside:e.beside})),s=[];if(o.mode==="frame"&&s.push(`${o.out} (${o.piece} · ${o.format} · ${o.part} · ${o.t.toFixed(2)} s)`),o.mode==="grid"){s.push(`${o.out} (${o.piece} · ${String(o.tiles.length)} moments in ${String(o.cols)} columns)`,` ${o.tiles.map(c=>`${c.t.toFixed(o.stretch?3:2)} ${c.part}`).join(" · ")}`);const r=[...new Set(o.tiles.flatMap(c=>c.overlay?.missing??[]))];r.length>0&&s.push(` Not measured: ${r.join(", ")}.`)}return o.stretch&&s.push(` Stretch ${o.stretch.from.toFixed(3)}–${o.stretch.to.toFixed(3)} s, one frame in ${String(o.stretch.every)}: ${String(o.stretch.frames)} frames.`),"clip"in o&&o.clip&&s.push(`${o.clip.out} (${o.clip.type}, ${String(o.clip.frames)} frames at ${String(o.clip.fps)} fps, no sound)`),{value:{...o,...b(m)},text:[...s,...g(m)].join(`
6
+ `)}}),framesCuts=f({name:"frames cuts",summary:"A review sheet per cut of a video (a cut take's jumps, part joins, a scenery camera's cuts): frames around it, waveform and level, the words each side, the sound at it",input:t.strictObject({...v,part:t.string().optional().describe("Only this part's cuts and its joins"),out:t.string().optional().describe("The folder the sheets go in; default .allyhub/work/cuts/"),params:A({span:t.number().positive().max(10).default(I.span).describe("Seconds shown on each side of a cut")})}),positional:["item"],output:t.looseObject({out:t.string(),cuts:t.array(t.looseObject({sheet:t.string()}))}),examples:["allyhub frames cuts launch/film","allyhub frames cuts launch/film --part hook"]},async(e,l)=>{const a=l.cwd,d=await u(a,e.dir),{result:i,...n}=await h(e,l,"render",s=>B(s,{cwd:a,root:d,part:e.part,out:e.out,review:{span:e.params.span}})),o=i.part===void 0?`${String(i.cuts.length)} cut${i.cuts.length===1?"":"s"}`:`${String(i.cuts.length)} of ${String(i.total)} cuts (part ${i.part} and its joins)`,m=[`${i.piece} · ${i.format} · ${o}; silence is sound under ${String(i.threshold)} dBFS`];for(const s of i.cuts){const r=s.sound?`level ${$(s.sound.levelDb)} / around ${$(s.sound.aroundDb)} dBFS, peak ${$(s.sound.peakDb)}, step ${s.sound.jumpDb<0?"−":"+"}${Math.abs(s.sound.jumpDb).toFixed(1)} dB`:"no sound";m.push(`${String(s.index).padStart(3)} ${s.t.toFixed(3).padStart(7)} s ${s.kind.padEnd(6)} ${L(s)}`,` silence at the cut: ${_(s.silence)} · ${r}`,` “${s.said.before}” | “${s.said.after}”${s.across?` · across the cut: “${s.across}”`:""}`,` ${s.sheet}`)}return{value:{...i,...b(n)},text:[...m,...g(n)].join(`
7
+ `)}});const D=M;export const framesCompare=f({name:"frames compare",summary:"How a candidate picture differs from a reference, as numbers (ΔE, channels, SSIM, levels, grain, edges, regions) with a heatmap and a side-by-side: a piece's moment, a picture file or a video file's frame",input:t.strictObject({reference:t.string().describe("The reference picture (PNG, WebP, JPEG…)"),candidate:t.string().optional().describe("A piece (its id, or a path into it; default the project's only one) at --at or --part's still; or a file by its extension: a picture (.png, .jpg, .webp…), or a video file's frame at --at (.mp4, .mov, .webm…)"),combo:v.combo,dir:T,at:t.string().optional().describe("The moment: seconds (from the start of --part when given) or an anchor of the piece; a video file's are seconds (default 0)"),part:t.string().optional().describe("The piece's part --at counts from; alone, its still"),refCrop:t.string().optional().describe("Cut the reference to x,y,width,height, or to an element of the elements.json beside it (frames web writes one)"),crop:t.string().optional().describe("Cut the candidate to x,y,width,height before any resize"),encode:t.string().optional().describe("Draw the candidate through this encode first, as a platform serves it: codec:kbps, h264 or hevc (hevc:618)"),out:t.string().optional().describe("Where its files go, a path without extension; default under .allyhub/work/compare/"),params:A({resize:t.enum(["stretch","width","none"]).default(D.resize).describe("When sizes differ: stretch the candidate to the reference, scale it to its width, or compare the common area"),shift:t.number().int().min(0).max(32).default(D.shift).describe("Search the best offset within this many pixels each way")})}),positional:["reference","candidate"],output:t.looseObject({reference:t.string(),files:t.looseObject({side:t.string(),heatmap:t.string()})}),examples:["allyhub frames compare reference.png launch/film --at 2.5 --encode hevc:618","allyhub frames compare reference.png shot.webp --ref-crop cta","allyhub frames compare reference.png theirs.mp4 --at 3"]},async(e,l)=>{const a=l.cwd,d=e.params,i=e.candidate!==void 0&&(R(e.candidate)||E(e.candidate))?e.candidate:void 0,n=r=>({cwd:a,root:r,reference:e.reference,file:i,at:e.at===void 0?void 0:[e.at],part:e.part,refCrop:e.refCrop,crop:e.crop,encode:e.encode,out:e.out,options:{shift:d.shift,resize:d.resize}});if(i!==void 0){if(e.combo!==void 0||e.part!==void 0)throw p("bad-option","--combo and --part are a piece's: the candidate is a file.");const r=await C(n(await S(a,e.dir)),void 0).catch(c=>{throw F(c)});return{value:r,text:O(r)}}const o=await u(a,e.dir),{result:m,...s}=await h({...e,item:e.candidate},l,"render",r=>C(n(o),r));return{value:{...m,...b(s)},text:[O(m),...g(s)].join(`
8
+ `)}}),framesWeb=f({name:"frames web",summary:"A web page's screenshot with its named elements' boxes in the image's pixels, for a screen demo",input:t.strictObject({url:t.string().describe("The page: an address, or an HTML file on this computer"),el:t.array(t.string()).optional().describe("An element to locate, name=selector (CSS, or text=<words>); [data-el] elements are found too"),click:t.array(t.string()).optional().describe("Selectors clicked in order before the shot (close a banner, open a dialog)"),full:t.boolean().default(!1).describe("The whole page, not one viewport"),out:t.string().optional().describe("Where the picture goes (a WebP), its boxes in <out>.elements.json beside it; default under .allyhub/work/pages/"),dir:T,size:t.string().default(`${String(y.width)}x${String(y.height)}`).describe("The viewport, WIDTHxHEIGHT in CSS pixels"),scale:t.number().min(1).max(4).default(y.scale).describe("Image pixels per CSS pixel; 2 draws a high-density screen, sharp when a camera goes in"),wait:t.number().int().min(0).optional().describe("Milliseconds to wait after loading and clicking")}),positional:["url"],output:t.looseObject({out:t.string(),elementsFile:t.string()}),examples:["allyhub frames web https://example.com --el cta=text=Sign\\ up --scale 2 --out assets/media/home","allyhub frames web page.html --click '#accept' --full"]},async(e,l)=>{const a=l.cwd,[d,i]=q(e.size),n=await N({cwd:a,root:await S(a,e.dir),url:e.url,out:e.out,el:e.el,click:e.click,width:d,height:i,scale:e.scale,full:e.full,wait:e.wait});return{value:n,text:[`${n.out}: ${String(n.width)}×${String(n.height)}${n.scale===1?"":` (${String(n.scale)} image pixels per CSS pixel)`}, ${String(Object.keys(n.elements).length)} elements (${Object.keys(n.elements).join(", ")||"none"}) in ${n.elementsFile}`,...n.missing.length>0?[`Not found: ${n.missing.join(", ")} (the selector is wrong, or something must be opened with --click first).`]:[]].join(`
9
+ `),exit:n.missing.length>0?k.failed:k.ok}}),FRAMES_COMMANDS=[frames,framesCuts,framesCompare,framesWeb];
@@ -1,2 +1,2 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{add as o,addSearch as r}from"./add.js";import{align as m}from"./align.js";import{audio as e,audioRecording as i}from"./audio.js";import{authLogin as t,authStatus as p}from"./auth.js";import{orgsList as f}from"./orgs.js";import{check as s}from"./check.js";import{dev as a}from"./dev.js";import{doctor as d}from"./doctor.js";import{FRAMES_COMMANDS as C}from"./frames.js";import{INSPECT_COMMANDS as l}from"./inspect/index.js";import{model as S,modelCapabilities as c}from"./model.js";import{slidesCapabilities as M,slidesImport as h}from"./slides.js";import{reference as n,referenceCompare as O,referenceSetCommand as D}from"./reference.js";import{render as E}from"./render.js";import{SCENERY_COMMANDS as N}from"./scenery.js";import{sheet as u,sheetCalc as A,sheetCapabilities as R,sheetDiff as _,sheetImport as g,sheetTrace as b}from"./sheet.js";import{siteMediaCommand as k}from"./site.js";import{skills as w,skillsShow as I}from"./skills.js";import{CLOUD_SOURCE as L,upload as U}from"./cloud-tools.js";import{voice as v}from"./voice.js";import{words as x,wordsEdits as T}from"./words.js";export const COMMANDS=[s,...l,E,...C,e,i,u,A,b,_,R,g,a,o,r,w,I,k,x,T,m,n,O,D,...N,S,c,M,h,t,p,f,U,v,d],COMMAND_SOURCES=[L];
2
+ import{add as o,addSearch as r}from"./add.js";import{align as m}from"./align.js";import{audio as t,audioRecording as e}from"./audio.js";import{authLogin as i,authStatus as p}from"./auth.js";import{orgsList as s}from"./orgs.js";import{check as f}from"./check.js";import{dev as a}from"./dev.js";import{doctor as d}from"./doctor.js";import{FRAMES_COMMANDS as C}from"./frames.js";import{INSPECT_COMMANDS as l}from"./inspect/index.js";import{model as S,modelCapabilities as c}from"./model.js";import{slidesCapabilities as h,slidesImport as M}from"./slides.js";import{reference as n,referenceCompare as D,referenceSetCommand as O}from"./reference.js";import{render as u}from"./render.js";import{SCENERY_COMMANDS as E}from"./scenery.js";import{sheet as N,sheetCalc as A,sheetCapabilities as R,sheetDiff as _,sheetImport as g,sheetTrace as L}from"./sheet.js";import{skills as b,skillsShow as k}from"./skills.js";import{CLOUD_SOURCE as v,upload as w}from"./cloud-tools.js";import{siteDeploy as I,siteLive as U,siteStatus as x}from"./site.js";import{voice as T}from"./voice.js";import{words as y,wordsEdits as F}from"./words.js";export const COMMANDS=[f,...l,u,...C,t,e,N,A,L,_,R,g,a,o,r,b,k,y,F,m,n,D,O,...E,S,c,h,M,i,p,s,w,T,I,x,U,d],COMMAND_SOURCES=[v];
@@ -1,3 +1,3 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{z as t}from"zod";import{consoleJson as m,momentsIn as p,versionLabel as l}from"@allyhub-next/project";import{EXIT as i}from"@allyhub-next/protocol";import{FACT_KINDS as d,countFacts as f,isFactKind as c}from"@allyhub-next/video-core";import{CommandError as s}from"../../command.js";import{formatConsole as u,formatFacts as h,formatProblem as b}from"../../text/index.js";import{known as x}from"../../version.js";export const plural=(e,o)=>`${String(e)} ${o}${e===1?"":"s"}`,sec=e=>e.toFixed(2),boxText=e=>`[${e.join(",")}]`,HEAD="measurements for you to judge, not problems. Boxes are [x,y,w,h] in pixels; --json has every one.",STRETCH={part:t.string().optional().describe("Only this part"),from:t.number().min(0).optional().describe("From this second of the video"),to:t.number().min(0).optional().describe("Up to this second of the video")},MOMENTS={at:t.array(t.string()).optional().describe("At these moments: seconds (from --part's start when given) or anchors (@press, @/map, @press+0.2)"),every:t.number().positive().optional().describe("Every this many seconds through the stretch (--part, or --from to --to, else all of it)")},kind=t.array(t.string()).optional().describe(`Only facts of these kinds: ${Object.keys(d).join(", ")}`),all=e=>t.boolean().default(!1).describe(`Every finding on a line of its own${e===void 0?"":`, and ${e}`}`);export function kindsOf(e){if(e!==void 0)return e.map(o=>{if(!c(o))throw new s("bad-kind",`There is no kind of fact ${o}.`,{exit:i.usage,hint:`Kinds: ${Object.keys(d).join(", ")}.`});return o})}export function momentsOf(e,o){if(e.at!==void 0&&e.every!==void 0)throw new s("bad-option","--at and --every do not go together.",{exit:i.usage});const n=e.at?.map(r=>{const a=Number(r.replace(/s$/u,""));return r.trim().startsWith("@")||!Number.isFinite(a)?r:a});return x(()=>p(o.timeline,{...n===void 0?{}:{at:n},...e.every===void 0?{}:{every:e.every},part:e.part,from:e.from,to:e.to},o.target))}export function mustBeVideo(e,o){if(e.piece.kind!=="video")throw new s("bad-option",`${l(e.target)} is not a video: ${o}.`,{exit:i.usage})}export function pageLines(e){const o=e.problems.filter(n=>n.level==="error");return[...o.length>0?["Must fix (facts may be missing where they are):",...o.map(b)]:[],...u(m(e.console))]}export const pageJson=e=>({problems:e.problems.filter(o=>o.level==="error"),...m(e.console)});export function factsResult(e,o,n,r=[]){return{value:{facts:e,counts:f(e),total:n.total??e.length,...n.extra,...pageJson(o)},text:[`${plural(e.length,"fact")} measured now: ${HEAD}`,...h(e,{all:n.all}),...r,...pageLines(o)].join(`
2
+ import{z as t}from"zod";import{consoleJson as m,momentsIn as p,versionLabel as l}from"@allyhub-next/project";import{EXIT as i}from"@allyhub-next/protocol";import{FACT_KINDS as d,countFacts as f,isFactKind as c}from"@allyhub-next/video-core";import{CommandError as s}from"../../command.js";import{formatConsole as u,formatFacts as h,formatProblem as b}from"../../text/index.js";import{known as x}from"../../version.js";export const plural=(e,o)=>`${String(e)} ${o}${e===1?"":"s"}`,sec=e=>e.toFixed(2),boxText=e=>`[${e.join(",")}]`,HEAD="measurements for you to judge, not problems. Boxes are [x,y,w,h], in pixels (a deck's in points); --json has every one.",STRETCH={part:t.string().optional().describe("Only this part"),from:t.number().min(0).optional().describe("From this second of the video"),to:t.number().min(0).optional().describe("Up to this second of the video")},MOMENTS={at:t.array(t.string()).optional().describe("At these moments: seconds (from --part's start when given) or anchors (@press, @/map, @press+0.2)"),every:t.number().positive().optional().describe("Every this many seconds through the stretch (--part, or --from to --to, else all of it)")},kind=t.array(t.string()).optional().describe(`Only facts of these kinds: ${Object.keys(d).join(", ")}`),all=e=>t.boolean().default(!1).describe(`Every finding on a line of its own${e===void 0?"":`, and ${e}`}`);export function kindsOf(e){if(e!==void 0)return e.map(o=>{if(!c(o))throw new s("bad-kind",`There is no kind of fact ${o}.`,{exit:i.usage,hint:`Kinds: ${Object.keys(d).join(", ")}.`});return o})}export function momentsOf(e,o){if(e.at!==void 0&&e.every!==void 0)throw new s("bad-option","--at and --every do not go together.",{exit:i.usage});const n=e.at?.map(r=>{const a=Number(r.replace(/s$/u,""));return r.trim().startsWith("@")||!Number.isFinite(a)?r:a});return x(()=>p(o.timeline,{...n===void 0?{}:{at:n},...e.every===void 0?{}:{every:e.every},part:e.part,from:e.from,to:e.to},o.target))}export function mustBeVideo(e,o){if(e.piece.kind!=="video")throw new s("bad-option",`${l(e.target)} is not a video: ${o}.`,{exit:i.usage})}export function pageLines(e){const o=e.problems.filter(n=>n.level==="error");return[...o.length>0?["Must fix (facts may be missing where they are):",...o.map(b)]:[],...u(m(e.console))]}export const pageJson=e=>({problems:e.problems.filter(o=>o.level==="error"),...m(e.console)});export function factsResult(e,o,n,r=[]){return{value:{facts:e,counts:f(e),total:n.total??e.length,...n.extra,...pageJson(o)},text:[`${plural(e.length,"fact")} measured now: ${HEAD}`,...h(e,{all:n.all}),...r,...pageLines(o)].join(`
3
3
  `)}}
@@ -1,2 +1,2 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{z as r}from"zod";import{measuredFacts as u}from"@allyhub-next/measure";import{DECK_FACT_DEFAULTS as c,deckFacts as h}from"@allyhub-next/slides-core";import{stretchOf as y}from"@allyhub-next/project";import{ffmpegOf as b}from"@allyhub-next/render";import{filterFacts as k}from"@allyhub-next/video-core";import{defineCommand as w}from"../../command.js";import{textOnScreen as g}from"../../text/index.js";import{VERSION_FIELDS as x,known as v,withVersion as O}from"../../version.js";import{MOMENTS as S,STRETCH as $,all as A,boxText as E,factsResult as F,kind as T,kindsOf as C,momentsOf as L,sec as N}from"./common.js";export const inspectLayout=w({name:"inspect layout",summary:"One version's layout measured now, at its measured moments or at --at / --every; --texts lists every text block with its fonts",input:r.strictObject({...x,...S,...$,texts:r.boolean().default(!1).describe("List every text block at every moment, with its box and fonts"),within:r.number().positive().optional().describe(`A deck: lines up to this many points apart and not in line are near-alignment (default ${String(c.within)})`),drift:r.number().nonnegative().optional().describe(`A deck: places further apart than this, in points, are placement-drift (default ${String(c.drift)})`),level:r.array(r.enum(["master","layout","slide"])).optional().describe("A deck: measure only shapes of these levels (default every one): slide leaves out what a master or a layout draws on every slide"),except:r.array(r.string()).optional().describe("A deck: leave shapes of these names out of every fact, * for any letters (tick-*)"),room:r.string().regex(/^[\d.]+,[\d.]+$/u).optional().describe("A deck's read-size: a room as its screen's width and its farthest seat, in metres (3,12); without it no room is measured"),kind:T,all:A()}),positional:["item"],output:r.looseObject({}),examples:["allyhub inspect layout launch/film --at 1.5,@press --texts","allyhub inspect layout launch/film --every 0.5 --part hook","allyhub inspect layout launch/deck --kind near-alignment --within 10","allyhub inspect layout launch/deck --level slide --except 'tick-*'"]},async(e,d)=>{const s=await O(e,d,"render",async t=>{const n=t.timeline,{part:l}=v(()=>y(n,e)),o=await t.version.measure(L(e,t)),m=[...t.version.summary?.facts??[],...await u(o,n,t.target,{root:t.prepared.root,media:t.prepared.media,ffmpeg:await b()},n.profile?.label),...o.deck?h(o.deck,{width:o.width,height:o.height},{piece:t.target.piece,output:t.target.output,combo:t.target.combo,format:t.target.format},{...e.within===void 0?{}:{within:e.within},...e.drift===void 0?{}:{drift:e.drift},...e.level===void 0?{}:{levels:e.level},...e.except===void 0?{}:{except:e.except},...e.room===void 0?{}:{room:{screen:Number(e.room.split(",")[0]),distance:Number(e.room.split(",")[1])}}}):[]];return{facts:k(m,{kinds:C(e.kind),part:e.part}),total:m.length,moments:e.texts?o.moments.filter(i=>!l||i.part===l.key).map(i=>({t:i.t,part:i.part,...i.face?{face:i.face}:{},texts:i.texts})):void 0}}),{facts:p,total:f,moments:a}=s.result;return F(p,s,{all:e.all,total:f,...a?{extra:{moments:a}}:{}},(a??[]).map(t=>` ${N(t.t)} ${t.part}${t.face?` face ${E(t.face)}`:""}: ${t.texts.map(g).join("; ")||"(no text)"}`))});
2
+ import{z as r}from"zod";import{measuredFacts as u}from"@allyhub-next/measure";import{DECK_FACT_DEFAULTS as c,deckFacts as h}from"@allyhub-next/slides-core";import{stretchOf as y}from"@allyhub-next/project";import{ffmpegOf as b}from"@allyhub-next/render";import{filterFacts as k}from"@allyhub-next/video-core";import{defineCommand as w}from"../../command.js";import{textOnScreen as g}from"../../text/index.js";import{VERSION_FIELDS as x,known as v,withVersion as O}from"../../version.js";import{MOMENTS as S,STRETCH as $,all as A,boxText as E,factsResult as F,kind as T,kindsOf as C,momentsOf as L,sec as N}from"./common.js";export const inspectLayout=w({name:"inspect layout",summary:"One version's layout measured now, at its measured moments or at --at / --every; --texts lists every text block with its fonts",input:r.strictObject({...x,...S,...$,texts:r.boolean().default(!1).describe("List every text block at every moment, with its box and fonts"),within:r.number().positive().optional().describe(`A deck: lines up to this many points apart and not in line are near-alignment (default ${String(c.within)})`),drift:r.number().nonnegative().optional().describe(`A deck: places further apart than this, in points, are placement-drift (default ${String(c.drift)})`),level:r.array(r.enum(["master","layout","slide"])).optional().describe("A deck: measure only shapes of these levels (default every one): slide leaves out what a master or a layout draws on every slide"),except:r.array(r.string()).optional().describe("A deck: leave shapes of these names out of every fact, * for any letters (tick-*)"),room:r.string().regex(/^[\d.]+,[\d.]+$/u).optional().describe("A deck's read-size: a room as its screen's width and its farthest seat, in metres (3,12); without it no room is measured"),kind:T,all:A()}),positional:["item"],output:r.looseObject({}),examples:["allyhub inspect layout launch/film --at 1.5,@press --texts","allyhub inspect layout launch/film --every 0.5 --part hook","allyhub inspect layout launch/deck --kind near-alignment --within 10","allyhub inspect layout launch/deck --level slide --except 'tick-*'"]},async(e,d)=>{const s=await O(e,d,"render",async t=>{const n=t.timeline,{part:l}=v(()=>y(n,e)),o=await t.version.measure(L(e,t)),m=[...t.version.summary?.facts??[],...o.deck?h(o.deck,{width:o.width,height:o.height},{piece:t.target.piece,output:t.target.output,combo:t.target.combo,format:t.target.format},{...e.within===void 0?{}:{within:e.within},...e.drift===void 0?{}:{drift:e.drift},...e.level===void 0?{}:{levels:e.level},...e.except===void 0?{}:{except:e.except},...e.room===void 0?{}:{room:{screen:Number(e.room.split(",")[0]),distance:Number(e.room.split(",")[1])}}}):await u(o,n,t.target,{root:t.prepared.root,media:t.prepared.media,ffmpeg:await b()},n.profile?.label)];return{facts:k(m,{kinds:C(e.kind),part:e.part}),total:m.length,moments:e.texts?o.moments.filter(i=>!l||i.part===l.key).map(i=>({t:i.t,part:i.part,...i.face?{face:i.face}:{},texts:i.texts})):void 0}}),{facts:p,total:f,moments:a}=s.result;return F(p,s,{all:e.all,total:f,...a?{extra:{moments:a}}:{}},(a??[]).map(t=>` ${N(t.t)} ${t.part}${t.face?` face ${E(t.face)}`:""}: ${t.texts.map(g).join("; ")||"(no text)"}`))});
@@ -1,3 +1,3 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{join as x,resolve as y}from"node:path";import{z as t}from"zod";import{formatConsole as w,formatProblem as v}from"../text/index.js";import{exportProject as k}from"@allyhub-next/export";import{SHARE_ENCODE as n}from"@allyhub-next/render";import{consoleJson as p}from"@allyhub-next/project";import{OUT_DIR as $}from"@allyhub-next/formats";import{EXIT as c}from"@allyhub-next/protocol";import{defineCommand as P}from"../command.js";import{parameters as O}from"../parameters.js";import{projectRoot as S}from"../project.js";import{combosOf as j,commandError as B}from"../version.js";import{dir as A,indexing as D}from"../fields.js";const N={codec:t.enum(["h264","h265"]).default("h264").describe("The mp4's video codec; h265 is smaller"),crf:t.number().int().min(0).max(63).optional().describe(`Quality, lower is better: default ${String(n.crf)} for an mp4, ready to share (a platform profile's format its own), 30 for a webm`),maxBitrate:t.number().int().min(0).max(5e5).optional().describe(`An mp4's most video bitrate, kbit/s, 0 for none: default ${String(n.maxKbps)} at 1080p ${String(n.fps)} fps, scaled by the frame's pixels and the frames a second (16000 at 1080p 60, 32000 at 4K 30), so the file is ready to share; a platform profile's format its own`),audioBitrate:t.number().int().min(32).max(512).optional().describe("The sound's bitrate, kbit/s: default 192 (AAC in an mp4), 160 (Opus in a webm); a mov keeps PCM"),steps:t.boolean().default(!1).describe("A deck's pdf, png and pptx: a page, a file or a slide per step of each page, not only its last"),pptx:t.enum(["native","picture","editable"]).default("native").describe("A deck's pptx: native, PowerPoint's own model (the deck's masters, layouts, placeholders, shapes, text, pictures, videos and notes, a component as its picture); picture, each slide a picture of the page; or editable, the page's picture without its text under a text box per block of text")},T=(o,i)=>`${String(o)} ${i}${o===1?"":"s"}`;export const render=P({name:"render",summary:"The files: a video, its frames, subtitles, cover and mastered mix; a batch's table of ads; a deck's PDF, PPTX and PNGs; a doc's PDF and Markdown; a sheet's Excel workbook with live formulas, PDF, PNG, CSV, Markdown and JSON; a 3D model's GLB",input:t.strictObject({items:t.array(t.string()).optional().describe("Only these items: an id, a path into one, or a folder of items; default every one"),combo:t.array(t.string()).optional().describe("Only the combos matching name=value pairs joined with commas (lang=zh-cn,hook=b), or a combo's id (c03)"),type:t.array(t.string()).optional().describe("File types: mp4, mov, webm, gif, png, srt, vtt (cues cut as the piece's captions layer cuts them, else by default), cover, wav (the mix, mastered as the render masters it: 48 kHz, 16 bits, the film's length), pdf, pptx; csv for a piece with slots, its table of ads (<piece>/ads.csv: a row per ad with its combo, picks, length, file, name and generated media); a doc's pdf, docx, png, md; a sheet's xlsx (every sheet, formulas live with their values cached), pdf, png, csv, md, json; a 3D model's glb. Default mp4 for a video, pdf for a deck and a doc, xlsx for a sheet, glb for a model; a type an item does not have is skipped"),out:t.string().optional().describe("The folder the files go in; default .allyhub/out"),name:t.string().optional().describe("Name a video's or deck's files <name>.<ext> in its folder of the output, with what tells its versions apart before the extension when there are several (<name>.zh-cn.mp4, <name>.c03.mp4); default <output>.<combo>.<ext>"),params:O(N),dir:A}),positional:["items"],output:t.looseObject({out:t.string(),files:t.array(t.looseObject({name:t.string(),path:t.string(),type:t.string()})),failed:t.array(t.looseObject({name:t.string(),code:t.string()}))}),examples:["allyhub render","allyhub render launch/film --type mp4,srt","allyhub render launch/film --type wav","allyhub render ads/tidyform --type csv","allyhub render launch/plan --type pdf,md","allyhub render finance/budget --type xlsx,pdf","allyhub render launch/deck --type pptx --param pptx=editable","allyhub render --combo lang=zh-cn --param crf=16","allyhub render launch/film --name launch-film --param max-bitrate=0"]},async(o,i)=>{const d=await S(i.cwd,o.dir),f=y(i.cwd,o.out??x(d,$)),r=o.params,h={codec:r.codec,...r.crf===void 0?{}:{crf:r.crf},...r.maxBitrate===void 0?{}:{maxBitrate:r.maxBitrate},...r.audioBitrate===void 0?{}:{audioBitrate:r.audioBitrate}};let l=0,a;try{a=await k({root:d,out:f,...o.items===void 0?{}:{items:o.items},combos:j(o),...o.type===void 0?{}:{types:o.type},...o.name===void 0?{}:{name:o.name},encode:h,...r.steps?{steps:!0}:{},...r.pptx==="native"?{}:{pptx:r.pptx},index:D(i.env),log:e=>{i.progress(e)},onProgress:e=>{const s=Math.floor(e*10);s<=l||s>=10||(l=s,i.progress(`${String(s*10)}%`))},signal:i.signal})}catch(e){throw B(e)}const u=e=>e?` (${e.integrated.toFixed(1)} LUFS, true peak ${e.truePeak===void 0?"–":e.truePeak.toFixed(1)} dBTP)`:"",b=a.problems.filter(e=>e.level==="error"),m=a.files.flatMap(e=>e.files.length>1?e.files.map(s=>` ${s}`):[` ${e.path}${u(e.loudness)}`]),g=[`${T(m.length,"file")} in ${a.out}:`,...m,...a.failed.length>0?["Not made:",...a.failed.map(e=>` ${e.name}: ${e.message}${e.hint?` ${e.hint}`:""}`)]:[],...a.unindexed.map(e=>`Not indexed, drawn the fallback way: ${e.file} (${e.error})`),...new Set(a.files.flatMap(e=>(e.fontsLeft??[]).map(s=>`Not in the file: ${s.font} (${s.why}); PowerPoint shows another font where it is not installed.`))),...b.map(v),...w(p(a.console))];return{value:{out:a.out,files:a.files.map(e=>({...e})),failed:a.failed.map(e=>({...e})),problems:a.problems,...a.unindexed.length>0?{unindexed:a.unindexed}:{},...p(a.console)},text:g.join(`
2
+ import{join as y,resolve as x}from"node:path";import{z as t}from"zod";import{formatConsole as v,formatProblem as w}from"../text/index.js";import{exportProject as k}from"@allyhub-next/export";import{SHARE_ENCODE as n}from"@allyhub-next/render";import{consoleJson as p}from"@allyhub-next/project";import{OUT_DIR as $}from"@allyhub-next/formats";import{EXIT as c}from"@allyhub-next/protocol";import{defineCommand as P}from"../command.js";import{parameters as j}from"../parameters.js";import{projectRoot as O}from"../project.js";import{combosOf as S,commandError as A}from"../version.js";import{dir as B,indexing as N}from"../fields.js";const T={codec:t.enum(["h264","h265"]).default("h264").describe("The mp4's video codec; h265 is smaller"),crf:t.number().int().min(0).max(63).optional().describe(`Quality, lower is better: default ${String(n.crf)} for an mp4, ready to share (a platform profile's format its own), 30 for a webm`),maxBitrate:t.number().int().min(0).max(5e5).optional().describe(`An mp4's most video bitrate, kbit/s, 0 for none: default ${String(n.maxKbps)} at 1080p ${String(n.fps)} fps, scaled by the frame's pixels and the frames a second (16000 at 1080p 60, 32000 at 4K 30), so the file is ready to share; a platform profile's format its own`),audioBitrate:t.number().int().min(32).max(512).optional().describe("The sound's bitrate, kbit/s: default 192 (AAC in an mp4), 160 (Opus in a webm); a mov keeps PCM"),steps:t.boolean().default(!1).describe("A deck's pdf, png and pptx: a page, a file or a slide per step of each page, not only its last"),values:t.enum(["data","shown"]).optional().describe("A sheet's csv, json and md: each value as data (a date 2026-01-15, a time 09:30, a duration 36:00, a number to 15 digits; csv's and json's default) or as its format shows it (15 Jan 2026, $1,200.00; md's default)"),bom:t.boolean().default(!0).describe("A sheet's csv starts with a UTF-8 byte-order mark, by which Excel reads its letters right (é, €, 中文); false for a tool that does not expect one"),pptx:t.enum(["native","picture"]).default("native").describe("A deck's pptx: native, PowerPoint's own model, editable there (the deck's masters, layouts, placeholders, shapes, text, pictures, videos and notes, a component as its picture); or picture, each slide a picture of the page")},D=(o,i)=>`${String(o)} ${i}${o===1?"":"s"}`;export const render=P({name:"render",summary:"The files: a video, its frames, subtitles, cover and mastered mix; a batch's table of ads; a deck's PDF, PPTX and PNGs; a doc's PDF and Markdown; a sheet's Excel workbook with live formulas, PDF, PNG, CSV, Markdown and JSON; a 3D model's GLB",input:t.strictObject({items:t.array(t.string()).optional().describe("Only these items: an id, a path into one, or a folder of items; default every one"),combo:t.array(t.string()).optional().describe("Only the combos matching name=value pairs joined with commas (lang=zh-cn,hook=b), or a combo's id (c03)"),type:t.array(t.string()).optional().describe("File types: mp4, mov, webm, gif, png, srt, vtt (cues cut as the piece's captions layer cuts them, else by default), cover, wav (the mix, mastered as the render masters it: 48 kHz, 16 bits, the film's length), pdf, pptx; csv for a piece with slots, its table of ads (<piece>/ads.csv: a row per ad with its combo, picks, length, file, name and generated media); a doc's pdf, docx, png, md; a sheet's xlsx (every sheet, formulas live with their values cached), pdf, png, csv, md, json; a 3D model's glb. Default mp4 for a video, pdf for a deck and a doc, xlsx for a sheet, glb for a model; a type an item does not have is skipped"),out:t.string().optional().describe("The folder the files go in; default .allyhub/out"),name:t.string().optional().describe("Name a video's or deck's files <name>.<ext> in its folder of the output, with what tells its versions apart before the extension when there are several (<name>.zh-cn.mp4, <name>.c03.mp4); default <output>.<combo>.<ext>"),params:j(T),dir:B}),positional:["items"],output:t.looseObject({out:t.string(),files:t.array(t.looseObject({name:t.string(),path:t.string(),type:t.string()})),failed:t.array(t.looseObject({name:t.string(),code:t.string()}))}),examples:["allyhub render","allyhub render launch/film --type mp4,srt","allyhub render launch/film --type wav","allyhub render ads/tidyform --type csv","allyhub render launch/plan --type pdf,md","allyhub render finance/budget --type xlsx,pdf","allyhub render finance/budget --type csv --param bom=false","allyhub render launch/deck --type pptx --param pptx=picture","allyhub render --combo lang=zh-cn --param crf=16","allyhub render launch/film --name launch-film --param max-bitrate=0"]},async(o,i)=>{const d=await O(i.cwd,o.dir),f=x(i.cwd,o.out??y(d,$)),s=o.params,h={codec:s.codec,...s.crf===void 0?{}:{crf:s.crf},...s.maxBitrate===void 0?{}:{maxBitrate:s.maxBitrate},...s.audioBitrate===void 0?{}:{audioBitrate:s.audioBitrate}};let l=0,a;try{a=await k({root:d,out:f,...o.items===void 0?{}:{items:o.items},combos:S(o),...o.type===void 0?{}:{types:o.type},...o.name===void 0?{}:{name:o.name},encode:h,...s.steps?{steps:!0}:{},...s.pptx==="native"?{}:{pptx:s.pptx},sheet:{bom:s.bom,...s.values===void 0?{}:{values:s.values}},index:N(i.env),log:e=>{i.progress(e)},onProgress:e=>{const r=Math.floor(e*10);r<=l||r>=10||(l=r,i.progress(`${String(r*10)}%`))},signal:i.signal})}catch(e){throw A(e)}const u=e=>e?` (${e.integrated.toFixed(1)} LUFS, true peak ${e.truePeak===void 0?"–":e.truePeak.toFixed(1)} dBTP)`:"",b=a.problems.filter(e=>e.level==="error"),m=a.files.flatMap(e=>e.files.length>1?e.files.map(r=>` ${r}`):[` ${e.path}${u(e.loudness)}`]),g=[`${D(m.length,"file")} in ${a.out}:`,...m,...a.failed.length>0?["Not made:",...a.failed.map(e=>` ${e.name}: ${e.message}${e.hint?` ${e.hint}`:""}`)]:[],...a.unindexed.map(e=>`Not indexed, drawn the fallback way: ${e.file} (${e.error})`),...a.files.flatMap(e=>(e.missing??[]).map(r=>`Not measured: ${r}`)),...new Set(a.files.flatMap(e=>(e.fontsLeft??[]).map(r=>`Not in the file: ${r.font} (${r.why}); PowerPoint shows another font where it is not installed.`))),...b.map(w),...v(p(a.console))];return{value:{out:a.out,files:a.files.map(e=>({...e})),failed:a.failed.map(e=>({...e})),problems:a.problems,...a.unindexed.length>0?{unindexed:a.unindexed}:{},...p(a.console)},text:g.join(`
3
3
  `),exit:a.failed.length>0?c.failed:c.ok}});
@@ -1,8 +1,8 @@
1
1
  /*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
2
- import{mkdir as ie,readFile as X,stat as q,writeFile as ce}from"node:fs/promises";import{basename as k,dirname as L,extname as A,join as S,relative as B,resolve as D}from"node:path";import{z as f}from"zod";import{readSheetSource as he,sheetRoot as de,workbookFiles as fe}from"@allyhub-next/build";import{ITEM_KINDS as me}from"@allyhub-next/formats";import{EXIT as $}from"@allyhub-next/protocol";import{CellError as ue,DIFF_DEFAULTS as we,FormulaCell as O,Matrix as pe,PROFILE_TOP as be,SharedFormula as $e,cellName as M,checkWorkbook as z,dataValue as _,diffWorkbooks as ge,importRows as ye,profileTable as xe,rangeName as G,readAddress as ve,readArea as ke,scenarioNames as K,shownValue as j}from"@allyhub-next/sheet";import{CAPABILITIES as Y}from"@allyhub-next/sheet/api";import{COMPARE_TOLERANCE as Se,importXlsx as Q}from"@allyhub-next/sheet/xlsx";import{CommandError as g,defineCommand as E}from"../command.js";import{projectRoot as T}from"../project.js";import{dir as C}from"../fields.js";const x=me.sheet.entries[0];export const CALC_ROWS=50,TRACE_CELLS=50;export async function findSheet(e,o,s){const t=D(o,s);for(const n of[k(t)===x?t:S(t,x),S(e,s,x),S(e,"content",s,x)])if((await q(n).catch(()=>{}))?.isFile())return n}export const sheetFolderName=(e,o)=>B(e,L(o)).replace(/^content\//u,"");export async function sheetAt(e,o,s){const t=await findSheet(e,o,s);if(t!==void 0)return t;throw new g("not-found",`There is no sheet ${s}.`,{exit:$.notFound,hint:"Name it by its folder (research/leads, a folder under content/ with or without content/) or its sheet.yaml."})}export async function sourceOfSheet(e,o){const s=de(e,L(o)),t=await he(s.root,s.dir);return{...s,source:t,files:fe(s.root,t)}}export async function openSheet(e,o,s,t){const n=await sheetAt(e,o,s),{source:a,files:r}=await sourceOfSheet(e,n),{workbook:c,calc:i,problems:l}=z(r,{scenario:t});if(!c||!i)throw new g("bad-file",`${B(e,n)} cannot be read: ${l.map(m=>`${m.line===void 0?"":`line ${String(m.line)}: `}${m.message}`).join("; ")}`,{exit:$.usage,hint:"allyhub check lists what is wrong."});return{file:B(e,n),workbook:c,calc:i,problems:l.length+a.problems.length}}function je(e,o){const s=K(e);if(!s.includes(o))throw new g("not-found",`There is no scenario ${o}.`,{exit:$.notFound,hint:s.length>0?`It has ${s.join(", ")}.`:"sheet.yaml's scenarios holds none."})}const u=e=>e.toLocaleString("en-US"),R=e=>e.toLocaleString("en-US",{maximumFractionDigits:4}),P=e=>e>0?["",`The workbook has ${String(e)} problem${e===1?"":"s"}: allyhub check lists them.`]:[];function Ee(e,o){const s=[`${u(e.empty)} empty`,`${u(e.distinct)} distinct`];e.errors>0&&s.push(`${u(e.errors)} errors`),e.min!==void 0&&e.max!==void 0&&s.push(`${R(e.min)} to ${R(e.max)}`),e.sum!==void 0&&s.push(`sum ${R(e.sum)}`),e.mean!==void 0&&s.push(`mean ${R(e.mean)}`),e.shortest!==void 0&&e.longest!==void 0&&s.push(`${String(e.shortest)} to ${String(e.longest)} characters`);const t=[`${e.name.padEnd(o)} ${s.join(", ")}`];return e.formula!==void 0&&t.push(`${"".padEnd(o)} ${e.formula}`),e.top.some(n=>n.count>1)&&t.push(`${"".padEnd(o)} most: ${e.top.map(n=>`${JSON.stringify(n.value.length>40?`${n.value.slice(0,39)}…`:n.value)} ${u(n.count)}`).join(", ")}`),t}export const sheet=E({name:"sheet",summary:"Each table of a sheet measured: its columns' counts, empty, distinct, ranges and frequent values",input:f.strictObject({sheet:f.string().describe("The sheet, by its folder or its sheet.yaml"),dir:C}),positional:["sheet"],output:f.looseObject({}),examples:["allyhub sheet research/leads"]},async(e,o)=>{const s=await T(o.cwd,e.dir),{file:t,workbook:n,calc:a,problems:r}=await openSheet(s,o.cwd,e.sheet),c=n.tables.map(l=>({name:l.name,rows:l.rows,columns:xe(a,l)})),i=c.flatMap(l=>{const m=Math.min(24,Math.max(4,...l.columns.map(w=>w.name.length)));return["",`${l.name}: ${u(l.rows)} rows, ${String(l.columns.length)} columns; each column's ${String(be)} most frequent values`,...l.columns.flatMap(w=>Ee(w,m))]});return{value:{file:t,tables:c,problems:r},text:[`${t}: ${String(n.sheets.length)} sheet${n.sheets.length===1?"":"s"}, ${String(c.length)} table${c.length===1?"":"s"}`,...i,...P(r)].join(`
3
- `)}});const Z=e=>{const o=e.sheets[0];if(!o)throw new g("bad-file","The workbook has no sheets.",{exit:$.usage});return o};function ee(e,o){const s=o.lastIndexOf("!");if(s<0)return{sheet:Z(e),address:o};const t=o.slice(0,s).replace(/^'|'$/gu,"").replaceAll("''","'"),n=e.sheet(t);if(!n)throw new g("not-found",`There is no sheet ${t}.`,{exit:$.notFound,hint:`It has ${e.sheets.map(a=>a.name).join(", ")}.`});return{sheet:n,address:o.slice(s+1)}}function N(e,o,s,t){const n=[];for(let a=o.top;a<=o.bottom;a++){const r=[];for(let c=o.left;c<=o.right;c++){const i=t.value(e,a,c),l=e.lookAt(a,c).format,m=e.at(a,c);r.push({address:M({row:a,col:c}),value:_(i,l),shown:j(i,l),...m instanceof O?{formula:m.text}:{}})}n.push(r)}return{sheet:e.name,what:s,area:G(o),rows:n}}function Oe(e,o,s){const t=a=>({address:"",value:_(a,void 0),shown:j(a)});if(!(s instanceof pe))return{sheet:e.name,what:o,rows:[[t(s)]]};const n=[];for(let a=0;a<s.rows;a++){const r=[];for(let c=0;c<s.cols;c++)r.push(t(s.at(a,c)));n.push(r)}return{sheet:e.name,what:o,rows:n}}function te(e,o){const{wb:s}=e;if(o===void 0)return s.sheets.flatMap(l=>{const m=l.used;return m?[N(l,m,l.name,e)]:[]});const t=s.table(o);if(t)return[N(t.sheet,t.area,o,e)];const n=s.name(o);if(n){const l=new $e(n.formula?.text??`=${o}`,0,0,{file:""}),m=Z(s);return[Oe(m,o,e.evaluate(l,m))]}const a=s.sheet(o);if(a){const l=a.used;return[l?N(a,l,o,e):{sheet:a.name,what:o,rows:[]}]}const{sheet:r,address:c}=ee(s,o),i=ke(c);if(!i)throw new g("not-found",`${o} is not a sheet, a table, a name or a range of this workbook.`,{exit:$.notFound,hint:[`Sheets: ${s.sheets.map(l=>l.name).join(", ")}.`,s.tables.length>0?`Tables: ${s.tables.map(l=>l.name).join(", ")}.`:"",s.names.size>0?`Names: ${[...s.names.values()].map(l=>l.name).join(", ")}.`:"","A range is Summary!B3:D3, or B3 on the first sheet."].filter(Boolean).join(" ")});return[N(r,i,o,e)]}function W(e){const o=[];for(const s of e)s.forEach((t,n)=>{o[n]=Math.max(o[n]??0,t.length)});return e.map(s=>s.map((t,n)=>n===s.length-1?t:t.padEnd(o[n]??0)).join(" ").trimEnd())}function Te(e,o){const s=e.area===void 0?e.what:`${e.sheet}!${e.area}`,t=e.rows.slice(0,o),n=e.area!==void 0,a=t.map(c=>[...n?[/\d+$/u.exec(c[0]?.address??"")?.[0]??""]:[],...c.map(i=>i.shown)]),r=(e.rows[0]??[]).map(c=>c.address.replace(/\d+$/u,""));return[s,...W(n?[["",...r],...a]:a),...e.rows.length>t.length?[`… ${u(e.rows.length-t.length)} more rows (--all)`]:[]]}export const sheetCalc=E({name:"sheet calc",summary:"What a sheet computes, without opening anything: a sheet, a range, a table, a name, or every sheet, as an aligned table",input:f.strictObject({sheet:f.string().describe("The sheet, by its folder or its sheet.yaml"),what:f.string().optional().describe("A sheet (its used range), a range (Summary!B3:D3, or B3 on the first sheet), a table or a name; default every sheet"),all:f.boolean().default(!1).describe(`Every row, not the first ${String(CALC_ROWS)}`),scenario:f.string().optional().describe("Compute it with this scenario's inputs (sheet.yaml's scenarios); nothing is written"),scenarios:f.boolean().default(!1).describe("Compare the base case and every scenario: what is names, cells or ranges, apart by commas, a row each; default the names no scenario sets"),dir:C}),positional:["sheet","what"],output:f.looseObject({}),examples:["allyhub sheet calc finance/budget","allyhub sheet calc finance/budget Summary","allyhub sheet calc finance/budget orders","allyhub sheet calc finance/budget 'Summary!B3:M3' --json","allyhub sheet calc finance/budget revenue --scenario high","allyhub sheet calc finance/budget 'revenue,Summary!B4' --scenarios"]},async(e,o)=>{const s=await T(o.cwd,e.dir);if(e.scenarios)return Fe(s,o.cwd,e.sheet,e.what);const{file:t,calc:n,problems:a,workbook:r}=await openSheet(s,o.cwd,e.sheet,e.scenario);e.scenario!==void 0&&je(r,e.scenario);const c=te(n,e.what),i=e.all?1/0:CALC_ROWS;return{value:{file:t,grids:c,problems:a},text:[...c.flatMap((l,m)=>[...m>0?[""]:[],...Te(l,i)]),...P(a)].join(`
4
- `)}});function Ce(e,o){return te(e,o.trim()).flatMap(s=>s.rows.flat().map(t=>({...t,address:t.address===""?o.trim():`${s.sheet}!${t.address}`})))}async function Fe(e,o,s,t){const n=await openSheet(e,o,s),a=K(n.workbook);if(a.length===0)throw new g("not-found",`${n.file} has no scenarios.`,{exit:$.notFound,hint:"sheet.yaml's scenarios: { high: { growth: 0.2 } } names some."});const r=new Set(a.flatMap(h=>Object.keys(n.workbook.file.scenarios?.[h]??{}).map(b=>b.toLowerCase()))),c=t?.split(",")??[...n.workbook.names.values()].map(h=>h.name).filter(h=>!r.has(h.toLowerCase()));if(c.length===0)throw new g("bad-input","Say what to compare: names, cells or ranges, apart by commas.",{exit:$.usage});const i=["Base case",...a],l=[n,...await Promise.all(a.map(h=>openSheet(e,o,s,h)))],w=c.map(h=>l.map(b=>Ce(b.calc,h))).flatMap(h=>(h[0]??[]).map((b,p)=>({output:b.address,values:Object.fromEntries(i.map((v,y)=>[v,h[y]?.[p]?.value??null])),shown:Object.fromEntries(i.map((v,y)=>[v,h[y]?.[p]?.shown??""]))})));return{value:{file:n.file,scenarios:i,outputs:w},text:[...W([["",...i],...w.map(h=>[h.output,...i.map(b=>h.shown[b]??"")])]),...P(n.problems)].join(`
5
- `)}}const Ae=(e,o)=>`${e.sheet===o?"":`${e.sheet.name}!`}${G({top:e.top,left:e.left,bottom:Math.min(e.bottom,Math.max(e.top,e.sheet.lastRow)),right:e.right})}`;export const sheetTrace=E({name:"sheet trace",summary:"What a cell depends on and what depends on it: its formula, where it is written, the places it reads and the cells that read it",input:f.strictObject({sheet:f.string().describe("The sheet, by its folder or its sheet.yaml"),cell:f.string().describe("The cell: Summary!B5, or B5 on the first sheet"),all:f.boolean().default(!1).describe(`Every cell that reads it, not the first ${String(TRACE_CELLS)}`),dir:C}),positional:["sheet","cell"],output:f.looseObject({}),examples:["allyhub sheet trace finance/budget 'Summary!B1'"]},async(e,o)=>{const s=await T(o.cwd,e.dir),{file:t,workbook:n,calc:a}=await openSheet(s,o.cwd,e.sheet),{sheet:r,address:c}=ee(n,e.cell),i=ve(c);if(!i)throw new g("bad-input",`${e.cell} is not a cell.`,{exit:$.usage});const{row:l,col:m}=i,w=a.value(r,l,m),h=r.lookAt(l,m).format,b=r.at(l,m),p=n.sourceOf(r,l,m),v=b instanceof O?a.precedents(b).map(d=>{const le=d.single?j(a.value(d.sheet,d.top,d.left),d.sheet.lookAt(d.top,d.left).format):`${u(d.cols)} × ${u(Math.max(0,Math.min(d.bottom,d.sheet.lastRow)-d.top+1))}`,J=d.single?d.sheet.at(d.top,d.left):void 0,H=J instanceof O?J.text:void 0;return{address:Ae(d,r),shown:le,...H===void 0?{}:{formula:H}}}):[],y=a.readers(r,l,m),I=e.all?y:y.slice(0,TRACE_CELLS),V=I.map(d=>({address:`${d.sheet===r?"":`${d.sheet.name}!`}${M(d)}`,shown:j(d.value,d.sheet.lookAt(d.row,d.col).format),formula:d.text})),U=d=>[` ${d.address}`,d.shown,d.formula].filter(Boolean).join(" "),F=p===void 0?void 0:p.line===void 0?p.file:`${p.file}:${String(p.line)}`;return{value:{file:t,cell:`${r.name}!${M(i)}`,value:_(w,h),shown:j(w,h),...w instanceof ue?{error:w.code}:{},...b instanceof O?{formula:b.text}:{},...F===void 0?{}:{written:F},reads:v,readBy:V,readers:y.length},text:[`${r.name}!${M(i)} ${j(w,h)}`,...b instanceof O?[` ${b.text}`]:[],...F===void 0?[]:[` written in ${F}`],...v.length>0?["reads:",...v.map(U)]:[],...y.length>0?[`read by ${u(y.length)}:`,...V.map(U),...y.length>I.length?[` … ${u(y.length-I.length)} more (--all)`]:[]]:["read by nothing"]].join(`
6
- `)}}),sheetCapabilities=E({name:"sheet capabilities",summary:"What @allyhub/sdk/sheets holds of openpyxl's (its classes), how it differs and what it adds, and the worksheet functions, as JSON",input:f.strictObject({}),output:f.looseObject({}),examples:["allyhub sheet capabilities"]},()=>Promise.resolve({value:{...Y},text:JSON.stringify(Y,null,2)}));const se=new Set([".xlsx",".xlsm",".xltx",".xltm"]);export const DIFF_ROWS=50;const oe={value:"Value changed, formula the same",formula:"Formula changed, value the same",both:"Formula and value changed",added:"Added",removed:"Removed"},Me=e=>{const o=(e.now??e.was)?.cell??"",s=e.table===void 0?o:`${e.table}[${e.key??o}]`,t=e.column===void 0?"":` ${e.column}`;return`${e.sheet}!${s}${t}`},Re=e=>{const o=e.was?.formula??"",s=e.now?.formula??"";return[Me(e),e.was?.shown??"","→",e.now?.shown??"",e.kind==="value"?s:e.kind==="formula"||e.kind==="both"?`${o} → ${s}`:s===""?o:s]};function Ne(e,o){const s=[];for(const t of e.sheets)s.push(`Sheet ${t.name} ${t.added?"added":"removed"}`);for(const t of e.tables){const n=[t.rowsAdded.length>0?`rows added: ${t.rowsAdded.slice(0,20).join(", ")}`:"",t.rowsRemoved.length>0?`rows removed: ${t.rowsRemoved.slice(0,20).join(", ")}`:"",t.columnsAdded.length>0?`columns added: ${t.columnsAdded.join(", ")}`:"",t.columnsRemoved.length>0?`columns removed: ${t.columnsRemoved.join(", ")}`:""].filter(Boolean);s.push(`Table ${t.name}, rows lined up by ${t.by==="key"?t.key??"its key":"their place"}${n.length>0?`: ${n.join("; ")}`:""}`)}for(const t of e.names)s.push(`Name ${t.name}: ${t.was??"(none)"} → ${t.now??"(none)"}`);for(const t of e.charts)s.push(`Charts of ${t} changed`);for(const t of Object.keys(oe)){const n=e.cells.filter(r=>r.kind===t);if(n.length===0)continue;const a=o?n:n.slice(0,DIFF_ROWS);s.push("",`${oe[t]}: ${u(n.length)}`,...W(a.map(Re)).map(r=>` ${r}`),...n.length>a.length?[` … ${u(n.length-a.length)} more (--all)`]:[])}return s}async function ne(e,o,s){const t=D(o,s);if(se.has(A(t).toLowerCase())){const r=await X(t).catch(()=>{throw new g("not-found",`There is no file ${t}.`,{exit:$.notFound})}),c=Q(new Uint8Array(r),{name:k(t,A(t))}),{calc:i}=z({text:c.files.get(x)??"",read:l=>c.files.get(l)});if(!i)throw new g("bad-file",`${s} cannot be read.`,{exit:$.usage});return{calc:i,file:s}}const{calc:n,file:a}=await openSheet(e,o,s);return{calc:n,file:a}}export const sheetDiff=E({name:"sheet diff",summary:"Two versions of a workbook compared, by value and by formula: two folders, or a folder and an .xlsx. Cells whose formula changed and value did not are apart from those whose value changed; rows of a table line up by its key, else by their place",input:f.strictObject({was:f.string().describe("The version before: a sheet's folder or an .xlsx"),now:f.string().describe("The version after: a sheet's folder or an .xlsx"),tolerance:f.number().min(0).default(we.tolerance).describe("How far apart two numbers may be, as a share of the larger, and be the same"),all:f.boolean().default(!1).describe(`Every cell, not the first ${String(DIFF_ROWS)} of each kind`),dir:C}),positional:["was","now"],output:f.looseObject({}),examples:["allyhub sheet diff finance/budget finance/budget-v2","allyhub sheet diff finance/budget ~/Downloads/budget.xlsx --json"]},async(e,o)=>{const s=await T(o.cwd,e.dir),t=await ne(s,o.cwd,e.was),n=await ne(s,o.cwd,e.now),a=ge(t.calc,n.calc,{tolerance:e.tolerance}),{counts:r}=a,c=a.cells.length;return{value:{was:t.file,now:n.file,...a},text:[`${t.file} → ${n.file}: ${u(c)} cell${c===1?"":"s"} differ (${u(r.value)} value, ${u(r.formula)} formula, ${u(r.both)} both, ${u(r.added)} added, ${u(r.removed)} removed)`,...Ne(a,e.all)].join(`
7
- `)}});const Ie=f.string().transform(e=>e.replace(/^\/+|\/+$/gu,"")).refine(e=>e!==""&&!e.split("/").some(o=>o===""||o==="."||o===".."),{message:"a folder from the project's root, such as research/leads"});export const IMPORT_DIFFERENCES=50;const ae=e=>e===null?"empty":typeof e=="string"?JSON.stringify(e):String(e);function Le(e,o){const{formulas:s,same:t,uncached:n,moving:a,differences:r}=e,c=[`${u(t)} of ${u(s)} formulas compute what the file holds`,...a>0?[`${u(a)} read the clock or a random number, not compared`]:[],...n>0?[`${u(n)} have no value in the file`]:[]],i=o?r:r.slice(0,IMPORT_DIFFERENCES);return[`Computed here against the file: ${c.join("; ")}.`,...r.length>0?[`${u(r.length)} differ${r.length===1?"s":""}:`,...i.map(l=>` ${l.sheet}!${l.cell} ${l.formula} file ${ae(l.file)} here ${ae(l.engine)}`),...r.length>i.length?[` … ${u(r.length-i.length)} more (--all)`]:[]]:[]]}async function re(e,o){for(const[s,t]of o){const n=S(e,s);await ie(L(n),{recursive:!0}),await ce(n,t,{flag:"wx"})}}export const sheetImport=E({name:"sheet import",summary:"Makes a sheet of an Excel, CSV or TSV file: its sheets, tables, formulas, names and looks as sheet.yaml and CSV files, said what could not be carried over, each formula computed here and compared with the value the file holds; never over a place that is taken",input:f.strictObject({file:f.string().describe("The file to make a sheet of: .xlsx, .xlsm, .csv or .tsv"),to:Ie.optional().describe("The sheet's folder, from the project's root (default the file's name)"),tolerance:f.number().min(0).default(Se).describe("How far apart a computed number and the file's may be, as a share of the larger, and count as the same; 0 lists every difference"),all:f.boolean().default(!1).describe(`Every difference, not the first ${String(IMPORT_DIFFERENCES)}`),dir:C}),positional:["file"],output:f.looseObject({}),examples:["allyhub sheet import ~/Downloads/forecast.xlsx --to finance/forecast","allyhub sheet import ~/Downloads/leads.csv --to research/leads"]},async(e,o)=>{const s=await T(o.cwd,e.dir),t=D(o.cwd,e.file),n=A(t).toLowerCase(),a=se.has(n);if(n===".xls"||n===".xlsb")throw new g("bad-file",`${k(t)} is Excel's binary format.`,{exit:$.usage,hint:"Save it as .xlsx, then import that."});if(!a&&n!==".csv"&&n!==".tsv")throw new g("bad-file",`${k(t)} is not an .xlsx, .xlsm, .csv or .tsv file.`,{exit:$.usage});const r=await X(t).catch(()=>{throw new g("not-found",`There is no file ${t}.`,{exit:$.notFound})}),c=k(t,A(t)),i=e.to??c;if(await q(S(s,i)).catch(()=>{}))throw new g("place-taken",`${i} is already there.`,{exit:$.conflict,hint:"Name another place with --to."});const l=S(s,i),m=e.to===void 0?c:k(e.to);if(a){let h;try{h=Q(new Uint8Array(r),{name:m,tolerance:e.tolerance})}catch(p){throw new g("bad-file",`${k(t)} cannot be read: ${p.message}`,{exit:$.usage})}await re(l,h.files);const b=[...h.files.keys()];return{value:{place:i,files:b.map(p=>`${i}/${p}`),sheets:h.sheets,tables:h.tables,lost:h.lost,problems:h.problems,compared:h.compared},text:[`Made ${i}/: ${b.join(", ")}`,...h.lost.length>0?["Not carried over:",...h.lost.map(p=>` ${p}`)]:["Nothing was left out."],...Le(h.compared,e.all),...h.problems.length>0?["Problems:",...h.problems.map(p=>` ${p.file}${p.line===void 0?"":`:${String(p.line)}`}: ${p.message}`)]:[],`allyhub sheet calc ${i}, then allyhub frames ${i}, to see it.`].join(`
8
- `)}}let w;try{w=ye(m,r.toString("utf8"),n===".tsv"?" ":",")}catch(h){throw new g("bad-file",h.message,{exit:$.usage})}return await re(l,new Map([[x,w.text],[w.path,w.csv]])),{value:{place:i,files:[`${i}/${x}`,`${i}/${w.path}`],rows:w.rows,lost:[]},text:`Made ${i}/${x} and ${i}/${w.path}: ${u(w.rows)} row${w.rows===1?"":"s"}`}});
2
+ import{mkdir as ie,readFile as H,stat as X,writeFile as ce}from"node:fs/promises";import{basename as k,dirname as N,extname as A,join as S,relative as B,resolve as D}from"node:path";import{z as d}from"zod";import{readSheetSource as he,sheetRoot as de,workbookFiles as fe}from"@allyhub-next/build";import{ITEM_KINDS as me,ZIP_LIMITS as ue}from"@allyhub-next/formats";import{EXIT as $}from"@allyhub-next/protocol";import{CellError as we,DIFF_DEFAULTS as pe,FormulaCell as O,Matrix as be,PROFILE_TOP as $e,SharedFormula as ge,cellName as M,checkWorkbook as q,dataValue as _,diffWorkbooks as ye,importRows as xe,profileTable as ve,rangeName as G,readAddress as ke,readArea as Se,scenarioNames as K,shownValue as j}from"@allyhub-next/sheet";import{CAPABILITIES as Y}from"@allyhub-next/sheet/api";import{COMPARE_TOLERANCE as je,importXlsx as Z}from"@allyhub-next/sheet/xlsx";import{CommandError as g,defineCommand as E}from"../command.js";import{projectRoot as T}from"../project.js";import{dir as C}from"../fields.js";const x=me.sheet.entries[0];export const CALC_ROWS=50,TRACE_CELLS=50;export async function findSheet(e,o,s){const t=D(o,s);for(const n of[k(t)===x?t:S(t,x),S(e,s,x),S(e,"content",s,x)])if((await X(n).catch(()=>{}))?.isFile())return n}export const sheetFolderName=(e,o)=>B(e,N(o)).replace(/^content\//u,"");export async function sheetAt(e,o,s){const t=await findSheet(e,o,s);if(t!==void 0)return t;throw new g("not-found",`There is no sheet ${s}.`,{exit:$.notFound,hint:"Name it by its folder (research/leads, a folder under content/ with or without content/) or its sheet.yaml."})}export async function sourceOfSheet(e,o){const s=de(e,N(o)),t=await he(s.root,s.dir);return{...s,source:t,files:fe(s.root,t)}}export async function openSheet(e,o,s,t){const n=await sheetAt(e,o,s),{source:a,files:r}=await sourceOfSheet(e,n),{workbook:c,calc:i,problems:l}=q(r,{scenario:t});if(!c||!i)throw new g("bad-file",`${B(e,n)} cannot be read: ${l.map(m=>`${m.line===void 0?"":`line ${String(m.line)}: `}${m.message}`).join("; ")}`,{exit:$.usage,hint:"allyhub check lists what is wrong."});return{file:B(e,n),workbook:c,calc:i,problems:l.length+a.problems.length}}function Ee(e,o){const s=K(e);if(!s.includes(o))throw new g("not-found",`There is no scenario ${o}.`,{exit:$.notFound,hint:s.length>0?`It has ${s.join(", ")}.`:"sheet.yaml's scenarios holds none."})}const u=e=>e.toLocaleString("en-US"),I=e=>e.toLocaleString("en-US",{maximumFractionDigits:4}),P=e=>e>0?["",`The workbook has ${String(e)} problem${e===1?"":"s"}: allyhub check lists them.`]:[];function Oe(e,o){const s=[`${u(e.empty)} empty`,`${u(e.distinct)} distinct`];e.errors>0&&s.push(`${u(e.errors)} errors`),e.min!==void 0&&e.max!==void 0&&s.push(`${I(e.min)} to ${I(e.max)}`),e.sum!==void 0&&s.push(`sum ${I(e.sum)}`),e.mean!==void 0&&s.push(`mean ${I(e.mean)}`),e.shortest!==void 0&&e.longest!==void 0&&s.push(`${String(e.shortest)} to ${String(e.longest)} characters`);const t=[`${e.name.padEnd(o)} ${s.join(", ")}`];return e.formula!==void 0&&t.push(`${"".padEnd(o)} ${e.formula}`),e.top.some(n=>n.count>1)&&t.push(`${"".padEnd(o)} most: ${e.top.map(n=>`${JSON.stringify(n.value.length>40?`${n.value.slice(0,39)}…`:n.value)} ${u(n.count)}`).join(", ")}`),t}export const sheet=E({name:"sheet",summary:"Each table of a sheet measured: its columns' counts, empty, distinct, ranges and frequent values",input:d.strictObject({sheet:d.string().describe("The sheet, by its folder or its sheet.yaml"),dir:C}),positional:["sheet"],output:d.looseObject({}),examples:["allyhub sheet research/leads"]},async(e,o)=>{const s=await T(o.cwd,e.dir),{file:t,workbook:n,calc:a,problems:r}=await openSheet(s,o.cwd,e.sheet),c=n.tables.map(l=>({name:l.name,rows:l.rows,columns:ve(a,l)})),i=c.flatMap(l=>{const m=Math.min(24,Math.max(4,...l.columns.map(w=>w.name.length)));return["",`${l.name}: ${u(l.rows)} rows, ${String(l.columns.length)} columns; each column's ${String($e)} most frequent values`,...l.columns.flatMap(w=>Oe(w,m))]});return{value:{file:t,tables:c,problems:r},text:[`${t}: ${String(n.sheets.length)} sheet${n.sheets.length===1?"":"s"}, ${String(c.length)} table${c.length===1?"":"s"}`,...i,...P(r)].join(`
3
+ `)}});const Q=e=>{const o=e.sheets[0];if(!o)throw new g("bad-file","The workbook has no sheets.",{exit:$.usage});return o};function ee(e,o){const s=o.lastIndexOf("!");if(s<0)return{sheet:Q(e),address:o};const t=o.slice(0,s).replace(/^'|'$/gu,"").replaceAll("''","'"),n=e.sheet(t);if(!n)throw new g("not-found",`There is no sheet ${t}.`,{exit:$.notFound,hint:`It has ${e.sheets.map(a=>a.name).join(", ")}.`});return{sheet:n,address:o.slice(s+1)}}function R(e,o,s,t){const n=[];for(let a=o.top;a<=o.bottom;a++){const r=[];for(let c=o.left;c<=o.right;c++){const i=t.value(e,a,c),l=e.lookAt(a,c).format,m=e.at(a,c);r.push({address:M({row:a,col:c}),value:_(i,l),shown:j(i,l),...m instanceof O?{formula:m.text}:{}})}n.push(r)}return{sheet:e.name,what:s,area:G(o),rows:n}}function Te(e,o,s){const t=a=>({address:"",value:_(a,void 0),shown:j(a)});if(!(s instanceof be))return{sheet:e.name,what:o,rows:[[t(s)]]};const n=[];for(let a=0;a<s.rows;a++){const r=[];for(let c=0;c<s.cols;c++)r.push(t(s.at(a,c)));n.push(r)}return{sheet:e.name,what:o,rows:n}}function te(e,o){const{wb:s}=e;if(o===void 0)return s.sheets.flatMap(l=>{const m=l.used;return m?[R(l,m,l.name,e)]:[]});const t=s.table(o);if(t)return[R(t.sheet,t.area,o,e)];const n=s.name(o);if(n){const l=new ge(n.formula?.text??`=${o}`,0,0,{file:""}),m=Q(s);return[Te(m,o,e.evaluate(l,m))]}const a=s.sheet(o);if(a){const l=a.used;return[l?R(a,l,o,e):{sheet:a.name,what:o,rows:[]}]}const{sheet:r,address:c}=ee(s,o),i=Se(c);if(!i)throw new g("not-found",`${o} is not a sheet, a table, a name or a range of this workbook.`,{exit:$.notFound,hint:[`Sheets: ${s.sheets.map(l=>l.name).join(", ")}.`,s.tables.length>0?`Tables: ${s.tables.map(l=>l.name).join(", ")}.`:"",s.names.size>0?`Names: ${[...s.names.values()].map(l=>l.name).join(", ")}.`:"","A range is Summary!B3:D3, or B3 on the first sheet."].filter(Boolean).join(" ")});return[R(r,i,o,e)]}function W(e){const o=[];for(const s of e)s.forEach((t,n)=>{o[n]=Math.max(o[n]??0,t.length)});return e.map(s=>s.map((t,n)=>n===s.length-1?t:t.padEnd(o[n]??0)).join(" ").trimEnd())}function Ce(e,o){const s=e.area===void 0?e.what:`${e.sheet}!${e.area}`,t=e.rows.slice(0,o),n=e.area!==void 0,a=t.map(c=>[...n?[/\d+$/u.exec(c[0]?.address??"")?.[0]??""]:[],...c.map(i=>i.shown)]),r=(e.rows[0]??[]).map(c=>c.address.replace(/\d+$/u,""));return[s,...W(n?[["",...r],...a]:a),...e.rows.length>t.length?[`… ${u(e.rows.length-t.length)} more rows (--all)`]:[]]}export const sheetCalc=E({name:"sheet calc",summary:"What a sheet computes, without opening anything: a sheet, a range, a table, a name, or every sheet, as an aligned table",input:d.strictObject({sheet:d.string().describe("The sheet, by its folder or its sheet.yaml"),what:d.string().optional().describe("A sheet (its used range), a range (Summary!B3:D3, or B3 on the first sheet), a table or a name; default every sheet"),all:d.boolean().default(!1).describe(`Every row, not the first ${String(CALC_ROWS)}`),scenario:d.string().optional().describe("Compute it with this scenario's inputs (sheet.yaml's scenarios); nothing is written"),scenarios:d.boolean().default(!1).describe("Compare the base case and every scenario: what is names, cells or ranges, apart by commas, a row each; default the names no scenario sets"),dir:C}),positional:["sheet","what"],output:d.looseObject({}),examples:["allyhub sheet calc finance/budget","allyhub sheet calc finance/budget Summary","allyhub sheet calc finance/budget orders","allyhub sheet calc finance/budget 'Summary!B3:M3' --json","allyhub sheet calc finance/budget revenue --scenario high","allyhub sheet calc finance/budget 'revenue,Summary!B4' --scenarios"]},async(e,o)=>{const s=await T(o.cwd,e.dir);if(e.scenarios)return Ae(s,o.cwd,e.sheet,e.what);const{file:t,calc:n,problems:a,workbook:r}=await openSheet(s,o.cwd,e.sheet,e.scenario);e.scenario!==void 0&&Ee(r,e.scenario);const c=te(n,e.what),i=e.all?1/0:CALC_ROWS;return{value:{file:t,grids:c,problems:a},text:[...c.flatMap((l,m)=>[...m>0?[""]:[],...Ce(l,i)]),...P(a)].join(`
4
+ `)}});function Fe(e,o){return te(e,o.trim()).flatMap(s=>s.rows.flat().map(t=>({...t,address:t.address===""?o.trim():`${s.sheet}!${t.address}`})))}async function Ae(e,o,s,t){const n=await openSheet(e,o,s),a=K(n.workbook);if(a.length===0)throw new g("not-found",`${n.file} has no scenarios.`,{exit:$.notFound,hint:"sheet.yaml's scenarios: { high: { growth: 0.2 } } names some."});const r=new Set(a.flatMap(h=>Object.keys(n.workbook.file.scenarios?.[h]??{}).map(b=>b.toLowerCase()))),c=t?.split(",")??[...n.workbook.names.values()].map(h=>h.name).filter(h=>!r.has(h.toLowerCase()));if(c.length===0)throw new g("bad-input","Say what to compare: names, cells or ranges, apart by commas.",{exit:$.usage});const i=["Base case",...a],l=[n,...await Promise.all(a.map(h=>openSheet(e,o,s,h)))],w=c.map(h=>l.map(b=>Fe(b.calc,h))).flatMap(h=>(h[0]??[]).map((b,p)=>({output:b.address,values:Object.fromEntries(i.map((v,y)=>[v,h[y]?.[p]?.value??null])),shown:Object.fromEntries(i.map((v,y)=>[v,h[y]?.[p]?.shown??""]))})));return{value:{file:n.file,scenarios:i,outputs:w},text:[...W([["",...i],...w.map(h=>[h.output,...i.map(b=>h.shown[b]??"")])]),...P(n.problems)].join(`
5
+ `)}}const Me=(e,o)=>`${e.sheet===o?"":`${e.sheet.name}!`}${G({top:e.top,left:e.left,bottom:Math.min(e.bottom,Math.max(e.top,e.sheet.lastRow)),right:e.right})}`;export const sheetTrace=E({name:"sheet trace",summary:"What a cell depends on and what depends on it: its formula, where it is written, the places it reads and the cells that read it",input:d.strictObject({sheet:d.string().describe("The sheet, by its folder or its sheet.yaml"),cell:d.string().describe("The cell: Summary!B5, or B5 on the first sheet"),all:d.boolean().default(!1).describe(`Every cell that reads it, not the first ${String(TRACE_CELLS)}`),dir:C}),positional:["sheet","cell"],output:d.looseObject({}),examples:["allyhub sheet trace finance/budget 'Summary!B1'"]},async(e,o)=>{const s=await T(o.cwd,e.dir),{file:t,workbook:n,calc:a}=await openSheet(s,o.cwd,e.sheet),{sheet:r,address:c}=ee(n,e.cell),i=ke(c);if(!i)throw new g("bad-input",`${e.cell} is not a cell.`,{exit:$.usage});const{row:l,col:m}=i,w=a.value(r,l,m),h=r.lookAt(l,m).format,b=r.at(l,m),p=n.sourceOf(r,l,m),v=b instanceof O?a.precedents(b).map(f=>{const le=f.single?j(a.value(f.sheet,f.top,f.left),f.sheet.lookAt(f.top,f.left).format):`${u(f.cols)} × ${u(Math.max(0,Math.min(f.bottom,f.sheet.lastRow)-f.top+1))}`,V=f.single?f.sheet.at(f.top,f.left):void 0,J=V instanceof O?V.text:void 0;return{address:Me(f,r),shown:le,...J===void 0?{}:{formula:J}}}):[],y=a.readers(r,l,m),L=e.all?y:y.slice(0,TRACE_CELLS),U=L.map(f=>({address:`${f.sheet===r?"":`${f.sheet.name}!`}${M(f)}`,shown:j(f.value,f.sheet.lookAt(f.row,f.col).format),formula:f.text})),z=f=>[` ${f.address}`,f.shown,f.formula].filter(Boolean).join(" "),F=p===void 0?void 0:p.line===void 0?p.file:`${p.file}:${String(p.line)}`;return{value:{file:t,cell:`${r.name}!${M(i)}`,value:_(w,h),shown:j(w,h),...w instanceof we?{error:w.code}:{},...b instanceof O?{formula:b.text}:{},...F===void 0?{}:{written:F},reads:v,readBy:U,readers:y.length},text:[`${r.name}!${M(i)} ${j(w,h)}`,...b instanceof O?[` ${b.text}`]:[],...F===void 0?[]:[` written in ${F}`],...v.length>0?["reads:",...v.map(z)]:[],...y.length>0?[`read by ${u(y.length)}:`,...U.map(z),...y.length>L.length?[` … ${u(y.length-L.length)} more (--all)`]:[]]:["read by nothing"]].join(`
6
+ `)}}),sheetCapabilities=E({name:"sheet capabilities",summary:"What @allyhub/sdk/sheets holds of openpyxl's (its classes), how it differs and what it adds, and the worksheet functions, as JSON",input:d.strictObject({}),output:d.looseObject({}),examples:["allyhub sheet capabilities"]},()=>Promise.resolve({value:{...Y},text:JSON.stringify(Y,null,2)}));const se=new Set([".xlsx",".xlsm",".xltx",".xltm"]);export const DIFF_ROWS=50;const oe={value:"Value changed, formula the same",formula:"Formula changed, value the same",both:"Formula and value changed",added:"Added",removed:"Removed"},Ie=e=>{const o=(e.now??e.was)?.cell??"",s=e.table===void 0?o:`${e.table}[${e.key??o}]`,t=e.column===void 0?"":` ${e.column}`;return`${e.sheet}!${s}${t}`},Re=e=>{const o=e.was?.formula??"",s=e.now?.formula??"";return[Ie(e),e.was?.shown??"","→",e.now?.shown??"",e.kind==="value"?s:e.kind==="formula"||e.kind==="both"?`${o} → ${s}`:s===""?o:s]};function Le(e,o){const s=[];for(const t of e.sheets)s.push(`Sheet ${t.name} ${t.added?"added":"removed"}`);for(const t of e.tables){const n=[t.rowsAdded.length>0?`rows added: ${t.rowsAdded.slice(0,20).join(", ")}`:"",t.rowsRemoved.length>0?`rows removed: ${t.rowsRemoved.slice(0,20).join(", ")}`:"",t.columnsAdded.length>0?`columns added: ${t.columnsAdded.join(", ")}`:"",t.columnsRemoved.length>0?`columns removed: ${t.columnsRemoved.join(", ")}`:""].filter(Boolean);s.push(`Table ${t.name}, rows lined up by ${t.by==="key"?t.key??"its key":"their place"}${n.length>0?`: ${n.join("; ")}`:""}`)}for(const t of e.names)s.push(`Name ${t.name}: ${t.was??"(none)"} → ${t.now??"(none)"}`);for(const t of e.parts)s.push(`${t.sheet??"Workbook"} ${t.part}${t.key===void 0?"":` ${t.key}`}: ${t.was??"(none)"} → ${t.now??"(none)"}`);for(const t of e.charts)s.push(`Charts of ${t} changed`);for(const t of Object.keys(oe)){const n=e.cells.filter(r=>r.kind===t);if(n.length===0)continue;const a=o?n:n.slice(0,DIFF_ROWS);s.push("",`${oe[t]}: ${u(n.length)}`,...W(a.map(Re)).map(r=>` ${r}`),...n.length>a.length?[` … ${u(n.length-a.length)} more (--all)`]:[])}return s}async function ne(e,o,s){const t=D(o,s);if(se.has(A(t).toLowerCase())){const r=await H(t).catch(()=>{throw new g("not-found",`There is no file ${t}.`,{exit:$.notFound})}),c=Z(new Uint8Array(r),{name:k(t,A(t))}),{calc:i}=q({text:c.files.get(x)??"",read:l=>c.files.get(l)});if(!i)throw new g("bad-file",`${s} cannot be read.`,{exit:$.usage});return{calc:i,file:s}}const{calc:n,file:a}=await openSheet(e,o,s);return{calc:n,file:a}}export const sheetDiff=E({name:"sheet diff",summary:"Two versions of a workbook compared, by value and by formula: two folders, or a folder and an .xlsx. Cells whose formula changed and value did not are apart from those whose value changed; rows of a table line up by its key, else by their place",input:d.strictObject({was:d.string().describe("The version before: a sheet's folder or an .xlsx"),now:d.string().describe("The version after: a sheet's folder or an .xlsx"),tolerance:d.number().min(0).default(pe.tolerance).describe("How far apart two numbers may be, as a share of the larger, and be the same"),all:d.boolean().default(!1).describe(`Every cell, not the first ${String(DIFF_ROWS)} of each kind`),dir:C}),positional:["was","now"],output:d.looseObject({}),examples:["allyhub sheet diff finance/budget finance/budget-v2","allyhub sheet diff finance/budget ~/Downloads/budget.xlsx --json"]},async(e,o)=>{const s=await T(o.cwd,e.dir),t=await ne(s,o.cwd,e.was),n=await ne(s,o.cwd,e.now),a=ye(t.calc,n.calc,{tolerance:e.tolerance}),{counts:r}=a,c=a.cells.length;return{value:{was:t.file,now:n.file,...a},text:[`${t.file} → ${n.file}: ${u(c)} cell${c===1?"":"s"} differ (${u(r.value)} value, ${u(r.formula)} formula, ${u(r.both)} both, ${u(r.added)} added, ${u(r.removed)} removed); ${u(a.names.length+a.parts.length)} other thing${a.names.length+a.parts.length===1?"":"s"} differ${a.names.length+a.parts.length===1?"s":""}`,...Le(a,e.all)].join(`
7
+ `)}});const Ne=d.string().transform(e=>e.replace(/^\/+|\/+$/gu,"")).refine(e=>e!==""&&!e.split("/").some(o=>o===""||o==="."||o===".."),{message:"a folder from the project's root, such as research/leads"});export const IMPORT_DIFFERENCES=50;const ae=e=>e===null?"empty":typeof e=="string"?JSON.stringify(e):String(e);function Be(e,o){const{formulas:s,same:t,uncached:n,moving:a,differences:r}=e,c=[`${u(t)} of ${u(s)} formulas compute what the file holds`,...a>0?[`${u(a)} read the clock or a random number, not compared`]:[],...n>0?[`${u(n)} have no value in the file`]:[]],i=o?r:r.slice(0,IMPORT_DIFFERENCES);return[`Computed here against the file: ${c.join("; ")}.`,...r.length>0?[`${u(r.length)} differ${r.length===1?"s":""}:`,...i.map(l=>` ${l.sheet}!${l.cell} ${l.formula} file ${ae(l.file)} here ${ae(l.engine)}`),...r.length>i.length?[` … ${u(r.length-i.length)} more (--all)`]:[]]:[]]}async function re(e,o){for(const[s,t]of o){const n=S(e,s);await ie(N(n),{recursive:!0}),await ce(n,t,{flag:"wx"})}}export const sheetImport=E({name:"sheet import",summary:"Makes a sheet of an Excel, CSV or TSV file: its sheets, tables, formulas, names and looks as sheet.yaml and CSV files, said what could not be carried over, each formula computed here and compared with the value the file holds; never over a place that is taken",input:d.strictObject({file:d.string().describe("The file to make a sheet of: .xlsx, .xlsm, .csv or .tsv"),to:Ne.optional().describe("The sheet's folder, from the project's root (default the file's name)"),maxUnzipped:d.number().positive().default(ue.bytes/1024/1024).describe("MB the file may unzip to, a file past it refused"),tolerance:d.number().min(0).default(je).describe("How far apart a computed number and the file's may be, as a share of the larger, and count as the same; 0 lists every difference"),all:d.boolean().default(!1).describe(`Every difference, not the first ${String(IMPORT_DIFFERENCES)}`),dir:C}),positional:["file"],output:d.looseObject({}),examples:["allyhub sheet import ~/Downloads/forecast.xlsx --to finance/forecast","allyhub sheet import ~/Downloads/leads.csv --to research/leads"]},async(e,o)=>{const s=await T(o.cwd,e.dir),t=D(o.cwd,e.file),n=A(t).toLowerCase(),a=se.has(n);if(n===".xls"||n===".xlsb")throw new g("bad-file",`${k(t)} is Excel's binary format.`,{exit:$.usage,hint:"Save it as .xlsx, then import that."});if(!a&&n!==".csv"&&n!==".tsv")throw new g("bad-file",`${k(t)} is not an .xlsx, .xlsm, .csv or .tsv file.`,{exit:$.usage});const r=await H(t).catch(()=>{throw new g("not-found",`There is no file ${t}.`,{exit:$.notFound})}),c=k(t,A(t)),i=e.to??c;if(await X(S(s,i)).catch(()=>{}))throw new g("place-taken",`${i} is already there.`,{exit:$.conflict,hint:"Name another place with --to."});const l=S(s,i),m=e.to===void 0?c:k(e.to);if(a){let h;try{h=Z(new Uint8Array(r),{name:m,tolerance:e.tolerance,zip:{bytes:e.maxUnzipped*1024*1024}})}catch(p){throw new g("bad-file",`${k(t)} cannot be read: ${p.message}`,{exit:$.usage})}await re(l,new Map([...h.files,...h.assets]));const b=[...h.files.keys(),...h.assets.keys()];return{value:{place:i,files:b.map(p=>`${i}/${p}`),sheets:h.sheets,tables:h.tables,lost:h.lost,problems:h.problems,compared:h.compared},text:[`Made ${i}/: ${b.join(", ")}`,...h.lost.length>0?["Not carried over:",...h.lost.map(p=>` ${p}`)]:["Nothing was left out."],...Be(h.compared,e.all),...h.problems.length>0?["Problems:",...h.problems.map(p=>` ${p.file}${p.line===void 0?"":`:${String(p.line)}`}: ${p.message}`)]:[],`allyhub sheet calc ${i}, then allyhub frames ${i}, to see it.`].join(`
8
+ `)}}let w;try{w=xe(m,r.toString("utf8"),n===".tsv"?" ":",")}catch(h){throw new g("bad-file",h.message,{exit:$.usage})}return await re(l,new Map([[x,w.text],[w.path,w.csv]])),{value:{place:i,files:[`${i}/${x}`,`${i}/${w.path}`],rows:w.rows,lost:[]},text:`Made ${i}/${x} and ${i}/${w.path}: ${u(w.rows)} row${w.rows===1?"":"s"}`}});