codex-overleaf-link 1.8.5 → 1.9.0

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 (74) 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 +8895 -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 +1126 -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/compatibility.js +1 -1
  60. package/extension/styles/panel.css +4048 -0
  61. package/native-host/src/index.js +9 -2
  62. package/native-host/src/launcher.js +2 -0
  63. package/native-host/src/managedInstall.js +393 -0
  64. package/native-host/src/managedLauncherRuntime.js +71 -0
  65. package/native-host/src/nativeEnvironment.js +4 -0
  66. package/native-host/src/nativeHostPlatform.js +16 -0
  67. package/native-host/src/runtimeInstaller.js +6 -1
  68. package/native-host/src/taskRunnerRuntime.js +8 -0
  69. package/native-host/src/updateArchive.js +253 -0
  70. package/native-host/src/updateManager.js +548 -0
  71. package/native-host/src/updateTrust.js +156 -0
  72. package/package.json +11 -2
  73. package/scripts/install-managed.mjs +64 -0
  74. package/scripts/uninstall-managed.mjs +48 -0
@@ -0,0 +1,247 @@
1
+ (function initPopup() {
2
+ 'use strict';
3
+
4
+ const CodexOverleafCompatibility = window.CodexOverleafCompatibility;
5
+ const DEFAULT_INSTALL_COMMAND = CodexOverleafCompatibility?.buildInstallCommand?.(
6
+ undefined,
7
+ undefined,
8
+ getCurrentExtensionId()
9
+ ) || 'curl -fsSL https://raw.githubusercontent.com/Ghqqqq/codex-overleaf-link/main/install.sh | bash -s -- --extension-id <chrome-extension-id>';
10
+ const button = document.getElementById('open-panel');
11
+ const status = document.getElementById('status');
12
+ const compatStatusIcon = document.getElementById('compat-status-icon');
13
+ const versionPair = document.getElementById('version-pair');
14
+ const nativeInstall = document.getElementById('native-install');
15
+ const installCommand = document.getElementById('install-command');
16
+ const copyInstallCommand = document.getElementById('copy-install-command');
17
+ let activeOverleafTab = null;
18
+ let currentInstallCommand = DEFAULT_INSTALL_COMMAND;
19
+
20
+ installCommand.textContent = currentInstallCommand;
21
+ button.textContent = 'Open panel in Overleaf';
22
+ setVersionStatus({
23
+ status: 'native_missing',
24
+ classification: 'incompatible',
25
+ extensionVersion: getExtensionCompatibilityMetadata().version
26
+ });
27
+
28
+ button.addEventListener('click', async () => {
29
+ const tab = activeOverleafTab || await getActiveOverleafProjectTab();
30
+ if (!tab?.id) {
31
+ status.textContent = 'Open an Overleaf project tab first.';
32
+ return;
33
+ }
34
+
35
+ await chrome.tabs.sendMessage(tab.id, { type: 'codex-overleaf/toggle-panel' });
36
+ window.close();
37
+ });
38
+
39
+ copyInstallCommand.addEventListener('click', async () => {
40
+ await navigator.clipboard.writeText(currentInstallCommand);
41
+ copyInstallCommand.textContent = 'Copied';
42
+ setTimeout(() => {
43
+ copyInstallCommand.textContent = 'Copy install command';
44
+ }, 1400);
45
+ });
46
+
47
+ initPopupState();
48
+
49
+ async function initPopupState() {
50
+ await checkNativeHost();
51
+ await refreshPanelButtonState();
52
+ }
53
+
54
+ async function refreshPanelButtonState() {
55
+ const tab = await getActiveOverleafProjectTab();
56
+ activeOverleafTab = tab;
57
+ if (!tab?.id) {
58
+ button.textContent = 'Open panel in Overleaf';
59
+ return;
60
+ }
61
+
62
+ try {
63
+ const response = await chrome.tabs.sendMessage(tab.id, { type: 'codex-overleaf/get-panel-state' });
64
+ const open = response?.open === true;
65
+ button.textContent = open ? 'Close panel in Overleaf' : 'Open panel in Overleaf';
66
+ status.textContent = open
67
+ ? 'Panel is open in this Overleaf tab.'
68
+ : 'Panel is closed in this Overleaf tab.';
69
+ } catch (_error) {
70
+ button.textContent = 'Open panel in Overleaf';
71
+ status.textContent = 'Refresh the Overleaf tab, then open the panel.';
72
+ }
73
+ }
74
+
75
+ async function getActiveOverleafProjectTab() {
76
+ const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
77
+ return tab?.id && isOverleafProjectUrl(tab.url) ? tab : null;
78
+ }
79
+
80
+ function isOverleafProjectUrl(url) {
81
+ return /^https:\/\/(www\.)?overleaf\.com\/project\//.test(String(url || ''));
82
+ }
83
+
84
+ async function checkNativeHost() {
85
+ try {
86
+ const response = await chrome.runtime.sendMessage({
87
+ type: 'codex-overleaf/native-request',
88
+ payload: {
89
+ id: crypto.randomUUID(),
90
+ method: 'bridge.ping',
91
+ params: CodexOverleafCompatibility?.buildBridgePingParams?.(getExtensionCompatibilityMetadata()) || {}
92
+ }
93
+ });
94
+ const compatibility = evaluateNativeCompatibility(response);
95
+ setVersionStatus(compatibility);
96
+ if (getCompatibilityClassification(compatibility) === 'compatible') {
97
+ nativeInstall.hidden = true;
98
+ status.textContent = 'Native host connected. Open an Overleaf project tab to use Codex.';
99
+ return;
100
+ }
101
+ showNativeInstallGuide(compatibility);
102
+ } catch (_error) {
103
+ const compatibility = {
104
+ status: 'native_missing',
105
+ classification: 'incompatible',
106
+ installCommand: DEFAULT_INSTALL_COMMAND,
107
+ updateCommand: DEFAULT_INSTALL_COMMAND,
108
+ extensionVersion: getExtensionCompatibilityMetadata().version
109
+ };
110
+ setVersionStatus(compatibility);
111
+ showNativeInstallGuide(compatibility);
112
+ }
113
+ }
114
+
115
+ function showNativeInstallGuide(compatibility = {}) {
116
+ nativeInstall.hidden = false;
117
+ currentInstallCommand = getCompatibilityUpdateCommand(compatibility);
118
+ installCommand.textContent = currentInstallCommand;
119
+ status.textContent = getNativeStatusMessage(compatibility.status, getCompatibilityClassification(compatibility));
120
+ }
121
+
122
+ function evaluateNativeCompatibility(response) {
123
+ if (CodexOverleafCompatibility?.evaluateNativeCompatibility) {
124
+ return CodexOverleafCompatibility.evaluateNativeCompatibility(response, getExtensionCompatibilityMetadata());
125
+ }
126
+ return response?.ok
127
+ ? {
128
+ status: 'ok',
129
+ classification: 'compatible',
130
+ native: response.result,
131
+ nativeVersion: response.result?.version,
132
+ currentNativeVersion: response.result?.version,
133
+ installCommand: DEFAULT_INSTALL_COMMAND,
134
+ updateCommand: DEFAULT_INSTALL_COMMAND,
135
+ extensionVersion: getExtensionCompatibilityMetadata().version
136
+ }
137
+ : {
138
+ status: 'native_missing',
139
+ classification: 'incompatible',
140
+ native: response,
141
+ installCommand: DEFAULT_INSTALL_COMMAND,
142
+ updateCommand: DEFAULT_INSTALL_COMMAND,
143
+ extensionVersion: getExtensionCompatibilityMetadata().version
144
+ };
145
+ }
146
+
147
+ function setVersionStatus(compatibility = {}) {
148
+ const classification = getCompatibilityClassification(compatibility);
149
+ const extensionVersion = compatibility.extensionVersion || getExtensionCompatibilityMetadata().version;
150
+ const nativeVersion = compatibility.currentNativeVersion || compatibility.nativeVersion || compatibility.native?.version;
151
+ versionPair.textContent = `Extension ${formatVersion(extensionVersion)} / Native ${formatVersion(nativeVersion)}`;
152
+ compatStatusIcon.textContent = getStatusIconText(classification);
153
+ compatStatusIcon.className = `status-icon ${classification}`;
154
+ compatStatusIcon.title = getCompatibilityStatusTitle(classification);
155
+ if (compatStatusIcon.dataset) {
156
+ compatStatusIcon.dataset.status = classification;
157
+ }
158
+ compatStatusIcon.setAttribute?.('aria-label', compatStatusIcon.title);
159
+ }
160
+
161
+ function getExtensionCompatibilityMetadata() {
162
+ return {
163
+ version: CodexOverleafCompatibility?.BUILD_TARGET_VERSION ||
164
+ chrome.runtime.getManifest?.().version ||
165
+ '',
166
+ extensionId: getCurrentExtensionId()
167
+ };
168
+ }
169
+
170
+ function getCurrentExtensionId() {
171
+ return typeof chrome === 'object' && chrome?.runtime?.id
172
+ ? chrome.runtime.id
173
+ : '';
174
+ }
175
+
176
+ function getCompatibilityClassification(compatibility = {}) {
177
+ const classification = compatibility.classification || compatibility.status;
178
+ switch (classification) {
179
+ case 'compatible':
180
+ case 'update-available':
181
+ case 'incompatible':
182
+ return classification;
183
+ case 'ok':
184
+ return 'compatible';
185
+ default:
186
+ return 'incompatible';
187
+ }
188
+ }
189
+
190
+ function getCompatibilityUpdateCommand(compatibility = {}) {
191
+ return CodexOverleafCompatibility?.buildInstallCommand?.(
192
+ compatibility.recommendedVersion || CodexOverleafCompatibility.BUILD_TARGET_VERSION,
193
+ compatibility.native?.platform || compatibility.platform,
194
+ getCurrentExtensionId()
195
+ ) || compatibility.updateCommand || compatibility.installCommand || DEFAULT_INSTALL_COMMAND;
196
+ }
197
+
198
+ function getStatusIconText(classification) {
199
+ switch (classification) {
200
+ case 'compatible':
201
+ return 'OK';
202
+ case 'update-available':
203
+ return '!';
204
+ default:
205
+ return 'X';
206
+ }
207
+ }
208
+
209
+ function getCompatibilityStatusTitle(classification) {
210
+ switch (classification) {
211
+ case 'compatible':
212
+ return 'Native host compatible';
213
+ case 'update-available':
214
+ return 'Native host update available';
215
+ default:
216
+ return 'Native host incompatible';
217
+ }
218
+ }
219
+
220
+ function formatVersion(version) {
221
+ const value = String(version || '').trim();
222
+ if (!value) {
223
+ return 'unknown';
224
+ }
225
+ return value.startsWith('v') ? value : `v${value}`;
226
+ }
227
+
228
+ function getNativeStatusMessage(statusValue, classification) {
229
+ if (classification === 'update-available') {
230
+ return 'Native host update available. Run the update command, then reload the extension.';
231
+ }
232
+ switch (statusValue) {
233
+ case 'native_too_old':
234
+ return 'Native host update required. Run the install command, then reload the extension.';
235
+ case 'protocol_unsupported':
236
+ return 'Native host protocol mismatch. Update the native host and extension together.';
237
+ case 'extension_too_old':
238
+ return 'Extension update required. Update the Chrome extension before running Codex.';
239
+ case 'native_unhealthy':
240
+ return 'Native host connected, but local Codex is not ready. Check the panel diagnostics.';
241
+ case 'native_missing':
242
+ return 'Install the local native host before running Codex.';
243
+ default:
244
+ return 'Native host is not compatible. Update the native host, then reload the extension.';
245
+ }
246
+ }
247
+ })();
@@ -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.8.5';
15
+ const BUILD_TARGET_VERSION = '1.9.0';
16
16
  const DEFAULT_CHROME_EXTENSION_ID = 'illdpneeeopfffmiepaejglgmhpmdhdc';
17
17
  const REQUIRED_CAPABILITIES = Object.freeze([
18
18
  'bridgePing',