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
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
const api = factory();
|
|
3
|
+
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
4
|
+
if (root) root.CodexOverleafSharedSessionsBackground = api;
|
|
5
|
+
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
const MESSAGE = 'codex-overleaf/shared-sessions-v1';
|
|
8
|
+
const LOCK_PORT = 'codex-overleaf/shared-session-lock-v1';
|
|
9
|
+
const CHANGE_KEY = 'codex-overleaf-shared-sessions-changed-v1';
|
|
10
|
+
const HOSTS = ['overleaf.com', 'www.overleaf.com', 'cn.overleaf.com'];
|
|
11
|
+
const META_PREFIX = 'codex-overleaf-scoped-persistence-v1:';
|
|
12
|
+
const MAX_BYTES = 8 * 1024 * 1024;
|
|
13
|
+
const own = (value, key) => Object.prototype.hasOwnProperty.call(value || {}, key);
|
|
14
|
+
const clone = value => value === undefined ? undefined : JSON.parse(JSON.stringify(value));
|
|
15
|
+
const equal = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
16
|
+
const failure = (code, message) => Object.assign(new Error(message), { code });
|
|
17
|
+
function part(value) {
|
|
18
|
+
if (typeof value !== 'string' || !value.trim() || value.length > 256 || /[\0\r\n]/.test(value))
|
|
19
|
+
throw failure('shared_store_scope_invalid', 'The shared session identity is invalid.');
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function scope(input) {
|
|
23
|
+
return { accountScopeId: part(input?.accountScopeId), projectId: typeof input?.projectId === 'string' ? input.projectId : '' };
|
|
24
|
+
}
|
|
25
|
+
function keyFor(kind, value) {
|
|
26
|
+
return kind === 'preferences' ? 'preferences'
|
|
27
|
+
: 'state:' + encodeURIComponent(value.accountScopeId);
|
|
28
|
+
}
|
|
29
|
+
function metaKey(value) {
|
|
30
|
+
return META_PREFIX + encodeURIComponent(value.accountScopeId) + ':' + encodeURIComponent(value.projectId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Three-way merge preserves changes made by another tab to untouched fields.
|
|
34
|
+
// Conflicting edits fail closed; removed records are never silently revived.
|
|
35
|
+
function mergeValue(base, current, incoming, field = '') {
|
|
36
|
+
if (equal(incoming, base)) return clone(current);
|
|
37
|
+
if (equal(current, base) || equal(current, incoming)) return clone(incoming);
|
|
38
|
+
if (field === 'updatedAt' || field === 'lastActivityAt')
|
|
39
|
+
return (Date.parse(current) || 0) >= (Date.parse(incoming) || 0) ? current : incoming;
|
|
40
|
+
if (Array.isArray(base) && Array.isArray(current) && Array.isArray(incoming)) {
|
|
41
|
+
if (['runs', 'pendingInputs'].includes(field)
|
|
42
|
+
&& [base, current, incoming].every(items => items.every(item => item && typeof item.id === 'string')
|
|
43
|
+
&& new Set(items.map(item => item.id)).size === items.length)) {
|
|
44
|
+
const before = new Map(base.map(item => [item.id, item]));
|
|
45
|
+
const latest = new Map(current.map(item => [item.id, item]));
|
|
46
|
+
const proposed = new Map(incoming.map(item => [item.id, item]));
|
|
47
|
+
const ids = [...current.map(item => item.id), ...incoming.map(item => item.id).filter(id => !latest.has(id))];
|
|
48
|
+
return ids.map(id => mergeValue(before.get(id), latest.get(id), proposed.get(id)))
|
|
49
|
+
.filter(item => item !== undefined);
|
|
50
|
+
}
|
|
51
|
+
const extendsBase = items => items.length >= base.length && base.every((item, i) => equal(item, items[i]));
|
|
52
|
+
if (extendsBase(current) && extendsBase(incoming)) {
|
|
53
|
+
const result = clone(current), seen = new Set(result.map(item => JSON.stringify(item)));
|
|
54
|
+
for (const item of incoming.slice(base.length)) {
|
|
55
|
+
const key = JSON.stringify(item);
|
|
56
|
+
if (!seen.has(key)) { result.push(clone(item)); seen.add(key); }
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (base && current && incoming && !Array.isArray(base) && !Array.isArray(current) && !Array.isArray(incoming)
|
|
62
|
+
&& [base, current, incoming].every(value => typeof value === 'object')) {
|
|
63
|
+
const result = {};
|
|
64
|
+
for (const key of new Set([...Object.keys(base), ...Object.keys(current), ...Object.keys(incoming)])) {
|
|
65
|
+
if (key === 'sharedRevision') continue;
|
|
66
|
+
const value = mergeValue(base[key], current[key], incoming[key], key);
|
|
67
|
+
if (value !== undefined) Object.defineProperty(result, key, { value, enumerable: true, configurable: true, writable: true });
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
throw failure('shared_session_conflict', 'The same session was edited in another tab. Refresh its history before retrying; the local draft was kept.');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function createService(options = {}) {
|
|
75
|
+
const chromeApi = options.chromeApi, idb = options.indexedDB, ranges = options.IDBKeyRange;
|
|
76
|
+
const locks = new Map(), queues = new Map();
|
|
77
|
+
// Account-wide writes serialize cross-project clears and shared preference saves.
|
|
78
|
+
// IndexedDB transactions still provide the atomic boundary for session batches.
|
|
79
|
+
let opening;
|
|
80
|
+
function openDb() {
|
|
81
|
+
if (!opening) opening = new Promise((resolve, reject) => {
|
|
82
|
+
const request = idb.open('codex-overleaf-shared-sessions', 1);
|
|
83
|
+
request.onupgradeneeded = () => {
|
|
84
|
+
const db = request.result;
|
|
85
|
+
const sessions = db.createObjectStore('sessions', { keyPath: ['accountScopeId', 'id'] });
|
|
86
|
+
sessions.createIndex('account', 'accountScopeId');
|
|
87
|
+
sessions.createIndex('project', ['accountScopeId', 'projectId']);
|
|
88
|
+
db.createObjectStore('tombstones', { keyPath: ['accountScopeId', 'id'] });
|
|
89
|
+
db.createObjectStore('migrations', { keyPath: ['accountScopeId', 'origin'] });
|
|
90
|
+
};
|
|
91
|
+
request.onsuccess = () => resolve(request.result);
|
|
92
|
+
request.onerror = () => { opening = null; reject(request.error); };
|
|
93
|
+
});
|
|
94
|
+
return opening;
|
|
95
|
+
}
|
|
96
|
+
const readRequest = request => new Promise((resolve, reject) => {
|
|
97
|
+
request.onsuccess = () => resolve(request.result);
|
|
98
|
+
request.onerror = () => reject(request.error);
|
|
99
|
+
});
|
|
100
|
+
const finished = tx => new Promise((resolve, reject) => {
|
|
101
|
+
tx.oncomplete = () => resolve();
|
|
102
|
+
tx.onabort = tx.onerror = () => reject(tx.error || failure('shared_store_transaction_failed', 'The shared session transaction failed.'));
|
|
103
|
+
});
|
|
104
|
+
async function readOne(store, key) {
|
|
105
|
+
const db = await openDb();
|
|
106
|
+
return readRequest(db.transaction(store, 'readonly').objectStore(store).get(key));
|
|
107
|
+
}
|
|
108
|
+
function senderOrigin(sender) {
|
|
109
|
+
const url = new URL(sender?.url || sender?.tab?.url || '');
|
|
110
|
+
if (sender?.id !== chromeApi.runtime.id || !sender.tab || (sender.frameId != null && sender.frameId !== 0)
|
|
111
|
+
|| url.protocol !== 'https:' || !HOSTS.includes(url.hostname) || !/^\/project(?:\/|$)/.test(url.pathname))
|
|
112
|
+
throw failure('forbidden_sender', 'Shared sessions require an authorized Overleaf project page.');
|
|
113
|
+
return url.origin;
|
|
114
|
+
}
|
|
115
|
+
function ensureLock(message, value, sender) {
|
|
116
|
+
const held = locks.get(keyFor('state', value));
|
|
117
|
+
if (!held || held.disconnected || held.token !== message.lockToken || held.tabId !== sender.tab.id)
|
|
118
|
+
throw failure('storage_lock_lost', 'The shared persistence lock was lost.');
|
|
119
|
+
}
|
|
120
|
+
async function notify(value, clientId) {
|
|
121
|
+
// A missed refresh notification must not turn a committed write into a failure.
|
|
122
|
+
await chromeApi.storage.local.set({ [CHANGE_KEY]: {
|
|
123
|
+
accountScopeId: value.accountScopeId, projectId: value.projectId,
|
|
124
|
+
clientId, nonce: crypto.randomUUID(), at: Date.now()
|
|
125
|
+
} }).catch(() => {});
|
|
126
|
+
}
|
|
127
|
+
async function list(value, after = '') {
|
|
128
|
+
const db = await openDb();
|
|
129
|
+
return new Promise((resolve, reject) => {
|
|
130
|
+
const result = []; let bytes = 0, last = after;
|
|
131
|
+
const cursor = db.transaction('sessions', 'readonly').objectStore('sessions')
|
|
132
|
+
.openCursor(ranges.bound([value.accountScopeId, after], [value.accountScopeId, '\uffff'], Boolean(after), false));
|
|
133
|
+
cursor.onerror = () => reject(cursor.error);
|
|
134
|
+
cursor.onsuccess = () => {
|
|
135
|
+
const item = cursor.result;
|
|
136
|
+
if (!item) { resolve({ records: result, next: '' }); return; }
|
|
137
|
+
const stored = item.value;
|
|
138
|
+
if (value.projectId && stored.projectId !== value.projectId) { item.continue(); return; }
|
|
139
|
+
const record = { ...stored.record, sharedRevision: stored.revision };
|
|
140
|
+
const size = JSON.stringify(record).length * 2;
|
|
141
|
+
if (result.length && (result.length >= 8 || bytes + size > MAX_BYTES)) {
|
|
142
|
+
resolve({ records: result, next: last }); return;
|
|
143
|
+
}
|
|
144
|
+
result.push(record); bytes += size; last = stored.id; item.continue();
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async function legacyDeleted(record) {
|
|
149
|
+
const key = 'codexOverleafSessionTombstone:v2:' + encodeURIComponent(record.projectId) + ':' + encodeURIComponent(record.id);
|
|
150
|
+
const meta = metaKey(record);
|
|
151
|
+
const stored = await chromeApi.storage.local.get([key, meta, 'codexOverleafSessionTombstones']);
|
|
152
|
+
return Boolean(stored[key] || stored[meta]?.sessionTombstones?.[record.id]
|
|
153
|
+
|| stored.codexOverleafSessionTombstones?.[record.projectId]?.includes(record.id));
|
|
154
|
+
}
|
|
155
|
+
function recoveryCopy(record, origin) {
|
|
156
|
+
const suffix = origin.replace(/^https:\/\//, '').replace(/\W/g, '-');
|
|
157
|
+
return { ...record, id: record.id.slice(0, 200) + ':recovered:' + suffix, codexThreadId: '', pendingInputs: [],
|
|
158
|
+
titleSource: 'manual', title: (record.title || 'Recovered session') + ' [' + suffix + ']',
|
|
159
|
+
runs: (record.runs || []).map(run => ({ ...run, forkSnapshot: true, codexThreadId: '',
|
|
160
|
+
status: run.status === 'running' ? 'interrupted' : run.status,
|
|
161
|
+
undoOperations: [], undoBaseFiles: [], undoExpectedFiles: [], undoTrackedChanges: [],
|
|
162
|
+
appliedOperations: [], trackedChangeCaptures: [], undoStatus: '' })) };
|
|
163
|
+
}
|
|
164
|
+
async function writeMany(message, value, importing, origin, sender) {
|
|
165
|
+
const entries = (importing ? [{ record: message.record }] : message.entries || [])
|
|
166
|
+
.map(entry => ({ record: clone(entry.record), base: clone(entry.base) }));
|
|
167
|
+
if (JSON.stringify(entries).length * 2 > MAX_BYTES * 3)
|
|
168
|
+
throw failure('shared_session_too_large', 'The session batch exceeds the shared storage transfer limit.');
|
|
169
|
+
for (const { record, base } of entries) {
|
|
170
|
+
if (!record || record.accountScopeId !== value.accountScopeId || record.projectId !== value.projectId)
|
|
171
|
+
throw failure('shared_store_scope_mismatch', 'The session does not belong to the captured account and project.');
|
|
172
|
+
part(record.id); part(record.projectId);
|
|
173
|
+
delete record.sharedRevision;
|
|
174
|
+
if (base && (base.id !== record.id || base.accountScopeId !== value.accountScopeId || base.projectId !== value.projectId))
|
|
175
|
+
throw failure('shared_store_scope_mismatch', 'The session baseline belongs to a different scope.');
|
|
176
|
+
}
|
|
177
|
+
if (importing && await legacyDeleted(entries[0].record)) return [];
|
|
178
|
+
ensureLock(message, value, sender);
|
|
179
|
+
const db = await openDb();
|
|
180
|
+
// Recheck after opening the database; a disconnected owner cannot commit.
|
|
181
|
+
ensureLock(message, value, sender);
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
const tx = db.transaction(['sessions', 'tombstones', 'migrations'], 'readwrite');
|
|
184
|
+
const store = tx.objectStore('sessions'), deleted = tx.objectStore('tombstones');
|
|
185
|
+
const results = []; let caught;
|
|
186
|
+
const abort = error => { caught = error; tx.abort(); };
|
|
187
|
+
tx.oncomplete = () => resolve(results);
|
|
188
|
+
tx.onabort = tx.onerror = () => reject(caught || tx.error || failure('shared_store_write_failed', 'The session could not be saved.'));
|
|
189
|
+
const marker = tx.objectStore('migrations').get([value.accountScopeId, '*']);
|
|
190
|
+
marker.onsuccess = () => {
|
|
191
|
+
for (const entry of entries) {
|
|
192
|
+
if (marker.result?.clearedAt && (importing || (Date.parse(entry.record.createdAt) || 0) <= marker.result.clearedAt)) {
|
|
193
|
+
if (importing) continue;
|
|
194
|
+
abort(failure('shared_session_deleted', 'This history was cleared and cannot be restored by a stale tab.'));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
putAt(entry.record, entry.base);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
function putAt(candidate, base, copy = false) {
|
|
201
|
+
const key = [value.accountScopeId, candidate.id];
|
|
202
|
+
const tombstone = deleted.get(key);
|
|
203
|
+
tombstone.onsuccess = () => {
|
|
204
|
+
if (tombstone.result) {
|
|
205
|
+
if (importing) return;
|
|
206
|
+
abort(failure('shared_session_deleted', 'This session was deleted in another tab.')); return;
|
|
207
|
+
}
|
|
208
|
+
const request = store.get(key);
|
|
209
|
+
request.onsuccess = () => {
|
|
210
|
+
try {
|
|
211
|
+
const existing = request.result;
|
|
212
|
+
if (existing && existing.projectId !== candidate.projectId)
|
|
213
|
+
throw failure('shared_store_scope_mismatch', 'Session identity conflicts with another project.');
|
|
214
|
+
let next = candidate;
|
|
215
|
+
if (importing && existing) {
|
|
216
|
+
if (equal(existing.record, candidate) || copy) {
|
|
217
|
+
results.push({ ...existing.record, sharedRevision: existing.revision }); return;
|
|
218
|
+
}
|
|
219
|
+
putAt(recoveryCopy(candidate, origin), null, true); return;
|
|
220
|
+
}
|
|
221
|
+
if (existing) {
|
|
222
|
+
if (!base) throw failure('shared_session_conflict', 'Reload the session before updating existing history.');
|
|
223
|
+
// Keep the established first-durable-review-decision policy.
|
|
224
|
+
const reviewed = options.mergeSessionReviewState?.(candidate, existing.record, message.reviewRunIds || []) || candidate;
|
|
225
|
+
next = mergeValue(base, existing.record, reviewed);
|
|
226
|
+
} else if (base && !importing) {
|
|
227
|
+
throw failure('shared_session_deleted', 'The session no longer exists.');
|
|
228
|
+
}
|
|
229
|
+
const revision = (existing?.revision || 0) + 1;
|
|
230
|
+
store.put({ accountScopeId: value.accountScopeId, projectId: value.projectId,
|
|
231
|
+
id: next.id, record: next, revision });
|
|
232
|
+
results.push({ ...next, sharedRevision: revision });
|
|
233
|
+
} catch (error) { abort(error); }
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
async function erase(value, id, all, message, sender) {
|
|
240
|
+
const db = await openDb();
|
|
241
|
+
ensureLock(message, value, sender);
|
|
242
|
+
const tx = db.transaction(['sessions', 'tombstones', 'migrations'], 'readwrite');
|
|
243
|
+
const done = finished(tx), sessions = tx.objectStore('sessions'), tombstones = tx.objectStore('tombstones');
|
|
244
|
+
if (id) {
|
|
245
|
+
const request = sessions.get([value.accountScopeId, id]);
|
|
246
|
+
request.onsuccess = () => {
|
|
247
|
+
const existing = request.result;
|
|
248
|
+
if (existing && value.projectId && existing.projectId !== value.projectId) { tx.abort(); return; }
|
|
249
|
+
tombstones.put({ accountScopeId: value.accountScopeId, id, deletedAt: Date.now() });
|
|
250
|
+
sessions.delete([value.accountScopeId, id]);
|
|
251
|
+
};
|
|
252
|
+
} else {
|
|
253
|
+
const cursor = sessions.index('account').openCursor(ranges.only(value.accountScopeId));
|
|
254
|
+
cursor.onsuccess = () => {
|
|
255
|
+
const item = cursor.result;
|
|
256
|
+
if (!item) return;
|
|
257
|
+
if (all || item.value.projectId === value.projectId) {
|
|
258
|
+
tombstones.put({ accountScopeId: value.accountScopeId, id: item.value.id, deletedAt: Date.now() });
|
|
259
|
+
item.delete();
|
|
260
|
+
}
|
|
261
|
+
item.continue();
|
|
262
|
+
};
|
|
263
|
+
if (all) tx.objectStore('migrations').put({ accountScopeId: value.accountScopeId, origin: '*', clearedAt: Date.now() });
|
|
264
|
+
}
|
|
265
|
+
await done;
|
|
266
|
+
}
|
|
267
|
+
async function handle(message, sender) {
|
|
268
|
+
const origin = senderOrigin(sender), value = scope(message.scope);
|
|
269
|
+
const method = message.method;
|
|
270
|
+
if (method === 'list') return list(value, typeof message.after === 'string' ? message.after : '');
|
|
271
|
+
if (method === 'get') {
|
|
272
|
+
const record = await readOne('sessions', [value.accountScopeId, part(message.id)]);
|
|
273
|
+
return record && (!value.projectId || value.projectId === record.projectId)
|
|
274
|
+
? { ...record.record, sharedRevision: record.revision } : null;
|
|
275
|
+
}
|
|
276
|
+
if (method === 'migration-status') {
|
|
277
|
+
const cleared = await readOne('migrations', [value.accountScopeId, '*']);
|
|
278
|
+
return cleared?.clearedAt ? { complete: true, clearedAt: cleared.clearedAt }
|
|
279
|
+
: await readOne('migrations', [value.accountScopeId, origin]) || { complete: false };
|
|
280
|
+
}
|
|
281
|
+
if (method === 'migration-complete') {
|
|
282
|
+
ensureLock(message, value, sender);
|
|
283
|
+
const db = await openDb(), tx = db.transaction('migrations', 'readwrite'), done = finished(tx);
|
|
284
|
+
tx.objectStore('migrations').put({ ...value, origin, complete: true, at: Date.now() });
|
|
285
|
+
await done; return { complete: true };
|
|
286
|
+
}
|
|
287
|
+
if (method === 'put' || method === 'import') {
|
|
288
|
+
const result = await writeMany(message, value, method === 'import', origin, sender);
|
|
289
|
+
if (result.length) await notify(value, message.clientId);
|
|
290
|
+
return result;
|
|
291
|
+
}
|
|
292
|
+
if (method === 'delete' || method === 'clear-project' || method === 'clear-account') {
|
|
293
|
+
if (method === 'clear-project') part(value.projectId);
|
|
294
|
+
await erase(value, method === 'delete' ? part(message.id) : '', method === 'clear-account', message, sender);
|
|
295
|
+
await notify(value, message.clientId); return true;
|
|
296
|
+
}
|
|
297
|
+
if (method === 'meta-read' || method === 'meta-write') {
|
|
298
|
+
const key = metaKey(value);
|
|
299
|
+
if (method === 'meta-read') return (await chromeApi.storage.local.get(key))[key] || {};
|
|
300
|
+
const held = locks.get(keyFor('state', value));
|
|
301
|
+
if (!held || held.token !== message.lockToken || held.tabId !== sender.tab.id)
|
|
302
|
+
throw failure('storage_lock_lost', 'The shared persistence lock was lost.');
|
|
303
|
+
await chromeApi.storage.local.set({ [key]: message.meta }); return message.meta;
|
|
304
|
+
}
|
|
305
|
+
throw failure('shared_store_method_invalid', 'Unsupported shared session operation.');
|
|
306
|
+
}
|
|
307
|
+
function connect(port) {
|
|
308
|
+
if (port.name !== LOCK_PORT) return;
|
|
309
|
+
try { senderOrigin(port.sender); } catch (_error) { port.disconnect(); return; }
|
|
310
|
+
let heldKey = '', job = null, closed = false;
|
|
311
|
+
function pump(key) {
|
|
312
|
+
if (locks.has(key)) return;
|
|
313
|
+
const queue = queues.get(key);
|
|
314
|
+
while (queue?.length) {
|
|
315
|
+
const next = queue.shift();
|
|
316
|
+
if (next.closed()) continue;
|
|
317
|
+
const token = crypto.randomUUID();
|
|
318
|
+
const held = { token, tabId: next.tabId, port: next.port, inFlight: 0, disconnected: false,
|
|
319
|
+
release() {
|
|
320
|
+
if (locks.get(key) !== held) return;
|
|
321
|
+
locks.delete(key); pump(key);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
locks.set(key, held);
|
|
325
|
+
next.grant(token); return;
|
|
326
|
+
}
|
|
327
|
+
queues.delete(key);
|
|
328
|
+
}
|
|
329
|
+
port.onMessage.addListener(message => {
|
|
330
|
+
if (message?.type === 'ping') { port.postMessage({ type: 'pong' }); return; }
|
|
331
|
+
if (message?.type !== 'acquire' || job) return;
|
|
332
|
+
try {
|
|
333
|
+
const value = scope(message.scope), kind = message.kind === 'preferences' ? 'preferences' : 'state';
|
|
334
|
+
heldKey = keyFor(kind, value);
|
|
335
|
+
job = { port, tabId: port.sender.tab.id, closed: () => closed, grant: token => port.postMessage({ type: 'granted', token }) };
|
|
336
|
+
if (!queues.has(heldKey)) queues.set(heldKey, []);
|
|
337
|
+
queues.get(heldKey).push(job);
|
|
338
|
+
pump(heldKey);
|
|
339
|
+
} catch (_error) { port.disconnect(); }
|
|
340
|
+
});
|
|
341
|
+
port.onDisconnect.addListener(() => {
|
|
342
|
+
closed = true;
|
|
343
|
+
const held = locks.get(heldKey);
|
|
344
|
+
if (held?.port === port) {
|
|
345
|
+
held.disconnected = true;
|
|
346
|
+
if (!held.inFlight) held.release();
|
|
347
|
+
} else if (heldKey) pump(heldKey);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function install() {
|
|
351
|
+
chromeApi.runtime.onConnect.addListener(connect);
|
|
352
|
+
chromeApi.runtime.onMessage.addListener((message, sender, respond) => {
|
|
353
|
+
if (message?.type !== MESSAGE) return undefined;
|
|
354
|
+
let held;
|
|
355
|
+
try {
|
|
356
|
+
const candidate = locks.get(keyFor('state', scope(message.scope)));
|
|
357
|
+
if (candidate?.token === message.lockToken && candidate.tabId === sender?.tab?.id) {
|
|
358
|
+
held = candidate; held.inFlight += 1;
|
|
359
|
+
}
|
|
360
|
+
} catch (_error) { /* The handler returns the scoped validation error. */ }
|
|
361
|
+
handle(message, sender).then(result => respond({ ok: true, result }),
|
|
362
|
+
error => respond({ ok: false, error: { code: error.code || 'shared_store_unavailable',
|
|
363
|
+
message: error.code ? error.message : 'Shared session storage is unavailable.' } }))
|
|
364
|
+
.finally(() => {
|
|
365
|
+
if (!held) return;
|
|
366
|
+
held.inFlight -= 1;
|
|
367
|
+
if (held.disconnected && !held.inFlight) held.release();
|
|
368
|
+
});
|
|
369
|
+
return true;
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
return { install, handle };
|
|
373
|
+
}
|
|
374
|
+
function installBackground(chromeApi) {
|
|
375
|
+
const service = createService({ chromeApi, indexedDB, IDBKeyRange,
|
|
376
|
+
mergeSessionReviewState: globalThis.CodexOverleafStorageRunActions?.mergeSessionReviewState });
|
|
377
|
+
service.install(); return service;
|
|
378
|
+
}
|
|
379
|
+
return { createService, installBackground, mergeValue };
|
|
380
|
+
});
|