codex-overleaf-link 2.4.1 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +275 -305
- package/README.zh-CN.md +290 -320
- package/extension/bootstrap/background.js +99 -19
- package/extension/bootstrap/manifest.template.json +9 -4
- package/extension/bootstrap/popup.html +11 -16
- package/extension/bootstrap/popupFallback.js +55 -0
- package/extension/bootstrap/update.js +25 -2
- package/extension/bootstrap/updateStatus.js +1 -0
- package/extension/runtime-manifest.json +3 -1
- package/extension/src/background.js +234 -56
- package/extension/src/backgroundBootstrapMigration.js +181 -0
- package/extension/src/backgroundSharedSessions.js +440 -0
- package/extension/src/backgroundUpdateCoordinator.js +541 -381
- package/extension/src/backgroundUpdateSafety.js +173 -0
- package/extension/src/content/activeTurnControl.js +16 -2
- package/extension/src/content/applyResultFormatters.js +46 -73
- package/extension/src/content/assetTransferBroker.js +244 -12
- package/extension/src/content/changeHistoryView.js +175 -0
- package/extension/src/content/composerAttachments.js +117 -67
- package/extension/src/content/composerPanel.js +41 -8
- package/extension/src/content/contentRuntime.js +1084 -1099
- package/extension/src/content/diagnosticsController.js +122 -97
- package/extension/src/content/diagnosticsExport.js +236 -0
- package/extension/src/content/diagnosticsPanel.js +78 -19
- package/extension/src/content/diffReviewPanel.js +8 -5
- package/extension/src/content/directoryCleanupRecovery.js +54 -0
- package/extension/src/content/generated/content.bundle.js +14680 -3606
- package/extension/src/content/generated/content.bundle.meta.json +30 -3
- package/extension/src/content/globalPreferencesController.js +1 -1
- package/extension/src/content/legacyGlobalRegistry.js +25 -1
- package/extension/src/content/localSkillsPanel.js +141 -16
- package/extension/src/content/markdownDomRenderer.js +9 -4
- package/extension/src/content/markdownText.js +5 -6
- package/extension/src/content/modelPicker.js +8 -5
- package/extension/src/content/nativeCompatibilityController.js +45 -20
- package/extension/src/content/otWarmMirror.js +4 -5
- package/extension/src/content/otWarmMirrorController.js +17 -20
- package/extension/src/content/pageBridgeClient.js +33 -5
- package/extension/src/content/panelMaintenance.js +87 -132
- package/extension/src/content/panelRenderer.js +10 -0
- package/extension/src/content/pendingInputView.js +109 -76
- package/extension/src/content/projectProviderSelection.js +13 -4
- package/extension/src/content/projectSessionCleanup.js +109 -62
- package/extension/src/content/projectSettingsCoordinator.js +39 -2
- package/extension/src/content/providerSettingsCoordinator.js +63 -14
- package/extension/src/content/providerSettingsDialog.js +724 -113
- package/extension/src/content/recentProjects.js +21 -6
- package/extension/src/content/runActivitySummary.js +665 -0
- package/extension/src/content/runCompletionMeta.js +344 -0
- package/extension/src/content/runController.js +40 -15
- package/extension/src/content/runFailureNotice.js +34 -12
- package/extension/src/content/runGuidanceController.js +76 -30
- package/extension/src/content/runGuidanceView.js +59 -10
- package/extension/src/content/runPresence.js +306 -0
- package/extension/src/content/runQueueScheduler.js +150 -43
- package/extension/src/content/runRecoveryActions.js +146 -0
- package/extension/src/content/runResultActions.js +11 -8
- package/extension/src/content/runReviewController.js +574 -0
- package/extension/src/content/runScrollLayout.js +21 -2
- package/extension/src/content/runTimelineView.js +315 -290
- package/extension/src/content/scopedPersistencePanelState.js +51 -6
- package/extension/src/content/selectionContextView.js +300 -0
- package/extension/src/content/sensitivePreflight.js +140 -0
- package/extension/src/content/sessionForkController.js +80 -17
- package/extension/src/content/sessionManager.js +1 -1
- package/extension/src/content/sessionPersistence.js +6 -1
- package/extension/src/content/settingsPanel.js +84 -55
- package/extension/src/content/settingsWorkbench.js +379 -0
- package/extension/src/content/sharedSessionViewSync.js +109 -0
- package/extension/src/content/subagentActivityView.js +195 -0
- package/extension/src/content/trackedChangeCaptureController.js +7 -3
- package/extension/src/content/updateIdle.js +4 -1
- package/extension/src/content/updateNotice.js +179 -56
- package/extension/src/content/updateSafetyReceiver.js +58 -0
- package/extension/src/content/writebackController.js +308 -2
- package/extension/src/content/writebackOrchestrator.js +213 -199
- package/extension/src/content/writebackPlan.js +231 -0
- package/extension/src/content/writebackRecovery.js +122 -0
- package/extension/src/content/writingStyleSettings.js +600 -0
- package/extension/src/content/writtenChangesView.js +152 -0
- package/extension/src/page/binaryAssetUploader.js +223 -23
- package/extension/src/page/fileMover.js +256 -0
- package/extension/src/page/overleafProjectSnapshot.js +1 -0
- package/extension/src/page/ownedDirectoryCleanup.js +94 -0
- package/extension/src/page/referenceProjects.js +149 -0
- package/extension/src/page/reviewContext.js +113 -0
- package/extension/src/page/saveState.js +20 -6
- package/extension/src/page/snapshotRouter.js +124 -48
- package/extension/src/page/textCoordinates.js +102 -0
- package/extension/src/page/textFileCreator.js +442 -71
- package/extension/src/page/trackedChangeCapture.js +53 -57
- package/extension/src/page/trackedChangeOwnership.js +216 -0
- package/extension/src/page/trackedChangeReplay.js +184 -0
- package/extension/src/page/trackedChangesLifecycle.js +343 -339
- package/extension/src/page/treeOperations.js +33 -12
- package/extension/src/page/updateSafetyProbe.js +41 -0
- package/extension/src/page/writebackReceiptJournal.js +114 -0
- package/extension/src/page/writebackRouter.js +242 -201
- package/extension/src/pageBridge.js +73 -102
- package/extension/src/popup.js +261 -65
- package/extension/src/shared/agentTranscript.js +41 -4
- package/extension/src/shared/auditRecords.js +73 -0
- package/extension/src/shared/changeHistoryModel.js +94 -0
- package/extension/src/shared/compatibility.js +22 -6
- package/extension/src/shared/compileAdapter.js +101 -37
- package/extension/src/shared/composerAttachmentDraft.js +151 -0
- package/extension/src/shared/directoryCleanupProof.js +43 -0
- package/extension/src/shared/failureReasons.js +329 -3
- package/extension/src/shared/globalPreferences.js +31 -14
- package/extension/src/shared/governanceRules.js +4 -37
- package/extension/src/shared/i18n.js +389 -25
- package/extension/src/shared/managedUpdateProjection.js +8 -5
- package/extension/src/shared/nativeRequestIdentity.js +1 -0
- package/extension/src/shared/pageRpcContract.js +9 -2
- package/extension/src/shared/projectFiles.js +21 -44
- package/extension/src/shared/providerProfiles.js +114 -3
- package/extension/src/shared/runActivityModel.js +361 -0
- package/extension/src/shared/runExecutionSnapshot.js +8 -2
- package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
- package/extension/src/shared/runInputQueue.js +48 -5
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
- package/extension/src/shared/selectionContext.js +37 -0
- package/extension/src/shared/sessionState.js +166 -30
- package/extension/src/shared/settlementFacts.js +10 -2
- package/extension/src/shared/sharedSessionBridge.js +311 -0
- package/extension/src/shared/sharedSessionTransfer.js +140 -0
- package/extension/src/shared/staleGuard.js +118 -13
- package/extension/src/shared/storageDb.js +77 -78
- package/extension/src/shared/storageMigration.js +74 -111
- package/extension/src/shared/storageRunActions.js +211 -22
- package/extension/src/shared/storageValuePruning.js +40 -0
- package/extension/src/shared/subagentActivityModel.js +174 -0
- package/extension/src/shared/undoOperations.js +216 -6
- package/extension/src/shared/updateConsent.js +42 -11
- package/extension/src/shared/updateRuntimeIdentity.js +1 -1
- package/extension/src/shared/writebackIntent.js +78 -0
- package/extension/src/shared/writebackOperationEvidence.js +4 -15
- package/extension/src/shared/writebackSettlement.js +67 -48
- package/extension/src/shared/writingStyle.js +33 -0
- package/extension/styles/panel.css +1987 -385
- package/extension/styles/popup.css +110 -0
- package/native-host/src/anthropicBridgeRequest.js +6 -3
- package/native-host/src/anthropicBridgeResponse.js +6 -2
- package/native-host/src/anthropicMessagesBridge.js +24 -16
- package/native-host/src/bootstrapMigration.js +296 -0
- package/native-host/src/bootstrapMigrationContract.js +101 -0
- package/native-host/src/bootstrapUpdate.js +233 -0
- package/native-host/src/bootstrapUpdateWatchdog.js +44 -0
- package/native-host/src/chatBridgeResponse.js +10 -0
- package/native-host/src/chatCompletionsBridge.js +21 -15
- package/native-host/src/codexConfigPaths.js +106 -0
- package/native-host/src/codexHome.js +66 -73
- package/native-host/src/codexHomeScope.js +124 -0
- package/native-host/src/codexInheritedAuth.js +90 -0
- package/native-host/src/codexLocalSkills.js +301 -0
- package/native-host/src/codexModelRecovery.js +107 -0
- package/native-host/src/codexPromptAssembly.js +33 -12
- package/native-host/src/codexProviderLaunch.js +3 -3
- package/native-host/src/codexProviderTest.js +24 -26
- package/native-host/src/codexRuntimeIdentity.js +1 -0
- package/native-host/src/codexSessionRunner.js +211 -318
- package/native-host/src/codexSessionTiming.js +21 -8
- package/native-host/src/codexSkillIsolation.js +170 -0
- package/native-host/src/codexThreadFork.js +19 -3
- package/native-host/src/index.js +19 -7
- package/native-host/src/managedInstall.js +115 -39
- package/native-host/src/managedInstallRecovery.js +140 -0
- package/native-host/src/managedRuntimeEvidence.js +57 -0
- package/native-host/src/mirrorWorkspace.js +92 -22
- package/native-host/src/nativeDoctor.js +15 -0
- package/native-host/src/nativeEnvironment.js +70 -0
- package/native-host/src/nativeHelperLifecycle.js +21 -0
- package/native-host/src/nativeHostRegistration.js +33 -0
- package/native-host/src/nativeQuotas.js +15 -8
- package/native-host/src/nativeRunLifecycle.js +71 -0
- package/native-host/src/overleafWorkspaceRules.js +16 -0
- package/native-host/src/processStopBarrier.js +115 -0
- package/native-host/src/projectPathPlatform.js +30 -0
- package/native-host/src/providerHttp.js +80 -0
- package/native-host/src/providerModelCatalog.js +4 -3
- package/native-host/src/providerProfile.js +17 -3
- package/native-host/src/providerReasoning.js +10 -11
- package/native-host/src/providerRuntime.js +1 -0
- package/native-host/src/providerStore.js +76 -14
- package/native-host/src/releaseTransport.js +14 -5
- package/native-host/src/responsesPassthroughBridge.js +266 -52
- package/native-host/src/runtimeInstaller.js +21 -1
- package/native-host/src/selectionScope.js +86 -0
- package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
- package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
- package/native-host/src/subagentAdmission.js +26 -0
- package/native-host/src/subagentBroker.js +176 -159
- package/native-host/src/subagentTelemetry.js +325 -0
- package/native-host/src/subagentWorkspace.js +103 -0
- package/native-host/src/subagentWorkspacePath.js +34 -0
- package/native-host/src/taskRunnerRuntime.js +130 -57
- package/native-host/src/tomlStatements.js +140 -0
- package/native-host/src/turnAttachments.js +113 -0
- package/native-host/src/updateManager.js +406 -38
- package/native-host/src/updateNetworkControl.js +75 -0
- package/native-host/src/updateTrust.js +21 -2
- package/native-host/src/vendor/pdfjs/LICENSE +177 -0
- package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
- package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
- package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
- package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
- package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
- package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
- package/native-host/src/writingStyleEvidence.js +102 -0
- package/native-host/src/writingStylePdfWorker.js +35 -0
- package/native-host/src/writingStyleProfile.js +165 -0
- package/native-host/src/writingStyleRuntime.js +475 -0
- package/native-host/src/writingStyleStore.js +73 -0
- package/package.json +1 -1
- package/scripts/install-managed.mjs +1 -0
|
@@ -9,39 +9,147 @@
|
|
|
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, cancelled = false, halted = false;
|
|
21
|
+
function skipUndispatched(operations) {
|
|
22
|
+
const result = normalizeTextResult({ ok: false,
|
|
23
|
+
code: cancelled ? 'codex_cancelled' : blocked ? 'writeback_tail_not_started' : 'writeback_deadline_exceeded',
|
|
24
|
+
error: cancelled ? 'The run was cancelled. This operation was not dispatched.'
|
|
25
|
+
: halted ? 'An earlier writeback stopped this file plan. This operation was not dispatched.'
|
|
26
|
+
: blocked ? 'An earlier writeback is unconfirmed. This operation was not dispatched.'
|
|
27
|
+
: invalidDeadline ? 'The writeback deadline is invalid. This operation was not dispatched.'
|
|
28
|
+
: 'The writeback deadline has elapsed. This operation was not dispatched.',
|
|
29
|
+
changedDocument: false }, operations);
|
|
30
|
+
result.receiptUnconfirmed = false;
|
|
31
|
+
results.push(result);
|
|
32
|
+
}
|
|
16
33
|
async function flushTextBatch() {
|
|
17
34
|
if (!textBatch.length) return;
|
|
18
|
-
|
|
19
|
-
|
|
35
|
+
const operations = textBatch;
|
|
36
|
+
textBatch = [];
|
|
37
|
+
if (blocked || cancelled || expired()) { skipUndispatched(operations); return; }
|
|
38
|
+
let response;
|
|
39
|
+
try { response = await callPageBridge('applyOperations', {
|
|
40
|
+
operations,
|
|
20
41
|
baseFiles: input.baseFiles || [],
|
|
42
|
+
reviewingPolicy: input.reviewingPolicy || '',
|
|
43
|
+
...(input.reviewOwnerToken ? { reviewOwnerToken: input.reviewOwnerToken } : {}),
|
|
44
|
+
...(deadlineAt !== null ? { deadlineAt } : {}),
|
|
21
45
|
requireReviewing: input.requireReviewing === true,
|
|
22
46
|
requireEditing: input.requireEditing === true,
|
|
47
|
+
retryCreates: input.retryCreates === true,
|
|
23
48
|
runProjectId: input.runProjectId || ''
|
|
24
|
-
}))
|
|
25
|
-
|
|
49
|
+
}); } catch (error) {
|
|
50
|
+
if (error?.code !== 'codex_cancelled' && error?.cancelled !== true) throw error;
|
|
51
|
+
cancelled = true;
|
|
52
|
+
// A later cancelled batch must not discard earlier write/Undo evidence.
|
|
53
|
+
if (!error.requestId && !results.length) throw error;
|
|
54
|
+
response = { ok: false, code: 'codex_cancelled', error: error.message,
|
|
55
|
+
requestId: error.requestId, changedDocument: error.changedDocument !== false };
|
|
56
|
+
}
|
|
57
|
+
const recovered = ['page_bridge_timeout', 'codex_cancelled'].includes(response?.code) && response.requestId
|
|
58
|
+
? await recoverTextReceipt(response, operations, input.runProjectId || '', deadlineAt)
|
|
59
|
+
: response;
|
|
60
|
+
const result = normalizeTextResult(recovered, operations);
|
|
61
|
+
if (response?.code === 'codex_cancelled' && response.changedDocument === false) result.receiptUnconfirmed = false;
|
|
62
|
+
results.push(result);
|
|
63
|
+
cancelled ||= hasCancellation(result);
|
|
64
|
+
halted ||= result.haltRemainingOperations === true;
|
|
65
|
+
blocked = halted || result.receiptUnconfirmed === true;
|
|
26
66
|
}
|
|
27
67
|
for (const operation of Array.isArray(input.operations) ? input.operations : []) {
|
|
68
|
+
if (blocked || cancelled || expired()) {
|
|
69
|
+
skipUndispatched([operation]);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
28
72
|
if (!BINARY_TYPES.has(operation?.type)) {
|
|
29
73
|
textBatch.push(operation);
|
|
30
74
|
continue;
|
|
31
75
|
}
|
|
32
76
|
await flushTextBatch();
|
|
33
|
-
|
|
77
|
+
if (blocked || cancelled || expired()) {
|
|
78
|
+
skipUndispatched([operation]);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const binaryResult = await applyBinaryOperation(operation, input);
|
|
82
|
+
results.push(binaryResult);
|
|
83
|
+
cancelled ||= hasCancellation(binaryResult);
|
|
84
|
+
blocked = binaryResult.receiptUnconfirmed === true;
|
|
34
85
|
}
|
|
35
86
|
await flushTextBatch();
|
|
36
87
|
return mergeApplyResults(results);
|
|
37
88
|
}
|
|
38
89
|
|
|
90
|
+
async function recoverTextReceipt(timeout, operations, runProjectId, deadlineAt = null) {
|
|
91
|
+
const budget = Number.isFinite(deps.receiptTimeoutMs) ? Math.max(0, deps.receiptTimeoutMs)
|
|
92
|
+
: Math.min(600000, Math.max(90000, operations.length * 60000));
|
|
93
|
+
const deadline = deadlineAt ?? (now() + budget);
|
|
94
|
+
let partial = {}, state = 'unavailable', recoveryError = '', first = true;
|
|
95
|
+
while (deadlineAt === null ? (first || now() <= deadline) : now() < deadline) {
|
|
96
|
+
first = false;
|
|
97
|
+
let receipt, transportFailed = false;
|
|
98
|
+
try {
|
|
99
|
+
receipt = await callPageBridge('getWritebackReceipt', { requestId: timeout.requestId, runProjectId,
|
|
100
|
+
...(deadlineAt !== null ? { deadlineAt } : {}) });
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error?.code === 'codex_cancelled' || error?.cancelled === true) {
|
|
103
|
+
recoveryError = error.message || 'Receipt settlement was cancelled.'; break;
|
|
104
|
+
}
|
|
105
|
+
recoveryError = error?.message || String(error);
|
|
106
|
+
if (!isTransientReceiptFailure(error)) break;
|
|
107
|
+
transportFailed = true;
|
|
108
|
+
}
|
|
109
|
+
if (!transportFailed) {
|
|
110
|
+
if (receipt?.code === 'codex_cancelled' || receipt?.cancelled === true) {
|
|
111
|
+
recoveryError = receipt.error || 'Receipt settlement was cancelled.'; break;
|
|
112
|
+
}
|
|
113
|
+
if (receipt?.ok !== true) {
|
|
114
|
+
recoveryError = receipt?.error?.message || receipt?.error || receipt?.reason
|
|
115
|
+
|| 'Writeback receipt could not be read.';
|
|
116
|
+
if (!isTransientReceiptFailure(receipt)) break;
|
|
117
|
+
} else {
|
|
118
|
+
if (receipt.requestId !== timeout.requestId || receipt.runProjectId !== runProjectId) {
|
|
119
|
+
recoveryError = 'Writeback receipt identity could not be confirmed.';
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
state = receipt.state;
|
|
123
|
+
if (receipt.result && typeof receipt.result === 'object') partial = receipt.result;
|
|
124
|
+
if (state === 'completed') {
|
|
125
|
+
if (!receipt.result || typeof receipt.result !== 'object') {
|
|
126
|
+
recoveryError = 'The completed writeback receipt has no result.';
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
if (deadlineAt !== null && now() > deadline) break;
|
|
130
|
+
return { ...partial,
|
|
131
|
+
receiptRecovery: { requestId: timeout.requestId, recovered: true, initialError: timeout.error } };
|
|
132
|
+
}
|
|
133
|
+
if (state !== 'running') {
|
|
134
|
+
recoveryError = 'The original writeback receipt is no longer available.';
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (now() >= deadline) break;
|
|
140
|
+
await delay(Math.min(deps.receiptPollMs || 500, Math.max(1, deadline - now())));
|
|
141
|
+
}
|
|
142
|
+
return { ...timeout, ...partial, ok: false, code: timeout.code, error: timeout.error,
|
|
143
|
+
requestId: timeout.requestId, receiptUnconfirmed: true, receiptState: state, recoveryError };
|
|
144
|
+
}
|
|
145
|
+
|
|
39
146
|
async function applyBinaryOperation(operation, input) {
|
|
40
147
|
const transferId = `asset_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
41
148
|
const assetRef = operation.assetRef || null;
|
|
42
149
|
const safeOperation = sanitizeOperation(operation);
|
|
43
|
-
let pageBegun = false;
|
|
150
|
+
let beginAttempted = false, pageBegun = false, commitAttempted = false;
|
|
44
151
|
try {
|
|
152
|
+
beginAttempted = true;
|
|
45
153
|
const begin = await callPageBridge('binaryUploadBegin', {
|
|
46
154
|
transferId,
|
|
47
155
|
path: operation.path,
|
|
@@ -49,6 +157,7 @@
|
|
|
49
157
|
sha256: assetRef?.sha256 || operation.sha256 || '',
|
|
50
158
|
mimeType: assetRef?.mimeType || operation.mimeType || 'application/octet-stream',
|
|
51
159
|
overwrite: operation.type === 'overwrite-binary',
|
|
160
|
+
previousSha256: operation.type === 'overwrite-binary' ? await binaryBaselineHash(operation, input.baseFiles) : undefined,
|
|
52
161
|
runProjectId: input.runProjectId || ''
|
|
53
162
|
});
|
|
54
163
|
if (!begin?.ok) throw responseError(begin, 'binary_upload_begin_failed');
|
|
@@ -66,6 +175,7 @@
|
|
|
66
175
|
} else {
|
|
67
176
|
throw codedError('binary_asset_payload_missing', 'Binary asset payload is unavailable.');
|
|
68
177
|
}
|
|
178
|
+
commitAttempted = true;
|
|
69
179
|
const committed = await callPageBridge('binaryUploadCommit', {
|
|
70
180
|
transferId,
|
|
71
181
|
runProjectId: input.runProjectId || ''
|
|
@@ -73,12 +183,41 @@
|
|
|
73
183
|
if (!committed?.ok) throw responseError(committed, committed?.code || 'binary_upload_failed');
|
|
74
184
|
return { ok: true, applied: [{ operation: safeOperation, result: committed }], skipped: [] };
|
|
75
185
|
} catch (error) {
|
|
76
|
-
|
|
186
|
+
// A commit rejected before dispatch still leaves staged bytes to clean up.
|
|
187
|
+
if (error.requestDispatched === false) commitAttempted = false;
|
|
188
|
+
let changedDocument = error?.changedDocument === true
|
|
189
|
+
|| (commitAttempted && error?.changedDocument !== false);
|
|
190
|
+
if (commitAttempted && changedDocument) {
|
|
191
|
+
const deadline = now() + 30000;
|
|
192
|
+
do {
|
|
193
|
+
const receipt = await callPageBridge('binaryUploadStatus', {
|
|
194
|
+
transferId, runProjectId: input.runProjectId || ''
|
|
195
|
+
}).catch(() => null);
|
|
196
|
+
if (!receipt?.ok || receipt.transferId !== transferId
|
|
197
|
+
|| receipt.runProjectId !== input.runProjectId) break;
|
|
198
|
+
if (receipt.result?.ok === true) {
|
|
199
|
+
return { ok: true, applied: [{ operation: safeOperation, result: receipt.result }], skipped: [],
|
|
200
|
+
cancelled: error.code === 'codex_cancelled' || error.cancelled === true,
|
|
201
|
+
receiptRecovery: { transferId, recovered: true, initialError: error.message } };
|
|
202
|
+
}
|
|
203
|
+
if (receipt.state === 'completed' && receipt.changedDocument === false) {
|
|
204
|
+
changedDocument = false;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
if (now() >= deadline) break;
|
|
208
|
+
await delay(Math.min(500, Math.max(1, deadline - now())));
|
|
209
|
+
} while (now() <= deadline);
|
|
210
|
+
}
|
|
211
|
+
const uncertainBegin = beginAttempted && error.code === 'codex_cancelled' && error.requestDispatched !== false;
|
|
212
|
+
if (!commitAttempted && (pageBegun || uncertainBegin)) {
|
|
77
213
|
await callPageBridge('binaryUploadAbort', { transferId, runProjectId: input.runProjectId || '' }).catch(() => null);
|
|
78
214
|
}
|
|
79
215
|
const code = error.code || 'binary_upload_failed';
|
|
80
216
|
return {
|
|
81
217
|
ok: false,
|
|
218
|
+
receiptUnconfirmed: changedDocument,
|
|
219
|
+
error: error.message || 'Binary asset upload failed.',
|
|
220
|
+
code,
|
|
82
221
|
applied: [],
|
|
83
222
|
skipped: [{
|
|
84
223
|
operation: safeOperation,
|
|
@@ -87,8 +226,11 @@
|
|
|
87
226
|
ok: false,
|
|
88
227
|
code,
|
|
89
228
|
reason: error.message || 'Binary asset upload failed.',
|
|
90
|
-
|
|
91
|
-
|
|
229
|
+
...(Array.isArray(error.createdDirectories) ? { createdDirectories: error.createdDirectories,
|
|
230
|
+
folderChanged: error.folderChanged === true, fileUploadAttempted: error.fileUploadAttempted === true,
|
|
231
|
+
directoryCleanupRequired: error.createdDirectories.length > 0 } : {}),
|
|
232
|
+
changedDocument,
|
|
233
|
+
failure: { code, stage: 'write', file: operation.path, changedDocument }
|
|
92
234
|
}
|
|
93
235
|
}]
|
|
94
236
|
};
|
|
@@ -129,18 +271,66 @@
|
|
|
129
271
|
return { applyOperations };
|
|
130
272
|
}
|
|
131
273
|
|
|
274
|
+
function normalizeTextResult(response, operations) {
|
|
275
|
+
const result = response && typeof response === 'object' ? { ...response } : { ok: false };
|
|
276
|
+
result.applied = Array.isArray(result.applied) ? result.applied : [];
|
|
277
|
+
result.skipped = Array.isArray(result.skipped) ? result.skipped.slice() : [];
|
|
278
|
+
if (result.skipped.some(entry => entry.result?.receiptUnconfirmed === true)) result.receiptUnconfirmed = true;
|
|
279
|
+
const key = operation => [operation?.type, operation?.path, operation?.to || ''].join('\0');
|
|
280
|
+
const known = new Map();
|
|
281
|
+
for (const entry of [...result.applied, ...result.skipped]) {
|
|
282
|
+
const id = key(entry.operation); known.set(id, (known.get(id) || 0) + 1);
|
|
283
|
+
}
|
|
284
|
+
const missing = [];
|
|
285
|
+
for (const operation of operations) {
|
|
286
|
+
const id = key(operation), count = known.get(id) || 0;
|
|
287
|
+
if (count) known.set(id, count - 1); else missing.push(operation);
|
|
288
|
+
}
|
|
289
|
+
if (!missing.length && (result.ok !== false || result.skipped.length)) return result;
|
|
290
|
+
const code = result.code || 'writeback_result_unconfirmed';
|
|
291
|
+
const error = typeof result.error === 'string' ? result.error
|
|
292
|
+
: result.error?.message || 'The page did not return a complete writeback result.';
|
|
293
|
+
const changedDocument = result.changedDocument !== false;
|
|
294
|
+
for (const operation of missing.length ? missing : [null]) {
|
|
295
|
+
const reason = changedDocument
|
|
296
|
+
? 'Write status is unconfirmed; Overleaf may already contain changes. Check the project before retrying. ' + error
|
|
297
|
+
: error;
|
|
298
|
+
result.skipped.push({ operation, path: operation?.path || '', result: {
|
|
299
|
+
ok: false, code, reason, changedDocument, failure: {
|
|
300
|
+
code, stage: 'write', severity: 'warning', terminalState: 'needs_review', retryable: false,
|
|
301
|
+
file: operation?.path || '', userMessage: reason,
|
|
302
|
+
nextAction: 'Check the current Overleaf files and original writeback result before starting another write.',
|
|
303
|
+
changedDocument, evidence: { requestId: result.requestId || '', receiptState: result.receiptState || '',
|
|
304
|
+
transportError: error, recoveryError: result.recoveryError || '' }
|
|
305
|
+
}
|
|
306
|
+
} });
|
|
307
|
+
}
|
|
308
|
+
return { ...result, ok: false, code, error, receiptUnconfirmed: true };
|
|
309
|
+
}
|
|
310
|
+
|
|
132
311
|
function mergeApplyResults(results) {
|
|
133
312
|
const merged = { ok: true, applied: [], skipped: [], trackedChanges: [] };
|
|
134
313
|
for (const result of results) {
|
|
135
314
|
merged.applied.push(...(Array.isArray(result?.applied) ? result.applied : []));
|
|
136
315
|
merged.skipped.push(...(Array.isArray(result?.skipped) ? result.skipped : []));
|
|
316
|
+
if (result?.haltRemainingOperations) merged.haltRemainingOperations = true;
|
|
137
317
|
// Text writeback returns the Reviewing references captured by the page
|
|
138
318
|
// bridge. They are lifecycle data, not diagnostics: dropping them makes
|
|
139
319
|
// recordUndoFromApply classify a successful Track write as legacy Undo,
|
|
140
320
|
// which hides Accept and prevents the lifecycle from surviving reload.
|
|
141
321
|
merged.trackedChanges.push(...(Array.isArray(result?.trackedChanges) ? result.trackedChanges : []));
|
|
322
|
+
if (result?.reviewingPolicy !== undefined) merged.reviewingPolicy = result.reviewingPolicy;
|
|
142
323
|
if (result?.trackedChangeCaptures?.length) (merged.trackedChangeCaptures ||= []).push(...result.trackedChangeCaptures);
|
|
143
|
-
if (result?.ok !== true)
|
|
324
|
+
if (result?.ok !== true) {
|
|
325
|
+
merged.ok = false;
|
|
326
|
+
for (const key of ['code', 'error', 'failure', 'requestId', 'receiptState', 'recoveryError']) {
|
|
327
|
+
if (result?.[key] !== undefined && merged[key] === undefined) merged[key] = result[key];
|
|
328
|
+
}
|
|
329
|
+
if (result?.receiptUnconfirmed !== undefined) {
|
|
330
|
+
merged.receiptUnconfirmed = merged.receiptUnconfirmed === true || result.receiptUnconfirmed === true;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (result?.receiptRecovery) (merged.receiptRecoveries ||= []).push(result.receiptRecovery);
|
|
144
334
|
}
|
|
145
335
|
if (merged.trackedChangeCaptures?.some(capture => capture.state !== 'observed')) merged.trackedChanges = [];
|
|
146
336
|
if (merged.skipped.length) merged.ok = false;
|
|
@@ -160,11 +350,53 @@
|
|
|
160
350
|
return safe;
|
|
161
351
|
}
|
|
162
352
|
|
|
353
|
+
function hasCancellation(result) {
|
|
354
|
+
return result?.cancelled === true || result?.code === 'codex_cancelled'
|
|
355
|
+
|| result?.skipped?.some(entry => entry.result?.code === 'codex_cancelled');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
async function binaryBaselineHash(operation, baseFiles = []) {
|
|
359
|
+
const valid = value => typeof value === 'string' && /^[a-f0-9]{64}$/i.test(value);
|
|
360
|
+
const base = (baseFiles || []).find(file => file?.path === operation.path);
|
|
361
|
+
let captured = valid(base?.sha256) ? base.sha256.toLowerCase() : '';
|
|
362
|
+
if (typeof base?.contentBase64 === 'string' && globalThis.crypto?.subtle && typeof atob === 'function') {
|
|
363
|
+
const bytes = Uint8Array.from(atob(base.contentBase64), value => value.charCodeAt(0));
|
|
364
|
+
const hash = await globalThis.crypto.subtle.digest('SHA-256', bytes);
|
|
365
|
+
const digest = Array.from(new Uint8Array(hash), value => value.toString(16).padStart(2, '0')).join('');
|
|
366
|
+
if (captured && captured !== digest) throw codedError('binary_asset_baseline_conflict', 'The captured binary baseline has conflicting content and hash.');
|
|
367
|
+
captured = digest;
|
|
368
|
+
}
|
|
369
|
+
if (operation.previousSha256 != null) {
|
|
370
|
+
if (!valid(operation.previousSha256) || (captured && captured !== operation.previousSha256.toLowerCase())) {
|
|
371
|
+
throw codedError('binary_asset_baseline_conflict', 'The Native and browser binary baselines differ. Read the project again before replacement.');
|
|
372
|
+
}
|
|
373
|
+
return operation.previousSha256.toLowerCase();
|
|
374
|
+
}
|
|
375
|
+
return captured;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function isTransientReceiptFailure(value) {
|
|
379
|
+
const code = value?.code || value?.error?.code;
|
|
380
|
+
if (code) return ['page_bridge_timeout', 'page_bridge_unavailable', 'page_bridge_transport_error',
|
|
381
|
+
'page_bridge_disconnected', 'network_error', 'ETIMEDOUT', 'ECONNRESET', 'ECONNABORTED',
|
|
382
|
+
'EPIPE', 'ERR_NETWORK'].includes(code);
|
|
383
|
+
const message = value?.message || value?.error?.message || value?.error || '';
|
|
384
|
+
return /timed?\s*out|timeout|network|transport|bridge unavailable|port.*closed|receiving end|socket hang up/i.test(String(message));
|
|
385
|
+
}
|
|
386
|
+
|
|
163
387
|
function responseError(response, fallbackCode) {
|
|
164
|
-
|
|
388
|
+
const error = codedError(
|
|
165
389
|
response?.code || response?.error?.code || fallbackCode,
|
|
166
390
|
response?.reason || response?.error?.message || response?.error || 'Asset transfer failed.'
|
|
167
391
|
);
|
|
392
|
+
if (typeof response?.changedDocument === 'boolean') error.changedDocument = response.changedDocument;
|
|
393
|
+
if (Array.isArray(response?.createdDirectories)) {
|
|
394
|
+
error.createdDirectories = response.createdDirectories;
|
|
395
|
+
error.folderChanged = response.folderChanged === true;
|
|
396
|
+
error.fileUploadAttempted = response.fileUploadAttempted === true;
|
|
397
|
+
}
|
|
398
|
+
error.stage = response?.failure?.stage || 'write';
|
|
399
|
+
return error;
|
|
168
400
|
}
|
|
169
401
|
function codedError(code, message) { const error = new Error(String(message || code)); error.code = code; return error; }
|
|
170
402
|
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
|
+
});
|