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
@@ -0,0 +1,574 @@
1
+ (function (root, factory) {
2
+ const api = factory();
3
+ if (typeof module === 'object' && module.exports) module.exports = api;
4
+ if (root) root.CodexOverleafRunReviewController = api;
5
+ })(typeof window !== 'undefined' ? window : globalThis, function () {
6
+ 'use strict';
7
+ function create(deps = {}) {
8
+ const {
9
+ Modules, WritebackSettlement, trackedChangeInFlight, findRunRecord,
10
+ getRunUndoCount, isTrackedChangeLifecycleRun, getPendingMirrorRefresh, hasTrackedEditorUndo,
11
+ buildNoTraceUndoRestore, findUnsafeFullFileUndoOperation, showUndoFileSelection, showPluginConfirm,
12
+ tr, truncateRunTitle, formatOperationFiles, formatTrackedChangeFiles,
13
+ formatTrackedUndoFiles, getPageBridgeTimeoutMs, callPageBridge, setRunUndoStatus,
14
+ appendRunRecordEvent, getRunProjectIdForWriteback, isUndoResultEffectivelyApplied, writebackOrchestrator,
15
+ appendUndoReviewingPolicyEvent, formatOperationType, formatApplyResultReason, buildTrackedUndoPostFiles,
16
+ getTrackedChangeCaptureController, buildContentFailure, applyTrackedChangeSettlement, refreshRunCardControls,
17
+ formatBridgeResultReason, advanceRunUndoProgress, saveStateSoon, flushQueuedSaveState,
18
+ getState, getCurrentProjectId, getAccountScopeId, getRouteGeneration, notify, tx,
19
+ } = deps;
20
+ const reviewOwners = new Map();
21
+ function reviewEventFailure(run, result) {
22
+ const reasons = deps.FailureReasons || Modules.FailureReasons;
23
+ if (!reasons?.normalizeFailureReason) return undefined;
24
+ const primary = reasons.selectPrimaryWritebackFailure(WritebackSettlement.collectFailuresFromResult(result, reasons));
25
+ if (!primary) return undefined;
26
+ const paths = new Set(['appliedOperations', 'undoOperations', 'undoBaseFiles', 'undoExpectedFiles', 'undoTrackedChanges']
27
+ .flatMap(key => (Array.isArray(run?.[key]) ? run[key] : []).map(item => item?.path)));
28
+ const candidate = typeof primary.file === 'string' ? primary.file : '';
29
+ const file = paths.has(candidate) && candidate.length <= 300 && !/[\r\n]/.test(candidate)
30
+ && !candidate.replace(/\\/g, '/').startsWith('/') && !/^[A-Za-z]:/.test(candidate) && !candidate.replace(/\\/g, '/').split('/').includes('..') ? candidate : '';
31
+ const code = Object.hasOwn(reasons.FAILURE_CODE_CATALOG, primary.code) ? primary.code : 'unknown_legacy_failure';
32
+ let displayCode = code;
33
+ reasons.formatFailureReasonForDisplay({ ...primary, userMessage: String(primary.userMessage || '').slice(0, 2000) }, undefined, key => {
34
+ const value = tr(key), match = /^failureReason_([a-z0-9_]+)_user$/.exec(key);
35
+ if (value && value !== key) { if (match) displayCode = match[1]; return value; }
36
+ });
37
+ // This event keeps only machine facts and owned UI copy, never the Page's
38
+ // arbitrary reason, technical message or evidence payload.
39
+ const safe = reasons.normalizeFailureReason({ code }, file ? { path: file } : undefined);
40
+ if (displayCode !== code) safe.evidence = { originalCode: displayCode };
41
+ const localized = reasons.localizeFailureReason(safe, undefined, key => { const value = tr(key, file ? undefined : { file: tr('unknownFile'), activeFile: tr('unknownFile') }); return value && value !== key ? value : undefined; });
42
+ safe.userMessage = localized.userMessage;
43
+ safe.nextAction = localized.nextAction || safe.nextAction;
44
+ if (displayCode === 'unknown_legacy_failure') {
45
+ safe.userMessage = tr('unknownReason'); safe.nextAction = tr('failureReason_review_detail_next');
46
+ }
47
+ return safe;
48
+ }
49
+ let undoRecoveryTimer = null, undoRecoveryView = null, undoRecoveryGeneration = 0;
50
+ const undoRecoveryFailures = new Map();
51
+ async function prepareUndoDispatch(runId) {
52
+ const owner = reviewOwners.get(runId);
53
+ if (owner && !owner.deadlineAt) await owner.markDispatched();
54
+ owner?.();
55
+ return Math.min(Date.now() + getPageBridgeTimeoutMs('rejectTrackedChanges'), owner?.deadlineAt || Infinity);
56
+ }
57
+ async function persistUndoOwnerMarker(runId) {
58
+ if (Modules.StorageDb?.sharedSessionsEnabled?.() !== true) return;
59
+ findRunRecord(runId).undoOwnerProtocol = 1;
60
+ try { await flushQueuedSaveState({ requireDurable: true, reviewRunIds: [runId] }); }
61
+ catch (cause) { throw Object.assign(new Error('The Undo owner marker could not be durably saved.'), { code: 'review_state_not_persisted', cause }); }
62
+ reviewOwners.get(runId)?.();
63
+ const saved = await Modules.StorageDb.getRecord('sessions', getState().activeSessionId);
64
+ if (saved?.runs?.find(run => run.id === runId)?.undoOwnerProtocol !== 1)
65
+ throw Object.assign(new Error('The Undo owner marker was not durably retained.'), { code: 'review_state_not_persisted' });
66
+ reviewOwners.get(runId)?.();
67
+ }
68
+ async function withSharedReviewOwnership(runId, work) {
69
+ const db = Modules.StorageDb;
70
+ if (db?.sharedSessionsEnabled?.() !== true) return work();
71
+ const run = findRunRecord(runId);
72
+ if (!run || trackedChangeInFlight.has(runId)) return;
73
+ const assertCurrent = undoOwner(run);
74
+ const sessionId = getState().activeSessionId;
75
+ return db.withSharedReviewLock({ projectId: getRunProjectIdForWriteback(run), accountScopeId: getAccountScopeId(), runId,
76
+ onLost: token => { void callPageBridge('cancelActiveWrite', { reviewOwnerToken: token }).catch(() => {}); } }, async assertOwner => {
77
+ reviewOwners.set(runId, assertOwner);
78
+ try {
79
+ assertCurrent();
80
+ const session = await db.getRecord('sessions', sessionId);
81
+ assertCurrent();
82
+ const latest = session?.runs?.find(record => record.id === runId);
83
+ if (!latest || session.projectId !== getRunProjectIdForWriteback(run) || session.accountScopeId !== getAccountScopeId())
84
+ throw Object.assign(new Error('The shared Undo run is no longer available in its original scope.'), { code: 'review_context_changed' });
85
+ const restored = Modules.SessionState.normalizeRuns([latest], { recoverSettledRuns: true })[0];
86
+ // A budget-omitted first checkpoint may still be complete in its original page.
87
+ // Shared partial/terminal progress always wins over that in-memory copy.
88
+ const keepCheckpoint = restored.recoveryRetention?.state === 'omitted' && restored.recoveryRetention.coreRetained !== true
89
+ && !restored.undoStatus && !restored.trackedChangeStatus && !run.undoStatus && !run.trackedChangeStatus
90
+ && restored.runProjectId === run.runProjectId && restored.nativeEventSeq === run.nativeEventSeq
91
+ && restored.codexThreadId === run.codexThreadId && restored.codexTurnId === run.codexTurnId
92
+ && restored.startedAt === run.startedAt && JSON.stringify(restored.executionSnapshot) === JSON.stringify(run.executionSnapshot);
93
+ const checkpoint = keepCheckpoint ? Object.fromEntries(['appliedOperations', 'undoOperations', 'undoBaseFiles', 'undoTrackedChanges', 'undoExpectedFiles', 'trackedChangeCaptures']
94
+ .filter(key => Object.hasOwn(run, key)).map(key => [key, run[key]])) : {};
95
+ for (const key of Object.keys(run)) delete run[key];
96
+ Object.assign(run, restored, checkpoint);
97
+ if (run.undoStatus === 'applied' || ['accepted', 'rejected'].includes(run.trackedChangeStatus)) return;
98
+ if (run.undoStatus === 'running' && run.undoOwnerProtocol !== 1) run.undoRecoveryCheckRequired = true;
99
+ return await work();
100
+ } finally { reviewOwners.delete(runId); refreshRunCardControls(runId); }
101
+ }).catch(error => {
102
+ if (error.code === 'review_busy') notify?.(tx('Another page is reviewing this run. Wait for it to finish.', '另一页面正在审阅本轮记录,请等待其完成。'));
103
+ throw error;
104
+ });
105
+ }
106
+ async function recoverInterruptedUndoStatuses(options = {}) {
107
+ if (undoRecoveryTimer) { clearTimeout(undoRecoveryTimer); undoRecoveryTimer = null; }
108
+ const generation = ++undoRecoveryGeneration;
109
+ const captured = getState(), sessionId = captured.activeSessionId;
110
+ const scope = JSON.stringify([getCurrentProjectId?.(), getAccountScopeId?.(), getRouteGeneration?.()]);
111
+ const sameScope = () => JSON.stringify([getCurrentProjectId?.(), getAccountScopeId?.(), getRouteGeneration?.()]) === scope;
112
+ const current = () => generation === undoRecoveryGeneration && sameScope()
113
+ && getState() === captured && captured.activeSessionId === sessionId;
114
+ const schedule = delay => {
115
+ if (generation !== undoRecoveryGeneration || !sameScope()) return;
116
+ if (undoRecoveryTimer) clearTimeout(undoRecoveryTimer);
117
+ undoRecoveryTimer = setTimeout(() => {
118
+ if (generation === undoRecoveryGeneration && sameScope())
119
+ void recoverInterruptedUndoStatuses({ automatic: true }).catch(() => {});
120
+ }, delay);
121
+ undoRecoveryTimer.unref?.();
122
+ };
123
+ if (undoRecoveryView?.state !== captured || undoRecoveryView?.scope !== scope || undoRecoveryView?.sessionId !== sessionId) {
124
+ undoRecoveryFailures.clear(); undoRecoveryView = { state: captured, scope, sessionId };
125
+ }
126
+ if (options.automatic !== true) undoRecoveryFailures.clear();
127
+ let nextCheck = Infinity;
128
+ const db = Modules.StorageDb;
129
+ const runs = Array.from(new Set([...(captured.runs || []), ...(captured.sessions || []).flatMap(session => session.runs || [])]));
130
+ for (const run of runs) {
131
+ if (run.undoStatus !== 'running' || (undoRecoveryFailures.get(run.id) || 0) >= 3) continue;
132
+ if (db?.sharedSessionsEnabled?.() === true) {
133
+ let owner;
134
+ try {
135
+ owner = await db.hasSharedReviewOwner({ projectId: getRunProjectIdForWriteback(run), accountScopeId: getAccountScopeId(), runId: run.id });
136
+ if (!owner || typeof owner.busy !== 'boolean') throw new Error('Undo recovery ownership is unavailable.');
137
+ } catch (_error) {
138
+ if (!current()) { schedule(50); return; }
139
+ delete run.undoRecoveryCheckRequired; run.undoRecoveryUnavailable = true; refreshRunCardControls(run.id);
140
+ const attempts = (undoRecoveryFailures.get(run.id) || 0) + 1; undoRecoveryFailures.set(run.id, attempts);
141
+ if (attempts === 1) notify?.(tx('Undo recovery checks are temporarily unavailable. Other tasks remain available; keep the recovery files and retry after the connection recovers.',
142
+ '撤销恢复检查暂不可用,其他任务仍可继续。请保留恢复材料,连接恢复后再检查。'));
143
+ if (attempts < 3) nextCheck = Math.min(nextCheck, 5000 * attempts);
144
+ continue;
145
+ }
146
+ if (!current()) { schedule(50); return; }
147
+ undoRecoveryFailures.delete(run.id); delete run.undoRecoveryUnavailable;
148
+ if (!owner.busy && run.undoOwnerProtocol !== 1) {
149
+ run.undoRecoveryCheckRequired = true; refreshRunCardControls(run.id); continue;
150
+ }
151
+ if (owner.busy) { nextCheck = Math.min(nextCheck, owner.deadlineAt > Date.now() ? owner.deadlineAt - Date.now() + 50 : 5000); continue; }
152
+ }
153
+ // Recovery only restores an explicit action; Page work is never replayed.
154
+ delete run.undoRecoveryCheckRequired; run.undoStatus = 'partial'; refreshRunCardControls(run.id);
155
+ }
156
+ if (nextCheck !== Infinity) schedule(Math.min(30000, Math.max(50, nextCheck)));
157
+ }
158
+ async function withLocalUndoLock(runId, work) {
159
+ const run = findRunRecord(runId);
160
+ if (!run || run.forkSnapshot || run.undoStatus === 'applied' || !getRunUndoCount(run) || trackedChangeInFlight.has(runId)) return;
161
+ const assertOwner = undoOwner(run);
162
+ trackedChangeInFlight.set(runId, 'reject'); refreshRunCardControls(runId);
163
+ try { return await work(); }
164
+ catch (error) {
165
+ let current = true; try { assertOwner(); } catch (_stale) { current = false; }
166
+ if (current && findRunRecord(runId) === run) {
167
+ if (run.undoStatus === 'running') setRunUndoStatus(runId, 'partial');
168
+ appendRunRecordEvent(runId, { title: tr('undoNoTraceTitle'), status: 'failed',
169
+ detail: { [tr('detailReason')]: error.message } });
170
+ }
171
+ notify?.(error.code === 'review_state_not_persisted' ? tx('Undo recovery ownership could not be saved. No Undo was dispatched; keep this page open and inspect the files before retrying.',
172
+ '撤销恢复归属未能保存,尚未派发撤销。请保留本页并核对文件后重试。') : error.message);
173
+ throw error;
174
+ } finally { trackedChangeInFlight.delete(runId); refreshRunCardControls(runId); }
175
+ }
176
+ const withUndoLock = (runId, work) => withSharedReviewOwnership(runId, () => withLocalUndoLock(runId, work));
177
+ const undoRun = runId => withUndoLock(runId, () => executeUndo(runId));
178
+ const acceptRun = runId => withSharedReviewOwnership(runId, () => executeAcceptRun(runId));
179
+ const undoRunTrackedChanges = (runId, run) => withUndoLock(runId, () => executeTrackedUndo(runId, run));
180
+
181
+ function undoOwner(run) {
182
+ const captured = getState(), sessionId = captured.activeSessionId;
183
+ const scope = [getCurrentProjectId?.(), getAccountScopeId?.(), getRouteGeneration?.()];
184
+ return () => {
185
+ reviewOwners.get(run.id)?.();
186
+ if (getState() !== captured || captured.activeSessionId !== sessionId || findRunRecord(run.id) !== run
187
+ || JSON.stringify(scope) !== JSON.stringify([getCurrentProjectId?.(), getAccountScopeId?.(), getRouteGeneration?.()]))
188
+ throw Object.assign(new Error('The Undo project, account or session changed.'), { code: 'review_context_changed' });
189
+ };
190
+ }
191
+
192
+ function undoConfirmationTask(run) {
193
+ const task = truncateRunTitle(run.task);
194
+ return run.undoStatus === 'running' && run.undoOwnerProtocol !== 1
195
+ ? task + '\n\n' + tx('Before confirming Undo, close or reload every older project page and inspect the current files in Overleaf. Continue only after those checks are complete.',
196
+ '确认撤销前,请先关闭或重载全部旧版项目页面,并在 Overleaf 核对当前文件。完成这些检查后再继续。')
197
+ : task;
198
+ }
199
+
200
+ async function executeUndo(runId) {
201
+ const run = findRunRecord(runId);
202
+ if (run) Object.assign(run, Modules.UndoOperations.prepareRunUndo(run));
203
+ const assertCurrent = undoOwner(run);
204
+ if (!getRunUndoCount(run) || run.undoStatus === 'applied') {
205
+ return;
206
+ }
207
+ // Wait out any background mirror refresh before undoing (v1.7.5): a
208
+ // mirror.sync finishing after the undo would push the pre-undo snapshot
209
+ // as the local baseline and resurrect the undone content next run.
210
+ const pendingMirror = getPendingMirrorRefresh?.();
211
+ if (pendingMirror) {
212
+ await pendingMirror.catch(() => {});
213
+ assertCurrent();
214
+ }
215
+
216
+ if ((Array.isArray(run.undoTrackedChanges) && run.undoTrackedChanges.length) || hasTrackedEditorUndo(run)
217
+ || (run.trackedChangeStatus === 'needs_review' && run.undoOperations?.some(Modules.UndoOperations.isFileUndoOperation))) {
218
+ await executeTrackedUndo(runId, run);
219
+ return;
220
+ }
221
+
222
+ const undoRestore = buildNoTraceUndoRestore(run);
223
+ const undoOperations = undoRestore.operations;
224
+ const unsafeFullFileUndo = findUnsafeFullFileUndoOperation(undoOperations, {
225
+ allowSnapshotRestore: undoRestore.snapshotRestore
226
+ });
227
+ if (unsafeFullFileUndo) {
228
+ appendRunRecordEvent(runId, {
229
+ title: tr('undoUnsafeFullFileTitle'),
230
+ status: 'failed',
231
+ detail: {
232
+ [tr('detailFile')]: unsafeFullFileUndo.path,
233
+ [tr('detailReason')]: tr('undoUnsafeFullFileReason')
234
+ }
235
+ });
236
+ return;
237
+ }
238
+
239
+ // v1.8.0 C3: multi-file undos confirm through a per-file selection —
240
+ // undoing a subset leaves undoStatus 'partial' and the button usable;
241
+ // re-undoing an already-restored file is skipped by the base check.
242
+ const undoPaths = Array.from(new Set(undoOperations.map(operation => operation?.path).filter(Boolean)));
243
+ let selectedOperations = undoOperations;
244
+ if (undoPaths.length > 1 && typeof showUndoFileSelection === 'function') {
245
+ const selectedPaths = await showUndoFileSelection({
246
+ title: tr('undoFileSelectTitle'),
247
+ task: undoConfirmationTask(run),
248
+ confirmLabel: tr('undoFileSelectConfirm'),
249
+ cancelLabel: tr('confirmDefaultCancel'),
250
+ selectAllLabel: tr('undoFileSelectAll'),
251
+ paths: undoPaths
252
+ });
253
+ if (!selectedPaths) {
254
+ return;
255
+ }
256
+ const selectedSet = new Set(selectedPaths);
257
+ selectedOperations = undoOperations.filter(operation => selectedSet.has(operation?.path));
258
+ } else {
259
+ const approved = await showPluginConfirm({
260
+ title: tr('undoNoTraceTitle'),
261
+ message: [
262
+ undoConfirmationTask(run),
263
+ '',
264
+ tr('undoNoTraceMessage', { files: formatOperationFiles(undoOperations) })
265
+ ].join('\n'),
266
+ confirmLabel: tr('undoConfirm'),
267
+ cancelLabel: tr('confirmDefaultCancel'),
268
+ destructive: true
269
+ });
270
+ if (!approved) {
271
+ return;
272
+ }
273
+ }
274
+
275
+ assertCurrent();
276
+ const deadlineAt = await prepareUndoDispatch(runId);
277
+ setRunUndoStatus(runId, 'running');
278
+ appendRunRecordEvent(runId, {
279
+ title: tr('undoNoTraceStarted'),
280
+ status: 'running',
281
+ detail: { [tr('detailWillUndo')]: formatOperationFiles(selectedOperations) }
282
+ });
283
+
284
+ await persistUndoOwnerMarker(runId); assertCurrent();
285
+ const result = await callPageBridge('applyOperations', {
286
+ operations: selectedOperations, deadlineAt, reviewOwnerToken: reviewOwners.get(runId)?.token,
287
+ baseFiles: run.undoBaseFiles || [],
288
+ reviewingPolicy: 'no-trace-undo',
289
+ // Undo remains bound to its original project, including after navigation.
290
+ runProjectId: getRunProjectIdForWriteback(run)
291
+ });
292
+ assertCurrent();
293
+ const undoApplied = isUndoResultEffectivelyApplied(run, result);
294
+ writebackOrchestrator.invalidateMirrorAfterUndo(runId, getRunProjectIdForWriteback(run), result);
295
+ appendUndoReviewingPolicyEvent(runId, result.reviewingPolicy);
296
+ appendRunRecordEvent(runId, {
297
+ title: tr('undoResult', { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
298
+ failure: reviewEventFailure(run, result),
299
+ status: undoApplied ? 'completed' : 'failed',
300
+ detail: {
301
+ [tr('detailUndone')]: (result.applied || []).map(item => ({
302
+ [tr('detailAction')]: formatOperationType(item.operation?.type),
303
+ [tr('detailFile')]: item.operation?.path
304
+ })),
305
+ [tr('detailSkipped')]: (result.skipped || []).map(item => ({
306
+ [tr('detailAction')]: formatOperationType(item.operation?.type),
307
+ [tr('detailFile')]: item.operation?.path,
308
+ [tr('detailReason')]: formatApplyResultReason(item)
309
+ }))
310
+ }
311
+ });
312
+ // A subset undo never closes the ledger: unselected files can still
313
+ // be undone later, so the run stays 'partial' and the button usable.
314
+ const fullSelection = selectedOperations.length === undoOperations.length;
315
+ await applyLegacyUndoSettlement(
316
+ runId,
317
+ undoApplied && fullSelection ? 'applied' : 'partial',
318
+ result
319
+ );
320
+ }
321
+
322
+ async function executeTrackedUndo(runId, run) {
323
+ const assertCurrent = undoOwner(run);
324
+ const fileUndoOperations = Modules.UndoOperations.getFileUndoOperations(run);
325
+ const textRun = Modules.UndoOperations.textUndoRun(run);
326
+ const trackedUndo = textRun.undoTrackedChanges.length > 0;
327
+ const hasTextUndo = trackedUndo || buildTrackedUndoPostFiles(textRun).length > 0;
328
+ const approved = await showPluginConfirm({
329
+ title: !hasTextUndo ? tr('undoNoTraceTitle') : trackedUndo ? tr('undoTrackedTitle') : tr('undoNativeTitle'),
330
+ message: [
331
+ undoConfirmationTask(run),
332
+ '',
333
+ ...(hasTextUndo ? [trackedUndo
334
+ ? tr('undoTrackedMessage', { files: formatTrackedChangeFiles(run.undoTrackedChanges) })
335
+ : tr('undoNativeMessage', { files: formatTrackedUndoFiles(run) })] : []),
336
+ ...(fileUndoOperations.length ? [tr('undoNoTraceMessage', { files: formatOperationFiles(fileUndoOperations) })] : [])
337
+ ].join('\n'),
338
+ confirmLabel: trackedUndo ? tr('undoTrackedConfirm') : tr('undoConfirm'),
339
+ cancelLabel: tr('confirmDefaultCancel'),
340
+ destructive: true
341
+ });
342
+ if (!approved) {
343
+ return;
344
+ }
345
+
346
+ assertCurrent();
347
+ const deadlineAt = await prepareUndoDispatch(runId);
348
+ // Keep the review lifecycle until every pending part has settled.
349
+ // Its local lock stays active while verified recovery progress is persisted.
350
+ const lifecycleReject = (trackedUndo || fileUndoOperations.length > 0) && isTrackedChangeLifecycleRun(run);
351
+ if (lifecycleReject) {
352
+ trackedChangeInFlight.set(runId, 'reject');
353
+ refreshRunCardControls(runId);
354
+ } else {
355
+ setRunUndoStatus(runId, 'running');
356
+ }
357
+ appendRunRecordEvent(runId, {
358
+ title: !hasTextUndo ? tr('undoNoTraceStarted') : trackedUndo ? tr('undoTrackedStarted') : tr('undoNativeStarted'),
359
+ status: 'running',
360
+ detail: { [tr('detailWillUndo')]: !hasTextUndo ? formatOperationFiles(fileUndoOperations)
361
+ : trackedUndo ? formatTrackedChangeFiles(run.undoTrackedChanges) : formatTrackedUndoFiles(run) }
362
+ });
363
+
364
+ let result;
365
+ try {
366
+ await persistUndoOwnerMarker(runId); assertCurrent();
367
+ const trackedUndoPostFilesAtDispatch = buildTrackedUndoPostFiles(textRun);
368
+ result = hasTextUndo ? await callPageBridge('rejectTrackedChanges', {
369
+ trackedChanges: textRun.undoTrackedChanges || [], deadlineAt, reviewOwnerToken: reviewOwners.get(runId)?.token,
370
+ expectedFiles: textRun.undoExpectedFiles || [],
371
+ postFiles: trackedUndoPostFilesAtDispatch,
372
+ untrackedUndo: run.executionSnapshot
373
+ ? run.executionSnapshot.requireReviewing === false && ['submitted', 'legacy-captured'].includes(run.executionSnapshot.source)
374
+ : getTrackedChangeCaptureController().hasLegacyUntrackedCheckpoint(run),
375
+ // The page-side project guard still refuses writes after navigation.
376
+ runProjectId: getRunProjectIdForWriteback(run)
377
+ }) : { ok: true, applied: [], skipped: [] };
378
+ assertCurrent();
379
+ if (hasTextUndo) WritebackSettlement.attachUndoNotVerifiedFailure(textRun, result, {
380
+ buildFailure: buildContentFailure, postFiles: trackedUndoPostFilesAtDispatch });
381
+ if (fileUndoOperations.length && lifecycleReject && hasTextUndo) {
382
+ WritebackSettlement.attachUndoNotVerifiedFailure(textRun, result, { buildFailure: buildContentFailure, postFiles: trackedUndoPostFilesAtDispatch });
383
+ await applyTrackedChangeSettlement(runId, 'reject', { ...result, ok: false }, { assertCurrent });
384
+ }
385
+ if (fileUndoOperations.length) {
386
+ let createdResult;
387
+ try {
388
+ if (result.ok === false || result.skipped?.length) {
389
+ throw new Error('Text changes remain unresolved; file restoration was kept for the next undo attempt.');
390
+ }
391
+ createdResult = await callPageBridge('applyOperations', {
392
+ operations: fileUndoOperations, reviewOwnerToken: reviewOwners.get(runId)?.token, deadlineAt,
393
+ baseFiles: run.undoBaseFiles || [],
394
+ reviewingPolicy: 'no-trace-undo',
395
+ runProjectId: getRunProjectIdForWriteback(run)
396
+ });
397
+ } catch (error) {
398
+ createdResult = { ok: false, applied: [], skipped: fileUndoOperations.map(operation => ({
399
+ operation, result: { ok: false, code: 'undo_operation_failed', reason: error.message }
400
+ })) };
401
+ }
402
+ assertCurrent();
403
+ result = Modules.UndoOperations.mergeFileUndoResult(result, createdResult, fileUndoOperations);
404
+ }
405
+ appendRunRecordEvent(runId, {
406
+ title: fileUndoOperations.length ? tr('undoResult', { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }) : trackedUndo
407
+ ? tr('undoTrackedResult', { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 })
408
+ : tr('undoNativeResult', { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
409
+ failure: reviewEventFailure(run, result),
410
+ status: result.ok === true && !result.skipped?.length ? 'completed' : 'failed',
411
+ detail: {
412
+ [trackedUndo && !fileUndoOperations.length ? tr('detailRejected') : tr('detailUndone')]: (result.applied || []).map(item => ({
413
+ [tr('detailFile')]: item.trackedChange?.path || item.operation?.path || tr('unknownFile'),
414
+ [tr('detailRecord')]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || item.operation?.type
415
+ })),
416
+ [tr('detailSkipped')]: (result.skipped || []).map(item => ({
417
+ [tr('detailFile')]: item.trackedChange?.path || item.operation?.path || tr('unknownFile'),
418
+ [tr('detailRecord')]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || item.operation?.type || '',
419
+ [tr('detailReason')]: formatBridgeResultReason(item.result, item.trackedChange?.path || item.operation?.path)
420
+ }))
421
+ }
422
+ });
423
+ if (lifecycleReject) {
424
+ WritebackSettlement.attachUndoNotVerifiedFailure(textRun, result, {
425
+ buildFailure: buildContentFailure,
426
+ postFiles: trackedUndoPostFilesAtDispatch
427
+ });
428
+ await applyTrackedChangeSettlement(runId, 'reject', result, { assertCurrent });
429
+ return;
430
+ }
431
+ await applyLegacyUndoSettlement(runId, result.ok === true && !result.skipped?.length ? 'applied' : 'partial', result);
432
+ } finally {
433
+ // Known Page changes require invalidation even when a durable checkpoint fails.
434
+ if (result) writebackOrchestrator.invalidateMirrorAfterUndo(runId, getRunProjectIdForWriteback(run), result);
435
+ }
436
+ }
437
+
438
+ function reviewOwner(run) {
439
+ const owner = { run, state: getState(), sessionId: getState().activeSessionId,
440
+ projectId: getCurrentProjectId(), accountScopeId: getAccountScopeId(), generation: getRouteGeneration() };
441
+ const assert = () => {
442
+ reviewOwners.get(run.id)?.();
443
+ if (!owner.projectId || !owner.accountScopeId || run.runProjectId !== owner.projectId
444
+ || getCurrentProjectId() !== owner.projectId || getAccountScopeId() !== owner.accountScopeId
445
+ || getRouteGeneration() !== owner.generation || getState() !== owner.state
446
+ || getState().activeSessionId !== owner.sessionId || findRunRecord(run.id) !== run
447
+ || (run.runAccountScopeId && run.runAccountScopeId !== owner.accountScopeId))
448
+ throw Object.assign(new Error('The original review project, account or session changed.'), { code: 'review_context_changed' });
449
+ return run;
450
+ };
451
+ assert(); return { ...owner, assert };
452
+ }
453
+
454
+ async function executeAcceptRun(runId) {
455
+ const run = findRunRecord(runId);
456
+ if (!run || !isTrackedChangeLifecycleRun(run)) {
457
+ return;
458
+ }
459
+ const status = run.trackedChangeStatus || '';
460
+ // pending and needs_review are both actionable per §7: needs_review means
461
+ // the prior attempt could not prove a clean post-action state, and the
462
+ // user is supposed to be able to retry after inspecting Overleaf.
463
+ if (status !== 'pending' && status !== 'needs_review') {
464
+ return;
465
+ }
466
+ if (!Array.isArray(run.undoTrackedChanges) || !run.undoTrackedChanges.length) {
467
+ return;
468
+ }
469
+ if (trackedChangeInFlight.get(runId)) {
470
+ return;
471
+ }
472
+
473
+ const owner = reviewOwner(run);
474
+ trackedChangeInFlight.set(runId, 'accept');
475
+ refreshRunCardControls(runId);
476
+ appendRunRecordEvent(runId, {
477
+ title: tr('runAcceptTrackedStarted'),
478
+ status: 'running',
479
+ detail: { [tr('detailAccepted')]: formatTrackedChangeFiles(run.undoTrackedChanges) }
480
+ });
481
+
482
+ try {
483
+ const deadlineAt = await prepareUndoDispatch(runId);
484
+ const result = await callPageBridge('acceptTrackedChanges', { deadlineAt, reviewOwnerToken: reviewOwners.get(runId)?.token,
485
+ trackedChanges: run.undoTrackedChanges || [],
486
+ expectedFiles: run.undoExpectedFiles || [],
487
+ postFiles: buildTrackedUndoPostFiles(run),
488
+ appliedOperations: Array.isArray(run.appliedOperations) ? run.appliedOperations : [],
489
+ runProjectId: owner.projectId, accountScopeId: owner.accountScopeId
490
+ });
491
+ owner.assert();
492
+ appendAcceptDiagnosticEvents(runId, Array.isArray(result.diagnostics) ? result.diagnostics : []);
493
+ appendRunRecordEvent(runId, {
494
+ title: tr('runAcceptTrackedResult', { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
495
+ failure: reviewEventFailure(run, result),
496
+ status: result.ok === true && !result.skipped?.length ? 'completed' : 'failed',
497
+ detail: {
498
+ [tr('detailAccepted')]: (result.applied || []).map(item => ({
499
+ [tr('detailFile')]: item.trackedChange?.path || tr('unknownFile'),
500
+ [tr('detailRecord')]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
501
+ })),
502
+ [tr('detailSkipped')]: (result.skipped || []).map(item => ({
503
+ [tr('detailFile')]: item.trackedChange?.path || tr('unknownFile'),
504
+ [tr('detailRecord')]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || '',
505
+ [tr('detailReason')]: formatBridgeResultReason(item.result, item.trackedChange?.path)
506
+ }))
507
+ }
508
+ });
509
+ if (result.ok === false) {
510
+ appendRunRecordEvent(runId, {
511
+ title: tr('runAcceptTrackedFailed'),
512
+ status: 'failed',
513
+ detail: {
514
+ [tr('detailReason')]: tr('runAcceptTrackedFailedReason')
515
+ }
516
+ });
517
+ if (!WritebackSettlement.isSuccessfulTrackedChangeSettlement(result)) {
518
+ refreshRunCardControls(runId);
519
+ }
520
+ }
521
+ WritebackSettlement.attachAcceptNotVerifiedFailure(run, result, {
522
+ buildFailure: buildContentFailure
523
+ });
524
+ await applyTrackedChangeSettlement(runId, 'accept', result, { assertCurrent: owner.assert });
525
+ owner.assert();
526
+ } catch (error) { notify?.(error.message); throw error; }
527
+ finally {
528
+ trackedChangeInFlight.delete(runId);
529
+ refreshRunCardControls(runId);
530
+ }
531
+ }
532
+
533
+ function appendAcceptDiagnosticEvents(runId, diagnostics) {
534
+ for (const entry of diagnostics || []) {
535
+ const step = entry && entry.step;
536
+ const info = (entry && entry.info) || {};
537
+ const titleKey = WritebackSettlement.ACCEPT_DIAGNOSTIC_TITLE_KEYS[step];
538
+ if (!titleKey) {
539
+ continue;
540
+ }
541
+ const title = titleKey === 'runAcceptTrackedStepReplayStart' || titleKey === 'runAcceptTrackedStepReplayDone'
542
+ ? tr(titleKey, { path: info.path || tr('unknownFile') })
543
+ : tr(titleKey);
544
+ const status = WritebackSettlement.acceptDiagnosticStatus(step, info);
545
+ appendRunRecordEvent(runId, {
546
+ title,
547
+ kind: 'activity',
548
+ status,
549
+ detail: info
550
+ });
551
+ }
552
+ }
553
+
554
+ async function applyLegacyUndoSettlement(runId, undoStatus, result) {
555
+ const run = findRunRecord(runId);
556
+ if (!run) return;
557
+ const assertCurrent = undoOwner(run);
558
+ const checkpoint = advanceRunUndoProgress(run, result);
559
+ const transition = WritebackSettlement.applySettlementTransition(
560
+ checkpoint,
561
+ WritebackSettlement.settleLegacyUndo({
562
+ run: checkpoint,
563
+ status: undoStatus,
564
+ result
565
+ })
566
+ );
567
+ await Modules.ScopedPersistenceCoordinator.applyReviewTransition({ getState, runId, transition,
568
+ legacyUndo: true, persist: flushQueuedSaveState, assertCurrent });
569
+ refreshRunCardControls(runId);
570
+ }
571
+ return { recoverInterruptedUndoStatuses, undoRun, undoRunTrackedChanges, acceptRun, applyLegacyUndoSettlement };
572
+ }
573
+ return { create };
574
+ });
@@ -7,7 +7,7 @@
7
7
  })(typeof window !== 'undefined' ? window : globalThis, function runScrollLayoutFactory() {
8
8
  'use strict';
9
9
 
10
- const READING_ANCHORS = '.run-final-answer p, .run-final-answer li, .run-final-answer pre, .run-final-answer h1, .run-final-answer h2, .run-final-answer h3, .run-stream p, .run-stream li, .run-stream pre, [data-run-task], [data-run-status]';
10
+ const READING_ANCHORS = '.run-final-answer p, .run-final-answer li, .run-final-answer pre, .run-final-answer h1, .run-final-answer h2, .run-final-answer h3, .run-stream p, .run-stream li, .run-stream pre, .run-guidance-text, [data-run-task], [data-run-status]';
11
11
 
12
12
  function create({ getScroller, onLayoutChange, isFollowing = () => true, window: host = globalThis } = {}) {
13
13
  let current = null;
@@ -66,6 +66,25 @@
66
66
  captureAnchor(true);
67
67
  }
68
68
 
69
+ function revealGuidance(row) {
70
+ const scroller = getScroller();
71
+ if (!isFollowing() || !scroller?.contains?.(row)) return null;
72
+ const bounds = scroller.getBoundingClientRect?.(), start = row.getBoundingClientRect?.();
73
+ if (!bounds || !start || !start.height) return null;
74
+ const summary = row.closest?.('[data-run-id]')?.querySelector('[data-run-process-summary]');
75
+ const end = Math.max(start.bottom, summary?.getBoundingClientRect?.().bottom || start.bottom);
76
+ const bottom = Math.max(0, scroller.scrollHeight - scroller.clientHeight), shift = bottom - scroller.scrollTop;
77
+ const fitsAtBottom = start.top - shift >= bounds.top + 8 && end - shift <= bounds.bottom - 8;
78
+ // Default folded runs can show the new input and header while following.
79
+ // A long expanded runtime may require leaving its bottom; show the input
80
+ // without changing disclosure or asking the surrounding page to scroll.
81
+ if (fitsAtBottom) scroller.scrollTop = bottom;
82
+ else if (start.top < bounds.top + 8 || end > bounds.bottom - 8) {
83
+ scroller.scrollTop += start.top - bounds.top - 8;
84
+ }
85
+ return { following: fitsAtBottom || Math.abs(bottom - scroller.scrollTop) < 1 };
86
+ }
87
+
69
88
  function dispose() {
70
89
  resizeObserver?.disconnect();
71
90
  mutationObserver?.disconnect();
@@ -117,7 +136,7 @@
117
136
  }
118
137
  }
119
138
 
120
- return Object.freeze({ bind, dispose, captureAnchor, snapshot, restore });
139
+ return Object.freeze({ bind, dispose, captureAnchor, snapshot, restore, revealGuidance });
121
140
  }
122
141
 
123
142
  return Object.freeze({ create });