codex-overleaf-link 1.8.5 → 1.9.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 +45 -21
- package/bin/codex-overleaf-link.mjs +58 -0
- package/extension/assets/icons/codex-overleaf-dialog-icon.png +0 -0
- package/extension/assets/icons/codex-overleaf-icon.png +0 -0
- package/extension/assets/icons/icon128.png +0 -0
- package/extension/assets/icons/icon16.png +0 -0
- package/extension/assets/icons/icon32.png +0 -0
- package/extension/assets/icons/icon48.png +0 -0
- package/extension/bootstrap/background.js +404 -0
- package/extension/bootstrap/manifest.template.json +51 -0
- package/extension/bootstrap/popup.css +26 -0
- package/extension/bootstrap/popup.html +38 -0
- package/extension/bootstrap/popup.js +44 -0
- package/extension/bootstrap/runtimeContext.js +2 -0
- package/extension/runtime-manifest.json +60 -0
- package/extension/src/background.js +532 -0
- package/extension/src/content/applyResultFormatters.js +387 -0
- package/extension/src/content/composerAttachments.js +522 -0
- package/extension/src/content/composerPanel.js +254 -0
- package/extension/src/content/contentRuntime.js +8895 -0
- package/extension/src/content/contextTray.js +686 -0
- package/extension/src/content/diagnosticsController.js +659 -0
- package/extension/src/content/diagnosticsPanel.js +342 -0
- package/extension/src/content/diffReviewPanel.js +797 -0
- package/extension/src/content/localSkillsPanel.js +280 -0
- package/extension/src/content/markdownText.js +606 -0
- package/extension/src/content/mirrorHealth.js +92 -0
- package/extension/src/content/modelPicker.js +489 -0
- package/extension/src/content/nativeChannel.js +62 -0
- package/extension/src/content/otWarmMirror.js +964 -0
- package/extension/src/content/otWarmMirrorController.js +174 -0
- package/extension/src/content/panelMaintenance.js +367 -0
- package/extension/src/content/panelRenderer.js +253 -0
- package/extension/src/content/recentProjects.js +1063 -0
- package/extension/src/content/reviewHunks.js +247 -0
- package/extension/src/content/runController.js +242 -0
- package/extension/src/content/runTimelineView.js +1126 -0
- package/extension/src/content/sessionManager.js +487 -0
- package/extension/src/content/sessionPanel.js +263 -0
- package/extension/src/content/settingsPanel.js +527 -0
- package/extension/src/content/themeController.js +91 -0
- package/extension/src/content/updateIdle.js +67 -0
- package/extension/src/content/writebackController.js +300 -0
- package/extension/src/content/writebackOrchestrator.js +850 -0
- package/extension/src/contentScript.js +8 -0
- package/extension/src/page/compileBridge.js +460 -0
- package/extension/src/page/overleafCapabilities.js +100 -0
- package/extension/src/page/overleafEditor.js +282 -0
- package/extension/src/page/overleafProjectSnapshot.js +234 -0
- package/extension/src/page/overleafRealtimeObserver.js +491 -0
- package/extension/src/page/pageBridgeCapability.js +71 -0
- package/extension/src/page/snapshotRouter.js +948 -0
- package/extension/src/page/trackedChangesLifecycle.js +1506 -0
- package/extension/src/page/treeOperations.js +1584 -0
- package/extension/src/page/writeGuard.js +142 -0
- package/extension/src/page/writebackRouter.js +1934 -0
- package/extension/src/pageBridge.js +2224 -0
- package/extension/src/popup.js +247 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/styles/panel.css +4048 -0
- package/native-host/src/index.js +9 -2
- package/native-host/src/launcher.js +2 -0
- package/native-host/src/managedInstall.js +393 -0
- package/native-host/src/managedLauncherRuntime.js +71 -0
- package/native-host/src/nativeEnvironment.js +4 -0
- package/native-host/src/nativeHostPlatform.js +16 -0
- package/native-host/src/runtimeInstaller.js +6 -1
- package/native-host/src/taskRunnerRuntime.js +8 -0
- package/native-host/src/updateArchive.js +253 -0
- package/native-host/src/updateManager.js +548 -0
- package/native-host/src/updateTrust.js +156 -0
- package/package.json +11 -2
- package/scripts/install-managed.mjs +64 -0
- package/scripts/uninstall-managed.mjs +48 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
(function initCodexOverleafApplyResultFormatters() {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const i18n = window.CodexOverleafI18n;
|
|
5
|
+
const FailureReasons = window.CodexOverleafFailureReasons;
|
|
6
|
+
|
|
7
|
+
// Apply-result / failure-reason formatters carved out of contentRuntime.js
|
|
8
|
+
// (v1.4.7 structural-debt phase 3): the skipped-detail renderer and the
|
|
9
|
+
// bilingual apply/bridge reason formatters. Code moved verbatim; the few
|
|
10
|
+
// runtime collaborators are factory-injected.
|
|
11
|
+
function create(deps = {}) {
|
|
12
|
+
const {
|
|
13
|
+
getLocale,
|
|
14
|
+
tr,
|
|
15
|
+
tx,
|
|
16
|
+
getAppliedEntries,
|
|
17
|
+
getSkippedEntries,
|
|
18
|
+
appendRunEvent
|
|
19
|
+
} = deps;
|
|
20
|
+
|
|
21
|
+
function appendApplyResult(result) {
|
|
22
|
+
if (!result) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const appliedEntries = getAppliedEntries(result);
|
|
26
|
+
const skippedEntries = getSkippedEntries(result);
|
|
27
|
+
const applied = appliedEntries.length;
|
|
28
|
+
const skipped = skippedEntries.length;
|
|
29
|
+
const skippedFailures = skippedEntries
|
|
30
|
+
.map(item => normalizeSkippedFailure(item))
|
|
31
|
+
.filter(Boolean);
|
|
32
|
+
const primaryFailure = pickPrimarySkippedFailure(skippedFailures);
|
|
33
|
+
const detail = {
|
|
34
|
+
[tx('Written', '已写入')]: appliedEntries.map(item => ({
|
|
35
|
+
[tr('detailAction')]: formatOperationType(item.operation?.type),
|
|
36
|
+
[tr('detailFile')]: item.operation?.path,
|
|
37
|
+
[tx('Status', '状态')]: item.result?.status
|
|
38
|
+
})),
|
|
39
|
+
[tr('detailSkipped')]: skippedEntries.map(item => buildSkippedDetail(item))
|
|
40
|
+
};
|
|
41
|
+
if (primaryFailure && primaryFailure.nextAction) {
|
|
42
|
+
detail[tr('detailNext')] = primaryFailure.nextAction;
|
|
43
|
+
}
|
|
44
|
+
appendRunEvent({
|
|
45
|
+
title: tx(`Write result: wrote ${applied} item(s), skipped ${skipped}`, `写入结果:已写入 ${applied} 项,跳过 ${skipped} 项`),
|
|
46
|
+
status: skipped ? 'failed' : 'completed',
|
|
47
|
+
detail
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Build the per-skipped-entry detail block surfaced in the run-card expand
|
|
53
|
+
* view. Includes the canonical FailureReason fields (Reason/Stage/Code/Next)
|
|
54
|
+
* when the normalizer can produce a usable record, falling back to the
|
|
55
|
+
* legacy parenthesized reason otherwise.
|
|
56
|
+
*/
|
|
57
|
+
function buildSkippedDetail(item) {
|
|
58
|
+
const operation = item?.operation || {};
|
|
59
|
+
const base = {
|
|
60
|
+
[tr('detailAction')]: formatOperationType(operation.type),
|
|
61
|
+
[tr('detailFile')]: operation.path,
|
|
62
|
+
[tr('detailReason')]: formatApplyResultReason(item)
|
|
63
|
+
};
|
|
64
|
+
const failure = normalizeSkippedFailure(item);
|
|
65
|
+
if (failure) {
|
|
66
|
+
base[tx('Stage', '阶段')] = failure.stage;
|
|
67
|
+
base[tx('Code', '代码')] = failure.code;
|
|
68
|
+
if (failure.nextAction) {
|
|
69
|
+
base[tr('detailNext')] = failure.nextAction;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Always surface the writeback debug payload (signatures, active paths,
|
|
73
|
+
// open diagnostics) on skipped rows — without it a navigation-stage skip
|
|
74
|
+
// is undiagnosable from the UI (v1.6 lesson).
|
|
75
|
+
const debugText = formatApplyResultDebug(item?.result?.debug || item?.result?.diagnostics);
|
|
76
|
+
if (debugText) {
|
|
77
|
+
base[tx('Debug', '调试')] = debugText;
|
|
78
|
+
}
|
|
79
|
+
return base;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Normalize a skipped writeback item into a localized FailureReason. Returns
|
|
84
|
+
* null when the FailureReasons module is unavailable so callers fall back to
|
|
85
|
+
* legacy rendering.
|
|
86
|
+
*/
|
|
87
|
+
function normalizeSkippedFailure(item) {
|
|
88
|
+
if (!FailureReasons || !FailureReasons.normalizeFailureReason) return null;
|
|
89
|
+
const failure = FailureReasons.normalizeFailureReason(item?.result, item?.operation || {}, { locale: getLocale() });
|
|
90
|
+
if (!failure || !failure.code) return null;
|
|
91
|
+
const localized = FailureReasons.localizeFailureReason
|
|
92
|
+
? FailureReasons.localizeFailureReason(failure, getLocale(), failureReasonI18nLookup)
|
|
93
|
+
: { userMessage: failure.userMessage, nextAction: failure.nextAction };
|
|
94
|
+
return Object.assign({}, failure, {
|
|
95
|
+
userMessage: localized.userMessage || failure.userMessage,
|
|
96
|
+
nextAction: localized.nextAction || failure.nextAction
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function pickPrimarySkippedFailure(failures) {
|
|
101
|
+
if (!FailureReasons || !FailureReasons.selectPrimaryFailure) return null;
|
|
102
|
+
return FailureReasons.selectPrimaryFailure(failures);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function failureReasonI18nLookup(key) {
|
|
106
|
+
if (!i18n || !i18n.t) return undefined;
|
|
107
|
+
const localized = i18n.t(getLocale(), key);
|
|
108
|
+
// i18n.t returns the key itself on miss; treat that as a miss so the
|
|
109
|
+
// catalog fallback wins for codes without bespoke localization.
|
|
110
|
+
return localized && localized !== key ? localized : undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Compact one-liner for toasts, collapsed run-card rows, and single-line
|
|
115
|
+
* debug logs: `<code>: <userMessage truncated to one line>`. Returns ''
|
|
116
|
+
* when the failure or its userMessage is missing.
|
|
117
|
+
* @param {{ code?: string, userMessage?: string } | null} failure
|
|
118
|
+
* @param {number} [maxLength=140]
|
|
119
|
+
* @returns {string}
|
|
120
|
+
*/
|
|
121
|
+
function formatFailureReasonOneLiner(failure, maxLength) {
|
|
122
|
+
if (!failure || !failure.code || !failure.userMessage) return '';
|
|
123
|
+
const limit = Number.isFinite(maxLength) ? Math.max(40, Math.floor(maxLength)) : 140;
|
|
124
|
+
const flat = String(failure.userMessage).replace(/\s+/g, ' ').trim();
|
|
125
|
+
const codePrefix = `${failure.code}: `;
|
|
126
|
+
const remaining = Math.max(20, limit - codePrefix.length);
|
|
127
|
+
const truncated = flat.length > remaining ? `${flat.slice(0, remaining - 1).trimEnd()}…` : flat;
|
|
128
|
+
return `${codePrefix}${truncated}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function formatApplyResultReason(item = {}) {
|
|
132
|
+
const result = item.result || {};
|
|
133
|
+
const operation = item.operation || {};
|
|
134
|
+
const key = result.reasonKey || '';
|
|
135
|
+
const code = result.code || '';
|
|
136
|
+
const filePath = result.reasonParams?.filePath || operation.path || operation.from || operation.to || '';
|
|
137
|
+
const withDebug = reason => appendApplyResultDebug(reason, result);
|
|
138
|
+
if (key === 'missingBaseFile' || code === 'missing_base_file') {
|
|
139
|
+
const target = filePath || tx('this file', '这个文件');
|
|
140
|
+
return withDebug(tx(
|
|
141
|
+
`${target} was not read when the task started. Codex did not overwrite it; refresh the project content and retry.`,
|
|
142
|
+
`${target} 在任务开始时没有被 Codex 读到。Codex 没有覆盖它;请刷新项目内容后重试。`
|
|
143
|
+
));
|
|
144
|
+
}
|
|
145
|
+
if (key === 'staleSnapshot' || code === 'stale_snapshot') {
|
|
146
|
+
const target = filePath || tx('this file', '这个文件');
|
|
147
|
+
return withDebug(tx(
|
|
148
|
+
`${target} changed while Codex was working, so Codex did not overwrite it. Review the diff and retry.`,
|
|
149
|
+
`${target} 在任务执行期间被你或协作者改过,Codex 没有覆盖它。请查看差异后重试。`
|
|
150
|
+
));
|
|
151
|
+
}
|
|
152
|
+
if (key === 'stalePatchLocation') {
|
|
153
|
+
return withDebug(tx(
|
|
154
|
+
'The edit location no longer matches the current Overleaf content, so nothing was written. Rerun the task.',
|
|
155
|
+
'Codex 要修改的位置已经无法和当前 Overleaf 内容对齐,所以没有写入。请重新运行任务。'
|
|
156
|
+
));
|
|
157
|
+
}
|
|
158
|
+
if (key === 'stalePatchConflict' || code === 'stale_patch_range') {
|
|
159
|
+
return withDebug(tx(
|
|
160
|
+
'The exact edit location was changed by you or a collaborator, so Codex did not overwrite it. Review the diff and retry.',
|
|
161
|
+
'Codex 要修改的具体位置已经被你或协作者改过,所以没有覆盖它。请查看差异后重试。'
|
|
162
|
+
));
|
|
163
|
+
}
|
|
164
|
+
if (code === 'stale_patch') {
|
|
165
|
+
return withDebug(tx(
|
|
166
|
+
'This exact text changed since Codex read it, so nothing was written. Rerun after Codex reads the latest Overleaf content.',
|
|
167
|
+
'这处内容已经和 Codex 读取时不同,所以没有写入。请重新运行,让 Codex 先读取你的最新 Overleaf 内容。'
|
|
168
|
+
));
|
|
169
|
+
}
|
|
170
|
+
if (code === 'invalid_patch') {
|
|
171
|
+
return withDebug(tx(
|
|
172
|
+
'Codex produced an invalid local edit range, so nothing was written.',
|
|
173
|
+
'Codex 生成的局部写入范围无效,所以没有写入。'
|
|
174
|
+
));
|
|
175
|
+
}
|
|
176
|
+
if (code === 'write_verification_failed') {
|
|
177
|
+
return withDebug(tx(
|
|
178
|
+
'After writing, the editor content did not match Codex\'s expected result, so the write was not marked successful. Reload Overleaf and retry.',
|
|
179
|
+
'写入后读回内容和 Codex 预期不一致,已停止把这次操作标记为成功。请刷新 Overleaf 后重试。'
|
|
180
|
+
));
|
|
181
|
+
}
|
|
182
|
+
if (code === 'file_tree_verification_failed') {
|
|
183
|
+
return tx(
|
|
184
|
+
'Overleaf did not confirm the file-tree operation, so Codex did not mark it successful.',
|
|
185
|
+
'Overleaf 文件树操作没有被确认,Codex 已停止把这次操作标记为成功。'
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
if (code === 'path_exists_in_snapshot') {
|
|
189
|
+
const target = filePath || tx('this file', '这个文件');
|
|
190
|
+
return tx(
|
|
191
|
+
`${target} already existed when the task started. Codex did not overwrite it; edit the file instead or choose another filename.`,
|
|
192
|
+
`${target} 在任务开始前已经存在。Codex 没有覆盖它;请改用修改文件或换一个文件名。`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
if (code === 'path_created_since_snapshot') {
|
|
196
|
+
const target = filePath || tx('this file', '这个文件');
|
|
197
|
+
return tx(
|
|
198
|
+
`${target} was created by you or a collaborator while Codex was working, so Codex did not overwrite it. Review the diff and retry.`,
|
|
199
|
+
`${target} 在任务执行期间被你或协作者新建了,Codex 没有覆盖它。请查看差异后重试。`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
return withDebug(localizeVisibleReason(result.reason || result.error || result.code || tr('unknownReason')));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function appendApplyResultDebug(reason, result = {}) {
|
|
206
|
+
const debug = result.debug || result.diagnostics;
|
|
207
|
+
const text = formatApplyResultDebug(debug);
|
|
208
|
+
return text ? `${reason} [debug: ${text}]` : reason;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function formatApplyResultDebug(debug) {
|
|
212
|
+
if (!debug || typeof debug !== 'object') {
|
|
213
|
+
return '';
|
|
214
|
+
}
|
|
215
|
+
const parts = [];
|
|
216
|
+
const add = (key, value) => {
|
|
217
|
+
if (value === undefined || value === null || value === '') {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
parts.push(`${key}=${String(value)}`);
|
|
221
|
+
};
|
|
222
|
+
add('stage', debug.stage);
|
|
223
|
+
add('rev', debug.revision);
|
|
224
|
+
add('op', debug.operationPath);
|
|
225
|
+
add('active', debug.activePath);
|
|
226
|
+
add('initial', debug.initialActivePath);
|
|
227
|
+
add('last', debug.lastActivePath);
|
|
228
|
+
add('currentLen', debug.current?.length);
|
|
229
|
+
add('currentNorm', debug.current?.normalizedLength);
|
|
230
|
+
add('currentHash', debug.current?.hash);
|
|
231
|
+
add('baseKnown', debug.baseKnown);
|
|
232
|
+
add('baseLen', debug.base?.length);
|
|
233
|
+
add('baseNorm', debug.base?.normalizedLength);
|
|
234
|
+
add('baseHash', debug.base?.hash);
|
|
235
|
+
add('elapsed', debug.elapsedMs);
|
|
236
|
+
add('opened', debug.openedMethod);
|
|
237
|
+
return parts.join(', ');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function formatBridgeResultReason(result = {}, fallbackPath = '') {
|
|
241
|
+
const code = result.code || '';
|
|
242
|
+
const path = result.path || fallbackPath || '';
|
|
243
|
+
if (getLocale() !== 'en') {
|
|
244
|
+
return localizeVisibleReason(result.reason || result.error || result.code || tr('unknownReason'));
|
|
245
|
+
}
|
|
246
|
+
if (code === 'missing_tracked_changes') {
|
|
247
|
+
return 'No matching Overleaf tracked-change records were found for this run, so Codex did not undo with text patches.';
|
|
248
|
+
}
|
|
249
|
+
if (code === 'tracked_change_file_open_failed') {
|
|
250
|
+
return path
|
|
251
|
+
? `Could not open ${path} to find this run's tracked changes. Handle them manually in the Overleaf review tools.`
|
|
252
|
+
: 'Could not open the file to find this run\'s tracked changes. Handle them manually in the Overleaf review tools.';
|
|
253
|
+
}
|
|
254
|
+
if (code === 'tracked_change_not_found') {
|
|
255
|
+
return 'No matching tracked changes were found on the Overleaf page for this run.';
|
|
256
|
+
}
|
|
257
|
+
if (code === 'tracked_change_reject_control_not_found') {
|
|
258
|
+
return path
|
|
259
|
+
? `Some tracked changes in ${path} remain, but the matching Reject button was not found. Reject them manually in Overleaf.`
|
|
260
|
+
: 'Some tracked changes remain, but the matching Reject button was not found. Reject them manually in Overleaf.';
|
|
261
|
+
}
|
|
262
|
+
if (code === 'tracked_change_reject_not_confirmed') {
|
|
263
|
+
return 'Codex clicked Reject, but Overleaf still shows this tracked change. Reject it manually in the Overleaf review panel.';
|
|
264
|
+
}
|
|
265
|
+
if (code === 'tracked_change_accept_control_not_found') {
|
|
266
|
+
return path
|
|
267
|
+
? `Some tracked changes in ${path} remain, but the matching Accept button was not found. Accept them manually in Overleaf.`
|
|
268
|
+
: 'Some tracked changes remain, but the matching Accept button was not found. Accept them manually in Overleaf.';
|
|
269
|
+
}
|
|
270
|
+
if (code === 'tracked_change_accept_not_confirmed') {
|
|
271
|
+
return 'Codex clicked Accept, but Overleaf still shows this tracked change. Accept it manually in the Overleaf review panel.';
|
|
272
|
+
}
|
|
273
|
+
if (code === 'tracked_change_editor_undo_open_failed') {
|
|
274
|
+
return path ? `Could not open ${path} for Overleaf native undo.` : 'Could not open the file for Overleaf native undo.';
|
|
275
|
+
}
|
|
276
|
+
if (code === 'tracked_change_editor_undo_current_mismatch') {
|
|
277
|
+
return path
|
|
278
|
+
? `${path} no longer matches this run's written content, so Codex did not use Overleaf native undo.`
|
|
279
|
+
: 'The current content no longer matches this run\'s written content, so Codex did not use Overleaf native undo.';
|
|
280
|
+
}
|
|
281
|
+
if (code === 'editor_undo_control_not_found') {
|
|
282
|
+
return path
|
|
283
|
+
? `Could not find Overleaf's editor Undo button to undo this run in ${path}.`
|
|
284
|
+
: 'Could not find Overleaf\'s editor Undo button to undo this run.';
|
|
285
|
+
}
|
|
286
|
+
if (code === 'editor_undo_no_progress') {
|
|
287
|
+
return path
|
|
288
|
+
? `Codex clicked Overleaf Undo, but ${path} did not change.`
|
|
289
|
+
: 'Codex clicked Overleaf Undo, but the file did not change.';
|
|
290
|
+
}
|
|
291
|
+
if (code === 'editor_undo_max_iterations') {
|
|
292
|
+
return path
|
|
293
|
+
? `${path} did not return to its pre-run content after repeated Overleaf native undo steps. Codex stopped to avoid undoing other edits.`
|
|
294
|
+
: 'The file did not return to its pre-run content after repeated Overleaf native undo steps. Codex stopped to avoid undoing other edits.';
|
|
295
|
+
}
|
|
296
|
+
if (code === 'tracked_change_undo_max_iterations') {
|
|
297
|
+
return path
|
|
298
|
+
? `${path} still has tracked changes left. Codex stopped to avoid rejecting unrelated edits.`
|
|
299
|
+
: 'Tracked changes are still left. Codex stopped to avoid rejecting unrelated edits.';
|
|
300
|
+
}
|
|
301
|
+
if (code === 'tracked_change_undo_verify_open_failed') {
|
|
302
|
+
return path
|
|
303
|
+
? `Could not open ${path} after undo to verify content. Reload Overleaf and check manually.`
|
|
304
|
+
: 'Could not open the file after undo to verify content. Reload Overleaf and check manually.';
|
|
305
|
+
}
|
|
306
|
+
if (code === 'tracked_change_undo_verify_failed') {
|
|
307
|
+
return path
|
|
308
|
+
? `${path} did not return to its pre-run content after rejecting tracked changes. Check this run's changes in the Overleaf review panel.`
|
|
309
|
+
: 'The file did not return to its pre-run content after rejecting tracked changes. Check this run\'s changes in the Overleaf review panel.';
|
|
310
|
+
}
|
|
311
|
+
return localizeVisibleReason(result.reason || result.error || result.code || tr('unknownReason'));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function localizeVisibleReason(reason) {
|
|
315
|
+
const text = String(reason || '').trim();
|
|
316
|
+
if (!text || getLocale() !== 'en') {
|
|
317
|
+
return text;
|
|
318
|
+
}
|
|
319
|
+
let match = text.match(/^(.+?) 在任务开始时没有被 Codex 读到。Codex 没有覆盖它;请刷新项目内容后重试。$/);
|
|
320
|
+
if (match) {
|
|
321
|
+
return `${match[1]} was not read when the task started. Codex did not overwrite it; refresh the project content and retry.`;
|
|
322
|
+
}
|
|
323
|
+
match = text.match(/^(.+?) 在任务执行期间被你或协作者改过,Codex 没有覆盖它。请查看差异后重试。$/);
|
|
324
|
+
if (match) {
|
|
325
|
+
return `${match[1]} changed while Codex was working, so Codex did not overwrite it. Review the diff and retry.`;
|
|
326
|
+
}
|
|
327
|
+
if (text.includes('Codex 要修改的位置已经无法和当前 Overleaf 内容对齐')) {
|
|
328
|
+
return 'The edit location no longer matches the current Overleaf content, so nothing was written. Rerun the task.';
|
|
329
|
+
}
|
|
330
|
+
if (text.includes('Codex 要修改的具体位置已经被你或协作者改过')) {
|
|
331
|
+
return 'The exact edit location was changed by you or a collaborator, so Codex did not overwrite it. Review the diff and retry.';
|
|
332
|
+
}
|
|
333
|
+
const patchMatch = text.match(/^同步本地 Codex workspace 中的局部文件改动((\d+) 处)。$/);
|
|
334
|
+
if (patchMatch) {
|
|
335
|
+
const count = Number(patchMatch[1]) || 0;
|
|
336
|
+
return `Synced ${count} local Codex workspace edit${count === 1 ? '' : 's'}.`;
|
|
337
|
+
}
|
|
338
|
+
if (text === '本地 Codex workspace 删除了这个文件。') {
|
|
339
|
+
return 'Local Codex workspace deleted this file.';
|
|
340
|
+
}
|
|
341
|
+
if (text === '同步本地 Codex workspace 中的文件内容。') {
|
|
342
|
+
return 'Synced file content from the local Codex workspace.';
|
|
343
|
+
}
|
|
344
|
+
if (text === '同步本地 Codex workspace 中的新文件。') {
|
|
345
|
+
return 'Synced a new file from the local Codex workspace.';
|
|
346
|
+
}
|
|
347
|
+
return text;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function formatOperationType(type) {
|
|
351
|
+
const labels = {
|
|
352
|
+
edit: tr('operationEdit'),
|
|
353
|
+
create: tr('operationCreate'),
|
|
354
|
+
rename: tr('operationRename'),
|
|
355
|
+
move: tr('operationMove'),
|
|
356
|
+
delete: tr('operationDelete')
|
|
357
|
+
};
|
|
358
|
+
return labels[type] || type || tr('operationUnknown');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function formatOperationFiles(operations = []) {
|
|
362
|
+
const files = [];
|
|
363
|
+
const seen = new Set();
|
|
364
|
+
for (const operation of operations || []) {
|
|
365
|
+
const path = operation?.path || operation?.from || operation?.to;
|
|
366
|
+
if (!path || seen.has(path)) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
seen.add(path);
|
|
370
|
+
files.push(path);
|
|
371
|
+
}
|
|
372
|
+
return files.length ? files.join(', ') : tr('noneValue');
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
appendApplyResult,
|
|
377
|
+
failureReasonI18nLookup,
|
|
378
|
+
formatApplyResultReason,
|
|
379
|
+
formatBridgeResultReason,
|
|
380
|
+
localizeVisibleReason,
|
|
381
|
+
formatOperationType,
|
|
382
|
+
formatOperationFiles
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
window.CodexOverleafApplyResultFormatters = { create };
|
|
387
|
+
})();
|