codex-overleaf-link 2.5.1 → 2.6.5
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 +149 -398
- package/README.zh-CN.md +153 -404
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +148 -3
- package/extension/src/backgroundSharedSessions.js +55 -2
- package/extension/src/backgroundUpdateCoordinator.js +128 -12
- package/extension/src/content/activeTurnControl.js +164 -7
- package/extension/src/content/composerAttachments.js +46 -10
- package/extension/src/content/composerPanel.js +92 -12
- package/extension/src/content/contentRuntime.js +1114 -321
- package/extension/src/content/contextTray.js +8 -2
- package/extension/src/content/contextUsageView.js +267 -0
- package/extension/src/content/diagnosticsController.js +77 -34
- package/extension/src/content/diagnosticsExport.js +1 -1
- package/extension/src/content/diagnosticsPanel.js +147 -42
- package/extension/src/content/generated/content.bundle.js +5761 -1237
- package/extension/src/content/generated/content.bundle.meta.json +6 -3
- package/extension/src/content/legacyGlobalRegistry.js +4 -0
- package/extension/src/content/localSkillsPanel.js +6 -4
- package/extension/src/content/markdownDomRenderer.js +5 -3
- package/extension/src/content/markdownText.js +53 -14
- package/extension/src/content/modelPicker.js +29 -19
- package/extension/src/content/nativeCompatibilityController.js +52 -19
- package/extension/src/content/otWarmMirror.js +1 -1
- package/extension/src/content/pageBridgeClient.js +7 -7
- package/extension/src/content/panelMaintenance.js +10 -2
- package/extension/src/content/panelRenderer.js +55 -28
- package/extension/src/content/pendingInputView.js +1 -1
- package/extension/src/content/projectSettingsCoordinator.js +30 -6
- package/extension/src/content/providerSettingsDialog.js +28 -19
- package/extension/src/content/recentProjects.js +30 -19
- package/extension/src/content/runActivitySummary.js +122 -14
- package/extension/src/content/runCompletionMeta.js +194 -6
- package/extension/src/content/runController.js +2 -1
- package/extension/src/content/runFailureNotice.js +8 -1
- package/extension/src/content/runPresence.js +18 -8
- package/extension/src/content/runQueueScheduler.js +27 -13
- package/extension/src/content/runRecoveryActions.js +2 -1
- package/extension/src/content/runResultActions.js +73 -24
- package/extension/src/content/runReviewController.js +102 -37
- package/extension/src/content/runTimelineView.js +224 -25
- package/extension/src/content/scopedPersistencePanelState.js +124 -46
- package/extension/src/content/selectionContextView.js +30 -3
- package/extension/src/content/sensitivePreflight.js +14 -1
- package/extension/src/content/sessionManager.js +49 -3
- package/extension/src/content/sessionMenuView.js +54 -18
- package/extension/src/content/sessionPersistence.js +25 -5
- package/extension/src/content/settingsPanel.js +15 -2
- package/extension/src/content/settingsWorkbench.js +127 -89
- package/extension/src/content/sharedSessionViewSync.js +13 -4
- package/extension/src/content/subagentActivityView.js +23 -7
- package/extension/src/content/updateNotice.js +60 -6
- package/extension/src/content/writebackOrchestrator.js +301 -72
- package/extension/src/content/writingStyleSettings.js +70 -17
- package/extension/src/page/compileBridge.js +193 -180
- package/extension/src/page/overleafCapabilities.js +4 -1
- package/extension/src/page/overleafEditor.js +12 -3
- package/extension/src/page/overleafProjectSnapshot.js +56 -3
- package/extension/src/page/snapshotRouter.js +75 -66
- package/extension/src/page/textCoordinates.js +17 -1
- package/extension/src/page/textFileCreator.js +9 -1
- package/extension/src/page/treeOperations.js +200 -19
- package/extension/src/page/writebackRouter.js +172 -113
- package/extension/src/pageBridge.js +124 -73
- package/extension/src/popup.js +1 -1
- package/extension/src/shared/agentTranscript.js +372 -18
- package/extension/src/shared/auditRecords.js +3 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/compileAdapter.js +58 -17
- package/extension/src/shared/composerAttachmentDraft.js +27 -7
- package/extension/src/shared/contextUsage.js +125 -0
- package/extension/src/shared/failureReasons.js +57 -3
- package/extension/src/shared/i18n.js +315 -29
- package/extension/src/shared/lineReferences.js +38 -31
- package/extension/src/shared/pageRpcContract.js +1 -1
- package/extension/src/shared/panelIcons.js +39 -0
- package/extension/src/shared/projectFiles.js +2 -1
- package/extension/src/shared/reviewing.js +130 -1
- package/extension/src/shared/runActivityModel.js +70 -4
- package/extension/src/shared/runExecutionSnapshot.js +13 -0
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +34 -0
- package/extension/src/shared/sessionState.js +63 -4
- package/extension/src/shared/sessionTitle.js +14 -1
- package/extension/src/shared/sharedSessionBridge.js +81 -13
- package/extension/src/shared/staleGuard.js +130 -63
- package/extension/src/shared/storageDb.js +35 -3
- package/extension/src/shared/storageMigration.js +111 -2
- package/extension/src/shared/storageRunActions.js +62 -8
- package/extension/src/shared/undoOperations.js +126 -28
- package/extension/src/shared/updateRuntimeIdentity.js +16 -2
- package/extension/src/shared/writebackSettlement.js +21 -3
- package/extension/styles/panel.css +1293 -549
- package/native-host/src/bootstrapUpdate.js +52 -16
- package/native-host/src/chatBridgeRequest.js +60 -6
- package/native-host/src/chatBridgeResponse.js +10 -1
- package/native-host/src/chatCompletionsBridge.js +29 -2
- package/native-host/src/codexPromptAssembly.js +86 -118
- package/native-host/src/codexSessionRunner.js +127 -17
- package/native-host/src/debugLog.js +27 -3
- package/native-host/src/index.js +42 -11
- package/native-host/src/localSkills.js +1 -1
- package/native-host/src/mirrorWorkspace.js +47 -3
- package/native-host/src/nativeEnvironment.js +27 -5
- package/native-host/src/providerContextError.js +20 -0
- package/native-host/src/providerRuntime.js +1 -0
- package/native-host/src/skills/reviewer-response/SKILL.md +65 -0
- package/native-host/src/taskRunnerRuntime.js +28 -8
- package/native-host/src/textPatch.js +473 -377
- package/native-host/src/updateManager.js +144 -21
- package/native-host/src/writingStyleRuntime.js +1 -1
- package/package.json +5 -8
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"entry": "extension/entries/content-entry.mjs",
|
|
4
4
|
"output": "extension/src/content/generated/content.bundle.js",
|
|
5
|
-
"sourceDigest": "
|
|
6
|
-
"outputDigest": "
|
|
7
|
-
"byteLength":
|
|
5
|
+
"sourceDigest": "91739cf894fed56c2880986120922d3b54bb423ab2d116705385da1d0fe518be",
|
|
6
|
+
"outputDigest": "a52bf46e64085f1a64339769d64ab59246323c3a51c65851f3385750727b0624",
|
|
7
|
+
"byteLength": 3443627,
|
|
8
8
|
"inputs": [
|
|
9
9
|
"extension/entries/content-entry.mjs",
|
|
10
10
|
"extension/src/content/activeTurnControl.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"extension/src/content/composerPanel.js",
|
|
16
16
|
"extension/src/content/contentRuntime.js",
|
|
17
17
|
"extension/src/content/contextTray.js",
|
|
18
|
+
"extension/src/content/contextUsageView.js",
|
|
18
19
|
"extension/src/content/diagnosticsController.js",
|
|
19
20
|
"extension/src/content/diagnosticsExport.js",
|
|
20
21
|
"extension/src/content/diagnosticsPanel.js",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"extension/src/shared/compatibility.js",
|
|
90
91
|
"extension/src/shared/compileAdapter.js",
|
|
91
92
|
"extension/src/shared/composerAttachmentDraft.js",
|
|
93
|
+
"extension/src/shared/contextUsage.js",
|
|
92
94
|
"extension/src/shared/directoryCleanupProof.js",
|
|
93
95
|
"extension/src/shared/failureReasons.js",
|
|
94
96
|
"extension/src/shared/globalPreferences.js",
|
|
@@ -99,6 +101,7 @@
|
|
|
99
101
|
"extension/src/shared/models.js",
|
|
100
102
|
"extension/src/shared/otText.js",
|
|
101
103
|
"extension/src/shared/pageRpcContract.js",
|
|
104
|
+
"extension/src/shared/panelIcons.js",
|
|
102
105
|
"extension/src/shared/pathRedaction.js",
|
|
103
106
|
"extension/src/shared/projectFiles.js",
|
|
104
107
|
"extension/src/shared/providerProfiles.js",
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
'ComposerPanel',
|
|
30
30
|
'ContentRuntime',
|
|
31
31
|
'ContextTray',
|
|
32
|
+
'ContextUsage',
|
|
33
|
+
'ContextUsageView',
|
|
32
34
|
'DiagnosticsController',
|
|
33
35
|
'DiagnosticsExport',
|
|
34
36
|
'DiagnosticsPanel',
|
|
@@ -55,10 +57,12 @@
|
|
|
55
57
|
'PostNavigationSettlementPersistence',
|
|
56
58
|
'ProjectFiles',
|
|
57
59
|
'ProjectProviderSelection',
|
|
60
|
+
'PanelIcons',
|
|
58
61
|
'ProjectSettingsCoordinator',
|
|
59
62
|
'ProviderSettingsCoordinator',
|
|
60
63
|
'RecentProjects',
|
|
61
64
|
'ReviewHunks',
|
|
65
|
+
'Reviewing',
|
|
62
66
|
'RunActivitySummary',
|
|
63
67
|
'RunPresence',
|
|
64
68
|
'RunActivityModel',
|
|
@@ -204,7 +204,8 @@
|
|
|
204
204
|
copy.append(text);
|
|
205
205
|
const descriptions = {
|
|
206
206
|
'annotated-rewrite': tx('Guided editing for document revisions.', '用于文稿修订的编辑流程。'),
|
|
207
|
-
'parallel-subagents': tx('Split independent subtasks across multiple agents.', '将相互独立的子任务分配给多个 agent。')
|
|
207
|
+
'parallel-subagents': tx('Split independent subtasks across multiple agents.', '将相互独立的子任务分配给多个 agent。'),
|
|
208
|
+
'reviewer-response': tx('Map reviewer comments to evidence, edits and reply drafts.', '把审稿意见对应到论文证据、修改和回复草稿。')
|
|
208
209
|
};
|
|
209
210
|
const description = (!local && descriptions[id])
|
|
210
211
|
|| (typeof skill.description === 'string' ? skill.description.replace(/\s+/g, ' ').trim() : '');
|
|
@@ -249,7 +250,8 @@
|
|
|
249
250
|
if (sourceLabel) sourceLabel.textContent = sourceText();
|
|
250
251
|
toggle.setAttribute('aria-label', accessibleSkillName + ': ' + tr('codexOverleafSkillEnableToggle'));
|
|
251
252
|
const label = !local && id === 'annotated-rewrite' ? tx('Guided editing for document revisions.', '用于文稿修订的编辑流程。')
|
|
252
|
-
: !local && id === 'parallel-subagents' ? tx('Split independent subtasks across multiple agents.', '将相互独立的子任务分配给多个 agent。')
|
|
253
|
+
: !local && id === 'parallel-subagents' ? tx('Split independent subtasks across multiple agents.', '将相互独立的子任务分配给多个 agent。')
|
|
254
|
+
: !local && id === 'reviewer-response' ? tx('Map reviewer comments to evidence, edits and reply drafts.', '把审稿意见对应到论文证据、修改和回复草稿。') : '';
|
|
253
255
|
const help = copy.querySelector('.codex-local-skill-description');
|
|
254
256
|
if (label && help) { help.textContent = label; help.title = label; }
|
|
255
257
|
};
|
|
@@ -320,7 +322,7 @@
|
|
|
320
322
|
toggle.disabled = true;
|
|
321
323
|
confirmBtn.textContent = tr('localSkillRemoving');
|
|
322
324
|
removeCodexOverleafSkill(id).catch(error => {
|
|
323
|
-
setProjectSettingsStatus(tx(`Failed to remove Codex Overleaf skill: ${error.message}`, `删除 Codex Overleaf 技能失败:${error.message}`), 'failed');
|
|
325
|
+
setProjectSettingsStatus(tx(`Failed to remove Codex Overleaf skill: ${error.message}`, `删除 Codex Overleaf 技能失败:${error.message}`), 'failed', { page: 'context' });
|
|
324
326
|
// Restore row on failure so the user can retry.
|
|
325
327
|
confirmBtn.disabled = false;
|
|
326
328
|
cancelBtn.disabled = false;
|
|
@@ -381,7 +383,7 @@
|
|
|
381
383
|
if (activeSkill?.scope === 'codex-overleaf' && activeSkill.id === id) {
|
|
382
384
|
clearComposerSkillInvocation();
|
|
383
385
|
}
|
|
384
|
-
setProjectSettingsStatus(tr('codexOverleafSkillRemoveDone'), 'completed');
|
|
386
|
+
setProjectSettingsStatus(tr('codexOverleafSkillRemoveDone'), 'completed', { page: 'context' });
|
|
385
387
|
clearSlashCodexOverleafSkills();
|
|
386
388
|
await refreshLocalSkills();
|
|
387
389
|
await saveState?.();
|
|
@@ -468,10 +468,10 @@
|
|
|
468
468
|
textNode.textContent = `${match[1]}${text.slice(match[0].length)}`;
|
|
469
469
|
textNode.parentNode.insertBefore(label, textNode);
|
|
470
470
|
}
|
|
471
|
-
decorateChangeReceipts(container, document, tx);
|
|
471
|
+
decorateChangeReceipts(container, document, tx, options.formatOperationType);
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
-
function decorateChangeReceipts(container, document, tx) {
|
|
474
|
+
function decorateChangeReceipts(container, document, tx, formatOperationType = type => type) {
|
|
475
475
|
const label = container.querySelector?.('.run-system-label[data-system-label="changes"]');
|
|
476
476
|
const list = label?.closest?.('p')?.nextElementSibling;
|
|
477
477
|
if (!list || !['UL', 'OL'].includes(list.tagName)) return;
|
|
@@ -508,7 +508,9 @@
|
|
|
508
508
|
file.textContent = receipt.file;
|
|
509
509
|
const operation = document.createElement('span');
|
|
510
510
|
operation.className = 'run-change-receipt__operation';
|
|
511
|
-
|
|
511
|
+
const type = ({ 编辑: 'edit', 新建: 'create', 重命名: 'rename', 移动: 'move', 删除: 'delete' })[receipt.operation]
|
|
512
|
+
|| receipt.operation.toLowerCase();
|
|
513
|
+
operation.textContent = formatOperationType(type);
|
|
512
514
|
receipt.item.classList.add('run-change-receipt');
|
|
513
515
|
receipt.item.setAttribute('aria-label', receipt.original);
|
|
514
516
|
receipt.item.title = receipt.original;
|
|
@@ -70,6 +70,15 @@
|
|
|
70
70
|
macros: getMathMacros(), renderText: buildMarkdownInlineNodesWithoutMath });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
function buildParsedTextNodes(value) {
|
|
74
|
+
const source = String(value || '');
|
|
75
|
+
if (!MathText?.buildMathNodes) {
|
|
76
|
+
return buildLineReferenceInlineNodes(source);
|
|
77
|
+
}
|
|
78
|
+
return MathText.buildMathNodes(source, { document, katex: window.katex,
|
|
79
|
+
macros: getMathMacros(), renderText: buildLineReferenceInlineNodes });
|
|
80
|
+
}
|
|
81
|
+
|
|
73
82
|
function buildMarkdownInlineNodesWithoutMath(value) {
|
|
74
83
|
const source = String(value || '');
|
|
75
84
|
const nodes = [];
|
|
@@ -99,7 +108,7 @@
|
|
|
99
108
|
index = next.end;
|
|
100
109
|
}
|
|
101
110
|
|
|
102
|
-
return nodes;
|
|
111
|
+
return groupLineReferenceNodes(nodes);
|
|
103
112
|
}
|
|
104
113
|
|
|
105
114
|
function buildInlineCodeNodes(value) {
|
|
@@ -152,7 +161,7 @@
|
|
|
152
161
|
cursor = start + rawText.length;
|
|
153
162
|
}
|
|
154
163
|
appendSanitizedTextNode(nodes, source.slice(cursor));
|
|
155
|
-
return nodes;
|
|
164
|
+
return groupLineReferenceNodes(nodes);
|
|
156
165
|
}
|
|
157
166
|
|
|
158
167
|
function buildMarkdownLinkNodes(text, href) {
|
|
@@ -187,6 +196,24 @@
|
|
|
187
196
|
}
|
|
188
197
|
}
|
|
189
198
|
|
|
199
|
+
function groupLineReferenceNodes(nodes) {
|
|
200
|
+
const grouped = [];
|
|
201
|
+
for (const node of nodes) {
|
|
202
|
+
const previous = grouped[grouped.length - 1];
|
|
203
|
+
if (node.classList?.contains('codex-line-reference') && previous?.nodeType === 3 &&
|
|
204
|
+
previous.textContent.endsWith('(')) {
|
|
205
|
+
previous.textContent = previous.textContent.slice(0, -1);
|
|
206
|
+
const group = document.createElement('span');
|
|
207
|
+
group.className = 'codex-line-reference-group';
|
|
208
|
+
group.append(document.createTextNode('('), node);
|
|
209
|
+
grouped.push(group);
|
|
210
|
+
} else {
|
|
211
|
+
grouped.push(node);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return grouped;
|
|
215
|
+
}
|
|
216
|
+
|
|
190
217
|
function resolveMarkdownLineReference(text, href) {
|
|
191
218
|
const candidates = [
|
|
192
219
|
{ value: href, mode: 'markdown-link-target' },
|
|
@@ -230,12 +257,16 @@
|
|
|
230
257
|
return null;
|
|
231
258
|
}
|
|
232
259
|
const line = Number(ref?.line);
|
|
260
|
+
const endLine = ref?.endLine === undefined ? null : Number(ref.endLine);
|
|
233
261
|
const column = ref?.column === null || ref?.column === undefined || ref?.column === ''
|
|
234
262
|
? null
|
|
235
263
|
: Number(ref.column);
|
|
236
264
|
if (!Number.isSafeInteger(line) || line < 1 || (column !== null && (!Number.isSafeInteger(column) || column < 1))) {
|
|
237
265
|
return null;
|
|
238
266
|
}
|
|
267
|
+
if (endLine !== null && (!Number.isSafeInteger(endLine) || endLine < line)) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
239
270
|
let resolved;
|
|
240
271
|
try {
|
|
241
272
|
resolved = LineReferences.resolveProjectReference({
|
|
@@ -251,6 +282,7 @@
|
|
|
251
282
|
return {
|
|
252
283
|
path: resolved.path,
|
|
253
284
|
line,
|
|
285
|
+
...(endLine > line ? { endLine } : {}),
|
|
254
286
|
column
|
|
255
287
|
};
|
|
256
288
|
}
|
|
@@ -262,10 +294,15 @@
|
|
|
262
294
|
button.textContent = formatLineReferenceText(reference);
|
|
263
295
|
button.dataset.path = reference.path;
|
|
264
296
|
button.dataset.line = String(reference.line);
|
|
297
|
+
if (reference.endLine) {
|
|
298
|
+
button.dataset.endLine = String(reference.endLine);
|
|
299
|
+
}
|
|
265
300
|
if (reference.column) {
|
|
266
301
|
button.dataset.column = String(reference.column);
|
|
267
302
|
}
|
|
268
|
-
const ariaLabel = reference.
|
|
303
|
+
const ariaLabel = reference.endLine
|
|
304
|
+
? `Open ${reference.path} lines ${reference.line} to ${reference.endLine}`
|
|
305
|
+
: reference.column
|
|
269
306
|
? `Open ${reference.path} line ${reference.line} column ${reference.column}`
|
|
270
307
|
: `Open ${reference.path} line ${reference.line}`;
|
|
271
308
|
button.setAttribute('aria-label', ariaLabel);
|
|
@@ -278,7 +315,10 @@
|
|
|
278
315
|
line: reference.line,
|
|
279
316
|
selectLine: !reference.column
|
|
280
317
|
};
|
|
281
|
-
if (reference.
|
|
318
|
+
if (reference.endLine) {
|
|
319
|
+
params.endLine = reference.endLine;
|
|
320
|
+
params.selectLine = true;
|
|
321
|
+
} else if (reference.column) {
|
|
282
322
|
params.column = reference.column;
|
|
283
323
|
params.selectLine = false;
|
|
284
324
|
}
|
|
@@ -310,7 +350,7 @@
|
|
|
310
350
|
}
|
|
311
351
|
|
|
312
352
|
function formatLineReferenceText(reference) {
|
|
313
|
-
return `${reference.path}:${reference.line}${reference.column ? `:${reference.column}` : ''}`;
|
|
353
|
+
return `${reference.path}:${reference.line}${reference.endLine ? `–${reference.endLine}` : reference.column ? `:${reference.column}` : ''}`;
|
|
314
354
|
}
|
|
315
355
|
|
|
316
356
|
function normalizeReferencePathForRuntime(value) {
|
|
@@ -483,15 +523,8 @@
|
|
|
483
523
|
document,
|
|
484
524
|
markdownIt: runtimeRoot.markdownit,
|
|
485
525
|
mathText: runtimeRoot.CodexOverleafMathText,
|
|
486
|
-
renderTextNodes:
|
|
487
|
-
renderLinkNodes:
|
|
488
|
-
const safeLabel = String(label || '');
|
|
489
|
-
const target = String(href || '').trim();
|
|
490
|
-
if (!/^https?:\/\//i.test(target) && !resolveMarkdownLineReference(safeLabel, target)) return buildMarkdownInlineNodes(safeLabel);
|
|
491
|
-
return buildMarkdownInlineNodes(
|
|
492
|
-
`[${safeLabel.replace(/]/g, '\\]')}](${target.replace(/\)/g, '\\)')})`
|
|
493
|
-
);
|
|
494
|
-
},
|
|
526
|
+
renderTextNodes: buildParsedTextNodes,
|
|
527
|
+
renderLinkNodes: buildMarkdownLinkNodes,
|
|
495
528
|
renderCodeNodes: text => buildInlineCodeNodes(text),
|
|
496
529
|
sanitizeText: sanitizeAssistantVisibleText,
|
|
497
530
|
createMathNode: segment => runtimeRoot.CodexOverleafMathText.createMathNode(segment,
|
|
@@ -499,6 +532,12 @@
|
|
|
499
532
|
renderText: text => buildMarkdownInlineNodes(text) }),
|
|
500
533
|
recordDiagnostic: recordRenderingDiagnostic
|
|
501
534
|
});
|
|
535
|
+
// The DOM renderer emits text and links from separate Markdown tokens.
|
|
536
|
+
const parents = new Set(Array.from(target.querySelectorAll('.codex-line-reference'), button => button.parentNode)
|
|
537
|
+
.filter(parent => !parent.classList.contains('codex-line-reference-group')));
|
|
538
|
+
for (const parent of parents) {
|
|
539
|
+
parent.replaceChildren(...groupLineReferenceNodes(Array.from(parent.childNodes)));
|
|
540
|
+
}
|
|
502
541
|
return;
|
|
503
542
|
} catch (error) {
|
|
504
543
|
recordRenderingDiagnostic({
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
retainSelectedModel
|
|
34
34
|
} = Support;
|
|
35
35
|
|
|
36
|
-
let modelDiscovery = { status: 'fallback', source: 'fallback', fetchedAt: '' };
|
|
36
|
+
let modelDiscovery = { status: 'fallback', source: 'fallback', fetchedAt: '', provisional: true };
|
|
37
37
|
let modelLoadGeneration = 0;
|
|
38
38
|
|
|
39
39
|
function getModelDiscovery() {
|
|
@@ -83,24 +83,21 @@
|
|
|
83
83
|
const modelSelect = getPanel()?.querySelector('[data-model]');
|
|
84
84
|
const reasoningSelect = getPanel()?.querySelector('[data-reasoning]');
|
|
85
85
|
const speedSelect = getPanel()?.querySelector('[data-speed]');
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
const changedInput = choice.dataset.reasoningChoice ? reasoningSelect
|
|
87
|
+
: choice.dataset.modelChoice ? modelSelect : choice.dataset.speedChoice ? speedSelect : null;
|
|
88
|
+
const value = choice.dataset.reasoningChoice || choice.dataset.modelChoice || choice.dataset.speedChoice;
|
|
89
|
+
const option = Array.from(changedInput?.options || []).find(item => item.value === value);
|
|
90
|
+
if (!changedInput || changedInput.disabled || !option || option.disabled) return;
|
|
91
|
+
|
|
92
|
+
changedInput.value = value;
|
|
93
|
+
if (changedInput === modelSelect) {
|
|
94
94
|
renderReasoningOptions(getRenderedModelEntries());
|
|
95
95
|
renderSpeedOptions(getRenderedModelEntries());
|
|
96
|
-
} else if (choice.dataset.speedChoice && speedSelect) {
|
|
97
|
-
speedSelect.value = choice.dataset.speedChoice;
|
|
98
|
-
changedInput = speedSelect;
|
|
99
96
|
}
|
|
100
97
|
|
|
101
98
|
renderModelConfigChoices();
|
|
102
99
|
updateModelDisplay();
|
|
103
|
-
await persistPanelInputs(
|
|
100
|
+
await persistPanelInputs({ type: 'change', target: changedInput });
|
|
104
101
|
}
|
|
105
102
|
async function loadModelOptions(providerSelection, options = {}) {
|
|
106
103
|
const generation = ++modelLoadGeneration;
|
|
@@ -136,7 +133,9 @@
|
|
|
136
133
|
}
|
|
137
134
|
const sourceModels = hasDiscoveredModels ? response.result.models : fallbackModels;
|
|
138
135
|
const preserveBuiltin = (selection?.providerId || 'builtin') === 'builtin' && (getState()?.providerId || 'builtin') === 'builtin';
|
|
139
|
-
const retainedSelectedModel = retainSelectedModel(sourceModels, currentSelectedModel, { preserveUnavailable: preserveBuiltin })
|
|
136
|
+
const retainedSelectedModel = retainSelectedModel(sourceModels, currentSelectedModel, { preserveUnavailable: preserveBuiltin })
|
|
137
|
+
|| (responseProviderId && responseProviderId !== 'builtin'
|
|
138
|
+
? retainSelectedModel(sourceModels, response.result?.defaultModelId) : '');
|
|
140
139
|
const normalized = modelCatalog.normalizeDiscoveredModels({ models: sourceModels, selectedModel: retainedSelectedModel });
|
|
141
140
|
if (normalized.usedFallback && response.result?.providerId && response.result.providerId !== 'builtin') {
|
|
142
141
|
applyUnavailableModelOptions({ code: 'provider_model_catalog_invalid', message: 'The active provider returned no usable models.' });
|
|
@@ -238,6 +237,13 @@
|
|
|
238
237
|
}
|
|
239
238
|
|
|
240
239
|
const selectedId = normalizeModelOptionId(selectedModel);
|
|
240
|
+
if (options.provisionalSelected === true) {
|
|
241
|
+
models = [...(Array.isArray(models) ? models : [])];
|
|
242
|
+
if (selectedId && !models.some(model => normalizeModelOptionId(model?.id) === selectedId)) {
|
|
243
|
+
models.push({ id: selectedId, label: selectedId, unverified: true });
|
|
244
|
+
}
|
|
245
|
+
models = Support.preserveSelectedCapabilities(models, selectedId, getState(), true);
|
|
246
|
+
}
|
|
241
247
|
modelSelect.textContent = '';
|
|
242
248
|
modelSelect.disabled = false;
|
|
243
249
|
let renderedSelected = false;
|
|
@@ -373,7 +379,8 @@
|
|
|
373
379
|
list.append(createModelConfigChoice({
|
|
374
380
|
value: option.value,
|
|
375
381
|
label: formatReasoningEffortLabel(option.value, reasoningSelect.dataset.presentation),
|
|
376
|
-
datasetName: 'reasoningChoice'
|
|
382
|
+
datasetName: 'reasoningChoice',
|
|
383
|
+
disabled: reasoningSelect.disabled || option.disabled
|
|
377
384
|
}));
|
|
378
385
|
}
|
|
379
386
|
}
|
|
@@ -390,7 +397,8 @@
|
|
|
390
397
|
const choice = createModelConfigChoice({
|
|
391
398
|
value: option.value,
|
|
392
399
|
label: option.textContent || option.value,
|
|
393
|
-
datasetName: 'modelChoice'
|
|
400
|
+
datasetName: 'modelChoice',
|
|
401
|
+
disabled: modelSelect.disabled || option.disabled
|
|
394
402
|
});
|
|
395
403
|
choice.title = option.textContent || option.value;
|
|
396
404
|
list.append(choice);
|
|
@@ -408,16 +416,17 @@
|
|
|
408
416
|
const choice = createModelConfigChoice({
|
|
409
417
|
value: option.value,
|
|
410
418
|
label: formatSpeedTierLabel(option.value),
|
|
411
|
-
datasetName: 'speedChoice'
|
|
419
|
+
datasetName: 'speedChoice',
|
|
420
|
+
disabled: speedSelect.disabled || option.disabled
|
|
412
421
|
});
|
|
413
|
-
choice.disabled = speedSelect.disabled && speedSelect.options.length <= 1;
|
|
414
422
|
list.append(choice);
|
|
415
423
|
}
|
|
416
424
|
}
|
|
417
425
|
|
|
418
|
-
function createModelConfigChoice({ value, label, datasetName }) {
|
|
426
|
+
function createModelConfigChoice({ value, label, datasetName, disabled = false }) {
|
|
419
427
|
const button = document.createElement('button');
|
|
420
428
|
button.type = 'button';
|
|
429
|
+
button.disabled = disabled;
|
|
421
430
|
button.className = 'codex-model-config-choice';
|
|
422
431
|
button.dataset[datasetName] = value;
|
|
423
432
|
button.setAttribute('role', 'menuitemradio');
|
|
@@ -525,6 +534,7 @@
|
|
|
525
534
|
readSelectedSpeedInput() === 'fast' ? tx('Fast mode', '快速模式') : tx('Standard speed', '标准速度')
|
|
526
535
|
].filter(Boolean).join(' · ');
|
|
527
536
|
}
|
|
537
|
+
deps.onSelectionRendered?.();
|
|
528
538
|
}
|
|
529
539
|
|
|
530
540
|
return {
|
|
@@ -37,8 +37,10 @@
|
|
|
37
37
|
try {
|
|
38
38
|
compatibilityGate = await ensureForMethod(payload?.method, context);
|
|
39
39
|
if (!compatibilityGate.ok) return compatibilityGate.response;
|
|
40
|
+
// Catalog reads belong to the selected session, not a retained cancelled run.
|
|
41
|
+
const independentCatalog = payload?.method === 'codex.models' || payload?.method === 'codex.providers.list';
|
|
40
42
|
// Post-Undo cache bookkeeping must survive the ended run's cancellation.
|
|
41
|
-
if (gatedMethods.has(payload?.method) && payload.method !== 'mirror.invalidate') {
|
|
43
|
+
if (gatedMethods.has(payload?.method) && payload.method !== 'mirror.invalidate' && !independentCatalog) {
|
|
42
44
|
options.throwIfCancellationRequested?.();
|
|
43
45
|
}
|
|
44
46
|
context.assertCurrent?.();
|
|
@@ -88,7 +90,7 @@
|
|
|
88
90
|
requiredVersion: compatibility.requiredVersion || Compatibility?.BUILD_TARGET_VERSION || '',
|
|
89
91
|
releaseUrl: compatibility.releaseUrl || ''
|
|
90
92
|
};
|
|
91
|
-
notifyBlocked(error, compatibility);
|
|
93
|
+
notifyBlocked(error, compatibility, method);
|
|
92
94
|
return { ok: false, compatibility, response: { ok: false, error } };
|
|
93
95
|
}
|
|
94
96
|
|
|
@@ -103,7 +105,7 @@
|
|
|
103
105
|
};
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
function notifyBlocked(error, compatibility = {}) {
|
|
108
|
+
function notifyBlocked(error, compatibility = {}, method) {
|
|
107
109
|
const message = error?.message || String(error || '');
|
|
108
110
|
if (options.getCurrentRunView?.()) {
|
|
109
111
|
options.appendRunEvent?.({ title: message, status: 'failed' });
|
|
@@ -111,7 +113,17 @@
|
|
|
111
113
|
return;
|
|
112
114
|
}
|
|
113
115
|
showUpdateGuidance(compatibility);
|
|
114
|
-
|
|
116
|
+
const missing = compatibility.status === 'native_missing';
|
|
117
|
+
options.showPluginToast?.(missing ? tr('nativeCompatibilityMissingGuidance') : message, {
|
|
118
|
+
status: 'failed',
|
|
119
|
+
sticky: true,
|
|
120
|
+
...(missing ? {
|
|
121
|
+
title: tr('nativeCompatibilityMissingTitle'),
|
|
122
|
+
groupKey: 'native-missing',
|
|
123
|
+
groupItem: method || 'native request',
|
|
124
|
+
groupSummary: count => tr('nativeCompatibilityUnavailableFeatures', { count })
|
|
125
|
+
} : {})
|
|
126
|
+
});
|
|
115
127
|
}
|
|
116
128
|
|
|
117
129
|
async function refreshBadge() {
|
|
@@ -137,7 +149,9 @@
|
|
|
137
149
|
options.setDiagnosticsHealth?.(classification === 'update-available' ? 'warn' : 'fail');
|
|
138
150
|
options.setBadge?.(renderer.headerEl, {
|
|
139
151
|
type: 'update',
|
|
140
|
-
tooltip:
|
|
152
|
+
tooltip: compatibility.status === 'native_unhealthy'
|
|
153
|
+
? tx('Codex Unavailable', 'Codex 不可用')
|
|
154
|
+
: tx('Native host update available', 'Native host 可更新'),
|
|
141
155
|
onClick: () => showUpdateGuidance(compatibility)
|
|
142
156
|
});
|
|
143
157
|
if (!compatibility?.native?.version) maybePromptFirstRunSetup();
|
|
@@ -181,7 +195,9 @@
|
|
|
181
195
|
|| compatibility.nativeVersion
|
|
182
196
|
|| native.version
|
|
183
197
|
|| tx('missing', '未安装');
|
|
184
|
-
const
|
|
198
|
+
const codexUnavailable = compatibility.status === 'native_unhealthy';
|
|
199
|
+
const resolvedCommand = resolveInstallCommand(compatibility);
|
|
200
|
+
const command = codexUnavailable ? '' : resolvedCommand;
|
|
185
201
|
const releaseUrl = compatibility.releaseUrl || '';
|
|
186
202
|
const overlay = options.document.createElement('div');
|
|
187
203
|
overlay.className = 'codex-plugin-confirm';
|
|
@@ -191,20 +207,40 @@
|
|
|
191
207
|
const nativeMissing = !native.version;
|
|
192
208
|
overlay.setAttribute(
|
|
193
209
|
'aria-label',
|
|
194
|
-
|
|
210
|
+
codexUnavailable
|
|
211
|
+
? tx('Codex Unavailable', 'Codex 不可用')
|
|
212
|
+
: nativeMissing
|
|
195
213
|
? tx('Set up the native host', '安装 Native host')
|
|
196
214
|
: tx('Native host update available', 'Native host 可更新')
|
|
197
215
|
);
|
|
198
216
|
const card = options.document.createElement('section');
|
|
199
217
|
card.className = 'codex-plugin-confirm-card';
|
|
218
|
+
const head = options.document.createElement('div');
|
|
219
|
+
head.className = 'codex-plugin-confirm-head';
|
|
220
|
+
const icon = options.document.createElement('img');
|
|
221
|
+
icon.className = 'codex-plugin-confirm-icon';
|
|
222
|
+
icon.alt = '';
|
|
223
|
+
icon.setAttribute('aria-hidden', 'true');
|
|
224
|
+
icon.src = options.getIconUrl?.() || '';
|
|
225
|
+
const titleWrap = options.document.createElement('div');
|
|
226
|
+
const brand = options.document.createElement('div');
|
|
227
|
+
brand.className = 'codex-plugin-confirm-brand';
|
|
228
|
+
brand.textContent = 'Codex Overleaf Link';
|
|
200
229
|
const title = options.document.createElement('div');
|
|
201
230
|
title.className = 'codex-plugin-confirm-title';
|
|
202
|
-
title.textContent =
|
|
231
|
+
title.textContent = codexUnavailable
|
|
232
|
+
? tx('Codex Unavailable', 'Codex 不可用')
|
|
233
|
+
: nativeMissing
|
|
203
234
|
? tx('One step left: install the native host', '还差一步:安装 Native host')
|
|
204
235
|
: tx('Native host update available', 'Native host 可更新');
|
|
236
|
+
titleWrap.append(brand, title);
|
|
237
|
+
head.append(icon, titleWrap);
|
|
205
238
|
const body = options.document.createElement('div');
|
|
206
239
|
body.className = 'codex-plugin-confirm-body';
|
|
207
|
-
body.textContent = [
|
|
240
|
+
body.textContent = codexUnavailable ? [
|
|
241
|
+
tx('The extension reached the native host, but local Codex was not found, so tasks cannot start.', '插件已经连上 native host,但没有找到本机 Codex,所以不能启动任务。'),
|
|
242
|
+
tx('Make sure codex works in Terminal, then reload the extension.', '请确认终端里可以运行 codex,然后重新加载扩展。')
|
|
243
|
+
].join('\n\n') : [
|
|
208
244
|
nativeMissing
|
|
209
245
|
? tx(
|
|
210
246
|
`Extension v${extensionVersion} is ready; Codex still needs its local bridge to read and edit this project.`,
|
|
@@ -222,20 +258,16 @@
|
|
|
222
258
|
? tx(' Use PowerShell.', ' 请使用 PowerShell。') : '')
|
|
223
259
|
].join('\n\n');
|
|
224
260
|
const commandCode = options.document.createElement('code');
|
|
261
|
+
commandCode.className = 'codex-native-guidance-command';
|
|
225
262
|
commandCode.textContent = command;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
whiteSpace: 'pre-wrap',
|
|
229
|
-
marginTop: '0.75rem'
|
|
230
|
-
});
|
|
231
|
-
body.append(commandCode);
|
|
232
|
-
if (releaseUrl) {
|
|
263
|
+
if (!codexUnavailable) body.append(commandCode);
|
|
264
|
+
if (!codexUnavailable && releaseUrl) {
|
|
233
265
|
const link = options.document.createElement('a');
|
|
266
|
+
link.className = 'codex-native-guidance-link';
|
|
234
267
|
link.href = releaseUrl;
|
|
235
268
|
link.target = '_blank';
|
|
236
269
|
link.rel = 'noopener noreferrer';
|
|
237
270
|
link.textContent = tx('Open GitHub Release', '打开 GitHub Release');
|
|
238
|
-
Object.assign(link.style, { display: 'block', marginTop: '0.75rem' });
|
|
239
271
|
body.append(link);
|
|
240
272
|
}
|
|
241
273
|
const actions = options.document.createElement('div');
|
|
@@ -255,8 +287,9 @@
|
|
|
255
287
|
close.className = 'codex-plugin-confirm-cancel';
|
|
256
288
|
close.textContent = tx('Close', '关闭');
|
|
257
289
|
close.addEventListener('click', () => overlay.remove());
|
|
258
|
-
actions.append(close
|
|
259
|
-
|
|
290
|
+
actions.append(close);
|
|
291
|
+
if (!codexUnavailable) actions.append(copy);
|
|
292
|
+
card.append(head, body, actions);
|
|
260
293
|
overlay.append(card);
|
|
261
294
|
overlay.addEventListener('click', event => {
|
|
262
295
|
if (event.target === overlay) overlay.remove();
|
|
@@ -895,7 +895,7 @@
|
|
|
895
895
|
appendLog(tx(`Cannot continue: ${formatProjectSnapshotWarning(warning)}`, `无法继续:${formatProjectSnapshotWarning(warning)}`));
|
|
896
896
|
}
|
|
897
897
|
appendCompletionReport({
|
|
898
|
-
conclusion: tr('warmMirrorStaleBlockedConclusion'),
|
|
898
|
+
conclusion: tr('warmMirrorStaleBlockedConclusion'), conclusionKey: 'warm_mirror_stale',
|
|
899
899
|
status: 'blocked',
|
|
900
900
|
operations: [],
|
|
901
901
|
applyResults: [],
|
|
@@ -6,25 +6,26 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const PAGE_WORLD_SCRIPTS = Object.freeze([
|
|
9
|
-
['src/shared/reviewing.js', 'codex-overleaf-reviewing-script'],
|
|
9
|
+
['src/shared/reviewing.js', 'codex-overleaf-reviewing-script', true],
|
|
10
10
|
['src/shared/projectFiles.js', 'codex-overleaf-project-files-script'],
|
|
11
11
|
['src/shared/compatibility.js', 'codex-overleaf-compatibility-page-script'],
|
|
12
12
|
['src/shared/pageRpcContract.js', 'codex-overleaf-page-rpc-contract-script', true],
|
|
13
|
-
['src/shared/staleGuard.js', 'codex-overleaf-stale-guard-script'],
|
|
13
|
+
['src/shared/staleGuard.js', 'codex-overleaf-stale-guard-script', true],
|
|
14
|
+
['src/shared/otText.js', 'codex-overleaf-ot-text-script'],
|
|
14
15
|
['src/shared/compileAdapter.js', 'codex-overleaf-compile-adapter-script'],
|
|
15
16
|
['src/shared/sensitiveScan.js', 'codex-overleaf-sensitive-scan-script'],
|
|
16
17
|
['src/shared/auditRecords.js', 'codex-overleaf-audit-records-script'],
|
|
17
18
|
['src/page/saveState.js', 'codex-overleaf-save-state-script', true],
|
|
18
|
-
['src/page/overleafCapabilities.js', 'codex-overleaf-capabilities-script'],
|
|
19
|
+
['src/page/overleafCapabilities.js', 'codex-overleaf-capabilities-script', true],
|
|
19
20
|
['src/page/compileBridge.js', 'codex-overleaf-compile-bridge-script'],
|
|
20
|
-
['src/page/overleafEditor.js', 'codex-overleaf-editor-script'],
|
|
21
|
-
['src/page/overleafProjectSnapshot.js', 'codex-overleaf-project-snapshot-script'],
|
|
21
|
+
['src/page/overleafEditor.js', 'codex-overleaf-editor-script', true],
|
|
22
|
+
['src/page/overleafProjectSnapshot.js', 'codex-overleaf-project-snapshot-script', true],
|
|
22
23
|
['src/page/pageBridgeCapability.js', 'codex-overleaf-page-bridge-capability-script'],
|
|
23
24
|
['src/page/treeOperations.js', 'codex-overleaf-tree-operations-script', true],
|
|
24
25
|
['src/page/ownedDirectoryCleanup.js', 'codex-overleaf-owned-directory-cleanup-script', true],
|
|
25
26
|
['src/page/textFileCreator.js', 'codex-overleaf-text-file-creator-script', true],
|
|
26
27
|
['src/page/binaryAssetUploader.js', 'codex-overleaf-binary-asset-uploader-script', true],
|
|
27
|
-
['src/page/snapshotRouter.js', 'codex-overleaf-snapshot-router-script'],
|
|
28
|
+
['src/page/snapshotRouter.js', 'codex-overleaf-snapshot-router-script', true],
|
|
28
29
|
['src/page/referenceProjects.js', 'codex-overleaf-reference-projects-script', true],
|
|
29
30
|
['src/page/fileMover.js', 'codex-overleaf-file-mover-script', true],
|
|
30
31
|
['src/page/writeGuard.js', 'codex-overleaf-write-guard-script', true],
|
|
@@ -39,7 +40,6 @@
|
|
|
39
40
|
['src/pageBridge.js', 'codex-overleaf-page-bridge-script', true]
|
|
40
41
|
]);
|
|
41
42
|
const OPTIONAL_OT_SCRIPTS = Object.freeze([
|
|
42
|
-
['src/shared/otText.js', 'codex-overleaf-ot-text-script'],
|
|
43
43
|
['src/page/overleafRealtimeObserver.js', 'codex-overleaf-realtime-observer-script']
|
|
44
44
|
]);
|
|
45
45
|
|
|
@@ -181,6 +181,7 @@
|
|
|
181
181
|
// the failed task usually needs a tweak before it is worth resending.
|
|
182
182
|
function refillComposerForRetry(run, textOverride) {
|
|
183
183
|
const input = getPanel()?.querySelector('[data-task]');
|
|
184
|
+
if (input?.readOnly) return;
|
|
184
185
|
const task = typeof textOverride === 'string' && textOverride.trim()
|
|
185
186
|
? textOverride
|
|
186
187
|
: String(run?.task || '');
|
|
@@ -188,6 +189,10 @@
|
|
|
188
189
|
showPluginToast(tx('Nothing to refill: the original task text is unavailable.', '无法回填:原任务文本不可用。'));
|
|
189
190
|
return;
|
|
190
191
|
}
|
|
192
|
+
if (input.value.trim() && input.value.trim() !== task.trim()) {
|
|
193
|
+
showPluginToast(tx('Kept your draft. Clear the composer, then try again to refill this task.', '已保留你的草稿。清空输入框后再试一次,即可回填这条任务。'));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
191
196
|
prepareRetryReplacement?.(run || null, task);
|
|
192
197
|
input.value = task;
|
|
193
198
|
getState().task = task;
|
|
@@ -310,7 +315,9 @@
|
|
|
310
315
|
// Settings history card, expanded and loaded.
|
|
311
316
|
function openChangeHistory() {
|
|
312
317
|
openCustomInstructionsSettings();
|
|
313
|
-
|
|
318
|
+
// The workbench shows one page at a time; switch to the page holding the card.
|
|
319
|
+
const card = getSettingsPanelInstance()?.revealGroup?.('history')
|
|
320
|
+
|| getSettingsPanelInstance()?.container?.querySelector('[data-history-card]');
|
|
314
321
|
if (card) {
|
|
315
322
|
if (!card.open) {
|
|
316
323
|
card.open = true;
|
|
@@ -322,7 +329,8 @@
|
|
|
322
329
|
|
|
323
330
|
function openStorageSettings() {
|
|
324
331
|
openCustomInstructionsSettings();
|
|
325
|
-
const card =
|
|
332
|
+
const card = getSettingsPanelInstance()?.revealGroup?.('storage')
|
|
333
|
+
|| getPanel()?.querySelector('[data-storage-card]');
|
|
326
334
|
if (card) {
|
|
327
335
|
card.open = true;
|
|
328
336
|
card.scrollIntoView({ block: 'center' });
|