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.
Files changed (72) hide show
  1. package/README.md +25 -23
  2. package/extension/bootstrap/manifest.template.json +1 -1
  3. package/extension/runtime-manifest.json +5 -71
  4. package/extension/src/background.js +53 -69
  5. package/extension/src/backgroundUpdateCoordinator.js +128 -66
  6. package/extension/src/content/applyResultFormatters.js +2 -3
  7. package/extension/src/content/contentRuntime.js +650 -1449
  8. package/extension/src/content/contextTray.js +4 -6
  9. package/extension/src/content/diagnosticsController.js +1 -2
  10. package/extension/src/content/diffReviewPanel.js +14 -13
  11. package/extension/src/content/generated/content.bundle.js +41370 -0
  12. package/extension/src/content/generated/content.bundle.meta.json +102 -0
  13. package/extension/src/content/legacyGlobalRegistry.js +129 -0
  14. package/extension/src/content/markdownText.js +5 -7
  15. package/extension/src/content/modelPicker.js +1 -1
  16. package/extension/src/content/modelPickerSupport.js +10 -5
  17. package/extension/src/content/moduleRegistryKernel.js +125 -0
  18. package/extension/src/content/nativeCompatibilityController.js +313 -0
  19. package/extension/src/content/otWarmMirror.js +7 -5
  20. package/extension/src/content/pageBridgeClient.js +224 -0
  21. package/extension/src/content/panelMaintenance.js +8 -3
  22. package/extension/src/content/postNavigationSettlementPersistence.js +100 -0
  23. package/extension/src/content/projectProviderSelection.js +4 -12
  24. package/extension/src/content/projectSessionCleanup.js +3 -3
  25. package/extension/src/content/providerSettingsCoordinator.js +59 -26
  26. package/extension/src/content/providerSettingsDialog.js +30 -18
  27. package/extension/src/content/recentProjects.js +15 -23
  28. package/extension/src/content/runGuidanceController.js +1 -1
  29. package/extension/src/content/runQueueScheduler.js +129 -29
  30. package/extension/src/content/runSettlementPersistence.js +51 -0
  31. package/extension/src/content/runTimelineView.js +11 -8
  32. package/extension/src/content/scopedPersistenceCoordinator.js +100 -0
  33. package/extension/src/content/scopedPersistenceDetachedCommit.js +47 -0
  34. package/extension/src/content/scopedPersistencePanelState.js +111 -0
  35. package/extension/src/content/sessionManager.js +15 -12
  36. package/extension/src/content/sessionPersistence.js +67 -8
  37. package/extension/src/content/updateNotice.js +10 -4
  38. package/extension/src/content/writebackOrchestrator.js +91 -23
  39. package/extension/src/contentScript.js +5 -1
  40. package/extension/src/page/trackedChangesLifecycle.js +6 -1
  41. package/extension/src/pageBridge.js +47 -98
  42. package/extension/src/shared/agentTranscript.js +8 -5
  43. package/extension/src/shared/compatibility.js +1 -1
  44. package/extension/src/shared/governanceRules.js +1 -1
  45. package/extension/src/shared/managedUpdateProjection.js +337 -0
  46. package/extension/src/shared/nativeRequestIdentity.js +60 -0
  47. package/extension/src/shared/otText.js +0 -19
  48. package/extension/src/shared/pageRpcContract.js +136 -0
  49. package/extension/src/shared/runExecutionSnapshot.js +177 -0
  50. package/extension/src/shared/runExecutionSnapshotCodec.js +168 -0
  51. package/extension/src/shared/runInputQueue.js +81 -34
  52. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +79 -0
  53. package/extension/src/shared/scopedPersistenceQueuePolicy.js +181 -0
  54. package/extension/src/shared/scopedPersistenceTransaction.js +238 -0
  55. package/extension/src/shared/sessionState.js +64 -48
  56. package/extension/src/shared/settlementFacts.js +351 -0
  57. package/extension/src/shared/storageDb.js +19 -5
  58. package/extension/src/shared/storageMigration.js +275 -61
  59. package/extension/src/shared/storageSessionClaims.js +60 -0
  60. package/extension/src/shared/updateConsent.js +4 -0
  61. package/extension/src/shared/updateRevocationIntent.js +109 -0
  62. package/extension/src/shared/writebackEvidenceProjection.js +150 -0
  63. package/extension/src/shared/writebackOperationEvidence.js +143 -0
  64. package/extension/src/shared/writebackSettlement.js +705 -0
  65. package/native-host/src/codexRuntimeIdentity.js +1 -1
  66. package/native-host/src/codexSessionRunner.js +7 -13
  67. package/native-host/src/index.js +3 -69
  68. package/native-host/src/managedInstall.js +50 -8
  69. package/native-host/src/mirrorWorkspace.js +15 -8
  70. package/native-host/src/nativeTransportEnvelope.js +148 -0
  71. package/native-host/src/taskRunnerRuntime.js +3 -3
  72. 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 = 700;
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 { enforceNativeOkResponseBudget } = require('./nativeResponseBudget');
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 enforceNativeOkResponseBudget({
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 enforceNativeOkResponseBudget({
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 = enforceNativeOkResponseBudget({
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, '')
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- const { decodeFrames, encodeMessage } = require('./nativeMessaging');
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 = decodeFrames(buffered);
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
- let frame;
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
- buildManagedExtensionTree({
58
- packageRoot,
59
- targetRoot: extensionStage,
60
- version,
61
- releaseRef,
62
- releaseChannel,
63
- allowedFiles: options.allowedFiles
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 (!previous && isGeneratedArtifactPath(filePath, baselineByPath)) {
128
- unsupportedChanges.push({
129
- type: 'unsupported-local-file',
130
- path: filePath,
131
- reason: 'generated_artifact',
132
- size: stat.size
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
- return baselineByPath.has(`${stem}.tex`) || stem === 'main' || stem === 'output';
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
- validateNativeRequestQuotas,
29
+ getRequestQuotaViolation,
30
30
  validateOperationListQuota,
31
31
  validateOperationPayloadQuota
32
- } = require('./nativeQuotas');
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 = validateNativeRequestQuotas(request);
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.2.0",
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
- "test": "node scripts/run-tests.mjs",
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
  }