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.
- package/README.md +24 -23
- package/extension/bootstrap/manifest.template.json +2 -1
- package/extension/runtime-manifest.json +13 -6
- package/extension/src/background.js +7 -0
- package/extension/src/content/composerPanel.js +13 -3
- package/extension/src/content/contentRuntime.js +130 -65
- package/extension/src/content/contextTray.js +173 -9
- package/extension/src/content/markdownText.js +16 -1
- package/extension/src/content/mathText.js +233 -0
- package/extension/src/content/modelPicker.js +117 -106
- package/extension/src/content/modelPickerSupport.js +115 -0
- package/extension/src/content/nativeChannel.js +20 -1
- package/extension/src/content/panelMaintenance.js +2 -0
- package/extension/src/content/projectSettingsCoordinator.js +2 -0
- package/extension/src/content/providerSettingsCoordinator.js +413 -0
- package/extension/src/content/providerSettingsDialog.js +981 -0
- package/extension/src/content/runTimelineView.js +24 -5
- package/extension/src/content/settingsPanel.js +33 -2
- package/extension/src/content/writebackOrchestrator.js +3 -1
- package/extension/src/page/overleafProjectSnapshot.js +29 -33
- package/extension/src/page/snapshotRouter.js +75 -8
- package/extension/src/page/trackedChangesLifecycle.js +154 -26
- package/extension/src/page/writebackRouter.js +31 -60
- package/extension/src/pageBridge.js +1 -1
- package/extension/src/shared/agentTranscript.js +130 -0
- package/extension/src/shared/compatibility.js +10 -7
- package/extension/src/shared/failureReasons.js +75 -0
- package/extension/src/shared/i18n.js +22 -0
- package/extension/src/shared/models.js +1 -0
- package/extension/src/shared/providerProfiles.js +283 -0
- package/extension/src/shared/sessionState.js +12 -2
- package/extension/src/shared/storageDb.js +27 -19
- package/extension/src/shared/storageRunActions.js +99 -0
- package/extension/styles/panel.css +587 -1
- package/extension/vendor/katex/LICENSE +21 -0
- package/extension/vendor/katex/VERSION +2 -0
- package/extension/vendor/katex/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Bold.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Italic.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Math-Italic.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Script-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/extension/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/extension/vendor/katex/katex.min.css +1 -0
- package/extension/vendor/katex/katex.min.js +1 -0
- package/native-host/src/anthropicBridgeRequest.js +435 -0
- package/native-host/src/anthropicBridgeResponse.js +431 -0
- package/native-host/src/anthropicMessagesBridge.js +281 -0
- package/native-host/src/chatBridgeRequest.js +274 -0
- package/native-host/src/chatBridgeResponse.js +594 -0
- package/native-host/src/chatCompletionsBridge.js +485 -0
- package/native-host/src/codexCommand.js +25 -0
- package/native-host/src/codexPromptAssembly.js +9 -0
- package/native-host/src/codexProviderLaunch.js +213 -0
- package/native-host/src/codexProviderTest.js +196 -0
- package/native-host/src/codexSessionRunner.js +29 -25
- package/native-host/src/managedInstall.js +1 -0
- package/native-host/src/providerBridgeRoutes.js +11 -0
- package/native-host/src/providerModelCatalog.js +107 -0
- package/native-host/src/providerProfile.js +454 -0
- package/native-host/src/providerReasoning.js +235 -0
- package/native-host/src/providerRedaction.js +18 -0
- package/native-host/src/providerRuntime.js +365 -0
- package/native-host/src/providerStore.js +691 -0
- package/native-host/src/readProgressGuard.js +360 -0
- package/native-host/src/taskRunnerRuntime.js +40 -4
- package/native-host/src/updateArchive.js +1 -0
- package/native-host/src/updateTrust.js +2 -1
- package/package.json +2 -1
|
@@ -23,6 +23,14 @@
|
|
|
23
23
|
getPanel,
|
|
24
24
|
getState
|
|
25
25
|
} = deps;
|
|
26
|
+
const Support = window.CodexOverleafModelPickerSupport;
|
|
27
|
+
const {
|
|
28
|
+
formatCompactModelLabel,
|
|
29
|
+
normalizeModelOptionId,
|
|
30
|
+
normalizeReasoningEffortsForSelect,
|
|
31
|
+
normalizeSpeedTiersForSelect,
|
|
32
|
+
retainSelectedModel
|
|
33
|
+
} = Support;
|
|
26
34
|
|
|
27
35
|
let modelDiscovery = { status: 'fallback', source: 'fallback', fetchedAt: '' };
|
|
28
36
|
|
|
@@ -78,6 +86,7 @@
|
|
|
78
86
|
reasoningSelect.value = choice.dataset.reasoningChoice;
|
|
79
87
|
} else if (choice.dataset.modelChoice && modelSelect) {
|
|
80
88
|
modelSelect.value = choice.dataset.modelChoice;
|
|
89
|
+
renderReasoningOptions(getRenderedModelEntries());
|
|
81
90
|
renderSpeedOptions(getRenderedModelEntries());
|
|
82
91
|
} else if (choice.dataset.speedChoice && speedSelect) {
|
|
83
92
|
speedSelect.value = choice.dataset.speedChoice;
|
|
@@ -101,9 +110,18 @@
|
|
|
101
110
|
const hasDiscoveredModels = response?.ok
|
|
102
111
|
&& Array.isArray(response.result?.models)
|
|
103
112
|
&& response.result.models.length > 0;
|
|
113
|
+
if (!hasDiscoveredModels && !Support.shouldUseBuiltInFallback(response)) {
|
|
114
|
+
applyUnavailableModelOptions(response?.error);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
104
117
|
const sourceModels = hasDiscoveredModels ? response.result.models : fallbackModels;
|
|
105
|
-
const
|
|
106
|
-
|
|
118
|
+
const retainedSelectedModel = retainSelectedModel(sourceModels, currentSelectedModel);
|
|
119
|
+
const normalized = modelCatalog.normalizeDiscoveredModels({ models: sourceModels, selectedModel: retainedSelectedModel });
|
|
120
|
+
if (normalized.usedFallback && response.result?.providerId && response.result.providerId !== 'builtin') {
|
|
121
|
+
applyUnavailableModelOptions({ code: 'provider_model_catalog_invalid', message: 'The active provider returned no usable models.' });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
renderModelOptions(normalized.models, retainedSelectedModel);
|
|
107
125
|
modelDiscovery = {
|
|
108
126
|
status: hasDiscoveredModels && !normalized.usedFallback ? 'discovered' : 'fallback',
|
|
109
127
|
source: hasDiscoveredModels ? response.result?.source || 'unknown' : 'fallback',
|
|
@@ -113,16 +131,43 @@
|
|
|
113
131
|
};
|
|
114
132
|
updateModelDisplay();
|
|
115
133
|
} catch (error) {
|
|
116
|
-
|
|
134
|
+
applyUnavailableModelOptions(error);
|
|
117
135
|
}
|
|
118
136
|
}
|
|
119
137
|
|
|
138
|
+
function applyUnavailableModelOptions(error) {
|
|
139
|
+
const modelSelect = getPanel()?.querySelector('[data-model]');
|
|
140
|
+
if (modelSelect) {
|
|
141
|
+
modelSelect.textContent = '';
|
|
142
|
+
const option = document.createElement('option');
|
|
143
|
+
option.value = '';
|
|
144
|
+
option.textContent = tx('Models unavailable', '模型不可用');
|
|
145
|
+
option.disabled = true;
|
|
146
|
+
modelSelect.append(option);
|
|
147
|
+
modelSelect.value = '';
|
|
148
|
+
modelSelect.disabled = true;
|
|
149
|
+
}
|
|
150
|
+
if (getState()) getState().model = '';
|
|
151
|
+
modelDiscovery = {
|
|
152
|
+
status: 'unavailable',
|
|
153
|
+
source: 'custom-provider',
|
|
154
|
+
fetchedAt: '',
|
|
155
|
+
errorCode: error?.code || '',
|
|
156
|
+
errorMessage: error?.message || (error ? String(error) : '')
|
|
157
|
+
};
|
|
158
|
+
renderReasoningOptions([]);
|
|
159
|
+
renderSpeedOptions([]);
|
|
160
|
+
renderModelConfigChoices();
|
|
161
|
+
updateModelDisplay();
|
|
162
|
+
}
|
|
163
|
+
|
|
120
164
|
function applyFallbackModelOptions(selectedModel, error) {
|
|
121
165
|
const modelCatalog = getModelCatalog();
|
|
122
166
|
const fallbackModels = modelCatalog.FALLBACK_MODELS;
|
|
123
167
|
const sourceModels = fallbackModels;
|
|
124
|
-
const
|
|
125
|
-
|
|
168
|
+
const retainedSelectedModel = retainSelectedModel(sourceModels, selectedModel);
|
|
169
|
+
const normalized = modelCatalog.normalizeDiscoveredModels({ models: sourceModels, selectedModel: retainedSelectedModel });
|
|
170
|
+
renderModelOptions(normalized.models, retainedSelectedModel);
|
|
126
171
|
modelDiscovery = {
|
|
127
172
|
status: 'fallback',
|
|
128
173
|
source: 'fallback',
|
|
@@ -134,86 +179,7 @@
|
|
|
134
179
|
}
|
|
135
180
|
|
|
136
181
|
function getModelCatalog() {
|
|
137
|
-
|
|
138
|
-
if (Array.isArray(shared?.FALLBACK_MODELS) && typeof shared?.normalizeDiscoveredModels === 'function') {
|
|
139
|
-
return shared;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
FALLBACK_MODELS: buildDomModelCatalogFallback(),
|
|
144
|
-
normalizeDiscoveredModels: normalizeDiscoveredModelsFallback
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function buildDomModelCatalogFallback() {
|
|
149
|
-
const modelSelect = getPanel()?.querySelector('[data-model]');
|
|
150
|
-
const domModels = Array.from(modelSelect?.options || [])
|
|
151
|
-
.map(option => ({
|
|
152
|
-
id: normalizeModelOptionId(option.value),
|
|
153
|
-
label: option.textContent || option.value
|
|
154
|
-
}))
|
|
155
|
-
.filter(model => model.id);
|
|
156
|
-
|
|
157
|
-
return domModels.length ? domModels : [
|
|
158
|
-
{ id: 'gpt-5.5', label: 'GPT-5.5' },
|
|
159
|
-
{ id: 'gpt-5.4', label: 'GPT-5.4' },
|
|
160
|
-
{ id: 'gpt-5.4-mini', label: 'GPT-5.4 Mini' },
|
|
161
|
-
{ id: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
|
|
162
|
-
{ id: 'gpt-5.3-codex-spark', label: 'GPT-5.3 Codex Spark' },
|
|
163
|
-
{ id: 'gpt-5.2', label: 'GPT-5.2' }
|
|
164
|
-
];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function normalizeDiscoveredModelsFallback({ models, selectedModel } = {}) {
|
|
168
|
-
const normalized = normalizeModelCatalogEntries(models);
|
|
169
|
-
const usedFallback = normalized.length === 0;
|
|
170
|
-
const resultModels = usedFallback ? buildDomModelCatalogFallback().map(model => ({ ...model })) : normalized;
|
|
171
|
-
const selectedId = normalizeModelOptionId(selectedModel);
|
|
172
|
-
|
|
173
|
-
if (selectedId && !resultModels.some(model => model.id === selectedId)) {
|
|
174
|
-
resultModels.push({
|
|
175
|
-
id: selectedId,
|
|
176
|
-
label: `${selectedId} (custom)`,
|
|
177
|
-
unverified: true
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return {
|
|
182
|
-
models: resultModels,
|
|
183
|
-
usedFallback
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function normalizeModelCatalogEntries(models) {
|
|
188
|
-
if (!Array.isArray(models)) {
|
|
189
|
-
return [];
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const seen = new Set();
|
|
193
|
-
const result = [];
|
|
194
|
-
|
|
195
|
-
for (const model of models) {
|
|
196
|
-
const id = normalizeModelOptionId(typeof model === 'string' ? model : model?.id);
|
|
197
|
-
if (!id || seen.has(id)) {
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
seen.add(id);
|
|
201
|
-
const normalized = {
|
|
202
|
-
id,
|
|
203
|
-
label: typeof model?.label === 'string' && model.label.length > 0 ? model.label : id,
|
|
204
|
-
reasoningEfforts: Array.isArray(model?.reasoningEfforts) ? model.reasoningEfforts.slice() : [],
|
|
205
|
-
speedTiers: normalizeSpeedTiersForSelect(model?.speedTiers)
|
|
206
|
-
};
|
|
207
|
-
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultReasoningEffort')) {
|
|
208
|
-
normalized.defaultReasoningEffort = model.defaultReasoningEffort;
|
|
209
|
-
}
|
|
210
|
-
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultSpeedTier')) {
|
|
211
|
-
normalized.defaultSpeedTier = model.defaultSpeedTier;
|
|
212
|
-
}
|
|
213
|
-
result.push(normalized);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return result;
|
|
182
|
+
return Support.getModelCatalog({ getPanel });
|
|
217
183
|
}
|
|
218
184
|
|
|
219
185
|
function renderModelOptions(models, selectedModel) {
|
|
@@ -224,6 +190,7 @@
|
|
|
224
190
|
|
|
225
191
|
const selectedId = normalizeModelOptionId(selectedModel);
|
|
226
192
|
modelSelect.textContent = '';
|
|
193
|
+
modelSelect.disabled = false;
|
|
227
194
|
let renderedSelected = false;
|
|
228
195
|
let firstModelId = '';
|
|
229
196
|
|
|
@@ -238,6 +205,9 @@
|
|
|
238
205
|
const option = document.createElement('option');
|
|
239
206
|
option.value = id;
|
|
240
207
|
option.textContent = model.label;
|
|
208
|
+
option.dataset.reasoningEfforts = normalizeReasoningEffortsForSelect(model.reasoningEfforts).join(',');
|
|
209
|
+
option.dataset.defaultReasoningEffort = model.defaultReasoningEffort || '';
|
|
210
|
+
option.dataset.reasoningPresentation = model.reasoningPresentation || '';
|
|
241
211
|
option.dataset.speedTiers = normalizeSpeedTiersForSelect(model.speedTiers).join(',');
|
|
242
212
|
option.dataset.defaultSpeedTier = model.defaultSpeedTier || 'standard';
|
|
243
213
|
if (model.unverified) {
|
|
@@ -253,6 +223,9 @@
|
|
|
253
223
|
const option = document.createElement('option');
|
|
254
224
|
option.value = selectedId;
|
|
255
225
|
option.textContent = `${selectedId} (custom)`;
|
|
226
|
+
option.dataset.reasoningEfforts = '';
|
|
227
|
+
option.dataset.defaultReasoningEffort = '';
|
|
228
|
+
option.dataset.reasoningPresentation = 'none';
|
|
256
229
|
option.dataset.speedTiers = 'standard';
|
|
257
230
|
option.dataset.defaultSpeedTier = 'standard';
|
|
258
231
|
option.dataset.unverified = 'true';
|
|
@@ -265,6 +238,7 @@
|
|
|
265
238
|
} else if (firstModelId) {
|
|
266
239
|
modelSelect.value = firstModelId;
|
|
267
240
|
}
|
|
241
|
+
renderReasoningOptions(models);
|
|
268
242
|
renderSpeedOptions(models);
|
|
269
243
|
renderModelConfigChoices();
|
|
270
244
|
updateModelDisplay();
|
|
@@ -296,6 +270,37 @@
|
|
|
296
270
|
renderModelConfigChoices();
|
|
297
271
|
}
|
|
298
272
|
|
|
273
|
+
function renderReasoningOptions(models) {
|
|
274
|
+
const reasoningSelect = getPanel()?.querySelector('[data-reasoning]');
|
|
275
|
+
const modelSelect = getPanel()?.querySelector('[data-model]');
|
|
276
|
+
if (!reasoningSelect || !modelSelect) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const selectedModel = normalizeModelOptionId(modelSelect.value);
|
|
281
|
+
const model = (Array.isArray(models) ? models : []).find(item => normalizeModelOptionId(item?.id) === selectedModel);
|
|
282
|
+
const presentation = model?.reasoningPresentation || 'effort';
|
|
283
|
+
let efforts = normalizeReasoningEffortsForSelect(model?.reasoningEfforts);
|
|
284
|
+
if (!efforts.length) {
|
|
285
|
+
efforts = presentation === 'none' ? ['none'] : ['low', 'medium', 'high', 'xhigh'];
|
|
286
|
+
}
|
|
287
|
+
const current = reasoningSelect.value || getState()?.reasoningEffort || '';
|
|
288
|
+
const fallback = efforts.includes(model?.defaultReasoningEffort)
|
|
289
|
+
? model.defaultReasoningEffort
|
|
290
|
+
: efforts.includes('high') ? 'high' : efforts[0];
|
|
291
|
+
|
|
292
|
+
reasoningSelect.textContent = '';
|
|
293
|
+
for (const effort of efforts) {
|
|
294
|
+
const option = document.createElement('option');
|
|
295
|
+
option.value = effort;
|
|
296
|
+
option.textContent = formatReasoningEffortLabel(effort, presentation);
|
|
297
|
+
reasoningSelect.append(option);
|
|
298
|
+
}
|
|
299
|
+
reasoningSelect.value = efforts.includes(current) ? current : fallback;
|
|
300
|
+
reasoningSelect.disabled = presentation === 'none';
|
|
301
|
+
reasoningSelect.dataset.presentation = presentation;
|
|
302
|
+
}
|
|
303
|
+
|
|
299
304
|
function renderModelConfigChoices() {
|
|
300
305
|
renderReasoningChoices();
|
|
301
306
|
renderModelChoices();
|
|
@@ -310,10 +315,15 @@
|
|
|
310
315
|
return;
|
|
311
316
|
}
|
|
312
317
|
list.textContent = '';
|
|
318
|
+
const hidden = reasoningSelect.dataset.presentation === 'none';
|
|
319
|
+
list.hidden = hidden;
|
|
320
|
+
if (list.nextElementSibling?.classList?.contains('codex-model-config-divider')) {
|
|
321
|
+
list.nextElementSibling.hidden = hidden;
|
|
322
|
+
}
|
|
313
323
|
for (const option of Array.from(reasoningSelect.options || [])) {
|
|
314
324
|
list.append(createModelConfigChoice({
|
|
315
325
|
value: option.value,
|
|
316
|
-
label: formatReasoningEffortLabel(option.value),
|
|
326
|
+
label: option.textContent || formatReasoningEffortLabel(option.value, reasoningSelect.dataset.presentation),
|
|
317
327
|
datasetName: 'reasoningChoice'
|
|
318
328
|
}));
|
|
319
329
|
}
|
|
@@ -394,39 +404,33 @@
|
|
|
394
404
|
}
|
|
395
405
|
}
|
|
396
406
|
|
|
397
|
-
function normalizeSpeedTiersForSelect(speedTiers) {
|
|
398
|
-
const tiers = Array.isArray(speedTiers)
|
|
399
|
-
? speedTiers.map(tier => normalizeModelOptionId(tier)).filter(Boolean)
|
|
400
|
-
: ['standard'];
|
|
401
|
-
return tiers.includes('standard') ? tiers : ['standard', ...tiers];
|
|
402
|
-
}
|
|
403
|
-
|
|
404
407
|
function formatSpeedTierLabel(tier) {
|
|
405
408
|
return tier === 'fast' ? tx('Fast', '快速') : tx('Standard', '标准');
|
|
406
409
|
}
|
|
407
410
|
|
|
408
|
-
function formatReasoningEffortLabel(effort) {
|
|
411
|
+
function formatReasoningEffortLabel(effort, presentation = '') {
|
|
412
|
+
if (presentation === 'toggle') {
|
|
413
|
+
return effort === 'none' ? tx('Off', '关闭') : tx('On', '开启');
|
|
414
|
+
}
|
|
415
|
+
if (presentation === 'deepseek') {
|
|
416
|
+
if (effort === 'none') return tx('Off', '关闭');
|
|
417
|
+
if (effort === 'xhigh') return 'Max';
|
|
418
|
+
}
|
|
409
419
|
const labels = getLocale() === 'zh'
|
|
410
|
-
? { low: '低', medium: '中', high: '高', xhigh: '超高' }
|
|
411
|
-
: { low: 'Low', medium: 'Medium', high: 'High', xhigh: 'XHigh' };
|
|
420
|
+
? { none: '关闭', minimal: '最小', low: '低', medium: '中', high: '高', xhigh: '超高' }
|
|
421
|
+
: { none: 'Off', minimal: 'Minimal', low: 'Low', medium: 'Medium', high: 'High', xhigh: 'XHigh' };
|
|
412
422
|
return labels[effort] || effort || '';
|
|
413
423
|
}
|
|
414
424
|
|
|
415
|
-
function formatCompactModelLabel(label) {
|
|
416
|
-
return String(label || '').replace(/^gpt[-\s]*/i, '');
|
|
417
|
-
}
|
|
418
|
-
|
|
419
425
|
function resolveSelectedModel() {
|
|
420
426
|
return getPanel()?.querySelector('[data-model]')?.value || getState()?.model || '';
|
|
421
427
|
}
|
|
422
428
|
|
|
423
|
-
function normalizeModelOptionId(id) {
|
|
424
|
-
return typeof id === 'string' ? id.trim() : '';
|
|
425
|
-
}
|
|
426
|
-
|
|
427
429
|
function getModelDiscoverySourceLabel() {
|
|
428
430
|
if (modelDiscovery.errorCode || modelDiscovery.errorMessage) {
|
|
429
|
-
return
|
|
431
|
+
return modelDiscovery.status === 'fallback'
|
|
432
|
+
? `${tr('modelSourceFailed')} (${tr('modelSourceFallback')})`
|
|
433
|
+
: tr('modelSourceFailed');
|
|
430
434
|
}
|
|
431
435
|
if (modelDiscovery.source === 'fallback') {
|
|
432
436
|
return tr('modelSourceFallback');
|
|
@@ -454,7 +458,12 @@
|
|
|
454
458
|
});
|
|
455
459
|
modelDisplay.title = sourceTitle;
|
|
456
460
|
if (reasoningDisplay) {
|
|
457
|
-
|
|
461
|
+
const reasoningSelect = getPanel()?.querySelector('[data-reasoning]');
|
|
462
|
+
const presentation = reasoningSelect?.dataset.presentation || '';
|
|
463
|
+
reasoningDisplay.hidden = presentation === 'none';
|
|
464
|
+
reasoningDisplay.textContent = presentation === 'none'
|
|
465
|
+
? ''
|
|
466
|
+
: formatReasoningEffortLabel(reasoningSelect?.value || getState()?.reasoningEffort || '', presentation);
|
|
458
467
|
}
|
|
459
468
|
if (speedIndicator) {
|
|
460
469
|
speedIndicator.hidden = readSelectedSpeedInput() !== 'fast';
|
|
@@ -475,8 +484,10 @@
|
|
|
475
484
|
handleModelConfigChoiceClick,
|
|
476
485
|
loadModelOptions,
|
|
477
486
|
applyFallbackModelOptions,
|
|
487
|
+
applyUnavailableModelOptions,
|
|
478
488
|
getModelCatalog,
|
|
479
489
|
renderModelOptions,
|
|
490
|
+
renderReasoningOptions,
|
|
480
491
|
renderSpeedOptions,
|
|
481
492
|
renderModelConfigChoices,
|
|
482
493
|
resolveSelectedModel,
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
(function initCodexOverleafModelPickerSupport(root) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
function normalizeModelOptionId(id) {
|
|
5
|
+
return typeof id === 'string' ? id.trim() : '';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function normalizeSpeedTiersForSelect(speedTiers) {
|
|
9
|
+
const tiers = Array.isArray(speedTiers)
|
|
10
|
+
? speedTiers.map(tier => normalizeModelOptionId(tier)).filter(Boolean)
|
|
11
|
+
: ['standard'];
|
|
12
|
+
return tiers.includes('standard') ? tiers : ['standard', ...tiers];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizeReasoningEffortsForSelect(efforts) {
|
|
16
|
+
const allowed = new Set(['none', 'minimal', 'low', 'medium', 'high', 'xhigh']);
|
|
17
|
+
return Array.from(new Set((Array.isArray(efforts) ? efforts : [])
|
|
18
|
+
.map(effort => normalizeModelOptionId(effort))
|
|
19
|
+
.filter(effort => allowed.has(effort))));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function formatCompactModelLabel(label) {
|
|
23
|
+
return String(label || '').replace(/^gpt[-\s]*/i, '');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function retainSelectedModel(models, selectedModel) {
|
|
27
|
+
const selectedId = normalizeModelOptionId(selectedModel);
|
|
28
|
+
if (!selectedId) return '';
|
|
29
|
+
return (Array.isArray(models) ? models : []).some(model => (
|
|
30
|
+
normalizeModelOptionId(typeof model === 'string' ? model : model?.id) === selectedId
|
|
31
|
+
)) ? selectedId : '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function shouldUseBuiltInFallback(response) {
|
|
35
|
+
const providerId = normalizeModelOptionId(response?.result?.providerId);
|
|
36
|
+
return response?.ok === true && (!providerId || providerId === 'builtin');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getModelCatalog({ getPanel } = {}) {
|
|
40
|
+
const shared = root.CodexOverleafModels;
|
|
41
|
+
if (Array.isArray(shared?.FALLBACK_MODELS) && typeof shared?.normalizeDiscoveredModels === 'function') {
|
|
42
|
+
return shared;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
FALLBACK_MODELS: buildDomModelCatalogFallback(getPanel),
|
|
46
|
+
normalizeDiscoveredModels: input => normalizeDiscoveredModelsFallback(input, getPanel)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function buildDomModelCatalogFallback(getPanel) {
|
|
51
|
+
const modelSelect = getPanel?.()?.querySelector('[data-model]');
|
|
52
|
+
const domModels = Array.from(modelSelect?.options || [])
|
|
53
|
+
.map(option => ({ id: normalizeModelOptionId(option.value), label: option.textContent || option.value }))
|
|
54
|
+
.filter(model => model.id);
|
|
55
|
+
return domModels.length ? domModels : [
|
|
56
|
+
{ id: 'gpt-5.5', label: 'GPT-5.5' },
|
|
57
|
+
{ id: 'gpt-5.4', label: 'GPT-5.4' },
|
|
58
|
+
{ id: 'gpt-5.4-mini', label: 'GPT-5.4 Mini' },
|
|
59
|
+
{ id: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
|
|
60
|
+
{ id: 'gpt-5.3-codex-spark', label: 'GPT-5.3 Codex Spark' },
|
|
61
|
+
{ id: 'gpt-5.2', label: 'GPT-5.2' }
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function normalizeDiscoveredModelsFallback({ models, selectedModel } = {}, getPanel) {
|
|
66
|
+
const normalized = normalizeModelCatalogEntries(models);
|
|
67
|
+
const usedFallback = normalized.length === 0;
|
|
68
|
+
const resultModels = usedFallback
|
|
69
|
+
? buildDomModelCatalogFallback(getPanel).map(model => ({ ...model }))
|
|
70
|
+
: normalized;
|
|
71
|
+
const selectedId = normalizeModelOptionId(selectedModel);
|
|
72
|
+
if (selectedId && !resultModels.some(model => model.id === selectedId)) {
|
|
73
|
+
resultModels.push({ id: selectedId, label: `${selectedId} (custom)`, unverified: true });
|
|
74
|
+
}
|
|
75
|
+
return { models: resultModels, usedFallback };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function normalizeModelCatalogEntries(models) {
|
|
79
|
+
if (!Array.isArray(models)) return [];
|
|
80
|
+
const seen = new Set();
|
|
81
|
+
const result = [];
|
|
82
|
+
for (const model of models) {
|
|
83
|
+
const id = normalizeModelOptionId(typeof model === 'string' ? model : model?.id);
|
|
84
|
+
if (!id || seen.has(id)) continue;
|
|
85
|
+
seen.add(id);
|
|
86
|
+
const normalized = {
|
|
87
|
+
id,
|
|
88
|
+
label: typeof model?.label === 'string' && model.label.length > 0 ? model.label : id,
|
|
89
|
+
reasoningEfforts: Array.isArray(model?.reasoningEfforts) ? model.reasoningEfforts.slice() : [],
|
|
90
|
+
reasoningPresentation: typeof model?.reasoningPresentation === 'string' ? model.reasoningPresentation : '',
|
|
91
|
+
speedTiers: normalizeSpeedTiersForSelect(model?.speedTiers)
|
|
92
|
+
};
|
|
93
|
+
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultReasoningEffort')) {
|
|
94
|
+
normalized.defaultReasoningEffort = model.defaultReasoningEffort;
|
|
95
|
+
}
|
|
96
|
+
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultSpeedTier')) {
|
|
97
|
+
normalized.defaultSpeedTier = model.defaultSpeedTier;
|
|
98
|
+
}
|
|
99
|
+
result.push(normalized);
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const api = {
|
|
105
|
+
formatCompactModelLabel,
|
|
106
|
+
getModelCatalog,
|
|
107
|
+
normalizeModelOptionId,
|
|
108
|
+
normalizeReasoningEffortsForSelect,
|
|
109
|
+
normalizeSpeedTiersForSelect,
|
|
110
|
+
retainSelectedModel,
|
|
111
|
+
shouldUseBuiltInFallback
|
|
112
|
+
};
|
|
113
|
+
root.CodexOverleafModelPickerSupport = api;
|
|
114
|
+
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
115
|
+
})(typeof window !== 'undefined' ? window : globalThis);
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
const runtime = deps.chrome?.runtime || chrome.runtime;
|
|
12
12
|
const cryptoImpl = deps.crypto || crypto;
|
|
13
13
|
let activeRequestId = null;
|
|
14
|
+
const backgroundEventHandlers = new Map();
|
|
14
15
|
|
|
15
16
|
function sendNative(payload) {
|
|
16
17
|
const id = cryptoImpl.randomUUID();
|
|
@@ -24,14 +25,19 @@
|
|
|
24
25
|
});
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
function sendBackgroundNative(payload) {
|
|
28
|
+
function sendBackgroundNative(payload, onEvent) {
|
|
28
29
|
const id = cryptoImpl.randomUUID();
|
|
30
|
+
if (typeof onEvent === 'function') {
|
|
31
|
+
backgroundEventHandlers.set(id, onEvent);
|
|
32
|
+
}
|
|
29
33
|
return runtime.sendMessage({
|
|
30
34
|
type: 'codex-overleaf/native-request',
|
|
31
35
|
payload: {
|
|
32
36
|
id,
|
|
33
37
|
...payload
|
|
34
38
|
}
|
|
39
|
+
}).finally(() => {
|
|
40
|
+
backgroundEventHandlers.delete(id);
|
|
35
41
|
});
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -47,9 +53,22 @@
|
|
|
47
53
|
return message?.type === 'codex-overleaf/native-event' && message.id === activeRequestId;
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
function handleBackgroundNativeEvent(message = {}) {
|
|
57
|
+
if (message?.type !== 'codex-overleaf/native-event') {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
const handler = backgroundEventHandlers.get(message.id);
|
|
61
|
+
if (!handler) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
handler(message.event);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
50
68
|
return {
|
|
51
69
|
clearActiveRequest,
|
|
52
70
|
getActiveRequestId,
|
|
71
|
+
handleBackgroundNativeEvent,
|
|
53
72
|
sendBackgroundNative,
|
|
54
73
|
sendNative,
|
|
55
74
|
shouldHandleNativeEvent
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
saveState,
|
|
19
19
|
saveStateSoon,
|
|
20
20
|
autosizeTaskTextarea,
|
|
21
|
+
syncComposerSendAvailability,
|
|
21
22
|
applyStateToPanel,
|
|
22
23
|
normalizePanelState,
|
|
23
24
|
openCustomInstructionsSettings,
|
|
@@ -220,6 +221,7 @@
|
|
|
220
221
|
input.value = task;
|
|
221
222
|
getState().task = task;
|
|
222
223
|
autosizeTaskTextarea();
|
|
224
|
+
syncComposerSendAvailability();
|
|
223
225
|
saveStateSoon();
|
|
224
226
|
input.focus();
|
|
225
227
|
try {
|
|
@@ -254,6 +254,7 @@
|
|
|
254
254
|
|
|
255
255
|
function getSkillLoadingSettings() {
|
|
256
256
|
return {
|
|
257
|
+
preloadProjectContext: getState()?.preloadProjectContext !== false,
|
|
257
258
|
loadCodexLocalSkills: getState()?.loadCodexLocalSkills !== false,
|
|
258
259
|
loadCodexOverleafSkills: getState()?.loadCodexOverleafSkills !== false
|
|
259
260
|
};
|
|
@@ -262,6 +263,7 @@
|
|
|
262
263
|
function setSkillLoadingSettings(settings = {}) {
|
|
263
264
|
setState({
|
|
264
265
|
...getState(),
|
|
266
|
+
preloadProjectContext: settings.preloadProjectContext !== false,
|
|
265
267
|
loadCodexLocalSkills: settings.loadCodexLocalSkills !== false,
|
|
266
268
|
loadCodexOverleafSkills: settings.loadCodexOverleafSkills !== false
|
|
267
269
|
});
|