codex-overleaf-link 2.4.0 → 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 -311
- package/README.zh-CN.md +287 -326
- 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 +572 -571
- 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 +8974 -1781
- 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 +51 -120
- 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 +364 -356
- 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 +194 -164
- package/extension/src/content/scopedPersistenceCoordinator.js +2 -1
- package/extension/src/content/scopedPersistencePanelState.js +45 -2
- package/extension/src/content/selectionContextView.js +300 -0
- package/extension/src/content/sessionPersistence.js +10 -2
- package/extension/src/content/settingsPanel.js +93 -54
- 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 +58 -3
- 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 +139 -150
- package/extension/src/page/treeOperations.js +36 -29
- package/extension/src/page/writebackReceiptJournal.js +112 -0
- package/extension/src/page/writebackRouter.js +176 -136
- package/extension/src/pageBridge.js +59 -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 +187 -65
- 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 +23 -55
- package/extension/src/shared/storageMigration.js +3 -0
- package/extension/src/shared/storageRunActions.js +54 -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 +2136 -744
- 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 +146 -177
- package/native-host/src/codexSessionTiming.js +71 -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/readProgressGuard.js +84 -17
- 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
|
@@ -98,6 +98,11 @@
|
|
|
98
98
|
if (!journal?.terminal && !journal?.ownerLost) {
|
|
99
99
|
continue;
|
|
100
100
|
}
|
|
101
|
+
// Native completion can precede the owner's writeback and durable
|
|
102
|
+
// session save. A passive shared-history reader must not settle it.
|
|
103
|
+
if (options.requireOwnerLost === true && journal.ownerLost !== true) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
101
106
|
const session = options.findSession?.(journal.sessionId);
|
|
102
107
|
if (!session) {
|
|
103
108
|
continue;
|
|
@@ -112,6 +117,9 @@
|
|
|
112
117
|
if (!record) {
|
|
113
118
|
continue;
|
|
114
119
|
}
|
|
120
|
+
if (record.status === 'running') {
|
|
121
|
+
options.normalizeInterruptedRun?.(record);
|
|
122
|
+
}
|
|
115
123
|
const reloadReports = (record.events || []).filter(event => event?.failure?.source === 'panel_reload');
|
|
116
124
|
record.events = (record.events || []).filter(event => event?.failure?.source !== 'panel_reload');
|
|
117
125
|
const lastSequence = Number(record.nativeEventSeq || 0);
|
|
@@ -9,38 +9,128 @@
|
|
|
9
9
|
|
|
10
10
|
function create(deps = {}) {
|
|
11
11
|
const { callPageBridge, sendBackgroundNative } = deps;
|
|
12
|
+
const now = deps.now || Date.now;
|
|
13
|
+
const delay = deps.delay || (ms => new Promise(resolve => setTimeout(resolve, ms)));
|
|
12
14
|
|
|
13
15
|
async function applyOperations(input = {}) {
|
|
14
16
|
const results = [];
|
|
15
|
-
|
|
17
|
+
const deadlineAt = Number.isFinite(input.deadlineAt) && input.deadlineAt > 0 ? input.deadlineAt : null;
|
|
18
|
+
const invalidDeadline = input.deadlineAt !== undefined && deadlineAt === null;
|
|
19
|
+
const expired = () => invalidDeadline || (deadlineAt !== null && now() >= deadlineAt);
|
|
20
|
+
let textBatch = [], blocked = false;
|
|
21
|
+
function skipUndispatched(operations) {
|
|
22
|
+
const result = normalizeTextResult({ ok: false,
|
|
23
|
+
code: blocked ? 'writeback_tail_not_started' : 'writeback_deadline_exceeded',
|
|
24
|
+
error: blocked ? 'An earlier writeback is unconfirmed. This operation was not dispatched.'
|
|
25
|
+
: invalidDeadline ? 'The writeback deadline is invalid. This operation was not dispatched.'
|
|
26
|
+
: 'The writeback deadline has elapsed. This operation was not dispatched.',
|
|
27
|
+
changedDocument: false }, operations);
|
|
28
|
+
result.receiptUnconfirmed = false;
|
|
29
|
+
results.push(result);
|
|
30
|
+
}
|
|
16
31
|
async function flushTextBatch() {
|
|
17
32
|
if (!textBatch.length) return;
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
const operations = textBatch;
|
|
34
|
+
textBatch = [];
|
|
35
|
+
if (blocked || expired()) { skipUndispatched(operations); return; }
|
|
36
|
+
const response = await callPageBridge('applyOperations', {
|
|
37
|
+
operations,
|
|
20
38
|
baseFiles: input.baseFiles || [],
|
|
39
|
+
reviewingPolicy: input.reviewingPolicy || '',
|
|
40
|
+
...(deadlineAt !== null ? { deadlineAt } : {}),
|
|
21
41
|
requireReviewing: input.requireReviewing === true,
|
|
22
42
|
requireEditing: input.requireEditing === true,
|
|
43
|
+
retryCreates: input.retryCreates === true,
|
|
23
44
|
runProjectId: input.runProjectId || ''
|
|
24
|
-
})
|
|
25
|
-
|
|
45
|
+
});
|
|
46
|
+
const recovered = response?.code === 'page_bridge_timeout' && response.requestId
|
|
47
|
+
? await recoverTextReceipt(response, operations, input.runProjectId || '', deadlineAt)
|
|
48
|
+
: response;
|
|
49
|
+
const result = normalizeTextResult(recovered, operations);
|
|
50
|
+
results.push(result);
|
|
51
|
+
blocked = result.receiptUnconfirmed === true;
|
|
26
52
|
}
|
|
27
53
|
for (const operation of Array.isArray(input.operations) ? input.operations : []) {
|
|
54
|
+
if (blocked || expired()) {
|
|
55
|
+
skipUndispatched([operation]);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
28
58
|
if (!BINARY_TYPES.has(operation?.type)) {
|
|
29
59
|
textBatch.push(operation);
|
|
30
60
|
continue;
|
|
31
61
|
}
|
|
32
62
|
await flushTextBatch();
|
|
33
|
-
|
|
63
|
+
if (blocked || expired()) {
|
|
64
|
+
skipUndispatched([operation]);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const binaryResult = await applyBinaryOperation(operation, input);
|
|
68
|
+
results.push(binaryResult);
|
|
69
|
+
blocked = binaryResult.receiptUnconfirmed === true;
|
|
34
70
|
}
|
|
35
71
|
await flushTextBatch();
|
|
36
72
|
return mergeApplyResults(results);
|
|
37
73
|
}
|
|
38
74
|
|
|
75
|
+
async function recoverTextReceipt(timeout, operations, runProjectId, deadlineAt = null) {
|
|
76
|
+
const budget = Number.isFinite(deps.receiptTimeoutMs) ? Math.max(0, deps.receiptTimeoutMs)
|
|
77
|
+
: Math.min(600000, Math.max(90000, operations.length * 60000));
|
|
78
|
+
const deadline = deadlineAt ?? (now() + budget);
|
|
79
|
+
let partial = {}, state = 'unavailable', recoveryError = '', first = true;
|
|
80
|
+
while (deadlineAt === null ? (first || now() <= deadline) : now() < deadline) {
|
|
81
|
+
first = false;
|
|
82
|
+
let receipt, transportFailed = false;
|
|
83
|
+
try {
|
|
84
|
+
receipt = await callPageBridge('getWritebackReceipt', { requestId: timeout.requestId, runProjectId,
|
|
85
|
+
...(deadlineAt !== null ? { deadlineAt } : {}) });
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (error?.code === 'codex_cancelled' || error?.cancelled === true) throw error;
|
|
88
|
+
recoveryError = error?.message || String(error);
|
|
89
|
+
if (!isTransientReceiptFailure(error)) break;
|
|
90
|
+
transportFailed = true;
|
|
91
|
+
}
|
|
92
|
+
if (!transportFailed) {
|
|
93
|
+
if (receipt?.code === 'codex_cancelled' || receipt?.cancelled === true) {
|
|
94
|
+
throw responseError(receipt, 'codex_cancelled');
|
|
95
|
+
}
|
|
96
|
+
if (receipt?.ok !== true) {
|
|
97
|
+
recoveryError = receipt?.error?.message || receipt?.error || receipt?.reason
|
|
98
|
+
|| 'Writeback receipt could not be read.';
|
|
99
|
+
if (!isTransientReceiptFailure(receipt)) break;
|
|
100
|
+
} else {
|
|
101
|
+
if (receipt.requestId !== timeout.requestId || receipt.runProjectId !== runProjectId) {
|
|
102
|
+
recoveryError = 'Writeback receipt identity could not be confirmed.';
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
state = receipt.state;
|
|
106
|
+
if (receipt.result && typeof receipt.result === 'object') partial = receipt.result;
|
|
107
|
+
if (state === 'completed') {
|
|
108
|
+
if (!receipt.result || typeof receipt.result !== 'object') {
|
|
109
|
+
recoveryError = 'The completed writeback receipt has no result.';
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
if (deadlineAt !== null && now() > deadline) break;
|
|
113
|
+
return { ...partial,
|
|
114
|
+
receiptRecovery: { requestId: timeout.requestId, recovered: true, initialError: timeout.error } };
|
|
115
|
+
}
|
|
116
|
+
if (state !== 'running') {
|
|
117
|
+
recoveryError = 'The original writeback receipt is no longer available.';
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (now() >= deadline) break;
|
|
123
|
+
await delay(Math.min(deps.receiptPollMs || 500, Math.max(1, deadline - now())));
|
|
124
|
+
}
|
|
125
|
+
return { ...timeout, ...partial, ok: false, code: timeout.code, error: timeout.error,
|
|
126
|
+
requestId: timeout.requestId, receiptUnconfirmed: true, receiptState: state, recoveryError };
|
|
127
|
+
}
|
|
128
|
+
|
|
39
129
|
async function applyBinaryOperation(operation, input) {
|
|
40
130
|
const transferId = `asset_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
41
131
|
const assetRef = operation.assetRef || null;
|
|
42
132
|
const safeOperation = sanitizeOperation(operation);
|
|
43
|
-
let pageBegun = false;
|
|
133
|
+
let pageBegun = false, commitAttempted = false;
|
|
44
134
|
try {
|
|
45
135
|
const begin = await callPageBridge('binaryUploadBegin', {
|
|
46
136
|
transferId,
|
|
@@ -66,6 +156,7 @@
|
|
|
66
156
|
} else {
|
|
67
157
|
throw codedError('binary_asset_payload_missing', 'Binary asset payload is unavailable.');
|
|
68
158
|
}
|
|
159
|
+
commitAttempted = true;
|
|
69
160
|
const committed = await callPageBridge('binaryUploadCommit', {
|
|
70
161
|
transferId,
|
|
71
162
|
runProjectId: input.runProjectId || ''
|
|
@@ -73,12 +164,37 @@
|
|
|
73
164
|
if (!committed?.ok) throw responseError(committed, committed?.code || 'binary_upload_failed');
|
|
74
165
|
return { ok: true, applied: [{ operation: safeOperation, result: committed }], skipped: [] };
|
|
75
166
|
} catch (error) {
|
|
76
|
-
|
|
167
|
+
let changedDocument = error?.changedDocument === true
|
|
168
|
+
|| (commitAttempted && error?.changedDocument !== false);
|
|
169
|
+
if (commitAttempted && changedDocument) {
|
|
170
|
+
const deadline = now() + 30000;
|
|
171
|
+
do {
|
|
172
|
+
const receipt = await callPageBridge('binaryUploadStatus', {
|
|
173
|
+
transferId, runProjectId: input.runProjectId || ''
|
|
174
|
+
}).catch(() => null);
|
|
175
|
+
if (!receipt?.ok || receipt.transferId !== transferId
|
|
176
|
+
|| receipt.runProjectId !== input.runProjectId) break;
|
|
177
|
+
if (receipt.result?.ok === true) {
|
|
178
|
+
return { ok: true, applied: [{ operation: safeOperation, result: receipt.result }], skipped: [],
|
|
179
|
+
receiptRecovery: { transferId, recovered: true, initialError: error.message } };
|
|
180
|
+
}
|
|
181
|
+
if (receipt.state === 'completed' && receipt.changedDocument === false) {
|
|
182
|
+
changedDocument = false;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
if (now() >= deadline) break;
|
|
186
|
+
await delay(Math.min(500, Math.max(1, deadline - now())));
|
|
187
|
+
} while (now() <= deadline);
|
|
188
|
+
}
|
|
189
|
+
if (pageBegun && !commitAttempted) {
|
|
77
190
|
await callPageBridge('binaryUploadAbort', { transferId, runProjectId: input.runProjectId || '' }).catch(() => null);
|
|
78
191
|
}
|
|
79
192
|
const code = error.code || 'binary_upload_failed';
|
|
80
193
|
return {
|
|
81
194
|
ok: false,
|
|
195
|
+
receiptUnconfirmed: changedDocument,
|
|
196
|
+
error: error.message || 'Binary asset upload failed.',
|
|
197
|
+
code,
|
|
82
198
|
applied: [],
|
|
83
199
|
skipped: [{
|
|
84
200
|
operation: safeOperation,
|
|
@@ -87,8 +203,8 @@
|
|
|
87
203
|
ok: false,
|
|
88
204
|
code,
|
|
89
205
|
reason: error.message || 'Binary asset upload failed.',
|
|
90
|
-
changedDocument
|
|
91
|
-
failure: { code, stage: 'write', file: operation.path, changedDocument
|
|
206
|
+
changedDocument,
|
|
207
|
+
failure: { code, stage: 'write', file: operation.path, changedDocument }
|
|
92
208
|
}
|
|
93
209
|
}]
|
|
94
210
|
};
|
|
@@ -129,6 +245,42 @@
|
|
|
129
245
|
return { applyOperations };
|
|
130
246
|
}
|
|
131
247
|
|
|
248
|
+
function normalizeTextResult(response, operations) {
|
|
249
|
+
const result = response && typeof response === 'object' ? { ...response } : { ok: false };
|
|
250
|
+
result.applied = Array.isArray(result.applied) ? result.applied : [];
|
|
251
|
+
result.skipped = Array.isArray(result.skipped) ? result.skipped.slice() : [];
|
|
252
|
+
const key = operation => [operation?.type, operation?.path, operation?.to || ''].join('\0');
|
|
253
|
+
const known = new Map();
|
|
254
|
+
for (const entry of [...result.applied, ...result.skipped]) {
|
|
255
|
+
const id = key(entry.operation); known.set(id, (known.get(id) || 0) + 1);
|
|
256
|
+
}
|
|
257
|
+
const missing = [];
|
|
258
|
+
for (const operation of operations) {
|
|
259
|
+
const id = key(operation), count = known.get(id) || 0;
|
|
260
|
+
if (count) known.set(id, count - 1); else missing.push(operation);
|
|
261
|
+
}
|
|
262
|
+
if (!missing.length && (result.ok !== false || result.skipped.length)) return result;
|
|
263
|
+
const code = result.code || 'writeback_result_unconfirmed';
|
|
264
|
+
const error = typeof result.error === 'string' ? result.error
|
|
265
|
+
: result.error?.message || 'The page did not return a complete writeback result.';
|
|
266
|
+
const changedDocument = result.changedDocument !== false;
|
|
267
|
+
for (const operation of missing.length ? missing : [null]) {
|
|
268
|
+
const reason = changedDocument
|
|
269
|
+
? 'Write status is unconfirmed; Overleaf may already contain changes. Check the project before retrying. ' + error
|
|
270
|
+
: error;
|
|
271
|
+
result.skipped.push({ operation, path: operation?.path || '', result: {
|
|
272
|
+
ok: false, code, reason, changedDocument, failure: {
|
|
273
|
+
code, stage: 'write', severity: 'warning', terminalState: 'needs_review', retryable: false,
|
|
274
|
+
file: operation?.path || '', userMessage: reason,
|
|
275
|
+
nextAction: 'Check the current Overleaf files and original writeback result before starting another write.',
|
|
276
|
+
changedDocument, evidence: { requestId: result.requestId || '', receiptState: result.receiptState || '',
|
|
277
|
+
transportError: error, recoveryError: result.recoveryError || '' }
|
|
278
|
+
}
|
|
279
|
+
} });
|
|
280
|
+
}
|
|
281
|
+
return { ...result, ok: false, code, error, receiptUnconfirmed: true };
|
|
282
|
+
}
|
|
283
|
+
|
|
132
284
|
function mergeApplyResults(results) {
|
|
133
285
|
const merged = { ok: true, applied: [], skipped: [], trackedChanges: [] };
|
|
134
286
|
for (const result of results) {
|
|
@@ -139,8 +291,18 @@
|
|
|
139
291
|
// recordUndoFromApply classify a successful Track write as legacy Undo,
|
|
140
292
|
// which hides Accept and prevents the lifecycle from surviving reload.
|
|
141
293
|
merged.trackedChanges.push(...(Array.isArray(result?.trackedChanges) ? result.trackedChanges : []));
|
|
294
|
+
if (result?.reviewingPolicy !== undefined) merged.reviewingPolicy = result.reviewingPolicy;
|
|
142
295
|
if (result?.trackedChangeCaptures?.length) (merged.trackedChangeCaptures ||= []).push(...result.trackedChangeCaptures);
|
|
143
|
-
if (result?.ok !== true)
|
|
296
|
+
if (result?.ok !== true) {
|
|
297
|
+
merged.ok = false;
|
|
298
|
+
for (const key of ['code', 'error', 'failure', 'requestId', 'receiptState', 'recoveryError']) {
|
|
299
|
+
if (result?.[key] !== undefined && merged[key] === undefined) merged[key] = result[key];
|
|
300
|
+
}
|
|
301
|
+
if (result?.receiptUnconfirmed !== undefined) {
|
|
302
|
+
merged.receiptUnconfirmed = merged.receiptUnconfirmed === true || result.receiptUnconfirmed === true;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (result?.receiptRecovery) (merged.receiptRecoveries ||= []).push(result.receiptRecovery);
|
|
144
306
|
}
|
|
145
307
|
if (merged.trackedChangeCaptures?.some(capture => capture.state !== 'observed')) merged.trackedChanges = [];
|
|
146
308
|
if (merged.skipped.length) merged.ok = false;
|
|
@@ -160,11 +322,23 @@
|
|
|
160
322
|
return safe;
|
|
161
323
|
}
|
|
162
324
|
|
|
325
|
+
function isTransientReceiptFailure(value) {
|
|
326
|
+
const code = value?.code || value?.error?.code;
|
|
327
|
+
if (code) return ['page_bridge_timeout', 'page_bridge_unavailable', 'page_bridge_transport_error',
|
|
328
|
+
'page_bridge_disconnected', 'network_error', 'ETIMEDOUT', 'ECONNRESET', 'ECONNABORTED',
|
|
329
|
+
'EPIPE', 'ERR_NETWORK'].includes(code);
|
|
330
|
+
const message = value?.message || value?.error?.message || value?.error || '';
|
|
331
|
+
return /timed?\s*out|timeout|network|transport|bridge unavailable|port.*closed|receiving end|socket hang up/i.test(String(message));
|
|
332
|
+
}
|
|
333
|
+
|
|
163
334
|
function responseError(response, fallbackCode) {
|
|
164
|
-
|
|
335
|
+
const error = codedError(
|
|
165
336
|
response?.code || response?.error?.code || fallbackCode,
|
|
166
337
|
response?.reason || response?.error?.message || response?.error || 'Asset transfer failed.'
|
|
167
338
|
);
|
|
339
|
+
if (typeof response?.changedDocument === 'boolean') error.changedDocument = response.changedDocument;
|
|
340
|
+
error.stage = response?.failure?.stage || 'write';
|
|
341
|
+
return error;
|
|
168
342
|
}
|
|
169
343
|
function codedError(code, message) { const error = new Error(String(message || code)); error.code = code; return error; }
|
|
170
344
|
return { create, mergeApplyResults };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
(function initChangeHistoryView(root, factory) {
|
|
2
|
+
root.CodexOverleafModuleRegistry.define('ChangeHistoryView', ['ChangeHistoryModel'], factory);
|
|
3
|
+
})(typeof globalThis !== 'undefined' ? globalThis : window, function changeHistoryViewFactory(Model) {
|
|
4
|
+
'use strict';
|
|
5
|
+
function create(deps) {
|
|
6
|
+
const { tx, StorageDb, getState, getCurrentProjectId, getAccountScopeId,
|
|
7
|
+
getSettingsPanelInstance, onHistoryRowJump, sanitizeText } = deps;
|
|
8
|
+
let generation = 0, owner = null, records = [], storedSessions = [], limit = 8, loading = false, error = '';
|
|
9
|
+
const container = () => getSettingsPanelInstance()?.container;
|
|
10
|
+
const make = (tag, className, text) => {
|
|
11
|
+
const element = document.createElement(tag); element.className = className;
|
|
12
|
+
if (text !== undefined) element.textContent = text;
|
|
13
|
+
return element;
|
|
14
|
+
};
|
|
15
|
+
function icon(kind) {
|
|
16
|
+
const node = make('span', 'codex-history-icon');
|
|
17
|
+
node.setAttribute('aria-hidden', 'true');
|
|
18
|
+
const paths = {
|
|
19
|
+
file: '<path d="M9 2H4v12h8V5L9 2Z M9 2v4h3 M6 9h4 M6 11h3"/>',
|
|
20
|
+
message: '<path d="M3 3h10v8H7l-4 3V3Z M5 6h6 M5 8h4"/>',
|
|
21
|
+
arrow: '<path d="M4 12 12 4 M5 4h7v7"/>'
|
|
22
|
+
};
|
|
23
|
+
node.innerHTML = '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round">' + paths[kind] + '</svg>';
|
|
24
|
+
return node;
|
|
25
|
+
}
|
|
26
|
+
function label(state) {
|
|
27
|
+
return ({
|
|
28
|
+
pending: tx('Pending review', '待接受'), accepted: tx('Accepted', '已接受'),
|
|
29
|
+
undone: tx('Undone', '已撤销'), attention: tx('Needs attention', '需检查'),
|
|
30
|
+
written: tx('Written', '已写入'), running: tx('In progress', '进行中'),
|
|
31
|
+
unchanged: tx('No file changes', '未修改文件'), unknown: tx('Status unavailable', '状态不可用')
|
|
32
|
+
})[state] || '';
|
|
33
|
+
}
|
|
34
|
+
function title(row) {
|
|
35
|
+
if (row.summary) return row.summary;
|
|
36
|
+
if (!row.hasWrites) return tx('Task without file changes', '未修改文件的任务');
|
|
37
|
+
if (row.status === 'attention') return row.paths.length === 1
|
|
38
|
+
? tx('Check changes to ', '检查文件修改:') + row.paths[0] : tx('File changes need attention', '文件修改需要检查');
|
|
39
|
+
if (row.paths.length === 1) {
|
|
40
|
+
const verbs = { create: ['Created ', '新建 '], 'binary-create': ['Created ', '新建 '],
|
|
41
|
+
delete: ['Deleted ', '删除 '], move: ['Moved ', '移动 '], rename: ['Renamed ', '重命名 '] };
|
|
42
|
+
const verb = verbs[row.operation] || ['Updated ', '修改 '];
|
|
43
|
+
return tx(verb[0], verb[1]) + row.paths[0];
|
|
44
|
+
}
|
|
45
|
+
return row.paths.length ? tx('Changed ' + row.paths.length + ' files', '修改 ' + row.paths.length + ' 个文件')
|
|
46
|
+
: tx('Project file changes', '项目文件修改');
|
|
47
|
+
}
|
|
48
|
+
function when(value) {
|
|
49
|
+
const date = new Date(value);
|
|
50
|
+
if (!Number.isFinite(date.getTime())) return tx('Time unavailable', '时间不可用');
|
|
51
|
+
const locale = getState()?.locale === 'zh' ? 'zh-CN' : 'en';
|
|
52
|
+
const now = new Date(), yesterday = new Date(now); yesterday.setDate(now.getDate() - 1);
|
|
53
|
+
const day = date.toDateString() === now.toDateString() ? tx('Today', '今天')
|
|
54
|
+
: date.toDateString() === yesterday.toDateString() ? tx('Yesterday', '昨天')
|
|
55
|
+
: date.toLocaleDateString(locale, { month: 'short', day: 'numeric', ...(date.getFullYear() !== now.getFullYear() ? { year: 'numeric' } : {}) });
|
|
56
|
+
return day + ' ' + date.toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit', hour12: false });
|
|
57
|
+
}
|
|
58
|
+
function current(snapshot) {
|
|
59
|
+
return snapshot && snapshot.projectId === getCurrentProjectId()
|
|
60
|
+
&& snapshot.accountScopeId === getAccountScopeId?.() && snapshot.container === container();
|
|
61
|
+
}
|
|
62
|
+
function message(list, content, retry = false) {
|
|
63
|
+
const empty = make('div', 'codex-history-empty', content);
|
|
64
|
+
if (retry) {
|
|
65
|
+
const button = make('button', 'codex-history-jump', tx('Try again', '重试'));
|
|
66
|
+
button.type = 'button'; button.addEventListener('click', load); empty.append(button);
|
|
67
|
+
}
|
|
68
|
+
list.replaceChildren(empty);
|
|
69
|
+
}
|
|
70
|
+
function render() {
|
|
71
|
+
const host = container(), list = host?.querySelector('[data-history-list]');
|
|
72
|
+
if (!list) return;
|
|
73
|
+
const search = host.querySelector('[data-history-filter]');
|
|
74
|
+
search.placeholder = tx('Search files or summaries', '搜索文件或修改摘要');
|
|
75
|
+
search.setAttribute('aria-label', search.placeholder);
|
|
76
|
+
const count = host.querySelector('[data-history-count]');
|
|
77
|
+
const toggle = host.querySelector('[data-history-include-empty]');
|
|
78
|
+
const includeLabel = host.querySelector('[data-history-include-label]');
|
|
79
|
+
const more = host.querySelector('[data-history-more]');
|
|
80
|
+
if (count) count.textContent = '';
|
|
81
|
+
if (more) more.hidden = true;
|
|
82
|
+
if (loading || error || !current(owner)) {
|
|
83
|
+
if (toggle?.parentElement) toggle.parentElement.hidden = true;
|
|
84
|
+
message(list, loading ? tx('Loading file changes…', '正在读取文件修改记录…')
|
|
85
|
+
: error || tx('Open this project again to load its history.', '重新打开本项目以读取历史记录。'), Boolean(error));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const state = getState();
|
|
89
|
+
const projected = Model.project(records, {
|
|
90
|
+
projectId: owner.projectId, accountScopeId: owner.accountScopeId,
|
|
91
|
+
storedSessions, sessions: state.sessions, activeSessionId: state.activeSessionId, activeRuns: state.runs,
|
|
92
|
+
sanitizeText
|
|
93
|
+
});
|
|
94
|
+
const query = search.value.trim().toLowerCase();
|
|
95
|
+
const selected = host.querySelector('[data-history-status]')?.value || 'all';
|
|
96
|
+
const rows = projected.filter(row => (toggle?.checked || row.hasWrites)
|
|
97
|
+
&& (selected === 'all' || row.status === selected)
|
|
98
|
+
&& (!query || [title(row), ...row.paths].join(' ').toLowerCase().includes(query)));
|
|
99
|
+
if (count) count.textContent = tx(rows.length + ' records', rows.length + ' 条');
|
|
100
|
+
const noWrites = projected.filter(row => !row.hasWrites).length;
|
|
101
|
+
if (toggle?.parentElement) toggle.parentElement.hidden = noWrites === 0;
|
|
102
|
+
if (includeLabel) includeLabel.textContent = tx('Include ' + noWrites + ' tasks without file changes', '同时显示 ' + noWrites + ' 条未修改文件的任务');
|
|
103
|
+
list.replaceChildren();
|
|
104
|
+
if (!rows.length) {
|
|
105
|
+
message(list, query || selected !== 'all'
|
|
106
|
+
? tx('No matching file changes. Try another file name or status.', '没有匹配的修改记录,可尝试其他文件名或状态。')
|
|
107
|
+
: tx('No file changes recorded for this project yet.', '本项目还没有已记录的文件修改。'));
|
|
108
|
+
}
|
|
109
|
+
for (const row of rows.slice(0, limit)) {
|
|
110
|
+
const element = make('article', 'codex-history-row');
|
|
111
|
+
element.dataset.resultStatus = row.status;
|
|
112
|
+
const mark = make('span', 'codex-history-mark'); mark.append(icon(row.hasWrites ? 'file' : 'message'));
|
|
113
|
+
const body = make('div', 'codex-history-copy'), top = make('div', 'codex-history-top');
|
|
114
|
+
const name = make('div', 'codex-history-task', title(row));
|
|
115
|
+
const status = make('span', 'codex-history-status', label(row.status)); status.dataset.state = row.status;
|
|
116
|
+
top.append(name, status);
|
|
117
|
+
const files = make('div', 'codex-history-files', row.paths.length ? row.paths.join(' · ')
|
|
118
|
+
: row.hasWrites ? tx('Detailed file names are no longer available.', '详细文件名已不可用。')
|
|
119
|
+
: tx('No files were written to Overleaf.', '没有向 Overleaf 写入文件。'));
|
|
120
|
+
const footer = make('div', 'codex-history-bottom');
|
|
121
|
+
const fileCount = row.paths.length ? tx(' · ' + row.paths.length + ' file(s)', ' · ' + row.paths.length + ' 个文件') : '';
|
|
122
|
+
footer.append(make('time', 'codex-history-when', when(row.createdAt) + fileCount));
|
|
123
|
+
const jump = make('button', 'codex-history-jump');
|
|
124
|
+
jump.type = 'button'; jump.disabled = !row.canJump;
|
|
125
|
+
jump.append(make('span', '', row.canJump ? tx('View conversation', '查看对应对话') : tx('Conversation unavailable', '对话不可用')));
|
|
126
|
+
if (row.canJump) jump.append(icon('arrow'));
|
|
127
|
+
jump.title = row.canJump ? tx('Open the original run', '定位到对应轮次')
|
|
128
|
+
: tx('The original run is no longer in the loaded conversation history.', '原轮次已不在当前可用的对话历史中。');
|
|
129
|
+
jump.setAttribute('aria-label', jump.textContent + ': ' + title(row));
|
|
130
|
+
const snapshot = owner;
|
|
131
|
+
jump.addEventListener('click', () => {
|
|
132
|
+
if (current(snapshot)) void onHistoryRowJump?.(row);
|
|
133
|
+
});
|
|
134
|
+
footer.append(jump); body.append(top, files, footer); element.append(mark, body); list.append(element);
|
|
135
|
+
}
|
|
136
|
+
if (more) {
|
|
137
|
+
more.hidden = rows.length <= limit;
|
|
138
|
+
more.textContent = tx('Show more (' + Math.min(8, rows.length - limit) + ')', '再显示 ' + Math.min(8, rows.length - limit) + ' 条');
|
|
139
|
+
more.onclick = () => { limit += 8; render(); };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function load() {
|
|
143
|
+
const host = container();
|
|
144
|
+
if (!host?.querySelector('[data-history-list]')) return;
|
|
145
|
+
const requestId = ++generation;
|
|
146
|
+
owner = { projectId: getCurrentProjectId(), accountScopeId: getAccountScopeId?.() || '', container: host };
|
|
147
|
+
const snapshot = owner;
|
|
148
|
+
records = []; storedSessions = []; limit = 8; error = '';
|
|
149
|
+
if (!snapshot.accountScopeId || !snapshot.projectId) {
|
|
150
|
+
loading = false; error = tx('Project identity is unavailable. Reopen the project to load its history.', '暂时无法确认项目身份,请重新打开项目后查看历史。'); render(); return;
|
|
151
|
+
}
|
|
152
|
+
loading = true; render();
|
|
153
|
+
let timer;
|
|
154
|
+
try {
|
|
155
|
+
const data = await Promise.race([
|
|
156
|
+
Promise.all([
|
|
157
|
+
StorageDb.getAllByIndex('auditLogs', 'projectId', snapshot.projectId),
|
|
158
|
+
StorageDb.getAllByIndex('sessions', 'projectId', snapshot.projectId)
|
|
159
|
+
]),
|
|
160
|
+
new Promise((_, reject) => { timer = setTimeout(() => reject(new Error('history_load_timeout')), 3000); })
|
|
161
|
+
]);
|
|
162
|
+
if (requestId !== generation || !current(snapshot)) return;
|
|
163
|
+
[records, storedSessions] = data;
|
|
164
|
+
loading = false; render();
|
|
165
|
+
} catch (_) {
|
|
166
|
+
if (requestId !== generation || !current(snapshot)) return;
|
|
167
|
+
loading = false; error = tx('File changes could not be loaded.', '暂时无法读取文件修改记录。'); render();
|
|
168
|
+
} finally { clearTimeout(timer); }
|
|
169
|
+
}
|
|
170
|
+
return { load, filter() { limit = 8; render(); }, invalidate() {
|
|
171
|
+
generation += 1; records = []; storedSessions = []; owner = null; loading = false; error = '';
|
|
172
|
+
} };
|
|
173
|
+
}
|
|
174
|
+
return { create };
|
|
175
|
+
});
|
|
@@ -361,54 +361,56 @@
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
function renderAttachmentPreviewList(attachments = [], container, options = {}) {
|
|
364
|
-
if (!container)
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
364
|
+
if (!container) return;
|
|
367
365
|
container.replaceChildren();
|
|
368
366
|
const items = Array.isArray(attachments) ? attachments : [];
|
|
369
367
|
container.hidden = items.length === 0;
|
|
370
368
|
for (const attachment of items) {
|
|
371
369
|
const isImage = attachment.kind === 'image' && attachment.previewDataUrl;
|
|
372
|
-
const
|
|
370
|
+
const label = attachment.name || (options.tx ? options.tx('Attachment', '附件') : 'Attachment');
|
|
371
|
+
const card = document.createElement('div');
|
|
373
372
|
card.className = 'codex-attachment-preview-card';
|
|
374
373
|
card.dataset.kind = isImage ? 'image' : 'file';
|
|
374
|
+
card.title = label + ' · ' + formatFileSize(attachment.size);
|
|
375
375
|
if (isImage) {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
376
|
+
const preview = document.createElement('button');
|
|
377
|
+
preview.type = 'button';
|
|
378
|
+
preview.className = 'codex-attachment-preview-open';
|
|
379
|
+
preview.setAttribute('aria-label', options.tx ? options.tx('Preview ' + label, '预览 ' + label) : 'Preview ' + label);
|
|
380
|
+
preview.addEventListener('click', () => showAttachmentPreviewDialog(attachment, options));
|
|
381
381
|
const image = document.createElement('img');
|
|
382
382
|
image.src = attachment.previewDataUrl;
|
|
383
|
-
image.alt =
|
|
384
|
-
|
|
383
|
+
image.alt = label;
|
|
384
|
+
preview.append(image);
|
|
385
|
+
card.append(preview);
|
|
385
386
|
} else {
|
|
386
387
|
const icon = document.createElement('span');
|
|
387
388
|
icon.className = 'codex-attachment-file-icon';
|
|
388
389
|
icon.textContent = getAttachmentIconLabel(attachment);
|
|
390
|
+
icon.setAttribute('aria-hidden', 'true');
|
|
389
391
|
card.append(icon);
|
|
390
392
|
}
|
|
391
|
-
|
|
392
393
|
const meta = document.createElement('span');
|
|
393
394
|
meta.className = 'codex-attachment-preview-meta';
|
|
394
395
|
const name = document.createElement('span');
|
|
395
396
|
name.className = 'codex-attachment-preview-name';
|
|
396
|
-
name.textContent =
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
397
|
+
name.textContent = label;
|
|
398
|
+
meta.append(name);
|
|
399
|
+
if (!isImage) {
|
|
400
|
+
const size = document.createElement('span');
|
|
401
|
+
size.className = 'codex-attachment-preview-size';
|
|
402
|
+
size.textContent = formatFileSize(attachment.size);
|
|
403
|
+
meta.append(size);
|
|
404
|
+
}
|
|
401
405
|
card.append(meta);
|
|
402
|
-
|
|
403
406
|
if (options.removable) {
|
|
404
407
|
const remove = document.createElement('button');
|
|
405
408
|
remove.type = 'button';
|
|
406
409
|
remove.className = 'codex-attachment-preview-remove';
|
|
407
410
|
remove.textContent = '×';
|
|
408
|
-
|
|
409
|
-
remove.
|
|
410
|
-
|
|
411
|
-
: `Remove ${attachment.name}`);
|
|
411
|
+
const removeLabel = options.tx ? options.tx('Remove ' + label, '移除 ' + label) : 'Remove ' + label;
|
|
412
|
+
remove.title = removeLabel;
|
|
413
|
+
remove.setAttribute('aria-label', removeLabel);
|
|
412
414
|
remove.addEventListener('click', event => {
|
|
413
415
|
event.preventDefault();
|
|
414
416
|
event.stopPropagation();
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
<div class="codex-pending-inputs" data-pending-inputs hidden></div>
|
|
19
19
|
<form class="codex-composer" data-composer-form>
|
|
20
20
|
<div class="codex-attachment-strip codex-attachment-preview-list" data-attachment-strip hidden></div>
|
|
21
|
+
<div class="codex-composer-selection" data-composer-selection hidden></div>
|
|
21
22
|
<div class="codex-composer-skill-context" data-composer-skill-context hidden>
|
|
22
23
|
<span class="codex-composer-skill-icon" aria-hidden="true">◇</span>
|
|
23
24
|
<span data-composer-skill-label></span>
|
|
@@ -35,17 +36,31 @@
|
|
|
35
36
|
<option value="ask">Ask</option>
|
|
36
37
|
<option value="auto">Auto</option>
|
|
37
38
|
</select>
|
|
39
|
+
<div class="codex-write-preferences">
|
|
40
|
+
<label class="codex-review-toggle" title="When enabled, Codex checks or switches Overleaf Reviewing/Track Changes before writing. Deletes still require confirmation.">
|
|
41
|
+
<input type="checkbox" data-require-reviewing>
|
|
42
|
+
<svg class="codex-composer-option-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
43
|
+
<path d="m9 11 8-8 4 4-8 8M9 11l4 4-3 3H6v-4l3-3ZM3 21h7"></path>
|
|
44
|
+
</svg>
|
|
45
|
+
<span class="codex-review-label" data-i18n="requireReviewing">Track</span>
|
|
46
|
+
<svg class="codex-composer-option-check" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
|
47
|
+
<path d="m3.5 8 3 3 6-6"></path>
|
|
48
|
+
</svg>
|
|
49
|
+
</label>
|
|
50
|
+
<label class="codex-recompile-toggle" title="Automatically recompile in Overleaf after Codex writes and record the result. Toggling this setting does not compile immediately. Ask mode does not trigger compilation.">
|
|
51
|
+
<input type="checkbox" data-auto-recompile>
|
|
52
|
+
<svg class="codex-composer-option-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
53
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8ZM14 2v6h6m-11 7 2 2 4-4"></path>
|
|
54
|
+
</svg>
|
|
55
|
+
<span class="codex-recompile-label" data-i18n="autoCompile">Auto compile</span>
|
|
56
|
+
<svg class="codex-composer-option-check" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
|
57
|
+
<path d="m3.5 8 3 3 6-6"></path>
|
|
58
|
+
</svg>
|
|
59
|
+
</label>
|
|
60
|
+
</div>
|
|
38
61
|
</div>
|
|
39
62
|
<div class="codex-composer-toolbar">
|
|
40
63
|
<button type="button" data-add-context title="Add @ context" aria-label="Add @ context" aria-expanded="false">+</button>
|
|
41
|
-
<label class="codex-review-toggle" title="When enabled, Codex checks or switches Overleaf Reviewing/Track Changes before writing. Deletes still require confirmation.">
|
|
42
|
-
<input type="checkbox" data-require-reviewing>
|
|
43
|
-
<span class="codex-review-label" data-i18n="requireReviewing">Track</span>
|
|
44
|
-
</label>
|
|
45
|
-
<label class="codex-recompile-toggle" title="After Codex writes, click Overleaf Recompile and record the compile result for this task. Ask mode will not trigger it.">
|
|
46
|
-
<input type="checkbox" data-auto-recompile>
|
|
47
|
-
<span class="codex-recompile-label" data-i18n="autoCompile">Compile</span>
|
|
48
|
-
</label>
|
|
49
64
|
<div class="codex-model-config" data-model-config>
|
|
50
65
|
<button type="button" class="codex-model-config-button" data-model-config-toggle aria-haspopup="menu" aria-expanded="false">
|
|
51
66
|
<span class="codex-model-speed-indicator" data-speed-indicator hidden aria-hidden="true">
|