codex-overleaf-link 2.5.0 → 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 (168) hide show
  1. package/README.md +38 -26
  2. package/README.zh-CN.md +39 -27
  3. package/extension/bootstrap/background.js +52 -9
  4. package/extension/bootstrap/manifest.template.json +1 -1
  5. package/extension/bootstrap/popup.html +1 -0
  6. package/extension/bootstrap/popupFallback.js +55 -0
  7. package/extension/bootstrap/updateStatus.js +1 -0
  8. package/extension/src/background.js +206 -53
  9. package/extension/src/backgroundBootstrapMigration.js +181 -0
  10. package/extension/src/backgroundSharedSessions.js +74 -14
  11. package/extension/src/backgroundUpdateCoordinator.js +118 -21
  12. package/extension/src/backgroundUpdateSafety.js +173 -0
  13. package/extension/src/content/activeTurnControl.js +8 -2
  14. package/extension/src/content/applyResultFormatters.js +46 -73
  15. package/extension/src/content/assetTransferBroker.js +72 -14
  16. package/extension/src/content/composerAttachments.js +93 -45
  17. package/extension/src/content/composerPanel.js +18 -0
  18. package/extension/src/content/contentRuntime.js +661 -676
  19. package/extension/src/content/diagnosticsController.js +122 -96
  20. package/extension/src/content/diagnosticsExport.js +19 -5
  21. package/extension/src/content/diagnosticsPanel.js +30 -0
  22. package/extension/src/content/directoryCleanupRecovery.js +54 -0
  23. package/extension/src/content/generated/content.bundle.js +6879 -2786
  24. package/extension/src/content/generated/content.bundle.meta.json +11 -3
  25. package/extension/src/content/globalPreferencesController.js +1 -1
  26. package/extension/src/content/legacyGlobalRegistry.js +6 -0
  27. package/extension/src/content/localSkillsPanel.js +102 -12
  28. package/extension/src/content/markdownText.js +5 -6
  29. package/extension/src/content/modelPicker.js +7 -4
  30. package/extension/src/content/nativeCompatibilityController.js +45 -20
  31. package/extension/src/content/otWarmMirror.js +4 -5
  32. package/extension/src/content/otWarmMirrorController.js +17 -20
  33. package/extension/src/content/pageBridgeClient.js +15 -2
  34. package/extension/src/content/panelMaintenance.js +40 -12
  35. package/extension/src/content/panelRenderer.js +6 -0
  36. package/extension/src/content/projectProviderSelection.js +13 -4
  37. package/extension/src/content/projectSessionCleanup.js +109 -62
  38. package/extension/src/content/projectSettingsCoordinator.js +39 -2
  39. package/extension/src/content/providerSettingsCoordinator.js +46 -8
  40. package/extension/src/content/providerSettingsDialog.js +71 -13
  41. package/extension/src/content/recentProjects.js +11 -5
  42. package/extension/src/content/runActivitySummary.js +40 -6
  43. package/extension/src/content/runCompletionMeta.js +344 -0
  44. package/extension/src/content/runController.js +37 -14
  45. package/extension/src/content/runFailureNotice.js +21 -12
  46. package/extension/src/content/runGuidanceController.js +72 -27
  47. package/extension/src/content/runGuidanceView.js +59 -10
  48. package/extension/src/content/runQueueScheduler.js +148 -42
  49. package/extension/src/content/runRecoveryActions.js +146 -0
  50. package/extension/src/content/runResultActions.js +8 -125
  51. package/extension/src/content/runReviewController.js +574 -0
  52. package/extension/src/content/runScrollLayout.js +21 -2
  53. package/extension/src/content/runTimelineView.js +146 -153
  54. package/extension/src/content/scopedPersistencePanelState.js +51 -6
  55. package/extension/src/content/selectionContextView.js +1 -1
  56. package/extension/src/content/sensitivePreflight.js +140 -0
  57. package/extension/src/content/sessionForkController.js +80 -17
  58. package/extension/src/content/sessionManager.js +1 -1
  59. package/extension/src/content/settingsPanel.js +7 -3
  60. package/extension/src/content/settingsWorkbench.js +5 -0
  61. package/extension/src/content/sharedSessionViewSync.js +45 -8
  62. package/extension/src/content/updateIdle.js +4 -1
  63. package/extension/src/content/updateNotice.js +60 -8
  64. package/extension/src/content/updateSafetyReceiver.js +58 -0
  65. package/extension/src/content/writebackController.js +53 -4
  66. package/extension/src/content/writebackOrchestrator.js +82 -73
  67. package/extension/src/content/writingStyleSettings.js +35 -11
  68. package/extension/src/page/binaryAssetUploader.js +136 -14
  69. package/extension/src/page/fileMover.js +256 -0
  70. package/extension/src/page/ownedDirectoryCleanup.js +94 -0
  71. package/extension/src/page/referenceProjects.js +1 -0
  72. package/extension/src/page/reviewContext.js +113 -0
  73. package/extension/src/page/saveState.js +6 -4
  74. package/extension/src/page/snapshotRouter.js +84 -39
  75. package/extension/src/page/textFileCreator.js +105 -25
  76. package/extension/src/page/trackedChangeCapture.js +12 -2
  77. package/extension/src/page/trackedChangeOwnership.js +19 -1
  78. package/extension/src/page/trackedChangeReplay.js +41 -21
  79. package/extension/src/page/trackedChangesLifecycle.js +217 -199
  80. package/extension/src/page/treeOperations.js +7 -10
  81. package/extension/src/page/updateSafetyProbe.js +41 -0
  82. package/extension/src/page/writebackReceiptJournal.js +2 -0
  83. package/extension/src/page/writebackRouter.js +80 -79
  84. package/extension/src/pageBridge.js +19 -3
  85. package/extension/src/popup.js +62 -10
  86. package/extension/src/shared/agentTranscript.js +23 -0
  87. package/extension/src/shared/auditRecords.js +2 -0
  88. package/extension/src/shared/compatibility.js +22 -6
  89. package/extension/src/shared/compileAdapter.js +79 -57
  90. package/extension/src/shared/composerAttachmentDraft.js +151 -0
  91. package/extension/src/shared/directoryCleanupProof.js +43 -0
  92. package/extension/src/shared/failureReasons.js +309 -3
  93. package/extension/src/shared/globalPreferences.js +30 -13
  94. package/extension/src/shared/governanceRules.js +4 -37
  95. package/extension/src/shared/i18n.js +298 -2
  96. package/extension/src/shared/managedUpdateProjection.js +2 -2
  97. package/extension/src/shared/nativeRequestIdentity.js +1 -0
  98. package/extension/src/shared/pageRpcContract.js +5 -4
  99. package/extension/src/shared/projectFiles.js +21 -44
  100. package/extension/src/shared/providerProfiles.js +5 -3
  101. package/extension/src/shared/runInputQueue.js +48 -5
  102. package/extension/src/shared/selectionContext.js +12 -3
  103. package/extension/src/shared/sessionState.js +72 -27
  104. package/extension/src/shared/settlementFacts.js +10 -2
  105. package/extension/src/shared/sharedSessionBridge.js +37 -14
  106. package/extension/src/shared/sharedSessionTransfer.js +140 -0
  107. package/extension/src/shared/staleGuard.js +118 -13
  108. package/extension/src/shared/storageDb.js +58 -26
  109. package/extension/src/shared/storageMigration.js +71 -111
  110. package/extension/src/shared/storageRunActions.js +209 -26
  111. package/extension/src/shared/subagentActivityModel.js +1 -1
  112. package/extension/src/shared/undoOperations.js +136 -13
  113. package/extension/src/shared/updateConsent.js +6 -4
  114. package/extension/src/shared/updateRuntimeIdentity.js +1 -1
  115. package/extension/src/shared/writebackIntent.js +16 -0
  116. package/extension/src/shared/writebackOperationEvidence.js +4 -15
  117. package/extension/src/shared/writebackSettlement.js +38 -38
  118. package/extension/styles/panel.css +19 -5
  119. package/native-host/src/anthropicBridgeRequest.js +4 -2
  120. package/native-host/src/anthropicBridgeResponse.js +6 -2
  121. package/native-host/src/anthropicMessagesBridge.js +24 -16
  122. package/native-host/src/bootstrapMigration.js +296 -0
  123. package/native-host/src/bootstrapMigrationContract.js +101 -0
  124. package/native-host/src/bootstrapUpdate.js +233 -0
  125. package/native-host/src/bootstrapUpdateWatchdog.js +44 -0
  126. package/native-host/src/chatBridgeResponse.js +10 -0
  127. package/native-host/src/chatCompletionsBridge.js +21 -15
  128. package/native-host/src/codexConfigPaths.js +106 -0
  129. package/native-host/src/codexHome.js +66 -73
  130. package/native-host/src/codexHomeScope.js +124 -0
  131. package/native-host/src/codexInheritedAuth.js +90 -0
  132. package/native-host/src/codexLocalSkills.js +301 -0
  133. package/native-host/src/codexPromptAssembly.js +31 -12
  134. package/native-host/src/codexProviderTest.js +24 -26
  135. package/native-host/src/codexSessionRunner.js +110 -183
  136. package/native-host/src/codexSessionTiming.js +18 -8
  137. package/native-host/src/codexSkillIsolation.js +170 -0
  138. package/native-host/src/codexThreadFork.js +19 -3
  139. package/native-host/src/index.js +19 -7
  140. package/native-host/src/managedInstall.js +110 -35
  141. package/native-host/src/managedInstallRecovery.js +140 -0
  142. package/native-host/src/managedRuntimeEvidence.js +57 -0
  143. package/native-host/src/mirrorWorkspace.js +92 -22
  144. package/native-host/src/nativeDoctor.js +15 -0
  145. package/native-host/src/nativeHelperLifecycle.js +21 -0
  146. package/native-host/src/nativeHostRegistration.js +33 -0
  147. package/native-host/src/nativeRunLifecycle.js +71 -0
  148. package/native-host/src/processStopBarrier.js +42 -7
  149. package/native-host/src/projectPathPlatform.js +30 -0
  150. package/native-host/src/providerHttp.js +80 -0
  151. package/native-host/src/providerProfile.js +4 -2
  152. package/native-host/src/providerReasoning.js +2 -7
  153. package/native-host/src/providerRuntime.js +1 -0
  154. package/native-host/src/providerStore.js +72 -14
  155. package/native-host/src/responsesPassthroughBridge.js +266 -52
  156. package/native-host/src/runtimeInstaller.js +21 -1
  157. package/native-host/src/selectionScope.js +36 -8
  158. package/native-host/src/subagentAdmission.js +26 -0
  159. package/native-host/src/subagentBroker.js +79 -66
  160. package/native-host/src/subagentTelemetry.js +19 -10
  161. package/native-host/src/subagentWorkspacePath.js +5 -2
  162. package/native-host/src/taskRunnerRuntime.js +77 -54
  163. package/native-host/src/tomlStatements.js +140 -0
  164. package/native-host/src/updateManager.js +297 -39
  165. package/native-host/src/writingStyleRuntime.js +57 -29
  166. package/native-host/src/writingStyleStore.js +73 -0
  167. package/package.json +1 -1
  168. package/scripts/install-managed.mjs +1 -0
package/README.md CHANGED
@@ -2,16 +2,24 @@
2
2
  <img src="extension/assets/icons/codex-overleaf-icon.png" width="72" alt="Codex Overleaf Link">
3
3
  <h1>Codex Overleaf Link</h1>
4
4
  <p><strong>Empower Overleaf with Codex.</strong></p>
5
- <p><img src="https://img.shields.io/badge/version-2.5.0-blue" alt="version 2.5.0"></p>
5
+ <p><img src="https://img.shields.io/badge/version-2.5.1-blue" alt="version 2.5.1"></p>
6
6
  <p>English | <a href="README.zh-CN.md">简体中文</a></p>
7
7
  <p>Chrome · macOS / Windows / Linux · Local Codex</p>
8
+ <p>
9
+ <img src="https://img.shields.io/badge/platform-macOS%20%2F%20Windows%20%2F%20Linux-lightgrey" alt="platform">
10
+ <img src="https://img.shields.io/badge/chrome-MV3-green" alt="chrome manifest v3">
11
+ <img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen" alt="node version">
12
+ <a href="https://github.com/Ghqqqq/codex-overleaf-link/actions/workflows/test.yml"><img src="https://github.com/Ghqqqq/codex-overleaf-link/actions/workflows/test.yml/badge.svg" alt="tests"></a>
13
+ <img src="https://img.shields.io/badge/runtime%20dependencies-0-orange" alt="zero npm runtime dependencies">
14
+ <img src="https://img.shields.io/badge/license-MIT-blue" alt="license">
15
+ </p>
8
16
  </div>
9
17
 
10
18
  Ask about the project, revise a passage, and review the result beside the PDF. Codex Overleaf Link brings a local Codex workflow into the Overleaf editor, with project context, model selection, and conversations in one place.
11
19
 
12
20
  ![The source editor, PDF preview, and a real Codex project review in the Example paper demo](assets/readme/2.5.0/overview@2x.png)
13
21
 
14
- *Actual 2.5.0 interface. A read-only review of the standard Overleaf example project.*
22
+ *Interface captured on 2.5.0. A read-only review of the standard Overleaf example project.*
15
23
 
16
24
  <details>
17
25
  <summary>Read the conversation detail (native 2x PNG)</summary>
@@ -91,12 +99,14 @@ Connection shortcuts cover OpenAI-compatible and Anthropic-compatible APIs, Kimi
91
99
 
92
100
  > **Upgrading from an older version**
93
101
  >
94
- > **Versions earlier than 2.5.0 require a manual update to 2.5.0.** The in-extension **Update now** action cannot perform this upgrade. Run the installation command below, reload the extension in `chrome://extensions`, then refresh the Overleaf page.
102
+ > **Local candidate:** 2.5.1 is being tested and has not been published. For this checkout, use `npm run build:content` followed by `npm run install:managed`. The version-pinned npm and download commands below apply after publication. The compatible 2.5.0 → 2.5.1 update migration is implemented and awaiting complete acceptance; it is not yet available through the public update feed.
103
+
104
+ > **Versions earlier than 2.5.0 require a manual installation to move to the 2.5.x line.** The in-extension **Update now** action cannot perform this upgrade. Run the installation command below, reload the extension in `chrome://extensions`, then refresh the Overleaf page.
95
105
 
96
106
  **Prerequisites:** Chrome, Node.js 20+, and an installed, signed-in Codex CLI. Source installation also uses Git.
97
107
 
98
108
  ```bash
99
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
109
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
100
110
  ```
101
111
 
102
112
  1. Run the managed installer. It prints the extension directory.
@@ -150,14 +160,14 @@ Report the chosen release, installed Extension and Native Host versions, the bro
150
160
  macOS / Linux:
151
161
 
152
162
  ```bash
153
- CODEX_OVERLEAF_REF=v2.5.0 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.0/install.sh)"
163
+ CODEX_OVERLEAF_REF=v2.5.1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.1/install.sh)"
154
164
  ```
155
165
 
156
166
  Windows PowerShell:
157
167
 
158
168
  ```powershell
159
- iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.0/install.ps1 -OutFile install.ps1
160
- $env:CODEX_OVERLEAF_REF='v2.5.0'
169
+ iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.1/install.ps1 -OutFile install.ps1
170
+ $env:CODEX_OVERLEAF_REF='v2.5.1'
161
171
  powershell -ExecutionPolicy Bypass -File install.ps1
162
172
  ```
163
173
 
@@ -166,7 +176,7 @@ The script checks the prerequisites, builds the extension, installs the native h
166
176
  ### Option C: npm
167
177
 
168
178
  ```bash
169
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
179
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
170
180
  ```
171
181
 
172
182
  Same result as Option B, without keeping a source checkout around.
@@ -249,17 +259,19 @@ The choice applies to every session in the current project; other projects keep
249
259
 
250
260
  Managed installs check GitHub for new signed stable releases on their own. When one is available, choose **Update now** in the notice or under **Settings → Software updates**. The update waits until every Overleaf tab is saved and no task is running, replaces the extension and native host together, and restores the previous version if the new one fails its health check. Drafts and prereleases are never picked up, and an update never adds Chrome permissions silently.
251
261
 
262
+ The 2.5.1 candidate adds a compatible update from the published 2.5.0 installation through the same **Update now** action. Its signed package carries the startup-file fixes, retains recovery copies and progress, and reloads the extension before confirming the updated startup code. Bootstrap protocol 3 and existing Chrome permissions remain unchanged. This migration is still undergoing local acceptance; the candidate is unpublished.
263
+
252
264
  The updater respects HTTP(S) proxy environment variables and the macOS/Windows system proxy. SOCKS-only or PAC-only setups need an HTTP proxy endpoint.
253
265
 
254
266
  ### Coming from v2.4.x or earlier
255
267
 
256
- v2.5.0 adds `cn.overleaf.com` support, which needs a new Chrome permission, so it moves the install to Bootstrap protocol 3. Older updaters refuse that step by design rather than granting permissions themselves. **Update now will not work for this one release.** Run the installer once:
268
+ v2.5.0 adds `cn.overleaf.com` support, which needs a new Chrome permission, so it moves the install to Bootstrap protocol 3. Older updaters refuse that step by design rather than granting permissions themselves. **Installations older than 2.5.0 need the full installer for this migration.** Run the installer once:
257
269
 
258
270
  ```bash
259
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
271
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
260
272
  ```
261
273
 
262
- Then click **Reload** on the extension in `chrome://extensions` and refresh Overleaf. Your sessions, settings, provider keys and project mirrors are kept. Later releases update in place again.
274
+ Then click **Reload** on the extension in `chrome://extensions` and refresh Overleaf. Your sessions, settings, provider keys and project mirrors are kept. In-place updates require the target release to pass the Bootstrap compatibility checks.
263
275
 
264
276
  From v2.5.0 on, a release that ever needs another reinstall is announced in the panel as **Reinstall needed for this update**, with the reason, the exact command for that version, and a copy button, instead of a failed update. New Overleaf sites no longer need a reinstall at all: the extension popup asks you to allow the site, and Chrome confirms it.
265
277
 
@@ -269,14 +281,14 @@ Checkout and Release-zip installs are unmanaged and always update by hand.
269
281
 
270
282
  | Action | Command |
271
283
  |---|---|
272
- | Install, repair or migrate | `npm exec --yes codex-overleaf-link@2.5.0 -- install-managed` |
273
- | Diagnose | `npm exec --yes codex-overleaf-link@2.5.0 -- doctor` |
274
- | Uninstall | `npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-managed` |
284
+ | Install, repair or migrate | `npm exec --yes codex-overleaf-link@2.5.1 -- install-managed` |
285
+ | Diagnose | `npm exec --yes codex-overleaf-link@2.5.1 -- doctor` |
286
+ | Uninstall | `npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-managed` |
275
287
 
276
288
  npm installs, updates, and uninstalls the coordinated managed extension/native pair. The legacy `install-native` command remains available only for explicitly unmanaged extension directories:
277
289
 
278
290
  ```bash
279
- npm exec --yes codex-overleaf-link@2.5.0 -- install-native
291
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-native
280
292
  ```
281
293
 
282
294
  Use `--extension-id <chrome-extension-id>` only for a custom/dev unpacked extension id that differs from the official bundled id. On Linux Chromium, add `--browser chromium` to any of these.
@@ -286,13 +298,13 @@ Use `--extension-id <chrome-extension-id>` only for a custom/dev unpacked extens
286
298
  <summary><strong>Uninstall</strong></summary>
287
299
 
288
300
  ```bash
289
- npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-managed
301
+ npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-managed
290
302
  ```
291
303
 
292
304
  This works in PowerShell too, and also removes installs made by `install.sh` / `install.ps1`. For an unmanaged checkout or native-only install, run `npm run uninstall:native` from the checkout, or:
293
305
 
294
306
  ```bash
295
- npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-native
307
+ npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-native
296
308
  ```
297
309
 
298
310
  An older native-only source install can also be removed with its bundled uninstaller:
@@ -315,7 +327,7 @@ Uninstalling removes the native host registration, bridge, managed extension and
315
327
  Rerun the installer, reload the extension in `chrome://extensions`, then refresh Overleaf:
316
328
 
317
329
  ```bash
318
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
330
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
319
331
  ```
320
332
 
321
333
  For a checkout install, rebuild and rerun `npm run install:native` from the same checkout.
@@ -408,8 +420,8 @@ Chromium on macOS and Windows isn't supported yet. The extension runs on project
408
420
  Linux Chromium:
409
421
 
410
422
  ```bash
411
- CODEX_OVERLEAF_REF=v2.5.0 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.0/install.sh)" -- --browser chromium
412
- npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-managed --browser chromium
423
+ CODEX_OVERLEAF_REF=v2.5.1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.1/install.sh)" -- --browser chromium
424
+ npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-managed --browser chromium
413
425
  ```
414
426
 
415
427
  ## Extension ID
@@ -423,7 +435,7 @@ illdpneeeopfffmiepaejglgmhpmdhdc
423
435
  If you load a custom build and Chrome gives it a different id, reinstall with that id so the native host's `allowed_origins` matches:
424
436
 
425
437
  ```bash
426
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed --extension-id "<your-chrome-extension-id>"
438
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed --extension-id "<your-chrome-extension-id>"
427
439
  ```
428
440
 
429
441
  For an unmanaged extension, use `install-native --extension-id "<your-chrome-extension-id>"` instead. The source installers also read `CODEX_OVERLEAF_EXTENSION_ID`.
@@ -432,10 +444,10 @@ For an unmanaged extension, use `install-native --extension-id "<your-chrome-ext
432
444
 
433
445
  Each GitHub Release includes:
434
446
 
435
- - `codex-overleaf-link-extension-v2.5.0.zip`: the extension, for manual unpacked installation.
436
- - `codex-overleaf-native-host-v2.5.0.tar.gz`: the native host runtime used by the installers.
437
- - `codex-overleaf-update-v2.5.0.tar.gz`: the combined bundle the in-product updater downloads.
438
- - `codex-overleaf-link-2.5.0.tgz`: the npm package behind the `npm exec` commands.
447
+ - `codex-overleaf-link-extension-v2.5.1.zip`: the extension, for manual unpacked installation.
448
+ - `codex-overleaf-native-host-v2.5.1.tar.gz`: the native host runtime used by the installers.
449
+ - `codex-overleaf-update-v2.5.1.tar.gz`: the combined bundle the in-product updater downloads.
450
+ - `codex-overleaf-link-2.5.1.tgz`: the npm package behind the `npm exec` commands.
439
451
  - `install.sh` and `install.ps1`: installers pinned to this release.
440
452
  - `uninstall-native-host.mjs` plus its helpers `nativeHostPlatform.js`, `manifest.js` and `runtimeInstaller.js`.
441
453
  - `SHA256SUMS`, `release-manifest.json` and `release-manifest.sig`: checksums and the Ed25519-signed release metadata the updater verifies.
@@ -473,7 +485,7 @@ Native Messaging registration:
473
485
  | macOS Chrome | `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.codex.overleaf.json` |
474
486
  | Linux Chrome | `~/.config/google-chrome/NativeMessagingHosts/com.codex.overleaf.json` |
475
487
  | Linux Chromium | `~/.config/chromium/NativeMessagingHosts/com.codex.overleaf.json` |
476
- | Windows Chrome | `HKCU\Software\Google\Chrome\NativeMessagingHosts\com.codex.overleaf` → `%LOCALAPPDATA%\CodexOverleaf\native-host-runtime\com.codex.overleaf.json` |
488
+ | Windows Chrome | `HKCU\Software\Google\Chrome\NativeMessagingHosts\com.codex.overleaf` → `%LOCALAPPDATA%\codex-overleaf\native-messaging-hosts\com.codex.overleaf.json` |
477
489
 
478
490
  To remove everything:
479
491
 
package/README.zh-CN.md CHANGED
@@ -2,16 +2,24 @@
2
2
  <img src="extension/assets/icons/codex-overleaf-icon.png" width="72" alt="Codex Overleaf Link">
3
3
  <h1>Codex Overleaf Link</h1>
4
4
  <p><strong>Empower Overleaf with Codex.</strong></p>
5
- <p><img src="https://img.shields.io/badge/version-2.5.0-blue" alt="version 2.5.0"></p>
5
+ <p><img src="https://img.shields.io/badge/version-2.5.1-blue" alt="version 2.5.1"></p>
6
6
  <p><a href="README.md">English</a> | 简体中文</p>
7
7
  <p>Chrome · macOS / Windows / Linux · 本地 Codex</p>
8
+ <p>
9
+ <img src="https://img.shields.io/badge/platform-macOS%20%2F%20Windows%20%2F%20Linux-lightgrey" alt="支持平台">
10
+ <img src="https://img.shields.io/badge/chrome-MV3-green" alt="Chrome Manifest V3">
11
+ <img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen" alt="Node.js 版本要求">
12
+ <a href="https://github.com/Ghqqqq/codex-overleaf-link/actions/workflows/test.yml"><img src="https://github.com/Ghqqqq/codex-overleaf-link/actions/workflows/test.yml/badge.svg" alt="测试状态"></a>
13
+ <img src="https://img.shields.io/badge/runtime%20dependencies-0-orange" alt="无 npm 运行时依赖">
14
+ <img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT 许可证">
15
+ </p>
8
16
  </div>
9
17
 
10
18
  理解项目、修改段落、对照 PDF 查看结果。Codex Overleaf Link 把本地 Codex 工作流带进 Overleaf 编辑器,让项目上下文、模型选择和写作对话留在同一个工作区。
11
19
 
12
20
  ![Example paper 演示项目中的源码、PDF 和真实 Codex 项目导览](assets/readme/2.5.0/overview@2x.png)
13
21
 
14
- *2.5.0 当前界面实拍,展示对 Overleaf 默认示例项目的一次只读导览。*
22
+ *2.5.0 界面实拍,展示对 Overleaf 默认示例项目的一次只读导览。*
15
23
 
16
24
  <details>
17
25
  <summary>展开对话细节(原生 2× PNG)</summary>
@@ -91,12 +99,14 @@
91
99
 
92
100
  > **从旧版本升级**
93
101
  >
94
- > **2.5.0 之前的版本需要手动更新到 2.5.0。** 本次升级无法通过插件内的“立即更新”完成。运行下方安装命令后,在 `chrome://extensions` 中重新加载扩展,并刷新 Overleaf 页面。
102
+ > **本地候选版本:** 2.5.1 正在测试,尚未发布。当前源码可依次运行 `npm run build:content`、`npm run install:managed` 进行本机完整安装;下方固定版本的 npm 和下载命令在发布后适用。`2.5.0 → 2.5.1` 的兼容升级迁移已经实现,仍待完整验收,目前无法从公开更新源取得该候选版本。
103
+
104
+ > **2.5.0 之前的版本需要通过完整安装迁移到 2.5.x。** 本次升级无法通过插件内的“立即更新”完成。运行下方安装命令后,在 `chrome://extensions` 中重新加载扩展,并刷新 Overleaf 页面。
95
105
 
96
106
  **准备条件:** Chrome、Node.js 20+,以及已安装并登录的 Codex CLI。源码安装还需要 Git。
97
107
 
98
108
  ```bash
99
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
109
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
100
110
  ```
101
111
 
102
112
  1. 运行托管安装命令,取得安装器输出的扩展目录。
@@ -150,14 +160,14 @@ Report the chosen release, installed Extension and Native Host versions, the bro
150
160
  macOS / Linux:
151
161
 
152
162
  ```bash
153
- CODEX_OVERLEAF_REF=v2.5.0 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.0/install.sh)"
163
+ CODEX_OVERLEAF_REF=v2.5.1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.1/install.sh)"
154
164
  ```
155
165
 
156
166
  Windows PowerShell:
157
167
 
158
168
  ```powershell
159
- iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.0/install.ps1 -OutFile install.ps1
160
- $env:CODEX_OVERLEAF_REF='v2.5.0'
169
+ iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.1/install.ps1 -OutFile install.ps1
170
+ $env:CODEX_OVERLEAF_REF='v2.5.1'
161
171
  powershell -ExecutionPolicy Bypass -File install.ps1
162
172
  ```
163
173
 
@@ -166,7 +176,7 @@ powershell -ExecutionPolicy Bypass -File install.ps1
166
176
  ### 方式 C:npm
167
177
 
168
178
  ```bash
169
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
179
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
170
180
  ```
171
181
 
172
182
  效果和方式 B 一样,只是不用保留源码目录。
@@ -249,19 +259,21 @@ Auto 不会逐段等你确认,但删除文件、新建或替换图片和 PDF
249
259
 
250
260
  托管安装会自动去 GitHub 检查新的已签名正式版。有更新时,在提示里或 **设置 → 软件更新** 里点**立即更新**。更新会等所有 Overleaf 标签页都保存好、没有任务在跑时才开始,扩展和 native host 一起替换;新版本健康检查不通过会自动回到旧版本。草稿和预发布版本不会被选中,更新也不会悄悄增加 Chrome 权限。
251
261
 
262
+ 2.5.1 候选版本补充了从已发布 2.5.0 安装出发的兼容迁移,继续使用同一个**立即更新**入口。签名更新包携带启动文件修复,替换时保留恢复副本和进度,重载扩展并确认新版启动代码后才报告成功。Bootstrap 协议仍为3,Chrome 权限保持原有范围。这条迁移仍在本地验收,候选版本尚未发布。
263
+
252
264
  更新器会使用 HTTP(S) 代理环境变量以及 macOS/Windows 系统代理。只有 SOCKS 或 PAC 的环境需要提供一个 HTTP 代理地址。
253
265
 
254
266
  ### 从 v2.4.x 或更早版本升级
255
267
 
256
- v2.5.0 新增了 `cn.overleaf.com` 支持,需要一项新的 Chrome 权限,因此安装结构升级到了 Bootstrap 协议 3。旧版更新器按设计会拒绝这一步,而不是自己去加权限。**这一版没法通过“立即更新”升级**。请手动运行一次安装:
268
+ v2.5.0 新增了 `cn.overleaf.com` 支持,需要一项新的 Chrome 权限,因此安装结构升级到了 Bootstrap 协议 3。旧版更新器按设计会拒绝这一步,新增权限需通过完整安装取得。**早于 2.5.0 的安装需要通过完整安装完成这次迁移**。请手动运行一次安装:
257
269
 
258
270
  ```bash
259
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
271
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
260
272
  ```
261
273
 
262
- 然后在 `chrome://extensions` 里点扩展的**重新加载**,再刷新 Overleaf。会话、设置、模型服务的 key 和项目镜像都会保留。之后的版本又可以在插件里直接更新。
274
+ 然后在 `chrome://extensions` 里点扩展的**重新加载**,再刷新 Overleaf。会话、设置、模型服务的 key 和项目镜像都会保留。后续版本需通过 Bootstrap 兼容检查,才能支持插件内更新。
263
275
 
264
- 从 v2.5.0 起,如果以后某个版本又需要重新安装,面板会直接提示“这次更新需要重新安装”,写明原因,给出对应版本的命令和复制按钮,而不是显示更新失败。新增 Overleaf 站点也不再需要重装:扩展弹窗会请你允许访问该站点,Chrome 确认后即可使用。
276
+ 从 v2.5.0 起,如果以后某个版本又需要重新安装,面板会直接提示“这次更新需要重新安装”,写明原因,给出对应版本的命令和复制按钮。新增 Overleaf 站点也不再需要重装:扩展弹窗会请你允许访问该站点,Chrome 确认后即可使用。
265
277
 
266
278
  源码安装和 Release zip 安装不受托管,始终需要手动更新。
267
279
 
@@ -269,14 +281,14 @@ npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
269
281
 
270
282
  | 操作 | 命令 |
271
283
  |---|---|
272
- | 安装、修复或迁移 | `npm exec --yes codex-overleaf-link@2.5.0 -- install-managed` |
273
- | 诊断 | `npm exec --yes codex-overleaf-link@2.5.0 -- doctor` |
274
- | 卸载 | `npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-managed` |
284
+ | 安装、修复或迁移 | `npm exec --yes codex-overleaf-link@2.5.1 -- install-managed` |
285
+ | 诊断 | `npm exec --yes codex-overleaf-link@2.5.1 -- doctor` |
286
+ | 卸载 | `npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-managed` |
275
287
 
276
288
  npm 负责安装、更新和卸载配套的托管扩展与 native host。旧的 `install-native` 命令只用于明确不受托管的扩展目录:
277
289
 
278
290
  ```bash
279
- npm exec --yes codex-overleaf-link@2.5.0 -- install-native
291
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-native
280
292
  ```
281
293
 
282
294
  只有自定义或开发版扩展 id 与官方 id 不同时,才需要 `--extension-id <chrome-extension-id>`。Linux Chromium 请在以上命令后加 `--browser chromium`。
@@ -286,13 +298,13 @@ npm exec --yes codex-overleaf-link@2.5.0 -- install-native
286
298
  <summary><strong>卸载</strong></summary>
287
299
 
288
300
  ```bash
289
- npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-managed
301
+ npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-managed
290
302
  ```
291
303
 
292
304
  PowerShell 里同样可用,也能卸载 `install.sh` / `install.ps1` 装的版本。源码安装或只装了 native host 的情况,在源码目录里执行 `npm run uninstall:native`,或者:
293
305
 
294
306
  ```bash
295
- npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-native
307
+ npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-native
296
308
  ```
297
309
 
298
310
  旧的 native-only 源码安装也可以用它自带的卸载脚本:
@@ -315,7 +327,7 @@ node "$env:LOCALAPPDATA\CodexOverleaf\source\scripts\uninstall-native-host.mjs"
315
327
  重新运行安装器,在 `chrome://extensions` 里重新加载扩展,再刷新 Overleaf:
316
328
 
317
329
  ```bash
318
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed
330
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed
319
331
  ```
320
332
 
321
333
  源码安装请在同一个源码目录里重新构建,并重新执行 `npm run install:native`。
@@ -408,8 +420,8 @@ macOS 和 Windows 上的 Chromium 暂不支持。扩展在 `overleaf.com`、`www
408
420
  Linux Chromium:
409
421
 
410
422
  ```bash
411
- CODEX_OVERLEAF_REF=v2.5.0 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.0/install.sh)" -- --browser chromium
412
- npm exec --yes codex-overleaf-link@2.5.0 -- uninstall-managed --browser chromium
423
+ CODEX_OVERLEAF_REF=v2.5.1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v2.5.1/install.sh)" -- --browser chromium
424
+ npm exec --yes codex-overleaf-link@2.5.1 -- uninstall-managed --browser chromium
413
425
  ```
414
426
 
415
427
  ## 扩展 ID
@@ -423,7 +435,7 @@ illdpneeeopfffmiepaejglgmhpmdhdc
423
435
  如果你加载的是自己构建的版本,Chrome 给了不同的 id,就用那个 id 重新安装,让 native host 的 `allowed_origins` 对得上:
424
436
 
425
437
  ```bash
426
- npm exec --yes codex-overleaf-link@2.5.0 -- install-managed --extension-id "<your-chrome-extension-id>"
438
+ npm exec --yes codex-overleaf-link@2.5.1 -- install-managed --extension-id "<your-chrome-extension-id>"
427
439
  ```
428
440
 
429
441
  不受托管的扩展改用 `install-native --extension-id "<your-chrome-extension-id>"`。源码安装器也会读取 `CODEX_OVERLEAF_EXTENSION_ID` 环境变量。
@@ -432,10 +444,10 @@ npm exec --yes codex-overleaf-link@2.5.0 -- install-managed --extension-id "<you
432
444
 
433
445
  每个 GitHub Release 包含:
434
446
 
435
- - `codex-overleaf-link-extension-v2.5.0.zip`:扩展本体,用于手动加载。
436
- - `codex-overleaf-native-host-v2.5.0.tar.gz`:安装器使用的 native host 运行时。
437
- - `codex-overleaf-update-v2.5.0.tar.gz`:插件内更新下载的合并包。
438
- - `codex-overleaf-link-2.5.0.tgz`:`npm exec` 命令背后的 npm 包。
447
+ - `codex-overleaf-link-extension-v2.5.1.zip`:扩展本体,用于手动加载。
448
+ - `codex-overleaf-native-host-v2.5.1.tar.gz`:安装器使用的 native host 运行时。
449
+ - `codex-overleaf-update-v2.5.1.tar.gz`:插件内更新下载的合并包。
450
+ - `codex-overleaf-link-2.5.1.tgz`:`npm exec` 命令背后的 npm 包。
439
451
  - `install.sh` 和 `install.ps1`:固定到本版本的安装器。
440
452
  - `uninstall-native-host.mjs` 及其依赖 `nativeHostPlatform.js`、`manifest.js`、`runtimeInstaller.js`。
441
453
  - `SHA256SUMS`、`release-manifest.json` 和 `release-manifest.sig`:校验和,以及更新器会验证的 Ed25519 签名元数据。
@@ -473,7 +485,7 @@ Native Messaging 注册位置:
473
485
  | macOS Chrome | `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.codex.overleaf.json` |
474
486
  | Linux Chrome | `~/.config/google-chrome/NativeMessagingHosts/com.codex.overleaf.json` |
475
487
  | Linux Chromium | `~/.config/chromium/NativeMessagingHosts/com.codex.overleaf.json` |
476
- | Windows Chrome | `HKCU\Software\Google\Chrome\NativeMessagingHosts\com.codex.overleaf` → `%LOCALAPPDATA%\CodexOverleaf\native-host-runtime\com.codex.overleaf.json` |
488
+ | Windows Chrome | `HKCU\Software\Google\Chrome\NativeMessagingHosts\com.codex.overleaf` → `%LOCALAPPDATA%\codex-overleaf\native-messaging-hosts\com.codex.overleaf.json` |
477
489
 
478
490
  彻底删除:
479
491
 
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ globalThis.__CODEX_OVERLEAF_BOOTSTRAP_REVISION__ = '3.1';
4
+
3
5
  const CODEX_OVERLEAF_HOST = 'com.codex.overleaf';
4
6
  const RUNTIME_SCRIPT_ID = 'codex-overleaf-managed-runtime';
5
7
  const UPDATE_STATE_KEY = 'codex-overleaf-managed-update-state-v1';
@@ -75,7 +77,7 @@ chrome.alarms.onAlarm.addListener(alarm => {
75
77
  }
76
78
  });
77
79
 
78
- initializeBootstrap().catch(async error => {
80
+ globalThis.__CODEX_OVERLEAF_BOOTSTRAP_READY__ = initializeBootstrap().catch(async error => {
79
81
  await setUpdateState({ state: 'failed', code: safeCode(error), message: safeMessage(error) });
80
82
  });
81
83
 
@@ -91,6 +93,8 @@ async function initializeBootstrap() {
91
93
  return;
92
94
  }
93
95
 
96
+ const migration = await globalThis.CodexOverleafBootstrapMigration?.ready?.();
97
+ if (migration?.continueInitialization === false) return;
94
98
  const nativeStatus = await requestInternal({ method: 'update.status', params: {} }).catch(() => null);
95
99
  const transaction = nativeStatus?.ok ? nativeStatus.result?.transaction : null;
96
100
  if (transaction?.state === 'awaiting_health') {
@@ -381,12 +385,12 @@ async function confirmPendingUpdate(transaction) {
381
385
  const targetVersion = transaction.targetVersion;
382
386
  const runtimeHealthy = await verifyPendingRuntimeHealth(targetVersion);
383
387
  if (!runtimeHealthy) {
384
- await rollbackBrokenRuntime(new Error('Updated Overleaf content runtime did not report the target version.'));
388
+ await rollbackBrokenRuntime(new Error('Updated Overleaf content runtime did not report the target version.'), transaction);
385
389
  return;
386
390
  }
387
391
  const ping = await requestInternal({ method: 'bridge.ping', params: {} }).catch(() => null);
388
392
  if (!ping?.ok || ping.result?.version !== targetVersion) {
389
- await rollbackBrokenRuntime(new Error('Updated native host did not report the target version.'));
393
+ await rollbackBrokenRuntime(new Error('Updated native host did not report the target version.'), transaction);
390
394
  return;
391
395
  }
392
396
  const native = ping.result || {};
@@ -399,19 +403,20 @@ async function confirmPendingUpdate(transaction) {
399
403
  native.protocolVersion < protocolRange.min ||
400
404
  native.protocolVersion > protocolRange.max ||
401
405
  missingCapabilities.length) {
402
- await rollbackBrokenRuntime(new Error('Updated native host did not pass protocol and capability health checks.'));
406
+ await rollbackBrokenRuntime(new Error('Updated native host did not pass protocol and capability health checks.'), transaction);
403
407
  return;
404
408
  }
405
409
  const confirmed = await requestInternal({
406
410
  method: 'update.confirm',
407
411
  params: {
408
412
  transactionId: transaction.id,
413
+ bootstrapRevision: String(globalThis.__CODEX_OVERLEAF_BOOTSTRAP_REVISION__ || ''),
409
414
  extensionVersion: chrome.runtime.getManifest().version,
410
415
  nativeVersion: ping.result.version
411
416
  }
412
417
  });
413
418
  if (!confirmed?.ok) {
414
- await rollbackBrokenRuntime(nativeError(confirmed));
419
+ await rollbackBrokenRuntime(nativeError(confirmed), transaction);
415
420
  return;
416
421
  }
417
422
  await setUpdateState({
@@ -451,20 +456,56 @@ async function verifyPendingRuntimeHealth(targetVersion) {
451
456
  return remaining.size === 0;
452
457
  }
453
458
 
454
- async function rollbackBrokenRuntime(error) {
459
+ async function rollbackBrokenRuntime(error, transaction) {
455
460
  await setUpdateState({ state: 'rolling_back', code: safeCode(error), message: safeMessage(error) });
461
+ let pending = transaction;
462
+ let readback;
463
+ if (!pending) {
464
+ readback = await requestInternal({ method: 'update.status', params: {} }).catch(() => null);
465
+ pending = readback?.ok ? readback.result?.transaction : null;
466
+ }
467
+ // A status recovery may have completed an interrupted apply before this
468
+ // loader obtained its transaction. The same source-byte proof is required.
469
+ if (isRollbackReadback(readback, pending)) {
470
+ await setUpdateState({ state: 'rolled_back', code: safeCode(error), currentVersion: pending.sourceVersion, transactionId: pending.id });
471
+ chrome.runtime.reload();
472
+ return;
473
+ }
474
+ if (!pending?.id || !pending.sourceVersion || !['applying', 'bootstrap_pending', 'awaiting_health', 'committed'].includes(pending.state)) {
475
+ await setUpdateState({ state: 'failed', code: safeCode(error), message: safeMessage(error) });
476
+ return;
477
+ }
456
478
  const rolledBack = await requestInternal({
457
479
  method: 'update.rollback',
458
- params: { reasonCode: safeCode(error) }
480
+ params: { reasonCode: safeCode(error), transactionId: pending.id, expectedState: pending.state }
459
481
  }).catch(() => null);
460
- if (rolledBack?.ok) {
461
- await setUpdateState({ state: 'rolled_back', code: safeCode(error), currentVersion: rolledBack.result.version });
482
+ if (rolledBack?.ok && rolledBack.result?.transactionId === pending.id
483
+ && rolledBack.result?.state === 'rolled_back' && rolledBack.result?.version === pending.sourceVersion) {
484
+ readback = await requestInternal({ method: 'update.status', params: {} }).catch(() => null);
485
+ }
486
+ if (rolledBack?.result?.restoredPair && isRollbackReadback(readback, pending, rolledBack.result.restoredPair)) {
487
+ await setUpdateState({ state: 'rolled_back', code: safeCode(error), currentVersion: pending.sourceVersion, transactionId: pending.id });
462
488
  chrome.runtime.reload();
463
489
  return;
464
490
  }
465
491
  await setUpdateState({ state: 'failed', code: safeCode(error), message: safeMessage(error) });
466
492
  }
467
493
 
494
+ function isRollbackReadback(response, transaction, expectedPair) {
495
+ const status = response?.ok ? response.result : null;
496
+ const pair = status?.restoredPair;
497
+ return Boolean(transaction?.id && status?.transaction?.id === transaction.id
498
+ && status.transaction.state === 'rolled_back' && status.activeVersion === transaction.sourceVersion
499
+ && status.installedAligned === true && pair?.extensionVersion === transaction.sourceVersion
500
+ && pair?.nativeVersion === transaction.sourceVersion
501
+ && /^[0-9a-f]{64}$/.test(pair.extensionSha256 || '') && /^[0-9a-f]{64}$/.test(pair.nativeSha256 || '')
502
+ && (!(transaction.bootstrapRevision || status.transaction.bootstrapRevision || expectedPair?.bootstrapSha256)
503
+ || (/^[0-9a-f]{64}$/.test(pair.bootstrapSha256 || '')
504
+ && (!expectedPair || pair.bootstrapSha256 === expectedPair.bootstrapSha256)))
505
+ && (!expectedPair || ['extensionVersion', 'nativeVersion', 'extensionSha256', 'nativeSha256']
506
+ .every(key => pair[key] === expectedPair[key])));
507
+ }
508
+
468
509
  async function reloadPendingOverleafTabs() {
469
510
  const tabIds = await getPendingOverleafTabIds();
470
511
  await chrome.storage.local.remove(UPDATE_RELOAD_TABS_KEY);
@@ -485,6 +526,8 @@ async function postponeUpdate() {
485
526
  }
486
527
 
487
528
  async function requestInternal(payload) {
529
+ if (payload?.method === 'update.status') payload = { ...payload,
530
+ params: { ...payload.params, bootstrapRevision: String(globalThis.__CODEX_OVERLEAF_BOOTSTRAP_REVISION__ || '') } };
488
531
  if (globalThis.CodexOverleafNativeBridge?.requestInternal) {
489
532
  return globalThis.CodexOverleafNativeBridge.requestInternal({
490
533
  id: crypto.randomUUID(),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Codex Overleaf Link",
4
- "version": "2.5.0",
4
+ "version": "2.5.1",
5
5
  "description": "Connect the active Overleaf project to a local Codex bridge.",
6
6
  "icons": {
7
7
  "16": "assets/icons/icon16.png",
@@ -13,6 +13,7 @@
13
13
  <main id="popup-shell" data-bootstrap-shell>
14
14
  <p class="popup-note">Codex Overleaf Link could not load its runtime. Rerun the installer, then reload the extension.</p>
15
15
  </main>
16
+ <script src="popupFallback.js"></script>
16
17
  <script src="../runtime/src/shared/compatibility.js"></script>
17
18
  <script src="../runtime/src/popup.js"></script>
18
19
  <script src="updateStatus.js"></script>
@@ -0,0 +1,55 @@
1
+ (function localizePopupFallback() {
2
+ 'use strict';
3
+
4
+ const preferenceKeys = ['codexOverleafGlobalPrefsV1', 'codexOverleafPrefs'];
5
+ let revision = 0;
6
+ let recoveryReloaded = false;
7
+
8
+ async function refreshFallback() {
9
+ const requestRevision = ++revision;
10
+ let preferences = {};
11
+ try {
12
+ const stored = await chrome.storage.local.get(preferenceKeys);
13
+ preferences = stored.codexOverleafGlobalPrefsV1?.values || stored.codexOverleafPrefs || {};
14
+ } catch (_) { /* A missing language preference uses the product default. */ }
15
+ if (requestRevision !== revision) return;
16
+ const shell = document.querySelector('[data-bootstrap-shell]');
17
+ const message = shell?.querySelector('p');
18
+ // The healthy runtime replaces this shell. Late preference reads must
19
+ // never change the runtime's content or its current language.
20
+ if (!message) return;
21
+ const chinese = preferences.locale === 'zh';
22
+ document.documentElement.lang = chinese ? 'zh-CN' : 'en';
23
+ message.textContent = chinese
24
+ ? 'Codex Overleaf Link 无法加载运行组件。请重新运行安装程序,再重新加载扩展。'
25
+ : 'Codex Overleaf Link could not load its runtime. Rerun the installer, then reload the extension.';
26
+ }
27
+
28
+ chrome.storage.onChanged.addListener((changes, area) => {
29
+ if (area === 'local' && preferenceKeys.some(key => changes[key])) refreshFallback();
30
+ });
31
+ refreshFallback();
32
+
33
+ // This independent extension page can still start when the worker/runtime
34
+ // cannot. Native decides whether a persisted migration needs recovery; the
35
+ // popup never guesses a transaction or sends an unbound rollback request.
36
+ document.addEventListener?.('DOMContentLoaded', () => {
37
+ setTimeout(() => {
38
+ if (!document.querySelector('[data-bootstrap-shell]') || !chrome.runtime?.sendNativeMessage) return;
39
+ chrome.runtime.sendNativeMessage('com.codex.overleaf', {
40
+ id: crypto.randomUUID(), method: 'update.status', params: { bootstrapRecovery: true }
41
+ }, response => {
42
+ if (chrome.runtime.lastError || recoveryReloaded || !document.querySelector('[data-bootstrap-shell]')) return;
43
+ const status = response?.ok ? response.result : null;
44
+ const transaction = status?.transaction;
45
+ const pair = status?.restoredPair;
46
+ if (!transaction?.id || transaction.state !== 'rolled_back' || !transaction.sourceVersion
47
+ || status.activeVersion !== transaction.sourceVersion || status.installedAligned !== true
48
+ || pair?.extensionVersion !== transaction.sourceVersion || pair?.nativeVersion !== transaction.sourceVersion
49
+ || !['extensionSha256', 'nativeSha256', 'bootstrapSha256'].every(key => /^[0-9a-f]{64}$/.test(pair[key] || ''))) return;
50
+ recoveryReloaded = true;
51
+ chrome.runtime.reload();
52
+ });
53
+ }, 250);
54
+ }, { once: true });
55
+ })();
@@ -17,6 +17,7 @@
17
17
  tab_not_idle: 'An Overleaf tab is still busy.',
18
18
  native_project_locked: 'The native host still holds a project lock.',
19
19
  native_run_active: 'The native host is still processing a Codex run.',
20
+ native_process_stop_unconfirmed: 'A previous Codex process has not yet confirmed its exit.',
20
21
  native_gate_unavailable: 'The native host could not report whether it is idle.',
21
22
  native_not_idle: 'The native host is still busy.',
22
23
  busy: 'An update safety check is still busy.'