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,16 +2,19 @@
|
|
|
2
2
|
if (typeof module === 'object' && module.exports) {
|
|
3
3
|
module.exports = factory({
|
|
4
4
|
getFailureReasons: function getFailureReasonsCjs() { return require('./failureReasons.js'); },
|
|
5
|
-
getI18n: function getI18nCjs() { return require('./i18n.js'); }
|
|
5
|
+
getI18n: function getI18nCjs() { return require('./i18n.js'); },
|
|
6
|
+
RunActivityModel: require('./runActivityModel.js')
|
|
6
7
|
});
|
|
7
8
|
} else {
|
|
8
9
|
root.CodexOverleafModuleRegistry.define('AgentTranscript', [
|
|
9
10
|
'FailureReasons',
|
|
10
|
-
'I18n'
|
|
11
|
-
|
|
11
|
+
'I18n',
|
|
12
|
+
'RunActivityModel'
|
|
13
|
+
], function createAgentTranscript(FailureReasons, I18n, RunActivityModel) {
|
|
12
14
|
return factory({
|
|
13
15
|
getFailureReasons: function getFailureReasonsWindow() { return FailureReasons; },
|
|
14
|
-
getI18n: function getI18nWindow() { return I18n; }
|
|
16
|
+
getI18n: function getI18nWindow() { return I18n; },
|
|
17
|
+
RunActivityModel
|
|
15
18
|
});
|
|
16
19
|
});
|
|
17
20
|
}
|
|
@@ -25,6 +28,227 @@
|
|
|
25
28
|
? deps.getI18n
|
|
26
29
|
: function noI18n() { return null; };
|
|
27
30
|
|
|
31
|
+
// Only explicit product producers may attach these semantic identities.
|
|
32
|
+
const PRODUCT_CONCLUSIONS = {
|
|
33
|
+
"context_compacted": ["Conversation context compacted.", "会话上下文已压缩。"],
|
|
34
|
+
"compact_busy": ["Wait for the current task to finish before compacting context.", "请等待当前任务结束后再压缩上下文。"],
|
|
35
|
+
"compact_unsupported": ["This local Codex connection does not support manual compaction. Update Codex and reload the extension.", "当前本地 Codex 连接不支持手动压缩,请更新 Codex 并重新加载扩展。"],
|
|
36
|
+
"compact_failed": ["Context compaction did not complete. Check Technical Details before retrying.", "上下文压缩未完成,请查看技术详情后再重试。"],
|
|
37
|
+
"full_project_unread": [
|
|
38
|
+
"This run did not continue: the full Overleaf project was not read.",
|
|
39
|
+
"这轮没有继续:没有读到完整的 Overleaf 项目内容。"
|
|
40
|
+
],
|
|
41
|
+
"empty_result": [
|
|
42
|
+
"Codex completed, but it produced no assistant response and no local file changes.",
|
|
43
|
+
"Codex 已完成,但没有产生助手回复,也没有产生本地文件改动。"
|
|
44
|
+
],
|
|
45
|
+
"skill_installer_completed": [
|
|
46
|
+
"Skill installer completed.",
|
|
47
|
+
"Skill installer 已完成。"
|
|
48
|
+
],
|
|
49
|
+
"launch_not_started": [
|
|
50
|
+
"This task did not start: Codex did not run and no files were written.",
|
|
51
|
+
"这轮任务没有开始:Codex 没有运行,也没有写入文件。"
|
|
52
|
+
],
|
|
53
|
+
"cancelled": [
|
|
54
|
+
"This run was cancelled. It did not continue syncing or writing to Overleaf.",
|
|
55
|
+
"这轮已中断,没有继续同步或写入 Overleaf。"
|
|
56
|
+
],
|
|
57
|
+
"reload_interrupted": [
|
|
58
|
+
"The plugin reloaded while this run was still marked in progress. It has been marked interrupted to avoid showing a stale status — run the task again to continue.",
|
|
59
|
+
"插件重新加载时发现这轮任务还标记为处理中。为了避免继续显示过期状态,已把它标记为中断;可以重新运行任务。"
|
|
60
|
+
],
|
|
61
|
+
"ask_inspected": [
|
|
62
|
+
"This run only inspected and explained; no files were written.",
|
|
63
|
+
"这轮只做了检查和说明,没有写入文件。"
|
|
64
|
+
],
|
|
65
|
+
"delete_handled": [
|
|
66
|
+
"Changes were written, and delete items were handled after your confirmation.",
|
|
67
|
+
"已写入修改,并按你的确认处理删除项。"
|
|
68
|
+
],
|
|
69
|
+
"delete_rejected": [
|
|
70
|
+
"Non-delete changes were kept; delete items were not written.",
|
|
71
|
+
"已保留非删除修改;删除项没有写入。"
|
|
72
|
+
],
|
|
73
|
+
"run_complete": [
|
|
74
|
+
"This run is complete.",
|
|
75
|
+
"这轮任务已完成。"
|
|
76
|
+
],
|
|
77
|
+
"withheld_changes": [
|
|
78
|
+
"Some generated changes were blocked.",
|
|
79
|
+
"部分生成的改动已被阻止。"
|
|
80
|
+
],
|
|
81
|
+
"ask_ignored_changes": [
|
|
82
|
+
"Codex finished in Ask mode. Any local file changes were ignored and were not synced to Overleaf.",
|
|
83
|
+
"Codex 已在 Ask 模式完成;本地文件改动已忽略,未同步到 Overleaf。"
|
|
84
|
+
],
|
|
85
|
+
"no_sync_changes": [
|
|
86
|
+
"Codex finished locally. There are no changes to sync back to Overleaf.",
|
|
87
|
+
"Codex 已完成本地处理,没有需要同步回 Overleaf 的改动。"
|
|
88
|
+
],
|
|
89
|
+
"no_approved_changes": [
|
|
90
|
+
"No approved changes were written back to Overleaf.",
|
|
91
|
+
"没有已确认的改动写回 Overleaf。"
|
|
92
|
+
],
|
|
93
|
+
"reviewing_unavailable": [
|
|
94
|
+
"No files were written: Track is enabled, but Codex could not verify Overleaf Reviewing/Track Changes.",
|
|
95
|
+
"这轮没有写入:已开启“留痕”要求,但 Codex 没能确认 Overleaf 正在用 Reviewing/Track Changes。"
|
|
96
|
+
],
|
|
97
|
+
"sensitive_blocked": [
|
|
98
|
+
"This run was blocked before Codex received project context because sensitive content was detected.",
|
|
99
|
+
"检测到敏感内容,本轮已在向 Codex 发送项目上下文前阻止。"
|
|
100
|
+
],
|
|
101
|
+
"synced": [
|
|
102
|
+
"Local Codex changes were synced back to Overleaf.",
|
|
103
|
+
"本地 Codex 改动已同步回 Overleaf。"
|
|
104
|
+
],
|
|
105
|
+
"partial_sync": [
|
|
106
|
+
"Local Codex changes were sent to Overleaf, but some items were skipped.",
|
|
107
|
+
"本地 Codex 改动已尝试同步回 Overleaf,但有部分项目被跳过。"
|
|
108
|
+
],
|
|
109
|
+
"blocked_sync": [
|
|
110
|
+
"No changes were written to Overleaf; every change was blocked before writing.",
|
|
111
|
+
"没有向 Overleaf 写入任何改动;所有改动都在写入前被拦下。"
|
|
112
|
+
],
|
|
113
|
+
"unconfirmed_sync": [
|
|
114
|
+
"Codex tried to write local changes to Overleaf, but the write result did not confirm any applied or skipped entries.",
|
|
115
|
+
"Codex 已尝试把本地改动写入 Overleaf,但写入结果没有确认任何已写入或已跳过条目。"
|
|
116
|
+
],
|
|
117
|
+
"partial_sync_note": [
|
|
118
|
+
"Sync note: local Codex changes were sent to Overleaf, but some items were skipped.",
|
|
119
|
+
"同步提示:本地 Codex 改动已尝试写回 Overleaf,但有部分项目被跳过。"
|
|
120
|
+
],
|
|
121
|
+
"blocked_sync_note": [
|
|
122
|
+
"Sync note: no changes were written to Overleaf; every change was blocked before writing.",
|
|
123
|
+
"同步提示:没有向 Overleaf 写入任何改动;所有改动都在写入前被拦下。"
|
|
124
|
+
],
|
|
125
|
+
"unconfirmed_sync_note": [
|
|
126
|
+
"Writeback note: Codex could not confirm any Overleaf write result entries, so local mirror refresh and auto compile were skipped.",
|
|
127
|
+
"写入提示:Codex 没能确认任何 Overleaf 写入结果条目,因此已跳过本地 mirror 刷新和自动编译。"
|
|
128
|
+
],
|
|
129
|
+
"retry_sync": [
|
|
130
|
+
"Retried the remaining file transfers for this task.",
|
|
131
|
+
"已重试本轮未完成的文件同步。"
|
|
132
|
+
],
|
|
133
|
+
"default_no_write": [
|
|
134
|
+
"This task completed without writing Overleaf files.",
|
|
135
|
+
"这轮任务已完成,没有写入 Overleaf 文件。"
|
|
136
|
+
],
|
|
137
|
+
"default_complete": [
|
|
138
|
+
"This task completed.",
|
|
139
|
+
"这轮任务已完成。"
|
|
140
|
+
],
|
|
141
|
+
"warm_mirror_stale": [
|
|
142
|
+
"This run did not continue: Overleaf did not provide the full project, and the local workspace is not fresh enough.",
|
|
143
|
+
"这轮没有继续:Overleaf 没有提供完整项目内容,本地 workspace 也不够新。"
|
|
144
|
+
]
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const ERROR_CONCLUSIONS = {
|
|
148
|
+
"local_skill_unavailable": {
|
|
149
|
+
"code": "codex_local_skill_unavailable"
|
|
150
|
+
},
|
|
151
|
+
"local_skills_failed": {
|
|
152
|
+
"code": "codex_local_skills_failed"
|
|
153
|
+
},
|
|
154
|
+
"mode_removed": {
|
|
155
|
+
"message": "suggest_mode_removed"
|
|
156
|
+
},
|
|
157
|
+
"mode_write_required": {
|
|
158
|
+
"message": "Mode must be \"ask\" or \"auto\""
|
|
159
|
+
},
|
|
160
|
+
"invalid_json": {
|
|
161
|
+
"message": "Agent returned invalid JSON"
|
|
162
|
+
},
|
|
163
|
+
"invalid_output": {
|
|
164
|
+
"message": "Could not parse Codex output"
|
|
165
|
+
},
|
|
166
|
+
"timeout": {
|
|
167
|
+
"message": "timed out"
|
|
168
|
+
},
|
|
169
|
+
"native_request_timeout": {
|
|
170
|
+
"code": "native_request_timeout"
|
|
171
|
+
},
|
|
172
|
+
"output_limit": {
|
|
173
|
+
"message": "output limit exceeded"
|
|
174
|
+
},
|
|
175
|
+
"context_limit": {
|
|
176
|
+
"code": "codex_context_limit"
|
|
177
|
+
},
|
|
178
|
+
"codex_not_found": {
|
|
179
|
+
"message": "codex_not_found"
|
|
180
|
+
},
|
|
181
|
+
"project_locked": {
|
|
182
|
+
"message": "project_locked"
|
|
183
|
+
},
|
|
184
|
+
"reasoning_unsupported": {
|
|
185
|
+
"message": "unsupported_parameter reasoning.summary"
|
|
186
|
+
},
|
|
187
|
+
"storage_quota": {
|
|
188
|
+
"message": "storage quota"
|
|
189
|
+
},
|
|
190
|
+
"checkpoint": {
|
|
191
|
+
"message": "checkpoint"
|
|
192
|
+
},
|
|
193
|
+
"stale_source": {
|
|
194
|
+
"message": "changed while Codex was working"
|
|
195
|
+
},
|
|
196
|
+
"post_processing": {
|
|
197
|
+
"codexReturned": true
|
|
198
|
+
},
|
|
199
|
+
"ask_failed": {
|
|
200
|
+
"mode": "ask"
|
|
201
|
+
},
|
|
202
|
+
"auto_failed": {
|
|
203
|
+
"mode": "auto"
|
|
204
|
+
},
|
|
205
|
+
"provider_revision_conflict": {
|
|
206
|
+
"message": "provider_revision_conflict"
|
|
207
|
+
},
|
|
208
|
+
"provider_auth_rejected": {
|
|
209
|
+
"message": "provider_auth_rejected"
|
|
210
|
+
},
|
|
211
|
+
"provider_model_not_found": {
|
|
212
|
+
"message": "provider_model_not_found"
|
|
213
|
+
},
|
|
214
|
+
"provider_model_not_configured": {
|
|
215
|
+
"message": "provider_model_not_configured"
|
|
216
|
+
},
|
|
217
|
+
"provider_protocol_unverified": {
|
|
218
|
+
"message": "provider_protocol_unverified"
|
|
219
|
+
},
|
|
220
|
+
"provider_protocol_incompatible": {
|
|
221
|
+
"message": "provider_protocol_incompatible"
|
|
222
|
+
},
|
|
223
|
+
"provider_rate_limited": {
|
|
224
|
+
"message": "provider_rate_limited"
|
|
225
|
+
},
|
|
226
|
+
"provider_quota_exceeded": {
|
|
227
|
+
"message": "provider_quota_exceeded"
|
|
228
|
+
},
|
|
229
|
+
"provider_connection_timeout": {
|
|
230
|
+
"message": "provider_connection_timeout"
|
|
231
|
+
},
|
|
232
|
+
"provider_dns_failed": {
|
|
233
|
+
"message": "provider_dns_failed"
|
|
234
|
+
},
|
|
235
|
+
"provider_tls_failed": {
|
|
236
|
+
"message": "provider_tls_failed"
|
|
237
|
+
},
|
|
238
|
+
"provider_not_found": {
|
|
239
|
+
"message": "provider_not_found"
|
|
240
|
+
},
|
|
241
|
+
"provider_store_corrupt": {
|
|
242
|
+
"message": "provider_store_corrupt"
|
|
243
|
+
},
|
|
244
|
+
"provider_store_unavailable": {
|
|
245
|
+
"message": "provider_store_unavailable"
|
|
246
|
+
},
|
|
247
|
+
"provider_response_invalid": {
|
|
248
|
+
"message": "provider_response_invalid"
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
28
252
|
const TECHNICAL_EVENT_PATTERNS = [
|
|
29
253
|
/^agent\.command\./,
|
|
30
254
|
/^native\.task\./,
|
|
@@ -436,16 +660,11 @@
|
|
|
436
660
|
}
|
|
437
661
|
|
|
438
662
|
function isContextCompactionEvent(event = {}) {
|
|
439
|
-
|
|
440
|
-
const method = String(event.detail?.method || event.title || '');
|
|
441
|
-
const label = `${type} ${method}`;
|
|
442
|
-
return /(compact|compaction|compacted)/i.test(label)
|
|
443
|
-
&& /(context|thread|turn|conversation|codex)/i.test(label);
|
|
663
|
+
return Boolean(deps.RunActivityModel.contextCompactionState(event));
|
|
444
664
|
}
|
|
445
665
|
|
|
446
666
|
function formatContextCompactionCheckpoint(event = {}, locale = 'en') {
|
|
447
|
-
const
|
|
448
|
-
const running = event.status === 'running' || /(started|starting|begin|prepar)/i.test(method);
|
|
667
|
+
const running = deps.RunActivityModel.contextCompactionState(event) === 'running';
|
|
449
668
|
return {
|
|
450
669
|
kind: 'checkpoint',
|
|
451
670
|
visible: true,
|
|
@@ -652,6 +871,14 @@
|
|
|
652
871
|
nextEn: 'Switch between Responses and Chat Completions, or test again with Auto detection.',
|
|
653
872
|
code: 'provider_protocol_incompatible'
|
|
654
873
|
},
|
|
874
|
+
{
|
|
875
|
+
pattern: /provider_quota_exceeded|insufficient_quota|exceeded your current quota|(?:billing|usage|spend(?:ing)?|credit)[_ -]?(?:hard[_ -]?)?limit[_ -]?(?:reached|exceeded)|(?:billing|plan).{0,40}(?:quota|limit|exhausted)|(?:quota|credits?).{0,40}(?:billing|plan|exhausted|insufficient)/i,
|
|
876
|
+
conclusionZh: '模型服务的配额或账单限额已达到。',
|
|
877
|
+
conclusionEn: 'The model provider quota or billing limit was reached.',
|
|
878
|
+
nextZh: '请检查模型服务账户和套餐,或切换模型或模型服务后重试。',
|
|
879
|
+
nextEn: 'Check the provider account and plan, or switch model or provider before retrying.',
|
|
880
|
+
code: 'provider_quota_exceeded'
|
|
881
|
+
},
|
|
655
882
|
{
|
|
656
883
|
pattern: /provider_rate_limited|rate limit was reached/i,
|
|
657
884
|
conclusionZh: '这轮没有完成:第三方模型服务触发了限流。',
|
|
@@ -728,7 +955,7 @@
|
|
|
728
955
|
};
|
|
729
956
|
}
|
|
730
957
|
|
|
731
|
-
function
|
|
958
|
+
function translateRawErrorCopy(message, context = {}) {
|
|
732
959
|
const locale = normalizeLocale(context);
|
|
733
960
|
const text = String(message || '');
|
|
734
961
|
// Each branch returns the user-visible {conclusion, nextStep} pair and,
|
|
@@ -738,6 +965,13 @@
|
|
|
738
965
|
// failure data alongside the human-readable text. The string text is kept
|
|
739
966
|
// verbatim because it has mode-aware nuance (e.g. "No files were written"
|
|
740
967
|
// vs "This run did not start") the catalog's fallback strings don't capture.
|
|
968
|
+
if (context.code === 'native_request_timeout' || /native_request_timeout/i.test(text)) {
|
|
969
|
+
return {
|
|
970
|
+
conclusion: textFor(locale, '本机服务没有响应。', 'The local service did not respond.'),
|
|
971
|
+
nextStep: textFor(locale, '请重试,或打开「诊断」检查本机连接。', 'Retry, or open Diagnostics to check the local connection.'),
|
|
972
|
+
failureCode: 'native_request_timeout'
|
|
973
|
+
};
|
|
974
|
+
}
|
|
741
975
|
if (context.code === 'codex_local_skill_unavailable' || /(?:The )?selected local Codex skill is unavailable/i.test(text)) {
|
|
742
976
|
return {
|
|
743
977
|
conclusion: textFor(locale, '所选 Codex 本地技能不可用或已关闭,本轮没有启动。', 'The selected local Codex skill is unavailable or disabled. This run did not start.'),
|
|
@@ -753,6 +987,13 @@
|
|
|
753
987
|
failureCode: 'codex_local_skills_failed'
|
|
754
988
|
};
|
|
755
989
|
}
|
|
990
|
+
if (getFailureReasonsModule()?.isContextLimitError(text, context.code)) {
|
|
991
|
+
return {
|
|
992
|
+
conclusion: textFor(locale, '本轮已停止:上下文超出模型的容量限制。', 'This run stopped because the model context limit was exceeded.'),
|
|
993
|
+
nextStep: textFor(locale, '请重试任务;如果再次超限,可使用 /compact,或新建会话并减少上下文。', 'Retry the task. If the context limit is reached again, use /compact or start a new conversation with less context.'),
|
|
994
|
+
failureCode: 'codex_context_limit'
|
|
995
|
+
};
|
|
996
|
+
}
|
|
756
997
|
const providerError = translateProviderError(text, locale);
|
|
757
998
|
if (providerError) {
|
|
758
999
|
return providerError;
|
|
@@ -824,7 +1065,7 @@
|
|
|
824
1065
|
failureCode: 'native_protocol_incompatible'
|
|
825
1066
|
};
|
|
826
1067
|
}
|
|
827
|
-
if (/
|
|
1068
|
+
if (/kQuotaBytes|QUOTA_BYTES|QuotaExceededError|storage quota/i.test(text)) {
|
|
828
1069
|
return {
|
|
829
1070
|
conclusion: textFor(locale, 'Codex 结果已经生成,但本地会话记录超出 Chrome 存储配额。', 'Codex produced a result, but local session history exceeded Chrome storage quota.'),
|
|
830
1071
|
nextStep: textFor(locale, '请删除一些旧 session,或刷新扩展后重试;这不是论文分析本身失败。', 'Delete older sessions or reload the extension and retry. The paper analysis itself did not fail.'),
|
|
@@ -871,12 +1112,107 @@
|
|
|
871
1112
|
};
|
|
872
1113
|
}
|
|
873
1114
|
|
|
1115
|
+
function productConclusionText(key, locale = 'en') {
|
|
1116
|
+
if (Object.hasOwn(PRODUCT_CONCLUSIONS, key)) return PRODUCT_CONCLUSIONS[key][locale === 'zh' ? 1 : 0];
|
|
1117
|
+
const error = key.startsWith('error:') && Object.hasOwn(ERROR_CONCLUSIONS, key.slice(6)) && ERROR_CONCLUSIONS[key.slice(6)];
|
|
1118
|
+
return error ? translateRawErrorCopy(error.message || '', { ...error, locale }).conclusion : null;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
function translateRawError(message, context = {}) {
|
|
1122
|
+
const translated = translateRawErrorCopy(message, context), locale = normalizeLocale(context);
|
|
1123
|
+
const key = Object.keys(ERROR_CONCLUSIONS).find(id => productConclusionText(`error:${id}`, locale) === translated.conclusion);
|
|
1124
|
+
return { ...translated, ...(key ? { conclusionKey: `error:${key}` } : {}) };
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// Old Native failures retained the real transport error even when their
|
|
1128
|
+
// product summary used the generic empty-result category. Re-project only
|
|
1129
|
+
// those identified product events; model prose and stored records stay intact.
|
|
1130
|
+
function projectContextLimitEvent(event, locale = 'en') {
|
|
1131
|
+
const failure = event?.failure;
|
|
1132
|
+
if (event?.status !== 'failed' || event.streamRole || event.guidanceId || event.subagent) return event;
|
|
1133
|
+
if (failure?.code === 'codex_context_limit' && failure.stage === 'codex'
|
|
1134
|
+
&& (!event.kind || event.kind === 'activity')
|
|
1135
|
+
&& ['en', 'zh'].some(language => productConclusionText('error:context_limit', language) === event.title)) {
|
|
1136
|
+
return { ...event, title: productConclusionText('error:context_limit', locale) };
|
|
1137
|
+
}
|
|
1138
|
+
if (failure?.code !== 'codex_no_usable_result' || failure.stage !== 'codex'
|
|
1139
|
+
|| !getFailureReasonsModule()?.isContextLimitError(failure.technicalMessage)) return event;
|
|
1140
|
+
const generic = ['ask_failed', 'auto_failed'].flatMap(key => ['en', 'zh'].map(language =>
|
|
1141
|
+
productConclusionText(`error:${key}`, language)));
|
|
1142
|
+
const translated = translateRawError(failure.technicalMessage, { locale });
|
|
1143
|
+
const projectedFailure = { ...failure, code: translated.failureCode,
|
|
1144
|
+
userMessage: translated.conclusion, nextAction: translated.nextStep };
|
|
1145
|
+
if ((!event.kind || event.kind === 'activity') && generic.includes(event.title)) {
|
|
1146
|
+
return { ...event, title: translated.conclusion, failure: projectedFailure };
|
|
1147
|
+
}
|
|
1148
|
+
const structured = event.detailStructured, source = structured?.conclusionSource;
|
|
1149
|
+
if (event.kind !== 'report' || source?.origin !== 'product'
|
|
1150
|
+
|| !['error:ask_failed', 'error:auto_failed'].includes(source.key)
|
|
1151
|
+
|| !generic.includes(structured.conclusion)) return event;
|
|
1152
|
+
const oldNext = ['en', 'zh'].map(language => translateRawError('', { locale: language }).nextStep);
|
|
1153
|
+
return { ...event, failure: projectedFailure, detailStructured: { ...structured,
|
|
1154
|
+
conclusion: translated.conclusion, conclusionSource: { origin: 'product', key: translated.conclusionKey },
|
|
1155
|
+
meta: (structured.meta || []).map(row => row.key === 'nextStep' && oldNext.includes(row.value)
|
|
1156
|
+
? { ...row, value: translated.nextStep } : row) } };
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
function normalizeConclusionSource(source) {
|
|
1160
|
+
if (source?.origin !== 'product' || typeof source.key !== 'string') return null;
|
|
1161
|
+
if (productConclusionText(source.key) !== null) return { origin: 'product', key: source.key };
|
|
1162
|
+
if (source.key !== 'writeback' || !['synced', 'partial_sync', 'blocked_sync', 'unconfirmed_sync'].includes(source.outcome)) return null;
|
|
1163
|
+
return { origin: 'product', key: 'writeback', outcome: source.outcome,
|
|
1164
|
+
prefixLength: Number.isSafeInteger(source.prefixLength) && source.prefixLength >= 0 ? source.prefixLength : -1,
|
|
1165
|
+
prefixKey: source.prefixKey === 'retry_sync' ? 'retry_sync' : '',
|
|
1166
|
+
hasCompile: source.hasCompile === true,
|
|
1167
|
+
compileStatus: typeof source.compileStatus === 'string' ? source.compileStatus : '',
|
|
1168
|
+
compileReason: typeof source.compileReason === 'string' ? source.compileReason : '',
|
|
1169
|
+
errorCount: Number.isSafeInteger(source.errorCount) && source.errorCount >= 0 ? source.errorCount : 0,
|
|
1170
|
+
errors: Array.isArray(source.errors) ? source.errors.slice(0, 3).filter(value => typeof value === 'string') : [],
|
|
1171
|
+
warningCount: Number.isSafeInteger(source.warningCount) && source.warningCount >= 0 ? source.warningCount : 0 };
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
function projectProductConclusion(source, locale = 'en', localizeCompileReason = value => value, raw = '') {
|
|
1175
|
+
const identity = normalizeConclusionSource(source);
|
|
1176
|
+
if (!identity) return null;
|
|
1177
|
+
if (identity.key !== 'writeback') return productConclusionText(identity.key, locale);
|
|
1178
|
+
if (identity.prefixLength < 0 || identity.prefixLength > raw.length) return null;
|
|
1179
|
+
const originalPrefix = raw.slice(0, identity.prefixLength);
|
|
1180
|
+
if (identity.prefixKey && !['en', 'zh'].some(language => productConclusionText(identity.prefixKey, language) === originalPrefix)) return null;
|
|
1181
|
+
const compose = (language, projectReason) => {
|
|
1182
|
+
const tx = (en, zh) => language === 'zh' ? zh : en;
|
|
1183
|
+
const prefix = projectReason && identity.prefixKey ? productConclusionText(identity.prefixKey, language) : originalPrefix;
|
|
1184
|
+
const note = productConclusionText(identity.outcome + (prefix && identity.outcome !== 'synced' ? '_note' : ''), language);
|
|
1185
|
+
const conclusion = prefix ? [prefix, identity.outcome === 'synced' ? '' : note].filter(Boolean).join('\n\n') : note;
|
|
1186
|
+
const { compileStatus: status, errors, errorCount, warningCount: warnings } = identity;
|
|
1187
|
+
if (!identity.hasCompile) return conclusion;
|
|
1188
|
+
const reason = projectReason ? localizeCompileReason(identity.compileReason) : identity.compileReason;
|
|
1189
|
+
const summary = errorCount
|
|
1190
|
+
? tx(`Post-write compile check: ${errorCount} remaining error(s): ${errors.slice(0, 3).join('; ')}`,
|
|
1191
|
+
`写后编译检查:仍有 ${errorCount} 个错误:${errors.slice(0, 3).join(';')}`)
|
|
1192
|
+
: status === 'success' ? (warnings
|
|
1193
|
+
? tx(`Post-write compile check succeeded with ${warnings} warning(s).`, `写后编译检查已通过,但仍有 ${warnings} 个警告。`)
|
|
1194
|
+
: tx('Post-write compile check succeeded with no reported errors.', '写后编译检查已通过,未发现错误。'))
|
|
1195
|
+
: status === 'triggered' ? (warnings
|
|
1196
|
+
? tx(`Post-write compile was triggered; latest log shows ${warnings} warning(s).`, `已触发写后编译;最新日志显示 ${warnings} 个警告。`)
|
|
1197
|
+
: tx('Post-write compile was triggered; Overleaf may still be updating the result.', '已触发写后编译;Overleaf 可能仍在更新结果。'))
|
|
1198
|
+
: status === 'unconfirmed' ? getI18nModule().t(language, 'runCompileUnconfirmed')
|
|
1199
|
+
: status === 'failed' ? tx(`Post-write compile check failed: ${reason || 'unknown reason'}`,
|
|
1200
|
+
`写后编译检查失败:${reason || '未知原因'}`)
|
|
1201
|
+
: tx(`Post-write compile finished with status: ${status || 'unknown'}.`, `写后编译完成,状态:${status || '未知'}。`);
|
|
1202
|
+
return [conclusion, summary].filter(Boolean).join('\n');
|
|
1203
|
+
};
|
|
1204
|
+
// A compacted or changed raw answer must never be reconstructed from metadata.
|
|
1205
|
+
if (!['en', 'zh'].some(language => compose(language, false) === raw)) return null;
|
|
1206
|
+
return compose(locale, true);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
874
1209
|
function buildHumanCompletionReport(input = {}) {
|
|
875
1210
|
const locale = normalizeLocale(input);
|
|
876
1211
|
const applyResults = normalizeApplyResults(input.applyResults);
|
|
877
1212
|
const appliedCount = countApplyResultEntries(applyResults, 'applied');
|
|
878
1213
|
const skippedCount = countApplyResultEntries(applyResults, 'skipped');
|
|
879
|
-
const translatedError = input.errorMessage ? translateRawError(input.errorMessage, { mode: input.mode, locale
|
|
1214
|
+
const translatedError = input.errorMessage ? translateRawError(input.errorMessage, { mode: input.mode, locale, code: input.failure?.code,
|
|
1215
|
+
codexReturned: input.conclusionKey === 'error:post_processing' }) : null;
|
|
880
1216
|
const userReport = normalizeUserReport(input.userReport);
|
|
881
1217
|
const report = userReport || buildFallbackReport(input, {
|
|
882
1218
|
appliedCount,
|
|
@@ -928,6 +1264,16 @@
|
|
|
928
1264
|
return report.text;
|
|
929
1265
|
}
|
|
930
1266
|
|
|
1267
|
+
function completionConclusionText(report) {
|
|
1268
|
+
const source = report.conclusionSource;
|
|
1269
|
+
// The new blocked composite preserves its exact model prefix. Keep the
|
|
1270
|
+
// historical formatter for every other report shape.
|
|
1271
|
+
if (source?.key === 'writeback' && source.outcome === 'blocked_sync'
|
|
1272
|
+
&& typeof report.conclusion === 'string' && ['en', 'zh'].some(locale =>
|
|
1273
|
+
projectProductConclusion(source, locale, undefined, report.conclusion) === report.conclusion)) return report.conclusion;
|
|
1274
|
+
return cleanVisibleMarkdownText(report.conclusion || '');
|
|
1275
|
+
}
|
|
1276
|
+
|
|
931
1277
|
/**
|
|
932
1278
|
* Splits the human report into a conclusion (the human-language outcome),
|
|
933
1279
|
* a body of list-style content sections (checked / findings / planned /
|
|
@@ -938,7 +1284,7 @@
|
|
|
938
1284
|
* shape for transcripts, storage fallback, and existing assertions.
|
|
939
1285
|
*/
|
|
940
1286
|
function buildStructuredHumanReport(report = {}, locale = 'en') {
|
|
941
|
-
const conclusion =
|
|
1287
|
+
const conclusion = completionConclusionText(report);
|
|
942
1288
|
|
|
943
1289
|
const bodySections = [];
|
|
944
1290
|
addListSection(bodySections, textFor(locale, '检查范围', 'Checked'), report.checked, locale);
|
|
@@ -982,12 +1328,13 @@
|
|
|
982
1328
|
}
|
|
983
1329
|
|
|
984
1330
|
if (report.saveState) meta.push({ key: 'saveState', label: textFor(locale, '保存', 'Save'), value: report.saveState });
|
|
985
|
-
return { conclusion, body: bodySections.join('\n\n'), meta
|
|
1331
|
+
return { conclusion, body: bodySections.join('\n\n'), meta,
|
|
1332
|
+
...(normalizeConclusionSource(report.conclusionSource) ? { conclusionSource: normalizeConclusionSource(report.conclusionSource) } : {}) };
|
|
986
1333
|
}
|
|
987
1334
|
|
|
988
1335
|
function formatHumanReport(report = {}, locale = 'en') {
|
|
989
1336
|
const sections = [];
|
|
990
|
-
const conclusion =
|
|
1337
|
+
const conclusion = completionConclusionText(report);
|
|
991
1338
|
if (conclusion) {
|
|
992
1339
|
sections.push(textFor(locale, `结论:${conclusion}`, `Conclusion: ${conclusion}`));
|
|
993
1340
|
}
|
|
@@ -1028,8 +1375,13 @@
|
|
|
1028
1375
|
? textFor(locale, '这轮任务已完成,没有写入 Overleaf 文件。', 'This task completed without writing Overleaf files.')
|
|
1029
1376
|
: textFor(locale, '这轮任务已完成。', 'This task completed.'));
|
|
1030
1377
|
|
|
1378
|
+
const conclusionSource = counts.translatedError?.conclusionKey
|
|
1379
|
+
? { origin: 'product', key: counts.translatedError.conclusionKey }
|
|
1380
|
+
: input.conclusionKey ? { origin: 'product', key: input.conclusionKey }
|
|
1381
|
+
: input.conclusionSource || (!input.conclusion && !input.notes
|
|
1382
|
+
? { origin: 'product', key: noWrites ? 'default_no_write' : 'default_complete' } : null);
|
|
1031
1383
|
return {
|
|
1032
|
-
conclusion,
|
|
1384
|
+
conclusion, conclusionSource: normalizeConclusionSource(conclusionSource),
|
|
1033
1385
|
checked: normalizeStringList(input.checked || input.userReport?.checked),
|
|
1034
1386
|
findings: normalizeStringList(input.findings),
|
|
1035
1387
|
plannedChanges: counts.appliedCount ? [] : operations.map(operation => formatOperationLine(operation, locale)),
|
|
@@ -1756,6 +2108,8 @@
|
|
|
1756
2108
|
|
|
1757
2109
|
return {
|
|
1758
2110
|
buildHumanCompletionReport,
|
|
2111
|
+
projectProductConclusion,
|
|
2112
|
+
projectContextLimitEvent,
|
|
1759
2113
|
buildStructuredHumanReport,
|
|
1760
2114
|
formatFallbackFinalReport,
|
|
1761
2115
|
formatFailureBlock,
|
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
createdAt: redactSecretLikeText(stringField(input.createdAt)) || now,
|
|
33
33
|
completedAt: '',
|
|
34
34
|
mode: redactSecretLikeText(stringField(input.mode)),
|
|
35
|
+
requireReviewing: typeof input.requireReviewing === 'boolean' ? input.requireReviewing : undefined,
|
|
36
|
+
trackingDecision: ['continue', 'disable'].includes(input.trackingDecision) ? input.trackingDecision : '',
|
|
35
37
|
providerId: redactSecretLikeText(stringField(input.providerId)) || 'builtin',
|
|
36
38
|
providerName: redactSecretLikeText(stringField(input.providerName)),
|
|
37
39
|
providerRevision: finiteNumber(input.providerRevision) || 0,
|
|
@@ -259,6 +261,7 @@
|
|
|
259
261
|
}
|
|
260
262
|
|
|
261
263
|
function summarizeMirror(mirror = {}) {
|
|
264
|
+
mirror = mirror ?? { status: 'unavailable' };
|
|
262
265
|
const files = Array.isArray(mirror.files) ? mirror.files : [];
|
|
263
266
|
const skippedFiles = Array.isArray(mirror.skippedFiles) ? mirror.skippedFiles : [];
|
|
264
267
|
return removeEmptySummaryFields({
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
const MIN_NATIVE_VERSION = '1.0.0';
|
|
13
13
|
const MIN_COMPATIBLE_NATIVE_VERSION = '1.0.0';
|
|
14
14
|
const MIN_COMPATIBLE_EXTENSION_VERSION = '1.0.0';
|
|
15
|
-
const BUILD_TARGET_VERSION = '2.5
|
|
15
|
+
const BUILD_TARGET_VERSION = '2.6.5';
|
|
16
16
|
const DEFAULT_CHROME_EXTENSION_ID = 'illdpneeeopfffmiepaejglgmhpmdhdc';
|
|
17
17
|
const REQUIRED_CAPABILITIES = Object.freeze([
|
|
18
18
|
'bridgePing',
|