codex-overleaf-link 2.4.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +272 -314
- package/README.zh-CN.md +287 -329
- package/extension/bootstrap/background.js +47 -10
- package/extension/bootstrap/manifest.template.json +9 -4
- package/extension/bootstrap/popup.html +10 -16
- package/extension/bootstrap/update.js +25 -2
- package/extension/runtime-manifest.json +3 -1
- package/extension/src/background.js +28 -3
- package/extension/src/backgroundSharedSessions.js +380 -0
- package/extension/src/backgroundUpdateCoordinator.js +442 -379
- package/extension/src/content/activeTurnControl.js +8 -0
- package/extension/src/content/assetTransferBroker.js +186 -12
- package/extension/src/content/changeHistoryView.js +175 -0
- package/extension/src/content/composerAttachments.js +24 -22
- package/extension/src/content/composerPanel.js +23 -8
- package/extension/src/content/contentRuntime.js +507 -507
- package/extension/src/content/diagnosticsController.js +1 -2
- package/extension/src/content/diagnosticsExport.js +222 -0
- package/extension/src/content/diagnosticsPanel.js +48 -19
- package/extension/src/content/diffReviewPanel.js +8 -5
- package/extension/src/content/generated/content.bundle.js +8330 -1349
- package/extension/src/content/generated/content.bundle.meta.json +22 -3
- package/extension/src/content/legacyGlobalRegistry.js +19 -1
- package/extension/src/content/localSkillsPanel.js +42 -7
- package/extension/src/content/markdownDomRenderer.js +9 -4
- package/extension/src/content/modelPicker.js +1 -1
- package/extension/src/content/pageBridgeClient.js +18 -3
- package/extension/src/content/panelMaintenance.js +48 -121
- package/extension/src/content/panelRenderer.js +4 -0
- package/extension/src/content/pendingInputView.js +109 -76
- package/extension/src/content/providerSettingsCoordinator.js +17 -6
- package/extension/src/content/providerSettingsDialog.js +661 -108
- package/extension/src/content/recentProjects.js +10 -1
- package/extension/src/content/runActivitySummary.js +631 -0
- package/extension/src/content/runController.js +3 -1
- package/extension/src/content/runFailureNotice.js +14 -1
- package/extension/src/content/runGuidanceController.js +4 -3
- package/extension/src/content/runPresence.js +306 -0
- package/extension/src/content/runQueueScheduler.js +2 -1
- package/extension/src/content/runResultActions.js +123 -3
- package/extension/src/content/runTimelineView.js +186 -154
- package/extension/src/content/selectionContextView.js +300 -0
- package/extension/src/content/sessionPersistence.js +6 -1
- package/extension/src/content/settingsPanel.js +77 -52
- package/extension/src/content/settingsWorkbench.js +374 -0
- package/extension/src/content/sharedSessionViewSync.js +72 -0
- package/extension/src/content/subagentActivityView.js +195 -0
- package/extension/src/content/trackedChangeCaptureController.js +7 -3
- package/extension/src/content/updateNotice.js +121 -50
- package/extension/src/content/writebackController.js +257 -0
- package/extension/src/content/writebackOrchestrator.js +146 -141
- package/extension/src/content/writebackPlan.js +231 -0
- package/extension/src/content/writebackRecovery.js +122 -0
- package/extension/src/content/writingStyleSettings.js +576 -0
- package/extension/src/content/writtenChangesView.js +152 -0
- package/extension/src/page/binaryAssetUploader.js +97 -19
- package/extension/src/page/overleafProjectSnapshot.js +1 -0
- package/extension/src/page/referenceProjects.js +148 -0
- package/extension/src/page/saveState.js +14 -2
- package/extension/src/page/snapshotRouter.js +44 -13
- package/extension/src/page/textCoordinates.js +102 -0
- package/extension/src/page/textFileCreator.js +350 -59
- package/extension/src/page/trackedChangeCapture.js +42 -56
- package/extension/src/page/trackedChangeOwnership.js +198 -0
- package/extension/src/page/trackedChangeReplay.js +164 -0
- package/extension/src/page/trackedChangesLifecycle.js +135 -149
- package/extension/src/page/treeOperations.js +26 -2
- package/extension/src/page/writebackReceiptJournal.js +112 -0
- package/extension/src/page/writebackRouter.js +175 -135
- package/extension/src/pageBridge.js +56 -101
- package/extension/src/popup.js +203 -59
- package/extension/src/shared/agentTranscript.js +18 -4
- package/extension/src/shared/auditRecords.js +71 -0
- package/extension/src/shared/changeHistoryModel.js +94 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/compileAdapter.js +42 -0
- package/extension/src/shared/failureReasons.js +20 -0
- package/extension/src/shared/globalPreferences.js +1 -1
- package/extension/src/shared/i18n.js +93 -25
- package/extension/src/shared/managedUpdateProjection.js +6 -3
- package/extension/src/shared/pageRpcContract.js +7 -1
- package/extension/src/shared/providerProfiles.js +109 -0
- package/extension/src/shared/runActivityModel.js +361 -0
- package/extension/src/shared/runExecutionSnapshot.js +8 -2
- package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
- package/extension/src/shared/selectionContext.js +28 -0
- package/extension/src/shared/sessionState.js +97 -6
- package/extension/src/shared/sharedSessionBridge.js +288 -0
- package/extension/src/shared/storageDb.js +22 -55
- package/extension/src/shared/storageMigration.js +3 -0
- package/extension/src/shared/storageRunActions.js +10 -4
- package/extension/src/shared/storageValuePruning.js +40 -0
- package/extension/src/shared/subagentActivityModel.js +174 -0
- package/extension/src/shared/undoOperations.js +87 -0
- package/extension/src/shared/updateConsent.js +37 -8
- package/extension/src/shared/writebackIntent.js +62 -0
- package/extension/src/shared/writebackSettlement.js +29 -10
- package/extension/src/shared/writingStyle.js +33 -0
- package/extension/styles/panel.css +1972 -384
- package/extension/styles/popup.css +110 -0
- package/native-host/src/anthropicBridgeRequest.js +2 -1
- package/native-host/src/codexModelRecovery.js +107 -0
- package/native-host/src/codexPromptAssembly.js +2 -0
- package/native-host/src/codexProviderLaunch.js +3 -3
- package/native-host/src/codexRuntimeIdentity.js +1 -0
- package/native-host/src/codexSessionRunner.js +106 -140
- package/native-host/src/codexSessionTiming.js +3 -0
- package/native-host/src/managedInstall.js +5 -4
- package/native-host/src/nativeEnvironment.js +70 -0
- package/native-host/src/nativeQuotas.js +15 -8
- package/native-host/src/overleafWorkspaceRules.js +16 -0
- package/native-host/src/processStopBarrier.js +80 -0
- package/native-host/src/providerModelCatalog.js +4 -3
- package/native-host/src/providerProfile.js +13 -1
- package/native-host/src/providerReasoning.js +9 -5
- package/native-host/src/providerStore.js +4 -0
- package/native-host/src/releaseTransport.js +14 -5
- package/native-host/src/selectionScope.js +58 -0
- package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
- package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
- package/native-host/src/subagentBroker.js +102 -98
- package/native-host/src/subagentTelemetry.js +316 -0
- package/native-host/src/subagentWorkspace.js +103 -0
- package/native-host/src/subagentWorkspacePath.js +31 -0
- package/native-host/src/taskRunnerRuntime.js +55 -5
- package/native-host/src/turnAttachments.js +113 -0
- package/native-host/src/updateManager.js +122 -12
- package/native-host/src/updateNetworkControl.js +75 -0
- package/native-host/src/updateTrust.js +21 -2
- package/native-host/src/vendor/pdfjs/LICENSE +177 -0
- package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
- package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
- package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
- package/native-host/src/writingStyleEvidence.js +102 -0
- package/native-host/src/writingStylePdfWorker.js +35 -0
- package/native-host/src/writingStyleProfile.js +165 -0
- package/native-host/src/writingStyleRuntime.js +447 -0
- package/package.json +1 -1
|
@@ -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,22 @@
|
|
|
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 } = Ownership.create({
|
|
133
|
+
fingerprint, readActiveEditorText, mergedPrefix, nativeKey, ledgerKeys
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
128
138
|
function prepareTrackedChangeReview(path, refs = []) {
|
|
129
139
|
const snapshot = readNativeSnapshot(path);
|
|
130
140
|
const blocked = reason => ({ ...snapshot, ok: false, reason });
|
|
131
141
|
if (!snapshot.ready) return blocked(snapshot.reason || 'native_review_unavailable');
|
|
132
142
|
const targets = refs.filter(ref => ref.path === path), ids = new Set(targets.map(ref => ref.id));
|
|
143
|
+
if (targets.some(ref => ref.key?.startsWith(mergedPrefix)))
|
|
144
|
+
return prepareMergedInsertionReview(path, targets, snapshot);
|
|
133
145
|
let expected;
|
|
134
146
|
try {
|
|
135
147
|
expected = targets.map(ref => {
|
|
@@ -150,19 +162,6 @@
|
|
|
150
162
|
return { ...snapshot, ok: true, targets, ids: [...ids],
|
|
151
163
|
unrelated: snapshot.refs.filter(ref => !ids.has(ref.id)) };
|
|
152
164
|
}
|
|
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
165
|
const identity = ref => (ref.path || '') + '\0' + ref.key;
|
|
167
166
|
function diff(before, after) {
|
|
168
167
|
const seen = new Set(before.map(identity));
|
|
@@ -173,34 +172,6 @@
|
|
|
173
172
|
return true;
|
|
174
173
|
});
|
|
175
174
|
}
|
|
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
175
|
function allowedRef(ref, capture) {
|
|
205
176
|
if (ref.path !== capture.path) return false;
|
|
206
177
|
if (capture.source === 'native') return nativeOwned(ref, capture);
|
|
@@ -212,16 +183,6 @@
|
|
|
212
183
|
// insufficient to assign a new task ownership after a delayed capture.
|
|
213
184
|
return Boolean(ref.id);
|
|
214
185
|
}
|
|
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
186
|
async function waitForTrackedChangeDiff(before, paths, options = {}) {
|
|
226
187
|
const waitMs = Math.max(0, Number(options.waitMs ?? 5000));
|
|
227
188
|
const intervalMs = Math.max(1, Number(options.intervalMs ?? 180));
|
|
@@ -244,9 +205,15 @@
|
|
|
244
205
|
if (options.capture && !allowedRef(ref, options.capture)) { filtered++; continue; }
|
|
245
206
|
found.set(identity(ref), ref);
|
|
246
207
|
}
|
|
208
|
+
const merged = native && lastSnapshotReady
|
|
209
|
+
? mergedInsertionScope(options.capture, after, readActiveEditorText()) : null;
|
|
210
|
+
if (merged) { found.clear(); found.set(identity(merged.ref), merged.ref); }
|
|
247
211
|
const nextSignature = after.map(ref => native ? ref.key : identity(ref)).sort().join('\n');
|
|
248
212
|
if (nextSignature !== signature) { signature = nextSignature; lastChange = now(); }
|
|
249
213
|
if (options.stopOnFirst && found.size) { reason = 'observed'; break; }
|
|
214
|
+
if (options.capture && now() - start >= 5000 && lastSnapshotReady && found.size
|
|
215
|
+
&& now() - lastChange >= stableMs && scopeCovered(Array.from(found.values()), options.capture)
|
|
216
|
+
&& afterCount < limit) { reason = 'observed'; break; }
|
|
250
217
|
if (now() >= deadline) break;
|
|
251
218
|
await delay(Math.min(intervalMs, deadline - now()));
|
|
252
219
|
}
|
|
@@ -263,7 +230,7 @@
|
|
|
263
230
|
source: options.capture?.source || 'dom', sourceReason }
|
|
264
231
|
};
|
|
265
232
|
}
|
|
266
|
-
async function captureTrackedWrite({ trackedBefore, captureBaseline, operation, beforeContent, postContent, runProjectId }) {
|
|
233
|
+
async function captureTrackedWrite({ trackedBefore, captureBaseline, operation, beforeContent, postContent, runProjectId, waitMs = 5000 }) {
|
|
267
234
|
if (beforeContent === postContent) return { trackedChanges: [], capture: null };
|
|
268
235
|
const ranges = rangesFor(operation, beforeContent, postContent);
|
|
269
236
|
const baseline = shiftedBaseline(trackedBefore, ranges);
|
|
@@ -284,7 +251,7 @@
|
|
|
284
251
|
capture.reason = baseline.overlap ? 'preexisting_change_overlap' : 'capture_baseline_limit';
|
|
285
252
|
return { trackedChanges: [], capture };
|
|
286
253
|
}
|
|
287
|
-
return observe(capture, postContent, 5000);
|
|
254
|
+
return observe(capture, postContent, Math.min(35000, Math.max(5000, Number(waitMs) || 5000)));
|
|
288
255
|
}
|
|
289
256
|
function validCapture(capture) {
|
|
290
257
|
return capture?.version === 1 && typeof capture.path === 'string'
|
|
@@ -333,7 +300,26 @@
|
|
|
333
300
|
if (params.capture?.runProjectId !== params.runProjectId) {
|
|
334
301
|
return { ok: false, code: 'capture_project_mismatch', trackedChanges: [] };
|
|
335
302
|
}
|
|
336
|
-
|
|
303
|
+
const capture = params.capture;
|
|
304
|
+
// An expired polling window does not erase a provable, unchanged scope.
|
|
305
|
+
// Recovery is read-only and must reconstruct the complete old/new ledger.
|
|
306
|
+
if (validCapture(capture) && capture.source === 'native'
|
|
307
|
+
&& (now() >= capture.expiresAt || capture.state === 'needs_review')) {
|
|
308
|
+
const active = getActiveFilePath() === capture.path
|
|
309
|
+
&& readActiveEditorText() === params.expectedContent
|
|
310
|
+
&& (!deps.getProjectId || deps.getProjectId() === params.runProjectId);
|
|
311
|
+
const snapshot = active ? readNativeSnapshot(capture.path, capture.nativeDocId) : null;
|
|
312
|
+
const merged = snapshot?.ready && snapshot.acceptByIdSupported
|
|
313
|
+
? mergedInsertionScope(capture, snapshot.refs, params.expectedContent) : null;
|
|
314
|
+
if (merged) return { ok: true, trackedChanges: [merged.ref], capture: {
|
|
315
|
+
...capture, refs: [merged.ref], state: 'observed', reason: 'observed',
|
|
316
|
+
diagnostics: { ...capture.diagnostics, capturedCount: 1,
|
|
317
|
+
sourceReason: 'native_merged_insertion_recovered' }
|
|
318
|
+
} };
|
|
319
|
+
return { ok: false, trackedChanges: [], capture: { ...capture,
|
|
320
|
+
state: 'needs_review', reason: 'capture_merged_scope_unavailable' } };
|
|
321
|
+
}
|
|
322
|
+
return observe(capture, params.expectedContent, 1200);
|
|
337
323
|
}
|
|
338
324
|
return { collectTrackedChangeNodes, trackedChangeRefFromNode, collectTrackedChangeRefsForPaths,
|
|
339
325
|
waitForTrackedChangeDiff, prepareTrackedChangeCapture, prepareTrackedChangeReview, prepareUntrackedUndo, getTrackedChangeCaptureStatus, captureTrackedWrite, reconcileTrackedChangeCapture };
|
|
@@ -0,0 +1,198 @@
|
|
|
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
|
+
return { mergedInsertionScope, prepareMergedInsertionReview, nativeOwned, rangesFor, shiftedBaseline, scopeCovered };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return { create };
|
|
198
|
+
});
|
|
@@ -0,0 +1,164 @@
|
|
|
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
|
+
if (originalPatches && originalPatches.length && patchesApplyCleanly(preContent, originalPatches)) {
|
|
37
|
+
operations.push({
|
|
38
|
+
type: 'edit',
|
|
39
|
+
path,
|
|
40
|
+
patches: originalPatches,
|
|
41
|
+
reason: 'Accept tracked edit (replay untracked)'
|
|
42
|
+
});
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Fallback: minimal pre->post diff trimmed to a single targeted patch.
|
|
47
|
+
const diffPatch = buildMinimalDiffPatch(preContent, postContent);
|
|
48
|
+
if (!diffPatch) {
|
|
49
|
+
// pre === post: nothing to replay for this file.
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
operations.push({
|
|
53
|
+
type: 'edit',
|
|
54
|
+
path,
|
|
55
|
+
patches: [diffPatch],
|
|
56
|
+
reason: 'Accept tracked edit (replay untracked)'
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return { ok: true, operations };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Collects the per-path `patches` arrays from the run's applied edit
|
|
63
|
+
// operations. Only edit operations that actually carried `patches` are
|
|
64
|
+
// usable; whole-file replaceAll / verifiedContent operations are skipped so
|
|
65
|
+
// the replay never falls back to a whole-file write.
|
|
66
|
+
function collectAppliedEditPatchesByPath(appliedOperations) {
|
|
67
|
+
const patchesByPath = new Map();
|
|
68
|
+
for (const rawOperation of Array.isArray(appliedOperations) ? appliedOperations : []) {
|
|
69
|
+
if (!rawOperation || rawOperation.type !== 'edit') {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const path = typeof rawOperation.path === 'string'
|
|
73
|
+
? normalizeSafeProjectPath(rawOperation.path)
|
|
74
|
+
: '';
|
|
75
|
+
if (!path || !Array.isArray(rawOperation.patches) || !rawOperation.patches.length) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const normalized = rawOperation.patches.map(patch => ({
|
|
79
|
+
from: Number(patch?.from),
|
|
80
|
+
to: Number(patch?.to),
|
|
81
|
+
expected: String(patch?.expected ?? ''),
|
|
82
|
+
insert: String(patch?.insert ?? '')
|
|
83
|
+
}));
|
|
84
|
+
const existing = patchesByPath.get(path) || [];
|
|
85
|
+
patchesByPath.set(path, existing.concat(normalized));
|
|
86
|
+
}
|
|
87
|
+
return patchesByPath;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Confirms a patch set re-applies cleanly against the given (pre-write) text:
|
|
91
|
+
// every patch range is valid and its `expected` slice matches.
|
|
92
|
+
function patchesApplyCleanly(text, patches) {
|
|
93
|
+
const applied = applyTextPatches(text, patches);
|
|
94
|
+
return applied.ok === true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Computes a single targeted {from,to,insert} patch describing the pre->post
|
|
98
|
+
// change by trimming the common prefix and suffix. Returns null when the two
|
|
99
|
+
// strings are identical.
|
|
100
|
+
function buildMinimalDiffPatch(preContent, postContent) {
|
|
101
|
+
if (preContent === postContent) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const preLen = preContent.length;
|
|
105
|
+
const postLen = postContent.length;
|
|
106
|
+
let prefix = 0;
|
|
107
|
+
const maxPrefix = Math.min(preLen, postLen);
|
|
108
|
+
while (prefix < maxPrefix && preContent[prefix] === postContent[prefix]) {
|
|
109
|
+
prefix += 1;
|
|
110
|
+
}
|
|
111
|
+
let suffix = 0;
|
|
112
|
+
const maxSuffix = Math.min(preLen, postLen) - prefix;
|
|
113
|
+
while (
|
|
114
|
+
suffix < maxSuffix
|
|
115
|
+
&& preContent[preLen - 1 - suffix] === postContent[postLen - 1 - suffix]
|
|
116
|
+
) {
|
|
117
|
+
suffix += 1;
|
|
118
|
+
}
|
|
119
|
+
const from = prefix;
|
|
120
|
+
const to = preLen - suffix;
|
|
121
|
+
return {
|
|
122
|
+
from,
|
|
123
|
+
to,
|
|
124
|
+
expected: preContent.slice(from, to),
|
|
125
|
+
insert: postContent.slice(from, postLen - suffix)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function rebaseCheckpointPair(actualContent, expectedContent, postContent) {
|
|
130
|
+
const actual = String(actualContent ?? '');
|
|
131
|
+
const expected = String(expectedContent ?? '');
|
|
132
|
+
const post = String(postContent ?? '');
|
|
133
|
+
if (actual === post) {
|
|
134
|
+
return {
|
|
135
|
+
ok: true,
|
|
136
|
+
expectedContent: expected,
|
|
137
|
+
postContent: post,
|
|
138
|
+
prefixLength: 0,
|
|
139
|
+
suffixLength: 0
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (!post) {
|
|
143
|
+
return { ok: false };
|
|
144
|
+
}
|
|
145
|
+
const matchIndex = actual.indexOf(post);
|
|
146
|
+
if (matchIndex < 0 || actual.indexOf(post, matchIndex + 1) >= 0) {
|
|
147
|
+
return { ok: false };
|
|
148
|
+
}
|
|
149
|
+
const prefix = actual.slice(0, matchIndex);
|
|
150
|
+
const suffix = actual.slice(matchIndex + post.length);
|
|
151
|
+
return {
|
|
152
|
+
ok: true,
|
|
153
|
+
expectedContent: prefix + expected + suffix,
|
|
154
|
+
postContent: actual,
|
|
155
|
+
prefixLength: prefix.length,
|
|
156
|
+
suffixLength: suffix.length
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return { buildAcceptReplayOperations, rebaseCheckpointPair };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return { create };
|
|
164
|
+
});
|