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
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
(function
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) module.exports = factory(require('./runRecoveryActions'));
|
|
3
|
+
else root.CodexOverleafModuleRegistry.define('RunTimelineView', ['RunRecoveryActions'], factory);
|
|
4
|
+
})(typeof window !== 'undefined' ? window : globalThis, function (RunRecoveryActions) {
|
|
2
5
|
'use strict';
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// run-card / stream-event / activity rendering, the completion report, and
|
|
8
|
-
// the run-card Undo/Accept controls. Code moved verbatim (original
|
|
9
|
-
// indentation kept); runtime collaborators are factory-injected and mutable
|
|
10
|
-
// runtime state (panel, panel state, the live run view) is read through lazy
|
|
11
|
-
// getters. The view-local scroll/timer state below moved here with the code
|
|
12
|
-
// that owns it.
|
|
7
|
+
|
|
8
|
+
// Owns scroll, cards, reports and mature run actions. The optional activity
|
|
9
|
+
// presenter projects stored events without taking ownership of settlement.
|
|
13
10
|
function create(deps = {}) {
|
|
14
11
|
const {
|
|
12
|
+
RunActivitySummary,
|
|
13
|
+
RunPresence,
|
|
14
|
+
RunActivityModel,
|
|
15
|
+
SubagentActivityView,
|
|
15
16
|
RunGuidanceView,
|
|
17
|
+
getPendingGuidance = () => [],
|
|
16
18
|
RunResultActions,
|
|
17
19
|
RunScrollLayout,
|
|
18
20
|
RunFailureNotice,
|
|
21
|
+
I18n,
|
|
22
|
+
FailureReasons,
|
|
23
|
+
localizeVisibleReason = value => value,
|
|
24
|
+
localizeCompileReason = value => value,
|
|
19
25
|
tr,
|
|
20
26
|
tx,
|
|
21
27
|
getLocale,
|
|
@@ -25,6 +31,7 @@
|
|
|
25
31
|
formatEventDetail,
|
|
26
32
|
formatEventTime,
|
|
27
33
|
renderAttachmentPreviewList,
|
|
34
|
+
renderSentSelection,
|
|
28
35
|
formatModeLabel,
|
|
29
36
|
undoRun,
|
|
30
37
|
acceptRun,
|
|
@@ -41,11 +48,16 @@
|
|
|
41
48
|
getState,
|
|
42
49
|
getCurrentRunView,
|
|
43
50
|
refillComposerForRetry,
|
|
51
|
+
canEditRun,
|
|
52
|
+
retryWriteback,
|
|
44
53
|
showNativeSetupGuidance,
|
|
45
54
|
openProjectFileForFailure,
|
|
46
55
|
openStorageSettings,
|
|
47
56
|
trackedChangeInFlight,
|
|
48
|
-
projectRunSettlement
|
|
57
|
+
projectRunSettlement,
|
|
58
|
+
getCurrentProjectId,
|
|
59
|
+
getAccountScopeId,
|
|
60
|
+
getProjectName
|
|
49
61
|
} = deps;
|
|
50
62
|
|
|
51
63
|
let logAutoFollow = true;
|
|
@@ -57,11 +69,10 @@
|
|
|
57
69
|
// drives the floating "jump to latest" button's counter.
|
|
58
70
|
let scrollLogRafId = 0;
|
|
59
71
|
let scrollLogPendingForce = false;
|
|
72
|
+
let pendingGuidanceReveal = null;
|
|
60
73
|
let jumpToLatestButton = null;
|
|
61
74
|
let unreadSinceDetach = 0;
|
|
62
|
-
//
|
|
63
|
-
// reads a static "Processing…" and the user can't tell a working run from a
|
|
64
|
-
// hung one — the single highest-value streaming signal per competitor UX.
|
|
75
|
+
// Elapsed time belongs to the run; tool rows retain their own lifecycle.
|
|
65
76
|
let runElapsedTimer = null;
|
|
66
77
|
const scrollLayout = RunScrollLayout?.create({
|
|
67
78
|
getScroller: getLogScrollContainer,
|
|
@@ -69,12 +80,32 @@
|
|
|
69
80
|
onLayoutChange: scroller => logAutoFollow ? scrollLogToBottom() : updateJumpToLatestButton(scroller)
|
|
70
81
|
});
|
|
71
82
|
const failureNotice = RunFailureNotice?.create({ tr, projectRunSettlement, sanitizeText: sanitizeAssistantVisibleText });
|
|
83
|
+
const { buildRecoveryButton, appendRecoveryActionForFailure } = RunRecoveryActions.create({
|
|
84
|
+
document: typeof document === 'undefined' ? undefined : document,
|
|
85
|
+
window: typeof window === 'undefined' ? undefined : window,
|
|
86
|
+
tx, failureNotice, refillComposerForRetry, openProjectFileForFailure, showNativeSetupGuidance,
|
|
87
|
+
openStorageSettings, forceCancelStuckTaskForCurrentProject
|
|
88
|
+
});
|
|
89
|
+
const presence = RunPresence?.create({ tx, getLocale, formatElapsed });
|
|
90
|
+
const displayRun = run => RunFailureNotice?.projectResolvedUndo?.(run) || run;
|
|
91
|
+
const displayLocalizedRun = run => {
|
|
92
|
+
const displayed = displayRun(run);
|
|
93
|
+
return displayed ? { ...displayed, events: (displayed.events || []).map(sanitizeRunEventForRender) } : displayed;
|
|
94
|
+
};
|
|
95
|
+
const activitySummary = RunActivitySummary?.create({ RunActivityModel, RunGuidanceView, getPendingGuidance, SubagentActivityView, tx, findRunRecord: (...args) => displayLocalizedRun(findRunRecord(...args)), getPanel, cssEscape,
|
|
96
|
+
projectReviewResultEvent: sanitizeRunEventForRender,
|
|
97
|
+
formatReviewResultFailure,
|
|
98
|
+
formatEventTime, formatElapsed, renderMarkdownBlockText, renderRunEvent, formatEventDetail,
|
|
99
|
+
presence, classifyStatus: classifyRunPresence, getProjectId: () => getCurrentProjectId?.() || '',
|
|
100
|
+
summarizeCommand: RunPresence?.commandSummary,
|
|
101
|
+
isGuidance: event => Boolean(RunGuidanceView.getGuidanceText(event)), sanitizeAssistantVisibleText });
|
|
72
102
|
|
|
73
103
|
// Re-arm auto-follow (called by the runtime when a new run starts, so the
|
|
74
104
|
// log snaps back to following the live stream).
|
|
75
105
|
function resetAutoFollow() {
|
|
76
106
|
logAutoFollow = true;
|
|
77
107
|
userScrollIntentUntil = 0;
|
|
108
|
+
pendingGuidanceReveal = null;
|
|
78
109
|
}
|
|
79
110
|
|
|
80
111
|
function bindLogAutoFollow() {
|
|
@@ -176,6 +207,7 @@
|
|
|
176
207
|
if ((event?.type === 'wheel' && event.deltaY < 0) || ['ArrowUp', 'PageUp', 'Home'].includes(event?.key)) {
|
|
177
208
|
logAutoFollow = false;
|
|
178
209
|
scrollLogPendingForce = false;
|
|
210
|
+
pendingGuidanceReveal = null;
|
|
179
211
|
}
|
|
180
212
|
}
|
|
181
213
|
|
|
@@ -187,6 +219,7 @@
|
|
|
187
219
|
}
|
|
188
220
|
|
|
189
221
|
function scrollLogToBottom(options = {}) {
|
|
222
|
+
if (activitySummary?.isSubagentViewOpen?.()) return;
|
|
190
223
|
const scroller = getLogScrollContainer();
|
|
191
224
|
if (!scroller) {
|
|
192
225
|
return;
|
|
@@ -199,6 +232,7 @@
|
|
|
199
232
|
userScrollIntentUntil = 0;
|
|
200
233
|
unreadSinceDetach = 0;
|
|
201
234
|
scrollLogPendingForce = true;
|
|
235
|
+
pendingGuidanceReveal = null;
|
|
202
236
|
} else if (!logAutoFollow) {
|
|
203
237
|
// The user has scrolled up: do not yank them. Just keep the jump button
|
|
204
238
|
// state current.
|
|
@@ -233,10 +267,25 @@
|
|
|
233
267
|
writeNow();
|
|
234
268
|
});
|
|
235
269
|
}
|
|
270
|
+
function revealGuidance(row) {
|
|
271
|
+
if (!logAutoFollow || activitySummary?.isSubagentViewOpen?.() || !getLogScrollContainer()?.contains?.(row)) return false;
|
|
272
|
+
pendingGuidanceReveal = row;
|
|
273
|
+
scrollLogToBottom();
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
236
276
|
function setLogScrollPosition(scroller) {
|
|
277
|
+
const reveal = pendingGuidanceReveal;
|
|
278
|
+
pendingGuidanceReveal = null;
|
|
279
|
+
const result = reveal && scrollLayout?.revealGuidance(reveal);
|
|
280
|
+
if (result) {
|
|
281
|
+
logAutoFollow = result.following;
|
|
282
|
+
if (!logAutoFollow) scrollLayout.captureAnchor(true);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
237
285
|
scroller.scrollTop = scroller.scrollHeight;
|
|
238
286
|
}
|
|
239
287
|
function collapseRunProcess(view, statusText) {
|
|
288
|
+
if (activitySummary) { activitySummary.settle(view, statusText); return; }
|
|
240
289
|
const runProcess = view?.runProcess || view?.root?.querySelector('[data-run-process]');
|
|
241
290
|
if (runProcess) {
|
|
242
291
|
runProcess.open = false;
|
|
@@ -245,23 +294,15 @@
|
|
|
245
294
|
if (statusEl) {
|
|
246
295
|
// Append the step count to the collapsed header ("Processed 18s · 6 steps")
|
|
247
296
|
// so the user sees how much work the run did without expanding it.
|
|
248
|
-
const
|
|
297
|
+
const record = view?.recordId ? findRunRecord(view.recordId, view.sessionId) : null;
|
|
298
|
+
const stepCount = (record?.events || []).filter(event => (event.kind || 'activity') === 'activity').length;
|
|
249
299
|
statusEl.textContent = stepCount > 0
|
|
250
300
|
? `${statusText} · ${tx(`${stepCount} steps`, `${stepCount} 步`)}`
|
|
251
301
|
: statusText;
|
|
252
302
|
}
|
|
253
303
|
}
|
|
254
304
|
|
|
255
|
-
|
|
256
|
-
const record = view?.recordId ? findRunRecord(view.recordId, view.sessionId) : null;
|
|
257
|
-
if (!Array.isArray(record?.events)) {
|
|
258
|
-
return 0;
|
|
259
|
-
}
|
|
260
|
-
return record.events.filter(event => (event.kind || 'activity') === 'activity').length;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// The sticky run-process header shows a live "Processing… {elapsed}" while a
|
|
264
|
-
// run is in flight so the user can distinguish a working run from a hung one.
|
|
305
|
+
// Keep elapsed labels live without creating new activity records.
|
|
265
306
|
function startRunElapsedTick() {
|
|
266
307
|
stopRunElapsedTick();
|
|
267
308
|
if (typeof window.setInterval !== 'function') {
|
|
@@ -272,6 +313,7 @@
|
|
|
272
313
|
stopRunElapsedTick();
|
|
273
314
|
return;
|
|
274
315
|
}
|
|
316
|
+
if (activitySummary?.update(getCurrentRunView()) && presence) return;
|
|
275
317
|
const statusEl = getCurrentRunView().status
|
|
276
318
|
|| getCurrentRunView().root?.querySelector('[data-run-status]');
|
|
277
319
|
if (statusEl) {
|
|
@@ -289,6 +331,13 @@
|
|
|
289
331
|
runElapsedTimer = null;
|
|
290
332
|
}
|
|
291
333
|
|
|
334
|
+
function classifyRunPresence(run = {}) {
|
|
335
|
+
if (run.retryingWriteback) return 'plain';
|
|
336
|
+
if (run.status === 'completed') return 'done';
|
|
337
|
+
if (run.status === 'cancelled' || run.status === 'rejected') return 'stopped';
|
|
338
|
+
return run.status === 'failed' || run.status === 'abandoned_after_navigation' ? 'failed' : 'plain';
|
|
339
|
+
}
|
|
340
|
+
|
|
292
341
|
function formatProcessedSummary(status, elapsedMs) {
|
|
293
342
|
const elapsed = formatElapsed(elapsedMs);
|
|
294
343
|
if (status === 'failed') {
|
|
@@ -303,6 +352,7 @@
|
|
|
303
352
|
return tr('processed', { elapsed });
|
|
304
353
|
}
|
|
305
354
|
function renderRunHistory(options = {}) {
|
|
355
|
+
activitySummary?.closeSubagentView?.();
|
|
306
356
|
const log = getPanel()?.querySelector('[data-log]');
|
|
307
357
|
if (!log) {
|
|
308
358
|
return;
|
|
@@ -323,7 +373,12 @@
|
|
|
323
373
|
const hint = document.createElement('div');
|
|
324
374
|
hint.className = 'empty-runs-hint';
|
|
325
375
|
hint.textContent = tr('emptyRunsHint');
|
|
376
|
+
label.className = 'empty-runs-title';
|
|
326
377
|
empty.append(icon, label, hint);
|
|
378
|
+
if (presence) {
|
|
379
|
+
icon.remove();
|
|
380
|
+
presence.decorateEmpty(empty, { projectName: getProjectName?.() || '' });
|
|
381
|
+
}
|
|
327
382
|
log.append(empty);
|
|
328
383
|
return;
|
|
329
384
|
}
|
|
@@ -342,6 +397,7 @@
|
|
|
342
397
|
}
|
|
343
398
|
|
|
344
399
|
function renderRunCard(run) {
|
|
400
|
+
run = displayLocalizedRun(run);
|
|
345
401
|
const root = document.createElement('section');
|
|
346
402
|
root.className = 'transcript-turn run-card';
|
|
347
403
|
root.dataset.status = run.status || 'completed';
|
|
@@ -356,11 +412,14 @@
|
|
|
356
412
|
root.innerHTML = `
|
|
357
413
|
<div class="transcript-turn-main">
|
|
358
414
|
<div class="run-attachments codex-attachment-preview-list" data-run-attachments hidden></div>
|
|
415
|
+
<div class="run-selection" data-run-selection hidden></div>
|
|
359
416
|
<div class="run-prompt" data-run-task></div>
|
|
360
417
|
<div class="run-guidance-list" data-run-guidance></div>
|
|
361
418
|
<div class="run-turn-meta">
|
|
362
419
|
<button type="button" data-run-accept hidden title="Accept this run's tracked changes in Overleaf">Accept changes</button>
|
|
363
420
|
<button type="button" data-run-undo hidden title="Undo this run's writes to Overleaf">Undo</button>
|
|
421
|
+
<button type="button" class="run-copy-action run-edit-action" data-run-edit hidden></button>
|
|
422
|
+
<button type="button" class="run-copy-action run-sync-action" data-run-sync-retry hidden></button>
|
|
364
423
|
</div>
|
|
365
424
|
<details class="run-process" data-run-process>
|
|
366
425
|
<summary data-run-process-summary>
|
|
@@ -379,6 +438,7 @@
|
|
|
379
438
|
`;
|
|
380
439
|
|
|
381
440
|
renderAttachmentPreviewList(run.attachments, root.querySelector('[data-run-attachments]'), { readonly: true });
|
|
441
|
+
renderSentSelection?.(root.querySelector('[data-run-selection]'), run.executionSnapshot?.selectionContext, { document, tx });
|
|
382
442
|
const runTask = root.querySelector('[data-run-task]');
|
|
383
443
|
runTask.classList.add('run-user-message');
|
|
384
444
|
runTask.textContent = run.task || '';
|
|
@@ -398,42 +458,41 @@
|
|
|
398
458
|
truncated.textContent = tr('eventsTruncatedNote');
|
|
399
459
|
events.append(truncated);
|
|
400
460
|
}
|
|
401
|
-
|
|
402
|
-
const renderedGuidanceIds = new Set();
|
|
403
|
-
const completedLegacyGuidance = new Set((run.events || [])
|
|
404
|
-
.filter(event => event.kind === 'guidance' && !event.guidanceId && event.status === 'completed')
|
|
405
|
-
.map(event => event.title));
|
|
461
|
+
if (!activitySummary) RunGuidanceView.reconcileGuidance?.(guidance, (run.events || []).concat(getPendingGuidance(run)), tx, { active: run.status === 'running' });
|
|
406
462
|
for (const event of run.events || []) {
|
|
407
463
|
if (event.kind === 'report') {
|
|
408
464
|
report.hidden = false;
|
|
409
465
|
report.replaceChildren(renderCompletionReport(event, run));
|
|
410
|
-
} else if (event.kind === 'technical') {
|
|
466
|
+
} else if (activitySummary || event.kind === 'technical') {
|
|
411
467
|
continue;
|
|
412
468
|
} else if (RunGuidanceView.getGuidanceText(event)) {
|
|
413
|
-
|
|
414
|
-
continue;
|
|
415
|
-
}
|
|
416
|
-
if (!event.guidanceId && event.status === 'queued' && completedLegacyGuidance.has(event.title)) {
|
|
417
|
-
continue;
|
|
418
|
-
}
|
|
419
|
-
if (event.guidanceId) {
|
|
420
|
-
renderedGuidanceIds.add(event.guidanceId);
|
|
421
|
-
}
|
|
422
|
-
guidanceTarget.append(renderRunEvent(event));
|
|
469
|
+
continue;
|
|
423
470
|
} else if (event.kind === 'stream') {
|
|
424
471
|
upsertStreamEvent({ events }, event);
|
|
425
472
|
} else {
|
|
426
|
-
events
|
|
473
|
+
appendActivityDetail({ events }, renderRunEvent(event), event);
|
|
427
474
|
}
|
|
428
475
|
}
|
|
429
476
|
|
|
430
477
|
RunResultActions.configureResultActions(root, run);
|
|
431
478
|
configureAcceptButton(root, run);
|
|
432
479
|
configureUndoButton(root, run);
|
|
480
|
+
configureEditButton(root, run);
|
|
481
|
+
configureWritebackButton(root, run);
|
|
482
|
+
activitySummary?.mount(root, run);
|
|
433
483
|
return root;
|
|
434
484
|
}
|
|
435
485
|
|
|
436
486
|
function getRunStatusText(run = {}) {
|
|
487
|
+
if (run.retryingWriteback) return tx('Checking file sync', '正在检查文件同步');
|
|
488
|
+
if (['Stopped tracking after a page refresh', '页面刷新后已停止跟踪'].includes(run.statusText)) return tr('restoredRunStoppedStatus');
|
|
489
|
+
const knownStatus = /^(?:Done|Failed|Cancelled|Running|已处理|处理失败|已取消|处理中)(?:\s+[\d.]+(?:ms|s|m|h|秒|分钟)(?:\s+[\d.]+(?:ms|s|m|h|秒|分钟))*)?$/.test(run.statusText || '');
|
|
490
|
+
if (knownStatus) {
|
|
491
|
+
const elapsed = String(run.statusText).replace(/^(?:Done|Failed|Cancelled|Running|已处理|处理失败|已取消|处理中)\s*/, '');
|
|
492
|
+
const key = run.status === 'running' ? 'processing' : run.status === 'failed' ? 'processedFailed'
|
|
493
|
+
: ['rejected', 'cancelled'].includes(run.status) ? 'processedCancelled' : 'processed';
|
|
494
|
+
return tr(key, { elapsed }).trim();
|
|
495
|
+
}
|
|
437
496
|
if (run.statusText) {
|
|
438
497
|
return run.statusText;
|
|
439
498
|
}
|
|
@@ -461,6 +520,7 @@
|
|
|
461
520
|
if (!view?.events) {
|
|
462
521
|
return;
|
|
463
522
|
}
|
|
523
|
+
if (activitySummary?.update(view, event)) return;
|
|
464
524
|
const streamKey = event.streamKey || event.streamRole || 'codex-stream';
|
|
465
525
|
const selector = `[data-stream-key="${cssEscape(streamKey)}"]`;
|
|
466
526
|
const existing = view.events.querySelector(selector);
|
|
@@ -477,7 +537,12 @@
|
|
|
477
537
|
}
|
|
478
538
|
return;
|
|
479
539
|
}
|
|
480
|
-
view
|
|
540
|
+
appendActivityDetail(view, renderStreamEvent({ ...event, streamKey }), event);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function appendActivityDetail(view, row, event) {
|
|
544
|
+
if (activitySummary) activitySummary.appendDetail(view, row, event);
|
|
545
|
+
else view.events.append(row);
|
|
481
546
|
}
|
|
482
547
|
|
|
483
548
|
function renderStreamEvent(input) {
|
|
@@ -504,18 +569,61 @@
|
|
|
504
569
|
function sanitizeRunEventForRender(event = {}) {
|
|
505
570
|
const streamRole = sanitizeAssistantVisibleText(event.streamRole);
|
|
506
571
|
const title = sanitizeAssistantVisibleText(event.title);
|
|
572
|
+
const activity = !streamRole && (!event.kind || event.kind === 'activity') && !event.guidanceId;
|
|
573
|
+
const localized = activity ? localizeProductActivity(title, sanitizeAssistantVisibleValue(event.detail)) : null;
|
|
507
574
|
return {
|
|
508
575
|
...event,
|
|
576
|
+
...(activity && event.activity?.kind === 'compile' ? { activity: { ...event.activity, output: localizeCompileReason(event.activity.output) } } : {}),
|
|
509
577
|
title: streamRole === 'reasoning'
|
|
510
578
|
? stripEmptyHtmlCommentPlaceholders(title)
|
|
511
|
-
: title,
|
|
579
|
+
: localized?.title || title,
|
|
512
580
|
status: sanitizeAssistantVisibleText(event.status),
|
|
513
|
-
detail: sanitizeAssistantVisibleValue(event.detail),
|
|
581
|
+
detail: localized?.detail ?? sanitizeAssistantVisibleValue(event.detail),
|
|
514
582
|
technicalDetail: sanitizeAssistantVisibleValue(event.technicalDetail),
|
|
515
583
|
streamKey: sanitizeAssistantVisibleText(event.streamKey),
|
|
516
584
|
streamRole
|
|
517
585
|
};
|
|
518
586
|
}
|
|
587
|
+
|
|
588
|
+
function localizeProductActivity(title, detail) {
|
|
589
|
+
let known = false, nextTitle = title;
|
|
590
|
+
const keys = ['undoUnsafeFullFileTitle', 'undoNoTraceTitle', 'undoFileSelectTitle', 'undoNoTraceStarted', 'undoTrackedTitle', 'undoNativeTitle', 'undoTrackedStarted', 'undoNativeStarted', 'undoSwitchedEditing', 'undoReviewingRestoreUnverified', 'runAcceptTrackedStarted', 'runAcceptTrackedFailed', 'undoResult', 'undoTrackedResult', 'undoNativeResult', 'runAcceptTrackedResult'];
|
|
591
|
+
if (I18n?.t) outer: for (const key of keys) for (const locale of ['en', 'zh']) {
|
|
592
|
+
const template = I18n.t(locale, key, { applied: '__APPLIED__', skipped: '__SKIPPED__' });
|
|
593
|
+
const pattern = template.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace('__APPLIED__', '(\\d+)').replace('__SKIPPED__', '(\\d+)');
|
|
594
|
+
const match = new RegExp('^' + pattern + '$').exec(title);
|
|
595
|
+
if (match) { known = true; nextTitle = tr(key, { applied: match[1], skipped: match[2] }); break outer; }
|
|
596
|
+
}
|
|
597
|
+
let countedTitle;
|
|
598
|
+
const writeResult = /^(?:Write result: wrote (\d+) item\(s\), skipped (\d+)|写入结果:已写入 (\d+) 项,跳过 (\d+) 项)$/.exec(title);
|
|
599
|
+
const governance = /^(?:Project governance blocked (\d+) write\(s\) before review\.|项目治理规则在审核前阻止了 (\d+) 项写入。)$/.exec(title);
|
|
600
|
+
if (writeResult) {
|
|
601
|
+
const applied = writeResult[1] ?? writeResult[3], skipped = writeResult[2] ?? writeResult[4];
|
|
602
|
+
countedTitle = tx(`Write result: wrote ${applied} item(s), skipped ${skipped}`, `写入结果:已写入 ${applied} 项,跳过 ${skipped} 项`);
|
|
603
|
+
} else if (governance) {
|
|
604
|
+
const count = governance[1] ?? governance[2];
|
|
605
|
+
countedTitle = tx(`Project governance blocked ${count} write(s) before review.`, `项目治理规则在审核前阻止了 ${count} 项写入。`);
|
|
606
|
+
}
|
|
607
|
+
const labels = ['detailAccepted', 'detailRejected', 'detailUndone', 'detailSkipped', 'detailFile', 'detailRecord', 'detailReason'];
|
|
608
|
+
const project = (value, reason = false) => {
|
|
609
|
+
if (typeof value === 'string') return reason ? localizeVisibleReason(value) : value;
|
|
610
|
+
if (Array.isArray(value)) return value.map(item => project(item, reason));
|
|
611
|
+
if (!value || typeof value !== 'object') return value;
|
|
612
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => {
|
|
613
|
+
const label = labels.find(id => ['en', 'zh'].some(locale => I18n?.t?.(locale, id) === key));
|
|
614
|
+
return [label ? tr(label) : key, project(child, label === 'detailReason')];
|
|
615
|
+
}));
|
|
616
|
+
};
|
|
617
|
+
return { title: countedTitle || (known ? nextTitle : localizeCompileReason(localizeVisibleReason(title))),
|
|
618
|
+
detail: typeof detail === 'string' ? localizeVisibleReason(detail) : known ? project(detail) : detail };
|
|
619
|
+
}
|
|
620
|
+
function formatReviewResultFailure(failure) {
|
|
621
|
+
if (failure?.code === 'unknown_legacy_failure' && (!failure.evidence?.originalCode || failure.evidence.originalCode === 'unknown_legacy_failure')
|
|
622
|
+
&& ['Unknown reason', '未知原因'].includes(failure.userMessage)) {
|
|
623
|
+
failure = { ...failure, userMessage: tr('unknownReason') };
|
|
624
|
+
}
|
|
625
|
+
return FailureReasons?.formatFailureReasonForDisplay(failure, getLocale?.(), key => { const value = tr(key, failure?.file ? undefined : { file: tr('unknownFile'), activeFile: tr('unknownFile') }); return value && value !== key ? value : undefined; });
|
|
626
|
+
}
|
|
519
627
|
function renderActivityLine(input) {
|
|
520
628
|
const event = sanitizeRunEventForRender(input);
|
|
521
629
|
const row = document.createElement('div');
|
|
@@ -543,54 +651,8 @@
|
|
|
543
651
|
return row;
|
|
544
652
|
}
|
|
545
653
|
|
|
546
|
-
function hasNonEmptyDetail(value) {
|
|
547
|
-
if (value === undefined || value === null || value === '') {
|
|
548
|
-
return false;
|
|
549
|
-
}
|
|
550
|
-
if (Array.isArray(value)) {
|
|
551
|
-
return value.length > 0;
|
|
552
|
-
}
|
|
553
|
-
if (typeof value === 'object') {
|
|
554
|
-
return Object.keys(value).length > 0;
|
|
555
|
-
}
|
|
556
|
-
return true;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
function renderTechnicalEvent(event) {
|
|
560
|
-
const block = document.createElement('section');
|
|
561
|
-
block.className = 'run-technical-event';
|
|
562
|
-
block.dataset.status = event.status || 'info';
|
|
563
654
|
|
|
564
|
-
const title = document.createElement('div');
|
|
565
|
-
title.className = 'run-technical-event-title';
|
|
566
|
-
title.textContent = event.title || tr('technicalDetails');
|
|
567
|
-
|
|
568
|
-
const body = document.createElement('pre');
|
|
569
|
-
body.textContent = formatEventDetail(buildTechnicalEventDetail(event));
|
|
570
|
-
block.append(title, body);
|
|
571
|
-
return block;
|
|
572
|
-
}
|
|
573
655
|
|
|
574
|
-
function buildTechnicalEventDetail(event) {
|
|
575
|
-
if (event?.kind === 'technical') {
|
|
576
|
-
return event.detail || {};
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
const detail = {
|
|
580
|
-
[tx('Step', '步骤')]: event?.title || '',
|
|
581
|
-
[tx('Status', '状态')]: event?.status || ''
|
|
582
|
-
};
|
|
583
|
-
if (event?.timestamp) {
|
|
584
|
-
detail[tx('Time', '时间')] = formatEventTime(event.timestamp);
|
|
585
|
-
}
|
|
586
|
-
if (hasNonEmptyDetail(event?.detail)) {
|
|
587
|
-
detail[tx('Content', '内容')] = event.detail;
|
|
588
|
-
}
|
|
589
|
-
if (hasNonEmptyDetail(event?.technicalDetail)) {
|
|
590
|
-
detail[tx('Raw event', '原始事件')] = event.technicalDetail;
|
|
591
|
-
}
|
|
592
|
-
return detail;
|
|
593
|
-
}
|
|
594
656
|
|
|
595
657
|
function buildActivityTooltip(event) {
|
|
596
658
|
return [
|
|
@@ -599,71 +661,73 @@
|
|
|
599
661
|
].filter(Boolean).join('\n');
|
|
600
662
|
}
|
|
601
663
|
|
|
602
|
-
// The
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
{ key: 'unchangedReason', prefixes: ['Why nothing changed:', '未修改原因:'], en: 'Why nothing changed', zh: '未修改原因' },
|
|
609
|
-
{ key: 'writeResult', prefixes: ['Write result:', '写入结果:'], en: 'Write result', zh: '写入结果' },
|
|
610
|
-
{ key: 'undo', prefixes: ['Undo:', '可撤销:'], en: 'Undo', zh: '可撤销' },
|
|
611
|
-
{ key: 'nextStep', prefixes: ['Next:', '下一步:'], en: 'Next', zh: '下一步' }
|
|
612
|
-
];
|
|
613
|
-
|
|
614
|
-
// Splits a flat completion-report string (formatHumanReport output) into the
|
|
615
|
-
// answer body and the demoted meta rows. Only single-line sections whose head
|
|
616
|
-
// matches a known status label are demoted, so a multi-paragraph conclusion
|
|
617
|
-
// that happens to contain "Next: …" prose stays in the body.
|
|
618
|
-
function splitFlatCompletionReport(text) {
|
|
619
|
-
const raw = typeof text === 'string' ? text : '';
|
|
620
|
-
if (!raw.trim()) {
|
|
621
|
-
return { body: raw, meta: [] };
|
|
622
|
-
}
|
|
623
|
-
const bodySections = [];
|
|
624
|
-
const meta = [];
|
|
625
|
-
for (const section of raw.split(/\n{2,}/)) {
|
|
626
|
-
const trimmed = section.trim();
|
|
627
|
-
if (!trimmed) continue;
|
|
628
|
-
const entry = trimmed.includes('\n')
|
|
629
|
-
? null
|
|
630
|
-
: FLAT_REPORT_STATUS_SECTIONS.find(item => item.prefixes.some(prefix => trimmed.startsWith(prefix)));
|
|
631
|
-
if (entry) {
|
|
632
|
-
const prefix = entry.prefixes.find(p => trimmed.startsWith(p));
|
|
633
|
-
const value = trimmed.slice(prefix.length).trim();
|
|
634
|
-
if (value) {
|
|
635
|
-
meta.push({ key: entry.key, label: tx(entry.en, entry.zh), value });
|
|
636
|
-
continue;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
bodySections.push(trimmed);
|
|
640
|
-
}
|
|
641
|
-
return { body: bodySections.join('\n\n'), meta };
|
|
642
|
-
}
|
|
664
|
+
// The result presenter owns parsing and current lifecycle metadata.
|
|
665
|
+
const splitFlatCompletionReport = text => RunResultActions.splitFlatCompletionReport(text, tx);
|
|
666
|
+
const projectCompletionMeta = (meta, run) => RunResultActions.projectCompletionMeta(meta, run, {
|
|
667
|
+
tx, getLocale, tr, trackedChangeInFlight, isTrackedChangeLifecycleRun, projectRunSettlement,
|
|
668
|
+
projectId: getCurrentProjectId?.(), accountScopeId: getAccountScopeId?.()
|
|
669
|
+
});
|
|
643
670
|
|
|
644
|
-
//
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
671
|
+
// The user's own open/closed choice per run survives card re-renders.
|
|
672
|
+
const metaOpenChoices = new Map();
|
|
673
|
+
|
|
674
|
+
// Renders the run-metadata rows (Why nothing changed / Write result / Undo /
|
|
675
|
+
// Next) behind a one-line summary beneath the answer. Shared by the
|
|
676
|
+
// structured and flat-fallback render paths so both demote identically.
|
|
677
|
+
function appendCompletionMetaBlock(report, meta, run) {
|
|
648
678
|
if (!Array.isArray(meta) || !meta.length) {
|
|
649
679
|
return;
|
|
650
680
|
}
|
|
681
|
+
const rows = projectCompletionMeta(meta, run).filter(row => row?.label && row.value)
|
|
682
|
+
.map(row => ({ ...row, shown: failureNotice?.formatMetaValue(report, row) ?? row.value }));
|
|
683
|
+
if (!rows.length) return;
|
|
684
|
+
const summary = RunResultActions.summarizeCompletionMeta(rows, run, {
|
|
685
|
+
tx, failed: report.dataset.status === 'failed', unconfirmed: rows.some(row => row.shown !== row.value)
|
|
686
|
+
});
|
|
651
687
|
const metaBlock = document.createElement('dl');
|
|
652
688
|
metaBlock.className = 'run-final-answer__meta';
|
|
653
|
-
|
|
654
|
-
|
|
689
|
+
metaBlock.id = `codex-run-meta-${String(run?.id || 'report').replace(/[^a-zA-Z0-9_-]/g, '-')}`;
|
|
690
|
+
for (const row of rows) {
|
|
655
691
|
const dt = document.createElement('dt');
|
|
656
692
|
dt.className = 'run-final-answer__meta-label';
|
|
657
693
|
dt.textContent = row.label;
|
|
658
694
|
if (row.key) dt.dataset.metaKey = row.key;
|
|
659
695
|
const dd = document.createElement('dd');
|
|
660
696
|
dd.className = 'run-final-answer__meta-value';
|
|
661
|
-
dd.textContent =
|
|
697
|
+
dd.textContent = row.shown;
|
|
698
|
+
if (summary.warnKeys.has(row.key)) dt.dataset.tone = dd.dataset.tone = 'warn';
|
|
662
699
|
metaBlock.append(dt, dd);
|
|
663
700
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
701
|
+
const facts = document.createElement('div');
|
|
702
|
+
facts.className = 'run-final-answer__facts';
|
|
703
|
+
const toggle = document.createElement('button');
|
|
704
|
+
toggle.type = 'button';
|
|
705
|
+
toggle.className = 'run-final-answer__facts-sum';
|
|
706
|
+
toggle.setAttribute('aria-controls', metaBlock.id);
|
|
707
|
+
summary.facts.forEach((fact, index) => {
|
|
708
|
+
if (index) toggle.append(Object.assign(document.createElement('span'), { className: 'run-final-answer__facts-sep', textContent: '·' }));
|
|
709
|
+
const item = Object.assign(document.createElement('span'), { className: 'run-final-answer__fact', textContent: fact.text });
|
|
710
|
+
if (fact.tone) item.dataset.tone = fact.tone;
|
|
711
|
+
item.dataset.fact = fact.key;
|
|
712
|
+
toggle.append(item);
|
|
713
|
+
});
|
|
714
|
+
const more = Object.assign(document.createElement('span'), { className: 'run-final-answer__facts-more' });
|
|
715
|
+
toggle.append(Object.assign(document.createElement('span'), { className: 'run-final-answer__facts-sep', textContent: '·' }), more);
|
|
716
|
+
const setOpen = open => {
|
|
717
|
+
facts.dataset.open = String(open);
|
|
718
|
+
metaBlock.hidden = !open;
|
|
719
|
+
toggle.setAttribute('aria-expanded', String(open));
|
|
720
|
+
more.innerHTML = `${open ? tx('Hide', '收起') : tx('Details', '详情')}<svg class="codex-glyph" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path d="m6 4 4 4-4 4"/></svg>`;
|
|
721
|
+
};
|
|
722
|
+
setOpen(metaOpenChoices.get(run?.id) ?? summary.open);
|
|
723
|
+
toggle.addEventListener('click', event => {
|
|
724
|
+
event.stopPropagation();
|
|
725
|
+
const open = facts.dataset.open !== 'true';
|
|
726
|
+
if (run?.id) metaOpenChoices.set(run.id, open);
|
|
727
|
+
setOpen(open);
|
|
728
|
+
});
|
|
729
|
+
facts.append(toggle, metaBlock);
|
|
730
|
+
report.append(facts);
|
|
667
731
|
}
|
|
668
732
|
|
|
669
733
|
function renderCompletionReport(input, run) {
|
|
@@ -724,10 +788,10 @@
|
|
|
724
788
|
main.className = 'run-final-answer';
|
|
725
789
|
const mainSections = [];
|
|
726
790
|
if (structured.conclusion) {
|
|
727
|
-
mainSections.push(
|
|
791
|
+
mainSections.push(String(structured.conclusion));
|
|
728
792
|
}
|
|
729
793
|
if (structured.body) {
|
|
730
|
-
mainSections.push(structured.body);
|
|
794
|
+
mainSections.push(RunResultActions.projectCompletionBody?.(structured.body, tx) ?? structured.body);
|
|
731
795
|
}
|
|
732
796
|
if (mainSections.length) {
|
|
733
797
|
renderMarkdownBlockText(main, mainSections.join('\n\n'));
|
|
@@ -736,7 +800,7 @@
|
|
|
736
800
|
}
|
|
737
801
|
|
|
738
802
|
failureNotice?.append(report, event, run);
|
|
739
|
-
appendCompletionMetaBlock(report, structured.meta);
|
|
803
|
+
appendCompletionMetaBlock(report, structured.meta, run);
|
|
740
804
|
appendCompileFix(report);
|
|
741
805
|
appendRejectedRedo(report);
|
|
742
806
|
appendRecoveryActionForFailure(report, event, run);
|
|
@@ -758,24 +822,11 @@
|
|
|
758
822
|
appendCompileFix(report);
|
|
759
823
|
appendRejectedRedo(report);
|
|
760
824
|
failureNotice?.append(report, event, run);
|
|
761
|
-
appendCompletionMetaBlock(report, split.meta);
|
|
825
|
+
appendCompletionMetaBlock(report, split.meta, run);
|
|
762
826
|
appendRecoveryActionForFailure(report, event, run);
|
|
763
827
|
return report;
|
|
764
828
|
}
|
|
765
829
|
|
|
766
|
-
function formatConclusionMarkdown(value) {
|
|
767
|
-
const conclusion = String(value || '');
|
|
768
|
-
const label = getLocale() === 'zh' ? '结论:' : 'Conclusion:';
|
|
769
|
-
return hasLeadingMarkdownBlock(conclusion)
|
|
770
|
-
? `${label}\n${conclusion}`
|
|
771
|
-
: `${label} ${conclusion}`;
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
function hasLeadingMarkdownBlock(value) {
|
|
775
|
-
const firstLine = String(value || '').trimStart().split(/\r?\n/, 1)[0];
|
|
776
|
-
return /^(?:#{1,6}\s+\S|```|~~~|(?:[-+*]|\d+[.)])\s+\S|\*\*[^*]+\*\*:?\s*$)/.test(firstLine);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
830
|
// For failure codes that have an actionable recovery path the user can
|
|
780
831
|
// invoke directly from the run card, append a button inside the completion
|
|
781
832
|
// report. Today's only consumer is codex_project_locked → "Force-release
|
|
@@ -783,128 +834,6 @@
|
|
|
783
834
|
// the normal cancel button is hidden because currentRunView is null).
|
|
784
835
|
// Recovery-action registry: failure codes whose "next step" is executable
|
|
785
836
|
// from the panel get a button, not prose. One primary action per failure.
|
|
786
|
-
const RETRYABLE_FAILURE_CODES = new Set([
|
|
787
|
-
'native_request_failed', 'codex_timeout', 'codex_no_usable_result',
|
|
788
|
-
'codex_output_limit', 'stale_source_changed', 'patch_anchor_not_found',
|
|
789
|
-
'target_editor_not_ready', 'write_timeout', 'partial_write_needs_review',
|
|
790
|
-
'write_operation_failed'
|
|
791
|
-
]);
|
|
792
|
-
const NATIVE_SETUP_FAILURE_CODES = new Set([
|
|
793
|
-
'native_bridge_unavailable', 'native_protocol_incompatible'
|
|
794
|
-
]);
|
|
795
|
-
const OPEN_FILE_FAILURE_CODES = new Set([
|
|
796
|
-
'target_file_not_active', 'target_file_open_failed', 'target_file_not_found'
|
|
797
|
-
]);
|
|
798
|
-
const STORAGE_FAILURE_CODES = new Set([
|
|
799
|
-
'storage_quota_exceeded', 'run_state_persist_failed'
|
|
800
|
-
]);
|
|
801
|
-
// A missing `codex` binary is fixed in the terminal, not the panel — the
|
|
802
|
-
// action opens the README troubleshooting section (PATH / login checks).
|
|
803
|
-
const CODEX_INSTALL_FAILURE_CODES = new Set(['codex_not_found']);
|
|
804
|
-
const CODEX_CLI_TROUBLESHOOTING_URL = 'https://github.com/Ghqqqq/codex-overleaf-link#faq-and-troubleshooting';
|
|
805
|
-
|
|
806
|
-
function buildRecoveryButton(failureCode, label, title) {
|
|
807
|
-
const button = document.createElement('button');
|
|
808
|
-
button.type = 'button';
|
|
809
|
-
button.className = 'run-final-answer__recovery-action';
|
|
810
|
-
button.dataset.recoveryFor = failureCode;
|
|
811
|
-
button.textContent = label;
|
|
812
|
-
if (title) {
|
|
813
|
-
button.title = title;
|
|
814
|
-
}
|
|
815
|
-
return button;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
function appendRecoveryActionForFailure(report, event, run) {
|
|
819
|
-
const recovery = failureNotice?.prepareRecovery(report, { openFile: openProjectFileForFailure });
|
|
820
|
-
if (recovery?.handled) return;
|
|
821
|
-
report = recovery?.target || report;
|
|
822
|
-
const failureCode = event?.failure?.code || '';
|
|
823
|
-
if (RETRYABLE_FAILURE_CODES.has(failureCode) && typeof refillComposerForRetry === 'function') {
|
|
824
|
-
const retry = buildRecoveryButton(failureCode,
|
|
825
|
-
tx('Edit & resend', '编辑后重发'),
|
|
826
|
-
tx('Put this run\u2019s task back into the composer so you can adjust and resend it.', '把本轮任务填回输入框,修改后可直接重发。'));
|
|
827
|
-
retry.addEventListener('click', clickEvent => {
|
|
828
|
-
clickEvent.stopPropagation();
|
|
829
|
-
refillComposerForRetry(run || null);
|
|
830
|
-
});
|
|
831
|
-
report.append(retry);
|
|
832
|
-
return;
|
|
833
|
-
}
|
|
834
|
-
if (NATIVE_SETUP_FAILURE_CODES.has(failureCode) && typeof showNativeSetupGuidance === 'function') {
|
|
835
|
-
const fix = buildRecoveryButton(failureCode,
|
|
836
|
-
tx('Fix the native host', '修复 native host'),
|
|
837
|
-
tx('Opens the install/update guidance with the copyable command.', '打开安装/更新指引(含可复制命令)。'));
|
|
838
|
-
fix.addEventListener('click', clickEvent => {
|
|
839
|
-
clickEvent.stopPropagation();
|
|
840
|
-
showNativeSetupGuidance();
|
|
841
|
-
});
|
|
842
|
-
report.append(fix);
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
if (OPEN_FILE_FAILURE_CODES.has(failureCode) && event?.failure?.file && typeof openProjectFileForFailure === 'function') {
|
|
846
|
-
const open = buildRecoveryButton(failureCode,
|
|
847
|
-
tx(`Open ${event.failure.file} in Overleaf`, `在 Overleaf 打开 ${event.failure.file}`), '');
|
|
848
|
-
open.addEventListener('click', clickEvent => {
|
|
849
|
-
clickEvent.stopPropagation();
|
|
850
|
-
openProjectFileForFailure(event.failure.file);
|
|
851
|
-
});
|
|
852
|
-
report.append(open);
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
if (STORAGE_FAILURE_CODES.has(failureCode) && typeof openStorageSettings === 'function') {
|
|
856
|
-
const clean = buildRecoveryButton(failureCode,
|
|
857
|
-
tx('Open history & storage cleanup', '打开历史与存储清理'), '');
|
|
858
|
-
clean.addEventListener('click', clickEvent => {
|
|
859
|
-
clickEvent.stopPropagation();
|
|
860
|
-
openStorageSettings();
|
|
861
|
-
});
|
|
862
|
-
report.append(clean);
|
|
863
|
-
return;
|
|
864
|
-
}
|
|
865
|
-
if (CODEX_INSTALL_FAILURE_CODES.has(failureCode)) {
|
|
866
|
-
const guide = buildRecoveryButton(failureCode,
|
|
867
|
-
tx('Codex CLI troubleshooting guide', '查看 Codex CLI 排查指引'),
|
|
868
|
-
tx('Opens the README section on fixing a missing `codex` command (PATH / login).', '打开 README 中「找不到 codex 命令」的排查说明(PATH/登录)。'));
|
|
869
|
-
guide.addEventListener('click', clickEvent => {
|
|
870
|
-
clickEvent.stopPropagation();
|
|
871
|
-
window.open(CODEX_CLI_TROUBLESHOOTING_URL, '_blank', 'noopener');
|
|
872
|
-
});
|
|
873
|
-
report.append(guide);
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
if (failureCode !== 'codex_project_locked') return;
|
|
877
|
-
const button = document.createElement('button');
|
|
878
|
-
button.type = 'button';
|
|
879
|
-
button.className = 'run-final-answer__recovery-action';
|
|
880
|
-
button.dataset.recoveryFor = failureCode;
|
|
881
|
-
button.textContent = tx('Force-release the stuck task', '强制释放卡住的任务');
|
|
882
|
-
button.title = tx(
|
|
883
|
-
'Sends a force-cancel to the native host that drops the project lock so a new run can start. Use this when refreshing the tab did not free the project.',
|
|
884
|
-
'向 native host 发送强制取消请求,释放当前 Overleaf 项目的占用,让新的任务可以启动。刷新页面没用时使用。'
|
|
885
|
-
);
|
|
886
|
-
button.addEventListener('click', event => {
|
|
887
|
-
event.stopPropagation();
|
|
888
|
-
button.disabled = true;
|
|
889
|
-
button.textContent = tx('Releasing…', '正在释放…');
|
|
890
|
-
forceCancelStuckTaskForCurrentProject().then(result => {
|
|
891
|
-
if (result?.ok) {
|
|
892
|
-
button.textContent = tx('Force-released — you can retry the run.', '已释放,可以重试本轮任务。');
|
|
893
|
-
return;
|
|
894
|
-
}
|
|
895
|
-
// The helper resolves (never throws) with a non-ok result when the
|
|
896
|
-
// request was not delivered. Report the real outcome instead of a
|
|
897
|
-
// blanket success, and re-enable the button so the user can retry.
|
|
898
|
-
button.disabled = false;
|
|
899
|
-
button.textContent = tx('Release failed — refresh the tab, then try again.', '释放失败,请刷新页面后重试。');
|
|
900
|
-
}).catch(() => {
|
|
901
|
-
button.disabled = false;
|
|
902
|
-
button.textContent = tx('Release failed — refresh the tab, then try again.', '释放失败,请刷新页面后重试。');
|
|
903
|
-
});
|
|
904
|
-
});
|
|
905
|
-
report.append(button);
|
|
906
|
-
}
|
|
907
|
-
|
|
908
837
|
// A run belongs to the tracked-change lifecycle iff trackedChangeStatus is set
|
|
909
838
|
// or it still has tracked-change refs. Every other run is a legacy-undo run.
|
|
910
839
|
function isTrackedChangeLifecycleRun(run) {
|
|
@@ -917,6 +846,47 @@
|
|
|
917
846
|
return Array.isArray(run.undoTrackedChanges) && run.undoTrackedChanges.length > 0;
|
|
918
847
|
}
|
|
919
848
|
|
|
849
|
+
function configureEditButton(root, run, options = {}) {
|
|
850
|
+
const existing = root.querySelector('[data-run-edit]');
|
|
851
|
+
if (!existing) return;
|
|
852
|
+
const button = existing.cloneNode(true);
|
|
853
|
+
existing.replaceWith(button);
|
|
854
|
+
const available = ['cancelled', 'rejected'].includes(run?.status)
|
|
855
|
+
&& Boolean(String(run?.task || '').trim())
|
|
856
|
+
&& typeof canEditRun === 'function' && canEditRun(run)
|
|
857
|
+
&& typeof refillComposerForRetry === 'function';
|
|
858
|
+
button.hidden = !available;
|
|
859
|
+
if (!available) return;
|
|
860
|
+
button.disabled = typeof options.running === 'boolean'
|
|
861
|
+
? options.running : Boolean(getCurrentRunView?.());
|
|
862
|
+
button.title = tx('Edit & resend', '编辑后重发');
|
|
863
|
+
button.setAttribute('aria-label', button.title);
|
|
864
|
+
button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><path d="m12.8 3.2 4 4M3.5 16.5l4.2-.9 9-9a1.7 1.7 0 0 0 0-2.4l-.9-.9a1.7 1.7 0 0 0-2.4 0l-9 9z"/></svg>';
|
|
865
|
+
button.addEventListener('click', event => {
|
|
866
|
+
event.stopPropagation();
|
|
867
|
+
if (getCurrentRunView?.()) return;
|
|
868
|
+
refillComposerForRetry(run);
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
function configureWritebackButton(root, run, options = {}) {
|
|
873
|
+
const existing = root.querySelector('[data-run-sync-retry]');
|
|
874
|
+
if (!existing) return;
|
|
875
|
+
const button = existing.cloneNode(true);
|
|
876
|
+
existing.replaceWith(button);
|
|
877
|
+
const count = run?.retryWriteback?.operations?.length || 0;
|
|
878
|
+
const available = !run?.forkSnapshot && (count || run?.saveCheck?.files?.length)
|
|
879
|
+
&& run.undoStatus !== 'applied' && run.trackedChangeStatus !== 'rejected' && typeof retryWriteback === 'function';
|
|
880
|
+
button.hidden = !available;
|
|
881
|
+
if (!available) return;
|
|
882
|
+
button.disabled = typeof options.running === 'boolean' ? options.running : Boolean(getCurrentRunView?.());
|
|
883
|
+
button.title = count ? tx('Retry sync (' + count + ' files)', '重试同步(' + count + ' 个文件)')
|
|
884
|
+
: tx('Check save status', '检查保存状态');
|
|
885
|
+
button.setAttribute('aria-label', button.title);
|
|
886
|
+
button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M16.5 7A7 7 0 0 0 4 5L2 7m0-4v4h4M3.5 13A7 7 0 0 0 16 15l2-2m0 4v-4h-4"/></svg>';
|
|
887
|
+
button.addEventListener('click', event => { event.stopPropagation(); if (!getCurrentRunView?.()) void retryWriteback(run.id); });
|
|
888
|
+
}
|
|
889
|
+
|
|
920
890
|
function configureUndoButton(root, run) {
|
|
921
891
|
const existing = root.querySelector('[data-run-undo]');
|
|
922
892
|
const button = existing.cloneNode(true);
|
|
@@ -939,13 +909,16 @@
|
|
|
939
909
|
}
|
|
940
910
|
|
|
941
911
|
button.hidden = false;
|
|
942
|
-
|
|
943
|
-
|
|
912
|
+
const inFlight = trackedChangeInFlight?.get(run.id) === 'reject';
|
|
913
|
+
const applied = run.undoStatus === 'applied' && !inFlight;
|
|
914
|
+
button.disabled = inFlight || (run.undoStatus === 'running' && !run.undoRecoveryCheckRequired) || run.undoStatus === 'applied';
|
|
915
|
+
button.textContent = applied
|
|
944
916
|
? tr('undoApplied')
|
|
945
917
|
: (run.partialWriteback ? tr('undoPartialRun') : tr('undoRun'));
|
|
946
|
-
button.title =
|
|
918
|
+
button.title = applied
|
|
947
919
|
? tr('undoAppliedTitle')
|
|
948
920
|
: (run.partialWriteback ? tr('undoPartialRunTitle') : tr('undoRunTitle'));
|
|
921
|
+
if (run.undoRecoveryUnavailable) button.title = tx('Undo recovery checks are unavailable. Reload this page after the connection recovers.', '撤销恢复检查暂不可用,请在连接恢复后重新加载此页面。');
|
|
949
922
|
button.addEventListener('click', event => {
|
|
950
923
|
event.stopPropagation();
|
|
951
924
|
undoRun(run.id);
|
|
@@ -1028,7 +1001,11 @@
|
|
|
1028
1001
|
}
|
|
1029
1002
|
|
|
1030
1003
|
if (!isTrackedChangeLifecycleRun(run)) {
|
|
1031
|
-
|
|
1004
|
+
const captures = run.undoStatus !== 'applied' && Array.isArray(run.trackedChangeCaptures) ? run.trackedChangeCaptures.filter(c => c && c.state !== 'observed') : [];
|
|
1005
|
+
button.hidden = !captures.length; button.disabled = true;
|
|
1006
|
+
button.textContent = tr('runAcceptTracked');
|
|
1007
|
+
button.title = captures.length ? tx('Tracked-change ownership is unconfirmed. Check the reasons below.', '本轮留痕归属尚未确认,请先核对下方原因。')
|
|
1008
|
+
+ '\n' + captures.map(c => c.path + ': ' + (c.reason || c.state) + (c.diagnostics?.sourceReason ? ' / ' + c.diagnostics.sourceReason : '')).join('\n') : tr('runAcceptTrackedTitle');
|
|
1032
1009
|
return;
|
|
1033
1010
|
}
|
|
1034
1011
|
|
|
@@ -1125,17 +1102,63 @@
|
|
|
1125
1102
|
const log = getPanel()?.querySelector('[data-log]');
|
|
1126
1103
|
const existing = log?.querySelector(`[data-run-id="${cssEscape(runId)}"]`);
|
|
1127
1104
|
const run = findRunRecord(runId);
|
|
1128
|
-
if (!log || !existing || !run) {
|
|
1129
|
-
return;
|
|
1105
|
+
if (!log || !existing || !run || displayRun(run) === run) {
|
|
1106
|
+
return false;
|
|
1130
1107
|
}
|
|
1131
|
-
existing.
|
|
1108
|
+
const reading = scrollLayout?.snapshot(), open = existing.querySelector('[data-run-process]')?.open;
|
|
1109
|
+
const next = renderRunCard(run);
|
|
1110
|
+
const process = next.querySelector('[data-run-process]');
|
|
1111
|
+
if (process && typeof open === 'boolean') process.open = open;
|
|
1112
|
+
existing.replaceWith(next);
|
|
1113
|
+
if (reading) scrollLayout?.restore(reading);
|
|
1114
|
+
return true;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
function refreshLocale() {
|
|
1118
|
+
const log = getPanel()?.querySelector('[data-log]');
|
|
1119
|
+
if (!log) return;
|
|
1120
|
+
if (!getState().runs?.length) { renderRunHistory({ preserveScroll: true }); return; }
|
|
1121
|
+
const reading = scrollLayout?.snapshot() || { scrollTop: log.scrollTop };
|
|
1122
|
+
for (const run of getState().runs) {
|
|
1123
|
+
const existing = log.querySelector(`[data-run-id="${cssEscape(run.id)}"]`);
|
|
1124
|
+
if (!existing) continue;
|
|
1125
|
+
const current = getCurrentRunView();
|
|
1126
|
+
if (current?.root === existing) {
|
|
1127
|
+
// Streaming owners retain their DOM references and buffered model text.
|
|
1128
|
+
const status = existing.querySelector('[data-run-status]');
|
|
1129
|
+
if (status) status.textContent = getRunStatusText(run);
|
|
1130
|
+
configureAcceptButton(existing, run); configureUndoButton(existing, run);
|
|
1131
|
+
configureEditButton(existing, run); configureWritebackButton(existing, run);
|
|
1132
|
+
RunResultActions.configureResultActions(existing, run);
|
|
1133
|
+
const reportEvent = (run.events || []).filter(event => event.kind === 'report').at(-1);
|
|
1134
|
+
const report = current.report || existing.querySelector('[data-run-report]');
|
|
1135
|
+
if (reportEvent && report) report.replaceChildren(renderCompletionReport(reportEvent, displayLocalizedRun(run)));
|
|
1136
|
+
activitySummary?.update(current);
|
|
1137
|
+
if (!activitySummary) RunGuidanceView.reconcileGuidance?.(existing.querySelector('[data-run-guidance]'),
|
|
1138
|
+
(run.events || []).concat(getPendingGuidance(run)), tx, { active: run.status === 'running' });
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
const open = existing.querySelector('[data-run-process]')?.open;
|
|
1142
|
+
const next = renderRunCard(run);
|
|
1143
|
+
const process = next.querySelector('[data-run-process]');
|
|
1144
|
+
if (process && typeof open === 'boolean') process.open = open;
|
|
1145
|
+
existing.replaceWith(next);
|
|
1146
|
+
}
|
|
1147
|
+
log.scrollTop = reading.scrollTop;
|
|
1148
|
+
scrollLayout?.restore(reading);
|
|
1149
|
+
updateJumpToLatestButton(log);
|
|
1132
1150
|
}
|
|
1133
1151
|
|
|
1134
1152
|
return {
|
|
1153
|
+
refreshLocale,
|
|
1154
|
+
refreshResolvedUndo: refreshRunCard,
|
|
1155
|
+
refreshActivitySummary: activitySummary?.update,
|
|
1156
|
+
appendActivityDetail,
|
|
1135
1157
|
resetAutoFollow,
|
|
1136
1158
|
bindLogAutoFollow,
|
|
1137
1159
|
bumpUnreadIfDetached,
|
|
1138
1160
|
scrollLogToBottom,
|
|
1161
|
+
revealGuidance,
|
|
1139
1162
|
collapseRunProcess,
|
|
1140
1163
|
startRunElapsedTick,
|
|
1141
1164
|
stopRunElapsedTick,
|
|
@@ -1147,10 +1170,12 @@
|
|
|
1147
1170
|
upsertStreamEvent,
|
|
1148
1171
|
renderCompletionReport,
|
|
1149
1172
|
isTrackedChangeLifecycleRun,
|
|
1173
|
+
configureEditButton,
|
|
1174
|
+
configureWritebackButton,
|
|
1150
1175
|
configureUndoButton,
|
|
1151
1176
|
configureAcceptButton
|
|
1152
1177
|
};
|
|
1153
1178
|
}
|
|
1154
1179
|
|
|
1155
|
-
|
|
1156
|
-
})
|
|
1180
|
+
return { create };
|
|
1181
|
+
});
|