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