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.
Files changed (73) hide show
  1. package/README.md +45 -21
  2. package/bin/codex-overleaf-link.mjs +58 -0
  3. package/extension/assets/icons/codex-overleaf-dialog-icon.png +0 -0
  4. package/extension/assets/icons/codex-overleaf-icon.png +0 -0
  5. package/extension/assets/icons/icon128.png +0 -0
  6. package/extension/assets/icons/icon16.png +0 -0
  7. package/extension/assets/icons/icon32.png +0 -0
  8. package/extension/assets/icons/icon48.png +0 -0
  9. package/extension/bootstrap/background.js +404 -0
  10. package/extension/bootstrap/manifest.template.json +51 -0
  11. package/extension/bootstrap/popup.css +26 -0
  12. package/extension/bootstrap/popup.html +38 -0
  13. package/extension/bootstrap/popup.js +44 -0
  14. package/extension/bootstrap/runtimeContext.js +2 -0
  15. package/extension/runtime-manifest.json +60 -0
  16. package/extension/src/background.js +532 -0
  17. package/extension/src/content/applyResultFormatters.js +387 -0
  18. package/extension/src/content/composerAttachments.js +522 -0
  19. package/extension/src/content/composerPanel.js +254 -0
  20. package/extension/src/content/contentRuntime.js +8897 -0
  21. package/extension/src/content/contextTray.js +686 -0
  22. package/extension/src/content/diagnosticsController.js +659 -0
  23. package/extension/src/content/diagnosticsPanel.js +342 -0
  24. package/extension/src/content/diffReviewPanel.js +797 -0
  25. package/extension/src/content/localSkillsPanel.js +280 -0
  26. package/extension/src/content/markdownText.js +606 -0
  27. package/extension/src/content/mirrorHealth.js +92 -0
  28. package/extension/src/content/modelPicker.js +489 -0
  29. package/extension/src/content/nativeChannel.js +62 -0
  30. package/extension/src/content/otWarmMirror.js +964 -0
  31. package/extension/src/content/otWarmMirrorController.js +174 -0
  32. package/extension/src/content/panelMaintenance.js +367 -0
  33. package/extension/src/content/panelRenderer.js +253 -0
  34. package/extension/src/content/recentProjects.js +1063 -0
  35. package/extension/src/content/reviewHunks.js +247 -0
  36. package/extension/src/content/runController.js +242 -0
  37. package/extension/src/content/runTimelineView.js +1131 -0
  38. package/extension/src/content/sessionManager.js +487 -0
  39. package/extension/src/content/sessionPanel.js +263 -0
  40. package/extension/src/content/settingsPanel.js +527 -0
  41. package/extension/src/content/themeController.js +91 -0
  42. package/extension/src/content/updateIdle.js +67 -0
  43. package/extension/src/content/writebackController.js +300 -0
  44. package/extension/src/content/writebackOrchestrator.js +850 -0
  45. package/extension/src/contentScript.js +8 -0
  46. package/extension/src/page/compileBridge.js +460 -0
  47. package/extension/src/page/overleafCapabilities.js +100 -0
  48. package/extension/src/page/overleafEditor.js +282 -0
  49. package/extension/src/page/overleafProjectSnapshot.js +234 -0
  50. package/extension/src/page/overleafRealtimeObserver.js +491 -0
  51. package/extension/src/page/pageBridgeCapability.js +71 -0
  52. package/extension/src/page/snapshotRouter.js +948 -0
  53. package/extension/src/page/trackedChangesLifecycle.js +1506 -0
  54. package/extension/src/page/treeOperations.js +1584 -0
  55. package/extension/src/page/writeGuard.js +142 -0
  56. package/extension/src/page/writebackRouter.js +1934 -0
  57. package/extension/src/pageBridge.js +2224 -0
  58. package/extension/src/popup.js +247 -0
  59. package/extension/src/shared/agentTranscript.js +18 -4
  60. package/extension/src/shared/compatibility.js +1 -1
  61. package/extension/styles/panel.css +4048 -0
  62. package/native-host/src/index.js +9 -2
  63. package/native-host/src/managedInstall.js +393 -0
  64. package/native-host/src/managedLauncherRuntime.js +71 -0
  65. package/native-host/src/nativeHostPlatform.js +16 -0
  66. package/native-host/src/runtimeInstaller.js +6 -1
  67. package/native-host/src/taskRunnerRuntime.js +8 -0
  68. package/native-host/src/updateArchive.js +253 -0
  69. package/native-host/src/updateManager.js +548 -0
  70. package/native-host/src/updateTrust.js +156 -0
  71. package/package.json +11 -2
  72. package/scripts/install-managed.mjs +64 -0
  73. package/scripts/uninstall-managed.mjs +48 -0
@@ -0,0 +1,280 @@
1
+ (function initCodexOverleafLocalSkillsPanel(root, factory) {
2
+ if (typeof module === 'object' && module.exports) {
3
+ module.exports = factory();
4
+ } else {
5
+ root.CodexOverleafLocalSkillsPanel = factory();
6
+ }
7
+ })(typeof window !== 'undefined' ? window : globalThis, function localSkillsPanelFactory() {
8
+ 'use strict';
9
+
10
+ // Destructuring defaults handle the "dep omitted" case. Production callers
11
+ // pass real functions; tests that exercise partial wiring rely on the
12
+ // undefined-only defaults to land on the noop. Passing `null` or a non-
13
+ // function value is no longer silently coerced — that was an antipattern
14
+ // (the typeof guards used to hide a missing wire-up by swapping in a noop).
15
+ function createLocalSkillsPanelController({
16
+ root = (typeof window !== 'undefined' ? window : globalThis),
17
+ document: documentDep = null,
18
+ getPanel = () => null,
19
+ getState = () => null,
20
+ setState = () => {},
21
+ saveState = null,
22
+ sendBackgroundNative = () => Promise.resolve({ ok: false }),
23
+ getSkillLoadingSettings = () => ({ loadCodexOverleafSkills: true }),
24
+ isCodexOverleafSkillEnabled = () => true,
25
+ setCodexOverleafSkillEnabled = () => {},
26
+ setProjectSettingsStatus = () => {},
27
+ tr = (key) => key,
28
+ tx = (english) => english,
29
+ getComposerSkillInvocation = () => null,
30
+ normalizeComposerSkillInvocation = (value) => value,
31
+ clearComposerSkillInvocation = () => {},
32
+ setSlashCodexOverleafSkills = () => {},
33
+ clearSlashCodexOverleafSkills = () => {}
34
+ } = {}) {
35
+ const document = documentDep
36
+ || root.document
37
+ || (typeof globalThis !== 'undefined' ? globalThis.document : null);
38
+
39
+ async function refreshLocalSkills() {
40
+ showSkillListLoading();
41
+ try {
42
+ const codexOverleafResponse = await sendBackgroundNative({
43
+ method: 'skills.list',
44
+ params: { scope: 'codex-overleaf' }
45
+ });
46
+ if (!codexOverleafResponse?.ok) {
47
+ throw new Error(codexOverleafResponse?.error?.message || 'native host did not return Codex Overleaf skills');
48
+ }
49
+ const codexOverleafSkills = Array.isArray(codexOverleafResponse.result?.skills)
50
+ ? codexOverleafResponse.result.skills
51
+ : [];
52
+ const state = getState() || {};
53
+ setState({
54
+ ...state,
55
+ codexOverleafSkills
56
+ });
57
+ setSlashCodexOverleafSkills(codexOverleafSkills);
58
+ renderLocalSkillList();
59
+ } catch (err) {
60
+ renderLocalSkillList();
61
+ throw err;
62
+ }
63
+ }
64
+
65
+ function showSkillListLoading() {
66
+ const list = getPanel()?.querySelector('[data-local-skill-list]');
67
+ if (!list) {
68
+ return;
69
+ }
70
+ list.textContent = '';
71
+ const placeholder = document.createElement('div');
72
+ placeholder.className = 'codex-project-settings-empty';
73
+ placeholder.textContent = tr('codexOverleafSkillsLoading');
74
+ list.append(placeholder);
75
+ }
76
+
77
+ // Tracks which row is currently in "confirming remove" state.
78
+ // Only one row may be in this state at a time.
79
+ let confirmingRowId = null;
80
+
81
+ function getCodexOverleafSkillsForSettings() {
82
+ const state = getState() || {};
83
+ return Array.isArray(state.codexOverleafSkills) ? state.codexOverleafSkills : [];
84
+ }
85
+
86
+ function renderLocalSkillList() {
87
+ const list = getPanel()?.querySelector('[data-local-skill-list]');
88
+ if (!list) {
89
+ return;
90
+ }
91
+ confirmingRowId = null;
92
+ const codexOverleafSkills = getCodexOverleafSkillsForSettings();
93
+ const codexOverleafEnabled = getSkillLoadingSettings().loadCodexOverleafSkills !== false;
94
+ list.textContent = '';
95
+ if (!codexOverleafEnabled) {
96
+ appendLocalSkillEmpty(list, tr('codexOverleafSkillsDisabled'));
97
+ }
98
+ if (!codexOverleafSkills.length) {
99
+ appendLocalSkillEmpty(list, tr('codexOverleafSkillsEmpty'));
100
+ return;
101
+ }
102
+ for (const skill of codexOverleafSkills) {
103
+ renderCodexOverleafSkillRow(list, skill, codexOverleafEnabled);
104
+ }
105
+ }
106
+
107
+ function renderCodexOverleafSkillRow(list, skill, masterEnabled) {
108
+ const id = String(skill?.id || '').trim();
109
+ if (!id) {
110
+ return;
111
+ }
112
+ const row = document.createElement('div');
113
+ row.className = 'codex-local-skill-row';
114
+ row.dataset.scope = 'codex-overleaf';
115
+ if (!masterEnabled) {
116
+ row.dataset.disabled = 'true';
117
+ }
118
+
119
+ // Skill display name on the left — a single human-readable label
120
+ // (title when available, else the id). Avoids redundant "Title (id)"
121
+ // form per user feedback: one canonical name. The id remains as the
122
+ // accessible `title` tooltip so the underlying identifier is still
123
+ // discoverable on hover for advanced users.
124
+ const text = document.createElement('span');
125
+ const trimmedTitle = typeof skill.title === 'string' ? skill.title.trim() : '';
126
+ text.textContent = trimmedTitle || id;
127
+ text.title = id;
128
+ row.append(text);
129
+
130
+ // Per-skill enable switch — appended last so it sits on the right of the
131
+ // row, after the Remove control. It remains a real checkbox input.
132
+ const toggle = document.createElement('input');
133
+ toggle.type = 'checkbox';
134
+ toggle.className = 'codex-switch';
135
+ toggle.checked = isCodexOverleafSkillEnabled(id);
136
+ toggle.setAttribute('aria-label', tr('codexOverleafSkillEnableToggle'));
137
+ if (!masterEnabled) {
138
+ toggle.disabled = true;
139
+ }
140
+ toggle.addEventListener('change', event => {
141
+ setCodexOverleafSkillEnabled(id, event.target.checked);
142
+ });
143
+
144
+ if (skill.removable !== false) {
145
+ // The Remove / Confirm / Cancel controls share an actions container so
146
+ // the per-skill switch always stays rightmost in the row, regardless of
147
+ // the inline confirmation state.
148
+ const actions = document.createElement('div');
149
+ actions.className = 'codex-local-skill-actions';
150
+
151
+ // Remove button — clicking it enters the inline confirmation state.
152
+ const removeBtn = document.createElement('button');
153
+ removeBtn.type = 'button';
154
+ removeBtn.className = 'codex-set-btn codex-set-btn--subtle';
155
+ removeBtn.textContent = tr('localSkillRemove');
156
+
157
+ // Confirm and Cancel buttons — only in the DOM while confirming.
158
+ const confirmBtn = document.createElement('button');
159
+ confirmBtn.type = 'button';
160
+ confirmBtn.className = 'codex-set-btn codex-set-btn--danger';
161
+ confirmBtn.textContent = tr('localSkillRemoveConfirm');
162
+
163
+ const cancelBtn = document.createElement('button');
164
+ cancelBtn.type = 'button';
165
+ cancelBtn.className = 'codex-set-btn';
166
+ cancelBtn.textContent = tr('localSkillRemoveCancel');
167
+
168
+ function enterConfirming() {
169
+ // Reset any previously confirming row back to its Remove button state.
170
+ if (confirmingRowId !== null && confirmingRowId !== id) {
171
+ resetConfirmingRow();
172
+ }
173
+ confirmingRowId = id;
174
+ removeBtn.remove();
175
+ row.dataset.confirming = 'true';
176
+ actions.append(confirmBtn, cancelBtn);
177
+ }
178
+
179
+ function exitConfirming() {
180
+ confirmingRowId = null;
181
+ confirmBtn.remove();
182
+ cancelBtn.remove();
183
+ delete row.dataset.confirming;
184
+ actions.append(removeBtn);
185
+ }
186
+
187
+ removeBtn.addEventListener('click', event => {
188
+ event.preventDefault();
189
+ enterConfirming();
190
+ });
191
+
192
+ cancelBtn.addEventListener('click', event => {
193
+ event.preventDefault();
194
+ exitConfirming();
195
+ });
196
+
197
+ confirmBtn.addEventListener('click', event => {
198
+ event.preventDefault();
199
+ // In-progress: disable Confirm, Cancel, and the enable toggle; update text.
200
+ confirmBtn.disabled = true;
201
+ cancelBtn.disabled = true;
202
+ toggle.disabled = true;
203
+ confirmBtn.textContent = tr('localSkillRemoving');
204
+ removeCodexOverleafSkill(id).catch(error => {
205
+ setProjectSettingsStatus(tx(`Failed to remove Codex Overleaf skill: ${error.message}`, `删除 Codex Overleaf 技能失败:${error.message}`), 'failed');
206
+ // Restore row on failure so the user can retry.
207
+ confirmBtn.disabled = false;
208
+ cancelBtn.disabled = false;
209
+ toggle.disabled = !masterEnabled;
210
+ confirmBtn.textContent = tr('localSkillRemoveConfirm');
211
+ });
212
+ });
213
+
214
+ actions.append(removeBtn);
215
+ row.append(actions);
216
+
217
+ // Store references so resetConfirmingRow can find and reset this row.
218
+ row._exitConfirming = exitConfirming;
219
+ row._skillId = id;
220
+ }
221
+
222
+ // Per-skill enable switch is always the last child (rightmost).
223
+ row.append(toggle);
224
+
225
+ list.append(row);
226
+ }
227
+
228
+ function resetConfirmingRow() {
229
+ // Walk the skill list to find the row whose id matches confirmingRowId.
230
+ const list = getPanel()?.querySelector('[data-local-skill-list]');
231
+ if (!list) {
232
+ return;
233
+ }
234
+ for (const child of Array.from(list.children || [])) {
235
+ if (child._skillId === confirmingRowId && child._exitConfirming) {
236
+ child._exitConfirming();
237
+ break;
238
+ }
239
+ }
240
+ }
241
+
242
+ function appendLocalSkillEmpty(list, text) {
243
+ const empty = document.createElement('div');
244
+ empty.className = 'codex-project-settings-empty';
245
+ empty.textContent = text;
246
+ list.append(empty);
247
+ }
248
+
249
+ async function removeCodexOverleafSkill(id) {
250
+ const response = await sendBackgroundNative({
251
+ method: 'skills.remove',
252
+ params: {
253
+ scope: 'codex-overleaf',
254
+ id
255
+ }
256
+ });
257
+ if (!response?.ok) {
258
+ throw new Error(response?.error?.message || 'native host did not remove Codex Overleaf skill');
259
+ }
260
+ const activeSkill = normalizeComposerSkillInvocation(getComposerSkillInvocation());
261
+ if (activeSkill?.scope === 'codex-overleaf' && activeSkill.skillId === id) {
262
+ clearComposerSkillInvocation();
263
+ }
264
+ setProjectSettingsStatus(tr('codexOverleafSkillRemoveDone'), 'completed');
265
+ clearSlashCodexOverleafSkills();
266
+ await refreshLocalSkills();
267
+ await saveState?.();
268
+ }
269
+
270
+ return {
271
+ refreshLocalSkills,
272
+ renderLocalSkillList,
273
+ removeCodexOverleafSkill
274
+ };
275
+ }
276
+
277
+ return {
278
+ createLocalSkillsPanelController
279
+ };
280
+ });