codex-overleaf-link 2.2.1 → 2.3.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 +25 -23
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/runtime-manifest.json +5 -71
- package/extension/src/background.js +53 -69
- package/extension/src/backgroundUpdateCoordinator.js +128 -66
- package/extension/src/content/applyResultFormatters.js +2 -3
- package/extension/src/content/contentRuntime.js +650 -1449
- package/extension/src/content/contextTray.js +4 -6
- package/extension/src/content/diagnosticsController.js +1 -2
- package/extension/src/content/diffReviewPanel.js +14 -13
- package/extension/src/content/generated/content.bundle.js +41370 -0
- package/extension/src/content/generated/content.bundle.meta.json +102 -0
- package/extension/src/content/legacyGlobalRegistry.js +129 -0
- package/extension/src/content/markdownText.js +5 -7
- package/extension/src/content/modelPicker.js +1 -1
- package/extension/src/content/modelPickerSupport.js +10 -5
- package/extension/src/content/moduleRegistryKernel.js +125 -0
- package/extension/src/content/nativeCompatibilityController.js +313 -0
- package/extension/src/content/otWarmMirror.js +7 -5
- package/extension/src/content/pageBridgeClient.js +224 -0
- package/extension/src/content/panelMaintenance.js +8 -3
- package/extension/src/content/postNavigationSettlementPersistence.js +100 -0
- package/extension/src/content/projectProviderSelection.js +4 -12
- package/extension/src/content/projectSessionCleanup.js +3 -3
- package/extension/src/content/providerSettingsCoordinator.js +59 -26
- package/extension/src/content/providerSettingsDialog.js +30 -18
- package/extension/src/content/recentProjects.js +15 -23
- package/extension/src/content/runGuidanceController.js +1 -1
- package/extension/src/content/runQueueScheduler.js +129 -29
- package/extension/src/content/runSettlementPersistence.js +51 -0
- package/extension/src/content/runTimelineView.js +11 -8
- package/extension/src/content/scopedPersistenceCoordinator.js +100 -0
- package/extension/src/content/scopedPersistenceDetachedCommit.js +47 -0
- package/extension/src/content/scopedPersistencePanelState.js +111 -0
- package/extension/src/content/sessionManager.js +15 -12
- package/extension/src/content/sessionPersistence.js +67 -8
- package/extension/src/content/updateNotice.js +10 -4
- package/extension/src/content/writebackOrchestrator.js +91 -23
- package/extension/src/contentScript.js +5 -1
- package/extension/src/page/trackedChangesLifecycle.js +6 -1
- package/extension/src/pageBridge.js +47 -98
- package/extension/src/shared/agentTranscript.js +8 -5
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/governanceRules.js +1 -1
- package/extension/src/shared/managedUpdateProjection.js +337 -0
- package/extension/src/shared/nativeRequestIdentity.js +60 -0
- package/extension/src/shared/otText.js +0 -19
- package/extension/src/shared/pageRpcContract.js +136 -0
- package/extension/src/shared/runExecutionSnapshot.js +177 -0
- package/extension/src/shared/runExecutionSnapshotCodec.js +168 -0
- package/extension/src/shared/runInputQueue.js +81 -34
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +79 -0
- package/extension/src/shared/scopedPersistenceQueuePolicy.js +181 -0
- package/extension/src/shared/scopedPersistenceTransaction.js +238 -0
- package/extension/src/shared/sessionState.js +64 -48
- package/extension/src/shared/settlementFacts.js +351 -0
- package/extension/src/shared/storageDb.js +19 -5
- package/extension/src/shared/storageMigration.js +275 -61
- package/extension/src/shared/storageSessionClaims.js +60 -0
- package/extension/src/shared/updateConsent.js +4 -0
- package/extension/src/shared/updateRevocationIntent.js +109 -0
- package/extension/src/shared/writebackEvidenceProjection.js +150 -0
- package/extension/src/shared/writebackOperationEvidence.js +143 -0
- package/extension/src/shared/writebackSettlement.js +705 -0
- package/native-host/src/codexRuntimeIdentity.js +1 -1
- package/native-host/src/codexSessionRunner.js +7 -13
- package/native-host/src/index.js +3 -69
- package/native-host/src/managedInstall.js +50 -8
- package/native-host/src/nativeTransportEnvelope.js +148 -0
- package/native-host/src/taskRunnerRuntime.js +3 -3
- package/package.json +13 -5
|
@@ -19,13 +19,6 @@
|
|
|
19
19
|
const SLOW_IDLE_RETRY_MS = 15000;
|
|
20
20
|
const FAST_IDLE_RETRY_BLOCKERS = new Set(['recent_user_activity', 'save_state_not_stable']);
|
|
21
21
|
const WATCHDOG_INTERVAL_MINUTES = 1;
|
|
22
|
-
const PHASE_TIMEOUT_MS = Object.freeze({
|
|
23
|
-
checking: 30 * 1000,
|
|
24
|
-
downloading: 2 * 60 * 1000,
|
|
25
|
-
applying: 90 * 1000,
|
|
26
|
-
awaiting_health: 2 * 60 * 1000,
|
|
27
|
-
rolling_back: 60 * 1000
|
|
28
|
-
});
|
|
29
22
|
const LEGACY_GUARD = Number.MAX_SAFE_INTEGER;
|
|
30
23
|
const OVERLEAF_MATCHES = [
|
|
31
24
|
'https://www.overleaf.com/project',
|
|
@@ -42,6 +35,7 @@
|
|
|
42
35
|
]);
|
|
43
36
|
|
|
44
37
|
const policy = root.CodexOverleafUpdateConsent;
|
|
38
|
+
const revocation = root.CodexOverleafUpdateRevocation;
|
|
45
39
|
let nativeBridge = null;
|
|
46
40
|
let initialized = false;
|
|
47
41
|
let policyTail = Promise.resolve();
|
|
@@ -49,7 +43,7 @@
|
|
|
49
43
|
let activationPromise = null;
|
|
50
44
|
|
|
51
45
|
function init(options = {}) {
|
|
52
|
-
if (initialized || !policy) return;
|
|
46
|
+
if (initialized || !policy || !revocation) return;
|
|
53
47
|
initialized = true;
|
|
54
48
|
nativeBridge = options.nativeBridge || root.CodexOverleafNativeBridge;
|
|
55
49
|
|
|
@@ -70,7 +64,7 @@
|
|
|
70
64
|
void enqueuePolicyAction(() => checkOnly({ manual: false })).catch(() => {});
|
|
71
65
|
}
|
|
72
66
|
if (alarm?.name === WATCHDOG_ALARM) {
|
|
73
|
-
void enqueuePolicyAction(() =>
|
|
67
|
+
void enqueuePolicyAction(() => reconcileRecoveryState()).catch(() => {});
|
|
74
68
|
}
|
|
75
69
|
if (alarm?.name === IDLE_ALARM) {
|
|
76
70
|
void enqueuePolicyAction(() => tryActivateStagedUpdate()).catch(() => {});
|
|
@@ -95,7 +89,7 @@
|
|
|
95
89
|
periodInMinutes: WATCHDOG_INTERVAL_MINUTES
|
|
96
90
|
});
|
|
97
91
|
await recoverInterruptedCheck();
|
|
98
|
-
await
|
|
92
|
+
await reconcileRecoveryState();
|
|
99
93
|
await settleTerminalConsent();
|
|
100
94
|
await armLegacyGuard();
|
|
101
95
|
await publishView();
|
|
@@ -274,20 +268,27 @@
|
|
|
274
268
|
}
|
|
275
269
|
|
|
276
270
|
const authorizationId = crypto.randomUUID();
|
|
271
|
+
let authorizationIntent = revocation.prepareAuthorization(
|
|
272
|
+
consent,
|
|
273
|
+
authorizationId,
|
|
274
|
+
state.latestVersion,
|
|
275
|
+
Date.now()
|
|
276
|
+
);
|
|
277
277
|
try {
|
|
278
|
+
authorizationIntent = await setConsentState(authorizationIntent);
|
|
278
279
|
await requestNative('update.authorize', {
|
|
279
280
|
authorizationId,
|
|
280
281
|
targetVersion: state.latestVersion,
|
|
281
282
|
currentVersion: currentVersion()
|
|
282
283
|
});
|
|
283
|
-
await setConsentState({
|
|
284
|
-
...
|
|
284
|
+
await setConsentState(revocation.clear({
|
|
285
|
+
...authorizationIntent,
|
|
285
286
|
snoozedVersion: '',
|
|
286
287
|
snoozedUntil: 0,
|
|
287
288
|
authorizedVersion: state.latestVersion,
|
|
288
289
|
authorizationId,
|
|
289
290
|
authorizedAt: Date.now()
|
|
290
|
-
});
|
|
291
|
+
}));
|
|
291
292
|
await setUpdateState({ ...state, postponeUntil: 0, code: '', message: '' });
|
|
292
293
|
const executor = globalThis.CodexOverleafManagedUpdateExecutor;
|
|
293
294
|
if (!executor || typeof executor.installAuthorizedUpdate !== 'function') {
|
|
@@ -299,17 +300,31 @@
|
|
|
299
300
|
await executor.installAuthorizedUpdate();
|
|
300
301
|
return getView();
|
|
301
302
|
} catch (error) {
|
|
302
|
-
await
|
|
303
|
+
const observedConsent = await getConsentState().catch(() => consent);
|
|
304
|
+
const pendingConsent = revocation.prepareAuthorization({
|
|
305
|
+
...observedConsent,
|
|
306
|
+
authorizedVersion: state.latestVersion,
|
|
303
307
|
authorizationId,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
308
|
+
authorizedAt: observedConsent.authorizedAt || Date.now()
|
|
309
|
+
}, authorizationId, state.latestVersion, Date.now());
|
|
310
|
+
await setConsentState(pendingConsent);
|
|
311
|
+
try {
|
|
312
|
+
await requestNative('update.revoke', {
|
|
313
|
+
authorizationId: pendingConsent.revokingAuthorizationId,
|
|
314
|
+
targetVersion: pendingConsent.revokingVersion,
|
|
315
|
+
transactionId: pendingConsent.revokingTransactionId
|
|
316
|
+
});
|
|
317
|
+
await setConsentState(revocation.clear({
|
|
318
|
+
...pendingConsent,
|
|
319
|
+
authorizedVersion: '',
|
|
320
|
+
authorizationId: '',
|
|
321
|
+
authorizedAt: 0
|
|
322
|
+
}));
|
|
323
|
+
} catch (revokeError) {
|
|
324
|
+
if (error && typeof error === 'object') {
|
|
325
|
+
error.revocationError = safeMessage(revokeError);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
313
328
|
const observed = await getUpdateState().catch(() => state);
|
|
314
329
|
if (!['awaiting_health', 'committed', 'rolled_back'].includes(observed.state)) {
|
|
315
330
|
await setUpdateState({
|
|
@@ -486,15 +501,19 @@
|
|
|
486
501
|
if (['applying', 'awaiting_health'].includes(state.state)) {
|
|
487
502
|
throw codedError('update_revoke_too_late', 'The update is already being installed.');
|
|
488
503
|
}
|
|
504
|
+
let pendingConsent = consent;
|
|
489
505
|
if (consent.authorizationId) {
|
|
506
|
+
pendingConsent = revocation.begin(consent, state, Date.now());
|
|
507
|
+
await setConsentState(pendingConsent);
|
|
490
508
|
try {
|
|
491
509
|
await requestNative('update.revoke', {
|
|
492
|
-
authorizationId:
|
|
493
|
-
targetVersion:
|
|
494
|
-
transactionId:
|
|
510
|
+
authorizationId: pendingConsent.revokingAuthorizationId,
|
|
511
|
+
targetVersion: pendingConsent.revokingVersion,
|
|
512
|
+
transactionId: pendingConsent.revokingTransactionId
|
|
495
513
|
});
|
|
496
514
|
} catch (error) {
|
|
497
515
|
if (error?.code === 'update_revoke_too_late') {
|
|
516
|
+
await setConsentState(revocation.clear(pendingConsent));
|
|
498
517
|
return getView();
|
|
499
518
|
}
|
|
500
519
|
throw error;
|
|
@@ -503,31 +522,56 @@
|
|
|
503
522
|
throw codedError('update_consent_mismatch', 'The staged update has no matching runtime authorization.');
|
|
504
523
|
}
|
|
505
524
|
|
|
506
|
-
const snoozedUntil = Date.now() + SNOOZE_MS;
|
|
507
525
|
clearIdleRetryTimer();
|
|
508
526
|
await chrome.alarms?.clear?.(IDLE_ALARM).catch(() => {});
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
stagedAt: 0,
|
|
514
|
-
blocker: '',
|
|
515
|
-
blockers: [],
|
|
516
|
-
postponeUntil: LEGACY_GUARD,
|
|
517
|
-
code: '',
|
|
518
|
-
message: ''
|
|
519
|
-
});
|
|
520
|
-
await setConsentState({
|
|
521
|
-
...consent,
|
|
522
|
-
snoozedVersion: state.latestVersion,
|
|
523
|
-
snoozedUntil,
|
|
524
|
-
authorizedVersion: '',
|
|
525
|
-
authorizationId: '',
|
|
526
|
-
authorizedAt: 0
|
|
527
|
+
const completed = revocation.complete(state, pendingConsent, {
|
|
528
|
+
now: Date.now(),
|
|
529
|
+
snoozeMs: SNOOZE_MS,
|
|
530
|
+
postponeUntil: LEGACY_GUARD
|
|
527
531
|
});
|
|
532
|
+
await setUpdateAndConsentState(completed.updateState, completed.consentState);
|
|
528
533
|
return getView();
|
|
529
534
|
}
|
|
530
535
|
|
|
536
|
+
async function reconcileRecoveryState() {
|
|
537
|
+
await reconcilePendingRevocation();
|
|
538
|
+
return reconcileExpiredPhase();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async function reconcilePendingRevocation() {
|
|
542
|
+
const [state, consent] = await Promise.all([getUpdateState(), getConsentState()]);
|
|
543
|
+
if (!revocation.hasPending(consent)) return state;
|
|
544
|
+
|
|
545
|
+
try {
|
|
546
|
+
await requestNative('update.revoke', {
|
|
547
|
+
authorizationId: consent.revokingAuthorizationId,
|
|
548
|
+
targetVersion: consent.revokingVersion,
|
|
549
|
+
transactionId: consent.revokingTransactionId
|
|
550
|
+
});
|
|
551
|
+
} catch (error) {
|
|
552
|
+
if (error?.code === 'update_revoke_too_late') {
|
|
553
|
+
await setConsentState(revocation.clear(consent));
|
|
554
|
+
return state;
|
|
555
|
+
}
|
|
556
|
+
if (!['update_already_revoked', 'update_authorization_revoked'].includes(error?.code)) {
|
|
557
|
+
return state;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
clearIdleRetryTimer();
|
|
562
|
+
await chrome.alarms?.clear?.(IDLE_ALARM).catch(() => {});
|
|
563
|
+
const completed = revocation.complete(state, consent, {
|
|
564
|
+
now: Date.now(),
|
|
565
|
+
snoozeMs: SNOOZE_MS,
|
|
566
|
+
postponeUntil: LEGACY_GUARD
|
|
567
|
+
});
|
|
568
|
+
const settled = await setUpdateAndConsentState(
|
|
569
|
+
completed.updateState,
|
|
570
|
+
completed.consentState
|
|
571
|
+
);
|
|
572
|
+
return settled.updateState;
|
|
573
|
+
}
|
|
574
|
+
|
|
531
575
|
async function settleTerminalConsent() {
|
|
532
576
|
const [state, consent] = await Promise.all([getUpdateState(), getConsentState()]);
|
|
533
577
|
if (!policy.isTerminalState(state.state) || !consent.authorizationId) return;
|
|
@@ -558,7 +602,7 @@
|
|
|
558
602
|
currentVersion: transaction.sourceVersion || state.currentVersion,
|
|
559
603
|
code: 'update_health_timeout',
|
|
560
604
|
message: 'The updated runtime did not complete its health check and was rolled back. Retry, or use the manual update command.'
|
|
561
|
-
});
|
|
605
|
+
}, { observed: true });
|
|
562
606
|
}
|
|
563
607
|
if (transaction?.state === 'committed') {
|
|
564
608
|
return setUpdateState({
|
|
@@ -568,7 +612,7 @@
|
|
|
568
612
|
latestVersion: transaction.targetVersion,
|
|
569
613
|
code: '',
|
|
570
614
|
message: ''
|
|
571
|
-
});
|
|
615
|
+
}, { observed: true });
|
|
572
616
|
}
|
|
573
617
|
if (transaction?.state === 'rolled_back') {
|
|
574
618
|
return setUpdateState({
|
|
@@ -577,7 +621,7 @@
|
|
|
577
621
|
currentVersion: transaction.sourceVersion || state.currentVersion,
|
|
578
622
|
code: transaction.reasonCode || 'update_rolled_back',
|
|
579
623
|
message: 'The managed update was rolled back after activation did not complete.'
|
|
580
|
-
});
|
|
624
|
+
}, { observed: true });
|
|
581
625
|
}
|
|
582
626
|
}
|
|
583
627
|
return setUpdateState({
|
|
@@ -641,20 +685,34 @@
|
|
|
641
685
|
return policy.normalizeUpdateState(stored?.[UPDATE_STATE_KEY], currentVersion());
|
|
642
686
|
}
|
|
643
687
|
|
|
644
|
-
async function setUpdateState(value) {
|
|
688
|
+
async function setUpdateState(value, options = {}) {
|
|
645
689
|
const stored = await chrome.storage.local.get(UPDATE_STATE_KEY);
|
|
646
690
|
const previous = policy.normalizeUpdateState(stored?.[UPDATE_STATE_KEY], currentVersion());
|
|
691
|
+
const next = projectUpdateState(previous, value, options);
|
|
692
|
+
await chrome.storage.local.set({ [UPDATE_STATE_KEY]: next });
|
|
693
|
+
return next;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
function projectUpdateState(previous, value, options = {}) {
|
|
647
697
|
const now = Date.now();
|
|
648
|
-
const
|
|
649
|
-
const timeoutMs = PHASE_TIMEOUT_MS[value.state] || 0;
|
|
650
|
-
const next = policy.normalizeUpdateState({
|
|
698
|
+
const candidate = {
|
|
651
699
|
...value,
|
|
652
|
-
initiatedBy: value.initiatedBy || previous.initiatedBy
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
700
|
+
initiatedBy: value.initiatedBy || previous.initiatedBy
|
|
701
|
+
};
|
|
702
|
+
const projection = root.CodexOverleafManagedUpdateProjection;
|
|
703
|
+
let next;
|
|
704
|
+
if (projection) {
|
|
705
|
+
const transition = options.observed === true
|
|
706
|
+
? projection.transition
|
|
707
|
+
: projection.transitionCommand;
|
|
708
|
+
next = transition(previous, candidate, {
|
|
709
|
+
merge: true,
|
|
710
|
+
currentVersion: currentVersion(),
|
|
711
|
+
now
|
|
712
|
+
});
|
|
713
|
+
} else {
|
|
714
|
+
next = policy.normalizeUpdateState(candidate, currentVersion());
|
|
715
|
+
}
|
|
658
716
|
return next;
|
|
659
717
|
}
|
|
660
718
|
|
|
@@ -669,6 +727,18 @@
|
|
|
669
727
|
return next;
|
|
670
728
|
}
|
|
671
729
|
|
|
730
|
+
async function setUpdateAndConsentState(updateValue, consentValue, options = {}) {
|
|
731
|
+
const stored = await chrome.storage.local.get([UPDATE_STATE_KEY, CONSENT_STATE_KEY]);
|
|
732
|
+
const previous = policy.normalizeUpdateState(stored?.[UPDATE_STATE_KEY], currentVersion());
|
|
733
|
+
const updateState = projectUpdateState(previous, updateValue, options);
|
|
734
|
+
const consentState = policy.normalizeConsentState(consentValue);
|
|
735
|
+
await chrome.storage.local.set({
|
|
736
|
+
[UPDATE_STATE_KEY]: updateState,
|
|
737
|
+
[CONSENT_STATE_KEY]: consentState
|
|
738
|
+
});
|
|
739
|
+
return { updateState, consentState };
|
|
740
|
+
}
|
|
741
|
+
|
|
672
742
|
async function requestNative(method, params = {}) {
|
|
673
743
|
const response = await nativeBridge?.requestInternal?.({
|
|
674
744
|
id: crypto.randomUUID(),
|
|
@@ -684,14 +754,6 @@
|
|
|
684
754
|
return response.result || {};
|
|
685
755
|
}
|
|
686
756
|
|
|
687
|
-
async function bestEffortRevoke(params) {
|
|
688
|
-
try {
|
|
689
|
-
await requestNative('update.revoke', params);
|
|
690
|
-
} catch (_error) {
|
|
691
|
-
// Native authorization remains the hard gate if cleanup cannot connect.
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
|
|
695
757
|
function enqueuePolicyAction(action) {
|
|
696
758
|
const result = policyTail.then(action, action);
|
|
697
759
|
policyTail = result.catch(() => {});
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
(function initCodexOverleafApplyResultFormatters() {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const i18n = window.CodexOverleafI18n;
|
|
5
|
-
const FailureReasons = window.CodexOverleafFailureReasons;
|
|
6
|
-
|
|
7
4
|
// Apply-result / failure-reason formatters carved out of contentRuntime.js
|
|
8
5
|
// (v1.4.7 structural-debt phase 3): the skipped-detail renderer and the
|
|
9
6
|
// bilingual apply/bridge reason formatters. Code moved verbatim; the few
|
|
10
7
|
// runtime collaborators are factory-injected.
|
|
11
8
|
function create(deps = {}) {
|
|
12
9
|
const {
|
|
10
|
+
i18n,
|
|
11
|
+
FailureReasons,
|
|
13
12
|
getLocale,
|
|
14
13
|
tr,
|
|
15
14
|
tx,
|