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.
Files changed (397) hide show
  1. package/README.md +275 -305
  2. package/README.zh-CN.md +290 -320
  3. package/extension/bootstrap/background.js +99 -19
  4. package/extension/bootstrap/manifest.template.json +9 -4
  5. package/extension/bootstrap/popup.html +11 -16
  6. package/extension/bootstrap/popupFallback.js +55 -0
  7. package/extension/bootstrap/update.js +25 -2
  8. package/extension/bootstrap/updateStatus.js +1 -0
  9. package/extension/runtime-manifest.json +3 -1
  10. package/extension/src/background.js +234 -56
  11. package/extension/src/backgroundBootstrapMigration.js +181 -0
  12. package/extension/src/backgroundSharedSessions.js +440 -0
  13. package/extension/src/backgroundUpdateCoordinator.js +541 -381
  14. package/extension/src/backgroundUpdateSafety.js +173 -0
  15. package/extension/src/content/activeTurnControl.js +16 -2
  16. package/extension/src/content/applyResultFormatters.js +46 -73
  17. package/extension/src/content/assetTransferBroker.js +244 -12
  18. package/extension/src/content/changeHistoryView.js +175 -0
  19. package/extension/src/content/composerAttachments.js +117 -67
  20. package/extension/src/content/composerPanel.js +41 -8
  21. package/extension/src/content/contentRuntime.js +1084 -1099
  22. package/extension/src/content/diagnosticsController.js +122 -97
  23. package/extension/src/content/diagnosticsExport.js +236 -0
  24. package/extension/src/content/diagnosticsPanel.js +78 -19
  25. package/extension/src/content/diffReviewPanel.js +8 -5
  26. package/extension/src/content/directoryCleanupRecovery.js +54 -0
  27. package/extension/src/content/generated/content.bundle.js +14680 -3606
  28. package/extension/src/content/generated/content.bundle.meta.json +30 -3
  29. package/extension/src/content/globalPreferencesController.js +1 -1
  30. package/extension/src/content/legacyGlobalRegistry.js +25 -1
  31. package/extension/src/content/localSkillsPanel.js +141 -16
  32. package/extension/src/content/markdownDomRenderer.js +9 -4
  33. package/extension/src/content/markdownText.js +5 -6
  34. package/extension/src/content/modelPicker.js +8 -5
  35. package/extension/src/content/nativeCompatibilityController.js +45 -20
  36. package/extension/src/content/otWarmMirror.js +4 -5
  37. package/extension/src/content/otWarmMirrorController.js +17 -20
  38. package/extension/src/content/pageBridgeClient.js +33 -5
  39. package/extension/src/content/panelMaintenance.js +87 -132
  40. package/extension/src/content/panelRenderer.js +10 -0
  41. package/extension/src/content/pendingInputView.js +109 -76
  42. package/extension/src/content/projectProviderSelection.js +13 -4
  43. package/extension/src/content/projectSessionCleanup.js +109 -62
  44. package/extension/src/content/projectSettingsCoordinator.js +39 -2
  45. package/extension/src/content/providerSettingsCoordinator.js +63 -14
  46. package/extension/src/content/providerSettingsDialog.js +724 -113
  47. package/extension/src/content/recentProjects.js +21 -6
  48. package/extension/src/content/runActivitySummary.js +665 -0
  49. package/extension/src/content/runCompletionMeta.js +344 -0
  50. package/extension/src/content/runController.js +40 -15
  51. package/extension/src/content/runFailureNotice.js +34 -12
  52. package/extension/src/content/runGuidanceController.js +76 -30
  53. package/extension/src/content/runGuidanceView.js +59 -10
  54. package/extension/src/content/runPresence.js +306 -0
  55. package/extension/src/content/runQueueScheduler.js +150 -43
  56. package/extension/src/content/runRecoveryActions.js +146 -0
  57. package/extension/src/content/runResultActions.js +11 -8
  58. package/extension/src/content/runReviewController.js +574 -0
  59. package/extension/src/content/runScrollLayout.js +21 -2
  60. package/extension/src/content/runTimelineView.js +315 -290
  61. package/extension/src/content/scopedPersistencePanelState.js +51 -6
  62. package/extension/src/content/selectionContextView.js +300 -0
  63. package/extension/src/content/sensitivePreflight.js +140 -0
  64. package/extension/src/content/sessionForkController.js +80 -17
  65. package/extension/src/content/sessionManager.js +1 -1
  66. package/extension/src/content/sessionPersistence.js +6 -1
  67. package/extension/src/content/settingsPanel.js +84 -55
  68. package/extension/src/content/settingsWorkbench.js +379 -0
  69. package/extension/src/content/sharedSessionViewSync.js +109 -0
  70. package/extension/src/content/subagentActivityView.js +195 -0
  71. package/extension/src/content/trackedChangeCaptureController.js +7 -3
  72. package/extension/src/content/updateIdle.js +4 -1
  73. package/extension/src/content/updateNotice.js +179 -56
  74. package/extension/src/content/updateSafetyReceiver.js +58 -0
  75. package/extension/src/content/writebackController.js +308 -2
  76. package/extension/src/content/writebackOrchestrator.js +213 -199
  77. package/extension/src/content/writebackPlan.js +231 -0
  78. package/extension/src/content/writebackRecovery.js +122 -0
  79. package/extension/src/content/writingStyleSettings.js +600 -0
  80. package/extension/src/content/writtenChangesView.js +152 -0
  81. package/extension/src/page/binaryAssetUploader.js +223 -23
  82. package/extension/src/page/fileMover.js +256 -0
  83. package/extension/src/page/overleafProjectSnapshot.js +1 -0
  84. package/extension/src/page/ownedDirectoryCleanup.js +94 -0
  85. package/extension/src/page/referenceProjects.js +149 -0
  86. package/extension/src/page/reviewContext.js +113 -0
  87. package/extension/src/page/saveState.js +20 -6
  88. package/extension/src/page/snapshotRouter.js +124 -48
  89. package/extension/src/page/textCoordinates.js +102 -0
  90. package/extension/src/page/textFileCreator.js +442 -71
  91. package/extension/src/page/trackedChangeCapture.js +53 -57
  92. package/extension/src/page/trackedChangeOwnership.js +216 -0
  93. package/extension/src/page/trackedChangeReplay.js +184 -0
  94. package/extension/src/page/trackedChangesLifecycle.js +343 -339
  95. package/extension/src/page/treeOperations.js +33 -12
  96. package/extension/src/page/updateSafetyProbe.js +41 -0
  97. package/extension/src/page/writebackReceiptJournal.js +114 -0
  98. package/extension/src/page/writebackRouter.js +242 -201
  99. package/extension/src/pageBridge.js +73 -102
  100. package/extension/src/popup.js +261 -65
  101. package/extension/src/shared/agentTranscript.js +41 -4
  102. package/extension/src/shared/auditRecords.js +73 -0
  103. package/extension/src/shared/changeHistoryModel.js +94 -0
  104. package/extension/src/shared/compatibility.js +22 -6
  105. package/extension/src/shared/compileAdapter.js +101 -37
  106. package/extension/src/shared/composerAttachmentDraft.js +151 -0
  107. package/extension/src/shared/directoryCleanupProof.js +43 -0
  108. package/extension/src/shared/failureReasons.js +329 -3
  109. package/extension/src/shared/globalPreferences.js +31 -14
  110. package/extension/src/shared/governanceRules.js +4 -37
  111. package/extension/src/shared/i18n.js +389 -25
  112. package/extension/src/shared/managedUpdateProjection.js +8 -5
  113. package/extension/src/shared/nativeRequestIdentity.js +1 -0
  114. package/extension/src/shared/pageRpcContract.js +9 -2
  115. package/extension/src/shared/projectFiles.js +21 -44
  116. package/extension/src/shared/providerProfiles.js +114 -3
  117. package/extension/src/shared/runActivityModel.js +361 -0
  118. package/extension/src/shared/runExecutionSnapshot.js +8 -2
  119. package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
  120. package/extension/src/shared/runInputQueue.js +48 -5
  121. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
  122. package/extension/src/shared/selectionContext.js +37 -0
  123. package/extension/src/shared/sessionState.js +166 -30
  124. package/extension/src/shared/settlementFacts.js +10 -2
  125. package/extension/src/shared/sharedSessionBridge.js +311 -0
  126. package/extension/src/shared/sharedSessionTransfer.js +140 -0
  127. package/extension/src/shared/staleGuard.js +118 -13
  128. package/extension/src/shared/storageDb.js +77 -78
  129. package/extension/src/shared/storageMigration.js +74 -111
  130. package/extension/src/shared/storageRunActions.js +211 -22
  131. package/extension/src/shared/storageValuePruning.js +40 -0
  132. package/extension/src/shared/subagentActivityModel.js +174 -0
  133. package/extension/src/shared/undoOperations.js +216 -6
  134. package/extension/src/shared/updateConsent.js +42 -11
  135. package/extension/src/shared/updateRuntimeIdentity.js +1 -1
  136. package/extension/src/shared/writebackIntent.js +78 -0
  137. package/extension/src/shared/writebackOperationEvidence.js +4 -15
  138. package/extension/src/shared/writebackSettlement.js +67 -48
  139. package/extension/src/shared/writingStyle.js +33 -0
  140. package/extension/styles/panel.css +1987 -385
  141. package/extension/styles/popup.css +110 -0
  142. package/native-host/src/anthropicBridgeRequest.js +6 -3
  143. package/native-host/src/anthropicBridgeResponse.js +6 -2
  144. package/native-host/src/anthropicMessagesBridge.js +24 -16
  145. package/native-host/src/bootstrapMigration.js +296 -0
  146. package/native-host/src/bootstrapMigrationContract.js +101 -0
  147. package/native-host/src/bootstrapUpdate.js +233 -0
  148. package/native-host/src/bootstrapUpdateWatchdog.js +44 -0
  149. package/native-host/src/chatBridgeResponse.js +10 -0
  150. package/native-host/src/chatCompletionsBridge.js +21 -15
  151. package/native-host/src/codexConfigPaths.js +106 -0
  152. package/native-host/src/codexHome.js +66 -73
  153. package/native-host/src/codexHomeScope.js +124 -0
  154. package/native-host/src/codexInheritedAuth.js +90 -0
  155. package/native-host/src/codexLocalSkills.js +301 -0
  156. package/native-host/src/codexModelRecovery.js +107 -0
  157. package/native-host/src/codexPromptAssembly.js +33 -12
  158. package/native-host/src/codexProviderLaunch.js +3 -3
  159. package/native-host/src/codexProviderTest.js +24 -26
  160. package/native-host/src/codexRuntimeIdentity.js +1 -0
  161. package/native-host/src/codexSessionRunner.js +211 -318
  162. package/native-host/src/codexSessionTiming.js +21 -8
  163. package/native-host/src/codexSkillIsolation.js +170 -0
  164. package/native-host/src/codexThreadFork.js +19 -3
  165. package/native-host/src/index.js +19 -7
  166. package/native-host/src/managedInstall.js +115 -39
  167. package/native-host/src/managedInstallRecovery.js +140 -0
  168. package/native-host/src/managedRuntimeEvidence.js +57 -0
  169. package/native-host/src/mirrorWorkspace.js +92 -22
  170. package/native-host/src/nativeDoctor.js +15 -0
  171. package/native-host/src/nativeEnvironment.js +70 -0
  172. package/native-host/src/nativeHelperLifecycle.js +21 -0
  173. package/native-host/src/nativeHostRegistration.js +33 -0
  174. package/native-host/src/nativeQuotas.js +15 -8
  175. package/native-host/src/nativeRunLifecycle.js +71 -0
  176. package/native-host/src/overleafWorkspaceRules.js +16 -0
  177. package/native-host/src/processStopBarrier.js +115 -0
  178. package/native-host/src/projectPathPlatform.js +30 -0
  179. package/native-host/src/providerHttp.js +80 -0
  180. package/native-host/src/providerModelCatalog.js +4 -3
  181. package/native-host/src/providerProfile.js +17 -3
  182. package/native-host/src/providerReasoning.js +10 -11
  183. package/native-host/src/providerRuntime.js +1 -0
  184. package/native-host/src/providerStore.js +76 -14
  185. package/native-host/src/releaseTransport.js +14 -5
  186. package/native-host/src/responsesPassthroughBridge.js +266 -52
  187. package/native-host/src/runtimeInstaller.js +21 -1
  188. package/native-host/src/selectionScope.js +86 -0
  189. package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
  190. package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
  191. package/native-host/src/subagentAdmission.js +26 -0
  192. package/native-host/src/subagentBroker.js +176 -159
  193. package/native-host/src/subagentTelemetry.js +325 -0
  194. package/native-host/src/subagentWorkspace.js +103 -0
  195. package/native-host/src/subagentWorkspacePath.js +34 -0
  196. package/native-host/src/taskRunnerRuntime.js +130 -57
  197. package/native-host/src/tomlStatements.js +140 -0
  198. package/native-host/src/turnAttachments.js +113 -0
  199. package/native-host/src/updateManager.js +406 -38
  200. package/native-host/src/updateNetworkControl.js +75 -0
  201. package/native-host/src/updateTrust.js +21 -2
  202. package/native-host/src/vendor/pdfjs/LICENSE +177 -0
  203. package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
  204. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  205. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  206. package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  207. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  208. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  209. package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  210. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  211. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  212. package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  213. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  214. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  215. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  216. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  217. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  218. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  219. package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  220. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  221. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  222. package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  223. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  224. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  225. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  226. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  227. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  228. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  229. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  230. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  231. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  232. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  233. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  234. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  235. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  236. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  237. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  238. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  239. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  240. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  241. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  242. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  243. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  244. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  245. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  246. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  247. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  248. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  249. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  250. package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  251. package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  252. package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  253. package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  254. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  255. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  256. package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  257. package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  258. package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  259. package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  260. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  261. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  262. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  263. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  264. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  265. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  266. package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  267. package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  268. package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  269. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  270. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  271. package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  272. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  273. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  274. package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  275. package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  276. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  277. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  278. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  279. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  280. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  281. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  282. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  283. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  284. package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  285. package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  286. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  287. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  288. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  289. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  290. package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
  291. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  292. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  293. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  294. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  295. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  296. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  297. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  298. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  299. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  300. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  301. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  302. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  303. package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  304. package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  305. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  306. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  307. package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  308. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  309. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  310. package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  311. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  312. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  313. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  314. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  315. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  316. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  317. package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  318. package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
  319. package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  320. package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  321. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  322. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  323. package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  324. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  325. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  326. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  327. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  328. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  329. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  330. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  331. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  332. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  333. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  334. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  335. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  336. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  337. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  338. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  339. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  340. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  341. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  342. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  343. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  344. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  345. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  346. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  347. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  348. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  349. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  350. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  351. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  352. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  353. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  354. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  355. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  356. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  357. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  358. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  359. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  360. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  361. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  362. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  363. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  364. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  365. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  366. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  367. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  368. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  369. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  370. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  371. package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
  372. package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  373. package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
  374. package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
  375. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  376. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  377. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  378. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  379. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  380. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  381. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  382. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  383. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  384. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  385. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  386. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  387. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  388. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  389. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  390. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  391. package/native-host/src/writingStyleEvidence.js +102 -0
  392. package/native-host/src/writingStylePdfWorker.js +35 -0
  393. package/native-host/src/writingStyleProfile.js +165 -0
  394. package/native-host/src/writingStyleRuntime.js +475 -0
  395. package/native-host/src/writingStyleStore.js +73 -0
  396. package/package.json +1 -1
  397. package/scripts/install-managed.mjs +1 -0
@@ -1,75 +1,218 @@
1
1
  (function initPopup() {
2
2
  'use strict';
3
3
 
4
+ // Keep only copy produced by this popup eligible for a language refresh.
5
+ const popupCopyPairs = new Map();
6
+ let newSiteCopyNodes = [];
7
+
8
+ const popupScriptUrl = document.currentScript?.src || chrome.runtime.getURL('src/popup.js');
9
+ ensureMinimalPopupShell();
4
10
  const CodexOverleafCompatibility = window.CodexOverleafCompatibility;
5
- const DEFAULT_INSTALL_COMMAND = CodexOverleafCompatibility?.buildInstallCommand?.(
11
+ const isManagedInstall = chrome.runtime.getManifest()?.background?.service_worker === 'bootstrap/background.js'
12
+ || window.__CODEX_OVERLEAF_RUNTIME_PREFIX__ === 'runtime/';
13
+ let installIdentity = { managed: isManagedInstall };
14
+ const DEFAULT_INSTALL_COMMAND = isManagedInstall ? '' : CodexOverleafCompatibility?.buildInstallCommand?.(
6
15
  undefined,
7
16
  undefined,
8
17
  getCurrentExtensionId()
9
18
  ) || 'curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/main/install.sh | bash -s -- --extension-id <chrome-extension-id>';
10
- const button = document.getElementById('open-panel');
19
+ const launcherToggle = document.getElementById('launcher-toggle');
11
20
  const status = document.getElementById('status');
21
+ const connectionToggle = document.getElementById('connection-toggle');
22
+ const connectionDetails = document.getElementById('connection-details');
23
+ const connectionLabel = document.getElementById('connection-label');
12
24
  const compatStatusIcon = document.getElementById('compat-status-icon');
13
- const versionPair = document.getElementById('version-pair');
25
+ const extensionVersionLabel = document.getElementById('extension-version');
26
+ const nativeVersionLabel = document.getElementById('native-version');
14
27
  const nativeInstall = document.getElementById('native-install');
28
+ const nativeStatusMessage = document.getElementById('native-status-message');
15
29
  const installCommand = document.getElementById('install-command');
16
30
  const copyInstallCommand = document.getElementById('copy-install-command');
31
+ const copyFeedback = document.getElementById('copy-feedback');
17
32
  let activeOverleafTab = null;
18
33
  let currentInstallCommand = DEFAULT_INSTALL_COMMAND;
34
+ let lastCompatibility = null;
35
+ let launcherVisible = false;
36
+ let launcherReady = false;
19
37
 
20
38
  installCommand.textContent = currentInstallCommand;
21
- button.textContent = 'Show Codex button in Overleaf';
22
- setVersionStatus({
23
- status: 'native_missing',
24
- classification: 'incompatible',
25
- extensionVersion: getExtensionCompatibilityMetadata().version
39
+ setVersionStatus({ status: 'checking', extensionVersion: getExtensionCompatibilityMetadata().version });
40
+
41
+ connectionToggle.addEventListener('click', () => {
42
+ connectionDetails.hidden = !connectionDetails.hidden;
43
+ connectionToggle.setAttribute('aria-expanded', String(!connectionDetails.hidden));
26
44
  });
27
45
 
28
- button.addEventListener('click', async () => {
29
- const tab = activeOverleafTab || await getActiveOverleafProjectTab();
30
- if (!tab?.id) {
31
- status.textContent = 'Open an Overleaf project tab first.';
32
- return;
46
+ launcherToggle.addEventListener('change', async () => {
47
+ const desired = launcherToggle.checked;
48
+ launcherToggle.disabled = true;
49
+ setLauncherStatus('');
50
+ try {
51
+ const tab = await getActiveOverleafProjectTab();
52
+ if (!tab?.id) throw new Error(utx('Open an Overleaf project tab first.', '请先打开 Overleaf 项目页。'));
53
+ activeOverleafTab = tab;
54
+ const before = await chrome.tabs.sendMessage(tab.id, { type: 'codex-overleaf/get-panel-state' });
55
+ if (typeof before?.launcherVisible !== 'boolean') {
56
+ throw new Error(utx('Refresh the Overleaf tab, then reopen this popup.', '请刷新 Overleaf 页面,再打开此弹窗。'));
57
+ }
58
+ // Keep the existing visibility contract. Do not open or close the panel.
59
+ if (before.launcherVisible !== desired) {
60
+ const response = await chrome.tabs.sendMessage(tab.id, { type: 'codex-overleaf/toggle-launcher' });
61
+ if (response?.ok === false) throw new Error(response.error?.message || response.error
62
+ || utx('The side button could not be changed.', '侧边入口设置未能修改。'));
63
+ }
64
+ const after = await chrome.tabs.sendMessage(tab.id, { type: 'codex-overleaf/get-panel-state' });
65
+ if (typeof after?.launcherVisible !== 'boolean' || after.launcherVisible !== desired) {
66
+ throw new Error(utx('The side button state could not be confirmed. Reopen this popup to retry.',
67
+ '未能确认侧边入口状态,请重新打开此弹窗后重试。'));
68
+ }
69
+ launcherVisible = after.launcherVisible;
70
+ launcherReady = true;
71
+ } catch (error) {
72
+ launcherReady = false;
73
+ setLauncherStatus(error?.message || utx('Refresh the Overleaf tab and try again.', '请刷新 Overleaf 页面后重试。'), true);
74
+ } finally {
75
+ launcherToggle.checked = launcherVisible;
76
+ launcherToggle.disabled = !launcherReady;
33
77
  }
34
-
35
- await chrome.tabs.sendMessage(tab.id, { type: 'codex-overleaf/toggle-launcher' });
36
- window.close();
37
78
  });
38
79
 
39
80
  copyInstallCommand.addEventListener('click', async () => {
40
- await navigator.clipboard.writeText(currentInstallCommand);
41
- copyInstallCommand.textContent = 'Copied';
42
- setTimeout(() => {
43
- copyInstallCommand.textContent = 'Copy install command';
44
- }, 1400);
81
+ if (!currentInstallCommand) return;
82
+ copyInstallCommand.disabled = true;
83
+ copyFeedback.hidden = true;
84
+ try {
85
+ await navigator.clipboard.writeText(currentInstallCommand);
86
+ copyInstallCommand.textContent = utx('Copied', '已复制');
87
+ setTimeout(() => { copyInstallCommand.textContent = utx('Copy install command', '复制安装命令'); }, 1400);
88
+ } catch (_error) {
89
+ copyFeedback.textContent = utx('Copy failed. Select the command above to copy it.', '复制失败,可选中上方命令复制。');
90
+ copyFeedback.hidden = false;
91
+ } finally {
92
+ copyInstallCommand.disabled = !currentInstallCommand;
93
+ }
45
94
  });
46
95
 
47
96
  initPopupState();
48
97
  scheduleConsentUpdateUi();
49
98
 
99
+ // Older managed installations keep their bootstrap HTML across runtime
100
+ // updates. Upgrade only this popup's shell, leaving runtime behavior shared.
101
+ function ensureMinimalPopupShell() {
102
+ document.documentElement.classList.add('popup-minimal-root');
103
+ document.body.classList.add('popup-minimal');
104
+ if (!document.getElementById('launcher-toggle')) {
105
+ const shell = document.createElement('div');
106
+ shell.innerHTML = "<main id=\"popup-shell\">\n <header class=\"popup-header\">\n <img id=\"brand-icon\" class=\"popup-icon\" src=\"assets/icons/icon128.png\" width=\"32\" height=\"32\" alt=\"\">\n <div class=\"popup-brand\">\n <h1>Codex Overleaf Link</h1>\n <button id=\"connection-toggle\" class=\"connection-toggle\" type=\"button\" aria-expanded=\"false\" aria-controls=\"connection-details\">\n <span id=\"compat-status-icon\" class=\"status-icon pending\" aria-hidden=\"true\"></span>\n <span id=\"connection-label\">Checking connection...</span>\n <span class=\"connection-chevron\" aria-hidden=\"true\"></span>\n </button>\n </div>\n </header>\n <section id=\"connection-details\" class=\"connection-details\" aria-label=\"Version details\" hidden>\n <dl id=\"version-pair\">\n <div><dt id=\"extension-version-label\">Extension</dt><dd id=\"extension-version\">Unknown</dd></div>\n <div><dt>Native Host</dt><dd id=\"native-version\">Checking...</dd></div>\n </dl>\n </section>\n <label class=\"launcher-setting\" for=\"launcher-toggle\">\n <span class=\"launcher-copy\">\n <strong id=\"launcher-label\">Show Codex side button</strong>\n <small id=\"launcher-description\">When the panel is closed</small>\n </span>\n <input id=\"launcher-toggle\" class=\"launcher-toggle\" type=\"checkbox\" aria-describedby=\"launcher-description\" disabled>\n </label>\n <p id=\"status\" class=\"popup-note\" role=\"status\" aria-live=\"polite\" hidden></p>\n <section id=\"native-install\" class=\"install\" aria-labelledby=\"native-install-title\" hidden>\n <strong id=\"native-install-title\">Native host attention required</strong>\n <p id=\"native-status-message\"></p>\n <code id=\"install-command\"></code>\n <button id=\"copy-install-command\" class=\"copy-command\" type=\"button\">Copy install command</button>\n <p id=\"copy-feedback\" class=\"copy-feedback\" role=\"status\" hidden></p>\n </section>\n</main>";
107
+ for (const element of Array.from(document.body.children)) {
108
+ if (element.tagName !== 'SCRIPT') element.remove();
109
+ }
110
+ document.body.prepend(shell.firstElementChild);
111
+ }
112
+ document.getElementById('brand-icon').src = chrome.runtime.getURL('assets/icons/icon128.png');
113
+ let stylesheet = document.getElementById('popup-styles');
114
+ if (!stylesheet) {
115
+ stylesheet = document.createElement('link');
116
+ stylesheet.id = 'popup-styles';
117
+ stylesheet.rel = 'stylesheet';
118
+ document.head.append(stylesheet);
119
+ }
120
+ stylesheet.href = new URL('../styles/popup.css', popupScriptUrl).href;
121
+ }
122
+
50
123
  async function initPopupState() {
51
- await checkNativeHost();
52
- await refreshPanelButtonState();
124
+ try {
125
+ const stored = await chrome.storage.local.get(['codexOverleafGlobalPrefsV1', 'codexOverleafPrefs']);
126
+ applyPopupPreferences(stored.codexOverleafGlobalPrefsV1?.values || stored.codexOverleafPrefs || {});
127
+ } catch (_error) { applyPopupPreferences({}); }
128
+ chrome.storage.onChanged?.addListener((changes, area) => {
129
+ if (area === 'local' && changes.codexOverleafGlobalPrefsV1?.newValue?.values) {
130
+ applyPopupPreferences(changes.codexOverleafGlobalPrefsV1.newValue.values);
131
+ }
132
+ });
133
+ await Promise.all([checkNativeHost(), refreshPanelButtonState(), offerNewSites()]);
53
134
  }
54
135
 
55
- async function refreshPanelButtonState() {
56
- const tab = await getActiveOverleafProjectTab();
57
- activeOverleafTab = tab;
58
- if (!tab?.id) {
59
- button.textContent = 'Show Codex button in Overleaf';
60
- return;
136
+ // A runtime update can list an Overleaf site the install did not grant.
137
+ // Chrome only grants it from a click here; nothing changes until then.
138
+ async function offerNewSites() {
139
+ if (!chrome.permissions?.contains || !chrome.permissions?.request) return;
140
+ let matches = [];
141
+ try {
142
+ const url = new URL('../runtime-manifest.json', popupScriptUrl).href;
143
+ matches = (await (await fetch(url, { cache: 'no-store' })).json()).matches || [];
144
+ } catch (_error) { return; }
145
+ const missing = [];
146
+ for (const value of matches) {
147
+ if (!/^https:\/\/(?:[a-z0-9-]+\.)*overleaf\.com\/project(?:\/\*)?$/.test(value)) continue;
148
+ if (!(await chrome.permissions.contains({ origins: [value] }).catch(() => true))) missing.push(value);
61
149
  }
150
+ if (!missing.length) return;
151
+ const hosts = [...new Set(missing.map(value => new URL(value.replace(/\*$/, '')).host))];
152
+ const section = document.createElement('section');
153
+ section.className = 'install';
154
+ section.dataset.newSites = '';
155
+ const title = document.createElement('strong');
156
+ title.textContent = utx('This version supports another Overleaf site', '这一版支持新的 Overleaf 站点');
157
+ const detail = document.createElement('p');
158
+ detail.textContent = utx(`Allow access to ${hosts.join(', ')} to use Codex there. Chrome will ask you to confirm.`,
159
+ `允许访问 ${hosts.join('、')} 后即可在那里使用 Codex,Chrome 会请你确认。`);
160
+ const button = document.createElement('button');
161
+ button.type = 'button';
162
+ button.className = 'copy-command';
163
+ button.textContent = utx('Allow', '允许');
164
+ button.addEventListener('click', async () => {
165
+ const granted = await chrome.permissions.request({ origins: missing }).catch(() => false);
166
+ if (granted) section.remove();
167
+ });
168
+ newSiteCopyNodes = [title, detail, button];
169
+ section.append(title, detail, button);
170
+ document.getElementById('popup-shell')?.append(section);
171
+ }
172
+
173
+ function applyPopupPreferences(preferences) {
174
+ document.documentElement.lang = preferences.locale === 'zh' ? 'zh-CN' : 'en';
175
+ document.documentElement.dataset.popupTheme = ['light', 'dark', 'auto'].includes(preferences.theme)
176
+ ? preferences.theme : 'dark';
177
+ document.getElementById('launcher-label').textContent = utx('Show Codex side button', '显示 Codex 侧边入口');
178
+ document.getElementById('launcher-description').textContent = utx('When the panel is closed', '面板关闭时显示');
179
+ document.getElementById('extension-version-label').textContent = utx('Extension', '扩展');
180
+ document.getElementById('native-install-title').textContent = utx('Local connection needs attention', '本地连接需要处理');
181
+ connectionDetails.setAttribute('aria-label', utx('Version details', '版本信息'));
182
+ connectionToggle.title = utx('Show or hide version details', '展开或收起版本信息');
183
+ copyInstallCommand.textContent = utx('Copy install command', '复制安装命令');
184
+ [status, copyFeedback, ...newSiteCopyNodes].forEach(refreshPopupCopy);
185
+ if (lastCompatibility) {
186
+ setVersionStatus(lastCompatibility);
187
+ if (!nativeInstall.hidden) showNativeInstallGuide(lastCompatibility);
188
+ }
189
+ }
190
+
191
+ function setLauncherStatus(message, failed = false) {
192
+ status.textContent = message;
193
+ status.hidden = !message;
194
+ status.setAttribute('role', failed ? 'alert' : 'status');
195
+ }
62
196
 
197
+ async function refreshPanelButtonState() {
198
+ launcherReady = false;
199
+ launcherToggle.disabled = true;
63
200
  try {
201
+ const tab = await getActiveOverleafProjectTab();
202
+ activeOverleafTab = tab;
203
+ if (!tab?.id) {
204
+ setLauncherStatus(utx('Open an Overleaf project to change this preference.', '打开 Overleaf 项目页后可设置侧边入口。'));
205
+ return;
206
+ }
64
207
  const response = await chrome.tabs.sendMessage(tab.id, { type: 'codex-overleaf/get-panel-state' });
65
- const visible = response?.launcherVisible !== false;
66
- button.textContent = visible ? 'Hide Codex edge button' : 'Show Codex edge button';
67
- status.textContent = visible
68
- ? 'The edge button appears whenever the Codex panel is closed.'
69
- : 'The Codex edge button is hidden in Overleaf.';
208
+ if (typeof response?.launcherVisible !== 'boolean') throw new Error('Panel state unavailable');
209
+ launcherVisible = response.launcherVisible;
210
+ launcherReady = true;
211
+ launcherToggle.checked = launcherVisible;
212
+ launcherToggle.disabled = false;
213
+ setLauncherStatus('');
70
214
  } catch (_error) {
71
- button.textContent = 'Show Codex button in Overleaf';
72
- status.textContent = 'Refresh the Overleaf tab, then show the Codex button.';
215
+ setLauncherStatus(utx('Refresh the Overleaf tab, then reopen this popup.', '请刷新 Overleaf 页面,再打开此弹窗。'));
73
216
  }
74
217
  }
75
218
 
@@ -79,10 +222,11 @@
79
222
  }
80
223
 
81
224
  function isOverleafProjectUrl(url) {
82
- return /^https:\/\/(www\.)?overleaf\.com\/project\//.test(String(url || ''));
225
+ return /^https:\/\/(?:(?:www|cn)\.)?overleaf\.com\/project\//.test(String(url || ''));
83
226
  }
84
227
 
85
228
  async function checkNativeHost() {
229
+ await readInstallIdentity();
86
230
  try {
87
231
  const response = await chrome.runtime.sendMessage({
88
232
  type: 'codex-overleaf/native-request',
@@ -96,16 +240,13 @@
96
240
  setVersionStatus(compatibility);
97
241
  if (getCompatibilityClassification(compatibility) === 'compatible') {
98
242
  nativeInstall.hidden = true;
99
- status.textContent = 'Native host connected. Open an Overleaf project tab to use Codex.';
100
243
  return;
101
244
  }
102
245
  showNativeInstallGuide(compatibility);
103
246
  } catch (_error) {
104
247
  const compatibility = {
105
- status: 'native_missing',
106
- classification: 'incompatible',
107
- installCommand: DEFAULT_INSTALL_COMMAND,
108
- updateCommand: DEFAULT_INSTALL_COMMAND,
248
+ status: 'native_missing', classification: 'incompatible',
249
+ installCommand: DEFAULT_INSTALL_COMMAND, updateCommand: DEFAULT_INSTALL_COMMAND,
109
250
  extensionVersion: getExtensionCompatibilityMetadata().version
110
251
  };
111
252
  setVersionStatus(compatibility);
@@ -113,11 +254,29 @@
113
254
  }
114
255
  }
115
256
 
257
+ async function readInstallIdentity() {
258
+ if (!isManagedInstall) return;
259
+ try {
260
+ const response = await fetch(chrome.runtime.getURL('.codex-overleaf-managed-extension.json'));
261
+ const marker = response.ok ? await response.json() : null;
262
+ if (marker?.managedBy === 'codex-overleaf-link' && marker.kind === 'extension'
263
+ && marker.installIdentity?.extensionId === getCurrentExtensionId()) {
264
+ installIdentity = { ...marker.installIdentity, managed: true };
265
+ }
266
+ } catch (_) { /* Older markers cannot prove the original root or browser. */ }
267
+ }
268
+
116
269
  function showNativeInstallGuide(compatibility = {}) {
117
270
  nativeInstall.hidden = false;
118
271
  currentInstallCommand = getCompatibilityUpdateCommand(compatibility);
119
272
  installCommand.textContent = currentInstallCommand;
120
- status.textContent = getNativeStatusMessage(compatibility.status, getCompatibilityClassification(compatibility));
273
+ copyInstallCommand.disabled = !currentInstallCommand;
274
+ nativeStatusMessage.textContent = !currentInstallCommand && isManagedInstall
275
+ ? utx('Repair this Managed installation using its original managed root, browser and extension ID. Rerun the original install-managed command with those parameters.',
276
+ '修复此托管安装需要原管理根目录、浏览器和扩展 ID。请使用这些原参数重新运行 install-managed 安装命令。')
277
+ : getNativeStatusMessage(compatibility.status, getCompatibilityClassification(compatibility))
278
+ + ((compatibility.native?.platform || installIdentity.platform) === 'win32' && isManagedInstall
279
+ ? utx(' Run the command in PowerShell.', ' 请在 PowerShell 中运行该命令。') : '');
121
280
  }
122
281
 
123
282
  function evaluateNativeCompatibility(response) {
@@ -146,17 +305,25 @@
146
305
  }
147
306
 
148
307
  function setVersionStatus(compatibility = {}) {
149
- const classification = getCompatibilityClassification(compatibility);
308
+ lastCompatibility = compatibility;
309
+ const pending = compatibility.status === 'checking';
310
+ const classification = pending ? 'pending' : getCompatibilityClassification(compatibility);
150
311
  const extensionVersion = compatibility.extensionVersion || getExtensionCompatibilityMetadata().version;
151
312
  const nativeVersion = compatibility.currentNativeVersion || compatibility.nativeVersion || compatibility.native?.version;
152
- versionPair.textContent = `Extension ${formatVersion(extensionVersion)} / Native ${formatVersion(nativeVersion)}`;
153
- compatStatusIcon.textContent = getStatusIconText(classification);
154
- compatStatusIcon.className = `status-icon ${classification}`;
155
- compatStatusIcon.title = getCompatibilityStatusTitle(classification);
156
- if (compatStatusIcon.dataset) {
157
- compatStatusIcon.dataset.status = classification;
158
- }
159
- compatStatusIcon.setAttribute?.('aria-label', compatStatusIcon.title);
313
+ extensionVersionLabel.textContent = formatVersion(extensionVersion);
314
+ nativeVersionLabel.textContent = pending ? utx('Checking...', '正在检查...') : formatVersion(nativeVersion);
315
+ let label = utx('Update required', '需要更新');
316
+ if (pending) label = utx('Checking connection...', '正在检查连接...');
317
+ else if (classification === 'compatible') label = utx('Connected', '已连接');
318
+ else if (classification === 'update-available') label = utx('Update available', '有可用更新');
319
+ else if (compatibility.status === 'native_missing') label = utx('Not connected', '未连接');
320
+ else if (compatibility.status === 'native_unhealthy') label = utx('Needs attention', '需要处理');
321
+ connectionLabel.textContent = label;
322
+ connectionToggle.setAttribute('aria-label', label + '. ' + utx('Version details', '版本信息'));
323
+ compatStatusIcon.textContent = '';
324
+ compatStatusIcon.className = 'status-icon ' + classification;
325
+ compatStatusIcon.title = label;
326
+ compatStatusIcon.dataset.status = classification;
160
327
  }
161
328
 
162
329
  function getExtensionCompatibilityMetadata() {
@@ -164,7 +331,8 @@
164
331
  version: CodexOverleafCompatibility?.BUILD_TARGET_VERSION ||
165
332
  chrome.runtime.getManifest?.().version ||
166
333
  '',
167
- extensionId: getCurrentExtensionId()
334
+ extensionId: getCurrentExtensionId(),
335
+ ...(isManagedInstall ? { installIdentity } : {})
168
336
  };
169
337
  }
170
338
 
@@ -192,8 +360,9 @@
192
360
  return CodexOverleafCompatibility?.buildInstallCommand?.(
193
361
  compatibility.recommendedVersion || CodexOverleafCompatibility.BUILD_TARGET_VERSION,
194
362
  compatibility.native?.platform || compatibility.platform,
195
- getCurrentExtensionId()
196
- ) || compatibility.updateCommand || compatibility.installCommand || DEFAULT_INSTALL_COMMAND;
363
+ getCurrentExtensionId(),
364
+ installIdentity
365
+ ) || (isManagedInstall ? '' : compatibility.updateCommand || compatibility.installCommand || DEFAULT_INSTALL_COMMAND);
197
366
  }
198
367
 
199
368
  function getStatusIconText(classification) {
@@ -221,28 +390,33 @@
221
390
  function formatVersion(version) {
222
391
  const value = String(version || '').trim();
223
392
  if (!value) {
224
- return 'unknown';
393
+ return utx('Unknown', '未知');
225
394
  }
226
395
  return value.startsWith('v') ? value : `v${value}`;
227
396
  }
228
397
 
229
398
  function getNativeStatusMessage(statusValue, classification) {
230
399
  if (classification === 'update-available') {
231
- return 'Native host update available. Run the update command, then reload the extension.';
400
+ return utx('An update is available for the local bridge. Run the command below, then reload the extension.',
401
+ '本地桥接程序有可用更新。运行下方命令后重新加载扩展。');
232
402
  }
233
403
  switch (statusValue) {
234
404
  case 'native_too_old':
235
- return 'Native host update required. Run the install command, then reload the extension.';
405
+ return utx('Update the local bridge with the command below, then reload the extension.',
406
+ '运行下方命令更新本地桥接程序,然后重新加载扩展。');
236
407
  case 'protocol_unsupported':
237
- return 'Native host protocol mismatch. Update the native host and extension together.';
408
+ return utx('The extension and local bridge use different protocols. Update both components together.',
409
+ '扩展与本地桥接程序的协议不匹配,请一并更新。');
238
410
  case 'extension_too_old':
239
- return 'Extension update required. Update the Chrome extension before running Codex.';
411
+ return utx('Update the Chrome extension before running Codex.', '运行 Codex 前需要更新 Chrome 扩展。');
240
412
  case 'native_unhealthy':
241
- return 'Native host connected, but local Codex is not ready. Check the panel diagnostics.';
413
+ return utx('The local bridge is connected, but Codex needs attention. Check diagnostics in the side panel.',
414
+ '本地桥接已连接,Codex 状态需要处理。请查看侧边栏中的诊断。');
242
415
  case 'native_missing':
243
- return 'Install the local native host before running Codex.';
416
+ return utx('Run this command in Terminal, then reload the extension.', '在终端运行下方命令,然后重新加载扩展。');
244
417
  default:
245
- return 'Native host is not compatible. Update the native host, then reload the extension.';
418
+ return utx('Update the local bridge with the command below, then reload the extension.',
419
+ '运行下方命令更新本地桥接程序,然后重新加载扩展。');
246
420
  }
247
421
  }
248
422
 
@@ -414,7 +588,7 @@ async function sendConsentAction(action) {
414
588
  const summary = document.createElement('summary');
415
589
  summary.textContent = utx('Technical details', '技术详情');
416
590
  const code = document.createElement('code');
417
- code.textContent = [state.code, state.message].filter(Boolean).join(': ');
591
+ code.textContent = [state.code, formatUpdateFailure(state)].filter(Boolean).join(': ');
418
592
  details.append(summary, code);
419
593
  card.append(details);
420
594
  }
@@ -524,12 +698,26 @@ async function sendConsentAction(action) {
524
698
  awaiting_health: [utx('Checking updated components', '正在检查更新后的组件'), latest, utx('Restarting and checking both components', '正在重启并检查两个组件')],
525
699
  committed: [utx('Update complete', '更新完成'), latest || current, utx('Extension and Native Host are healthy.', '扩展与 Native Host 均运行正常。')],
526
700
  rolled_back: [utx('Previous version restored', '已恢复上一版本'), current, utx('Health check failed, so the previous coordinated pair was restored.', '健康检查失败,已恢复上一组协调版本。')],
527
- failed: [utx('Update could not continue', '更新无法继续'), latest, state.message || utx('Check the details and retry.', '请查看详情后重试。')]
701
+ failed: [utx('Update could not continue', '更新无法继续'), latest, formatUpdateFailure(state) || utx('Check the details and retry.', '请查看详情后重试。')]
528
702
  };
529
703
  const value = map[state.state] || map.idle;
530
704
  return { title: value[0], version: value[1], detail: value[2], phase: value[2] };
531
705
  }
532
706
 
707
+ function formatUpdateFailure(state = {}) {
708
+ const code = String(state.code || '');
709
+ if (code === 'update_recovery_pending') return utx('The update result is being checked. Recovery has not been confirmed.', '正在确认更新结果,恢复状态尚未确认。');
710
+ if (['update_bootstrap_health_timeout', 'update_bootstrap_reload_failed'].includes(code)) return utx('The updated startup components did not finish restarting and confirming. Check recovery before retrying.', '更新后的启动组件未能完成重启和确认,请先检查恢复状态。');
711
+ if (['update_bootstrap_source_mismatch', 'update_bootstrap_source_version_mismatch'].includes(code)) return utx('The installed startup files do not match a supported update source. Check recovery before retrying.', '已安装的启动文件与支持的升级来源不一致,请先检查恢复状态。');
712
+ if (['update_bootstrap_record_missing', 'update_bootstrap_record_invalid', 'update_bootstrap_backup_mismatch', 'update_bootstrap_already_restoring'].includes(code)) return utx('The startup recovery material could not be confirmed. The update result remains unconfirmed.', '尚未确认启动组件的恢复材料有效,更新结果仍待确认。');
713
+ if (['update_bootstrap_confirmation_pending', 'update_bootstrap_native_restart_required'].includes(code)) return utx('Waiting for the updated startup components and Native Host to finish restarting and confirming.', '正在等待更新后的启动组件和本机服务完成重启及确认。');
714
+ if (code === 'update_bootstrap_monitor_unavailable') return utx('The update recovery monitor could not start. Check recovery before retrying.', '更新恢复监护程序未能启动,请先检查恢复状态。');
715
+ if (['update_bootstrap_transaction_mismatch', 'update_bootstrap_transaction_invalid'].includes(code)) return utx('The startup update transaction could not be matched. Check recovery before retrying.', '未能匹配启动组件的更新事务,请先检查恢复状态。');
716
+ if (code.startsWith('update_bootstrap_')) return utx('The startup update package or installed files could not be verified. Check recovery before retrying.', '无法验证启动组件更新包或已安装文件,请先检查恢复状态。');
717
+ if (['update_health_failed', 'update_request_failed', 'update_failed'].includes(code)) return utx('The updated components could not be confirmed. Check recovery before retrying.', '尚未确认更新后的组件正常,请先检查恢复状态。');
718
+ return state.message || '';
719
+ }
720
+
533
721
  function formatBlocker(blocker) {
534
722
  const labels = {
535
723
  unsaved: utx('Overleaf has not confirmed that this document is saved.', 'Overleaf 尚未确认当前文档已保存。'),
@@ -544,7 +732,15 @@ async function sendConsentAction(action) {
544
732
  return labels[blocker] || utx('Waiting until every Overleaf tab is saved and idle.', '正在等待所有 Overleaf 标签页完成保存并进入空闲状态。');
545
733
  }
546
734
 
735
+ function refreshPopupCopy(element) {
736
+ const pair = popupCopyPairs.get(element?.textContent);
737
+ if (pair) element.textContent = utx(...pair);
738
+ }
739
+
547
740
  function utx(english, chinese) {
741
+ const pair = [english, chinese];
742
+ popupCopyPairs.set(english, pair);
743
+ popupCopyPairs.set(chinese, pair);
548
744
  const locale = document.documentElement?.lang || 'en';
549
745
  return /^zh\b/i.test(locale) ? chinese : english;
550
746
  }
@@ -63,6 +63,14 @@
63
63
  const locale = normalizeLocale(options);
64
64
  const type = String(event.type || '');
65
65
 
66
+ if (type === 'codex.local_skills.missing' || type === 'codex.local_skill_invocation.ignored') {
67
+ return { kind: 'activity', visible: true,
68
+ title: type === 'codex.local_skills.missing'
69
+ ? textFor(locale, '所选的本地技能未能加载。', 'A selected local skill could not be loaded.')
70
+ : textFor(locale, '所选的本地技能已关闭或不可用。', 'A selected local skill is disabled or unavailable.'),
71
+ status: event.status || 'failed', technicalDetail: normalizeRawEvent(event) };
72
+ }
73
+
66
74
  if (isContextCompactionEvent(event)) {
67
75
  return formatContextCompactionCheckpoint(event, locale);
68
76
  }
@@ -372,6 +380,7 @@
372
380
  status: 'running',
373
381
  streamKey: getCodexStreamKey(method, params),
374
382
  streamRole: method === 'item/agentMessage/delta' ? 'assistant' : 'reasoning',
383
+ streamPhase: params.phase || '',
375
384
  appendText: true
376
385
  };
377
386
  }
@@ -412,12 +421,13 @@
412
421
  };
413
422
  }
414
423
  if (method === 'warning' || method === 'guardianWarning' || method === 'configWarning') {
415
- const title = cleanVisibleText(params.message || params.warning || '');
424
+ const title = cleanVisibleText(params.message || params.warning || params.summary || '');
425
+ if (!title) return technicalOnly(event, locale);
416
426
  return {
417
427
  kind: 'activity',
418
428
  visible: true,
419
- title: title || textFor(locale, 'Codex 返回了一条运行提示。', 'Codex returned a runtime notice.'),
420
- status: 'running',
429
+ title,
430
+ status: event.status === 'failed' ? 'failed' : method === 'guardianWarning' ? 'warning' : 'info',
421
431
  technicalDetail: normalizeRawEvent(event)
422
432
  };
423
433
  }
@@ -459,6 +469,7 @@
459
469
  status,
460
470
  streamKey: getItemStreamKey('agent', item),
461
471
  streamRole: 'assistant',
472
+ streamPhase: item.phase || '',
462
473
  replaceText: true
463
474
  };
464
475
  }
@@ -500,6 +511,10 @@
500
511
  status,
501
512
  detail: {
502
513
  command: item.command,
514
+ itemId: item.id,
515
+ threadId: event.detail?.params?.threadId,
516
+ turnId: event.detail?.params?.turnId,
517
+ commandActions: item.commandActions,
503
518
  output: item.aggregatedOutput,
504
519
  exitCode: item.exitCode
505
520
  }
@@ -723,6 +738,21 @@
723
738
  // failure data alongside the human-readable text. The string text is kept
724
739
  // verbatim because it has mode-aware nuance (e.g. "No files were written"
725
740
  // vs "This run did not start") the catalog's fallback strings don't capture.
741
+ if (context.code === 'codex_local_skill_unavailable' || /(?:The )?selected local Codex skill is unavailable/i.test(text)) {
742
+ return {
743
+ conclusion: textFor(locale, '所选 Codex 本地技能不可用或已关闭,本轮没有启动。', 'The selected local Codex skill is unavailable or disabled. This run did not start.'),
744
+ nextStep: textFor(locale, '请打开技能页,选择可用且已启用的技能后重新提交。', 'Open Skills, select an available enabled skill, and submit again.'),
745
+ failureCode: 'codex_local_skill_unavailable'
746
+ };
747
+ }
748
+ if (/^codex_local_skills_/.test(String(context.code || ''))
749
+ || /local Codex skill discovery|Codex could not (?:list local skills|start local skill discovery)|Codex returned an invalid local skill catalog/i.test(text)) {
750
+ return {
751
+ conclusion: textFor(locale, 'Codex 本地技能未能加载,本轮没有启动。', 'Local Codex skills could not be loaded. This run did not start.'),
752
+ nextStep: textFor(locale, '请打开技能页重新加载本地目录,然后重新提交。', 'Open Skills to reload the local catalog, then submit again.'),
753
+ failureCode: 'codex_local_skills_failed'
754
+ };
755
+ }
726
756
  const providerError = translateProviderError(text, locale);
727
757
  if (providerError) {
728
758
  return providerError;
@@ -863,6 +893,11 @@
863
893
  : textFor(locale, '本轮没有可撤销的写入', 'this run has no reversible writes');
864
894
  }
865
895
 
896
+ if (input.saveVerification && input.saveVerification.state !== 'not_checked') {
897
+ report.saveState = input.saveVerification.state === 'verified_saved'
898
+ ? textFor(locale, '已确认保存', 'Saved')
899
+ : textFor(locale, '待确认,可检查保存状态', 'Pending confirmation; check save status');
900
+ }
866
901
  const failed = input.status === 'failed' || input.status === 'blocked';
867
902
  return {
868
903
  title: textFor(locale, '本轮完成报告', 'Task report'),
@@ -946,6 +981,7 @@
946
981
  });
947
982
  }
948
983
 
984
+ if (report.saveState) meta.push({ key: 'saveState', label: textFor(locale, '保存', 'Save'), value: report.saveState });
949
985
  return { conclusion, body: bodySections.join('\n\n'), meta };
950
986
  }
951
987
 
@@ -976,6 +1012,7 @@
976
1012
  if (nextStep) {
977
1013
  sections.push(textFor(locale, `下一步:${nextStep}`, `Next: ${nextStep}`));
978
1014
  }
1015
+ if (report.saveState) sections.push(textFor(locale, `保存:${report.saveState}`, `Save: ${report.saveState}`));
979
1016
  return sections.join('\n\n');
980
1017
  }
981
1018
 
@@ -1045,7 +1082,7 @@
1045
1082
  if (input.mode === 'ask' || input.status === '只问不改') {
1046
1083
  return textFor(locale, '这轮是只问不改。', 'This run was Ask mode.');
1047
1084
  }
1048
- if (input.status === 'rejected') {
1085
+ if (input.status === 'cancelled' || input.status === 'rejected') {
1049
1086
  return textFor(locale, '你取消了这轮修改。', 'You cancelled this change.');
1050
1087
  }
1051
1088
  return '';