codex-overleaf-link 2.3.0 → 2.3.2
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 +23 -23
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +20 -0
- package/extension/src/content/assetTransferBroker.js +169 -0
- package/extension/src/content/composerPanel.js +0 -2
- package/extension/src/content/contentRuntime.js +135 -111
- package/extension/src/content/generated/content.bundle.js +1066 -345
- package/extension/src/content/generated/content.bundle.meta.json +7 -3
- package/extension/src/content/legacyGlobalRegistry.js +3 -0
- package/extension/src/content/markdownText.js +12 -10
- package/extension/src/content/mathText.js +155 -9
- package/extension/src/content/modelPicker.js +2 -2
- package/extension/src/content/modelPickerSupport.js +3 -3
- package/extension/src/content/nativeCompatibilityController.js +2 -2
- package/extension/src/content/otWarmMirror.js +1 -1
- package/extension/src/content/pageBridgeClient.js +1 -0
- package/extension/src/content/runResultActions.js +114 -0
- package/extension/src/content/runTimelineView.js +23 -0
- package/extension/src/content/sessionForkController.js +120 -0
- package/extension/src/content/writebackController.js +3 -0
- package/extension/src/content/writebackOrchestrator.js +5 -50
- package/extension/src/page/binaryAssetUploader.js +343 -0
- package/extension/src/page/trackedChangesLifecycle.js +12 -4
- package/extension/src/page/writebackRouter.js +6 -2
- package/extension/src/pageBridge.js +30 -1
- package/extension/src/shared/agentTranscript.js +10 -3
- package/extension/src/shared/compatibility.js +4 -2
- package/extension/src/shared/i18n.js +18 -4
- package/extension/src/shared/models.js +13 -2
- package/extension/src/shared/pageRpcContract.js +6 -2
- package/extension/src/shared/runExecutionSnapshot.js +14 -4
- package/extension/src/shared/runExecutionSnapshotCodec.js +5 -2
- package/extension/src/shared/scopedPersistenceQueuePolicy.js +20 -1
- package/extension/src/shared/scopedPersistenceReceipt.js +60 -0
- package/extension/src/shared/scopedPersistenceTransaction.js +50 -47
- package/extension/src/shared/sessionState.js +58 -15
- package/extension/src/shared/storageDb.js +6 -5
- package/extension/src/shared/storageRunActions.js +11 -1
- package/extension/src/shared/writebackOperationEvidence.js +16 -6
- package/extension/src/shared/writebackSettlement.js +28 -6
- package/extension/styles/panel.css +79 -8
- package/native-host/src/codexModels.js +6 -2
- package/native-host/src/codexPromptAssembly.js +1 -1
- package/native-host/src/codexSessionRunner.js +5 -1
- package/native-host/src/codexThreadFork.js +103 -0
- package/native-host/src/mirrorWorkspace.js +5 -19
- package/native-host/src/nativeAssetTransfer.js +183 -0
- package/native-host/src/taskRunnerRuntime.js +33 -81
- package/native-host/src/updateManager.js +36 -1
- package/package.json +1 -1
|
@@ -2,13 +2,14 @@
|
|
|
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": "d2167fca49721d0ef5e477dc76b11a0cedb33c9f51b920b55ea666ab4668dc4c",
|
|
6
|
+
"outputDigest": "87cbcf7d9877860b7c1d047cd3fa6e985e28812c8df81c9105ec9312a5e45ea6",
|
|
7
|
+
"byteLength": 2309285,
|
|
8
8
|
"inputs": [
|
|
9
9
|
"extension/entries/content-entry.mjs",
|
|
10
10
|
"extension/src/content/activeTurnControl.js",
|
|
11
11
|
"extension/src/content/applyResultFormatters.js",
|
|
12
|
+
"extension/src/content/assetTransferBroker.js",
|
|
12
13
|
"extension/src/content/composerAttachments.js",
|
|
13
14
|
"extension/src/content/composerPanel.js",
|
|
14
15
|
"extension/src/content/contentRuntime.js",
|
|
@@ -45,11 +46,13 @@
|
|
|
45
46
|
"extension/src/content/runGuidanceController.js",
|
|
46
47
|
"extension/src/content/runGuidanceView.js",
|
|
47
48
|
"extension/src/content/runQueueScheduler.js",
|
|
49
|
+
"extension/src/content/runResultActions.js",
|
|
48
50
|
"extension/src/content/runSettlementPersistence.js",
|
|
49
51
|
"extension/src/content/runTimelineView.js",
|
|
50
52
|
"extension/src/content/scopedPersistenceCoordinator.js",
|
|
51
53
|
"extension/src/content/scopedPersistenceDetachedCommit.js",
|
|
52
54
|
"extension/src/content/scopedPersistencePanelState.js",
|
|
55
|
+
"extension/src/content/sessionForkController.js",
|
|
53
56
|
"extension/src/content/sessionManager.js",
|
|
54
57
|
"extension/src/content/sessionMenuView.js",
|
|
55
58
|
"extension/src/content/sessionPanel.js",
|
|
@@ -81,6 +84,7 @@
|
|
|
81
84
|
"extension/src/shared/runInputQueue.js",
|
|
82
85
|
"extension/src/shared/scopedPersistenceBrowserAdapter.js",
|
|
83
86
|
"extension/src/shared/scopedPersistenceQueuePolicy.js",
|
|
87
|
+
"extension/src/shared/scopedPersistenceReceipt.js",
|
|
84
88
|
"extension/src/shared/scopedPersistenceTransaction.js",
|
|
85
89
|
"extension/src/shared/sensitiveScan.js",
|
|
86
90
|
"extension/src/shared/sessionState.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
'ActiveTurnControl',
|
|
16
16
|
'AgentTranscript',
|
|
17
17
|
'ApplyResultFormatters',
|
|
18
|
+
'AssetTransferBroker',
|
|
18
19
|
'AuditRecords',
|
|
19
20
|
'Compatibility',
|
|
20
21
|
'ComposerAttachments',
|
|
@@ -53,12 +54,14 @@
|
|
|
53
54
|
'RunGuidanceController',
|
|
54
55
|
'RunInputQueue',
|
|
55
56
|
'RunQueueScheduler',
|
|
57
|
+
'RunResultActions',
|
|
56
58
|
'RunSettlementPersistence',
|
|
57
59
|
'RunTimelineView',
|
|
58
60
|
'ScopedPersistenceCoordinator',
|
|
59
61
|
'ScopedPersistenceTransaction',
|
|
60
62
|
'SensitiveScan',
|
|
61
63
|
'SessionManager',
|
|
64
|
+
'SessionForkController',
|
|
62
65
|
'SessionPanel',
|
|
63
66
|
'SessionPersistence',
|
|
64
67
|
'SessionState',
|
|
@@ -13,12 +13,14 @@
|
|
|
13
13
|
tx,
|
|
14
14
|
callPageBridge, getCurrentProjectId,
|
|
15
15
|
getCurrentProjectReferenceFiles,
|
|
16
|
+
getCurrentProjectMathSources,
|
|
16
17
|
showPluginToast
|
|
17
18
|
} = deps;
|
|
18
19
|
|
|
19
20
|
function renderMarkdownInlineText(target, value) {
|
|
20
21
|
target.replaceChildren(...buildMarkdownInlineNodes(value));
|
|
21
22
|
}
|
|
23
|
+
function getMathMacros() { return MathText?.buildMathMacros?.(getCurrentProjectMathSources?.() || []) || {}; }
|
|
22
24
|
|
|
23
25
|
function sanitizeAssistantVisibleText(value) {
|
|
24
26
|
if (typeof value !== 'string' || !value) {
|
|
@@ -67,11 +69,8 @@
|
|
|
67
69
|
if (!mathText?.buildMathNodes) {
|
|
68
70
|
return buildMarkdownInlineNodesWithoutMath(source);
|
|
69
71
|
}
|
|
70
|
-
return mathText.buildMathNodes(source, {
|
|
71
|
-
|
|
72
|
-
katex: window.katex,
|
|
73
|
-
renderText: buildMarkdownInlineNodesWithoutMath
|
|
74
|
-
});
|
|
72
|
+
return mathText.buildMathNodes(source, { document, katex: window.katex,
|
|
73
|
+
macros: getMathMacros(), renderText: buildMarkdownInlineNodesWithoutMath });
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
function buildMarkdownInlineNodesWithoutMath(value) {
|
|
@@ -109,6 +108,10 @@
|
|
|
109
108
|
function buildInlineCodeNodes(value) {
|
|
110
109
|
const source = String(value || '');
|
|
111
110
|
const trimmed = source.trim();
|
|
111
|
+
const standaloneMath = MathText?.parseStandaloneMath?.(trimmed);
|
|
112
|
+
if (standaloneMath && MathText?.createMathNode) return [MathText.createMathNode(
|
|
113
|
+
standaloneMath, { document, katex: window.katex, macros: getMathMacros() }
|
|
114
|
+
)];
|
|
112
115
|
const refs = trimmed ? parseRuntimeLineReferences(trimmed, 'plain-text-token') : [];
|
|
113
116
|
const ref = refs.length === 1 && refs[0]?.rawText === trimmed ? refs[0] : null;
|
|
114
117
|
if (ref && !isRuntimeLocalPathLike(ref.rawPath)) {
|
|
@@ -492,12 +495,11 @@
|
|
|
492
495
|
`[${safeLabel.replace(/]/g, '\\]')}](${target.replace(/\)/g, '\\)')})`
|
|
493
496
|
);
|
|
494
497
|
},
|
|
495
|
-
renderCodeNodes: text =>
|
|
498
|
+
renderCodeNodes: text => buildInlineCodeNodes(text),
|
|
496
499
|
sanitizeText: sanitizeAssistantVisibleText,
|
|
497
|
-
createMathNode: segment => runtimeRoot.CodexOverleafMathText.createMathNode(segment,
|
|
498
|
-
document, katex: runtimeRoot.katex,
|
|
499
|
-
|
|
500
|
-
}),
|
|
500
|
+
createMathNode: segment => runtimeRoot.CodexOverleafMathText.createMathNode(segment,
|
|
501
|
+
{ document, katex: runtimeRoot.katex, macros: getMathMacros(),
|
|
502
|
+
renderText: text => buildMarkdownInlineNodes(text) }),
|
|
501
503
|
recordDiagnostic: recordRenderingDiagnostic
|
|
502
504
|
});
|
|
503
505
|
return;
|
|
@@ -9,6 +9,19 @@
|
|
|
9
9
|
]);
|
|
10
10
|
const LONG_INLINE_MATH_CHARS = 120;
|
|
11
11
|
const COMPLEX_INLINE_MATH_CHARS = 80;
|
|
12
|
+
const MAX_PROJECT_MACRO_SOURCES = 12;
|
|
13
|
+
const MAX_PROJECT_MACRO_SOURCE_CHARS = 256 * 1024;
|
|
14
|
+
const MAX_PROJECT_MACROS = 64;
|
|
15
|
+
const MAX_MACRO_EXPANSION_CHARS = 512;
|
|
16
|
+
const DEFAULT_MATH_MACROS = Object.freeze({
|
|
17
|
+
'\\E': '\\mathbb{E}',
|
|
18
|
+
'\\Var': '\\operatorname{Var}',
|
|
19
|
+
'\\Cov': '\\operatorname{Cov}',
|
|
20
|
+
'\\R': '\\mathbb{R}',
|
|
21
|
+
'\\N': '\\mathbb{N}',
|
|
22
|
+
'\\Z': '\\mathbb{Z}'
|
|
23
|
+
});
|
|
24
|
+
const UNSAFE_MACRO_PATTERN = /\\(?:href|url|includegraphics|input|include|write|openout|read|html\w*|class|style|data|def|gdef|edef|xdef|newcommand|renewcommand|providecommand|DeclareMathOperator)\b/i;
|
|
12
25
|
|
|
13
26
|
function parseMathSegments(value) {
|
|
14
27
|
const source = String(value || '');
|
|
@@ -74,9 +87,10 @@
|
|
|
74
87
|
searchFrom = start + delimiter.open.length;
|
|
75
88
|
continue;
|
|
76
89
|
}
|
|
77
|
-
const
|
|
90
|
+
const rawValue = source.slice(start + delimiter.open.length, closeStart);
|
|
91
|
+
const value = rawValue.trim();
|
|
78
92
|
const end = closeStart + delimiter.close.length;
|
|
79
|
-
if (!isValidMathValue(
|
|
93
|
+
if (!isValidMathValue(rawValue, delimiter) || overlapsCodeRange(start, end, codeRanges)) {
|
|
80
94
|
searchFrom = start + delimiter.open.length;
|
|
81
95
|
continue;
|
|
82
96
|
}
|
|
@@ -94,7 +108,7 @@
|
|
|
94
108
|
}
|
|
95
109
|
const previous = source[index - 1] || '';
|
|
96
110
|
const next = source[index + 1] || '';
|
|
97
|
-
return previous !== '$' && next !== '$' && next !== ''
|
|
111
|
+
return previous !== '$' && next !== '$' && next !== '';
|
|
98
112
|
}
|
|
99
113
|
|
|
100
114
|
function findClosingDelimiter(source, fromIndex, delimiter, codeRanges) {
|
|
@@ -107,7 +121,7 @@
|
|
|
107
121
|
const previous = source[index - 1] || '';
|
|
108
122
|
const next = source[index + delimiter.close.length] || '';
|
|
109
123
|
const invalidSingleDollar = delimiter.singleDollar
|
|
110
|
-
&& (previous === '$' || next === '$'
|
|
124
|
+
&& (previous === '$' || next === '$');
|
|
111
125
|
if (!isEscaped(source, index) && !isInsideRange(index, codeRanges) && !invalidSingleDollar) {
|
|
112
126
|
return index;
|
|
113
127
|
}
|
|
@@ -118,10 +132,24 @@
|
|
|
118
132
|
|
|
119
133
|
function isValidMathValue(value, delimiter) {
|
|
120
134
|
const source = String(value || '');
|
|
121
|
-
|
|
135
|
+
const trimmed = source.trim();
|
|
136
|
+
if (!trimmed) {
|
|
122
137
|
return false;
|
|
123
138
|
}
|
|
124
|
-
|
|
139
|
+
if (!delimiter.display && /[\r\n]/.test(source)) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (!delimiter.singleDollar || (!/^\s/.test(source) && !/\s$/.test(source))) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
return looksLikeWhitespaceWrappedMath(trimmed);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function looksLikeWhitespaceWrappedMath(value) {
|
|
149
|
+
const source = String(value || '').trim();
|
|
150
|
+
return /\\[A-Za-z]+/.test(source)
|
|
151
|
+
|| /[_^=<>+\-*/()[\]{}|]/.test(source)
|
|
152
|
+
|| /^[A-Za-z](?:_[A-Za-z0-9{}]+|\^[A-Za-z0-9{}]+)?$/.test(source);
|
|
125
153
|
}
|
|
126
154
|
|
|
127
155
|
function collectInlineCodeRanges(source) {
|
|
@@ -179,7 +207,8 @@
|
|
|
179
207
|
}
|
|
180
208
|
nodes.push(createMathNode(segment, {
|
|
181
209
|
document: documentRef,
|
|
182
|
-
katex: options.katex || root.katex
|
|
210
|
+
katex: options.katex || root.katex,
|
|
211
|
+
macros: options.macros || buildMathMacros(options.projectSources)
|
|
183
212
|
}));
|
|
184
213
|
}
|
|
185
214
|
return nodes;
|
|
@@ -206,6 +235,7 @@
|
|
|
206
235
|
strict: 'warn',
|
|
207
236
|
maxExpand: 200,
|
|
208
237
|
maxSize: 20,
|
|
238
|
+
macros: options.macros || buildMathMacros(),
|
|
209
239
|
output: 'htmlAndMathml'
|
|
210
240
|
});
|
|
211
241
|
node.dataset.mathRendered = 'true';
|
|
@@ -213,7 +243,7 @@
|
|
|
213
243
|
} catch (_error) {
|
|
214
244
|
node.classList.add('run-math--fallback');
|
|
215
245
|
node.dataset.mathRendered = 'false';
|
|
216
|
-
node.textContent =
|
|
246
|
+
node.textContent = source;
|
|
217
247
|
return node;
|
|
218
248
|
}
|
|
219
249
|
}
|
|
@@ -235,6 +265,120 @@
|
|
|
235
265
|
return /(?:=|\\(?:le|ge|approx|sim|to|Rightarrow|Longrightarrow)\b|\\begin\{(?:aligned|gathered|split|array)\}|\\\\)/.test(source);
|
|
236
266
|
}
|
|
237
267
|
|
|
268
|
+
function parseStandaloneMath(value) {
|
|
269
|
+
const source = String(value || '').trim();
|
|
270
|
+
if (!source) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
const segments = parseMathSegments(source);
|
|
274
|
+
if (segments.length !== 1 || segments[0].type !== 'math' || segments[0].raw !== source) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
return segments[0];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function buildMathMacros(projectSources = []) {
|
|
281
|
+
const macros = { ...DEFAULT_MATH_MACROS };
|
|
282
|
+
let remainingChars = MAX_PROJECT_MACRO_SOURCE_CHARS;
|
|
283
|
+
let projectMacroCount = 0;
|
|
284
|
+
for (const sourceRecord of Array.isArray(projectSources)
|
|
285
|
+
? projectSources.slice(0, MAX_PROJECT_MACRO_SOURCES)
|
|
286
|
+
: []) {
|
|
287
|
+
if (projectMacroCount >= MAX_PROJECT_MACROS || remainingChars <= 0) {
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
const path = String(sourceRecord?.path || '');
|
|
291
|
+
if (!/\.(?:tex|sty|cls|ltx)$/i.test(path)) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
const source = stripLatexComments(
|
|
295
|
+
String(sourceRecord?.content || '').slice(0, remainingChars)
|
|
296
|
+
);
|
|
297
|
+
remainingChars -= source.length;
|
|
298
|
+
const pattern = /\\(newcommand|renewcommand|providecommand|DeclareMathOperator)(\*)?/g;
|
|
299
|
+
let match;
|
|
300
|
+
while ((match = pattern.exec(source)) !== null && projectMacroCount < MAX_PROJECT_MACROS) {
|
|
301
|
+
let cursor = skipWhitespace(source, pattern.lastIndex);
|
|
302
|
+
const nameGroup = readBracedGroup(source, cursor);
|
|
303
|
+
if (!nameGroup) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
const macroName = nameGroup.value.trim();
|
|
307
|
+
cursor = skipWhitespace(source, nameGroup.end);
|
|
308
|
+
if (source[cursor] === '[') {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const expansionGroup = readBracedGroup(source, cursor);
|
|
312
|
+
if (!expansionGroup) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
let expansion = expansionGroup.value.trim();
|
|
316
|
+
if (match[1] === 'DeclareMathOperator') {
|
|
317
|
+
expansion = `\\operatorname${match[2] ? '*' : ''}{${expansion}}`;
|
|
318
|
+
}
|
|
319
|
+
if (!isSafeMacroDefinition(macroName, expansion)) {
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
macros[macroName] = expansion;
|
|
323
|
+
projectMacroCount++;
|
|
324
|
+
pattern.lastIndex = expansionGroup.end;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return macros;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function readBracedGroup(source, start) {
|
|
331
|
+
if (source[start] !== '{') {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
let depth = 0;
|
|
335
|
+
for (let index = start; index < source.length; index++) {
|
|
336
|
+
if (source[index] === '{' && !isEscaped(source, index)) {
|
|
337
|
+
depth++;
|
|
338
|
+
} else if (source[index] === '}' && !isEscaped(source, index)) {
|
|
339
|
+
depth--;
|
|
340
|
+
if (depth === 0) {
|
|
341
|
+
return {
|
|
342
|
+
value: source.slice(start + 1, index),
|
|
343
|
+
end: index + 1
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function skipWhitespace(source, start) {
|
|
352
|
+
let index = start;
|
|
353
|
+
while (index < source.length && /\s/.test(source[index])) {
|
|
354
|
+
index++;
|
|
355
|
+
}
|
|
356
|
+
return index;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function stripLatexComments(source) {
|
|
360
|
+
return String(source || '').split(/\r?\n/).map(line => {
|
|
361
|
+
for (let index = 0; index < line.length; index++) {
|
|
362
|
+
if (line[index] === '%' && !isEscaped(line, index)) {
|
|
363
|
+
return line.slice(0, index);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return line;
|
|
367
|
+
}).join('\n');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function isSafeMacroDefinition(name, expansion) {
|
|
371
|
+
const macroName = String(name || '');
|
|
372
|
+
const body = String(expansion || '');
|
|
373
|
+
return /^\\[A-Za-z@]+$/.test(macroName)
|
|
374
|
+
&& body.length > 0
|
|
375
|
+
&& body.length <= MAX_MACRO_EXPANSION_CHARS
|
|
376
|
+
&& !body.includes('#')
|
|
377
|
+
&& !body.includes(macroName)
|
|
378
|
+
&& !UNSAFE_MACRO_PATTERN.test(macroName)
|
|
379
|
+
&& !UNSAFE_MACRO_PATTERN.test(body);
|
|
380
|
+
}
|
|
381
|
+
|
|
238
382
|
function toNodeArray(value) {
|
|
239
383
|
if (Array.isArray(value)) {
|
|
240
384
|
return value;
|
|
@@ -265,11 +409,13 @@
|
|
|
265
409
|
}
|
|
266
410
|
|
|
267
411
|
const api = {
|
|
412
|
+
buildMathMacros,
|
|
268
413
|
buildMathNodes,
|
|
269
414
|
createMathNode,
|
|
270
415
|
matchMathAt,
|
|
271
416
|
normalizeMathForRendering,
|
|
272
|
-
parseMathSegments
|
|
417
|
+
parseMathSegments,
|
|
418
|
+
parseStandaloneMath
|
|
273
419
|
};
|
|
274
420
|
root.CodexOverleafMathText = api;
|
|
275
421
|
if (typeof module !== 'undefined' && module.exports) {
|
|
@@ -452,8 +452,8 @@
|
|
|
452
452
|
if (effort === 'xhigh') return 'Max';
|
|
453
453
|
}
|
|
454
454
|
const labels = getLocale() === 'zh'
|
|
455
|
-
? { none: '关闭', minimal: '最小', low: '低', medium: '中', high: '高', xhigh: '超高' }
|
|
456
|
-
: { none: 'Off', minimal: 'Minimal', low: 'Low', medium: 'Medium', high: 'High', xhigh: 'XHigh' };
|
|
455
|
+
? { none: '关闭', minimal: '最小', low: '低', medium: '中', high: '高', xhigh: '超高', max: '最大', ultra: '极限' }
|
|
456
|
+
: { none: 'Off', minimal: 'Minimal', low: 'Low', medium: 'Medium', high: 'High', xhigh: 'XHigh', max: 'Max', ultra: 'Ultra' };
|
|
457
457
|
return labels[effort] || effort || '';
|
|
458
458
|
}
|
|
459
459
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function normalizeReasoningEffortsForSelect(efforts) {
|
|
22
|
-
const allowed = new Set(['none', 'minimal', 'low', 'medium', 'high', 'xhigh']);
|
|
22
|
+
const allowed = new Set(['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'ultra']);
|
|
23
23
|
return Array.from(new Set((Array.isArray(efforts) ? efforts : [])
|
|
24
24
|
.map(effort => normalizeModelOptionId(effort))
|
|
25
25
|
.filter(effort => allowed.has(effort))));
|
|
@@ -92,12 +92,12 @@
|
|
|
92
92
|
const normalized = {
|
|
93
93
|
id,
|
|
94
94
|
label: typeof model?.label === 'string' && model.label.length > 0 ? model.label : id,
|
|
95
|
-
reasoningEfforts:
|
|
95
|
+
reasoningEfforts: normalizeReasoningEffortsForSelect(model?.reasoningEfforts),
|
|
96
96
|
reasoningPresentation: typeof model?.reasoningPresentation === 'string' ? model.reasoningPresentation : '',
|
|
97
97
|
speedTiers: normalizeSpeedTiersForSelect(model?.speedTiers)
|
|
98
98
|
};
|
|
99
99
|
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultReasoningEffort')) {
|
|
100
|
-
normalized.defaultReasoningEffort = model.defaultReasoningEffort;
|
|
100
|
+
normalized.defaultReasoningEffort = normalizeModelOptionId(model.defaultReasoningEffort);
|
|
101
101
|
}
|
|
102
102
|
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultSpeedTier')) {
|
|
103
103
|
normalized.defaultSpeedTier = model.defaultSpeedTier;
|
|
@@ -256,8 +256,8 @@
|
|
|
256
256
|
tip.dataset.onboardingTip = 'true';
|
|
257
257
|
tip.setAttribute('role', 'status');
|
|
258
258
|
tip.textContent = tx(
|
|
259
|
-
'Tip: Start with Ask mode to explore safely. Switch to
|
|
260
|
-
'提示:先用 Ask
|
|
259
|
+
'Tip: Start with Ask mode to explore safely. Switch to Auto only when you want Codex to edit files.',
|
|
260
|
+
'提示:先用 Ask 模式安全探索;只有需要 Codex 修改文件时才切换到 Auto。'
|
|
261
261
|
);
|
|
262
262
|
Object.assign(tip.style, {
|
|
263
263
|
position: 'absolute',
|
|
@@ -868,7 +868,7 @@
|
|
|
868
868
|
applyResults: [],
|
|
869
869
|
nextStep: tr('warmMirrorStaleBlockedNextStep')
|
|
870
870
|
});
|
|
871
|
-
finishRunView(tr('warmMirrorStaleBlockedTitle'), 'failed');
|
|
871
|
+
await finishRunView(tr('warmMirrorStaleBlockedTitle'), 'failed');
|
|
872
872
|
return { ok: false };
|
|
873
873
|
}
|
|
874
874
|
if (focusedPartialSnapshot) {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
['src/page/overleafProjectSnapshot.js', 'codex-overleaf-project-snapshot-script'],
|
|
22
22
|
['src/page/pageBridgeCapability.js', 'codex-overleaf-page-bridge-capability-script'],
|
|
23
23
|
['src/page/treeOperations.js', 'codex-overleaf-tree-operations-script', true],
|
|
24
|
+
['src/page/binaryAssetUploader.js', 'codex-overleaf-binary-asset-uploader-script', true],
|
|
24
25
|
['src/page/snapshotRouter.js', 'codex-overleaf-snapshot-router-script'],
|
|
25
26
|
['src/page/writeGuard.js', 'codex-overleaf-write-guard-script', true],
|
|
26
27
|
['src/page/trackedChangesLifecycle.js', 'codex-overleaf-tracked-changes-lifecycle-script', true],
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
(function initCodexOverleafRunResultActions(root, factory) {
|
|
2
|
+
const api = factory();
|
|
3
|
+
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
4
|
+
if (root) root.CodexOverleafRunResultActions = api;
|
|
5
|
+
})(typeof window !== 'undefined' ? window : globalThis, function runResultActionsFactory() {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
function create(deps = {}) {
|
|
9
|
+
const {
|
|
10
|
+
tr,
|
|
11
|
+
getLocale,
|
|
12
|
+
forkRunFromNode,
|
|
13
|
+
document: documentRef = globalThis.document,
|
|
14
|
+
navigator: navigatorRef = globalThis.navigator
|
|
15
|
+
} = deps;
|
|
16
|
+
|
|
17
|
+
function configureResultActions(root, run) {
|
|
18
|
+
const actions = root.querySelector('.run-result-actions');
|
|
19
|
+
const reports = root.querySelectorAll('.run-completion-report');
|
|
20
|
+
const report = reports[reports.length - 1];
|
|
21
|
+
if (!actions || !report) return;
|
|
22
|
+
report.append(actions);
|
|
23
|
+
actions.hidden = false;
|
|
24
|
+
configureCopyButton(root);
|
|
25
|
+
configureForkButton(root, run);
|
|
26
|
+
configureCompletedTime(actions, run);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function configureForkButton(root, run) {
|
|
30
|
+
const existing = root.querySelector('[data-run-fork]');
|
|
31
|
+
const button = existing.cloneNode(true);
|
|
32
|
+
existing.replaceWith(button);
|
|
33
|
+
const available = run.forkSnapshot !== true
|
|
34
|
+
&& run.status !== 'running'
|
|
35
|
+
&& Boolean(run.codexTurnId)
|
|
36
|
+
&& typeof forkRunFromNode === 'function';
|
|
37
|
+
button.hidden = false;
|
|
38
|
+
button.disabled = !available;
|
|
39
|
+
button.title = tr(available ? 'forkRunTitle' : 'forkRunUnavailable');
|
|
40
|
+
button.setAttribute('aria-label', button.title);
|
|
41
|
+
button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M3 10h3.5c3.5 0 4.2-4 7.5-4h2m-2.5-2.5L16 6l-2.5 2.5M6.5 10c3.5 0 4.2 4 7.5 4h2m-2.5-2.5L16 14l-2.5 2.5"/></svg>';
|
|
42
|
+
if (!available) return;
|
|
43
|
+
button.addEventListener('click', async event => {
|
|
44
|
+
event.stopPropagation();
|
|
45
|
+
button.disabled = true;
|
|
46
|
+
button.classList.add('is-running');
|
|
47
|
+
try {
|
|
48
|
+
await forkRunFromNode(run.id);
|
|
49
|
+
} catch (_error) {
|
|
50
|
+
button.disabled = false;
|
|
51
|
+
button.classList.remove('is-running');
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function configureCompletedTime(actions, run) {
|
|
57
|
+
const target = actions.querySelector('[data-run-completed-time]');
|
|
58
|
+
const finishedAt = String(run.finishedAt || '').trim();
|
|
59
|
+
const date = finishedAt ? new Date(finishedAt) : null;
|
|
60
|
+
if (!target || !date || !Number.isFinite(date.getTime())) return;
|
|
61
|
+
target.hidden = false;
|
|
62
|
+
target.textContent = new Intl.DateTimeFormat(getLocale(), {
|
|
63
|
+
hour: '2-digit',
|
|
64
|
+
minute: '2-digit'
|
|
65
|
+
}).format(date);
|
|
66
|
+
target.title = date.toLocaleString(getLocale());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function configureCopyButton(root) {
|
|
70
|
+
const existing = root.querySelector('[data-run-copy]');
|
|
71
|
+
const button = existing.cloneNode(true);
|
|
72
|
+
existing.replaceWith(button);
|
|
73
|
+
const finalAnswer = root.querySelector('.run-completion-report .run-final-answer');
|
|
74
|
+
const copyText = String(finalAnswer?.innerText || finalAnswer?.textContent || '').trim();
|
|
75
|
+
button.hidden = false;
|
|
76
|
+
button.disabled = !copyText;
|
|
77
|
+
button.title = tr('copyConclusionTitle');
|
|
78
|
+
button.setAttribute('aria-label', button.title);
|
|
79
|
+
button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><rect x="6.5" y="6.5" width="9" height="9" rx="2"/><path d="M13.5 6.5V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6.5a2 2 0 0 0 2 2h1.5"/></svg>';
|
|
80
|
+
if (!copyText) return;
|
|
81
|
+
button.addEventListener('click', async event => {
|
|
82
|
+
event.stopPropagation();
|
|
83
|
+
try {
|
|
84
|
+
await writeClipboardText(copyText);
|
|
85
|
+
button.title = tr('copyConclusionDone');
|
|
86
|
+
} catch (_error) {
|
|
87
|
+
button.title = tr('copyConclusionFailed');
|
|
88
|
+
}
|
|
89
|
+
button.setAttribute('aria-label', button.title);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function writeClipboardText(text) {
|
|
94
|
+
if (navigatorRef?.clipboard?.writeText) {
|
|
95
|
+
await navigatorRef.clipboard.writeText(text);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const textarea = documentRef.createElement('textarea');
|
|
99
|
+
textarea.value = text;
|
|
100
|
+
textarea.setAttribute('readonly', '');
|
|
101
|
+
textarea.style.position = 'fixed';
|
|
102
|
+
textarea.style.opacity = '0';
|
|
103
|
+
documentRef.body.append(textarea);
|
|
104
|
+
textarea.select();
|
|
105
|
+
const copied = documentRef.execCommand('copy');
|
|
106
|
+
textarea.remove();
|
|
107
|
+
if (!copied) throw new Error('clipboard_copy_failed');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return Object.freeze({ configureResultActions });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return Object.freeze({ create });
|
|
114
|
+
});
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
function create(deps = {}) {
|
|
14
14
|
const {
|
|
15
15
|
RunGuidanceView,
|
|
16
|
+
RunResultActions,
|
|
16
17
|
tr,
|
|
17
18
|
tx,
|
|
18
19
|
getLocale,
|
|
@@ -274,6 +275,9 @@
|
|
|
274
275
|
if (status === 'failed') {
|
|
275
276
|
return tr('processedFailed', { elapsed });
|
|
276
277
|
}
|
|
278
|
+
if (status === 'rejected' || status === 'cancelled') {
|
|
279
|
+
return tr('processedCancelled', { elapsed });
|
|
280
|
+
}
|
|
277
281
|
if (status === 'running') {
|
|
278
282
|
return tr('processing', { elapsed });
|
|
279
283
|
}
|
|
@@ -343,6 +347,11 @@
|
|
|
343
347
|
</summary>
|
|
344
348
|
</details>
|
|
345
349
|
<div class="run-activity-list" data-run-events></div>
|
|
350
|
+
<div class="run-result-actions" hidden>
|
|
351
|
+
<button type="button" class="run-copy-action" data-run-copy hidden></button>
|
|
352
|
+
<button type="button" class="run-fork-action" data-run-fork hidden></button>
|
|
353
|
+
<span class="run-completed-time" data-run-completed-time hidden></span>
|
|
354
|
+
</div>
|
|
346
355
|
<div class="run-report" data-run-report aria-live="polite" hidden></div>
|
|
347
356
|
</div>
|
|
348
357
|
`;
|
|
@@ -396,6 +405,7 @@
|
|
|
396
405
|
}
|
|
397
406
|
}
|
|
398
407
|
|
|
408
|
+
RunResultActions.configureResultActions(root, run);
|
|
399
409
|
configureAcceptButton(root, run);
|
|
400
410
|
configureUndoButton(root, run);
|
|
401
411
|
return root;
|
|
@@ -411,6 +421,9 @@
|
|
|
411
421
|
if (run.startedAt && run.finishedAt) {
|
|
412
422
|
return formatProcessedSummary(run.status || 'completed', new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime());
|
|
413
423
|
}
|
|
424
|
+
if (run.status === 'rejected' || run.status === 'cancelled') {
|
|
425
|
+
return tx('Cancelled', '已取消');
|
|
426
|
+
}
|
|
414
427
|
return run.status === 'failed' ? tx('Failed', '处理失败') : tx('Done', '已处理');
|
|
415
428
|
}
|
|
416
429
|
|
|
@@ -880,6 +893,11 @@
|
|
|
880
893
|
const button = existing.cloneNode(true);
|
|
881
894
|
existing.replaceWith(button);
|
|
882
895
|
|
|
896
|
+
if (run.forkSnapshot === true) {
|
|
897
|
+
button.hidden = true;
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
|
|
883
901
|
if (isTrackedChangeLifecycleRun(run)) {
|
|
884
902
|
configureLifecycleUndoButton(button, run);
|
|
885
903
|
return;
|
|
@@ -976,6 +994,11 @@
|
|
|
976
994
|
const button = existing.cloneNode(true);
|
|
977
995
|
existing.replaceWith(button);
|
|
978
996
|
|
|
997
|
+
if (run.forkSnapshot === true) {
|
|
998
|
+
button.hidden = true;
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
979
1002
|
if (!isTrackedChangeLifecycleRun(run)) {
|
|
980
1003
|
button.hidden = true;
|
|
981
1004
|
return;
|