@agent-native/toolkit 0.4.10 → 0.5.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 (143) hide show
  1. package/README.md +17 -6
  2. package/dist/collab-ui/agent-identity.d.ts +9 -0
  3. package/dist/collab-ui/agent-identity.d.ts.map +1 -0
  4. package/dist/collab-ui/agent-identity.js +9 -0
  5. package/dist/collab-ui/agent-identity.js.map +1 -0
  6. package/dist/collab-ui/index.d.ts +2 -0
  7. package/dist/collab-ui/index.d.ts.map +1 -1
  8. package/dist/collab-ui/index.js +2 -0
  9. package/dist/collab-ui/index.js.map +1 -1
  10. package/dist/collab-ui/lead-client.d.ts +3 -0
  11. package/dist/collab-ui/lead-client.d.ts.map +1 -0
  12. package/dist/collab-ui/lead-client.js +29 -0
  13. package/dist/collab-ui/lead-client.js.map +1 -0
  14. package/dist/context-ui/ContextMeter.d.ts +10 -0
  15. package/dist/context-ui/ContextMeter.d.ts.map +1 -0
  16. package/dist/context-ui/ContextMeter.js +20 -0
  17. package/dist/context-ui/ContextMeter.js.map +1 -0
  18. package/dist/context-ui/ContextSegmentRow.d.ts +14 -0
  19. package/dist/context-ui/ContextSegmentRow.d.ts.map +1 -0
  20. package/dist/context-ui/ContextSegmentRow.js +25 -0
  21. package/dist/context-ui/ContextSegmentRow.js.map +1 -0
  22. package/dist/context-ui/ContextTreemap.d.ts +7 -0
  23. package/dist/context-ui/ContextTreemap.d.ts.map +1 -0
  24. package/dist/context-ui/ContextTreemap.js +55 -0
  25. package/dist/context-ui/ContextTreemap.js.map +1 -0
  26. package/dist/context-ui/ContextXRayPanel.d.ts +13 -0
  27. package/dist/context-ui/ContextXRayPanel.d.ts.map +1 -0
  28. package/dist/context-ui/ContextXRayPanel.js +120 -0
  29. package/dist/context-ui/ContextXRayPanel.js.map +1 -0
  30. package/dist/context-ui/format.d.ts +6 -0
  31. package/dist/context-ui/format.d.ts.map +1 -0
  32. package/dist/context-ui/format.js +58 -0
  33. package/dist/context-ui/format.js.map +1 -0
  34. package/dist/context-ui/index.d.ts +7 -0
  35. package/dist/context-ui/index.d.ts.map +1 -0
  36. package/dist/context-ui/index.js +6 -0
  37. package/dist/context-ui/index.js.map +1 -0
  38. package/dist/context-ui/types.d.ts +39 -0
  39. package/dist/context-ui/types.d.ts.map +1 -0
  40. package/dist/context-ui/types.js +2 -0
  41. package/dist/context-ui/types.js.map +1 -0
  42. package/dist/design-tweaks/index.d.ts +2 -0
  43. package/dist/design-tweaks/index.d.ts.map +1 -0
  44. package/dist/design-tweaks/index.js +2 -0
  45. package/dist/design-tweaks/index.js.map +1 -0
  46. package/dist/design-tweaks/visual-style-controls.d.ts +90 -0
  47. package/dist/design-tweaks/visual-style-controls.d.ts.map +1 -0
  48. package/dist/design-tweaks/visual-style-controls.js +499 -0
  49. package/dist/design-tweaks/visual-style-controls.js.map +1 -0
  50. package/dist/editor/BubbleToolbar.d.ts +37 -0
  51. package/dist/editor/BubbleToolbar.d.ts.map +1 -0
  52. package/dist/editor/BubbleToolbar.js +171 -0
  53. package/dist/editor/BubbleToolbar.js.map +1 -0
  54. package/dist/editor/CodeBlockNode.d.ts +49 -0
  55. package/dist/editor/CodeBlockNode.d.ts.map +1 -0
  56. package/dist/editor/CodeBlockNode.js +127 -0
  57. package/dist/editor/CodeBlockNode.js.map +1 -0
  58. package/dist/editor/DragHandle.d.ts +97 -0
  59. package/dist/editor/DragHandle.d.ts.map +1 -0
  60. package/dist/editor/DragHandle.js +1066 -0
  61. package/dist/editor/DragHandle.js.map +1 -0
  62. package/dist/editor/DragHandle.spec.d.ts +2 -0
  63. package/dist/editor/DragHandle.spec.d.ts.map +1 -0
  64. package/dist/editor/DragHandle.spec.js +407 -0
  65. package/dist/editor/DragHandle.spec.js.map +1 -0
  66. package/dist/editor/ImageExtension.d.ts +63 -0
  67. package/dist/editor/ImageExtension.d.ts.map +1 -0
  68. package/dist/editor/ImageExtension.js +243 -0
  69. package/dist/editor/ImageExtension.js.map +1 -0
  70. package/dist/editor/ImageExtension.roundtrip.spec.d.ts +2 -0
  71. package/dist/editor/ImageExtension.roundtrip.spec.d.ts.map +1 -0
  72. package/dist/editor/ImageExtension.roundtrip.spec.js +103 -0
  73. package/dist/editor/ImageExtension.roundtrip.spec.js.map +1 -0
  74. package/dist/editor/RichMarkdownEditor.collab.spec.d.ts +2 -0
  75. package/dist/editor/RichMarkdownEditor.collab.spec.d.ts.map +1 -0
  76. package/dist/editor/RichMarkdownEditor.collab.spec.js +65 -0
  77. package/dist/editor/RichMarkdownEditor.collab.spec.js.map +1 -0
  78. package/dist/editor/RichMarkdownEditor.d.ts +52 -0
  79. package/dist/editor/RichMarkdownEditor.d.ts.map +1 -0
  80. package/dist/editor/RichMarkdownEditor.js +38 -0
  81. package/dist/editor/RichMarkdownEditor.js.map +1 -0
  82. package/dist/editor/RichMarkdownEditor.roundtrip.spec.d.ts +2 -0
  83. package/dist/editor/RichMarkdownEditor.roundtrip.spec.d.ts.map +1 -0
  84. package/dist/editor/RichMarkdownEditor.roundtrip.spec.js +186 -0
  85. package/dist/editor/RichMarkdownEditor.roundtrip.spec.js.map +1 -0
  86. package/dist/editor/RunId.d.ts +28 -0
  87. package/dist/editor/RunId.d.ts.map +1 -0
  88. package/dist/editor/RunId.js +60 -0
  89. package/dist/editor/RunId.js.map +1 -0
  90. package/dist/editor/SharedRichEditor.d.ts +110 -0
  91. package/dist/editor/SharedRichEditor.d.ts.map +1 -0
  92. package/dist/editor/SharedRichEditor.js +144 -0
  93. package/dist/editor/SharedRichEditor.js.map +1 -0
  94. package/dist/editor/SlashCommandMenu.d.ts +41 -0
  95. package/dist/editor/SlashCommandMenu.d.ts.map +1 -0
  96. package/dist/editor/SlashCommandMenu.js +221 -0
  97. package/dist/editor/SlashCommandMenu.js.map +1 -0
  98. package/dist/editor/disableHistory.spec.d.ts +2 -0
  99. package/dist/editor/disableHistory.spec.d.ts.map +1 -0
  100. package/dist/editor/disableHistory.spec.js +73 -0
  101. package/dist/editor/disableHistory.spec.js.map +1 -0
  102. package/dist/editor/extensions.d.ts +178 -0
  103. package/dist/editor/extensions.d.ts.map +1 -0
  104. package/dist/editor/extensions.js +224 -0
  105. package/dist/editor/extensions.js.map +1 -0
  106. package/dist/editor/gfmDoc.d.ts +24 -0
  107. package/dist/editor/gfmDoc.d.ts.map +1 -0
  108. package/dist/editor/gfmDoc.js +83 -0
  109. package/dist/editor/gfmDoc.js.map +1 -0
  110. package/dist/editor/gfmDoc.spec.d.ts +2 -0
  111. package/dist/editor/gfmDoc.spec.d.ts.map +1 -0
  112. package/dist/editor/gfmDoc.spec.js +194 -0
  113. package/dist/editor/gfmDoc.spec.js.map +1 -0
  114. package/dist/editor/index.d.ts +13 -0
  115. package/dist/editor/index.d.ts.map +1 -0
  116. package/dist/editor/index.js +13 -0
  117. package/dist/editor/index.js.map +1 -0
  118. package/dist/editor/structuralReorderUndo.spec.d.ts +2 -0
  119. package/dist/editor/structuralReorderUndo.spec.d.ts.map +1 -0
  120. package/dist/editor/structuralReorderUndo.spec.js +120 -0
  121. package/dist/editor/structuralReorderUndo.spec.js.map +1 -0
  122. package/dist/editor/surgical-apply.d.ts +66 -0
  123. package/dist/editor/surgical-apply.d.ts.map +1 -0
  124. package/dist/editor/surgical-apply.js +147 -0
  125. package/dist/editor/surgical-apply.js.map +1 -0
  126. package/dist/editor/surgical-apply.spec.d.ts +2 -0
  127. package/dist/editor/surgical-apply.spec.d.ts.map +1 -0
  128. package/dist/editor/surgical-apply.spec.js +257 -0
  129. package/dist/editor/surgical-apply.spec.js.map +1 -0
  130. package/dist/editor/useCollabReconcile.concurrent.spec.d.ts +2 -0
  131. package/dist/editor/useCollabReconcile.concurrent.spec.d.ts.map +1 -0
  132. package/dist/editor/useCollabReconcile.concurrent.spec.js +329 -0
  133. package/dist/editor/useCollabReconcile.concurrent.spec.js.map +1 -0
  134. package/dist/editor/useCollabReconcile.d.ts +110 -0
  135. package/dist/editor/useCollabReconcile.d.ts.map +1 -0
  136. package/dist/editor/useCollabReconcile.idempotent.spec.d.ts +2 -0
  137. package/dist/editor/useCollabReconcile.idempotent.spec.d.ts.map +1 -0
  138. package/dist/editor/useCollabReconcile.idempotent.spec.js +248 -0
  139. package/dist/editor/useCollabReconcile.idempotent.spec.js.map +1 -0
  140. package/dist/editor/useCollabReconcile.js +440 -0
  141. package/dist/editor/useCollabReconcile.js.map +1 -0
  142. package/dist/editor.css +510 -0
  143. package/package.json +63 -9
@@ -0,0 +1,243 @@
1
+ import Image from "@tiptap/extension-image";
2
+ import { Plugin, PluginKey } from "@tiptap/pm/state";
3
+ const sharedImageUploadPluginKey = new PluginKey("an-shared-image-upload");
4
+ /** A monotonically increasing id so concurrent uploads patch the right node. */
5
+ let uploadCounter = 0;
6
+ function nextUploadId() {
7
+ uploadCounter += 1;
8
+ return `an-img-${Date.now()}-${uploadCounter}`;
9
+ }
10
+ /** Image files only — never ingest non-image clipboard/drop payloads. */
11
+ function imageFilesFrom(data) {
12
+ if (!data)
13
+ return [];
14
+ return Array.from(data.files ?? []).filter((file) => file.type.startsWith("image/"));
15
+ }
16
+ /**
17
+ * Insert a placeholder `image` node (empty `src`, transient `uploadId`) at
18
+ * `pos` for every file, then resolve each upload and patch the matching node's
19
+ * `src`. Mirrors Content's optimistic upload flow but is self-contained in the
20
+ * shared extension so it works for ANY editor wrapper (the plan's
21
+ * `SharedRichEditor` and Content's hand-rolled `useEditor` alike) without a new
22
+ * `editorProps` seam.
23
+ */
24
+ function uploadAndInsertImages(view, files, pos, upload) {
25
+ if (files.length === 0)
26
+ return;
27
+ const pending = [];
28
+ // Insert all placeholders first, top-down from `pos`, so multi-file
29
+ // paste/drop keeps source order.
30
+ let insertAt = pos;
31
+ for (const file of files) {
32
+ const uploadId = nextUploadId();
33
+ const node = view.state.schema.nodes.image?.create({
34
+ src: "",
35
+ alt: "",
36
+ uploadId,
37
+ });
38
+ if (!node)
39
+ continue;
40
+ const tr = view.state.tr.insert(insertAt, node);
41
+ view.dispatch(tr);
42
+ pending.push({ uploadId, file });
43
+ // Advance past the inserted atom for the next placeholder.
44
+ insertAt += node.nodeSize;
45
+ }
46
+ for (const item of pending) {
47
+ void (async () => {
48
+ try {
49
+ const { src, alt } = await upload(item.file);
50
+ if (!view.dom.isConnected || view.isDestroyed)
51
+ return;
52
+ patchUploadNode(view, item.uploadId, { src, alt: alt ?? "" });
53
+ }
54
+ catch (error) {
55
+ console.error("Image upload failed:", error);
56
+ // Drop the placeholder so a failed upload does not leave an empty box.
57
+ if (view.dom.isConnected && !view.isDestroyed) {
58
+ removeUploadNode(view, item.uploadId);
59
+ }
60
+ }
61
+ })();
62
+ }
63
+ }
64
+ /** Find a placeholder node by its transient `uploadId` and return its position. */
65
+ function findUploadNode(view, uploadId) {
66
+ let found = null;
67
+ view.state.doc.descendants((node, pos) => {
68
+ if (found)
69
+ return false;
70
+ if (node.type.name === "image" && node.attrs.uploadId === uploadId) {
71
+ found = { pos, nodeSize: node.nodeSize };
72
+ return false;
73
+ }
74
+ return true;
75
+ });
76
+ return found;
77
+ }
78
+ /** Patch the resolved `src`/`alt` onto the placeholder and clear `uploadId`. */
79
+ function patchUploadNode(view, uploadId, attrs) {
80
+ const target = findUploadNode(view, uploadId);
81
+ if (!target)
82
+ return;
83
+ const node = view.state.doc.nodeAt(target.pos);
84
+ if (!node)
85
+ return;
86
+ const tr = view.state.tr.setNodeMarkup(target.pos, undefined, {
87
+ ...node.attrs,
88
+ src: attrs.src,
89
+ alt: attrs.alt,
90
+ uploadId: null,
91
+ });
92
+ view.dispatch(tr);
93
+ }
94
+ /** Remove a placeholder whose upload failed. */
95
+ function removeUploadNode(view, uploadId) {
96
+ const target = findUploadNode(view, uploadId);
97
+ if (!target)
98
+ return;
99
+ const tr = view.state.tr.delete(target.pos, target.pos + target.nodeSize);
100
+ view.dispatch(tr);
101
+ }
102
+ /**
103
+ * The SHARED block-level image node. Built on `@tiptap/extension-image` (a
104
+ * node named `image`), so:
105
+ *
106
+ * - **GFM serialization** emits pure `![alt](src)` markdown via a block-aware
107
+ * `addStorage().markdown.serialize` (it calls `closeBlock` so a block image
108
+ * keeps its blank-line separator, byte-stable). It emits NO `<img width>`
109
+ * HTML, so plans stay source-syncable under the GFM `html:false` contract.
110
+ * - **Paste / drop** of local image files is handled by a self-contained
111
+ * ProseMirror plugin that calls the injected {@link ImageUploadFn}. Pasting
112
+ * an image URL or `![](url)` markdown works through the base node's input
113
+ * rules even when no uploader is supplied.
114
+ *
115
+ * The node adds one transient `uploadId` attribute (never parsed/rendered to
116
+ * HTML, never serialized to markdown) used to track an in-flight upload.
117
+ *
118
+ * Content keeps its own richer `ImageNode` (Assets picker, AI alt-text, resize,
119
+ * NFM `{color}` serialization) and does NOT use this shared node — both nodes
120
+ * are named `image` but never coexist in the same editor because Content leaves
121
+ * `features.image` off and injects its own via `extraExtensions`.
122
+ */
123
+ export const SharedImage = Image.extend({
124
+ // Block-level atom (Content's image is also a block atom). The base extension
125
+ // is block when `inline:false`.
126
+ inline: false,
127
+ group: "block",
128
+ addOptions() {
129
+ return {
130
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
131
+ ...this.parent(),
132
+ onImageUpload: null,
133
+ };
134
+ },
135
+ addAttributes() {
136
+ return {
137
+ ...this.parent?.(),
138
+ // Transient: marks an in-flight upload so the plugin can patch `src` on
139
+ // resolve. Never written to HTML or markdown.
140
+ uploadId: {
141
+ default: null,
142
+ parseHTML: () => null,
143
+ renderHTML: () => ({}),
144
+ },
145
+ };
146
+ },
147
+ addStorage() {
148
+ return {
149
+ ...this.parent?.(),
150
+ // A BLOCK-aware markdown serializer. tiptap-markdown's built-in fallback
151
+ // for the `image` node is prosemirror-markdown's INLINE image serializer,
152
+ // which omits the trailing block separator — so an image immediately
153
+ // followed by a paragraph loses its blank line on round-trip. This
154
+ // node-level spec (merged OVER the fallback by tiptap-markdown's
155
+ // `getMarkdownSpec`) emits the same pure `![alt](src)` markdown but calls
156
+ // `closeBlock`, so a block image stays byte-stable and source-syncable.
157
+ // No `<img width>` / HTML is emitted, so the GFM `html:false` contract and
158
+ // the plan round-trip corpus are preserved.
159
+ markdown: {
160
+ serialize(state, node) {
161
+ const src = node.attrs.src ?? "";
162
+ const alt = node.attrs.alt ?? "";
163
+ const title = node.attrs.title ?? "";
164
+ const titleSuffix = title ? ` "${title.replace(/"/g, '\\"')}"` : "";
165
+ state.write(`![${state.esc(alt)}](${state.esc(src)}${titleSuffix})`);
166
+ state.closeBlock(node);
167
+ },
168
+ parse: {
169
+ // Parsing `![alt](src)` is handled by markdown-it + the base node's
170
+ // markdown input rule.
171
+ },
172
+ },
173
+ };
174
+ },
175
+ addProseMirrorPlugins() {
176
+ const upload = this.options.onImageUpload;
177
+ const parentPlugins = this.parent?.() ?? [];
178
+ if (!upload)
179
+ return parentPlugins;
180
+ return [
181
+ ...parentPlugins,
182
+ new Plugin({
183
+ key: sharedImageUploadPluginKey,
184
+ props: {
185
+ handlePaste(view, event) {
186
+ const files = imageFilesFrom(event.clipboardData);
187
+ if (files.length === 0)
188
+ return false;
189
+ event.preventDefault();
190
+ uploadAndInsertImages(view, files, view.state.selection.from, upload);
191
+ return true;
192
+ },
193
+ handleDrop(view, event) {
194
+ const files = imageFilesFrom(event.dataTransfer);
195
+ if (files.length === 0)
196
+ return false;
197
+ event.preventDefault();
198
+ const coords = view.posAtCoords({
199
+ left: event.clientX,
200
+ top: event.clientY,
201
+ });
202
+ const pos = coords?.pos ?? view.state.selection.from;
203
+ uploadAndInsertImages(view, files, pos, upload);
204
+ return true;
205
+ },
206
+ },
207
+ }),
208
+ ];
209
+ },
210
+ });
211
+ /**
212
+ * Build the shared image extension, optionally wired with an app uploader.
213
+ *
214
+ * @example
215
+ * createImageExtension({ onImageUpload: uploadEditorImage })
216
+ */
217
+ export function createImageExtension(options = {}) {
218
+ return SharedImage.configure({
219
+ onImageUpload: options.onImageUpload ?? null,
220
+ HTMLAttributes: { class: "an-rich-md-image" },
221
+ });
222
+ }
223
+ /**
224
+ * Open a native file picker, then upload + insert the chosen image(s) through
225
+ * the same flow as paste/drop. Used by the `/image` slash command.
226
+ */
227
+ export function pickAndInsertImage(view, upload) {
228
+ const input = document.createElement("input");
229
+ input.type = "file";
230
+ input.accept = "image/*";
231
+ input.multiple = true;
232
+ input.style.display = "none";
233
+ input.addEventListener("change", () => {
234
+ const files = Array.from(input.files ?? []).filter((file) => file.type.startsWith("image/"));
235
+ input.remove();
236
+ if (files.length === 0)
237
+ return;
238
+ uploadAndInsertImages(view, files, view.state.selection.from, upload);
239
+ });
240
+ document.body.appendChild(input);
241
+ input.click();
242
+ }
243
+ //# sourceMappingURL=ImageExtension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageExtension.js","sourceRoot":"","sources":["../../src/editor/ImageExtension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ImageExtension.roundtrip.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageExtension.roundtrip.spec.d.ts","sourceRoot":"","sources":["../../src/editor/ImageExtension.roundtrip.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,103 @@
1
+ // @vitest-environment happy-dom
2
+ import { Editor } from "@tiptap/core";
3
+ import { describe, expect, it } from "vitest";
4
+ import { createSharedEditorExtensions } from "./extensions.js";
5
+ /**
6
+ * GFM image round-trip for the SHARED block-level image node.
7
+ *
8
+ * Plans turn on `features.image` and rely on the image serializing to standard
9
+ * markdown image syntax (`![alt](src)`) so plan blocks stay source-syncable and
10
+ * byte-stable. The shared image node is built on `@tiptap/extension-image` (a
11
+ * node named `image`), so tiptap-markdown serializes it through its built-in
12
+ * `defaultMarkdownSerializer.nodes.image` fallback — NO custom `<img width>`
13
+ * HTML override (that would break the GFM `html:false` contract).
14
+ *
15
+ * This mounts an `Editor` from the same `createSharedEditorExtensions` factory
16
+ * the editor component uses, with `features.image: true` (the plan config), and
17
+ * pins:
18
+ * - markdown `![alt](src)` parses to an `image` node and re-serializes
19
+ * byte-identically, and
20
+ * - a programmatically inserted image node serializes to `![alt](src)`.
21
+ */
22
+ function buildEditor(content) {
23
+ return new Editor({
24
+ element: document.createElement("div"),
25
+ extensions: createSharedEditorExtensions({
26
+ dialect: "gfm",
27
+ features: { image: true },
28
+ }),
29
+ content,
30
+ });
31
+ }
32
+ function getMarkdown(editor) {
33
+ const storage = editor.storage;
34
+ return storage.markdown?.getMarkdown?.() ?? "";
35
+ }
36
+ function roundTrip(markdown) {
37
+ const editor = buildEditor(markdown);
38
+ try {
39
+ return getMarkdown(editor);
40
+ }
41
+ finally {
42
+ editor.destroy();
43
+ }
44
+ }
45
+ describe("shared image block — GFM markdown round-trip", () => {
46
+ it("round-trips a standalone image (byte-stable)", () => {
47
+ expect(roundTrip("![A cat](https://cdn.example.com/cat.png)")).toBe("![A cat](https://cdn.example.com/cat.png)");
48
+ });
49
+ it("round-trips an image with no alt text", () => {
50
+ expect(roundTrip("![](https://cdn.example.com/y.png)")).toBe("![](https://cdn.example.com/y.png)");
51
+ });
52
+ it("round-trips an image embedded mid-body with a following paragraph (byte-stable)", () => {
53
+ // The shared node's block-aware markdown serializer calls `closeBlock`, so
54
+ // an image immediately followed by a paragraph keeps its blank-line
55
+ // separator — byte-stable, unlike tiptap-markdown's inline default.
56
+ const body = [
57
+ "# Title",
58
+ "",
59
+ "Intro paragraph.",
60
+ "",
61
+ "![diagram](https://cdn.example.com/d.png)",
62
+ "",
63
+ "Closing paragraph.",
64
+ ].join("\n");
65
+ expect(roundTrip(body)).toBe(body);
66
+ });
67
+ it("round-trips an image as the final block (byte-stable)", () => {
68
+ const body = [
69
+ "# Title",
70
+ "",
71
+ "Intro paragraph.",
72
+ "",
73
+ "![diagram](https://cdn.example.com/d.png)",
74
+ ].join("\n");
75
+ expect(roundTrip(body)).toBe(body);
76
+ });
77
+ it("parses `![alt](src)` markdown into an `image` node", () => {
78
+ const editor = buildEditor("![A cat](https://cdn.example.com/cat.png)");
79
+ try {
80
+ const json = editor.getJSON();
81
+ const flat = JSON.stringify(json);
82
+ expect(flat).toContain('"type":"image"');
83
+ expect(flat).toContain("https://cdn.example.com/cat.png");
84
+ }
85
+ finally {
86
+ editor.destroy();
87
+ }
88
+ });
89
+ it("serializes a programmatically inserted image node to `![alt](src)`", () => {
90
+ const editor = buildEditor("");
91
+ try {
92
+ editor.commands.setImage({
93
+ src: "https://cdn.example.com/x.png",
94
+ alt: "X",
95
+ });
96
+ expect(getMarkdown(editor)).toBe("![X](https://cdn.example.com/x.png)");
97
+ }
98
+ finally {
99
+ editor.destroy();
100
+ }
101
+ });
102
+ });
103
+ //# sourceMappingURL=ImageExtension.roundtrip.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageExtension.roundtrip.spec.js","sourceRoot":"","sources":["../../src/editor/ImageExtension.roundtrip.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=RichMarkdownEditor.collab.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichMarkdownEditor.collab.spec.d.ts","sourceRoot":"","sources":["../../src/editor/RichMarkdownEditor.collab.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ // @vitest-environment happy-dom
2
+ import { describe, expect, it } from "vitest";
3
+ import { Awareness } from "y-protocols/awareness";
4
+ import * as Y from "yjs";
5
+ import { createRichMarkdownExtensions } from "./RichMarkdownEditor.js";
6
+ /**
7
+ * The optional collaboration wiring on the shared rich-markdown editor must be
8
+ * strictly additive: with no `ydoc`, the editor behaves exactly as the existing
9
+ * controlled single-user editor (no Collaboration extensions, undo/redo on);
10
+ * with a `ydoc`, it binds Collaboration (+ a CollaborationCaret when awareness
11
+ * is present) and disables StarterKit's undo/redo so Yjs owns history.
12
+ */
13
+ function extensionNames(opts) {
14
+ return createRichMarkdownExtensions(opts).map((ext) => ext.name);
15
+ }
16
+ describe("createRichMarkdownExtensions collaboration wiring", () => {
17
+ it("adds no collaboration extensions when ydoc is absent", () => {
18
+ const names = extensionNames();
19
+ expect(names).not.toContain("collaboration");
20
+ expect(names).not.toContain("collaborationCaret");
21
+ });
22
+ it("adds Collaboration only when a ydoc is provided", () => {
23
+ const ydoc = new Y.Doc();
24
+ try {
25
+ const names = extensionNames({ ydoc });
26
+ expect(names).toContain("collaboration");
27
+ // No awareness → no caret extension, but core collab still binds.
28
+ expect(names).not.toContain("collaborationCaret");
29
+ }
30
+ finally {
31
+ ydoc.destroy();
32
+ }
33
+ });
34
+ it("adds CollaborationCaret when ydoc and awareness are both provided", () => {
35
+ const ydoc = new Y.Doc();
36
+ const awareness = new Awareness(ydoc);
37
+ try {
38
+ const names = extensionNames({
39
+ ydoc,
40
+ awareness,
41
+ user: { name: "Ada", color: "#60a5fa", email: "ada@example.com" },
42
+ });
43
+ expect(names).toContain("collaboration");
44
+ expect(names).toContain("collaborationCaret");
45
+ }
46
+ finally {
47
+ awareness.destroy();
48
+ ydoc.destroy();
49
+ }
50
+ });
51
+ it("disables StarterKit undo/redo only in collab mode", () => {
52
+ const findStarterKit = (opts) => createRichMarkdownExtensions(opts).find((ext) => ext.name === "starterKit");
53
+ const standalone = findStarterKit();
54
+ expect(standalone?.options?.undoRedo).toBe(undefined);
55
+ const ydoc = new Y.Doc();
56
+ try {
57
+ const collab = findStarterKit({ ydoc });
58
+ expect(collab?.options?.undoRedo).toBe(false);
59
+ }
60
+ finally {
61
+ ydoc.destroy();
62
+ }
63
+ });
64
+ });
65
+ //# sourceMappingURL=RichMarkdownEditor.collab.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichMarkdownEditor.collab.spec.js","sourceRoot":"","sources":["../../src/editor/RichMarkdownEditor.collab.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { Awareness } from "y-protocols/awareness";
2
+ import type { Doc as YDoc } from "yjs";
3
+ /**
4
+ * Back-compat surface for the shared rich markdown editor.
5
+ *
6
+ * The editor core now lives in dedicated modules:
7
+ * - {@link createSharedEditorExtensions} — the ONE extension factory.
8
+ * - {@link useCollabReconcile} — seed / reconcile / lead-client logic.
9
+ * - {@link SlashCommandMenu} / {@link BubbleToolbar} — shared menus.
10
+ * - {@link SharedRichEditor} — the editor component.
11
+ *
12
+ * This file keeps the historical `RichMarkdownEditor` component name (aliased to
13
+ * {@link SharedRichEditor}) and the `createRichMarkdownExtensions` factory so
14
+ * existing embedders and the round-trip / collab specs keep working unchanged.
15
+ */
16
+ import { type RichMarkdownDialect, type RichMarkdownEditorPreset, type RichMarkdownCollabUser } from "./extensions.js";
17
+ import { SharedRichEditor, type SharedRichEditorProps } from "./SharedRichEditor.js";
18
+ export type { RichMarkdownDialect, RichMarkdownEditorPreset, RichMarkdownCollabUser, };
19
+ /** @deprecated Prefer {@link CreateSharedEditorExtensionsOptions}. */
20
+ export interface CreateRichMarkdownExtensionsOptions {
21
+ dialect?: RichMarkdownDialect;
22
+ placeholder?: string;
23
+ /**
24
+ * Yjs document for collaborative editing. When present, the editor binds the
25
+ * shared Collaboration + CollaborationCaret extensions and StarterKit's
26
+ * built-in undo/redo is disabled (Yjs owns history).
27
+ */
28
+ ydoc?: YDoc | null;
29
+ /** Shared awareness instance for live multi-user cursors. */
30
+ awareness?: Awareness | null;
31
+ /** Current user info for the collaborative cursor label. */
32
+ user?: RichMarkdownCollabUser | null;
33
+ }
34
+ /**
35
+ * Back-compat factory preserving today's GFM/plan behavior EXACTLY. Implemented
36
+ * in terms of {@link createSharedEditorExtensions}: it maps the flat
37
+ * `{ ydoc, awareness, user }` collab options into the nested `collab` shape the
38
+ * shared factory expects. The round-trip and collab specs build their `Editor`
39
+ * from this, so its output must stay byte-stable.
40
+ */
41
+ export declare function createRichMarkdownExtensions({ dialect, placeholder, ydoc, awareness, user, }?: CreateRichMarkdownExtensionsOptions): (import("@tiptap/core").Extension<any, any> | import("@tiptap/core").Mark<any, any> | import("@tiptap/core").Node<any, any>)[];
42
+ /** @deprecated Prefer {@link SharedRichEditorProps}. */
43
+ export type RichMarkdownEditorProps = SharedRichEditorProps;
44
+ /**
45
+ * Historical name for {@link SharedRichEditor}. Kept so existing imports
46
+ * (`import { RichMarkdownEditor } from "@agent-native/core/client"`) and the
47
+ * plan editor tests (which assert the source mentions `RichMarkdownEditor`)
48
+ * keep working through the Core compatibility re-export. New code should import
49
+ * `SharedRichEditor` from `@agent-native/toolkit/editor`.
50
+ */
51
+ export declare const RichMarkdownEditor: typeof SharedRichEditor;
52
+ //# sourceMappingURL=RichMarkdownEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichMarkdownEditor.d.ts","sourceRoot":"","sources":["../../src/editor/RichMarkdownEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC;AAEvC;;;;;;;;;;;;GAYG;AACH,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,sBAAsB,GACvB,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,mCAAmC;IAClD,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,EAC3C,OAAe,EACf,WAAwC,EACxC,IAAW,EACX,SAAgB,EAChB,IAAW,GACZ,GAAE,mCAAwC,kIAM1C;AAED,wDAAwD;AACxD,MAAM,MAAM,uBAAuB,GAAG,qBAAqB,CAAC;AAE5D;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,yBAAmB,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Back-compat surface for the shared rich markdown editor.
3
+ *
4
+ * The editor core now lives in dedicated modules:
5
+ * - {@link createSharedEditorExtensions} — the ONE extension factory.
6
+ * - {@link useCollabReconcile} — seed / reconcile / lead-client logic.
7
+ * - {@link SlashCommandMenu} / {@link BubbleToolbar} — shared menus.
8
+ * - {@link SharedRichEditor} — the editor component.
9
+ *
10
+ * This file keeps the historical `RichMarkdownEditor` component name (aliased to
11
+ * {@link SharedRichEditor}) and the `createRichMarkdownExtensions` factory so
12
+ * existing embedders and the round-trip / collab specs keep working unchanged.
13
+ */
14
+ import { createSharedEditorExtensions, } from "./extensions.js";
15
+ import { SharedRichEditor, } from "./SharedRichEditor.js";
16
+ /**
17
+ * Back-compat factory preserving today's GFM/plan behavior EXACTLY. Implemented
18
+ * in terms of {@link createSharedEditorExtensions}: it maps the flat
19
+ * `{ ydoc, awareness, user }` collab options into the nested `collab` shape the
20
+ * shared factory expects. The round-trip and collab specs build their `Editor`
21
+ * from this, so its output must stay byte-stable.
22
+ */
23
+ export function createRichMarkdownExtensions({ dialect = "gfm", placeholder = "Type '/' for commands...", ydoc = null, awareness = null, user = null, } = {}) {
24
+ return createSharedEditorExtensions({
25
+ dialect,
26
+ placeholder,
27
+ collab: ydoc ? { ydoc, awareness, user } : null,
28
+ });
29
+ }
30
+ /**
31
+ * Historical name for {@link SharedRichEditor}. Kept so existing imports
32
+ * (`import { RichMarkdownEditor } from "@agent-native/core/client"`) and the
33
+ * plan editor tests (which assert the source mentions `RichMarkdownEditor`)
34
+ * keep working through the Core compatibility re-export. New code should import
35
+ * `SharedRichEditor` from `@agent-native/toolkit/editor`.
36
+ */
37
+ export const RichMarkdownEditor = SharedRichEditor;
38
+ //# sourceMappingURL=RichMarkdownEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichMarkdownEditor.js","sourceRoot":"","sources":["../../src/editor/RichMarkdownEditor.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,4BAA4B,GAI7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAwB/B;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAAC,EAC3C,OAAO,GAAG,KAAK,EACf,WAAW,GAAG,0BAA0B,EACxC,IAAI,GAAG,IAAI,EACX,SAAS,GAAG,IAAI,EAChB,IAAI,GAAG,IAAI,GACZ,GAAwC,EAAE;IACzC,OAAO,4BAA4B,CAAC;QAClC,OAAO;QACP,WAAW;QACX,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;KAChD,CAAC,CAAC;AACL,CAAC;AAKD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=RichMarkdownEditor.roundtrip.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichMarkdownEditor.roundtrip.spec.d.ts","sourceRoot":"","sources":["../../src/editor/RichMarkdownEditor.roundtrip.spec.ts"],"names":[],"mappings":""}