codex-overleaf-link 1.8.6 → 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 (72) 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/managedInstall.js +393 -0
  63. package/native-host/src/managedLauncherRuntime.js +71 -0
  64. package/native-host/src/nativeHostPlatform.js +16 -0
  65. package/native-host/src/runtimeInstaller.js +6 -1
  66. package/native-host/src/taskRunnerRuntime.js +8 -0
  67. package/native-host/src/updateArchive.js +253 -0
  68. package/native-host/src/updateManager.js +548 -0
  69. package/native-host/src/updateTrust.js +156 -0
  70. package/package.json +11 -2
  71. package/scripts/install-managed.mjs +64 -0
  72. package/scripts/uninstall-managed.mjs +48 -0
@@ -0,0 +1,142 @@
1
+ // Writeback project-ID guard: page-side dispatch gate that runs BEFORE any
2
+ // other readiness / openFile / staleness check on every writeback.
3
+ //
4
+ // Three fail-closed abort branches:
5
+ // • editorProjectId === null → editor_project_id_unavailable
6
+ // • runProjectId missing/empty → editor_project_id_unavailable
7
+ // • runProjectId !== editorPID → aborted_project_changed
8
+ //
9
+ // Hydration tolerance: Overleaf's `window._ide.project._id` is observably null
10
+ // for ~200–1000 ms after page load / SPA route change while the editor module
11
+ // hydrates. The guard retries the page-side reader with a 100/300/700 ms
12
+ // backoff (~1100 ms ceiling) before the null abort. Mismatch (runId !==
13
+ // editorId) short-circuits without retry because that means hydration
14
+ // completed to a *different* project and waiting won't fix it.
15
+ //
16
+ // Extracted from pageBridge.js to keep that file under its 2200-line budget;
17
+ // this module is the single source of truth for the guard surface and the
18
+ // only place that constructs the abort dispatch result shape.
19
+ (function initCodexOverleafWriteGuard(root, factory) {
20
+ if (typeof module === 'object' && module.exports) {
21
+ module.exports = factory();
22
+ } else {
23
+ root.CodexOverleafWriteGuard = factory();
24
+ }
25
+ })(typeof window !== 'undefined' ? window : globalThis, function writeGuardFactory() {
26
+ 'use strict';
27
+
28
+ const WRITE_GUARD_HYDRATION_RETRY_MS = [100, 300, 700]; // ~1100 ms ceiling
29
+
30
+ const ABORT_USER_MESSAGES = {
31
+ aborted_project_changed: 'Codex stopped a write because Overleaf switched to a different project mid-run.',
32
+ editor_project_id_unavailable: 'Codex could not confirm which Overleaf project the editor is showing, so it did not write.'
33
+ };
34
+
35
+ const ABORT_NEXT_ACTIONS = {
36
+ aborted_project_changed: 'Reopen the original project and rerun the task if you still want this change.',
37
+ editor_project_id_unavailable: 'Refresh Overleaf and retry; if it persists, reload the extension.'
38
+ };
39
+
40
+ function create(deps = {}) {
41
+ const win = deps.window || (typeof globalThis !== 'undefined' ? globalThis : {});
42
+ const doc = deps.document || win.document || {};
43
+ // treeOperations is optional — only needed for the URL fallback in
44
+ // getEditorProjectIdPageSide. When omitted the URL source short-circuits
45
+ // and the guard relies only on `_ide.project._id` and `[data-project-id]`.
46
+ const treeOperations = deps.treeOperations || null;
47
+ const sleep = deps.sleep || (ms => new Promise(resolve => setTimeout(resolve, ms)));
48
+
49
+ // The acceptable sources for the editor's currently-shown project id, in
50
+ // order:
51
+ // 1. `window._ide.project._id` — the in-page IDE module's authoritative
52
+ // project id once the SPA has bound the project.
53
+ // 2. `[data-project-id]` on the CodeMirror root — best-effort second
54
+ // source for cases where `_ide.project` is still hydrating.
55
+ // 3. URL project id, but ONLY when it exactly matches the immutable
56
+ // runProjectId captured at run start. This keeps SPA-navigation
57
+ // safety: a different URL project still fails closed, while current
58
+ // Overleaf builds that no longer expose `_ide.project._id` can still
59
+ // write on a stable same-project page.
60
+ // When none of these sources can prove the same project, return null so
61
+ // the guard fails closed.
62
+ function getEditorProjectIdPageSide(expectedRunProjectId = '') {
63
+ try {
64
+ const ideId = win._ide && win._ide.project && win._ide.project._id;
65
+ if (typeof ideId === 'string' && ideId) return ideId;
66
+ } catch (_error) { /* swallow; fall through */ }
67
+ try {
68
+ const cmRoot = doc.querySelector && doc.querySelector('[data-project-id]');
69
+ const attr = cmRoot && cmRoot.getAttribute && cmRoot.getAttribute('data-project-id');
70
+ if (typeof attr === 'string' && attr) return attr;
71
+ } catch (_error) { /* swallow */ }
72
+ try {
73
+ const urlProjectId = treeOperations && treeOperations.getProjectId
74
+ ? (treeOperations.getProjectId() || null)
75
+ : null;
76
+ if (expectedRunProjectId && urlProjectId === expectedRunProjectId) {
77
+ return urlProjectId;
78
+ }
79
+ } catch (_error) { /* swallow */ }
80
+ return null;
81
+ }
82
+
83
+ async function runWriteGuard(params) {
84
+ const runId = params && typeof params.runProjectId === 'string' ? params.runProjectId : '';
85
+ let editorId = getEditorProjectIdPageSide(runId);
86
+ for (let attempt = 0; attempt < WRITE_GUARD_HYDRATION_RETRY_MS.length; attempt++) {
87
+ if (editorId) break;
88
+ await sleep(WRITE_GUARD_HYDRATION_RETRY_MS[attempt]);
89
+ editorId = getEditorProjectIdPageSide(runId);
90
+ }
91
+ if (!editorId) {
92
+ return abortDispatchResult('editor_project_id_unavailable', runId || null, null);
93
+ }
94
+ if (!runId) {
95
+ return abortDispatchResult('editor_project_id_unavailable', null, editorId);
96
+ }
97
+ if (runId !== editorId) {
98
+ return abortDispatchResult('aborted_project_changed', runId, editorId);
99
+ }
100
+ return null;
101
+ }
102
+
103
+ // operation: {} (not null) — the guard fires before any per-op dispatch
104
+ // so there's no specific operation to attribute the block to, but
105
+ // downstream audit/transcript code traverses operation.path and the
106
+ // like; an empty object lets defaults flow through cleanly.
107
+ function abortDispatchResult(code, runProjectId, editorProjectId) {
108
+ return {
109
+ ok: false,
110
+ applied: [],
111
+ skipped: [{
112
+ operation: {},
113
+ result: {
114
+ ok: false,
115
+ code,
116
+ reason: ABORT_USER_MESSAGES[code],
117
+ failure: {
118
+ code,
119
+ stage: 'write',
120
+ severity: 'blocked',
121
+ userMessage: ABORT_USER_MESSAGES[code],
122
+ nextAction: ABORT_NEXT_ACTIONS[code],
123
+ retryable: true,
124
+ terminalState: 'blocked',
125
+ changedDocument: false,
126
+ evidence: { runProjectId, editorProjectId }
127
+ }
128
+ }
129
+ }]
130
+ };
131
+ }
132
+
133
+ return {
134
+ runWriteGuard,
135
+ abortDispatchResult,
136
+ getEditorProjectIdPageSide,
137
+ WRITE_GUARD_HYDRATION_RETRY_MS
138
+ };
139
+ }
140
+
141
+ return { create, WRITE_GUARD_HYDRATION_RETRY_MS };
142
+ });