@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.
@@ -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
- if (!isLeadClient)
163
- return;
164
- if (!value.trim())
165
- return;
166
- const fragment = ydoc.getXmlFragment("default");
167
- const currentMarkdown = getMarkdown(editor);
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
- return;
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 && (!collabSynced || !seededRef.current)) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/toolkit",
3
- "version": "0.10.5",
3
+ "version": "0.10.7",
4
4
  "description": "Reusable app-building UI and helpers for Agent-Native apps.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -2,7 +2,44 @@
2
2
 
3
3
  import { describe, expect, it } from "vitest";
4
4
 
5
- import { buildPromptComposerSubmission } from "./PromptComposer.js";
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
- (missingApiKey || agentEngineUnavailable) && "cursor-pointer",
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 || missingApiKey || agentEngineUnavailable}
626
+ disabled={disabled || gateComposer}
620
627
  placeholder={
621
- missingApiKey
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