codex-overleaf-link 2.2.0 → 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/mirrorWorkspace.js +15 -8
- package/native-host/src/nativeTransportEnvelope.js +148 -0
- package/native-host/src/taskRunnerRuntime.js +3 -3
- package/package.json +13 -5
|
@@ -7,7 +7,7 @@ const { spawnSync } = require('node:child_process');
|
|
|
7
7
|
|
|
8
8
|
const RUNTIME_ENV_KEY = 'CODEX_OVERLEAF_CODEX_RUNTIME_JSON';
|
|
9
9
|
const MAX_CODEX_CANDIDATES = 8;
|
|
10
|
-
const VERSION_TIMEOUT_MS =
|
|
10
|
+
const VERSION_TIMEOUT_MS = 3000;
|
|
11
11
|
|
|
12
12
|
function buildCodexRuntimeIdentity(options = {}) {
|
|
13
13
|
const env = options.env || process.env;
|
|
@@ -10,7 +10,10 @@ const { computeTextPatches } = require('./textPatch');
|
|
|
10
10
|
const { buildCodexHomeEnv } = require('./codexHome');
|
|
11
11
|
const { buildCodexSpeedArgs } = require('./codexArgs');
|
|
12
12
|
const { truncateText } = require('./debugLog');
|
|
13
|
-
const {
|
|
13
|
+
const {
|
|
14
|
+
estimateBase64DecodedBytes,
|
|
15
|
+
reduceTaskResult
|
|
16
|
+
} = require('./nativeTransportEnvelope');
|
|
14
17
|
const { buildCodexTurnPrompt: buildCodexPromptParts } = require('./codexPromptAssembly');
|
|
15
18
|
const { evaluateSkillCommand } = require('./commandApproval');
|
|
16
19
|
const {
|
|
@@ -186,7 +189,7 @@ async function runCodexSession({ params = {}, env = process.env, emit = () => {}
|
|
|
186
189
|
throwIfAborted(signal);
|
|
187
190
|
|
|
188
191
|
if (skillInstallTurn) {
|
|
189
|
-
return
|
|
192
|
+
return reduceTaskResult({
|
|
190
193
|
status: 'completed',
|
|
191
194
|
projectId: mirror.projectKey,
|
|
192
195
|
workspacePath: mirror.workspacePath,
|
|
@@ -245,7 +248,7 @@ async function runCodexSession({ params = {}, env = process.env, emit = () => {}
|
|
|
245
248
|
ignoredChangedCount: rawSyncChanges.length,
|
|
246
249
|
ignoredUnsupportedCount: unsupportedChanges.length
|
|
247
250
|
}, rawSyncChanges.length || unsupportedChanges.length ? 'warning' : 'completed');
|
|
248
|
-
return
|
|
251
|
+
return reduceTaskResult({
|
|
249
252
|
status: 'completed',
|
|
250
253
|
projectId: mirror.projectKey,
|
|
251
254
|
workspacePath: mirror.workspacePath,
|
|
@@ -266,7 +269,7 @@ async function runCodexSession({ params = {}, env = process.env, emit = () => {}
|
|
|
266
269
|
}
|
|
267
270
|
return change;
|
|
268
271
|
});
|
|
269
|
-
const response =
|
|
272
|
+
const response = reduceTaskResult({
|
|
270
273
|
status: 'completed',
|
|
271
274
|
projectId: mirror.projectKey,
|
|
272
275
|
workspacePath: mirror.workspacePath,
|
|
@@ -370,15 +373,6 @@ function normalizeTurnAttachments(value) {
|
|
|
370
373
|
return result;
|
|
371
374
|
}
|
|
372
375
|
|
|
373
|
-
function estimateBase64DecodedBytes(value) {
|
|
374
|
-
const clean = String(value || '').replace(/\s+/g, '');
|
|
375
|
-
if (!clean) {
|
|
376
|
-
return 0;
|
|
377
|
-
}
|
|
378
|
-
const padding = clean.endsWith('==') ? 2 : clean.endsWith('=') ? 1 : 0;
|
|
379
|
-
return Math.max(0, Math.floor(clean.length * 3 / 4) - padding);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
376
|
function sanitizeAttachmentFileName(value) {
|
|
383
377
|
const basename = String(value || '')
|
|
384
378
|
.replace(/\0/g, '')
|
package/native-host/src/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const {
|
|
4
|
+
const { decodeInputFrames, encodeOutputFrame } = require('./nativeTransportEnvelope');
|
|
5
5
|
const { logDebug } = require('./debugLog');
|
|
6
6
|
const { handleRequest } = require('./taskRunner');
|
|
7
7
|
const { abortAllActiveOperations, getActiveNativeWorkState } = require('./taskRunnerRuntime');
|
|
@@ -21,7 +21,7 @@ process.stdin.on('data', chunk => {
|
|
|
21
21
|
|
|
22
22
|
let decoded;
|
|
23
23
|
try {
|
|
24
|
-
decoded =
|
|
24
|
+
decoded = decodeInputFrames(buffered);
|
|
25
25
|
} catch (error) {
|
|
26
26
|
writeResponse({
|
|
27
27
|
ok: false,
|
|
@@ -111,24 +111,7 @@ function writeResponse(response) {
|
|
|
111
111
|
logDebug('stdout.write_skipped', { ok: response?.ok, code: response?.error?.code });
|
|
112
112
|
return false;
|
|
113
113
|
}
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
frame = encodeMessage(response);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
const fallback = buildOversizeResponseFallback(response, error);
|
|
119
|
-
try {
|
|
120
|
-
frame = encodeMessage(fallback);
|
|
121
|
-
} catch (fallbackError) {
|
|
122
|
-
frame = encodeMessage({
|
|
123
|
-
id: response?.id,
|
|
124
|
-
ok: false,
|
|
125
|
-
error: {
|
|
126
|
-
code: 'native_response_too_large',
|
|
127
|
-
message: truncateForNativeFrame(fallbackError.message || error.message || 'Native response exceeded the browser frame limit.', 800)
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
114
|
+
const frame = encodeOutputFrame(response);
|
|
132
115
|
logDebug('stdout.write', { bytes: frame.length, ok: response?.ok, code: response?.error?.code });
|
|
133
116
|
try {
|
|
134
117
|
process.stdout.write(frame, error => {
|
|
@@ -168,55 +151,6 @@ function handleNativeDisconnect(source, error) {
|
|
|
168
151
|
exitTimer.unref?.();
|
|
169
152
|
}
|
|
170
153
|
|
|
171
|
-
function buildOversizeResponseFallback(response, error) {
|
|
172
|
-
if (response?.event) {
|
|
173
|
-
const event = response.event || {};
|
|
174
|
-
return {
|
|
175
|
-
id: response.id,
|
|
176
|
-
ok: true,
|
|
177
|
-
event: {
|
|
178
|
-
type: event.type || 'native.event.truncated',
|
|
179
|
-
title: truncateForNativeFrame(event.title || 'Native event was truncated', 500),
|
|
180
|
-
status: event.status || 'warning',
|
|
181
|
-
detail: {
|
|
182
|
-
code: 'native_event_truncated',
|
|
183
|
-
reason: truncateForNativeFrame(error?.message || 'Native event exceeded the browser frame limit.', 800),
|
|
184
|
-
originalType: truncateForNativeFrame(event.type || '', 160),
|
|
185
|
-
originalTitle: truncateForNativeFrame(event.title || '', 500),
|
|
186
|
-
originalDetailBytes: stringByteLength(safeJsonStringify(event.detail))
|
|
187
|
-
},
|
|
188
|
-
timestamp: event.timestamp || new Date().toISOString()
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
id: response?.id,
|
|
195
|
-
ok: false,
|
|
196
|
-
error: {
|
|
197
|
-
code: 'native_response_too_large',
|
|
198
|
-
message: truncateForNativeFrame(error?.message || 'Native response exceeded the browser frame limit.', 800),
|
|
199
|
-
originalOk: response?.ok === true
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function truncateForNativeFrame(value, limit) {
|
|
205
|
-
const text = String(value || '');
|
|
206
|
-
if (text.length <= limit) {
|
|
207
|
-
return text;
|
|
208
|
-
}
|
|
209
|
-
return `${text.slice(0, Math.max(0, limit - 24))}... [truncated]`;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function safeJsonStringify(value) {
|
|
213
|
-
try {
|
|
214
|
-
return JSON.stringify(value);
|
|
215
|
-
} catch (_error) {
|
|
216
|
-
return '';
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
154
|
function summarizeRequest(message) {
|
|
221
155
|
const params = message?.params || {};
|
|
222
156
|
return {
|
|
@@ -54,14 +54,19 @@ function installManagedDistribution(options = {}) {
|
|
|
54
54
|
const unique = process.pid + '-' + Date.now() + '-' + Math.random().toString(16).slice(2);
|
|
55
55
|
const extensionStage = path.join(parent, '.extension.staging-' + unique);
|
|
56
56
|
const extensionRollback = path.join(parent, '.extension.rollback-' + unique);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
try {
|
|
58
|
+
buildManagedExtensionTree({
|
|
59
|
+
packageRoot,
|
|
60
|
+
targetRoot: extensionStage,
|
|
61
|
+
version,
|
|
62
|
+
releaseRef,
|
|
63
|
+
releaseChannel,
|
|
64
|
+
allowedFiles: options.allowedFiles
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
safeRemove(extensionStage);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
65
70
|
|
|
66
71
|
const previousExtensionMarker = readManagedMarker(extensionRoot, EXTENSION_MARKER);
|
|
67
72
|
if (fs.existsSync(extensionRoot) && !isManagedMarker(previousExtensionMarker, 'extension')) {
|
|
@@ -145,6 +150,7 @@ function buildManagedExtensionTree(options = {}) {
|
|
|
145
150
|
copyPackageTree(packageRoot, 'extension/vendor', targetRoot, 'runtime/vendor', { allowedFiles });
|
|
146
151
|
copyPackageFile(packageRoot, 'extension/runtime-manifest.json', targetRoot, 'runtime/runtime-manifest.json', allowedFiles);
|
|
147
152
|
rewriteManagedRuntimeAssetPaths(targetRoot);
|
|
153
|
+
assertManagedRuntimeManifestFiles(targetRoot);
|
|
148
154
|
fs.writeFileSync(path.join(targetRoot, EXTENSION_MARKER), JSON.stringify({
|
|
149
155
|
managedBy: MANAGED_BY,
|
|
150
156
|
kind: 'extension',
|
|
@@ -413,6 +419,41 @@ function resolveForPlatform(value, platformPath) {
|
|
|
413
419
|
return platformPath.isAbsolute(value) ? value : platformPath.resolve(value);
|
|
414
420
|
}
|
|
415
421
|
|
|
422
|
+
function assertManagedRuntimeManifestFiles(targetRoot) {
|
|
423
|
+
const runtimeRoot = path.join(targetRoot, 'runtime');
|
|
424
|
+
const runtimeManifest = readJson(path.join(runtimeRoot, 'runtime-manifest.json'));
|
|
425
|
+
const runtimeFiles = [
|
|
426
|
+
...(Array.isArray(runtimeManifest.js) ? runtimeManifest.js : []),
|
|
427
|
+
...(Array.isArray(runtimeManifest.css) ? runtimeManifest.css : [])
|
|
428
|
+
];
|
|
429
|
+
const missing = [];
|
|
430
|
+
|
|
431
|
+
for (const relativePath of runtimeFiles) {
|
|
432
|
+
if (
|
|
433
|
+
typeof relativePath !== 'string'
|
|
434
|
+
|| relativePath.length === 0
|
|
435
|
+
|| path.isAbsolute(relativePath)
|
|
436
|
+
|| relativePath.split(/[\\/]+/).includes('..')
|
|
437
|
+
) {
|
|
438
|
+
throw new Error('Managed runtime manifest contains an unsafe path: ' + String(relativePath));
|
|
439
|
+
}
|
|
440
|
+
const filePath = path.resolve(runtimeRoot, relativePath);
|
|
441
|
+
const relativeToRuntime = path.relative(runtimeRoot, filePath);
|
|
442
|
+
if (
|
|
443
|
+
relativeToRuntime.startsWith('..')
|
|
444
|
+
|| path.isAbsolute(relativeToRuntime)
|
|
445
|
+
|| !fs.existsSync(filePath)
|
|
446
|
+
|| !fs.statSync(filePath).isFile()
|
|
447
|
+
) {
|
|
448
|
+
missing.push(relativePath);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (missing.length > 0) {
|
|
453
|
+
throw new Error('Managed runtime is incomplete; missing file(s): ' + missing.join(', '));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
416
457
|
function safeRemove(target) {
|
|
417
458
|
fs.rmSync(target, { recursive: true, force: true });
|
|
418
459
|
}
|
|
@@ -425,6 +466,7 @@ module.exports = {
|
|
|
425
466
|
EXTENSION_MARKER,
|
|
426
467
|
MANAGED_BY,
|
|
427
468
|
NATIVE_MARKER,
|
|
469
|
+
assertManagedRuntimeManifestFiles,
|
|
428
470
|
assertSafeManagedRoot,
|
|
429
471
|
buildManagedExtensionTree,
|
|
430
472
|
installManagedDistribution,
|
|
@@ -124,13 +124,15 @@ async function collectMirrorChangesDetailed({ projectId, rootDir }) {
|
|
|
124
124
|
const previous = baselineByPath.get(filePath);
|
|
125
125
|
const target = resolveWorkspacePath(mirror.workspacePath, filePath);
|
|
126
126
|
const stat = fs.statSync(target);
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
127
|
+
if (isGeneratedArtifactPath(filePath, baselineByPath)) {
|
|
128
|
+
if (!previous || !workspaceFileMatchesBaseline(target, previous)) {
|
|
129
|
+
unsupportedChanges.push({
|
|
130
|
+
type: 'unsupported-local-file',
|
|
131
|
+
path: filePath,
|
|
132
|
+
reason: 'generated_artifact',
|
|
133
|
+
size: stat.size
|
|
134
|
+
});
|
|
135
|
+
}
|
|
134
136
|
continue;
|
|
135
137
|
}
|
|
136
138
|
if (isSupportedBinaryAssetPath(filePath)) {
|
|
@@ -602,7 +604,12 @@ function hasMatchingRootSourceFile(normalizedPdfPath, baselineByPath) {
|
|
|
602
604
|
return true;
|
|
603
605
|
}
|
|
604
606
|
const stem = normalizedPdfPath.replace(/\.pdf$/i, '');
|
|
605
|
-
|
|
607
|
+
const sourcePath = `${stem}.tex`;
|
|
608
|
+
const hasMatchingSource = baselineByPath.has(sourcePath)
|
|
609
|
+
|| Array.from(baselineByPath.keys()).some(filePath =>
|
|
610
|
+
normalizeRelativePath(filePath).toLowerCase() === sourcePath
|
|
611
|
+
);
|
|
612
|
+
return hasMatchingSource || stem === 'main' || stem === 'output';
|
|
606
613
|
}
|
|
607
614
|
|
|
608
615
|
function isSupportedBinaryAssetPath(filePath) {
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
MAX_NATIVE_OUTPUT_MESSAGE_BYTES,
|
|
5
|
+
decodeFrames,
|
|
6
|
+
encodeMessage
|
|
7
|
+
} = require('./nativeMessaging');
|
|
8
|
+
const nativeQuotas = require('./nativeQuotas');
|
|
9
|
+
const {
|
|
10
|
+
enforceNativeOkResponseBudget,
|
|
11
|
+
truncateUtf8Text
|
|
12
|
+
} = require('./nativeResponseBudget');
|
|
13
|
+
|
|
14
|
+
function decodeInputFrames(buffer) {
|
|
15
|
+
return decodeFrames(buffer);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function encodeOutputFrame(response) {
|
|
19
|
+
try {
|
|
20
|
+
return encodeMessage(response);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
const fallback = buildOversizeResponseFallback(response, error);
|
|
23
|
+
try {
|
|
24
|
+
return encodeMessage(fallback);
|
|
25
|
+
} catch (fallbackError) {
|
|
26
|
+
return encodeMessage(buildFinalOversizeError(response, fallbackError, error));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getRequestQuotaViolation(request) {
|
|
32
|
+
if (typeof request?.id === "string" && request.id.length > 160) {
|
|
33
|
+
return {
|
|
34
|
+
field: "id",
|
|
35
|
+
limit: 160,
|
|
36
|
+
actual: request.id.length,
|
|
37
|
+
reason: "request id is too large"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return nativeQuotas.validateNativeRequestQuotas(request);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function reduceTaskResult(result) {
|
|
44
|
+
return enforceNativeOkResponseBudget(result);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function buildOversizeResponseFallback(response, error) {
|
|
48
|
+
if (response?.event) {
|
|
49
|
+
const event = response.event || {};
|
|
50
|
+
return {
|
|
51
|
+
id: boundedResponseId(response.id),
|
|
52
|
+
ok: true,
|
|
53
|
+
event: {
|
|
54
|
+
type: event.type || 'native.event.truncated',
|
|
55
|
+
title: truncateForNativeFrame(event.title || 'Native event was truncated', 500),
|
|
56
|
+
status: event.status || 'warning',
|
|
57
|
+
detail: {
|
|
58
|
+
code: 'native_event_truncated',
|
|
59
|
+
reason: truncateForNativeFrame(
|
|
60
|
+
error?.message || 'Native event exceeded the browser frame limit.',
|
|
61
|
+
800
|
|
62
|
+
),
|
|
63
|
+
originalType: truncateForNativeFrame(event.type || '', 160),
|
|
64
|
+
originalTitle: truncateForNativeFrame(event.title || '', 500),
|
|
65
|
+
originalDetailBytes: measureJsonBytes(event.detail)
|
|
66
|
+
},
|
|
67
|
+
timestamp: event.timestamp || new Date().toISOString()
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
id: boundedResponseId(response?.id),
|
|
74
|
+
ok: false,
|
|
75
|
+
error: {
|
|
76
|
+
code: 'native_response_too_large',
|
|
77
|
+
message: truncateForNativeFrame(
|
|
78
|
+
error?.message || 'Native response exceeded the browser frame limit.',
|
|
79
|
+
800
|
|
80
|
+
),
|
|
81
|
+
originalOk: response?.ok === true
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function buildFinalOversizeError(response, fallbackError, originalError) {
|
|
87
|
+
return {
|
|
88
|
+
id: boundedResponseId(response?.id),
|
|
89
|
+
ok: false,
|
|
90
|
+
error: {
|
|
91
|
+
code: 'native_response_too_large',
|
|
92
|
+
message: truncateForNativeFrame(
|
|
93
|
+
fallbackError?.message
|
|
94
|
+
|| originalError?.message
|
|
95
|
+
|| 'Native response exceeded the browser frame limit.',
|
|
96
|
+
800
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function boundedResponseId(value) {
|
|
103
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
return truncateForNativeFrame(value, 160);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function measureJsonBytes(value) {
|
|
110
|
+
try {
|
|
111
|
+
return Buffer.byteLength(JSON.stringify(value), 'utf8');
|
|
112
|
+
} catch (_error) {
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function truncateForNativeFrame(value, maxChars) {
|
|
118
|
+
const text = String(value || '');
|
|
119
|
+
if (text.length <= maxChars) {
|
|
120
|
+
return text;
|
|
121
|
+
}
|
|
122
|
+
return `${text.slice(0, Math.max(0, maxChars - 24))}... [truncated]`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = {
|
|
126
|
+
MAX_NATIVE_OUTPUT_MESSAGE_BYTES,
|
|
127
|
+
NATIVE_REQUEST_QUOTAS: nativeQuotas.NATIVE_REQUEST_QUOTAS,
|
|
128
|
+
buildOversizeResponseFallback,
|
|
129
|
+
decodeInputFrames,
|
|
130
|
+
encodeOutputFrame,
|
|
131
|
+
estimateBase64DecodedBytes: nativeQuotas.estimateBase64DecodedBytes,
|
|
132
|
+
firstQuotaViolation: nativeQuotas.firstQuotaViolation,
|
|
133
|
+
getRequestQuotaViolation,
|
|
134
|
+
measureJsonBytes,
|
|
135
|
+
measureOperationPayloads: nativeQuotas.measureOperationPayloads,
|
|
136
|
+
quotaViolation: nativeQuotas.quotaViolation,
|
|
137
|
+
reduceTaskResult,
|
|
138
|
+
truncateForNativeFrame,
|
|
139
|
+
truncateUtf8Text,
|
|
140
|
+
validateAttachmentQuota: nativeQuotas.validateAttachmentQuota,
|
|
141
|
+
validateCompileLogQuota: nativeQuotas.validateCompileLogQuota,
|
|
142
|
+
validateFilePayloadQuota: nativeQuotas.validateFilePayloadQuota,
|
|
143
|
+
validateOperationListQuota: nativeQuotas.validateOperationListQuota,
|
|
144
|
+
validateOperationPayloadQuota: nativeQuotas.validateOperationPayloadQuota,
|
|
145
|
+
validatePatchFileTextQuota: nativeQuotas.validatePatchFileTextQuota,
|
|
146
|
+
validateProjectSnapshotQuota: nativeQuotas.validateProjectSnapshotQuota,
|
|
147
|
+
validateSkillContentQuota: nativeQuotas.validateSkillContentQuota
|
|
148
|
+
};
|
|
@@ -26,10 +26,10 @@ const { getNativeRuntimePlatform, summarizeNativeEnvironment } = require('./nati
|
|
|
26
26
|
const {
|
|
27
27
|
NATIVE_REQUEST_QUOTAS,
|
|
28
28
|
firstQuotaViolation,
|
|
29
|
-
|
|
29
|
+
getRequestQuotaViolation,
|
|
30
30
|
validateOperationListQuota,
|
|
31
31
|
validateOperationPayloadQuota
|
|
32
|
-
} = require('./
|
|
32
|
+
} = require('./nativeTransportEnvelope');
|
|
33
33
|
const { version: PACKAGE_VERSION } = require('../../package.json');
|
|
34
34
|
|
|
35
35
|
const activeProjectLocks = new Map();
|
|
@@ -49,7 +49,7 @@ async function handleRequest(request, env = process.env, emit = () => {}) {
|
|
|
49
49
|
return errorResponse(undefined, 'invalid_request', 'Request must be an object');
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const quotaError =
|
|
52
|
+
const quotaError = getRequestQuotaViolation(request);
|
|
53
53
|
if (quotaError) {
|
|
54
54
|
return quotaErrorResponse(request.id, quotaError);
|
|
55
55
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-overleaf-link",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Cross-platform Chrome bridge that connects Codex to the active Overleaf project.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -14,14 +14,19 @@
|
|
|
14
14
|
"homepage": "https://github.com/Ghqqqq/codex-overleaf-link#readme",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"agent:codex": "node scripts/codex-json-agent.mjs",
|
|
17
|
-
"
|
|
17
|
+
"build:content": "node scripts/build-content-bundle.mjs",
|
|
18
|
+
"check:module-graph": "node scripts/check-content-module-graph.mjs",
|
|
19
|
+
"test": "npm run check:module-graph && node scripts/run-tests.mjs",
|
|
18
20
|
"check:architecture": "node scripts/check-architecture-budget.mjs --enforce-target",
|
|
19
21
|
"benchmark:large": "node scripts/benchmark-large-project.mjs --gate",
|
|
20
|
-
"smoke:extension": "node scripts/smoke-extension.mjs",
|
|
22
|
+
"smoke:extension": "npm run build:content && node scripts/smoke-extension.mjs",
|
|
21
23
|
"verify:release": "node scripts/verify-release.mjs",
|
|
24
|
+
"verify:source": "node scripts/verify-release.mjs --source-hygiene-only",
|
|
22
25
|
"verify:release-artifacts": "node scripts/verify-release-artifacts.mjs",
|
|
23
26
|
"verify:update-boundary": "node scripts/verify-update-boundary.mjs",
|
|
24
27
|
"verify:update-hop": "node scripts/verify-update-hop.mjs",
|
|
28
|
+
"verify:update-hop:local": "node scripts/verify-update-hop.mjs --local-test-key",
|
|
29
|
+
"rehearse:update-hop": "npm run build:release && npm run verify:update-hop:local",
|
|
25
30
|
"build:release": "node scripts/build-release.mjs",
|
|
26
31
|
"sign:release": "node scripts/sign-release-manifest.mjs",
|
|
27
32
|
"install:managed": "node scripts/install-managed.mjs",
|
|
@@ -30,7 +35,7 @@
|
|
|
30
35
|
"uninstall:native": "node scripts/uninstall-native-host.mjs",
|
|
31
36
|
"bridge": "node native-host/src/index.js",
|
|
32
37
|
"verify:npm-package": "node scripts/verify-npm-package.mjs",
|
|
33
|
-
"pack:npm": "node scripts/verify-npm-package.mjs --pack"
|
|
38
|
+
"pack:npm": "npm run build:content && node scripts/verify-npm-package.mjs --pack"
|
|
34
39
|
},
|
|
35
40
|
"engines": {
|
|
36
41
|
"node": ">=20"
|
|
@@ -56,5 +61,8 @@
|
|
|
56
61
|
"scripts/verify-npm-package.mjs",
|
|
57
62
|
"README.md",
|
|
58
63
|
"package.json"
|
|
59
|
-
]
|
|
64
|
+
],
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"esbuild": "0.28.1"
|
|
67
|
+
}
|
|
60
68
|
}
|