nudge-ui 0.2.2 → 0.2.4
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/README.md +164 -46
- package/dist/client.mjs +260 -61
- package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
- package/dist/css/value-semantics/colorSemantics.js +17 -0
- package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
- package/dist/hosts/astro/clientTransport.js +38 -32
- package/dist/hosts/astro/integration.js +5 -1
- package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
- package/dist/hosts/astro/markdownIdentity.js +81 -0
- package/dist/hosts/next/manifest.js +1 -1
- package/dist/hosts/next/sidecar.js +5 -1
- package/dist/hosts/static/manifest.js +1 -1
- package/dist/hosts/static/server.js +3 -0
- package/dist/hosts/vite/vite.d.ts +3 -0
- package/dist/hosts/vite/vite.js +24 -4
- package/dist/inspector/agent/McpConnectionDialog.js +13 -19
- package/dist/inspector/agent/activity.d.ts +18 -0
- package/dist/inspector/agent/activity.js +70 -0
- package/dist/inspector/agent/client.d.ts +2 -0
- package/dist/inspector/agent/client.js +29 -1
- package/dist/inspector/agent/connectionStatus.js +1 -1
- package/dist/inspector/agent/httpTransport.js +9 -2
- package/dist/inspector/agent/protocol.d.ts +6 -3
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +15 -7
- package/dist/inspector/agent/verification.js +113 -41
- package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
- package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
- package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
- package/dist/inspector/canvas/CanvasCard.js +135 -38
- package/dist/inspector/canvas/CanvasElementOverlay.js +166 -16
- package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
- package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
- package/dist/inspector/canvas/CanvasToolbar.js +8 -4
- package/dist/inspector/canvas/CanvasWorkspace.js +270 -122
- package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
- package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
- package/dist/inspector/canvas/agentPresentation.js +64 -52
- package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
- package/dist/inspector/canvas/canvasGestures.js +1 -1
- package/dist/inspector/canvas/canvasStore.d.ts +46 -82
- package/dist/inspector/canvas/canvasStore.js +251 -284
- package/dist/inspector/canvas/frameContent.d.ts +21 -0
- package/dist/inspector/canvas/frameContent.js +44 -0
- package/dist/inspector/canvas/frameProtocol.d.ts +21 -4
- package/dist/inspector/canvas/frameProtocol.js +3 -3
- package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
- package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
- package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -1
- package/dist/inspector/canvas/keyboardShortcuts.js +4 -4
- package/dist/inspector/canvas/layout.d.ts +52 -0
- package/dist/inspector/canvas/layout.js +106 -0
- package/dist/inspector/canvas/projection.d.ts +15 -5
- package/dist/inspector/canvas/projection.js +69 -13
- package/dist/inspector/canvas/rendererBootstrap.js +32 -4
- package/dist/inspector/canvas/rendererElementSelector.js +47 -6
- package/dist/inspector/canvas/rendererStylesheet.js +2 -2
- package/dist/inspector/canvas/resizeHandleScale.js +1 -1
- package/dist/inspector/canvas/sessionStore.d.ts +11 -26
- package/dist/inspector/canvas/sessionStore.js +43 -183
- package/dist/inspector/canvas/staleChangeDetector.js +9 -3
- package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
- package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
- package/dist/inspector/canvas/viewStore.d.ts +38 -0
- package/dist/inspector/canvas/viewStore.js +104 -0
- package/dist/inspector/canvas/wheelPan.d.ts +8 -0
- package/dist/inspector/canvas/wheelPan.js +8 -0
- package/dist/inspector/changes/changesLog.d.ts +9 -6
- package/dist/inspector/changes/changesLog.js +48 -32
- package/dist/inspector/changes/codecs.d.ts +1 -0
- package/dist/inspector/changes/codecs.js +10 -1
- package/dist/inspector/changes/draftChanges.d.ts +58 -0
- package/dist/inspector/changes/draftChanges.js +304 -0
- package/dist/inspector/changes/editModel.d.ts +10 -0
- package/dist/inspector/changes/editModel.js +9 -2
- package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
- package/dist/inspector/changes/previewDiagnostics.js +11 -25
- package/dist/inspector/changes/types.d.ts +7 -0
- package/dist/inspector/clientManifest.d.ts +1 -1
- package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
- package/dist/inspector/comments/CommentsOverlay.js +250 -0
- package/dist/inspector/comments/element.d.ts +6 -0
- package/dist/inspector/comments/element.js +54 -0
- package/dist/inspector/comments/store.d.ts +29 -0
- package/dist/inspector/comments/store.js +121 -0
- package/dist/inspector/comments/verification.d.ts +5 -0
- package/dist/inspector/comments/verification.js +52 -0
- package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
- package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
- package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
- package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
- package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
- package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
- package/dist/inspector/componentSemantics/types.d.ts +11 -0
- package/dist/inspector/drafts/model.d.ts +35 -0
- package/dist/inspector/drafts/model.js +45 -0
- package/dist/inspector/drafts/store.d.ts +28 -0
- package/dist/inspector/drafts/store.js +231 -0
- package/dist/inspector/index.js +20 -27
- package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
- package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
- package/dist/inspector/iterations/capture.d.ts +2 -0
- package/dist/inspector/iterations/capture.js +174 -0
- package/dist/inspector/iterations/client.d.ts +7 -0
- package/dist/inspector/iterations/client.js +52 -0
- package/dist/inspector/iterations/coordinator.d.ts +15 -0
- package/dist/inspector/iterations/coordinator.js +130 -0
- package/dist/inspector/iterations/prompt.d.ts +3 -0
- package/dist/inspector/iterations/prompt.js +26 -0
- package/dist/inspector/overlay/DomNavigator.js +21 -15
- package/dist/inspector/overlay/interactionStyles.js +3 -1
- package/dist/inspector/overlay/spacingGestures.d.ts +13 -1
- package/dist/inspector/overlay/spacingGestures.js +82 -5
- package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
- package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
- package/dist/inspector/projection/renderedInstance.d.ts +17 -3
- package/dist/inspector/projection/renderedInstance.js +62 -11
- package/dist/inspector/projection/structuralProjection.d.ts +2 -1
- package/dist/inspector/projection/structuralProjection.js +21 -17
- package/dist/inspector/projection/textProjection.d.ts +2 -1
- package/dist/inspector/projection/textProjection.js +64 -15
- package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
- package/dist/inspector/prompt/clipboardHandoff.d.ts +15 -18
- package/dist/inspector/prompt/clipboardHandoff.js +97 -143
- package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
- package/dist/inspector/prompt/generatePrompt.js +22 -17
- package/dist/inspector/runtime/runtimeConfig.d.ts +9 -0
- package/dist/inspector/runtime/runtimeConfig.js +24 -0
- package/dist/inspector/selection/sourceSite.d.ts +12 -0
- package/dist/inspector/selection/sourceSite.js +28 -0
- package/dist/inspector/settings/SettingsDialog.js +21 -8
- package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
- package/dist/inspector/shell/AgentStatusButton.js +36 -0
- package/dist/inspector/shell/AppShell.js +4 -2
- package/dist/inspector/shell/ChangesLog.js +46 -26
- package/dist/inspector/shell/CopyPromptButton.js +184 -93
- package/dist/inspector/shell/EmptyState.js +9 -8
- package/dist/inspector/shell/InspectorShell.js +13 -21
- package/dist/inspector/shell/PeekOriginalButton.js +24 -23
- package/dist/inspector/shell/originalPreview.js +5 -5
- package/dist/inspector/shell/shortcuts.d.ts +3 -0
- package/dist/inspector/shell/shortcuts.js +11 -0
- package/dist/inspector/sketch/SketchEditor.js +14 -14
- package/dist/inspector/sketch/SketchEntryButton.js +1 -1
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
- package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
- package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
- package/dist/inspector/sketch/SketchOverlay.js +7 -7
- package/dist/inspector/sketch/SketchWorkspace.js +18 -12
- package/dist/inspector/sketch/interaction.d.ts +1 -0
- package/dist/inspector/sketch/interaction.js +8 -4
- package/dist/inspector/sketch/model.d.ts +5 -0
- package/dist/inspector/sketch/model.js +6 -2
- package/dist/inspector/sketch/raster.d.ts +1 -2
- package/dist/inspector/sketch/raster.js +68 -4
- package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
- package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
- package/dist/inspector/styleEditors/BorderEditor.js +49 -78
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
- package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
- package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
- package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
- package/dist/inspector/styleEditors/ColorPicker.js +10 -4
- package/dist/inspector/styleEditors/GapField.js +3 -5
- package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
- package/dist/inspector/styleEditors/GridChildSection.js +18 -9
- package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
- package/dist/inspector/styleEditors/GridPicker.js +8 -2
- package/dist/inspector/styleEditors/GridSection.js +1 -1
- package/dist/inspector/styleEditors/GridValueField.js +19 -14
- package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
- package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
- package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
- package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
- package/dist/inspector/styleEditors/LayoutSection.js +32 -11
- package/dist/inspector/styleEditors/SpacingBox.js +7 -5
- package/dist/inspector/styleEditors/Typography.js +11 -3
- package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
- package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
- package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
- package/dist/inspector/styleEditors/gradientValue.js +114 -0
- package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
- package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
- package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
- package/dist/inspector/styleEditors/layoutValue.js +0 -42
- package/dist/inspector/styleEditors/nudgeValue.d.ts +2 -2
- package/dist/inspector/styleEditors/nudgeValue.js +36 -8
- package/dist/inspector/tokens/TokenField.d.ts +7 -0
- package/dist/inspector/tokens/TokenField.js +35 -25
- package/dist/inspector/tokens/TokenLabel.js +5 -14
- package/dist/inspector/tokens/editActions.d.ts +1 -1
- package/dist/inspector/tokens/editActions.js +7 -1
- package/dist/inspector/ui/AtRuleContext.js +4 -6
- package/dist/inspector/ui/Button.d.ts +6 -2
- package/dist/inspector/ui/Button.js +4 -3
- package/dist/inspector/ui/ControlSurface.d.ts +2 -2
- package/dist/inspector/ui/ControlSurface.js +4 -3
- package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
- package/dist/inspector/ui/InlineStyleWarning.js +13 -0
- package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
- package/dist/inspector/ui/InspectorPopover.js +4 -5
- package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
- package/dist/inspector/ui/PopoverListbox.js +8 -7
- package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
- package/dist/inspector/ui/SegmentedControl.js +2 -2
- package/dist/inspector/ui/Select.d.ts +6 -1
- package/dist/inspector/ui/Select.js +7 -11
- package/dist/inspector/ui/SideValuesField.js +1 -1
- package/dist/inspector/ui/Tooltip.d.ts +26 -0
- package/dist/inspector/ui/Tooltip.js +32 -0
- package/dist/inspector/ui/classNames.d.ts +2 -0
- package/dist/inspector/ui/classNames.js +4 -0
- package/dist/inspector/ui/customCursors.d.ts +23 -0
- package/dist/inspector/ui/customCursors.js +122 -0
- package/dist/inspector/ui/dragCursor.d.ts +0 -2
- package/dist/inspector/ui/dragCursor.js +2 -10
- package/dist/inspector/ui/portalContainer.d.ts +2 -0
- package/dist/inspector/ui/portalContainer.js +6 -0
- package/dist/inspector/ui/styles.js +29 -21
- package/dist/inspector/workspace/commands.d.ts +9 -0
- package/dist/inspector/workspace/commands.js +82 -0
- package/dist/inspector/workspace/controller.d.ts +4 -0
- package/dist/inspector/workspace/controller.js +66 -0
- package/dist/inspector/workspace/handoff.d.ts +42 -0
- package/dist/inspector/workspace/handoff.js +115 -0
- package/dist/inspector/workspace/sentItems.d.ts +19 -0
- package/dist/inspector/workspace/sentItems.js +51 -0
- package/dist/inspector/workspace/timeline.d.ts +30 -0
- package/dist/inspector/workspace/timeline.js +108 -0
- package/dist/internal/agent-protocol.d.ts +19 -2
- package/dist/internal/agent-protocol.js +13 -0
- package/dist/nudge-ui.mjs +558 -311
- package/dist/project/artifacts.d.ts +13 -0
- package/dist/project/artifacts.js +253 -0
- package/dist/transport/artifacts.d.ts +8 -0
- package/dist/transport/artifacts.js +9 -0
- package/dist/transport/editor.js +3 -1
- package/dist/transport/routes.d.ts +2 -0
- package/dist/transport/routes.js +2 -0
- package/package.json +7 -3
- package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
- package/dist/inspector/changes/workspaceChanges.js +0 -265
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getActiveDraftChanges, getDraftChanges } from "../changes/draftChanges.js";
|
|
1
2
|
import { sourceSiteSelector } from "../selection/sourceSite.js";
|
|
2
3
|
import { isNudgeUiDev } from "../runtime/devFlag.js";
|
|
3
4
|
import { isTextContentChangeValue, isTextProjectionTargetValue, } from "../inline-text/textChangeBoundary.js";
|
|
@@ -48,6 +49,39 @@ function isEmptyTextAffordance(node) {
|
|
|
48
49
|
function hasInlineTextEditor(element) {
|
|
49
50
|
return element.querySelector('[data-inline-editor="true"]') !== null;
|
|
50
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* What the application last rendered into each projected Text node. A source
|
|
54
|
+
* update can render the projected value itself, so restoring `before` would
|
|
55
|
+
* overwrite real application output that the framework will not repaint.
|
|
56
|
+
*/
|
|
57
|
+
let applicationText = new WeakMap();
|
|
58
|
+
function isInlineEditorNode(node) {
|
|
59
|
+
return node.nodeType === 1 && (node.matches('[data-inline-editor="true"]')
|
|
60
|
+
|| hasInlineTextEditor(node));
|
|
61
|
+
}
|
|
62
|
+
function recordApplicationWrites(records) {
|
|
63
|
+
// The inline editor swaps its wrapper back for the original node, writing
|
|
64
|
+
// the draft, in one task. That write belongs to the editor.
|
|
65
|
+
if (records.some((record) => record.type === "childList"
|
|
66
|
+
&& [...record.addedNodes, ...record.removedNodes].some(isInlineEditorNode)))
|
|
67
|
+
return;
|
|
68
|
+
for (const record of records) {
|
|
69
|
+
if (record.type !== "characterData" || !isTextNode(record.target))
|
|
70
|
+
continue;
|
|
71
|
+
if (applicationText.has(record.target))
|
|
72
|
+
applicationText.set(record.target, record.target.nodeValue ?? "");
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Writes projection-owned text without mistaking it for an application render. */
|
|
76
|
+
function writeProjectedText(state, node, value) {
|
|
77
|
+
const pending = state.observer?.takeRecords() ?? [];
|
|
78
|
+
if (pending.length > 0) {
|
|
79
|
+
recordApplicationWrites(pending);
|
|
80
|
+
scheduleValidation(state.doc, state);
|
|
81
|
+
}
|
|
82
|
+
node.nodeValue = value;
|
|
83
|
+
state.observer?.takeRecords();
|
|
84
|
+
}
|
|
51
85
|
function readProjectionMarkers(element) {
|
|
52
86
|
const raw = element.getAttribute(TEXT_PROJECTION_ATTR);
|
|
53
87
|
if (!raw)
|
|
@@ -410,7 +444,7 @@ function textProjectionIdentityMatches(element, change) {
|
|
|
410
444
|
&& element.getAttribute("data-cprops") === change.target.props
|
|
411
445
|
&& element.getAttribute("aria-label") === change.target.ariaLabel;
|
|
412
446
|
}
|
|
413
|
-
function restoreAppliedProjection(applied) {
|
|
447
|
+
function restoreAppliedProjection(state, applied) {
|
|
414
448
|
const element = applied.element;
|
|
415
449
|
if (!element || !element.isConnected)
|
|
416
450
|
return;
|
|
@@ -425,7 +459,9 @@ function restoreAppliedProjection(applied) {
|
|
|
425
459
|
if (!textHostIsSafe(element, applied.change.after.length === 0, applied.change.target))
|
|
426
460
|
return;
|
|
427
461
|
if (textNode) {
|
|
428
|
-
|
|
462
|
+
const rendered = applicationText.get(textNode);
|
|
463
|
+
applicationText.delete(textNode);
|
|
464
|
+
writeProjectedText(state, textNode, rendered ?? applied.change.before);
|
|
429
465
|
}
|
|
430
466
|
else if (applied.change.target.textNodePath === undefined
|
|
431
467
|
&& applied.change.after.length === 0
|
|
@@ -466,7 +502,7 @@ function validationStatus(applied) {
|
|
|
466
502
|
* mutates; an overridden projection remains authoritative and is never
|
|
467
503
|
* re-applied.
|
|
468
504
|
*/
|
|
469
|
-
function resolvePendingProjection(doc, applied) {
|
|
505
|
+
function resolvePendingProjection(doc, state, applied) {
|
|
470
506
|
if (applied.status !== "missing" && applied.status !== "ambiguous") {
|
|
471
507
|
return validationStatus(applied);
|
|
472
508
|
}
|
|
@@ -483,7 +519,9 @@ function resolvePendingProjection(doc, applied) {
|
|
|
483
519
|
element.textContent = applied.change.after;
|
|
484
520
|
}
|
|
485
521
|
else {
|
|
486
|
-
|
|
522
|
+
if (!applicationText.has(textNode))
|
|
523
|
+
applicationText.set(textNode, textNode.nodeValue ?? "");
|
|
524
|
+
writeProjectedText(state, textNode, applied.change.after);
|
|
487
525
|
}
|
|
488
526
|
applied.element = element;
|
|
489
527
|
return "applied";
|
|
@@ -491,7 +529,7 @@ function resolvePendingProjection(doc, applied) {
|
|
|
491
529
|
function validateAppliedProjection(doc, state) {
|
|
492
530
|
let changed = false;
|
|
493
531
|
for (const applied of state.applied.values()) {
|
|
494
|
-
const status = resolvePendingProjection(doc, applied);
|
|
532
|
+
const status = resolvePendingProjection(doc, state, applied);
|
|
495
533
|
if (status !== applied.status) {
|
|
496
534
|
applied.status = status;
|
|
497
535
|
changed = true;
|
|
@@ -515,6 +553,7 @@ function getDocumentState(doc) {
|
|
|
515
553
|
if (existing)
|
|
516
554
|
return existing;
|
|
517
555
|
const state = {
|
|
556
|
+
doc,
|
|
518
557
|
applied: new Map(),
|
|
519
558
|
emptyAffordances: new Map(),
|
|
520
559
|
snapshotKey: null,
|
|
@@ -523,7 +562,10 @@ function getDocumentState(doc) {
|
|
|
523
562
|
};
|
|
524
563
|
const Observer = doc.defaultView?.MutationObserver;
|
|
525
564
|
if (Observer && doc.documentElement) {
|
|
526
|
-
state.observer = new Observer(() =>
|
|
565
|
+
state.observer = new Observer((records) => {
|
|
566
|
+
recordApplicationWrites(records);
|
|
567
|
+
scheduleValidation(doc, state);
|
|
568
|
+
});
|
|
527
569
|
state.observer.observe(doc.documentElement, {
|
|
528
570
|
childList: true,
|
|
529
571
|
subtree: true,
|
|
@@ -570,7 +612,7 @@ export function applyTextContentProjection(doc, changes) {
|
|
|
570
612
|
if (incomingIds.has(id))
|
|
571
613
|
continue;
|
|
572
614
|
removeEmptyTextAffordance(state, id);
|
|
573
|
-
restoreAppliedProjection(applied);
|
|
615
|
+
restoreAppliedProjection(state, applied);
|
|
574
616
|
if (applied.element)
|
|
575
617
|
removeProjectionMarker(applied.element, applied.change.target, id);
|
|
576
618
|
}
|
|
@@ -578,13 +620,13 @@ export function applyTextContentProjection(doc, changes) {
|
|
|
578
620
|
for (const change of changes) {
|
|
579
621
|
const existing = previous.get(change.id);
|
|
580
622
|
if (existing && JSON.stringify(existing.change) === JSON.stringify(change)) {
|
|
581
|
-
existing.status = resolvePendingProjection(doc, existing);
|
|
623
|
+
existing.status = resolvePendingProjection(doc, state, existing);
|
|
582
624
|
next.set(change.id, existing);
|
|
583
625
|
continue;
|
|
584
626
|
}
|
|
585
627
|
if (existing) {
|
|
586
628
|
removeEmptyTextAffordance(state, change.id);
|
|
587
|
-
restoreAppliedProjection(existing);
|
|
629
|
+
restoreAppliedProjection(state, existing);
|
|
588
630
|
if (existing.element)
|
|
589
631
|
removeProjectionMarker(existing.element, existing.change.target, change.id);
|
|
590
632
|
}
|
|
@@ -602,8 +644,11 @@ export function applyTextContentProjection(doc, changes) {
|
|
|
602
644
|
next.set(change.id, { change, element: null, status: "missing" });
|
|
603
645
|
continue;
|
|
604
646
|
}
|
|
605
|
-
if (textNode)
|
|
606
|
-
|
|
647
|
+
if (textNode) {
|
|
648
|
+
if (!applicationText.has(textNode))
|
|
649
|
+
applicationText.set(textNode, textNode.nodeValue ?? "");
|
|
650
|
+
writeProjectedText(state, textNode, change.after);
|
|
651
|
+
}
|
|
607
652
|
else
|
|
608
653
|
element.textContent = change.after;
|
|
609
654
|
next.set(change.id, { change, element, status: "applied" });
|
|
@@ -640,10 +685,10 @@ export function subscribeTextProjectionDiagnostics(listener) {
|
|
|
640
685
|
export function getTextProjectionDiagnosticRevision() {
|
|
641
686
|
return diagnosticRevision;
|
|
642
687
|
}
|
|
643
|
-
export function recordCanvasTextProjectionReports(cardId, revision, reports) {
|
|
688
|
+
export function recordCanvasTextProjectionReports(cardId, revision, reports, projection) {
|
|
644
689
|
if (!Number.isSafeInteger(revision) || revision < 0 || !reports.every(isTextProjectionReport))
|
|
645
690
|
return;
|
|
646
|
-
const expected = new Set(canonicalChanges.keys());
|
|
691
|
+
const expected = projection ? new Set(projection.textContentChanges.map((record) => record.id)) : new Set(canonicalChanges.keys());
|
|
647
692
|
if (reports.length !== expected.size
|
|
648
693
|
|| new Set(reports.map((report) => report.changeId)).size !== reports.length
|
|
649
694
|
|| reports.some((report) => !expected.has(report.changeId)))
|
|
@@ -654,7 +699,8 @@ export function recordCanvasTextProjectionReports(cardId, revision, reports) {
|
|
|
654
699
|
const next = reports.map((report) => ({ ...report }));
|
|
655
700
|
if (existing && existing.revision === revision && sameReports(existing.reports, next))
|
|
656
701
|
return;
|
|
657
|
-
|
|
702
|
+
const current = getActiveDraftChanges();
|
|
703
|
+
reportsByCanvasCard.set(cardId, { revision, reports: next, draftId: projection?.draftId ?? current.draftId, draftRevision: projection?.draftRevision ?? current.revision });
|
|
658
704
|
notifyDiagnostics();
|
|
659
705
|
}
|
|
660
706
|
export function clearCanvasTextProjectionReports(cardId) {
|
|
@@ -664,7 +710,7 @@ export function clearCanvasTextProjectionReports(cardId) {
|
|
|
664
710
|
}
|
|
665
711
|
export function getTextContentChangeDiagnostics(changeId) {
|
|
666
712
|
const diagnostics = [];
|
|
667
|
-
const change = canonicalChanges.get(changeId);
|
|
713
|
+
const change = getActiveDraftChanges().changes.find((change) => change.kind === "text-content" && change.id === changeId) ?? canonicalChanges.get(changeId);
|
|
668
714
|
const host = reportsByDocument.get(document)?.find((report) => report.changeId === changeId);
|
|
669
715
|
if (host)
|
|
670
716
|
diagnostics.push({
|
|
@@ -674,6 +720,8 @@ export function getTextContentChangeDiagnostics(changeId) {
|
|
|
674
720
|
evidence: change?.evidence,
|
|
675
721
|
});
|
|
676
722
|
for (const [cardId, entry] of reportsByCanvasCard) {
|
|
723
|
+
if (entry.draftId !== getActiveDraftChanges().draftId || entry.draftRevision !== getDraftChanges(entry.draftId).revision)
|
|
724
|
+
continue;
|
|
677
725
|
const report = entry.reports.find((candidate) => candidate.changeId === changeId);
|
|
678
726
|
if (report)
|
|
679
727
|
diagnostics.push({
|
|
@@ -704,6 +752,7 @@ export function resetTextProjectionState() {
|
|
|
704
752
|
}
|
|
705
753
|
}
|
|
706
754
|
documentStates = new Map();
|
|
755
|
+
applicationText = new WeakMap();
|
|
707
756
|
canonicalChanges = new Map();
|
|
708
757
|
reportsByDocument = new WeakMap();
|
|
709
758
|
reportsByCanvasCard.clear();
|
|
@@ -2,11 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useRef } from "react";
|
|
3
3
|
import { Dialog } from "@base-ui/react/dialog";
|
|
4
4
|
import { IconX } from "@tabler/icons-react";
|
|
5
|
-
|
|
6
|
-
return typeof document !== "undefined"
|
|
7
|
-
? document.getElementById("nudge-ui-root")?.shadowRoot ?? document.body
|
|
8
|
-
: null;
|
|
9
|
-
}
|
|
5
|
+
import { portalContainer } from "../ui/portalContainer.js";
|
|
10
6
|
/** Edits the instructions appended to every generated prompt. */
|
|
11
7
|
export function PromptSettingsFields({ value, onChange, instructionsRef, }) {
|
|
12
8
|
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "prompt-settings__field", children: _jsx("textarea", { ref: instructionsRef, id: "nudge-ui-custom-instructions", className: "prompt-settings__textarea", "data-test": "prompt-custom-instructions", "aria-label": "Custom instructions", rows: 6, value: value, onChange: (event) => onChange(event.currentTarget.value) }) }), _jsx("div", { className: "prompt-settings__actions", children: _jsx(Dialog.Close, { className: "button button--primary", "data-test": "prompt-settings-done", type: "button", children: "Done" }) })] }));
|
|
@@ -1,34 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { ChangeRecord } from "../changes/types.js";
|
|
2
|
+
import type { StructuralChange } from "../changes/structuralTypes.js";
|
|
3
|
+
import { type HandoffOwner } from "../agent/verification.js";
|
|
3
4
|
export interface ClipboardHandoffFingerprint {
|
|
4
5
|
readonly key: string;
|
|
5
6
|
readonly fingerprint: string;
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
+
interface ClipboardDraftHandoff {
|
|
9
|
+
readonly owner: HandoffOwner;
|
|
8
10
|
readonly changes: readonly ClipboardHandoffFingerprint[];
|
|
9
11
|
readonly structuralChanges: readonly ClipboardHandoffFingerprint[];
|
|
10
12
|
}
|
|
11
|
-
|
|
13
|
+
export interface ClipboardHandoffSnapshot {
|
|
14
|
+
readonly drafts: readonly ClipboardDraftHandoff[];
|
|
15
|
+
}
|
|
12
16
|
export declare function isClipboardHandoffSnapshot(value: unknown): value is ClipboardHandoffSnapshot | null;
|
|
13
|
-
|
|
14
|
-
export declare function recordClipboardHandoff(changes: readonly ChangeRecord[], structuralChanges?: readonly StructuralChange[]): void;
|
|
15
|
-
/** Returns a defensive copy for durable-session serialization. */
|
|
17
|
+
export declare function recordClipboardHandoff(changes: readonly ChangeRecord[], structuralChanges?: readonly StructuralChange[], owner?: HandoffOwner): void;
|
|
16
18
|
export declare function getClipboardHandoffSnapshot(): ClipboardHandoffSnapshot | null;
|
|
17
|
-
/** Replaces the in-memory checkpoint from a validated durable session. */
|
|
18
19
|
export declare function hydrateClipboardHandoff(value: ClipboardHandoffSnapshot | null): void;
|
|
19
20
|
export declare function clearClipboardHandoff(): void;
|
|
20
21
|
export declare function subscribeClipboardHandoff(listener: () => void): () => void;
|
|
21
|
-
/** Monotonic external-store snapshot for persistence and React consumers. */
|
|
22
22
|
export declare function getClipboardHandoffRevision(): number;
|
|
23
23
|
export declare function getLastClipboardReconciledCount(): number;
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
/** Records in one draft that still equal its copied, unverified snapshot. */
|
|
25
|
+
export declare function getClipboardHandoffRecords(draftId: string): {
|
|
26
|
+
changes: ChangeRecord[];
|
|
27
|
+
structuralChanges: StructuralChange[];
|
|
28
|
+
};
|
|
28
29
|
export declare function reconcileClipboardHandoff(doc?: Document): Promise<number>;
|
|
29
|
-
/**
|
|
30
|
-
* Watches source-driven document refreshes and page-return signals. The
|
|
31
|
-
* trailing debounce lets an HMR commit settle before verification lifts the
|
|
32
|
-
* inspector preview for two frames.
|
|
33
|
-
*/
|
|
34
30
|
export declare function startClipboardHandoffController(doc?: Document): () => void;
|
|
31
|
+
export {};
|
|
@@ -1,212 +1,166 @@
|
|
|
1
1
|
import { changeKey } from "../changes/model.js";
|
|
2
|
-
import {
|
|
3
|
-
import {} from "../projection/structuralProjection.js";
|
|
4
|
-
import { getWorkspaceChanges } from "../changes/workspaceChanges.js";
|
|
2
|
+
import { getDraftChanges, getActiveDraftChanges, subscribeActiveDraftChanges } from "../changes/draftChanges.js";
|
|
5
3
|
import { documentRevisions, subscribeDocumentRevision } from "../tokens/resolution/cssomCollector.js";
|
|
6
|
-
import { handoffChangeFingerprint, handoffStructuralFingerprint, verifyAndReconcileHandoff, } from "../agent/verification.js";
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const MAX_FINGERPRINT_LENGTH = 1_048_576;
|
|
10
|
-
const RECONCILE_DEBOUNCE_MS = 450;
|
|
11
|
-
let checkpoint = null;
|
|
4
|
+
import { captureHandoffOwner, handoffChangeFingerprint, handoffStructuralFingerprint, verifyAndReconcileHandoff, } from "../agent/verification.js";
|
|
5
|
+
import { isDraftTarget } from "../drafts/model.js";
|
|
6
|
+
const checkpoints = new Map();
|
|
12
7
|
let revision = 0;
|
|
13
|
-
|
|
8
|
+
const reconciledCounts = new Map();
|
|
14
9
|
const listeners = new Set();
|
|
15
10
|
function notify() {
|
|
16
11
|
revision += 1;
|
|
17
12
|
for (const listener of listeners)
|
|
18
13
|
listener();
|
|
19
14
|
}
|
|
20
|
-
function cloneSnapshot(snapshot) {
|
|
21
|
-
return {
|
|
22
|
-
changes: snapshot.changes.map((entry) => ({ ...entry })),
|
|
23
|
-
structuralChanges: snapshot.structuralChanges.map((entry) => ({ ...entry })),
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
15
|
function isFingerprint(value) {
|
|
27
|
-
if (!value || typeof value !== "object"
|
|
16
|
+
if (!value || typeof value !== "object")
|
|
28
17
|
return false;
|
|
29
18
|
const entry = value;
|
|
30
|
-
return
|
|
31
|
-
&& typeof entry.
|
|
32
|
-
&& entry.key.length > 0
|
|
33
|
-
&& entry.key.length <= MAX_KEY_LENGTH
|
|
34
|
-
&& typeof entry.fingerprint === "string"
|
|
35
|
-
&& entry.fingerprint.length > 0
|
|
36
|
-
&& entry.fingerprint.length <= MAX_FINGERPRINT_LENGTH;
|
|
19
|
+
return typeof entry.key === "string" && entry.key.length > 0 && entry.key.length <= 16_384
|
|
20
|
+
&& typeof entry.fingerprint === "string" && entry.fingerprint.length > 0 && entry.fingerprint.length <= 1_048_576;
|
|
37
21
|
}
|
|
38
|
-
/** Validates an origin-local persisted clipboard checkpoint. */
|
|
39
22
|
export function isClipboardHandoffSnapshot(value) {
|
|
40
23
|
if (value === null)
|
|
41
24
|
return true;
|
|
42
|
-
if (!value || typeof value !== "object"
|
|
25
|
+
if (!value || typeof value !== "object")
|
|
43
26
|
return false;
|
|
44
|
-
const
|
|
45
|
-
if (!
|
|
46
|
-
|| !Array.isArray(candidate.changes)
|
|
47
|
-
|| !Array.isArray(candidate.structuralChanges)
|
|
48
|
-
|| candidate.changes.length + candidate.structuralChanges.length > MAX_HANDOFF_RECORDS
|
|
49
|
-
|| !candidate.changes.every(isFingerprint)
|
|
50
|
-
|| !candidate.structuralChanges.every(isFingerprint)) {
|
|
27
|
+
const snapshot = value;
|
|
28
|
+
if (!Array.isArray(snapshot.drafts) || snapshot.drafts.length > 512)
|
|
51
29
|
return false;
|
|
30
|
+
const ids = new Set();
|
|
31
|
+
for (const draft of snapshot.drafts) {
|
|
32
|
+
const owner = draft?.owner;
|
|
33
|
+
if (!owner || typeof owner.draftId !== "string" || ids.has(owner.draftId)
|
|
34
|
+
|| !Number.isSafeInteger(owner.draftRevision) || owner.draftRevision < 0 || !isDraftTarget(owner.target)
|
|
35
|
+
|| !Array.isArray(owner.frameIds) || owner.frameIds.some((id) => typeof id !== "string")
|
|
36
|
+
|| !Array.isArray(draft.changes) || !Array.isArray(draft.structuralChanges)
|
|
37
|
+
|| draft.changes.length + draft.structuralChanges.length > 10_000
|
|
38
|
+
|| !draft.changes.every(isFingerprint) || !draft.structuralChanges.every(isFingerprint)
|
|
39
|
+
|| new Set(draft.changes.map((entry) => entry.key)).size !== draft.changes.length
|
|
40
|
+
|| new Set(draft.structuralChanges.map((entry) => entry.key)).size !== draft.structuralChanges.length)
|
|
41
|
+
return false;
|
|
42
|
+
ids.add(owner.draftId);
|
|
52
43
|
}
|
|
53
|
-
|
|
54
|
-
const structuralKeys = candidate.structuralChanges.map((entry) => entry.key);
|
|
55
|
-
return new Set(changeKeys).size === changeKeys.length
|
|
56
|
-
&& new Set(structuralKeys).size === structuralKeys.length;
|
|
44
|
+
return true;
|
|
57
45
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
changes: changes.map((change) => ({
|
|
62
|
-
|
|
63
|
-
fingerprint: handoffChangeFingerprint(change),
|
|
64
|
-
})),
|
|
65
|
-
structuralChanges: structuralChanges.map((change) => ({
|
|
66
|
-
key: change.id,
|
|
67
|
-
fingerprint: handoffStructuralFingerprint(change),
|
|
68
|
-
})),
|
|
46
|
+
function fingerprintSnapshot(owner, changes, structuralChanges) {
|
|
47
|
+
return {
|
|
48
|
+
owner: structuredClone(owner),
|
|
49
|
+
changes: changes.map((change) => ({ key: changeKey(change), fingerprint: handoffChangeFingerprint(change) })),
|
|
50
|
+
structuralChanges: structuralChanges.map((change) => ({ key: change.id, fingerprint: handoffStructuralFingerprint(change) })),
|
|
69
51
|
};
|
|
70
|
-
|
|
52
|
+
}
|
|
53
|
+
export function recordClipboardHandoff(changes, structuralChanges = [], owner = captureHandoffOwner()) {
|
|
54
|
+
checkpoints.set(owner.draftId, fingerprintSnapshot(owner, changes, structuralChanges));
|
|
55
|
+
reconciledCounts.delete(owner.draftId);
|
|
71
56
|
notify();
|
|
72
57
|
}
|
|
73
|
-
/** Returns a defensive copy for durable-session serialization. */
|
|
74
58
|
export function getClipboardHandoffSnapshot() {
|
|
75
|
-
return
|
|
59
|
+
return checkpoints.size ? structuredClone({ drafts: [...checkpoints.values()] }) : null;
|
|
76
60
|
}
|
|
77
|
-
/** Replaces the in-memory checkpoint from a validated durable session. */
|
|
78
61
|
export function hydrateClipboardHandoff(value) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
checkpoints.clear();
|
|
63
|
+
for (const draft of value?.drafts ?? [])
|
|
64
|
+
checkpoints.set(draft.owner.draftId, structuredClone(draft));
|
|
65
|
+
reconciledCounts.clear();
|
|
83
66
|
notify();
|
|
84
67
|
}
|
|
85
68
|
export function clearClipboardHandoff() {
|
|
86
|
-
if (!
|
|
69
|
+
if (!checkpoints.size && !reconciledCounts.size)
|
|
87
70
|
return;
|
|
88
|
-
|
|
89
|
-
|
|
71
|
+
checkpoints.clear();
|
|
72
|
+
reconciledCounts.clear();
|
|
90
73
|
notify();
|
|
91
74
|
}
|
|
92
75
|
export function subscribeClipboardHandoff(listener) {
|
|
93
76
|
listeners.add(listener);
|
|
94
77
|
return () => listeners.delete(listener);
|
|
95
78
|
}
|
|
96
|
-
|
|
97
|
-
export function
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
function matchingStructuralChanges(snapshot) {
|
|
108
|
-
const expected = new Map(snapshot.structuralChanges.map((entry) => [entry.key, entry.fingerprint]));
|
|
109
|
-
return getWorkspaceChanges().structuralChanges.filter((change) => expected.get(change.id) === handoffStructuralFingerprint(change));
|
|
79
|
+
export function getClipboardHandoffRevision() { return revision; }
|
|
80
|
+
export function getLastClipboardReconciledCount() { return reconciledCounts.get(getActiveDraftChanges().draftId) ?? 0; }
|
|
81
|
+
function matchingRecords(snapshot) {
|
|
82
|
+
const workspace = getDraftChanges(snapshot.owner.draftId);
|
|
83
|
+
const changes = new Map(snapshot.changes.map((entry) => [entry.key, entry.fingerprint]));
|
|
84
|
+
const structures = new Map(snapshot.structuralChanges.map((entry) => [entry.key, entry.fingerprint]));
|
|
85
|
+
return {
|
|
86
|
+
changes: workspace.changes.filter((change) => changes.get(changeKey(change)) === handoffChangeFingerprint(change)),
|
|
87
|
+
structuralChanges: workspace.structuralChanges.filter((change) => structures.get(change.id) === handoffStructuralFingerprint(change)),
|
|
88
|
+
};
|
|
110
89
|
}
|
|
111
|
-
/**
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
90
|
+
/** Records in one draft that still equal its copied, unverified snapshot. */
|
|
91
|
+
export function getClipboardHandoffRecords(draftId) {
|
|
92
|
+
const snapshot = checkpoints.get(draftId);
|
|
93
|
+
return snapshot ? matchingRecords(snapshot) : { changes: [], structuralChanges: [] };
|
|
94
|
+
}
|
|
95
|
+
function pruneCheckpoints() {
|
|
96
|
+
let changed = false;
|
|
97
|
+
for (const [id, snapshot] of checkpoints) {
|
|
98
|
+
const matching = matchingRecords(snapshot);
|
|
99
|
+
if (matching.changes.length === snapshot.changes.length && matching.structuralChanges.length === snapshot.structuralChanges.length)
|
|
100
|
+
continue;
|
|
101
|
+
changed = true;
|
|
102
|
+
if (matching.changes.length + matching.structuralChanges.length === 0)
|
|
103
|
+
checkpoints.delete(id);
|
|
104
|
+
else
|
|
105
|
+
checkpoints.set(id, fingerprintSnapshot(snapshot.owner, matching.changes, matching.structuralChanges));
|
|
120
106
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
: {
|
|
124
|
-
changes: changes.map((change) => ({
|
|
125
|
-
key: changeKey(change),
|
|
126
|
-
fingerprint: handoffChangeFingerprint(change),
|
|
127
|
-
})),
|
|
128
|
-
structuralChanges: structuralChanges.map((change) => ({
|
|
129
|
-
key: change.id,
|
|
130
|
-
fingerprint: handoffStructuralFingerprint(change),
|
|
131
|
-
})),
|
|
132
|
-
};
|
|
133
|
-
notify();
|
|
134
|
-
return true;
|
|
107
|
+
if (changed)
|
|
108
|
+
notify();
|
|
135
109
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Checks a copied prompt against source-rendered output and reconciles only
|
|
138
|
-
* exact records that the browser can positively verify.
|
|
139
|
-
*/
|
|
140
110
|
export async function reconcileClipboardHandoff(doc = document) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
111
|
+
let removed = 0;
|
|
112
|
+
for (const snapshot of [...checkpoints.values()]) {
|
|
113
|
+
const matching = matchingRecords(snapshot);
|
|
114
|
+
if (matching.changes.length + matching.structuralChanges.length === 0)
|
|
115
|
+
continue;
|
|
116
|
+
const count = await verifyAndReconcileHandoff({ owner: snapshot.owner, ...matching }, doc);
|
|
117
|
+
if (count > 0)
|
|
118
|
+
reconciledCounts.set(snapshot.owner.draftId, count);
|
|
119
|
+
removed += count;
|
|
149
120
|
}
|
|
150
|
-
|
|
151
|
-
pruneCheckpoint();
|
|
121
|
+
pruneCheckpoints();
|
|
152
122
|
if (removed > 0) {
|
|
153
|
-
lastReconciledCount = removed;
|
|
154
123
|
notify();
|
|
155
124
|
}
|
|
156
125
|
return removed;
|
|
157
126
|
}
|
|
158
|
-
/**
|
|
159
|
-
* Watches source-driven document refreshes and page-return signals. The
|
|
160
|
-
* trailing debounce lets an HMR commit settle before verification lifts the
|
|
161
|
-
* inspector preview for two frames.
|
|
162
|
-
*/
|
|
163
127
|
export function startClipboardHandoffController(doc = document) {
|
|
164
|
-
const
|
|
128
|
+
const view = doc.defaultView;
|
|
165
129
|
let timer = null;
|
|
166
130
|
let checking = false;
|
|
167
131
|
let stopped = false;
|
|
168
132
|
const schedule = () => {
|
|
169
|
-
if (stopped || checking || !
|
|
133
|
+
if (stopped || checking || !checkpoints.size)
|
|
170
134
|
return;
|
|
171
135
|
if (timer !== null)
|
|
172
136
|
clearTimeout(timer);
|
|
173
137
|
timer = setTimeout(() => {
|
|
174
138
|
timer = null;
|
|
175
|
-
if (stopped || checking || !
|
|
139
|
+
if (stopped || checking || !checkpoints.size)
|
|
176
140
|
return;
|
|
177
141
|
checking = true;
|
|
178
|
-
void reconcileClipboardHandoff(doc)
|
|
179
|
-
.catch(() => undefined)
|
|
180
|
-
.finally(() => {
|
|
181
|
-
// Keep the guard through the MutationObserver microtask generated by
|
|
182
|
-
// restoring managed projections, preventing a verification loop.
|
|
142
|
+
void reconcileClipboardHandoff(doc).catch(() => undefined).finally(() => {
|
|
183
143
|
setTimeout(() => { checking = false; }, 0);
|
|
184
144
|
});
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
const onCanonicalChange = () => {
|
|
188
|
-
pruneCheckpoint();
|
|
189
|
-
};
|
|
190
|
-
const onVisibilityChange = () => {
|
|
191
|
-
if (doc.visibilityState === "visible")
|
|
192
|
-
schedule();
|
|
145
|
+
}, 450);
|
|
193
146
|
};
|
|
194
|
-
|
|
147
|
+
const visible = () => { if (doc.visibilityState === "visible")
|
|
148
|
+
schedule(); };
|
|
195
149
|
documentRevisions(doc);
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
doc.addEventListener("visibilitychange",
|
|
150
|
+
const stopRevision = subscribeDocumentRevision(doc, schedule);
|
|
151
|
+
const stopChanges = subscribeActiveDraftChanges(pruneCheckpoints);
|
|
152
|
+
view?.addEventListener("focus", schedule);
|
|
153
|
+
view?.addEventListener("pageshow", schedule);
|
|
154
|
+
doc.addEventListener("visibilitychange", visible);
|
|
201
155
|
schedule();
|
|
202
156
|
return () => {
|
|
203
157
|
stopped = true;
|
|
204
158
|
if (timer !== null)
|
|
205
159
|
clearTimeout(timer);
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
doc.removeEventListener("visibilitychange",
|
|
160
|
+
stopRevision();
|
|
161
|
+
stopChanges();
|
|
162
|
+
view?.removeEventListener("focus", schedule);
|
|
163
|
+
view?.removeEventListener("pageshow", schedule);
|
|
164
|
+
doc.removeEventListener("visibilitychange", visible);
|
|
211
165
|
};
|
|
212
166
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ChangeRecord } from "../changes/changesLog.js";
|
|
2
2
|
import type { StructuralChange } from "../projection/structuralProjection.js";
|
|
3
3
|
import type { AgentSketchMetadata } from "../agent/protocol.js";
|
|
4
|
+
import { type ElementComment } from "../comments/store.js";
|
|
4
5
|
export interface FrameworkHints {
|
|
5
6
|
framework?: string;
|
|
6
7
|
stylingSystem?: string;
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
+
/** Counts the final edit intents exported by the prompt, preserving gesture history for undo. */
|
|
10
|
+
export declare function countPromptChanges(changes: readonly ChangeRecord[], structuralChanges?: readonly StructuralChange[], sketchCount?: number): number;
|
|
11
|
+
export declare function generatePrompt(changes: ChangeRecord[], frameworkHints?: FrameworkHints, structuralChanges?: readonly StructuralChange[], customInstructions?: string, sketches?: readonly AgentSketchMetadata[], comments?: readonly ElementComment[]): string;
|