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,301 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { spawn } = require('node:child_process');
|
|
7
|
+
const { version: PACKAGE_VERSION } = require('../../package.json');
|
|
8
|
+
const { getCodexOverleafSkillsRoot } = require('./localSkills');
|
|
9
|
+
const { resolveCodexCommand, shouldUseShellForCommand } = require('./codexCommand');
|
|
10
|
+
const { runOwnedNativeHelper } = require('./nativeHelperLifecycle');
|
|
11
|
+
const { stopCodexAppServer, throwIfAborted, getAbortReason } = require('./codexSessionTiming');
|
|
12
|
+
|
|
13
|
+
const CODEX_LOCAL_SKILL_SCOPE = 'codex-local';
|
|
14
|
+
const MAX_SKILL_BYTES = 64 * 1024;
|
|
15
|
+
const MAX_DISCOVERY_BYTES = 4 * 1024 * 1024;
|
|
16
|
+
const DISCOVERY_TIMEOUT_MS = 30000;
|
|
17
|
+
|
|
18
|
+
// System skills are regenerated inside each scoped home. Ordinary skills keep
|
|
19
|
+
// their physical source identity, including aliases and same-name skills.
|
|
20
|
+
function createCodexLocalSkillIdentity(skill = {}, env = process.env) {
|
|
21
|
+
const name = String(skill.name || '').trim();
|
|
22
|
+
let source;
|
|
23
|
+
if (skill.scope === 'system' && name) source = `system:${name}`;
|
|
24
|
+
else {
|
|
25
|
+
const location = canonicalSkillPath(skill.path);
|
|
26
|
+
if (!location) return '';
|
|
27
|
+
source = `path:${location}`;
|
|
28
|
+
}
|
|
29
|
+
return `local-${crypto.createHash('sha256').update(source).digest('hex')}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isCodexOverleafSkillSource(skill = {}, env = process.env) {
|
|
33
|
+
if (!path.isAbsolute(String(skill.path || ''))) return false;
|
|
34
|
+
const root = getCodexOverleafSkillsRoot({ env });
|
|
35
|
+
const roots = comparablePaths(root);
|
|
36
|
+
return comparablePaths(skill.path).some(candidate => roots.some(base => isInside(candidate, base)));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function listCodexLocalSkills(options = {}) {
|
|
40
|
+
const { entries, discoveryWarnings } = await discoverLocalSkills(options);
|
|
41
|
+
return { skills: entries.map(entry => entry.metadata), discoveryWarnings };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function loadSelectedCodexLocalSkill({ skillId, loadCodexLocalSkills = true,
|
|
45
|
+
enabledCodexLocalSkillIds, env = process.env, signal, timeoutMs } = {}) {
|
|
46
|
+
const id = String(skillId || '').trim();
|
|
47
|
+
const empty = { skill: null, missing: [], ignored: [] };
|
|
48
|
+
if (!id) return empty;
|
|
49
|
+
if (loadCodexLocalSkills === false) return { ...empty, ignored: [{ id, reason: 'codex_local_skills_disabled' }] };
|
|
50
|
+
if (Array.isArray(enabledCodexLocalSkillIds) && !enabledCodexLocalSkillIds.includes(id)) {
|
|
51
|
+
return { ...empty, ignored: [{ id, reason: 'codex_local_skill_disabled' }] };
|
|
52
|
+
}
|
|
53
|
+
if (!/^local-[a-f0-9]{64}$/.test(id)) return { ...empty, missing: [id] };
|
|
54
|
+
const { entries } = await discoverLocalSkills({ env, signal, timeoutMs });
|
|
55
|
+
throwIfAborted(signal);
|
|
56
|
+
const entry = entries.find(item => item.metadata.id === id);
|
|
57
|
+
if (!entry) return { ...empty, missing: [id] };
|
|
58
|
+
if (!Array.isArray(enabledCodexLocalSkillIds) && entry.metadata.enabled === false) {
|
|
59
|
+
return { ...empty, ignored: [{ id, reason: 'codex_local_skill_disabled' }] };
|
|
60
|
+
}
|
|
61
|
+
const content = readSelectedContent(entry);
|
|
62
|
+
if (content === null) return { ...empty, missing: [id] };
|
|
63
|
+
return { ...empty, skill: { ...entry.metadata, path: entry.canonicalPath, content } };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function discoverLocalSkills({ env = process.env, signal, timeoutMs = DISCOVERY_TIMEOUT_MS } = {}) {
|
|
67
|
+
return runOwnedNativeHelper(async ownedSignal => {
|
|
68
|
+
throwIfAborted(ownedSignal);
|
|
69
|
+
// Lazy import avoids the home -> isolation -> identity helper cycle.
|
|
70
|
+
const { buildCodexHomeEnv } = require('./codexHome');
|
|
71
|
+
const childEnv = buildCodexHomeEnv(env, { isolateRuntimeHome: true, forceIsolatedSkillSettings: true,
|
|
72
|
+
loadCodexLocalSkills: true, loadCodexOverleafSkills: false });
|
|
73
|
+
throwIfAborted(ownedSignal);
|
|
74
|
+
const result = await runSkillsMetadataProcess(childEnv, ownedSignal, timeoutMs);
|
|
75
|
+
throwIfAborted(ownedSignal);
|
|
76
|
+
return normalizeCatalog(result, childEnv);
|
|
77
|
+
}, signal);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function normalizeCatalog(result, env) {
|
|
81
|
+
if (!Array.isArray(result?.data)) throw codedError('codex_local_skills_invalid_response', 'Codex returned an invalid local skill catalog.');
|
|
82
|
+
const entries = new Map();
|
|
83
|
+
let skippedCount = 0;
|
|
84
|
+
for (const group of result.data) {
|
|
85
|
+
if (!Array.isArray(group?.skills)) throw codedError('codex_local_skills_invalid_response', 'Codex returned an invalid local skill catalog.');
|
|
86
|
+
if (group.errors !== undefined && !Array.isArray(group.errors)) {
|
|
87
|
+
throw codedError('codex_local_skills_invalid_response', 'Codex returned an invalid local skill catalog.');
|
|
88
|
+
}
|
|
89
|
+
// Invalid source files are omitted by Codex. Keep valid skills available
|
|
90
|
+
// while exposing only a count, never filesystem paths or error contents.
|
|
91
|
+
skippedCount += group.errors?.length || 0;
|
|
92
|
+
for (const skill of group.skills) {
|
|
93
|
+
if (!skill || typeof skill !== 'object' || isCodexOverleafSkillSource(skill, env)) continue;
|
|
94
|
+
const name = cleanText(skill.name, 160);
|
|
95
|
+
const canonicalPath = canonicalSkillPath(skill.path);
|
|
96
|
+
const id = createCodexLocalSkillIdentity(skill, env);
|
|
97
|
+
if (!id || !name || !canonicalPath) continue;
|
|
98
|
+
const sourceKind = getSkillSourceKind(skill, canonicalPath, env);
|
|
99
|
+
const description = cleanText(skill.description, 2048);
|
|
100
|
+
const metadata = { id, name, title: cleanText(skill.interface?.displayName, 160) || name,
|
|
101
|
+
description, preview: cleanText(skill.interface?.shortDescription || skill.shortDescription || description, 240),
|
|
102
|
+
scope: CODEX_LOCAL_SKILL_SCOPE, sourceKind,
|
|
103
|
+
sourceLabel: sourceKind === 'plugin' ? cleanText(skill.pluginId, 160) || pluginNamePrefix(name) : '',
|
|
104
|
+
enabled: skill.enabled !== false, removable: false };
|
|
105
|
+
const existing = entries.get(id);
|
|
106
|
+
if (existing) {
|
|
107
|
+
// An enabled alias makes this same physical skill discoverable.
|
|
108
|
+
existing.metadata.enabled ||= metadata.enabled;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
entries.set(id, { metadata, canonicalPath, discoveredPath: String(skill.path) });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const resolvedEntries = Array.from(entries.values());
|
|
115
|
+
const names = new Map(), titles = new Map();
|
|
116
|
+
for (const { metadata } of resolvedEntries) {
|
|
117
|
+
names.set(metadata.name, (names.get(metadata.name) || 0) + 1);
|
|
118
|
+
titles.set(metadata.title, (titles.get(metadata.title) || 0) + 1);
|
|
119
|
+
}
|
|
120
|
+
for (const entry of resolvedEntries) {
|
|
121
|
+
if (names.get(entry.metadata.name) > 1 || titles.get(entry.metadata.title) > 1) {
|
|
122
|
+
entry.metadata.sourceHint = buildSourceHint(entry, env, resolvedEntries);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
entries: resolvedEntries.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name) || a.metadata.id.localeCompare(b.metadata.id)),
|
|
127
|
+
discoveryWarnings: skippedCount ? [{ code: 'codex_local_skills_skipped', count: skippedCount }] : []
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function buildSourceHint(entry, env, entries) {
|
|
132
|
+
if (entry.metadata.sourceKind === 'system') return `.system/${entry.metadata.name}`;
|
|
133
|
+
const { getUserCodexHome } = require('./codexHome');
|
|
134
|
+
const userHome = getUserCodexHome(env), directory = path.dirname(entry.canonicalPath);
|
|
135
|
+
const relativeDirectory = root => {
|
|
136
|
+
for (const base of comparablePaths(root)) {
|
|
137
|
+
if (directory === base || isInside(directory, base)) return path.relative(base, directory).split(path.sep).join('/');
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
};
|
|
141
|
+
if (entry.metadata.sourceKind === 'plugin') {
|
|
142
|
+
const relative = relativeDirectory(path.join(userHome, 'plugins'));
|
|
143
|
+
if (relative !== null) return `plugins/${relative.replace(/^cache\//, '')}`;
|
|
144
|
+
}
|
|
145
|
+
const relative = relativeDirectory(userHome);
|
|
146
|
+
if (relative !== null) return relative || path.basename(directory);
|
|
147
|
+
// A user skill symlink may point outside the home. Recover its original
|
|
148
|
+
// relative entry from the composed discovery path without exposing its target.
|
|
149
|
+
const discovered = path.resolve(entry.discoveredPath), runtimeSkills = path.join(String(env.CODEX_HOME || ''), 'skills');
|
|
150
|
+
if (isInside(discovered, runtimeSkills)) {
|
|
151
|
+
const inSkills = path.relative(runtimeSkills, discovered);
|
|
152
|
+
if (canonicalSkillPath(path.join(userHome, 'skills', inSkills)) === entry.canonicalPath) {
|
|
153
|
+
return `skills/${path.dirname(inSkills).split(path.sep).join('/')}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const parts = directory.split(path.sep).filter(Boolean);
|
|
157
|
+
const peers = entries.filter(other => other !== entry && (other.metadata.name === entry.metadata.name
|
|
158
|
+
|| other.metadata.title === entry.metadata.title)).map(other => path.dirname(other.canonicalPath).split(path.sep).filter(Boolean));
|
|
159
|
+
let count = Math.min(3, parts.length);
|
|
160
|
+
while (count < parts.length && peers.some(other => other.slice(-count).join('/') === parts.slice(-count).join('/'))) count++;
|
|
161
|
+
return `…/${parts.slice(-count).join('/')}`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function getSkillSourceKind(skill, canonicalPath, env) {
|
|
165
|
+
if (skill.scope === 'system') return 'system';
|
|
166
|
+
if (skill.pluginId) return 'plugin';
|
|
167
|
+
// Current app-server metadata reports plugin skills as scope "user" and
|
|
168
|
+
// does not carry a pluginId. Classify only returned files under the active
|
|
169
|
+
// user plugin root; discovering old cache directories is never necessary.
|
|
170
|
+
const { getUserCodexHome } = require('./codexHome');
|
|
171
|
+
const pluginRoots = comparablePaths(path.join(getUserCodexHome(env), 'plugins'));
|
|
172
|
+
if (pluginRoots.some(root => isInside(canonicalPath, root))) return 'plugin';
|
|
173
|
+
return skill.scope === 'user' ? 'user' : 'local';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function pluginNamePrefix(name) {
|
|
177
|
+
const prefix = name.includes(':') ? name.slice(0, name.indexOf(':')).trim() : '';
|
|
178
|
+
return /[/\\]/.test(prefix) ? '' : prefix;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function runSkillsMetadataProcess(env, signal, timeoutMs) {
|
|
182
|
+
const command = resolveCodexCommand(env);
|
|
183
|
+
if (!command) throw codedError('codex_not_found', 'Codex CLI was not found.');
|
|
184
|
+
return new Promise((resolve, reject) => {
|
|
185
|
+
throwIfAborted(signal);
|
|
186
|
+
const child = spawn(command, ['app-server', '--listen', 'stdio://'], {
|
|
187
|
+
cwd: env.CODEX_HOME, env, shell: shouldUseShellForCommand(command, env),
|
|
188
|
+
detached: process.platform !== 'win32', stdio: ['pipe', 'pipe', 'pipe']
|
|
189
|
+
});
|
|
190
|
+
const pending = new Map();
|
|
191
|
+
let sequence = 0, buffer = '', outputBytes = 0, settled = false;
|
|
192
|
+
const onAbort = () => finish(getAbortReason(signal));
|
|
193
|
+
const budget = Math.min(DISCOVERY_TIMEOUT_MS, Math.max(1, Number(timeoutMs) || DISCOVERY_TIMEOUT_MS));
|
|
194
|
+
const timer = setTimeout(() => finish(codedError('codex_local_skills_timeout', 'Local Codex skill discovery timed out.')), budget);
|
|
195
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
196
|
+
child.stdout.setEncoding('utf8');
|
|
197
|
+
child.stderr.setEncoding('utf8');
|
|
198
|
+
child.stdout.on('data', chunk => {
|
|
199
|
+
if (settled || !countOutput(chunk)) return;
|
|
200
|
+
buffer += chunk;
|
|
201
|
+
const lines = buffer.split(/\r?\n/);
|
|
202
|
+
buffer = lines.pop() || '';
|
|
203
|
+
for (const line of lines) {
|
|
204
|
+
if (settled) break;
|
|
205
|
+
if (line.trim()) handleMessage(line);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
// Stderr may contain user configuration paths or server diagnostics. Count
|
|
209
|
+
// it for bounded lifetime, but never return it as catalog/UI content.
|
|
210
|
+
child.stderr.on('data', chunk => { if (!settled) countOutput(chunk); });
|
|
211
|
+
child.stdin.on('error', () => finish(codedError('codex_local_skills_failed', 'Local Codex skill discovery failed.')));
|
|
212
|
+
child.on('error', error => finish(codedError(error.code === 'ENOENT' ? 'codex_not_found' : 'codex_local_skills_failed', 'Codex could not start local skill discovery.')));
|
|
213
|
+
child.on('close', () => { if (!settled) finish(codedError('codex_local_skills_failed', 'Codex exited before local skill discovery completed.')); });
|
|
214
|
+
(async () => {
|
|
215
|
+
throwIfAborted(signal);
|
|
216
|
+
await request('initialize', { clientInfo: { name: 'codex-overleaf-link', version: PACKAGE_VERSION }, capabilities: null });
|
|
217
|
+
child.stdin.write(`${JSON.stringify({ method: 'initialized' })}\n`);
|
|
218
|
+
const result = await request('skills/list', { cwd: env.CODEX_HOME, cwds: [env.CODEX_HOME], includeDisabled: true, forceReload: true });
|
|
219
|
+
finish(null, result);
|
|
220
|
+
})().catch(finish);
|
|
221
|
+
|
|
222
|
+
function countOutput(chunk) {
|
|
223
|
+
outputBytes += Buffer.byteLength(chunk);
|
|
224
|
+
if (outputBytes <= MAX_DISCOVERY_BYTES) return true;
|
|
225
|
+
finish(codedError('codex_local_skills_output_limit', 'Local Codex skill discovery exceeded its output limit.'));
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
function request(method, params) {
|
|
229
|
+
return new Promise((resolveRequest, rejectRequest) => {
|
|
230
|
+
if (settled) return rejectRequest(codedError('codex_local_skills_closed', 'Local Codex skill discovery has closed.'));
|
|
231
|
+
const id = ++sequence;
|
|
232
|
+
pending.set(id, { resolve: resolveRequest, reject: rejectRequest });
|
|
233
|
+
child.stdin.write(`${JSON.stringify({ id, method, params })}\n`);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function handleMessage(line) {
|
|
237
|
+
let message;
|
|
238
|
+
try { message = JSON.parse(line); } catch { return; }
|
|
239
|
+
const waiter = pending.get(message?.id);
|
|
240
|
+
if (waiter && (Object.hasOwn(message, 'result') || message.error)) {
|
|
241
|
+
pending.delete(message.id);
|
|
242
|
+
if (message.error) waiter.reject(codedError('codex_local_skills_failed', 'Codex could not list local skills.'));
|
|
243
|
+
else waiter.resolve(message.result);
|
|
244
|
+
} else if (message && Object.hasOwn(message, 'id') && message.method) {
|
|
245
|
+
child.stdin.write(`${JSON.stringify({ id: message.id, error: { code: -32601, message: 'Unsupported during skill discovery' } })}\n`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function finish(error, result) {
|
|
249
|
+
if (settled) return;
|
|
250
|
+
settled = true;
|
|
251
|
+
clearTimeout(timer);
|
|
252
|
+
signal.removeEventListener('abort', onAbort);
|
|
253
|
+
for (const waiter of pending.values()) waiter.reject(error || codedError('codex_local_skills_closed', 'Local Codex skill discovery has closed.'));
|
|
254
|
+
pending.clear();
|
|
255
|
+
stopCodexAppServer(child, { processGroup: process.platform !== 'win32', reason: error }).then(() => {
|
|
256
|
+
if (error) reject(error); else resolve(result);
|
|
257
|
+
}, reject);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function readSelectedContent(entry) {
|
|
263
|
+
let fd;
|
|
264
|
+
try {
|
|
265
|
+
if (canonicalSkillPath(entry.discoveredPath) !== entry.canonicalPath) return null;
|
|
266
|
+
fd = fs.openSync(entry.canonicalPath, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW || 0));
|
|
267
|
+
const stat = fs.fstatSync(fd);
|
|
268
|
+
if (!stat.isFile() || stat.size > MAX_SKILL_BYTES) return null;
|
|
269
|
+
const bytes = Buffer.alloc(MAX_SKILL_BYTES + 1);
|
|
270
|
+
let length = 0, count;
|
|
271
|
+
while ((count = fs.readSync(fd, bytes, length, bytes.length - length, length)) > 0) {
|
|
272
|
+
length += count;
|
|
273
|
+
if (length > MAX_SKILL_BYTES) return null;
|
|
274
|
+
}
|
|
275
|
+
if (canonicalSkillPath(entry.discoveredPath) !== entry.canonicalPath || bytes.subarray(0, length).includes(0)) return null;
|
|
276
|
+
const current = fs.statSync(entry.canonicalPath);
|
|
277
|
+
if (current.dev !== stat.dev || current.ino !== stat.ino) return null;
|
|
278
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes.subarray(0, length));
|
|
279
|
+
} catch (error) {
|
|
280
|
+
if (['ENOENT', 'ENOTDIR', 'EACCES', 'ELOOP'].includes(error.code) || error instanceof TypeError) return null;
|
|
281
|
+
throw error;
|
|
282
|
+
} finally { if (fd !== undefined) fs.closeSync(fd); }
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function canonicalSkillPath(value) {
|
|
286
|
+
if (!path.isAbsolute(String(value || '')) || path.basename(String(value)) !== 'SKILL.md') return '';
|
|
287
|
+
try {
|
|
288
|
+
const resolved = fs.realpathSync(String(value));
|
|
289
|
+
return fs.statSync(resolved).isFile() ? resolved : '';
|
|
290
|
+
} catch { return ''; }
|
|
291
|
+
}
|
|
292
|
+
function comparablePaths(value) {
|
|
293
|
+
const resolved = path.resolve(value);
|
|
294
|
+
try { return [resolved, fs.realpathSync(resolved)]; } catch { return [resolved]; }
|
|
295
|
+
}
|
|
296
|
+
function isInside(candidate, root) { const relative = path.relative(root, candidate); return relative !== '' && relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative); }
|
|
297
|
+
function cleanText(value, limit) { return typeof value === 'string' ? value.replace(/\s+/g, ' ').trim().slice(0, limit) : ''; }
|
|
298
|
+
function codedError(code, message) { return Object.assign(new Error(message), { code }); }
|
|
299
|
+
|
|
300
|
+
module.exports = { CODEX_LOCAL_SKILL_SCOPE, createCodexLocalSkillIdentity, isCodexOverleafSkillSource,
|
|
301
|
+
listCodexLocalSkills, loadSelectedCodexLocalSkill };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { refreshCodexRuntimeEnv } = require('./nativeEnvironment');
|
|
4
|
+
const { getCodexRuntimeIdentityFromEnv, compareCodexVersions, buildCodexRuntimeEvent } = require('./codexRuntimeIdentity');
|
|
5
|
+
const { logDebug } = require('./debugLog');
|
|
6
|
+
|
|
7
|
+
const UPGRADE_CODE = 'codex_model_requires_newer_cli';
|
|
8
|
+
const STOP_CODES = new Set(['codex_cancelled', 'codex_process_stop_unconfirmed', 'thread_resume_failed']);
|
|
9
|
+
|
|
10
|
+
function rejectedModel(error, expectedModel) {
|
|
11
|
+
if (!error || STOP_CODES.has(error.code)) return '';
|
|
12
|
+
let current = error, inheritedStatus = 0;
|
|
13
|
+
for (let depth = 0; depth < 4 && current && typeof current === 'object'; depth++) {
|
|
14
|
+
const detail = current.error && typeof current.error === 'object' ? current.error : current;
|
|
15
|
+
const status = Number(current.status || current.statusCode || inheritedStatus);
|
|
16
|
+
const type = detail.type || detail.code;
|
|
17
|
+
const message = String(detail.message || current.message || '');
|
|
18
|
+
const match = /^The ['"]([^'"]+)['"] model requires a newer version of Codex\b/i.exec(message.trim());
|
|
19
|
+
if (status === 400 && type === 'invalid_request_error' && match) {
|
|
20
|
+
return !expectedModel || match[1] === expectedModel ? match[1] : '';
|
|
21
|
+
}
|
|
22
|
+
inheritedStatus = status;
|
|
23
|
+
if (message.length <= 12000 && message.trim().startsWith('{')) {
|
|
24
|
+
try { current = JSON.parse(message); continue; } catch (_) {}
|
|
25
|
+
}
|
|
26
|
+
if (detail !== current) current = detail;
|
|
27
|
+
else break;
|
|
28
|
+
}
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function formatModelUpgradeError(error, env, options = {}) {
|
|
33
|
+
if (error?.code === UPGRADE_CODE) return error;
|
|
34
|
+
const model = rejectedModel(error, options.model);
|
|
35
|
+
if (!model) return null;
|
|
36
|
+
const identity = getCodexRuntimeIdentityFromEnv(env);
|
|
37
|
+
const selected = identity.selected || {};
|
|
38
|
+
const version = selected.version || env.CODEX_OVERLEAF_CODEX_VERSION || 'unknown';
|
|
39
|
+
const pinned = identity.selectedBy === 'explicit-path' || identity.selectedBy === 'legacy-path';
|
|
40
|
+
const chinese = /^zh\b/i.test(String(options.locale || ''));
|
|
41
|
+
const message = chinese
|
|
42
|
+
? '模型 ' + model + ' 要求更新的 Codex 运行时。本次使用 CLI ' + version + '。'
|
|
43
|
+
+ (pinned ? '当前 CLI 路径已手动固定,请更新该安装或调整固定路径后重试。'
|
|
44
|
+
: options.retried ? '切换本机较新版本后仍被拒绝,请更新 Codex 后重试。'
|
|
45
|
+
: '未找到可自动切换的更新版本,请更新 Codex 后重试。')
|
|
46
|
+
: 'Model ' + model + ' requires a newer Codex runtime. This task used CLI ' + version + '. '
|
|
47
|
+
+ (pinned ? 'The CLI path is pinned. Update that installation or change the configured path, then retry.'
|
|
48
|
+
: options.retried ? 'The newer local CLI was also rejected. Update Codex and retry.'
|
|
49
|
+
: 'No newer local CLI was available for automatic recovery. Update Codex and retry.');
|
|
50
|
+
return Object.assign(new Error(message), {
|
|
51
|
+
code: UPGRADE_CODE,
|
|
52
|
+
details: {
|
|
53
|
+
model, codexVersion: version, codexSource: selected.source || '',
|
|
54
|
+
codexPath: selected.displayPath || selected.path || '',
|
|
55
|
+
pinned, recoveryAttempted: options.retried === true
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// This runner is used only for the isolated, read-only style-generation job.
|
|
61
|
+
// Its model/provider/input remain unchanged; the one retry changes only CLI env.
|
|
62
|
+
function createRecoveringStyleRunner(options) {
|
|
63
|
+
let currentEnv = options.env;
|
|
64
|
+
let retried = false;
|
|
65
|
+
return async function run(input) {
|
|
66
|
+
if (input.signal?.aborted) throw input.signal.reason || Object.assign(new Error('Cancelled'), { code: 'codex_cancelled' });
|
|
67
|
+
try {
|
|
68
|
+
return await options.execute({ ...input, env: currentEnv });
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (input.signal?.aborted || !rejectedModel(error, input.model)) throw error;
|
|
71
|
+
const previous = getCodexRuntimeIdentityFromEnv(currentEnv);
|
|
72
|
+
let refreshed = currentEnv;
|
|
73
|
+
try { refreshed = refreshCodexRuntimeEnv(currentEnv, { force: true }); }
|
|
74
|
+
catch (_) { /* Keep the original failure if discovery itself is unavailable. */ }
|
|
75
|
+
const next = getCodexRuntimeIdentityFromEnv(refreshed);
|
|
76
|
+
const newer = next.selected?.path && compareCodexVersions(
|
|
77
|
+
next.selected.version, previous.selected?.version || ''
|
|
78
|
+
) > 0;
|
|
79
|
+
if (!retried && newer) {
|
|
80
|
+
retried = true;
|
|
81
|
+
currentEnv = refreshed;
|
|
82
|
+
if (input.signal?.aborted) throw input.signal.reason || Object.assign(new Error('Cancelled'), { code: 'codex_cancelled' });
|
|
83
|
+
logDebug('codex.runtime.model_retry_started', {
|
|
84
|
+
model: input.model, previousVersion: previous.selected?.version || '',
|
|
85
|
+
selectedVersion: next.selected.version, source: next.selected.source
|
|
86
|
+
});
|
|
87
|
+
const runtimeEvent = buildCodexRuntimeEvent(currentEnv);
|
|
88
|
+
if (runtimeEvent && typeof options.emit === 'function') options.emit(runtimeEvent);
|
|
89
|
+
try {
|
|
90
|
+
const result = await options.execute({ ...input, env: currentEnv });
|
|
91
|
+
logDebug('codex.runtime.model_retry_completed', { model: input.model, selectedVersion: next.selected.version });
|
|
92
|
+
return result;
|
|
93
|
+
} catch (retryError) {
|
|
94
|
+
if (input.signal?.aborted) throw retryError;
|
|
95
|
+
throw formatModelUpgradeError(retryError, currentEnv, {
|
|
96
|
+
model: input.model, locale: options.locale, retried: true
|
|
97
|
+
}) || retryError;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
throw formatModelUpgradeError(error, currentEnv, {
|
|
101
|
+
model: input.model, locale: options.locale, retried
|
|
102
|
+
}) || error;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = { createRecoveringStyleRunner, formatModelUpgradeError };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { truncateText } = require('./debugLog');
|
|
4
|
+
const { formatOverleafWorkspaceRules } = require('./overleafWorkspaceRules');
|
|
4
5
|
|
|
5
6
|
const PROJECT_CUSTOM_INSTRUCTIONS_MAX_CHARS = 12000;
|
|
6
7
|
const NATIVE_MESSAGE_PROMPT_MAX_CHARS = 1024 * 1024;
|
|
@@ -30,8 +31,8 @@ function buildCodexTurnPrompt(options = {}) {
|
|
|
30
31
|
'',
|
|
31
32
|
'Current Overleaf workspace:',
|
|
32
33
|
`- Project: ${context.projectKey || context.projectId || 'unknown'}`,
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
...formatWorkspaceSnapshotContext(context.unreadFiles),
|
|
35
|
+
...(isSkillInstallerInvocation(context.skillInvocation) ? [] : ['', formatOverleafWorkspaceRules()]),
|
|
35
36
|
'',
|
|
36
37
|
'Project location citation rules:',
|
|
37
38
|
formatProjectLocationCitationRules(),
|
|
@@ -129,6 +130,7 @@ function normalizePromptOptions(options = {}) {
|
|
|
129
130
|
projectKey: mirror.projectKey || options.projectKey || params.projectId || params.project?.id || params.project?.projectId,
|
|
130
131
|
projectId: options.projectId || params.projectId || params.project?.id || params.project?.projectId,
|
|
131
132
|
workspacePath: mirror.workspacePath || options.workspacePath || '',
|
|
133
|
+
unreadFiles: Array.isArray(mirror.skippedFiles) ? mirror.skippedFiles : [],
|
|
132
134
|
userTask: String(options.task !== undefined ? options.task : params.task || '').trim(),
|
|
133
135
|
mode: options.mode || params.mode || 'auto',
|
|
134
136
|
customInstructions: options.customInstructions !== undefined ? options.customInstructions : params.customInstructions,
|
|
@@ -152,6 +154,19 @@ function normalizePromptOptions(options = {}) {
|
|
|
152
154
|
};
|
|
153
155
|
}
|
|
154
156
|
|
|
157
|
+
function formatWorkspaceSnapshotContext(unreadFiles) {
|
|
158
|
+
if (!unreadFiles.length) return [
|
|
159
|
+
'- The local workspace was synced from Overleaf immediately before this turn.',
|
|
160
|
+
'- If the recent session history conflicts with the files in the workspace, trust the files.'
|
|
161
|
+
];
|
|
162
|
+
return [
|
|
163
|
+
'- The readable project files were synced from Overleaf before this turn.',
|
|
164
|
+
'- The following assets were not read because of the binary size limits. A retained local copy may be stale; a missing local copy does not mean the asset was deleted from Overleaf.',
|
|
165
|
+
'- Do not rely on these assets as current evidence or edit them. Their local changes cannot be written back until their current Overleaf content is read. Other readable files remain available for this task.',
|
|
166
|
+
...unreadFiles.map(file => `- Unavailable current content: ${JSON.stringify(file.path)} (${file.reason}).`)
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
|
|
155
170
|
function normalizeLoadedSkills(skills = []) {
|
|
156
171
|
return (Array.isArray(skills) ? skills : [])
|
|
157
172
|
.map(skill => ({
|
|
@@ -393,17 +408,20 @@ function formatSkillInvocationContext(context = {}) {
|
|
|
393
408
|
const codexSkillInvocationContext = context.codexSkillInvocationContext || {};
|
|
394
409
|
const contextInvocation = normalizeSkillInvocation(codexSkillInvocationContext.invocation);
|
|
395
410
|
const effectiveInvocation = contextInvocation || invocation;
|
|
411
|
+
const skillLabel = effectiveInvocation?.scope === 'codex-local' ? 'local Codex' : 'Codex Overleaf';
|
|
396
412
|
if (Array.isArray(codexSkillInvocationContext.ignored) && codexSkillInvocationContext.ignored.length) {
|
|
397
413
|
return [
|
|
398
|
-
|
|
414
|
+
`Ignored selected ${skillLabel} skill:`,
|
|
399
415
|
...codexSkillInvocationContext.ignored.map(item => `- ${item.id}`),
|
|
400
|
-
|
|
416
|
+
effectiveInvocation?.scope === 'codex-local'
|
|
417
|
+
? '- Reason: The selected local Codex skill is disabled for this turn.'
|
|
418
|
+
: '- Reason: Codex Overleaf skills are disabled for this turn.',
|
|
401
419
|
'- The stale slash selection was ignored; no selected skill instructions were forced into this prompt.'
|
|
402
420
|
].join('\n');
|
|
403
421
|
}
|
|
404
422
|
if (Array.isArray(codexSkillInvocationContext.missing) && codexSkillInvocationContext.missing.length) {
|
|
405
423
|
return [
|
|
406
|
-
|
|
424
|
+
`Missing selected ${skillLabel} skill:`,
|
|
407
425
|
...codexSkillInvocationContext.missing.map(id => `- ${id}`),
|
|
408
426
|
'- The stale slash selection was ignored; no selected skill instructions were forced into this prompt.'
|
|
409
427
|
].join('\n');
|
|
@@ -425,17 +443,19 @@ function formatSkillInvocationContext(context = {}) {
|
|
|
425
443
|
if (loadedSkill) {
|
|
426
444
|
return [
|
|
427
445
|
`- ${effectiveInvocation.id} (${effectiveInvocation.title})`,
|
|
428
|
-
|
|
446
|
+
`- REQUIRED for this turn: read and use this selected ${skillLabel} skill before answering.`,
|
|
429
447
|
'- Follow the embedded SKILL.md instructions when they apply to the current user request.',
|
|
448
|
+
...(effectiveInvocation.scope === 'codex-local' && loadedSkill.path
|
|
449
|
+
? [`- Skill source: ${loadedSkill.path}`, '- Resolve relative skill resources against this SKILL.md directory.'] : []),
|
|
430
450
|
'',
|
|
431
|
-
|
|
451
|
+
`Selected ${skillLabel} SKILL.md:`,
|
|
432
452
|
`## ${loadedSkill.id}: ${loadedSkill.title || effectiveInvocation.title || loadedSkill.id}`,
|
|
433
453
|
fencedBlock(loadedSkill.content)
|
|
434
454
|
].join('\n');
|
|
435
455
|
}
|
|
436
456
|
return [
|
|
437
457
|
`- ${effectiveInvocation.id} (${effectiveInvocation.title})`,
|
|
438
|
-
|
|
458
|
+
`- Use this selected ${skillLabel} skill for the current turn.`,
|
|
439
459
|
'- Follow the skill instructions and workflow when they apply to the user request.'
|
|
440
460
|
].join('\n');
|
|
441
461
|
}
|
|
@@ -448,17 +468,18 @@ function normalizeSkillInvocation(value) {
|
|
|
448
468
|
const title = String(value?.title || value?.name || (id === 'skill-installer' ? 'Skill Installer' : id))
|
|
449
469
|
.trim()
|
|
450
470
|
.slice(0, 80) || 'Skill Installer';
|
|
451
|
-
if (id === 'skill-installer') {
|
|
471
|
+
if (id === 'skill-installer' && (!value?.scope || value.scope === 'builtin')) {
|
|
452
472
|
return { id, title };
|
|
453
473
|
}
|
|
454
|
-
if (
|
|
474
|
+
if (!['codex-overleaf', 'codex-local'].includes(value?.scope) && !Object.prototype.hasOwnProperty.call(value || {}, 'skillId')) {
|
|
455
475
|
return null;
|
|
456
476
|
}
|
|
457
|
-
return { id, title, scope: 'codex-overleaf' };
|
|
477
|
+
return { id, title, scope: value?.scope === 'codex-local' ? 'codex-local' : 'codex-overleaf' };
|
|
458
478
|
}
|
|
459
479
|
|
|
460
480
|
function isSkillInstallerInvocation(value) {
|
|
461
|
-
|
|
481
|
+
const invocation = normalizeSkillInvocation(value);
|
|
482
|
+
return invocation?.id === 'skill-installer' && !invocation.scope;
|
|
462
483
|
}
|
|
463
484
|
|
|
464
485
|
function isSafeSkillId(id) {
|
|
@@ -26,8 +26,8 @@ function createProviderLaunch({ profile, secret = '', modelId, wireApi, reasonin
|
|
|
26
26
|
wireApi,
|
|
27
27
|
upstreamResponseMode: resolvedResponseMode === 'buffered' ? 'buffered' : 'streaming',
|
|
28
28
|
requestTimeoutMs: profile.requestTimeoutMs,
|
|
29
|
-
reasoningAdapter: profile.reasoningAdapter || 'auto',
|
|
30
|
-
reasoningCapability: profile.reasoningCapability || 'auto',
|
|
29
|
+
reasoningAdapter: model.reasoningAdapter || profile.reasoningAdapter || 'auto',
|
|
30
|
+
reasoningCapability: model.reasoningCapability || profile.reasoningCapability || 'auto',
|
|
31
31
|
reasoningEffort,
|
|
32
32
|
reasoningEfforts: model.reasoningEfforts?.length
|
|
33
33
|
? model.reasoningEfforts.slice()
|
|
@@ -50,7 +50,7 @@ function createProviderLaunch({ profile, secret = '', modelId, wireApi, reasonin
|
|
|
50
50
|
anthropicThinkingMode: profile.anthropicThinkingMode || 'budget',
|
|
51
51
|
anthropicPromptCaching: profile.anthropicPromptCaching === true,
|
|
52
52
|
impersonateClaudeCode: profile.impersonateClaudeCode === true,
|
|
53
|
-
maxOutputTokens: profile.maxOutputTokens || 65536,
|
|
53
|
+
maxOutputTokens: model.maxOutputTokens || profile.maxOutputTokens || 65536,
|
|
54
54
|
apiKey: secret
|
|
55
55
|
});
|
|
56
56
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { runOwnedNativeHelper } = require('./nativeHelperLifecycle');
|
|
4
|
+
const { stopCodexAppServer } = require('./codexSessionTiming');
|
|
5
|
+
const { spawn } = require('node:child_process');
|
|
4
6
|
const crypto = require('node:crypto');
|
|
5
7
|
const fs = require('node:fs');
|
|
6
8
|
const os = require('node:os');
|
|
@@ -12,16 +14,22 @@ const { providerError } = require('./providerProfile');
|
|
|
12
14
|
const MAX_OUTPUT_BYTES = 256 * 1024;
|
|
13
15
|
|
|
14
16
|
async function runProviderConnectionTest({ launch, env = process.env, signal } = {}) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
throwIfTestCancelled(signal);
|
|
18
|
+
return runOwnedNativeHelper(async ownedSignal => {
|
|
19
|
+
throwIfTestCancelled(ownedSignal);
|
|
20
|
+
const prepared = await prepareProviderLaunch(launch, { signal: ownedSignal });
|
|
21
|
+
try {
|
|
22
|
+
throwIfTestCancelled(ownedSignal);
|
|
23
|
+
return await runProviderConnectionTestProcess({ launch: prepared.launch, env, signal: ownedSignal });
|
|
24
|
+
} finally {
|
|
25
|
+
await prepared.close();
|
|
26
|
+
}
|
|
27
|
+
}, signal);
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
function runProviderConnectionTestProcess({ launch, env = process.env, signal } = {}) {
|
|
24
31
|
return new Promise((resolve, reject) => {
|
|
32
|
+
throwIfTestCancelled(signal);
|
|
25
33
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'codex-overleaf-provider-test-'));
|
|
26
34
|
const codexHome = path.join(root, 'codex-home');
|
|
27
35
|
const workspace = path.join(root, 'workspace');
|
|
@@ -52,6 +60,7 @@ function runProviderConnectionTestProcess({ launch, env = process.env, signal }
|
|
|
52
60
|
const startedAt = Date.now();
|
|
53
61
|
let child;
|
|
54
62
|
try {
|
|
63
|
+
throwIfTestCancelled(signal);
|
|
55
64
|
child = spawn(command, args, {
|
|
56
65
|
cwd: workspace,
|
|
57
66
|
env: childEnv,
|
|
@@ -61,7 +70,8 @@ function runProviderConnectionTestProcess({ launch, env = process.env, signal }
|
|
|
61
70
|
});
|
|
62
71
|
} catch (error) {
|
|
63
72
|
cleanup(root);
|
|
64
|
-
reject(
|
|
73
|
+
reject(error?.code === 'provider_test_cancelled' ? error
|
|
74
|
+
: providerError('provider_test_spawn_failed', 'Codex could not start the provider connection test.', { cause: error }));
|
|
65
75
|
return;
|
|
66
76
|
}
|
|
67
77
|
let stdout = '';
|
|
@@ -121,10 +131,10 @@ function runProviderConnectionTestProcess({ launch, env = process.env, signal }
|
|
|
121
131
|
settled = true;
|
|
122
132
|
clearTimeout(timer);
|
|
123
133
|
signal?.removeEventListener('abort', onAbort);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
stopCodexAppServer(child, { processGroup: process.platform !== 'win32', reason: error }).then(() => {
|
|
135
|
+
cleanup(root);
|
|
136
|
+
if (error) reject(error); else resolve(result);
|
|
137
|
+
}, stopError => { cleanup(root); reject(stopError); });
|
|
128
138
|
}
|
|
129
139
|
});
|
|
130
140
|
}
|
|
@@ -168,20 +178,8 @@ function hasLeakedToolControlTokens(value) {
|
|
|
168
178
|
return /<\|tool_call_(?:begin|argument_begin|end)\|>/i.test(String(value || ''));
|
|
169
179
|
}
|
|
170
180
|
|
|
171
|
-
function
|
|
172
|
-
if (
|
|
173
|
-
try {
|
|
174
|
-
if (process.platform === 'win32') {
|
|
175
|
-
spawnSync('taskkill', ['/pid', String(child.pid), '/t', '/f'], { stdio: 'ignore', windowsHide: true });
|
|
176
|
-
} else {
|
|
177
|
-
process.kill(-child.pid, 'SIGTERM');
|
|
178
|
-
setTimeout(() => {
|
|
179
|
-
try { process.kill(-child.pid, 'SIGKILL'); } catch (_error) {}
|
|
180
|
-
}, 500).unref?.();
|
|
181
|
-
}
|
|
182
|
-
} catch (_error) {
|
|
183
|
-
try { child.kill('SIGKILL'); } catch (_killError) {}
|
|
184
|
-
}
|
|
181
|
+
function throwIfTestCancelled(signal) {
|
|
182
|
+
if (signal?.aborted) throw providerError('provider_test_cancelled', 'Provider connection test was cancelled.');
|
|
185
183
|
}
|
|
186
184
|
|
|
187
185
|
function cleanup(root) {
|