@parhelia/core 0.1.12939 → 0.1.12940

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/agents-view/AgentCard.js +1 -1
  2. package/dist/agents-view/AgentsView.js +1 -1
  3. package/dist/agents-view/AgentsView.js.map +1 -1
  4. package/dist/agents-view/DateAgentsGroup.js +1 -1
  5. package/dist/agents-view/DateAgentsGroup.js.map +1 -1
  6. package/dist/components/ui/context-menu.js +5 -0
  7. package/dist/components/ui/context-menu.js.map +1 -1
  8. package/dist/components/ui/popover.d.ts +2 -0
  9. package/dist/components/ui/popover.js +62 -1
  10. package/dist/components/ui/popover.js.map +1 -1
  11. package/dist/config/notificationRoutes.js +86 -97
  12. package/dist/config/notificationRoutes.js.map +1 -1
  13. package/dist/editor/ai/Agents.js +24 -1
  14. package/dist/editor/ai/Agents.js.map +1 -1
  15. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js +2 -10
  16. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js.map +1 -1
  17. package/dist/editor/ai/terminal/components/AgentGreeting.js +2 -2
  18. package/dist/editor/ai/terminal/components/AgentGreeting.js.map +1 -1
  19. package/dist/editor/ai/terminal/components/AgentProfileSwitcher.d.ts +4 -0
  20. package/dist/editor/ai/terminal/components/AgentProfileSwitcher.js +76 -11
  21. package/dist/editor/ai/terminal/components/AgentProfileSwitcher.js.map +1 -1
  22. package/dist/editor/ai/terminal/components/AgentPromptInputArea.js +18 -5
  23. package/dist/editor/ai/terminal/components/AgentPromptInputArea.js.map +1 -1
  24. package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.d.ts +0 -2
  25. package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.js.map +1 -1
  26. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.d.ts +3 -1
  27. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js +2 -2
  28. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js.map +1 -1
  29. package/dist/editor/ai/terminal/components/AgentTerminalFullUpperContent.d.ts +1 -1
  30. package/dist/editor/ai/terminal/components/AgentTerminalView.d.ts +2 -1
  31. package/dist/editor/ai/terminal/components/AgentTerminalView.js +3 -3
  32. package/dist/editor/ai/terminal/components/AgentTerminalView.js.map +1 -1
  33. package/dist/editor/ai/terminal/components/AiResponseMessage.d.ts +0 -2
  34. package/dist/editor/ai/terminal/components/AiResponseMessage.js +10 -42
  35. package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
  36. package/dist/editor/ai/terminal/types.d.ts +2 -0
  37. package/dist/editor/ai/terminal/useAgentAutoStartOnCreate.d.ts +1 -0
  38. package/dist/editor/ai/terminal/useAgentAutoStartOnCreate.js +3 -1
  39. package/dist/editor/ai/terminal/useAgentAutoStartOnCreate.js.map +1 -1
  40. package/dist/editor/ai/terminal/useAgentDraftInitializer.js +19 -2
  41. package/dist/editor/ai/terminal/useAgentDraftInitializer.js.map +1 -1
  42. package/dist/editor/ai/terminal/useAgentInitialPrompt.d.ts +1 -0
  43. package/dist/editor/ai/terminal/useAgentInitialPrompt.js +3 -1
  44. package/dist/editor/ai/terminal/useAgentInitialPrompt.js.map +1 -1
  45. package/dist/editor/ai/terminal/useAgentPendingInitialPrompt.d.ts +1 -0
  46. package/dist/editor/ai/terminal/useAgentPendingInitialPrompt.js +3 -1
  47. package/dist/editor/ai/terminal/useAgentPendingInitialPrompt.js.map +1 -1
  48. package/dist/editor/ai/terminal/useAgentProfileSelection.d.ts +18 -0
  49. package/dist/editor/ai/terminal/useAgentProfileSelection.js +37 -7
  50. package/dist/editor/ai/terminal/useAgentProfileSelection.js.map +1 -1
  51. package/dist/editor/ai/terminal/useAgentPromptComposerSurface.d.ts +2 -2
  52. package/dist/editor/ai/terminal/useAgentQuickActions.d.ts +2 -2
  53. package/dist/editor/ai/terminal/useAgentQuickActions.js +3 -61
  54. package/dist/editor/ai/terminal/useAgentQuickActions.js.map +1 -1
  55. package/dist/editor/ai/terminal/useAgentSettingsCommands.d.ts +10 -0
  56. package/dist/editor/ai/terminal/useAgentSettingsCommands.js +65 -23
  57. package/dist/editor/ai/terminal/useAgentSettingsCommands.js.map +1 -1
  58. package/dist/editor/ai/terminal/useAgentSettingsPanel.d.ts +1 -1
  59. package/dist/editor/ai/terminal/useAgentSettingsPanel.js +4 -3
  60. package/dist/editor/ai/terminal/useAgentSettingsPanel.js.map +1 -1
  61. package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +1 -0
  62. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +6 -1
  63. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
  64. package/dist/editor/ai/terminal/useAgentTerminalController.d.ts +1 -1
  65. package/dist/editor/ai/terminal/useAgentTerminalController.js +29 -3
  66. package/dist/editor/ai/terminal/useAgentTerminalController.js.map +1 -1
  67. package/dist/editor/ai/terminal/useAgentTerminalViewProps.d.ts +1 -0
  68. package/dist/editor/ai/terminal/useAgentTerminalViewProps.js +2 -1
  69. package/dist/editor/ai/terminal/useAgentTerminalViewProps.js.map +1 -1
  70. package/dist/editor/bridge/protocol.d.ts +4 -0
  71. package/dist/editor/bridge/protocol.js.map +1 -1
  72. package/dist/editor/menubar/PageSelector.js +7 -16
  73. package/dist/editor/menubar/PageSelector.js.map +1 -1
  74. package/dist/editor/menubar/pageSelectorHistoryFilter.d.ts +2 -0
  75. package/dist/editor/menubar/pageSelectorHistoryFilter.js +15 -0
  76. package/dist/editor/menubar/pageSelectorHistoryFilter.js.map +1 -0
  77. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js +11 -3
  78. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js.map +1 -1
  79. package/dist/editor/page-viewer/MiniMap.d.ts +3 -0
  80. package/dist/editor/page-viewer/MiniMap.js +9 -2
  81. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  82. package/dist/editor/page-viewer/PageViewerFrame.js +72 -76
  83. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  84. package/dist/editor/page-viewer/bridgeFieldPatch.d.ts +12 -0
  85. package/dist/editor/page-viewer/bridgeFieldPatch.js +34 -0
  86. package/dist/editor/page-viewer/bridgeFieldPatch.js.map +1 -1
  87. package/dist/editor/page-viewer/bridgeTextCompletion.d.ts +25 -0
  88. package/dist/editor/page-viewer/bridgeTextCompletion.js +98 -0
  89. package/dist/editor/page-viewer/bridgeTextCompletion.js.map +1 -0
  90. package/dist/editor/reviews/Comments.js +31 -2
  91. package/dist/editor/reviews/Comments.js.map +1 -1
  92. package/dist/editor/reviews/CreateReviewDialog.js +3 -1
  93. package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
  94. package/dist/editor/reviews/EditReviewSettingsDialog.js +52 -96
  95. package/dist/editor/reviews/EditReviewSettingsDialog.js.map +1 -1
  96. package/dist/editor/reviews/ReviewCard.d.ts +6 -3
  97. package/dist/editor/reviews/ReviewCard.js +62 -35
  98. package/dist/editor/reviews/ReviewCard.js.map +1 -1
  99. package/dist/editor/reviews/ReviewDetail.d.ts +1 -1
  100. package/dist/editor/reviews/ReviewDetail.js +83 -93
  101. package/dist/editor/reviews/ReviewDetail.js.map +1 -1
  102. package/dist/editor/reviews/ReviewItemsPanel.d.ts +29 -0
  103. package/dist/editor/reviews/ReviewItemsPanel.js +176 -0
  104. package/dist/editor/reviews/ReviewItemsPanel.js.map +1 -0
  105. package/dist/editor/reviews/ReviewersPanel.d.ts +1 -1
  106. package/dist/editor/reviews/ReviewersPanel.js +108 -235
  107. package/dist/editor/reviews/ReviewersPanel.js.map +1 -1
  108. package/dist/editor/reviews/ReviewsList.d.ts +1 -1
  109. package/dist/editor/reviews/ReviewsList.js +116 -67
  110. package/dist/editor/reviews/ReviewsList.js.map +1 -1
  111. package/dist/editor/reviews/SuggestedEdit.js +2 -16
  112. package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
  113. package/dist/editor/reviews/feedbackSelection.d.ts +2 -1
  114. package/dist/editor/reviews/feedbackSelection.js +18 -1
  115. package/dist/editor/reviews/feedbackSelection.js.map +1 -1
  116. package/dist/editor/reviews/pendingFeedbackFocus.d.ts +19 -0
  117. package/dist/editor/reviews/pendingFeedbackFocus.js +36 -0
  118. package/dist/editor/reviews/pendingFeedbackFocus.js.map +1 -0
  119. package/dist/editor/reviews/reviewListPresentation.d.ts +19 -0
  120. package/dist/editor/reviews/reviewListPresentation.js +78 -0
  121. package/dist/editor/reviews/reviewListPresentation.js.map +1 -0
  122. package/dist/editor/services/agentService.js.map +1 -1
  123. package/dist/editor/services/contentService.js +16 -0
  124. package/dist/editor/services/contentService.js.map +1 -1
  125. package/dist/revision.d.ts +2 -2
  126. package/dist/revision.js +2 -2
  127. package/dist/splash-screen/NewPage.d.ts +7 -0
  128. package/dist/splash-screen/NewPage.js +11 -6
  129. package/dist/splash-screen/NewPage.js.map +1 -1
  130. package/dist/types.d.ts +6 -0
  131. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react";
3
3
  import { BRIDGE_DOM_UPDATED_EVENT, MiniMap } from "./MiniMap";
4
4
  import { resolveMiniMapVisibility, } from "./minimapVisibility";
5
5
  import { useCanvasSelection, useEditContext, useEditContextRef, useFieldsEditContext, useFieldsEditContextRef, } from "../client/editContext";
@@ -30,7 +30,8 @@ import { pickVersionAtDate } from "../utils/versionAtDate";
30
30
  import { BridgeClient } from "../bridge/BridgeClient";
31
31
  import { beginPerfTrace, isPerfTraceActive, isPerfTraceEnabled, perfTraceStep, } from "../perfTrace";
32
32
  import { getSuggestionDisplayValue } from "../reviews/suggestionDisplayValue";
33
- import { buildBridgeFieldPatchPayload, getBridgeFieldPatchValue, isBridgePatchableTextField, } from "./bridgeFieldPatch";
33
+ import { buildBridgeFieldPatchPayload, getBridgeFieldPatchValue, isBridgePatchableTextField, reduceActiveBridgeInlineEditForRefreshEvent, } from "./bridgeFieldPatch";
34
+ import { bridgeSelectionMatchesInteraction, resolveBridgeTextCompletionInput, } from "./bridgeTextCompletion";
34
35
  import { logFieldValueDiagnostic, summarizeField, summarizeFieldDescriptor, summarizeFieldValue, } from "../fieldValueDiagnostics";
35
36
  import { createKeyboardEventFromBridgeInteraction } from "./bridgeKeyboardShortcuts";
36
37
  import { formatParentBridgeInjectionDiagnostic, injectParheliaBridgeFromParent, } from "./parentBridgeInjection";
@@ -573,33 +574,10 @@ function isBridgeLinkShortcutRange(range, interaction) {
573
574
  ((interaction.elementKey && range.elementKey === interaction.elementKey) ||
574
575
  bridgeIdsMatch(range.fieldId, interaction.fieldId)));
575
576
  }
576
- function bridgeSelectionMatchesInteraction(selection, interaction) {
577
- return !!(selection?.activeField &&
578
- ((interaction.elementKey &&
579
- selection.activeField.elementKey === interaction.elementKey) ||
580
- bridgeIdsMatch(selection.activeField.fieldId, interaction.fieldId)));
581
- }
582
577
  function getBridgeSelectionMetadataString(selection, key) {
583
578
  const value = selection?.metadata?.[key];
584
579
  return typeof value === "string" ? value : undefined;
585
580
  }
586
- function clampTextOffset(value, length) {
587
- if (typeof value !== "number" || !Number.isFinite(value)) {
588
- return length;
589
- }
590
- return Math.min(length, Math.max(0, value));
591
- }
592
- function getPlainTextFromBridgeValue(value) {
593
- if (!/[<&]/.test(value))
594
- return value;
595
- try {
596
- const parser = new DOMParser();
597
- return parser.parseFromString(value, "text/html").body.textContent ?? "";
598
- }
599
- catch {
600
- return value.replace(/<[^>]*>/g, "");
601
- }
602
- }
603
581
  export function PageViewerFrame(props) {
604
582
  const editContext = useEditContext();
605
583
  useViewportChangeSignal();
@@ -616,6 +594,13 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
616
594
  useEffect(() => {
617
595
  pageViewContextRef.current = pageViewContext;
618
596
  }, [pageViewContext]);
597
+ const latestBridgeSelectionRef = useRef(pageViewContext.bridgeSelection);
598
+ // Bridge events are ordered, but the context setter commits asynchronously.
599
+ // A layout synchronization cannot run later and clobber a newer event-time
600
+ // ref the way a pending passive effect could.
601
+ useLayoutEffect(() => {
602
+ latestBridgeSelectionRef.current = pageViewContext.bridgeSelection;
603
+ }, [pageViewContext.bridgeSelection]);
619
604
  const editContextRef = useEditContextRef();
620
605
  const fieldsContextRef = useFieldsEditContextRef();
621
606
  const iframeRef = useRef(null);
@@ -637,6 +622,14 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
637
622
  activeBridgeInlineEditRef.current = null;
638
623
  setIsBridgeInlineEditing(false);
639
624
  }, []);
625
+ const reconcileActiveBridgeInlineEdit = useCallback((event) => {
626
+ const current = activeBridgeInlineEditRef.current;
627
+ const reconciled = reduceActiveBridgeInlineEditForRefreshEvent(current, event);
628
+ if (reconciled === current)
629
+ return;
630
+ activeBridgeInlineEditRef.current = reconciled;
631
+ setIsBridgeInlineEditing(!!reconciled);
632
+ }, []);
640
633
  const bridgeTextCompletionRef = useRef(null);
641
634
  const bridgeTextCompletionAbortRef = useRef(null);
642
635
  const bridgeTextCompletionRequestIdRef = useRef(0);
@@ -1352,7 +1345,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
1352
1345
  clearBridgeTextCompletion();
1353
1346
  return;
1354
1347
  }
1355
- const bridgeSelection = pageViewContextRef.current?.bridgeSelection;
1348
+ const bridgeSelection = latestBridgeSelectionRef.current;
1356
1349
  const selectionMatches = bridgeSelectionMatchesInteraction(bridgeSelection, interaction);
1357
1350
  const activeField = selectionMatches
1358
1351
  ? bridgeSelection?.activeField
@@ -1384,11 +1377,13 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
1384
1377
  const bridgeSelectionEndOffset = selectionMatches && typeof bridgeSelection?.endOffset === "number"
1385
1378
  ? bridgeSelection?.endOffset
1386
1379
  : undefined;
1387
- const selectedText = typeof interaction.selectedText === "string"
1380
+ const liveSelectedText = typeof interaction.selectedText === "string"
1388
1381
  ? interaction.selectedText
1389
- : selectionMatches && typeof bridgeSelection?.text === "string"
1382
+ : undefined;
1383
+ const selectedText = liveSelectedText ??
1384
+ (selectionMatches && typeof bridgeSelection?.text === "string"
1390
1385
  ? bridgeSelection.text
1391
- : "";
1386
+ : "");
1392
1387
  const selectionStartOffset = liveSelectionStartOffset ??
1393
1388
  (selectionMatches && typeof bridgeSelection?.startOffset === "number"
1394
1389
  ? bridgeSelection.startOffset
@@ -1405,44 +1400,27 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
1405
1400
  const rawValue = activeInlineEditMatches && activeInlineEdit.value !== undefined
1406
1401
  ? activeInlineEdit.value
1407
1402
  : getBridgeFieldPatchValue(field);
1408
- let completionValue = rawValue;
1409
- let completionSelectionStart = 0;
1410
- let completionSelectionEnd = 0;
1411
- if (isRichText) {
1412
- const contextBefore = selectionMatches
1403
+ const completionInput = resolveBridgeTextCompletionInput({
1404
+ rawValue,
1405
+ isRichText,
1406
+ selectedText,
1407
+ liveSelectedText,
1408
+ selectionStartOffset,
1409
+ selectionEndOffset,
1410
+ liveSelectionStartOffset,
1411
+ liveSelectionEndOffset,
1412
+ snapshotSelectionStartOffset: bridgeSelectionStartOffset,
1413
+ snapshotSelectionEndOffset: bridgeSelectionEndOffset,
1414
+ contextBefore: selectionMatches
1413
1415
  ? getBridgeSelectionMetadataString(bridgeSelection, "contextBefore")
1414
- : undefined;
1415
- const contextAfter = selectionMatches
1416
+ : undefined,
1417
+ contextAfter: selectionMatches
1416
1418
  ? getBridgeSelectionMetadataString(bridgeSelection, "contextAfter")
1417
- : undefined;
1418
- const hasLiveInteractionOffsets = liveSelectionStartOffset !== undefined &&
1419
- liveSelectionEndOffset !== undefined;
1420
- const selectionSnapshotMatchesLiveOffsets = bridgeSelectionStartOffset === undefined ||
1421
- bridgeSelectionEndOffset === undefined ||
1422
- !hasLiveInteractionOffsets ||
1423
- (bridgeSelectionStartOffset === liveSelectionStartOffset &&
1424
- bridgeSelectionEndOffset === liveSelectionEndOffset);
1425
- const metadataMatchesLiveOffsets = selectionSnapshotMatchesLiveOffsets ||
1426
- ((contextBefore?.length ?? 0) === interaction.selectionStartOffset &&
1427
- (contextBefore?.length ?? 0) + selectedText.length ===
1428
- interaction.selectionEndOffset);
1429
- if (metadataMatchesLiveOffsets &&
1430
- (contextBefore !== undefined || contextAfter !== undefined)) {
1431
- completionValue = `${contextBefore ?? ""}${selectedText}${contextAfter ?? ""}`;
1432
- completionSelectionStart = contextBefore?.length ?? 0;
1433
- completionSelectionEnd =
1434
- completionSelectionStart + selectedText.length;
1435
- }
1436
- else {
1437
- completionValue = getPlainTextFromBridgeValue(rawValue);
1438
- completionSelectionStart = clampTextOffset(selectionStartOffset, completionValue.length);
1439
- completionSelectionEnd = clampTextOffset(selectionEndOffset ?? selectionStartOffset, completionValue.length);
1440
- }
1441
- }
1442
- else {
1443
- completionSelectionStart = clampTextOffset(selectionStartOffset, completionValue.length);
1444
- completionSelectionEnd = clampTextOffset(selectionEndOffset ?? selectionStartOffset, completionValue.length);
1445
- }
1419
+ : undefined,
1420
+ });
1421
+ const completionValue = completionInput.value;
1422
+ const completionSelectionStart = completionInput.requestSelectionStart;
1423
+ const completionSelectionEnd = completionInput.requestSelectionEnd;
1446
1424
  if (!force &&
1447
1425
  completionValue.slice(0, completionSelectionStart).trim().length < 3) {
1448
1426
  clearBridgeTextCompletion();
@@ -1480,13 +1458,9 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
1480
1458
  elementKey,
1481
1459
  fieldId: hostFieldId,
1482
1460
  completion,
1483
- selectedText,
1484
- selectionStartOffset: typeof selectionStartOffset === "number"
1485
- ? selectionStartOffset
1486
- : completionSelectionStart,
1487
- selectionEndOffset: typeof selectionEndOffset === "number"
1488
- ? selectionEndOffset
1489
- : completionSelectionEnd,
1461
+ selectedText: completionInput.commandSelectedText,
1462
+ selectionStartOffset: completionInput.commandSelectionStart,
1463
+ selectionEndOffset: completionInput.commandSelectionEnd,
1490
1464
  };
1491
1465
  bridgeTextCompletionRef.current = commandPayload;
1492
1466
  sendTextCompletionCommand({
@@ -1556,7 +1530,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
1556
1530
  const editor = editContextRef.current;
1557
1531
  let linkRange = editor?.selectedRange;
1558
1532
  if (!isBridgeLinkShortcutRange(linkRange, interaction)) {
1559
- const bridgeSelection = pageViewContextRef.current?.bridgeSelection;
1533
+ const bridgeSelection = latestBridgeSelectionRef.current;
1560
1534
  const item = bridgeSelection?.activeField?.item ??
1561
1535
  pageViewContextRef.current?.page?.item ??
1562
1536
  pageViewContextRef.current?.pageItemDescriptor;
@@ -1620,7 +1594,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
1620
1594
  await editor.setFocusedField(field, editor.mode !== "suggestions");
1621
1595
  }
1622
1596
  const iframeRect = iframe.getBoundingClientRect();
1623
- const bridgeSelection = pageViewContextRef.current?.bridgeSelection;
1597
+ const bridgeSelection = latestBridgeSelectionRef.current;
1624
1598
  const fallbackCaretRect = !interaction.selectionRect &&
1625
1599
  !interaction.caretRect &&
1626
1600
  bridgeSelection?.collapsed &&
@@ -2010,6 +1984,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
2010
1984
  editorOrigin: window.location.origin,
2011
1985
  sessionId: editContextRef.current?.sessionId,
2012
1986
  mode: editContextRef.current?.mode ?? "edit",
1987
+ readOnly: editContextRef.current?.readonly ?? true,
2013
1988
  suggestionsCursorActive: !activeBridgeInlineEditRef.current &&
2014
1989
  (editContextRef.current?.mode === "suggestions" ||
2015
1990
  !!editContextRef.current?.showSuggestedEdits),
@@ -2041,6 +2016,10 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
2041
2016
  pageViewContext.setBridgeStructure(event.payload.structure);
2042
2017
  if (canvasRefreshInFlightSinceRef.current !== null) {
2043
2018
  hostAppRefreshSawStructureUpdateRef.current = true;
2019
+ reconcileActiveBridgeInlineEdit({
2020
+ type: "structureUpdated",
2021
+ fields: event.payload.structure.fields,
2022
+ });
2044
2023
  }
2045
2024
  if (awaitingHostAppRefreshRenderRef.current) {
2046
2025
  // First structure change after a host-app refresh: the page's
@@ -2090,9 +2069,18 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
2090
2069
  });
2091
2070
  clearBridgeTextCompletion();
2092
2071
  clearBridgePatchSignatures();
2093
- clearActiveBridgeInlineEdit();
2072
+ // The host preserves the focused field, its live draft, and its
2073
+ // selection while it patches the refreshed DOM. Keep the matching
2074
+ // editor-side session as well so repository patch propagation does
2075
+ // not overwrite that restored DOM and move the caret.
2076
+ reconcileActiveBridgeInlineEdit({ type: "started" });
2094
2077
  break;
2095
2078
  case "refreshCompleted":
2079
+ reconcileActiveBridgeInlineEdit({
2080
+ type: "completed",
2081
+ applied: event.payload.applied,
2082
+ fields: event.payload.structure?.fields,
2083
+ });
2096
2084
  logFieldValueDiagnostic("bridge-frame", "refresh completed", {
2097
2085
  activeInlineEdit: activeBridgeInlineEditRef.current,
2098
2086
  hasStructure: !!event.payload.structure,
@@ -2155,6 +2143,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
2155
2143
  setShowSpinner(false);
2156
2144
  break;
2157
2145
  case "selectionChanged":
2146
+ latestBridgeSelectionRef.current = event.payload.selection;
2158
2147
  pageViewContext.setBridgeSelection(event.payload.selection);
2159
2148
  handleBridgeSelection(event.payload.selection, iframe);
2160
2149
  break;
@@ -2284,6 +2273,7 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
2284
2273
  clearBridgeTextCompletion,
2285
2274
  clearBridgePatchSignatures,
2286
2275
  clearActiveBridgeInlineEdit,
2276
+ reconcileActiveBridgeInlineEdit,
2287
2277
  pageViewContext.editUrl,
2288
2278
  pageViewContext.previewUrl,
2289
2279
  scheduleBridgeDomRevision,
@@ -3016,10 +3006,16 @@ function PageViewerFrameContent({ compareView, pageViewContext, editContext, cla
3016
3006
  });
3017
3007
  bridge?.sendCommand("setEditorMode", {
3018
3008
  mode: editContext.mode,
3009
+ readOnly: editContext.readonly,
3019
3010
  suggestionsCursorActive: !isBridgeInlineEditing &&
3020
3011
  (editContext.mode === "suggestions" || editContext.showSuggestedEdits),
3021
3012
  });
3022
- }, [editContext.mode, editContext.showSuggestedEdits, isBridgeInlineEditing]);
3013
+ }, [
3014
+ editContext.mode,
3015
+ editContext.readonly,
3016
+ editContext.showSuggestedEdits,
3017
+ isBridgeInlineEditing,
3018
+ ]);
3023
3019
  useEffect(() => {
3024
3020
  const previousMode = previousBridgeInlineEditModeRef.current;
3025
3021
  previousBridgeInlineEditModeRef.current = editContext.mode;