@yadsh/dsh-qa-surface 0.5.0 → 0.6.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 (374) hide show
  1. package/README.md +194 -9
  2. package/compatibility.json +10 -1
  3. package/cordis.patch.yml +9 -0
  4. package/lib/account-remotes.js +10 -0
  5. package/lib/account-remotes.js.map +1 -1
  6. package/lib/accounts/errors.js.map +1 -1
  7. package/lib/accounts/file.js.map +1 -1
  8. package/lib/accounts/store.js +22 -0
  9. package/lib/accounts/store.js.map +1 -1
  10. package/lib/client/QaAccountsController.js +29 -0
  11. package/lib/client/QaAccountsController.js.map +1 -1
  12. package/lib/client/QaSessionController.js +168 -48
  13. package/lib/client/QaSessionController.js.map +1 -1
  14. package/lib/client/QaSurface.js +125 -56
  15. package/lib/client/QaSurface.js.map +1 -1
  16. package/lib/client/QaSurfaceGuard.js +96 -0
  17. package/lib/client/QaSurfaceGuard.js.map +1 -0
  18. package/lib/client/QaTranscriptAdapter.js +11 -5
  19. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  20. package/lib/client/components/QaChangelog.js +31 -0
  21. package/lib/client/components/QaChangelog.js.map +1 -1
  22. package/lib/client/components/QaComposer.js +1 -1
  23. package/lib/client/components/QaComposer.js.map +1 -1
  24. package/lib/client/components/QaHeader.js +2 -8
  25. package/lib/client/components/QaHeader.js.map +1 -1
  26. package/lib/client/components/QaMessage.js +20 -7
  27. package/lib/client/components/QaMessage.js.map +1 -1
  28. package/lib/client/components/QaModal.js +24 -6
  29. package/lib/client/components/QaModal.js.map +1 -1
  30. package/lib/client/components/QaSidebar.js +2 -6
  31. package/lib/client/components/QaSidebar.js.map +1 -1
  32. package/lib/client/components/QaSourcesPanel.js +6 -5
  33. package/lib/client/components/QaSourcesPanel.js.map +1 -1
  34. package/lib/client/components/QaWidthHandle.js +21 -1
  35. package/lib/client/components/QaWidthHandle.js.map +1 -1
  36. package/lib/client/components/surface-utils.js +2 -0
  37. package/lib/client/components/surface-utils.js.map +1 -1
  38. package/lib/client/index.js +72 -24
  39. package/lib/client/index.js.map +1 -1
  40. package/lib/client/panels/PanelHost.js +209 -0
  41. package/lib/client/panels/PanelHost.js.map +1 -0
  42. package/lib/client/panels/PanelLauncher.js +39 -0
  43. package/lib/client/panels/PanelLauncher.js.map +1 -0
  44. package/lib/client/panels/contract.js +2 -0
  45. package/lib/client/panels/contract.js.map +1 -0
  46. package/lib/client/panels/index.js +2 -0
  47. package/lib/client/panels/index.js.map +1 -0
  48. package/lib/client/panels/registry.js +171 -0
  49. package/lib/client/panels/registry.js.map +1 -0
  50. package/lib/client/project-session-state.js +3 -0
  51. package/lib/client/project-session-state.js.map +1 -1
  52. package/lib/client/settings/card.js +2 -2
  53. package/lib/client/settings/card.js.map +1 -1
  54. package/lib/client/settings/sections/accounts.js +3 -1
  55. package/lib/client/settings/sections/accounts.js.map +1 -1
  56. package/lib/client/settings/sections/documents.js +88 -0
  57. package/lib/client/settings/sections/documents.js.map +1 -0
  58. package/lib/client/settings/sections/interface.js +2 -0
  59. package/lib/client/settings/sections/interface.js.map +1 -1
  60. package/lib/client/settings/sections.js +1 -0
  61. package/lib/client/settings/sections.js.map +1 -1
  62. package/lib/client/settings-extensions/contract.js +2 -0
  63. package/lib/client/settings-extensions/contract.js.map +1 -0
  64. package/lib/client/settings-extensions/index.js +2 -0
  65. package/lib/client/settings-extensions/index.js.map +1 -0
  66. package/lib/client/settings-extensions/registry.js +63 -0
  67. package/lib/client/settings-extensions/registry.js.map +1 -0
  68. package/lib/client/settlement.js +51 -5
  69. package/lib/client/settlement.js.map +1 -1
  70. package/lib/client/source-preview.js +24 -0
  71. package/lib/client/source-preview.js.map +1 -0
  72. package/lib/client/styles.js +157 -32
  73. package/lib/client/styles.js.map +1 -1
  74. package/lib/client/subagent-codenames.js +109 -0
  75. package/lib/client/subagent-codenames.js.map +1 -0
  76. package/lib/client/types.js +1 -0
  77. package/lib/client/types.js.map +1 -1
  78. package/lib/client/user-settings/GeneralSettingsPage.js +13 -0
  79. package/lib/client/user-settings/GeneralSettingsPage.js.map +1 -0
  80. package/lib/client/user-settings/ProfileSettingsPage.js +59 -0
  81. package/lib/client/user-settings/ProfileSettingsPage.js.map +1 -0
  82. package/lib/client/user-settings/SkillCatalog.js +23 -0
  83. package/lib/client/user-settings/SkillCatalog.js.map +1 -0
  84. package/lib/client/user-settings/SkillEditor.js +89 -0
  85. package/lib/client/user-settings/SkillEditor.js.map +1 -0
  86. package/lib/client/user-settings/SkillToolPicker.js +58 -0
  87. package/lib/client/user-settings/SkillToolPicker.js.map +1 -0
  88. package/lib/client/user-settings/SkillsSettingsPage.js +171 -0
  89. package/lib/client/user-settings/SkillsSettingsPage.js.map +1 -0
  90. package/lib/client/user-settings/StartersSettingsPage.js +78 -0
  91. package/lib/client/user-settings/StartersSettingsPage.js.map +1 -0
  92. package/lib/client/user-settings/UserSettingsDialog.js +50 -0
  93. package/lib/client/user-settings/UserSettingsDialog.js.map +1 -0
  94. package/lib/client/user-settings/copy.js +84 -0
  95. package/lib/client/user-settings/copy.js.map +1 -0
  96. package/lib/client/user-settings/draft.js +127 -0
  97. package/lib/client/user-settings/draft.js.map +1 -0
  98. package/lib/client/user-settings/fields.js +24 -0
  99. package/lib/client/user-settings/fields.js.map +1 -0
  100. package/lib/client.js +5467 -1379
  101. package/lib/client.js.map +1 -1
  102. package/lib/config-resolvers/accounts.js +30 -0
  103. package/lib/config-resolvers/accounts.js.map +1 -1
  104. package/lib/config-resolvers/defaults.js +23 -0
  105. package/lib/config-resolvers/defaults.js.map +1 -1
  106. package/lib/config-resolvers/tools.js +37 -0
  107. package/lib/config-resolvers/tools.js.map +1 -0
  108. package/lib/config-resolvers/ui.js +2 -0
  109. package/lib/config-resolvers/ui.js.map +1 -1
  110. package/lib/config.js +288 -0
  111. package/lib/config.js.map +1 -1
  112. package/lib/documents/artifacts/ids.js +43 -0
  113. package/lib/documents/artifacts/ids.js.map +1 -0
  114. package/lib/documents/artifacts/manifest.js +66 -0
  115. package/lib/documents/artifacts/manifest.js.map +1 -0
  116. package/lib/documents/artifacts/store.js +169 -0
  117. package/lib/documents/artifacts/store.js.map +1 -0
  118. package/lib/documents/capabilities.js +93 -0
  119. package/lib/documents/capabilities.js.map +1 -0
  120. package/lib/documents/config.js +302 -0
  121. package/lib/documents/config.js.map +1 -0
  122. package/lib/documents/defaults.js +78 -0
  123. package/lib/documents/defaults.js.map +1 -0
  124. package/lib/documents/errors.js +101 -0
  125. package/lib/documents/errors.js.map +1 -0
  126. package/lib/documents/index.js +80 -0
  127. package/lib/documents/index.js.map +1 -0
  128. package/lib/documents/inspect/facts.js +161 -0
  129. package/lib/documents/inspect/facts.js.map +1 -0
  130. package/lib/documents/inspect/zip.js +108 -0
  131. package/lib/documents/inspect/zip.js.map +1 -0
  132. package/lib/documents/markdown/directives.js +135 -0
  133. package/lib/documents/markdown/directives.js.map +1 -0
  134. package/lib/documents/markdown/frontmatter.js +35 -0
  135. package/lib/documents/markdown/frontmatter.js.map +1 -0
  136. package/lib/documents/markdown/normalize.js +113 -0
  137. package/lib/documents/markdown/normalize.js.map +1 -0
  138. package/lib/documents/orchestrator/assets.js +243 -0
  139. package/lib/documents/orchestrator/assets.js.map +1 -0
  140. package/lib/documents/orchestrator/convert-document.js +186 -0
  141. package/lib/documents/orchestrator/convert-document.js.map +1 -0
  142. package/lib/documents/orchestrator/create-document.js +292 -0
  143. package/lib/documents/orchestrator/create-document.js.map +1 -0
  144. package/lib/documents/orchestrator/extract-document.js +162 -0
  145. package/lib/documents/orchestrator/extract-document.js.map +1 -0
  146. package/lib/documents/orchestrator/inspect-document.js +89 -0
  147. package/lib/documents/orchestrator/inspect-document.js.map +1 -0
  148. package/lib/documents/orchestrator/runtime-deps.js +59 -0
  149. package/lib/documents/orchestrator/runtime-deps.js.map +1 -0
  150. package/lib/documents/orchestrator/scope.js +132 -0
  151. package/lib/documents/orchestrator/scope.js.map +1 -0
  152. package/lib/documents/providers/docling.js +247 -0
  153. package/lib/documents/providers/docling.js.map +1 -0
  154. package/lib/documents/providers/libreoffice.js +130 -0
  155. package/lib/documents/providers/libreoffice.js.map +1 -0
  156. package/lib/documents/providers/markitdown.js +89 -0
  157. package/lib/documents/providers/markitdown.js.map +1 -0
  158. package/lib/documents/providers/pandoc.js +161 -0
  159. package/lib/documents/providers/pandoc.js.map +1 -0
  160. package/lib/documents/providers/process.js +164 -0
  161. package/lib/documents/providers/process.js.map +1 -0
  162. package/lib/documents/providers/registry.js +152 -0
  163. package/lib/documents/providers/registry.js.map +1 -0
  164. package/lib/documents/providers/shared.js +75 -0
  165. package/lib/documents/providers/shared.js.map +1 -0
  166. package/lib/documents/runtime.js +114 -0
  167. package/lib/documents/runtime.js.map +1 -0
  168. package/lib/documents/security/file-types.js +188 -0
  169. package/lib/documents/security/file-types.js.map +1 -0
  170. package/lib/documents/security/limits.js +78 -0
  171. package/lib/documents/security/limits.js.map +1 -0
  172. package/lib/documents/security/mime.js +43 -0
  173. package/lib/documents/security/mime.js.map +1 -0
  174. package/lib/documents/security/paths.js +133 -0
  175. package/lib/documents/security/paths.js.map +1 -0
  176. package/lib/documents/templates/registry.js +147 -0
  177. package/lib/documents/templates/registry.js.map +1 -0
  178. package/lib/documents/templates/resolver.js +59 -0
  179. package/lib/documents/templates/resolver.js.map +1 -0
  180. package/lib/documents/tools/convert.js +125 -0
  181. package/lib/documents/tools/convert.js.map +1 -0
  182. package/lib/documents/tools/create.js +187 -0
  183. package/lib/documents/tools/create.js.map +1 -0
  184. package/lib/documents/tools/index.js +41 -0
  185. package/lib/documents/tools/index.js.map +1 -0
  186. package/lib/documents/tools/inspect.js +135 -0
  187. package/lib/documents/tools/inspect.js.map +1 -0
  188. package/lib/documents/tools/shared.js +88 -0
  189. package/lib/documents/tools/shared.js.map +1 -0
  190. package/lib/documents/tools/to-markdown.js +125 -0
  191. package/lib/documents/tools/to-markdown.js.map +1 -0
  192. package/lib/documents/types.js +12 -0
  193. package/lib/documents/types.js.map +1 -0
  194. package/lib/index.js +225 -20
  195. package/lib/index.js.map +1 -1
  196. package/lib/integration-principals.js +22 -0
  197. package/lib/integration-principals.js.map +1 -0
  198. package/lib/lockdown-policy.js +15 -3
  199. package/lib/lockdown-policy.js.map +1 -1
  200. package/lib/personal-skills/errors.js +9 -0
  201. package/lib/personal-skills/errors.js.map +1 -0
  202. package/lib/personal-skills/host.js +80 -0
  203. package/lib/personal-skills/host.js.map +1 -0
  204. package/lib/personal-skills/index.js +10 -0
  205. package/lib/personal-skills/index.js.map +1 -0
  206. package/lib/personal-skills/paths.js +127 -0
  207. package/lib/personal-skills/paths.js.map +1 -0
  208. package/lib/personal-skills/provider.js +109 -0
  209. package/lib/personal-skills/provider.js.map +1 -0
  210. package/lib/personal-skills/remotes.js +40 -0
  211. package/lib/personal-skills/remotes.js.map +1 -0
  212. package/lib/personal-skills/service.js +686 -0
  213. package/lib/personal-skills/service.js.map +1 -0
  214. package/lib/personal-skills/skill-file.js +278 -0
  215. package/lib/personal-skills/skill-file.js.map +1 -0
  216. package/lib/personal-skills/skill-format.js +202 -0
  217. package/lib/personal-skills/skill-format.js.map +1 -0
  218. package/lib/personal-skills/watcher.js +96 -0
  219. package/lib/personal-skills/watcher.js.map +1 -0
  220. package/lib/profile.js +6 -4
  221. package/lib/profile.js.map +1 -1
  222. package/lib/prompt-notes.js +19 -0
  223. package/lib/prompt-notes.js.map +1 -1
  224. package/lib/provenance/file-preview.js +68 -21
  225. package/lib/provenance/file-preview.js.map +1 -1
  226. package/lib/provenance/host-store.js +44 -11
  227. package/lib/provenance/host-store.js.map +1 -1
  228. package/lib/provenance/index.js +1 -0
  229. package/lib/provenance/index.js.map +1 -1
  230. package/lib/provenance/normalize.js +3 -1
  231. package/lib/provenance/normalize.js.map +1 -1
  232. package/lib/provenance/snapshot-store.js +154 -0
  233. package/lib/provenance/snapshot-store.js.map +1 -0
  234. package/lib/qa-tools/activation-detector.js +53 -0
  235. package/lib/qa-tools/activation-detector.js.map +1 -0
  236. package/lib/qa-tools/activation-manager.js +111 -0
  237. package/lib/qa-tools/activation-manager.js.map +1 -0
  238. package/lib/qa-tools/catalog.js +108 -0
  239. package/lib/qa-tools/catalog.js.map +1 -0
  240. package/lib/qa-tools/durable-marker.js +115 -0
  241. package/lib/qa-tools/durable-marker.js.map +1 -0
  242. package/lib/qa-tools/index.js +83 -0
  243. package/lib/qa-tools/index.js.map +1 -0
  244. package/lib/qa-tools/lifecycle.js +64 -0
  245. package/lib/qa-tools/lifecycle.js.map +1 -0
  246. package/lib/qa-tools/types.js +2 -0
  247. package/lib/qa-tools/types.js.map +1 -0
  248. package/lib/resolve-config.js +5 -0
  249. package/lib/resolve-config.js.map +1 -1
  250. package/lib/secure-session.js +35 -3
  251. package/lib/secure-session.js.map +1 -1
  252. package/lib/starters.js +117 -0
  253. package/lib/starters.js.map +1 -0
  254. package/lib/typert.host.js +767 -22
  255. package/lib/typert.remote-client.d.ts +17 -1
  256. package/lib/typert.remote-client.js +609 -17
  257. package/lib/types/account-remotes.d.ts +3 -1
  258. package/lib/types/accounts/errors.d.ts +1 -1
  259. package/lib/types/accounts/file.d.ts +10 -0
  260. package/lib/types/accounts/store.d.ts +7 -1
  261. package/lib/types/client/QaAccountsController.d.ts +7 -1
  262. package/lib/types/client/QaSessionController.d.ts +12 -0
  263. package/lib/types/client/QaSurface.d.ts +14 -4
  264. package/lib/types/client/QaSurfaceGuard.d.ts +27 -0
  265. package/lib/types/client/QaTranscriptAdapter.d.ts +7 -0
  266. package/lib/types/client/components/QaComposer.d.ts +3 -1
  267. package/lib/types/client/components/QaHeader.d.ts +3 -1
  268. package/lib/types/client/components/QaModal.d.ts +5 -4
  269. package/lib/types/client/components/QaSidebar.d.ts +8 -11
  270. package/lib/types/client/components/QaWidthHandle.d.ts +13 -0
  271. package/lib/types/client/index.d.ts +1 -0
  272. package/lib/types/client/panels/PanelHost.d.ts +18 -0
  273. package/lib/types/client/panels/PanelLauncher.d.ts +5 -0
  274. package/lib/types/client/panels/contract.d.ts +83 -0
  275. package/lib/types/client/panels/index.d.ts +3 -0
  276. package/lib/types/client/panels/registry.d.ts +40 -0
  277. package/lib/types/client/project-session-state.d.ts +5 -0
  278. package/lib/types/client/settings/sections/documents.d.ts +13 -0
  279. package/lib/types/client/settings/sections.d.ts +1 -0
  280. package/lib/types/client/settings-extensions/contract.d.ts +32 -0
  281. package/lib/types/client/settings-extensions/index.d.ts +3 -0
  282. package/lib/types/client/settings-extensions/registry.d.ts +15 -0
  283. package/lib/types/client/settlement.d.ts +41 -5
  284. package/lib/types/client/source-preview.d.ts +8 -0
  285. package/lib/types/client/styles.d.ts +2 -0
  286. package/lib/types/client/subagent-codenames.d.ts +18 -0
  287. package/lib/types/client/types.d.ts +35 -3
  288. package/lib/types/client/user-settings/GeneralSettingsPage.d.ts +14 -0
  289. package/lib/types/client/user-settings/ProfileSettingsPage.d.ts +18 -0
  290. package/lib/types/client/user-settings/SkillCatalog.d.ts +16 -0
  291. package/lib/types/client/user-settings/SkillEditor.d.ts +42 -0
  292. package/lib/types/client/user-settings/SkillToolPicker.d.ts +17 -0
  293. package/lib/types/client/user-settings/SkillsSettingsPage.d.ts +15 -0
  294. package/lib/types/client/user-settings/StartersSettingsPage.d.ts +14 -0
  295. package/lib/types/client/user-settings/UserSettingsDialog.d.ts +43 -0
  296. package/lib/types/client/user-settings/copy.d.ts +25 -0
  297. package/lib/types/client/user-settings/draft.d.ts +51 -0
  298. package/lib/types/client/user-settings/fields.d.ts +43 -0
  299. package/lib/types/config-resolvers/tools.d.ts +6 -0
  300. package/lib/types/documents/artifacts/ids.d.ts +14 -0
  301. package/lib/types/documents/artifacts/manifest.d.ts +32 -0
  302. package/lib/types/documents/artifacts/store.d.ts +67 -0
  303. package/lib/types/documents/capabilities.d.ts +32 -0
  304. package/lib/types/documents/config.d.ts +27 -0
  305. package/lib/types/documents/defaults.d.ts +161 -0
  306. package/lib/types/documents/errors.d.ts +42 -0
  307. package/lib/types/documents/index.d.ts +63 -0
  308. package/lib/types/documents/inspect/facts.d.ts +43 -0
  309. package/lib/types/documents/inspect/zip.d.ts +28 -0
  310. package/lib/types/documents/markdown/directives.d.ts +39 -0
  311. package/lib/types/documents/markdown/frontmatter.d.ts +15 -0
  312. package/lib/types/documents/markdown/normalize.d.ts +30 -0
  313. package/lib/types/documents/orchestrator/assets.d.ts +55 -0
  314. package/lib/types/documents/orchestrator/convert-document.d.ts +25 -0
  315. package/lib/types/documents/orchestrator/create-document.d.ts +18 -0
  316. package/lib/types/documents/orchestrator/extract-document.d.ts +24 -0
  317. package/lib/types/documents/orchestrator/inspect-document.d.ts +12 -0
  318. package/lib/types/documents/orchestrator/runtime-deps.d.ts +43 -0
  319. package/lib/types/documents/orchestrator/scope.d.ts +52 -0
  320. package/lib/types/documents/providers/docling.d.ts +54 -0
  321. package/lib/types/documents/providers/libreoffice.d.ts +40 -0
  322. package/lib/types/documents/providers/markitdown.d.ts +28 -0
  323. package/lib/types/documents/providers/pandoc.d.ts +42 -0
  324. package/lib/types/documents/providers/process.d.ts +54 -0
  325. package/lib/types/documents/providers/registry.d.ts +68 -0
  326. package/lib/types/documents/providers/shared.d.ts +27 -0
  327. package/lib/types/documents/runtime.d.ts +59 -0
  328. package/lib/types/documents/security/file-types.d.ts +39 -0
  329. package/lib/types/documents/security/limits.d.ts +24 -0
  330. package/lib/types/documents/security/mime.d.ts +13 -0
  331. package/lib/types/documents/security/paths.d.ts +38 -0
  332. package/lib/types/documents/templates/registry.d.ts +50 -0
  333. package/lib/types/documents/templates/resolver.d.ts +30 -0
  334. package/lib/types/documents/tools/convert.d.ts +9 -0
  335. package/lib/types/documents/tools/create.d.ts +14 -0
  336. package/lib/types/documents/tools/index.d.ts +33 -0
  337. package/lib/types/documents/tools/inspect.d.ts +9 -0
  338. package/lib/types/documents/tools/shared.d.ts +77 -0
  339. package/lib/types/documents/tools/to-markdown.d.ts +12 -0
  340. package/lib/types/documents/types.d.ts +294 -0
  341. package/lib/types/index.d.ts +75 -3
  342. package/lib/types/integration-principals.d.ts +9 -0
  343. package/lib/types/lockdown-policy.d.ts +12 -2
  344. package/lib/types/personal-skills/errors.d.ts +11 -0
  345. package/lib/types/personal-skills/host.d.ts +42 -0
  346. package/lib/types/personal-skills/index.d.ts +10 -0
  347. package/lib/types/personal-skills/paths.d.ts +39 -0
  348. package/lib/types/personal-skills/provider.d.ts +33 -0
  349. package/lib/types/personal-skills/remotes.d.ts +35 -0
  350. package/lib/types/personal-skills/service.d.ts +131 -0
  351. package/lib/types/personal-skills/skill-file.d.ts +64 -0
  352. package/lib/types/personal-skills/skill-format.d.ts +100 -0
  353. package/lib/types/personal-skills/watcher.d.ts +39 -0
  354. package/lib/types/profile.d.ts +13 -0
  355. package/lib/types/prompt-notes.d.ts +9 -0
  356. package/lib/types/provenance/file-preview.d.ts +47 -4
  357. package/lib/types/provenance/host-store.d.ts +7 -1
  358. package/lib/types/provenance/index.d.ts +1 -0
  359. package/lib/types/provenance/snapshot-store.d.ts +23 -0
  360. package/lib/types/qa-tools/activation-detector.d.ts +29 -0
  361. package/lib/types/qa-tools/activation-manager.d.ts +47 -0
  362. package/lib/types/qa-tools/catalog.d.ts +40 -0
  363. package/lib/types/qa-tools/durable-marker.d.ts +16 -0
  364. package/lib/types/qa-tools/index.d.ts +40 -0
  365. package/lib/types/qa-tools/lifecycle.d.ts +44 -0
  366. package/lib/types/qa-tools/types.d.ts +45 -0
  367. package/lib/types/secure-session.d.ts +24 -2
  368. package/lib/types/starters.d.ts +45 -0
  369. package/lib/types/types.d.ts +202 -3
  370. package/package.json +24 -11
  371. package/scripts/repair-session-events.mjs +260 -0
  372. package/lib/client/components/QaProfile.js +0 -64
  373. package/lib/client/components/QaProfile.js.map +0 -1
  374. package/lib/types/client/components/QaProfile.d.ts +0 -25
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Docling provider — the default DOCX/PDF → Markdown extractor (§6.1, §15).
3
+ *
4
+ * Docling runs as a separate HTTP service (`docling-serve`) rather than inside
5
+ * the host process: it is the heaviest dependency of the pipeline, it is where
6
+ * OCR happens, and keeping it across a network boundary is what lets the QA
7
+ * image stay small (§21, §39).
8
+ *
9
+ * Two behaviours are deliberate:
10
+ *
11
+ * - images come back inline as base64 data URIs (the only representation that
12
+ * survives an HTTP boundary without a second fetch), and the extractor writes
13
+ * them out as real files under `assets/`, rewriting references to relative
14
+ * paths (§17.2);
15
+ * - nothing about the response shape is assumed beyond "there is Markdown
16
+ * somewhere in it": a deployment upgrades docling-serve independently of
17
+ * this plugin, so both the wrapped (`document.md_content`) and flat
18
+ * (`md_content`) spellings are read.
19
+ */
20
+ import { mkdir } from "node:fs/promises";
21
+ import path from "node:path";
22
+ import { DocumentError, sanitizeBackendOutput } from "../errors.js";
23
+ import { backendInfo } from "./shared.js";
24
+ const HEALTH_TIMEOUT_MS = 5_000;
25
+ const DATA_URI_PATTERN = /!\[([^\]]*)\]\(data:image\/(png|jpe?g|gif|webp|bmp|tiff);base64,([A-Za-z0-9+/=\s]+)\)/gu;
26
+ const EXTENSION_BY_MIME = {
27
+ png: "png",
28
+ jpg: "jpeg",
29
+ jpeg: "jpeg",
30
+ gif: "gif",
31
+ webp: "webp",
32
+ bmp: "bmp",
33
+ tiff: "tiff",
34
+ };
35
+ function joinUrl(baseUrl, route) {
36
+ const trimmed = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
37
+ return `${trimmed}${route}`;
38
+ }
39
+ export class DoclingExtractor {
40
+ options;
41
+ name = "docling";
42
+ constructor(options) {
43
+ this.options = options;
44
+ }
45
+ supports(_format) {
46
+ return true;
47
+ }
48
+ get fetchImpl() {
49
+ return this.options.fetchImpl ?? fetch;
50
+ }
51
+ async health() {
52
+ for (const route of ["/health", "/v1/health"]) {
53
+ try {
54
+ const response = await this.fetchImpl(joinUrl(this.options.baseUrl, route), {
55
+ method: "GET",
56
+ signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS),
57
+ });
58
+ if (response.ok)
59
+ return "ok";
60
+ }
61
+ catch {
62
+ continue;
63
+ }
64
+ }
65
+ return "unavailable";
66
+ }
67
+ async extract(input) {
68
+ const warnings = [];
69
+ const body = new FormData();
70
+ const file = await import("node:fs/promises").then((fs) => fs.readFile(input.inputPath));
71
+ body.append("files", new Blob([new Uint8Array(file)], { type: "application/octet-stream" }), path.basename(input.inputPath));
72
+ body.append("to_formats", "md");
73
+ body.append("image_export_mode", input.extractImages ? "embedded" : "placeholder");
74
+ body.append("abort_on_error", "false");
75
+ if (input.extractTables)
76
+ body.append("table_mode", "accurate");
77
+ if (input.ocr === "force") {
78
+ body.append("do_ocr", "true");
79
+ body.append("force_ocr", "true");
80
+ warnings.push({
81
+ code: "OCR_USED",
82
+ message: "Document was processed using OCR.",
83
+ backend: this.name,
84
+ });
85
+ }
86
+ else if (input.ocr === "off") {
87
+ body.append("do_ocr", "false");
88
+ }
89
+ else {
90
+ // Let Docling decide per page; the service turns OCR on for pages that
91
+ // carry no text layer.
92
+ body.append("do_ocr", "true");
93
+ body.append("force_ocr", "false");
94
+ }
95
+ for (const language of input.ocrLanguages ?? []) {
96
+ const clean = language.trim();
97
+ if (clean !== "")
98
+ body.append("ocr_lang", clean);
99
+ }
100
+ let response;
101
+ try {
102
+ response = await this.fetchImpl(joinUrl(this.options.baseUrl, "/v1/convert/file"), {
103
+ method: "POST",
104
+ body,
105
+ signal: input.signal ?? AbortSignal.timeout(this.options.timeoutMs),
106
+ });
107
+ }
108
+ catch (error) {
109
+ const aborted = input.signal?.aborted === true;
110
+ throw new DocumentError(aborted ? "BACKEND_TIMEOUT" : "BACKEND_UNAVAILABLE", aborted
111
+ ? "the document extractor was cancelled"
112
+ : `the document extractor is unreachable: ${sanitizeBackendOutput(error instanceof Error ? error.message : String(error))}`, { backend: this.name, cause: error });
113
+ }
114
+ if (!response.ok) {
115
+ const detail = sanitizeBackendOutput(await response.text().catch(() => ""));
116
+ throw new DocumentError(response.status === 503 ? "BACKEND_UNAVAILABLE" : "EXTRACTION_FAILED", `the document extractor answered ${response.status}${detail === "" ? "" : `: ${detail}`}`, { backend: this.name, details: { status: response.status } });
117
+ }
118
+ const raw = await response.text();
119
+ if (raw.length > this.options.maxResponseBytes) {
120
+ throw new DocumentError("DOCUMENT_TOO_LARGE", "the extracted document exceeds the configured response budget", { backend: this.name, details: { bytes: raw.length } });
121
+ }
122
+ let payload;
123
+ try {
124
+ payload = JSON.parse(raw);
125
+ }
126
+ catch (error) {
127
+ throw new DocumentError("EXTRACTION_FAILED", "the document extractor returned a response that is not JSON", { backend: this.name, cause: error });
128
+ }
129
+ const { markdown, pages, serviceVersion } = readDoclingPayload(payload, this.name);
130
+ const { text, assets } = await this.materializeAssets(markdown, input.assetsDir, input.extractImages, warnings);
131
+ if (input.preservePageMarkers && !/\f/u.test(text)) {
132
+ warnings.push({
133
+ code: "METADATA_PARTIALLY_EXTRACTED",
134
+ message: "the extractor reported no page boundaries for this document",
135
+ backend: this.name,
136
+ });
137
+ }
138
+ return {
139
+ markdown: text,
140
+ assets,
141
+ ...(pages === undefined ? {} : { pages }),
142
+ backend: backendInfo(this.name, serviceVersion),
143
+ warnings,
144
+ };
145
+ }
146
+ /**
147
+ * Write inline images out as files and rewrite the Markdown to reference
148
+ * them relatively. Images beyond the configured cap are dropped with a
149
+ * warning rather than silently inflating the artifact (§25).
150
+ */
151
+ async materializeAssets(markdown, assetsDir, extractImages, warnings) {
152
+ const matches = [...markdown.matchAll(DATA_URI_PATTERN)];
153
+ if (matches.length === 0) {
154
+ if (extractImages && markdown.includes("data:image/")) {
155
+ warnings.push({
156
+ code: "IMAGE_SKIPPED",
157
+ message: "images reported by the extractor could not be decoded",
158
+ backend: this.name,
159
+ });
160
+ }
161
+ return { text: markdown, assets: [] };
162
+ }
163
+ await mkdir(assetsDir, { recursive: true });
164
+ const assets = [];
165
+ const replacements = new Map();
166
+ let index = 0;
167
+ let skipped = 0;
168
+ const { writeFile } = await import("node:fs/promises");
169
+ for (const match of matches) {
170
+ const [full, alt = "", mime = "png", base64 = ""] = match;
171
+ if (index >= this.options.maxImages) {
172
+ skipped += 1;
173
+ replacements.set(full, alt);
174
+ continue;
175
+ }
176
+ const extension = EXTENSION_BY_MIME[mime.toLowerCase()] ?? "bin";
177
+ const fileName = `image-${String(index + 1).padStart(3, "0")}.${extension}`;
178
+ const payload = Buffer.from(base64.replace(/\s+/gu, ""), "base64");
179
+ if (payload.length === 0) {
180
+ skipped += 1;
181
+ replacements.set(full, alt);
182
+ continue;
183
+ }
184
+ await writeFile(path.join(assetsDir, fileName), payload);
185
+ assets.push({
186
+ path: fileName,
187
+ mediaType: `image/${extension === "jpg" ? "jpeg" : extension}`,
188
+ });
189
+ replacements.set(full, `![${alt}](assets/${fileName})`);
190
+ index += 1;
191
+ }
192
+ let text = markdown;
193
+ for (const [from, to] of replacements) {
194
+ text = text.split(from).join(to);
195
+ }
196
+ if (skipped > 0) {
197
+ warnings.push({
198
+ code: "IMAGE_SKIPPED",
199
+ message: `${skipped} image(s) were left out: the configured image budget is ${this.options.maxImages}`,
200
+ backend: this.name,
201
+ details: { skipped },
202
+ });
203
+ }
204
+ if (!extractImages && assets.length > 0) {
205
+ warnings.push({
206
+ code: "IMAGE_SKIPPED",
207
+ message: "extracted images were written anyway; extraction asked for none",
208
+ backend: this.name,
209
+ });
210
+ }
211
+ return { text, assets };
212
+ }
213
+ }
214
+ /** Read the Markdown out of a docling-serve response, in either spelling. */
215
+ export function readDoclingPayload(payload, backend) {
216
+ if (payload === null || typeof payload !== "object") {
217
+ throw new DocumentError("EXTRACTION_FAILED", "the extractor returned no document", {
218
+ backend,
219
+ });
220
+ }
221
+ const root = payload;
222
+ const status = root["status"];
223
+ if (typeof status === "string" && status.toLowerCase() !== "success") {
224
+ const errors = Array.isArray(root["errors"])
225
+ ? root["errors"]
226
+ .map((entry) => sanitizeBackendOutput(JSON.stringify(entry), 300))
227
+ .join("; ")
228
+ : "";
229
+ throw new DocumentError("EXTRACTION_FAILED", `the extractor reported "${status}"${errors === "" ? "" : `: ${errors}`}`, { backend, details: { status } });
230
+ }
231
+ const document = root["document"] !== null && typeof root["document"] === "object"
232
+ ? root["document"]
233
+ : root;
234
+ const markdown = document["md_content"] ?? document["markdown"];
235
+ if (typeof markdown !== "string") {
236
+ throw new DocumentError("EXTRACTION_FAILED", "the extractor returned no Markdown content", { backend });
237
+ }
238
+ const pagesSource = document["page_count"] ?? document["pages"] ?? root["page_count"];
239
+ const pages = typeof pagesSource === "number" ? pagesSource : undefined;
240
+ const version = root["version"] ?? document["version"];
241
+ return {
242
+ markdown,
243
+ ...(pages === undefined ? {} : { pages }),
244
+ ...(typeof version === "string" ? { serviceVersion: version } : {}),
245
+ };
246
+ }
247
+ //# sourceMappingURL=docling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docling.js","sourceRoot":"","sources":["../../../src/documents/providers/docling.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * LibreOffice provider — DOCX → PDF (§6.1, §14.1, §46).
3
+ *
4
+ * Two details matter beyond "call the converter":
5
+ *
6
+ * - every invocation gets its own `-env:UserInstallation` profile, because
7
+ * concurrent headless LibreOffice processes sharing one profile corrupt each
8
+ * other's state; the temp profile is removed afterwards on success and on
9
+ * failure alike;
10
+ * - a conversion that produced no file, timed out, or died is reported as a
11
+ * failure of this step only. The orchestrator keeps whatever earlier steps
12
+ * already produced (§45).
13
+ */
14
+ import { mkdtemp, readdir, rm, stat } from "node:fs/promises";
15
+ import { tmpdir } from "node:os";
16
+ import path from "node:path";
17
+ import { sha256OfFile } from "../artifacts/store.js";
18
+ import { DocumentError } from "../errors.js";
19
+ import { expectProcessOk, runProcess } from "./process.js";
20
+ import { backendInfo, parseVersionOutput, verifyOutput } from "./shared.js";
21
+ import { toFileUri } from "../security/paths.js";
22
+ const VERSION_TIMEOUT_MS = 20_000;
23
+ const MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
24
+ /** Flags that keep a headless conversion from touching shared user state. */
25
+ const HEADLESS_FLAGS = [
26
+ "--headless",
27
+ "--invisible",
28
+ "--norestore",
29
+ "--nolockcheck",
30
+ "--nodefault",
31
+ "--nofirststartwizard",
32
+ "--nologo",
33
+ ];
34
+ export class LibreOfficePdfConverter {
35
+ options;
36
+ name = "libreoffice";
37
+ cachedVersion;
38
+ constructor(options) {
39
+ this.options = options;
40
+ }
41
+ supports(source, target) {
42
+ return source === "docx" && target === "pdf";
43
+ }
44
+ async version() {
45
+ this.cachedVersion ??= this.probeVersion();
46
+ return await this.cachedVersion;
47
+ }
48
+ async probeVersion() {
49
+ if (this.options.versionProbe !== undefined)
50
+ return await this.options.versionProbe();
51
+ try {
52
+ const result = await runProcess(this.options.executable, ["--version"], {
53
+ timeoutMs: VERSION_TIMEOUT_MS,
54
+ maxStdoutBytes: 8 * 1024,
55
+ backend: this.name,
56
+ context: "reporting its version",
57
+ ...(this.options.programPrefixArgs === undefined
58
+ ? {}
59
+ : { programPrefixArgs: this.options.programPrefixArgs }),
60
+ });
61
+ if (result.exitCode !== 0)
62
+ return undefined;
63
+ return parseVersionOutput(result.stdout, this.name);
64
+ }
65
+ catch {
66
+ return undefined;
67
+ }
68
+ }
69
+ async convert(input) {
70
+ const outputDir = path.dirname(input.outputPath);
71
+ const profile = await mkdtemp(path.join(this.options.profileRoot ?? tmpdir(), "qa-libreoffice-"));
72
+ try {
73
+ const argv = [
74
+ ...HEADLESS_FLAGS,
75
+ `-env:UserInstallation=${toFileUri(profile)}`,
76
+ "--convert-to",
77
+ "pdf",
78
+ "--outdir",
79
+ outputDir,
80
+ input.inputPath,
81
+ ];
82
+ const result = await runProcess(this.options.executable, argv, {
83
+ cwd: input.workDir,
84
+ timeoutMs: this.options.timeoutMs,
85
+ maxStdoutBytes: MAX_OUTPUT_BYTES,
86
+ backend: this.name,
87
+ context: "converting DOCX to PDF",
88
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
89
+ ...(this.options.programPrefixArgs === undefined
90
+ ? {}
91
+ : { programPrefixArgs: this.options.programPrefixArgs }),
92
+ });
93
+ expectProcessOk(result, {
94
+ backend: this.name,
95
+ context: "converting DOCX to PDF",
96
+ fallbackCode: "CONVERSION_FAILED",
97
+ });
98
+ const produced = await this.locateOutput(outputDir, input.outputPath);
99
+ const verified = await verifyOutput(produced, this.name, "CONVERSION_FAILED");
100
+ return {
101
+ path: verified.path,
102
+ size: verified.size,
103
+ sha256: await sha256OfFile(verified.path),
104
+ backend: backendInfo(this.name, await this.version()),
105
+ warnings: [],
106
+ };
107
+ }
108
+ finally {
109
+ await rm(profile, { recursive: true, force: true }).catch(() => undefined);
110
+ }
111
+ }
112
+ /**
113
+ * LibreOffice derives the output name from the input, so the expected path
114
+ * is a prediction. When it is absent exactly one PDF in the output directory
115
+ * is accepted; anything else is a failure rather than a guess.
116
+ */
117
+ async locateOutput(outputDir, expected) {
118
+ const details = await stat(expected).catch(() => undefined);
119
+ if (details?.isFile() === true)
120
+ return expected;
121
+ const entries = await readdir(outputDir).catch(() => []);
122
+ const pdfs = entries.filter((entry) => entry.toLowerCase().endsWith(".pdf"));
123
+ if (pdfs.length === 1)
124
+ return path.join(outputDir, pdfs[0] ?? "");
125
+ throw new DocumentError("CONVERSION_FAILED", pdfs.length === 0
126
+ ? "the PDF converter reported success but produced no PDF"
127
+ : "the PDF converter produced an unexpected number of PDF files", { backend: this.name, details: { candidates: pdfs.length } });
128
+ }
129
+ }
130
+ //# sourceMappingURL=libreoffice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libreoffice.js","sourceRoot":"","sources":["../../../src/documents/providers/libreoffice.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * MarkItDown provider — the optional fast extractor (§6.2, §9).
3
+ *
4
+ * Kept behind `documents.markitdown.enabled` (off by default): it is a
5
+ * convenient fallback when Docling is unreachable and high-fidelity parsing is
6
+ * not needed, but it is not the extractor a QA report should be built on.
7
+ */
8
+ import { DocumentError } from "../errors.js";
9
+ import { expectProcessOk, runProcess } from "./process.js";
10
+ import { backendInfo, parseVersionOutput } from "./shared.js";
11
+ const VERSION_TIMEOUT_MS = 10_000;
12
+ export class MarkItDownExtractor {
13
+ options;
14
+ name = "markitdown";
15
+ cachedVersion;
16
+ constructor(options) {
17
+ this.options = options;
18
+ }
19
+ supports(format) {
20
+ return format === "docx" || format === "pdf";
21
+ }
22
+ async version() {
23
+ this.cachedVersion ??= this.probeVersion();
24
+ return await this.cachedVersion;
25
+ }
26
+ async probeVersion() {
27
+ if (this.options.versionProbe !== undefined)
28
+ return await this.options.versionProbe();
29
+ try {
30
+ const result = await runProcess(this.options.executable, ["--version"], {
31
+ timeoutMs: VERSION_TIMEOUT_MS,
32
+ maxStdoutBytes: 8 * 1024,
33
+ backend: this.name,
34
+ context: "reporting its version",
35
+ });
36
+ if (result.exitCode !== 0)
37
+ return undefined;
38
+ return parseVersionOutput(result.stdout, this.name);
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
44
+ async health() {
45
+ try {
46
+ return (await this.version()) === undefined ? "unavailable" : "ok";
47
+ }
48
+ catch {
49
+ return "unavailable";
50
+ }
51
+ }
52
+ async extract(input) {
53
+ const result = await runProcess(this.options.executable, [input.inputPath], {
54
+ cwd: input.workDir,
55
+ timeoutMs: this.options.timeoutMs,
56
+ maxStdoutBytes: this.options.maxStdoutBytes,
57
+ backend: this.name,
58
+ context: "extracting Markdown",
59
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
60
+ ...(this.options.programPrefixArgs === undefined
61
+ ? {}
62
+ : { programPrefixArgs: this.options.programPrefixArgs }),
63
+ });
64
+ expectProcessOk(result, {
65
+ backend: this.name,
66
+ context: "extracting Markdown",
67
+ fallbackCode: "EXTRACTION_FAILED",
68
+ });
69
+ const text = result.stdout.trimStart();
70
+ if (text.trim() === "") {
71
+ throw new DocumentError("EXTRACTION_FAILED", "the extractor produced no text for this document", { backend: this.name });
72
+ }
73
+ return {
74
+ markdown: text,
75
+ assets: [],
76
+ backend: backendInfo(this.name, await this.version()),
77
+ warnings: input.extractImages
78
+ ? [
79
+ {
80
+ code: "IMAGE_SKIPPED",
81
+ message: "this extractor does not report images; the response carries text only",
82
+ backend: this.name,
83
+ },
84
+ ]
85
+ : [],
86
+ };
87
+ }
88
+ }
89
+ //# sourceMappingURL=markitdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markitdown.js","sourceRoot":"","sources":["../../../src/documents/providers/markitdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Pandoc provider (§6.1, §13, §14.2).
3
+ *
4
+ * The command line is assembled here and nowhere else: the agent supplies
5
+ * content, a template *name* and a handful of enumerated options, and this
6
+ * module turns them into argv. There is no path through the pipeline by which
7
+ * a caller can add `--lua-filter`, an arbitrary `--resource-path`, or a
8
+ * `--pdf-engine-opt` (§26.1).
9
+ */
10
+ import path from "node:path";
11
+ import { sha256OfFile } from "../artifacts/store.js";
12
+ import { DocumentError } from "../errors.js";
13
+ import { expectProcessOk, runProcess } from "./process.js";
14
+ import { backendInfo, metadataArguments, parseVersionOutput, verifyOutput, } from "./shared.js";
15
+ const VERSION_TIMEOUT_MS = 10_000;
16
+ const MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
17
+ function spawnPandoc(options, argv, context) {
18
+ return runProcess(options.executable, argv, {
19
+ cwd: context.cwd,
20
+ timeoutMs: options.timeoutMs,
21
+ maxStdoutBytes: MAX_OUTPUT_BYTES,
22
+ backend: context.backend,
23
+ context: context.action,
24
+ ...(context.signal === undefined ? {} : { signal: context.signal }),
25
+ ...(options.programPrefixArgs === undefined
26
+ ? {}
27
+ : { programPrefixArgs: options.programPrefixArgs }),
28
+ });
29
+ }
30
+ async function probeVersion(options, backend) {
31
+ if (options.versionProbe !== undefined)
32
+ return await options.versionProbe();
33
+ try {
34
+ const result = await runProcess(options.executable, ["--version"], {
35
+ timeoutMs: VERSION_TIMEOUT_MS,
36
+ maxStdoutBytes: 8 * 1024,
37
+ backend,
38
+ context: "reporting its version",
39
+ ...(options.programPrefixArgs === undefined
40
+ ? {}
41
+ : { programPrefixArgs: options.programPrefixArgs }),
42
+ });
43
+ if (result.exitCode !== 0)
44
+ return undefined;
45
+ return parseVersionOutput(result.stdout, backend);
46
+ }
47
+ catch {
48
+ return undefined;
49
+ }
50
+ }
51
+ /** Pandoc renders Markdown into DOCX, optionally through a reference document. */
52
+ export class PandocDocxRenderer {
53
+ options;
54
+ name = "pandoc";
55
+ cachedVersion;
56
+ constructor(options) {
57
+ this.options = options;
58
+ }
59
+ async version() {
60
+ this.cachedVersion ??= probeVersion(this.options, this.name);
61
+ return await this.cachedVersion;
62
+ }
63
+ async render(input) {
64
+ const argv = [
65
+ input.sourcePath,
66
+ "--from=gfm",
67
+ "--to=docx",
68
+ `--output=${input.outputPath}`,
69
+ ...(input.referenceDocPath === undefined
70
+ ? []
71
+ : [`--reference-doc=${input.referenceDocPath}`]),
72
+ ...(input.assetsDir === undefined
73
+ ? []
74
+ : [`--resource-path=${input.assetsDir}`]),
75
+ ...(input.toc === true ? ["--toc", "--toc-depth=3"] : []),
76
+ ...(input.title === undefined ? [] : [`--metadata=title=${input.title}`]),
77
+ ...metadataArguments(input.metadata),
78
+ ];
79
+ const result = await spawnPandoc(this.options, argv, {
80
+ cwd: input.workDir,
81
+ backend: this.name,
82
+ action: "rendering DOCX",
83
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
84
+ });
85
+ if (result.truncated) {
86
+ throw new DocumentError("RENDER_FAILED", "the DOCX renderer produced more output than the pipeline accepts", { backend: this.name });
87
+ }
88
+ expectProcessOk(result, {
89
+ backend: this.name,
90
+ context: "rendering DOCX",
91
+ fallbackCode: "RENDER_FAILED",
92
+ });
93
+ const verified = await verifyOutput(input.outputPath, this.name, "RENDER_FAILED");
94
+ return {
95
+ path: verified.path,
96
+ size: verified.size,
97
+ sha256: await sha256OfFile(verified.path),
98
+ backend: backendInfo(this.name, await this.version()),
99
+ warnings: [],
100
+ };
101
+ }
102
+ }
103
+ /**
104
+ * Pandoc-driven PDF renderer. The only engine this pipeline enables is Typst,
105
+ * so the provider exists for `pdfMode: "typst"` alone (§14.2); the office route
106
+ * renders DOCX first and converts it with LibreOffice.
107
+ */
108
+ export class PandocTypstPdfRenderer {
109
+ options;
110
+ name = "typst";
111
+ cachedVersion;
112
+ constructor(options) {
113
+ this.options = options;
114
+ }
115
+ async version() {
116
+ this.cachedVersion ??= probeVersion(this.options, this.name);
117
+ return await this.cachedVersion;
118
+ }
119
+ async render(input) {
120
+ const argv = [
121
+ input.sourcePath,
122
+ "--from=gfm",
123
+ "--to=pdf",
124
+ "--standalone",
125
+ "--pdf-engine=typst",
126
+ `--output=${input.outputPath}`,
127
+ ...(input.typstTemplateDir === undefined
128
+ ? []
129
+ : [`--template=${path.join(input.typstTemplateDir, "main.typ")}`]),
130
+ ...(input.assetsDir === undefined
131
+ ? []
132
+ : [`--resource-path=${input.assetsDir}`]),
133
+ ...(input.pageSize === undefined
134
+ ? []
135
+ : [`-V=papersize=${input.pageSize}`]),
136
+ ...(input.toc === true ? ["--toc", "--toc-depth=3"] : []),
137
+ ...(input.title === undefined ? [] : [`--metadata=title=${input.title}`]),
138
+ ...metadataArguments(input.metadata),
139
+ ];
140
+ const result = await spawnPandoc(this.options, argv, {
141
+ cwd: input.workDir,
142
+ backend: this.name,
143
+ action: "rendering PDF with Typst",
144
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
145
+ });
146
+ expectProcessOk(result, {
147
+ backend: this.name,
148
+ context: "rendering PDF with Typst",
149
+ fallbackCode: "RENDER_FAILED",
150
+ });
151
+ const verified = await verifyOutput(input.outputPath, this.name, "RENDER_FAILED");
152
+ return {
153
+ path: verified.path,
154
+ size: verified.size,
155
+ sha256: await sha256OfFile(verified.path),
156
+ backend: backendInfo(this.name, await this.version()),
157
+ warnings: [],
158
+ };
159
+ }
160
+ }
161
+ //# sourceMappingURL=pandoc.js.map