codex-overleaf-link 2.3.6 → 2.4.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.
- package/README.md +59 -34
- package/README.zh-CN.md +543 -0
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +3 -0
- package/extension/src/content/activeTurnControl.js +1 -0
- package/extension/src/content/assetTransferBroker.js +2 -0
- package/extension/src/content/contentRuntime.js +53 -50
- package/extension/src/content/contextTray.js +4 -0
- package/extension/src/content/diagnosticsController.js +4 -0
- package/extension/src/content/diagnosticsPanel.js +128 -4
- package/extension/src/content/generated/content.bundle.js +583 -112
- package/extension/src/content/generated/content.bundle.meta.json +4 -3
- package/extension/src/content/legacyGlobalRegistry.js +1 -0
- package/extension/src/content/modelPicker.js +21 -9
- package/extension/src/content/modelPickerSupport.js +38 -1
- package/extension/src/content/nativeCompatibilityController.js +4 -1
- package/extension/src/content/otWarmMirror.js +34 -30
- package/extension/src/content/otWarmMirrorController.js +20 -0
- package/extension/src/content/pageBridgeClient.js +2 -0
- package/extension/src/content/runResultActions.js +16 -1
- package/extension/src/content/runTimelineView.js +1 -1
- package/extension/src/content/sessionForkController.js +20 -11
- package/extension/src/content/trackedChangeCaptureController.js +153 -0
- package/extension/src/content/writebackOrchestrator.js +31 -0
- package/extension/src/page/binaryAssetUploader.js +101 -29
- package/extension/src/page/overleafRealtimeObserver.js +4 -1
- package/extension/src/page/textFileCreator.js +493 -0
- package/extension/src/page/trackedChangeCapture.js +342 -0
- package/extension/src/page/trackedChangesLifecycle.js +145 -149
- package/extension/src/page/treeOperations.js +30 -2
- package/extension/src/page/writebackRouter.js +94 -48
- package/extension/src/pageBridge.js +62 -25
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/pageRpcContract.js +2 -1
- package/extension/src/shared/sessionState.js +6 -2
- package/extension/src/shared/storageDb.js +10 -12
- package/extension/src/shared/storageRunActions.js +29 -1
- package/extension/src/shared/writebackSettlement.js +19 -5
- package/extension/styles/panel.css +55 -10
- package/native-host/src/taskRunnerRuntime.js +25 -0
- package/package.json +5 -1
|
@@ -397,7 +397,7 @@
|
|
|
397
397
|
if (!result || typeof result !== 'object' || result.ok === false) return result;
|
|
398
398
|
if (Array.isArray(result.skipped) && result.skipped.length > 0) return result;
|
|
399
399
|
const expectedFiles = Array.isArray(run?.undoExpectedFiles) ? run.undoExpectedFiles : [];
|
|
400
|
-
if (!expectedFiles.length || isUndoVerifiedContentMatching(run, result)) return result;
|
|
400
|
+
if (!expectedFiles.length || isUndoVerifiedContentMatching(run, result, options)) return result;
|
|
401
401
|
const path = expectedFiles.find(entry => typeof entry?.path === 'string')?.path || '';
|
|
402
402
|
appendSyntheticFailure(result, options.buildFailure?.('undo_not_verified', { path, type: 'undo' }, {
|
|
403
403
|
changedDocument: true,
|
|
@@ -407,15 +407,18 @@
|
|
|
407
407
|
return result;
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
-
function isUndoVerifiedContentMatching(run, result) {
|
|
410
|
+
function isUndoVerifiedContentMatching(run, result, options = {}) {
|
|
411
411
|
const expectedByPath = new Map((run?.undoExpectedFiles || [])
|
|
412
412
|
.filter(file => typeof file?.path === 'string' && typeof file?.content === 'string')
|
|
413
413
|
.map(file => [normalizeSettlementPath(file.path), file.content])
|
|
414
414
|
.filter(([path]) => path));
|
|
415
415
|
if (!expectedByPath.size) return true;
|
|
416
|
+
const postByPath = new Map((Array.isArray(options?.postFiles) ? options.postFiles : [])
|
|
417
|
+
.filter(file => typeof file?.path === 'string' && typeof file?.content === 'string')
|
|
418
|
+
.map(file => [normalizeSettlementPath(file.path), file.content]));
|
|
416
419
|
const applied = Array.isArray(result?.applied) ? result.applied : [];
|
|
417
420
|
return Array.from(expectedByPath).every(([path, expected]) =>
|
|
418
|
-
applied.some(entry => isVerifiedUndoEntryForPath(entry, path, expected))
|
|
421
|
+
applied.some(entry => isVerifiedUndoEntryForPath(entry, path, expected, postByPath.get(path)))
|
|
419
422
|
);
|
|
420
423
|
}
|
|
421
424
|
|
|
@@ -438,7 +441,7 @@
|
|
|
438
441
|
));
|
|
439
442
|
}
|
|
440
443
|
|
|
441
|
-
function isVerifiedUndoEntryForPath(entry, path, expectedContent) {
|
|
444
|
+
function isVerifiedUndoEntryForPath(entry, path, expectedContent, postContent) {
|
|
442
445
|
const inner = entry?.result || {};
|
|
443
446
|
if (inner.ok === false) return false;
|
|
444
447
|
const normalizedPath = normalizeSettlementPath(path);
|
|
@@ -456,7 +459,18 @@
|
|
|
456
459
|
&& inner.verifiedContent === expectedContent;
|
|
457
460
|
}
|
|
458
461
|
if (key === `snapshot-undo:${normalizedPath}`) {
|
|
459
|
-
|
|
462
|
+
if (inner.verifiedContent === expectedContent) return true;
|
|
463
|
+
const proof = inner.undoRebaseProof, before = proof?.beforeUndoContent;
|
|
464
|
+
if (inner.verified !== true || proof?.version !== 1
|
|
465
|
+
|| normalizeSettlementPath(proof.path) !== normalizedPath
|
|
466
|
+
|| typeof before !== 'string' || typeof postContent !== 'string' || !postContent
|
|
467
|
+
|| typeof inner.verifiedContent !== 'string') return false;
|
|
468
|
+
// The page observed prefix + post + suffix before Undo. Prove that only
|
|
469
|
+
// this run's post-image became its pre-image, preserving both envelopes.
|
|
470
|
+
const start = before.indexOf(postContent);
|
|
471
|
+
if (start < 0 || before.indexOf(postContent, start + 1) >= 0) return false;
|
|
472
|
+
return inner.verifiedContent === before.slice(0, start) + expectedContent
|
|
473
|
+
+ before.slice(start + postContent.length);
|
|
460
474
|
}
|
|
461
475
|
return false;
|
|
462
476
|
}
|
|
@@ -1029,11 +1029,21 @@
|
|
|
1029
1029
|
}
|
|
1030
1030
|
|
|
1031
1031
|
#codex-overleaf-panel .codex-diagnostics-menu {
|
|
1032
|
-
position:
|
|
1032
|
+
position: fixed;
|
|
1033
1033
|
z-index: 2147483647;
|
|
1034
|
-
top:
|
|
1035
|
-
right:
|
|
1036
|
-
|
|
1034
|
+
top: 44px;
|
|
1035
|
+
right: 12px;
|
|
1036
|
+
bottom: auto;
|
|
1037
|
+
left: auto;
|
|
1038
|
+
margin: 0;
|
|
1039
|
+
box-sizing: border-box;
|
|
1040
|
+
width: min(300px, calc(100vw - 24px));
|
|
1041
|
+
max-width: calc(100vw - 24px);
|
|
1042
|
+
max-height: calc(100vh - 24px);
|
|
1043
|
+
overflow: auto;
|
|
1044
|
+
overscroll-behavior: contain;
|
|
1045
|
+
overflow-wrap: anywhere;
|
|
1046
|
+
color: var(--tl-fg-2);
|
|
1037
1047
|
border: 1px solid var(--tl-border-strong);
|
|
1038
1048
|
border-radius: 6px;
|
|
1039
1049
|
background: var(--tl-surface-2);
|
|
@@ -1084,15 +1094,30 @@
|
|
|
1084
1094
|
z-index: 2147483647;
|
|
1085
1095
|
top: 44px;
|
|
1086
1096
|
right: 12px;
|
|
1087
|
-
|
|
1088
|
-
|
|
1097
|
+
bottom: auto;
|
|
1098
|
+
left: auto;
|
|
1099
|
+
margin: 0;
|
|
1100
|
+
padding: 0;
|
|
1101
|
+
box-sizing: border-box;
|
|
1102
|
+
width: min(560px, calc(100vw - 24px));
|
|
1103
|
+
max-width: calc(100vw - 24px);
|
|
1104
|
+
max-height: min(640px, calc(100vh - 24px));
|
|
1089
1105
|
overflow: auto;
|
|
1106
|
+
overscroll-behavior: contain;
|
|
1107
|
+
overflow-wrap: anywhere;
|
|
1108
|
+
color: var(--tl-fg-2);
|
|
1090
1109
|
border: 1px solid var(--tl-border-strong);
|
|
1091
1110
|
border-radius: 8px;
|
|
1092
1111
|
background: var(--tl-surface-1);
|
|
1093
1112
|
box-shadow: 0 14px 34px rgba(0, 0, 0, 0.48);
|
|
1094
1113
|
}
|
|
1095
1114
|
|
|
1115
|
+
#codex-overleaf-panel .codex-diagnostics-menu::backdrop,
|
|
1116
|
+
#codex-overleaf-panel .codex-diagnostics-result::backdrop {
|
|
1117
|
+
background: transparent;
|
|
1118
|
+
pointer-events: none;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1096
1121
|
#codex-overleaf-panel .codex-diagnostics-result[hidden] {
|
|
1097
1122
|
display: none;
|
|
1098
1123
|
}
|
|
@@ -1821,9 +1846,12 @@
|
|
|
1821
1846
|
#codex-overleaf-panel .codex-plugin-confirm::backdrop { background: transparent; }
|
|
1822
1847
|
|
|
1823
1848
|
#codex-overleaf-panel .codex-plugin-confirm-card {
|
|
1849
|
+
display: flex;
|
|
1850
|
+
flex-direction: column;
|
|
1851
|
+
box-sizing: border-box;
|
|
1824
1852
|
width: 100%;
|
|
1825
1853
|
max-height: min(520px, calc(100vh - 28px));
|
|
1826
|
-
overflow:
|
|
1854
|
+
overflow: auto;
|
|
1827
1855
|
border: 1px solid var(--tl-border-strong);
|
|
1828
1856
|
border-radius: 8px;
|
|
1829
1857
|
background: var(--tl-surface-1);
|
|
@@ -1832,6 +1860,7 @@
|
|
|
1832
1860
|
|
|
1833
1861
|
#codex-overleaf-panel .codex-plugin-confirm-head {
|
|
1834
1862
|
display: flex;
|
|
1863
|
+
flex: 0 0 auto;
|
|
1835
1864
|
align-items: center;
|
|
1836
1865
|
gap: 10px;
|
|
1837
1866
|
padding: 14px 14px 12px;
|
|
@@ -1860,6 +1889,8 @@
|
|
|
1860
1889
|
}
|
|
1861
1890
|
|
|
1862
1891
|
#codex-overleaf-panel .codex-plugin-confirm-body {
|
|
1892
|
+
flex: 0 1 auto;
|
|
1893
|
+
min-height: 0;
|
|
1863
1894
|
max-height: 300px;
|
|
1864
1895
|
overflow: auto;
|
|
1865
1896
|
padding: 12px 14px;
|
|
@@ -1872,6 +1903,9 @@
|
|
|
1872
1903
|
|
|
1873
1904
|
#codex-overleaf-panel .codex-plugin-confirm-actions {
|
|
1874
1905
|
display: flex;
|
|
1906
|
+
flex: 0 0 auto;
|
|
1907
|
+
flex-wrap: wrap;
|
|
1908
|
+
align-items: stretch;
|
|
1875
1909
|
justify-content: flex-end;
|
|
1876
1910
|
gap: 8px;
|
|
1877
1911
|
padding: 12px 14px 14px;
|
|
@@ -1879,12 +1913,23 @@
|
|
|
1879
1913
|
}
|
|
1880
1914
|
|
|
1881
1915
|
#codex-overleaf-panel .codex-plugin-confirm-actions button {
|
|
1882
|
-
|
|
1883
|
-
|
|
1916
|
+
display: flex;
|
|
1917
|
+
flex: 1 1 auto;
|
|
1918
|
+
align-items: center;
|
|
1919
|
+
justify-content: center;
|
|
1920
|
+
box-sizing: border-box;
|
|
1921
|
+
min-width: min(72px, 100%);
|
|
1922
|
+
max-width: 100%;
|
|
1923
|
+
min-height: 34px;
|
|
1924
|
+
height: auto;
|
|
1884
1925
|
border: 1px solid var(--tl-border-strong);
|
|
1885
1926
|
border-radius: 6px;
|
|
1886
|
-
padding:
|
|
1927
|
+
padding: 7px 12px;
|
|
1887
1928
|
font-weight: 650;
|
|
1929
|
+
line-height: 1.35;
|
|
1930
|
+
text-align: center;
|
|
1931
|
+
white-space: normal;
|
|
1932
|
+
overflow-wrap: anywhere;
|
|
1888
1933
|
}
|
|
1889
1934
|
|
|
1890
1935
|
#codex-overleaf-panel .codex-plugin-confirm-cancel {
|
|
@@ -82,6 +82,10 @@ async function handleRequest(request, env = process.env, emit = () => {}) {
|
|
|
82
82
|
return handleMirrorStatus(request, env);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
if (request.method === 'mirror.invalidate') {
|
|
86
|
+
return handleMirrorInvalidate(request, env);
|
|
87
|
+
}
|
|
88
|
+
|
|
85
89
|
if (request.method === 'mirror.scanSensitive') {
|
|
86
90
|
return handleMirrorScanSensitive(request, env);
|
|
87
91
|
}
|
|
@@ -709,6 +713,27 @@ async function handleMirrorConfirmWriteback(request, env) {
|
|
|
709
713
|
}
|
|
710
714
|
}
|
|
711
715
|
|
|
716
|
+
function handleMirrorInvalidate(request, env) {
|
|
717
|
+
const projectId = request.params?.projectId;
|
|
718
|
+
if (typeof projectId !== 'string' || !projectId.trim()) {
|
|
719
|
+
return errorResponse(request.id, 'invalid_project_id', 'Mirror invalidation requires an explicit project id.');
|
|
720
|
+
}
|
|
721
|
+
const projectKey = resolveProjectKey({ projectId });
|
|
722
|
+
const lockToken = acquireProjectLock(projectKey);
|
|
723
|
+
if (!lockToken) {
|
|
724
|
+
return errorResponse(request.id, 'project_locked', `Project ${projectKey} is currently in use by codex.run`);
|
|
725
|
+
}
|
|
726
|
+
try {
|
|
727
|
+
const { markMirrorDirty } = require('./mirrorWorkspace');
|
|
728
|
+
markMirrorDirty({ projectId, rootDir: env.CODEX_OVERLEAF_MIRROR_ROOT, reason: 'overleaf_undo' });
|
|
729
|
+
return okResponse(request.id, { invalidated: true, projectKey });
|
|
730
|
+
} catch (error) {
|
|
731
|
+
return errorResponse(request.id, 'mirror_invalidation_failed', error.message);
|
|
732
|
+
} finally {
|
|
733
|
+
releaseProjectLock(projectKey, lockToken);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
712
737
|
function handleMirrorStatus(request, env) {
|
|
713
738
|
const { getMirrorStatus } = require('./mirrorWorkspace');
|
|
714
739
|
const params = request.params || {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-overleaf-link",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Cross-platform Chrome bridge that connects Codex to the active Overleaf project.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -17,9 +17,12 @@
|
|
|
17
17
|
"build:content": "node scripts/build-content-bundle.mjs",
|
|
18
18
|
"check:module-graph": "node scripts/check-content-module-graph.mjs",
|
|
19
19
|
"test": "npm run check:module-graph && node scripts/run-tests.mjs",
|
|
20
|
+
"test:fast": "npm run check:module-graph && node scripts/run-tests.mjs --fast",
|
|
21
|
+
"test:focus": "npm run check:module-graph && node scripts/run-tests.mjs",
|
|
20
22
|
"check:architecture": "node scripts/check-architecture-budget.mjs --enforce-target",
|
|
21
23
|
"benchmark:large": "node scripts/benchmark-large-project.mjs --gate",
|
|
22
24
|
"smoke:extension": "npm run build:content && node scripts/smoke-extension.mjs",
|
|
25
|
+
"smoke:prepare:chrome": "npm run build:content && npm run test:fast && npm run install:managed",
|
|
23
26
|
"verify:release": "node scripts/verify-release.mjs",
|
|
24
27
|
"verify:source": "node scripts/verify-release.mjs --source-hygiene-only",
|
|
25
28
|
"verify:release-artifacts": "node scripts/verify-release-artifacts.mjs",
|
|
@@ -60,6 +63,7 @@
|
|
|
60
63
|
"scripts/uninstall-native-host.mjs",
|
|
61
64
|
"scripts/verify-npm-package.mjs",
|
|
62
65
|
"README.md",
|
|
66
|
+
"README.zh-CN.md",
|
|
63
67
|
"package.json"
|
|
64
68
|
],
|
|
65
69
|
"devDependencies": {
|