codex-overleaf-link 2.4.1 → 2.5.1

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 (397) hide show
  1. package/README.md +275 -305
  2. package/README.zh-CN.md +290 -320
  3. package/extension/bootstrap/background.js +99 -19
  4. package/extension/bootstrap/manifest.template.json +9 -4
  5. package/extension/bootstrap/popup.html +11 -16
  6. package/extension/bootstrap/popupFallback.js +55 -0
  7. package/extension/bootstrap/update.js +25 -2
  8. package/extension/bootstrap/updateStatus.js +1 -0
  9. package/extension/runtime-manifest.json +3 -1
  10. package/extension/src/background.js +234 -56
  11. package/extension/src/backgroundBootstrapMigration.js +181 -0
  12. package/extension/src/backgroundSharedSessions.js +440 -0
  13. package/extension/src/backgroundUpdateCoordinator.js +541 -381
  14. package/extension/src/backgroundUpdateSafety.js +173 -0
  15. package/extension/src/content/activeTurnControl.js +16 -2
  16. package/extension/src/content/applyResultFormatters.js +46 -73
  17. package/extension/src/content/assetTransferBroker.js +244 -12
  18. package/extension/src/content/changeHistoryView.js +175 -0
  19. package/extension/src/content/composerAttachments.js +117 -67
  20. package/extension/src/content/composerPanel.js +41 -8
  21. package/extension/src/content/contentRuntime.js +1084 -1099
  22. package/extension/src/content/diagnosticsController.js +122 -97
  23. package/extension/src/content/diagnosticsExport.js +236 -0
  24. package/extension/src/content/diagnosticsPanel.js +78 -19
  25. package/extension/src/content/diffReviewPanel.js +8 -5
  26. package/extension/src/content/directoryCleanupRecovery.js +54 -0
  27. package/extension/src/content/generated/content.bundle.js +14680 -3606
  28. package/extension/src/content/generated/content.bundle.meta.json +30 -3
  29. package/extension/src/content/globalPreferencesController.js +1 -1
  30. package/extension/src/content/legacyGlobalRegistry.js +25 -1
  31. package/extension/src/content/localSkillsPanel.js +141 -16
  32. package/extension/src/content/markdownDomRenderer.js +9 -4
  33. package/extension/src/content/markdownText.js +5 -6
  34. package/extension/src/content/modelPicker.js +8 -5
  35. package/extension/src/content/nativeCompatibilityController.js +45 -20
  36. package/extension/src/content/otWarmMirror.js +4 -5
  37. package/extension/src/content/otWarmMirrorController.js +17 -20
  38. package/extension/src/content/pageBridgeClient.js +33 -5
  39. package/extension/src/content/panelMaintenance.js +87 -132
  40. package/extension/src/content/panelRenderer.js +10 -0
  41. package/extension/src/content/pendingInputView.js +109 -76
  42. package/extension/src/content/projectProviderSelection.js +13 -4
  43. package/extension/src/content/projectSessionCleanup.js +109 -62
  44. package/extension/src/content/projectSettingsCoordinator.js +39 -2
  45. package/extension/src/content/providerSettingsCoordinator.js +63 -14
  46. package/extension/src/content/providerSettingsDialog.js +724 -113
  47. package/extension/src/content/recentProjects.js +21 -6
  48. package/extension/src/content/runActivitySummary.js +665 -0
  49. package/extension/src/content/runCompletionMeta.js +344 -0
  50. package/extension/src/content/runController.js +40 -15
  51. package/extension/src/content/runFailureNotice.js +34 -12
  52. package/extension/src/content/runGuidanceController.js +76 -30
  53. package/extension/src/content/runGuidanceView.js +59 -10
  54. package/extension/src/content/runPresence.js +306 -0
  55. package/extension/src/content/runQueueScheduler.js +150 -43
  56. package/extension/src/content/runRecoveryActions.js +146 -0
  57. package/extension/src/content/runResultActions.js +11 -8
  58. package/extension/src/content/runReviewController.js +574 -0
  59. package/extension/src/content/runScrollLayout.js +21 -2
  60. package/extension/src/content/runTimelineView.js +315 -290
  61. package/extension/src/content/scopedPersistencePanelState.js +51 -6
  62. package/extension/src/content/selectionContextView.js +300 -0
  63. package/extension/src/content/sensitivePreflight.js +140 -0
  64. package/extension/src/content/sessionForkController.js +80 -17
  65. package/extension/src/content/sessionManager.js +1 -1
  66. package/extension/src/content/sessionPersistence.js +6 -1
  67. package/extension/src/content/settingsPanel.js +84 -55
  68. package/extension/src/content/settingsWorkbench.js +379 -0
  69. package/extension/src/content/sharedSessionViewSync.js +109 -0
  70. package/extension/src/content/subagentActivityView.js +195 -0
  71. package/extension/src/content/trackedChangeCaptureController.js +7 -3
  72. package/extension/src/content/updateIdle.js +4 -1
  73. package/extension/src/content/updateNotice.js +179 -56
  74. package/extension/src/content/updateSafetyReceiver.js +58 -0
  75. package/extension/src/content/writebackController.js +308 -2
  76. package/extension/src/content/writebackOrchestrator.js +213 -199
  77. package/extension/src/content/writebackPlan.js +231 -0
  78. package/extension/src/content/writebackRecovery.js +122 -0
  79. package/extension/src/content/writingStyleSettings.js +600 -0
  80. package/extension/src/content/writtenChangesView.js +152 -0
  81. package/extension/src/page/binaryAssetUploader.js +223 -23
  82. package/extension/src/page/fileMover.js +256 -0
  83. package/extension/src/page/overleafProjectSnapshot.js +1 -0
  84. package/extension/src/page/ownedDirectoryCleanup.js +94 -0
  85. package/extension/src/page/referenceProjects.js +149 -0
  86. package/extension/src/page/reviewContext.js +113 -0
  87. package/extension/src/page/saveState.js +20 -6
  88. package/extension/src/page/snapshotRouter.js +124 -48
  89. package/extension/src/page/textCoordinates.js +102 -0
  90. package/extension/src/page/textFileCreator.js +442 -71
  91. package/extension/src/page/trackedChangeCapture.js +53 -57
  92. package/extension/src/page/trackedChangeOwnership.js +216 -0
  93. package/extension/src/page/trackedChangeReplay.js +184 -0
  94. package/extension/src/page/trackedChangesLifecycle.js +343 -339
  95. package/extension/src/page/treeOperations.js +33 -12
  96. package/extension/src/page/updateSafetyProbe.js +41 -0
  97. package/extension/src/page/writebackReceiptJournal.js +114 -0
  98. package/extension/src/page/writebackRouter.js +242 -201
  99. package/extension/src/pageBridge.js +73 -102
  100. package/extension/src/popup.js +261 -65
  101. package/extension/src/shared/agentTranscript.js +41 -4
  102. package/extension/src/shared/auditRecords.js +73 -0
  103. package/extension/src/shared/changeHistoryModel.js +94 -0
  104. package/extension/src/shared/compatibility.js +22 -6
  105. package/extension/src/shared/compileAdapter.js +101 -37
  106. package/extension/src/shared/composerAttachmentDraft.js +151 -0
  107. package/extension/src/shared/directoryCleanupProof.js +43 -0
  108. package/extension/src/shared/failureReasons.js +329 -3
  109. package/extension/src/shared/globalPreferences.js +31 -14
  110. package/extension/src/shared/governanceRules.js +4 -37
  111. package/extension/src/shared/i18n.js +389 -25
  112. package/extension/src/shared/managedUpdateProjection.js +8 -5
  113. package/extension/src/shared/nativeRequestIdentity.js +1 -0
  114. package/extension/src/shared/pageRpcContract.js +9 -2
  115. package/extension/src/shared/projectFiles.js +21 -44
  116. package/extension/src/shared/providerProfiles.js +114 -3
  117. package/extension/src/shared/runActivityModel.js +361 -0
  118. package/extension/src/shared/runExecutionSnapshot.js +8 -2
  119. package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
  120. package/extension/src/shared/runInputQueue.js +48 -5
  121. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
  122. package/extension/src/shared/selectionContext.js +37 -0
  123. package/extension/src/shared/sessionState.js +166 -30
  124. package/extension/src/shared/settlementFacts.js +10 -2
  125. package/extension/src/shared/sharedSessionBridge.js +311 -0
  126. package/extension/src/shared/sharedSessionTransfer.js +140 -0
  127. package/extension/src/shared/staleGuard.js +118 -13
  128. package/extension/src/shared/storageDb.js +77 -78
  129. package/extension/src/shared/storageMigration.js +74 -111
  130. package/extension/src/shared/storageRunActions.js +211 -22
  131. package/extension/src/shared/storageValuePruning.js +40 -0
  132. package/extension/src/shared/subagentActivityModel.js +174 -0
  133. package/extension/src/shared/undoOperations.js +216 -6
  134. package/extension/src/shared/updateConsent.js +42 -11
  135. package/extension/src/shared/updateRuntimeIdentity.js +1 -1
  136. package/extension/src/shared/writebackIntent.js +78 -0
  137. package/extension/src/shared/writebackOperationEvidence.js +4 -15
  138. package/extension/src/shared/writebackSettlement.js +67 -48
  139. package/extension/src/shared/writingStyle.js +33 -0
  140. package/extension/styles/panel.css +1987 -385
  141. package/extension/styles/popup.css +110 -0
  142. package/native-host/src/anthropicBridgeRequest.js +6 -3
  143. package/native-host/src/anthropicBridgeResponse.js +6 -2
  144. package/native-host/src/anthropicMessagesBridge.js +24 -16
  145. package/native-host/src/bootstrapMigration.js +296 -0
  146. package/native-host/src/bootstrapMigrationContract.js +101 -0
  147. package/native-host/src/bootstrapUpdate.js +233 -0
  148. package/native-host/src/bootstrapUpdateWatchdog.js +44 -0
  149. package/native-host/src/chatBridgeResponse.js +10 -0
  150. package/native-host/src/chatCompletionsBridge.js +21 -15
  151. package/native-host/src/codexConfigPaths.js +106 -0
  152. package/native-host/src/codexHome.js +66 -73
  153. package/native-host/src/codexHomeScope.js +124 -0
  154. package/native-host/src/codexInheritedAuth.js +90 -0
  155. package/native-host/src/codexLocalSkills.js +301 -0
  156. package/native-host/src/codexModelRecovery.js +107 -0
  157. package/native-host/src/codexPromptAssembly.js +33 -12
  158. package/native-host/src/codexProviderLaunch.js +3 -3
  159. package/native-host/src/codexProviderTest.js +24 -26
  160. package/native-host/src/codexRuntimeIdentity.js +1 -0
  161. package/native-host/src/codexSessionRunner.js +211 -318
  162. package/native-host/src/codexSessionTiming.js +21 -8
  163. package/native-host/src/codexSkillIsolation.js +170 -0
  164. package/native-host/src/codexThreadFork.js +19 -3
  165. package/native-host/src/index.js +19 -7
  166. package/native-host/src/managedInstall.js +115 -39
  167. package/native-host/src/managedInstallRecovery.js +140 -0
  168. package/native-host/src/managedRuntimeEvidence.js +57 -0
  169. package/native-host/src/mirrorWorkspace.js +92 -22
  170. package/native-host/src/nativeDoctor.js +15 -0
  171. package/native-host/src/nativeEnvironment.js +70 -0
  172. package/native-host/src/nativeHelperLifecycle.js +21 -0
  173. package/native-host/src/nativeHostRegistration.js +33 -0
  174. package/native-host/src/nativeQuotas.js +15 -8
  175. package/native-host/src/nativeRunLifecycle.js +71 -0
  176. package/native-host/src/overleafWorkspaceRules.js +16 -0
  177. package/native-host/src/processStopBarrier.js +115 -0
  178. package/native-host/src/projectPathPlatform.js +30 -0
  179. package/native-host/src/providerHttp.js +80 -0
  180. package/native-host/src/providerModelCatalog.js +4 -3
  181. package/native-host/src/providerProfile.js +17 -3
  182. package/native-host/src/providerReasoning.js +10 -11
  183. package/native-host/src/providerRuntime.js +1 -0
  184. package/native-host/src/providerStore.js +76 -14
  185. package/native-host/src/releaseTransport.js +14 -5
  186. package/native-host/src/responsesPassthroughBridge.js +266 -52
  187. package/native-host/src/runtimeInstaller.js +21 -1
  188. package/native-host/src/selectionScope.js +86 -0
  189. package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
  190. package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
  191. package/native-host/src/subagentAdmission.js +26 -0
  192. package/native-host/src/subagentBroker.js +176 -159
  193. package/native-host/src/subagentTelemetry.js +325 -0
  194. package/native-host/src/subagentWorkspace.js +103 -0
  195. package/native-host/src/subagentWorkspacePath.js +34 -0
  196. package/native-host/src/taskRunnerRuntime.js +130 -57
  197. package/native-host/src/tomlStatements.js +140 -0
  198. package/native-host/src/turnAttachments.js +113 -0
  199. package/native-host/src/updateManager.js +406 -38
  200. package/native-host/src/updateNetworkControl.js +75 -0
  201. package/native-host/src/updateTrust.js +21 -2
  202. package/native-host/src/vendor/pdfjs/LICENSE +177 -0
  203. package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
  204. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  205. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  206. package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  207. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  208. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  209. package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  210. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  211. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  212. package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  213. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  214. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  215. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  216. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  217. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  218. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  219. package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  220. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  221. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  222. package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  223. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  224. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  225. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  226. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  227. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  228. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  229. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  230. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  231. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  232. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  233. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  234. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  235. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  236. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  237. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  238. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  239. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  240. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  241. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  242. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  243. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  244. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  245. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  246. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  247. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  248. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  249. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  250. package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  251. package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  252. package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  253. package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  254. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  255. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  256. package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  257. package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  258. package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  259. package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  260. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  261. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  262. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  263. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  264. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  265. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  266. package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  267. package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  268. package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  269. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  270. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  271. package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  272. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  273. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  274. package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  275. package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  276. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  277. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  278. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  279. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  280. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  281. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  282. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  283. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  284. package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  285. package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  286. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  287. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  288. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  289. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  290. package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
  291. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  292. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  293. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  294. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  295. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  296. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  297. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  298. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  299. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  300. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  301. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  302. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  303. package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  304. package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  305. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  306. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  307. package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  308. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  309. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  310. package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  311. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  312. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  313. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  314. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  315. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  316. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  317. package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  318. package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
  319. package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  320. package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  321. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  322. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  323. package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  324. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  325. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  326. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  327. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  328. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  329. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  330. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  331. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  332. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  333. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  334. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  335. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  336. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  337. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  338. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  339. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  340. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  341. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  342. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  343. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  344. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  345. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  346. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  347. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  348. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  349. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  350. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  351. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  352. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  353. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  354. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  355. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  356. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  357. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  358. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  359. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  360. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  361. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  362. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  363. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  364. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  365. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  366. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  367. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  368. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  369. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  370. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  371. package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
  372. package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  373. package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
  374. package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
  375. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  376. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  377. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  378. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  379. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  380. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  381. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  382. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  383. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  384. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  385. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  386. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  387. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  388. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  389. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  390. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  391. package/native-host/src/writingStyleEvidence.js +102 -0
  392. package/native-host/src/writingStylePdfWorker.js +35 -0
  393. package/native-host/src/writingStyleProfile.js +165 -0
  394. package/native-host/src/writingStyleRuntime.js +475 -0
  395. package/native-host/src/writingStyleStore.js +73 -0
  396. package/package.json +1 -1
  397. package/scripts/install-managed.mjs +1 -0
@@ -1,8 +1,9 @@
1
1
  (function (root, factory) {
2
- const api = factory();
2
+ const api = factory(typeof module === 'object' && module.exports
3
+ ? require('./trackedChangeOwnership') : root.CodexOverleafTrackedChangeOwnership);
3
4
  if (typeof module === 'object' && module.exports) module.exports = api;
4
5
  if (root) root.CodexOverleafTrackedChangeCapture = api;
5
- })(typeof window !== 'undefined' ? window : globalThis, function () {
6
+ })(typeof window !== 'undefined' ? window : globalThis, function (Ownership) {
6
7
  'use strict';
7
8
 
8
9
  function create(deps = {}) {
@@ -125,11 +126,32 @@
125
126
  reason: snapshot.ready ? (snapshot.refs.length ? 'native_untracked_undo_pending_changes' : '')
126
127
  : snapshot.reason || 'native_review_unavailable' };
127
128
  }
129
+ const mergedPrefix = 'native-merge:';
130
+ const nativeKey = tuple => 'native:' + JSON.stringify(tuple);
131
+ const ledgerKeys = refs => refs.map(ref => ref.key).sort();
132
+ const { mergedInsertionScope, prepareMergedInsertionReview, nativeOwned, rangesFor, shiftedBaseline, scopeCovered, reviewNodeMatches } = Ownership.create({
133
+ fingerprint, readActiveEditorText, mergedPrefix, nativeKey, ledgerKeys
134
+ });
135
+
136
+
137
+
138
+ function isTrackedChangeNodeInNativeScope(node, path) {
139
+ if (typeof deps.getCodeMirrorEditorView !== 'function') return true;
140
+ return reviewNodeMatches(node, path, readNativeSnapshot(path), explicitId(node));
141
+ }
142
+ function rememberTrackedChangeNodeContext(path) {
143
+ if (typeof deps.getCodeMirrorEditorView !== 'function') return;
144
+ const snapshot = readNativeSnapshot(path);
145
+ if (snapshot.ready) for (const node of collectTrackedChangeNodes()) reviewNodeMatches(node, path, snapshot, explicitId(node));
146
+ }
147
+
128
148
  function prepareTrackedChangeReview(path, refs = []) {
129
149
  const snapshot = readNativeSnapshot(path);
130
150
  const blocked = reason => ({ ...snapshot, ok: false, reason });
131
151
  if (!snapshot.ready) return blocked(snapshot.reason || 'native_review_unavailable');
132
152
  const targets = refs.filter(ref => ref.path === path), ids = new Set(targets.map(ref => ref.id));
153
+ if (targets.some(ref => ref.key?.startsWith(mergedPrefix)))
154
+ return prepareMergedInsertionReview(path, targets, snapshot);
133
155
  let expected;
134
156
  try {
135
157
  expected = targets.map(ref => {
@@ -150,19 +172,6 @@
150
172
  return { ...snapshot, ok: true, targets, ids: [...ids],
151
173
  unrelated: snapshot.refs.filter(ref => !ids.has(ref.id)) };
152
174
  }
153
- function nativeOwned(ref, capture) {
154
- if (ref.source !== 'native' || !Number.isSafeInteger(ref.from) || !Number.isSafeInteger(ref.to)) return false;
155
- if (ref.kind === 'delete') return capture.ranges.some(range => ref.from >= range.start && ref.from <= range.end
156
- && ref.textLength === range.removedLength && ref.textHash === range.removedHash && range.removedLength > 0);
157
- let covered = ref.from;
158
- for (const range of capture.ranges) {
159
- if (range.end < covered) continue;
160
- if (range.start > covered) break;
161
- covered = Math.max(covered, range.end);
162
- if (covered >= ref.to) return ref.to > ref.from;
163
- }
164
- return false;
165
- }
166
175
  const identity = ref => (ref.path || '') + '\0' + ref.key;
167
176
  function diff(before, after) {
168
177
  const seen = new Set(before.map(identity));
@@ -173,34 +182,6 @@
173
182
  return true;
174
183
  });
175
184
  }
176
- function rangesFor(operation, beforeContent, postContent) {
177
- const patches = Array.isArray(operation.patches) && operation.patches.length
178
- ? operation.patches
179
- : [{ from: 0, to: beforeContent.length, insert: postContent }];
180
- let delta = 0;
181
- return patches.map(patch => {
182
- const range = { from: patch.from, to: patch.to,
183
- start: patch.from + delta, end: patch.from + delta + String(patch.insert ?? '').length,
184
- removedLength: patch.to - patch.from, removedHash: fingerprint(beforeContent.slice(patch.from, patch.to)) };
185
- delta += String(patch.insert ?? '').length - (patch.to - patch.from);
186
- return range;
187
- });
188
- }
189
- function shiftedBaseline(before, ranges) {
190
- let overlap = false;
191
- const refs = before.map(ref => {
192
- const match = /^pos:(\d+):/.exec(ref.key);
193
- if (!match) return ref;
194
- const pos = Number(match[1]);
195
- let delta = 0;
196
- for (const range of ranges) {
197
- if (pos >= range.from && pos < range.to) overlap = true;
198
- if (pos >= range.to) delta += (range.end - range.start) - (range.to - range.from);
199
- }
200
- return { ...ref, key: ref.key.replace(/^pos:\d+:/, 'pos:' + (pos + delta) + ':') };
201
- });
202
- return { refs, overlap };
203
- }
204
185
  function allowedRef(ref, capture) {
205
186
  if (ref.path !== capture.path) return false;
206
187
  if (capture.source === 'native') return nativeOwned(ref, capture);
@@ -212,16 +193,6 @@
212
193
  // insufficient to assign a new task ownership after a delayed capture.
213
194
  return Boolean(ref.id);
214
195
  }
215
- function scopeCovered(refs, capture) {
216
- if (capture.source === 'native') return capture.ranges.every(range => refs.some(ref =>
217
- ref.from <= range.end && ref.to >= range.start));
218
- const positioned = refs.filter(ref => /^pos:\d+:/.test(ref.key));
219
- if (refs.some(ref => ref.id)) return true;
220
- return capture.ranges.every(range => positioned.some(ref => {
221
- const pos = Number(/^pos:(\d+):/.exec(ref.key)[1]);
222
- return pos >= range.start && pos <= range.end;
223
- }));
224
- }
225
196
  async function waitForTrackedChangeDiff(before, paths, options = {}) {
226
197
  const waitMs = Math.max(0, Number(options.waitMs ?? 5000));
227
198
  const intervalMs = Math.max(1, Number(options.intervalMs ?? 180));
@@ -244,9 +215,15 @@
244
215
  if (options.capture && !allowedRef(ref, options.capture)) { filtered++; continue; }
245
216
  found.set(identity(ref), ref);
246
217
  }
218
+ const merged = native && lastSnapshotReady
219
+ ? mergedInsertionScope(options.capture, after, readActiveEditorText()) : null;
220
+ if (merged) { found.clear(); found.set(identity(merged.ref), merged.ref); }
247
221
  const nextSignature = after.map(ref => native ? ref.key : identity(ref)).sort().join('\n');
248
222
  if (nextSignature !== signature) { signature = nextSignature; lastChange = now(); }
249
223
  if (options.stopOnFirst && found.size) { reason = 'observed'; break; }
224
+ if (options.capture && now() - start >= 5000 && lastSnapshotReady && found.size
225
+ && now() - lastChange >= stableMs && scopeCovered(Array.from(found.values()), options.capture)
226
+ && afterCount < limit) { reason = 'observed'; break; }
250
227
  if (now() >= deadline) break;
251
228
  await delay(Math.min(intervalMs, deadline - now()));
252
229
  }
@@ -263,7 +240,7 @@
263
240
  source: options.capture?.source || 'dom', sourceReason }
264
241
  };
265
242
  }
266
- async function captureTrackedWrite({ trackedBefore, captureBaseline, operation, beforeContent, postContent, runProjectId }) {
243
+ async function captureTrackedWrite({ trackedBefore, captureBaseline, operation, beforeContent, postContent, runProjectId, waitMs = 5000 }) {
267
244
  if (beforeContent === postContent) return { trackedChanges: [], capture: null };
268
245
  const ranges = rangesFor(operation, beforeContent, postContent);
269
246
  const baseline = shiftedBaseline(trackedBefore, ranges);
@@ -284,7 +261,7 @@
284
261
  capture.reason = baseline.overlap ? 'preexisting_change_overlap' : 'capture_baseline_limit';
285
262
  return { trackedChanges: [], capture };
286
263
  }
287
- return observe(capture, postContent, 5000);
264
+ return observe(capture, postContent, Math.min(35000, Math.max(5000, Number(waitMs) || 5000)));
288
265
  }
289
266
  function validCapture(capture) {
290
267
  return capture?.version === 1 && typeof capture.path === 'string'
@@ -333,9 +310,28 @@
333
310
  if (params.capture?.runProjectId !== params.runProjectId) {
334
311
  return { ok: false, code: 'capture_project_mismatch', trackedChanges: [] };
335
312
  }
336
- return observe(params.capture, params.expectedContent, 1200);
313
+ const capture = params.capture;
314
+ // An expired polling window does not erase a provable, unchanged scope.
315
+ // Recovery is read-only and must reconstruct the complete old/new ledger.
316
+ if (validCapture(capture) && capture.source === 'native'
317
+ && (now() >= capture.expiresAt || capture.state === 'needs_review')) {
318
+ const active = getActiveFilePath() === capture.path
319
+ && readActiveEditorText() === params.expectedContent
320
+ && (!deps.getProjectId || deps.getProjectId() === params.runProjectId);
321
+ const snapshot = active ? readNativeSnapshot(capture.path, capture.nativeDocId) : null;
322
+ const merged = snapshot?.ready && snapshot.acceptByIdSupported
323
+ ? mergedInsertionScope(capture, snapshot.refs, params.expectedContent) : null;
324
+ if (merged) return { ok: true, trackedChanges: [merged.ref], capture: {
325
+ ...capture, refs: [merged.ref], state: 'observed', reason: 'observed',
326
+ diagnostics: { ...capture.diagnostics, capturedCount: 1,
327
+ sourceReason: 'native_merged_insertion_recovered' }
328
+ } };
329
+ return { ok: false, trackedChanges: [], capture: { ...capture,
330
+ state: 'needs_review', reason: 'capture_merged_scope_unavailable' } };
331
+ }
332
+ return observe(capture, params.expectedContent, 1200);
337
333
  }
338
- return { collectTrackedChangeNodes, trackedChangeRefFromNode, collectTrackedChangeRefsForPaths,
334
+ return { collectTrackedChangeNodes, trackedChangeRefFromNode, collectTrackedChangeRefsForPaths, isTrackedChangeNodeInNativeScope, rememberTrackedChangeNodeContext,
339
335
  waitForTrackedChangeDiff, prepareTrackedChangeCapture, prepareTrackedChangeReview, prepareUntrackedUndo, getTrackedChangeCaptureStatus, captureTrackedWrite, reconcileTrackedChangeCapture };
340
336
  }
341
337
  return { create };
@@ -0,0 +1,216 @@
1
+ (function (root, factory) {
2
+ const api = factory();
3
+ if (typeof module === 'object' && module.exports) module.exports = api;
4
+ if (root) root.CodexOverleafTrackedChangeOwnership = api;
5
+ })(typeof window !== 'undefined' ? window : globalThis, function () {
6
+ 'use strict';
7
+
8
+ function create({ fingerprint, readActiveEditorText, mergedPrefix, nativeKey, ledgerKeys }) {
9
+ function parseNativeRef(ref) {
10
+ try {
11
+ if (!ref?.key?.startsWith('native:') || ref.key.length > 1024) return null;
12
+ const tuple = JSON.parse(ref.key.slice(7));
13
+ if (!Array.isArray(tuple) || tuple.length !== 5 || tuple[0] !== ref.id
14
+ || typeof tuple[0] !== 'string' || !tuple[0] || tuple[0].length > 256
15
+ || !['insert', 'delete'].includes(tuple[1])
16
+ || !Number.isSafeInteger(tuple[2]) || !Number.isSafeInteger(tuple[3])
17
+ || tuple[2] < 0 || tuple[3] < tuple[2]
18
+ || (tuple[1] === 'delete' && tuple[2] !== tuple[3])
19
+ || (tuple[1] === 'insert' && tuple[2] === tuple[3])
20
+ || typeof tuple[4] !== 'string' || !/^\d+:[0-9a-f]+:[0-9a-f]+$/.test(tuple[4])) return null;
21
+ return tuple;
22
+ } catch (_error) { return null; }
23
+ }
24
+
25
+ // An existing ID can grow when a later insertion touches an older change.
26
+ // Prove the entire ledger as old fragments + this run's inserted slices.
27
+ // Never assign ownership of the whole merged ID.
28
+ function mergedInsertionScope(capture, after, postContent) {
29
+ if (capture?.source !== 'native' || !capture.nativeDocId || !capture.runProjectId
30
+ || typeof postContent !== 'string' || fingerprint(postContent) !== capture.expected
31
+ || !Array.isArray(capture.before) || !capture.before.length || capture.before.length > 128
32
+ || !Array.isArray(after) || !after.length || after.length > 128
33
+ || !Array.isArray(capture.ranges) || !capture.ranges.length || capture.ranges.length > 64) return null;
34
+ const ranges = capture.ranges;
35
+ let delta = 0, previousFrom = -1;
36
+ for (const range of ranges) {
37
+ if (!Number.isSafeInteger(range.from) || range.from <= previousFrom || range.to !== range.from
38
+ || range.removedLength !== 0 || !Number.isSafeInteger(range.start) || !Number.isSafeInteger(range.end)
39
+ || range.start !== range.from + delta || range.end <= range.start || range.end > postContent.length) return null;
40
+ delta += range.end - range.start;
41
+ previousFrom = range.from;
42
+ }
43
+ let preContent = postContent;
44
+ for (const range of ranges.slice().reverse()) {
45
+ preContent = preContent.slice(0, range.start) + preContent.slice(range.end);
46
+ }
47
+ const before = capture.before.map(parseNativeRef);
48
+ if (before.some(tuple => !tuple)) return null;
49
+ const beforeKeys = before.map(nativeKey).sort();
50
+ if (new Set(beforeKeys).size !== beforeKeys.length) return null;
51
+ const preservedKeys = [];
52
+ for (const tuple of before) {
53
+ const [id, kind, from, to, hash] = tuple;
54
+ if (to > preContent.length
55
+ || (kind === 'insert' && fingerprint(preContent.slice(from, to)) !== hash)) return null;
56
+ // Interior edits and deletion-boundary ambiguity need a different proof.
57
+ if (ranges.some(range => kind === 'insert'
58
+ ? range.from > from && range.from < to : range.from === from)) return null;
59
+ const startShift = ranges.filter(range => range.from <= from)
60
+ .reduce((sum, range) => sum + range.end - range.start, 0);
61
+ const endShift = kind === 'delete' ? startShift : ranges.filter(range => range.from < to)
62
+ .reduce((sum, range) => sum + range.end - range.start, 0);
63
+ preservedKeys.push(nativeKey([id, kind, from + startShift, to + endShift, hash]));
64
+ }
65
+ preservedKeys.sort();
66
+ const oldIds = new Set(before.map(tuple => tuple[0]));
67
+ const mergedIds = new Set(), residue = [], claims = ranges.map(() => []);
68
+ for (const ref of after) {
69
+ const tuple = parseNativeRef(ref);
70
+ if (!tuple || ref.path !== capture.path) return null;
71
+ const [id, kind, from, to, hash] = tuple;
72
+ if (kind === 'delete') { residue.push(nativeKey(tuple)); continue; }
73
+ if (to > postContent.length || fingerprint(postContent.slice(from, to)) !== hash) return null;
74
+ let pieces = [[from, to]];
75
+ ranges.forEach((range, index) => {
76
+ const start = Math.max(from, range.start), end = Math.min(to, range.end);
77
+ if (start >= end) return;
78
+ claims[index].push([start, end]);
79
+ if (oldIds.has(id)) mergedIds.add(id);
80
+ pieces = pieces.flatMap(([left, right]) => {
81
+ if (range.end <= left || range.start >= right) return [[left, right]];
82
+ const remaining = [];
83
+ if (left < range.start) remaining.push([left, range.start]);
84
+ if (range.end < right) remaining.push([range.end, right]);
85
+ return remaining;
86
+ });
87
+ });
88
+ for (const [left, right] of pieces) {
89
+ residue.push(nativeKey([id, kind, left, right, fingerprint(postContent.slice(left, right))]));
90
+ }
91
+ }
92
+ if (!mergedIds.size || JSON.stringify(residue.sort()) !== JSON.stringify(preservedKeys)) return null;
93
+ for (let index = 0; index < ranges.length; index++) {
94
+ let cursor = ranges[index].start;
95
+ for (const [start, end] of claims[index].sort((a, b) => a[0] - b[0])) {
96
+ if (start !== cursor) return null;
97
+ cursor = end;
98
+ }
99
+ if (cursor !== ranges[index].end) return null;
100
+ }
101
+ const proof = [1, capture.runProjectId, capture.nativeDocId, fingerprint(preContent),
102
+ capture.expected, beforeKeys, ranges.map(range => [range.from, range.start, range.end]),
103
+ fingerprint(JSON.stringify(ledgerKeys(after)))];
104
+ const key = mergedPrefix + JSON.stringify(proof);
105
+ if (key.length > 32768) return null;
106
+ return {
107
+ ref: { key, id: [...mergedIds].sort()[0], path: capture.path,
108
+ label: 'This run: insertion merged with an earlier tracked change' },
109
+ runProjectId: capture.runProjectId, beforeKeys, preservedKeys, ranges, preContent, postContent
110
+ };
111
+ }
112
+
113
+ function prepareMergedInsertionReview(path, targets, snapshot) {
114
+ const blocked = reason => ({ ...snapshot, ok: false, reason });
115
+ if (targets.length !== 1 || !snapshot.acceptByIdSupported) return blocked('native_merged_review_unsupported');
116
+ const target = targets[0];
117
+ try {
118
+ if (target.key.length > 32768) return blocked('native_merged_review_invalid');
119
+ const proof = JSON.parse(target.key.slice(mergedPrefix.length));
120
+ if (!Array.isArray(proof) || proof.length !== 8 || proof[0] !== 1
121
+ || proof[2] !== snapshot.nativeDocId || !Array.isArray(proof[5]) || proof[5].length > 128
122
+ || !Array.isArray(proof[6]) || proof[6].length > 64) return blocked('native_merged_review_invalid');
123
+ const before = proof[5].map(key => {
124
+ const tuple = JSON.parse(key.slice(7));
125
+ return { key, id: tuple[0], path };
126
+ });
127
+ const ranges = proof[6].map(([from, start, end]) => ({
128
+ from, to: from, start, end, removedLength: 0
129
+ }));
130
+ const merged = mergedInsertionScope({ source: 'native', path, runProjectId: proof[1],
131
+ nativeDocId: proof[2], expected: proof[4], before, ranges }, snapshot.refs, readActiveEditorText());
132
+ if (!merged || merged.ref.key !== target.key || merged.ref.id !== target.id)
133
+ return blocked('native_merged_review_scope_changed');
134
+ return { ...snapshot, ok: true, targets, ids: [], unrelated: snapshot.refs, merged };
135
+ } catch (_error) { return blocked('native_merged_review_invalid'); }
136
+ }
137
+
138
+ function nativeOwned(ref, capture) {
139
+ if (ref.source !== 'native' || !Number.isSafeInteger(ref.from) || !Number.isSafeInteger(ref.to)) return false;
140
+ if (ref.kind === 'delete') return capture.ranges.some(range => ref.from >= range.start && ref.from <= range.end
141
+ && ref.textLength === range.removedLength && ref.textHash === range.removedHash && range.removedLength > 0);
142
+ let covered = ref.from;
143
+ for (const range of capture.ranges) {
144
+ if (range.end < covered) continue;
145
+ if (range.start > covered) break;
146
+ covered = Math.max(covered, range.end);
147
+ if (covered >= ref.to) return ref.to > ref.from;
148
+ }
149
+ return false;
150
+ }
151
+
152
+ function rangesFor(operation, beforeContent, postContent) {
153
+ const patches = Array.isArray(operation.patches) && operation.patches.length
154
+ ? operation.patches
155
+ : [{ from: 0, to: beforeContent.length, insert: postContent }];
156
+ let delta = 0;
157
+ return patches.map(patch => {
158
+ const range = { from: patch.from, to: patch.to,
159
+ start: patch.from + delta, end: patch.from + delta + String(patch.insert ?? '').length,
160
+ removedLength: patch.to - patch.from, removedHash: fingerprint(beforeContent.slice(patch.from, patch.to)) };
161
+ delta += String(patch.insert ?? '').length - (patch.to - patch.from);
162
+ return range;
163
+ });
164
+ }
165
+
166
+ function shiftedBaseline(before, ranges) {
167
+ let overlap = false;
168
+ const refs = before.map(ref => {
169
+ const match = /^pos:(\d+):/.exec(ref.key);
170
+ if (!match) return ref;
171
+ const pos = Number(match[1]);
172
+ let delta = 0;
173
+ for (const range of ranges) {
174
+ if (pos >= range.from && pos < range.to) overlap = true;
175
+ if (pos >= range.to) delta += (range.end - range.start) - (range.to - range.from);
176
+ }
177
+ return { ...ref, key: ref.key.replace(/^pos:\d+:/, 'pos:' + (pos + delta) + ':') };
178
+ });
179
+ return { refs, overlap };
180
+ }
181
+
182
+ function scopeCovered(refs, capture) {
183
+ if (refs.length === 1 && refs[0].key?.startsWith(mergedPrefix)) return true;
184
+ if (capture.source === 'native') return capture.ranges.every(range => refs.some(ref =>
185
+ ref.from <= range.end && ref.to >= range.start));
186
+ const positioned = refs.filter(ref => /^pos:\d+:/.test(ref.key));
187
+ if (refs.some(ref => ref.id)) return true;
188
+ return capture.ranges.every(range => positioned.some(ref => {
189
+ const pos = Number(/^pos:(\d+):/.exec(ref.key)[1]);
190
+ return pos >= range.start && pos <= range.end;
191
+ }));
192
+ }
193
+
194
+ const reviewNodeOwners = new WeakMap();
195
+ function reviewNodeMatches(node, path, snapshot, id = '') {
196
+ if (!node || snapshot?.ready !== true || !snapshot.nativeDocId) return false;
197
+ const explicitPath = node.getAttribute?.('data-path') || node.getAttribute?.('data-file-path') || node.getAttribute?.('data-doc-path');
198
+ if (explicitPath && explicitPath !== path) return false;
199
+ const rawPosition = node.getAttribute?.('data-pos'), from = Number(rawPosition);
200
+ const parts = Array.from(node.querySelectorAll?.('.review-panel-expandable-content') || []);
201
+ if (parts.length !== 1 || (!id && (rawPosition == null || rawPosition === '' || !Number.isSafeInteger(from) || from < 0))) return false;
202
+ const kind = /(?:delete|change-d)(?:\s|$)/.test(node.className || '') ? 'delete' : 'insert';
203
+ const textHash = fingerprint(parts[0].textContent || '');
204
+ if (!snapshot.refs.some(ref => (id ? ref.id === id : ref.from === from) && ref.kind === kind && ref.textHash === textHash)) return false;
205
+ const signature = JSON.stringify([id, from, kind, textHash]);
206
+ const prior = reviewNodeOwners.get(node);
207
+ if (prior && prior.docId !== snapshot.nativeDocId && prior.signature === signature) return false;
208
+ reviewNodeOwners.set(node, { docId: snapshot.nativeDocId, signature });
209
+ return true;
210
+ }
211
+
212
+ return { mergedInsertionScope, prepareMergedInsertionReview, nativeOwned, rangesFor, shiftedBaseline, scopeCovered, reviewNodeMatches };
213
+ }
214
+
215
+ return { create };
216
+ });
@@ -0,0 +1,184 @@
1
+ (function (root, factory) {
2
+ const api = factory();
3
+ if (typeof module === 'object' && module.exports) module.exports = api;
4
+ if (root) root.CodexOverleafTrackedChangeReplay = api;
5
+ })(typeof window !== 'undefined' ? window : globalThis, function () {
6
+ 'use strict';
7
+
8
+ function create({ normalizeSafeProjectPath, applyTextPatches }) {
9
+ // Builds the minimal replay operations for Accept All. The replay must write
10
+ // only the changed fragments, never a whole-file replaceAll.
11
+ //
12
+ // Preferred source: the run's own original forward writeback operations
13
+ // (carrying their `patches`). After the editor-undo the document is back at
14
+ // the pre-write content, so those patches' `expected` slices match and
15
+ // re-apply cleanly.
16
+ //
17
+ // Fallback: when a path has no usable original patch operation, compute a
18
+ // minimal pre->post diff (trim the common prefix/suffix to a single targeted
19
+ // {from,to,insert} patch).
20
+ function buildAcceptReplayOperations(paths, expectedByPath, postByPath, appliedOperations) {
21
+ const patchesByPath = collectAppliedEditPatchesByPath(appliedOperations);
22
+ const operations = [];
23
+ for (const path of paths) {
24
+ const preContent = expectedByPath.get(path);
25
+ const postContent = postByPath.get(path);
26
+ if (typeof preContent !== 'string' || typeof postContent !== 'string') {
27
+ return {
28
+ ok: false,
29
+ code: 'accept_missing_run_content',
30
+ reason: `${path} 缺少写入前/写入后内容;Codex 没有重放本轮改动。`
31
+ };
32
+ }
33
+
34
+ // Preferred: re-apply the run's original forward patches verbatim.
35
+ const originalPatches = patchesByPath.get(path);
36
+ // Fallback: minimal pre->post diff trimmed to a single targeted patch.
37
+ const useOriginal = originalPatches?.length > 0 && applyTextPatches(preContent, originalPatches).ok === true;
38
+ const patches = useOriginal ? originalPatches : [buildMinimalDiffPatch(preContent, postContent)].filter(Boolean);
39
+ if (!patches.length) {
40
+ // pre === post: nothing to replay for this file.
41
+ continue;
42
+ }
43
+ operations.push({
44
+ type: 'edit',
45
+ path,
46
+ patches,
47
+ reason: 'Accept tracked edit (replay untracked)'
48
+ });
49
+ }
50
+ return { ok: true, operations };
51
+ }
52
+
53
+ // Collects the per-path `patches` arrays from the run's applied edit
54
+ // operations. Only edit operations that actually carried `patches` are
55
+ // usable; whole-file replaceAll / verifiedContent operations are skipped so
56
+ // the replay never falls back to a whole-file write.
57
+ function collectAppliedEditPatchesByPath(appliedOperations) {
58
+ const patchesByPath = new Map();
59
+ for (const rawOperation of Array.isArray(appliedOperations) ? appliedOperations : []) {
60
+ if (!rawOperation || rawOperation.type !== 'edit') {
61
+ continue;
62
+ }
63
+ const path = typeof rawOperation.path === 'string'
64
+ ? normalizeSafeProjectPath(rawOperation.path)
65
+ : '';
66
+ if (!path || !Array.isArray(rawOperation.patches) || !rawOperation.patches.length) {
67
+ continue;
68
+ }
69
+ const normalized = rawOperation.patches.map(patch => ({
70
+ from: Number(patch?.from),
71
+ to: Number(patch?.to),
72
+ expected: String(patch?.expected ?? ''),
73
+ insert: String(patch?.insert ?? '')
74
+ }));
75
+ const existing = patchesByPath.get(path) || [];
76
+ patchesByPath.set(path, existing.concat(normalized));
77
+ }
78
+ return patchesByPath;
79
+ }
80
+
81
+ // Computes a single targeted {from,to,insert} patch describing the pre->post
82
+ // change by trimming the common prefix and suffix. Returns null when the two
83
+ // strings are identical.
84
+ function buildMinimalDiffPatch(preContent, postContent) {
85
+ if (preContent === postContent) {
86
+ return null;
87
+ }
88
+ const preLen = preContent.length;
89
+ const postLen = postContent.length;
90
+ let prefix = 0;
91
+ const maxPrefix = Math.min(preLen, postLen);
92
+ while (prefix < maxPrefix && preContent[prefix] === postContent[prefix]) {
93
+ prefix += 1;
94
+ }
95
+ let suffix = 0;
96
+ const maxSuffix = Math.min(preLen, postLen) - prefix;
97
+ while (
98
+ suffix < maxSuffix
99
+ && preContent[preLen - 1 - suffix] === postContent[postLen - 1 - suffix]
100
+ ) {
101
+ suffix += 1;
102
+ }
103
+ const from = prefix;
104
+ const to = preLen - suffix;
105
+ return {
106
+ from,
107
+ to,
108
+ expected: preContent.slice(from, to),
109
+ insert: postContent.slice(from, postLen - suffix)
110
+ };
111
+ }
112
+
113
+ function rebaseCheckpointPair(actualContent, expectedContent, postContent) {
114
+ const actual = String(actualContent ?? '');
115
+ const expected = String(expectedContent ?? '');
116
+ const post = String(postContent ?? '');
117
+ if (actual === post) {
118
+ return {
119
+ ok: true,
120
+ expectedContent: expected,
121
+ postContent: post,
122
+ prefixLength: 0,
123
+ suffixLength: 0
124
+ };
125
+ }
126
+ if (!post) {
127
+ return { ok: false };
128
+ }
129
+ const matchIndex = actual.indexOf(post);
130
+ if (matchIndex < 0 || actual.indexOf(post, matchIndex + 1) >= 0) {
131
+ return { ok: false };
132
+ }
133
+ const prefix = actual.slice(0, matchIndex);
134
+ const suffix = actual.slice(matchIndex + post.length);
135
+ return {
136
+ ok: true,
137
+ expectedContent: prefix + expected + suffix,
138
+ postContent: actual,
139
+ prefixLength: prefix.length,
140
+ suffixLength: suffix.length
141
+ };
142
+ }
143
+
144
+ function prepareSnapshotUndoCheckpoints(expectedFiles, postFiles) {
145
+ const contentByPath = files => new Map((files || [])
146
+ .filter(file => file?.path && typeof file.content === 'string')
147
+ .map(file => [normalizeSafeProjectPath(file.path), file.content])
148
+ .filter(([path]) => path));
149
+ const expectedByPath = contentByPath(expectedFiles);
150
+ const postByPath = contentByPath(postFiles);
151
+ return { expectedByPath, postByPath,
152
+ paths: Array.from(expectedByPath.keys()).filter(path => postByPath.has(path)) };
153
+ }
154
+
155
+ // Convert edit receipts back to the review checkpoint contract. Native
156
+ // identity checks and editor mutations remain owned by the lifecycle.
157
+ function buildSnapshotUndoResult(result, expectedByPath, postByPath, undoRebaseProofs) {
158
+ const toTrackedResult = item => ({
159
+ trackedChange: {
160
+ key: `snapshot-undo:${item.operation?.path || ''}`,
161
+ id: '',
162
+ path: item.operation?.path || '',
163
+ label: 'No-trace snapshot undo'
164
+ },
165
+ result: item.result?.ok !== false && item.result?.verified === true
166
+ && undoRebaseProofs.has(item.operation?.path)
167
+ && item.result.verifiedContent === expectedByPath.get(item.operation?.path)
168
+ ? { ...item.result, undoRebaseProof: undoRebaseProofs.get(item.operation.path) }
169
+ : item.result
170
+ });
171
+ return {
172
+ attempted: true,
173
+ applied: (result.applied || []).map(toTrackedResult),
174
+ skipped: (result.skipped || []).map(toTrackedResult),
175
+ rebasedExpectedFiles: Array.from(expectedByPath, ([path, content]) => ({ path, content })),
176
+ rebasedPostFiles: Array.from(postByPath, ([path, content]) => ({ path, content }))
177
+ };
178
+ }
179
+
180
+ return { buildAcceptReplayOperations, rebaseCheckpointPair, prepareSnapshotUndoCheckpoints, buildSnapshotUndoResult };
181
+ }
182
+
183
+ return { create };
184
+ });