codex-overleaf-link 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/README.md +272 -311
  2. package/README.zh-CN.md +287 -326
  3. package/extension/bootstrap/background.js +47 -10
  4. package/extension/bootstrap/manifest.template.json +9 -4
  5. package/extension/bootstrap/popup.html +10 -16
  6. package/extension/bootstrap/update.js +25 -2
  7. package/extension/runtime-manifest.json +3 -1
  8. package/extension/src/background.js +28 -3
  9. package/extension/src/backgroundSharedSessions.js +380 -0
  10. package/extension/src/backgroundUpdateCoordinator.js +442 -379
  11. package/extension/src/content/activeTurnControl.js +8 -0
  12. package/extension/src/content/assetTransferBroker.js +186 -12
  13. package/extension/src/content/changeHistoryView.js +175 -0
  14. package/extension/src/content/composerAttachments.js +24 -22
  15. package/extension/src/content/composerPanel.js +23 -8
  16. package/extension/src/content/contentRuntime.js +572 -571
  17. package/extension/src/content/diagnosticsController.js +1 -2
  18. package/extension/src/content/diagnosticsExport.js +222 -0
  19. package/extension/src/content/diagnosticsPanel.js +48 -19
  20. package/extension/src/content/diffReviewPanel.js +8 -5
  21. package/extension/src/content/generated/content.bundle.js +8974 -1781
  22. package/extension/src/content/generated/content.bundle.meta.json +22 -3
  23. package/extension/src/content/legacyGlobalRegistry.js +19 -1
  24. package/extension/src/content/localSkillsPanel.js +42 -7
  25. package/extension/src/content/markdownDomRenderer.js +9 -4
  26. package/extension/src/content/modelPicker.js +1 -1
  27. package/extension/src/content/pageBridgeClient.js +18 -3
  28. package/extension/src/content/panelMaintenance.js +51 -120
  29. package/extension/src/content/panelRenderer.js +4 -0
  30. package/extension/src/content/pendingInputView.js +109 -76
  31. package/extension/src/content/providerSettingsCoordinator.js +17 -6
  32. package/extension/src/content/providerSettingsDialog.js +661 -108
  33. package/extension/src/content/recentProjects.js +364 -356
  34. package/extension/src/content/runActivitySummary.js +631 -0
  35. package/extension/src/content/runController.js +3 -1
  36. package/extension/src/content/runFailureNotice.js +14 -1
  37. package/extension/src/content/runGuidanceController.js +4 -3
  38. package/extension/src/content/runPresence.js +306 -0
  39. package/extension/src/content/runQueueScheduler.js +2 -1
  40. package/extension/src/content/runResultActions.js +123 -3
  41. package/extension/src/content/runTimelineView.js +194 -164
  42. package/extension/src/content/scopedPersistenceCoordinator.js +2 -1
  43. package/extension/src/content/scopedPersistencePanelState.js +45 -2
  44. package/extension/src/content/selectionContextView.js +300 -0
  45. package/extension/src/content/sessionPersistence.js +10 -2
  46. package/extension/src/content/settingsPanel.js +93 -54
  47. package/extension/src/content/settingsWorkbench.js +374 -0
  48. package/extension/src/content/sharedSessionViewSync.js +72 -0
  49. package/extension/src/content/subagentActivityView.js +195 -0
  50. package/extension/src/content/trackedChangeCaptureController.js +7 -3
  51. package/extension/src/content/updateNotice.js +121 -50
  52. package/extension/src/content/writebackController.js +257 -0
  53. package/extension/src/content/writebackOrchestrator.js +146 -141
  54. package/extension/src/content/writebackPlan.js +231 -0
  55. package/extension/src/content/writebackRecovery.js +122 -0
  56. package/extension/src/content/writingStyleSettings.js +576 -0
  57. package/extension/src/content/writtenChangesView.js +152 -0
  58. package/extension/src/page/binaryAssetUploader.js +97 -19
  59. package/extension/src/page/overleafProjectSnapshot.js +1 -0
  60. package/extension/src/page/referenceProjects.js +148 -0
  61. package/extension/src/page/saveState.js +58 -3
  62. package/extension/src/page/snapshotRouter.js +44 -13
  63. package/extension/src/page/textCoordinates.js +102 -0
  64. package/extension/src/page/textFileCreator.js +350 -59
  65. package/extension/src/page/trackedChangeCapture.js +42 -56
  66. package/extension/src/page/trackedChangeOwnership.js +198 -0
  67. package/extension/src/page/trackedChangeReplay.js +164 -0
  68. package/extension/src/page/trackedChangesLifecycle.js +139 -150
  69. package/extension/src/page/treeOperations.js +36 -29
  70. package/extension/src/page/writebackReceiptJournal.js +112 -0
  71. package/extension/src/page/writebackRouter.js +176 -136
  72. package/extension/src/pageBridge.js +59 -101
  73. package/extension/src/popup.js +203 -59
  74. package/extension/src/shared/agentTranscript.js +18 -4
  75. package/extension/src/shared/auditRecords.js +71 -0
  76. package/extension/src/shared/changeHistoryModel.js +94 -0
  77. package/extension/src/shared/compatibility.js +1 -1
  78. package/extension/src/shared/compileAdapter.js +42 -0
  79. package/extension/src/shared/failureReasons.js +20 -0
  80. package/extension/src/shared/globalPreferences.js +1 -1
  81. package/extension/src/shared/i18n.js +187 -65
  82. package/extension/src/shared/managedUpdateProjection.js +6 -3
  83. package/extension/src/shared/pageRpcContract.js +7 -1
  84. package/extension/src/shared/providerProfiles.js +109 -0
  85. package/extension/src/shared/runActivityModel.js +361 -0
  86. package/extension/src/shared/runExecutionSnapshot.js +8 -2
  87. package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
  88. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
  89. package/extension/src/shared/selectionContext.js +28 -0
  90. package/extension/src/shared/sessionState.js +97 -6
  91. package/extension/src/shared/sharedSessionBridge.js +288 -0
  92. package/extension/src/shared/storageDb.js +23 -55
  93. package/extension/src/shared/storageMigration.js +3 -0
  94. package/extension/src/shared/storageRunActions.js +54 -4
  95. package/extension/src/shared/storageValuePruning.js +40 -0
  96. package/extension/src/shared/subagentActivityModel.js +174 -0
  97. package/extension/src/shared/undoOperations.js +87 -0
  98. package/extension/src/shared/updateConsent.js +37 -8
  99. package/extension/src/shared/writebackIntent.js +62 -0
  100. package/extension/src/shared/writebackSettlement.js +29 -10
  101. package/extension/src/shared/writingStyle.js +33 -0
  102. package/extension/styles/panel.css +2136 -744
  103. package/extension/styles/popup.css +110 -0
  104. package/native-host/src/anthropicBridgeRequest.js +2 -1
  105. package/native-host/src/codexModelRecovery.js +107 -0
  106. package/native-host/src/codexPromptAssembly.js +2 -0
  107. package/native-host/src/codexProviderLaunch.js +3 -3
  108. package/native-host/src/codexRuntimeIdentity.js +1 -0
  109. package/native-host/src/codexSessionRunner.js +146 -177
  110. package/native-host/src/codexSessionTiming.js +71 -0
  111. package/native-host/src/managedInstall.js +5 -4
  112. package/native-host/src/nativeEnvironment.js +70 -0
  113. package/native-host/src/nativeQuotas.js +15 -8
  114. package/native-host/src/overleafWorkspaceRules.js +16 -0
  115. package/native-host/src/processStopBarrier.js +80 -0
  116. package/native-host/src/providerModelCatalog.js +4 -3
  117. package/native-host/src/providerProfile.js +13 -1
  118. package/native-host/src/providerReasoning.js +9 -5
  119. package/native-host/src/providerStore.js +4 -0
  120. package/native-host/src/readProgressGuard.js +84 -17
  121. package/native-host/src/releaseTransport.js +14 -5
  122. package/native-host/src/selectionScope.js +58 -0
  123. package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
  124. package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
  125. package/native-host/src/subagentBroker.js +102 -98
  126. package/native-host/src/subagentTelemetry.js +316 -0
  127. package/native-host/src/subagentWorkspace.js +103 -0
  128. package/native-host/src/subagentWorkspacePath.js +31 -0
  129. package/native-host/src/taskRunnerRuntime.js +55 -5
  130. package/native-host/src/turnAttachments.js +113 -0
  131. package/native-host/src/updateManager.js +122 -12
  132. package/native-host/src/updateNetworkControl.js +75 -0
  133. package/native-host/src/updateTrust.js +21 -2
  134. package/native-host/src/vendor/pdfjs/LICENSE +177 -0
  135. package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
  136. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  137. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  138. package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  139. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  140. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  141. package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  142. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  143. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  144. package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  145. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  146. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  147. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  148. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  149. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  150. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  151. package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  152. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  153. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  154. package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  155. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  156. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  157. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  158. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  159. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  160. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  161. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  162. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  163. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  164. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  165. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  166. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  167. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  168. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  169. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  170. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  171. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  172. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  173. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  174. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  175. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  176. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  177. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  178. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  179. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  180. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  181. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  182. package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  183. package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  184. package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  185. package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  186. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  187. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  188. package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  189. package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  190. package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  191. package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  192. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  193. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  194. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  195. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  196. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  197. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  198. package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  199. package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  200. package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  201. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  202. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  203. package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  204. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  205. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  206. package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  207. package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  208. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  209. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  210. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  211. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  212. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  213. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  214. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  215. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  216. package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  217. package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  218. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  219. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  220. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  221. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  222. package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
  223. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  224. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  225. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  226. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  227. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  228. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  229. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  230. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  231. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  232. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  233. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  234. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  235. package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  236. package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  237. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  238. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  239. package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  240. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  241. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  242. package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  243. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  244. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  245. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  246. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  247. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  248. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  249. package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  250. package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
  251. package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  252. package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  253. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  254. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  255. package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  256. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  257. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  258. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  259. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  260. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  261. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  262. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  263. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  264. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  265. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  266. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  267. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  268. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  269. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  270. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  271. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  272. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  273. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  274. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  275. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  276. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  277. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  278. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  279. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  280. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  281. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  282. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  283. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  284. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  285. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  286. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  287. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  288. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  289. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  290. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  291. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  292. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  293. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  294. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  295. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  296. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  297. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  298. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  299. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  300. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  301. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  302. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  303. package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
  304. package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  305. package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
  306. package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
  307. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  308. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  309. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  310. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  311. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  312. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  313. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  314. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  315. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  316. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  317. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  318. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  319. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  320. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  321. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  322. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  323. package/native-host/src/writingStyleEvidence.js +102 -0
  324. package/native-host/src/writingStylePdfWorker.js +35 -0
  325. package/native-host/src/writingStyleProfile.js +165 -0
  326. package/native-host/src/writingStyleRuntime.js +447 -0
  327. package/package.json +1 -1
@@ -95,6 +95,7 @@
95
95
  }
96
96
  return Object.freeze({
97
97
  createController: createController,
98
- persistPanelState: PanelState?.persistPanelState || null
98
+ persistPanelState: PanelState?.persistPanelState || null,
99
+ applyReviewTransition: PanelState?.applyReviewTransition || null
99
100
  });
100
101
  });
@@ -15,6 +15,42 @@
15
15
  return JSON.parse(JSON.stringify(value));
16
16
  }
17
17
 
18
+ async function applyReviewTransition({ getState, runId, transition, persist }) {
19
+ const targets = () => Array.from(new Set([
20
+ ...(getState().runs || []),
21
+ ...(getState().sessions || []).flatMap(session => session.runs || [])
22
+ ])).filter(run => run.id === runId);
23
+ const records = targets();
24
+ const sessions = (getState().sessions || []).filter(session =>
25
+ (session.runs || []).some(run => run.id === runId));
26
+ if (!records.length || !sessions.length) throw reviewPersistenceError();
27
+ const previous = cloneSnapshot(records[0]);
28
+ for (const record of records) Object.assign(record, cloneSnapshot(transition));
29
+ for (const session of sessions) {
30
+ session.updatedAt = new Date(Math.max(Date.now(), (Date.parse(session.updatedAt) || 0) + 1,
31
+ (Date.parse(session.lastActivityAt) || 0) + 1)).toISOString();
32
+ session.lastActivityAt = session.updatedAt;
33
+ }
34
+ try {
35
+ await persist({ preserveRunActionPayload: true, reviewRunIds: [runId] });
36
+ } catch (error) {
37
+ // The remote action may have succeeded. Keep its recovery data and expose uncertainty.
38
+ for (const record of targets()) {
39
+ Object.assign(record, cloneSnapshot(previous), { trackedChangeStatus: 'needs_review' });
40
+ for (const field of ['settlement', 'settlementFacts']) {
41
+ if (!Object.prototype.hasOwnProperty.call(previous, field)) delete record[field];
42
+ }
43
+ }
44
+ throw error;
45
+ }
46
+ }
47
+
48
+ function reviewPersistenceError() {
49
+ return Object.assign(new Error('The review outcome was not durably saved. Check Overleaf before retrying.'), {
50
+ code: 'review_state_not_persisted'
51
+ });
52
+ }
53
+
18
54
  async function persistPanelState(input) {
19
55
  var state = cloneSnapshot(input.state || {});
20
56
  var compactState = cloneSnapshot(input.compactState || {});
@@ -35,6 +71,9 @@
35
71
  code: 'stale_view'
36
72
  });
37
73
  }
74
+ var reviewRuns = (input.reviewRunIds || []).map(id =>
75
+ (state.sessions || []).flatMap(session => session.runs || []).find(run => run.id === id));
76
+ if (reviewRuns.some(run => !run)) throw reviewPersistenceError();
38
77
  var latestPrefs = typeof Migration.loadPrefs === 'function'
39
78
  ? await Migration.loadPrefs(accountScopeId, projectId)
40
79
  : {};
@@ -94,18 +133,22 @@
94
133
  .filter(function (item) { return !queueTombstones[item?.id]; })
95
134
  }), { preserveRunActionPayload: true });
96
135
  });
97
- await input.SessionPersistence.writeSessions({
136
+ var written = await input.SessionPersistence.writeSessions({
98
137
  Migration: Migration,
99
138
  StorageDb: StorageDb,
100
139
  projectId: projectId,
101
140
  accountScopeId: accountScopeId,
102
141
  deletedSessionIds: deletedSessionIds,
103
142
  sessionRecords: sessionRecords,
143
+ reviewRunIds: input.reviewRunIds,
104
144
  queueClaims: persistenceMeta.queueClaims || {},
105
145
  queueTombstones: queueTombstones,
106
146
  writerId: input.persistenceContext?.writerId || ''
107
147
  });
148
+ if (!reviewRuns.every(reviewRun => (written || []).some(session => (session.runs || []).some(run =>
149
+ run.id === reviewRun.id && run.trackedChangeStatus === reviewRun.trackedChangeStatus
150
+ )))) throw reviewPersistenceError();
108
151
  }
109
152
 
110
- return Object.freeze({ persistPanelState: persistPanelState });
153
+ return Object.freeze({ persistPanelState: persistPanelState, applyReviewTransition: applyReviewTransition });
111
154
  });
@@ -0,0 +1,300 @@
1
+ (function (root, factory) {
2
+ if (typeof module === 'object' && module.exports) module.exports = factory(require('../shared/selectionContext'));
3
+ else root.CodexOverleafModuleRegistry.define('SelectionContextView', ['SelectionContext'], factory);
4
+ })(typeof globalThis !== 'undefined' ? globalThis : window, function (SelectionContext) {
5
+ 'use strict';
6
+
7
+ // The chip shared by the composer and sent messages: file:lines, the edit-only
8
+ // scope label, and the selected text behind a disclosure.
9
+ function buildChip(selection, { document: doc = globalThis.document, tx = en => en, expanded = false } = {}) {
10
+ const lines = selection.lineStart === selection.lineEnd
11
+ ? String(selection.lineStart) : selection.lineStart + '-' + selection.lineEnd;
12
+ const location = selection.path + ':' + lines;
13
+ const details = doc.createElement('details');
14
+ details.open = expanded;
15
+ const summary = doc.createElement('summary');
16
+ summary.title = location;
17
+ summary.setAttribute('aria-label', tx('Preview selection from ' + location, '预览选区:' + location));
18
+ const file = doc.createElement('span');
19
+ file.className = 'codex-selection-file';
20
+ file.textContent = selection.path.split('/').pop();
21
+ const range = doc.createElement('span');
22
+ range.className = 'codex-selection-range';
23
+ range.textContent = ':' + lines;
24
+ summary.append(file, range);
25
+ if (selection.mode === 'edit') {
26
+ const scope = doc.createElement('span');
27
+ scope.className = 'codex-selection-scope';
28
+ scope.textContent = tx('Selection only', '仅此处');
29
+ summary.append(scope);
30
+ }
31
+ const source = doc.createElement('pre');
32
+ source.textContent = selection.text;
33
+ details.append(summary, source);
34
+ return details;
35
+ }
36
+
37
+ // Read-only chip for a sent message: the selection travels with the run's
38
+ // execution snapshot, so the bubble keeps showing what was attached.
39
+ function renderSent(host, value, options = {}) {
40
+ if (!host) return;
41
+ const selection = SelectionContext.normalize(value);
42
+ host.replaceChildren();
43
+ host.hidden = !selection;
44
+ if (selection) host.append(buildChip(selection, options));
45
+ }
46
+
47
+ function create(deps = {}) {
48
+ let generation = 0;
49
+ let probeGeneration = 0;
50
+ let timer = null;
51
+ let controller = null;
52
+ let toolbar = null;
53
+ let candidate = null;
54
+ let pointerSelecting = false;
55
+ let pointerEditor = null;
56
+ const resetEvent = 'codex-overleaf-selection-ui-reset';
57
+ const tx = (en, zh) => deps.tx ? deps.tx(en, zh) : en;
58
+
59
+ function capture() {
60
+ const selection = SelectionContext.normalize(deps.getState()?.selectionContext);
61
+ return selection?.projectId === deps.getProjectId() ? selection : null;
62
+ }
63
+
64
+ function clear() {
65
+ generation += 1;
66
+ hideFloating();
67
+ deps.setSelection(null);
68
+ render();
69
+ }
70
+
71
+ function render() {
72
+ const panel = deps.getPanel();
73
+ if (toolbar && !toolbar.hidden) syncFloatingAppearance();
74
+ const host = panel?.querySelector('[data-composer-selection]');
75
+ if (!host) return;
76
+ const selection = capture();
77
+ const id = selection ? [selection.projectId, selection.path, selection.from, selection.to,
78
+ selection.documentHash, selection.capturedAt, selection.mode].join(':') : '';
79
+ const expanded = Boolean(id && host.dataset.selectionId === id && host.querySelector('details')?.open);
80
+ host.replaceChildren();
81
+ host.dataset.selectionId = id;
82
+ host.hidden = !selection;
83
+ if (!selection) return;
84
+
85
+ host.append(buildChip(selection, { document, tx, expanded }));
86
+ const remove = document.createElement('button');
87
+ remove.type = 'button';
88
+ remove.textContent = '\u00d7';
89
+ remove.title = tx('Remove selection', '移除选区');
90
+ remove.setAttribute('aria-label', remove.title);
91
+ remove.addEventListener('click', clear);
92
+ host.append(remove);
93
+ }
94
+
95
+ async function attach(mode = 'reference', selected = null) {
96
+ const request = ++generation;
97
+ const projectId = deps.getProjectId();
98
+ const sessionId = deps.getState()?.activeSessionId;
99
+ if (selected && (selected.projectId !== projectId || selected.sessionId !== sessionId)) return null;
100
+ hideFloating();
101
+ try {
102
+ const response = selected
103
+ ? { ok: true, selection: selected.selection }
104
+ : await deps.callPageBridge('getSelectionContext', { runProjectId: projectId });
105
+ if (request !== generation || projectId !== deps.getProjectId()
106
+ || sessionId !== deps.getState()?.activeSessionId) return null;
107
+ const selection = SelectionContext.normalize({
108
+ ...(response?.selection || response), mode: mode === 'edit' ? 'edit' : 'reference'
109
+ });
110
+ if (response?.ok !== true || !selection || selection.projectId !== projectId) {
111
+ deps.toast?.(response?.code === 'selection_too_large'
112
+ ? tx('Select a shorter passage (up to 20,000 characters).', '请选择较短的片段,最多 20,000 个字符。')
113
+ : tx('Select text in the source editor first.', '请先在源码编辑器中选中文字。'));
114
+ return null;
115
+ }
116
+ await deps.openComposer?.();
117
+ if (request !== generation || projectId !== deps.getProjectId()
118
+ || sessionId !== deps.getState()?.activeSessionId) return null;
119
+ deps.setSelection(selection, { edit: selection.mode === 'edit' });
120
+ render();
121
+ const panel = deps.getPanel();
122
+ const tray = panel?.querySelector('[data-context-tray]');
123
+ if (tray) tray.hidden = true;
124
+ panel?.querySelector('[data-add-context]')?.setAttribute('aria-expanded', 'false');
125
+ panel?.querySelector('[data-task]')?.focus();
126
+ return selection;
127
+ } catch (_) {
128
+ if (request === generation && projectId === deps.getProjectId()
129
+ && sessionId === deps.getState()?.activeSessionId) {
130
+ deps.toast?.(tx('Could not attach the selection. Select it again and retry.', '未能添加选区,请重新选取后再试。'));
131
+ }
132
+ return null;
133
+ }
134
+ }
135
+
136
+ function editorFor(node) {
137
+ const element = node?.nodeType === 1 ? node : node?.parentElement;
138
+ const editor = element?.closest?.('.cm-editor');
139
+ return editor && !editor.closest('#codex-overleaf-panel') ? editor : null;
140
+ }
141
+
142
+ function hideFloating() {
143
+ probeGeneration += 1;
144
+ clearTimeout(timer);
145
+ timer = null;
146
+ candidate = null;
147
+ if (!toolbar) return;
148
+ if (typeof toolbar.hidePopover === 'function' && toolbar.matches(':popover-open')) toolbar.hidePopover();
149
+ toolbar.hidden = true;
150
+ }
151
+
152
+ function syncFloatingAppearance() {
153
+ if (!toolbar) return;
154
+ const panel = deps.getPanel();
155
+ const computed = panel ? window.getComputedStyle(panel) : null;
156
+ const theme = deps.getState()?.theme;
157
+ const dark = theme === 'dark' || (theme !== 'light' && window.matchMedia('(prefers-color-scheme: dark)').matches);
158
+ const colors = dark
159
+ ? ['#26282b', '#f1f2f4', '#adb4be', '#454b53', '#353a41', '#91b7e1']
160
+ : ['#ffffff', '#24292f', '#67717e', '#d8dde3', '#f0f3f6', '#2f73b8'];
161
+ ['--tl-surface-0', '--tl-fg-1', '--tl-fg-3', '--tl-border-strong', '--tl-hover', '--tl-accent']
162
+ .forEach((name, index) => toolbar.style.setProperty(name, computed?.getPropertyValue(name).trim() || colors[index]));
163
+ if (computed?.fontFamily) toolbar.style.fontFamily = computed.fontFamily;
164
+ toolbar.setAttribute('aria-label', tx('Selected text actions', '选区操作'));
165
+ toolbar.querySelector('[data-selection-action="reference"]').textContent = tx('Add to Chat', '加入对话');
166
+ toolbar.querySelector('[data-selection-action="edit"]').textContent = tx('Edit Selection', '仅编辑此处');
167
+ }
168
+
169
+ function ensureToolbar() {
170
+ if (toolbar) return;
171
+ toolbar = document.createElement('div');
172
+ toolbar.className = 'codex-selection-actions';
173
+ toolbar.setAttribute('data-codex-selection-actions', '');
174
+ toolbar.setAttribute('role', 'toolbar');
175
+ toolbar.hidden = true;
176
+ if (typeof toolbar.showPopover === 'function') toolbar.setAttribute('popover', 'manual');
177
+ for (const mode of ['reference', 'edit']) {
178
+ if (mode === 'edit') {
179
+ const divider = document.createElement('span');
180
+ divider.className = 'codex-selection-action-divider';
181
+ divider.setAttribute('aria-hidden', 'true');
182
+ toolbar.append(divider);
183
+ }
184
+ const button = document.createElement('button');
185
+ button.type = 'button';
186
+ button.dataset.selectionAction = mode;
187
+ button.addEventListener('click', () => {
188
+ const selected = candidate;
189
+ if (selected) void attach(mode, selected);
190
+ });
191
+ toolbar.append(button);
192
+ }
193
+ document.body.append(toolbar);
194
+ syncFloatingAppearance();
195
+ }
196
+
197
+ function showFloating(anchor) {
198
+ ensureToolbar();
199
+ syncFloatingAppearance();
200
+ toolbar.hidden = false;
201
+ if (typeof toolbar.showPopover === 'function' && !toolbar.matches(':popover-open')) toolbar.showPopover();
202
+ const rect = toolbar.getBoundingClientRect();
203
+ const width = window.innerWidth, height = window.innerHeight;
204
+ const left = Math.max(8, Math.min(width - rect.width - 8,
205
+ (anchor.left + anchor.right) / 2 - rect.width / 2));
206
+ const preferredTop = anchor.top - rect.height - 8;
207
+ const top = Math.max(8, Math.min(height - rect.height - 8,
208
+ preferredTop >= 8 ? preferredTop : anchor.bottom + 8));
209
+ toolbar.style.left = left + 'px';
210
+ toolbar.style.top = top + 'px';
211
+ }
212
+
213
+ function schedule(editor) {
214
+ hideFloating();
215
+ if (!controller || pointerSelecting || !editor) return;
216
+ const request = ++probeGeneration;
217
+ timer = setTimeout(() => { timer = null; void probe(editor, request); }, 90);
218
+ }
219
+
220
+ async function probe(editor, request) {
221
+ if (!controller || request !== probeGeneration || document.hidden
222
+ || !editor.isConnected || !editor.contains(document.activeElement)) return;
223
+ const projectId = deps.getProjectId();
224
+ const sessionId = deps.getState()?.activeSessionId;
225
+ try {
226
+ const response = await deps.callPageBridge('getSelectionContext', { runProjectId: projectId });
227
+ if (request !== probeGeneration || projectId !== deps.getProjectId()
228
+ || sessionId !== deps.getState()?.activeSessionId || !editor.isConnected
229
+ || !editor.contains(document.activeElement)) return;
230
+ const selection = SelectionContext.normalize(response?.selection || response);
231
+ const anchor = response?.anchor;
232
+ if (!response?.ok || !selection || selection.projectId !== projectId || !anchor
233
+ || !['left', 'right', 'top', 'bottom'].every(key => Number.isFinite(anchor[key]))
234
+ || anchor.bottom < 0 || anchor.top > window.innerHeight) return;
235
+ candidate = { selection, anchor, projectId, sessionId };
236
+ showFloating(anchor);
237
+ } catch (_) { /* Transient editor states do not interrupt ordinary selection. */ }
238
+ }
239
+
240
+ function start() {
241
+ if (controller) return;
242
+ // Replacing a content runtime retires the old selection listener set.
243
+ document.dispatchEvent(new Event(resetEvent));
244
+ controller = new AbortController();
245
+ const options = { capture: true, signal: controller.signal };
246
+ document.addEventListener(resetEvent, destroy, options);
247
+ document.addEventListener('pointerdown', event => {
248
+ if (toolbar?.contains(event.target)) {
249
+ if (event.button === 0) event.preventDefault();
250
+ return;
251
+ }
252
+ hideFloating();
253
+ pointerEditor = editorFor(event.target);
254
+ pointerSelecting = Boolean(pointerEditor && event.button === 0);
255
+ }, options);
256
+ document.addEventListener('pointerup', () => {
257
+ if (!pointerSelecting) return;
258
+ pointerSelecting = false;
259
+ const editor = pointerEditor;
260
+ pointerEditor = null;
261
+ schedule(editor);
262
+ }, options);
263
+ document.addEventListener('pointercancel', () => {
264
+ pointerSelecting = false;
265
+ pointerEditor = null;
266
+ hideFloating();
267
+ }, options);
268
+ document.addEventListener('selectionchange', () => {
269
+ if (pointerSelecting || toolbar?.contains(document.activeElement)) return;
270
+ schedule(editorFor(document.activeElement));
271
+ }, options);
272
+ document.addEventListener('keyup', event => {
273
+ if (event.key !== 'Escape' && editorFor(event.target)) schedule(editorFor(event.target));
274
+ }, options);
275
+ document.addEventListener('keydown', event => {
276
+ if (event.key === 'Escape') hideFloating();
277
+ }, options);
278
+ document.addEventListener('scroll', hideFloating, { ...options, passive: true });
279
+ document.addEventListener('visibilitychange', () => { if (document.hidden) hideFloating(); }, options);
280
+ window.addEventListener('resize', hideFloating, { ...options, passive: true });
281
+ window.addEventListener('blur', hideFloating, options);
282
+ window.addEventListener('pagehide', event => { if (event.persisted) hideFloating(); else destroy(); }, options);
283
+ }
284
+
285
+ function destroy() {
286
+ generation += 1;
287
+ hideFloating();
288
+ controller?.abort();
289
+ controller = null;
290
+ pointerSelecting = false;
291
+ pointerEditor = null;
292
+ toolbar?.remove();
293
+ toolbar = null;
294
+ }
295
+
296
+ return { attach, capture, clear, render, start, destroy };
297
+ }
298
+
299
+ return { create, buildChip, renderSent };
300
+ });
@@ -73,7 +73,10 @@
73
73
  const existingById = new Map(existingSessions
74
74
  .filter(record => !deleted.has(record.id))
75
75
  .map(record => [record.id, record]));
76
- const writable = sessionRecords.filter(record => {
76
+ const mergedRecords = sessionRecords.map(record => StorageDb.mergeSessionReviewState?.(
77
+ record, existingById.get(record.id), options.reviewRunIds
78
+ ) || record);
79
+ const writable = mergedRecords.filter(record => {
77
80
  const existing = existingById.get(record.id);
78
81
  if (!existing) return true;
79
82
  return (Date.parse(record.updatedAt || '') || 0) >= (Date.parse(existing.updatedAt || '') || 0);
@@ -82,7 +85,12 @@
82
85
  record !== rawExistingSessions[index] && !writable.some(item => item.id === record.id)
83
86
  );
84
87
  if (cleanedExisting.length || writable.length) {
85
- await StorageDb.putRecords('sessions', [...cleanedExisting, ...writable]);
88
+ const written = await StorageDb.putRecords('sessions', [...cleanedExisting, ...writable], {
89
+ reviewRunIds: options.reviewRunIds
90
+ });
91
+ // Check the actual durable result, including a decision already saved
92
+ // from another origin, instead of acknowledging only the proposed view.
93
+ return written.filter(record => writable.some(candidate => candidate.id === record.id));
86
94
  }
87
95
  return writable;
88
96
  }