codex-overleaf-link 1.3.0 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -146
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/i18n.js +36 -18
- package/extension/src/shared/lineReferences.js +4 -6
- package/extension/src/shared/sessionState.js +20 -0
- package/extension/src/shared/storageDb.js +21 -1
- package/native-host/src/codexHome.js +83 -7
- package/native-host/src/codexSessionRunner.js +3 -0
- package/native-host/src/localSkills.js +46 -7
- package/native-host/src/skills/annotated-rewrite/SKILL.md +71 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<h1>Codex Overleaf Link</h1>
|
|
4
4
|
<p><strong>Empower Overleaf with Codex.</strong></p>
|
|
5
5
|
<p>
|
|
6
|
-
<img src="https://img.shields.io/badge/version-1.3.
|
|
6
|
+
<img src="https://img.shields.io/badge/version-1.3.5-blue" alt="version">
|
|
7
7
|
<img src="https://img.shields.io/badge/platform-macOS%20%2F%20Windows%20%2F%20Linux-lightgrey" alt="platform">
|
|
8
8
|
<img src="https://img.shields.io/badge/chrome-MV3-green" alt="chrome manifest v3">
|
|
9
9
|
<img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen" alt="node version">
|
|
@@ -21,136 +21,89 @@ Overleaf is great for collaborative LaTeX writing. Codex is great for AI-assiste
|
|
|
21
21
|
|
|
22
22
|
Codex Overleaf Link bridges the two: it adds a Codex panel directly inside Overleaf, mirrors the project locally for Codex to work on, and writes accepted changes back through the browser — with stale-write guards, diff review, and undo checkpoints to reduce the risk of accidental overwrites.
|
|
23
23
|
|
|
24
|
-
## Preview
|
|
25
|
-
|
|
26
24
|
<p align="center">
|
|
27
25
|
<img src="assets/codex-preview.png" alt="Codex Overleaf Link running inside Overleaf">
|
|
28
26
|
</p>
|
|
29
27
|
|
|
30
28
|
## Install
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
1. Install or update the native host with the pinned npm package:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npm exec --yes codex-overleaf-link@1.3.0 -- install-native
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
2. Download `codex-overleaf-link-extension-v1.3.0.zip` from the [v1.3.0 GitHub Release](https://github.com/Ghqqqq/codex-overleaf-link/releases/tag/v1.3.0), then unzip it to a stable local folder.
|
|
30
|
+
Codex Overleaf Link has two pieces, installed separately:
|
|
41
31
|
|
|
42
|
-
|
|
32
|
+
- **Native host** — installed and updated with the pinned npm package. npm installs, updates, uninstalls, and diagnoses the native host *only*; it never installs the Chrome extension.
|
|
33
|
+
- **Chrome extension** — loaded manually as an unpacked extension from the GitHub Release zip (or a source checkout). The bundled extension key gives the official build a stable id, so normal installs do not need `--extension-id`.
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
If you modify the extension key or load a custom build that gets a different id, rerun the native install with `--extension-id <chrome-extension-id>`.
|
|
47
|
-
|
|
48
|
-
Source installer fallback for macOS / Linux, mainly for development or source checkout installs:
|
|
35
|
+
**1. Install or update the native host:**
|
|
49
36
|
|
|
50
37
|
```bash
|
|
51
|
-
|
|
38
|
+
npm exec --yes codex-overleaf-link@1.3.5 -- install-native
|
|
52
39
|
```
|
|
53
40
|
|
|
54
|
-
|
|
41
|
+
**2. Load the extension:** Download `codex-overleaf-link-extension-v1.3.5.zip` from the [v1.3.5 GitHub Release](https://github.com/Ghqqqq/codex-overleaf-link/releases/tag/v1.3.5) and unzip it to a stable local folder. In `chrome://extensions`, enable **Developer mode**, click **Load unpacked**, and select that folder.
|
|
55
42
|
|
|
56
|
-
|
|
57
|
-
iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.0/install.ps1 -OutFile install.ps1
|
|
58
|
-
$env:CODEX_OVERLEAF_REF='v1.3.0'
|
|
59
|
-
powershell -ExecutionPolicy Bypass -File install.ps1
|
|
60
|
-
```
|
|
43
|
+
**3. Open any Overleaf project.** The Codex panel appears on the right; confirm the native host is connected from the panel diagnostics.
|
|
61
44
|
|
|
62
|
-
|
|
45
|
+
Start in Ask mode; switch to Suggest mode for reviewed edits, or Auto mode once project governance and checkpoint settings are ready for direct writeback.
|
|
63
46
|
|
|
64
|
-
|
|
47
|
+
If Chrome assigns a custom build a different id, rerun the native install with `--extension-id <chrome-extension-id>` so the native manifest `allowed_origins` entry matches.
|
|
65
48
|
|
|
66
|
-
|
|
49
|
+
### Source installer fallback
|
|
67
50
|
|
|
68
|
-
|
|
69
|
-
npm exec --yes codex-overleaf-link@1.3.0 -- install-native
|
|
70
|
-
```
|
|
51
|
+
If npm is unavailable, use the release-pinned script for your platform. These also serve development and source-checkout installs.
|
|
71
52
|
|
|
72
|
-
|
|
53
|
+
macOS / Linux:
|
|
73
54
|
|
|
74
55
|
```bash
|
|
75
|
-
|
|
56
|
+
CODEX_OVERLEAF_REF=v1.3.5 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.5/install.sh)"
|
|
76
57
|
```
|
|
77
58
|
|
|
78
|
-
|
|
59
|
+
Windows PowerShell:
|
|
79
60
|
|
|
80
|
-
```
|
|
81
|
-
|
|
61
|
+
```powershell
|
|
62
|
+
iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.5/install.ps1 -OutFile install.ps1
|
|
63
|
+
$env:CODEX_OVERLEAF_REF='v1.3.5'
|
|
64
|
+
powershell -ExecutionPolicy Bypass -File install.ps1
|
|
82
65
|
```
|
|
83
66
|
|
|
84
|
-
Use `--extension-id <chrome-extension-id>` only for a custom/dev unpacked extension id that differs from the official bundled id.
|
|
85
|
-
|
|
86
|
-
Open any Overleaf project - the Codex panel appears on the right.
|
|
87
|
-
|
|
88
|
-
## Quick Start
|
|
89
|
-
|
|
90
|
-
1. Install or update the native host with the version-pinned npm command, or use the GitHub Release script fallback for your platform.
|
|
91
|
-
2. In `chrome://extensions`, enable Developer mode, load or reload the unpacked extension folder, and confirm the native host is connected from the panel diagnostics.
|
|
92
|
-
3. Open an Overleaf project and start in Ask mode; switch to Suggest mode when you want Codex to propose reviewed edits, or Auto mode when the project governance and checkpoint settings are ready for direct writeback.
|
|
93
|
-
|
|
94
|
-
<p align="center">
|
|
95
|
-
<img src="assets/codex-preview.png" alt="Codex Overleaf Link panel inside Overleaf">
|
|
96
|
-
</p>
|
|
97
|
-
|
|
98
67
|
<details>
|
|
99
|
-
<summary><strong>Manual install</strong> (
|
|
68
|
+
<summary><strong>Manual checkout install</strong> (custom location)</summary>
|
|
100
69
|
|
|
101
70
|
```bash
|
|
102
71
|
git clone https://github.com/Ghqqqq/codex-overleaf-link.git
|
|
103
72
|
cd codex-overleaf-link
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Then load `extension/` as an unpacked extension in Chrome and register the native host:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
73
|
npm run install:native
|
|
110
74
|
```
|
|
111
75
|
|
|
112
|
-
If Chrome assigns a different extension id, rerun `npm run install:native -- --extension-id <chrome-extension-id>`.
|
|
76
|
+
Then load `extension/` as an unpacked extension in Chrome. If Chrome assigns a different extension id, rerun `npm run install:native -- --extension-id <chrome-extension-id>`.
|
|
113
77
|
|
|
114
78
|
</details>
|
|
115
79
|
|
|
116
|
-
|
|
117
|
-
<summary><strong>Update</strong></summary>
|
|
118
|
-
|
|
119
|
-
For a deterministic v1.3.0 update, run the pinned npm command. This is also the native mismatch recovery command shown by the popup and panel when they report **Native host update required**.
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
npm exec --yes codex-overleaf-link@1.3.0 -- install-native
|
|
123
|
-
```
|
|
80
|
+
## npm Native Host CLI
|
|
124
81
|
|
|
125
|
-
|
|
82
|
+
npm installs, updates, uninstalls, and diagnoses the native host only. npm does not install the Chrome extension; install the Chrome extension separately from the release source checkout or extension zip.
|
|
126
83
|
|
|
127
|
-
|
|
84
|
+
| Action | Command |
|
|
85
|
+
|--------|---------|
|
|
86
|
+
| Install / update | `npm exec --yes codex-overleaf-link@1.3.5 -- install-native` |
|
|
87
|
+
| Diagnose | `npm exec --yes codex-overleaf-link@1.3.5 -- doctor` |
|
|
88
|
+
| Uninstall | `npm exec --yes codex-overleaf-link@1.3.5 -- uninstall-native` |
|
|
128
89
|
|
|
129
|
-
|
|
130
|
-
CODEX_OVERLEAF_REF=v1.3.0 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.0/install.sh)"
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Windows PowerShell:
|
|
90
|
+
Use `--extension-id <chrome-extension-id>` only for a custom/dev unpacked extension id that differs from the official bundled id.
|
|
134
91
|
|
|
135
|
-
|
|
136
|
-
iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.0/install.ps1 -OutFile install.ps1
|
|
137
|
-
$env:CODEX_OVERLEAF_REF='v1.3.0'
|
|
138
|
-
powershell -ExecutionPolicy Bypass -File install.ps1
|
|
139
|
-
```
|
|
92
|
+
## Update
|
|
140
93
|
|
|
141
|
-
|
|
94
|
+
For a deterministic v1.3.5 update, run the pinned npm install command above. This is also the native mismatch recovery command shown by the popup and panel when they report **Native host update required** — it fixes extension/native version mismatch and native protocol mismatch.
|
|
142
95
|
|
|
143
|
-
|
|
96
|
+
If npm is unavailable, run the [source installer fallback](#source-installer-fallback) for your platform. After updating, reload the extension in `chrome://extensions` and refresh the Overleaf page.
|
|
144
97
|
|
|
145
98
|
## GitHub Release Artifacts
|
|
146
99
|
|
|
147
|
-
The v1.3.
|
|
100
|
+
The v1.3.5 GitHub Release contains:
|
|
148
101
|
|
|
149
|
-
- `codex-overleaf-link-extension-v1.3.
|
|
150
|
-
- `codex-overleaf-native-host-v1.3.
|
|
151
|
-
- `codex-overleaf-link-1.3.
|
|
152
|
-
- `install.sh`: release-pinned macOS / Linux installer that defaults to `v1.3.
|
|
153
|
-
- `install.ps1`: release-pinned Windows PowerShell installer that defaults to `v1.3.
|
|
102
|
+
- `codex-overleaf-link-extension-v1.3.5.zip`: loadable Chrome extension package for manual unpacked installation.
|
|
103
|
+
- `codex-overleaf-native-host-v1.3.5.tar.gz`: native host runtime files used by the installer and release verification.
|
|
104
|
+
- `codex-overleaf-link-1.3.5.tgz`: npm native host CLI package for pinned install, doctor, and uninstall flows.
|
|
105
|
+
- `install.sh`: release-pinned macOS / Linux installer that defaults to `v1.3.5` when run directly from the release artifact.
|
|
106
|
+
- `install.ps1`: release-pinned Windows PowerShell installer that defaults to `v1.3.5` when run directly from the release artifact.
|
|
154
107
|
- `uninstall-native-host.mjs`: native host uninstaller that removes the Chrome Native Messaging manifest, bridge executable, and runtime copy.
|
|
155
108
|
- `nativeHostPlatform.js`, `manifest.js`, `runtimeInstaller.js`: helper files required by the loose uninstaller asset.
|
|
156
109
|
- `SHA256SUMS` and `release-manifest.json`: checksum and artifact metadata for release verification.
|
|
@@ -158,23 +111,17 @@ The v1.3.0 GitHub Release contains:
|
|
|
158
111
|
<details>
|
|
159
112
|
<summary><strong>Uninstall</strong></summary>
|
|
160
113
|
|
|
161
|
-
|
|
114
|
+
Remove the native host (use `--browser chromium` on Linux Chromium):
|
|
162
115
|
|
|
163
116
|
```bash
|
|
164
|
-
npm exec --yes codex-overleaf-link@1.3.
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Windows PowerShell:
|
|
168
|
-
|
|
169
|
-
```powershell
|
|
170
|
-
npm exec --yes codex-overleaf-link@1.3.0 -- uninstall-native
|
|
117
|
+
npm exec --yes codex-overleaf-link@1.3.5 -- uninstall-native
|
|
171
118
|
```
|
|
172
119
|
|
|
173
|
-
If you installed from a manual checkout or source installer, you can also run `npm run uninstall:native` inside the repo, use `node ~/.codex-overleaf/source/scripts/uninstall-native-host.mjs` on macOS / Linux, or use `node $env:LOCALAPPDATA\CodexOverleaf\source\scripts\uninstall-native-host.mjs` on Windows PowerShell.
|
|
120
|
+
The same command works on Windows PowerShell. If you installed from a manual checkout or source installer, you can also run `npm run uninstall:native` inside the repo, use `node ~/.codex-overleaf/source/scripts/uninstall-native-host.mjs` on macOS / Linux, or use `node $env:LOCALAPPDATA\CodexOverleaf\source\scripts\uninstall-native-host.mjs` on Windows PowerShell.
|
|
174
121
|
|
|
175
|
-
|
|
122
|
+
The uninstaller removes the Native Messaging registration, bridge executable, and native runtime copy. It does not remove browser IndexedDB, `chrome.storage.local`, project mirrors, plugin Codex history, or project/plugin skills.
|
|
176
123
|
|
|
177
|
-
|
|
124
|
+
Then remove the extension from `chrome://extensions`. To delete local data: on macOS / Linux, delete `~/.codex-overleaf`. On Windows, `%LOCALAPPDATA%\CodexOverleaf` holds the native source, runtime, bridge, and native log, while `%USERPROFILE%\.codex-overleaf` holds project mirrors, plugin Codex home/history, and Codex Overleaf skills — full Windows cleanup requires deleting both roots. See [Local Data And Cleanup](#local-data-and-cleanup) for full deletion steps.
|
|
178
125
|
|
|
179
126
|
</details>
|
|
180
127
|
|
|
@@ -202,13 +149,13 @@ The uninstaller removes the Native Messaging registration, bridge executable, an
|
|
|
202
149
|
Linux Chromium install or update:
|
|
203
150
|
|
|
204
151
|
```bash
|
|
205
|
-
CODEX_OVERLEAF_REF=v1.3.
|
|
152
|
+
CODEX_OVERLEAF_REF=v1.3.5 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.5/install.sh)" -- --browser chromium
|
|
206
153
|
```
|
|
207
154
|
|
|
208
155
|
Linux Chromium uninstall:
|
|
209
156
|
|
|
210
157
|
```bash
|
|
211
|
-
npm exec --yes codex-overleaf-link@1.3.
|
|
158
|
+
npm exec --yes codex-overleaf-link@1.3.5 -- uninstall-native --browser chromium
|
|
212
159
|
```
|
|
213
160
|
|
|
214
161
|
## Features
|
|
@@ -222,22 +169,20 @@ npm exec --yes codex-overleaf-link@1.3.0 -- uninstall-native --browser chromium
|
|
|
222
169
|
- **Auto-recompile** — triggers Overleaf recompile after writeback; logs compile errors as context.
|
|
223
170
|
- **@ context** — attach specific files, `@compile-log`, or `@current-section` to the prompt.
|
|
224
171
|
- **Composer attachments and binary writeback** — paste or drop PDFs, images, and files into the composer as turn-scoped Codex context, and review Codex-created assets before creating or replacing them in Overleaf.
|
|
225
|
-
- **Codex Overleaf skills** — install reusable plugin-scoped skills through the slash menu, then let Codex auto-trigger them or select one explicitly for the next turn.
|
|
172
|
+
- **Codex Overleaf skills** — install reusable plugin-scoped skills through the slash menu, then let Codex auto-trigger them or select one explicitly for the next turn. Each skill has its own enable toggle, honored at run time.
|
|
226
173
|
- **Governance rules** — configure project read-only and writable path rules that block unsafe writeback before browser mutation.
|
|
227
174
|
- **Sensitive preflight** — scan selected project context for likely secrets before sending it to Codex.
|
|
228
175
|
- **Audit and diagnostics** — keep local run records and export redacted diagnostic bundles for issue reports.
|
|
229
176
|
- **Model picker** — discover available Codex models locally, then switch model, reasoning effort, and speed from one compact control.
|
|
230
177
|
- **Session history** — multi-session management with rename, resume, and delete.
|
|
231
|
-
- **Isolated Codex home** — plugin sessions
|
|
232
|
-
- **Experimental OT warm mirror**
|
|
233
|
-
|
|
234
|
-
> Note: The OT warm mirror is experimental, off by default, and never writes back to Overleaf through realtime collaboration channels.
|
|
178
|
+
- **Isolated Codex home** — plugin sessions run under `~/.codex-overleaf/codex-home` (not global `~/.codex/sessions`) and do not inherit your global Codex personalization.
|
|
179
|
+
- **Experimental OT warm mirror** — optional read-only observation of active Overleaf text edits to keep focused local mirror files warm. Falls back to full snapshots when unavailable or inconsistent. Off by default; it never writes back to Overleaf through realtime collaboration channels.
|
|
235
180
|
|
|
236
181
|
## Common Workflows
|
|
237
182
|
|
|
238
|
-
- **Fix a compile error**
|
|
239
|
-
- **Rewrite a paragraph**
|
|
240
|
-
- **Translate a section**
|
|
183
|
+
- **Fix a compile error** — choose Suggest mode, attach `@compile-log`, ask Codex to diagnose and patch the failing file, review the diff, apply it, then recompile from the panel.
|
|
184
|
+
- **Rewrite a paragraph** — select the target file or `@current-section`, ask for a tone or clarity rewrite in Suggest mode, review the text diff, and accept only the hunks you want.
|
|
185
|
+
- **Translate a section** — attach the source section with `@file` or `@current-section`, specify the target language and terminology constraints, then review the proposed replacement before writeback.
|
|
241
186
|
|
|
242
187
|
## How It Works
|
|
243
188
|
|
|
@@ -278,16 +223,12 @@ This repo ships a stable Chrome extension `key`, producing the deterministic id:
|
|
|
278
223
|
illdpneeeopfffmiepaejglgmhpmdhdc
|
|
279
224
|
```
|
|
280
225
|
|
|
281
|
-
The installer uses this id by default. If Chrome assigns a different id, reinstall the native host with the actual id
|
|
282
|
-
|
|
283
|
-
macOS / Linux:
|
|
226
|
+
The installer uses this id by default. If Chrome assigns a different id, reinstall the native host with the actual id:
|
|
284
227
|
|
|
285
228
|
```bash
|
|
286
229
|
cd ~/.codex-overleaf/source && npm run install:native -- --extension-id <your-chrome-extension-id>
|
|
287
230
|
```
|
|
288
231
|
|
|
289
|
-
Windows PowerShell:
|
|
290
|
-
|
|
291
232
|
```powershell
|
|
292
233
|
cd $env:LOCALAPPDATA\CodexOverleaf\source
|
|
293
234
|
npm run install:native -- --extension-id <your-chrome-extension-id>
|
|
@@ -308,7 +249,7 @@ Codex Overleaf Link does not use a hosted backend or default telemetry. Data is
|
|
|
308
249
|
| macOS/Linux bridge | `~/.codex-overleaf/codex-overleaf-bridge` | Native Messaging launcher executable. |
|
|
309
250
|
| Windows source/runtime/bridge | `%LOCALAPPDATA%\CodexOverleaf` | `source`, `native-host-runtime`, `codex-overleaf-bridge.cmd`, and native debug log. |
|
|
310
251
|
| Project mirrors | `~/.codex-overleaf/projects` on macOS/Linux, `%USERPROFILE%\.codex-overleaf\projects` on Windows | Local mirror workspaces and mirror metadata for each Overleaf project. |
|
|
311
|
-
| Plugin Codex home | `~/.codex-overleaf/codex-home` on macOS/Linux, `%USERPROFILE%\.codex-overleaf\codex-home` on Windows | Isolated Codex home for plugin runs. It copies auth/config metadata but does not reuse global Codex sessions. |
|
|
252
|
+
| Plugin Codex home | `~/.codex-overleaf/codex-home` on macOS/Linux, `%USERPROFILE%\.codex-overleaf\codex-home` on Windows | Isolated Codex home for plugin runs. It copies auth/config metadata but does not reuse global Codex sessions or inherit global Codex personalization. |
|
|
312
253
|
| Codex Overleaf skills | `~/.codex-overleaf/skills` on macOS/Linux, `%USERPROFILE%\.codex-overleaf\skills` on Windows | Project/plugin skills managed by the extension. |
|
|
313
254
|
| Native logs | `~/.codex-overleaf/native-host.log` on macOS/Linux, `%LOCALAPPDATA%\CodexOverleaf\native-host.log` on Windows | Native debug events with content length summaries where possible. |
|
|
314
255
|
| Launcher logs | `~/.codex-overleaf/native-host-launcher.log` on macOS/Linux | POSIX launcher startup path and Node diagnostics. The Windows `.cmd` launcher does not currently emit a separate launcher log. |
|
|
@@ -318,6 +259,8 @@ Skill loading toggles default to enabled. In Project Settings:
|
|
|
318
259
|
- `Load local Codex skills` loads the user's local Codex skill environment from the global Codex home into the isolated `~/.codex-overleaf/codex-home`: `~/.codex/skills`, local Codex `plugins`, `superpowers`, and related skill/plugin configuration. Turning it off hides user/system Codex skills and local Codex plugins from Codex Overleaf runs. This affects only the plugin CODEX_HOME prepared for the run; it does not write to or reuse global `~/.codex/sessions`.
|
|
319
260
|
- `Load Codex Overleaf skills` loads project/plugin skills managed by the extension from `~/.codex-overleaf/skills` on macOS/Linux or `%USERPROFILE%\.codex-overleaf\skills` on Windows into the same isolated Codex home. Turning it off hides those extension-managed skills while preserving the stored skill files. If both toggles are off, the run starts without local Codex skills or Codex Overleaf skills.
|
|
320
261
|
|
|
262
|
+
The isolated plugin Codex home copies auth and config metadata but excludes global Codex personalization: it does not copy `~/.codex/AGENTS.md`, strips the top-level `personality` key from the copied `config.toml`, and does not link the global `rules` or `memories` directories.
|
|
263
|
+
|
|
321
264
|
Native registration paths:
|
|
322
265
|
|
|
323
266
|
| Platform/browser | Registration path |
|
|
@@ -341,31 +284,15 @@ Composer attachments are turn-scoped Codex context. Limits are 8 attachments per
|
|
|
341
284
|
|
|
342
285
|
**Native host missing or update required**
|
|
343
286
|
|
|
344
|
-
Run the pinned npm native-host installer, reload the extension in `chrome://extensions`, then refresh the Overleaf tab. This also fixes extension/native version mismatch and native protocol mismatch.
|
|
287
|
+
Run the pinned npm native-host installer, reload the extension in `chrome://extensions`, then refresh the Overleaf tab. This also fixes extension/native version mismatch and native protocol mismatch. If npm is unavailable, use the [source installer fallback](#source-installer-fallback) for your platform.
|
|
345
288
|
|
|
346
289
|
```bash
|
|
347
|
-
npm exec --yes codex-overleaf-link@1.3.
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
If npm is unavailable, use the GitHub Release script fallback for your platform.
|
|
351
|
-
|
|
352
|
-
macOS/Linux:
|
|
353
|
-
|
|
354
|
-
```bash
|
|
355
|
-
CODEX_OVERLEAF_REF=v1.3.0 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.0/install.sh)"
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
Windows PowerShell:
|
|
359
|
-
|
|
360
|
-
```powershell
|
|
361
|
-
iwr https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/v1.3.0/install.ps1 -OutFile install.ps1
|
|
362
|
-
$env:CODEX_OVERLEAF_REF='v1.3.0'
|
|
363
|
-
powershell -ExecutionPolicy Bypass -File install.ps1
|
|
290
|
+
npm exec --yes codex-overleaf-link@1.3.5 -- install-native
|
|
364
291
|
```
|
|
365
292
|
|
|
366
293
|
**The Windows popup or panel shows a Bash recovery command**
|
|
367
294
|
|
|
368
|
-
Use the PowerShell recovery command
|
|
295
|
+
Use the PowerShell recovery command on Windows. The Bash command is for macOS/Linux installers.
|
|
369
296
|
|
|
370
297
|
**Codex CLI not found**
|
|
371
298
|
|
|
@@ -373,16 +300,7 @@ Confirm `codex --version` works in a new terminal and that you are logged in. On
|
|
|
373
300
|
|
|
374
301
|
**Extension id mismatch**
|
|
375
302
|
|
|
376
|
-
Copy the id shown in `chrome://extensions` and reinstall the native host with that id
|
|
377
|
-
|
|
378
|
-
```bash
|
|
379
|
-
cd ~/.codex-overleaf/source && npm run install:native -- --extension-id <your-chrome-extension-id>
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
```powershell
|
|
383
|
-
cd $env:LOCALAPPDATA\CodexOverleaf\source
|
|
384
|
-
npm run install:native -- --extension-id <your-chrome-extension-id>
|
|
385
|
-
```
|
|
303
|
+
Copy the id shown in `chrome://extensions` and reinstall the native host with that id (see [Extension ID](#extension-id)).
|
|
386
304
|
|
|
387
305
|
**Linux Chromium does not connect**
|
|
388
306
|
|
|
@@ -418,8 +336,8 @@ Use this matrix for release-candidate signoff and compatibility reports. Record
|
|
|
418
336
|
| Browser/channel/version | Google Chrome channel and version. | Google Chrome channel and version. | Google Chrome channel and version. | Chromium channel/package and version. |
|
|
419
337
|
| Install mode | Manual unpacked extension from GitHub Release zip or checkout. | Manual unpacked extension from GitHub Release zip or checkout. | Manual unpacked extension from GitHub Release zip or checkout. | Manual unpacked extension from GitHub Release zip or checkout; native host installed with `--browser chromium`. |
|
|
420
338
|
| Extension id | Bundled id `illdpneeeopfffmiepaejglgmhpmdhdc`, or actual custom id passed with `--extension-id`. | Bundled id `illdpneeeopfffmiepaejglgmhpmdhdc`, or actual custom id passed with `--extension-id`. | Bundled id `illdpneeeopfffmiepaejglgmhpmdhdc`, or actual custom id passed with `--extension-id`. | Bundled id `illdpneeeopfffmiepaejglgmhpmdhdc`, or actual custom id passed with `--extension-id`. |
|
|
421
|
-
| Installer/update command | `npm exec --yes codex-overleaf-link@1.3.
|
|
422
|
-
| Uninstall command | `npm exec --yes codex-overleaf-link@1.3.
|
|
339
|
+
| Installer/update command | `npm exec --yes codex-overleaf-link@1.3.5 -- install-native` | `npm exec --yes codex-overleaf-link@1.3.5 -- install-native` | `npm exec --yes codex-overleaf-link@1.3.5 -- install-native` | `npm exec --yes codex-overleaf-link@1.3.5 -- install-native --browser chromium` |
|
|
340
|
+
| Uninstall command | `npm exec --yes codex-overleaf-link@1.3.5 -- uninstall-native` | `npm exec --yes codex-overleaf-link@1.3.5 -- uninstall-native` | `npm exec --yes codex-overleaf-link@1.3.5 -- uninstall-native` | `npm exec --yes codex-overleaf-link@1.3.5 -- uninstall-native --browser chromium` |
|
|
423
341
|
| Manifest/registry path | `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.codex.overleaf.json` | `HKCU\Software\Google\Chrome\NativeMessagingHosts\com.codex.overleaf` -> `%LOCALAPPDATA%\CodexOverleaf\native-host-runtime\com.codex.overleaf.json` | `~/.config/google-chrome/NativeMessagingHosts/com.codex.overleaf.json` | `~/.config/chromium/NativeMessagingHosts/com.codex.overleaf.json` |
|
|
424
342
|
| Bridge/runtime/source path | Bridge `~/.codex-overleaf/codex-overleaf-bridge`; runtime `~/.codex-overleaf/native-host-runtime`; source `~/.codex-overleaf/source`. | Bridge `%LOCALAPPDATA%\CodexOverleaf\codex-overleaf-bridge.cmd`; runtime `%LOCALAPPDATA%\CodexOverleaf\native-host-runtime`; source `%LOCALAPPDATA%\CodexOverleaf\source`. | Bridge `~/.codex-overleaf/codex-overleaf-bridge`; runtime `~/.codex-overleaf/native-host-runtime`; source `~/.codex-overleaf/source`. | Bridge `~/.codex-overleaf/codex-overleaf-bridge`; runtime `~/.codex-overleaf/native-host-runtime`; source `~/.codex-overleaf/source`. |
|
|
425
343
|
| Node/Git/Codex/TeX | Node.js >= 20; Git; Codex CLI installed and logged in; TeX optional. | Node.js >= 20; Git; Codex CLI installed and logged in; TeX optional. | Node.js >= 20; Git; Codex CLI installed and logged in; TeX optional. | Node.js >= 20; Git; Codex CLI installed and logged in; TeX optional. |
|
|
@@ -430,11 +348,11 @@ Use this matrix for release-candidate signoff and compatibility reports. Record
|
|
|
430
348
|
## Development
|
|
431
349
|
|
|
432
350
|
```bash
|
|
433
|
-
npm test
|
|
351
|
+
npm test # Node.js built-in test runner, zero dependencies
|
|
434
352
|
npm run check:architecture # enforce v1.0 final architecture budgets
|
|
435
353
|
npm run benchmark:large # run the synthetic large-project regression gate
|
|
436
|
-
npm run bridge
|
|
437
|
-
npm run install:native
|
|
354
|
+
npm run bridge # run the native host directly for protocol work
|
|
355
|
+
npm run install:native # reinstall native host after changing native-host/src or extension/src/shared
|
|
438
356
|
```
|
|
439
357
|
|
|
440
358
|
## Contributing
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
const MIN_NATIVE_VERSION = '1.0.0';
|
|
13
13
|
const MIN_COMPATIBLE_NATIVE_VERSION = '1.0.0';
|
|
14
14
|
const MIN_COMPATIBLE_EXTENSION_VERSION = '1.0.0';
|
|
15
|
-
const BUILD_TARGET_VERSION = '1.3.
|
|
15
|
+
const BUILD_TARGET_VERSION = '1.3.5';
|
|
16
16
|
const DEFAULT_CHROME_EXTENSION_ID = 'illdpneeeopfffmiepaejglgmhpmdhdc';
|
|
17
17
|
const REQUIRED_CAPABILITIES = Object.freeze([
|
|
18
18
|
'bridgePing',
|
|
@@ -155,15 +155,15 @@
|
|
|
155
155
|
switchLanguageHint: 'Change panel language',
|
|
156
156
|
close: 'Close',
|
|
157
157
|
closeDiagnostics: 'Close diagnostics result',
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
customInstructionsSubtitle: 'Give Codex extra instructions and context for this Overleaf project.',
|
|
161
|
-
customInstructionsLearnMore: 'Learn more',
|
|
162
|
-
customInstructionsClose: 'Close custom instructions',
|
|
158
|
+
settingsBack: 'Back',
|
|
159
|
+
projectSettings: 'Project Settings',
|
|
163
160
|
customInstructionsPlaceholder: 'Style, terminology, venue constraints, and LaTeX conventions for this project.',
|
|
164
|
-
projectSettingsSavedToast: 'Project settings saved.',
|
|
165
161
|
projectSettingsTitle: 'Project Settings',
|
|
166
|
-
projectSettingsSubtitle: '
|
|
162
|
+
projectSettingsSubtitle: 'Customize how Codex behaves in this and all projects.',
|
|
163
|
+
settingsScopeProjectTitle: 'This project',
|
|
164
|
+
settingsScopeProjectSubtitle: 'Instructions and rules applied to this Overleaf project only.',
|
|
165
|
+
settingsScopeGlobalTitle: 'All projects',
|
|
166
|
+
settingsScopeGlobalSubtitle: 'Skill loading settings that apply across all Overleaf projects.',
|
|
167
167
|
governanceRulesTitle: 'Governance Rules',
|
|
168
168
|
governanceReadonlyPatterns: 'Read-only patterns',
|
|
169
169
|
governanceWritablePatterns: 'Writable patterns',
|
|
@@ -173,13 +173,21 @@
|
|
|
173
173
|
sensitiveConfirmMessage: 'Codex found possible sensitive content. Raw detected secrets are not shown here. Continue only if this project context may be sent to Codex.',
|
|
174
174
|
sensitiveConfirmRun: 'Run anyway',
|
|
175
175
|
localSkillsTitle: 'Skills',
|
|
176
|
-
codexOverleafSkillsTitle: 'Codex Overleaf skills',
|
|
177
176
|
codexOverleafSkillsEmpty: 'No Codex Overleaf skills installed.',
|
|
178
177
|
codexOverleafSkillsDisabled: 'Codex Overleaf skills are disabled for runs.',
|
|
179
178
|
loadCodexLocalSkills: 'Load local Codex skills',
|
|
180
179
|
loadCodexOverleafSkills: 'Load Codex Overleaf skills',
|
|
181
180
|
localSkillRemove: 'Remove',
|
|
181
|
+
localSkillRemoveConfirm: 'Confirm',
|
|
182
|
+
localSkillRemoveCancel: 'Cancel',
|
|
183
|
+
localSkillRemoving: 'Removing…',
|
|
184
|
+
codexOverleafSkillsLoading: 'Loading skills…',
|
|
185
|
+
codexOverleafSkillEnableToggle: 'Enable this skill',
|
|
182
186
|
codexOverleafSkillRemoveDone: 'Codex Overleaf skill removed.',
|
|
187
|
+
codexOverleafSkillsTitle: 'Codex Overleaf skills',
|
|
188
|
+
codexOverleafSkillsEntry: 'Codex Overleaf skills',
|
|
189
|
+
codexOverleafSkillsSummaryOff: 'Off',
|
|
190
|
+
codexOverleafSkillsSummaryCount: '{count} enabled',
|
|
183
191
|
slashInstallSkillTitle: 'Install skill',
|
|
184
192
|
slashInstallSkillSubtitle: 'Use the Codex skill installer with natural language.',
|
|
185
193
|
slashUseSkillSubtitle: 'Use this skill for the next Codex turn.',
|
|
@@ -191,7 +199,8 @@
|
|
|
191
199
|
binaryAssetConfirm: 'Write assets',
|
|
192
200
|
binaryAssetCancel: 'Skip assets',
|
|
193
201
|
personalizationConfig: 'Personalization',
|
|
194
|
-
|
|
202
|
+
settingsSaved: 'Saved',
|
|
203
|
+
settingsSaving: 'Saving…',
|
|
195
204
|
technicalDetails: 'Technical Details',
|
|
196
205
|
newSession: 'New Session',
|
|
197
206
|
tasks: 'Tasks',
|
|
@@ -414,15 +423,15 @@
|
|
|
414
423
|
switchLanguageHint: '切换面板语言',
|
|
415
424
|
close: '关闭',
|
|
416
425
|
closeDiagnostics: '关闭诊断结果',
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
customInstructionsSubtitle: '为当前 Overleaf 项目提供额外指令和上下文。',
|
|
420
|
-
customInstructionsLearnMore: '了解更多',
|
|
421
|
-
customInstructionsClose: '关闭自定义指令',
|
|
426
|
+
settingsBack: '返回',
|
|
427
|
+
projectSettings: '项目设置',
|
|
422
428
|
customInstructionsPlaceholder: '写下此项目的风格、术语、会议要求和 LaTeX 约定。',
|
|
423
|
-
projectSettingsSavedToast: '项目设置已保存。',
|
|
424
429
|
projectSettingsTitle: '项目设置',
|
|
425
|
-
projectSettingsSubtitle: '
|
|
430
|
+
projectSettingsSubtitle: '自定义 Codex 在当前项目和所有项目中的行为。',
|
|
431
|
+
settingsScopeProjectTitle: '当前项目',
|
|
432
|
+
settingsScopeProjectSubtitle: '仅应用于当前 Overleaf 项目的指令和规则。',
|
|
433
|
+
settingsScopeGlobalTitle: '所有项目',
|
|
434
|
+
settingsScopeGlobalSubtitle: '适用于所有 Overleaf 项目的技能加载设置。',
|
|
426
435
|
governanceRulesTitle: '治理规则',
|
|
427
436
|
governanceReadonlyPatterns: '只读路径规则',
|
|
428
437
|
governanceWritablePatterns: '可写路径规则',
|
|
@@ -432,13 +441,21 @@
|
|
|
432
441
|
sensitiveConfirmMessage: 'Codex 发现了可能的敏感内容。这里不会显示原始密钥或秘密值。只有在确认可以把这些项目上下文发送给 Codex 时才继续。',
|
|
433
442
|
sensitiveConfirmRun: '仍然运行',
|
|
434
443
|
localSkillsTitle: '技能',
|
|
435
|
-
codexOverleafSkillsTitle: 'Codex Overleaf 专属技能',
|
|
436
444
|
codexOverleafSkillsEmpty: '没有安装 Codex Overleaf 专属技能。',
|
|
437
445
|
codexOverleafSkillsDisabled: '运行时已禁用 Codex Overleaf 专属技能。',
|
|
438
446
|
loadCodexLocalSkills: '加载 Codex 本地技能',
|
|
439
447
|
loadCodexOverleafSkills: '加载 Codex Overleaf 专属技能',
|
|
440
448
|
localSkillRemove: '删除',
|
|
449
|
+
localSkillRemoveConfirm: '确认',
|
|
450
|
+
localSkillRemoveCancel: '取消',
|
|
451
|
+
localSkillRemoving: '删除中…',
|
|
452
|
+
codexOverleafSkillsLoading: '正在加载技能…',
|
|
453
|
+
codexOverleafSkillEnableToggle: '启用该技能',
|
|
441
454
|
codexOverleafSkillRemoveDone: 'Codex Overleaf 技能已删除。',
|
|
455
|
+
codexOverleafSkillsTitle: 'Codex Overleaf 专属技能',
|
|
456
|
+
codexOverleafSkillsEntry: 'Codex Overleaf 专属技能',
|
|
457
|
+
codexOverleafSkillsSummaryOff: '已关闭',
|
|
458
|
+
codexOverleafSkillsSummaryCount: '已启用 {count} 个',
|
|
442
459
|
slashInstallSkillTitle: '安装 skill',
|
|
443
460
|
slashInstallSkillSubtitle: '用自然语言调用 Codex 的 skill installer。',
|
|
444
461
|
slashUseSkillSubtitle: '本轮使用这个 skill。',
|
|
@@ -450,7 +467,8 @@
|
|
|
450
467
|
binaryAssetConfirm: '写入资源',
|
|
451
468
|
binaryAssetCancel: '跳过资源',
|
|
452
469
|
personalizationConfig: '个性化配置',
|
|
453
|
-
|
|
470
|
+
settingsSaved: '已保存',
|
|
471
|
+
settingsSaving: '保存中…',
|
|
454
472
|
technicalDetails: '技术细节',
|
|
455
473
|
newSession: '新建会话',
|
|
456
474
|
tasks: '任务',
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
'markdown-link-target'
|
|
14
14
|
]);
|
|
15
15
|
const TEXT_EXTENSION_PATTERN = '(?:tex|bib|sty|cls|bst|bbx|cbx|lbx|cfg|def|clo|ist|txt|md|latex)';
|
|
16
|
-
const
|
|
17
|
-
const
|
|
16
|
+
const CJK_PUNCTUATION = '、,;。!?:';
|
|
17
|
+
const REFERENCE_PREFIX_PATTERN = `(^|[\\s\\[({\"',;${CJK_PUNCTUATION}])`;
|
|
18
|
+
const PATH_PATTERN = `([^\\s\\[\\](){}<>"'\`,;${CJK_PUNCTUATION}]+?\\.${TEXT_EXTENSION_PATTERN})`;
|
|
18
19
|
const BARE_LOCAL_PATH_PATTERN = /(?:file:\/\/\/?[^\s)\]]+|[A-Za-z]:[\\/][^\s)\]]+|\/(?:Users|home|private|var|tmp)\/[^\s)\]]+|[^\s)\]]*[\\/]\.codex-overleaf[\\/]projects[\\/][^\s)\]]+)/gi;
|
|
19
20
|
|
|
20
21
|
function parseLineReferencesFromText({ text, mode }) {
|
|
@@ -76,9 +77,6 @@
|
|
|
76
77
|
placeholderBrackets: true
|
|
77
78
|
});
|
|
78
79
|
|
|
79
|
-
if (context === 'render' || context === 'persist') {
|
|
80
|
-
return sanitized;
|
|
81
|
-
}
|
|
82
80
|
return sanitized;
|
|
83
81
|
}
|
|
84
82
|
|
|
@@ -460,7 +458,7 @@
|
|
|
460
458
|
}
|
|
461
459
|
|
|
462
460
|
function splitTrailingPunctuation(value) {
|
|
463
|
-
const match = String(value || '').match(/^(.*?)([
|
|
461
|
+
const match = String(value || '').match(/^(.*?)([.,;!?、,;。!?:]+)$/);
|
|
464
462
|
if (!match) {
|
|
465
463
|
return { value, trailing: '' };
|
|
466
464
|
}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
autoOpen: true,
|
|
18
18
|
loadCodexLocalSkills: true,
|
|
19
19
|
loadCodexOverleafSkills: true,
|
|
20
|
+
codexOverleafSkillEnabled: {},
|
|
20
21
|
panelWidth: 380,
|
|
21
22
|
task: '',
|
|
22
23
|
focusFiles: [],
|
|
@@ -105,6 +106,7 @@
|
|
|
105
106
|
state.autoOpen = state.autoOpen !== false;
|
|
106
107
|
state.loadCodexLocalSkills = state.loadCodexLocalSkills !== false;
|
|
107
108
|
state.loadCodexOverleafSkills = state.loadCodexOverleafSkills !== false;
|
|
109
|
+
state.codexOverleafSkillEnabled = normalizeCodexOverleafSkillEnabled(state.codexOverleafSkillEnabled);
|
|
108
110
|
state.panelWidth = normalizePanelWidth(state.panelWidth);
|
|
109
111
|
state.task = typeof state.task === 'string' ? state.task : '';
|
|
110
112
|
state.model = typeof state.model === 'string' && state.model ? state.model : DEFAULT_PANEL_STATE.model;
|
|
@@ -669,6 +671,23 @@
|
|
|
669
671
|
return result;
|
|
670
672
|
}
|
|
671
673
|
|
|
674
|
+
function normalizeCodexOverleafSkillEnabled(value) {
|
|
675
|
+
const result = {};
|
|
676
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
677
|
+
return result;
|
|
678
|
+
}
|
|
679
|
+
for (const key of Object.keys(value)) {
|
|
680
|
+
if (typeof key !== 'string' || !key) {
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
if (typeof value[key] !== 'boolean') {
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
result[key] = value[key];
|
|
687
|
+
}
|
|
688
|
+
return result;
|
|
689
|
+
}
|
|
690
|
+
|
|
672
691
|
function normalizeProjectPrefKey(value) {
|
|
673
692
|
const key = typeof value === 'string' ? value.trim() : '';
|
|
674
693
|
if (!key) {
|
|
@@ -714,6 +733,7 @@
|
|
|
714
733
|
autoOpen: source.autoOpen !== false,
|
|
715
734
|
loadCodexLocalSkills: source.loadCodexLocalSkills !== false,
|
|
716
735
|
loadCodexOverleafSkills: source.loadCodexOverleafSkills !== false,
|
|
736
|
+
codexOverleafSkillEnabled: normalizeCodexOverleafSkillEnabled(source.codexOverleafSkillEnabled),
|
|
717
737
|
panelWidth: normalizePanelWidth(source.panelWidth),
|
|
718
738
|
task: summarizeTextForStorage(active?.task || source.task || '', 'task'),
|
|
719
739
|
focusFiles: normalizeFocusFiles(active?.focusFiles || source.focusFiles),
|
|
@@ -342,11 +342,31 @@
|
|
|
342
342
|
experimentalOtByProject: normalizeBooleanMap(state.experimentalOtByProject),
|
|
343
343
|
customInstructionsByProject: normalizeStringMap(state.customInstructionsByProject),
|
|
344
344
|
governanceRulesByProject: normalizeGovernanceRulesMap(state.governanceRulesByProject),
|
|
345
|
-
selectedLocalSkillIdsByProject: normalizeStringListMap(state.selectedLocalSkillIdsByProject)
|
|
345
|
+
selectedLocalSkillIdsByProject: normalizeStringListMap(state.selectedLocalSkillIdsByProject),
|
|
346
|
+
codexOverleafSkillEnabled: normalizeCodexOverleafSkillEnabledMap(state.codexOverleafSkillEnabled)
|
|
346
347
|
};
|
|
347
348
|
return prefs;
|
|
348
349
|
}
|
|
349
350
|
|
|
351
|
+
function normalizeCodexOverleafSkillEnabledMap(value) {
|
|
352
|
+
var result = {};
|
|
353
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
var keys = Object.keys(value);
|
|
357
|
+
for (var i = 0; i < keys.length; i++) {
|
|
358
|
+
var key = keys[i];
|
|
359
|
+
if (typeof key !== 'string' || !key) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (typeof value[key] !== 'boolean') {
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
result[key] = value[key];
|
|
366
|
+
}
|
|
367
|
+
return result;
|
|
368
|
+
}
|
|
369
|
+
|
|
350
370
|
function normalizeBooleanMap(value) {
|
|
351
371
|
var result = {};
|
|
352
372
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
@@ -7,25 +7,31 @@ const {
|
|
|
7
7
|
getNativeHostPlatform
|
|
8
8
|
} = require('./nativeHostPlatform');
|
|
9
9
|
const {
|
|
10
|
+
ensureCodexOverleafSkillInstalled,
|
|
10
11
|
getCodexOverleafSkillsRoot,
|
|
11
|
-
materializeProjectSkillsAsCodexSkills
|
|
12
|
+
materializeProjectSkillsAsCodexSkills,
|
|
13
|
+
OFFICIAL_CODEX_OVERLEAF_SKILL_IDS
|
|
12
14
|
} = require('./localSkills');
|
|
13
15
|
|
|
14
16
|
const COPIED_USER_CODEX_FILES = [
|
|
15
17
|
'auth.json',
|
|
16
18
|
'config.toml',
|
|
17
|
-
'AGENTS.md',
|
|
18
19
|
'installation_id',
|
|
19
20
|
'models_cache.json',
|
|
20
21
|
'version.json'
|
|
21
22
|
];
|
|
22
23
|
|
|
23
24
|
const LINKED_USER_CODEX_DIRS = [
|
|
24
|
-
'rules',
|
|
25
|
-
'memories',
|
|
26
25
|
'vendor_imports'
|
|
27
26
|
];
|
|
28
27
|
|
|
28
|
+
// User-global Codex instruction/memory entries that must never enter the plugin
|
|
29
|
+
// Codex home. The extension supplies its own per-project personalization via the
|
|
30
|
+
// prompt; inheriting the user's global Codex guidance here is a leak. The plugin
|
|
31
|
+
// home is reused across runs, so these are removed every prepare to also clear
|
|
32
|
+
// entries left by earlier extension versions.
|
|
33
|
+
const ISOLATED_USER_INSTRUCTION_ENTRIES = ['AGENTS.md', 'rules', 'memories'];
|
|
34
|
+
|
|
29
35
|
const LOCAL_SKILL_USER_CODEX_DIRS = [
|
|
30
36
|
'plugins',
|
|
31
37
|
'superpowers'
|
|
@@ -93,6 +99,18 @@ function preparePluginCodexHome(env = process.env, options = {}) {
|
|
|
93
99
|
copied.push(fileName);
|
|
94
100
|
}
|
|
95
101
|
|
|
102
|
+
// Personalization isolation: the plugin Codex home must never inherit the
|
|
103
|
+
// user's global Codex instructions/memory. Remove them every run — this also
|
|
104
|
+
// clears stale entries left by earlier extension versions. This runs after
|
|
105
|
+
// the samePath early-return above, so it never touches the user's real
|
|
106
|
+
// ~/.codex when the plugin home and user home are the same directory.
|
|
107
|
+
for (const entryName of ISOLATED_USER_INSTRUCTION_ENTRIES) {
|
|
108
|
+
removePluginHomeEntry(pluginHome, entryName, skippedLinks);
|
|
109
|
+
}
|
|
110
|
+
if (!isRegularFile(path.join(userHome, 'config.toml'))) {
|
|
111
|
+
removePluginHomeEntry(pluginHome, 'config.toml', skippedLinks);
|
|
112
|
+
}
|
|
113
|
+
|
|
96
114
|
if (!loadCodexLocalSkills) {
|
|
97
115
|
for (const entryName of LOCAL_SKILL_PLUGIN_HOME_ENTRIES) {
|
|
98
116
|
removePluginHomeEntry(pluginHome, entryName, skippedLinks);
|
|
@@ -119,6 +137,8 @@ function preparePluginCodexHome(env = process.env, options = {}) {
|
|
|
119
137
|
linked.push(dirName);
|
|
120
138
|
}
|
|
121
139
|
|
|
140
|
+
ensureDefaultCodexOverleafSkills({ env });
|
|
141
|
+
|
|
122
142
|
const skillsResult = composePluginSkillsDirectory({
|
|
123
143
|
userHome,
|
|
124
144
|
pluginHome,
|
|
@@ -137,13 +157,68 @@ function preparePluginCodexHome(env = process.env, options = {}) {
|
|
|
137
157
|
return { userHome, pluginHome, copied, linked, skippedLinks };
|
|
138
158
|
}
|
|
139
159
|
|
|
160
|
+
function ensureDefaultCodexOverleafSkills({ env = process.env } = {}) {
|
|
161
|
+
for (const id of OFFICIAL_CODEX_OVERLEAF_SKILL_IDS) {
|
|
162
|
+
const src = path.resolve(__dirname, 'skills', id, 'SKILL.md');
|
|
163
|
+
const content = fs.readFileSync(src, 'utf8');
|
|
164
|
+
ensureCodexOverleafSkillInstalled({ skillId: id, content, env });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
140
168
|
function copyUserCodexFile(source, target, fileName, options = {}) {
|
|
141
|
-
if (fileName !== 'config.toml'
|
|
169
|
+
if (fileName !== 'config.toml') {
|
|
142
170
|
fs.copyFileSync(source, target);
|
|
143
171
|
return;
|
|
144
172
|
}
|
|
145
|
-
|
|
146
|
-
|
|
173
|
+
let content = stripPersonalizationFromCodexConfig(fs.readFileSync(source, 'utf8'));
|
|
174
|
+
if (options.loadCodexLocalSkills === false) {
|
|
175
|
+
content = sanitizeCodexConfigForLocalSkillIsolation(content);
|
|
176
|
+
}
|
|
177
|
+
fs.writeFileSync(target, content, 'utf8');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Removes the top-level `personality` key (Codex's built-in "personality"
|
|
181
|
+
// feature) so the plugin Codex home never inherits the user's global
|
|
182
|
+
// personalization. Only the top-level key is removed — a `personality` key
|
|
183
|
+
// inside a [section] is a different key and is preserved. Handles single-line
|
|
184
|
+
// values and both multi-line string forms (""" basic and ''' literal). All
|
|
185
|
+
// other lines pass through unchanged, aside from line endings being normalized to LF.
|
|
186
|
+
function stripPersonalizationFromCodexConfig(content) {
|
|
187
|
+
const lines = String(content || '').split(/\r?\n/);
|
|
188
|
+
const output = [];
|
|
189
|
+
let beforeFirstSection = true;
|
|
190
|
+
let closingDelimiter = '';
|
|
191
|
+
|
|
192
|
+
for (const line of lines) {
|
|
193
|
+
if (closingDelimiter) {
|
|
194
|
+
if (line.includes(closingDelimiter)) {
|
|
195
|
+
closingDelimiter = '';
|
|
196
|
+
}
|
|
197
|
+
// Drop every line of the multi-line value, including the one that closes it.
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (parseTomlSectionName(line)) {
|
|
201
|
+
beforeFirstSection = false;
|
|
202
|
+
output.push(line);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (beforeFirstSection) {
|
|
206
|
+
const match = line.match(/^\s*personality\s*=\s*(.*)$/);
|
|
207
|
+
if (match) {
|
|
208
|
+
const value = match[1];
|
|
209
|
+
const opener = value.startsWith('"""') ? '"""'
|
|
210
|
+
: value.startsWith("'''") ? "'''"
|
|
211
|
+
: '';
|
|
212
|
+
if (opener && value.indexOf(opener, opener.length) === -1) {
|
|
213
|
+
closingDelimiter = opener;
|
|
214
|
+
}
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
output.push(line);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return output.join('\n');
|
|
147
222
|
}
|
|
148
223
|
|
|
149
224
|
function sanitizeCodexConfigForLocalSkillIsolation(content) {
|
|
@@ -532,6 +607,7 @@ module.exports = {
|
|
|
532
607
|
buildCodexHomeEnv,
|
|
533
608
|
clearPluginCodexHistory,
|
|
534
609
|
composePluginSkillsDirectory,
|
|
610
|
+
ensureDefaultCodexOverleafSkills,
|
|
535
611
|
getPluginCodexHome,
|
|
536
612
|
getUserCodexHome,
|
|
537
613
|
preparePluginCodexHome
|
|
@@ -68,6 +68,7 @@ async function runCodexSession({ params = {}, env = process.env, emit = () => {}
|
|
|
68
68
|
const codexSkillInvocationContext = loadCodexSkillInvocationContext({
|
|
69
69
|
skillInvocation,
|
|
70
70
|
loadCodexOverleafSkills: skillLoading.loadCodexOverleafSkills,
|
|
71
|
+
enabledCodexOverleafSkillIds: params.enabledCodexOverleafSkillIds,
|
|
71
72
|
env,
|
|
72
73
|
emit
|
|
73
74
|
});
|
|
@@ -385,6 +386,7 @@ function normalizeSkillLoadingSettings(params = {}) {
|
|
|
385
386
|
function loadCodexSkillInvocationContext({
|
|
386
387
|
skillInvocation,
|
|
387
388
|
loadCodexOverleafSkills = true,
|
|
389
|
+
enabledCodexOverleafSkillIds,
|
|
388
390
|
env = process.env,
|
|
389
391
|
emit = () => {}
|
|
390
392
|
} = {}) {
|
|
@@ -399,6 +401,7 @@ function loadCodexSkillInvocationContext({
|
|
|
399
401
|
const result = loadSelectedCodexOverleafSkill({
|
|
400
402
|
skillId: invocation.id,
|
|
401
403
|
loadCodexOverleafSkills,
|
|
404
|
+
enabledCodexOverleafSkillIds,
|
|
402
405
|
env
|
|
403
406
|
});
|
|
404
407
|
if (result.missing.length) {
|
|
@@ -13,6 +13,7 @@ const MAX_SKILL_CONTENT_CHARS = MAX_SKILL_CONTENT_BYTES;
|
|
|
13
13
|
const MAX_SKILL_PREVIEW_CHARS = 240;
|
|
14
14
|
const PROJECT_SKILL_SCOPE = 'project';
|
|
15
15
|
const CODEX_OVERLEAF_SKILL_SCOPE = 'codex-overleaf';
|
|
16
|
+
const OFFICIAL_CODEX_OVERLEAF_SKILL_IDS = ['annotated-rewrite'];
|
|
16
17
|
|
|
17
18
|
function listProjectSkills({ projectId, rootDir } = {}) {
|
|
18
19
|
const skillsDir = getProjectSkillsDir(projectId, { rootDir });
|
|
@@ -110,13 +111,18 @@ function listCodexOverleafSkills({ env = process.env, skillsRoot } = {}) {
|
|
|
110
111
|
continue;
|
|
111
112
|
}
|
|
112
113
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
const isOfficial = OFFICIAL_CODEX_OVERLEAF_SKILL_IDS.includes(entry.name);
|
|
115
|
+
skills.push({
|
|
116
|
+
...buildSkillMetadata({
|
|
117
|
+
id: entry.name,
|
|
118
|
+
content,
|
|
119
|
+
size: stat.size,
|
|
120
|
+
updatedAt: stat.mtime.toISOString(),
|
|
121
|
+
scope: CODEX_OVERLEAF_SKILL_SCOPE
|
|
122
|
+
}),
|
|
123
|
+
official: isOfficial,
|
|
124
|
+
removable: !isOfficial
|
|
125
|
+
});
|
|
120
126
|
}
|
|
121
127
|
|
|
122
128
|
return { skills: skills.sort((left, right) => left.id.localeCompare(right.id)) };
|
|
@@ -147,6 +153,9 @@ function installCodexOverleafSkill({ skillId, content, env = process.env, skills
|
|
|
147
153
|
|
|
148
154
|
function removeCodexOverleafSkill({ skillId, env = process.env, skillsRoot } = {}) {
|
|
149
155
|
const id = validateSkillId(skillId);
|
|
156
|
+
if (OFFICIAL_CODEX_OVERLEAF_SKILL_IDS.includes(id)) {
|
|
157
|
+
throw new Error(`Cannot remove official skill: ${id}`);
|
|
158
|
+
}
|
|
150
159
|
const root = getCodexOverleafSkillsRoot({ env, skillsRoot });
|
|
151
160
|
const skillDir = resolveInside(root, id, 'Unsafe Codex Overleaf skill path');
|
|
152
161
|
const removed = fs.existsSync(skillDir);
|
|
@@ -156,6 +165,21 @@ function removeCodexOverleafSkill({ skillId, env = process.env, skillsRoot } = {
|
|
|
156
165
|
return { id, scope: CODEX_OVERLEAF_SKILL_SCOPE, removed };
|
|
157
166
|
}
|
|
158
167
|
|
|
168
|
+
function ensureCodexOverleafSkillInstalled({ skillId, content, env = process.env } = {}) {
|
|
169
|
+
const root = getCodexOverleafSkillsRoot({ env });
|
|
170
|
+
const skillPath = resolveCodexOverleafSkillPath(skillId, { env });
|
|
171
|
+
if (fs.existsSync(skillPath)) {
|
|
172
|
+
assertNoSymlinkEscape(skillPath, root, 'Existing official skill path is unsafe');
|
|
173
|
+
const stat = fs.lstatSync(skillPath);
|
|
174
|
+
if (stat.isFile()) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
// symlink, directory, or other — remove and reinstall
|
|
178
|
+
fs.rmSync(skillPath, { recursive: true, force: true });
|
|
179
|
+
}
|
|
180
|
+
installCodexOverleafSkill({ skillId, content, env });
|
|
181
|
+
}
|
|
182
|
+
|
|
159
183
|
function loadSelectedProjectSkills({ projectId, selectedSkillIds, rootDir, projectRoot } = {}) {
|
|
160
184
|
const ids = normalizeSelectedSkillIds(selectedSkillIds);
|
|
161
185
|
const skills = [];
|
|
@@ -230,6 +254,7 @@ function materializeProjectSkillsAsCodexSkills({
|
|
|
230
254
|
function loadSelectedCodexOverleafSkill({
|
|
231
255
|
skillId,
|
|
232
256
|
loadCodexOverleafSkills = true,
|
|
257
|
+
enabledCodexOverleafSkillIds,
|
|
233
258
|
env = process.env,
|
|
234
259
|
skillsRoot
|
|
235
260
|
} = {}) {
|
|
@@ -248,6 +273,18 @@ function loadSelectedCodexOverleafSkill({
|
|
|
248
273
|
}]
|
|
249
274
|
};
|
|
250
275
|
}
|
|
276
|
+
// Per-skill enable check: if enabledCodexOverleafSkillIds is provided and does not include
|
|
277
|
+
// this skill, treat it as not available. Absent param = all enabled (backward-safe).
|
|
278
|
+
if (Array.isArray(enabledCodexOverleafSkillIds) && !enabledCodexOverleafSkillIds.includes(id)) {
|
|
279
|
+
return {
|
|
280
|
+
skill: null,
|
|
281
|
+
missing: [],
|
|
282
|
+
ignored: [{
|
|
283
|
+
id,
|
|
284
|
+
reason: 'codex_overleaf_skill_disabled'
|
|
285
|
+
}]
|
|
286
|
+
};
|
|
287
|
+
}
|
|
251
288
|
|
|
252
289
|
const filePath = resolveCodexOverleafSkillPath(id, { env, skillsRoot });
|
|
253
290
|
if (!fs.existsSync(filePath)) {
|
|
@@ -461,7 +498,9 @@ module.exports = {
|
|
|
461
498
|
CODEX_OVERLEAF_SKILL_SCOPE,
|
|
462
499
|
MAX_SKILL_CONTENT_BYTES,
|
|
463
500
|
MAX_SKILL_CONTENT_CHARS,
|
|
501
|
+
OFFICIAL_CODEX_OVERLEAF_SKILL_IDS,
|
|
464
502
|
PROJECT_SKILL_SCOPE,
|
|
503
|
+
ensureCodexOverleafSkillInstalled,
|
|
465
504
|
getDefaultCodexOverleafSkillsRoot,
|
|
466
505
|
getCodexOverleafSkillsRoot,
|
|
467
506
|
installCodexOverleafSkill,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: annotated-rewrite
|
|
3
|
+
description: >
|
|
4
|
+
When editing `.tex` files, use this skill as often as possible. When
|
|
5
|
+
rewriting `.tex` content spanning more than a few words, comment out the
|
|
6
|
+
original and write the replacement below it so the user can review the
|
|
7
|
+
before/after diff directly in the source.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Annotated Rewrite
|
|
11
|
+
|
|
12
|
+
When rewriting `.tex` file content (paragraphs, sentences, equations, list
|
|
13
|
+
bodies, or any block larger than a few words), preserve the original by
|
|
14
|
+
commenting it out rather than deleting it, then write the replacement below.
|
|
15
|
+
This lets the user review exactly what changed before accepting the edit.
|
|
16
|
+
|
|
17
|
+
## When to apply
|
|
18
|
+
|
|
19
|
+
Default to this pattern whenever the replaced content is **more than a short inline phrase** (see the word-level exception below), regardless of content type — prose, equations, lists, environment bodies, or any contiguous block. Use it as often as possible — when in doubt, use it.
|
|
20
|
+
|
|
21
|
+
A useful guide: if the replaced content is **3 or more source lines**, always apply it. For shorter replacements (1-2 source lines), lean toward applying it unless the change is purely **word-level**: replacing a single word, fixing a typo, or changing a run of 1-5 words within an unbroken clause.
|
|
22
|
+
|
|
23
|
+
Word-level edits are the only case where skipping the annotated format is clearly appropriate (subject to the structural exceptions in Rule 8).
|
|
24
|
+
|
|
25
|
+
## Edit format
|
|
26
|
+
|
|
27
|
+
```tex
|
|
28
|
+
% [original]
|
|
29
|
+
% The proposed method encodes user history as a fixed-length vector,
|
|
30
|
+
% then applies a linear projection before computing dot-product scores.
|
|
31
|
+
% Training uses binary cross-entropy loss over sampled negatives.
|
|
32
|
+
%
|
|
33
|
+
% \begin{equation}
|
|
34
|
+
% \hat{y}_{ui} = \mathbf{u}_i^\top \mathbf{v}_j
|
|
35
|
+
% \end{equation}
|
|
36
|
+
|
|
37
|
+
% [revised]
|
|
38
|
+
We encode user history with a transformer encoder, producing a
|
|
39
|
+
context-aware representation that is projected into the item space.
|
|
40
|
+
Training minimises a softmax loss over in-batch negatives.
|
|
41
|
+
|
|
42
|
+
\begin{equation}
|
|
43
|
+
\hat{y}_{ui} = \mathrm{softmax}(\mathbf{U}\mathbf{V}^\top)_{ij}
|
|
44
|
+
\end{equation}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Rules
|
|
48
|
+
|
|
49
|
+
1. Copy the original lines **verbatim** into the comment block — do not alter them
|
|
50
|
+
2. Include every line of the replaced content verbatim with `%` prepended;
|
|
51
|
+
blank lines within the block become `%` empty-comment lines (a line
|
|
52
|
+
containing only `%`). Include `\begin{...}` / `\end{...}` markers only when
|
|
53
|
+
they are part of the replaced content — do not comment out enclosing
|
|
54
|
+
environment markers that are not themselves changing
|
|
55
|
+
3. No blank line between `% [original]` and the first commented line
|
|
56
|
+
4. One blank line between the last commented line and `% [revised]`; one blank
|
|
57
|
+
line before `% [original]` and after the last line of the replacement (to
|
|
58
|
+
separate the annotated construct from surrounding document text)
|
|
59
|
+
5. The new content after `% [revised]` is normal LaTeX (not commented)
|
|
60
|
+
6. For multiple non-adjacent replaced blocks, apply the pattern independently
|
|
61
|
+
to each block
|
|
62
|
+
7. **Idempotency**: if the content being edited already contains a
|
|
63
|
+
`% [original]` / `% [revised]` block, edit only the active content after
|
|
64
|
+
`% [revised]` — do not re-wrap the existing annotated block or create a new
|
|
65
|
+
outer annotation around it
|
|
66
|
+
8. **Structure safety**: only apply this pattern at **block level** (paragraph,
|
|
67
|
+
sentence, equation block, list body, or environment body). Do NOT insert
|
|
68
|
+
`% [original]` / `% [revised]` inside
|
|
69
|
+
macro arguments, table rows, math expressions, `\caption{...}`,
|
|
70
|
+
`\item[...]`, or preamble commands — make minimal direct edits there instead,
|
|
71
|
+
or ask for confirmation before changing structurally sensitive content
|