codex-overleaf-link 2.3.5 → 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 +63 -31
- package/README.zh-CN.md +543 -0
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +7 -0
- package/extension/src/backgroundUpdateCoordinator.js +88 -4
- package/extension/src/content/activeTurnControl.js +1 -0
- package/extension/src/content/assetTransferBroker.js +2 -0
- package/extension/src/content/contentRuntime.js +77 -57
- package/extension/src/content/contextTray.js +4 -0
- package/extension/src/content/diagnosticsController.js +17 -3
- package/extension/src/content/diagnosticsPanel.js +129 -5
- package/extension/src/content/generated/content.bundle.js +1422 -348
- package/extension/src/content/generated/content.bundle.meta.json +7 -3
- package/extension/src/content/legacyGlobalRegistry.js +3 -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 +126 -92
- package/extension/src/content/otWarmMirrorController.js +122 -1
- package/extension/src/content/pageBridgeClient.js +2 -0
- package/extension/src/content/panelMaintenance.js +26 -15
- package/extension/src/content/providerSettingsCoordinator.js +1 -0
- package/extension/src/content/runFailureNotice.js +104 -0
- package/extension/src/content/runResultActions.js +16 -1
- package/extension/src/content/runScrollLayout.js +124 -0
- package/extension/src/content/runTimelineView.js +37 -11
- package/extension/src/content/sessionForkController.js +20 -11
- package/extension/src/content/settingsPanel.js +28 -11
- package/extension/src/content/trackedChangeCaptureController.js +153 -0
- package/extension/src/content/updateNotice.js +24 -4
- package/extension/src/content/writebackOrchestrator.js +31 -0
- package/extension/src/page/binaryAssetUploader.js +101 -29
- package/extension/src/page/overleafRealtimeObserver.js +120 -25
- 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/i18n.js +77 -37
- package/extension/src/shared/managedUpdateProjection.js +1 -1
- package/extension/src/shared/otText.js +0 -1
- package/extension/src/shared/pageRpcContract.js +2 -1
- package/extension/src/shared/sessionState.js +23 -23
- package/extension/src/shared/sessionTitle.js +120 -0
- package/extension/src/shared/storageDb.js +10 -12
- package/extension/src/shared/storageRunActions.js +29 -1
- package/extension/src/shared/updateRuntimeIdentity.js +32 -0
- package/extension/src/shared/writebackSettlement.js +19 -5
- package/extension/styles/panel.css +128 -24
- package/native-host/src/mirrorWorkspace.js +20 -1
- package/native-host/src/releaseProxy.js +177 -0
- package/native-host/src/releaseTransport.js +154 -0
- package/native-host/src/taskRunnerRuntime.js +25 -0
- package/native-host/src/updateManager.js +40 -39
- package/package.json +5 -1
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
require('./settlementFacts'),
|
|
6
6
|
require('./runInputQueue'),
|
|
7
7
|
require('./lineReferences'),
|
|
8
|
-
require('./pathRedaction')
|
|
8
|
+
require('./pathRedaction'),
|
|
9
|
+
require('./sessionTitle')
|
|
9
10
|
);
|
|
10
11
|
} else {
|
|
11
12
|
root.CodexOverleafModuleRegistry.define(
|
|
12
13
|
'SessionState',
|
|
13
|
-
['I18n', 'SettlementFacts', 'RunInputQueue', 'LineReferences', 'PathRedaction'],
|
|
14
|
+
['I18n', 'SettlementFacts', 'RunInputQueue', 'LineReferences', 'PathRedaction', 'SessionTitle'],
|
|
14
15
|
factory
|
|
15
16
|
);
|
|
16
17
|
}
|
|
@@ -19,7 +20,8 @@
|
|
|
19
20
|
SettlementFacts,
|
|
20
21
|
RunInputQueue,
|
|
21
22
|
LineReferences,
|
|
22
|
-
PathRedaction
|
|
23
|
+
PathRedaction,
|
|
24
|
+
SessionTitle
|
|
23
25
|
) {
|
|
24
26
|
'use strict';
|
|
25
27
|
|
|
@@ -402,6 +404,12 @@
|
|
|
402
404
|
) {
|
|
403
405
|
next.title = session.title;
|
|
404
406
|
next.titleSource = 'manual';
|
|
407
|
+
} else if (session.titleSource === 'auto' && patch.titleSource !== 'manual'
|
|
408
|
+
&& typeof patch.title === 'string' && patch.title.trim() && session.runs?.length
|
|
409
|
+
&& SessionTitle.isGeneric(sanitizeAutoTitle(patch.title))
|
|
410
|
+
&& !SessionTitle.isGeneric(sanitizeAutoTitle(session.title))) {
|
|
411
|
+
next.title = session.title;
|
|
412
|
+
next.titleSource = 'auto';
|
|
405
413
|
}
|
|
406
414
|
return normalizeSession({
|
|
407
415
|
...next
|
|
@@ -472,12 +480,7 @@
|
|
|
472
480
|
}
|
|
473
481
|
|
|
474
482
|
function deriveSessionTitle(runs, task) {
|
|
475
|
-
|
|
476
|
-
if (taskTitle) {
|
|
477
|
-
return taskTitle;
|
|
478
|
-
}
|
|
479
|
-
const firstRunTask = Array.isArray(runs) && runs.length ? runs[0]?.task : '';
|
|
480
|
-
return sanitizeAutoTitle(firstRunTask);
|
|
483
|
+
return SessionTitle.derive(runs, task, { sanitize: sanitizeAssistantVisibleText, maxChars: SESSION_AUTO_TITLE_CHARS });
|
|
481
484
|
}
|
|
482
485
|
|
|
483
486
|
// Rename a session with the placeholder/derived-title ghost guard (mirrors
|
|
@@ -519,21 +522,14 @@
|
|
|
519
522
|
if (titleSource === 'manual') {
|
|
520
523
|
return normalizeTextField(rawTitle === LEGACY_DEFAULT_SESSION_TITLE ? '' : rawTitle, STORAGE_DEFAULT_LIMITS.sessionTitleChars);
|
|
521
524
|
}
|
|
522
|
-
|
|
525
|
+
const current = sanitizeAutoTitle(rawTitle === LEGACY_DEFAULT_SESSION_TITLE ? '' : rawTitle);
|
|
526
|
+
if (!current || SessionTitle.isGeneric(current)) return derivedTitle || current || '';
|
|
527
|
+
if (current.endsWith('…') && derivedTitle.startsWith(current.slice(0, -1))) return derivedTitle;
|
|
528
|
+
return current;
|
|
523
529
|
}
|
|
524
530
|
|
|
525
531
|
function sanitizeAutoTitle(value) {
|
|
526
|
-
|
|
527
|
-
.replace(/@file:[^\s]+/g, ' ')
|
|
528
|
-
.replace(/@(context|compile-log)\b/g, ' ')
|
|
529
|
-
.replace(/\s+/g, ' ')
|
|
530
|
-
.trim();
|
|
531
|
-
if (!title) {
|
|
532
|
-
return '';
|
|
533
|
-
}
|
|
534
|
-
return title.length > SESSION_AUTO_TITLE_CHARS
|
|
535
|
-
? `${title.slice(0, SESSION_AUTO_TITLE_CHARS - 1)}…`
|
|
536
|
-
: title;
|
|
532
|
+
return SessionTitle.fromPrompt(value, { sanitize: sanitizeAssistantVisibleText, maxChars: SESSION_AUTO_TITLE_CHARS });
|
|
537
533
|
}
|
|
538
534
|
|
|
539
535
|
function isDisplayableSession(session) {
|
|
@@ -640,7 +636,7 @@
|
|
|
640
636
|
undoExpectedFiles: normalizeRunFiles(run.undoExpectedFiles),
|
|
641
637
|
undoStatus: sanitizeAssistantVisibleText(run.undoStatus),
|
|
642
638
|
nativeRequestId: sanitizeAssistantVisibleText(run.nativeRequestId),
|
|
643
|
-
codexTurnId: sanitizeAssistantVisibleText(run.codexTurnId),
|
|
639
|
+
codexThreadId: sanitizeAssistantVisibleText(run.codexThreadId), codexTurnId: sanitizeAssistantVisibleText(run.codexTurnId),
|
|
644
640
|
forkSnapshot: run.forkSnapshot === true,
|
|
645
641
|
forkSourceRunId: sanitizeAssistantVisibleText(run.forkSourceRunId),
|
|
646
642
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
@@ -660,6 +656,9 @@
|
|
|
660
656
|
if (run.changedDocument === true) {
|
|
661
657
|
normalized.changedDocument = true;
|
|
662
658
|
}
|
|
659
|
+
if (Array.isArray(run.trackedChangeCaptures) && run.trackedChangeCaptures.length && !run.forkSnapshot) {
|
|
660
|
+
normalized.trackedChangeCaptures = sanitizeAssistantVisibleValue(run.trackedChangeCaptures);
|
|
661
|
+
}
|
|
663
662
|
applyTrackedChangeStatus(normalized, run.trackedChangeStatus);
|
|
664
663
|
|
|
665
664
|
return normalized;
|
|
@@ -1219,7 +1218,7 @@
|
|
|
1219
1218
|
undoExpectedFiles: undoPayload.undoExpectedFiles,
|
|
1220
1219
|
undoStatus: summarizeTextForStorage(run.undoStatus, 'undo status'),
|
|
1221
1220
|
nativeRequestId: normalizeTextField(run.nativeRequestId, 160),
|
|
1222
|
-
codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
1221
|
+
codexThreadId: normalizeTextField(run.codexThreadId, 160), codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
1223
1222
|
forkSnapshot: run.forkSnapshot === true,
|
|
1224
1223
|
forkSourceRunId: normalizeTextField(run.forkSourceRunId, 160),
|
|
1225
1224
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
@@ -1631,6 +1630,7 @@
|
|
|
1631
1630
|
setActiveSession,
|
|
1632
1631
|
updateActiveSession,
|
|
1633
1632
|
normalizeRuns,
|
|
1633
|
+
normalizeProjectReferenceFiles,
|
|
1634
1634
|
prepareStateForStorage,
|
|
1635
1635
|
estimateJsonBytes,
|
|
1636
1636
|
computeSafeTaskSummary
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
(function initSessionTitle(root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) {
|
|
3
|
+
module.exports = factory();
|
|
4
|
+
} else {
|
|
5
|
+
root.CodexOverleafModuleRegistry.define('SessionTitle', [], factory);
|
|
6
|
+
}
|
|
7
|
+
})(typeof globalThis !== 'undefined' ? globalThis : window, function sessionTitleFactory() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const INPUT_LIMIT = 12000;
|
|
11
|
+
const STORAGE_LIMIT = 80;
|
|
12
|
+
const segmenter = typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function'
|
|
13
|
+
? new Intl.Segmenter(undefined, { granularity: 'grapheme' }) : null;
|
|
14
|
+
const FILE_TOKEN = /@file:(?:"([^"]+)"|'([^']+)'|([^\s]+))/g;
|
|
15
|
+
|
|
16
|
+
function derive(runs, task, options = {}) {
|
|
17
|
+
let fallback = '';
|
|
18
|
+
for (const run of Array.isArray(runs) ? runs : []) {
|
|
19
|
+
const candidate = fromPrompt(run?.task, options);
|
|
20
|
+
fallback ||= candidate;
|
|
21
|
+
if (candidate && !isGeneric(candidate)) return candidate;
|
|
22
|
+
}
|
|
23
|
+
const draft = fromPrompt(task, options);
|
|
24
|
+
return draft && !isGeneric(draft) ? draft : fallback || draft;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function fromPrompt(value, { sanitize = text => text, maxChars = 24 } = {}) {
|
|
28
|
+
if (typeof value !== 'string' || !value.trim()) return '';
|
|
29
|
+
const source = String(sanitize(value.slice(0, INPUT_LIMIT)) || '');
|
|
30
|
+
let fence = null;
|
|
31
|
+
let fallback = '';
|
|
32
|
+
for (const rawLine of source.split(/\r?\n/)) {
|
|
33
|
+
const line = rawLine.trim();
|
|
34
|
+
const marker = /^(`{3,}|~{3,})(.*)$/.exec(line);
|
|
35
|
+
if (marker) {
|
|
36
|
+
if (!fence) {
|
|
37
|
+
fence = marker[1];
|
|
38
|
+
const language = marker[2].trim().match(/^[A-Za-z0-9_+-]{1,24}\b/)?.[0] || 'code';
|
|
39
|
+
fallback ||= `${language} snippet`;
|
|
40
|
+
} else if (marker[1][0] === fence[0] && marker[1].length >= fence.length && !marker[2].trim()) {
|
|
41
|
+
fence = null;
|
|
42
|
+
}
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (fence || !line || /^>/.test(line)) continue;
|
|
46
|
+
const withoutContext = line.replace(FILE_TOKEN, ' ').replace(/@(context|compile-log)\b/g, ' ').trim();
|
|
47
|
+
const cleaned = cleanLine(line);
|
|
48
|
+
if (!withoutContext || /^https?:\/\/\S+$/i.test(line)) {
|
|
49
|
+
fallback ||= cleaned;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
for (const sentence of cleaned.split(/[\u3002\uff01\uff1f]+/u)) {
|
|
53
|
+
const candidate = sentence.trim().replace(/[,;:\uff0c\uff1b\uff1a]+$/u, '').trim();
|
|
54
|
+
if (!/[\p{L}\p{N}]/u.test(candidate) || isScaffolding(candidate)) continue;
|
|
55
|
+
fallback ||= candidate;
|
|
56
|
+
if (!isGeneric(candidate)) return shorten(candidate, maxChars);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return shorten(fallback, maxChars);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function cleanLine(value) {
|
|
63
|
+
return value
|
|
64
|
+
.replace(/^#{1,6}\s+/, '')
|
|
65
|
+
.replace(/^(?:[-*+]\s+|\d+\.\s+|\d+[)\u3001]\s*)/, '')
|
|
66
|
+
.replace(FILE_TOKEN, (_match, quoted, singleQuoted, bare) =>
|
|
67
|
+
String(quoted || singleQuoted || bare || '').replace(/\\/g, '/').split('/').pop())
|
|
68
|
+
.replace(/@(context|compile-log)\b/g, ' ')
|
|
69
|
+
.replace(/!?\[([^\]]*)\]\([^\n)]*\)/g, '$1')
|
|
70
|
+
.replace(/`([^`]+)`/g, '$1')
|
|
71
|
+
.replace(/\*\*([^*]+)\*\*/g, '$1')
|
|
72
|
+
.replace(/https?:\/\/\S+/gi, address => {
|
|
73
|
+
try { return new URL(address).hostname; } catch (_error) { return ''; }
|
|
74
|
+
})
|
|
75
|
+
.replace(/\[(?:REDACTED_SECRET|local path(?::\d+)?)\]/gi, ' ')
|
|
76
|
+
.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')
|
|
77
|
+
.replace(/\s+/g, ' ').trim()
|
|
78
|
+
.replace(/^(?:\u8bf7(?:\u4f60)?\u5e2e\u6211|\u8bf7\u4f60|\u5e2e\u6211|\u9ebb\u70e6\u4f60(?:\u5e2e\u6211)?|\u9ebb\u70e6\u5e2e\u6211|please\s+)\s*/i, '');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function isScaffolding(value) {
|
|
82
|
+
return /^(?:my request(?: for [^:]+)?|request|task|context|files(?: mentioned by [^:]+)?|attachments|\u6211\u7684\u8bf7\u6c42|\u9700\u6c42|\u4efb\u52a1|\u4e0a\u4e0b\u6587|\u9644\u4ef6|\u6587\u4ef6)$/i.test(value);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isGeneric(value) {
|
|
86
|
+
const text = String(value || '').trim().replace(/[\s.!?\u3002\uff1f\uff01\u2026]+$/u, '');
|
|
87
|
+
if (!text || Array.from(text).length < 2) return true;
|
|
88
|
+
return /^(?:ok(?:ay)?|yes|no|go|done|continue|proceed|thanks?|thank you|hello|hi|test|new task|untitled task|\u597d(?:\u7684)?|\u53ef\u4ee5|\u7ee7\u7eed|\u786e\u8ba4|\u786e\u5b9a|\u6536\u5230|\u8c22\u8c22|\u6d4b\u8bd5|\u6267\u884c|\u662f\u7684|\u4f60\u597d)$/i.test(text)
|
|
89
|
+
|| /^[A-Za-z0-9_+-]{1,24} snippet$/i.test(text)
|
|
90
|
+
|| /^[^\s]+\.(?:tex|bib|md|txt|pdf|svg|png|jpe?g|webp)(?::\d+)?$/i.test(text)
|
|
91
|
+
|| /^(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,}$/i.test(text);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function shorten(value, maxChars) {
|
|
95
|
+
const title = String(value || '').trim();
|
|
96
|
+
if (!title) return '';
|
|
97
|
+
const chars = Number.isFinite(maxChars) && maxChars > 0 ? Math.min(40, Math.floor(maxChars)) : 24;
|
|
98
|
+
const maxUnits = chars * 2;
|
|
99
|
+
const glyphs = segmenter
|
|
100
|
+
? Array.from(segmenter.segment(title), item => item.segment) : Array.from(title);
|
|
101
|
+
const width = glyph => /[^\u0000-\u00ff]/u.test(glyph) ? 2 : 1;
|
|
102
|
+
if (title.length <= STORAGE_LIMIT && glyphs.reduce((total, glyph) => total + width(glyph), 0) <= maxUnits) return title;
|
|
103
|
+
let prefix = '';
|
|
104
|
+
let units = 0;
|
|
105
|
+
let index = 0;
|
|
106
|
+
for (; index < glyphs.length; index++) {
|
|
107
|
+
const glyph = glyphs[index];
|
|
108
|
+
if (units + width(glyph) > maxUnits - 2 || prefix.length + glyph.length > STORAGE_LIMIT - 1) break;
|
|
109
|
+
prefix += glyph;
|
|
110
|
+
units += width(glyph);
|
|
111
|
+
}
|
|
112
|
+
const boundary = prefix.lastIndexOf(' ');
|
|
113
|
+
if (/[A-Za-z0-9]$/.test(prefix) && /^[A-Za-z0-9]/.test(glyphs[index] || '') && boundary >= prefix.length * 0.6) {
|
|
114
|
+
prefix = prefix.slice(0, boundary);
|
|
115
|
+
}
|
|
116
|
+
return prefix.trimEnd().replace(/[,;:\uff0c\uff1b\uff1a]+$/u, '') + '\u2026';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return Object.freeze({ derive, fromPrompt, isGeneric });
|
|
120
|
+
});
|
|
@@ -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
|
};
|
|
@@ -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',
|
|
@@ -147,6 +174,7 @@
|
|
|
147
174
|
compactRunsForStorage: compactRunsForStorage,
|
|
148
175
|
compactRunActionPayload: compactRunActionPayload,
|
|
149
176
|
compactProviderSnapshot: compactProviderSnapshot,
|
|
177
|
+
compactRunExecutionSnapshot: compactRunExecutionSnapshot,
|
|
150
178
|
hashString: hashString
|
|
151
179
|
};
|
|
152
180
|
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
const api = factory();
|
|
3
|
+
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
4
|
+
if (root) root.CodexOverleafUpdateRuntimeIdentity = api;
|
|
5
|
+
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
function version(value) { return /^\d+\.\d+\.\d+$/.test(String(value || '')) ? String(value) : ''; }
|
|
9
|
+
function compare(left, right) {
|
|
10
|
+
const a = left.split('.').map(Number);
|
|
11
|
+
const b = right.split('.').map(Number);
|
|
12
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function inspectInstalledRuntime(status = {}, options = {}) {
|
|
16
|
+
const result = { installedVersion: version(status.activeVersion), nativeVersion: version(status.runtimeVersion),
|
|
17
|
+
extensionVersion: version(options.extensionVersion), runtimeVersion: version(options.runtimeVersion), state: 'unknown' };
|
|
18
|
+
if (!status.managed || !result.installedVersion || !result.nativeVersion ||
|
|
19
|
+
!result.extensionVersion || !result.runtimeVersion) return result;
|
|
20
|
+
if (['authorized', 'bound'].includes(status.authorization?.state) ||
|
|
21
|
+
['staged', 'activation_pending', 'applying', 'awaiting_health'].includes(status.transaction?.state)) {
|
|
22
|
+
return { ...result, state: 'transaction_active' };
|
|
23
|
+
}
|
|
24
|
+
if (status.installedAligned !== true) return { ...result, state: 'repair_required' };
|
|
25
|
+
const loaded = [result.nativeVersion, result.extensionVersion, result.runtimeVersion];
|
|
26
|
+
if (loaded.every(value => value === result.installedVersion)) return { ...result, state: 'aligned' };
|
|
27
|
+
return { ...result, state: loaded.every(value => compare(result.installedVersion, value) >= 0)
|
|
28
|
+
? 'reload_required' : 'repair_required' };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return Object.freeze({ inspectInstalledRuntime });
|
|
32
|
+
});
|
|
@@ -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
|
}
|