@agent-native/toolkit 0.10.5 → 0.10.7
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.
- package/dist/composer/PromptComposer.d.ts +10 -0
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +14 -15
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/PromptComposer.spec.js +24 -1
- package/dist/composer/PromptComposer.spec.js.map +1 -1
- package/dist/editor/useCollabReconcile.concurrent.spec.js +240 -1
- package/dist/editor/useCollabReconcile.concurrent.spec.js.map +1 -1
- package/dist/editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/editor/useCollabReconcile.js +77 -13
- package/dist/editor/useCollabReconcile.js.map +1 -1
- package/package.json +1 -1
- package/src/composer/PromptComposer.spec.ts +38 -1
- package/src/composer/PromptComposer.tsx +23 -20
- package/src/editor/useCollabReconcile.concurrent.spec.ts +270 -1
- package/src/editor/useCollabReconcile.ts +83 -15
|
@@ -18,6 +18,11 @@ export function getEditorMarkdown(editor) {
|
|
|
18
18
|
* is identical, so skipping it is safe by construction.
|
|
19
19
|
*/
|
|
20
20
|
const EMITTED_RING_MAX = 16;
|
|
21
|
+
// The hosted awareness transport polls every 2s when its SSE gateway cannot
|
|
22
|
+
// forward presence. Give that first snapshot one poll plus margin before an
|
|
23
|
+
// empty SQL value is allowed to clear a nonempty Y.Doc. This is the same settle
|
|
24
|
+
// window used below when a known peer may deliver an edit through Yjs.
|
|
25
|
+
const PEER_SETTLE_MS = 2500;
|
|
21
26
|
function pushEmittedRing(ring, value) {
|
|
22
27
|
if (!value)
|
|
23
28
|
return;
|
|
@@ -119,6 +124,11 @@ export function useCollabReconcile({ editor, ydoc = null, collabSynced = true, a
|
|
|
119
124
|
// arrives via Yjs, so external markdown reconcile must defer (avoid applying
|
|
120
125
|
// the same change through both Yjs and setContent).
|
|
121
126
|
const peerCountRef = useRef(0);
|
|
127
|
+
// Briefly gates the first empty-SQL reconcile while Collaboration projects
|
|
128
|
+
// a nonempty fragment. `seededRef` is still released immediately so a real
|
|
129
|
+
// first keystroke can persist; this ref only postpones the ambiguous clear
|
|
130
|
+
// decision until we can distinguish an active/local edit from stale CRDT.
|
|
131
|
+
const emptySnapshotDecisionPendingRef = useRef(false);
|
|
122
132
|
useEffect(() => {
|
|
123
133
|
if (!collab || !awareness || !ydoc) {
|
|
124
134
|
setIsLeadClient(true);
|
|
@@ -159,25 +169,68 @@ export function useCollabReconcile({ editor, ydoc = null, collabSynced = true, a
|
|
|
159
169
|
return;
|
|
160
170
|
if (!collabSynced)
|
|
161
171
|
return;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Seed only when the shared doc is genuinely empty — either the fragment has
|
|
169
|
-
// no nodes yet, or it holds no semantic markdown (an empty paragraph, or an
|
|
170
|
-
// app's sentinel-empty filler via a custom `shouldSeed`).
|
|
171
|
-
if (!shouldSeed({ value, currentMarkdown, fragmentLength: fragment.length })) {
|
|
172
|
+
// An empty SQL value has nothing to seed. Release the first real keystroke
|
|
173
|
+
// immediately, but when a fragment already exists defer the ambiguous
|
|
174
|
+
// reconcile decision for one task: active-peer or just-emitted local content
|
|
175
|
+
// is live and must be adopted; stale persisted CRDT with no active writer is
|
|
176
|
+
// cleared by the canonical SQL snapshot.
|
|
177
|
+
if (!value.trim()) {
|
|
172
178
|
seededRef.current = true;
|
|
173
|
-
|
|
179
|
+
const fragment = ydoc.getXmlFragment("default");
|
|
180
|
+
const currentMarkdown = getMarkdown(editor);
|
|
181
|
+
if (fragment.length === 0 && !currentMarkdown.trim())
|
|
182
|
+
return;
|
|
183
|
+
emptySnapshotDecisionPendingRef.current = true;
|
|
184
|
+
let cancelled = false;
|
|
185
|
+
const adoptTimer = setTimeout(() => {
|
|
186
|
+
if (cancelled || editor.isDestroyed)
|
|
187
|
+
return;
|
|
188
|
+
const projectedMarkdown = getMarkdown(editor);
|
|
189
|
+
const isOwnFreshEdit = projectedMarkdown.trim() &&
|
|
190
|
+
(projectedMarkdown === lastEmittedRef.current ||
|
|
191
|
+
recentEmittedRef.current.includes(projectedMarkdown));
|
|
192
|
+
if (projectedMarkdown.trim() &&
|
|
193
|
+
(peerCountRef.current > 0 || isOwnFreshEdit)) {
|
|
194
|
+
lastAppliedValueRef.current = value;
|
|
195
|
+
lastAppliedSerializedRef.current = projectedMarkdown;
|
|
196
|
+
if (contentUpdatedAt) {
|
|
197
|
+
lastAppliedUpdatedAtRef.current = contentUpdatedAt;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
emptySnapshotDecisionPendingRef.current = false;
|
|
201
|
+
}, awareness ? PEER_SETTLE_MS : 0);
|
|
202
|
+
return () => {
|
|
203
|
+
cancelled = true;
|
|
204
|
+
clearTimeout(adoptTimer);
|
|
205
|
+
emptySnapshotDecisionPendingRef.current = false;
|
|
206
|
+
};
|
|
174
207
|
}
|
|
208
|
+
if (!isLeadClient)
|
|
209
|
+
return;
|
|
175
210
|
let cancelled = false;
|
|
176
211
|
// Defer via a timer task (NOT a microtask — microtasks can still run
|
|
177
212
|
// inside React's commit and trigger flushSync-from-lifecycle warnings).
|
|
213
|
+
// Read the editor and fragment INSIDE that task. The collaboration
|
|
214
|
+
// extension can finish projecting an already-populated Y.Doc into
|
|
215
|
+
// ProseMirror after this effect is scheduled. Capturing the pre-projection
|
|
216
|
+
// empty editor here would incorrectly seed the SQL snapshot alongside the
|
|
217
|
+
// existing CRDT content, duplicating the whole document after reload.
|
|
178
218
|
const seedTimer = setTimeout(() => {
|
|
179
219
|
if (cancelled || editor.isDestroyed)
|
|
180
220
|
return;
|
|
221
|
+
const fragment = ydoc.getXmlFragment("default");
|
|
222
|
+
const currentMarkdown = getMarkdown(editor);
|
|
223
|
+
// Seed only when the shared doc is genuinely empty — either the fragment
|
|
224
|
+
// has no nodes yet, or it holds no semantic markdown (an empty paragraph,
|
|
225
|
+
// or an app's sentinel-empty filler via a custom `shouldSeed`).
|
|
226
|
+
if (!shouldSeed({
|
|
227
|
+
value,
|
|
228
|
+
currentMarkdown,
|
|
229
|
+
fragmentLength: fragment.length,
|
|
230
|
+
})) {
|
|
231
|
+
seededRef.current = true;
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
181
234
|
isSettingContentRef.current = true;
|
|
182
235
|
try {
|
|
183
236
|
setContent(editor, value, {});
|
|
@@ -223,16 +276,27 @@ export function useCollabReconcile({ editor, ydoc = null, collabSynced = true, a
|
|
|
223
276
|
// With peers present, a peer's edit also arrives via Yjs. Defer one poll
|
|
224
277
|
// cycle (+margin) and re-check before applying via setContent so the same
|
|
225
278
|
// change isn't inserted twice (Yjs + setContent → duplicated region).
|
|
226
|
-
const PEER_SETTLE_MS = 2500;
|
|
227
279
|
const apply = (deferred = false) => {
|
|
228
280
|
if (cancelled || editor.isDestroyed)
|
|
229
281
|
return;
|
|
230
282
|
// In collab mode, defer all reconcile until the shared doc is seeded so we
|
|
231
283
|
// never setContent over an unseeded fragment.
|
|
232
|
-
if (collab &&
|
|
284
|
+
if (collab && !collabSynced) {
|
|
233
285
|
retry = setTimeout(() => apply(deferred), 300);
|
|
234
286
|
return;
|
|
235
287
|
}
|
|
288
|
+
// The seed decision itself is deferred one task so Collaboration can
|
|
289
|
+
// project persisted Y.Doc state before we inspect it. Poll that short
|
|
290
|
+
// handoff promptly: waiting the full provider cadence here makes a newer
|
|
291
|
+
// canonical SQL snapshot visibly stale after reload.
|
|
292
|
+
if (collab && !seededRef.current) {
|
|
293
|
+
retry = setTimeout(() => apply(deferred), 25);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (collab && emptySnapshotDecisionPendingRef.current) {
|
|
297
|
+
retry = setTimeout(() => apply(deferred), 50);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
236
300
|
const currentMarkdown = getMarkdown(editor);
|
|
237
301
|
// Compare against the canonical form the editor would emit so a serializer
|
|
238
302
|
// that re-normalizes (Content's NFM) still recognizes "already in sync".
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCollabReconcile.js","sourceRoot":"","sources":["../../src/editor/useCollabReconcile.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useCollabReconcile.js","sourceRoot":"","sources":["../../src/editor/useCollabReconcile.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
buildPromptComposerSubmission,
|
|
7
|
+
shouldGateComposerForMissingEngine,
|
|
8
|
+
} from "./PromptComposer.js";
|
|
9
|
+
|
|
10
|
+
describe("shouldGateComposerForMissingEngine", () => {
|
|
11
|
+
it("never disables the composer while the status check is unresolved", () => {
|
|
12
|
+
for (const state of ["unknown", "unavailable"]) {
|
|
13
|
+
expect(
|
|
14
|
+
shouldGateComposerForMissingEngine({ state, hasSetupComponent: true }),
|
|
15
|
+
).toBe(false);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("gates only when a connect affordance can be rendered", () => {
|
|
20
|
+
expect(
|
|
21
|
+
shouldGateComposerForMissingEngine({
|
|
22
|
+
state: "missing",
|
|
23
|
+
hasSetupComponent: true,
|
|
24
|
+
}),
|
|
25
|
+
).toBe(true);
|
|
26
|
+
expect(
|
|
27
|
+
shouldGateComposerForMissingEngine({
|
|
28
|
+
state: "missing",
|
|
29
|
+
hasSetupComponent: false,
|
|
30
|
+
}),
|
|
31
|
+
).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("leaves the composer usable once an engine is configured", () => {
|
|
35
|
+
expect(
|
|
36
|
+
shouldGateComposerForMissingEngine({
|
|
37
|
+
state: "configured",
|
|
38
|
+
hasSetupComponent: true,
|
|
39
|
+
}),
|
|
40
|
+
).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
6
43
|
|
|
7
44
|
describe("buildPromptComposerSubmission", () => {
|
|
8
45
|
it("passes images through files only — never inlines base64 into prompt text", async () => {
|
|
@@ -228,6 +228,19 @@ function formatInlineTextFile(name: string, text: string): string {
|
|
|
228
228
|
.join("\n");
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Only a confirmed-missing engine that also has a setup component to render
|
|
233
|
+
* may block typing: a disabled composer with no way out is never an acceptable
|
|
234
|
+
* terminal state, and `unknown`/`unavailable` mean the status check has not
|
|
235
|
+
* answered — not that no provider is configured.
|
|
236
|
+
*/
|
|
237
|
+
export function shouldGateComposerForMissingEngine(input: {
|
|
238
|
+
state: string;
|
|
239
|
+
hasSetupComponent: boolean;
|
|
240
|
+
}): boolean {
|
|
241
|
+
return input.state === "missing" && input.hasSetupComponent;
|
|
242
|
+
}
|
|
243
|
+
|
|
231
244
|
export async function buildPromptComposerSubmission(options: {
|
|
232
245
|
text: string;
|
|
233
246
|
attachments?: ReadonlyArray<unknown>;
|
|
@@ -518,7 +531,6 @@ function PromptComposerInner({
|
|
|
518
531
|
resolvedModelStatusChecksEnabled,
|
|
519
532
|
);
|
|
520
533
|
const missingApiKey = agentEngineConfigured.missing;
|
|
521
|
-
const agentEngineUnavailable = agentEngineConfigured.state === "unavailable";
|
|
522
534
|
const [missingKeyBouncePulse, setMissingKeyBouncePulse] = useState(0);
|
|
523
535
|
const bounceMissingKeySetup = useCallback(() => {
|
|
524
536
|
setMissingKeyBouncePulse((pulse) => pulse + 1);
|
|
@@ -531,11 +543,6 @@ function PromptComposerInner({
|
|
|
531
543
|
window.dispatchEvent(new Event("agent-engine:configured-changed"));
|
|
532
544
|
}
|
|
533
545
|
}, []);
|
|
534
|
-
const retryAgentEngineStatus = useCallback(() => {
|
|
535
|
-
if (typeof window !== "undefined") {
|
|
536
|
-
window.dispatchEvent(new Event("agent-engine:configured-changed"));
|
|
537
|
-
}
|
|
538
|
-
}, []);
|
|
539
546
|
|
|
540
547
|
useEffect(() => {
|
|
541
548
|
if (!autoFocus) return;
|
|
@@ -576,6 +583,12 @@ function PromptComposerInner({
|
|
|
576
583
|
[composerEffort, composerEngine, composerModel, onSubmit],
|
|
577
584
|
);
|
|
578
585
|
const useInlineMissingKeySetup = layoutVariant === "compact";
|
|
586
|
+
const gateComposer = shouldGateComposerForMissingEngine({
|
|
587
|
+
state: agentEngineConfigured.state,
|
|
588
|
+
hasSetupComponent: Boolean(
|
|
589
|
+
useInlineMissingKeySetup ? BuilderSetupContent : BuilderSetupCard,
|
|
590
|
+
),
|
|
591
|
+
});
|
|
579
592
|
|
|
580
593
|
return (
|
|
581
594
|
<>
|
|
@@ -598,31 +611,21 @@ function PromptComposerInner({
|
|
|
598
611
|
<AgentComposerFrame
|
|
599
612
|
className={cn(
|
|
600
613
|
"text-start",
|
|
601
|
-
|
|
614
|
+
gateComposer && "cursor-pointer",
|
|
602
615
|
className,
|
|
603
616
|
)}
|
|
604
617
|
rootClassName={rootClassName}
|
|
605
618
|
style={style}
|
|
606
619
|
rootStyle={rootStyle}
|
|
607
620
|
layoutVariant={layoutVariant}
|
|
608
|
-
onClick={
|
|
609
|
-
missingApiKey
|
|
610
|
-
? bounceMissingKeySetup
|
|
611
|
-
: agentEngineUnavailable
|
|
612
|
-
? retryAgentEngineStatus
|
|
613
|
-
: undefined
|
|
614
|
-
}
|
|
621
|
+
onClick={gateComposer ? bounceMissingKeySetup : undefined}
|
|
615
622
|
>
|
|
616
623
|
<PromptAttachmentStrip />
|
|
617
624
|
<TiptapComposer
|
|
618
625
|
focusRef={handleRef}
|
|
619
|
-
disabled={disabled ||
|
|
626
|
+
disabled={disabled || gateComposer}
|
|
620
627
|
placeholder={
|
|
621
|
-
|
|
622
|
-
? "Connect AI above to continue..."
|
|
623
|
-
: agentEngineUnavailable
|
|
624
|
-
? "Unable to check AI connection. Click to retry."
|
|
625
|
-
: placeholder
|
|
628
|
+
gateComposer ? "Connect AI above to continue..." : placeholder
|
|
626
629
|
}
|
|
627
630
|
initialText={initialText}
|
|
628
631
|
initialTextKey={initialTextKey}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// @vitest-environment happy-dom
|
|
2
2
|
|
|
3
|
+
import { Editor as CoreEditor } from "@tiptap/core";
|
|
3
4
|
import { useEditor, type Editor } from "@tiptap/react";
|
|
4
5
|
import React, { act } from "react";
|
|
5
6
|
import { createRoot, type Root } from "react-dom/client";
|
|
6
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
+
import { Awareness } from "y-protocols/awareness";
|
|
9
|
+
import * as Y from "yjs";
|
|
7
10
|
|
|
8
11
|
import { createRichMarkdownExtensions } from "./RichMarkdownEditor.js";
|
|
9
12
|
import { useCollabReconcile, getEditorMarkdown } from "./useCollabReconcile.js";
|
|
@@ -38,6 +41,7 @@ beforeEach(() => {
|
|
|
38
41
|
|
|
39
42
|
afterEach(() => {
|
|
40
43
|
act(() => root.unmount());
|
|
44
|
+
vi.useRealTimers();
|
|
41
45
|
container.remove();
|
|
42
46
|
});
|
|
43
47
|
|
|
@@ -330,6 +334,37 @@ describe("useCollabReconcile — concurrent edit / lost-update guards", () => {
|
|
|
330
334
|
expect(results).toEqual([true]);
|
|
331
335
|
});
|
|
332
336
|
|
|
337
|
+
it("allows the first user edit after an authoritative empty doc finishes loading", async () => {
|
|
338
|
+
let shouldIgnoreUpdate:
|
|
339
|
+
| ((transaction: Editor["state"]["tr"]) => boolean)
|
|
340
|
+
| null = null;
|
|
341
|
+
let editor: Editor | null = null;
|
|
342
|
+
|
|
343
|
+
function Probe() {
|
|
344
|
+
editor = useEditor({
|
|
345
|
+
extensions: createRichMarkdownExtensions({ dialect: "gfm" }),
|
|
346
|
+
content: "",
|
|
347
|
+
});
|
|
348
|
+
const fakeYdoc = { clientID: 1, getXmlFragment: () => ({ length: 0 }) };
|
|
349
|
+
const guards = useCollabReconcile({
|
|
350
|
+
editor,
|
|
351
|
+
ydoc: fakeYdoc as never,
|
|
352
|
+
collabSynced: true,
|
|
353
|
+
value: "",
|
|
354
|
+
contentUpdatedAt: "2024-01-01T00:00:01.000Z",
|
|
355
|
+
editable: true,
|
|
356
|
+
});
|
|
357
|
+
shouldIgnoreUpdate = guards.shouldIgnoreUpdate;
|
|
358
|
+
return React.createElement("div", null);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
act(() => root.render(React.createElement(Probe)));
|
|
362
|
+
|
|
363
|
+
expect(editor).not.toBeNull();
|
|
364
|
+
expect(shouldIgnoreUpdate).not.toBeNull();
|
|
365
|
+
expect(shouldIgnoreUpdate!(editor!.state.tr)).toBe(false);
|
|
366
|
+
});
|
|
367
|
+
|
|
333
368
|
it("refuses to persist an empty doc in collab mode (registerEmitted guard)", async () => {
|
|
334
369
|
// Directly exercise the guard contract: in collab mode an empty markdown
|
|
335
370
|
// string must not be registered/persisted (would clobber stored content
|
|
@@ -399,6 +434,240 @@ describe("useCollabReconcile — concurrent edit / lost-update guards", () => {
|
|
|
399
434
|
expect(setContentValues).toEqual(["second seed"]);
|
|
400
435
|
});
|
|
401
436
|
|
|
437
|
+
it("does not seed beside persisted Y.Doc content projected during initial sync", async () => {
|
|
438
|
+
const persistedYdoc = new Y.Doc();
|
|
439
|
+
const persistedEditor = new CoreEditor({
|
|
440
|
+
extensions: createRichMarkdownExtensions({
|
|
441
|
+
dialect: "gfm",
|
|
442
|
+
ydoc: persistedYdoc,
|
|
443
|
+
}),
|
|
444
|
+
});
|
|
445
|
+
persistedEditor.commands.setContent("persisted collab body");
|
|
446
|
+
const persistedUpdate = Y.encodeStateAsUpdate(persistedYdoc);
|
|
447
|
+
persistedEditor.destroy();
|
|
448
|
+
persistedYdoc.destroy();
|
|
449
|
+
|
|
450
|
+
const liveYdoc = new Y.Doc();
|
|
451
|
+
const setContentValues: string[] = [];
|
|
452
|
+
let capturedEditor: Editor | null = null;
|
|
453
|
+
|
|
454
|
+
function Probe({ collabSynced }: { collabSynced: boolean }) {
|
|
455
|
+
const editor = useEditor({
|
|
456
|
+
extensions: createRichMarkdownExtensions({
|
|
457
|
+
dialect: "gfm",
|
|
458
|
+
ydoc: liveYdoc,
|
|
459
|
+
}),
|
|
460
|
+
});
|
|
461
|
+
capturedEditor = editor;
|
|
462
|
+
useCollabReconcile({
|
|
463
|
+
editor,
|
|
464
|
+
ydoc: liveYdoc,
|
|
465
|
+
collabSynced,
|
|
466
|
+
value: "persisted collab body",
|
|
467
|
+
contentUpdatedAt: "2024-01-01T00:00:01.000Z",
|
|
468
|
+
editable: true,
|
|
469
|
+
setContent: (_editor, nextValue) => {
|
|
470
|
+
setContentValues.push(nextValue);
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
return React.createElement("div", null);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
act(() => root.render(React.createElement(Probe, { collabSynced: false })));
|
|
477
|
+
act(() => Y.applyUpdate(liveYdoc, persistedUpdate, "remote"));
|
|
478
|
+
act(() => root.render(React.createElement(Probe, { collabSynced: true })));
|
|
479
|
+
await flush();
|
|
480
|
+
|
|
481
|
+
expect(getEditorMarkdown(capturedEditor!)).toBe("persisted collab body");
|
|
482
|
+
expect(setContentValues).toEqual([]);
|
|
483
|
+
expect(
|
|
484
|
+
getEditorMarkdown(capturedEditor!).match(/persisted collab body/g),
|
|
485
|
+
).toHaveLength(1);
|
|
486
|
+
liveYdoc.destroy();
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it("adopts a nonempty synced Y.Doc instead of reconciling an empty SQL snapshot", async () => {
|
|
490
|
+
vi.useFakeTimers();
|
|
491
|
+
const persistedYdoc = new Y.Doc();
|
|
492
|
+
const persistedEditor = new CoreEditor({
|
|
493
|
+
extensions: createRichMarkdownExtensions({
|
|
494
|
+
dialect: "gfm",
|
|
495
|
+
ydoc: persistedYdoc,
|
|
496
|
+
}),
|
|
497
|
+
});
|
|
498
|
+
persistedEditor.commands.setContent("live collaborator body");
|
|
499
|
+
const liveYdoc = new Y.Doc();
|
|
500
|
+
Y.applyUpdate(liveYdoc, Y.encodeStateAsUpdate(persistedYdoc), "remote");
|
|
501
|
+
persistedEditor.destroy();
|
|
502
|
+
persistedYdoc.destroy();
|
|
503
|
+
|
|
504
|
+
const awareness = new Awareness(liveYdoc);
|
|
505
|
+
const setContentValues: string[] = [];
|
|
506
|
+
let capturedEditor: Editor | null = null;
|
|
507
|
+
|
|
508
|
+
function Probe() {
|
|
509
|
+
const editor = useEditor({
|
|
510
|
+
extensions: createRichMarkdownExtensions({
|
|
511
|
+
dialect: "gfm",
|
|
512
|
+
ydoc: liveYdoc,
|
|
513
|
+
}),
|
|
514
|
+
});
|
|
515
|
+
capturedEditor = editor;
|
|
516
|
+
useCollabReconcile({
|
|
517
|
+
editor,
|
|
518
|
+
ydoc: liveYdoc,
|
|
519
|
+
awareness,
|
|
520
|
+
collabSynced: true,
|
|
521
|
+
value: "",
|
|
522
|
+
contentUpdatedAt: "2024-01-01T00:00:01.000Z",
|
|
523
|
+
editable: true,
|
|
524
|
+
setContent: (_editor, nextValue) => {
|
|
525
|
+
setContentValues.push(nextValue);
|
|
526
|
+
},
|
|
527
|
+
});
|
|
528
|
+
return React.createElement("div", null);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
act(() => root.render(React.createElement(Probe)));
|
|
532
|
+
await act(async () => vi.advanceTimersByTimeAsync(0));
|
|
533
|
+
// The document state can finish syncing before the first awareness poll.
|
|
534
|
+
// Publish the active peer after mount to cover that real transport order.
|
|
535
|
+
act(() => {
|
|
536
|
+
awareness.getStates().set(4_294_967_295, {
|
|
537
|
+
user: { name: "Active peer" },
|
|
538
|
+
visible: true,
|
|
539
|
+
});
|
|
540
|
+
awareness.emit("change", [
|
|
541
|
+
{ added: [4_294_967_295], updated: [], removed: [] },
|
|
542
|
+
"remote",
|
|
543
|
+
]);
|
|
544
|
+
});
|
|
545
|
+
await act(async () => vi.advanceTimersByTimeAsync(2500));
|
|
546
|
+
|
|
547
|
+
expect(getEditorMarkdown(capturedEditor!)).toBe("live collaborator body");
|
|
548
|
+
expect(setContentValues).toEqual([]);
|
|
549
|
+
vi.useRealTimers();
|
|
550
|
+
awareness.destroy();
|
|
551
|
+
liveYdoc.destroy();
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it("lets canonical empty SQL clear stale persisted Y.Doc content with no active peer", async () => {
|
|
555
|
+
const persistedYdoc = new Y.Doc();
|
|
556
|
+
const persistedEditor = new CoreEditor({
|
|
557
|
+
extensions: createRichMarkdownExtensions({
|
|
558
|
+
dialect: "gfm",
|
|
559
|
+
ydoc: persistedYdoc,
|
|
560
|
+
}),
|
|
561
|
+
});
|
|
562
|
+
persistedEditor.commands.setContent("stale persisted body");
|
|
563
|
+
const liveYdoc = new Y.Doc();
|
|
564
|
+
Y.applyUpdate(liveYdoc, Y.encodeStateAsUpdate(persistedYdoc), "remote");
|
|
565
|
+
persistedEditor.destroy();
|
|
566
|
+
persistedYdoc.destroy();
|
|
567
|
+
|
|
568
|
+
const setContentValues: string[] = [];
|
|
569
|
+
let capturedEditor: Editor | null = null;
|
|
570
|
+
const awareness = new Awareness(liveYdoc);
|
|
571
|
+
|
|
572
|
+
function Probe() {
|
|
573
|
+
const editor = useEditor({
|
|
574
|
+
extensions: createRichMarkdownExtensions({
|
|
575
|
+
dialect: "gfm",
|
|
576
|
+
ydoc: liveYdoc,
|
|
577
|
+
}),
|
|
578
|
+
});
|
|
579
|
+
capturedEditor = editor;
|
|
580
|
+
useCollabReconcile({
|
|
581
|
+
editor,
|
|
582
|
+
ydoc: liveYdoc,
|
|
583
|
+
awareness,
|
|
584
|
+
collabSynced: true,
|
|
585
|
+
value: "",
|
|
586
|
+
contentUpdatedAt: "2024-01-01T00:00:01.000Z",
|
|
587
|
+
editable: true,
|
|
588
|
+
setContent: (editorToClear, nextValue) => {
|
|
589
|
+
setContentValues.push(nextValue);
|
|
590
|
+
editorToClear.commands.setContent(nextValue);
|
|
591
|
+
},
|
|
592
|
+
});
|
|
593
|
+
return React.createElement("div", null);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
vi.useFakeTimers();
|
|
597
|
+
act(() => root.render(React.createElement(Probe)));
|
|
598
|
+
await act(async () => vi.advanceTimersByTimeAsync(2499));
|
|
599
|
+
expect(setContentValues).toEqual([]);
|
|
600
|
+
await act(async () => vi.advanceTimersByTimeAsync(51));
|
|
601
|
+
|
|
602
|
+
expect(setContentValues).toContain("");
|
|
603
|
+
expect(getEditorMarkdown(capturedEditor!)).toBe("");
|
|
604
|
+
vi.useRealTimers();
|
|
605
|
+
awareness.destroy();
|
|
606
|
+
liveYdoc.destroy();
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
it("preserves and permits a first local edit during the awareness settle window", async () => {
|
|
610
|
+
const persistedYdoc = new Y.Doc();
|
|
611
|
+
const persistedEditor = new CoreEditor({
|
|
612
|
+
extensions: createRichMarkdownExtensions({
|
|
613
|
+
dialect: "gfm",
|
|
614
|
+
ydoc: persistedYdoc,
|
|
615
|
+
}),
|
|
616
|
+
});
|
|
617
|
+
persistedEditor.commands.setContent("stale persisted body");
|
|
618
|
+
const liveYdoc = new Y.Doc();
|
|
619
|
+
Y.applyUpdate(liveYdoc, Y.encodeStateAsUpdate(persistedYdoc), "remote");
|
|
620
|
+
persistedEditor.destroy();
|
|
621
|
+
persistedYdoc.destroy();
|
|
622
|
+
|
|
623
|
+
const awareness = new Awareness(liveYdoc);
|
|
624
|
+
let capturedEditor: Editor | null = null;
|
|
625
|
+
let guards: ReturnType<typeof useCollabReconcile> | null = null;
|
|
626
|
+
const setContentValues: string[] = [];
|
|
627
|
+
|
|
628
|
+
function Probe() {
|
|
629
|
+
const editor = useEditor({
|
|
630
|
+
extensions: createRichMarkdownExtensions({
|
|
631
|
+
dialect: "gfm",
|
|
632
|
+
ydoc: liveYdoc,
|
|
633
|
+
}),
|
|
634
|
+
});
|
|
635
|
+
capturedEditor = editor;
|
|
636
|
+
guards = useCollabReconcile({
|
|
637
|
+
editor,
|
|
638
|
+
ydoc: liveYdoc,
|
|
639
|
+
awareness,
|
|
640
|
+
collabSynced: true,
|
|
641
|
+
value: "",
|
|
642
|
+
contentUpdatedAt: "2024-01-01T00:00:01.000Z",
|
|
643
|
+
editable: true,
|
|
644
|
+
setContent: (editorToSet, nextValue) => {
|
|
645
|
+
setContentValues.push(nextValue);
|
|
646
|
+
editorToSet.commands.setContent(nextValue);
|
|
647
|
+
},
|
|
648
|
+
});
|
|
649
|
+
return React.createElement("div", null);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
vi.useFakeTimers();
|
|
653
|
+
act(() => root.render(React.createElement(Probe)));
|
|
654
|
+
await act(async () => vi.advanceTimersByTimeAsync(0));
|
|
655
|
+
|
|
656
|
+
expect(guards).not.toBeNull();
|
|
657
|
+
expect(capturedEditor).not.toBeNull();
|
|
658
|
+
expect(guards!.shouldIgnoreUpdate(capturedEditor!.state.tr)).toBe(false);
|
|
659
|
+
expect(guards!.registerEmitted("first local edit")).toBe(true);
|
|
660
|
+
act(() => capturedEditor!.commands.setContent("first local edit"));
|
|
661
|
+
|
|
662
|
+
await act(async () => vi.advanceTimersByTimeAsync(2500));
|
|
663
|
+
expect(getEditorMarkdown(capturedEditor!)).toBe("first local edit");
|
|
664
|
+
expect(setContentValues).toEqual([]);
|
|
665
|
+
|
|
666
|
+
vi.useRealTimers();
|
|
667
|
+
awareness.destroy();
|
|
668
|
+
liveYdoc.destroy();
|
|
669
|
+
});
|
|
670
|
+
|
|
402
671
|
it("applies a genuinely newer external value once the user is no longer focused", async () => {
|
|
403
672
|
const { captured, Harness } = makeHarness();
|
|
404
673
|
|