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
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
// Exact bytes from the published v2.5.0 Bootstrap. Unknown local modifications
|
|
8
|
+
// are never converted into a migration source simply because versions agree.
|
|
9
|
+
const BOOTSTRAP_MIGRATION_BASELINE = Object.freeze({
|
|
10
|
+
"bootstrap/background.js": "5e15d208f07668f96cb94a84642d5fd9ad2dd921991bb3bd5bf67cc43037c87a",
|
|
11
|
+
"bootstrap/popup.css": "0709a4b8aba5e59e95fd07afec4d29ba441bde46fae48863133a170ad12cbe58",
|
|
12
|
+
"bootstrap/popup.html": "7cbcead701cb03a4006bbd682a744aeca30d613eb8315a194f2ba751b6fd9e55",
|
|
13
|
+
"bootstrap/popup.js": "24f7171045ad7de9431d24e0e4a7d15237620f4217dd5e68772dbdf52b8ce4d8",
|
|
14
|
+
"bootstrap/popupFallback.js": null,
|
|
15
|
+
"bootstrap/runtimeContext.js": "ac04d9bb28308015ecfe296f152996521398dc0bb018416e34abe8424734a21b",
|
|
16
|
+
"bootstrap/update.css": "43a0d4345f6f35a30c792a6fd67227776ec85ba710f89cae9c167b453de72342",
|
|
17
|
+
"bootstrap/update.html": "7ce092eabcdf51564f994d8f72c474285f07777bd7a5a205eca8e5a0931964ab",
|
|
18
|
+
"bootstrap/update.js": "ee67a23d89d435f05d3e4c1ec1f9c5a7f0bdcef4449e13be4d7acbbcf182413c",
|
|
19
|
+
"bootstrap/updateStatus.js": "d2ad90e78c50367a5489bb6f5c27c7248112047aca9f05d2ad868ac3b5266b24"
|
|
20
|
+
});
|
|
21
|
+
const BOOTSTRAP_MIGRATION_FILES = Object.freeze(Object.keys(BOOTSTRAP_MIGRATION_BASELINE));
|
|
22
|
+
const BOOTSTRAP_MIGRATION_TARGET_VERSION = '2.5.1';
|
|
23
|
+
const BOOTSTRAP_MIGRATION_REVISION = '3.1';
|
|
24
|
+
const BOOTSTRAP_MIGRATION_IMPLEMENTATION_FILES = Object.freeze([
|
|
25
|
+
'native-host/src/bootstrapMigrationContract.js',
|
|
26
|
+
'native-host/src/bootstrapMigration.js',
|
|
27
|
+
'native-host/src/bootstrapUpdate.js',
|
|
28
|
+
'native-host/src/bootstrapUpdateWatchdog.js',
|
|
29
|
+
'extension/src/backgroundBootstrapMigration.js'
|
|
30
|
+
]);
|
|
31
|
+
const BOOTSTRAP_MANIFEST_SHAPE_SHA256 = '85c2d3875196ff9b334b40bb115a42fe4b8cab4e9c37609fb65e8834284c8fbe';
|
|
32
|
+
|
|
33
|
+
function isBootstrapMigrationRelease(version) {
|
|
34
|
+
return version === BOOTSTRAP_MIGRATION_TARGET_VERSION;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildBootstrapMigrationDescriptor({ packageRoot, version } = {}) {
|
|
38
|
+
if (!isBootstrapMigrationRelease(version)) return null;
|
|
39
|
+
assertBootstrapManifestShape(JSON.parse(fs.readFileSync(path.join(packageRoot,
|
|
40
|
+
'extension/bootstrap/manifest.template.json'), 'utf8')), { version });
|
|
41
|
+
const files = BOOTSTRAP_MIGRATION_FILES.map(relativePath => ({
|
|
42
|
+
path: relativePath,
|
|
43
|
+
sourceSha256: BOOTSTRAP_MIGRATION_BASELINE[relativePath],
|
|
44
|
+
targetSha256: sha256(fs.readFileSync(path.join(packageRoot, 'extension', relativePath)))
|
|
45
|
+
}));
|
|
46
|
+
return validateBootstrapMigrationDescriptor({
|
|
47
|
+
schemaVersion: 1,
|
|
48
|
+
id: 'bootstrap-v3.1-from-2.5.0',
|
|
49
|
+
bootstrapProtocol: 3,
|
|
50
|
+
sourceVersions: ['2.5.0'],
|
|
51
|
+
targetVersion: version,
|
|
52
|
+
targetRevision: BOOTSTRAP_MIGRATION_REVISION,
|
|
53
|
+
files
|
|
54
|
+
}, { targetVersion: version });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function validateBootstrapMigrationDescriptor(descriptor, { targetVersion } = {}) {
|
|
58
|
+
if (!descriptor || descriptor.schemaVersion !== 1 || descriptor.id !== 'bootstrap-v3.1-from-2.5.0'
|
|
59
|
+
|| descriptor.bootstrapProtocol !== 3 || descriptor.targetRevision !== BOOTSTRAP_MIGRATION_REVISION
|
|
60
|
+
|| descriptor.targetVersion !== BOOTSTRAP_MIGRATION_TARGET_VERSION
|
|
61
|
+
|| (targetVersion && descriptor.targetVersion !== targetVersion)
|
|
62
|
+
|| JSON.stringify(descriptor.sourceVersions) !== JSON.stringify(['2.5.0'])
|
|
63
|
+
|| !Array.isArray(descriptor.files) || descriptor.files.length !== BOOTSTRAP_MIGRATION_FILES.length) {
|
|
64
|
+
throw new Error('Unsupported Bootstrap migration descriptor.');
|
|
65
|
+
}
|
|
66
|
+
const seen = new Set();
|
|
67
|
+
for (const file of descriptor.files) {
|
|
68
|
+
if (!file || !Object.hasOwn(BOOTSTRAP_MIGRATION_BASELINE, file.path) || seen.has(file.path)
|
|
69
|
+
|| file.sourceSha256 !== BOOTSTRAP_MIGRATION_BASELINE[file.path]
|
|
70
|
+
|| !/^[0-9a-f]{64}$/.test(file.targetSha256 || '')) {
|
|
71
|
+
throw new Error('Bootstrap migration file identity is invalid.');
|
|
72
|
+
}
|
|
73
|
+
seen.add(file.path);
|
|
74
|
+
}
|
|
75
|
+
return descriptor;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function assertBootstrapManifestShape(manifest, { version } = {}) {
|
|
79
|
+
if (!manifest || (version && manifest.version !== version)
|
|
80
|
+
|| sha256(Buffer.from(stableJson({ ...manifest, version: '<release-version>' }))) !== BOOTSTRAP_MANIFEST_SHAPE_SHA256) {
|
|
81
|
+
throw new Error('Bootstrap migration cannot change the extension manifest shape or permissions.');
|
|
82
|
+
}
|
|
83
|
+
return manifest;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function stableJson(value) {
|
|
87
|
+
if (Array.isArray(value)) return '[' + value.map(stableJson).join(',') + ']';
|
|
88
|
+
if (value && typeof value === 'object') return '{' + Object.keys(value).sort()
|
|
89
|
+
.map(key => JSON.stringify(key) + ':' + stableJson(value[key])).join(',') + '}';
|
|
90
|
+
return JSON.stringify(value);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function sha256(bytes) {
|
|
94
|
+
return crypto.createHash('sha256').update(bytes).digest('hex');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = {
|
|
98
|
+
BOOTSTRAP_MIGRATION_BASELINE, BOOTSTRAP_MIGRATION_FILES, BOOTSTRAP_MIGRATION_TARGET_VERSION,
|
|
99
|
+
BOOTSTRAP_MIGRATION_REVISION, isBootstrapMigrationRelease, buildBootstrapMigrationDescriptor,
|
|
100
|
+
BOOTSTRAP_MIGRATION_IMPLEMENTATION_FILES, validateBootstrapMigrationDescriptor, assertBootstrapManifestShape
|
|
101
|
+
};
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Coordination for the one compatible 2.5.0 -> 2.5.1 Bootstrap revision.
|
|
4
|
+
// All mutations run under updateManager's existing cross-process lock.
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
const crypto = require('node:crypto');
|
|
8
|
+
const vm = require('node:vm');
|
|
9
|
+
const { spawn } = require('node:child_process');
|
|
10
|
+
const Files = require('./bootstrapMigration');
|
|
11
|
+
const Contract = require('./bootstrapMigrationContract');
|
|
12
|
+
const { updateError } = require('./updateTrust');
|
|
13
|
+
|
|
14
|
+
const BOOTSTRAP_DEADLINE_MS = 120000;
|
|
15
|
+
const BOOTSTRAP_STATES = new Set(['bootstrap_pending', 'bootstrap_rolling_back']);
|
|
16
|
+
const backupRoot = context => path.join(context.updatesRoot, 'bootstrap-migrations');
|
|
17
|
+
const hash = bytes => crypto.createHash('sha256').update(bytes).digest('hex');
|
|
18
|
+
|
|
19
|
+
function migrationHint(context, journal) {
|
|
20
|
+
if (!journal || !['awaiting_health', ...BOOTSTRAP_STATES].includes(journal.state)) return null;
|
|
21
|
+
if (journal.bootstrapMigration) return journal.bootstrapMigration;
|
|
22
|
+
if (journal.sourceVersion !== '2.5.0' || journal.targetVersion !== '2.5.1') return null;
|
|
23
|
+
// This exact release pair requires migration even when discovery data was
|
|
24
|
+
// lost. Missing evidence must not downgrade an update into a false success.
|
|
25
|
+
return { phase: 'pending', targetRevision: '3.1' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function bindBootstrapMigration(context, journal, deps) {
|
|
29
|
+
if (journal?.state !== 'awaiting_health' || journal.bootstrapMigration || !migrationHint(context, journal)) return journal;
|
|
30
|
+
const candidate = readJson(path.join(context.updatesRoot, 'candidate.json'));
|
|
31
|
+
let verificationError = '';
|
|
32
|
+
try { deps.assertAuthorization(journal); verifiedDescriptor(journal, candidate, deps); }
|
|
33
|
+
catch (error) { verificationError = error.code || 'update_bootstrap_manifest_mismatch'; }
|
|
34
|
+
const next = { ...journal, state: 'bootstrap_pending', bootstrapMigration: {
|
|
35
|
+
phase: 'pending', targetRevision: '3.1', reloadCount: 0, verificationError,
|
|
36
|
+
manifestBase64: candidate?.manifestBase64 || '', signatureBase64: candidate?.signatureBase64 || ''
|
|
37
|
+
}, updatedAt: new Date().toISOString() };
|
|
38
|
+
deps.writeJournal(next);
|
|
39
|
+
return next;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function verifiedDescriptor(journal, evidence, deps) {
|
|
43
|
+
const bytes = Buffer.from(evidence?.manifestBase64 || '', 'base64');
|
|
44
|
+
if (!journal.manifestSha256 || hash(bytes) !== journal.manifestSha256) {
|
|
45
|
+
throw updateError('update_bootstrap_manifest_mismatch', 'Bootstrap migration does not match the applied release.');
|
|
46
|
+
}
|
|
47
|
+
const manifest = deps.verifyManifest(bytes, Buffer.from(evidence?.signatureBase64 || '', 'base64'));
|
|
48
|
+
if (manifest.version !== journal.targetVersion || manifest.updateBundle?.sha256 !== journal.bundleSha256
|
|
49
|
+
|| manifest.updateBundle?.size !== journal.bundleSize) {
|
|
50
|
+
throw updateError('update_bootstrap_manifest_mismatch', 'Bootstrap migration does not match the update archive.');
|
|
51
|
+
}
|
|
52
|
+
const descriptor = Contract.validateBootstrapMigrationDescriptor(manifest.bootstrapMigration, { targetVersion: journal.targetVersion });
|
|
53
|
+
if (!descriptor.sourceVersions.includes(journal.sourceVersion)) {
|
|
54
|
+
throw updateError('update_bootstrap_source_version_mismatch', 'This installation has no compatible Bootstrap migration.');
|
|
55
|
+
}
|
|
56
|
+
return descriptor;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function payloadRootFor(context, journal) {
|
|
60
|
+
return path.join(context.nativeRoot, 'versions', journal.targetVersion, 'native-host', 'bootstrap-payload');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function loadPlan(context, journal) {
|
|
64
|
+
const root = backupRoot(context);
|
|
65
|
+
if (!fs.existsSync(path.join(root, journal.id, 'state.json'))) return null;
|
|
66
|
+
const plan = Files.loadBootstrapMigration({ backupRoot: root, transactionId: journal.id });
|
|
67
|
+
if (plan.extensionRoot !== context.extensionRoot || plan.payloadRoot !== payloadRootFor(context, journal)
|
|
68
|
+
|| plan.sourceVersion !== journal.sourceVersion || plan.targetVersion !== journal.targetVersion) {
|
|
69
|
+
throw updateError('update_bootstrap_transaction_mismatch', 'Bootstrap recovery belongs to a different installation.');
|
|
70
|
+
}
|
|
71
|
+
return plan;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function advanceBootstrapMigration(context, journal, params, deps, options = {}) {
|
|
75
|
+
if (!journal || !migrationHint(context, journal)) return { state: 'not_required' };
|
|
76
|
+
if (params.transactionId !== journal.id) throw updateError('update_transaction_mismatch', 'Bootstrap update transaction changed.');
|
|
77
|
+
journal = bindBootstrapMigration(context, journal, deps);
|
|
78
|
+
if (journal.state !== 'bootstrap_pending') {
|
|
79
|
+
throw updateError('update_transaction_state_changed', 'Bootstrap migration is no longer waiting to continue.');
|
|
80
|
+
}
|
|
81
|
+
if (deps.runningVersion !== journal.targetVersion) {
|
|
82
|
+
throw updateError('update_bootstrap_native_restart_required', 'The target Native Host must start before updating Bootstrap.');
|
|
83
|
+
}
|
|
84
|
+
deps.assertAuthorization(journal);
|
|
85
|
+
const descriptor = verifiedDescriptor(journal, journal.bootstrapMigration, deps);
|
|
86
|
+
const payloadRoot = payloadRootFor(context, journal);
|
|
87
|
+
Contract.assertBootstrapManifestShape(JSON.parse(fs.readFileSync(path.join(context.extensionRoot, 'manifest.json'), 'utf8')),
|
|
88
|
+
{ version: journal.targetVersion });
|
|
89
|
+
Contract.assertBootstrapManifestShape(JSON.parse(fs.readFileSync(path.join(payloadRoot, 'manifest.template.json'), 'utf8')),
|
|
90
|
+
{ version: journal.targetVersion });
|
|
91
|
+
// A syntax failure must be found before changing the only background entry.
|
|
92
|
+
for (const file of descriptor.files) {
|
|
93
|
+
const bytes = fs.readFileSync(path.join(payloadRoot, file.path));
|
|
94
|
+
if (hash(bytes) !== file.targetSha256) throw updateError('update_bootstrap_payload_mismatch', 'Bootstrap payload changed after verification.');
|
|
95
|
+
if (file.path.endsWith('.js')) new vm.Script(bytes.toString('utf8'), { filename: file.path });
|
|
96
|
+
}
|
|
97
|
+
deps.verifyArchive(journal);
|
|
98
|
+
let plan = loadPlan(context, journal);
|
|
99
|
+
if (!plan) plan = Files.prepareBootstrapMigration({
|
|
100
|
+
descriptor, payloadRoot, extensionRoot: context.extensionRoot, backupRoot: backupRoot(context),
|
|
101
|
+
transactionId: journal.id, sourceVersion: journal.sourceVersion, targetVersion: journal.targetVersion
|
|
102
|
+
});
|
|
103
|
+
if (plan.descriptorSha256 !== hash(JSON.stringify(descriptor))) {
|
|
104
|
+
throw updateError('update_bootstrap_manifest_mismatch', 'Bootstrap recovery material does not match the signed release.');
|
|
105
|
+
}
|
|
106
|
+
let migration = { ...journal.bootstrapMigration, phase: plan.state === 'applied' ? 'applied' : 'prepared',
|
|
107
|
+
targetDigest: plan.targetDigest, sourceDigest: plan.sourceDigest,
|
|
108
|
+
deadline: journal.bootstrapMigration.deadline || Date.now() + BOOTSTRAP_DEADLINE_MS };
|
|
109
|
+
if (Date.now() >= migration.deadline) throw updateError('update_bootstrap_health_timeout', 'Bootstrap update did not finish within its health window.');
|
|
110
|
+
journal = { ...journal, bootstrapMigration: migration };
|
|
111
|
+
deps.writeJournal(journal);
|
|
112
|
+
// A new connection always establishes a new monitor handshake. PID reuse
|
|
113
|
+
// alone can never authorize writing the only browser background entry.
|
|
114
|
+
{
|
|
115
|
+
const token = crypto.randomUUID();
|
|
116
|
+
migration = { ...migration, watchdogToken: token, watchdogPid: null };
|
|
117
|
+
journal = { ...journal, bootstrapMigration: migration };
|
|
118
|
+
deps.writeJournal(journal);
|
|
119
|
+
const pid = await (options.startWatchdog || startWatchdog)(context, journal, token);
|
|
120
|
+
migration = { ...migration, watchdogPid: pid };
|
|
121
|
+
journal = { ...journal, bootstrapMigration: migration };
|
|
122
|
+
deps.writeJournal(journal);
|
|
123
|
+
}
|
|
124
|
+
Files.applyBootstrapMigration(plan, options.fileHooks);
|
|
125
|
+
const observed = Files.verifyBootstrapMigration(plan);
|
|
126
|
+
migration = { ...migration, phase: 'applied', targetDigest: observed.digest };
|
|
127
|
+
if (params.bootstrapRevision === descriptor.targetRevision) {
|
|
128
|
+
migration = { ...migration, phase: 'loaded', loadedAt: new Date().toISOString() };
|
|
129
|
+
deps.writeJournal({ ...journal, state: 'awaiting_health', bootstrapMigration: migration });
|
|
130
|
+
return { state: 'awaiting_health', transactionId: journal.id, targetVersion: journal.targetVersion,
|
|
131
|
+
bootstrapRevision: descriptor.targetRevision };
|
|
132
|
+
}
|
|
133
|
+
if (migration.reloadCount >= 2) throw updateError('update_bootstrap_reload_failed', 'The new Bootstrap did not load after extension restart.');
|
|
134
|
+
migration.reloadCount += 1;
|
|
135
|
+
deps.writeJournal({ ...journal, bootstrapMigration: migration });
|
|
136
|
+
return { state: 'reload_required', transactionId: journal.id, targetVersion: journal.targetVersion,
|
|
137
|
+
bootstrapRevision: descriptor.targetRevision };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function assertBootstrapConfirmation(context, journal, params) {
|
|
141
|
+
if (!journal.bootstrapMigration) {
|
|
142
|
+
if (migrationHint(context, journal)) throw updateError('update_bootstrap_confirmation_pending', 'Bootstrap migration is still pending.');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (journal.bootstrapMigration.phase !== 'loaded' || params.bootstrapRevision !== journal.bootstrapMigration.targetRevision) {
|
|
146
|
+
throw updateError('update_bootstrap_confirmation_pending', 'The loaded Bootstrap did not confirm the target revision.');
|
|
147
|
+
}
|
|
148
|
+
const plan = loadPlan(context, journal);
|
|
149
|
+
if (!plan || Files.verifyBootstrapMigration(plan).digest !== journal.bootstrapMigration.targetDigest) {
|
|
150
|
+
throw updateError('update_bootstrap_target_mismatch', 'The confirmed Bootstrap bytes no longer match the target.');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function restoreBootstrap(context, journal) {
|
|
155
|
+
const plan = loadPlan(context, journal);
|
|
156
|
+
if (!plan) {
|
|
157
|
+
if (journal.bootstrapMigration && journal.bootstrapMigration.phase !== 'pending') {
|
|
158
|
+
throw updateError('update_bootstrap_record_missing', 'Bootstrap recovery material is missing.');
|
|
159
|
+
}
|
|
160
|
+
if (journal.bootstrapMigration) return assertSourceBootstrap(context, journal);
|
|
161
|
+
}
|
|
162
|
+
return plan ? Files.restoreBootstrapMigration(plan) : null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function bootstrapEvidence(context, journal, expected) {
|
|
166
|
+
const plan = loadPlan(context, journal);
|
|
167
|
+
if (!plan && journal.bootstrapMigration) {
|
|
168
|
+
if (expected !== 'source' || !(journal.bootstrapMigration.phase === 'pending'
|
|
169
|
+
|| journal.bootstrapMigration.phase === 'restored' && journal.bootstrapMigration.sourceUnchanged === true)) {
|
|
170
|
+
throw updateError('update_bootstrap_record_missing', 'Bootstrap recovery material is missing.');
|
|
171
|
+
}
|
|
172
|
+
return assertSourceBootstrap(context, journal);
|
|
173
|
+
}
|
|
174
|
+
return plan ? Files.verifyBootstrapMigration(plan, { expected }) : null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function assertSourceBootstrap(context, journal) {
|
|
178
|
+
for (const [relative, expected] of Object.entries(Contract.BOOTSTRAP_MIGRATION_BASELINE)) {
|
|
179
|
+
const filename = path.join(context.extensionRoot, relative);
|
|
180
|
+
if (expected === null ? fs.existsSync(filename)
|
|
181
|
+
: !fs.existsSync(filename) || !fs.lstatSync(filename).isFile() || hash(fs.readFileSync(filename)) !== expected) {
|
|
182
|
+
throw updateError('update_bootstrap_source_mismatch', 'Bootstrap source bytes cannot be confirmed.');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const entries = Object.entries(Contract.BOOTSTRAP_MIGRATION_BASELINE).sort((a, b) => a[0].localeCompare(b[0]));
|
|
186
|
+
return { transactionId: journal.id, migrationId: 'bootstrap-v3.1-from-2.5.0',
|
|
187
|
+
state: 'restored', expected: 'source', digest: hash(JSON.stringify(entries)), unmodified: true };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function bootstrapExpired(journal, { recoveryRequested = false, context } = {}) {
|
|
191
|
+
const migration = journal?.bootstrapMigration;
|
|
192
|
+
if (!migration || !['bootstrap_pending', 'bootstrap_rolling_back', 'awaiting_health'].includes(journal.state)) return false;
|
|
193
|
+
return journal.state === 'bootstrap_rolling_back'
|
|
194
|
+
|| (migration.deadline && Date.now() >= migration.deadline)
|
|
195
|
+
|| (recoveryRequested && migration.phase !== 'pending' && !watchdogAlive(migration, context, journal));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function watchdogAlive(migration, context, journal) {
|
|
199
|
+
if (!Number.isInteger(migration?.watchdogPid) || migration.watchdogPid < 1) return false;
|
|
200
|
+
const heartbeat = context && journal && readJson(path.join(backupRoot(context), journal.id, 'watchdog.json'));
|
|
201
|
+
if (!heartbeat || heartbeat.token !== migration.watchdogToken || heartbeat.pid !== migration.watchdogPid
|
|
202
|
+
|| heartbeat.transactionId !== journal.id || Date.now() - heartbeat.at > 2500 || heartbeat.at > Date.now() + 1000) return false;
|
|
203
|
+
try { process.kill(migration.watchdogPid, 0); return true; } catch (error) { return error.code === 'EPERM'; }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function startWatchdog(context, journal, token) {
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
const child = spawn(process.execPath, [path.join(__dirname, 'bootstrapUpdateWatchdog.js'),
|
|
209
|
+
context.nativeRoot, context.extensionRoot, journal.id, token], {
|
|
210
|
+
env: { ...context.env }, detached: true, windowsHide: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc']
|
|
211
|
+
});
|
|
212
|
+
const timer = setTimeout(() => fail(new Error('Bootstrap recovery monitor did not become ready.')), 5000);
|
|
213
|
+
let settled = false;
|
|
214
|
+
function fail(error) {
|
|
215
|
+
if (settled) return;
|
|
216
|
+
settled = true; clearTimeout(timer);
|
|
217
|
+
try { child.kill(); } catch (_) { /* A failed child may already be gone. */ }
|
|
218
|
+
reject(Object.assign(error, { code: 'update_bootstrap_monitor_unavailable' }));
|
|
219
|
+
}
|
|
220
|
+
child.on('error', fail);
|
|
221
|
+
child.on('exit', () => { if (!settled) fail(new Error('Bootstrap recovery monitor exited before readiness.')); });
|
|
222
|
+
child.on('message', message => {
|
|
223
|
+
if (settled || message?.type !== 'ready' || message.token !== token || message.pid !== child.pid) return;
|
|
224
|
+
settled = true; clearTimeout(timer); child.disconnect(); child.unref(); resolve(child.pid);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function readJson(filename) { try { return JSON.parse(fs.readFileSync(filename, 'utf8')); } catch (_) { return null; } }
|
|
230
|
+
|
|
231
|
+
module.exports = { BOOTSTRAP_DEADLINE_MS, BOOTSTRAP_STATES, migrationHint, bindBootstrapMigration,
|
|
232
|
+
advanceBootstrapMigration, assertBootstrapConfirmation, restoreBootstrap, bootstrapEvidence,
|
|
233
|
+
bootstrapExpired, watchdogAlive };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Independent of the browser worker being replaced. The Native update lock
|
|
4
|
+
// serializes timeout recovery with normal health confirmation.
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
const [nativeRoot, extensionRoot, transactionId, token] = process.argv.slice(2);
|
|
8
|
+
const { recoverBootstrapTransaction } = require('./updateManager');
|
|
9
|
+
if (typeof recoverBootstrapTransaction !== 'function') throw new Error('Bootstrap recovery entry is unavailable.');
|
|
10
|
+
const env = { ...process.env, CODEX_OVERLEAF_MANAGED: '1',
|
|
11
|
+
CODEX_OVERLEAF_MANAGED_NATIVE_ROOT: nativeRoot, CODEX_OVERLEAF_MANAGED_EXTENSION_ROOT: extensionRoot };
|
|
12
|
+
let busy = false;
|
|
13
|
+
let failures = 0;
|
|
14
|
+
function heartbeat() {
|
|
15
|
+
const directory = path.join(nativeRoot, 'updates', 'bootstrap-migrations', transactionId);
|
|
16
|
+
const temporary = path.join(directory, 'watchdog-' + process.pid + '.tmp');
|
|
17
|
+
fs.writeFileSync(temporary, JSON.stringify({ transactionId, token, pid: process.pid, at: Date.now() }), { mode: 0o600 });
|
|
18
|
+
fs.renameSync(temporary, path.join(directory, 'watchdog.json'));
|
|
19
|
+
}
|
|
20
|
+
const timer = setInterval(async () => {
|
|
21
|
+
if (busy) return;
|
|
22
|
+
busy = true;
|
|
23
|
+
try {
|
|
24
|
+
const journal = JSON.parse(fs.readFileSync(path.join(nativeRoot, 'updates', 'transaction.json'), 'utf8'));
|
|
25
|
+
if (journal.id !== transactionId || journal.bootstrapMigration?.watchdogToken !== token
|
|
26
|
+
|| ['committed', 'superseded'].includes(journal.state)
|
|
27
|
+
|| journal.state === 'rolled_back' && !journal.sourceActivationPending) {
|
|
28
|
+
clearInterval(timer); return;
|
|
29
|
+
}
|
|
30
|
+
heartbeat();
|
|
31
|
+
if (journal.sourceActivationPending || journal.bootstrapMigration?.deadline && Date.now() >= journal.bootstrapMigration.deadline) {
|
|
32
|
+
await recoverBootstrapTransaction({ env }, transactionId, token);
|
|
33
|
+
clearInterval(timer);
|
|
34
|
+
}
|
|
35
|
+
} catch (_) {
|
|
36
|
+
// Retry boundedly if a filesystem/lock is temporarily unavailable. Recovery
|
|
37
|
+
// material remains durable for the next Native start or popup recovery probe.
|
|
38
|
+
if (++failures >= 20) clearInterval(timer);
|
|
39
|
+
} finally { busy = false; }
|
|
40
|
+
}, 500);
|
|
41
|
+
const initial = JSON.parse(fs.readFileSync(path.join(nativeRoot, 'updates', 'transaction.json'), 'utf8'));
|
|
42
|
+
if (initial.id !== transactionId || initial.bootstrapMigration?.watchdogToken !== token) throw new Error('Bootstrap recovery identity changed.');
|
|
43
|
+
heartbeat();
|
|
44
|
+
process.send?.({ type: 'ready', token, pid: process.pid });
|
|
@@ -295,6 +295,7 @@ function completeMessage(state, res) {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
function completeTool(state, res, tool) {
|
|
298
|
+
assertCompleteToolArguments(tool.arguments);
|
|
298
299
|
if (!tool.opened) openTool(state, res, tool);
|
|
299
300
|
tool.item.status = 'completed';
|
|
300
301
|
if (tool.kind === 'custom') {
|
|
@@ -419,6 +420,7 @@ function normalizeToolCalls(values, toolKinds) {
|
|
|
419
420
|
const name = normalizeText(value?.function?.name) || 'tool';
|
|
420
421
|
const callId = normalizeText(value?.id) || randomId('call');
|
|
421
422
|
const argumentsText = normalizeText(value?.function?.arguments) || '{}';
|
|
423
|
+
assertCompleteToolArguments(argumentsText);
|
|
422
424
|
const spec = toolKinds?.get(name);
|
|
423
425
|
const kind = (typeof spec === 'object' ? spec.kind : spec) === 'custom' ? 'custom' : 'function';
|
|
424
426
|
const originalName = typeof spec === 'object' ? spec.name || name : name;
|
|
@@ -533,6 +535,14 @@ function unwrapCustomArguments(value) {
|
|
|
533
535
|
}
|
|
534
536
|
}
|
|
535
537
|
|
|
538
|
+
function assertCompleteToolArguments(value) {
|
|
539
|
+
try {
|
|
540
|
+
JSON.parse(value || '{}');
|
|
541
|
+
} catch (_error) {
|
|
542
|
+
throw responseError('The provider returned incomplete or invalid JSON tool arguments.');
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
536
546
|
function reserveItem(state, item) {
|
|
537
547
|
const index = state.items.length;
|
|
538
548
|
state.items.push(item);
|
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
const { requiresReasoningContentReplay } = require('./providerReasoning');
|
|
12
12
|
const { classifyResponsesRoute } = require('./providerBridgeRoutes');
|
|
13
13
|
const { providerError } = require('./providerProfile');
|
|
14
|
+
const { fetchProvider, readProviderText, readProviderJson } = require('./providerHttp');
|
|
14
15
|
const { sanitizeProviderMessage } = require('./providerRedaction');
|
|
15
16
|
const { logDebug } = require('./debugLog');
|
|
16
17
|
const {
|
|
@@ -118,15 +119,19 @@ async function handleRequest({
|
|
|
118
119
|
const startedAt = Date.now();
|
|
119
120
|
const previousResponseId = String(requestBody.previous_response_id || '');
|
|
120
121
|
const previous = history.get(previousResponseId);
|
|
121
|
-
const
|
|
122
|
+
const fallbackAllowed = !previousResponseId || previousResponseId === continuationState.responseId;
|
|
123
|
+
const fallbackAnchor = previous || !fallbackAllowed
|
|
122
124
|
? []
|
|
123
125
|
: continuationState.anchorMessages;
|
|
126
|
+
const continuationAttempts = previous
|
|
127
|
+
? Number(previous.continuationAttempts) || 0
|
|
128
|
+
: fallbackAllowed ? continuationState.attempts : 0;
|
|
124
129
|
const translated = buildChatRequest({
|
|
125
130
|
requestBody,
|
|
126
131
|
launch,
|
|
127
132
|
historyMessages: previous?.messages || fallbackAnchor
|
|
128
133
|
});
|
|
129
|
-
assertReasoningContinuationBudget(translated.messages,
|
|
134
|
+
assertReasoningContinuationBudget(translated.messages, continuationAttempts);
|
|
130
135
|
const idleTimeoutMs = resolveProviderIdleTimeoutMs(launch);
|
|
131
136
|
const totalTimeoutMs = resolveProviderTotalTimeoutMs(launch, idleTimeoutMs);
|
|
132
137
|
logDebug('provider.bridge.request', {
|
|
@@ -141,7 +146,7 @@ async function handleRequest({
|
|
|
141
146
|
usedFallbackAnchor: fallbackAnchor.length > 0,
|
|
142
147
|
inputItemCount: Array.isArray(requestBody.input) ? requestBody.input.length : requestBody.input ? 1 : 0,
|
|
143
148
|
messageCount: translated.messages.length,
|
|
144
|
-
continuationAttempts
|
|
149
|
+
continuationAttempts,
|
|
145
150
|
idleTimeoutMs,
|
|
146
151
|
totalTimeoutMs
|
|
147
152
|
});
|
|
@@ -161,15 +166,15 @@ async function handleRequest({
|
|
|
161
166
|
res.on('close', onClientClose);
|
|
162
167
|
lifecycle.start();
|
|
163
168
|
try {
|
|
164
|
-
const upstream = await
|
|
169
|
+
const upstream = await fetchProvider(buildChatCompletionsUrl(launch.baseUrl, launch), {
|
|
165
170
|
method: 'POST',
|
|
166
171
|
headers: buildUpstreamHeaders(launch),
|
|
167
172
|
body: JSON.stringify(translated.body),
|
|
168
173
|
signal: controller.signal
|
|
169
|
-
});
|
|
174
|
+
}, launch);
|
|
170
175
|
lifecycle.touch();
|
|
171
176
|
if (!upstream.ok) {
|
|
172
|
-
await forwardUpstreamError(upstream, res, launch.apiKey);
|
|
177
|
+
await forwardUpstreamError(upstream, res, launch.apiKey, lifecycle.touch);
|
|
173
178
|
return;
|
|
174
179
|
}
|
|
175
180
|
const context = {
|
|
@@ -193,7 +198,7 @@ async function handleRequest({
|
|
|
193
198
|
: 0;
|
|
194
199
|
if (anchored) {
|
|
195
200
|
continuationState.anchorMessages = continuation;
|
|
196
|
-
continuationState.attempts
|
|
201
|
+
continuationState.attempts = continuationAttempts + 1;
|
|
197
202
|
continuationState.responseId = converted.response.id;
|
|
198
203
|
} else {
|
|
199
204
|
continuationState.anchorMessages = [];
|
|
@@ -217,7 +222,7 @@ async function handleRequest({
|
|
|
217
222
|
rememberHistory(history, converted.response.id, [
|
|
218
223
|
...translated.messages,
|
|
219
224
|
...continuation
|
|
220
|
-
]);
|
|
225
|
+
], { continuationAttempts: anchored ? continuationAttempts + 1 : 0 });
|
|
221
226
|
};
|
|
222
227
|
if (requestBody.stream !== false) {
|
|
223
228
|
const contentType = String(upstream.headers.get('content-type') || '').toLowerCase();
|
|
@@ -231,11 +236,11 @@ async function handleRequest({
|
|
|
231
236
|
recoverInterrupted: lifecycle.recoverInterrupted
|
|
232
237
|
});
|
|
233
238
|
} else {
|
|
234
|
-
const converted = convertChatResponse(await upstream.
|
|
239
|
+
const converted = convertChatResponse(await readProviderJson(upstream, lifecycle.touch), context);
|
|
235
240
|
writeConvertedResponseAsSse(res, converted, context, remember);
|
|
236
241
|
}
|
|
237
242
|
} else {
|
|
238
|
-
const converted = convertChatResponse(await upstream.
|
|
243
|
+
const converted = convertChatResponse(await readProviderJson(upstream, lifecycle.touch), context);
|
|
239
244
|
remember(converted);
|
|
240
245
|
sendJson(res, 200, converted.response);
|
|
241
246
|
}
|
|
@@ -376,7 +381,8 @@ function normalizeBridgeErrorCode(value) {
|
|
|
376
381
|
'provider_agent_tools_incompatible',
|
|
377
382
|
'provider_reasoning_continuation_exhausted',
|
|
378
383
|
'provider_stream_tool_parse_failed',
|
|
379
|
-
'provider_protocol_incompatible'
|
|
384
|
+
'provider_protocol_incompatible',
|
|
385
|
+
'provider_upstream_error'
|
|
380
386
|
].includes(value) ? value : 'provider_bridge_failed';
|
|
381
387
|
}
|
|
382
388
|
|
|
@@ -386,8 +392,8 @@ function bridgeErrorMessage(code) {
|
|
|
386
392
|
: 'The local provider bridge failed.';
|
|
387
393
|
}
|
|
388
394
|
|
|
389
|
-
async function forwardUpstreamError(upstream, res, apiKey) {
|
|
390
|
-
const text = (await upstream
|
|
395
|
+
async function forwardUpstreamError(upstream, res, apiKey, onActivity) {
|
|
396
|
+
const text = (await readProviderText(upstream, onActivity)).slice(0, MAX_ERROR_BYTES);
|
|
391
397
|
let message = `Provider returned HTTP ${upstream.status}.`;
|
|
392
398
|
try {
|
|
393
399
|
const parsed = JSON.parse(text);
|
|
@@ -396,9 +402,9 @@ async function forwardUpstreamError(upstream, res, apiKey) {
|
|
|
396
402
|
sendJsonError(res, upstream.status, 'provider_upstream_error', sanitizeProviderMessage(message, [apiKey]));
|
|
397
403
|
}
|
|
398
404
|
|
|
399
|
-
function rememberHistory(history, responseId, messages) {
|
|
405
|
+
function rememberHistory(history, responseId, messages, metadata = {}) {
|
|
400
406
|
history.delete(responseId);
|
|
401
|
-
history.set(responseId, { messages });
|
|
407
|
+
history.set(responseId, { messages, ...metadata });
|
|
402
408
|
while (history.size > MAX_HISTORY_ENTRIES) {
|
|
403
409
|
history.delete(history.keys().next().value);
|
|
404
410
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const { splitTomlStatements, readTomlStatementPath } = require('./tomlStatements');
|
|
5
|
+
|
|
6
|
+
// These fields are paths resolved against the defining configuration layer by
|
|
7
|
+
// Codex. Moving that layer into an execution scope must preserve its old anchor.
|
|
8
|
+
const ROOT_PATHS = new Set(['sqlite_home', 'log_dir', 'model_catalog_json', 'model_instructions_file', 'experimental_compact_prompt_file']);
|
|
9
|
+
const PROFILE_PATHS = new Set(['model_catalog_json', 'model_instructions_file', 'experimental_compact_prompt_file']);
|
|
10
|
+
const TLS_PATHS = new Set(['ca-certificate', 'client-certificate', 'client-private-key']);
|
|
11
|
+
|
|
12
|
+
function isConfigPath(keys) {
|
|
13
|
+
if (keys.length === 1 && ROOT_PATHS.has(keys[0])) return true;
|
|
14
|
+
if (keys.length === 3 && keys[0] === 'profiles' && PROFILE_PATHS.has(keys[2])) return true;
|
|
15
|
+
if (keys.length === 3 && keys[0] === 'agents' && keys[2] === 'config_file') return true;
|
|
16
|
+
if (keys.length === 3 && keys[0] === 'skills' && keys[1] === 'config' && keys[2] === 'path') return true;
|
|
17
|
+
if (keys.length === 2 && keys[0] === 'sandbox_workspace_write' && keys[1] === 'writable_roots') return true;
|
|
18
|
+
if (keys.length === 4 && keys[0] === 'model_providers' && keys[2] === 'auth' && keys[3] === 'cwd') return true;
|
|
19
|
+
return keys[0] === 'otel' && keys.includes('tls') && TLS_PATHS.has(keys.at(-1));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function rebaseCodexConfigPaths(content, originalDirectory) {
|
|
23
|
+
let section = [];
|
|
24
|
+
return splitTomlStatements(content).map(statement => {
|
|
25
|
+
const parsed = readTomlStatementPath(statement);
|
|
26
|
+
if (!parsed) return statement;
|
|
27
|
+
if (parsed.table) { section = parsed.keys; return statement; }
|
|
28
|
+
const edits = [];
|
|
29
|
+
visitValue(statement, parsed.valueStart, [...section, ...parsed.keys], edits, originalDirectory);
|
|
30
|
+
for (const edit of edits.reverse()) statement = statement.slice(0, edit.start) + edit.text + statement.slice(edit.end);
|
|
31
|
+
return statement;
|
|
32
|
+
}).join('');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function skipTrivia(text, position) {
|
|
36
|
+
while (position < text.length) {
|
|
37
|
+
if (/\s/.test(text[position])) { position++; continue; }
|
|
38
|
+
if (text[position] !== '#') break;
|
|
39
|
+
while (position < text.length && text[position] !== '\n') position++;
|
|
40
|
+
}
|
|
41
|
+
return position;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function visitValue(text, start, keys, edits, directory) {
|
|
45
|
+
start = skipTrivia(text, start);
|
|
46
|
+
if (text[start] === '"' || text[start] === "'") {
|
|
47
|
+
const value = readString(text, start);
|
|
48
|
+
if (isConfigPath(keys) && !path.isAbsolute(value.value) && !/^~(?:[/\\]|$)/.test(value.value) && !/^[a-z][a-z\d+.-]*:\/\//i.test(value.value)) {
|
|
49
|
+
edits.push({ start, end: value.end, text: JSON.stringify(path.resolve(directory, value.value)) });
|
|
50
|
+
}
|
|
51
|
+
return value.end;
|
|
52
|
+
}
|
|
53
|
+
if (text[start] === '[' || text[start] === '{') {
|
|
54
|
+
const table = text[start] === '{', end = table ? '}' : ']';
|
|
55
|
+
let cursor = start + 1;
|
|
56
|
+
while ((cursor = skipTrivia(text, cursor)) < text.length && text[cursor] !== end) {
|
|
57
|
+
let childKeys = keys;
|
|
58
|
+
if (table) {
|
|
59
|
+
const key = readTomlStatementPath(text.slice(cursor));
|
|
60
|
+
if (!key || key.table) throw new Error('Codex configuration contains an invalid inline TOML key.');
|
|
61
|
+
childKeys = [...keys, ...key.keys]; cursor += key.valueStart;
|
|
62
|
+
}
|
|
63
|
+
const next = visitValue(text, cursor, childKeys, edits, directory);
|
|
64
|
+
if (next <= cursor) break;
|
|
65
|
+
cursor = skipTrivia(text, next);
|
|
66
|
+
if (text[cursor] === ',') cursor++;
|
|
67
|
+
}
|
|
68
|
+
return cursor + 1;
|
|
69
|
+
}
|
|
70
|
+
let end = start;
|
|
71
|
+
while (end < text.length && ![',', ']', '}', '#', '\n'].includes(text[end])) end++;
|
|
72
|
+
return end;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function readString(text, start) {
|
|
76
|
+
const quote = text[start], triple = text.slice(start, start + 3) === quote.repeat(3);
|
|
77
|
+
let cursor = start + (triple ? 3 : 1), raw = '';
|
|
78
|
+
if (triple && text[cursor] === '\n') cursor++;
|
|
79
|
+
while (cursor < text.length) {
|
|
80
|
+
if (text[cursor] === quote && (!triple || text.slice(cursor, cursor + 3) === quote.repeat(3))) {
|
|
81
|
+
let count = triple ? 3 : 1;
|
|
82
|
+
if (triple) while (count < 5 && text[cursor + count] === quote) count++;
|
|
83
|
+
raw += triple ? quote.repeat(count - 3) : '';
|
|
84
|
+
return { value: raw, end: cursor + count };
|
|
85
|
+
}
|
|
86
|
+
const char = text[cursor++];
|
|
87
|
+
if (quote !== '"' || char !== '\\') { raw += char; continue; }
|
|
88
|
+
const escaped = text[cursor++];
|
|
89
|
+
if (triple && /\s/.test(escaped)) {
|
|
90
|
+
while (/\s/.test(text[cursor] || '') && cursor < text.length) cursor++;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const simple = { b: '\b', t: '\t', n: '\n', f: '\f', r: '\r', '"': '"', '\\': '\\' };
|
|
94
|
+
if (Object.prototype.hasOwnProperty.call(simple, escaped)) { raw += simple[escaped]; continue; }
|
|
95
|
+
const count = escaped === 'u' ? 4 : escaped === 'U' ? 8 : 0;
|
|
96
|
+
const hex = text.slice(cursor, cursor + count);
|
|
97
|
+
const point = Number.parseInt(hex, 16);
|
|
98
|
+
if (!count || !/^[\da-f]+$/i.test(hex) || hex.length !== count || point > 0x10ffff || (point >= 0xd800 && point <= 0xdfff)) {
|
|
99
|
+
throw new Error('Codex configuration contains an invalid TOML string escape.');
|
|
100
|
+
}
|
|
101
|
+
raw += String.fromCodePoint(point); cursor += count;
|
|
102
|
+
}
|
|
103
|
+
throw new Error('Codex configuration contains an unterminated TOML string.');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { rebaseCodexConfigPaths };
|