codex-overleaf-link 2.3.6 → 2.4.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 +62 -34
- package/README.zh-CN.md +546 -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 +122 -118
- 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 +1233 -550
- 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/panelMaintenance.js +8 -4
- package/extension/src/content/recentProjects.js +354 -355
- package/extension/src/content/runResultActions.js +16 -1
- package/extension/src/content/runTimelineView.js +9 -11
- package/extension/src/content/scopedPersistenceCoordinator.js +2 -1
- package/extension/src/content/scopedPersistencePanelState.js +45 -2
- package/extension/src/content/sessionForkController.js +20 -11
- package/extension/src/content/sessionPersistence.js +4 -1
- package/extension/src/content/settingsPanel.js +16 -2
- 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/saveState.js +44 -1
- package/extension/src/page/textFileCreator.js +493 -0
- package/extension/src/page/trackedChangeCapture.js +342 -0
- package/extension/src/page/trackedChangesLifecycle.js +149 -150
- package/extension/src/page/treeOperations.js +40 -29
- package/extension/src/page/writebackRouter.js +95 -49
- package/extension/src/pageBridge.js +65 -25
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/i18n.js +94 -40
- package/extension/src/shared/pageRpcContract.js +2 -1
- package/extension/src/shared/sessionState.js +6 -2
- package/extension/src/shared/storageDb.js +11 -12
- package/extension/src/shared/storageRunActions.js +73 -1
- package/extension/src/shared/writebackSettlement.js +19 -5
- package/extension/styles/panel.css +254 -405
- package/native-host/src/codexSessionRunner.js +41 -38
- package/native-host/src/codexSessionTiming.js +68 -0
- package/native-host/src/readProgressGuard.js +84 -17
- package/native-host/src/taskRunnerRuntime.js +25 -0
- package/package.json +5 -1
|
@@ -636,7 +636,7 @@
|
|
|
636
636
|
undoExpectedFiles: normalizeRunFiles(run.undoExpectedFiles),
|
|
637
637
|
undoStatus: sanitizeAssistantVisibleText(run.undoStatus),
|
|
638
638
|
nativeRequestId: sanitizeAssistantVisibleText(run.nativeRequestId),
|
|
639
|
-
codexTurnId: sanitizeAssistantVisibleText(run.codexTurnId),
|
|
639
|
+
codexThreadId: sanitizeAssistantVisibleText(run.codexThreadId), codexTurnId: sanitizeAssistantVisibleText(run.codexTurnId),
|
|
640
640
|
forkSnapshot: run.forkSnapshot === true,
|
|
641
641
|
forkSourceRunId: sanitizeAssistantVisibleText(run.forkSourceRunId),
|
|
642
642
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
@@ -656,6 +656,9 @@
|
|
|
656
656
|
if (run.changedDocument === true) {
|
|
657
657
|
normalized.changedDocument = true;
|
|
658
658
|
}
|
|
659
|
+
if (Array.isArray(run.trackedChangeCaptures) && run.trackedChangeCaptures.length && !run.forkSnapshot) {
|
|
660
|
+
normalized.trackedChangeCaptures = sanitizeAssistantVisibleValue(run.trackedChangeCaptures);
|
|
661
|
+
}
|
|
659
662
|
applyTrackedChangeStatus(normalized, run.trackedChangeStatus);
|
|
660
663
|
|
|
661
664
|
return normalized;
|
|
@@ -1215,7 +1218,7 @@
|
|
|
1215
1218
|
undoExpectedFiles: undoPayload.undoExpectedFiles,
|
|
1216
1219
|
undoStatus: summarizeTextForStorage(run.undoStatus, 'undo status'),
|
|
1217
1220
|
nativeRequestId: normalizeTextField(run.nativeRequestId, 160),
|
|
1218
|
-
codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
1221
|
+
codexThreadId: normalizeTextField(run.codexThreadId, 160), codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
1219
1222
|
forkSnapshot: run.forkSnapshot === true,
|
|
1220
1223
|
forkSourceRunId: normalizeTextField(run.forkSourceRunId, 160),
|
|
1221
1224
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
@@ -1627,6 +1630,7 @@
|
|
|
1627
1630
|
setActiveSession,
|
|
1628
1631
|
updateActiveSession,
|
|
1629
1632
|
normalizeRuns,
|
|
1633
|
+
normalizeProjectReferenceFiles,
|
|
1630
1634
|
prepareStateForStorage,
|
|
1631
1635
|
estimateJsonBytes,
|
|
1632
1636
|
computeSafeTaskSummary
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
(function initStorageDb(root, factory) {
|
|
2
2
|
if (typeof module === 'object' && module.exports) {
|
|
3
3
|
module.exports = factory(require('./storageRunActions'), require('./runInputQueue'),
|
|
4
|
-
require('./settlementFacts'), require('./storageSessionClaims'));
|
|
4
|
+
require('./settlementFacts'), require('./storageSessionClaims'), require('./sessionState'));
|
|
5
5
|
} else {
|
|
6
6
|
root.CodexOverleafModuleRegistry.define('StorageDb', [
|
|
7
7
|
'StorageRunActions',
|
|
8
8
|
'RunInputQueue',
|
|
9
9
|
'SettlementFacts',
|
|
10
|
-
'StorageSessionClaims'
|
|
10
|
+
'StorageSessionClaims',
|
|
11
|
+
'SessionState'
|
|
11
12
|
], factory);
|
|
12
13
|
}
|
|
13
|
-
})(typeof globalThis !== 'undefined' ? globalThis : window, function storageDbFactory(StorageRunActions, RunInputQueue, SettlementFacts, StorageSessionClaims) {
|
|
14
|
+
})(typeof globalThis !== 'undefined' ? globalThis : window, function storageDbFactory(StorageRunActions, RunInputQueue, SettlementFacts, StorageSessionClaims, SessionState) {
|
|
14
15
|
'use strict';
|
|
15
|
-
if (!StorageRunActions?.compactRunsForStorage || !StorageRunActions?.compactRunActionPayload || !StorageRunActions?.compactProviderSnapshot || !StorageRunActions?.compactStructuredEventValue || !StorageRunActions?.hashString || !RunInputQueue?.compactForStorage || !SettlementFacts?.compactSettlementFacts || !StorageSessionClaims?.createSessionClaimer) {
|
|
16
|
+
if (!StorageRunActions?.compactRunsForStorage || !StorageRunActions?.compactRunActionPayload || !StorageRunActions?.compactProviderSnapshot || !StorageRunActions?.compactRunExecutionSnapshot || !StorageRunActions?.compactStructuredEventValue || !StorageRunActions?.hashString || !RunInputQueue?.compactForStorage || !SettlementFacts?.compactSettlementFacts || !StorageSessionClaims?.createSessionClaimer) {
|
|
16
17
|
throw new Error('Codex Overleaf storage run-action helpers are unavailable.');
|
|
17
18
|
}
|
|
18
19
|
// IndexedDB versions are monotonic; v2.0 RC profiles have already opened v3.
|
|
@@ -279,6 +280,7 @@
|
|
|
279
280
|
codexThreadId: typeof input.codexThreadId === 'string' ? input.codexThreadId : '',
|
|
280
281
|
status: typeof input.status === 'string' && input.status ? input.status : 'active',
|
|
281
282
|
focusFiles: normalizePathList(input.focusFiles),
|
|
283
|
+
projectReferenceFiles: SessionState.normalizeProjectReferenceFiles(input.projectReferenceFiles),
|
|
282
284
|
pendingInputs: RunInputQueue.compactForStorage(input.pendingInputs, {
|
|
283
285
|
normalizeField: normalizeTextField,
|
|
284
286
|
normalizeDisplay: normalizeDisplayTextForStorage,
|
|
@@ -650,20 +652,15 @@
|
|
|
650
652
|
}
|
|
651
653
|
|
|
652
654
|
function compactRunsForStorage(runs, options) {
|
|
653
|
-
return StorageRunActions.compactRunsForStorage(
|
|
654
|
-
runs,
|
|
655
|
-
options,
|
|
656
|
-
SESSION_STORAGE_LIMITS.maxRunsPerSession,
|
|
657
|
-
compactRunForStorage
|
|
658
|
-
);
|
|
655
|
+
return StorageRunActions.compactRunsForStorage(runs, options, SESSION_STORAGE_LIMITS.maxRunsPerSession, compactRunForStorage);
|
|
659
656
|
}
|
|
660
|
-
|
|
661
657
|
function compactRunForStorage(run, keepActionPayload) {
|
|
662
658
|
var actionPayload = StorageRunActions.compactRunActionPayload(run, keepActionPayload);
|
|
663
659
|
var compact = {
|
|
664
660
|
id: run.id,
|
|
665
661
|
task: normalizeDisplayTextForStorage(run.task || 'untitled task', SESSION_STORAGE_LIMITS.taskChars),
|
|
666
662
|
mode: typeof run.mode === 'string' ? redactSecretLikeText(run.mode) : '', ...StorageRunActions.compactProviderSnapshot(run),
|
|
663
|
+
...StorageRunActions.compactRunExecutionSnapshot(run, function (text) { return normalizeTextField(text, 4096); }),
|
|
667
664
|
model: normalizeTextField(run.model, 80),
|
|
668
665
|
reasoningEffort: typeof run.reasoningEffort === 'string' ? redactSecretLikeText(run.reasoningEffort) : '',
|
|
669
666
|
speedTier: typeof run.speedTier === 'string' ? redactSecretLikeText(run.speedTier) : '',
|
|
@@ -679,9 +676,10 @@
|
|
|
679
676
|
undoBaseFiles: actionPayload.undoBaseFiles,
|
|
680
677
|
undoTrackedChanges: actionPayload.undoTrackedChanges,
|
|
681
678
|
undoExpectedFiles: actionPayload.undoExpectedFiles,
|
|
679
|
+
...(actionPayload.trackedChangeCaptures ? { trackedChangeCaptures: actionPayload.trackedChangeCaptures } : {}),
|
|
682
680
|
undoStatus: normalizeDisplayTextForStorage(run.undoStatus, SESSION_STORAGE_LIMITS.statusTextChars),
|
|
683
681
|
nativeRequestId: normalizeTextField(run.nativeRequestId, 160),
|
|
684
|
-
codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
682
|
+
codexThreadId: normalizeTextField(run.codexThreadId, 160), codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
685
683
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
686
684
|
queueItemId: normalizeTextField(run.queueItemId, 160)
|
|
687
685
|
};
|
|
@@ -1345,6 +1343,7 @@
|
|
|
1345
1343
|
clearStore: clearStore,
|
|
1346
1344
|
clearAllStores: clearAllStores,
|
|
1347
1345
|
buildSessionRecord: buildSessionRecord,
|
|
1346
|
+
mergeSessionReviewState: StorageRunActions.mergeSessionReviewState,
|
|
1348
1347
|
buildTurnRecord: buildTurnRecord,
|
|
1349
1348
|
buildEventRecord: buildEventRecord,
|
|
1350
1349
|
buildArtifactRecord: buildArtifactRecord,
|
|
@@ -70,7 +70,13 @@
|
|
|
70
70
|
} catch (_error) {
|
|
71
71
|
return empty;
|
|
72
72
|
}
|
|
73
|
-
|
|
73
|
+
if (getUtf8ByteLength(serialized) > MAX_PERSISTED_ACTION_BYTES_PER_RUN) return empty;
|
|
74
|
+
const captures = cloneSerializableArray(run.trackedChangeCaptures);
|
|
75
|
+
if (captures.length) {
|
|
76
|
+
const extended = { ...payload, trackedChangeCaptures: captures };
|
|
77
|
+
if (getUtf8ByteLength(JSON.stringify(extended)) <= MAX_PERSISTED_ACTION_BYTES_PER_RUN) return extended;
|
|
78
|
+
}
|
|
79
|
+
return payload; // Optional capture evidence must never evict a mature Undo payload.
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
function emptyActionPayload() {
|
|
@@ -102,6 +108,27 @@
|
|
|
102
108
|
return value.length * 2;
|
|
103
109
|
}
|
|
104
110
|
|
|
111
|
+
// Persist only execution metadata; never infer a missing historical setting.
|
|
112
|
+
function compactRunExecutionSnapshot(run, normalizeString) {
|
|
113
|
+
var snapshot = run && run.executionSnapshot;
|
|
114
|
+
if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) return {};
|
|
115
|
+
var normalize = typeof normalizeString === 'function' ? normalizeString : String;
|
|
116
|
+
var compact = {};
|
|
117
|
+
var fields = ['schemaVersion', 'mode', 'providerId', 'providerRevision', 'model',
|
|
118
|
+
'reasoningEffort', 'speedTier', 'autoRecompile', 'requireReviewing', 'capturedAt', 'source'];
|
|
119
|
+
for (var key of fields) {
|
|
120
|
+
if (!Object.prototype.hasOwnProperty.call(snapshot, key)) continue;
|
|
121
|
+
var value = snapshot[key];
|
|
122
|
+
if (typeof value === 'string') compact[key] = normalize(value);
|
|
123
|
+
else if (value === null || typeof value === 'number' || typeof value === 'boolean') compact[key] = value;
|
|
124
|
+
}
|
|
125
|
+
if (Array.isArray(snapshot.focusFiles)) {
|
|
126
|
+
compact.focusFiles = snapshot.focusFiles.slice(0, 100)
|
|
127
|
+
.filter(function (value) { return typeof value === 'string'; }).map(normalize);
|
|
128
|
+
}
|
|
129
|
+
return { executionSnapshot: compact };
|
|
130
|
+
}
|
|
131
|
+
|
|
105
132
|
function compactProviderSnapshot(value) {
|
|
106
133
|
return {
|
|
107
134
|
providerId: typeof value.providerId === 'string' && value.providerId ? value.providerId : 'builtin',
|
|
@@ -132,6 +159,49 @@
|
|
|
132
159
|
return out;
|
|
133
160
|
}
|
|
134
161
|
|
|
162
|
+
// Review terminal states are monotonic even when a later session snapshot is stale.
|
|
163
|
+
function mergeSessionReviewState(incoming, existing, reviewRunIds) {
|
|
164
|
+
if (!existing || incoming.id !== existing.id || incoming.projectId !== existing.projectId
|
|
165
|
+
|| !incoming.accountScopeId || incoming.accountScopeId !== existing.accountScopeId) return incoming;
|
|
166
|
+
var terminal = run => ['accepted', 'rejected'].includes(run?.trackedChangeStatus);
|
|
167
|
+
var incomingRuns = new Map((incoming.runs || []).map(run => [run.id, run]));
|
|
168
|
+
var existingRuns = new Map((existing.runs || []).map(run => [run.id, run]));
|
|
169
|
+
var requestedIds = new Set(reviewRunIds || []);
|
|
170
|
+
var explicitReview = Array.from(requestedIds).some(id =>
|
|
171
|
+
['accepted', 'rejected', 'needs_review'].includes(incomingRuns.get(id)?.trackedChangeStatus));
|
|
172
|
+
var newer = (Date.parse(incoming.updatedAt) || 0) >= (Date.parse(existing.updatedAt) || 0);
|
|
173
|
+
if (!newer && !explicitReview) return incoming;
|
|
174
|
+
var base = newer ? incoming : existing;
|
|
175
|
+
var fields = ['trackedChangeStatus', 'undoStatus', 'undoTrackedChanges', 'undoExpectedFiles',
|
|
176
|
+
'undoOperations', 'undoBaseFiles', 'appliedOperations', 'trackedChangeCaptures', 'settlement', 'settlementFacts'];
|
|
177
|
+
var changed = false;
|
|
178
|
+
var runs = (base.runs || []).map(function (run) {
|
|
179
|
+
var previous = existingRuns.get(run.id), candidate = incomingRuns.get(run.id);
|
|
180
|
+
// Never revive a removed run or change the first durably recorded review decision.
|
|
181
|
+
var source = terminal(previous) ? previous
|
|
182
|
+
: explicitReview && requestedIds.has(run.id) ? candidate : null;
|
|
183
|
+
if (!source || source === run) return run;
|
|
184
|
+
if (source.runProjectId && source.runProjectId !== incoming.projectId) return run;
|
|
185
|
+
var merged = { ...run };
|
|
186
|
+
for (var field of fields) {
|
|
187
|
+
if (Object.prototype.hasOwnProperty.call(source, field)) {
|
|
188
|
+
merged[field] = JSON.parse(JSON.stringify(source[field]));
|
|
189
|
+
} else {
|
|
190
|
+
delete merged[field];
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
changed = true;
|
|
194
|
+
return merged;
|
|
195
|
+
});
|
|
196
|
+
if (!changed) return base;
|
|
197
|
+
var merged = { ...base, runs };
|
|
198
|
+
if (explicitReview && !newer) {
|
|
199
|
+
merged.updatedAt = new Date(Math.max(Date.now(), Date.parse(existing.updatedAt) || 0,
|
|
200
|
+
Date.parse(incoming.updatedAt) || 0) + 1).toISOString();
|
|
201
|
+
}
|
|
202
|
+
return merged;
|
|
203
|
+
}
|
|
204
|
+
|
|
135
205
|
function hashString(value) {
|
|
136
206
|
var hash = 2166136261;
|
|
137
207
|
var text = String(value || '');
|
|
@@ -144,9 +214,11 @@
|
|
|
144
214
|
|
|
145
215
|
return {
|
|
146
216
|
compactStructuredEventValue: compactStructuredEventValue,
|
|
217
|
+
mergeSessionReviewState: mergeSessionReviewState,
|
|
147
218
|
compactRunsForStorage: compactRunsForStorage,
|
|
148
219
|
compactRunActionPayload: compactRunActionPayload,
|
|
149
220
|
compactProviderSnapshot: compactProviderSnapshot,
|
|
221
|
+
compactRunExecutionSnapshot: compactRunExecutionSnapshot,
|
|
150
222
|
hashString: hashString
|
|
151
223
|
};
|
|
152
224
|
});
|
|
@@ -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
|
}
|