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
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
'codex.providers.clear-secret',
|
|
51
51
|
'codex.providers.delete',
|
|
52
52
|
'task.run',
|
|
53
|
-
'task.confirm',
|
|
54
53
|
'mirror.sync',
|
|
55
54
|
'mirror.patchFiles',
|
|
56
55
|
'mirror.confirmWriteback',
|
|
@@ -183,6 +182,7 @@
|
|
|
183
182
|
callPageBridge,
|
|
184
183
|
getCurrentProjectId,
|
|
185
184
|
getCurrentProjectReferenceFiles,
|
|
185
|
+
getCurrentProjectMathSources,
|
|
186
186
|
showPluginToast,
|
|
187
187
|
recordRenderingDiagnostic: detail => appendTechnicalEvent({ type: 'rendering.diagnostic', detail })
|
|
188
188
|
});
|
|
@@ -398,8 +398,24 @@
|
|
|
398
398
|
openStorageSettings
|
|
399
399
|
} = panelMaintenance;
|
|
400
400
|
|
|
401
|
+
const sessionForkController = Modules.SessionForkController.create({
|
|
402
|
+
SessionState: Modules.SessionState,
|
|
403
|
+
getState: () => state,
|
|
404
|
+
setState: next => { state = next; },
|
|
405
|
+
sendBackgroundNative,
|
|
406
|
+
saveState,
|
|
407
|
+
applyStateToPanel,
|
|
408
|
+
showPluginToast,
|
|
409
|
+
tr
|
|
410
|
+
});
|
|
411
|
+
const runResultActions = Modules.RunResultActions.create({
|
|
412
|
+
tr,
|
|
413
|
+
getLocale,
|
|
414
|
+
forkRunFromNode: sessionForkController.forkRunFromNode
|
|
415
|
+
});
|
|
401
416
|
const runTimelineView = Modules.RunTimelineView.create({
|
|
402
417
|
RunGuidanceView: Modules.RunGuidanceView,
|
|
418
|
+
RunResultActions: runResultActions,
|
|
403
419
|
tr,
|
|
404
420
|
tx,
|
|
405
421
|
getLocale,
|
|
@@ -516,6 +532,7 @@
|
|
|
516
532
|
// lives in writebackOrchestrator.js. Every dep below is either a hoisted
|
|
517
533
|
// function declaration, an already-initialized const above, or a lazy
|
|
518
534
|
// accessor thunk — safe in the top-of-init() wiring zone.
|
|
535
|
+
const assetTransferBroker = Modules.AssetTransferBroker.create({ callPageBridge, sendBackgroundNative });
|
|
519
536
|
const writebackOrchestrator = Modules.WritebackOrchestrator.create({
|
|
520
537
|
tr,
|
|
521
538
|
tx,
|
|
@@ -526,7 +543,6 @@
|
|
|
526
543
|
appendOperationsPreview,
|
|
527
544
|
appendPartialWritebackWarning,
|
|
528
545
|
appendApplyResult,
|
|
529
|
-
renderDiffReview,
|
|
530
546
|
renderReadOnlyDiffReview,
|
|
531
547
|
showPluginConfirm,
|
|
532
548
|
callPageBridge,
|
|
@@ -556,6 +572,7 @@
|
|
|
556
572
|
confirmBinaryOperations,
|
|
557
573
|
filterSyncChangesByOperations,
|
|
558
574
|
writebackController,
|
|
575
|
+
assetTransferBroker,
|
|
559
576
|
writebackSettlement: WritebackSettlement,
|
|
560
577
|
compileAdapter: Modules.CompileAdapter,
|
|
561
578
|
RUN_SNAPSHOT_ZIP_TIMEOUT_MS,
|
|
@@ -1512,9 +1529,6 @@
|
|
|
1512
1529
|
if (mode === 'ask') {
|
|
1513
1530
|
return 'Ask';
|
|
1514
1531
|
}
|
|
1515
|
-
if (mode === 'confirm') {
|
|
1516
|
-
return 'Confirm';
|
|
1517
|
-
}
|
|
1518
1532
|
if (mode === 'auto') {
|
|
1519
1533
|
return 'Auto';
|
|
1520
1534
|
}
|
|
@@ -1877,7 +1891,7 @@
|
|
|
1877
1891
|
if (!useExistingMirror) {
|
|
1878
1892
|
appendLog(formatProjectSnapshotUserLog(project));
|
|
1879
1893
|
}
|
|
1880
|
-
|
|
1894
|
+
persistCurrentProjectReferenceFiles(project);
|
|
1881
1895
|
const snapshotWarnings = useExistingMirror
|
|
1882
1896
|
? { blocking: [], nonBlocking: [] }
|
|
1883
1897
|
: getProjectSnapshotWarnings(project);
|
|
@@ -1924,7 +1938,7 @@
|
|
|
1924
1938
|
skippedFiles: [],
|
|
1925
1939
|
blockedFiles: snapshotWarnings.blocking.map(reason => ({ path: 'project', reason }))
|
|
1926
1940
|
});
|
|
1927
|
-
finishRunView(tx('Blocked: full project was not read', '已阻止:没有读到完整项目'), 'failed');
|
|
1941
|
+
await finishRunView(tx('Blocked: full project was not read', '已阻止:没有读到完整项目'), 'failed');
|
|
1928
1942
|
return;
|
|
1929
1943
|
}
|
|
1930
1944
|
|
|
@@ -2011,7 +2025,7 @@
|
|
|
2011
2025
|
reason: finding.detectorId || 'sensitive'
|
|
2012
2026
|
}))
|
|
2013
2027
|
});
|
|
2014
|
-
finishRunView(tx('Blocked: sensitive content review required', '已阻止:需要处理敏感内容'), 'failed');
|
|
2028
|
+
await finishRunView(tx('Blocked: sensitive content review required', '已阻止:需要处理敏感内容'), 'failed');
|
|
2015
2029
|
return;
|
|
2016
2030
|
}
|
|
2017
2031
|
if (sensitiveFindings.findings.length) {
|
|
@@ -2049,7 +2063,7 @@
|
|
|
2049
2063
|
return;
|
|
2050
2064
|
}
|
|
2051
2065
|
project = staleRetry.project;
|
|
2052
|
-
|
|
2066
|
+
persistCurrentProjectReferenceFiles(project);
|
|
2053
2067
|
useExistingMirror = false;
|
|
2054
2068
|
fileOverlays = null;
|
|
2055
2069
|
otWarmStart = false;
|
|
@@ -2104,7 +2118,7 @@
|
|
|
2104
2118
|
} else {
|
|
2105
2119
|
appendRunEvent({ title: tx('Cancelled: user chose not to create a new thread.', '已取消:用户选择不新建线程。'), status: 'rejected' });
|
|
2106
2120
|
await finalizeAuditRecord(runAuditDraft, { resultStatus: 'rejected' });
|
|
2107
|
-
finishRunView(tx('Cancelled', '已取消'), 'rejected');
|
|
2121
|
+
await finishRunView(tx('Cancelled', '已取消'), 'rejected');
|
|
2108
2122
|
return;
|
|
2109
2123
|
}
|
|
2110
2124
|
}
|
|
@@ -2112,7 +2126,7 @@
|
|
|
2112
2126
|
if (!response.ok) {
|
|
2113
2127
|
if (runCancellationRequested || isRunCancellationError(response.error)) {
|
|
2114
2128
|
appendRunCancelledReport();
|
|
2115
|
-
finishRunView(tx('Cancelled', '已中断'), 'rejected');
|
|
2129
|
+
await finishRunView(tx('Cancelled', '已中断'), 'rejected');
|
|
2116
2130
|
void finalizeAuditRecord(runAuditDraft, { resultStatus: 'cancelled' });
|
|
2117
2131
|
return;
|
|
2118
2132
|
}
|
|
@@ -2199,7 +2213,7 @@
|
|
|
2199
2213
|
sensitiveFindings: sensitiveFindings.findings,
|
|
2200
2214
|
blockedFiles: [{ path: 'codex.run', reason: response.error?.code || response.error?.message || 'native_error' }]
|
|
2201
2215
|
});
|
|
2202
|
-
finishRunView(response.error?.code === 'project_locked'
|
|
2216
|
+
await finishRunView(response.error?.code === 'project_locked'
|
|
2203
2217
|
? tx('Codex task already running', 'Codex 任务正在运行')
|
|
2204
2218
|
: tx('Local Codex error', '本地 Codex 错误'), 'failed');
|
|
2205
2219
|
return;
|
|
@@ -2249,7 +2263,7 @@
|
|
|
2249
2263
|
sensitiveFindings: sensitiveFindings.findings,
|
|
2250
2264
|
blockedFiles: [{ path: 'codex.run', reason: 'codex_no_usable_result' }]
|
|
2251
2265
|
});
|
|
2252
|
-
finishRunView(tx('Local Codex returned nothing usable', '本地 Codex 没有返回可用结果'), 'failed');
|
|
2266
|
+
await finishRunView(tx('Local Codex returned nothing usable', '本地 Codex 没有返回可用结果'), 'failed');
|
|
2253
2267
|
return;
|
|
2254
2268
|
}
|
|
2255
2269
|
const writebackProject = useExistingMirror
|
|
@@ -2272,7 +2286,7 @@
|
|
|
2272
2286
|
resultStatus: syncOutcome.hasSkippedOperations ? 'completed_with_skips' : 'completed'
|
|
2273
2287
|
});
|
|
2274
2288
|
|
|
2275
|
-
finishRunView(
|
|
2289
|
+
await finishRunView(
|
|
2276
2290
|
syncOutcome.hasSkippedOperations ? tx('Sync completed with skipped items', '同步完成但有跳过项') : tx('Sync completed', '同步完成'),
|
|
2277
2291
|
syncOutcome.hasSkippedOperations ? 'failed' : 'completed'
|
|
2278
2292
|
);
|
|
@@ -2366,7 +2380,7 @@
|
|
|
2366
2380
|
} catch (error) {
|
|
2367
2381
|
if (runCancellationRequested || isRunCancellationError(error)) {
|
|
2368
2382
|
appendRunCancelledReport();
|
|
2369
|
-
finishRunView(tx('Cancelled', '已中断'), 'rejected');
|
|
2383
|
+
await finishRunView(tx('Cancelled', '已中断'), 'rejected');
|
|
2370
2384
|
void finalizeAuditRecord(runAuditDraft, { resultStatus: 'cancelled' });
|
|
2371
2385
|
return;
|
|
2372
2386
|
}
|
|
@@ -2416,7 +2430,7 @@
|
|
|
2416
2430
|
resultStatus: 'failed',
|
|
2417
2431
|
blockedFiles: [{ path: 'task', reason: error.message }]
|
|
2418
2432
|
});
|
|
2419
|
-
finishRunView(tx('Task failed', '任务失败'), 'failed');
|
|
2433
|
+
await finishRunView(tx('Task failed', '任务失败'), 'failed');
|
|
2420
2434
|
} finally {
|
|
2421
2435
|
const settledView = currentRunView;
|
|
2422
2436
|
const settledRecord = settledView ? findRunRecord(settledView.recordId, settledView.sessionId) : null;
|
|
@@ -2489,7 +2503,7 @@
|
|
|
2489
2503
|
if (runCancellationRequested || isRunCancellationError(response.error)) {
|
|
2490
2504
|
appendRunCancelledReport();
|
|
2491
2505
|
await finalizeAuditRecord(runAuditDraft, { resultStatus: 'cancelled' });
|
|
2492
|
-
finishRunView(tx('Cancelled', '已中断'), 'rejected');
|
|
2506
|
+
await finishRunView(tx('Cancelled', '已中断'), 'rejected');
|
|
2493
2507
|
return;
|
|
2494
2508
|
}
|
|
2495
2509
|
const translated = translateRawError(response.error.message, { mode: submittedMode, locale: getLocale() });
|
|
@@ -2522,7 +2536,7 @@
|
|
|
2522
2536
|
resultStatus: 'failed',
|
|
2523
2537
|
blockedFiles: [{ path: 'skill-installer', reason: response.error?.code || response.error?.message || 'native_error' }]
|
|
2524
2538
|
});
|
|
2525
|
-
finishRunView(tx('Skill installer failed', 'Skill installer 失败'), 'failed');
|
|
2539
|
+
await finishRunView(tx('Skill installer failed', 'Skill installer 失败'), 'failed');
|
|
2526
2540
|
return;
|
|
2527
2541
|
}
|
|
2528
2542
|
|
|
@@ -2536,7 +2550,7 @@
|
|
|
2536
2550
|
mode: submittedMode
|
|
2537
2551
|
});
|
|
2538
2552
|
await finalizeAuditRecord(runAuditDraft, { resultStatus: 'completed' });
|
|
2539
|
-
finishRunView(tx('Skill installer completed', 'Skill installer 已完成'), 'completed');
|
|
2553
|
+
await finishRunView(tx('Skill installer completed', 'Skill installer 已完成'), 'completed');
|
|
2540
2554
|
|
|
2541
2555
|
const runSessionForHistory = findSessionById(runSessionId) || getActiveSession(state);
|
|
2542
2556
|
const rawAssistantMessage = assistantMessage;
|
|
@@ -2659,7 +2673,7 @@
|
|
|
2659
2673
|
const finishTitle = requireReviewing
|
|
2660
2674
|
? tx('Not started: could not enable Track Changes', '未开始:无法开启留痕')
|
|
2661
2675
|
: tx('Not started: could not switch to Editing', '未开始:无法切换到 Editing');
|
|
2662
|
-
finishRunView(finishTitle, 'failed');
|
|
2676
|
+
await finishRunView(finishTitle, 'failed');
|
|
2663
2677
|
return {
|
|
2664
2678
|
ok: false,
|
|
2665
2679
|
reason,
|
|
@@ -3857,10 +3871,6 @@
|
|
|
3857
3871
|
return diffReviewPanel.createDiffReviewElement(syncChanges, options);
|
|
3858
3872
|
}
|
|
3859
3873
|
|
|
3860
|
-
function renderDiffReview(syncChanges) {
|
|
3861
|
-
return diffReviewPanel.renderDiffReview(syncChanges);
|
|
3862
|
-
}
|
|
3863
|
-
|
|
3864
3874
|
function renderReadOnlyDiffReview(syncChanges, title = tr('diffWrittenChangesTitle')) {
|
|
3865
3875
|
return diffReviewPanel.renderReadOnlyDiffReview(syncChanges, title);
|
|
3866
3876
|
}
|
|
@@ -4623,80 +4633,11 @@
|
|
|
4623
4633
|
mode,
|
|
4624
4634
|
operations: [],
|
|
4625
4635
|
applyResults: [],
|
|
4626
|
-
nextStep: tx('Continue the conversation, or switch to
|
|
4636
|
+
nextStep: tx('Continue the conversation, or switch to Auto to let Codex edit files.', '可以继续追问,或切换到自动写入后让 Codex 修改文件。')
|
|
4627
4637
|
});
|
|
4628
4638
|
return { status: tr('modeAsk'), summaryLine };
|
|
4629
4639
|
}
|
|
4630
4640
|
|
|
4631
|
-
if (result.status === 'requires_task_confirmation') {
|
|
4632
|
-
appendPlannedChangeSummary(result.summary, tx('Preparing changes', '准备修改'));
|
|
4633
|
-
const approved = await showPluginConfirm({
|
|
4634
|
-
title: tx('Apply these changes?', '应用这些修改?'),
|
|
4635
|
-
message: formatSummary(tx('Change Summary', '修改摘要'), result.summary),
|
|
4636
|
-
confirmLabel: tx('Apply changes', '应用修改'),
|
|
4637
|
-
cancelLabel: tr('confirmDefaultCancel')
|
|
4638
|
-
});
|
|
4639
|
-
if (!approved) {
|
|
4640
|
-
appendLog(tx('Cancelled: Codex did not write any files.', '已取消:Codex 没有写入任何文件。'));
|
|
4641
|
-
const summaryLine = appendChangeSummary({ notes, summary: result.summary, status: 'rejected' });
|
|
4642
|
-
appendCompletionReport({
|
|
4643
|
-
conclusion: tx('You cancelled this change. Codex did not write files.', '你取消了这轮修改,Codex 没有写入文件。'),
|
|
4644
|
-
status: 'rejected',
|
|
4645
|
-
notes,
|
|
4646
|
-
summary: result.summary,
|
|
4647
|
-
userReport: result.userReport,
|
|
4648
|
-
mode,
|
|
4649
|
-
operations: [],
|
|
4650
|
-
applyResults: [],
|
|
4651
|
-
nextStep: tx('Adjust the task and run again, or switch to Ask first so Codex can explain the plan.', '可以调整任务描述后重新运行,或切到只问不改先让 Codex 解释方案。')
|
|
4652
|
-
});
|
|
4653
|
-
return { status: 'rejected', summaryLine };
|
|
4654
|
-
}
|
|
4655
|
-
const confirmed = result.planId
|
|
4656
|
-
? await sendNative({ method: 'task.confirm', params: { planId: result.planId } })
|
|
4657
|
-
: { ok: true, result: { operations: result.operations || [] } };
|
|
4658
|
-
if (!confirmed.ok) {
|
|
4659
|
-
appendLog(`Confirm failed: ${confirmed.error.message}`);
|
|
4660
|
-
const summaryLine = appendChangeSummary({ notes, operations: [], status: 'confirm failed' });
|
|
4661
|
-
appendCompletionReport({
|
|
4662
|
-
conclusion: tx('No writable changes were returned after confirmation.', '确认后没有拿到可写入的修改。'),
|
|
4663
|
-
status: 'confirm failed',
|
|
4664
|
-
notes,
|
|
4665
|
-
userReport: result.userReport,
|
|
4666
|
-
mode,
|
|
4667
|
-
operations: [],
|
|
4668
|
-
applyResults: [],
|
|
4669
|
-
nextStep: confirmed.error.message
|
|
4670
|
-
});
|
|
4671
|
-
return { status: 'confirm failed', summaryLine };
|
|
4672
|
-
}
|
|
4673
|
-
const operations = confirmed.result.operations || [];
|
|
4674
|
-
appendOperationsPreview(operations, tx('Confirmed; preparing to write', '用户已确认,准备写入'));
|
|
4675
|
-
const applied = await applyTaskOperations(project, operations, { allowHighRisk: true });
|
|
4676
|
-
appendApplyResult(applied);
|
|
4677
|
-
recordUndoFromApply(project, applied);
|
|
4678
|
-
const summaryLine = appendChangeSummary({
|
|
4679
|
-
notes,
|
|
4680
|
-
operations,
|
|
4681
|
-
applyResults: [applied],
|
|
4682
|
-
status: 'confirmed and applied'
|
|
4683
|
-
});
|
|
4684
|
-
appendCompletionReport({
|
|
4685
|
-
conclusion: notes || tx('Changes were written after your confirmation.', '已按你的确认写入修改。'),
|
|
4686
|
-
status: 'confirmed and applied',
|
|
4687
|
-
notes,
|
|
4688
|
-
userReport: result.userReport,
|
|
4689
|
-
mode,
|
|
4690
|
-
operations,
|
|
4691
|
-
applyResults: [applied]
|
|
4692
|
-
});
|
|
4693
|
-
return {
|
|
4694
|
-
status: 'confirmed and applied',
|
|
4695
|
-
summaryLine,
|
|
4696
|
-
hasSkippedOperations: hasSkippedApplyOperations([applied])
|
|
4697
|
-
};
|
|
4698
|
-
}
|
|
4699
|
-
|
|
4700
4641
|
if (result.status === 'delete_plan_required') {
|
|
4701
4642
|
const operations = result.operations || [];
|
|
4702
4643
|
const applyResults = [];
|
|
@@ -4769,7 +4710,7 @@
|
|
|
4769
4710
|
|
|
4770
4711
|
const operations = result.operations || [];
|
|
4771
4712
|
appendOperationsPreview(operations, tx('Preparing to write', '准备写入'));
|
|
4772
|
-
const applied = await applyTaskOperations(project, operations
|
|
4713
|
+
const applied = await applyTaskOperations(project, operations);
|
|
4773
4714
|
appendApplyResult(applied);
|
|
4774
4715
|
recordUndoFromApply(project, applied);
|
|
4775
4716
|
appendLog(mode === 'auto' ? tx('Auto write task completed.', '自动写入任务完成。') : tx('Task completed.', '任务完成。'));
|
|
@@ -5089,9 +5030,6 @@
|
|
|
5089
5030
|
if (mode === 'ask') {
|
|
5090
5031
|
return tr('modeAsk');
|
|
5091
5032
|
}
|
|
5092
|
-
if (mode === 'confirm') {
|
|
5093
|
-
return tr('modeConfirm');
|
|
5094
|
-
}
|
|
5095
5033
|
if (mode === 'auto') {
|
|
5096
5034
|
return tr('modeAuto');
|
|
5097
5035
|
}
|
|
@@ -5103,8 +5041,6 @@
|
|
|
5103
5041
|
const labels = {
|
|
5104
5042
|
completed: tx('Completed', '已完成'),
|
|
5105
5043
|
rejected: tx('Cancelled', '已取消'),
|
|
5106
|
-
'confirm failed': tx('Confirmation failed', '确认失败'),
|
|
5107
|
-
'confirmed and applied': tx('Suggested changes applied', '已应用建议修改'),
|
|
5108
5044
|
'applied with delete plan': tx('Applied with confirmed deletes', '已应用并删除确认项'),
|
|
5109
5045
|
'applied without deletes': tx('Applied without deletes', '已应用非删除修改'),
|
|
5110
5046
|
'只问不改': tr('modeAsk')
|
|
@@ -5559,6 +5495,7 @@
|
|
|
5559
5495
|
speedTier: prefs.speedTier || '',
|
|
5560
5496
|
mode: prefs.mode || '',
|
|
5561
5497
|
locale: prefs.locale || '',
|
|
5498
|
+
theme: ['dark', 'light', 'auto'].includes(prefs.theme) ? prefs.theme : 'dark',
|
|
5562
5499
|
requireReviewing: prefs.requireReviewing !== false,
|
|
5563
5500
|
autoRecompile: prefs.autoRecompile !== false,
|
|
5564
5501
|
loadCodexLocalSkills: prefs.loadCodexLocalSkills !== false,
|
|
@@ -5581,7 +5518,7 @@
|
|
|
5581
5518
|
history: Array.isArray(session.history) ? session.history : [],
|
|
5582
5519
|
task: typeof session.task === 'string' ? session.task : '',
|
|
5583
5520
|
pendingInputs: Array.isArray(session.pendingInputs) ? session.pendingInputs : [],
|
|
5584
|
-
mode: session.mode || prefs.mode || '
|
|
5521
|
+
mode: session.mode || prefs.mode || 'ask', providerId: session.providerId || 'builtin',
|
|
5585
5522
|
model: session.model || prefs.model || 'gpt-5.4',
|
|
5586
5523
|
reasoningEffort: session.reasoningEffort || prefs.reasoningEffort || 'high',
|
|
5587
5524
|
speedTier: session.speedTier || prefs.speedTier || 'standard',
|
|
@@ -5609,6 +5546,7 @@
|
|
|
5609
5546
|
reasoningEffort: fallback.reasoningEffort || '',
|
|
5610
5547
|
speedTier: fallback.speedTier || '',
|
|
5611
5548
|
locale: fallback.locale || '',
|
|
5549
|
+
theme: ['dark', 'light', 'auto'].includes(fallback.theme) ? fallback.theme : 'dark',
|
|
5612
5550
|
requireReviewing: fallback.requireReviewing !== false,
|
|
5613
5551
|
autoOpen: fallback.autoOpen !== false,
|
|
5614
5552
|
loadCodexLocalSkills: fallback.loadCodexLocalSkills !== false,
|
|
@@ -5958,7 +5896,13 @@
|
|
|
5958
5896
|
saveStateSoon();
|
|
5959
5897
|
return;
|
|
5960
5898
|
}
|
|
5961
|
-
if (event?.target?.matches?.('[data-speed]'))
|
|
5899
|
+
if (event?.target?.matches?.('[data-speed]')) {
|
|
5900
|
+
// Capability rendering consults state.speedTier. Capture the user's
|
|
5901
|
+
// choice before rebuilding the select, otherwise the rebuild projects
|
|
5902
|
+
// the previous tier back into the DOM and makes Fast appear inert.
|
|
5903
|
+
state.speedTier = event.target.value || 'standard';
|
|
5904
|
+
renderReasoningOptions(getRenderedModelEntries());
|
|
5905
|
+
}
|
|
5962
5906
|
renderSpeedOptions(getRenderedModelEntries());
|
|
5963
5907
|
readPanelInputs();
|
|
5964
5908
|
renderModelConfigChoices();
|
|
@@ -5984,7 +5928,7 @@
|
|
|
5984
5928
|
}
|
|
5985
5929
|
|
|
5986
5930
|
async function selectMode(mode) {
|
|
5987
|
-
if (!['ask', '
|
|
5931
|
+
if (!['ask', 'auto'].includes(mode)) {
|
|
5988
5932
|
return;
|
|
5989
5933
|
}
|
|
5990
5934
|
const modeSelect = panel?.querySelector('[data-mode]');
|
|
@@ -6268,7 +6212,11 @@
|
|
|
6268
6212
|
events: root.querySelector('[data-run-events]'),
|
|
6269
6213
|
report: root.querySelector('[data-run-report]'),
|
|
6270
6214
|
status: root.querySelector('[data-run-status]'),
|
|
6271
|
-
|
|
6215
|
+
// A run starts before warm-mirror resolution has produced its lightweight
|
|
6216
|
+
// project snapshot. Seed references from the already-prefetched project
|
|
6217
|
+
// inventory so early stream events and fast Ask responses can still
|
|
6218
|
+
// resolve project-relative locations.
|
|
6219
|
+
projectFiles: getCurrentProjectReferenceFiles(),
|
|
6272
6220
|
startedAt: Date.now(),
|
|
6273
6221
|
queueItemId,
|
|
6274
6222
|
nativeRequestId: '',
|
|
@@ -6289,7 +6237,7 @@
|
|
|
6289
6237
|
return updatedAt;
|
|
6290
6238
|
}
|
|
6291
6239
|
|
|
6292
|
-
function finishRunView(text, status) {
|
|
6240
|
+
async function finishRunView(text, status) {
|
|
6293
6241
|
if (!currentRunView) {
|
|
6294
6242
|
return;
|
|
6295
6243
|
}
|
|
@@ -6316,7 +6264,11 @@
|
|
|
6316
6264
|
const navigationDivergent = currentRunView.runProjectId
|
|
6317
6265
|
&& activeProjectId !== currentRunView.runProjectId;
|
|
6318
6266
|
if (!navigationDivergent) {
|
|
6319
|
-
|
|
6267
|
+
// A terminal badge is a durability promise: once the user can see
|
|
6268
|
+
// Done/Failed/Cancelled, an immediate reload must hydrate that same
|
|
6269
|
+
// terminal state. Drain any older running snapshot and persist the
|
|
6270
|
+
// latest record before exposing the terminal UI.
|
|
6271
|
+
await flushQueuedSaveState().catch(() => {});
|
|
6320
6272
|
}
|
|
6321
6273
|
renderSessionList();
|
|
6322
6274
|
}
|
|
@@ -6636,6 +6588,39 @@
|
|
|
6636
6588
|
|
|
6637
6589
|
|
|
6638
6590
|
|
|
6591
|
+
function getCurrentProjectMathSources() {
|
|
6592
|
+
const sources = [];
|
|
6593
|
+
const seen = new Set();
|
|
6594
|
+
let remainingChars = 256 * 1024;
|
|
6595
|
+
const add = item => {
|
|
6596
|
+
if (!item || typeof item !== 'object' || typeof item.content !== 'string') return;
|
|
6597
|
+
const path = normalizeReferencePathForRuntime(item.path || item.filePath || '');
|
|
6598
|
+
if (!path || seen.has(path) || hasUnsafeRuntimePathSegments(path)
|
|
6599
|
+
|| !/\.(?:tex|sty|cls|ltx)$/i.test(path) || remainingChars <= 0) return;
|
|
6600
|
+
const content = item.content.slice(0, Math.min(64 * 1024, remainingChars));
|
|
6601
|
+
remainingChars -= content.length;
|
|
6602
|
+
seen.add(path);
|
|
6603
|
+
sources.push({ path, content });
|
|
6604
|
+
};
|
|
6605
|
+
for (const collection of [
|
|
6606
|
+
currentRunView?.projectFiles,
|
|
6607
|
+
currentRunView?.files,
|
|
6608
|
+
currentRunView?.project?.files,
|
|
6609
|
+
currentRunView?.snapshot?.files,
|
|
6610
|
+
currentRunView?.projectSnapshot?.files,
|
|
6611
|
+
currentRunView?.contextFiles,
|
|
6612
|
+
state?.projectFiles,
|
|
6613
|
+
state?.files,
|
|
6614
|
+
state?.project?.files,
|
|
6615
|
+
state?.snapshot?.files,
|
|
6616
|
+
state?.projectSnapshot?.files,
|
|
6617
|
+
state?.contextFiles
|
|
6618
|
+
]) {
|
|
6619
|
+
if (Array.isArray(collection)) collection.forEach(add);
|
|
6620
|
+
}
|
|
6621
|
+
return sources;
|
|
6622
|
+
}
|
|
6623
|
+
|
|
6639
6624
|
function getCurrentProjectReferenceFiles() {
|
|
6640
6625
|
const files = [];
|
|
6641
6626
|
const seen = new Set();
|
|
@@ -6686,7 +6671,14 @@
|
|
|
6686
6671
|
}
|
|
6687
6672
|
};
|
|
6688
6673
|
|
|
6674
|
+
const activeSession = typeof getActiveSession === 'function' ? getActiveSession(state) : null;
|
|
6689
6675
|
addFiles(currentRunView?.projectFiles);
|
|
6676
|
+
addFiles(activeSession?.projectReferenceFiles);
|
|
6677
|
+
// ContextTray owns the exact, background-prefetched project file list.
|
|
6678
|
+
// Warm-mirror runs intentionally carry only the active/focused overlay, so
|
|
6679
|
+
// omitting this inventory makes valid references to every other project
|
|
6680
|
+
// file render as plain text.
|
|
6681
|
+
addFiles(contextTrayController?.getContextProject?.()?.files);
|
|
6690
6682
|
addFiles(currentRunView?.files);
|
|
6691
6683
|
addFiles(currentRunView?.project?.files);
|
|
6692
6684
|
addFiles(currentRunView?.snapshot?.files);
|
|
@@ -6700,14 +6692,26 @@
|
|
|
6700
6692
|
addFiles(state?.contextFiles);
|
|
6701
6693
|
addTextPaths(state?.focusFiles);
|
|
6702
6694
|
addTextPaths(state?.session?.focusFiles);
|
|
6703
|
-
const activeSession = typeof getActiveSession === 'function' ? getActiveSession(state) : null;
|
|
6704
6695
|
addTextPaths(activeSession?.focusFiles);
|
|
6705
6696
|
for (const session of Array.isArray(state?.sessions) ? state.sessions : []) {
|
|
6697
|
+
addFiles(session?.projectReferenceFiles);
|
|
6706
6698
|
addTextPaths(session?.focusFiles);
|
|
6707
6699
|
}
|
|
6708
6700
|
return files;
|
|
6709
6701
|
}
|
|
6710
6702
|
|
|
6703
|
+
function persistCurrentProjectReferenceFiles(project) {
|
|
6704
|
+
const projectFiles = captureProjectReferenceFiles(project);
|
|
6705
|
+
if (currentRunView) {
|
|
6706
|
+
currentRunView.projectFiles = projectFiles;
|
|
6707
|
+
}
|
|
6708
|
+
if (getActiveSession(state)) {
|
|
6709
|
+
state = updateActiveSession(state, { projectReferenceFiles: projectFiles });
|
|
6710
|
+
saveStateSoon();
|
|
6711
|
+
}
|
|
6712
|
+
return projectFiles;
|
|
6713
|
+
}
|
|
6714
|
+
|
|
6711
6715
|
function captureProjectReferenceFiles(project) {
|
|
6712
6716
|
const result = [];
|
|
6713
6717
|
const seen = new Set();
|
|
@@ -7167,7 +7171,12 @@
|
|
|
7167
7171
|
record.undoOperations = [];
|
|
7168
7172
|
record.undoBaseFiles = [];
|
|
7169
7173
|
record.undoTrackedChanges = combinedTrackedChanges;
|
|
7170
|
-
record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(
|
|
7174
|
+
record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(
|
|
7175
|
+
project,
|
|
7176
|
+
combinedAppliedOperations,
|
|
7177
|
+
combinedTrackedChanges,
|
|
7178
|
+
record.undoExpectedFiles
|
|
7179
|
+
);
|
|
7171
7180
|
record.undoStatus = '';
|
|
7172
7181
|
record.partialWriteback = skippedEntries.length > 0;
|
|
7173
7182
|
// Recording tracked-change refs enters the run into the tracked-change
|
|
@@ -7215,7 +7224,12 @@
|
|
|
7215
7224
|
record.undoOperations = checkpoint.undoOperations;
|
|
7216
7225
|
record.undoBaseFiles = checkpoint.undoBaseFiles;
|
|
7217
7226
|
record.undoTrackedChanges = [];
|
|
7218
|
-
record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(
|
|
7227
|
+
record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(
|
|
7228
|
+
project,
|
|
7229
|
+
combinedAppliedOperations,
|
|
7230
|
+
[],
|
|
7231
|
+
record.undoExpectedFiles
|
|
7232
|
+
);
|
|
7219
7233
|
record.undoStatus = '';
|
|
7220
7234
|
record.partialWriteback = skippedEntries.length > 0;
|
|
7221
7235
|
refreshRunCardControls(record.id);
|
|
@@ -7235,8 +7249,18 @@
|
|
|
7235
7249
|
return WritebackSettlement.normalizeApplyTrackedChanges(changes);
|
|
7236
7250
|
}
|
|
7237
7251
|
|
|
7238
|
-
function selectExpectedFilesForTrackedUndo(
|
|
7239
|
-
|
|
7252
|
+
function selectExpectedFilesForTrackedUndo(
|
|
7253
|
+
project,
|
|
7254
|
+
operations = [],
|
|
7255
|
+
trackedChanges = [],
|
|
7256
|
+
previousExpectedFiles = []
|
|
7257
|
+
) {
|
|
7258
|
+
return WritebackSettlement.selectExpectedFilesForTrackedUndo(
|
|
7259
|
+
project,
|
|
7260
|
+
operations,
|
|
7261
|
+
trackedChanges,
|
|
7262
|
+
previousExpectedFiles
|
|
7263
|
+
);
|
|
7240
7264
|
}
|
|
7241
7265
|
|
|
7242
7266
|
function buildTrackedUndoPostFiles(run) {
|