codex-overleaf-link 1.9.13 → 2.1.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 (122) hide show
  1. package/README.md +24 -23
  2. package/extension/bootstrap/manifest.template.json +2 -1
  3. package/extension/runtime-manifest.json +13 -6
  4. package/extension/src/background.js +7 -0
  5. package/extension/src/content/composerPanel.js +13 -3
  6. package/extension/src/content/contentRuntime.js +130 -65
  7. package/extension/src/content/contextTray.js +173 -9
  8. package/extension/src/content/markdownText.js +16 -1
  9. package/extension/src/content/mathText.js +233 -0
  10. package/extension/src/content/modelPicker.js +117 -106
  11. package/extension/src/content/modelPickerSupport.js +115 -0
  12. package/extension/src/content/nativeChannel.js +20 -1
  13. package/extension/src/content/panelMaintenance.js +2 -0
  14. package/extension/src/content/projectSettingsCoordinator.js +2 -0
  15. package/extension/src/content/providerSettingsCoordinator.js +413 -0
  16. package/extension/src/content/providerSettingsDialog.js +981 -0
  17. package/extension/src/content/runTimelineView.js +24 -5
  18. package/extension/src/content/settingsPanel.js +33 -2
  19. package/extension/src/content/writebackOrchestrator.js +3 -1
  20. package/extension/src/page/overleafProjectSnapshot.js +29 -33
  21. package/extension/src/page/snapshotRouter.js +75 -8
  22. package/extension/src/page/trackedChangesLifecycle.js +154 -26
  23. package/extension/src/page/writebackRouter.js +31 -60
  24. package/extension/src/pageBridge.js +1 -1
  25. package/extension/src/shared/agentTranscript.js +130 -0
  26. package/extension/src/shared/compatibility.js +10 -7
  27. package/extension/src/shared/failureReasons.js +75 -0
  28. package/extension/src/shared/i18n.js +22 -0
  29. package/extension/src/shared/models.js +1 -0
  30. package/extension/src/shared/providerProfiles.js +283 -0
  31. package/extension/src/shared/sessionState.js +12 -2
  32. package/extension/src/shared/storageDb.js +27 -19
  33. package/extension/src/shared/storageRunActions.js +99 -0
  34. package/extension/styles/panel.css +587 -1
  35. package/extension/vendor/katex/LICENSE +21 -0
  36. package/extension/vendor/katex/VERSION +2 -0
  37. package/extension/vendor/katex/fonts/KaTeX_AMS-Regular.ttf +0 -0
  38. package/extension/vendor/katex/fonts/KaTeX_AMS-Regular.woff +0 -0
  39. package/extension/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  40. package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  41. package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  42. package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  43. package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  44. package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  45. package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  46. package/extension/vendor/katex/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  47. package/extension/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  48. package/extension/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  49. package/extension/vendor/katex/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  50. package/extension/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  51. package/extension/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  52. package/extension/vendor/katex/fonts/KaTeX_Main-Bold.ttf +0 -0
  53. package/extension/vendor/katex/fonts/KaTeX_Main-Bold.woff +0 -0
  54. package/extension/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  55. package/extension/vendor/katex/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  56. package/extension/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  57. package/extension/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  58. package/extension/vendor/katex/fonts/KaTeX_Main-Italic.ttf +0 -0
  59. package/extension/vendor/katex/fonts/KaTeX_Main-Italic.woff +0 -0
  60. package/extension/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  61. package/extension/vendor/katex/fonts/KaTeX_Main-Regular.ttf +0 -0
  62. package/extension/vendor/katex/fonts/KaTeX_Main-Regular.woff +0 -0
  63. package/extension/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  64. package/extension/vendor/katex/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  65. package/extension/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  66. package/extension/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  67. package/extension/vendor/katex/fonts/KaTeX_Math-Italic.ttf +0 -0
  68. package/extension/vendor/katex/fonts/KaTeX_Math-Italic.woff +0 -0
  69. package/extension/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  70. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  71. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  72. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  73. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  74. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  75. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  76. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  77. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  78. package/extension/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  79. package/extension/vendor/katex/fonts/KaTeX_Script-Regular.ttf +0 -0
  80. package/extension/vendor/katex/fonts/KaTeX_Script-Regular.woff +0 -0
  81. package/extension/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  82. package/extension/vendor/katex/fonts/KaTeX_Size1-Regular.ttf +0 -0
  83. package/extension/vendor/katex/fonts/KaTeX_Size1-Regular.woff +0 -0
  84. package/extension/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  85. package/extension/vendor/katex/fonts/KaTeX_Size2-Regular.ttf +0 -0
  86. package/extension/vendor/katex/fonts/KaTeX_Size2-Regular.woff +0 -0
  87. package/extension/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  88. package/extension/vendor/katex/fonts/KaTeX_Size3-Regular.ttf +0 -0
  89. package/extension/vendor/katex/fonts/KaTeX_Size3-Regular.woff +0 -0
  90. package/extension/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  91. package/extension/vendor/katex/fonts/KaTeX_Size4-Regular.ttf +0 -0
  92. package/extension/vendor/katex/fonts/KaTeX_Size4-Regular.woff +0 -0
  93. package/extension/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  94. package/extension/vendor/katex/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  95. package/extension/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  96. package/extension/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  97. package/extension/vendor/katex/katex.min.css +1 -0
  98. package/extension/vendor/katex/katex.min.js +1 -0
  99. package/native-host/src/anthropicBridgeRequest.js +435 -0
  100. package/native-host/src/anthropicBridgeResponse.js +431 -0
  101. package/native-host/src/anthropicMessagesBridge.js +281 -0
  102. package/native-host/src/chatBridgeRequest.js +274 -0
  103. package/native-host/src/chatBridgeResponse.js +594 -0
  104. package/native-host/src/chatCompletionsBridge.js +485 -0
  105. package/native-host/src/codexCommand.js +25 -0
  106. package/native-host/src/codexPromptAssembly.js +9 -0
  107. package/native-host/src/codexProviderLaunch.js +213 -0
  108. package/native-host/src/codexProviderTest.js +196 -0
  109. package/native-host/src/codexSessionRunner.js +29 -25
  110. package/native-host/src/managedInstall.js +1 -0
  111. package/native-host/src/providerBridgeRoutes.js +11 -0
  112. package/native-host/src/providerModelCatalog.js +107 -0
  113. package/native-host/src/providerProfile.js +454 -0
  114. package/native-host/src/providerReasoning.js +235 -0
  115. package/native-host/src/providerRedaction.js +18 -0
  116. package/native-host/src/providerRuntime.js +365 -0
  117. package/native-host/src/providerStore.js +691 -0
  118. package/native-host/src/readProgressGuard.js +360 -0
  119. package/native-host/src/taskRunnerRuntime.js +40 -4
  120. package/native-host/src/updateArchive.js +1 -0
  121. package/native-host/src/updateTrust.js +2 -1
  122. package/package.json +2 -1
@@ -288,6 +288,81 @@
288
288
  fallbackUserMessage: 'Local Codex returned no usable final report or operations.',
289
289
  fallbackNextAction: 'Open Technical Details and resolve the local Codex error.'
290
290
  },
291
+ provider_revision_conflict: {
292
+ stage: 'preflight', severity: 'blocked', defaultRetryable: true,
293
+ fallbackUserMessage: 'The active model provider changed after this tab loaded it.',
294
+ fallbackNextAction: 'Refresh the provider configuration and retry.'
295
+ },
296
+ provider_not_found: {
297
+ stage: 'preflight', severity: 'blocked', defaultRetryable: false,
298
+ fallbackUserMessage: 'The active model provider no longer exists.',
299
+ fallbackNextAction: 'Select Built-in Codex or another provider.'
300
+ },
301
+ provider_model_not_configured: {
302
+ stage: 'preflight', severity: 'blocked', defaultRetryable: false,
303
+ fallbackUserMessage: 'The selected model is not configured for the active provider.',
304
+ fallbackNextAction: 'Add or select a model in Model Providers.'
305
+ },
306
+ provider_protocol_unverified: {
307
+ stage: 'preflight', severity: 'blocked', defaultRetryable: true,
308
+ fallbackUserMessage: 'The provider API protocol has not been verified.',
309
+ fallbackNextAction: 'Run Test connection, save the provider, and retry.'
310
+ },
311
+ provider_auth_rejected: {
312
+ stage: 'codex', severity: 'blocked', defaultRetryable: false,
313
+ fallbackUserMessage: 'The provider rejected the configured API key.',
314
+ fallbackNextAction: 'Replace the API key and test the connection.'
315
+ },
316
+ provider_model_not_found: {
317
+ stage: 'codex', severity: 'blocked', defaultRetryable: false,
318
+ fallbackUserMessage: 'The provider could not find the configured model.',
319
+ fallbackNextAction: 'Correct the model ID and test the connection.'
320
+ },
321
+ provider_protocol_incompatible: {
322
+ stage: 'codex', severity: 'blocked', defaultRetryable: false,
323
+ fallbackUserMessage: 'The endpoint is incompatible with the selected API protocol.',
324
+ fallbackNextAction: 'Select another protocol or use Auto detection.'
325
+ },
326
+ provider_request_rejected: {
327
+ stage: 'codex', severity: 'blocked', defaultRetryable: false,
328
+ fallbackUserMessage: 'The provider rejected the protocol probe request.',
329
+ fallbackNextAction: 'Review the model ID, reasoning controls, tool support, and request overrides.'
330
+ },
331
+ provider_rate_limited: {
332
+ stage: 'codex', severity: 'error', defaultRetryable: true,
333
+ fallbackUserMessage: 'The provider rate limit was reached.',
334
+ fallbackNextAction: 'Wait for the rate-limit window to recover and retry.'
335
+ },
336
+ provider_connection_timeout: {
337
+ stage: 'codex', severity: 'error', defaultRetryable: true,
338
+ fallbackUserMessage: 'The provider connection timed out.',
339
+ fallbackNextAction: 'Check the endpoint and network, then retry.'
340
+ },
341
+ provider_dns_failed: {
342
+ stage: 'codex', severity: 'error', defaultRetryable: true,
343
+ fallbackUserMessage: 'The provider hostname could not be resolved.',
344
+ fallbackNextAction: 'Check the Base URL and DNS, then retry.'
345
+ },
346
+ provider_tls_failed: {
347
+ stage: 'codex', severity: 'error', defaultRetryable: true,
348
+ fallbackUserMessage: 'TLS verification failed for the provider endpoint.',
349
+ fallbackNextAction: 'Check the endpoint certificate and Base URL.'
350
+ },
351
+ provider_response_invalid: {
352
+ stage: 'codex', severity: 'error', defaultRetryable: true,
353
+ fallbackUserMessage: 'The provider returned an incompatible or invalid response.',
354
+ fallbackNextAction: 'Test the connection and verify protocol compatibility.'
355
+ },
356
+ provider_store_unavailable: {
357
+ stage: 'storage', severity: 'error', defaultRetryable: true,
358
+ fallbackUserMessage: 'The Native Host could not access provider configuration storage.',
359
+ fallbackNextAction: 'Check local permissions and Native Host status.'
360
+ },
361
+ provider_store_corrupt: {
362
+ stage: 'storage', severity: 'blocked', defaultRetryable: false,
363
+ fallbackUserMessage: 'The provider configuration store is corrupt or inconsistent.',
364
+ fallbackNextAction: 'Repair or rebuild the local provider configuration.'
365
+ },
291
366
  codex_project_locked: {
292
367
  stage: 'codex', severity: 'blocked', defaultRetryable: true,
293
368
  fallbackUserMessage: 'Another Codex task is already running for this Overleaf project.',
@@ -287,6 +287,11 @@
287
287
  softwareUpdatesTitle: 'Software updates',
288
288
  softwareUpdatesHelp: 'Automatically checks signed stable releases for the Extension and Native Host.',
289
289
  checkForUpdates: 'Check for updates',
290
+ providerSettingsTitle: 'Model providers',
291
+ providerSettingsExperimental: 'Third-party experimental',
292
+ providerSettingsHelp: 'Configure experimental third-party model APIs. Compatibility varies by provider and gateway.',
293
+ providerSettingsConfigure: 'Configure',
294
+ providerSettingsBuiltin: 'Built-in Codex is active',
290
295
  storageUsageLoading: 'Calculating usage\u2026',
291
296
  storageClearAll: 'Clear all history\u2026',
292
297
  storageClearAllHelp: 'Removes every stored session, run and audit record for all projects. Project settings and rules are kept.',
@@ -343,10 +348,16 @@
343
348
  refreshFileList: 'Refresh file list',
344
349
  contextStatus: 'Type @ to add files, or click +: files, attachments (PDF/images), @compile-log.',
345
350
  contextLoadingFiles: 'Reading available @files...',
351
+ contextSyncTreeLoading: 'Reading the project file tree.',
352
+ contextSyncExactLoading: 'Available files are ready. Completing the full ZIP file list.',
353
+ contextSyncExactReady: 'The complete project file list is ready.',
354
+ contextSyncPartial: 'Available files are shown. The complete ZIP file list is unavailable; refresh to retry.',
346
355
  contextReadFailed: 'Could not read files: {message}',
347
356
  contextNoFiles: 'No usable text files were read from this Overleaf project.',
348
357
  contextSelectedFiles: 'Added {count} @file items. Future tasks will focus on them first.',
349
358
  contextDefaultWholeProject: 'Default is the whole project. Add @file; @compile-log and @current-section are available as context options.',
359
+ preloadProjectContextTitle: 'Preload project context',
360
+ preloadProjectContextDescription: 'Fetch the exact project file list in the background after an Overleaf project becomes idle.',
350
361
  contextResourceTitle: '{path} (non-text resource, shown only as project structure for now)',
351
362
  contextWholeProjectChip: 'Default: whole project',
352
363
  clearFiles: 'Clear all @file context',
@@ -762,6 +773,11 @@
762
773
  softwareUpdatesTitle: '软件更新',
763
774
  softwareUpdatesHelp: '自动检查 Extension 与 Native Host 的签名稳定版本。',
764
775
  checkForUpdates: '检查更新',
776
+ providerSettingsTitle: '模型服务',
777
+ providerSettingsExperimental: '第三方实验性',
778
+ providerSettingsHelp: '配置实验性第三方模型 API;兼容性取决于具体模型服务与网关。',
779
+ providerSettingsConfigure: '配置',
780
+ providerSettingsBuiltin: '当前使用内置 Codex',
765
781
  storageUsageLoading: '正在计算占用…',
766
782
  storageClearAll: '清空全部历史…',
767
783
  storageClearAllHelp: '删除所有项目已存储的全部会话、运行与审计记录。项目设置与规则会保留。',
@@ -818,10 +834,16 @@
818
834
  refreshFileList: '刷新文件列表',
819
835
  contextStatus: '输入 @ 添加文件,或点 +:文件、附件(PDF/图片)、@compile-log。',
820
836
  contextLoadingFiles: '正在读取可添加的 @文件...',
837
+ contextSyncTreeLoading: '正在读取项目文件树。',
838
+ contextSyncExactLoading: '可用文件已经显示,正在补齐完整 ZIP 文件列表。',
839
+ contextSyncExactReady: '完整项目文件列表已经就绪。',
840
+ contextSyncPartial: '当前已显示可用文件,完整 ZIP 文件列表暂不可用;可刷新重试。',
821
841
  contextReadFailed: '读取文件失败:{message}',
822
842
  contextNoFiles: '没有从当前 Overleaf 项目读取到可用文本文件。',
823
843
  contextSelectedFiles: '已添加 {count} 个 @file;后续任务会优先围绕它们。',
824
844
  contextDefaultWholeProject: '默认使用整个项目。可添加 @file;@compile-log 和 @current-section 将作为后续上下文能力。',
845
+ preloadProjectContextTitle: '预加载项目上下文',
846
+ preloadProjectContextDescription: 'Overleaf 项目进入空闲状态后,在后台读取精确的项目文件列表。',
825
847
  contextResourceTitle: '{path}(非文本资源,当前只作为项目结构显示)',
826
848
  contextWholeProjectChip: '默认:整个项目',
827
849
  clearFiles: '清除全部 @file',
@@ -63,6 +63,7 @@
63
63
  id,
64
64
  label,
65
65
  reasoningEfforts: Array.isArray(model?.reasoningEfforts) ? model.reasoningEfforts.slice() : [],
66
+ reasoningPresentation: typeof model?.reasoningPresentation === 'string' ? model.reasoningPresentation : '',
66
67
  speedTiers: normalizeSpeedTiers(model?.speedTiers)
67
68
  };
68
69
 
@@ -0,0 +1,283 @@
1
+ (function initCodexOverleafProviderProfiles(root, factory) {
2
+ if (typeof module === 'object' && module.exports) {
3
+ module.exports = factory();
4
+ } else {
5
+ root.CodexOverleafProviderProfiles = factory();
6
+ }
7
+ })(typeof globalThis !== 'undefined' ? globalThis : window, function providerProfilesFactory() {
8
+ 'use strict';
9
+
10
+ const BUILTIN_PROVIDER_ID = 'builtin';
11
+
12
+ function normalizeCatalog(value = {}) {
13
+ const providers = Array.isArray(value.providers)
14
+ ? value.providers.map(normalizeProvider).filter(Boolean)
15
+ : [];
16
+ if (!providers.some(provider => provider.id === BUILTIN_PROVIDER_ID)) {
17
+ providers.unshift(buildBuiltinProvider());
18
+ }
19
+ const requestedActiveId = normalizeText(value.activeProviderId);
20
+ const activeProviderId = providers.some(provider => provider.id === requestedActiveId)
21
+ ? requestedActiveId
22
+ : BUILTIN_PROVIDER_ID;
23
+ return {
24
+ activeProviderId,
25
+ providers,
26
+ storeRevision: normalizeInteger(value.storeRevision)
27
+ };
28
+ }
29
+
30
+ function normalizeProvider(value) {
31
+ if (!value || typeof value !== 'object') {
32
+ return null;
33
+ }
34
+ const id = normalizeText(value.id);
35
+ if (!id) {
36
+ return null;
37
+ }
38
+ if (id === BUILTIN_PROVIDER_ID || value.kind === 'builtin') {
39
+ return buildBuiltinProvider();
40
+ }
41
+ const models = normalizeModels(value.models);
42
+ const defaultModelId = normalizeText(value.defaultModelId) || models[0]?.id || '';
43
+ return {
44
+ id,
45
+ kind: 'custom',
46
+ revision: normalizeInteger(value.revision),
47
+ name: normalizeText(value.name) || 'Custom provider',
48
+ baseUrl: normalizeText(value.baseUrl),
49
+ wireApiPreference: normalizeWireApi(value.wireApiPreference, true),
50
+ resolvedWireApi: normalizeWireApi(value.resolvedWireApi, false),
51
+ models,
52
+ defaultModelId,
53
+ requestTimeoutMs: normalizeInteger(value.requestTimeoutMs) || 30000,
54
+ reasoningAdapter: normalizeReasoningAdapter(value.reasoningAdapter),
55
+ reasoningCapability: normalizeReasoningCapability(value.reasoningCapability),
56
+ authMode: normalizeAuthMode(value.authMode),
57
+ apiKeyHeaderName: normalizeText(value.apiKeyHeaderName),
58
+ fullEndpoint: value.fullEndpoint === true,
59
+ customHeaders: normalizeRecord(value.customHeaders),
60
+ queryParams: normalizeRecord(value.queryParams),
61
+ bodyOverrides: normalizeRecord(value.bodyOverrides),
62
+ contextWindow: normalizeInteger(value.contextWindow) || 262144,
63
+ supportsParallelToolCalls: value.supportsParallelToolCalls === true,
64
+ supportsStreamOptions: value.supportsStreamOptions === true,
65
+ inputModalities: normalizeInputModalities(value.inputModalities),
66
+ anthropicVersion: normalizeText(value.anthropicVersion) || '2023-06-01',
67
+ anthropicBeta: normalizeText(value.anthropicBeta),
68
+ anthropicThinkingMode: normalizeAnthropicThinkingMode(value.anthropicThinkingMode),
69
+ anthropicPromptCaching: value.anthropicPromptCaching === true,
70
+ impersonateClaudeCode: value.impersonateClaudeCode === true,
71
+ maxOutputTokens: normalizeMaxOutputTokens(value.maxOutputTokens),
72
+ hasSecret: value.hasSecret === true,
73
+ secretUpdatedAt: normalizeInteger(value.secretUpdatedAt),
74
+ endpointDisclosureHost: normalizeText(value.endpointDisclosureHost),
75
+ endpointDisclosureBaseUrl: normalizeText(value.endpointDisclosureBaseUrl),
76
+ endpointDisclosureAcceptedAt: normalizeInteger(value.endpointDisclosureAcceptedAt),
77
+ modelDiagnostics: normalizeModelDiagnostics(value.modelDiagnostics),
78
+ lastVerified: value.lastVerified && typeof value.lastVerified === 'object'
79
+ ? {
80
+ revision: normalizeInteger(value.lastVerified.revision),
81
+ at: normalizeInteger(value.lastVerified.at),
82
+ modelId: normalizeText(value.lastVerified.modelId),
83
+ wireApi: normalizeWireApi(value.lastVerified.wireApi, false),
84
+ upstreamResponseMode: normalizeUpstreamResponseMode(value.lastVerified.upstreamResponseMode, false)
85
+ }
86
+ : null,
87
+ createdAt: normalizeInteger(value.createdAt),
88
+ updatedAt: normalizeInteger(value.updatedAt)
89
+ };
90
+ }
91
+
92
+ function normalizeModels(models) {
93
+ if (!Array.isArray(models)) {
94
+ return [];
95
+ }
96
+ const seen = new Set();
97
+ const result = [];
98
+ for (const value of models) {
99
+ const id = normalizeText(typeof value === 'string' ? value : value?.id);
100
+ if (!id || seen.has(id)) {
101
+ continue;
102
+ }
103
+ seen.add(id);
104
+ result.push({
105
+ id,
106
+ label: normalizeText(value?.label) || id,
107
+ reasoningEfforts: Array.isArray(value?.reasoningEfforts)
108
+ ? value.reasoningEfforts.map(normalizeText).filter(Boolean)
109
+ : [],
110
+ upstreamResponseMode: normalizeUpstreamResponseMode(value?.upstreamResponseMode, true),
111
+ resolvedUpstreamResponseMode: normalizeUpstreamResponseMode(value?.resolvedUpstreamResponseMode, false),
112
+ contextWindow: normalizeInteger(value?.contextWindow) || 262144,
113
+ supportsParallelToolCalls: value?.supportsParallelToolCalls === true,
114
+ inputModalities: normalizeInputModalities(value?.inputModalities),
115
+ baseInstructions: normalizeText(value?.baseInstructions)
116
+ });
117
+ }
118
+ return result;
119
+ }
120
+
121
+ function buildBuiltinProvider() {
122
+ return {
123
+ id: BUILTIN_PROVIDER_ID,
124
+ kind: 'builtin',
125
+ revision: 0,
126
+ name: 'Built-in Codex',
127
+ editable: false,
128
+ deletable: false,
129
+ models: []
130
+ };
131
+ }
132
+
133
+ function buildEmptyDraft() {
134
+ return {
135
+ id: '',
136
+ kind: 'custom',
137
+ revision: 0,
138
+ name: 'Custom provider',
139
+ baseUrl: '',
140
+ wireApiPreference: 'auto',
141
+ resolvedWireApi: '',
142
+ models: [],
143
+ defaultModelId: '',
144
+ requestTimeoutMs: 30000,
145
+ reasoningAdapter: 'auto',
146
+ reasoningCapability: 'auto',
147
+ authMode: 'bearer',
148
+ apiKeyHeaderName: '',
149
+ fullEndpoint: false,
150
+ customHeaders: {},
151
+ queryParams: {},
152
+ bodyOverrides: {},
153
+ contextWindow: 262144,
154
+ supportsParallelToolCalls: false,
155
+ supportsStreamOptions: false,
156
+ inputModalities: ['text'],
157
+ anthropicVersion: '2023-06-01',
158
+ anthropicBeta: '',
159
+ anthropicThinkingMode: 'budget',
160
+ anthropicPromptCaching: false,
161
+ impersonateClaudeCode: false,
162
+ maxOutputTokens: 32768,
163
+ hasSecret: false,
164
+ secretUpdatedAt: 0,
165
+ endpointDisclosureHost: '',
166
+ endpointDisclosureBaseUrl: '',
167
+ modelDiagnostics: {},
168
+ lastVerified: null
169
+ };
170
+ }
171
+
172
+ function getActiveProvider(catalog = {}) {
173
+ const normalized = normalizeCatalog(catalog);
174
+ return normalized.providers.find(provider => provider.id === normalized.activeProviderId)
175
+ || buildBuiltinProvider();
176
+ }
177
+
178
+ function buildRunSelection(catalog = {}) {
179
+ const active = getActiveProvider(catalog);
180
+ return {
181
+ providerId: active.id,
182
+ providerRevision: active.revision || 0
183
+ };
184
+ }
185
+
186
+ function normalizeWireApi(value, allowAuto) {
187
+ const normalized = normalizeText(value).toLowerCase();
188
+ if (normalized === 'responses' || normalized === 'chat' || normalized === 'anthropic') {
189
+ return normalized;
190
+ }
191
+ return allowAuto ? 'auto' : '';
192
+ }
193
+
194
+ function normalizeReasoningAdapter(value) {
195
+ const normalized = normalizeText(value).toLowerCase();
196
+ return ['auto', 'none', 'deepseek', 'anthropic', 'reasoning_effort', 'openrouter', 'enable_thinking', 'thinking', 'reasoning_split'].includes(normalized)
197
+ ? normalized
198
+ : 'auto';
199
+ }
200
+
201
+ function normalizeReasoningCapability(value) {
202
+ const normalized = normalizeText(value).toLowerCase();
203
+ return ['auto', 'none', 'toggle', 'effort'].includes(normalized) ? normalized : 'auto';
204
+ }
205
+
206
+ function normalizeUpstreamResponseMode(value, allowAuto) {
207
+ const normalized = normalizeText(value).toLowerCase();
208
+ if (normalized === 'streaming' || normalized === 'buffered' || (allowAuto && normalized === 'auto')) {
209
+ return normalized;
210
+ }
211
+ return allowAuto ? 'auto' : '';
212
+ }
213
+
214
+ function normalizeAuthMode(value) {
215
+ const normalized = normalizeText(value).toLowerCase();
216
+ return ['bearer', 'x-api-key', 'api-key', 'custom', 'none'].includes(normalized)
217
+ ? normalized
218
+ : 'bearer';
219
+ }
220
+
221
+ function normalizeRecord(value) {
222
+ return value && typeof value === 'object' && !Array.isArray(value) ? { ...value } : {};
223
+ }
224
+
225
+ function normalizeModelDiagnostics(value) {
226
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
227
+ return {};
228
+ }
229
+ const result = {};
230
+ for (const [rawModelId, rawDiagnostic] of Object.entries(value).slice(0, 32)) {
231
+ const modelId = normalizeText(rawModelId);
232
+ if (!modelId || !rawDiagnostic || typeof rawDiagnostic !== 'object') {
233
+ continue;
234
+ }
235
+ const status = normalizeText(rawDiagnostic.status).toLowerCase();
236
+ result[modelId] = {
237
+ modelId,
238
+ status: status === 'failed' ? 'failed' : 'tested',
239
+ at: normalizeInteger(rawDiagnostic.at),
240
+ wireApi: normalizeWireApi(rawDiagnostic.wireApi, false),
241
+ upstreamResponseMode: normalizeUpstreamResponseMode(rawDiagnostic.upstreamResponseMode, false),
242
+ durationMs: normalizeInteger(rawDiagnostic.durationMs),
243
+ errorCode: normalizeText(rawDiagnostic.errorCode)
244
+ };
245
+ }
246
+ return result;
247
+ }
248
+
249
+ function normalizeInputModalities(value) {
250
+ const values = Array.isArray(value) ? value : ['text'];
251
+ const result = Array.from(new Set(values.map(normalizeText).filter(item => item === 'text' || item === 'image')));
252
+ return result.includes('text') ? result : ['text', ...result];
253
+ }
254
+
255
+ function normalizeAnthropicThinkingMode(value) {
256
+ const normalized = normalizeText(value).toLowerCase();
257
+ return ['budget', 'adaptive', 'none'].includes(normalized) ? normalized : 'budget';
258
+ }
259
+
260
+ function normalizeText(value) {
261
+ return typeof value === 'string' ? value.trim() : '';
262
+ }
263
+
264
+ function normalizeInteger(value) {
265
+ const number = Number(value);
266
+ return Number.isFinite(number) && number >= 0 ? Math.floor(number) : 0;
267
+ }
268
+
269
+ function normalizeMaxOutputTokens(value) {
270
+ const number = normalizeInteger(value);
271
+ return !number || number === 8192 ? 32768 : number;
272
+ }
273
+
274
+ return {
275
+ BUILTIN_PROVIDER_ID,
276
+ buildBuiltinProvider,
277
+ buildEmptyDraft,
278
+ buildRunSelection,
279
+ getActiveProvider,
280
+ normalizeCatalog,
281
+ normalizeProvider
282
+ };
283
+ });
@@ -19,6 +19,7 @@
19
19
  locale: 'en',
20
20
  requireReviewing: true,
21
21
  autoOpen: true,
22
+ preloadProjectContext: true,
22
23
  loadCodexLocalSkills: true,
23
24
  loadCodexOverleafSkills: true,
24
25
  codexOverleafSkillEnabled: {},
@@ -34,7 +35,12 @@
34
35
  };
35
36
 
36
37
  const VALID_MODES = new Set(['ask', 'confirm', 'auto']);
37
- const VALID_REASONING = new Set(['low', 'medium', 'high', 'xhigh']);
38
+ // Keep the persisted/session-level contract aligned with the model picker
39
+ // and native provider bridge. Custom providers can explicitly disable
40
+ // reasoning (`none`) or expose the lightest Codex tier (`minimal`). Dropping
41
+ // either value here silently restores the global `high` default after the
42
+ // user has selected it in the composer.
43
+ const VALID_REASONING = new Set(['none', 'minimal', 'low', 'medium', 'high', 'xhigh']);
38
44
  const VALID_SPEED_TIERS = new Set(['standard', 'fast']);
39
45
  const VALID_LOCALES = new Set(['en', 'zh']);
40
46
  const VALID_EVENT_STATUSES = new Set(['info', 'running', 'completed', 'failed', 'warning', 'blocked', 'skipped', 'pending']);
@@ -63,7 +69,10 @@
63
69
  maxUndoRunsPerSession: 2,
64
70
  maxUndoBytesPerRun: 320 * 1024,
65
71
  targetBytes: 4 * 1024 * 1024,
66
- titleChars: 6000,
72
+ // Stream events carry accumulated assistant/reasoning text in `title`.
73
+ // Keep one provider-sized response intact; the 4 MiB state target below
74
+ // remains the aggregate history guard and prunes older events when needed.
75
+ titleChars: 128 * 1024,
67
76
  detailChars: 3000,
68
77
  reportDetailChars: 64000,
69
78
  historyChars: 1800,
@@ -945,6 +954,7 @@
945
954
  locale: normalizeLocale(source.locale),
946
955
  requireReviewing: active ? active.requireReviewing !== false : source.requireReviewing !== false,
947
956
  autoOpen: source.autoOpen !== false,
957
+ preloadProjectContext: source.preloadProjectContext !== false,
948
958
  loadCodexLocalSkills: source.loadCodexLocalSkills !== false,
949
959
  loadCodexOverleafSkills: source.loadCodexOverleafSkills !== false,
950
960
  codexOverleafSkillEnabled: normalizeCodexOverleafSkillEnabled(source.codexOverleafSkillEnabled),
@@ -1,13 +1,17 @@
1
1
  (function initStorageDb(root, factory) {
2
2
  if (typeof module === 'object' && module.exports) {
3
- module.exports = factory();
3
+ module.exports = factory(require('./storageRunActions'));
4
4
  } else {
5
- root.CodexOverleafStorageDb = factory();
5
+ root.CodexOverleafStorageDb = factory(root.CodexOverleafStorageRunActions);
6
6
  }
7
- })(typeof globalThis !== 'undefined' ? globalThis : window, function storageDbFactory() {
7
+ })(typeof globalThis !== 'undefined' ? globalThis : window, function storageDbFactory(StorageRunActions) {
8
8
  'use strict';
9
-
10
- var TARGET_SCHEMA_VERSION = 2;
9
+ if (!StorageRunActions?.compactRunsForStorage || !StorageRunActions?.compactRunActionPayload) {
10
+ throw new Error('Codex Overleaf storage run-action helpers are unavailable.');
11
+ }
12
+ // IndexedDB versions are monotonic; v2.0 RC profiles have already opened v3.
13
+ // Lowering it hides otherwise-intact session history behind fallback state.
14
+ var TARGET_SCHEMA_VERSION = 3;
11
15
  var DB_NAME = 'codex-overleaf';
12
16
  var CUSTOM_INSTRUCTIONS_MAX_CHARS = 12000;
13
17
  var PROJECT_PREF_KEY_MAX_CHARS = 160;
@@ -22,7 +26,7 @@
22
26
  taskChars: 12000,
23
27
  historyTaskChars: 300,
24
28
  historyResultChars: 1800,
25
- eventTitleChars: 6000,
29
+ eventTitleChars: 128 * 1024,
26
30
  statusTextChars: 800,
27
31
  detailChars: 3000,
28
32
  reportDetailChars: 64000,
@@ -235,7 +239,8 @@
235
239
 
236
240
  // --- Record builders ---
237
241
 
238
- function buildSessionRecord(input) {
242
+ function buildSessionRecord(input, options) {
243
+ options = options || {};
239
244
  var now = new Date().toISOString();
240
245
  var titleSource = input.titleSource === 'manual' ? 'manual' : 'auto';
241
246
  var updatedAt = typeof input.updatedAt === 'string' ? input.updatedAt : now;
@@ -268,7 +273,7 @@
268
273
  status: typeof input.status === 'string' && input.status ? input.status : 'active',
269
274
  focusFiles: normalizePathList(input.focusFiles),
270
275
  history: compactHistoryForStorage(input.history),
271
- runs: compactRunsForStorage(input.runs),
276
+ runs: compactRunsForStorage(input.runs, options),
272
277
  task: normalizeDisplayTextForStorage(input.task, SESSION_STORAGE_LIMITS.taskChars),
273
278
  mode: typeof input.mode === 'string' ? input.mode : '',
274
279
  model: typeof input.model === 'string' ? input.model : '',
@@ -628,14 +633,17 @@
628
633
  });
629
634
  }
630
635
 
631
- function compactRunsForStorage(runs) {
632
- return (Array.isArray(runs) ? runs : [])
633
- .filter(function (run) { return run && typeof run.id === 'string'; })
634
- .slice(-SESSION_STORAGE_LIMITS.maxRunsPerSession)
635
- .map(compactRunForStorage);
636
+ function compactRunsForStorage(runs, options) {
637
+ return StorageRunActions.compactRunsForStorage(
638
+ runs,
639
+ options,
640
+ SESSION_STORAGE_LIMITS.maxRunsPerSession,
641
+ compactRunForStorage
642
+ );
636
643
  }
637
644
 
638
- function compactRunForStorage(run) {
645
+ function compactRunForStorage(run, keepActionPayload) {
646
+ var actionPayload = StorageRunActions.compactRunActionPayload(run, keepActionPayload);
639
647
  var compact = {
640
648
  id: run.id,
641
649
  task: normalizeDisplayTextForStorage(run.task || 'untitled task', SESSION_STORAGE_LIMITS.taskChars),
@@ -650,11 +658,11 @@
650
658
  finishedAt: typeof run.finishedAt === 'string' ? redactSecretLikeText(run.finishedAt) : '',
651
659
  events: compactRunEventsForStorage(run.events),
652
660
  attachments: compactRunAttachmentsForStorage(run.attachments),
653
- appliedOperations: [],
654
- undoOperations: [],
655
- undoBaseFiles: [],
656
- undoTrackedChanges: [],
657
- undoExpectedFiles: [],
661
+ appliedOperations: actionPayload.appliedOperations,
662
+ undoOperations: actionPayload.undoOperations,
663
+ undoBaseFiles: actionPayload.undoBaseFiles,
664
+ undoTrackedChanges: actionPayload.undoTrackedChanges,
665
+ undoExpectedFiles: actionPayload.undoExpectedFiles,
658
666
  undoStatus: normalizeDisplayTextForStorage(run.undoStatus, SESSION_STORAGE_LIMITS.statusTextChars)
659
667
  };
660
668
  if (VALID_TRACKED_CHANGE_STATUSES[run.trackedChangeStatus] === true) {
@@ -0,0 +1,99 @@
1
+ (function initStorageRunActions(root, factory) {
2
+ if (typeof module === 'object' && module.exports) {
3
+ module.exports = factory();
4
+ } else {
5
+ root.CodexOverleafStorageRunActions = factory();
6
+ }
7
+ })(typeof globalThis !== 'undefined' ? globalThis : window, function storageRunActionsFactory() {
8
+ 'use strict';
9
+
10
+ var MAX_PERSISTED_ACTION_RUNS_PER_SESSION = 2;
11
+ var MAX_PERSISTED_ACTION_BYTES_PER_RUN = 320 * 1024;
12
+
13
+ function compactRunsForStorage(runs, options, maxRuns, compactRun) {
14
+ if (typeof compactRun !== 'function') {
15
+ throw new TypeError('compactRun must be a function.');
16
+ }
17
+ var selectedRuns = (Array.isArray(runs) ? runs : [])
18
+ .filter(function (run) { return run && typeof run.id === 'string'; })
19
+ .slice(-Math.max(0, Number(maxRuns) || 0));
20
+ var actionRunIds = new Set();
21
+ if (options && options.preserveRunActionPayload === true) {
22
+ for (var index = selectedRuns.length - 1;
23
+ index >= 0 && actionRunIds.size < MAX_PERSISTED_ACTION_RUNS_PER_SESSION;
24
+ index -= 1) {
25
+ if (hasReloadableRunActionPayload(selectedRuns[index])) {
26
+ actionRunIds.add(selectedRuns[index].id);
27
+ }
28
+ }
29
+ }
30
+ return selectedRuns.map(function (run) {
31
+ return compactRun(run, actionRunIds.has(run.id));
32
+ });
33
+ }
34
+
35
+ function hasReloadableRunActionPayload(run) {
36
+ var trackedStatus = run && run.trackedChangeStatus;
37
+ var trackedLifecycle = (trackedStatus === 'pending' || trackedStatus === 'needs_review')
38
+ && Array.isArray(run.undoTrackedChanges) && run.undoTrackedChanges.length > 0
39
+ && Array.isArray(run.undoExpectedFiles) && run.undoExpectedFiles.length > 0
40
+ && Array.isArray(run.appliedOperations) && run.appliedOperations.length > 0;
41
+ var legacyUndo = Array.isArray(run && run.undoOperations) && run.undoOperations.length > 0;
42
+ return trackedLifecycle || legacyUndo;
43
+ }
44
+
45
+ function compactRunActionPayload(run, keepActionPayload) {
46
+ var empty = emptyActionPayload();
47
+ if (!keepActionPayload || !hasReloadableRunActionPayload(run)) {
48
+ return empty;
49
+ }
50
+ var payload = {
51
+ appliedOperations: cloneSerializableArray(run.appliedOperations),
52
+ undoOperations: cloneSerializableArray(run.undoOperations),
53
+ undoBaseFiles: cloneSerializableArray(run.undoBaseFiles),
54
+ undoTrackedChanges: cloneSerializableArray(run.undoTrackedChanges),
55
+ undoExpectedFiles: cloneSerializableArray(run.undoExpectedFiles)
56
+ };
57
+ var serialized;
58
+ try {
59
+ serialized = JSON.stringify(payload);
60
+ } catch (_error) {
61
+ return empty;
62
+ }
63
+ return getUtf8ByteLength(serialized) <= MAX_PERSISTED_ACTION_BYTES_PER_RUN ? payload : empty;
64
+ }
65
+
66
+ function emptyActionPayload() {
67
+ return {
68
+ appliedOperations: [],
69
+ undoOperations: [],
70
+ undoBaseFiles: [],
71
+ undoTrackedChanges: [],
72
+ undoExpectedFiles: []
73
+ };
74
+ }
75
+
76
+ function cloneSerializableArray(value) {
77
+ if (!Array.isArray(value)) {
78
+ return [];
79
+ }
80
+ try {
81
+ var clone = JSON.parse(JSON.stringify(value));
82
+ return Array.isArray(clone) ? clone : [];
83
+ } catch (_error) {
84
+ return [];
85
+ }
86
+ }
87
+
88
+ function getUtf8ByteLength(value) {
89
+ if (typeof TextEncoder === 'function') {
90
+ return new TextEncoder().encode(value).byteLength;
91
+ }
92
+ return value.length * 2;
93
+ }
94
+
95
+ return {
96
+ compactRunsForStorage: compactRunsForStorage,
97
+ compactRunActionPayload: compactRunActionPayload
98
+ };
99
+ });