codex-overleaf-link 1.8.6 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -21
- package/bin/codex-overleaf-link.mjs +58 -0
- package/extension/assets/icons/codex-overleaf-dialog-icon.png +0 -0
- package/extension/assets/icons/codex-overleaf-icon.png +0 -0
- package/extension/assets/icons/icon128.png +0 -0
- package/extension/assets/icons/icon16.png +0 -0
- package/extension/assets/icons/icon32.png +0 -0
- package/extension/assets/icons/icon48.png +0 -0
- package/extension/bootstrap/background.js +404 -0
- package/extension/bootstrap/manifest.template.json +51 -0
- package/extension/bootstrap/popup.css +26 -0
- package/extension/bootstrap/popup.html +38 -0
- package/extension/bootstrap/popup.js +44 -0
- package/extension/bootstrap/runtimeContext.js +2 -0
- package/extension/runtime-manifest.json +60 -0
- package/extension/src/background.js +532 -0
- package/extension/src/content/applyResultFormatters.js +387 -0
- package/extension/src/content/composerAttachments.js +522 -0
- package/extension/src/content/composerPanel.js +254 -0
- package/extension/src/content/contentRuntime.js +8897 -0
- package/extension/src/content/contextTray.js +686 -0
- package/extension/src/content/diagnosticsController.js +659 -0
- package/extension/src/content/diagnosticsPanel.js +342 -0
- package/extension/src/content/diffReviewPanel.js +797 -0
- package/extension/src/content/localSkillsPanel.js +280 -0
- package/extension/src/content/markdownText.js +606 -0
- package/extension/src/content/mirrorHealth.js +92 -0
- package/extension/src/content/modelPicker.js +489 -0
- package/extension/src/content/nativeChannel.js +62 -0
- package/extension/src/content/otWarmMirror.js +964 -0
- package/extension/src/content/otWarmMirrorController.js +174 -0
- package/extension/src/content/panelMaintenance.js +367 -0
- package/extension/src/content/panelRenderer.js +253 -0
- package/extension/src/content/recentProjects.js +1063 -0
- package/extension/src/content/reviewHunks.js +247 -0
- package/extension/src/content/runController.js +242 -0
- package/extension/src/content/runTimelineView.js +1131 -0
- package/extension/src/content/sessionManager.js +487 -0
- package/extension/src/content/sessionPanel.js +263 -0
- package/extension/src/content/settingsPanel.js +527 -0
- package/extension/src/content/themeController.js +91 -0
- package/extension/src/content/updateIdle.js +67 -0
- package/extension/src/content/writebackController.js +300 -0
- package/extension/src/content/writebackOrchestrator.js +850 -0
- package/extension/src/contentScript.js +8 -0
- package/extension/src/page/compileBridge.js +460 -0
- package/extension/src/page/overleafCapabilities.js +100 -0
- package/extension/src/page/overleafEditor.js +282 -0
- package/extension/src/page/overleafProjectSnapshot.js +234 -0
- package/extension/src/page/overleafRealtimeObserver.js +491 -0
- package/extension/src/page/pageBridgeCapability.js +71 -0
- package/extension/src/page/snapshotRouter.js +948 -0
- package/extension/src/page/trackedChangesLifecycle.js +1506 -0
- package/extension/src/page/treeOperations.js +1584 -0
- package/extension/src/page/writeGuard.js +142 -0
- package/extension/src/page/writebackRouter.js +1934 -0
- package/extension/src/pageBridge.js +2224 -0
- package/extension/src/popup.js +247 -0
- package/extension/src/shared/agentTranscript.js +18 -4
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/styles/panel.css +4048 -0
- package/native-host/src/index.js +9 -2
- package/native-host/src/managedInstall.js +393 -0
- package/native-host/src/managedLauncherRuntime.js +71 -0
- package/native-host/src/nativeHostPlatform.js +16 -0
- package/native-host/src/runtimeInstaller.js +6 -1
- package/native-host/src/taskRunnerRuntime.js +8 -0
- package/native-host/src/updateArchive.js +253 -0
- package/native-host/src/updateManager.js +548 -0
- package/native-host/src/updateTrust.js +156 -0
- package/package.json +11 -2
- package/scripts/install-managed.mjs +64 -0
- package/scripts/uninstall-managed.mjs +48 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
(function initCodexOverleafComposerPanel() {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
function create(options = {}) {
|
|
5
|
+
const container = options.container;
|
|
6
|
+
if (!container) {
|
|
7
|
+
throw new Error('CodexOverleafComposerPanel requires a container');
|
|
8
|
+
}
|
|
9
|
+
const instance = {
|
|
10
|
+
container,
|
|
11
|
+
callbacks: options.callbacks || {},
|
|
12
|
+
i18n: options.i18n || {},
|
|
13
|
+
attachmentController: options.attachmentController || null,
|
|
14
|
+
listeners: []
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
container.innerHTML = `
|
|
18
|
+
<form class="codex-composer" data-composer-form>
|
|
19
|
+
<div class="codex-attachment-strip codex-attachment-preview-list" data-attachment-strip hidden></div>
|
|
20
|
+
<div class="codex-composer-skill-context" data-composer-skill-context hidden>
|
|
21
|
+
<span class="codex-composer-skill-icon" aria-hidden="true">◇</span>
|
|
22
|
+
<span data-composer-skill-label></span>
|
|
23
|
+
<button type="button" data-composer-skill-clear title="Clear skill" aria-label="Clear skill">×</button>
|
|
24
|
+
</div>
|
|
25
|
+
<textarea data-task rows="3" placeholder="Ask Codex anything. Type @ to add context"></textarea>
|
|
26
|
+
<div class="codex-context-summary" data-context-summary hidden></div>
|
|
27
|
+
<div class="codex-mode-row">
|
|
28
|
+
<span class="codex-mode-label" data-i18n="mode">Mode</span>
|
|
29
|
+
<div class="codex-mode-switch" role="group" aria-label="Write mode">
|
|
30
|
+
<button type="button" data-mode-choice="ask" aria-pressed="false" title="Read and analyze only. Do not write to Overleaf.">Ask</button>
|
|
31
|
+
<button type="button" data-mode-choice="confirm" aria-pressed="false" title="Show a change plan first, then write after approval.">Suggest</button>
|
|
32
|
+
<button type="button" data-mode-choice="auto" aria-pressed="false" title="Write directly after authorization. Deletes still require confirmation.">Auto</button>
|
|
33
|
+
</div>
|
|
34
|
+
<select data-mode aria-label="Mode" hidden>
|
|
35
|
+
<option value="ask">Ask</option>
|
|
36
|
+
<option value="confirm">Suggest</option>
|
|
37
|
+
<option value="auto">Auto</option>
|
|
38
|
+
</select>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="codex-composer-toolbar">
|
|
41
|
+
<button type="button" data-add-context title="Add @ context" aria-label="Add @ context" aria-expanded="false">+</button>
|
|
42
|
+
<label class="codex-review-toggle" title="When enabled, Codex checks or switches Overleaf Reviewing/Track Changes before writing. Deletes still require confirmation.">
|
|
43
|
+
<input type="checkbox" data-require-reviewing>
|
|
44
|
+
<span class="codex-review-label" data-i18n="requireReviewing">Track</span>
|
|
45
|
+
</label>
|
|
46
|
+
<label class="codex-recompile-toggle" title="After Codex writes, click Overleaf Recompile and record the compile result for this task. Ask mode will not trigger it.">
|
|
47
|
+
<input type="checkbox" data-auto-recompile>
|
|
48
|
+
<span class="codex-recompile-label" data-i18n="autoCompile">Compile</span>
|
|
49
|
+
</label>
|
|
50
|
+
<div class="codex-model-config" data-model-config>
|
|
51
|
+
<button type="button" class="codex-model-config-button" data-model-config-toggle aria-haspopup="menu" aria-expanded="false">
|
|
52
|
+
<span class="codex-model-speed-indicator" data-speed-indicator hidden>⚡</span>
|
|
53
|
+
<span data-model-display>5.4</span>
|
|
54
|
+
<span data-reasoning-display>Medium</span>
|
|
55
|
+
</button>
|
|
56
|
+
<div class="codex-model-config-popover" data-model-config-popover role="menu" hidden>
|
|
57
|
+
<div class="codex-model-config-section" data-reasoning-choice-list></div>
|
|
58
|
+
<div class="codex-model-config-divider"></div>
|
|
59
|
+
<div class="codex-model-config-section" data-model-choice-list></div>
|
|
60
|
+
<div class="codex-model-config-divider"></div>
|
|
61
|
+
<div class="codex-model-config-section" data-speed-choice-list></div>
|
|
62
|
+
<div class="codex-model-config-inputs" hidden>
|
|
63
|
+
<select data-model aria-label="Model">
|
|
64
|
+
<option value="gpt-5.5">GPT-5.5</option>
|
|
65
|
+
<option value="gpt-5.4">GPT-5.4</option>
|
|
66
|
+
<option value="gpt-5.4-mini">GPT-5.4 Mini</option>
|
|
67
|
+
<option value="gpt-5.3-codex">GPT-5.3 Codex</option>
|
|
68
|
+
<option value="gpt-5.3-codex-spark">GPT-5.3 Codex Spark</option>
|
|
69
|
+
<option value="gpt-5.2">GPT-5.2</option>
|
|
70
|
+
</select>
|
|
71
|
+
<select data-reasoning aria-label="Reasoning">
|
|
72
|
+
<option value="low">Low</option>
|
|
73
|
+
<option value="medium">Medium</option>
|
|
74
|
+
<option value="high">High</option>
|
|
75
|
+
<option value="xhigh">XHigh</option>
|
|
76
|
+
</select>
|
|
77
|
+
<select data-speed aria-label="Speed">
|
|
78
|
+
<option value="standard">Std</option>
|
|
79
|
+
<option value="fast">Fast</option>
|
|
80
|
+
</select>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
<button type="submit" data-run title="Send" aria-label="Send">↑</button>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="codex-slash-menu" data-slash-menu hidden>
|
|
87
|
+
<button type="button" data-slash-command="install-skill" data-slash-command-kind="installer">
|
|
88
|
+
<span data-i18n="slashInstallSkillTitle">Install skill</span>
|
|
89
|
+
<small data-i18n="slashInstallSkillSubtitle">Add a Codex Overleaf skill under this plugin.</small>
|
|
90
|
+
</button>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="codex-context-tray" data-context-tray hidden>
|
|
93
|
+
<div class="codex-context-head">
|
|
94
|
+
<span data-i18n="contextTitle">@ Context</span>
|
|
95
|
+
<button type="button" class="codex-attach-button" data-attach-file title="Attach files (PDF, images)" aria-label="Attach files (PDF, images)">⌲</button>
|
|
96
|
+
<input type="file" data-attach-input multiple hidden>
|
|
97
|
+
<button type="button" data-context-refresh title="Refresh file list" aria-label="Refresh file list">↻</button>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="codex-context-selection" data-context-selection></div>
|
|
100
|
+
<div class="codex-context-status" data-context-status>Type @ to add context: @file, @compile-log, @current-section.</div>
|
|
101
|
+
<div class="codex-context-files" data-context-file-list></div>
|
|
102
|
+
</div>
|
|
103
|
+
</form>
|
|
104
|
+
`;
|
|
105
|
+
|
|
106
|
+
bindEvents(instance);
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
setRunning: running => setRunning(instance, running),
|
|
110
|
+
setModels: models => setModels(instance, models),
|
|
111
|
+
setMode: mode => setMode(instance, mode),
|
|
112
|
+
focus: () => focus(instance),
|
|
113
|
+
destroy: () => destroy(instance),
|
|
114
|
+
_instance: instance
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function bindEvents(instance) {
|
|
119
|
+
const form = instance.container.querySelector('[data-composer-form]');
|
|
120
|
+
const task = instance.container.querySelector('[data-task]');
|
|
121
|
+
bind(instance, form, 'submit', event => {
|
|
122
|
+
event.preventDefault();
|
|
123
|
+
instance.callbacks.onSubmit?.();
|
|
124
|
+
});
|
|
125
|
+
bind(instance, task, 'paste', event => instance.callbacks.onPaste?.(event));
|
|
126
|
+
bind(instance, form, 'dragover', event => instance.callbacks.onDragOver?.(event));
|
|
127
|
+
bind(instance, form, 'dragleave', event => instance.callbacks.onDragLeave?.(event));
|
|
128
|
+
bind(instance, form, 'drop', event => instance.callbacks.onDrop?.(event));
|
|
129
|
+
bind(instance, instance.container.querySelector('[data-run]'), 'click', event => {
|
|
130
|
+
event.preventDefault();
|
|
131
|
+
if (instance.callbacks.isRunning?.()) {
|
|
132
|
+
instance.callbacks.onCancel?.();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
form?.requestSubmit?.();
|
|
136
|
+
});
|
|
137
|
+
bind(instance, task, 'keydown', event => instance.callbacks.onTaskKeydown?.(event));
|
|
138
|
+
bind(instance, task, 'input', event => instance.callbacks.onTaskInput?.(event));
|
|
139
|
+
bind(instance, instance.container.querySelector('[data-slash-menu]'), 'click', event => instance.callbacks.onSlashMenuClick?.(event));
|
|
140
|
+
bind(instance, instance.container.querySelector('[data-composer-skill-clear]'), 'click', () => instance.callbacks.onClearSkillInvocation?.());
|
|
141
|
+
bind(instance, instance.container.querySelector('[data-add-context]'), 'click', () => instance.callbacks.onAddContext?.());
|
|
142
|
+
bind(instance, instance.container.querySelector('[data-attach-file]'), 'click', () => instance.callbacks.onAttachClick?.());
|
|
143
|
+
bind(instance, instance.container.querySelector('[data-attach-input]'), 'change', event => instance.callbacks.onAttachInput?.(event));
|
|
144
|
+
bind(instance, instance.container.querySelector('[data-context-refresh]'), 'click', () => instance.callbacks.onContextRefresh?.());
|
|
145
|
+
bind(instance, instance.container.querySelector('[data-model-config-toggle]'), 'click', event => {
|
|
146
|
+
event.preventDefault();
|
|
147
|
+
instance.callbacks.onModelConfigToggle?.(event);
|
|
148
|
+
});
|
|
149
|
+
bind(instance, instance.container.querySelector('[data-model-config-popover]'), 'click', event => instance.callbacks.onModelConfigChoiceClick?.(event));
|
|
150
|
+
for (const button of instance.container.querySelectorAll('[data-mode-choice]')) {
|
|
151
|
+
bind(instance, button, 'click', () => instance.callbacks.onModeChoice?.(button.dataset.modeChoice));
|
|
152
|
+
}
|
|
153
|
+
for (const selector of ['[data-model]', '[data-reasoning]', '[data-speed]', '[data-mode]', '[data-task]', '[data-require-reviewing]', '[data-auto-recompile]']) {
|
|
154
|
+
const element = instance.container.querySelector(selector);
|
|
155
|
+
bind(instance, element, 'change', event => instance.callbacks.onInputChange?.(event));
|
|
156
|
+
bind(instance, element, 'input', event => instance.callbacks.onInputChange?.(event));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function bind(instance, target, type, listener) {
|
|
161
|
+
if (!target?.addEventListener) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
target.addEventListener(type, listener);
|
|
165
|
+
instance.listeners.push({ target, type, listener });
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function setRunning(target, running) {
|
|
169
|
+
const instance = target?._instance || target;
|
|
170
|
+
const runButton = instance?.container?.querySelector('[data-run]');
|
|
171
|
+
if (!runButton) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
runButton.disabled = false;
|
|
175
|
+
runButton.title = running ? t(instance, 'cancelRun') : t(instance, 'send');
|
|
176
|
+
runButton.setAttribute('aria-label', running ? t(instance, 'cancelRun') : t(instance, 'send'));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function setModels(target, models = []) {
|
|
180
|
+
const instance = target?._instance || target;
|
|
181
|
+
const modelSelect = instance?.container?.querySelector('[data-model]');
|
|
182
|
+
if (!modelSelect || !Array.isArray(models)) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
modelSelect.textContent = '';
|
|
186
|
+
for (const model of models) {
|
|
187
|
+
const option = document.createElement('option');
|
|
188
|
+
option.value = model.id || model.value || '';
|
|
189
|
+
option.textContent = model.label || model.id || model.value || '';
|
|
190
|
+
modelSelect.append(option);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function setMode(target, mode) {
|
|
195
|
+
const instance = target?._instance || target;
|
|
196
|
+
const select = instance?.container?.querySelector('[data-mode]');
|
|
197
|
+
if (select) {
|
|
198
|
+
select.value = mode;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function setState(target, state = {}) {
|
|
203
|
+
const instance = target?._instance || target;
|
|
204
|
+
if (Object.prototype.hasOwnProperty.call(state, 'running')) {
|
|
205
|
+
setRunning(instance, state.running);
|
|
206
|
+
}
|
|
207
|
+
if (state.mode) {
|
|
208
|
+
setMode(instance, state.mode);
|
|
209
|
+
}
|
|
210
|
+
if (Object.prototype.hasOwnProperty.call(state, 'compileEnabled')) {
|
|
211
|
+
const checkbox = instance?.container?.querySelector('[data-auto-recompile]');
|
|
212
|
+
if (checkbox) {
|
|
213
|
+
checkbox.checked = state.compileEnabled !== false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (Object.prototype.hasOwnProperty.call(state, 'trackEnabled')) {
|
|
217
|
+
const checkbox = instance?.container?.querySelector('[data-require-reviewing]');
|
|
218
|
+
if (checkbox) {
|
|
219
|
+
checkbox.checked = state.trackEnabled === true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function focus(target) {
|
|
225
|
+
const instance = target?._instance || target;
|
|
226
|
+
instance?.container?.querySelector('[data-task]')?.focus?.();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function t(instance, key, params) {
|
|
230
|
+
if (typeof instance?.i18n === 'function') {
|
|
231
|
+
return instance.i18n(key, params);
|
|
232
|
+
}
|
|
233
|
+
if (typeof instance?.i18n?.tr === 'function') {
|
|
234
|
+
return instance.i18n.tr(key, params);
|
|
235
|
+
}
|
|
236
|
+
if (typeof instance?.i18n?.t === 'function') {
|
|
237
|
+
return instance.i18n.t(key, params);
|
|
238
|
+
}
|
|
239
|
+
return key;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function destroy(instance) {
|
|
243
|
+
for (const { target, type, listener } of instance.listeners.splice(0)) {
|
|
244
|
+
target.removeEventListener?.(type, listener);
|
|
245
|
+
}
|
|
246
|
+
instance.container.textContent = '';
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
window.CodexOverleafComposerPanel = {
|
|
250
|
+
create,
|
|
251
|
+
setState,
|
|
252
|
+
setModels
|
|
253
|
+
};
|
|
254
|
+
})();
|