@ecsplico/editor 2.1.2 → 3.1.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 (706) hide show
  1. package/CHANGELOG.md +78 -1
  2. package/README.md +39 -156
  3. package/dist/adapters/comments/drizzle.d.ts +1 -1
  4. package/dist/adapters/comments/record.d.ts +15 -0
  5. package/dist/adapters/comments/{client.js → rest-model.js} +3 -3
  6. package/dist/adapters/comments/rest-model.js.map +1 -0
  7. package/dist/adapters/comments/server.d.ts +2 -1
  8. package/dist/adapters/comments/server.js +2 -1
  9. package/dist/adapters/comments/server.js.map +1 -1
  10. package/dist/adapters/comments/types.d.ts +2 -2
  11. package/dist/adapters/document-state.d.ts +23 -0
  12. package/dist/adapters/document-state.js +66 -0
  13. package/dist/adapters/document-state.js.map +1 -0
  14. package/dist/adapters/documents.js +14 -11
  15. package/dist/adapters/documents.js.map +1 -1
  16. package/dist/adapters/drizzle.d.ts +2 -2
  17. package/dist/adapters/drizzle.js +97 -88
  18. package/dist/adapters/drizzle.js.map +1 -1
  19. package/dist/adapters/forge.d.ts +12 -7
  20. package/dist/adapters/forge.js +38 -45
  21. package/dist/adapters/forge.js.map +1 -1
  22. package/dist/adapters/http.d.ts +20 -0
  23. package/dist/adapters/http.js +68 -0
  24. package/dist/adapters/http.js.map +1 -0
  25. package/dist/adapters/index.d.ts +5 -5
  26. package/dist/adapters/json.d.ts +3 -3
  27. package/dist/adapters/json.js +58 -49
  28. package/dist/adapters/json.js.map +1 -1
  29. package/dist/adapters/memory.d.ts +21 -0
  30. package/dist/adapters/memory.js +53 -0
  31. package/dist/adapters/memory.js.map +1 -0
  32. package/dist/adapters/nitro.d.ts +27 -20
  33. package/dist/adapters/nitro.js +59 -163
  34. package/dist/adapters/nitro.js.map +1 -1
  35. package/dist/adapters/react.d.ts +55 -0
  36. package/dist/adapters/react.js +209 -0
  37. package/dist/adapters/react.js.map +1 -0
  38. package/dist/adapters/shared.d.ts +15 -21
  39. package/dist/adapters/shared.js +10 -8
  40. package/dist/adapters/shared.js.map +1 -1
  41. package/dist/adapters/vue.d.ts +15 -30
  42. package/dist/adapters/vue.js +36 -87
  43. package/dist/adapters/vue.js.map +1 -1
  44. package/dist/code/CodeSurface.vue.d.ts +2 -2
  45. package/dist/config/index.d.ts +105 -0
  46. package/dist/config/index.js +95 -0
  47. package/dist/config/index.js.map +1 -0
  48. package/dist/core/abilities.js +1 -0
  49. package/dist/core/abilities.js.map +1 -1
  50. package/dist/{adapters/routes.js → core/api-routes.js} +5 -3
  51. package/dist/core/api-routes.js.map +1 -0
  52. package/dist/core/backend-capability.d.ts +7 -0
  53. package/dist/core/backend-capability.js +17 -0
  54. package/dist/core/backend-capability.js.map +1 -0
  55. package/dist/core/backend-types.d.ts +245 -0
  56. package/dist/core/backend-types.js +17 -0
  57. package/dist/core/backend-types.js.map +1 -0
  58. package/dist/core/backend.d.ts +108 -0
  59. package/dist/core/backend.js +14 -0
  60. package/dist/core/backend.js.map +1 -0
  61. package/dist/core/block-convert.d.ts +7 -5
  62. package/dist/core/block-convert.js +28 -5
  63. package/dist/core/block-convert.js.map +1 -1
  64. package/dist/core/command-types.d.ts +96 -0
  65. package/dist/core/commands.d.ts +40 -0
  66. package/dist/core/commands.js +151 -0
  67. package/dist/core/commands.js.map +1 -0
  68. package/dist/core/context.d.ts +17 -20
  69. package/dist/core/context.js +24 -21
  70. package/dist/core/context.js.map +1 -1
  71. package/dist/core/core-feature.d.ts +22 -7
  72. package/dist/core/core-feature.js +51 -18
  73. package/dist/core/core-feature.js.map +1 -1
  74. package/dist/core/define-editor.d.ts +4 -3
  75. package/dist/core/define-editor.js +14 -7
  76. package/dist/core/define-editor.js.map +1 -1
  77. package/dist/core/document-markdown.js +12 -3
  78. package/dist/core/document-markdown.js.map +1 -1
  79. package/dist/core/editor-ui.d.ts +8 -1
  80. package/dist/core/editor-ui.js +9 -8
  81. package/dist/core/editor-ui.js.map +1 -1
  82. package/dist/core/extension-points.d.ts +3 -15
  83. package/dist/core/feature-context.d.ts +8 -7
  84. package/dist/core/feature-context.js +12 -11
  85. package/dist/core/feature-context.js.map +1 -1
  86. package/dist/core/feature.d.ts +41 -19
  87. package/dist/core/feature.js.map +1 -1
  88. package/dist/core/fences.d.ts +2 -1
  89. package/dist/core/fences.js +3 -2
  90. package/dist/core/fences.js.map +1 -1
  91. package/dist/core/fetch-error.d.ts +1 -1
  92. package/dist/core/fetch-error.js +3 -1
  93. package/dist/core/fetch-error.js.map +1 -1
  94. package/dist/core/hash.d.ts +5 -0
  95. package/dist/core/hash.js +11 -0
  96. package/dist/core/hash.js.map +1 -0
  97. package/dist/core/http-backend.d.ts +11 -0
  98. package/dist/core/http-backend.js +195 -0
  99. package/dist/core/http-backend.js.map +1 -0
  100. package/dist/core/index.d.ts +15 -9
  101. package/dist/core/index.js +13 -9
  102. package/dist/core/palette.d.ts +48 -0
  103. package/dist/core/palette.js +95 -0
  104. package/dist/core/palette.js.map +1 -0
  105. package/dist/core/schema/abilities.d.ts +2 -1
  106. package/dist/core/schema/abilities.js +5 -1
  107. package/dist/core/schema/abilities.js.map +1 -1
  108. package/dist/core/schema/index.d.ts +11 -5
  109. package/dist/core/schema/index.js +13 -8
  110. package/dist/core/schema/index.js.map +1 -1
  111. package/dist/core/schema/mark-flags.d.ts +8 -1
  112. package/dist/core/schema/of-features.d.ts +13 -0
  113. package/dist/core/schema/of-features.js +14 -0
  114. package/dist/core/schema/of-features.js.map +1 -0
  115. package/dist/core/slash.d.ts +8 -6
  116. package/dist/core/slash.js +24 -16
  117. package/dist/core/slash.js.map +1 -1
  118. package/dist/core/surface-session.js +15 -5
  119. package/dist/core/surface-session.js.map +1 -1
  120. package/dist/core/toolbar-items.d.ts +10 -4
  121. package/dist/core/toolbar-items.js +269 -195
  122. package/dist/core/toolbar-items.js.map +1 -1
  123. package/dist/core/transaction-guards.d.ts +21 -0
  124. package/dist/core/transaction-guards.js +49 -0
  125. package/dist/core/transaction-guards.js.map +1 -0
  126. package/dist/core/util.js +11 -0
  127. package/dist/core/util.js.map +1 -0
  128. package/dist/document/DocumentSurface.d.ts +1 -1
  129. package/dist/document/DocumentSurface.vue.d.ts +2 -2
  130. package/dist/features/ai/agent-op-review.d.ts +1 -1
  131. package/dist/features/ai/agent-op-review.js +1 -1
  132. package/dist/features/ai/agent-ops.js +1 -1
  133. package/dist/features/ai/ai-apply.d.ts +2 -2
  134. package/dist/features/ai/ai-apply.js +1 -1
  135. package/dist/features/ai/ai-review.js +1 -1
  136. package/dist/features/ai/ai-sse.d.ts +6 -6
  137. package/dist/features/ai/ai-sse.js +20 -63
  138. package/dist/features/ai/ai-sse.js.map +1 -1
  139. package/dist/features/ai/assistant.d.ts +8 -7
  140. package/dist/features/ai/assistant.js +3 -3
  141. package/dist/features/ai/assistant.js.map +1 -1
  142. package/dist/features/ai/block-actions.d.ts +3 -2
  143. package/dist/features/ai/block-actions.js +3 -2
  144. package/dist/features/ai/block-actions.js.map +1 -1
  145. package/dist/features/ai/components/AiSelectionMenu.js +1 -1
  146. package/dist/features/ai/components/DocumentChatAnswer.js +1 -1
  147. package/dist/features/ai/components/DocumentChatOps.vue.d.ts +1 -1
  148. package/dist/features/ai/components/SettingsModelProfiles.js +8 -8
  149. package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
  150. package/dist/features/ai/document-chat-model.d.ts +8 -7
  151. package/dist/features/ai/document-chat-model.js +5 -5
  152. package/dist/features/ai/document-chat-model.js.map +1 -1
  153. package/dist/features/ai/document-chat.js +1 -1
  154. package/dist/features/ai/feature.js +27 -14
  155. package/dist/features/ai/feature.js.map +1 -1
  156. package/dist/features/ai/ghost-autocomplete.d.ts +7 -6
  157. package/dist/features/ai/ghost-autocomplete.js +6 -9
  158. package/dist/features/ai/ghost-autocomplete.js.map +1 -1
  159. package/dist/features/ai/index.d.ts +4 -3
  160. package/dist/features/ai/index.js +10 -10
  161. package/dist/features/ai/model-profiles.d.ts +5 -4
  162. package/dist/features/ai/model-profiles.js +2 -2
  163. package/dist/features/ai/model-profiles.js.map +1 -1
  164. package/dist/features/ai/protocol/block-lines.js +1 -1
  165. package/dist/features/ai/protocol/block-lines.js.map +1 -1
  166. package/dist/features/ai/protocol/chat.js +6 -2
  167. package/dist/features/ai/protocol/chat.js.map +1 -1
  168. package/dist/features/ai/protocol/index.d.ts +3 -2
  169. package/dist/features/ai/protocol/models.d.ts +2 -16
  170. package/dist/features/ai/protocol/models.js.map +1 -1
  171. package/dist/features/ai/rate-limit.d.ts +1 -1
  172. package/dist/features/ai/rate-limit.js +3 -1
  173. package/dist/features/ai/rate-limit.js.map +1 -1
  174. package/dist/features/ai/react/AiSelectionMenu.js +2 -2
  175. package/dist/features/ai/react/AiSidebar.js +4 -4
  176. package/dist/features/ai/react/DocumentChatAnswer.js +1 -1
  177. package/dist/features/ai/react/DocumentChatOps.d.ts +1 -1
  178. package/dist/features/ai/react/DocumentChatOps.js +1 -1
  179. package/dist/features/ai/react/SettingsModelProfiles.js +8 -10
  180. package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
  181. package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
  182. package/dist/features/ai/react/use-ai-assistant.js +3 -3
  183. package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
  184. package/dist/features/ai/react/use-document-chat.js +2 -2
  185. package/dist/features/ai/react/use-document-chat.js.map +1 -1
  186. package/dist/features/ai/react/use-model-profiles.d.ts +2 -1
  187. package/dist/features/ai/selection-flow.d.ts +1 -1
  188. package/dist/features/ai/selection-flow.js +1 -1
  189. package/dist/features/ai/sidebar-flow.d.ts +1 -1
  190. package/dist/features/ai/sidebar-flow.js +1 -1
  191. package/dist/features/ai/use-ai-assistant.d.ts +1 -1
  192. package/dist/features/ai/use-ai-assistant.js +3 -3
  193. package/dist/features/ai/use-ai-assistant.js.map +1 -1
  194. package/dist/features/ai/use-document-chat.js +2 -2
  195. package/dist/features/ai/use-document-chat.js.map +1 -1
  196. package/dist/features/ai/use-model-profiles.d.ts +2 -1
  197. package/dist/features/authors/attribution.d.ts +1 -1
  198. package/dist/features/authors/feature.js +12 -11
  199. package/dist/features/authors/feature.js.map +1 -1
  200. package/dist/features/block-ui/block-actions.d.ts +1 -1
  201. package/dist/features/block-ui/block-actions.js +1 -1
  202. package/dist/features/block-ui/block-actions.js.map +1 -1
  203. package/dist/features/block-ui/components/BlockUi.js +1 -1
  204. package/dist/features/block-ui/feature.js +1 -0
  205. package/dist/features/block-ui/feature.js.map +1 -1
  206. package/dist/features/block-ui/react/BlockUi.js +1 -1
  207. package/dist/features/collab/anchor-resolver.js +1 -1
  208. package/dist/features/collab/feature.js +2 -0
  209. package/dist/features/collab/feature.js.map +1 -1
  210. package/dist/features/comments/components/CommentThreadView.vue.d.ts +2 -1
  211. package/dist/features/comments/feature.js +12 -11
  212. package/dist/features/comments/feature.js.map +1 -1
  213. package/dist/features/comments/index.d.ts +3 -2
  214. package/dist/features/comments/index.js +1 -1
  215. package/dist/features/comments/margin-layout.d.ts +3 -2
  216. package/dist/features/comments/model.d.ts +3 -67
  217. package/dist/features/comments/model.js +2 -2
  218. package/dist/features/comments/model.js.map +1 -1
  219. package/dist/features/comments/react/CommentThreadView.d.ts +3 -2
  220. package/dist/features/comments/react/use-comments.d.ts +2 -1
  221. package/dist/features/comments/react.d.ts +1 -1
  222. package/dist/features/comments/schema.d.ts +2 -52
  223. package/dist/features/comments/schema.js.map +1 -1
  224. package/dist/features/comments/snapshot-equality.js.map +1 -1
  225. package/dist/features/comments/use-comments.d.ts +3 -2
  226. package/dist/features/comments/vue.d.ts +1 -1
  227. package/dist/features/composites/accepted-children.d.ts +1 -0
  228. package/dist/features/composites/accepted-children.js +16 -1
  229. package/dist/features/composites/accepted-children.js.map +1 -1
  230. package/dist/features/composites/ai-brief.js +39 -0
  231. package/dist/features/composites/ai-brief.js.map +1 -1
  232. package/dist/features/composites/bibliography-command.d.ts +11 -0
  233. package/dist/features/composites/bibliography-form.js +90 -0
  234. package/dist/features/composites/bibliography-form.js.map +1 -0
  235. package/dist/features/composites/bibliography.d.ts +33 -0
  236. package/dist/features/composites/bibliography.js +120 -0
  237. package/dist/features/composites/bibliography.js.map +1 -0
  238. package/dist/features/composites/components/BibliographyEditor.js +261 -0
  239. package/dist/features/composites/components/BibliographyEditor.js.map +1 -0
  240. package/dist/features/composites/components/CompositeChrome.js +78 -29
  241. package/dist/features/composites/components/CompositeChrome.js.map +1 -1
  242. package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
  243. package/dist/features/composites/components/CompositeDetails.js +46 -11
  244. package/dist/features/composites/components/CompositeDetails.js.map +1 -1
  245. package/dist/features/composites/components/CompositeDetails.vue.d.ts +2 -1
  246. package/dist/features/composites/components/CompositeFieldEditor.js +64 -5
  247. package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
  248. package/dist/features/composites/components/CompositeInspector.js +20 -7
  249. package/dist/features/composites/components/CompositeInspector.js.map +1 -1
  250. package/dist/features/composites/components/CompositeTable.js +13 -4
  251. package/dist/features/composites/components/CompositeTable.js.map +1 -1
  252. package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
  253. package/dist/features/composites/components/CompositeView.js +11 -1
  254. package/dist/features/composites/components/CompositeView.js.map +1 -1
  255. package/dist/features/composites/components/DerivationBadge.js +103 -0
  256. package/dist/features/composites/components/DerivationBadge.js.map +1 -0
  257. package/dist/features/composites/components/ReferenceFieldSelect.js +60 -0
  258. package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -0
  259. package/dist/features/composites/components/ReferenceView.js +122 -0
  260. package/dist/features/composites/components/ReferenceView.js.map +1 -0
  261. package/dist/features/composites/components/ReferenceView.vue.d.ts +96 -0
  262. package/dist/features/composites/components/SettingsEditingTab.js +1 -1
  263. package/dist/features/composites/convert.js +2 -2
  264. package/dist/features/composites/convert.js.map +1 -1
  265. package/dist/features/composites/derivation.d.ts +61 -0
  266. package/dist/features/composites/derivation.js +98 -0
  267. package/dist/features/composites/derivation.js.map +1 -0
  268. package/dist/features/composites/derived-chrome.js +69 -0
  269. package/dist/features/composites/derived-chrome.js.map +1 -0
  270. package/dist/features/composites/feature.js +159 -109
  271. package/dist/features/composites/feature.js.map +1 -1
  272. package/dist/features/composites/fences.d.ts +4 -3
  273. package/dist/features/composites/fences.js +51 -7
  274. package/dist/features/composites/fences.js.map +1 -1
  275. package/dist/features/composites/index.d.ts +12 -3
  276. package/dist/features/composites/index.js +15 -6
  277. package/dist/features/composites/inspector-model.d.ts +4 -1
  278. package/dist/features/composites/inspector-model.js +8 -4
  279. package/dist/features/composites/inspector-model.js.map +1 -1
  280. package/dist/features/composites/kinds.d.ts +16 -2
  281. package/dist/features/composites/kinds.js +145 -6
  282. package/dist/features/composites/kinds.js.map +1 -1
  283. package/dist/features/composites/legacy.d.ts +4 -1
  284. package/dist/features/composites/legacy.js +56 -1
  285. package/dist/features/composites/legacy.js.map +1 -1
  286. package/dist/features/composites/meta-display.js +45 -2
  287. package/dist/features/composites/meta-display.js.map +1 -1
  288. package/dist/features/composites/meta-keys.d.ts +7 -0
  289. package/dist/features/composites/meta-keys.js +21 -0
  290. package/dist/features/composites/meta-keys.js.map +1 -0
  291. package/dist/features/composites/node-views.d.ts +6 -3
  292. package/dist/features/composites/node-views.js +7 -3
  293. package/dist/features/composites/node-views.js.map +1 -1
  294. package/dist/features/composites/nodes.d.ts +6 -1
  295. package/dist/features/composites/nodes.js +33 -7
  296. package/dist/features/composites/nodes.js.map +1 -1
  297. package/dist/features/composites/react/BibliographyEditor.js +229 -0
  298. package/dist/features/composites/react/BibliographyEditor.js.map +1 -0
  299. package/dist/features/composites/react/CompositeChrome.js +67 -19
  300. package/dist/features/composites/react/CompositeChrome.js.map +1 -1
  301. package/dist/features/composites/react/CompositeDetails.d.ts +2 -1
  302. package/dist/features/composites/react/CompositeDetails.js +45 -6
  303. package/dist/features/composites/react/CompositeDetails.js.map +1 -1
  304. package/dist/features/composites/react/CompositeFieldEditor.d.ts +1 -1
  305. package/dist/features/composites/react/CompositeFieldEditor.js +43 -1
  306. package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
  307. package/dist/features/composites/react/CompositeInspector.js +12 -6
  308. package/dist/features/composites/react/CompositeInspector.js.map +1 -1
  309. package/dist/features/composites/react/CompositeStatusMenu.js +1 -1
  310. package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
  311. package/dist/features/composites/react/CompositeTable.js +16 -2
  312. package/dist/features/composites/react/CompositeTable.js.map +1 -1
  313. package/dist/features/composites/react/CompositeTagsEditor.js +2 -2
  314. package/dist/features/composites/react/CompositeView.js +6 -1
  315. package/dist/features/composites/react/CompositeView.js.map +1 -1
  316. package/dist/features/composites/react/DerivationBadge.js +116 -0
  317. package/dist/features/composites/react/DerivationBadge.js.map +1 -0
  318. package/dist/features/composites/react/ReferenceFieldSelect.js +52 -0
  319. package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -0
  320. package/dist/features/composites/react/ReferenceView.d.ts +11 -0
  321. package/dist/features/composites/react/ReferenceView.js +115 -0
  322. package/dist/features/composites/react/ReferenceView.js.map +1 -0
  323. package/dist/features/composites/react/SettingsEditingTab.js +2 -2
  324. package/dist/features/composites/react.d.ts +2 -1
  325. package/dist/features/composites/react.js +7 -3
  326. package/dist/features/composites/react.js.map +1 -1
  327. package/dist/features/composites/reference-ai.js +16 -0
  328. package/dist/features/composites/reference-ai.js.map +1 -0
  329. package/dist/features/composites/reference-label.d.ts +19 -0
  330. package/dist/features/composites/reference-label.js +58 -0
  331. package/dist/features/composites/reference-label.js.map +1 -0
  332. package/dist/features/composites/reference-suggestion.d.ts +10 -0
  333. package/dist/features/composites/reference-suggestion.js +41 -0
  334. package/dist/features/composites/reference-suggestion.js.map +1 -0
  335. package/dist/features/composites/reference-text.d.ts +18 -0
  336. package/dist/features/composites/reference-text.js +89 -0
  337. package/dist/features/composites/reference-text.js.map +1 -0
  338. package/dist/features/composites/reference.d.ts +44 -0
  339. package/dist/features/composites/reference.js +148 -0
  340. package/dist/features/composites/reference.js.map +1 -0
  341. package/dist/features/composites/reveal-source.d.ts +32 -0
  342. package/dist/features/composites/reveal-source.js +89 -0
  343. package/dist/features/composites/reveal-source.js.map +1 -0
  344. package/dist/features/composites/rows.d.ts +25 -3
  345. package/dist/features/composites/rows.js +72 -10
  346. package/dist/features/composites/rows.js.map +1 -1
  347. package/dist/features/composites/schema.d.ts +9 -3
  348. package/dist/features/composites/schema.js +11 -4
  349. package/dist/features/composites/schema.js.map +1 -1
  350. package/dist/features/composites/table-model.js +12 -21
  351. package/dist/features/composites/table-model.js.map +1 -1
  352. package/dist/features/composites/vue.d.ts +3 -2
  353. package/dist/features/composites/vue.js +8 -4
  354. package/dist/features/composites/vue.js.map +1 -1
  355. package/dist/features/media/assets.d.ts +2 -0
  356. package/dist/features/media/assets.js +3 -2
  357. package/dist/features/media/assets.js.map +1 -1
  358. package/dist/features/media/components/FileView.js +13 -4
  359. package/dist/features/media/components/FileView.js.map +1 -1
  360. package/dist/features/media/feature.d.ts +3 -3
  361. package/dist/features/media/feature.js +21 -28
  362. package/dist/features/media/feature.js.map +1 -1
  363. package/dist/features/media/file-import.js +2 -2
  364. package/dist/features/media/file-import.js.map +1 -1
  365. package/dist/features/media/index.d.ts +2 -2
  366. package/dist/features/media/index.js +3 -3
  367. package/dist/features/media/react/AudioRecorderModal.js +1 -1
  368. package/dist/features/media/react/FileView.js +19 -2
  369. package/dist/features/media/react/FileView.js.map +1 -1
  370. package/dist/features/media/react.js +1 -1
  371. package/dist/features/media/schema.d.ts +8 -0
  372. package/dist/features/media/schema.js +126 -11
  373. package/dist/features/media/schema.js.map +1 -1
  374. package/dist/features/media/upload.d.ts +16 -14
  375. package/dist/features/media/upload.js +13 -19
  376. package/dist/features/media/upload.js.map +1 -1
  377. package/dist/features/mentions/index.d.ts +4 -3
  378. package/dist/features/mentions/index.js +4 -1
  379. package/dist/features/mentions/index.js.map +1 -1
  380. package/dist/features/mentions/mention-text.d.ts +1 -1
  381. package/dist/features/mentions/mention-text.js.map +1 -1
  382. package/dist/features/mentions/mention.d.ts +0 -6
  383. package/dist/features/mentions/mention.js.map +1 -1
  384. package/dist/features/mentions/metadata-defaults.d.ts +2 -2
  385. package/dist/features/mentions/metadata-defaults.js +3 -9
  386. package/dist/features/mentions/metadata-defaults.js.map +1 -1
  387. package/dist/features/mentions/schema.d.ts +2 -1
  388. package/dist/features/mentions/schema.js.map +1 -1
  389. package/dist/features/tables/feature.d.ts +2 -1
  390. package/dist/features/tables/feature.js +90 -70
  391. package/dist/features/tables/feature.js.map +1 -1
  392. package/dist/features/themes/components/SettingsAppearanceTab.js +6 -9
  393. package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
  394. package/dist/features/themes/feature.js +2 -0
  395. package/dist/features/themes/feature.js.map +1 -1
  396. package/dist/features/themes/index.d.ts +2 -1
  397. package/dist/features/themes/react/SettingsAppearanceTab.js +7 -10
  398. package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
  399. package/dist/features/themes/schema.d.ts +2 -6
  400. package/dist/features/themes/schema.js.map +1 -1
  401. package/dist/features/themes/theme-runtime.d.ts +1 -1
  402. package/dist/features/themes/theme-runtime.js +4 -2
  403. package/dist/features/themes/theme-runtime.js.map +1 -1
  404. package/dist/features/transcript/TranscriptSegmentView.js +48 -28
  405. package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
  406. package/dist/features/transcript/feature.js +21 -19
  407. package/dist/features/transcript/feature.js.map +1 -1
  408. package/dist/features/transcript/react/TranscriptSegmentView.js +55 -36
  409. package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
  410. package/dist/features/transcript/segment-node.d.ts +2 -0
  411. package/dist/features/transcript/segment-node.js +35 -7
  412. package/dist/features/transcript/segment-node.js.map +1 -1
  413. package/dist/i18n/de/composites.js +91 -1
  414. package/dist/i18n/de/composites.js.map +1 -1
  415. package/dist/i18n/de/integrations.js +49 -8
  416. package/dist/i18n/de/integrations.js.map +1 -1
  417. package/dist/i18n/de/media.js +0 -1
  418. package/dist/i18n/de/media.js.map +1 -1
  419. package/dist/i18n/de/palette.js +22 -0
  420. package/dist/i18n/de/palette.js.map +1 -0
  421. package/dist/i18n/de/tables.js +0 -1
  422. package/dist/i18n/de/tables.js.map +1 -1
  423. package/dist/i18n/de/transcript.js +2 -1
  424. package/dist/i18n/de/transcript.js.map +1 -1
  425. package/dist/i18n/de/tree.js +3 -0
  426. package/dist/i18n/de/tree.js.map +1 -1
  427. package/dist/i18n/de.d.ts +157 -11
  428. package/dist/i18n/de.js +3 -1
  429. package/dist/i18n/de.js.map +1 -1
  430. package/dist/i18n/en/composites.js +89 -1
  431. package/dist/i18n/en/composites.js.map +1 -1
  432. package/dist/i18n/en/integrations.js +49 -8
  433. package/dist/i18n/en/integrations.js.map +1 -1
  434. package/dist/i18n/en/media.js +0 -1
  435. package/dist/i18n/en/media.js.map +1 -1
  436. package/dist/i18n/en/palette.js +22 -0
  437. package/dist/i18n/en/palette.js.map +1 -0
  438. package/dist/i18n/en/tables.js +0 -1
  439. package/dist/i18n/en/tables.js.map +1 -1
  440. package/dist/i18n/en/transcript.js +2 -1
  441. package/dist/i18n/en/transcript.js.map +1 -1
  442. package/dist/i18n/en/tree.js +3 -0
  443. package/dist/i18n/en/tree.js.map +1 -1
  444. package/dist/i18n/en.js +3 -1
  445. package/dist/i18n/en.js.map +1 -1
  446. package/dist/index.d.ts +4 -3
  447. package/dist/integrations/composite-ai/bibliography-fetch.d.ts +31 -0
  448. package/dist/integrations/composite-ai/bibliography-fetch.js +159 -0
  449. package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -0
  450. package/dist/integrations/composite-ai/composite-fill.d.ts +30 -8
  451. package/dist/integrations/composite-ai/composite-fill.js +97 -56
  452. package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
  453. package/dist/integrations/composite-ai/composite-summary.d.ts +4 -12
  454. package/dist/integrations/composite-ai/composite-summary.js +7 -26
  455. package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
  456. package/dist/integrations/composite-ai/derive.d.ts +29 -0
  457. package/dist/integrations/composite-ai/derive.js +173 -0
  458. package/dist/integrations/composite-ai/derive.js.map +1 -0
  459. package/dist/integrations/composite-ai/index.d.ts +11 -7
  460. package/dist/integrations/composite-ai/index.js +72 -14
  461. package/dist/integrations/composite-ai/index.js.map +1 -1
  462. package/dist/integrations/composite-ai/rendition.d.ts +45 -0
  463. package/dist/integrations/composite-ai/rendition.js +314 -0
  464. package/dist/integrations/composite-ai/rendition.js.map +1 -0
  465. package/dist/integrations/composite-media/index.d.ts +7 -5
  466. package/dist/integrations/composite-media/index.js +86 -13
  467. package/dist/integrations/composite-media/index.js.map +1 -1
  468. package/dist/integrations/transcript-ai/index.d.ts +1 -1
  469. package/dist/integrations/transcript-ai/index.js +5 -2
  470. package/dist/integrations/transcript-ai/index.js.map +1 -1
  471. package/dist/integrations/transcript-ai/protocol.d.ts +2 -12
  472. package/dist/integrations/transcript-ai/protocol.js +0 -2
  473. package/dist/integrations/transcript-ai/protocol.js.map +1 -1
  474. package/dist/integrations/transcript-ai/transcript-cleanup.d.ts +5 -5
  475. package/dist/integrations/transcript-ai/transcript-cleanup.js +7 -10
  476. package/dist/integrations/transcript-ai/transcript-cleanup.js.map +1 -1
  477. package/dist/markdown/MarkdownSurface.vue.d.ts +12 -11
  478. package/dist/markdown/MarkdownSurface2.js +3 -6
  479. package/dist/markdown/MarkdownSurface2.js.map +1 -1
  480. package/dist/markdown/document.js +1 -1
  481. package/dist/markdown/source-mode.d.ts +1 -1
  482. package/dist/nuxt/module.d.ts +1402 -54
  483. package/dist/nuxt/module.js +6 -49
  484. package/dist/nuxt/module.js.map +1 -1
  485. package/dist/nuxt/runtime/install-context.d.ts +7 -3
  486. package/dist/nuxt/runtime/install-context.js +14 -8
  487. package/dist/nuxt/runtime/install-context.js.map +1 -1
  488. package/dist/nuxt/runtime/plugins/editor-context-nuxt-ui.client.ts +2 -2
  489. package/dist/nuxt/runtime/server/plugins/editor-server.js +20 -12
  490. package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
  491. package/dist/presets/compose.d.ts +94 -0
  492. package/dist/presets/compose.js +164 -0
  493. package/dist/presets/compose.js.map +1 -0
  494. package/dist/react/AdvancedEditor.d.ts +15 -15
  495. package/dist/react/AdvancedEditor.js +15 -13
  496. package/dist/react/AdvancedEditor.js.map +1 -1
  497. package/dist/react/EditorCommandPalette.d.ts +13 -0
  498. package/dist/react/EditorCommandPalette.js +118 -0
  499. package/dist/react/EditorCommandPalette.js.map +1 -0
  500. package/dist/react/EditorSettingsModal.d.ts +5 -5
  501. package/dist/react/EditorSettingsModal.js +7 -4
  502. package/dist/react/EditorSettingsModal.js.map +1 -1
  503. package/dist/react/EditorSettingsPanel.d.ts +7 -7
  504. package/dist/react/EditorSettingsPanel.js +8 -5
  505. package/dist/react/EditorSettingsPanel.js.map +1 -1
  506. package/dist/react/EditorSurface.d.ts +7 -7
  507. package/dist/react/EditorSurface.js +10 -6
  508. package/dist/react/EditorSurface.js.map +1 -1
  509. package/dist/react/EditorToolbar.d.ts +4 -6
  510. package/dist/react/EditorToolbar.js +29 -37
  511. package/dist/react/EditorToolbar.js.map +1 -1
  512. package/dist/react/SimpleEditor.d.ts +22 -23
  513. package/dist/react/SimpleEditor.js +21 -7
  514. package/dist/react/SimpleEditor.js.map +1 -1
  515. package/dist/react/advanced.d.ts +4 -3
  516. package/dist/react/advanced.js +2 -2
  517. package/dist/react/compose.d.ts +20 -0
  518. package/dist/react/compose.js +49 -0
  519. package/dist/react/compose.js.map +1 -0
  520. package/dist/react/composed-surface.d.ts +39 -0
  521. package/dist/react/composed-surface.js +71 -0
  522. package/dist/react/composed-surface.js.map +1 -0
  523. package/dist/react/context.js +6 -2
  524. package/dist/react/context.js.map +1 -1
  525. package/dist/react/index.d.ts +2 -1
  526. package/dist/react/index.js +2 -1
  527. package/dist/react/key-labels.js +15 -0
  528. package/dist/react/key-labels.js.map +1 -0
  529. package/dist/react/settings.d.ts +1 -1
  530. package/dist/react/simple.d.ts +2 -2
  531. package/dist/react/ui/command.js +36 -1
  532. package/dist/react/ui/command.js.map +1 -1
  533. package/dist/schema/advanced.d.ts +6 -6
  534. package/dist/schema/advanced.js +26 -29
  535. package/dist/schema/advanced.js.map +1 -1
  536. package/dist/server/ai.d.ts +5 -16
  537. package/dist/server/ai.js.map +1 -1
  538. package/dist/server/auth.d.ts +9 -0
  539. package/dist/server/collab-state.d.ts +1 -1
  540. package/dist/server/collab-state.js.map +1 -1
  541. package/dist/server/collab.d.ts +13 -13
  542. package/dist/server/collab.js +34 -18
  543. package/dist/server/collab.js.map +1 -1
  544. package/dist/server/crossref.js +78 -0
  545. package/dist/server/crossref.js.map +1 -0
  546. package/dist/server/errors.d.ts +1 -1
  547. package/dist/server/errors.js +1 -1
  548. package/dist/server/errors.js.map +1 -1
  549. package/dist/server/extract.js +308 -0
  550. package/dist/server/extract.js.map +1 -0
  551. package/dist/server/h3.d.ts +8 -0
  552. package/dist/{nuxt/runtime/server/utils/editor-route.js → server/h3.js} +8 -16
  553. package/dist/server/h3.js.map +1 -0
  554. package/dist/server/handlers/ai.d.ts +32 -10
  555. package/dist/server/handlers/ai.js +172 -37
  556. package/dist/server/handlers/ai.js.map +1 -1
  557. package/dist/server/handlers/context.d.ts +12 -5
  558. package/dist/server/handlers/context.js +10 -4
  559. package/dist/server/handlers/context.js.map +1 -1
  560. package/dist/server/handlers/editor.d.ts +19 -13
  561. package/dist/server/handlers/editor.js +49 -38
  562. package/dist/server/handlers/editor.js.map +1 -1
  563. package/dist/server/handlers/index.d.ts +4 -4
  564. package/dist/server/handlers/index.js +4 -4
  565. package/dist/server/host.d.ts +16 -25
  566. package/dist/server/host.js +58 -41
  567. package/dist/server/host.js.map +1 -1
  568. package/dist/server/index.d.ts +6 -4
  569. package/dist/server/index.js +3 -2
  570. package/dist/server/pdf.js +97 -0
  571. package/dist/server/pdf.js.map +1 -0
  572. package/dist/server/{adapter.d.ts → ports.d.ts} +81 -30
  573. package/dist/server/ports.js +29 -0
  574. package/dist/server/ports.js.map +1 -0
  575. package/dist/server/routes.d.ts +22 -0
  576. package/dist/server/routes.js +144 -0
  577. package/dist/server/routes.js.map +1 -0
  578. package/dist/settings/index.d.ts +1 -1
  579. package/dist/settings/index.js.map +1 -1
  580. package/dist/styles/composites.css +25 -0
  581. package/dist/tree/DocumentTree.js +56 -29
  582. package/dist/tree/DocumentTree.js.map +1 -1
  583. package/dist/tree/react/DocumentTree.js +23 -0
  584. package/dist/tree/react/DocumentTree.js.map +1 -1
  585. package/dist/tree/tree-host.js +2 -2
  586. package/dist/tree/tree-items.js +1 -1
  587. package/dist/vue/AdvancedEditor.js +30 -9
  588. package/dist/vue/AdvancedEditor.js.map +1 -1
  589. package/dist/vue/AdvancedEditor.vue.d.ts +32 -12
  590. package/dist/vue/SimpleEditor.js +62 -16
  591. package/dist/vue/SimpleEditor.js.map +1 -1
  592. package/dist/vue/SimpleEditor.vue.d.ts +39 -9
  593. package/dist/vue/advanced.d.ts +3 -2
  594. package/dist/vue/advanced.js +2 -2
  595. package/dist/vue/components/EditorCommandPalette.js +91 -0
  596. package/dist/vue/components/EditorCommandPalette.js.map +1 -0
  597. package/dist/vue/components/EditorCommandPalette.vue.d.ts +15 -0
  598. package/dist/vue/components/EditorSettingsModal.js +10 -6
  599. package/dist/vue/components/EditorSettingsModal.js.map +1 -1
  600. package/dist/vue/components/EditorSettingsModal.vue.d.ts +4 -4
  601. package/dist/vue/components/EditorSettingsPanel.js +10 -6
  602. package/dist/vue/components/EditorSettingsPanel.js.map +1 -1
  603. package/dist/vue/components/EditorSettingsPanel.vue.d.ts +6 -6
  604. package/dist/vue/components/EditorSurface.js +11 -6
  605. package/dist/vue/components/EditorSurface.js.map +1 -1
  606. package/dist/vue/components/EditorSurface.vue.d.ts +11 -11
  607. package/dist/vue/components/EditorToolbar.js +41 -49
  608. package/dist/vue/components/EditorToolbar.js.map +1 -1
  609. package/dist/vue/components/EditorToolbar.vue.d.ts +2 -4
  610. package/dist/vue/compose.d.ts +17 -0
  611. package/dist/vue/compose.js +51 -0
  612. package/dist/vue/compose.js.map +1 -0
  613. package/dist/vue/context-key.d.ts +6 -0
  614. package/dist/vue/context-key.js +6 -0
  615. package/dist/vue/context-key.js.map +1 -0
  616. package/dist/vue/context.d.ts +8 -6
  617. package/dist/vue/context.js +6 -5
  618. package/dist/vue/context.js.map +1 -1
  619. package/dist/vue/index.d.ts +10 -8
  620. package/dist/vue/index.js +10 -8
  621. package/dist/vue/kit/index.d.ts +2 -2
  622. package/dist/vue/kit/nuxt-ui.js +23 -0
  623. package/dist/vue/kit/nuxt-ui.js.map +1 -1
  624. package/dist/vue/kit/types.d.ts +40 -1
  625. package/package.json +30 -16
  626. package/dist/adapters/comments/client.d.ts +0 -64
  627. package/dist/adapters/comments/client.js.map +0 -1
  628. package/dist/adapters/routes.js.map +0 -1
  629. package/dist/core/toolbar.d.ts +0 -74
  630. package/dist/core/toolbar.js +0 -45
  631. package/dist/core/toolbar.js.map +0 -1
  632. package/dist/integrations/composite-ai/document-transcribe.d.ts +0 -14
  633. package/dist/integrations/composite-ai/document-transcribe.js +0 -89
  634. package/dist/integrations/composite-ai/document-transcribe.js.map +0 -1
  635. package/dist/nuxt/runtime/server/api/ai/chat.post.d.ts +0 -5
  636. package/dist/nuxt/runtime/server/api/ai/chat.post.js +0 -8
  637. package/dist/nuxt/runtime/server/api/ai/chat.post.js.map +0 -1
  638. package/dist/nuxt/runtime/server/api/ai/complete.post.d.ts +0 -5
  639. package/dist/nuxt/runtime/server/api/ai/complete.post.js +0 -8
  640. package/dist/nuxt/runtime/server/api/ai/complete.post.js.map +0 -1
  641. package/dist/nuxt/runtime/server/api/ai/generate.post.d.ts +0 -5
  642. package/dist/nuxt/runtime/server/api/ai/generate.post.js +0 -8
  643. package/dist/nuxt/runtime/server/api/ai/generate.post.js.map +0 -1
  644. package/dist/nuxt/runtime/server/api/ai/models.get.d.ts +0 -5
  645. package/dist/nuxt/runtime/server/api/ai/models.get.js +0 -8
  646. package/dist/nuxt/runtime/server/api/ai/models.get.js.map +0 -1
  647. package/dist/nuxt/runtime/server/api/ai/transcribe.post.d.ts +0 -5
  648. package/dist/nuxt/runtime/server/api/ai/transcribe.post.js +0 -8
  649. package/dist/nuxt/runtime/server/api/ai/transcribe.post.js.map +0 -1
  650. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.d.ts +0 -5
  651. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js +0 -8
  652. package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js.map +0 -1
  653. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.d.ts +0 -5
  654. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js +0 -8
  655. package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js.map +0 -1
  656. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.d.ts +0 -5
  657. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js +0 -8
  658. package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js.map +0 -1
  659. package/dist/nuxt/runtime/server/api/editor/settings.get.d.ts +0 -5
  660. package/dist/nuxt/runtime/server/api/editor/settings.get.js +0 -8
  661. package/dist/nuxt/runtime/server/api/editor/settings.get.js.map +0 -1
  662. package/dist/nuxt/runtime/server/api/editor/settings.put.d.ts +0 -5
  663. package/dist/nuxt/runtime/server/api/editor/settings.put.js +0 -8
  664. package/dist/nuxt/runtime/server/api/editor/settings.put.js.map +0 -1
  665. package/dist/nuxt/runtime/server/api/editor/tags.get.d.ts +0 -5
  666. package/dist/nuxt/runtime/server/api/editor/tags.get.js +0 -8
  667. package/dist/nuxt/runtime/server/api/editor/tags.get.js.map +0 -1
  668. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.d.ts +0 -5
  669. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js +0 -8
  670. package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js.map +0 -1
  671. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.d.ts +0 -5
  672. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js +0 -8
  673. package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js.map +0 -1
  674. package/dist/nuxt/runtime/server/api/editor/themes/index.get.d.ts +0 -5
  675. package/dist/nuxt/runtime/server/api/editor/themes/index.get.js +0 -8
  676. package/dist/nuxt/runtime/server/api/editor/themes/index.get.js.map +0 -1
  677. package/dist/nuxt/runtime/server/api/editor/themes/index.post.d.ts +0 -5
  678. package/dist/nuxt/runtime/server/api/editor/themes/index.post.js +0 -8
  679. package/dist/nuxt/runtime/server/api/editor/themes/index.post.js.map +0 -1
  680. package/dist/nuxt/runtime/server/api/editor/users.get.d.ts +0 -5
  681. package/dist/nuxt/runtime/server/api/editor/users.get.js +0 -8
  682. package/dist/nuxt/runtime/server/api/editor/users.get.js.map +0 -1
  683. package/dist/nuxt/runtime/server/plugins/collab.d.ts +0 -5
  684. package/dist/nuxt/runtime/server/plugins/collab.js +0 -10
  685. package/dist/nuxt/runtime/server/plugins/collab.js.map +0 -1
  686. package/dist/nuxt/runtime/server/routes/collab/[id].d.ts +0 -5
  687. package/dist/nuxt/runtime/server/routes/collab/[id].js +0 -35
  688. package/dist/nuxt/runtime/server/routes/collab/[id].js.map +0 -1
  689. package/dist/nuxt/runtime/server/utils/editor-route.d.ts +0 -11
  690. package/dist/nuxt/runtime/server/utils/editor-route.js.map +0 -1
  691. package/dist/presets/advanced.d.ts +0 -33
  692. package/dist/presets/advanced.js +0 -50
  693. package/dist/presets/advanced.js.map +0 -1
  694. package/dist/presets/simple.d.ts +0 -9
  695. package/dist/presets/simple.js +0 -12
  696. package/dist/presets/simple.js.map +0 -1
  697. package/dist/react/advanced-preset.d.ts +0 -11
  698. package/dist/react/advanced-preset.js +0 -31
  699. package/dist/react/advanced-preset.js.map +0 -1
  700. package/dist/vue/advanced-preset.d.ts +0 -13
  701. package/dist/vue/advanced-preset.js +0 -33
  702. package/dist/vue/advanced-preset.js.map +0 -1
  703. package/docs/extending.md +0 -538
  704. package/docs/integration.md +0 -632
  705. package/docs/llms.md +0 -383
  706. package/docs/usage.md +0 -1076
@@ -1,17 +1,39 @@
1
1
  import { Translate } from "../../i18n/index.js";
2
+ import { EditorBackend } from "../../core/backend.js";
2
3
  import { Notifier } from "../../core/notify.js";
3
- import { ModelRef } from "../../features/ai/protocol/models.js";
4
+ import { ModelRef } from "../../core/backend-types.js";
4
5
  import "../../features/ai/index.js";
5
6
  import { Editor } from "@tiptap/core";
6
- import { $Fetch } from "ofetch";
7
7
  //#region src/integrations/composite-ai/composite-fill.d.ts
8
8
  /**
9
- * Fills the body of the composite at `pos`: its brief (`compositeAiBrief`) plus the preset's `aiBlockData` → task
10
- * `fill-block` (`generate` slot); the result opens the in-document diff review over the body (`startAiReview`), so
11
- * nothing is written until accepted. The body range is anchored when the run starts, so edits while the data loads or
12
- * the result streams do not misplace it. A contributor that rejects cancels the run before any request is sent. Title,
13
- * fields and the other chrome stay untouched. Notices go through `notify`, in the language of `t`.
9
+ * How `generateCompositeBody` ended. `done` carries the streamed Markdown (possibly empty); `data-error`: a
10
+ * contributor of `aiBlockData` rejected, before any request was sent (`message`); `error`: the request failed
11
+ * (`message`); `aborted` also covers a destroyed editor and a node that is no composite of an `ai` kind.
14
12
  */
15
- export declare function fillComposite(editor: Editor, pos: number, fetch: $Fetch, modelRef: (slot: 'generate') => ModelRef, notify: Notifier, t: Translate): Promise<void>;
13
+ export type CompositeBodyResult = {
14
+ status: 'done';
15
+ output: string;
16
+ } | {
17
+ status: 'rate-limited' | 'aborted';
18
+ output: string;
19
+ } | {
20
+ status: 'data-error' | 'error';
21
+ output: string;
22
+ message: string;
23
+ };
24
+ /**
25
+ * The request half of „Baustein füllen (KI)“: the brief (`compositeAiBrief`) of the composite at `pos` plus the preset's
26
+ * `aiBlockData` → task `fill-block` (`generate` slot), streamed to completion. Writes nothing; `fillComposite` opens
27
+ * the diff review with the result, `deriveComposite` writes it into a new Baustein. A contributor that rejects cancels
28
+ * the run before any request is sent. Never throws.
29
+ */
30
+ export declare function generateCompositeBody(editor: Editor, pos: number, ai: NonNullable<EditorBackend['ai']>, modelRef: (slot: 'generate') => ModelRef, t: Translate, signal: AbortSignal): Promise<CompositeBodyResult>;
31
+ /**
32
+ * Fills the body of the composite at `pos` (`generateCompositeBody`); the result opens the in-document diff review over
33
+ * the body (`startAiReview`), so nothing is written until accepted. The body range is anchored when the run starts, so
34
+ * edits while the data loads or the result streams do not misplace it. Title, fields and the other chrome stay
35
+ * untouched. Notices go through `notify`, in the language of `t`.
36
+ */
37
+ export declare function fillComposite(editor: Editor, pos: number, ai: NonNullable<EditorBackend['ai']>, modelRef: (slot: 'generate') => ModelRef, notify: Notifier, t: Translate): Promise<void>;
16
38
  //#endregion
17
39
  //# sourceMappingURL=composite-fill.d.ts.map
@@ -11,13 +11,95 @@ import { postAiSse } from "../../features/ai/ai-sse.js";
11
11
  /** Entries of `aiBlockData` that travel with a request (the server accepts at most as many). */
12
12
  const MAX_BLOCK_DATA = 10;
13
13
  /**
14
- * Fills the body of the composite at `pos`: its brief (`compositeAiBrief`) plus the preset's `aiBlockData` → task
15
- * `fill-block` (`generate` slot); the result opens the in-document diff review over the body (`startAiReview`), so
16
- * nothing is written until accepted. The body range is anchored when the run starts, so edits while the data loads or
17
- * the result streams do not misplace it. A contributor that rejects cancels the run before any request is sent. Title,
18
- * fields and the other chrome stay untouched. Notices go through `notify`, in the language of `t`.
14
+ * The request half of „Baustein füllen (KI)“: the brief (`compositeAiBrief`) of the composite at `pos` plus the preset's
15
+ * `aiBlockData` → task `fill-block` (`generate` slot), streamed to completion. Writes nothing; `fillComposite` opens
16
+ * the diff review with the result, `deriveComposite` writes it into a new Baustein. A contributor that rejects cancels
17
+ * the run before any request is sent. Never throws.
19
18
  */
20
- async function fillComposite(editor, pos, fetch, modelRef, notify, t) {
19
+ async function generateCompositeBody(editor, pos, ai, modelRef, t, signal) {
20
+ const brief = compositeAiBrief(editor, pos);
21
+ const node = editor.state.doc.nodeAt(pos);
22
+ if (!brief || !node) return {
23
+ status: "aborted",
24
+ output: ""
25
+ };
26
+ let data;
27
+ try {
28
+ data = (await aiBlockDataOf(editor)({
29
+ editor,
30
+ node,
31
+ pos,
32
+ signal
33
+ })).slice(0, MAX_BLOCK_DATA).map(({ label, text }) => ({
34
+ label,
35
+ text: text.slice(0, AI_LIMITS.block.data)
36
+ }));
37
+ } catch (error) {
38
+ if (signal.aborted || editor.isDestroyed) return {
39
+ status: "aborted",
40
+ output: ""
41
+ };
42
+ return {
43
+ status: "data-error",
44
+ output: "",
45
+ message: error instanceof Error ? error.message : String(error)
46
+ };
47
+ }
48
+ if (signal.aborted || editor.isDestroyed) return {
49
+ status: "aborted",
50
+ output: ""
51
+ };
52
+ const block = {
53
+ kind: brief.kind,
54
+ path: brief.path,
55
+ title: brief.title,
56
+ description: brief.description,
57
+ fields: brief.fields.map(({ label, value }) => ({
58
+ label,
59
+ value
60
+ })),
61
+ instructions: brief.instructions,
62
+ skeleton: brief.skeleton,
63
+ body: brief.body,
64
+ data
65
+ };
66
+ let output = "";
67
+ const outcome = await postAiSse(ai, "generate", {
68
+ task: "fill-block",
69
+ prompt: "",
70
+ selection: "",
71
+ context: documentMarkdown(editor),
72
+ blocks: aiContextOf(editor).blocks,
73
+ block,
74
+ model: modelRef("generate")
75
+ }, {
76
+ signal,
77
+ t,
78
+ onDelta: (text) => {
79
+ output += text;
80
+ }
81
+ });
82
+ if (outcome.status === "aborted" || editor.isDestroyed) return {
83
+ status: "aborted",
84
+ output
85
+ };
86
+ if (outcome.status === "error") return {
87
+ status: "error",
88
+ output,
89
+ message: outcome.message
90
+ };
91
+ return {
92
+ status: outcome.status,
93
+ output
94
+ };
95
+ }
96
+ /**
97
+ * Fills the body of the composite at `pos` (`generateCompositeBody`); the result opens the in-document diff review over
98
+ * the body (`startAiReview`), so nothing is written until accepted. The body range is anchored when the run starts, so
99
+ * edits while the data loads or the result streams do not misplace it. Title, fields and the other chrome stay
100
+ * untouched. Notices go through `notify`, in the language of `t`.
101
+ */
102
+ async function fillComposite(editor, pos, ai, modelRef, notify, t) {
21
103
  const brief = compositeAiBrief(editor, pos);
22
104
  const node = editor.state.doc.nodeAt(pos);
23
105
  if (!brief || !node) return;
@@ -29,71 +111,30 @@ async function fillComposite(editor, pos, fetch, modelRef, notify, t) {
29
111
  const controller = new AbortController();
30
112
  const abort = () => controller.abort();
31
113
  editor.on("destroy", abort);
32
- let output = "";
33
114
  try {
34
- let data;
35
- try {
36
- data = (await aiBlockDataOf(editor)({
37
- editor,
38
- node,
39
- pos,
40
- signal: controller.signal
41
- })).slice(0, MAX_BLOCK_DATA).map(({ label, text }) => ({
42
- label,
43
- text: text.slice(0, AI_LIMITS.block.data)
44
- }));
45
- } catch (error) {
46
- if (controller.signal.aborted || editor.isDestroyed) return;
115
+ const result = await generateCompositeBody(editor, pos, ai, modelRef, t, controller.signal);
116
+ if (result.status === "aborted") return;
117
+ if (result.status === "data-error") {
47
118
  notify({
48
119
  title: t("integrations.compositeFill.dataMissing"),
49
- description: error instanceof Error ? error.message : String(error),
120
+ description: result.message,
50
121
  kind: "error"
51
122
  });
52
123
  return;
53
124
  }
54
- if (controller.signal.aborted || editor.isDestroyed) return;
55
- const block = {
56
- kind: brief.kind,
57
- path: brief.path,
58
- title: brief.title,
59
- description: brief.description,
60
- fields: brief.fields.map(({ label, value }) => ({
61
- label,
62
- value
63
- })),
64
- instructions: brief.instructions,
65
- skeleton: brief.skeleton,
66
- body: brief.body,
67
- data
68
- };
69
- const outcome = await postAiSse(fetch, "/api/ai/generate", {
70
- task: "fill-block",
71
- prompt: "",
72
- selection: "",
73
- context: documentMarkdown(editor),
74
- blocks: aiContextOf(editor).blocks,
75
- block,
76
- model: modelRef("generate")
77
- }, {
78
- signal: controller.signal,
79
- t,
80
- onDelta: (text) => {
81
- output += text;
82
- }
83
- });
84
- if (outcome.status === "aborted" || editor.isDestroyed) return;
85
- if (outcome.status === "rate-limited") {
125
+ if (result.status === "rate-limited") {
86
126
  notifyAiRateLimited(notify, t);
87
127
  return;
88
128
  }
89
- if (outcome.status === "error") {
129
+ if (result.status === "error") {
90
130
  notify({
91
131
  title: t("integrations.compositeFill.failed"),
92
- description: outcome.message,
132
+ description: result.message,
93
133
  kind: "error"
94
134
  });
95
135
  return;
96
136
  }
137
+ const { output } = result;
97
138
  if (!output.trim()) {
98
139
  notify({
99
140
  title: t("integrations.compositeFill.empty.title"),
@@ -124,6 +165,6 @@ async function fillComposite(editor, pos, fetch, modelRef, notify, t) {
124
165
  }
125
166
  }
126
167
  //#endregion
127
- export { fillComposite };
168
+ export { fillComposite, generateCompositeBody };
128
169
 
129
170
  //# sourceMappingURL=composite-fill.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"composite-fill.js","names":[],"sources":["../../../src/integrations/composite-ai/composite-fill.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { $Fetch } from 'ofetch'\nimport { aiApplyFailure, AI_LIMITS, type AiBlockInput, documentMarkdown, type ModelRef, notifyAiRateLimited, postAiSse, startAiReview } from '../../features/ai'\nimport { aiBlockDataOf, aiContextOf, captureRange, releaseRanges, resolveRange } from '../../core'\nimport type { Translate } from '../../i18n'\nimport type { Notifier } from '../../core/notify'\nimport { COMPOSITE_CHROME_COUNT, compositeAiBrief } from '../../features/composites/schema'\n\n/** Entries of `aiBlockData` that travel with a request (the server accepts at most as many). */\nconst MAX_BLOCK_DATA = 10\n\n/**\n * Fills the body of the composite at `pos`: its brief (`compositeAiBrief`) plus the preset's `aiBlockData` → task\n * `fill-block` (`generate` slot); the result opens the in-document diff review over the body (`startAiReview`), so\n * nothing is written until accepted. The body range is anchored when the run starts, so edits while the data loads or\n * the result streams do not misplace it. A contributor that rejects cancels the run before any request is sent. Title,\n * fields and the other chrome stay untouched. Notices go through `notify`, in the language of `t`.\n */\nexport async function fillComposite(editor: Editor, pos: number, fetch: $Fetch, modelRef: (slot: 'generate') => ModelRef, notify: Notifier, t: Translate): Promise<void> {\n const brief = compositeAiBrief(editor, pos)\n const node = editor.state.doc.nodeAt(pos)\n if (!brief || !node) return\n\n const from = pos + 1 + node.child(0).nodeSize + node.child(1).nodeSize + node.child(2).nodeSize\n const anchor = captureRange(editor, { from, to: pos + node.nodeSize - 1 }, { startInside: true })\n\n const controller = new AbortController()\n const abort = () => controller.abort()\n editor.on('destroy', abort)\n let output = ''\n try {\n let data: AiBlockInput['data']\n try {\n const material = await aiBlockDataOf(editor)({ editor, node, pos, signal: controller.signal })\n data = material.slice(0, MAX_BLOCK_DATA).map(({ label, text }) => ({ label, text: text.slice(0, AI_LIMITS.block.data) }))\n }\n catch (error) {\n if (controller.signal.aborted || editor.isDestroyed) return\n notify({ title: t('integrations.compositeFill.dataMissing'), description: error instanceof Error ? error.message : String(error), kind: 'error' })\n return\n }\n if (controller.signal.aborted || editor.isDestroyed) return\n\n const block: AiBlockInput = {\n kind: brief.kind,\n path: brief.path,\n title: brief.title,\n description: brief.description,\n fields: brief.fields.map(({ label, value }) => ({ label, value })),\n instructions: brief.instructions,\n skeleton: brief.skeleton,\n body: brief.body,\n data,\n }\n const outcome = await postAiSse(fetch, '/api/ai/generate', {\n task: 'fill-block',\n prompt: '',\n selection: '',\n context: documentMarkdown(editor),\n blocks: aiContextOf(editor).blocks,\n block,\n model: modelRef('generate'),\n }, { signal: controller.signal, t, onDelta: (text) => { output += text } })\n\n if (outcome.status === 'aborted' || editor.isDestroyed) return\n if (outcome.status === 'rate-limited') {\n notifyAiRateLimited(notify, t)\n return\n }\n if (outcome.status === 'error') {\n notify({ title: t('integrations.compositeFill.failed'), description: outcome.message, kind: 'error' })\n return\n }\n if (!output.trim()) {\n notify({ title: t('integrations.compositeFill.empty.title'), description: t('integrations.compositeFill.empty.description'), kind: 'error' })\n return\n }\n\n // The body must still be where it was: a range directly inside a composite, after its chrome.\n const range = resolveRange(editor.state, anchor)\n const $from = range && editor.state.doc.resolve(range.from)\n if (!range || !$from || $from.parent.type.name !== 'composite' || $from.index() < COMPOSITE_CHROME_COUNT || !$from.sameParent(editor.state.doc.resolve(range.to))) {\n notify({ title: t('integrations.compositeFill.gone.title'), description: t('integrations.compositeFill.gone.description'), kind: 'error' })\n return\n }\n const review = startAiReview(editor, [{ id: 'fill', range: anchor, markdown: output }])\n if (review.hunks === 0) notify(aiApplyFailure(review.skipped[0]?.reason ?? 'unchanged', t))\n }\n finally {\n editor.off('destroy', abort)\n releaseRanges(editor, [anchor])\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"composite-fill.js","names":[],"sources":["../../../src/integrations/composite-ai/composite-fill.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { EditorBackend } from '../../core/backend'\nimport { aiApplyFailure, AI_LIMITS, type AiBlockInput, type AiSseOutcome, documentMarkdown, type ModelRef, notifyAiRateLimited, postAiSse, startAiReview } from '../../features/ai'\nimport { aiBlockDataOf, aiContextOf, captureRange, releaseRanges, resolveRange } from '../../core'\nimport type { Translate } from '../../i18n'\nimport type { Notifier } from '../../core/notify'\nimport { COMPOSITE_CHROME_COUNT, compositeAiBrief } from '../../features/composites/schema'\n\n/** Entries of `aiBlockData` that travel with a request (the server accepts at most as many). */\nconst MAX_BLOCK_DATA = 10\n\n/**\n * How `generateCompositeBody` ended. `done` carries the streamed Markdown (possibly empty); `data-error`: a\n * contributor of `aiBlockData` rejected, before any request was sent (`message`); `error`: the request failed\n * (`message`); `aborted` also covers a destroyed editor and a node that is no composite of an `ai` kind.\n */\nexport type CompositeBodyResult =\n | { status: 'done', output: string }\n | { status: 'rate-limited' | 'aborted', output: string }\n | { status: 'data-error' | 'error', output: string, message: string }\n\n/**\n * The request half of „Baustein füllen (KI)“: the brief (`compositeAiBrief`) of the composite at `pos` plus the preset's\n * `aiBlockData` → task `fill-block` (`generate` slot), streamed to completion. Writes nothing; `fillComposite` opens\n * the diff review with the result, `deriveComposite` writes it into a new Baustein. A contributor that rejects cancels\n * the run before any request is sent. Never throws.\n */\nexport async function generateCompositeBody(editor: Editor, pos: number, ai: NonNullable<EditorBackend['ai']>, modelRef: (slot: 'generate') => ModelRef, t: Translate, signal: AbortSignal): Promise<CompositeBodyResult> {\n const brief = compositeAiBrief(editor, pos)\n const node = editor.state.doc.nodeAt(pos)\n if (!brief || !node) return { status: 'aborted', output: '' }\n\n let data: AiBlockInput['data']\n try {\n const material = await aiBlockDataOf(editor)({ editor, node, pos, signal })\n data = material.slice(0, MAX_BLOCK_DATA).map(({ label, text }) => ({ label, text: text.slice(0, AI_LIMITS.block.data) }))\n }\n catch (error) {\n if (signal.aborted || editor.isDestroyed) return { status: 'aborted', output: '' }\n return { status: 'data-error', output: '', message: error instanceof Error ? error.message : String(error) }\n }\n if (signal.aborted || editor.isDestroyed) return { status: 'aborted', output: '' }\n\n const block: AiBlockInput = {\n kind: brief.kind,\n path: brief.path,\n title: brief.title,\n description: brief.description,\n fields: brief.fields.map(({ label, value }) => ({ label, value })),\n instructions: brief.instructions,\n skeleton: brief.skeleton,\n body: brief.body,\n data,\n }\n let output = ''\n const outcome: AiSseOutcome = await postAiSse(ai, 'generate', {\n task: 'fill-block',\n prompt: '',\n selection: '',\n context: documentMarkdown(editor),\n blocks: aiContextOf(editor).blocks,\n block,\n model: modelRef('generate'),\n }, { signal, t, onDelta: (text) => { output += text } })\n\n if (outcome.status === 'aborted' || editor.isDestroyed) return { status: 'aborted', output }\n if (outcome.status === 'error') return { status: 'error', output, message: outcome.message }\n return { status: outcome.status, output }\n}\n\n/**\n * Fills the body of the composite at `pos` (`generateCompositeBody`); the result opens the in-document diff review over\n * the body (`startAiReview`), so nothing is written until accepted. The body range is anchored when the run starts, so\n * edits while the data loads or the result streams do not misplace it. Title, fields and the other chrome stay\n * untouched. Notices go through `notify`, in the language of `t`.\n */\nexport async function fillComposite(editor: Editor, pos: number, ai: NonNullable<EditorBackend['ai']>, modelRef: (slot: 'generate') => ModelRef, notify: Notifier, t: Translate): Promise<void> {\n const brief = compositeAiBrief(editor, pos)\n const node = editor.state.doc.nodeAt(pos)\n if (!brief || !node) return\n\n const from = pos + 1 + node.child(0).nodeSize + node.child(1).nodeSize + node.child(2).nodeSize\n const anchor = captureRange(editor, { from, to: pos + node.nodeSize - 1 }, { startInside: true })\n\n const controller = new AbortController()\n const abort = () => controller.abort()\n editor.on('destroy', abort)\n try {\n const result = await generateCompositeBody(editor, pos, ai, modelRef, t, controller.signal)\n if (result.status === 'aborted') return\n if (result.status === 'data-error') {\n notify({ title: t('integrations.compositeFill.dataMissing'), description: result.message, kind: 'error' })\n return\n }\n if (result.status === 'rate-limited') {\n notifyAiRateLimited(notify, t)\n return\n }\n if (result.status === 'error') {\n notify({ title: t('integrations.compositeFill.failed'), description: result.message, kind: 'error' })\n return\n }\n const { output } = result\n if (!output.trim()) {\n notify({ title: t('integrations.compositeFill.empty.title'), description: t('integrations.compositeFill.empty.description'), kind: 'error' })\n return\n }\n\n // The body must still be where it was: a range directly inside a composite, after its chrome.\n const range = resolveRange(editor.state, anchor)\n const $from = range && editor.state.doc.resolve(range.from)\n if (!range || !$from || $from.parent.type.name !== 'composite' || $from.index() < COMPOSITE_CHROME_COUNT || !$from.sameParent(editor.state.doc.resolve(range.to))) {\n notify({ title: t('integrations.compositeFill.gone.title'), description: t('integrations.compositeFill.gone.description'), kind: 'error' })\n return\n }\n const review = startAiReview(editor, [{ id: 'fill', range: anchor, markdown: output }])\n if (review.hunks === 0) notify(aiApplyFailure(review.skipped[0]?.reason ?? 'unchanged', t))\n }\n finally {\n editor.off('destroy', abort)\n releaseRanges(editor, [anchor])\n }\n}\n"],"mappings":"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"}
@@ -1,28 +1,20 @@
1
1
  import { Translate } from "../../i18n/index.js";
2
+ import { EditorBackend } from "../../core/backend.js";
2
3
  import { Notifier } from "../../core/notify.js";
3
- import { ModelRef } from "../../features/ai/protocol/models.js";
4
+ import { ModelRef } from "../../core/backend-types.js";
4
5
  import "../../features/ai/index.js";
5
6
  import { Editor } from "@tiptap/core";
6
7
  import { Node as Node$1 } from "@tiptap/pm/model";
7
- import { $Fetch } from "ofetch";
8
8
  //#region src/integrations/composite-ai/composite-summary.d.ts
9
9
  /** Index of a composite's first body block, after `compositeTitle`, `compositeDescription` and `compositeTags`. */
10
10
  export declare const COMPOSITE_BODY_START = 3;
11
- /**
12
- * What a summary is made from: the text of a composite's body blocks, or, when the body holds no text (an audio or
13
- * video `document`), its `meta.transcript`. Empty for other nodes.
14
- */
11
+ /** What a summary is made from: the text of a composite's body blocks (renditions included). Empty for other nodes. */
15
12
  export declare function compositeSourceText(composite: Node$1): string;
16
- /** The stored asset behind a composite's first `audio`/`video` body block; null when it has none. */
17
- export declare function mediaAssetOf(composite: Node$1): {
18
- documentId: string;
19
- name: string;
20
- } | null;
21
13
  /**
22
14
  * Streams an AI summary of the composite at `pos` (its body as Markdown, task `summarize`, `rewrite` model slot) into
23
15
  * the composite's description, replacing what it held, and shows description and tags. The description is anchored
24
16
  * when the request starts, so edits while it streams do not misplace the result. Notices go through `notify`, in the language of `t`.
25
17
  */
26
- export declare function summarizeComposite(editor: Editor, pos: number, fetch: $Fetch, modelRef: (slot: 'rewrite') => ModelRef, notify: Notifier, t: Translate): Promise<void>;
18
+ export declare function summarizeComposite(editor: Editor, pos: number, ai: NonNullable<EditorBackend['ai']>, modelRef: (slot: 'rewrite') => ModelRef, notify: Notifier, t: Translate): Promise<void>;
27
19
  //#endregion
28
20
  //# sourceMappingURL=composite-summary.d.ts.map
@@ -1,7 +1,6 @@
1
1
  import { parseBlocks } from "../../core/pipeline.js";
2
2
  import { captureRange, releaseRanges, resolveRange } from "../../core/doc-anchors.js";
3
3
  import "../../features/composites/nodes.js";
4
- import { assetRefOf } from "../../features/media/assets.js";
5
4
  import { AI_LIMITS } from "../../features/ai/protocol/tasks.js";
6
5
  import { notifyAiRateLimited } from "../../features/ai/rate-limit.js";
7
6
  import { postAiSse } from "../../features/ai/ai-sse.js";
@@ -17,27 +16,9 @@ function compositeBody(composite) {
17
16
  });
18
17
  return body;
19
18
  }
20
- /** Text of a composite's body blocks (empty for other nodes). */
21
- function compositeBodyText(composite) {
22
- return compositeBody(composite).map((child) => child.textContent).join("\n");
23
- }
24
- /**
25
- * What a summary is made from: the text of a composite's body blocks, or, when the body holds no text (an audio or
26
- * video `document`), its `meta.transcript`. Empty for other nodes.
27
- */
19
+ /** What a summary is made from: the text of a composite's body blocks (renditions included). Empty for other nodes. */
28
20
  function compositeSourceText(composite) {
29
- if (composite.type.name !== "composite") return "";
30
- const text = compositeBodyText(composite);
31
- return text.trim() ? text : String(composite.attrs.meta?.transcript ?? "");
32
- }
33
- /** The stored asset behind a composite's first `audio`/`video` body block; null when it has none. */
34
- function mediaAssetOf(composite) {
35
- for (const child of compositeBody(composite)) {
36
- if (child.type.name !== "audio" && child.type.name !== "video") continue;
37
- const ref = assetRefOf(String(child.attrs.src ?? ""));
38
- if (ref) return ref;
39
- }
40
- return null;
21
+ return compositeBody(composite).map((child) => child.textContent).join("\n");
41
22
  }
42
23
  /** Inline content of the first textblock of a parsed AI result. */
43
24
  function firstInlineContent(editor, parsed) {
@@ -60,16 +41,16 @@ function firstInlineContent(editor, parsed) {
60
41
  * the composite's description, replacing what it held, and shows description and tags. The description is anchored
61
42
  * when the request starts, so edits while it streams do not misplace the result. Notices go through `notify`, in the language of `t`.
62
43
  */
63
- async function summarizeComposite(editor, pos, fetch, modelRef, notify, t) {
44
+ async function summarizeComposite(editor, pos, ai, modelRef, notify, t) {
64
45
  const composite = editor.state.doc.nodeAt(pos);
65
46
  if (composite?.type.name !== "composite" || composite.childCount <= COMPOSITE_BODY_START) return;
66
47
  const title = composite.child(0);
67
48
  const description = composite.child(1);
68
49
  const body = compositeBody(composite).map((child) => child.toJSON());
69
- const bodyMarkdown = compositeBodyText(composite).trim() ? editor.markdown.serialize({
50
+ const bodyMarkdown = compositeSourceText(composite).trim() ? editor.markdown.serialize({
70
51
  type: "doc",
71
52
  content: body
72
- }) : compositeSourceText(composite);
53
+ }) : "";
73
54
  const descriptionPos = pos + 1 + title.nodeSize;
74
55
  const anchor = captureRange(editor, {
75
56
  from: descriptionPos + 1,
@@ -81,7 +62,7 @@ async function summarizeComposite(editor, pos, fetch, modelRef, notify, t) {
81
62
  editor.on("destroy", abort);
82
63
  let output = "";
83
64
  try {
84
- const outcome = await postAiSse(fetch, "/api/ai/generate", {
65
+ const outcome = await postAiSse(ai, "generate", {
85
66
  task: "summarize",
86
67
  prompt: "",
87
68
  selection: bodyMarkdown.slice(0, AI_LIMITS.selection),
@@ -138,6 +119,6 @@ async function summarizeComposite(editor, pos, fetch, modelRef, notify, t) {
138
119
  }
139
120
  }
140
121
  //#endregion
141
- export { COMPOSITE_BODY_START, compositeSourceText, mediaAssetOf, summarizeComposite };
122
+ export { COMPOSITE_BODY_START, compositeSourceText, summarizeComposite };
142
123
 
143
124
  //# sourceMappingURL=composite-summary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"composite-summary.js","names":[],"sources":["../../../src/integrations/composite-ai/composite-summary.ts"],"sourcesContent":["import type { Editor, JSONContent } from '@tiptap/core'\nimport { Fragment, type Node as PMNode } from '@tiptap/pm/model'\nimport type { $Fetch } from 'ofetch'\nimport { AI_LIMITS, type ModelRef, notifyAiRateLimited, postAiSse } from '../../features/ai'\nimport { COMPOSITE_CHROME_COUNT } from '../../features/composites/schema'\nimport { assetRefOf } from '../../features/media/schema'\nimport { captureRange, parseBlocks, releaseRanges, resolveRange } from '../../core'\nimport type { Translate } from '../../i18n'\nimport type { Notifier } from '../../core/notify'\n\n/** Index of a composite's first body block, after `compositeTitle`, `compositeDescription` and `compositeTags`. */\nexport const COMPOSITE_BODY_START = COMPOSITE_CHROME_COUNT\n\nfunction compositeBody(composite: PMNode): PMNode[] {\n if (composite.type.name !== 'composite') return []\n const body: PMNode[] = []\n composite.forEach((child, _offset, index) => {\n if (index >= COMPOSITE_BODY_START) body.push(child)\n })\n return body\n}\n\n/** Text of a composite's body blocks (empty for other nodes). */\nfunction compositeBodyText(composite: PMNode): string {\n return compositeBody(composite).map(child => child.textContent).join('\\n')\n}\n\n/**\n * What a summary is made from: the text of a composite's body blocks, or, when the body holds no text (an audio or\n * video `document`), its `meta.transcript`. Empty for other nodes.\n */\nexport function compositeSourceText(composite: PMNode): string {\n if (composite.type.name !== 'composite') return ''\n const text = compositeBodyText(composite)\n return text.trim() ? text : String(composite.attrs.meta?.transcript ?? '')\n}\n\n/** The stored asset behind a composite's first `audio`/`video` body block; null when it has none. */\nexport function mediaAssetOf(composite: PMNode): { documentId: string, name: string } | null {\n for (const child of compositeBody(composite)) {\n if (child.type.name !== 'audio' && child.type.name !== 'video') continue\n const ref = assetRefOf(String(child.attrs.src ?? ''))\n if (ref) return ref\n }\n return null\n}\n\n/** Inline content of the first textblock of a parsed AI result. */\nfunction firstInlineContent(editor: Editor, parsed: JSONContent): Fragment | null {\n let doc: PMNode\n try {\n doc = editor.schema.nodeFromJSON(parsed)\n }\n catch {\n return null\n }\n let inline: Fragment | null = null\n doc.descendants((node) => {\n if (inline) return false\n if (node.isTextblock && node.content.size) inline = node.content\n return !inline\n })\n return inline\n}\n\n/**\n * Streams an AI summary of the composite at `pos` (its body as Markdown, task `summarize`, `rewrite` model slot) into\n * the composite's description, replacing what it held, and shows description and tags. The description is anchored\n * when the request starts, so edits while it streams do not misplace the result. Notices go through `notify`, in the language of `t`.\n */\nexport async function summarizeComposite(editor: Editor, pos: number, fetch: $Fetch, modelRef: (slot: 'rewrite') => ModelRef, notify: Notifier, t: Translate): Promise<void> {\n const composite = editor.state.doc.nodeAt(pos)\n if (composite?.type.name !== 'composite' || composite.childCount <= COMPOSITE_BODY_START) return\n const title = composite.child(0)\n const description = composite.child(1)\n const body = compositeBody(composite).map(child => child.toJSON() as JSONContent)\n const bodyMarkdown = compositeBodyText(composite).trim()\n ? editor.markdown!.serialize({ type: 'doc', content: body })\n : compositeSourceText(composite)\n const descriptionPos = pos + 1 + title.nodeSize\n const anchor = captureRange(editor, { from: descriptionPos + 1, to: descriptionPos + 1 + description.content.size })\n const model = modelRef('rewrite')\n\n const controller = new AbortController()\n const abort = () => controller.abort()\n editor.on('destroy', abort)\n let output = ''\n try {\n const outcome = await postAiSse(fetch, '/api/ai/generate', {\n task: 'summarize',\n prompt: '',\n selection: bodyMarkdown.slice(0, AI_LIMITS.selection),\n context: '',\n model,\n }, { signal: controller.signal, t, onDelta: (text) => { output += text } })\n\n if (outcome.status === 'aborted' || editor.isDestroyed) return\n if (outcome.status === 'rate-limited') {\n notifyAiRateLimited(notify, t)\n return\n }\n if (outcome.status === 'error') {\n notify({ title: t('integrations.compositeSummary.failed'), description: outcome.message, kind: 'error' })\n return\n }\n if (!output.trim()) {\n notify({ title: t('integrations.compositeSummary.empty.title'), description: t('integrations.compositeSummary.empty.description'), kind: 'error' })\n return\n }\n\n const range = resolveRange(editor.state, anchor)\n const $from = range && editor.state.doc.resolve(range.from)\n if (!range || !$from || $from.parent.type.name !== 'compositeDescription' || !$from.sameParent(editor.state.doc.resolve(range.to))) {\n notify({ title: t('integrations.compositeSummary.gone.title'), description: t('integrations.compositeSummary.gone.description'), kind: 'error' })\n return\n }\n const inline = firstInlineContent(editor, parseBlocks(editor, output).parsed) ?? Fragment.from(editor.schema.text(output.trim()))\n editor.view.dispatch(editor.state.tr.replaceWith(range.from, range.to, inline))\n notify({ title: t('integrations.compositeSummary.done'), kind: 'success', icon: 'i-lucide-text-quote' })\n }\n finally {\n editor.off('destroy', abort)\n releaseRanges(editor, [anchor])\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"composite-summary.js","names":[],"sources":["../../../src/integrations/composite-ai/composite-summary.ts"],"sourcesContent":["import type { Editor, JSONContent } from '@tiptap/core'\nimport { Fragment, type Node as PMNode } from '@tiptap/pm/model'\nimport type { EditorBackend } from '../../core/backend'\nimport { AI_LIMITS, type ModelRef, notifyAiRateLimited, postAiSse } from '../../features/ai'\nimport { COMPOSITE_CHROME_COUNT } from '../../features/composites/schema'\nimport { captureRange, parseBlocks, releaseRanges, resolveRange } from '../../core'\nimport type { Translate } from '../../i18n'\nimport type { Notifier } from '../../core/notify'\n\n/** Index of a composite's first body block, after `compositeTitle`, `compositeDescription` and `compositeTags`. */\nexport const COMPOSITE_BODY_START = COMPOSITE_CHROME_COUNT\n\nfunction compositeBody(composite: PMNode): PMNode[] {\n if (composite.type.name !== 'composite') return []\n const body: PMNode[] = []\n composite.forEach((child, _offset, index) => {\n if (index >= COMPOSITE_BODY_START) body.push(child)\n })\n return body\n}\n\n/** What a summary is made from: the text of a composite's body blocks (renditions included). Empty for other nodes. */\nexport function compositeSourceText(composite: PMNode): string {\n return compositeBody(composite).map(child => child.textContent).join('\\n')\n}\n\n/** Inline content of the first textblock of a parsed AI result. */\nfunction firstInlineContent(editor: Editor, parsed: JSONContent): Fragment | null {\n let doc: PMNode\n try {\n doc = editor.schema.nodeFromJSON(parsed)\n }\n catch {\n return null\n }\n let inline: Fragment | null = null\n doc.descendants((node) => {\n if (inline) return false\n if (node.isTextblock && node.content.size) inline = node.content\n return !inline\n })\n return inline\n}\n\n/**\n * Streams an AI summary of the composite at `pos` (its body as Markdown, task `summarize`, `rewrite` model slot) into\n * the composite's description, replacing what it held, and shows description and tags. The description is anchored\n * when the request starts, so edits while it streams do not misplace the result. Notices go through `notify`, in the language of `t`.\n */\nexport async function summarizeComposite(editor: Editor, pos: number, ai: NonNullable<EditorBackend['ai']>, modelRef: (slot: 'rewrite') => ModelRef, notify: Notifier, t: Translate): Promise<void> {\n const composite = editor.state.doc.nodeAt(pos)\n if (composite?.type.name !== 'composite' || composite.childCount <= COMPOSITE_BODY_START) return\n const title = composite.child(0)\n const description = composite.child(1)\n const body = compositeBody(composite).map(child => child.toJSON() as JSONContent)\n const bodyMarkdown = compositeSourceText(composite).trim()\n ? editor.markdown!.serialize({ type: 'doc', content: body })\n : ''\n const descriptionPos = pos + 1 + title.nodeSize\n const anchor = captureRange(editor, { from: descriptionPos + 1, to: descriptionPos + 1 + description.content.size })\n const model = modelRef('rewrite')\n\n const controller = new AbortController()\n const abort = () => controller.abort()\n editor.on('destroy', abort)\n let output = ''\n try {\n const outcome = await postAiSse(ai, 'generate', {\n task: 'summarize',\n prompt: '',\n selection: bodyMarkdown.slice(0, AI_LIMITS.selection),\n context: '',\n model,\n }, { signal: controller.signal, t, onDelta: (text) => { output += text } })\n\n if (outcome.status === 'aborted' || editor.isDestroyed) return\n if (outcome.status === 'rate-limited') {\n notifyAiRateLimited(notify, t)\n return\n }\n if (outcome.status === 'error') {\n notify({ title: t('integrations.compositeSummary.failed'), description: outcome.message, kind: 'error' })\n return\n }\n if (!output.trim()) {\n notify({ title: t('integrations.compositeSummary.empty.title'), description: t('integrations.compositeSummary.empty.description'), kind: 'error' })\n return\n }\n\n const range = resolveRange(editor.state, anchor)\n const $from = range && editor.state.doc.resolve(range.from)\n if (!range || !$from || $from.parent.type.name !== 'compositeDescription' || !$from.sameParent(editor.state.doc.resolve(range.to))) {\n notify({ title: t('integrations.compositeSummary.gone.title'), description: t('integrations.compositeSummary.gone.description'), kind: 'error' })\n return\n }\n const inline = firstInlineContent(editor, parseBlocks(editor, output).parsed) ?? Fragment.from(editor.schema.text(output.trim()))\n editor.view.dispatch(editor.state.tr.replaceWith(range.from, range.to, inline))\n notify({ title: t('integrations.compositeSummary.done'), kind: 'success', icon: 'i-lucide-text-quote' })\n }\n finally {\n editor.off('destroy', abort)\n releaseRanges(editor, [anchor])\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { Translate } from "../../i18n/index.js";
2
+ import { EditorBackend } from "../../core/backend.js";
3
+ import { Notifier } from "../../core/notify.js";
4
+ import { ModelRef } from "../../core/backend-types.js";
5
+ import "../../features/ai/index.js";
6
+ import { CompositeKind } from "../../features/composites/kinds.js";
7
+ import "../../features/composites/index.js";
8
+ import { Editor } from "@tiptap/core";
9
+ import { Node as Node$1 } from "@tiptap/pm/model";
10
+ //#region src/integrations/composite-ai/derive.d.ts
11
+ /** Kinds a Baustein can be derived into: the ones with an `ai` configuration (their brief drives the generation). */
12
+ export declare const derivableKindsOf: (editor: Editor) => CompositeKind[];
13
+ /** Whether the Baustein `node` can be the source of a derivation: a composite with a block id (the derivation points at it by id). */
14
+ export declare const isDerivableSource: (editor: Editor, node: Node$1) => boolean;
15
+ /** Whether a Baustein of `kindId` may be inserted right after the Baustein at `pos` (the same guards as creating it there). */
16
+ export declare function canDeriveAfter(editor: Editor, pos: number, kindId: string): boolean;
17
+ /**
18
+ * „Ableiten (KI) → <Art>“: inserts a sibling Baustein of kind `kindId` right after the Baustein at `pos`, titled
19
+ * „<Art>: <Quelle>“, whose `meta.derivation` points back at the source block (`from.block`, method `ai:<kindId>`, the
20
+ * Markdown hash of the source's body as `inputHash`), generates its body from the source (`generateCompositeBody`; the
21
+ * `aiBlockData` of composites hands the model the source's Markdown) and writes the result directly into the new
22
+ * Baustein — no review, the new Baustein is the proposal. The hash of the written body becomes `outputHash`, so a later
23
+ * edit shows as „bearbeitet“ and a later edit of the source as „Quelle geändert“. The new Baustein is found again by its
24
+ * block id after every await, so edits while the model runs do not misplace the result. When the run fails or yields
25
+ * nothing the still-empty Baustein is removed again. Notices go through `notify`, in the language of `t`.
26
+ */
27
+ export declare function deriveComposite(editor: Editor, pos: number, kindId: string, ai: NonNullable<EditorBackend['ai']>, modelRef: (slot: 'generate') => ModelRef, notify: Notifier, t: Translate): Promise<void>;
28
+ //#endregion
29
+ //# sourceMappingURL=derive.d.ts.map
@@ -0,0 +1,173 @@
1
+ import { parseBlocks } from "../../core/pipeline.js";
2
+ import { guardsAccept } from "../../core/commands.js";
3
+ import { blockIdOf, findBlockById, newBlockId } from "../../core/schema/block-ids.js";
4
+ import { sha256Hex } from "../../core/hash.js";
5
+ import { compositeKind } from "../../features/composites/kinds.js";
6
+ import { DERIVATION_KEY } from "../../features/composites/meta-keys.js";
7
+ import { bodyMarkdown, derivationOf } from "../../features/composites/derivation.js";
8
+ import { compositeJSON, compositeKindsOf } from "../../features/composites/nodes.js";
9
+ import { notifyAiRateLimited } from "../../features/ai/rate-limit.js";
10
+ import { generateCompositeBody } from "./composite-fill.js";
11
+ import { Fragment } from "@tiptap/pm/model";
12
+ //#region src/integrations/composite-ai/derive.ts
13
+ /** Kinds a Baustein can be derived into: the ones with an `ai` configuration (their brief drives the generation). */
14
+ const derivableKindsOf = (editor) => compositeKindsOf(editor).filter((kind) => kind.ai !== void 0);
15
+ /** Whether the Baustein `node` can be the source of a derivation: a composite with a block id (the derivation points at it by id). */
16
+ const isDerivableSource = (editor, node) => node.type.name === "composite" && blockIdOf(node) !== null && derivableKindsOf(editor).length > 0;
17
+ /** Whether a Baustein of `kindId` may be inserted right after the Baustein at `pos` (the same guards as creating it there). */
18
+ function canDeriveAfter(editor, pos, kindId) {
19
+ const source = editor.state.doc.nodeAt(pos);
20
+ if (!source) return false;
21
+ const $at = editor.state.doc.resolve(pos + source.nodeSize);
22
+ return guardsAccept(editor, $at, {
23
+ type: "composite",
24
+ attrs: { kind: kindId }
25
+ });
26
+ }
27
+ /**
28
+ * „Ableiten (KI) → <Art>“: inserts a sibling Baustein of kind `kindId` right after the Baustein at `pos`, titled
29
+ * „<Art>: <Quelle>“, whose `meta.derivation` points back at the source block (`from.block`, method `ai:<kindId>`, the
30
+ * Markdown hash of the source's body as `inputHash`), generates its body from the source (`generateCompositeBody`; the
31
+ * `aiBlockData` of composites hands the model the source's Markdown) and writes the result directly into the new
32
+ * Baustein — no review, the new Baustein is the proposal. The hash of the written body becomes `outputHash`, so a later
33
+ * edit shows as „bearbeitet“ and a later edit of the source as „Quelle geändert“. The new Baustein is found again by its
34
+ * block id after every await, so edits while the model runs do not misplace the result. When the run fails or yields
35
+ * nothing the still-empty Baustein is removed again. Notices go through `notify`, in the language of `t`.
36
+ */
37
+ async function deriveComposite(editor, pos, kindId, ai, modelRef, notify, t) {
38
+ const source = editor.state.doc.nodeAt(pos);
39
+ const sourceId = source && blockIdOf(source);
40
+ const kind = compositeKindsOf(editor).find((candidate) => candidate.id === kindId);
41
+ if (source?.type.name !== "composite" || !sourceId || !kind?.ai) return;
42
+ if (!canDeriveAfter(editor, pos, kindId)) {
43
+ notify({
44
+ title: t("integrations.compositeDerive.notAccepted"),
45
+ kind: "error"
46
+ });
47
+ return;
48
+ }
49
+ const sourceKind = compositeKind(compositeKindsOf(editor), String(source.attrs.kind));
50
+ const derivation = {
51
+ from: { block: sourceId },
52
+ method: `ai:${kindId}`,
53
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
54
+ inputHash: sha256Hex(bodyMarkdown(editor, source)),
55
+ outputHash: ""
56
+ };
57
+ const id = newBlockId();
58
+ const json = compositeJSON(kindId);
59
+ const [title, ...rest] = json.content;
60
+ const text = `${kind.label}: ${source.child(0).textContent.trim() || sourceKind.label}`;
61
+ const created = {
62
+ ...json,
63
+ attrs: {
64
+ ...json.attrs,
65
+ id,
66
+ meta: { [DERIVATION_KEY]: derivation }
67
+ },
68
+ content: [{
69
+ ...title,
70
+ content: [{
71
+ type: "text",
72
+ text
73
+ }]
74
+ }, ...rest]
75
+ };
76
+ editor.view.dispatch(editor.state.tr.insert(pos + source.nodeSize, editor.schema.nodeFromJSON(created)));
77
+ const toastId = `derive-${id}`;
78
+ const controller = new AbortController();
79
+ const abort = () => controller.abort();
80
+ editor.on("destroy", abort);
81
+ notify({
82
+ id: toastId,
83
+ title: t("integrations.compositeDerive.running", { kind: kind.label }),
84
+ kind: "info",
85
+ icon: "i-lucide-loader-circle",
86
+ duration: 0
87
+ });
88
+ /** Drops the new Baustein again, unless its body got content meanwhile (the user may have started writing in it). */
89
+ const discard = () => {
90
+ const found = editor.isDestroyed ? null : findBlockById(editor.state.doc, id);
91
+ if (!found) return;
92
+ if (Array.from({ length: found.node.childCount - 3 }, (_, index) => found.node.child(3 + index)).some((child) => child.textContent.trim() || child.type.name !== "paragraph")) return;
93
+ editor.view.dispatch(editor.state.tr.delete(found.pos, found.pos + found.node.nodeSize));
94
+ };
95
+ try {
96
+ const target = findBlockById(editor.state.doc, id);
97
+ const result = target ? await generateCompositeBody(editor, target.pos, ai, modelRef, t, controller.signal) : null;
98
+ if (!result || result.status === "aborted" || editor.isDestroyed) {
99
+ if (!editor.isDestroyed) discard();
100
+ return;
101
+ }
102
+ if (result.status === "rate-limited") {
103
+ discard();
104
+ notifyAiRateLimited(notify, t);
105
+ return;
106
+ }
107
+ if (result.status === "data-error") {
108
+ discard();
109
+ notify({
110
+ title: t("integrations.compositeFill.dataMissing"),
111
+ description: result.message,
112
+ kind: "error"
113
+ });
114
+ return;
115
+ }
116
+ if (result.status === "error") {
117
+ discard();
118
+ notify({
119
+ title: t("integrations.compositeDerive.failed"),
120
+ description: result.message,
121
+ kind: "error"
122
+ });
123
+ return;
124
+ }
125
+ const blocks = result.output.trim() ? parseBlocks(editor, result.output).blocks.map((block) => editor.schema.nodeFromJSON(block)) : [];
126
+ if (!blocks.length) {
127
+ discard();
128
+ notify({
129
+ title: t("integrations.compositeDerive.empty.title"),
130
+ description: t("integrations.compositeDerive.empty.description"),
131
+ kind: "error"
132
+ });
133
+ return;
134
+ }
135
+ const found = findBlockById(editor.state.doc, id);
136
+ if (!found || !found.node.canReplace(3, found.node.childCount, Fragment.from(blocks))) {
137
+ notify({
138
+ title: t("integrations.compositeDerive.gone.title"),
139
+ description: t("integrations.compositeDerive.gone.description"),
140
+ kind: "error"
141
+ });
142
+ return;
143
+ }
144
+ const chromeSize = Array.from({ length: 3 }, (_, index) => found.node.child(index).nodeSize).reduce((sum, size) => sum + size, 0);
145
+ const tr = editor.state.tr.replaceWith(found.pos + 1 + chromeSize, found.pos + found.node.nodeSize - 1, blocks);
146
+ const written = findBlockById(tr.doc, id);
147
+ const stored = derivationOf(written.node) ?? derivation;
148
+ tr.setNodeMarkup(written.pos, void 0, {
149
+ ...written.node.attrs,
150
+ meta: {
151
+ ...written.node.attrs.meta,
152
+ [DERIVATION_KEY]: {
153
+ ...stored,
154
+ outputHash: sha256Hex(bodyMarkdown(editor, written.node))
155
+ }
156
+ }
157
+ });
158
+ editor.view.dispatch(tr);
159
+ editor.commands.revealBlock(id);
160
+ notify({
161
+ title: t("integrations.compositeDerive.done", { kind: kind.label }),
162
+ kind: "success",
163
+ icon: "i-lucide-git-branch"
164
+ });
165
+ } finally {
166
+ notify.dismiss?.(toastId);
167
+ editor.off("destroy", abort);
168
+ }
169
+ }
170
+ //#endregion
171
+ export { canDeriveAfter, derivableKindsOf, deriveComposite, isDerivableSource };
172
+
173
+ //# sourceMappingURL=derive.js.map