quoin-editor 2.0.4 → 2.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 (215) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/MIGRATION.md +1 -1
  3. package/README.md +14 -13
  4. package/dist/ai.cjs +124 -94
  5. package/dist/ai.d.cts +7 -0
  6. package/dist/ai.d.ts +7 -0
  7. package/dist/ai.js +50 -20
  8. package/dist/ai.js.map +1 -1
  9. package/dist/catalogue.cjs +28 -26
  10. package/dist/catalogue.js +19 -17
  11. package/dist/catalogue.js.map +1 -1
  12. package/dist/{chunk-JGEDJYIV.cjs → chunk-2FUWXPPC.cjs} +92 -98
  13. package/dist/{chunk-NHNW5DK3.js → chunk-3F76QQ65.js} +6 -6
  14. package/dist/{chunk-NHNW5DK3.js.map → chunk-3F76QQ65.js.map} +1 -1
  15. package/dist/{chunk-DBOZFNWU.js → chunk-3QYFAAQR.js} +3 -3
  16. package/dist/{chunk-DBOZFNWU.js.map → chunk-3QYFAAQR.js.map} +1 -1
  17. package/dist/{chunk-I7X7B3WD.cjs → chunk-4JDRDPLC.cjs} +17 -8
  18. package/dist/{chunk-EBSDPHPS.cjs → chunk-4UFWFV43.cjs} +1060 -719
  19. package/dist/{chunk-LM3DHROX.cjs → chunk-5AUIA4B3.cjs} +2 -2
  20. package/dist/{chunk-3INFNIGN.cjs → chunk-5H3BB5VJ.cjs} +131 -78
  21. package/dist/{chunk-DJU25PFC.cjs → chunk-5L2NSIHZ.cjs} +11 -11
  22. package/dist/{chunk-W376L2GM.js → chunk-6Y7JAWYY.js} +8 -8
  23. package/dist/chunk-6Y7JAWYY.js.map +1 -0
  24. package/dist/{chunk-UDBLZILE.js → chunk-ATKDXQEY.js} +12 -7
  25. package/dist/{chunk-UDBLZILE.js.map → chunk-ATKDXQEY.js.map} +1 -1
  26. package/dist/{chunk-A2IQHMIH.js → chunk-BE2SYPK5.js} +49 -54
  27. package/dist/chunk-BE2SYPK5.js.map +1 -0
  28. package/dist/{chunk-PURYVDC3.cjs → chunk-CFICD2JP.cjs} +21 -16
  29. package/dist/{chunk-3HW3WRYC.cjs → chunk-CSIUXYRU.cjs} +2 -2
  30. package/dist/{chunk-N7BSFDDM.cjs → chunk-DBKL524I.cjs} +23 -23
  31. package/dist/{chunk-XE3IYW5B.js → chunk-DEFYFIWW.js} +90 -37
  32. package/dist/chunk-DEFYFIWW.js.map +1 -0
  33. package/dist/{chunk-7E43TURF.cjs → chunk-ECI3PSMS.cjs} +7 -7
  34. package/dist/{chunk-4G645EYO.js → chunk-F73QEF7E.js} +5 -5
  35. package/dist/{chunk-4G645EYO.js.map → chunk-F73QEF7E.js.map} +1 -1
  36. package/dist/{chunk-KHRVCTQQ.cjs → chunk-FUT7XLMP.cjs} +61 -74
  37. package/dist/{chunk-7J63427U.cjs → chunk-GQSBOBOM.cjs} +375 -320
  38. package/dist/{chunk-LU3T3JB4.js → chunk-HPNSQWRD.js} +15 -28
  39. package/dist/chunk-HPNSQWRD.js.map +1 -0
  40. package/dist/{chunk-7Y4B7NHO.js → chunk-I34BFOLL.js} +18 -11
  41. package/dist/chunk-I34BFOLL.js.map +1 -0
  42. package/dist/{chunk-AJT54OMZ.js → chunk-IFRXEFQH.js} +9 -15
  43. package/dist/chunk-IFRXEFQH.js.map +1 -0
  44. package/dist/{chunk-YYW33WUL.cjs → chunk-K3XWVRL4.cjs} +8 -8
  45. package/dist/{chunk-LSI4RMTY.js → chunk-L5L6YNLT.js} +3 -3
  46. package/dist/{chunk-LSI4RMTY.js.map → chunk-L5L6YNLT.js.map} +1 -1
  47. package/dist/{chunk-2BPXVQBP.js → chunk-MO4UMXMT.js} +238 -86
  48. package/dist/chunk-MO4UMXMT.js.map +1 -0
  49. package/dist/{chunk-2QKFRKOP.cjs → chunk-N25EH2GZ.cjs} +351 -205
  50. package/dist/{chunk-CSPCDVCT.js → chunk-NCV2ML25.js} +3 -3
  51. package/dist/{chunk-CSPCDVCT.js.map → chunk-NCV2ML25.js.map} +1 -1
  52. package/dist/{chunk-NUQ64S5B.cjs → chunk-OJSKSQTL.cjs} +26 -26
  53. package/dist/chunk-PIWMU4BV.js +9 -0
  54. package/dist/chunk-PIWMU4BV.js.map +1 -0
  55. package/dist/chunk-QFGWSFOI.cjs +10 -0
  56. package/dist/{chunk-GPTJYWGS.js → chunk-RNBLVGWY.js} +3 -3
  57. package/dist/{chunk-GPTJYWGS.js.map → chunk-RNBLVGWY.js.map} +1 -1
  58. package/dist/{chunk-5RBMZGKV.js → chunk-TL2MJOWM.js} +325 -57
  59. package/dist/chunk-TL2MJOWM.js.map +1 -0
  60. package/dist/{chunk-YEDPBYO5.cjs → chunk-UDQ52EEC.cjs} +4 -4
  61. package/dist/{chunk-EIWPJWY3.js → chunk-UE2NQPNG.js} +5 -5
  62. package/dist/{chunk-EIWPJWY3.js.map → chunk-UE2NQPNG.js.map} +1 -1
  63. package/dist/{chunk-BE2YHZXA.cjs → chunk-ULV3SCYP.cjs} +26 -15
  64. package/dist/{chunk-WDBFGX3U.cjs → chunk-VTTMJGWP.cjs} +72 -77
  65. package/dist/{chunk-556PFYES.js → chunk-WK4UGDZN.js} +290 -235
  66. package/dist/chunk-WK4UGDZN.js.map +1 -0
  67. package/dist/{chunk-JZF6UQH5.cjs → chunk-WMKA37NJ.cjs} +12 -12
  68. package/dist/{chunk-F2ZK6Z52.js → chunk-Y26F2X4E.js} +3 -3
  69. package/dist/{chunk-F2ZK6Z52.js.map → chunk-Y26F2X4E.js.map} +1 -1
  70. package/dist/{chunk-FK7EBZPX.cjs → chunk-Z5EEDCRI.cjs} +549 -276
  71. package/dist/{chunk-G6NBQYMM.js → chunk-ZGFZRVQA.js} +817 -478
  72. package/dist/chunk-ZGFZRVQA.js.map +1 -0
  73. package/dist/{chunk-QLVX7MPS.js → chunk-ZQF45LA4.js} +19 -8
  74. package/dist/chunk-ZQF45LA4.js.map +1 -0
  75. package/dist/comments.cjs +127 -65
  76. package/dist/comments.d.cts +35 -2
  77. package/dist/comments.d.ts +35 -2
  78. package/dist/comments.js +73 -12
  79. package/dist/comments.js.map +1 -1
  80. package/dist/{diagram-extension-22x_njXB.d.ts → diagram-extension-BMlh8GCw.d.ts} +1 -1
  81. package/dist/{diagram-extension-C_FSkoj9.d.cts → diagram-extension-gmndUpti.d.cts} +1 -1
  82. package/dist/diagram.cjs +10 -9
  83. package/dist/diagram.d.cts +2 -2
  84. package/dist/diagram.d.ts +2 -2
  85. package/dist/diagram.js +7 -6
  86. package/dist/diff.cjs +25 -25
  87. package/dist/diff.js +3 -3
  88. package/dist/docx.cjs +31 -30
  89. package/dist/docx.js +5 -4
  90. package/dist/docx.js.map +1 -1
  91. package/dist/embed.cjs +10 -9
  92. package/dist/embed.js +8 -7
  93. package/dist/{emoji-extension-Dk5IQLZf.d.cts → emoji-extension-DD9CQTQj.d.cts} +1 -1
  94. package/dist/{emoji-extension-C832oGeT.d.ts → emoji-extension-U_PWZ2fX.d.ts} +1 -1
  95. package/dist/emoji.cjs +10 -9
  96. package/dist/emoji.d.cts +2 -2
  97. package/dist/emoji.d.ts +2 -2
  98. package/dist/emoji.js +7 -6
  99. package/dist/engine.cjs +58 -58
  100. package/dist/engine.d.cts +3 -3
  101. package/dist/engine.d.ts +3 -3
  102. package/dist/engine.js +3 -3
  103. package/dist/{find-extension-DmK9_N81.d.ts → find-extension-BGlqooZi.d.ts} +1 -1
  104. package/dist/{find-extension-BfruAPLi.d.cts → find-extension-BPnAJ8bY.d.cts} +1 -1
  105. package/dist/find.cjs +11 -10
  106. package/dist/find.d.cts +1 -1
  107. package/dist/find.d.ts +1 -1
  108. package/dist/find.js +7 -6
  109. package/dist/headless.cjs +70 -69
  110. package/dist/headless.d.cts +33 -10
  111. package/dist/headless.d.ts +33 -10
  112. package/dist/headless.js +5 -4
  113. package/dist/highlight.cjs +7 -6
  114. package/dist/highlight.js +6 -5
  115. package/dist/highlight.js.map +1 -1
  116. package/dist/{index-3fYvwqUZ.d.cts → index-DN7vRKFw.d.cts} +1 -1
  117. package/dist/{index-CgxnzCO5.d.ts → index-DyIYI3PM.d.ts} +1 -1
  118. package/dist/index.cjs +82 -81
  119. package/dist/index.d.cts +19 -12
  120. package/dist/index.d.ts +19 -12
  121. package/dist/index.js +6 -5
  122. package/dist/{labels-CiCxj2jP.d.cts → labels-BJORhN93.d.ts} +10 -5
  123. package/dist/{labels-BhRJYo46.d.ts → labels-CVYJ2-1X.d.cts} +10 -5
  124. package/dist/locale-ar.cjs +10 -0
  125. package/dist/locale-ar.d.cts +1 -1
  126. package/dist/locale-ar.d.ts +1 -1
  127. package/dist/locale-ar.js +10 -0
  128. package/dist/locale-ar.js.map +1 -1
  129. package/dist/locale-de.cjs +4 -0
  130. package/dist/locale-de.d.cts +1 -1
  131. package/dist/locale-de.d.ts +1 -1
  132. package/dist/locale-de.js +4 -0
  133. package/dist/locale-de.js.map +1 -1
  134. package/dist/locale-es.cjs +4 -0
  135. package/dist/locale-es.d.cts +1 -1
  136. package/dist/locale-es.d.ts +1 -1
  137. package/dist/locale-es.js +4 -0
  138. package/dist/locale-es.js.map +1 -1
  139. package/dist/locale-fr.cjs +4 -0
  140. package/dist/locale-fr.d.cts +1 -1
  141. package/dist/locale-fr.d.ts +1 -1
  142. package/dist/locale-fr.js +4 -0
  143. package/dist/locale-fr.js.map +1 -1
  144. package/dist/locale-ja.cjs +4 -0
  145. package/dist/locale-ja.d.cts +1 -1
  146. package/dist/locale-ja.d.ts +1 -1
  147. package/dist/locale-ja.js +4 -0
  148. package/dist/locale-ja.js.map +1 -1
  149. package/dist/locale-pt.cjs +4 -0
  150. package/dist/locale-pt.d.cts +1 -1
  151. package/dist/locale-pt.d.ts +1 -1
  152. package/dist/locale-pt.js +4 -0
  153. package/dist/locale-pt.js.map +1 -1
  154. package/dist/locale-zh.cjs +4 -0
  155. package/dist/locale-zh.d.cts +1 -1
  156. package/dist/locale-zh.d.ts +1 -1
  157. package/dist/locale-zh.js +4 -0
  158. package/dist/locale-zh.js.map +1 -1
  159. package/dist/math.cjs +11 -10
  160. package/dist/math.js +9 -8
  161. package/dist/mention.cjs +11 -10
  162. package/dist/mention.js +9 -8
  163. package/dist/{node-reveal-DY6bimv3.d.cts → node-reveal-Be7Xa0BL.d.cts} +1 -1
  164. package/dist/{node-reveal-BnFcnHhz.d.ts → node-reveal-CftIEqF_.d.ts} +1 -1
  165. package/dist/palette-DuIFHYHc.d.cts +10 -0
  166. package/dist/palette-DuIFHYHc.d.ts +10 -0
  167. package/dist/presence.cjs +39 -38
  168. package/dist/presence.js +8 -7
  169. package/dist/presence.js.map +1 -1
  170. package/dist/source.cjs +10 -9
  171. package/dist/source.d.cts +1 -1
  172. package/dist/source.d.ts +1 -1
  173. package/dist/source.js +6 -5
  174. package/dist/source.js.map +1 -1
  175. package/dist/{stats-extension-Dmw0Ujxe.d.ts → stats-extension-Bbpr593p.d.ts} +1 -1
  176. package/dist/{stats-extension-D5HySF0a.d.cts → stats-extension-D7FaeydW.d.cts} +1 -1
  177. package/dist/stats.cjs +12 -10
  178. package/dist/stats.d.cts +2 -2
  179. package/dist/stats.d.ts +2 -2
  180. package/dist/stats.js +9 -7
  181. package/dist/styles.css +1 -1
  182. package/dist/{table-extension-7LkLNK6Q.d.cts → table-extension-DNijjmxV.d.cts} +1 -1
  183. package/dist/{table-extension-DEpV0DnP.d.ts → table-extension-Dp6FYGPh.d.ts} +1 -1
  184. package/dist/table.cjs +26 -25
  185. package/dist/table.d.cts +4 -3
  186. package/dist/table.d.ts +4 -3
  187. package/dist/table.js +7 -6
  188. package/dist/{toc-extension-Dvh37bWQ.d.cts → toc-extension-BGEVAmSY.d.cts} +1 -1
  189. package/dist/{toc-extension-SVckrFmb.d.ts → toc-extension-DZIe40eV.d.ts} +1 -1
  190. package/dist/toc.cjs +10 -9
  191. package/dist/toc.d.cts +2 -2
  192. package/dist/toc.d.ts +2 -2
  193. package/dist/toc.js +7 -6
  194. package/dist/{types-DMuuDBVh.d.ts → types-Byu2a9qk.d.ts} +6 -1
  195. package/dist/{types-Bzhq5AXj.d.cts → types-DdDlCyyZ.d.cts} +6 -1
  196. package/dist/view.cjs +4 -4
  197. package/dist/view.js +2 -2
  198. package/dist/yjs.cjs +121 -121
  199. package/dist/yjs.d.cts +2 -2
  200. package/dist/yjs.d.ts +2 -2
  201. package/dist/yjs.js +5 -5
  202. package/package.json +4 -3
  203. package/dist/chunk-2BPXVQBP.js.map +0 -1
  204. package/dist/chunk-556PFYES.js.map +0 -1
  205. package/dist/chunk-5RBMZGKV.js.map +0 -1
  206. package/dist/chunk-7Y4B7NHO.js.map +0 -1
  207. package/dist/chunk-A2IQHMIH.js.map +0 -1
  208. package/dist/chunk-AJT54OMZ.js.map +0 -1
  209. package/dist/chunk-G6NBQYMM.js.map +0 -1
  210. package/dist/chunk-LU3T3JB4.js.map +0 -1
  211. package/dist/chunk-QLVX7MPS.js.map +0 -1
  212. package/dist/chunk-W376L2GM.js.map +0 -1
  213. package/dist/chunk-XE3IYW5B.js.map +0 -1
  214. package/dist/palette-BrX-hEd-.d.cts +0 -4
  215. package/dist/palette-BrX-hEd-.d.ts +0 -4
package/dist/ai.cjs CHANGED
@@ -2,14 +2,15 @@
2
2
  'use strict';
3
3
 
4
4
  var chunkLE5XMIFJ_cjs = require('./chunk-LE5XMIFJ.cjs');
5
- var chunk3HW3WRYC_cjs = require('./chunk-3HW3WRYC.cjs');
6
- var chunkEBSDPHPS_cjs = require('./chunk-EBSDPHPS.cjs');
7
- var chunk2QKFRKOP_cjs = require('./chunk-2QKFRKOP.cjs');
5
+ var chunkCSIUXYRU_cjs = require('./chunk-CSIUXYRU.cjs');
6
+ var chunk4UFWFV43_cjs = require('./chunk-4UFWFV43.cjs');
7
+ var chunkN25EH2GZ_cjs = require('./chunk-N25EH2GZ.cjs');
8
8
  var chunkZWTIRGY5_cjs = require('./chunk-ZWTIRGY5.cjs');
9
9
  require('./chunk-A6PGQVTR.cjs');
10
- var chunkFK7EBZPX_cjs = require('./chunk-FK7EBZPX.cjs');
11
- require('./chunk-DJU25PFC.cjs');
12
- var chunkI7X7B3WD_cjs = require('./chunk-I7X7B3WD.cjs');
10
+ require('./chunk-QFGWSFOI.cjs');
11
+ var chunkZ5EEDCRI_cjs = require('./chunk-Z5EEDCRI.cjs');
12
+ require('./chunk-5L2NSIHZ.cjs');
13
+ var chunk4JDRDPLC_cjs = require('./chunk-4JDRDPLC.cjs');
13
14
  var react = require('react');
14
15
  var jsxRuntime = require('react/jsx-runtime');
15
16
 
@@ -110,30 +111,30 @@ function closeStreaming(markdown) {
110
111
  // src/extensions/ai/ai-target.ts
111
112
  function targetOfBlocks(state, ids) {
112
113
  const { doc, schema } = state;
113
- const first = chunkI7X7B3WD_cjs.blockById(doc, ids[0]);
114
- const last = chunkI7X7B3WD_cjs.blockById(doc, ids[ids.length - 1]);
114
+ const first = chunk4JDRDPLC_cjs.blockById(doc, ids[0]);
115
+ const last = chunk4JDRDPLC_cjs.blockById(doc, ids[ids.length - 1]);
115
116
  if (first === void 0 || last === void 0) return null;
116
- const start = chunkFK7EBZPX_cjs.primaryRegion(schema, first);
117
- const end = chunkFK7EBZPX_cjs.primaryRegion(schema, last);
117
+ const start = chunkZ5EEDCRI_cjs.primaryRegion(schema, first);
118
+ const end = chunkZ5EEDCRI_cjs.primaryRegion(schema, last);
118
119
  if (start === null || end === null) return null;
119
120
  const from = { block: first.id, region: start, offset: 0 };
120
- return { from, to: { block: last.id, region: end, offset: chunkFK7EBZPX_cjs.regionLength(last, end) }, selected: ids.length > 1 };
121
+ return { from, to: { block: last.id, region: end, offset: chunkZ5EEDCRI_cjs.regionLength(last, end) }, selected: ids.length > 1 };
121
122
  }
122
123
  function targetOfSelection(state) {
123
124
  const { doc, selection } = state;
124
125
  if (selection === null) return null;
125
- if (selection.kind !== "text") return targetOfBlocks(state, chunkFK7EBZPX_cjs.selectedBlockIds(doc, selection));
126
- const { from, to } = chunkFK7EBZPX_cjs.orderedRange(doc, selection.anchor, selection.head);
127
- if (chunkFK7EBZPX_cjs.comparePos(doc, from, to) !== 0) return { from, to, selected: true };
126
+ if (selection.kind !== "text") return targetOfBlocks(state, chunkZ5EEDCRI_cjs.selectedBlockIds(doc, selection));
127
+ const { from, to } = chunkZ5EEDCRI_cjs.orderedRange(doc, selection.anchor, selection.head);
128
+ if (chunkZ5EEDCRI_cjs.comparePos(doc, from, to) !== 0) return { from, to, selected: true };
128
129
  const block = doc.blocks[doc.index.get(from.block)];
129
130
  const whole = { block: from.block, region: from.region };
130
- return { from: { ...whole, offset: 0 }, to: { ...whole, offset: chunkFK7EBZPX_cjs.regionLength(block, from.region) }, selected: false };
131
+ return { from: { ...whole, offset: 0 }, to: { ...whole, offset: chunkZ5EEDCRI_cjs.regionLength(block, from.region) }, selected: false };
131
132
  }
132
133
  function nearestKept(tr, target) {
133
134
  const { doc } = tr.before;
134
135
  const first = doc.index.get(target.from.block) ?? 0;
135
136
  const last = doc.index.get(target.to.block) ?? first;
136
- const kept = (block) => block && chunkI7X7B3WD_cjs.blockById(tr.doc, block.id);
137
+ const kept = (block) => block && chunk4JDRDPLC_cjs.blockById(tr.doc, block.id);
137
138
  for (let step = 1; first - step >= 0 || last + step < doc.blocks.length; step++) {
138
139
  const found = kept(doc.blocks[first - step]) ?? kept(doc.blocks[last + step]);
139
140
  if (found) return found;
@@ -142,10 +143,10 @@ function nearestKept(tr, target) {
142
143
  }
143
144
  function edgeOf(tr, target) {
144
145
  const point = tr.mapPos(target.from, -1);
145
- const block = chunkI7X7B3WD_cjs.blockById(tr.doc, point.block) ?? nearestKept(tr, target);
146
+ const block = chunk4JDRDPLC_cjs.blockById(tr.doc, point.block) ?? nearestKept(tr, target);
146
147
  if (block === void 0) return null;
147
- const region = chunkFK7EBZPX_cjs.primaryRegion(tr.before.schema, block) ?? "";
148
- const length = region === "" ? 0 : chunkFK7EBZPX_cjs.regionLength(block, region);
148
+ const region = chunkZ5EEDCRI_cjs.primaryRegion(tr.before.schema, block) ?? "";
149
+ const length = region === "" ? 0 : chunkZ5EEDCRI_cjs.regionLength(block, region);
149
150
  const offset = block.id === point.block ? Math.min(point.offset, length) : length;
150
151
  const after = offset > 0 || length === 0;
151
152
  const at = { block: block.id, region, offset: after ? length : 0 };
@@ -157,31 +158,33 @@ function mapTarget(tr, target) {
157
158
  const from = tr.mapPos(target.from, inside);
158
159
  const mapped2 = tr.mapPos(target.to, -inside);
159
160
  if (!tr.doc.index.has(from.block) || !tr.doc.index.has(mapped2.block)) return edgeOf(tr, target);
160
- const to = chunkFK7EBZPX_cjs.comparePos(tr.doc, from, mapped2) > 0 ? from : mapped2;
161
+ const to = chunkZ5EEDCRI_cjs.comparePos(tr.doc, from, mapped2) > 0 ? from : mapped2;
161
162
  return from === target.from && to === target.to ? target : { ...target, from, to };
162
163
  }
163
- var targetGone = (doc, target) => target.lost !== void 0 || target.selected && chunkFK7EBZPX_cjs.comparePos(doc, target.from, target.to) === 0;
164
+ var targetGone = (doc, target) => target.lost !== void 0 || target.selected && chunkZ5EEDCRI_cjs.comparePos(doc, target.from, target.to) === 0;
164
165
  function targetRanges(state, { from, to }) {
165
166
  const { doc, schema } = state;
166
167
  const start = doc.index.get(from.block);
167
168
  const end = doc.index.get(to.block);
168
169
  return doc.blocks.slice(start, end + 1).flatMap((block, i) => {
169
- const region = i === 0 ? from.region : block.id === to.block ? to.region : chunkFK7EBZPX_cjs.primaryRegion(schema, block);
170
+ const region = i === 0 ? from.region : block.id === to.block ? to.region : chunkZ5EEDCRI_cjs.primaryRegion(schema, block);
170
171
  if (region === null || !Object.hasOwn(block.regions, region)) return [];
171
172
  const left = i === 0 ? from.offset : 0;
172
- const right = block.id === to.block ? to.offset : chunkFK7EBZPX_cjs.regionLength(block, region);
173
+ const right = block.id === to.block ? to.offset : chunkZ5EEDCRI_cjs.regionLength(block, region);
173
174
  return right > left ? [{ block: block.id, region, from: left, to: right }] : [];
174
175
  });
175
176
  }
176
177
 
177
178
  // src/extensions/ai/ai-plugin.ts
178
- var aiKey = chunkFK7EBZPX_cjs.createPluginKey("ai");
179
+ var aiKey = chunkZ5EEDCRI_cjs.createPluginKey("ai");
179
180
  var AI = "ai";
180
181
  var IDLE = { target: null, menu: null, ghost: null, held: [] };
181
- var aiState = (state) => chunkFK7EBZPX_cjs.getPluginState(state, aiKey);
182
- var aiTransaction = (state, act2) => new chunkFK7EBZPX_cjs.Transaction(state).setMeta(AI, act2).setMeta("addToHistory", false);
183
- function written(ghost, key, phase, output) {
184
- return ghost.key !== key ? ghost : { ...ghost, phase, output, shown: closeStreaming(output) };
182
+ var aiState = (state) => chunkZ5EEDCRI_cjs.getPluginState(state, aiKey);
183
+ var aiTransaction = (state, act2) => new chunkZ5EEDCRI_cjs.Transaction(state).setMeta(AI, act2).setMeta("addToHistory", false);
184
+ function written(ghost, key, phase, output, failure) {
185
+ if (ghost.key !== key) return ghost;
186
+ const next = { ...ghost, phase, output, shown: closeStreaming(output) };
187
+ return failure === void 0 ? next : { ...next, failure };
185
188
  }
186
189
  function act(value, action) {
187
190
  switch (action.type) {
@@ -197,8 +200,8 @@ function act(value, action) {
197
200
  case "end": {
198
201
  const { ghost } = value;
199
202
  if (ghost === null || ghost.phase !== "streaming") return value;
200
- const phase = action.type === "end" ? action.phase : "streaming";
201
- return { ...value, ghost: written(ghost, action.key, phase, action.output) };
203
+ if (action.type === "stream") return { ...value, ghost: written(ghost, action.key, "streaming", action.output) };
204
+ return { ...value, ghost: written(ghost, action.key, action.phase, action.output, action.failure) };
202
205
  }
203
206
  case "discard":
204
207
  return { ...value, target: null, menu: null, ghost: null };
@@ -211,8 +214,8 @@ function caretBlock(state) {
211
214
  return selection?.kind === "text" ? selection.head.block : null;
212
215
  }
213
216
  function hasText(state, id) {
214
- const block = chunkI7X7B3WD_cjs.blockById(state.doc, id);
215
- return block !== void 0 && Object.keys(block.regions).some((region) => chunkFK7EBZPX_cjs.regionLength(block, region) > 0);
217
+ const block = chunk4JDRDPLC_cjs.blockById(state.doc, id);
218
+ return block !== void 0 && Object.keys(block.regions).some((region) => chunkZ5EEDCRI_cjs.regionLength(block, region) > 0);
216
219
  }
217
220
  function heldText(tr, value, before, after) {
218
221
  if (!tr.docChanged) return value.held;
@@ -257,6 +260,20 @@ function aiDecorations(state) {
257
260
  return decorations;
258
261
  }
259
262
 
263
+ // src/extensions/ai/ai-failure.ts
264
+ function attempt(call) {
265
+ try {
266
+ return call();
267
+ } catch {
268
+ return void 0;
269
+ }
270
+ }
271
+ function failureOf(error, { describeError, isRetryable }) {
272
+ const reason = describeError && attempt(() => describeError(error));
273
+ const retryable = attempt(() => isRetryable?.(error)) !== false;
274
+ return typeof reason === "string" && reason.trim() !== "" ? { reason, retryable } : { retryable };
275
+ }
276
+
260
277
  // src/extensions/ai/ai-actions.ts
261
278
  var MENU_ACTIONS = [
262
279
  "continue",
@@ -280,8 +297,16 @@ var links = /* @__PURE__ */ new WeakMap();
280
297
  function linkOf(editor) {
281
298
  let link = links.get(editor);
282
299
  if (link === void 0) {
283
- link = { mounts: 0, run: null, last: null, report: (error) => console.error(error), ended: () => {
284
- }, stopWatching: null };
300
+ link = {
301
+ mounts: 0,
302
+ run: null,
303
+ last: null,
304
+ report: (error) => console.error(error),
305
+ failure: () => ({ retryable: true }),
306
+ ended: () => {
307
+ },
308
+ stopWatching: null
309
+ };
285
310
  links.set(editor, link);
286
311
  }
287
312
  return link;
@@ -310,13 +335,13 @@ function aroundSelection(text, start, end, limit = CONTEXT_LIMIT) {
310
335
  }
311
336
  var WHITESPACE_ENTITY = /(?<!\\)&#(32|9);/g;
312
337
  var plain = (markdown) => markdown.replace(WHITESPACE_ENTITY, (_, code) => code === "32" ? " " : " ");
313
- var markdownOf = (state, blocks) => chunkFK7EBZPX_cjs.toMarkdown(blocks, { schema: state.schema, comments: false });
338
+ var markdownOf = (state, blocks) => chunkZ5EEDCRI_cjs.toMarkdown(blocks, { schema: state.schema, comments: false });
314
339
  function rangeMarkdown(state, from, to) {
315
- const slice = chunkFK7EBZPX_cjs.sliceFromSelection({ ...state, selection: chunkFK7EBZPX_cjs.textSelection(from, to) }, chunkI7X7B3WD_cjs.createBlockCodec(state.schema));
340
+ const slice = chunkZ5EEDCRI_cjs.sliceFromSelection({ ...state, selection: chunkZ5EEDCRI_cjs.textSelection(from, to) }, chunk4JDRDPLC_cjs.createBlockCodec(state.schema));
316
341
  return slice === null ? "" : markdownOf(state, slice.blocks).replace(/\n$/, "");
317
342
  }
318
343
  function documentContext(state, target, selection) {
319
- const blocks = chunkI7X7B3WD_cjs.createBlockCodec(state.schema).blocksFromDoc(state.doc);
344
+ const blocks = chunk4JDRDPLC_cjs.createBlockCodec(state.schema).blocksFromDoc(state.doc);
320
345
  const full = plain(markdownOf(state, blocks));
321
346
  if (full.length <= CONTEXT_LIMIT) return full;
322
347
  const index = state.doc.index.get(target.from.block) ?? 0;
@@ -355,9 +380,9 @@ function endRun(link, ended = false) {
355
380
  var send = (editor, act2) => editor.dispatch(aiTransaction(editor.state, act2));
356
381
  async function read(editor, link, run, stream, request) {
357
382
  const live = () => link.run === run && link.mounts > 0;
358
- const end = (phase) => {
383
+ const end = (phase, failure) => {
359
384
  endRun(link, true);
360
- send(editor, { type: "end", key: run.key, phase, output: run.output });
385
+ send(editor, { type: "end", key: run.key, phase, output: run.output, ...failure && { failure } });
361
386
  };
362
387
  const draw = () => {
363
388
  run.cancelFrame = null;
@@ -376,8 +401,8 @@ async function read(editor, link, run, stream, request) {
376
401
  link.ended("done", run.output);
377
402
  } catch (error) {
378
403
  if (!live()) return;
379
- end("error");
380
- link.report(chunkEBSDPHPS_cjs.toError(error));
404
+ end("error", link.failure(error));
405
+ link.report(chunk4UFWFV43_cjs.toError(error));
381
406
  }
382
407
  }
383
408
  function startStream(editor, link, stream, request, replace) {
@@ -474,7 +499,7 @@ function aiSlashItems(labels, stream) {
474
499
  title: labels.askAi,
475
500
  description: labels.askAiDescription,
476
501
  group: "ai",
477
- icon: chunkEBSDPHPS_cjs.Sparkles,
502
+ icon: chunk4UFWFV43_cjs.Sparkles,
478
503
  keywords: KEYWORDS,
479
504
  run: ({ controller }) => void openFor(controller)
480
505
  },
@@ -482,7 +507,7 @@ function aiSlashItems(labels, stream) {
482
507
  id: "ai-continue",
483
508
  title: labels.actions.continue,
484
509
  group: "ai",
485
- icon: chunkEBSDPHPS_cjs.PenLine,
510
+ icon: chunk4UFWFV43_cjs.PenLine,
486
511
  keywords: [...KEYWORDS, "continue"],
487
512
  run: ({ controller }) => {
488
513
  if (openFor(controller)) askFrom({ controller, stream}, "continue");
@@ -493,14 +518,14 @@ function aiSlashItems(labels, stream) {
493
518
  var aiBubbleItem = (labels) => ({
494
519
  id: "ai",
495
520
  title: labels.askAi,
496
- icon: chunkEBSDPHPS_cjs.Sparkles,
521
+ icon: chunk4UFWFV43_cjs.Sparkles,
497
522
  available: (state) => aiState(state).ghost === null,
498
523
  run: (controller) => void openFor(controller)
499
524
  });
500
525
  var aiBlockMenuItem = (labels) => ({
501
526
  id: "ai",
502
527
  label: labels.askAi,
503
- icon: chunkEBSDPHPS_cjs.Sparkles,
528
+ icon: chunk4UFWFV43_cjs.Sparkles,
504
529
  available: (state, blockIds) => targetOfBlocks(state, blockIds) !== null,
505
530
  run: (controller, blockIds) => {
506
531
  const target = targetOfBlocks(controller.editor.state, blockIds);
@@ -549,25 +574,25 @@ var resolveAiLabels = (overrides) => chunkZWTIRGY5_cjs.mergeLabels(englishAiLabe
549
574
  var openOnSpace = (state, dispatch) => {
550
575
  const { selection, doc } = state;
551
576
  const ai = aiState(state);
552
- if (selection?.kind !== "text" || !chunkFK7EBZPX_cjs.isCollapsed(selection) || ai.menu !== null || ai.ghost !== null) return false;
577
+ if (selection?.kind !== "text" || !chunkZ5EEDCRI_cjs.isCollapsed(selection) || ai.menu !== null || ai.ghost !== null) return false;
553
578
  const { head } = selection;
554
579
  const block = doc.blocks[doc.index.get(head.block)];
555
580
  const paragraph = block.type === "MARKDOWN" && block.attrs.kind === "paragraph";
556
- if (!paragraph || chunkFK7EBZPX_cjs.regionLength(block, head.region) > 0 || ai.held.includes(block.id)) return false;
581
+ if (!paragraph || chunkZ5EEDCRI_cjs.regionLength(block, head.region) > 0 || ai.held.includes(block.id)) return false;
557
582
  dispatch?.(aiTransaction(state, { type: "open", target: { from: head, to: head, selected: false }, fromSpace: true }));
558
583
  return true;
559
584
  };
560
585
 
561
586
  // src/extensions/ai/ai-accept.ts
562
- var isParagraph = (block) => block?.type === "MARKDOWN" && chunkI7X7B3WD_cjs.parseLine(String(block.data.markdown ?? "")).kind === "paragraph";
587
+ var isParagraph = (block) => block?.type === "MARKDOWN" && chunk4JDRDPLC_cjs.parseLine(String(block.data.markdown ?? "")).kind === "paragraph";
563
588
  var DISCARD = { type: "discard" };
564
589
  function insertBeside(tr, schema, target, pieces, makeId) {
565
590
  const index = tr.doc.index.get(target.to.block);
566
- const at = target.lost?.after ? chunkFK7EBZPX_cjs.descendantsEnd(tr.doc, index) : index;
567
- const fresh = chunkFK7EBZPX_cjs.freshBlocks(pieces, tr.doc.blocks[index].indent, makeId);
568
- tr.step(chunkFK7EBZPX_cjs.insertBlocksStep(at, fresh));
569
- chunkFK7EBZPX_cjs.capIndents(tr, at, at + fresh.length);
570
- tr.setSelection(chunkFK7EBZPX_cjs.endOf(tr.doc, schema, fresh[fresh.length - 1].id));
591
+ const at = target.lost?.after ? chunkZ5EEDCRI_cjs.descendantsEnd(tr.doc, index) : index;
592
+ const fresh = chunkZ5EEDCRI_cjs.freshBlocks(pieces, tr.doc.blocks[index].indent, makeId);
593
+ tr.step(chunkZ5EEDCRI_cjs.insertBlocksStep(at, fresh));
594
+ chunkZ5EEDCRI_cjs.capIndents(tr, at, at + fresh.length);
595
+ tr.setSelection(chunkZ5EEDCRI_cjs.endOf(tr.doc, schema, fresh[fresh.length - 1].id));
571
596
  }
572
597
  function acceptAnswer(editor) {
573
598
  const { state } = editor;
@@ -575,7 +600,7 @@ function acceptAnswer(editor) {
575
600
  if (target === null || ghost === null || ghost.phase === "streaming" || ghost.phase === "error") return null;
576
601
  const { codec } = editor;
577
602
  const makeId = codec.context.newId;
578
- const blocks = chunkI7X7B3WD_cjs.fromMarkdown(ghost.output, { newId: makeId });
603
+ const blocks = chunk4JDRDPLC_cjs.fromMarkdown(ghost.output, { newId: makeId });
579
604
  const pieces = blocks.flatMap((block) => codec.toEngineBlocks(block));
580
605
  const tr = editor.createTransaction().setOrigin("ai").setMeta(AI, DISCARD);
581
606
  const gone = targetGone(state.doc, target);
@@ -585,12 +610,12 @@ function acceptAnswer(editor) {
585
610
  const { schema } = state;
586
611
  const open = { openStart: isParagraph(blocks[0]), openEnd: isParagraph(blocks[blocks.length - 1]) };
587
612
  if (ghost.replace || gone) {
588
- const caret = ghost.replace && !gone ? chunkFK7EBZPX_cjs.deleteRange(tr, schema, target.from, target.to, makeId) : target.to;
589
- chunkFK7EBZPX_cjs.pasteAtCaret(tr, schema, caret, open, pieces, makeId);
613
+ const caret = ghost.replace && !gone ? chunkZ5EEDCRI_cjs.deleteRange(tr, schema, target.from, target.to, makeId) : target.to;
614
+ chunkZ5EEDCRI_cjs.pasteAtCaret(tr, schema, caret, open, pieces, makeId);
590
615
  } else {
591
616
  const block = tr.doc.blocks[tr.doc.index.get(target.to.block)];
592
- const end = { ...target.to, offset: chunkFK7EBZPX_cjs.regionLength(block, target.to.region) };
593
- chunkFK7EBZPX_cjs.pasteAtCaret(tr, schema, end, { openStart: false, openEnd: false }, pieces, makeId);
617
+ const end = { ...target.to, offset: chunkZ5EEDCRI_cjs.regionLength(block, target.to.region) };
618
+ chunkZ5EEDCRI_cjs.pasteAtCaret(tr, schema, end, { openStart: false, openEnd: false }, pieces, makeId);
594
619
  }
595
620
  }
596
621
  editor.dispatch(tr);
@@ -603,14 +628,15 @@ function AiBar({ env, ghost, gone, barId }) {
603
628
  const content = react.useRef(null);
604
629
  const inside = react.useRef(false);
605
630
  const [next, setNext] = react.useState("");
606
- const { phase } = ghost;
631
+ const { phase, failure } = ghost;
632
+ const retryable = failure?.retryable !== false;
607
633
  const focusPrimary = () => content.current?.querySelector(`[${PRIMARY}]`)?.focus();
608
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
634
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
609
635
  const active = content.current?.ownerDocument.activeElement;
610
636
  inside.current = active == null || active === active.ownerDocument.body;
611
637
  if (inside.current) focusPrimary();
612
638
  }, []);
613
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
639
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
614
640
  const active = content.current?.ownerDocument.activeElement;
615
641
  if (inside.current && !content.current?.contains(active ?? null)) focusPrimary();
616
642
  }, [phase, ghost.key]);
@@ -658,21 +684,24 @@ function AiBar({ env, ghost, gone, barId }) {
658
684
  children: [
659
685
  phase === "streaming" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
660
686
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: labels.writing }),
661
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.Button, { ...primary, size: "sm", variant: "outline", onClick: () => stop(editor), children: labels.stop })
687
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.Button, { ...primary, size: "sm", variant: "outline", onClick: () => stop(editor), children: labels.stop })
662
688
  ] }),
663
689
  phase === "error" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
664
- /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-sm text-destructive", children: labels.failed }),
665
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.Button, { ...primary, size: "sm", onClick: () => retry(editor, stream), children: labels.retry }),
666
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.Button, { size: "sm", variant: "ghost", onClick: onDiscard, children: labels.discard })
690
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", className: "text-sm", children: [
691
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive", children: labels.failed }),
692
+ failure?.reason !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: failure.reason })
693
+ ] }),
694
+ retryable && /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.Button, { ...primary, size: "sm", onClick: () => retry(editor, stream), children: labels.retry }),
695
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.Button, { ...retryable ? {} : primary, size: "sm", variant: "ghost", onClick: onDiscard, children: labels.discard })
667
696
  ] }),
668
697
  (phase === "done" || phase === "stopped") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
669
698
  phase === "stopped" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: labels.stopped }),
670
699
  gone && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "w-full text-xs text-muted-foreground", children: labels.targetGone }),
671
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.Button, { ...primary, size: "sm", onClick: onAccept, children: labels.accept }),
672
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.Button, { size: "sm", variant: "ghost", onClick: onDiscard, children: labels.discard }),
673
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.Button, { size: "sm", variant: "ghost", onClick: () => retry(editor, stream), children: labels.retry }),
700
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.Button, { ...primary, size: "sm", onClick: onAccept, children: labels.accept }),
701
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.Button, { size: "sm", variant: "ghost", onClick: onDiscard, children: labels.discard }),
702
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.Button, { size: "sm", variant: "ghost", onClick: () => retry(editor, stream), children: labels.retry }),
674
703
  /* @__PURE__ */ jsxRuntime.jsx("form", { className: "w-full", onSubmit: onFollowUp, children: /* @__PURE__ */ jsxRuntime.jsx(
675
- chunkEBSDPHPS_cjs.Input,
704
+ chunk4UFWFV43_cjs.Input,
676
705
  {
677
706
  "aria-label": labels.followUp,
678
707
  placeholder: labels.followUp,
@@ -693,8 +722,8 @@ function AiBar({ env, ghost, gone, barId }) {
693
722
  var reader = null;
694
723
  function readerOf() {
695
724
  if (reader === null) {
696
- const schema = chunkI7X7B3WD_cjs.createSchema();
697
- reader = { schema, codec: chunkI7X7B3WD_cjs.createBlockCodec(schema) };
725
+ const schema = chunk4JDRDPLC_cjs.createSchema();
726
+ reader = { schema, codec: chunk4JDRDPLC_cjs.createBlockCodec(schema) };
698
727
  }
699
728
  return reader;
700
729
  }
@@ -702,16 +731,16 @@ function fillGhost(ghost, markdown) {
702
731
  const doc = ghost.ownerDocument;
703
732
  const { schema, codec } = readerOf();
704
733
  const drawn2 = [];
705
- for (const block of chunkI7X7B3WD_cjs.fromMarkdown(markdown)) {
734
+ for (const block of chunk4JDRDPLC_cjs.fromMarkdown(markdown)) {
706
735
  for (const piece of codec.toEngineBlocks(block)) {
707
736
  const element = doc.createElement("div");
708
737
  element.className = "quoin-ai-ghost-block";
709
738
  element.dataset.kind = String(piece.attrs.kind ?? piece.type.toLowerCase());
710
739
  if (piece.attrs.level !== void 0) element.dataset.level = String(piece.attrs.level);
711
740
  if (piece.indent > 0) element.style.setProperty("--quoin-ai-indent", String(piece.indent));
712
- const region = chunkFK7EBZPX_cjs.primaryRegion(schema, piece);
713
- if (region === null) element.textContent = chunkFK7EBZPX_cjs.toPlainText([codec.toQuoin(piece)], { schema });
714
- else chunk2QKFRKOP_cjs.renderInline(element, piece.regions[region], []);
741
+ const region = chunkZ5EEDCRI_cjs.primaryRegion(schema, piece);
742
+ if (region === null) element.textContent = chunkZ5EEDCRI_cjs.toPlainText([codec.toQuoin(piece)], { schema });
743
+ else chunkN25EH2GZ_cjs.renderInline(element, piece.regions[region], []);
715
744
  drawn2.push(element);
716
745
  }
717
746
  }
@@ -788,7 +817,7 @@ function clipAside(layer, text, areas, scale) {
788
817
  function useGhostPlace(controller, layer, block, region) {
789
818
  const placeNow = react.useRef(() => {
790
819
  });
791
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
820
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
792
821
  const root = controller.root;
793
822
  const element = layer.current;
794
823
  const view = root?.ownerDocument.defaultView;
@@ -827,7 +856,7 @@ function AiGhost({ env, ghost, target, gone, barId }) {
827
856
  const layer = react.useRef(null);
828
857
  const drawn2 = react.useRef(null);
829
858
  const place2 = useGhostPlace(env.controller, layer, target.to.block, target.to.region);
830
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
859
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
831
860
  const element = drawn2.current;
832
861
  if (element === null) return;
833
862
  element.setAttribute("inert", "");
@@ -841,7 +870,7 @@ function AiGhost({ env, ghost, target, gone, barId }) {
841
870
  }
842
871
  function useTargetAnchor(controller, target) {
843
872
  const latest = react.useRef(target);
844
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
873
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
845
874
  latest.current = target;
846
875
  });
847
876
  return react.useMemo(() => {
@@ -850,8 +879,8 @@ function useTargetAnchor(controller, target) {
850
879
  return { block: to.block, region: to.region, from: to.offset, to: to.offset };
851
880
  };
852
881
  return {
853
- current: chunkEBSDPHPS_cjs.virtualAnchor(
854
- () => chunkEBSDPHPS_cjs.rangeRect(controller, end()),
882
+ current: chunk4UFWFV43_cjs.virtualAnchor(
883
+ () => chunk4UFWFV43_cjs.rangeRect(controller, end()),
855
884
  () => controller.registry.get(end().block, end().region)
856
885
  )
857
886
  };
@@ -905,7 +934,7 @@ function AiMenu({ env, target, fromSpace }) {
905
934
  };
906
935
  const fieldLabel = asking === "tone" ? labels.tonePrompt : asking === "translate" ? labels.translatePrompt : labels.prompt;
907
936
  return /* @__PURE__ */ jsxRuntime.jsxs(
908
- chunkEBSDPHPS_cjs.Popover,
937
+ chunk4UFWFV43_cjs.Popover,
909
938
  {
910
939
  open: true,
911
940
  modal: false,
@@ -913,9 +942,9 @@ function AiMenu({ env, target, fromSpace }) {
913
942
  if (!next) closeMenu(controller.editor);
914
943
  },
915
944
  children: [
916
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.PopoverAnchor, { virtualRef: anchor }),
945
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.PopoverAnchor, { virtualRef: anchor }),
917
946
  /* @__PURE__ */ jsxRuntime.jsxs(
918
- chunkEBSDPHPS_cjs.PopoverContent,
947
+ chunk4UFWFV43_cjs.PopoverContent,
919
948
  {
920
949
  "aria-label": labels.askAi,
921
950
  side: "bottom",
@@ -932,7 +961,7 @@ function AiMenu({ env, target, fromSpace }) {
932
961
  },
933
962
  children: [
934
963
  /* @__PURE__ */ jsxRuntime.jsx(
935
- chunkEBSDPHPS_cjs.Input,
964
+ chunk4UFWFV43_cjs.Input,
936
965
  {
937
966
  ref: field,
938
967
  role: "combobox",
@@ -950,13 +979,13 @@ function AiMenu({ env, target, fromSpace }) {
950
979
  onKeyDown
951
980
  }
952
981
  ),
953
- choices.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { id: `${id}-list`, role: "listbox", "aria-label": labels.menu, className: "mt-1 max-h-72 overflow-y-auto", children: choices.map((choice, index) => /* @__PURE__ */ jsxRuntime.jsx(
982
+ choices.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { id: `${id}-list`, role: "listbox", "aria-label": labels.menu, className: "mt-1 max-h-72 list-none overflow-y-auto", children: choices.map((choice, index) => /* @__PURE__ */ jsxRuntime.jsx(
954
983
  "li",
955
984
  {
956
985
  id: optionId(index),
957
986
  role: "option",
958
987
  "aria-selected": index === current,
959
- className: chunkEBSDPHPS_cjs.cn(chunkEBSDPHPS_cjs.MENU_ITEM, index === current && "bg-accent text-accent-foreground"),
988
+ className: chunk4UFWFV43_cjs.cn(chunk4UFWFV43_cjs.MENU_ITEM, index === current && "bg-accent text-accent-foreground"),
960
989
  onMouseDown: (event) => event.preventDefault(),
961
990
  onClick: () => choose(choice),
962
991
  children: choice.label
@@ -974,17 +1003,17 @@ var goneOf = (state) => {
974
1003
  const { target, ghost } = aiState(state);
975
1004
  return target !== null && ghost !== null && targetGone(state.doc, target);
976
1005
  };
977
- var plainText = (markdown) => chunkFK7EBZPX_cjs.toPlainText(chunkI7X7B3WD_cjs.fromMarkdown(markdown));
1006
+ var plainText = (markdown) => chunkZ5EEDCRI_cjs.toPlainText(chunk4JDRDPLC_cjs.fromMarkdown(markdown));
978
1007
  function AiOverlay({ controller, stream, labels }) {
979
- const { onError } = chunkEBSDPHPS_cjs.useQuoin();
1008
+ const { onError } = chunk4UFWFV43_cjs.useQuoin();
980
1009
  const link = linkOf(controller.editor);
981
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
1010
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
982
1011
  link.report = onError;
983
1012
  link.ended = (phase, output) => controller.announce((phase === "done" ? labels.written : labels.halted)(plainText(output)));
984
1013
  }, [link, onError, controller, labels]);
985
- const value = chunk2QKFRKOP_cjs.useEditorState(controller, aiState);
986
- const gone = chunk2QKFRKOP_cjs.useEditorState(controller, goneOf);
987
- const readOnly = chunk2QKFRKOP_cjs.useReadOnly(controller);
1014
+ const value = chunkN25EH2GZ_cjs.useEditorState(controller, aiState);
1015
+ const gone = chunkN25EH2GZ_cjs.useEditorState(controller, goneOf);
1016
+ const readOnly = chunkN25EH2GZ_cjs.useReadOnly(controller);
988
1017
  const env = react.useMemo(() => ({ controller, stream, labels }), [controller, stream, labels]);
989
1018
  const barId = react.useId();
990
1019
  const showing = value.ghost !== null;
@@ -1003,7 +1032,7 @@ function AiOverlay({ controller, stream, labels }) {
1003
1032
  const root = controller.root;
1004
1033
  if (!root) return;
1005
1034
  let away = true;
1006
- return chunk3HW3WRYC_cjs.watchCanvasFocus(controller, root.ownerDocument, (inside, node) => {
1035
+ return chunkCSIUXYRU_cjs.watchCanvasFocus(controller, root.ownerDocument, (inside, node) => {
1007
1036
  if (!inside) away = true;
1008
1037
  else if (root.contains(node)) {
1009
1038
  if (away) noteFocus(controller.editor);
@@ -1039,7 +1068,7 @@ function aiExtension(options) {
1039
1068
  blockMenuItems: [aiBlockMenuItem(labels)],
1040
1069
  overlays: [Overlay]
1041
1070
  };
1042
- return chunkFK7EBZPX_cjs.defineExtension({
1071
+ return chunkZ5EEDCRI_cjs.defineExtension({
1043
1072
  name: "ai",
1044
1073
  plugins: [aiPlugin],
1045
1074
  decorations: aiDecorations,
@@ -1047,6 +1076,7 @@ function aiExtension(options) {
1047
1076
  // One watcher per editor however many views mount it, and the stream ends with the last of them.
1048
1077
  onMount(editor) {
1049
1078
  const link = linkOf(editor);
1079
+ link.failure = (error) => failureOf(error, options);
1050
1080
  if (link.mounts++ === 0) link.stopWatching = watchGhost(editor, link);
1051
1081
  return () => {
1052
1082
  if (--link.mounts > 0) return;
package/dist/ai.d.cts CHANGED
@@ -8,6 +8,13 @@ type AiOptions = {
8
8
  stream: AiStream;
9
9
  /** Every string AI actions show or speak, English by default. A key left out stays English. */
10
10
  labels?: Partial<AiLabels>;
11
+ /**
12
+ * The reason a failed answer shows under `labels.failed`, given what the stream threw or rejected with. Nothing is
13
+ * shown for an error it returns undefined for, so an error it was not written for stays out of the bar.
14
+ */
15
+ describeError?: (error: unknown) => string | undefined;
16
+ /** Whether a failed answer is worth asking for again: false leaves Discard alone in the bar. Defaults to always. */
17
+ isRetryable?: (error: unknown) => boolean;
11
18
  };
12
19
  /**
13
20
  * AI actions on the host's model: the AI menu, opened from the slash menu, the toolbar, the block menu or a Space on
package/dist/ai.d.ts CHANGED
@@ -8,6 +8,13 @@ type AiOptions = {
8
8
  stream: AiStream;
9
9
  /** Every string AI actions show or speak, English by default. A key left out stays English. */
10
10
  labels?: Partial<AiLabels>;
11
+ /**
12
+ * The reason a failed answer shows under `labels.failed`, given what the stream threw or rejected with. Nothing is
13
+ * shown for an error it returns undefined for, so an error it was not written for stays out of the bar.
14
+ */
15
+ describeError?: (error: unknown) => string | undefined;
16
+ /** Whether a failed answer is worth asking for again: false leaves Discard alone in the bar. Defaults to always. */
17
+ isRetryable?: (error: unknown) => boolean;
11
18
  };
12
19
  /**
13
20
  * AI actions on the host's model: the AI menu, opened from the slash menu, the toolbar, the block menu or a Space on