codex-overleaf-link 2.3.6 → 2.4.1
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 +62 -34
- package/README.zh-CN.md +546 -0
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +3 -0
- package/extension/src/content/activeTurnControl.js +1 -0
- package/extension/src/content/assetTransferBroker.js +2 -0
- package/extension/src/content/contentRuntime.js +122 -118
- package/extension/src/content/contextTray.js +4 -0
- package/extension/src/content/diagnosticsController.js +4 -0
- package/extension/src/content/diagnosticsPanel.js +128 -4
- package/extension/src/content/generated/content.bundle.js +1233 -550
- package/extension/src/content/generated/content.bundle.meta.json +4 -3
- package/extension/src/content/legacyGlobalRegistry.js +1 -0
- package/extension/src/content/modelPicker.js +21 -9
- package/extension/src/content/modelPickerSupport.js +38 -1
- package/extension/src/content/nativeCompatibilityController.js +4 -1
- package/extension/src/content/otWarmMirror.js +34 -30
- package/extension/src/content/otWarmMirrorController.js +20 -0
- package/extension/src/content/pageBridgeClient.js +2 -0
- package/extension/src/content/panelMaintenance.js +8 -4
- package/extension/src/content/recentProjects.js +354 -355
- package/extension/src/content/runResultActions.js +16 -1
- package/extension/src/content/runTimelineView.js +9 -11
- package/extension/src/content/scopedPersistenceCoordinator.js +2 -1
- package/extension/src/content/scopedPersistencePanelState.js +45 -2
- package/extension/src/content/sessionForkController.js +20 -11
- package/extension/src/content/sessionPersistence.js +4 -1
- package/extension/src/content/settingsPanel.js +16 -2
- package/extension/src/content/trackedChangeCaptureController.js +153 -0
- package/extension/src/content/writebackOrchestrator.js +31 -0
- package/extension/src/page/binaryAssetUploader.js +101 -29
- package/extension/src/page/overleafRealtimeObserver.js +4 -1
- package/extension/src/page/saveState.js +44 -1
- package/extension/src/page/textFileCreator.js +493 -0
- package/extension/src/page/trackedChangeCapture.js +342 -0
- package/extension/src/page/trackedChangesLifecycle.js +149 -150
- package/extension/src/page/treeOperations.js +40 -29
- package/extension/src/page/writebackRouter.js +95 -49
- package/extension/src/pageBridge.js +65 -25
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/i18n.js +94 -40
- package/extension/src/shared/pageRpcContract.js +2 -1
- package/extension/src/shared/sessionState.js +6 -2
- package/extension/src/shared/storageDb.js +11 -12
- package/extension/src/shared/storageRunActions.js +73 -1
- package/extension/src/shared/writebackSettlement.js +19 -5
- package/extension/styles/panel.css +254 -405
- package/native-host/src/codexSessionRunner.js +41 -38
- package/native-host/src/codexSessionTiming.js +68 -0
- package/native-host/src/readProgressGuard.js +84 -17
- package/native-host/src/taskRunnerRuntime.js +25 -0
- package/package.json +5 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
if (typeof document !== 'undefined' && document.documentElement) document.documentElement.setAttribute('data-codex-overleaf-source-digest', "b19a018ab6eb9c7bdca8cfad8ff6efcc4a30e80f81c3c0a2e89a7f78b6361d97");
|
|
1
2
|
(() => {
|
|
2
3
|
// extension/entries/content-entry.mjs
|
|
3
4
|
(function runClassicContentModule(module, exports, require2) {
|
|
@@ -4582,14 +4583,39 @@ ${block}`;
|
|
|
4582
4583
|
failureReason_editor_project_id_unavailable_next: "Refresh the Overleaf tab and retry; if it persists, reload the extension.",
|
|
4583
4584
|
// Welcome-panel + write-guard: Recent-projects
|
|
4584
4585
|
// variant copy. Spec §5.3–§5.5, §5.8, §5.10 are the source of truth.
|
|
4585
|
-
recentProjects_welcome: "
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4586
|
+
recentProjects_welcome: "Continue working",
|
|
4587
|
+
recentProjects_focusEyebrow: "Last conversation",
|
|
4588
|
+
recentProjects_historyHeading: "Other recent conversations",
|
|
4589
|
+
recentProjects_historyHint: "Select to continue",
|
|
4590
|
+
recentProjects_projectConversations: "View this project's conversations",
|
|
4591
|
+
recentProjects_allProjects: "All projects",
|
|
4592
|
+
recentProjects_showAllConversations: "View all {count} conversations",
|
|
4593
|
+
recentProjects_unstarted: "Not started \xB7 {count}",
|
|
4594
|
+
recentProjects_unstartedHint: "Empty conversations are kept here, without deleting their records.",
|
|
4595
|
+
recentProjects_noStarted: "No conversation has been started yet. Empty conversations are available below.",
|
|
4596
|
+
recentProjects_savedDraft: "Saved draft, ready to continue.",
|
|
4597
|
+
recentProjects_attention: "Needs attention",
|
|
4598
|
+
recentProjects_unavailableRecords: "Records with unavailable project links",
|
|
4599
|
+
recentProjects_loadingHistory: "Loading conversations...",
|
|
4600
|
+
recentProjects_loadFailed: "Conversation history could not be read. Please retry.",
|
|
4601
|
+
recentProjects_continueHint: "Open this conversation without automatically starting a task.",
|
|
4602
|
+
recentProjects_more: "More options",
|
|
4603
|
+
recentProjects_continue: "Continue",
|
|
4604
|
+
recentProjects_openProject: "Open project",
|
|
4605
|
+
recentProjects_loadingConversation: "Loading conversation...",
|
|
4606
|
+
recentProjects_noConversation: "No saved conversation",
|
|
4607
|
+
recentProjects_noRuns: "No runs yet",
|
|
4608
|
+
recentProjects_previewUnavailable: "Conversation unavailable",
|
|
4609
|
+
recentProjects_previewUnavailableHint: "Saved conversation could not be loaded.",
|
|
4610
|
+
recentProjects_conversationGone: "This conversation is no longer available. Choose another conversation from the refreshed list.",
|
|
4611
|
+
recentProjects_continueFailed: "Could not open the conversation. Please try again.",
|
|
4612
|
+
recentProjects_welcome_subtitle: "Conversations saved in this browser",
|
|
4613
|
+
recentProjects_empty: "No conversations saved in this browser yet. Open an Overleaf project and start a Codex conversation.",
|
|
4614
|
+
recentProjects_sessions_empty: "No saved conversations in this project",
|
|
4615
|
+
recentProjects_sessions_toggle: "Show or manage this project's conversations",
|
|
4616
|
+
recentProjects_sessions_action: "All conversations",
|
|
4617
|
+
recentProjects_sessions_action_open: "Hide conversations",
|
|
4618
|
+
recentProjects_clearProject: "Delete this project's conversations",
|
|
4593
4619
|
recentProjects_clearProject_title: "Delete all Codex sessions for {project}?",
|
|
4594
4620
|
recentProjects_clearProject_message: "This permanently deletes all {count} plugin sessions, run history, and matching plugin-local Codex thread history for {project}. It will not modify Overleaf files or global Codex history.",
|
|
4595
4621
|
recentProjects_clearProject_confirm: "Delete all",
|
|
@@ -4605,15 +4631,17 @@ ${block}`;
|
|
|
4605
4631
|
recentProjects_degraded: "Sign in to Overleaf to see your recent Codex projects.",
|
|
4606
4632
|
recentProjects_row_projectLinkUnavailable: "Project link unavailable.",
|
|
4607
4633
|
recentProjects_settings_entry: "Settings & Diagnostics",
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4634
|
+
recentProjects_settingsTitle: "General Settings",
|
|
4635
|
+
recentProjects_settingsSubtitle: "Manage Codex preferences and local history across all projects.",
|
|
4636
|
+
recentProjects_badge_pending: "Last run pending",
|
|
4637
|
+
recentProjects_badge_accepted: "Last changes accepted",
|
|
4638
|
+
recentProjects_badge_rejected: "Last changes undone",
|
|
4639
|
+
recentProjects_badge_needs_review: "Last run needs review",
|
|
4640
|
+
recentProjects_badge_running: "Last recorded as running",
|
|
4641
|
+
recentProjects_badge_completed: "Last run completed",
|
|
4642
|
+
recentProjects_badge_failed: "Last run failed",
|
|
4643
|
+
recentProjects_badge_interrupted: "Last run may have been interrupted",
|
|
4644
|
+
recentProjects_badge_stale: "Last run status unconfirmed",
|
|
4617
4645
|
recentProjects_unnamed: "Project \xB7 {prefix}",
|
|
4618
4646
|
recentProjects_zombieRunningNote: "Marked as running, but it may be a leftover from an interrupted run.",
|
|
4619
4647
|
recentProjects_zombieDeleteConfirm: "This session is marked as running. If no other tab is actually running it, you can delete it anyway.",
|
|
@@ -4621,9 +4649,9 @@ ${block}`;
|
|
|
4621
4649
|
recentProjects_degraded_hint: "Could not identify the Overleaf account on this page, so the project list is hidden to avoid mixing accounts. This usually resolves on a reload.",
|
|
4622
4650
|
recentProjects_sessionsCount: "{count} session(s)",
|
|
4623
4651
|
recentProjects_welcome_stats: "{projects} projects \xB7 {sessions} Codex sessions",
|
|
4624
|
-
recentProjects_badge_background_completed: "completed in background",
|
|
4625
|
-
recentProjects_badge_needs_review_after_navigation: "
|
|
4626
|
-
recentProjects_badge_abandoned_after_navigation: "
|
|
4652
|
+
recentProjects_badge_background_completed: "Last run completed in background",
|
|
4653
|
+
recentProjects_badge_needs_review_after_navigation: "Last run needs review",
|
|
4654
|
+
recentProjects_badge_abandoned_after_navigation: "Last run stopped after navigation"
|
|
4627
4655
|
},
|
|
4628
4656
|
zh: {
|
|
4629
4657
|
resizePanel: "\u62D6\u52A8\u8C03\u6574 Codex \u9762\u677F\u5BBD\u5EA6\uFF0C\u53CC\u51FB\u6062\u590D\u9ED8\u8BA4\u5BBD\u5EA6",
|
|
@@ -5121,14 +5149,39 @@ ${block}`;
|
|
|
5121
5149
|
failureReason_editor_project_id_unavailable_next: "\u8BF7\u5237\u65B0 Overleaf \u9875\u9762\u540E\u91CD\u8BD5\uFF1B\u5982\u679C\u4ECD\u7136\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55\u3002",
|
|
5122
5150
|
// Welcome-panel + write-guard: Recent-projects
|
|
5123
5151
|
// variant copy. 见 spec §5.3–§5.5、§5.8、§5.10。
|
|
5124
|
-
recentProjects_welcome: "
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5152
|
+
recentProjects_welcome: "\u7EE7\u7EED\u5DE5\u4F5C",
|
|
5153
|
+
recentProjects_focusEyebrow: "\u4E0A\u6B21\u5BF9\u8BDD",
|
|
5154
|
+
recentProjects_historyHeading: "\u5176\u4ED6\u6700\u8FD1\u5BF9\u8BDD",
|
|
5155
|
+
recentProjects_historyHint: "\u70B9\u51FB\u6761\u76EE\u7EE7\u7EED",
|
|
5156
|
+
recentProjects_projectConversations: "\u67E5\u770B\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u5BF9\u8BDD",
|
|
5157
|
+
recentProjects_allProjects: "\u6240\u6709\u9879\u76EE",
|
|
5158
|
+
recentProjects_showAllConversations: "\u67E5\u770B\u5168\u90E8 {count} \u6BB5\u5BF9\u8BDD",
|
|
5159
|
+
recentProjects_unstarted: "\u672A\u5F00\u59CB \xB7 {count}",
|
|
5160
|
+
recentProjects_unstartedHint: "\u7A7A\u767D\u5BF9\u8BDD\u6536\u7EB3\u5728\u8FD9\u91CC\uFF0C\u8BB0\u5F55\u4E0D\u4F1A\u88AB\u5220\u9664\u3002",
|
|
5161
|
+
recentProjects_noStarted: "\u5C1A\u65E0\u5DF2\u5F00\u59CB\u7684\u5BF9\u8BDD\uFF0C\u7A7A\u767D\u5BF9\u8BDD\u53EF\u5728\u4E0B\u65B9\u5C55\u5F00\u3002",
|
|
5162
|
+
recentProjects_savedDraft: "\u8349\u7A3F\u5DF2\u4FDD\u5B58\uFF0C\u53EF\u7EE7\u7EED\u8865\u5145\u3002",
|
|
5163
|
+
recentProjects_attention: "\u9700\u8981\u67E5\u770B",
|
|
5164
|
+
recentProjects_unavailableRecords: "\u9879\u76EE\u94FE\u63A5\u4E0D\u53EF\u7528\u7684\u8BB0\u5F55",
|
|
5165
|
+
recentProjects_loadingHistory: "\u6B63\u5728\u52A0\u8F7D\u5BF9\u8BDD\u2026",
|
|
5166
|
+
recentProjects_loadFailed: "\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u5BF9\u8BDD\u5386\u53F2\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
5167
|
+
recentProjects_continueHint: "\u4EC5\u6253\u5F00\u8FD9\u6BB5\u5BF9\u8BDD\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u542F\u52A8\u4EFB\u52A1\u3002",
|
|
5168
|
+
recentProjects_more: "\u66F4\u591A\u9009\u9879",
|
|
5169
|
+
recentProjects_continue: "\u7EE7\u7EED",
|
|
5170
|
+
recentProjects_openProject: "\u6253\u5F00\u9879\u76EE",
|
|
5171
|
+
recentProjects_loadingConversation: "\u6B63\u5728\u52A0\u8F7D\u5BF9\u8BDD\u2026",
|
|
5172
|
+
recentProjects_noConversation: "\u6682\u65E0\u4FDD\u5B58\u7684\u5BF9\u8BDD",
|
|
5173
|
+
recentProjects_noRuns: "\u5C1A\u672A\u8FD0\u884C\u4EFB\u52A1",
|
|
5174
|
+
recentProjects_previewUnavailable: "\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u5BF9\u8BDD",
|
|
5175
|
+
recentProjects_previewUnavailableHint: "\u5DF2\u4FDD\u5B58\u7684\u5BF9\u8BDD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002",
|
|
5176
|
+
recentProjects_conversationGone: "\u8BE5\u5BF9\u8BDD\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u4ECE\u66F4\u65B0\u540E\u7684\u5217\u8868\u4E2D\u9009\u62E9\u5176\u4ED6\u5BF9\u8BDD\u3002",
|
|
5177
|
+
recentProjects_continueFailed: "\u6682\u65F6\u65E0\u6CD5\u6253\u5F00\u5BF9\u8BDD\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
5178
|
+
recentProjects_welcome_subtitle: "\u5F53\u524D\u6D4F\u89C8\u5668\u4FDD\u5B58\u7684\u5BF9\u8BDD",
|
|
5179
|
+
recentProjects_empty: "\u5F53\u524D\u6D4F\u89C8\u5668\u8FD8\u6CA1\u6709\u4FDD\u5B58\u7684\u5BF9\u8BDD\u3002\u6253\u5F00\u4E00\u4E2A Overleaf \u9879\u76EE\uFF0C\u4E0E Codex \u5F00\u59CB\u5BF9\u8BDD\u5373\u53EF\u3002",
|
|
5180
|
+
recentProjects_sessions_empty: "\u8BE5\u9879\u76EE\u8FD8\u6CA1\u6709\u4FDD\u5B58\u7684\u5BF9\u8BDD",
|
|
5181
|
+
recentProjects_sessions_toggle: "\u67E5\u770B\u6216\u7BA1\u7406\u8BE5\u9879\u76EE\u7684\u5BF9\u8BDD",
|
|
5182
|
+
recentProjects_sessions_action: "\u5168\u90E8\u5BF9\u8BDD",
|
|
5183
|
+
recentProjects_sessions_action_open: "\u6536\u8D77\u5BF9\u8BDD",
|
|
5184
|
+
recentProjects_clearProject: "\u5220\u9664\u8BE5\u9879\u76EE\u7684\u5168\u90E8\u5BF9\u8BDD",
|
|
5132
5185
|
recentProjects_clearProject_title: "\u5220\u9664 {project} \u7684\u5168\u90E8 Codex \u4F1A\u8BDD\uFF1F",
|
|
5133
5186
|
recentProjects_clearProject_message: "\u8FD9\u4F1A\u6C38\u4E45\u5220\u9664 {project} \u7684\u5168\u90E8 {count} \u4E2A\u63D2\u4EF6\u4F1A\u8BDD\u3001\u8FD0\u884C\u5386\u53F2\u53CA\u5BF9\u5E94\u7684\u63D2\u4EF6\u672C\u5730 Codex \u7EBF\u7A0B\u5386\u53F2\u3002\u4E0D\u4F1A\u4FEE\u6539 Overleaf \u6587\u4EF6\u6216\u5168\u5C40 Codex \u5386\u53F2\u3002",
|
|
5134
5187
|
recentProjects_clearProject_confirm: "\u5168\u90E8\u5220\u9664",
|
|
@@ -5144,15 +5197,17 @@ ${block}`;
|
|
|
5144
5197
|
recentProjects_degraded: "\u8BF7\u767B\u5F55 Overleaf \u540E\u67E5\u770B\u4F60\u6700\u8FD1\u7684 Codex \u9879\u76EE\u3002",
|
|
5145
5198
|
recentProjects_row_projectLinkUnavailable: "\u9879\u76EE\u94FE\u63A5\u4E0D\u53EF\u7528\u3002",
|
|
5146
5199
|
recentProjects_settings_entry: "\u8BBE\u7F6E\u4E0E\u8BCA\u65AD",
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5200
|
+
recentProjects_settingsTitle: "\u901A\u7528\u8BBE\u7F6E",
|
|
5201
|
+
recentProjects_settingsSubtitle: "\u7BA1\u7406\u9002\u7528\u4E8E\u6240\u6709\u9879\u76EE\u7684 Codex \u504F\u597D\u8BBE\u7F6E\u4E0E\u672C\u5730\u5386\u53F2\u8BB0\u5F55\u3002",
|
|
5202
|
+
recentProjects_badge_pending: "\u4E0A\u6B21\u8FD0\u884C\u5F85\u5904\u7406",
|
|
5203
|
+
recentProjects_badge_accepted: "\u4E0A\u6B21\u4FEE\u6539\u5DF2\u63A5\u53D7",
|
|
5204
|
+
recentProjects_badge_rejected: "\u4E0A\u6B21\u4FEE\u6539\u5DF2\u64A4\u56DE",
|
|
5205
|
+
recentProjects_badge_needs_review: "\u4E0A\u6B21\u8FD0\u884C\u9700\u8981\u68C0\u67E5",
|
|
5206
|
+
recentProjects_badge_running: "\u4E0A\u6B21\u8BB0\u5F55\u4E3A\u8FD0\u884C\u4E2D",
|
|
5207
|
+
recentProjects_badge_completed: "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u5B8C\u6210",
|
|
5208
|
+
recentProjects_badge_failed: "\u4E0A\u6B21\u8FD0\u884C\u5931\u8D25",
|
|
5209
|
+
recentProjects_badge_interrupted: "\u4E0A\u6B21\u8FD0\u884C\u53EF\u80FD\u5DF2\u4E2D\u65AD",
|
|
5210
|
+
recentProjects_badge_stale: "\u4E0A\u6B21\u8FD0\u884C\u72B6\u6001\u672A\u786E\u8BA4",
|
|
5156
5211
|
recentProjects_unnamed: "\u9879\u76EE \xB7 {prefix}",
|
|
5157
5212
|
recentProjects_zombieRunningNote: "\u6807\u8BB0\u4E3A\u8FD0\u884C\u4E2D\uFF0C\u4F46\u53EF\u80FD\u662F\u88AB\u4E2D\u65AD\u540E\u7684\u6B8B\u7559\u3002",
|
|
5158
5213
|
recentProjects_zombieDeleteConfirm: "\u8BE5\u4F1A\u8BDD\u6807\u8BB0\u4E3A\u8FD0\u884C\u4E2D\u3002\u5982\u679C\u786E\u8BA4\u6CA1\u6709\u5176\u4ED6\u6807\u7B7E\u9875\u5728\u8FD0\u884C\u5B83\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5220\u9664\u3002",
|
|
@@ -5160,9 +5215,9 @@ ${block}`;
|
|
|
5160
5215
|
recentProjects_degraded_hint: "\u65E0\u6CD5\u8BC6\u522B\u672C\u9875\u7684 Overleaf \u8D26\u53F7\uFF0C\u4E3A\u907F\u514D\u8D26\u53F7\u95F4\u4E32\u6570\u636E\u5DF2\u9690\u85CF\u9879\u76EE\u5217\u8868\u3002\u901A\u5E38\u5237\u65B0\u5373\u53EF\u6062\u590D\u3002",
|
|
5161
5216
|
recentProjects_sessionsCount: "{count} \u4E2A\u4F1A\u8BDD",
|
|
5162
5217
|
recentProjects_welcome_stats: "{projects} \u4E2A\u9879\u76EE \xB7 {sessions} \u4E2A Codex \u4F1A\u8BDD",
|
|
5163
|
-
recentProjects_badge_background_completed: "\u540E\u53F0\
|
|
5164
|
-
recentProjects_badge_needs_review_after_navigation: "\
|
|
5165
|
-
recentProjects_badge_abandoned_after_navigation: "\u5DF2\
|
|
5218
|
+
recentProjects_badge_background_completed: "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u5728\u540E\u53F0\u5B8C\u6210",
|
|
5219
|
+
recentProjects_badge_needs_review_after_navigation: "\u4E0A\u6B21\u8FD0\u884C\u9700\u8981\u68C0\u67E5",
|
|
5220
|
+
recentProjects_badge_abandoned_after_navigation: "\u4E0A\u6B21\u8FD0\u884C\u5DF2\u5728\u79BB\u5F00\u9875\u9762\u540E\u505C\u6B62"
|
|
5166
5221
|
}
|
|
5167
5222
|
};
|
|
5168
5223
|
function normalizeLocale(value) {
|
|
@@ -7886,7 +7941,7 @@ ${block}`;
|
|
|
7886
7941
|
if (!result || typeof result !== "object" || result.ok === false) return result;
|
|
7887
7942
|
if (Array.isArray(result.skipped) && result.skipped.length > 0) return result;
|
|
7888
7943
|
const expectedFiles = Array.isArray(run?.undoExpectedFiles) ? run.undoExpectedFiles : [];
|
|
7889
|
-
if (!expectedFiles.length || isUndoVerifiedContentMatching(run, result)) return result;
|
|
7944
|
+
if (!expectedFiles.length || isUndoVerifiedContentMatching(run, result, options2)) return result;
|
|
7890
7945
|
const path = expectedFiles.find((entry) => typeof entry?.path === "string")?.path || "";
|
|
7891
7946
|
appendSyntheticFailure(result, options2.buildFailure?.("undo_not_verified", { path, type: "undo" }, {
|
|
7892
7947
|
changedDocument: true,
|
|
@@ -7895,12 +7950,13 @@ ${block}`;
|
|
|
7895
7950
|
}), path, "undo_not_verified", "undo");
|
|
7896
7951
|
return result;
|
|
7897
7952
|
}
|
|
7898
|
-
function isUndoVerifiedContentMatching(run, result) {
|
|
7953
|
+
function isUndoVerifiedContentMatching(run, result, options2 = {}) {
|
|
7899
7954
|
const expectedByPath = new Map((run?.undoExpectedFiles || []).filter((file) => typeof file?.path === "string" && typeof file?.content === "string").map((file) => [normalizeSettlementPath(file.path), file.content]).filter(([path]) => path));
|
|
7900
7955
|
if (!expectedByPath.size) return true;
|
|
7956
|
+
const postByPath = new Map((Array.isArray(options2?.postFiles) ? options2.postFiles : []).filter((file) => typeof file?.path === "string" && typeof file?.content === "string").map((file) => [normalizeSettlementPath(file.path), file.content]));
|
|
7901
7957
|
const applied = Array.isArray(result?.applied) ? result.applied : [];
|
|
7902
7958
|
return Array.from(expectedByPath).every(
|
|
7903
|
-
([path, expected]) => applied.some((entry) => isVerifiedUndoEntryForPath(entry, path, expected))
|
|
7959
|
+
([path, expected]) => applied.some((entry) => isVerifiedUndoEntryForPath(entry, path, expected, postByPath.get(path)))
|
|
7904
7960
|
);
|
|
7905
7961
|
}
|
|
7906
7962
|
function isUndoResultEffectivelyApplied(run, result, undoOperations = []) {
|
|
@@ -7914,7 +7970,7 @@ ${block}`;
|
|
|
7914
7970
|
(item) => isVerifiedUndoEntryForPath(item, path, expectedByPath.get(path))
|
|
7915
7971
|
));
|
|
7916
7972
|
}
|
|
7917
|
-
function isVerifiedUndoEntryForPath(entry, path, expectedContent) {
|
|
7973
|
+
function isVerifiedUndoEntryForPath(entry, path, expectedContent, postContent) {
|
|
7918
7974
|
const inner = entry?.result || {};
|
|
7919
7975
|
if (inner.ok === false) return false;
|
|
7920
7976
|
const normalizedPath = normalizeSettlementPath(path);
|
|
@@ -7929,7 +7985,12 @@ ${block}`;
|
|
|
7929
7985
|
return inner.method === "overleaf-editor-undo" && inner.verified === true && inner.verifiedContent === expectedContent;
|
|
7930
7986
|
}
|
|
7931
7987
|
if (key === `snapshot-undo:${normalizedPath}`) {
|
|
7932
|
-
|
|
7988
|
+
if (inner.verifiedContent === expectedContent) return true;
|
|
7989
|
+
const proof = inner.undoRebaseProof, before = proof?.beforeUndoContent;
|
|
7990
|
+
if (inner.verified !== true || proof?.version !== 1 || normalizeSettlementPath(proof.path) !== normalizedPath || typeof before !== "string" || typeof postContent !== "string" || !postContent || typeof inner.verifiedContent !== "string") return false;
|
|
7991
|
+
const start = before.indexOf(postContent);
|
|
7992
|
+
if (start < 0 || before.indexOf(postContent, start + 1) >= 0) return false;
|
|
7993
|
+
return inner.verifiedContent === before.slice(0, start) + expectedContent + before.slice(start + postContent.length);
|
|
7933
7994
|
}
|
|
7934
7995
|
return false;
|
|
7935
7996
|
}
|
|
@@ -8775,6 +8836,7 @@ ${block}`;
|
|
|
8775
8836
|
undoExpectedFiles: normalizeRunFiles(run.undoExpectedFiles),
|
|
8776
8837
|
undoStatus: sanitizeAssistantVisibleText(run.undoStatus),
|
|
8777
8838
|
nativeRequestId: sanitizeAssistantVisibleText(run.nativeRequestId),
|
|
8839
|
+
codexThreadId: sanitizeAssistantVisibleText(run.codexThreadId),
|
|
8778
8840
|
codexTurnId: sanitizeAssistantVisibleText(run.codexTurnId),
|
|
8779
8841
|
forkSnapshot: run.forkSnapshot === true,
|
|
8780
8842
|
forkSourceRunId: sanitizeAssistantVisibleText(run.forkSourceRunId),
|
|
@@ -8792,6 +8854,9 @@ ${block}`;
|
|
|
8792
8854
|
if (run.changedDocument === true) {
|
|
8793
8855
|
normalized.changedDocument = true;
|
|
8794
8856
|
}
|
|
8857
|
+
if (Array.isArray(run.trackedChangeCaptures) && run.trackedChangeCaptures.length && !run.forkSnapshot) {
|
|
8858
|
+
normalized.trackedChangeCaptures = sanitizeAssistantVisibleValue(run.trackedChangeCaptures);
|
|
8859
|
+
}
|
|
8795
8860
|
applyTrackedChangeStatus(normalized, run.trackedChangeStatus);
|
|
8796
8861
|
return normalized;
|
|
8797
8862
|
}
|
|
@@ -9226,6 +9291,7 @@ ${block}`;
|
|
|
9226
9291
|
undoExpectedFiles: undoPayload.undoExpectedFiles,
|
|
9227
9292
|
undoStatus: summarizeTextForStorage(run.undoStatus, "undo status"),
|
|
9228
9293
|
nativeRequestId: normalizeTextField(run.nativeRequestId, 160),
|
|
9294
|
+
codexThreadId: normalizeTextField(run.codexThreadId, 160),
|
|
9229
9295
|
codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
9230
9296
|
forkSnapshot: run.forkSnapshot === true,
|
|
9231
9297
|
forkSourceRunId: normalizeTextField(run.forkSourceRunId, 160),
|
|
@@ -9558,6 +9624,7 @@ ${block}`;
|
|
|
9558
9624
|
setActiveSession,
|
|
9559
9625
|
updateActiveSession,
|
|
9560
9626
|
normalizeRuns,
|
|
9627
|
+
normalizeProjectReferenceFiles,
|
|
9561
9628
|
prepareStateForStorage,
|
|
9562
9629
|
estimateJsonBytes,
|
|
9563
9630
|
computeSafeTaskSummary
|
|
@@ -9798,7 +9865,13 @@ ${block}`;
|
|
|
9798
9865
|
} catch (_error) {
|
|
9799
9866
|
return empty;
|
|
9800
9867
|
}
|
|
9801
|
-
|
|
9868
|
+
if (getUtf8ByteLength(serialized) > MAX_PERSISTED_ACTION_BYTES_PER_RUN) return empty;
|
|
9869
|
+
const captures = cloneSerializableArray(run.trackedChangeCaptures);
|
|
9870
|
+
if (captures.length) {
|
|
9871
|
+
const extended = { ...payload, trackedChangeCaptures: captures };
|
|
9872
|
+
if (getUtf8ByteLength(JSON.stringify(extended)) <= MAX_PERSISTED_ACTION_BYTES_PER_RUN) return extended;
|
|
9873
|
+
}
|
|
9874
|
+
return payload;
|
|
9802
9875
|
}
|
|
9803
9876
|
function emptyActionPayload() {
|
|
9804
9877
|
return {
|
|
@@ -9826,6 +9899,37 @@ ${block}`;
|
|
|
9826
9899
|
}
|
|
9827
9900
|
return value.length * 2;
|
|
9828
9901
|
}
|
|
9902
|
+
function compactRunExecutionSnapshot(run, normalizeString) {
|
|
9903
|
+
var snapshot = run && run.executionSnapshot;
|
|
9904
|
+
if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot)) return {};
|
|
9905
|
+
var normalize = typeof normalizeString === "function" ? normalizeString : String;
|
|
9906
|
+
var compact = {};
|
|
9907
|
+
var fields = [
|
|
9908
|
+
"schemaVersion",
|
|
9909
|
+
"mode",
|
|
9910
|
+
"providerId",
|
|
9911
|
+
"providerRevision",
|
|
9912
|
+
"model",
|
|
9913
|
+
"reasoningEffort",
|
|
9914
|
+
"speedTier",
|
|
9915
|
+
"autoRecompile",
|
|
9916
|
+
"requireReviewing",
|
|
9917
|
+
"capturedAt",
|
|
9918
|
+
"source"
|
|
9919
|
+
];
|
|
9920
|
+
for (var key of fields) {
|
|
9921
|
+
if (!Object.prototype.hasOwnProperty.call(snapshot, key)) continue;
|
|
9922
|
+
var value = snapshot[key];
|
|
9923
|
+
if (typeof value === "string") compact[key] = normalize(value);
|
|
9924
|
+
else if (value === null || typeof value === "number" || typeof value === "boolean") compact[key] = value;
|
|
9925
|
+
}
|
|
9926
|
+
if (Array.isArray(snapshot.focusFiles)) {
|
|
9927
|
+
compact.focusFiles = snapshot.focusFiles.slice(0, 100).filter(function(value2) {
|
|
9928
|
+
return typeof value2 === "string";
|
|
9929
|
+
}).map(normalize);
|
|
9930
|
+
}
|
|
9931
|
+
return { executionSnapshot: compact };
|
|
9932
|
+
}
|
|
9829
9933
|
function compactProviderSnapshot(value) {
|
|
9830
9934
|
return {
|
|
9831
9935
|
providerId: typeof value.providerId === "string" && value.providerId ? value.providerId : "builtin",
|
|
@@ -9854,6 +9958,56 @@ ${block}`;
|
|
|
9854
9958
|
}
|
|
9855
9959
|
return out;
|
|
9856
9960
|
}
|
|
9961
|
+
function mergeSessionReviewState(incoming, existing, reviewRunIds) {
|
|
9962
|
+
if (!existing || incoming.id !== existing.id || incoming.projectId !== existing.projectId || !incoming.accountScopeId || incoming.accountScopeId !== existing.accountScopeId) return incoming;
|
|
9963
|
+
var terminal = (run) => ["accepted", "rejected"].includes(run?.trackedChangeStatus);
|
|
9964
|
+
var incomingRuns = new Map((incoming.runs || []).map((run) => [run.id, run]));
|
|
9965
|
+
var existingRuns = new Map((existing.runs || []).map((run) => [run.id, run]));
|
|
9966
|
+
var requestedIds = new Set(reviewRunIds || []);
|
|
9967
|
+
var explicitReview = Array.from(requestedIds).some((id) => ["accepted", "rejected", "needs_review"].includes(incomingRuns.get(id)?.trackedChangeStatus));
|
|
9968
|
+
var newer = (Date.parse(incoming.updatedAt) || 0) >= (Date.parse(existing.updatedAt) || 0);
|
|
9969
|
+
if (!newer && !explicitReview) return incoming;
|
|
9970
|
+
var base = newer ? incoming : existing;
|
|
9971
|
+
var fields = [
|
|
9972
|
+
"trackedChangeStatus",
|
|
9973
|
+
"undoStatus",
|
|
9974
|
+
"undoTrackedChanges",
|
|
9975
|
+
"undoExpectedFiles",
|
|
9976
|
+
"undoOperations",
|
|
9977
|
+
"undoBaseFiles",
|
|
9978
|
+
"appliedOperations",
|
|
9979
|
+
"trackedChangeCaptures",
|
|
9980
|
+
"settlement",
|
|
9981
|
+
"settlementFacts"
|
|
9982
|
+
];
|
|
9983
|
+
var changed = false;
|
|
9984
|
+
var runs = (base.runs || []).map(function(run) {
|
|
9985
|
+
var previous = existingRuns.get(run.id), candidate = incomingRuns.get(run.id);
|
|
9986
|
+
var source = terminal(previous) ? previous : explicitReview && requestedIds.has(run.id) ? candidate : null;
|
|
9987
|
+
if (!source || source === run) return run;
|
|
9988
|
+
if (source.runProjectId && source.runProjectId !== incoming.projectId) return run;
|
|
9989
|
+
var merged2 = { ...run };
|
|
9990
|
+
for (var field of fields) {
|
|
9991
|
+
if (Object.prototype.hasOwnProperty.call(source, field)) {
|
|
9992
|
+
merged2[field] = JSON.parse(JSON.stringify(source[field]));
|
|
9993
|
+
} else {
|
|
9994
|
+
delete merged2[field];
|
|
9995
|
+
}
|
|
9996
|
+
}
|
|
9997
|
+
changed = true;
|
|
9998
|
+
return merged2;
|
|
9999
|
+
});
|
|
10000
|
+
if (!changed) return base;
|
|
10001
|
+
var merged = { ...base, runs };
|
|
10002
|
+
if (explicitReview && !newer) {
|
|
10003
|
+
merged.updatedAt = new Date(Math.max(
|
|
10004
|
+
Date.now(),
|
|
10005
|
+
Date.parse(existing.updatedAt) || 0,
|
|
10006
|
+
Date.parse(incoming.updatedAt) || 0
|
|
10007
|
+
) + 1).toISOString();
|
|
10008
|
+
}
|
|
10009
|
+
return merged;
|
|
10010
|
+
}
|
|
9857
10011
|
function hashString(value) {
|
|
9858
10012
|
var hash = 2166136261;
|
|
9859
10013
|
var text = String(value || "");
|
|
@@ -9865,9 +10019,11 @@ ${block}`;
|
|
|
9865
10019
|
}
|
|
9866
10020
|
return {
|
|
9867
10021
|
compactStructuredEventValue,
|
|
10022
|
+
mergeSessionReviewState,
|
|
9868
10023
|
compactRunsForStorage,
|
|
9869
10024
|
compactRunActionPayload,
|
|
9870
10025
|
compactProviderSnapshot,
|
|
10026
|
+
compactRunExecutionSnapshot,
|
|
9871
10027
|
hashString
|
|
9872
10028
|
};
|
|
9873
10029
|
});
|
|
@@ -9945,19 +10101,21 @@ ${block}`;
|
|
|
9945
10101
|
require2("./storageRunActions"),
|
|
9946
10102
|
require2("./runInputQueue"),
|
|
9947
10103
|
require2("./settlementFacts"),
|
|
9948
|
-
require2("./storageSessionClaims")
|
|
10104
|
+
require2("./storageSessionClaims"),
|
|
10105
|
+
require2("./sessionState")
|
|
9949
10106
|
);
|
|
9950
10107
|
} else {
|
|
9951
10108
|
root.CodexOverleafModuleRegistry.define("StorageDb", [
|
|
9952
10109
|
"StorageRunActions",
|
|
9953
10110
|
"RunInputQueue",
|
|
9954
10111
|
"SettlementFacts",
|
|
9955
|
-
"StorageSessionClaims"
|
|
10112
|
+
"StorageSessionClaims",
|
|
10113
|
+
"SessionState"
|
|
9956
10114
|
], factory);
|
|
9957
10115
|
}
|
|
9958
|
-
})(typeof globalThis !== "undefined" ? globalThis : window, function storageDbFactory(StorageRunActions, RunInputQueue, SettlementFacts, StorageSessionClaims) {
|
|
10116
|
+
})(typeof globalThis !== "undefined" ? globalThis : window, function storageDbFactory(StorageRunActions, RunInputQueue, SettlementFacts, StorageSessionClaims, SessionState) {
|
|
9959
10117
|
"use strict";
|
|
9960
|
-
if (!StorageRunActions?.compactRunsForStorage || !StorageRunActions?.compactRunActionPayload || !StorageRunActions?.compactProviderSnapshot || !StorageRunActions?.compactStructuredEventValue || !StorageRunActions?.hashString || !RunInputQueue?.compactForStorage || !SettlementFacts?.compactSettlementFacts || !StorageSessionClaims?.createSessionClaimer) {
|
|
10118
|
+
if (!StorageRunActions?.compactRunsForStorage || !StorageRunActions?.compactRunActionPayload || !StorageRunActions?.compactProviderSnapshot || !StorageRunActions?.compactRunExecutionSnapshot || !StorageRunActions?.compactStructuredEventValue || !StorageRunActions?.hashString || !RunInputQueue?.compactForStorage || !SettlementFacts?.compactSettlementFacts || !StorageSessionClaims?.createSessionClaimer) {
|
|
9961
10119
|
throw new Error("Codex Overleaf storage run-action helpers are unavailable.");
|
|
9962
10120
|
}
|
|
9963
10121
|
var TARGET_SCHEMA_VERSION = 3;
|
|
@@ -10225,6 +10383,7 @@ ${block}`;
|
|
|
10225
10383
|
codexThreadId: typeof input.codexThreadId === "string" ? input.codexThreadId : "",
|
|
10226
10384
|
status: typeof input.status === "string" && input.status ? input.status : "active",
|
|
10227
10385
|
focusFiles: normalizePathList(input.focusFiles),
|
|
10386
|
+
projectReferenceFiles: SessionState.normalizeProjectReferenceFiles(input.projectReferenceFiles),
|
|
10228
10387
|
pendingInputs: RunInputQueue.compactForStorage(input.pendingInputs, {
|
|
10229
10388
|
normalizeField: normalizeTextField,
|
|
10230
10389
|
normalizeDisplay: normalizeDisplayTextForStorage,
|
|
@@ -10264,8 +10423,8 @@ ${block}`;
|
|
|
10264
10423
|
}
|
|
10265
10424
|
}
|
|
10266
10425
|
function deriveSafeTaskSummaryFromInput(input) {
|
|
10267
|
-
var
|
|
10268
|
-
if (!
|
|
10426
|
+
var SessionState2 = loadSessionState();
|
|
10427
|
+
if (!SessionState2 || !(SessionState2.computeSafeTaskSummary instanceof Function)) {
|
|
10269
10428
|
return "";
|
|
10270
10429
|
}
|
|
10271
10430
|
var task = typeof input.task === "string" && input.task ? input.task : "";
|
|
@@ -10275,7 +10434,7 @@ ${block}`;
|
|
|
10275
10434
|
task = firstRun.task;
|
|
10276
10435
|
}
|
|
10277
10436
|
}
|
|
10278
|
-
return
|
|
10437
|
+
return SessionState2.computeSafeTaskSummary(task);
|
|
10279
10438
|
}
|
|
10280
10439
|
var _sessionStateCache = null;
|
|
10281
10440
|
function loadSessionState() {
|
|
@@ -10560,12 +10719,7 @@ ${block}`;
|
|
|
10560
10719
|
});
|
|
10561
10720
|
}
|
|
10562
10721
|
function compactRunsForStorage(runs, options2) {
|
|
10563
|
-
return StorageRunActions.compactRunsForStorage(
|
|
10564
|
-
runs,
|
|
10565
|
-
options2,
|
|
10566
|
-
SESSION_STORAGE_LIMITS.maxRunsPerSession,
|
|
10567
|
-
compactRunForStorage
|
|
10568
|
-
);
|
|
10722
|
+
return StorageRunActions.compactRunsForStorage(runs, options2, SESSION_STORAGE_LIMITS.maxRunsPerSession, compactRunForStorage);
|
|
10569
10723
|
}
|
|
10570
10724
|
function compactRunForStorage(run, keepActionPayload) {
|
|
10571
10725
|
var actionPayload = StorageRunActions.compactRunActionPayload(run, keepActionPayload);
|
|
@@ -10574,6 +10728,9 @@ ${block}`;
|
|
|
10574
10728
|
task: normalizeDisplayTextForStorage(run.task || "untitled task", SESSION_STORAGE_LIMITS.taskChars),
|
|
10575
10729
|
mode: typeof run.mode === "string" ? redactSecretLikeText(run.mode) : "",
|
|
10576
10730
|
...StorageRunActions.compactProviderSnapshot(run),
|
|
10731
|
+
...StorageRunActions.compactRunExecutionSnapshot(run, function(text) {
|
|
10732
|
+
return normalizeTextField(text, 4096);
|
|
10733
|
+
}),
|
|
10577
10734
|
model: normalizeTextField(run.model, 80),
|
|
10578
10735
|
reasoningEffort: typeof run.reasoningEffort === "string" ? redactSecretLikeText(run.reasoningEffort) : "",
|
|
10579
10736
|
speedTier: typeof run.speedTier === "string" ? redactSecretLikeText(run.speedTier) : "",
|
|
@@ -10589,8 +10746,10 @@ ${block}`;
|
|
|
10589
10746
|
undoBaseFiles: actionPayload.undoBaseFiles,
|
|
10590
10747
|
undoTrackedChanges: actionPayload.undoTrackedChanges,
|
|
10591
10748
|
undoExpectedFiles: actionPayload.undoExpectedFiles,
|
|
10749
|
+
...actionPayload.trackedChangeCaptures ? { trackedChangeCaptures: actionPayload.trackedChangeCaptures } : {},
|
|
10592
10750
|
undoStatus: normalizeDisplayTextForStorage(run.undoStatus, SESSION_STORAGE_LIMITS.statusTextChars),
|
|
10593
10751
|
nativeRequestId: normalizeTextField(run.nativeRequestId, 160),
|
|
10752
|
+
codexThreadId: normalizeTextField(run.codexThreadId, 160),
|
|
10594
10753
|
codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
10595
10754
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
10596
10755
|
queueItemId: normalizeTextField(run.queueItemId, 160)
|
|
@@ -11149,6 +11308,7 @@ ${block}`;
|
|
|
11149
11308
|
clearStore,
|
|
11150
11309
|
clearAllStores,
|
|
11151
11310
|
buildSessionRecord,
|
|
11311
|
+
mergeSessionReviewState: StorageRunActions.mergeSessionReviewState,
|
|
11152
11312
|
buildTurnRecord,
|
|
11153
11313
|
buildEventRecord,
|
|
11154
11314
|
buildArtifactRecord,
|
|
@@ -11775,7 +11935,7 @@ ${block}`;
|
|
|
11775
11935
|
const MIN_NATIVE_VERSION = "1.0.0";
|
|
11776
11936
|
const MIN_COMPATIBLE_NATIVE_VERSION = "1.0.0";
|
|
11777
11937
|
const MIN_COMPATIBLE_EXTENSION_VERSION = "1.0.0";
|
|
11778
|
-
const BUILD_TARGET_VERSION = "2.
|
|
11938
|
+
const BUILD_TARGET_VERSION = "2.4.1";
|
|
11779
11939
|
const DEFAULT_CHROME_EXTENSION_ID = "illdpneeeopfffmiepaejglgmhpmdhdc";
|
|
11780
11940
|
const REQUIRED_CAPABILITIES = Object.freeze([
|
|
11781
11941
|
"bridgePing",
|
|
@@ -12078,7 +12238,7 @@ ${block}`;
|
|
|
12078
12238
|
if (root) root.CodexOverleafPageRpcContract = api;
|
|
12079
12239
|
})(typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : this, function() {
|
|
12080
12240
|
"use strict";
|
|
12081
|
-
var REVISION = "2026-
|
|
12241
|
+
var REVISION = "2026-09-14-native-text-upload-v28";
|
|
12082
12242
|
var METHODS = freezeCatalog({
|
|
12083
12243
|
initializeCapability: entry("bridge.initialize", "control", "none", "default", false, "none"),
|
|
12084
12244
|
probe: entry("bridge.probe", "read", "none", "default", false, "safe"),
|
|
@@ -12095,6 +12255,7 @@ ${block}`;
|
|
|
12095
12255
|
binaryUploadCommit: entry("asset.write", "document", "required", "writeback", true, "no_retry"),
|
|
12096
12256
|
binaryUploadAbort: entry("asset.stage", "cache", "none", "default", false, "idempotent"),
|
|
12097
12257
|
jumpToPosition: entry("editor.navigate", "navigation", "required", "default", false, "idempotent"),
|
|
12258
|
+
reconcileTrackedChangeCapture: entry("tracked_changes.read", "read", "required", "default", false, "safe"),
|
|
12098
12259
|
rejectTrackedChanges: entry("tracked_changes.reject", "document", "required", "lifecycle", true, "no_retry"),
|
|
12099
12260
|
acceptTrackedChanges: entry("tracked_changes.accept", "document", "required", "lifecycle", true, "no_retry"),
|
|
12100
12261
|
triggerCompile: entry("compile.trigger", "page_state", "required", "compile", false, "no_retry"),
|
|
@@ -13463,9 +13624,11 @@ ${block}`;
|
|
|
13463
13624
|
["src/page/overleafProjectSnapshot.js", "codex-overleaf-project-snapshot-script"],
|
|
13464
13625
|
["src/page/pageBridgeCapability.js", "codex-overleaf-page-bridge-capability-script"],
|
|
13465
13626
|
["src/page/treeOperations.js", "codex-overleaf-tree-operations-script", true],
|
|
13627
|
+
["src/page/textFileCreator.js", "codex-overleaf-text-file-creator-script", true],
|
|
13466
13628
|
["src/page/binaryAssetUploader.js", "codex-overleaf-binary-asset-uploader-script", true],
|
|
13467
13629
|
["src/page/snapshotRouter.js", "codex-overleaf-snapshot-router-script"],
|
|
13468
13630
|
["src/page/writeGuard.js", "codex-overleaf-write-guard-script", true],
|
|
13631
|
+
["src/page/trackedChangeCapture.js", "codex-overleaf-tracked-change-capture-script", true],
|
|
13469
13632
|
["src/page/trackedChangesLifecycle.js", "codex-overleaf-tracked-changes-lifecycle-script", true],
|
|
13470
13633
|
["src/page/writebackRouter.js", "codex-overleaf-writeback-router-script", true],
|
|
13471
13634
|
["src/pageBridge.js", "codex-overleaf-page-bridge-script", true]
|
|
@@ -13665,7 +13828,9 @@ ${block}`;
|
|
|
13665
13828
|
async function dispatch(payload, channelMethod) {
|
|
13666
13829
|
const compatibilityGate = await ensureForMethod(payload?.method);
|
|
13667
13830
|
if (!compatibilityGate.ok) return compatibilityGate.response;
|
|
13668
|
-
if (gatedMethods.has(payload?.method)
|
|
13831
|
+
if (gatedMethods.has(payload?.method) && payload.method !== "mirror.invalidate") {
|
|
13832
|
+
options2.throwIfCancellationRequested?.();
|
|
13833
|
+
}
|
|
13669
13834
|
return nativeChannel[channelMethod](
|
|
13670
13835
|
attachEvidence(payload, compatibilityGate.compatibility)
|
|
13671
13836
|
);
|
|
@@ -14318,8 +14483,10 @@ ${block}`;
|
|
|
14318
14483
|
merged.applied.push(...Array.isArray(result?.applied) ? result.applied : []);
|
|
14319
14484
|
merged.skipped.push(...Array.isArray(result?.skipped) ? result.skipped : []);
|
|
14320
14485
|
merged.trackedChanges.push(...Array.isArray(result?.trackedChanges) ? result.trackedChanges : []);
|
|
14486
|
+
if (result?.trackedChangeCaptures?.length) (merged.trackedChangeCaptures || (merged.trackedChangeCaptures = [])).push(...result.trackedChangeCaptures);
|
|
14321
14487
|
if (result?.ok !== true) merged.ok = false;
|
|
14322
14488
|
}
|
|
14489
|
+
if (merged.trackedChangeCaptures?.some((capture) => capture.state !== "observed")) merged.trackedChanges = [];
|
|
14323
14490
|
if (merged.skipped.length) merged.ok = false;
|
|
14324
14491
|
return merged;
|
|
14325
14492
|
}
|
|
@@ -15315,6 +15482,8 @@ ${block}`;
|
|
|
15315
15482
|
saveState = null,
|
|
15316
15483
|
saveStateSoon = () => {
|
|
15317
15484
|
},
|
|
15485
|
+
onProjectFilesReady = () => {
|
|
15486
|
+
},
|
|
15318
15487
|
updateActiveSession = defaultUpdateActiveSession,
|
|
15319
15488
|
callPageBridge = () => Promise.resolve({ ok: false }),
|
|
15320
15489
|
getCurrentProjectId = () => "",
|
|
@@ -15478,6 +15647,7 @@ ${block}`;
|
|
|
15478
15647
|
renderContextFiles(contextProject);
|
|
15479
15648
|
if (isExactContextFileListProject(contextProject)) {
|
|
15480
15649
|
setContextSyncState("exact-ready");
|
|
15650
|
+
onProjectFilesReady(contextProject);
|
|
15481
15651
|
} else if (contextSyncState !== "partial") {
|
|
15482
15652
|
setContextSyncState("exact-loading");
|
|
15483
15653
|
void enhanceContextFilesFromExactSnapshot({ loadId: contextLoadId });
|
|
@@ -15499,6 +15669,7 @@ ${block}`;
|
|
|
15499
15669
|
contextProject = project;
|
|
15500
15670
|
setContextSyncState(isExactContextFileListProject(project) ? "exact-ready" : "exact-loading");
|
|
15501
15671
|
renderContextFiles(project);
|
|
15672
|
+
if (isExactContextFileListProject(project)) onProjectFilesReady(project);
|
|
15502
15673
|
if (!isExactContextFileListProject(project)) {
|
|
15503
15674
|
void enhanceContextFilesFromExactSnapshot({
|
|
15504
15675
|
force: Boolean(options2.force),
|
|
@@ -15556,6 +15727,7 @@ ${block}`;
|
|
|
15556
15727
|
contextProject = project;
|
|
15557
15728
|
setContextSyncState("exact-ready");
|
|
15558
15729
|
renderContextFiles(project);
|
|
15730
|
+
onProjectFilesReady(project);
|
|
15559
15731
|
} catch (_error) {
|
|
15560
15732
|
if (loadId === contextLoadId) {
|
|
15561
15733
|
setContextSyncState("partial");
|
|
@@ -16756,6 +16928,20 @@ ${block}`;
|
|
|
16756
16928
|
})) return { ok: false, reason: "ot_event_expired" };
|
|
16757
16929
|
return { ok: true };
|
|
16758
16930
|
}
|
|
16931
|
+
function readOtBridgeStatus(response) {
|
|
16932
|
+
if (!response || response.ok === false) return "unavailable";
|
|
16933
|
+
return response.state || response.status || response.result?.state || response.result?.status || "unavailable";
|
|
16934
|
+
}
|
|
16935
|
+
function readOtBridgeEvents(response) {
|
|
16936
|
+
if (Array.isArray(response)) return response;
|
|
16937
|
+
if (Array.isArray(response?.events)) return response.events;
|
|
16938
|
+
if (Array.isArray(response?.result?.events)) return response.result.events;
|
|
16939
|
+
return [];
|
|
16940
|
+
}
|
|
16941
|
+
function readOtBridgeErrorCode(response, fallback) {
|
|
16942
|
+
const value = response?.lastErrorCode || response?.reason || response?.error?.code || response?.error || fallback;
|
|
16943
|
+
return typeof value === "string" ? value : fallback;
|
|
16944
|
+
}
|
|
16759
16945
|
function normalizeFailureCode(value, fallback = "ot_error") {
|
|
16760
16946
|
const code = typeof value === "string" ? value : value?.code;
|
|
16761
16947
|
if (/^[a-z][a-z0-9_]{0,79}$/.test(code || "")) return code;
|
|
@@ -16833,6 +17019,9 @@ ${block}`;
|
|
|
16833
17019
|
takePatchBatch,
|
|
16834
17020
|
validatePatchReceipt,
|
|
16835
17021
|
normalizeFailureCode,
|
|
17022
|
+
readOtBridgeStatus,
|
|
17023
|
+
readOtBridgeEvents,
|
|
17024
|
+
readOtBridgeErrorCode,
|
|
16836
17025
|
getFailureMessageKey,
|
|
16837
17026
|
buildPatchFilesRequest,
|
|
16838
17027
|
canUseOtWarmStart,
|
|
@@ -17976,8 +18165,8 @@ ${block}`;
|
|
|
17976
18165
|
<div class="codex-custom-instructions-head">
|
|
17977
18166
|
<button type="button" data-settings-back title="Back" aria-label="Back">\u2039</button>
|
|
17978
18167
|
<div>
|
|
17979
|
-
<div class="codex-custom-instructions-title" data-i18n="projectSettingsTitle">Project Settings</div>
|
|
17980
|
-
<div class="codex-custom-instructions-subtitle" data-i18n="projectSettingsSubtitle">Customize how Codex behaves in this and all projects.</div>
|
|
18168
|
+
<div class="codex-custom-instructions-title" data-settings-title data-i18n="projectSettingsTitle">Project Settings</div>
|
|
18169
|
+
<div class="codex-custom-instructions-subtitle" data-settings-subtitle data-i18n="projectSettingsSubtitle">Customize how Codex behaves in this and all projects.</div>
|
|
17981
18170
|
</div>
|
|
17982
18171
|
</div>
|
|
17983
18172
|
<div class="codex-project-settings-status" data-project-settings-status></div>
|
|
@@ -18235,6 +18424,7 @@ ${block}`;
|
|
|
18235
18424
|
if (!root) {
|
|
18236
18425
|
return;
|
|
18237
18426
|
}
|
|
18427
|
+
refreshSettingsScope(instance, root);
|
|
18238
18428
|
const button = getButton(instance);
|
|
18239
18429
|
if (button) {
|
|
18240
18430
|
button.dataset.active = "true";
|
|
@@ -18242,6 +18432,17 @@ ${block}`;
|
|
|
18242
18432
|
}
|
|
18243
18433
|
root.querySelector("[data-custom-instructions-input]")?.focus?.();
|
|
18244
18434
|
}
|
|
18435
|
+
function refreshSettingsScope(instance, root) {
|
|
18436
|
+
const accountScope = instance.container?.closest?.("[data-settings-scope]")?.dataset?.settingsScope === "account";
|
|
18437
|
+
const prefix = accountScope ? "recentProjects_settings" : "projectSettings";
|
|
18438
|
+
for (const [selector, suffix] of [["[data-settings-title]", "Title"], ["[data-settings-subtitle]", "Subtitle"]]) {
|
|
18439
|
+
const label = root.querySelector(selector);
|
|
18440
|
+
if (!label) continue;
|
|
18441
|
+
const key = prefix + suffix;
|
|
18442
|
+
label.setAttribute("data-i18n", key);
|
|
18443
|
+
label.textContent = t(instance, key);
|
|
18444
|
+
}
|
|
18445
|
+
}
|
|
18245
18446
|
function hide(target) {
|
|
18246
18447
|
const instance = target?._instance || target;
|
|
18247
18448
|
const root = getRoot(instance);
|
|
@@ -18269,6 +18470,7 @@ ${block}`;
|
|
|
18269
18470
|
if (!root) {
|
|
18270
18471
|
return;
|
|
18271
18472
|
}
|
|
18473
|
+
refreshSettingsScope(instance, root);
|
|
18272
18474
|
if (Object.prototype.hasOwnProperty.call(state, "customInstructions")) {
|
|
18273
18475
|
const input = root.querySelector("[data-custom-instructions-input]");
|
|
18274
18476
|
if (input) {
|
|
@@ -20132,7 +20334,12 @@ ${block}`;
|
|
|
20132
20334
|
await Promise.all(deletedExisting.map((record) => StorageDb.deleteRecord("sessions", record.id)));
|
|
20133
20335
|
}
|
|
20134
20336
|
const existingById = new Map(existingSessions.filter((record) => !deleted.has(record.id)).map((record) => [record.id, record]));
|
|
20135
|
-
const
|
|
20337
|
+
const mergedRecords = sessionRecords.map((record) => StorageDb.mergeSessionReviewState?.(
|
|
20338
|
+
record,
|
|
20339
|
+
existingById.get(record.id),
|
|
20340
|
+
options2.reviewRunIds
|
|
20341
|
+
) || record);
|
|
20342
|
+
const writable = mergedRecords.filter((record) => {
|
|
20136
20343
|
const existing = existingById.get(record.id);
|
|
20137
20344
|
if (!existing) return true;
|
|
20138
20345
|
return (Date.parse(record.updatedAt || "") || 0) >= (Date.parse(existing.updatedAt || "") || 0);
|
|
@@ -20188,6 +20395,41 @@ ${block}`;
|
|
|
20188
20395
|
}
|
|
20189
20396
|
return JSON.parse(JSON.stringify(value));
|
|
20190
20397
|
}
|
|
20398
|
+
async function applyReviewTransition({ getState, runId, transition, persist }) {
|
|
20399
|
+
const targets = () => Array.from(/* @__PURE__ */ new Set([
|
|
20400
|
+
...getState().runs || [],
|
|
20401
|
+
...(getState().sessions || []).flatMap((session) => session.runs || [])
|
|
20402
|
+
])).filter((run) => run.id === runId);
|
|
20403
|
+
const records = targets();
|
|
20404
|
+
const sessions = (getState().sessions || []).filter((session) => (session.runs || []).some((run) => run.id === runId));
|
|
20405
|
+
if (!records.length || !sessions.length) throw reviewPersistenceError();
|
|
20406
|
+
const previous = cloneSnapshot(records[0]);
|
|
20407
|
+
for (const record of records) Object.assign(record, cloneSnapshot(transition));
|
|
20408
|
+
for (const session of sessions) {
|
|
20409
|
+
session.updatedAt = new Date(Math.max(
|
|
20410
|
+
Date.now(),
|
|
20411
|
+
(Date.parse(session.updatedAt) || 0) + 1,
|
|
20412
|
+
(Date.parse(session.lastActivityAt) || 0) + 1
|
|
20413
|
+
)).toISOString();
|
|
20414
|
+
session.lastActivityAt = session.updatedAt;
|
|
20415
|
+
}
|
|
20416
|
+
try {
|
|
20417
|
+
await persist({ preserveRunActionPayload: true, reviewRunIds: [runId] });
|
|
20418
|
+
} catch (error) {
|
|
20419
|
+
for (const record of targets()) {
|
|
20420
|
+
Object.assign(record, cloneSnapshot(previous), { trackedChangeStatus: "needs_review" });
|
|
20421
|
+
for (const field of ["settlement", "settlementFacts"]) {
|
|
20422
|
+
if (!Object.prototype.hasOwnProperty.call(previous, field)) delete record[field];
|
|
20423
|
+
}
|
|
20424
|
+
}
|
|
20425
|
+
throw error;
|
|
20426
|
+
}
|
|
20427
|
+
}
|
|
20428
|
+
function reviewPersistenceError() {
|
|
20429
|
+
return Object.assign(new Error("The review outcome was not durably saved. Check Overleaf before retrying."), {
|
|
20430
|
+
code: "review_state_not_persisted"
|
|
20431
|
+
});
|
|
20432
|
+
}
|
|
20191
20433
|
async function persistPanelState(input) {
|
|
20192
20434
|
var state = cloneSnapshot(input.state || {});
|
|
20193
20435
|
var compactState = cloneSnapshot(input.compactState || {});
|
|
@@ -20206,6 +20448,8 @@ ${block}`;
|
|
|
20206
20448
|
code: "stale_view"
|
|
20207
20449
|
});
|
|
20208
20450
|
}
|
|
20451
|
+
var reviewRuns = (input.reviewRunIds || []).map((id) => (state.sessions || []).flatMap((session) => session.runs || []).find((run) => run.id === id));
|
|
20452
|
+
if (reviewRuns.some((run) => !run)) throw reviewPersistenceError();
|
|
20209
20453
|
var latestPrefs = typeof Migration.loadPrefs === "function" ? await Migration.loadPrefs(accountScopeId, projectId) : {};
|
|
20210
20454
|
var prefs = Object.assign(
|
|
20211
20455
|
{},
|
|
@@ -20261,19 +20505,23 @@ ${block}`;
|
|
|
20261
20505
|
})
|
|
20262
20506
|
}), { preserveRunActionPayload: true });
|
|
20263
20507
|
});
|
|
20264
|
-
await input.SessionPersistence.writeSessions({
|
|
20508
|
+
var written = await input.SessionPersistence.writeSessions({
|
|
20265
20509
|
Migration,
|
|
20266
20510
|
StorageDb,
|
|
20267
20511
|
projectId,
|
|
20268
20512
|
accountScopeId,
|
|
20269
20513
|
deletedSessionIds,
|
|
20270
20514
|
sessionRecords,
|
|
20515
|
+
reviewRunIds: input.reviewRunIds,
|
|
20271
20516
|
queueClaims: persistenceMeta.queueClaims || {},
|
|
20272
20517
|
queueTombstones,
|
|
20273
20518
|
writerId: input.persistenceContext?.writerId || ""
|
|
20274
20519
|
});
|
|
20520
|
+
if (!reviewRuns.every((reviewRun) => (written || []).some((session) => (session.runs || []).some(
|
|
20521
|
+
(run) => run.id === reviewRun.id && run.trackedChangeStatus === reviewRun.trackedChangeStatus
|
|
20522
|
+
)))) throw reviewPersistenceError();
|
|
20275
20523
|
}
|
|
20276
|
-
return Object.freeze({ persistPanelState });
|
|
20524
|
+
return Object.freeze({ persistPanelState, applyReviewTransition });
|
|
20277
20525
|
});
|
|
20278
20526
|
}).call(globalThis, void 0, void 0, void 0);
|
|
20279
20527
|
(function runClassicContentModule63(module, exports, require2) {
|
|
@@ -20412,7 +20660,8 @@ ${block}`;
|
|
|
20412
20660
|
}
|
|
20413
20661
|
return Object.freeze({
|
|
20414
20662
|
createController,
|
|
20415
|
-
persistPanelState: PanelState?.persistPanelState || null
|
|
20663
|
+
persistPanelState: PanelState?.persistPanelState || null,
|
|
20664
|
+
applyReviewTransition: PanelState?.applyReviewTransition || null
|
|
20416
20665
|
});
|
|
20417
20666
|
});
|
|
20418
20667
|
}).call(globalThis, void 0, void 0, void 0);
|
|
@@ -20428,7 +20677,8 @@ ${block}`;
|
|
|
20428
20677
|
container,
|
|
20429
20678
|
callbacks: options2.callbacks || {},
|
|
20430
20679
|
i18n: options2.i18n || {},
|
|
20431
|
-
dismissInstalled: false
|
|
20680
|
+
dismissInstalled: false,
|
|
20681
|
+
cleanup: []
|
|
20432
20682
|
};
|
|
20433
20683
|
container.innerHTML = `
|
|
20434
20684
|
<div class="codex-diagnostics-wrap">
|
|
@@ -20512,6 +20762,11 @@ ${block}`;
|
|
|
20512
20762
|
instance.callbacks.onBeforeOpen?.();
|
|
20513
20763
|
}
|
|
20514
20764
|
popover.hidden = !open;
|
|
20765
|
+
if (open) {
|
|
20766
|
+
openFloating(instance, popover, 300);
|
|
20767
|
+
} else {
|
|
20768
|
+
hideFloating(popover);
|
|
20769
|
+
}
|
|
20515
20770
|
button.dataset.active = open ? "true" : "false";
|
|
20516
20771
|
button.setAttribute("aria-expanded", open ? "true" : "false");
|
|
20517
20772
|
}
|
|
@@ -20522,7 +20777,7 @@ ${block}`;
|
|
|
20522
20777
|
if (!popover || !button) {
|
|
20523
20778
|
return;
|
|
20524
20779
|
}
|
|
20525
|
-
popover
|
|
20780
|
+
hideFloating(popover);
|
|
20526
20781
|
button.dataset.active = "false";
|
|
20527
20782
|
button.setAttribute("aria-expanded", "false");
|
|
20528
20783
|
}
|
|
@@ -20530,7 +20785,7 @@ ${block}`;
|
|
|
20530
20785
|
const instance = target?._instance || target;
|
|
20531
20786
|
const result = instance?.container?.querySelector("[data-diagnostics-result]");
|
|
20532
20787
|
if (result) {
|
|
20533
|
-
result
|
|
20788
|
+
hideFloating(result);
|
|
20534
20789
|
}
|
|
20535
20790
|
}
|
|
20536
20791
|
function showLoading(target, title, subtitle) {
|
|
@@ -20586,6 +20841,65 @@ ${block}`;
|
|
|
20586
20841
|
details.open = false;
|
|
20587
20842
|
details.hidden = !technicalText;
|
|
20588
20843
|
technical.textContent = technicalText;
|
|
20844
|
+
closeMenu(instance);
|
|
20845
|
+
openFloating(instance, root, 560);
|
|
20846
|
+
}
|
|
20847
|
+
function openFloating(instance, element, preferredWidth) {
|
|
20848
|
+
if (element.isConnected === false) return;
|
|
20849
|
+
element.hidden = false;
|
|
20850
|
+
if (typeof element.showPopover === "function") {
|
|
20851
|
+
element.setAttribute("popover", "manual");
|
|
20852
|
+
try {
|
|
20853
|
+
if (!element.matches(":popover-open")) element.showPopover();
|
|
20854
|
+
} catch (_error) {
|
|
20855
|
+
element.removeAttribute("popover");
|
|
20856
|
+
}
|
|
20857
|
+
}
|
|
20858
|
+
positionFloating(instance, element, preferredWidth);
|
|
20859
|
+
}
|
|
20860
|
+
function hideFloating(element) {
|
|
20861
|
+
if (!element) return;
|
|
20862
|
+
if (typeof element.hidePopover === "function" && element.getAttribute("popover") === "manual") {
|
|
20863
|
+
try {
|
|
20864
|
+
if (element.matches(":popover-open")) element.hidePopover();
|
|
20865
|
+
} catch (_error) {
|
|
20866
|
+
element.removeAttribute("popover");
|
|
20867
|
+
}
|
|
20868
|
+
}
|
|
20869
|
+
element.hidden = true;
|
|
20870
|
+
}
|
|
20871
|
+
function positionFloating(instance, element, preferredWidth) {
|
|
20872
|
+
if (!element || element.hidden) return;
|
|
20873
|
+
const button = instance.container.querySelector("[data-diagnostics-menu]");
|
|
20874
|
+
if (!button?.getBoundingClientRect || !element.getBoundingClientRect) return;
|
|
20875
|
+
if (button.getClientRects && !button.getClientRects().length) {
|
|
20876
|
+
closeMenu(instance);
|
|
20877
|
+
closeResult(instance);
|
|
20878
|
+
return;
|
|
20879
|
+
}
|
|
20880
|
+
const doc = instance.container.ownerDocument || document;
|
|
20881
|
+
const view = doc.defaultView || window;
|
|
20882
|
+
const viewport = view.visualViewport;
|
|
20883
|
+
const width = viewport?.width || view.innerWidth || doc.documentElement?.clientWidth;
|
|
20884
|
+
const height = viewport?.height || view.innerHeight || doc.documentElement?.clientHeight;
|
|
20885
|
+
if (!(width > 0 && height > 0)) return;
|
|
20886
|
+
const margin = 12;
|
|
20887
|
+
const gap = 8;
|
|
20888
|
+
const leftEdge = (viewport?.offsetLeft || 0) + margin;
|
|
20889
|
+
const topEdge = (viewport?.offsetTop || 0) + margin;
|
|
20890
|
+
const rightEdge = leftEdge + Math.max(0, width - margin * 2);
|
|
20891
|
+
const bottomEdge = topEdge + Math.max(0, height - margin * 2);
|
|
20892
|
+
element.style.width = `${Math.min(preferredWidth, Math.max(0, width - margin * 2))}px`;
|
|
20893
|
+
element.style.maxHeight = `${Math.min(640, Math.max(0, height - margin * 2))}px`;
|
|
20894
|
+
const anchor = button.getBoundingClientRect();
|
|
20895
|
+
const bounds = element.getBoundingClientRect();
|
|
20896
|
+
const below = Math.max(0, bottomEdge - anchor.bottom - gap);
|
|
20897
|
+
const above = Math.max(0, anchor.top - topEdge - gap);
|
|
20898
|
+
const desiredTop = bounds.height > below && above > below ? anchor.top - gap - bounds.height : anchor.bottom + gap;
|
|
20899
|
+
element.style.left = `${Math.max(leftEdge, Math.min(anchor.right - bounds.width, rightEdge - bounds.width))}px`;
|
|
20900
|
+
element.style.top = `${Math.max(topEdge, Math.min(desiredTop, bottomEdge - bounds.height))}px`;
|
|
20901
|
+
element.style.right = "auto";
|
|
20902
|
+
element.style.bottom = "auto";
|
|
20589
20903
|
}
|
|
20590
20904
|
function renderInstallCommand(instance, container, command) {
|
|
20591
20905
|
const wrap = document.createElement("div");
|
|
@@ -20660,13 +20974,60 @@ ${block}`;
|
|
|
20660
20974
|
return;
|
|
20661
20975
|
}
|
|
20662
20976
|
instance.dismissInstalled = true;
|
|
20663
|
-
|
|
20977
|
+
const doc = instance.container.ownerDocument || document;
|
|
20978
|
+
const view = doc.defaultView || window;
|
|
20979
|
+
const listen = (target, type, handler, options2) => {
|
|
20980
|
+
if (!target?.addEventListener) return;
|
|
20981
|
+
target.addEventListener(type, handler, options2);
|
|
20982
|
+
instance.cleanup.push(() => target.removeEventListener(type, handler, options2));
|
|
20983
|
+
};
|
|
20984
|
+
listen(doc, "click", (event) => {
|
|
20664
20985
|
const wrap = instance.container?.querySelector(".codex-diagnostics-wrap");
|
|
20665
20986
|
if (!wrap || wrap.contains(event.target)) {
|
|
20666
20987
|
return;
|
|
20667
20988
|
}
|
|
20668
20989
|
closeMenu(instance);
|
|
20669
20990
|
}, true);
|
|
20991
|
+
listen(doc, "keydown", (event) => {
|
|
20992
|
+
if (event.key !== "Escape") return;
|
|
20993
|
+
const menu = instance.container.querySelector("[data-diagnostics-popover]");
|
|
20994
|
+
const result = instance.container.querySelector("[data-diagnostics-result]");
|
|
20995
|
+
if (menu && !menu.hidden) closeMenu(instance);
|
|
20996
|
+
else if (result && !result.hidden) closeResult(instance);
|
|
20997
|
+
else return;
|
|
20998
|
+
event.preventDefault();
|
|
20999
|
+
event.stopPropagation();
|
|
21000
|
+
instance.container.querySelector("[data-diagnostics-menu]")?.focus();
|
|
21001
|
+
}, true);
|
|
21002
|
+
let frame = null;
|
|
21003
|
+
const reposition = () => {
|
|
21004
|
+
frame = null;
|
|
21005
|
+
positionFloating(instance, instance.container.querySelector("[data-diagnostics-popover]"), 300);
|
|
21006
|
+
positionFloating(instance, instance.container.querySelector("[data-diagnostics-result]"), 560);
|
|
21007
|
+
};
|
|
21008
|
+
const schedule = () => {
|
|
21009
|
+
if (frame !== null) return;
|
|
21010
|
+
if (view.requestAnimationFrame) frame = view.requestAnimationFrame(reposition);
|
|
21011
|
+
else reposition();
|
|
21012
|
+
};
|
|
21013
|
+
listen(view, "resize", schedule);
|
|
21014
|
+
listen(doc, "scroll", schedule, true);
|
|
21015
|
+
listen(view.visualViewport, "resize", schedule);
|
|
21016
|
+
listen(view.visualViewport, "scroll", schedule);
|
|
21017
|
+
if (typeof view.ResizeObserver === "function") {
|
|
21018
|
+
const observer = new view.ResizeObserver(schedule);
|
|
21019
|
+
for (const node of [
|
|
21020
|
+
instance.container.closest("#codex-overleaf-panel") || instance.container,
|
|
21021
|
+
instance.container.querySelector("[data-diagnostics-popover]"),
|
|
21022
|
+
instance.container.querySelector("[data-diagnostics-result]")
|
|
21023
|
+
]) {
|
|
21024
|
+
if (node) observer.observe(node);
|
|
21025
|
+
}
|
|
21026
|
+
instance.cleanup.push(() => observer.disconnect());
|
|
21027
|
+
}
|
|
21028
|
+
instance.cleanup.push(() => {
|
|
21029
|
+
if (frame !== null) view.cancelAnimationFrame?.(frame);
|
|
21030
|
+
});
|
|
20670
21031
|
}
|
|
20671
21032
|
const HEALTH_STATES = ["ok", "warn", "fail", "unknown"];
|
|
20672
21033
|
function updateStatus(target, status = {}) {
|
|
@@ -20823,6 +21184,10 @@ ${block}`;
|
|
|
20823
21184
|
return key;
|
|
20824
21185
|
}
|
|
20825
21186
|
function destroy(instance) {
|
|
21187
|
+
closeMenu(instance);
|
|
21188
|
+
closeResult(instance);
|
|
21189
|
+
for (const cleanup of instance.cleanup || []) cleanup();
|
|
21190
|
+
instance.cleanup = [];
|
|
20826
21191
|
instance.container.textContent = "";
|
|
20827
21192
|
}
|
|
20828
21193
|
window.CodexOverleafDiagnosticsPanel = {
|
|
@@ -21290,6 +21655,7 @@ ${block}`;
|
|
|
21290
21655
|
const raw = entry?.event || {};
|
|
21291
21656
|
if (raw.type === "codex.turn.bound") {
|
|
21292
21657
|
session.codexThreadId = String(raw.detail?.threadId || session.codexThreadId || "");
|
|
21658
|
+
record.codexThreadId = String(raw.detail?.threadId || record.codexThreadId || "");
|
|
21293
21659
|
record.codexTurnId = String(raw.detail?.turnId || record.codexTurnId || "");
|
|
21294
21660
|
record.nativeEventSeq = sequence;
|
|
21295
21661
|
continue;
|
|
@@ -29322,6 +29688,8 @@ failedAt: ${new Date(failure.at).toISOString()}`;
|
|
|
29322
29688
|
lines.push(`CodeMirror: docLength=${view.docLength || 0}; dispatch=${Boolean(view.hasDispatch)}; source=${view.source || "unknown"}`);
|
|
29323
29689
|
}
|
|
29324
29690
|
}
|
|
29691
|
+
const capture = probe?.trackedChangeCapture;
|
|
29692
|
+
if (capture) lines.push(tx("Tracked ledger: ", "\u7559\u75D5\u8BB0\u5F55\uFF1A") + "source=" + capture.source + "; ready=" + capture.ready + "; count=" + capture.count + "; doc=" + (capture.docId || "none") + "; adapter=" + capture.adapter + "; reason=" + (capture.reason || "none"));
|
|
29325
29693
|
const projectDiagnostics = probe?.projectDiagnostics;
|
|
29326
29694
|
if (projectDiagnostics) {
|
|
29327
29695
|
lines.push(`Project records: ${projectDiagnostics.docRecordCount || 0}; roots=${(projectDiagnostics.internalRootKeys || []).slice(0, 6).join(", ") || "none"}`);
|
|
@@ -29548,7 +29916,17 @@ failedAt: ${new Date(failure.at).toISOString()}`;
|
|
|
29548
29916
|
textarea.remove();
|
|
29549
29917
|
if (!copied) throw new Error("clipboard_copy_failed");
|
|
29550
29918
|
}
|
|
29551
|
-
return Object.freeze({ configureResultActions });
|
|
29919
|
+
return Object.freeze({ configureResultActions, projectUndoAvailability });
|
|
29920
|
+
}
|
|
29921
|
+
function projectUndoAvailability(run, projectRunSettlement) {
|
|
29922
|
+
const payload = run.recoveryPayload && typeof run.recoveryPayload === "object" ? run.recoveryPayload : run;
|
|
29923
|
+
if (!Array.isArray(payload.appliedOperations)) return projectRunSettlement(run);
|
|
29924
|
+
const appliedOperations = payload.appliedOperations.filter((operation) => operation?.type !== "binary-create" && operation?.type !== "overwrite-binary");
|
|
29925
|
+
if (appliedOperations.length === payload.appliedOperations.length) return projectRunSettlement(run);
|
|
29926
|
+
return projectRunSettlement({
|
|
29927
|
+
...run,
|
|
29928
|
+
recoveryPayload: { ...payload, appliedOperations }
|
|
29929
|
+
});
|
|
29552
29930
|
}
|
|
29553
29931
|
return Object.freeze({ create });
|
|
29554
29932
|
});
|
|
@@ -30580,7 +30958,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30580
30958
|
configureLifecycleUndoButton(button, run);
|
|
30581
30959
|
return;
|
|
30582
30960
|
}
|
|
30583
|
-
const projection =
|
|
30961
|
+
const projection = RunResultActions.projectUndoAvailability(run, projectRunSettlement);
|
|
30584
30962
|
if (!projection.canUndo && run.undoStatus !== "applied") {
|
|
30585
30963
|
button.hidden = true;
|
|
30586
30964
|
return;
|
|
@@ -30596,11 +30974,11 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30596
30974
|
}
|
|
30597
30975
|
function configureLifecycleUndoButton(button, run) {
|
|
30598
30976
|
const status = run.trackedChangeStatus || "";
|
|
30977
|
+
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30599
30978
|
const projection = projectRunSettlement(run);
|
|
30600
30979
|
if (status === "needs_review") {
|
|
30601
|
-
const inFlight2 = trackedChangeInFlight.get(run.id);
|
|
30602
30980
|
button.hidden = false;
|
|
30603
|
-
button.disabled = !projection.canUndo ||
|
|
30981
|
+
button.disabled = !projection.canUndo || inFlight === "reject" || inFlight === "accept";
|
|
30604
30982
|
button.textContent = tr("undoRun");
|
|
30605
30983
|
button.title = tr("undoRunTitle");
|
|
30606
30984
|
button.addEventListener("click", (event) => {
|
|
@@ -30609,25 +30987,24 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30609
30987
|
});
|
|
30610
30988
|
return;
|
|
30611
30989
|
}
|
|
30612
|
-
if (status === "rejected") {
|
|
30990
|
+
if (status === "rejected" && !inFlight) {
|
|
30613
30991
|
button.hidden = false;
|
|
30614
30992
|
button.disabled = true;
|
|
30615
30993
|
button.textContent = tr("undoApplied");
|
|
30616
30994
|
button.title = tr("undoAppliedTitle");
|
|
30617
30995
|
return;
|
|
30618
30996
|
}
|
|
30619
|
-
if (status === "accepted") {
|
|
30997
|
+
if (status === "accepted" && !inFlight) {
|
|
30620
30998
|
button.hidden = false;
|
|
30621
30999
|
button.disabled = true;
|
|
30622
31000
|
button.textContent = tr("undoRun");
|
|
30623
31001
|
button.title = tr("undoRunTitle");
|
|
30624
31002
|
return;
|
|
30625
31003
|
}
|
|
30626
|
-
if (status !== "pending") {
|
|
31004
|
+
if (status !== "pending" && !inFlight) {
|
|
30627
31005
|
button.hidden = true;
|
|
30628
31006
|
return;
|
|
30629
31007
|
}
|
|
30630
|
-
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30631
31008
|
button.hidden = false;
|
|
30632
31009
|
button.disabled = !projection.canUndo || inFlight === "reject" || inFlight === "accept";
|
|
30633
31010
|
button.textContent = tr("undoRun");
|
|
@@ -30653,12 +31030,12 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30653
31030
|
return;
|
|
30654
31031
|
}
|
|
30655
31032
|
const status = run.trackedChangeStatus || "";
|
|
31033
|
+
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30656
31034
|
const projection = projectRunSettlement(run);
|
|
30657
31035
|
if (status === "needs_review") {
|
|
30658
|
-
const inFlight2 = trackedChangeInFlight.get(run.id);
|
|
30659
31036
|
button.hidden = false;
|
|
30660
|
-
button.disabled = !projection.canAccept ||
|
|
30661
|
-
if (
|
|
31037
|
+
button.disabled = !projection.canAccept || inFlight === "accept" || inFlight === "reject";
|
|
31038
|
+
if (inFlight === "accept") {
|
|
30662
31039
|
button.textContent = tr("runAcceptTrackedConfirming");
|
|
30663
31040
|
button.title = tr("runAcceptTrackedConfirming");
|
|
30664
31041
|
return;
|
|
@@ -30668,25 +31045,24 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
30668
31045
|
wireAcceptInlineConfirm(button, run.id);
|
|
30669
31046
|
return;
|
|
30670
31047
|
}
|
|
30671
|
-
if (status === "accepted") {
|
|
31048
|
+
if (status === "accepted" && !inFlight) {
|
|
30672
31049
|
button.hidden = false;
|
|
30673
31050
|
button.disabled = true;
|
|
30674
31051
|
button.textContent = tr("runAcceptTrackedDone");
|
|
30675
31052
|
button.title = tr("runAcceptTrackedDoneTitle");
|
|
30676
31053
|
return;
|
|
30677
31054
|
}
|
|
30678
|
-
if (status === "rejected") {
|
|
31055
|
+
if (status === "rejected" && !inFlight) {
|
|
30679
31056
|
button.hidden = false;
|
|
30680
31057
|
button.disabled = true;
|
|
30681
31058
|
button.textContent = tr("runAcceptTracked");
|
|
30682
31059
|
button.title = tr("runAcceptTrackedTitle");
|
|
30683
31060
|
return;
|
|
30684
31061
|
}
|
|
30685
|
-
if (status !== "pending") {
|
|
31062
|
+
if (status !== "pending" && !inFlight) {
|
|
30686
31063
|
button.hidden = true;
|
|
30687
31064
|
return;
|
|
30688
31065
|
}
|
|
30689
|
-
const inFlight = trackedChangeInFlight.get(run.id);
|
|
30690
31066
|
button.hidden = false;
|
|
30691
31067
|
button.disabled = !projection.canAccept || inFlight === "accept" || inFlight === "reject";
|
|
30692
31068
|
if (inFlight === "accept") {
|
|
@@ -31578,19 +31954,26 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
31578
31954
|
const source = findSource(previousState, runId);
|
|
31579
31955
|
if (!source) return failFork("session_fork_source_missing", tr("forkRunUnavailable"));
|
|
31580
31956
|
const { session, run, runIndex } = source;
|
|
31581
|
-
|
|
31957
|
+
const draftThreadId = run.codexTurnId && run.interruptedDraft?.turnId === run.codexTurnId ? run.interruptedDraft.threadId : "";
|
|
31958
|
+
const sourceThreadId = String(run.codexThreadId || draftThreadId || session.codexThreadId || "").trim();
|
|
31959
|
+
if (run.status === "running" || !sourceThreadId || !run.codexTurnId) {
|
|
31582
31960
|
return failFork("session_fork_unavailable", tr("forkRunUnavailable"));
|
|
31583
31961
|
}
|
|
31584
|
-
|
|
31585
|
-
|
|
31586
|
-
|
|
31587
|
-
|
|
31588
|
-
|
|
31589
|
-
|
|
31590
|
-
|
|
31591
|
-
|
|
31592
|
-
|
|
31593
|
-
|
|
31962
|
+
let response;
|
|
31963
|
+
try {
|
|
31964
|
+
response = await sendBackgroundNative({
|
|
31965
|
+
method: "codex.thread.fork",
|
|
31966
|
+
params: {
|
|
31967
|
+
threadId: sourceThreadId,
|
|
31968
|
+
lastTurnId: run.codexTurnId,
|
|
31969
|
+
speedTier: session.speedTier,
|
|
31970
|
+
loadCodexLocalSkills: previousState.loadCodexLocalSkills !== false,
|
|
31971
|
+
loadCodexOverleafSkills: previousState.loadCodexOverleafSkills !== false
|
|
31972
|
+
}
|
|
31973
|
+
});
|
|
31974
|
+
} catch (error) {
|
|
31975
|
+
return failFork(error?.code || "session_fork_failed", error?.message || tr("forkRunFailed"));
|
|
31976
|
+
}
|
|
31594
31977
|
if (!response?.ok || !response.result?.threadId) {
|
|
31595
31978
|
return failFork(response?.error?.code || "session_fork_failed", response?.error?.message || tr("forkRunFailed"));
|
|
31596
31979
|
}
|
|
@@ -32027,11 +32410,45 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32027
32410
|
function formatCompactModelLabel(label) {
|
|
32028
32411
|
return String(label || "").replace(/^gpt[-\s]*/i, "");
|
|
32029
32412
|
}
|
|
32030
|
-
function retainSelectedModel(models, selectedModel) {
|
|
32413
|
+
function retainSelectedModel(models, selectedModel, options2 = {}) {
|
|
32031
32414
|
const selectedId = normalizeModelOptionId(selectedModel);
|
|
32032
32415
|
if (!selectedId) return "";
|
|
32416
|
+
if (options2.preserveUnavailable === true) return selectedId;
|
|
32033
32417
|
return (Array.isArray(models) ? models : []).some((model) => normalizeModelOptionId(typeof model === "string" ? model : model?.id) === selectedId) ? selectedId : "";
|
|
32034
32418
|
}
|
|
32419
|
+
function preserveSelectedCapabilities(models, selectedModel, preferences = {}, provisional = false) {
|
|
32420
|
+
const selectedId = normalizeModelOptionId(selectedModel);
|
|
32421
|
+
const saved = preferences || {};
|
|
32422
|
+
return (Array.isArray(models) ? models : []).map((model) => {
|
|
32423
|
+
if (model.id !== selectedId || !provisional && !model.unverified) return model;
|
|
32424
|
+
const reasoningEfforts = normalizeReasoningEffortsForSelect([
|
|
32425
|
+
...model.reasoningEfforts || [],
|
|
32426
|
+
saved.reasoningEffort
|
|
32427
|
+
]);
|
|
32428
|
+
const speedTiers = normalizeSpeedTiersForSelect(model.speedTiers);
|
|
32429
|
+
const speed = ["standard", "fast"].includes(saved.speedTier) ? saved.speedTier : "";
|
|
32430
|
+
if (speed && !speedTiers.includes(speed)) speedTiers.push(speed);
|
|
32431
|
+
return {
|
|
32432
|
+
...model,
|
|
32433
|
+
unverified: true,
|
|
32434
|
+
reasoningEfforts,
|
|
32435
|
+
speedTiers,
|
|
32436
|
+
defaultReasoningEffort: reasoningEfforts.includes(saved.reasoningEffort) ? saved.reasoningEffort : model.defaultReasoningEffort,
|
|
32437
|
+
defaultSpeedTier: speed || model.defaultSpeedTier || "standard"
|
|
32438
|
+
};
|
|
32439
|
+
});
|
|
32440
|
+
}
|
|
32441
|
+
function getRenderedModelEntries(panel) {
|
|
32442
|
+
return Array.from(panel?.querySelector("[data-model]")?.options || []).map((option) => ({
|
|
32443
|
+
id: option.value,
|
|
32444
|
+
label: option.textContent,
|
|
32445
|
+
reasoningEfforts: (option.dataset.reasoningEfforts || "").split(",").filter(Boolean),
|
|
32446
|
+
defaultReasoningEffort: option.dataset.defaultReasoningEffort || "",
|
|
32447
|
+
reasoningPresentation: option.dataset.reasoningPresentation || "",
|
|
32448
|
+
speedTiers: (option.dataset.speedTiers || "standard").split(",").filter(Boolean),
|
|
32449
|
+
defaultSpeedTier: option.dataset.defaultSpeedTier || "standard"
|
|
32450
|
+
}));
|
|
32451
|
+
}
|
|
32035
32452
|
function shouldUseBuiltInFallback(response) {
|
|
32036
32453
|
const providerId = normalizeModelOptionId(response?.result?.providerId);
|
|
32037
32454
|
return response?.ok === true && (!providerId || providerId === "builtin");
|
|
@@ -32100,6 +32517,8 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32100
32517
|
normalizeReasoningEffortsForSelect,
|
|
32101
32518
|
normalizeSpeedTiersForSelect,
|
|
32102
32519
|
retainSelectedModel,
|
|
32520
|
+
preserveSelectedCapabilities,
|
|
32521
|
+
getRenderedModelEntries,
|
|
32103
32522
|
shouldUseBuiltInFallback
|
|
32104
32523
|
};
|
|
32105
32524
|
return api;
|
|
@@ -32222,7 +32641,8 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32222
32641
|
return { stale: false, error: response?.error || { code: "provider_models_unavailable" } };
|
|
32223
32642
|
}
|
|
32224
32643
|
const sourceModels = hasDiscoveredModels ? response.result.models : fallbackModels;
|
|
32225
|
-
const
|
|
32644
|
+
const preserveBuiltin = (selection?.providerId || "builtin") === "builtin" && (getState()?.providerId || "builtin") === "builtin";
|
|
32645
|
+
const retainedSelectedModel = retainSelectedModel(sourceModels, currentSelectedModel, { preserveUnavailable: preserveBuiltin });
|
|
32226
32646
|
const normalized = modelCatalog.normalizeDiscoveredModels({ models: sourceModels, selectedModel: retainedSelectedModel });
|
|
32227
32647
|
if (normalized.usedFallback && response.result?.providerId && response.result.providerId !== "builtin") {
|
|
32228
32648
|
applyUnavailableModelOptions({ code: "provider_model_catalog_invalid", message: "The active provider returned no usable models." });
|
|
@@ -32231,9 +32651,10 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32231
32651
|
error: { code: "provider_model_catalog_invalid", message: "The active provider returned no usable models." }
|
|
32232
32652
|
};
|
|
32233
32653
|
}
|
|
32234
|
-
|
|
32654
|
+
const renderedModels = preserveBuiltin ? Support.preserveSelectedCapabilities(normalized.models, retainedSelectedModel, getState(), !hasDiscoveredModels || response.result?.source === "fallback") : normalized.models;
|
|
32655
|
+
renderModelOptions(renderedModels, retainedSelectedModel, { allowUnknownSelected: false });
|
|
32235
32656
|
modelDiscovery = {
|
|
32236
|
-
status: hasDiscoveredModels && !normalized.usedFallback ? "discovered" : "fallback",
|
|
32657
|
+
status: hasDiscoveredModels && !normalized.usedFallback && response.result?.source !== "fallback" ? "discovered" : "fallback",
|
|
32237
32658
|
source: hasDiscoveredModels ? response.result?.source || "unknown" : "fallback",
|
|
32238
32659
|
fetchedAt: hasDiscoveredModels ? response.result?.fetchedAt || "" : "",
|
|
32239
32660
|
errorCode: hasDiscoveredModels ? "" : response?.error?.code || "",
|
|
@@ -32259,15 +32680,16 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32259
32680
|
}
|
|
32260
32681
|
}
|
|
32261
32682
|
function applyUnavailableModelOptions(error) {
|
|
32683
|
+
const selectedModel = resolveSelectedModel();
|
|
32262
32684
|
const modelSelect = getPanel()?.querySelector("[data-model]");
|
|
32263
32685
|
if (modelSelect) {
|
|
32264
32686
|
modelSelect.textContent = "";
|
|
32265
32687
|
const option = document.createElement("option");
|
|
32266
|
-
option.value =
|
|
32688
|
+
option.value = selectedModel;
|
|
32267
32689
|
option.textContent = tx("Models unavailable", "\u6A21\u578B\u4E0D\u53EF\u7528");
|
|
32268
32690
|
option.disabled = true;
|
|
32269
32691
|
modelSelect.append(option);
|
|
32270
|
-
modelSelect.value =
|
|
32692
|
+
modelSelect.value = selectedModel;
|
|
32271
32693
|
modelSelect.disabled = true;
|
|
32272
32694
|
}
|
|
32273
32695
|
modelDiscovery = {
|
|
@@ -32277,8 +32699,18 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32277
32699
|
errorCode: error?.code || "",
|
|
32278
32700
|
errorMessage: error?.message || (error ? String(error) : "")
|
|
32279
32701
|
};
|
|
32280
|
-
|
|
32281
|
-
|
|
32702
|
+
const pendingModels = Support.preserveSelectedCapabilities(
|
|
32703
|
+
[{ id: selectedModel, unverified: true }],
|
|
32704
|
+
selectedModel,
|
|
32705
|
+
getState(),
|
|
32706
|
+
true
|
|
32707
|
+
);
|
|
32708
|
+
renderReasoningOptions(pendingModels);
|
|
32709
|
+
renderSpeedOptions(pendingModels);
|
|
32710
|
+
for (const selector of ["[data-reasoning]", "[data-speed]"]) {
|
|
32711
|
+
const input = getPanel()?.querySelector(selector);
|
|
32712
|
+
if (input) input.disabled = true;
|
|
32713
|
+
}
|
|
32282
32714
|
renderModelConfigChoices();
|
|
32283
32715
|
updateModelDisplay();
|
|
32284
32716
|
}
|
|
@@ -32286,9 +32718,9 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32286
32718
|
const modelCatalog = getModelCatalog();
|
|
32287
32719
|
const fallbackModels = modelCatalog.FALLBACK_MODELS;
|
|
32288
32720
|
const sourceModels = fallbackModels;
|
|
32289
|
-
const retainedSelectedModel = retainSelectedModel(sourceModels, selectedModel);
|
|
32721
|
+
const retainedSelectedModel = retainSelectedModel(sourceModels, selectedModel, { preserveUnavailable: (getState()?.providerId || "builtin") === "builtin" });
|
|
32290
32722
|
const normalized = modelCatalog.normalizeDiscoveredModels({ models: sourceModels, selectedModel: retainedSelectedModel });
|
|
32291
|
-
renderModelOptions(normalized.models, retainedSelectedModel);
|
|
32723
|
+
renderModelOptions(Support.preserveSelectedCapabilities(normalized.models, retainedSelectedModel, getState(), true), retainedSelectedModel);
|
|
32292
32724
|
modelDiscovery = {
|
|
32293
32725
|
status: "fallback",
|
|
32294
32726
|
source: "fallback",
|
|
@@ -32723,6 +33155,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32723
33155
|
});
|
|
32724
33156
|
const PROJECT_NAME_CACHE_STORAGE_KEY = "projectNameCacheByAccount";
|
|
32725
33157
|
let projectNameCacheMirror = {};
|
|
33158
|
+
let dashboardRenderGeneration = 0;
|
|
32726
33159
|
function loadProjectNameCacheFromStorage() {
|
|
32727
33160
|
return new Promise(function(resolve) {
|
|
32728
33161
|
try {
|
|
@@ -32806,7 +33239,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32806
33239
|
await persistProjectNameCacheToStorage();
|
|
32807
33240
|
var visibleList = getPanel() && getPanel().querySelector("[data-recent-projects-list]");
|
|
32808
33241
|
if (visibleList) {
|
|
32809
|
-
var rows = visibleList.querySelectorAll("[data-
|
|
33242
|
+
var rows = visibleList.querySelectorAll("[data-project-id]");
|
|
32810
33243
|
for (var k = 0; k < rows.length; k++) {
|
|
32811
33244
|
var row = rows[k];
|
|
32812
33245
|
var rowPid = row.getAttribute("data-project-id");
|
|
@@ -32815,6 +33248,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32815
33248
|
var cached = lookupProjectName(rowPid);
|
|
32816
33249
|
if (cached) {
|
|
32817
33250
|
nameEl.textContent = cached;
|
|
33251
|
+
nameEl.title = cached;
|
|
32818
33252
|
}
|
|
32819
33253
|
}
|
|
32820
33254
|
}
|
|
@@ -32883,54 +33317,47 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32883
33317
|
var hr = Math.round(min / 60);
|
|
32884
33318
|
if (hr < 24) return tx(hr + " hr ago", hr + " \u5C0F\u65F6\u524D");
|
|
32885
33319
|
var day = Math.round(hr / 24);
|
|
32886
|
-
if (day < 30) return tx(day + " day ago", day + " \u5929\u524D");
|
|
33320
|
+
if (day < 30) return tx(day + (day === 1 ? " day ago" : " days ago"), day + " \u5929\u524D");
|
|
32887
33321
|
var month = Math.round(day / 30);
|
|
32888
33322
|
if (month < 12) return tx(month + " mo ago", month + " \u4E2A\u6708\u524D");
|
|
32889
33323
|
var year = Math.round(month / 12);
|
|
32890
33324
|
return tx(year + " yr ago", year + " \u5E74\u524D");
|
|
32891
33325
|
}
|
|
32892
|
-
function
|
|
32893
|
-
var el = document.createElement(
|
|
32894
|
-
if (className)
|
|
32895
|
-
|
|
32896
|
-
}
|
|
32897
|
-
el.textContent = text == null ? "" : String(text);
|
|
33326
|
+
function createViewElement(tag, className, text) {
|
|
33327
|
+
var el = document.createElement(tag);
|
|
33328
|
+
if (className) el.className = className;
|
|
33329
|
+
if (text !== void 0) el.textContent = text;
|
|
32898
33330
|
return el;
|
|
32899
33331
|
}
|
|
32900
|
-
function
|
|
32901
|
-
var
|
|
32902
|
-
|
|
33332
|
+
function createViewButton(label, onClick, attribute, className) {
|
|
33333
|
+
var button = createViewElement("button", className, label);
|
|
33334
|
+
button.type = "button";
|
|
33335
|
+
if (attribute) button.setAttribute(attribute, "");
|
|
33336
|
+
if (onClick) button.addEventListener("click", onClick);
|
|
33337
|
+
return button;
|
|
33338
|
+
}
|
|
33339
|
+
function textNode(text, className) {
|
|
33340
|
+
return createViewElement("span", className, text == null ? "" : String(text));
|
|
33341
|
+
}
|
|
33342
|
+
function renderWelcomeHeader() {
|
|
33343
|
+
var el = createViewElement("div", "recent-projects-welcome");
|
|
32903
33344
|
el.setAttribute("data-recent-projects-welcome", "");
|
|
32904
|
-
|
|
32905
|
-
|
|
32906
|
-
|
|
32907
|
-
var subtitle = document.createElement("div");
|
|
32908
|
-
subtitle.className = "recent-projects-welcome-subtitle";
|
|
32909
|
-
subtitle.textContent = stats && stats.projectCount ? tr("recentProjects_welcome_stats", { projects: stats.projectCount, sessions: stats.sessionTotal }) : tr("recentProjects_welcome_subtitle");
|
|
32910
|
-
el.appendChild(title);
|
|
32911
|
-
el.appendChild(subtitle);
|
|
33345
|
+
el.appendChild(textNode("CODEX", "recent-projects-eyebrow"));
|
|
33346
|
+
el.appendChild(textNode(tr("recentProjects_welcome"), "recent-projects-welcome-title"));
|
|
33347
|
+
el.appendChild(textNode(tr("recentProjects_welcome_subtitle"), "recent-projects-welcome-subtitle"));
|
|
32912
33348
|
return el;
|
|
32913
33349
|
}
|
|
32914
33350
|
function renderEmptyState() {
|
|
32915
|
-
var el =
|
|
32916
|
-
el.className = "recent-projects-empty";
|
|
33351
|
+
var el = createViewElement("div", "recent-projects-empty", tr("recentProjects_empty"));
|
|
32917
33352
|
el.setAttribute("data-recent-projects-empty", "");
|
|
32918
|
-
el.textContent = tr("recentProjects_empty");
|
|
32919
33353
|
return el;
|
|
32920
33354
|
}
|
|
32921
33355
|
function renderDegradedState() {
|
|
32922
|
-
var el =
|
|
32923
|
-
el.className = "recent-projects-degraded";
|
|
33356
|
+
var el = createViewElement("div", "recent-projects-degraded");
|
|
32924
33357
|
el.setAttribute("data-recent-projects-degraded", "");
|
|
32925
|
-
var hint =
|
|
32926
|
-
hint.textContent = tr("recentProjects_degraded_hint");
|
|
33358
|
+
var hint = createViewElement("div", "", tr("recentProjects_degraded_hint"));
|
|
32927
33359
|
el.appendChild(hint);
|
|
32928
|
-
var retry =
|
|
32929
|
-
retry.type = "button";
|
|
32930
|
-
retry.className = "recent-projects-show-all";
|
|
32931
|
-
retry.setAttribute("data-recent-projects-retry", "");
|
|
32932
|
-
retry.textContent = tr("recentProjects_retryScope");
|
|
32933
|
-
retry.addEventListener("click", function() {
|
|
33360
|
+
var retry = createViewButton(tr("recentProjects_retryScope"), function() {
|
|
32934
33361
|
if (typeof refreshAccountScopeId === "function") {
|
|
32935
33362
|
Promise.resolve(refreshAccountScopeId()).then(function() {
|
|
32936
33363
|
return renderRecentProjectsVariant();
|
|
@@ -32939,24 +33366,17 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32939
33366
|
} else {
|
|
32940
33367
|
renderRecentProjectsVariant();
|
|
32941
33368
|
}
|
|
32942
|
-
});
|
|
33369
|
+
}, "data-recent-projects-retry", "recent-projects-show-all");
|
|
32943
33370
|
el.appendChild(retry);
|
|
32944
33371
|
return el;
|
|
32945
33372
|
}
|
|
32946
33373
|
function renderSettingsEntry(options2) {
|
|
32947
33374
|
var scope = options2 && options2.scope === "account" ? "account" : "project";
|
|
32948
|
-
var entry =
|
|
32949
|
-
entry.type = "button";
|
|
32950
|
-
entry.className = "recent-projects-settings-entry";
|
|
32951
|
-
entry.setAttribute("data-recent-projects-settings-entry", "");
|
|
32952
|
-
entry.setAttribute("data-settings-scope", scope);
|
|
32953
|
-
var label = document.createElement("span");
|
|
32954
|
-
label.className = "recent-projects-settings-entry-label";
|
|
32955
|
-
label.textContent = tr("recentProjects_settings_entry");
|
|
32956
|
-
entry.appendChild(label);
|
|
32957
|
-
entry.addEventListener("click", function() {
|
|
33375
|
+
var entry = createViewButton(void 0, function() {
|
|
32958
33376
|
openSettingsInScope(scope);
|
|
32959
|
-
});
|
|
33377
|
+
}, "data-recent-projects-settings-entry", "recent-projects-settings-entry");
|
|
33378
|
+
entry.setAttribute("data-settings-scope", scope);
|
|
33379
|
+
entry.appendChild(textNode(tr("recentProjects_settings_entry"), "recent-projects-settings-entry-label"));
|
|
32960
33380
|
return entry;
|
|
32961
33381
|
}
|
|
32962
33382
|
function openSettingsInScope(scope) {
|
|
@@ -32979,10 +33399,8 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32979
33399
|
function renderStatusBadge(status) {
|
|
32980
33400
|
var safeStatus = typeof status === "string" && STATUS_BADGE_CLASS[status] ? status : "pending";
|
|
32981
33401
|
var cls = STATUS_BADGE_CLASS[safeStatus];
|
|
32982
|
-
var el =
|
|
32983
|
-
el.className = "recent-projects-row-badge " + cls;
|
|
33402
|
+
var el = textNode(tr("recentProjects_badge_" + safeStatus), "recent-projects-row-badge " + cls);
|
|
32984
33403
|
el.setAttribute("data-status", safeStatus);
|
|
32985
|
-
el.textContent = tr("recentProjects_badge_" + safeStatus);
|
|
32986
33404
|
return el;
|
|
32987
33405
|
}
|
|
32988
33406
|
function isValidProjectId(id) {
|
|
@@ -32994,121 +33412,137 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
32994
33412
|
}
|
|
32995
33413
|
window.location.assign("https://www.overleaf.com/project/" + encodeURIComponent(projectId));
|
|
32996
33414
|
}
|
|
33415
|
+
function renderActionsMenu(buttons) {
|
|
33416
|
+
var menu = createViewElement("details", "recent-projects-menu");
|
|
33417
|
+
var trigger = createViewElement("summary", "", "\u22EF");
|
|
33418
|
+
trigger.title = tr("recentProjects_more");
|
|
33419
|
+
trigger.setAttribute("aria-label", tr("recentProjects_more"));
|
|
33420
|
+
var actions = document.createElement("div");
|
|
33421
|
+
actions.setAttribute("data-recent-menu-actions", "");
|
|
33422
|
+
buttons.forEach(function(button) {
|
|
33423
|
+
actions.appendChild(button);
|
|
33424
|
+
});
|
|
33425
|
+
actions.addEventListener("click", function(event) {
|
|
33426
|
+
if (event.target.closest("button")) {
|
|
33427
|
+
menu.open = false;
|
|
33428
|
+
trigger.focus();
|
|
33429
|
+
}
|
|
33430
|
+
}, true);
|
|
33431
|
+
menu.appendChild(trigger);
|
|
33432
|
+
menu.appendChild(actions);
|
|
33433
|
+
menu.addEventListener("keydown", function(event) {
|
|
33434
|
+
if (event.key === "Escape") {
|
|
33435
|
+
event.preventDefault();
|
|
33436
|
+
event.stopPropagation();
|
|
33437
|
+
menu.open = false;
|
|
33438
|
+
trigger.focus();
|
|
33439
|
+
}
|
|
33440
|
+
});
|
|
33441
|
+
menu.addEventListener("focusout", function(event) {
|
|
33442
|
+
if (event.relatedTarget && !menu.contains(event.relatedTarget)) menu.open = false;
|
|
33443
|
+
});
|
|
33444
|
+
return menu;
|
|
33445
|
+
}
|
|
33446
|
+
function conversationActivity(record) {
|
|
33447
|
+
return String(record && (record.lastActivityAt || record.updatedAt || record.createdAt) || "");
|
|
33448
|
+
}
|
|
33449
|
+
function conversationHasContent(record) {
|
|
33450
|
+
return ["runs", "history", "pendingInputs"].some(function(key) {
|
|
33451
|
+
return Array.isArray(record[key]) && record[key].length > 0;
|
|
33452
|
+
}) || ["task", "safeTaskSummary", "codexThreadId"].some(function(key) {
|
|
33453
|
+
return typeof record[key] === "string" && Boolean(record[key].trim());
|
|
33454
|
+
}) || record.titleSource === "manual" && typeof record.title === "string" && Boolean(record.title.trim());
|
|
33455
|
+
}
|
|
33456
|
+
function conversationStatus(record) {
|
|
33457
|
+
if (!StorageDb || !Array.isArray(record.runs) || !record.runs.length) return "";
|
|
33458
|
+
return settleDashboardRunStatus(StorageDb.derivePrimaryStatusBadge(record), conversationActivity(record));
|
|
33459
|
+
}
|
|
33460
|
+
function projectDisplayName(projectId) {
|
|
33461
|
+
return lookupProjectName(projectId) || (isValidProjectId(projectId) ? tr("recentProjects_unnamed", { prefix: projectId.slice(0, 8) }) : tr("recentProjects_row_projectLinkUnavailable"));
|
|
33462
|
+
}
|
|
33463
|
+
async function loadDashboardConversations(scope) {
|
|
33464
|
+
if (!scope || !StorageDb) throw new Error("Conversation storage is unavailable.");
|
|
33465
|
+
var results = await Promise.all([StorageDb.getAllSessions(), SessionPersistence.loadTombstones()]);
|
|
33466
|
+
var records = results[0];
|
|
33467
|
+
var deletedByProject = results[1] || {};
|
|
33468
|
+
if (!Array.isArray(records)) throw new Error("Conversation history could not be read.");
|
|
33469
|
+
return records.filter(function(record) {
|
|
33470
|
+
if (!record || typeof record.id !== "string" || !record.id || record.accountScopeUnavailable === true) return false;
|
|
33471
|
+
var deletedIds = Object.prototype.hasOwnProperty.call(deletedByProject, record.projectId) ? deletedByProject[record.projectId] : [];
|
|
33472
|
+
return SessionPersistence.isVisibleRecord(record, Array.isArray(deletedIds) ? deletedIds : [], scope);
|
|
33473
|
+
}).sort(function(a, b) {
|
|
33474
|
+
var aTime = Date.parse(conversationActivity(a)) || 0;
|
|
33475
|
+
var bTime = Date.parse(conversationActivity(b)) || 0;
|
|
33476
|
+
return bTime - aTime || String(a.id).localeCompare(String(b.id));
|
|
33477
|
+
});
|
|
33478
|
+
}
|
|
33479
|
+
function dashboardViewOptions() {
|
|
33480
|
+
var root = getPanel() && getPanel().querySelector("[data-recent-projects-root]");
|
|
33481
|
+
var drafts = root && root.querySelector("[data-unstarted-conversations]");
|
|
33482
|
+
return {
|
|
33483
|
+
accountScopeId: root && root.dataset.accountScopeId || "",
|
|
33484
|
+
projectFilter: root && root.dataset.projectFilter || "",
|
|
33485
|
+
showAll: Boolean(root && root.dataset.showAll === "true"),
|
|
33486
|
+
draftsOpen: Boolean(drafts && drafts.open),
|
|
33487
|
+
restoreScrollTop: root ? root.scrollTop : 0
|
|
33488
|
+
};
|
|
33489
|
+
}
|
|
33490
|
+
async function refreshDashboardView() {
|
|
33491
|
+
var panelEl = getPanel();
|
|
33492
|
+
if (panelEl && panelEl.dataset.view === "recent-projects") {
|
|
33493
|
+
await renderRecentProjectsVariant(dashboardViewOptions());
|
|
33494
|
+
}
|
|
33495
|
+
}
|
|
33496
|
+
async function openDashboardConversation(projectId, record, row) {
|
|
33497
|
+
var scope = record.accountScopeId;
|
|
33498
|
+
var panelEl = getPanel();
|
|
33499
|
+
if (!scope || scope !== getCachedAccountScopeId() || !isValidProjectId(projectId) || !panelEl || panelEl.dataset.view !== "recent-projects" || row.getAttribute("aria-busy") === "true") return;
|
|
33500
|
+
row.setAttribute("aria-busy", "true");
|
|
33501
|
+
var resume = row.querySelector("[data-session-resume]");
|
|
33502
|
+
if (resume) resume.disabled = true;
|
|
33503
|
+
try {
|
|
33504
|
+
var records = await loadProjectSessionRecords(projectId);
|
|
33505
|
+
if (scope !== getCachedAccountScopeId() || panelEl !== getPanel() || panelEl.dataset.view !== "recent-projects" || row.isConnected === false) return;
|
|
33506
|
+
var selected = records.find(function(candidate) {
|
|
33507
|
+
return candidate.id === record.id;
|
|
33508
|
+
});
|
|
33509
|
+
if (!selected) {
|
|
33510
|
+
await refreshDashboardView();
|
|
33511
|
+
showPluginToast(tr("recentProjects_conversationGone"), { status: "warning" });
|
|
33512
|
+
return;
|
|
33513
|
+
}
|
|
33514
|
+
await activateSessionAndOpenProject(projectId, selected);
|
|
33515
|
+
} catch (_error) {
|
|
33516
|
+
if (scope === getCachedAccountScopeId() && row.isConnected !== false) {
|
|
33517
|
+
showPluginToast(tr("recentProjects_continueFailed"), { status: "warning" });
|
|
33518
|
+
}
|
|
33519
|
+
} finally {
|
|
33520
|
+
row.removeAttribute("aria-busy");
|
|
33521
|
+
if (resume) resume.disabled = false;
|
|
33522
|
+
}
|
|
33523
|
+
}
|
|
32997
33524
|
function renderRecentProjectRow(row) {
|
|
32998
33525
|
var projectId = row && row.projectId;
|
|
32999
33526
|
var valid = isValidProjectId(projectId);
|
|
33000
|
-
var
|
|
33001
|
-
|
|
33002
|
-
|
|
33003
|
-
|
|
33004
|
-
|
|
33005
|
-
|
|
33006
|
-
|
|
33007
|
-
|
|
33008
|
-
}
|
|
33009
|
-
var
|
|
33010
|
-
|
|
33011
|
-
name = isValidProjectId(projectId) ? tr("recentProjects_unnamed", { prefix: projectId.slice(0, 8) }) : tr("recentProjects_row_projectLinkUnavailable");
|
|
33012
|
-
}
|
|
33013
|
-
var nameNode = textNode(name, "recent-projects-row-name");
|
|
33014
|
-
nameNode.title = name;
|
|
33015
|
-
el.appendChild(nameNode);
|
|
33016
|
-
var rowTime = textNode(formatRelativeTime(row && row.lastActivityAt), "recent-projects-row-time");
|
|
33017
|
-
rowTime.setAttribute("data-rel-time", String(row && row.lastActivityAt || ""));
|
|
33018
|
-
el.appendChild(rowTime);
|
|
33019
|
-
var sessionCount = Number(row && row.sessionCount) || 0;
|
|
33020
|
-
if (sessionCount > 1) {
|
|
33021
|
-
el.appendChild(textNode(tr("recentProjects_sessionsCount", { count: sessionCount }), "recent-projects-row-sessions"));
|
|
33022
|
-
}
|
|
33023
|
-
el.appendChild(renderStatusBadge(settleDashboardRunStatus(row && row.primaryStatusBadge, row && row.lastActivityAt)));
|
|
33024
|
-
if (valid) {
|
|
33025
|
-
el.addEventListener("click", function() {
|
|
33026
|
-
openProjectFromRow(projectId);
|
|
33527
|
+
var wrap = createViewElement("div", "recent-projects-row-wrap recent-projects-unavailable-row");
|
|
33528
|
+
wrap.setAttribute("data-project-id", projectId || "");
|
|
33529
|
+
var link = createViewButton(void 0, null, "data-recent-projects-row", "recent-projects-row");
|
|
33530
|
+
link.setAttribute("data-project-id", projectId || "");
|
|
33531
|
+
link.disabled = !valid;
|
|
33532
|
+
link.appendChild(textNode(projectDisplayName(projectId), "recent-projects-row-name"));
|
|
33533
|
+
if (valid) link.addEventListener("click", function() {
|
|
33534
|
+
openProjectFromRow(projectId);
|
|
33535
|
+
});
|
|
33536
|
+
var cleanup = createViewButton(tr(valid ? "recentProjects_clearProject" : "recentProjects_cleanup"), function() {
|
|
33537
|
+
if (valid) projectSessionCleanup.clearProjectSessions(projectId, projectDisplayName(projectId)).catch(function() {
|
|
33027
33538
|
});
|
|
33028
|
-
|
|
33029
|
-
el.appendChild(textNode(tr("recentProjects_row_projectLinkUnavailable"), "recent-projects-row-warning"));
|
|
33030
|
-
}
|
|
33031
|
-
if (!valid) {
|
|
33032
|
-
var deadWrap = document.createElement("div");
|
|
33033
|
-
deadWrap.className = "recent-projects-row-wrap";
|
|
33034
|
-
var deadHead = document.createElement("div");
|
|
33035
|
-
deadHead.className = "recent-projects-row-head";
|
|
33036
|
-
var cleanup = document.createElement("button");
|
|
33037
|
-
cleanup.type = "button";
|
|
33038
|
-
cleanup.className = "recent-projects-row-cleanup";
|
|
33039
|
-
cleanup.setAttribute("data-row-cleanup", "");
|
|
33040
|
-
cleanup.title = tr("recentProjects_cleanup");
|
|
33041
|
-
cleanup.setAttribute("aria-label", tr("recentProjects_cleanup"));
|
|
33042
|
-
cleanup.textContent = "\xD7";
|
|
33043
|
-
cleanup.addEventListener("click", function() {
|
|
33044
|
-
cleanupDeadProjectEntry(projectId).catch(function() {
|
|
33045
|
-
});
|
|
33539
|
+
else cleanupDeadProjectEntry(projectId).catch(function() {
|
|
33046
33540
|
});
|
|
33047
|
-
|
|
33048
|
-
|
|
33049
|
-
|
|
33050
|
-
return deadWrap;
|
|
33051
|
-
}
|
|
33052
|
-
var wrap = document.createElement("div");
|
|
33053
|
-
wrap.className = "recent-projects-row-wrap";
|
|
33054
|
-
wrap.setAttribute("data-project-row-wrap", projectId);
|
|
33055
|
-
var expand = document.createElement("button");
|
|
33056
|
-
expand.type = "button";
|
|
33057
|
-
expand.className = "recent-projects-row-expand";
|
|
33058
|
-
expand.setAttribute("data-row-expand", "");
|
|
33059
|
-
expand.setAttribute("aria-expanded", "false");
|
|
33060
|
-
var sessionsElId = "codex-project-sessions-" + String(projectId || "").slice(0, 24);
|
|
33061
|
-
expand.setAttribute("aria-controls", sessionsElId);
|
|
33062
|
-
expand.title = tr("recentProjects_sessions_toggle");
|
|
33063
|
-
expand.setAttribute("aria-label", tr("recentProjects_sessions_toggle"));
|
|
33064
|
-
expand.textContent = tr("recentProjects_sessions_action");
|
|
33065
|
-
var head = document.createElement("div");
|
|
33066
|
-
head.className = "recent-projects-row-head";
|
|
33067
|
-
var clear = document.createElement("button");
|
|
33068
|
-
clear.type = "button";
|
|
33069
|
-
clear.className = "recent-projects-row-clear";
|
|
33070
|
-
clear.setAttribute("data-project-clear", "");
|
|
33071
|
-
clear.title = tr("recentProjects_clearProject");
|
|
33072
|
-
clear.setAttribute("aria-label", tr("recentProjects_clearProject"));
|
|
33073
|
-
clear.textContent = "\xD7";
|
|
33074
|
-
clear.addEventListener("click", function(event) {
|
|
33075
|
-
event.stopPropagation();
|
|
33076
|
-
projectSessionCleanup.clearProjectSessions(projectId, name).catch(function() {
|
|
33077
|
-
});
|
|
33078
|
-
});
|
|
33079
|
-
head.appendChild(el);
|
|
33080
|
-
head.appendChild(expand);
|
|
33081
|
-
head.appendChild(clear);
|
|
33082
|
-
var sessionsEl = document.createElement("div");
|
|
33083
|
-
sessionsEl.className = "recent-projects-sessions";
|
|
33084
|
-
sessionsEl.setAttribute("data-project-sessions", "");
|
|
33085
|
-
sessionsEl.id = sessionsElId;
|
|
33086
|
-
sessionsEl.setAttribute("role", "region");
|
|
33087
|
-
sessionsEl.setAttribute("aria-label", tr("recentProjects_sessions_toggle"));
|
|
33088
|
-
sessionsEl.hidden = true;
|
|
33089
|
-
expand.addEventListener("click", function() {
|
|
33090
|
-
toggleProjectSessions(wrap, projectId);
|
|
33091
|
-
});
|
|
33092
|
-
wrap.appendChild(head);
|
|
33093
|
-
wrap.appendChild(sessionsEl);
|
|
33541
|
+
}, valid ? "data-project-clear" : "data-row-cleanup");
|
|
33542
|
+
wrap.appendChild(link);
|
|
33543
|
+
wrap.appendChild(renderActionsMenu([cleanup]));
|
|
33094
33544
|
return wrap;
|
|
33095
33545
|
}
|
|
33096
|
-
function toggleProjectSessions(wrap, projectId) {
|
|
33097
|
-
var sessionsEl = wrap.querySelector("[data-project-sessions]");
|
|
33098
|
-
var expand = wrap.querySelector("[data-row-expand]");
|
|
33099
|
-
if (!sessionsEl || !expand) {
|
|
33100
|
-
return;
|
|
33101
|
-
}
|
|
33102
|
-
var opening = sessionsEl.hidden;
|
|
33103
|
-
sessionsEl.hidden = !opening;
|
|
33104
|
-
expand.setAttribute("aria-expanded", opening ? "true" : "false");
|
|
33105
|
-
expand.textContent = tr(opening ? "recentProjects_sessions_action_open" : "recentProjects_sessions_action");
|
|
33106
|
-
wrap.setAttribute("data-expanded", opening ? "true" : "false");
|
|
33107
|
-
if (opening) {
|
|
33108
|
-
renderProjectSessions(sessionsEl, projectId).catch(function() {
|
|
33109
|
-
});
|
|
33110
|
-
}
|
|
33111
|
-
}
|
|
33112
33546
|
function sessionRecordDisplayTitle(record) {
|
|
33113
33547
|
if (record && typeof record.title === "string" && record.title.trim()) {
|
|
33114
33548
|
return record.title.trim();
|
|
@@ -33130,87 +33564,90 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33130
33564
|
return String(b.updatedAt || b.createdAt || "").localeCompare(String(a.updatedAt || a.createdAt || ""));
|
|
33131
33565
|
});
|
|
33132
33566
|
}
|
|
33133
|
-
|
|
33134
|
-
|
|
33135
|
-
var sessionsLoading = document.createElement("div");
|
|
33136
|
-
sessionsLoading.className = "recent-projects-loading";
|
|
33137
|
-
sessionsLoading.textContent = tx("Loading sessions\u2026", "\u6B63\u5728\u52A0\u8F7D\u4F1A\u8BDD\u2026");
|
|
33138
|
-
sessionsEl.appendChild(sessionsLoading);
|
|
33139
|
-
var records = [];
|
|
33140
|
-
try {
|
|
33141
|
-
records = await loadProjectSessionRecords(projectId);
|
|
33142
|
-
} catch (_error) {
|
|
33143
|
-
records = [];
|
|
33144
|
-
}
|
|
33145
|
-
sessionsLoading.remove();
|
|
33146
|
-
if (!records.length) {
|
|
33147
|
-
sessionsEl.appendChild(textNode(tr("recentProjects_sessions_empty"), "recent-projects-sessions-empty"));
|
|
33148
|
-
return;
|
|
33149
|
-
}
|
|
33150
|
-
for (var i = 0; i < records.length; i++) {
|
|
33151
|
-
sessionsEl.appendChild(renderProjectSessionRow(sessionsEl, projectId, records[i]));
|
|
33152
|
-
}
|
|
33153
|
-
}
|
|
33154
|
-
function renderProjectSessionRow(sessionsEl, projectId, record) {
|
|
33567
|
+
function renderProjectSessionRow(sessionsEl, projectId, record, options2) {
|
|
33568
|
+
var featured = Boolean(options2 && options2.featured);
|
|
33155
33569
|
var running = Boolean(StorageDb) && settleDashboardRunStatus(StorageDb.derivePrimaryStatusBadge(record), record.updatedAt || record.lastActivityAt) === "running";
|
|
33156
|
-
var row =
|
|
33157
|
-
row.className = "recent-projects-session-row";
|
|
33570
|
+
var row = createViewElement("div", "recent-projects-session-row" + (featured ? " recent-projects-focus" : ""));
|
|
33158
33571
|
row.setAttribute("data-project-session-row", record.id);
|
|
33159
|
-
|
|
33160
|
-
|
|
33161
|
-
}
|
|
33572
|
+
row.setAttribute("data-project-id", projectId);
|
|
33573
|
+
if (running) row.setAttribute("data-running", "true");
|
|
33162
33574
|
var title = textNode(sessionRecordDisplayTitle(record), "recent-projects-session-title");
|
|
33163
|
-
title.title =
|
|
33164
|
-
var
|
|
33165
|
-
|
|
33166
|
-
var
|
|
33167
|
-
|
|
33168
|
-
|
|
33169
|
-
|
|
33170
|
-
|
|
33171
|
-
|
|
33172
|
-
|
|
33173
|
-
var
|
|
33174
|
-
|
|
33175
|
-
|
|
33176
|
-
|
|
33177
|
-
|
|
33178
|
-
|
|
33179
|
-
|
|
33180
|
-
|
|
33181
|
-
|
|
33182
|
-
|
|
33575
|
+
title.title = title.textContent;
|
|
33576
|
+
var copy = createViewElement("div", "recent-projects-session-copy");
|
|
33577
|
+
var meta = createViewElement("div", "recent-projects-session-meta");
|
|
33578
|
+
var project = textNode(projectDisplayName(projectId), "recent-projects-row-name");
|
|
33579
|
+
project.title = project.textContent;
|
|
33580
|
+
meta.appendChild(project);
|
|
33581
|
+
var time = textNode(formatRelativeTime(conversationActivity(record)), "recent-projects-session-time");
|
|
33582
|
+
time.setAttribute("data-rel-time", conversationActivity(record));
|
|
33583
|
+
time.title = conversationActivity(record);
|
|
33584
|
+
var status = conversationStatus(record);
|
|
33585
|
+
var footer = featured ? createViewElement("div", "recent-projects-focus-footer") : null;
|
|
33586
|
+
if (featured) {
|
|
33587
|
+
meta.insertBefore(textNode(tr("recentProjects_focusEyebrow"), "recent-projects-focus-eyebrow"), project);
|
|
33588
|
+
copy.appendChild(meta);
|
|
33589
|
+
copy.appendChild(title);
|
|
33590
|
+
footer.appendChild(status ? renderStatusBadge(status) : textNode(tr("recentProjects_savedDraft"), "recent-projects-row-badge"));
|
|
33591
|
+
} else {
|
|
33592
|
+
copy.appendChild(title);
|
|
33593
|
+
copy.appendChild(meta);
|
|
33594
|
+
if (["failed", "needs_review", "interrupted", "stale", "needs_review_after_navigation", "abandoned_after_navigation"].indexOf(status) !== -1) {
|
|
33595
|
+
var attention = textNode(tr("recentProjects_attention"), "recent-projects-session-attention");
|
|
33596
|
+
attention.title = tr("recentProjects_badge_" + status);
|
|
33597
|
+
meta.appendChild(attention);
|
|
33598
|
+
}
|
|
33183
33599
|
}
|
|
33184
|
-
|
|
33600
|
+
meta.appendChild(time);
|
|
33601
|
+
row.appendChild(copy);
|
|
33602
|
+
var rename = createViewButton(tr("renameSession"), function() {
|
|
33185
33603
|
beginDashboardSessionRename(sessionsEl, projectId, record, row, title);
|
|
33186
|
-
});
|
|
33187
|
-
|
|
33604
|
+
}, "data-session-rename-dash");
|
|
33605
|
+
rename.title = rename.textContent;
|
|
33606
|
+
rename.setAttribute("aria-label", rename.textContent);
|
|
33607
|
+
if (running) rename.disabled = true;
|
|
33608
|
+
var del = createViewButton(tr("deleteSession"), function() {
|
|
33188
33609
|
deleteDashboardSession(sessionsEl, projectId, record).catch(function() {
|
|
33189
33610
|
});
|
|
33611
|
+
}, "data-session-delete-dash");
|
|
33612
|
+
del.title = running ? tr("recentProjects_zombieRunningNote") : del.textContent;
|
|
33613
|
+
del.setAttribute("aria-label", del.textContent);
|
|
33614
|
+
var projectConversations = createViewButton(tr("recentProjects_projectConversations"), function() {
|
|
33615
|
+
renderRecentProjectsVariant({ projectFilter: projectId, showAll: true, restoreScrollTop: 0 }).catch(function() {
|
|
33616
|
+
});
|
|
33617
|
+
}, "data-project-conversations");
|
|
33618
|
+
var openProject = createViewButton(tr("recentProjects_openProject"), function() {
|
|
33619
|
+
openProjectFromRow(projectId);
|
|
33190
33620
|
});
|
|
33191
|
-
|
|
33192
|
-
|
|
33193
|
-
|
|
33194
|
-
|
|
33195
|
-
row.
|
|
33196
|
-
row.setAttribute("role", "button");
|
|
33197
|
-
row.tabIndex = 0;
|
|
33621
|
+
var clear = createViewButton(tr("recentProjects_clearProject"), function() {
|
|
33622
|
+
projectSessionCleanup.clearProjectSessions(projectId, projectDisplayName(projectId)).catch(function() {
|
|
33623
|
+
});
|
|
33624
|
+
}, "data-project-clear");
|
|
33625
|
+
row.appendChild(renderActionsMenu([rename, del, projectConversations, openProject, clear]));
|
|
33198
33626
|
var activate = function() {
|
|
33199
|
-
|
|
33627
|
+
openDashboardConversation(projectId, record, row).catch(function() {
|
|
33200
33628
|
});
|
|
33201
33629
|
};
|
|
33202
|
-
|
|
33203
|
-
|
|
33204
|
-
|
|
33205
|
-
|
|
33206
|
-
|
|
33207
|
-
|
|
33208
|
-
|
|
33209
|
-
|
|
33210
|
-
|
|
33211
|
-
|
|
33212
|
-
|
|
33213
|
-
|
|
33630
|
+
if (featured) {
|
|
33631
|
+
row.setAttribute("role", "group");
|
|
33632
|
+
row.setAttribute("aria-label", tr("recentProjects_focusEyebrow"));
|
|
33633
|
+
var resume = createViewButton(tr("recentProjects_continue"), activate, "data-session-resume", "recent-projects-continue");
|
|
33634
|
+
resume.title = tr("recentProjects_continueHint");
|
|
33635
|
+
footer.appendChild(resume);
|
|
33636
|
+
row.appendChild(footer);
|
|
33637
|
+
} else {
|
|
33638
|
+
row.classList.add("recent-projects-session-row--linked");
|
|
33639
|
+
row.setAttribute("role", "button");
|
|
33640
|
+
row.tabIndex = 0;
|
|
33641
|
+
row.addEventListener("click", function(event) {
|
|
33642
|
+
if (!event.target.closest("button, input, details")) activate();
|
|
33643
|
+
});
|
|
33644
|
+
row.addEventListener("keydown", function(event) {
|
|
33645
|
+
if (event.target === row && (event.key === "Enter" || event.key === " ")) {
|
|
33646
|
+
event.preventDefault();
|
|
33647
|
+
activate();
|
|
33648
|
+
}
|
|
33649
|
+
});
|
|
33650
|
+
}
|
|
33214
33651
|
return row;
|
|
33215
33652
|
}
|
|
33216
33653
|
async function activateSessionAndOpenProject(projectId, record) {
|
|
@@ -33341,11 +33778,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33341
33778
|
} catch (error) {
|
|
33342
33779
|
showPluginToast(tr("deleteSessionHistoryFailedToast", { message: error.message }), { status: "warning", sticky: true });
|
|
33343
33780
|
}
|
|
33344
|
-
|
|
33345
|
-
await renderRecentProjectsVariant({
|
|
33346
|
-
expandProjectId: projectId,
|
|
33347
|
-
restoreScrollTop: rootForScroll ? rootForScroll.scrollTop : void 0
|
|
33348
|
-
});
|
|
33781
|
+
await refreshDashboardView();
|
|
33349
33782
|
}
|
|
33350
33783
|
function beginDashboardSessionRename(sessionsEl, projectId, record, row, titleEl) {
|
|
33351
33784
|
if (row.querySelector("input")) {
|
|
@@ -33358,7 +33791,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33358
33791
|
input.className = "recent-projects-session-rename-input";
|
|
33359
33792
|
input.value = seed;
|
|
33360
33793
|
titleEl.hidden = true;
|
|
33361
|
-
|
|
33794
|
+
titleEl.parentElement.insertBefore(input, titleEl);
|
|
33362
33795
|
input.focus();
|
|
33363
33796
|
input.select();
|
|
33364
33797
|
var settled = false;
|
|
@@ -33420,7 +33853,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33420
33853
|
}
|
|
33421
33854
|
} catch (_error) {
|
|
33422
33855
|
}
|
|
33423
|
-
await
|
|
33856
|
+
await refreshDashboardView();
|
|
33424
33857
|
}
|
|
33425
33858
|
function ensureRecentProjectsRoot() {
|
|
33426
33859
|
if (!getPanel()) {
|
|
@@ -33430,9 +33863,13 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33430
33863
|
if (existing) {
|
|
33431
33864
|
return existing;
|
|
33432
33865
|
}
|
|
33433
|
-
var rootEl =
|
|
33434
|
-
rootEl.className = "recent-projects-root";
|
|
33866
|
+
var rootEl = createViewElement("section", "recent-projects-root");
|
|
33435
33867
|
rootEl.setAttribute("data-recent-projects-root", "");
|
|
33868
|
+
rootEl.addEventListener("click", function(event) {
|
|
33869
|
+
rootEl.querySelectorAll(".recent-projects-menu[open]").forEach(function(menu) {
|
|
33870
|
+
if (!menu.contains(event.target)) menu.open = false;
|
|
33871
|
+
});
|
|
33872
|
+
});
|
|
33436
33873
|
getPanel().appendChild(rootEl);
|
|
33437
33874
|
return rootEl;
|
|
33438
33875
|
}
|
|
@@ -33469,116 +33906,152 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33469
33906
|
return;
|
|
33470
33907
|
}
|
|
33471
33908
|
rootEl.appendChild(renderWelcomeHeader());
|
|
33472
|
-
var loading =
|
|
33473
|
-
loading.className = "recent-projects-loading";
|
|
33474
|
-
loading.textContent = tx("Loading projects\u2026", "\u6B63\u5728\u52A0\u8F7D\u9879\u76EE\u2026");
|
|
33909
|
+
var loading = createViewElement("div", "recent-projects-loading", tx("Loading projects\u2026", "\u6B63\u5728\u52A0\u8F7D\u9879\u76EE\u2026"));
|
|
33475
33910
|
rootEl.appendChild(loading);
|
|
33476
33911
|
}
|
|
33477
33912
|
async function renderRecentProjectsVariant(options2) {
|
|
33478
|
-
|
|
33479
|
-
|
|
33480
|
-
|
|
33481
|
-
|
|
33913
|
+
var panelEl = getPanel();
|
|
33914
|
+
var editorMatch = String(window.location && window.location.pathname || "").match(/^\/project\/([a-f0-9]{24})(?:\/|$)/);
|
|
33915
|
+
if (!panelEl || editorMatch && isValidProjectId(editorMatch[1])) return;
|
|
33916
|
+
var previous = dashboardViewOptions();
|
|
33917
|
+
options2 = Object.assign({}, previous, options2 || {});
|
|
33918
|
+
var generation = ++dashboardRenderGeneration;
|
|
33919
|
+
panelEl.dataset.view = "recent-projects";
|
|
33482
33920
|
startRelativeTimeTicker();
|
|
33483
33921
|
var rootEl = ensureRecentProjectsRoot();
|
|
33484
|
-
if (!rootEl)
|
|
33485
|
-
return;
|
|
33486
|
-
}
|
|
33487
|
-
rootEl.innerHTML = "";
|
|
33488
|
-
rootEl.appendChild(renderWelcomeHeader());
|
|
33922
|
+
if (!rootEl) return;
|
|
33489
33923
|
var accountScopeId = (window.codexOverleafDeriveAccountScopeId || function() {
|
|
33490
33924
|
return null;
|
|
33491
33925
|
})();
|
|
33926
|
+
if (previous.accountScopeId !== accountScopeId) {
|
|
33927
|
+
options2.projectFilter = "";
|
|
33928
|
+
options2.showAll = options2.draftsOpen = false;
|
|
33929
|
+
}
|
|
33930
|
+
var projectFilter = isValidProjectId(options2.projectFilter) ? options2.projectFilter : "";
|
|
33931
|
+
rootEl.dataset.accountScopeId = accountScopeId || "";
|
|
33932
|
+
rootEl.dataset.projectFilter = projectFilter;
|
|
33933
|
+
rootEl.dataset.showAll = options2.showAll ? "true" : "false";
|
|
33934
|
+
rootEl.innerHTML = "";
|
|
33935
|
+
rootEl.appendChild(renderWelcomeHeader());
|
|
33492
33936
|
if (!accountScopeId) {
|
|
33493
33937
|
rootEl.appendChild(renderDegradedState());
|
|
33494
33938
|
rootEl.appendChild(renderSettingsEntry({ scope: "account" }));
|
|
33495
|
-
opportunisticEnrichmentFromDom().catch(function() {
|
|
33496
|
-
});
|
|
33497
33939
|
return;
|
|
33498
33940
|
}
|
|
33499
|
-
|
|
33500
|
-
|
|
33941
|
+
if (projectFilter) {
|
|
33942
|
+
var filterBar = createViewElement("div", "recent-projects-filter");
|
|
33943
|
+
var back = createViewButton(tr("recentProjects_allProjects"), function() {
|
|
33944
|
+
renderRecentProjectsVariant({ projectFilter: "", showAll: false, restoreScrollTop: 0 }).catch(function() {
|
|
33945
|
+
});
|
|
33946
|
+
});
|
|
33947
|
+
filterBar.appendChild(back);
|
|
33948
|
+
var filterName = textNode(projectDisplayName(projectFilter));
|
|
33949
|
+
filterName.title = filterName.textContent;
|
|
33950
|
+
filterBar.appendChild(filterName);
|
|
33951
|
+
rootEl.appendChild(filterBar);
|
|
33952
|
+
}
|
|
33953
|
+
var listContainer = createViewElement("div", "recent-projects-list");
|
|
33501
33954
|
listContainer.setAttribute("data-recent-projects-list", "");
|
|
33502
33955
|
rootEl.appendChild(listContainer);
|
|
33503
|
-
var
|
|
33504
|
-
|
|
33505
|
-
|
|
33506
|
-
|
|
33956
|
+
var loading = textNode(tr("recentProjects_loadingHistory"), "recent-projects-loading");
|
|
33957
|
+
listContainer.appendChild(loading);
|
|
33958
|
+
function stillCurrent() {
|
|
33959
|
+
return generation === dashboardRenderGeneration && getPanel() === panelEl && panelEl.dataset.view === "recent-projects" && rootEl.isConnected !== false && getCachedAccountScopeId() === accountScopeId;
|
|
33960
|
+
}
|
|
33961
|
+
var records;
|
|
33507
33962
|
try {
|
|
33508
33963
|
await loadProjectNameCacheFromStorage();
|
|
33964
|
+
records = await loadDashboardConversations(accountScopeId);
|
|
33509
33965
|
} catch (_error) {
|
|
33966
|
+
if (!stillCurrent()) return;
|
|
33967
|
+
loading.textContent = tr("recentProjects_loadFailed");
|
|
33968
|
+
var retry = createViewButton(tr("recentProjects_retryScope"), function() {
|
|
33969
|
+
renderRecentProjectsVariant(options2).catch(function() {
|
|
33970
|
+
});
|
|
33971
|
+
}, null, "recent-projects-show-all");
|
|
33972
|
+
listContainer.appendChild(retry);
|
|
33973
|
+
rootEl.appendChild(renderSettingsEntry({ scope: "account" }));
|
|
33974
|
+
return;
|
|
33510
33975
|
}
|
|
33511
|
-
|
|
33512
|
-
|
|
33513
|
-
var
|
|
33514
|
-
|
|
33515
|
-
|
|
33516
|
-
|
|
33517
|
-
|
|
33518
|
-
|
|
33519
|
-
|
|
33520
|
-
|
|
33976
|
+
if (!stillCurrent()) return;
|
|
33977
|
+
loading.remove();
|
|
33978
|
+
var validRecords = records.filter(function(record) {
|
|
33979
|
+
return isValidProjectId(record.projectId) && (!projectFilter || record.projectId === projectFilter);
|
|
33980
|
+
});
|
|
33981
|
+
var started = validRecords.filter(conversationHasContent);
|
|
33982
|
+
var unstarted = validRecords.filter(function(record) {
|
|
33983
|
+
return !conversationHasContent(record);
|
|
33984
|
+
});
|
|
33985
|
+
if (started.length) {
|
|
33986
|
+
listContainer.appendChild(renderProjectSessionRow(listContainer, started[0].projectId, started[0], { featured: true }));
|
|
33987
|
+
if (started.length > 1) {
|
|
33988
|
+
var heading = createViewElement("div", "recent-projects-history-heading");
|
|
33989
|
+
heading.appendChild(textNode(tr("recentProjects_historyHeading")));
|
|
33990
|
+
heading.appendChild(textNode(tr("recentProjects_historyHint")));
|
|
33991
|
+
listContainer.appendChild(heading);
|
|
33992
|
+
var historyList = createViewElement("div", "recent-projects-history-list");
|
|
33993
|
+
var history = options2.showAll ? started.slice(1) : started.slice(1, 10);
|
|
33994
|
+
history.forEach(function(record) {
|
|
33995
|
+
historyList.appendChild(renderProjectSessionRow(historyList, record.projectId, record));
|
|
33521
33996
|
});
|
|
33997
|
+
listContainer.appendChild(historyList);
|
|
33998
|
+
if (!options2.showAll && started.length > 10) {
|
|
33999
|
+
var more = createViewButton(tr("recentProjects_showAllConversations", { count: started.length }), function() {
|
|
34000
|
+
renderRecentProjectsVariant({ showAll: true }).catch(function() {
|
|
34001
|
+
});
|
|
34002
|
+
}, "data-recent-projects-show-all", "recent-projects-show-all");
|
|
34003
|
+
listContainer.appendChild(more);
|
|
34004
|
+
}
|
|
33522
34005
|
}
|
|
33523
|
-
} catch (_error) {
|
|
33524
|
-
rows = [];
|
|
33525
|
-
}
|
|
33526
|
-
listLoading.remove();
|
|
33527
|
-
var restoreExpanded = Array.isArray(options2 && options2.restoreExpanded) ? options2.restoreExpanded : [];
|
|
33528
|
-
var welcomeSubtitle = rootEl.querySelector(".recent-projects-welcome-subtitle");
|
|
33529
|
-
if (welcomeSubtitle && rows && rows.length) {
|
|
33530
|
-
var sessionTotal = 0;
|
|
33531
|
-
for (var st = 0; st < rows.length; st++) {
|
|
33532
|
-
sessionTotal += Number(rows[st].sessionCount) || 1;
|
|
33533
|
-
}
|
|
33534
|
-
welcomeSubtitle.textContent = tr("recentProjects_welcome_stats", {
|
|
33535
|
-
projects: rows.length,
|
|
33536
|
-
sessions: sessionTotal
|
|
33537
|
-
});
|
|
33538
|
-
}
|
|
33539
|
-
var hasMore = !showAll && rows && rows.length > pageLimit;
|
|
33540
|
-
var visibleRows = hasMore ? rows.slice(0, pageLimit) : rows;
|
|
33541
|
-
if (!visibleRows || !visibleRows.length) {
|
|
33542
|
-
listContainer.appendChild(renderEmptyState());
|
|
33543
34006
|
} else {
|
|
33544
|
-
|
|
33545
|
-
|
|
33546
|
-
|
|
33547
|
-
}
|
|
33548
|
-
if (
|
|
33549
|
-
|
|
33550
|
-
|
|
33551
|
-
|
|
33552
|
-
|
|
33553
|
-
|
|
33554
|
-
|
|
33555
|
-
|
|
34007
|
+
var empty = renderEmptyState();
|
|
34008
|
+
if (unstarted.length) empty.textContent = tr("recentProjects_noStarted");
|
|
34009
|
+
listContainer.appendChild(empty);
|
|
34010
|
+
}
|
|
34011
|
+
if (unstarted.length) {
|
|
34012
|
+
let populateDrafts = function() {
|
|
34013
|
+
if (draftsBuilt || !stillCurrent()) return;
|
|
34014
|
+
draftsBuilt = true;
|
|
34015
|
+
drafts.appendChild(textNode(tr("recentProjects_unstartedHint"), "recent-projects-drafts-hint"));
|
|
34016
|
+
unstarted.forEach(function(record) {
|
|
34017
|
+
drafts.appendChild(renderProjectSessionRow(drafts, record.projectId, record));
|
|
34018
|
+
});
|
|
34019
|
+
};
|
|
34020
|
+
var drafts = createViewElement("details", "recent-projects-drafts");
|
|
34021
|
+
drafts.setAttribute("data-unstarted-conversations", "");
|
|
34022
|
+
var summary = createViewElement("summary", "", tr("recentProjects_unstarted", { count: unstarted.length }));
|
|
34023
|
+
drafts.appendChild(summary);
|
|
34024
|
+
var draftsBuilt = false;
|
|
34025
|
+
drafts.addEventListener("toggle", function() {
|
|
34026
|
+
if (drafts.open) populateDrafts();
|
|
33556
34027
|
});
|
|
33557
|
-
listContainer.appendChild(
|
|
33558
|
-
|
|
33559
|
-
|
|
33560
|
-
|
|
33561
|
-
var toReopen = restoreExpanded.slice();
|
|
33562
|
-
if (expandProjectId && toReopen.indexOf(expandProjectId) === -1) {
|
|
33563
|
-
toReopen.push(expandProjectId);
|
|
33564
|
-
}
|
|
33565
|
-
for (var reopenIndex = 0; reopenIndex < toReopen.length; reopenIndex++) {
|
|
33566
|
-
var wrap = listContainer.querySelector('[data-project-row-wrap="' + toReopen[reopenIndex] + '"]');
|
|
33567
|
-
if (wrap) {
|
|
33568
|
-
toggleProjectSessions(wrap, toReopen[reopenIndex]);
|
|
34028
|
+
listContainer.appendChild(drafts);
|
|
34029
|
+
if (options2.draftsOpen) {
|
|
34030
|
+
drafts.open = true;
|
|
34031
|
+
populateDrafts();
|
|
33569
34032
|
}
|
|
33570
34033
|
}
|
|
33571
|
-
if (
|
|
33572
|
-
|
|
33573
|
-
|
|
33574
|
-
|
|
33575
|
-
|
|
33576
|
-
|
|
34034
|
+
if (!projectFilter) {
|
|
34035
|
+
var invalid = records.filter(function(record) {
|
|
34036
|
+
return !isValidProjectId(record.projectId);
|
|
34037
|
+
});
|
|
34038
|
+
var invalidIds = /* @__PURE__ */ new Set();
|
|
34039
|
+
if (invalid.length) listContainer.appendChild(textNode(tr("recentProjects_unavailableRecords"), "recent-projects-history-heading"));
|
|
34040
|
+
invalid.forEach(function(record) {
|
|
34041
|
+
var id = String(record.projectId || "");
|
|
34042
|
+
if (!invalidIds.has(id)) {
|
|
34043
|
+
invalidIds.add(id);
|
|
34044
|
+
listContainer.appendChild(renderRecentProjectRow({ projectId: record.projectId }));
|
|
34045
|
+
}
|
|
34046
|
+
});
|
|
33577
34047
|
}
|
|
34048
|
+
rootEl.appendChild(renderSettingsEntry({ scope: "account" }));
|
|
34049
|
+
if (Number.isFinite(options2.restoreScrollTop)) rootEl.scrollTop = options2.restoreScrollTop;
|
|
33578
34050
|
opportunisticEnrichmentFromDom().catch(function() {
|
|
33579
34051
|
});
|
|
33580
34052
|
}
|
|
33581
34053
|
function renderPerProjectVariant() {
|
|
34054
|
+
dashboardRenderGeneration++;
|
|
33582
34055
|
if (!getPanel()) {
|
|
33583
34056
|
return;
|
|
33584
34057
|
}
|
|
@@ -33653,6 +34126,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33653
34126
|
let currentOtStatus = "off";
|
|
33654
34127
|
let otTogglePending = false;
|
|
33655
34128
|
let otSyncRequestId = 0;
|
|
34129
|
+
let otStartRetryCount = 0;
|
|
33656
34130
|
let otWarmMirrorProjectId = "";
|
|
33657
34131
|
let lastExperimentalOtProjectId = "";
|
|
33658
34132
|
let otWarmMirrorState = {
|
|
@@ -33802,6 +34276,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33802
34276
|
const projectId = getCurrentProjectId();
|
|
33803
34277
|
otWarmMirrorState.failureActive = false;
|
|
33804
34278
|
lastExperimentalOtProjectId = projectId;
|
|
34279
|
+
otStartRetryCount = 0;
|
|
33805
34280
|
setExperimentalOtEnabledForProject(projectId, checkbox.checked);
|
|
33806
34281
|
updateExperimentalOtToggleControl(checkbox.checked);
|
|
33807
34282
|
const savedBadge = getPanel()?.querySelector('details[data-set-group="experimental"] [data-set-saved]');
|
|
@@ -33877,8 +34352,10 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33877
34352
|
await pauseOtWarmMirror(pauseAfterStart.reason || "paused");
|
|
33878
34353
|
return response;
|
|
33879
34354
|
}
|
|
33880
|
-
|
|
34355
|
+
if (status === "starting") recordOtFailure("missing_active_path", "start");
|
|
34356
|
+
else otWarmMirrorState.failureActive = false;
|
|
33881
34357
|
updateOtStatusDisplay(status);
|
|
34358
|
+
otStartRetryCount = 0;
|
|
33882
34359
|
scheduleOtEventPolling(projectId, { immediate: true });
|
|
33883
34360
|
return response;
|
|
33884
34361
|
}
|
|
@@ -33905,23 +34382,31 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33905
34382
|
clearOtEventPolling({ clearPatchQueue: true });
|
|
33906
34383
|
recordOtFailure(readOtBridgeErrorCode(response, "ot_start_failed"), "start");
|
|
33907
34384
|
otWarmMirrorState.suspended = true;
|
|
33908
|
-
|
|
33909
|
-
const experimentalOtCheckbox = getPanel()?.querySelector("[data-experimental-ot]");
|
|
33910
|
-
if (experimentalOtCheckbox) {
|
|
33911
|
-
experimentalOtCheckbox.checked = false;
|
|
33912
|
-
}
|
|
34385
|
+
updateExperimentalOtToggleControl(isExperimentalOtEnabledForProject(projectId));
|
|
33913
34386
|
updateOtStatusDisplay("unavailable");
|
|
33914
|
-
saveStateSoon();
|
|
33915
34387
|
try {
|
|
33916
34388
|
await callPageBridge("stopOtObserver", { projectId });
|
|
33917
34389
|
} catch (_error) {
|
|
33918
34390
|
}
|
|
34391
|
+
scheduleOtStartRetry(projectId, requestId);
|
|
34392
|
+
}
|
|
34393
|
+
function scheduleOtStartRetry(projectId, requestId) {
|
|
34394
|
+
const retryDelays = [1e3, 3e3, 6e3];
|
|
34395
|
+
const canRetry = () => isCurrentOtSync(requestId, projectId) && getCurrentProjectId() === projectId && isExperimentalOtEnabledForProject(projectId) && !getCurrentRunView();
|
|
34396
|
+
if (!canRetry() || otStartRetryCount >= retryDelays.length) return;
|
|
34397
|
+
const delayMs = retryDelays[otStartRetryCount++];
|
|
34398
|
+
otWarmMirrorState.pollTimer = window.setTimeout(() => {
|
|
34399
|
+
otWarmMirrorState.pollTimer = null;
|
|
34400
|
+
if (!canRetry()) return;
|
|
34401
|
+
syncOtWarmMirrorController().catch(() => {
|
|
34402
|
+
if (getCurrentProjectId() === projectId && isExperimentalOtEnabledForProject(projectId)) {
|
|
34403
|
+
updateOtStatusDisplay("unavailable");
|
|
34404
|
+
}
|
|
34405
|
+
});
|
|
34406
|
+
}, delayMs);
|
|
33919
34407
|
}
|
|
33920
34408
|
function readOtBridgeStatus(response) {
|
|
33921
|
-
|
|
33922
|
-
return "unavailable";
|
|
33923
|
-
}
|
|
33924
|
-
return response.state || response.status || response.result?.state || response.result?.status || "unavailable";
|
|
34409
|
+
return otWarmMirrorController.readOtBridgeStatus(response);
|
|
33925
34410
|
}
|
|
33926
34411
|
function ensureOtWarmMirrorStateProject(projectId) {
|
|
33927
34412
|
if (!projectId || otWarmMirrorState.projectId === projectId) {
|
|
@@ -33929,6 +34414,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33929
34414
|
}
|
|
33930
34415
|
clearOtEventPolling({ clearPatchQueue: true });
|
|
33931
34416
|
otWarmMirrorState.projectId = projectId;
|
|
34417
|
+
otStartRetryCount = 0;
|
|
33932
34418
|
otWarmMirrorState.lastPatchAt = 0;
|
|
33933
34419
|
otWarmMirrorState.lastErrorCode = "";
|
|
33934
34420
|
otWarmMirrorState.failureActive = false;
|
|
@@ -33992,6 +34478,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
33992
34478
|
return statusResponse;
|
|
33993
34479
|
}
|
|
33994
34480
|
const status = readOtBridgeStatus(statusResponse);
|
|
34481
|
+
if (status === "observing" && otWarmMirrorState.lastFailure?.phase === "start") Object.assign(otWarmMirrorState, { failureActive: false, lastErrorCode: "", lastFailure: null });
|
|
33995
34482
|
if (["unavailable", "inconsistent"].includes(status)) recordOtFailure(readOtBridgeErrorCode(statusResponse, "ot_observer_unavailable"), "observe");
|
|
33996
34483
|
if (status) {
|
|
33997
34484
|
updateOtStatusDisplay(status);
|
|
@@ -34022,20 +34509,10 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
34022
34509
|
}
|
|
34023
34510
|
}
|
|
34024
34511
|
function readOtBridgeEvents(response) {
|
|
34025
|
-
|
|
34026
|
-
return response;
|
|
34027
|
-
}
|
|
34028
|
-
if (Array.isArray(response?.events)) {
|
|
34029
|
-
return response.events;
|
|
34030
|
-
}
|
|
34031
|
-
if (Array.isArray(response?.result?.events)) {
|
|
34032
|
-
return response.result.events;
|
|
34033
|
-
}
|
|
34034
|
-
return [];
|
|
34512
|
+
return otWarmMirrorController.readOtBridgeEvents(response);
|
|
34035
34513
|
}
|
|
34036
34514
|
function readOtBridgeErrorCode(response, fallback) {
|
|
34037
|
-
|
|
34038
|
-
return typeof value === "string" ? value : fallback;
|
|
34515
|
+
return otWarmMirrorController.readOtBridgeErrorCode(response, fallback);
|
|
34039
34516
|
}
|
|
34040
34517
|
function recordOtFailure(code, phase) {
|
|
34041
34518
|
code = otWarmMirrorController.normalizeFailureCode(code);
|
|
@@ -34511,6 +34988,7 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
34511
34988
|
let tx;
|
|
34512
34989
|
let getLocale;
|
|
34513
34990
|
let appendRunEvent;
|
|
34991
|
+
let appendRunRecordEvent;
|
|
34514
34992
|
let pendingMirrorRefresh = null;
|
|
34515
34993
|
let appendChangeSummary;
|
|
34516
34994
|
let appendCompletionReport;
|
|
@@ -34557,6 +35035,34 @@ ${conclusion}` : `${label} ${conclusion}`;
|
|
|
34557
35035
|
function buildSettlement(input = {}) {
|
|
34558
35036
|
return writebackSettlement?.settle instanceof Function ? writebackSettlement.settle(input) : null;
|
|
34559
35037
|
}
|
|
35038
|
+
function invalidateMirrorAfterUndo(runId, projectId, result = {}) {
|
|
35039
|
+
if (!projectId || result?.changedDocument !== true && !result?.applied?.length) return Promise.resolve("not-attempted");
|
|
35040
|
+
const pending = Promise.resolve(pendingMirrorRefresh).catch(() => {
|
|
35041
|
+
}).then(async () => {
|
|
35042
|
+
const response = await sendBackgroundNative({ method: "mirror.invalidate", params: { projectId } });
|
|
35043
|
+
if (!response?.ok || response.result?.invalidated !== true) {
|
|
35044
|
+
throw new Error(response?.error?.message || "Native host did not confirm mirror invalidation.");
|
|
35045
|
+
}
|
|
35046
|
+
if (getCurrentProjectId() === projectId) {
|
|
35047
|
+
resetContextProject();
|
|
35048
|
+
await callPageBridge("invalidateProjectSnapshot", { invalidateFileList: true });
|
|
35049
|
+
}
|
|
35050
|
+
return "invalidated";
|
|
35051
|
+
}).catch((error) => {
|
|
35052
|
+
appendRunRecordEvent?.(runId, {
|
|
35053
|
+
status: "warning",
|
|
35054
|
+
title: tx(
|
|
35055
|
+
`Overleaf undo finished, but local mirror invalidation failed: ${error.message}. Refresh this project or reconnect the native host before running again.`,
|
|
35056
|
+
`Overleaf \u64A4\u9500\u5DF2\u5B8C\u6210\uFF0C\u4F46\u672C\u5730\u955C\u50CF\u5931\u6548\u5904\u7406\u5931\u8D25\uFF1A${error.message}\u3002\u8BF7\u5237\u65B0\u9879\u76EE\u6216\u91CD\u65B0\u8FDE\u63A5 Native Host \u540E\u518D\u8FD0\u884C\u3002`
|
|
35057
|
+
)
|
|
35058
|
+
});
|
|
35059
|
+
return "failed";
|
|
35060
|
+
}).finally(() => {
|
|
35061
|
+
if (pendingMirrorRefresh === pending) pendingMirrorRefresh = null;
|
|
35062
|
+
});
|
|
35063
|
+
pendingMirrorRefresh = pending;
|
|
35064
|
+
return pending;
|
|
35065
|
+
}
|
|
34560
35066
|
async function applySyncChangesToOverleaf(syncChanges = [], project = {}, options2 = {}) {
|
|
34561
35067
|
const runMode = options2.mode || getState().mode;
|
|
34562
35068
|
const runRequireReviewing = typeof options2.requireReviewing === "boolean" ? options2.requireReviewing : getState().requireReviewing === true;
|
|
@@ -35209,6 +35715,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35209
35715
|
tx,
|
|
35210
35716
|
getLocale,
|
|
35211
35717
|
appendRunEvent,
|
|
35718
|
+
appendRunRecordEvent,
|
|
35212
35719
|
appendChangeSummary,
|
|
35213
35720
|
appendCompletionReport,
|
|
35214
35721
|
appendOperationsPreview,
|
|
@@ -35254,6 +35761,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35254
35761
|
return {
|
|
35255
35762
|
applySyncChangesToOverleaf,
|
|
35256
35763
|
resolveCompileLogContext,
|
|
35764
|
+
invalidateMirrorAfterUndo,
|
|
35257
35765
|
getPendingMirrorRefresh: () => pendingMirrorRefresh
|
|
35258
35766
|
};
|
|
35259
35767
|
}
|
|
@@ -35261,6 +35769,153 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35261
35769
|
})();
|
|
35262
35770
|
}).call(globalThis, void 0, void 0, void 0);
|
|
35263
35771
|
(function runClassicContentModule94(module, exports, require2) {
|
|
35772
|
+
(function(root, factory) {
|
|
35773
|
+
const api = factory();
|
|
35774
|
+
if (typeof module === "object" && module.exports) module.exports = api;
|
|
35775
|
+
if (root) root.CodexOverleafTrackedChangeCaptureController = api;
|
|
35776
|
+
})(typeof window !== "undefined" ? window : globalThis, function() {
|
|
35777
|
+
"use strict";
|
|
35778
|
+
function create(deps = {}) {
|
|
35779
|
+
const now = deps.now || (() => Date.now());
|
|
35780
|
+
const defer = deps.setTimeout || setTimeout;
|
|
35781
|
+
const cancelTimer = deps.clearTimeout || clearTimeout;
|
|
35782
|
+
let timer = null, busy = false, disposed = false;
|
|
35783
|
+
const runs = () => deps.getRuns() || [];
|
|
35784
|
+
const pending = (run) => Array.isArray(run.trackedChangeCaptures) && run.trackedChangeCaptures.some((capture) => capture.state === "pending");
|
|
35785
|
+
const terminal = (run) => ["accepted", "rejected"].includes(run.trackedChangeStatus) || run.undoStatus === "applied" || run.forkSnapshot === true;
|
|
35786
|
+
function buildPostFiles(run) {
|
|
35787
|
+
const expectedFiles = Array.isArray(run?.undoExpectedFiles) ? run.undoExpectedFiles : [];
|
|
35788
|
+
const appliedOperations = Array.isArray(run?.appliedOperations) ? run.appliedOperations : [];
|
|
35789
|
+
if (!expectedFiles.length || !appliedOperations.length) return [];
|
|
35790
|
+
const postFilesByPath = deps.buildExpectedFilesAfterOperations({ files: expectedFiles }, appliedOperations);
|
|
35791
|
+
const expectedPaths = new Set(expectedFiles.map((file) => file?.path).filter(Boolean));
|
|
35792
|
+
return Array.from(postFilesByPath.entries()).filter(([path, content]) => expectedPaths.has(path) && typeof content === "string").map(([path, content]) => ({ path, content }));
|
|
35793
|
+
}
|
|
35794
|
+
function hasLegacyUntrackedCheckpoint(run) {
|
|
35795
|
+
if (!run || run.executionSnapshot || run.trackedChangeStatus || run.undoStatus === "applied" || run.forkSnapshot || run.undoTrackedChanges?.length || run.trackedChangeCaptures?.length) return false;
|
|
35796
|
+
const operations = Array.isArray(run.undoOperations) ? run.undoOperations : [];
|
|
35797
|
+
const before = Array.isArray(run.undoExpectedFiles) ? run.undoExpectedFiles : [];
|
|
35798
|
+
if (!operations.length || !before.length || before.some((file) => !file?.path || typeof file.content !== "string")) return false;
|
|
35799
|
+
const paths = new Set(before.map((file) => file.path));
|
|
35800
|
+
if (paths.size !== before.length || operations.some((op) => op?.type !== "edit" || !paths.has(op.path))) return false;
|
|
35801
|
+
const complete = (files) => Array.isArray(files) && files.length === paths.size && new Set(files.map((file) => file?.path)).size === paths.size && files.every((file) => paths.has(file?.path) && typeof file.content === "string");
|
|
35802
|
+
const storedPost = run.undoBaseFiles;
|
|
35803
|
+
try {
|
|
35804
|
+
const post = buildPostFiles(run);
|
|
35805
|
+
if (!complete(storedPost) || !complete(post)) return false;
|
|
35806
|
+
const postByPath = new Map(post.map((file) => [file.path, file.content]));
|
|
35807
|
+
if (!storedPost.every((file) => postByPath.get(file.path) === file.content)) return false;
|
|
35808
|
+
const restored = deps.buildExpectedFilesAfterOperations({ files: storedPost }, operations);
|
|
35809
|
+
return before.every((file) => restored.get(file.path) === file.content);
|
|
35810
|
+
} catch (_error) {
|
|
35811
|
+
return false;
|
|
35812
|
+
}
|
|
35813
|
+
}
|
|
35814
|
+
function schedule() {
|
|
35815
|
+
if (disposed || timer !== null || busy || !runs().some(pending)) return;
|
|
35816
|
+
timer = defer(() => {
|
|
35817
|
+
timer = null;
|
|
35818
|
+
flush().catch((error) => deps.onError?.(error));
|
|
35819
|
+
}, 500);
|
|
35820
|
+
}
|
|
35821
|
+
function record(run, captures) {
|
|
35822
|
+
if (!Array.isArray(captures) || !captures.length) return;
|
|
35823
|
+
const next = [...run.trackedChangeCaptures || [], ...captures.filter(Boolean)];
|
|
35824
|
+
if (next.every((capture) => capture.state === "observed")) return;
|
|
35825
|
+
run.trackedChangeCaptures = next;
|
|
35826
|
+
deps.notify?.(run, next.some((capture) => capture.state === "pending") ? "pending" : "needs_review", {
|
|
35827
|
+
captures: next.map((capture) => ({ path: capture.path, reason: capture.reason, ...capture.diagnostics }))
|
|
35828
|
+
});
|
|
35829
|
+
deps.persist().then(schedule).catch((error) => deps.onError?.(error));
|
|
35830
|
+
}
|
|
35831
|
+
async function flush() {
|
|
35832
|
+
if (disposed || busy) return;
|
|
35833
|
+
busy = true;
|
|
35834
|
+
try {
|
|
35835
|
+
for (const run of runs().filter(pending)) {
|
|
35836
|
+
if (terminal(run)) {
|
|
35837
|
+
run.trackedChangeCaptures = [];
|
|
35838
|
+
await deps.persist();
|
|
35839
|
+
continue;
|
|
35840
|
+
}
|
|
35841
|
+
if (run.runProjectId !== deps.getProjectId()) continue;
|
|
35842
|
+
const newer = runs().some((other) => other.id !== run.id && other.runProjectId === run.runProjectId && Date.parse(other.startedAt) > Date.parse(run.startedAt));
|
|
35843
|
+
const original = run.trackedChangeCaptures;
|
|
35844
|
+
const captures = original.map((capture) => ({ ...capture }));
|
|
35845
|
+
const postFiles = buildPostFiles(run);
|
|
35846
|
+
for (let i = 0; i < captures.length; i++) {
|
|
35847
|
+
const capture = captures[i];
|
|
35848
|
+
if (capture.state !== "pending") continue;
|
|
35849
|
+
const expected = postFiles.find((file) => file.path === capture.path);
|
|
35850
|
+
if (newer || !expected || now() >= capture.expiresAt || run.status === "cancelled") {
|
|
35851
|
+
capture.state = "needs_review";
|
|
35852
|
+
capture.reason = newer ? "capture_superseded" : !expected ? "capture_baseline_missing" : run.status === "cancelled" ? "capture_cancelled" : "capture_expired";
|
|
35853
|
+
continue;
|
|
35854
|
+
}
|
|
35855
|
+
let response;
|
|
35856
|
+
try {
|
|
35857
|
+
response = await deps.callPageBridge("reconcileTrackedChangeCapture", {
|
|
35858
|
+
runProjectId: run.runProjectId,
|
|
35859
|
+
capture,
|
|
35860
|
+
expectedContent: expected.content
|
|
35861
|
+
});
|
|
35862
|
+
} catch (_error) {
|
|
35863
|
+
response = null;
|
|
35864
|
+
}
|
|
35865
|
+
if (disposed || deps.getProjectId() !== run.runProjectId || !runs().includes(run) || terminal(run) || run.trackedChangeCaptures !== original) return;
|
|
35866
|
+
const superseded = runs().some((other) => other.id !== run.id && other.runProjectId === run.runProjectId && Date.parse(other.startedAt) > Date.parse(run.startedAt));
|
|
35867
|
+
if (superseded || run.status === "cancelled") {
|
|
35868
|
+
captures[i] = { ...capture, state: "needs_review", reason: "capture_superseded" };
|
|
35869
|
+
} else if (response?.capture?.path === capture.path && response.capture.runProjectId === run.runProjectId && ["observed", "pending", "needs_review"].includes(response.capture.state)) {
|
|
35870
|
+
captures[i] = response.capture;
|
|
35871
|
+
} else {
|
|
35872
|
+
captures[i] = { ...capture, state: "needs_review", reason: "capture_bridge_unavailable" };
|
|
35873
|
+
}
|
|
35874
|
+
}
|
|
35875
|
+
if (!runs().includes(run) || terminal(run) || deps.getProjectId() !== run.runProjectId) continue;
|
|
35876
|
+
if (captures.length && captures.every((capture) => capture.state === "observed")) {
|
|
35877
|
+
const refs = deps.normalizeTrackedChanges([
|
|
35878
|
+
...run.undoTrackedChanges || [],
|
|
35879
|
+
...captures.flatMap((capture) => capture.refs || [])
|
|
35880
|
+
]);
|
|
35881
|
+
if (refs.length) {
|
|
35882
|
+
run.undoTrackedChanges = refs;
|
|
35883
|
+
run.trackedChangeStatus = "pending";
|
|
35884
|
+
run.trackedChangeCaptures = [];
|
|
35885
|
+
await deps.persist();
|
|
35886
|
+
deps.refresh(run);
|
|
35887
|
+
deps.notify?.(run, "observed", { count: refs.length });
|
|
35888
|
+
continue;
|
|
35889
|
+
}
|
|
35890
|
+
}
|
|
35891
|
+
const changed = JSON.stringify(original.map(summary)) !== JSON.stringify(captures.map(summary));
|
|
35892
|
+
if (changed) {
|
|
35893
|
+
run.trackedChangeCaptures = captures;
|
|
35894
|
+
await deps.persist();
|
|
35895
|
+
if (!pending(run)) deps.notify?.(run, "needs_review", {
|
|
35896
|
+
reasons: captures.filter((capture) => capture.state !== "observed").map((capture) => capture.reason)
|
|
35897
|
+
});
|
|
35898
|
+
}
|
|
35899
|
+
}
|
|
35900
|
+
} finally {
|
|
35901
|
+
busy = false;
|
|
35902
|
+
if (runs().some((run) => pending(run) && run.runProjectId === deps.getProjectId())) schedule();
|
|
35903
|
+
}
|
|
35904
|
+
}
|
|
35905
|
+
function summary(capture) {
|
|
35906
|
+
return { state: capture.state, reason: capture.reason, refs: (capture.refs || []).map((ref) => ref.key) };
|
|
35907
|
+
}
|
|
35908
|
+
function dispose() {
|
|
35909
|
+
disposed = true;
|
|
35910
|
+
if (timer !== null) cancelTimer(timer);
|
|
35911
|
+
timer = null;
|
|
35912
|
+
}
|
|
35913
|
+
return { record, schedule, flush, dispose, buildPostFiles, hasLegacyUntrackedCheckpoint };
|
|
35914
|
+
}
|
|
35915
|
+
return { create };
|
|
35916
|
+
});
|
|
35917
|
+
}).call(globalThis, void 0, void 0, void 0);
|
|
35918
|
+
(function runClassicContentModule95(module, exports, require2) {
|
|
35264
35919
|
(function initCodexOverleafRunSettlementPersistence(root, factory) {
|
|
35265
35920
|
const api = factory();
|
|
35266
35921
|
if (typeof module === "object" && module.exports) module.exports = api;
|
|
@@ -35303,7 +35958,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35303
35958
|
return Object.freeze({ create });
|
|
35304
35959
|
});
|
|
35305
35960
|
}).call(globalThis, void 0, void 0, void 0);
|
|
35306
|
-
(function
|
|
35961
|
+
(function runClassicContentModule96(module, exports, require2) {
|
|
35307
35962
|
(function initPostNavigationSettlementPersistence(root, factory) {
|
|
35308
35963
|
const api = factory();
|
|
35309
35964
|
if (typeof module === "object" && module.exports) module.exports = api;
|
|
@@ -35395,7 +36050,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35395
36050
|
return Object.freeze({ persist, persistRequired });
|
|
35396
36051
|
});
|
|
35397
36052
|
}).call(globalThis, void 0, void 0, void 0);
|
|
35398
|
-
(function
|
|
36053
|
+
(function runClassicContentModule97(module, exports, require2) {
|
|
35399
36054
|
(function initCodexOverleafPanelMaintenance() {
|
|
35400
36055
|
"use strict";
|
|
35401
36056
|
function create(deps = {}) {
|
|
@@ -35506,11 +36161,12 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35506
36161
|
}
|
|
35507
36162
|
const requestId = ++storageUsageRequestId;
|
|
35508
36163
|
const projectId = getCurrentProjectId?.();
|
|
35509
|
-
const
|
|
36164
|
+
const settingsScope = getPanel?.()?.dataset?.settingsScope;
|
|
36165
|
+
const isCurrent = () => requestId === storageUsageRequestId && projectId === getCurrentProjectId?.() && settingsScope === getPanel?.()?.dataset?.settingsScope && getSettingsPanelInstance()?.container?.querySelector("[data-storage-usage]") === node;
|
|
35510
36166
|
const current = getState();
|
|
35511
36167
|
const sessionCount = Array.isArray(current?.sessions) ? current.sessions.length : 0;
|
|
35512
36168
|
const runCount = Array.isArray(current?.runs) ? current.runs.length : 0;
|
|
35513
|
-
const counts = tx(
|
|
36169
|
+
const counts = settingsScope === "account" ? tx("All projects in this browser", "\u5F53\u524D\u6D4F\u89C8\u5668\u4E2D\u7684\u6240\u6709\u9879\u76EE") : tx(
|
|
35514
36170
|
`${sessionCount} loaded session(s) in this project \xB7 ${runCount} run(s) in the active session`,
|
|
35515
36171
|
`\u5F53\u524D\u9879\u76EE\u5DF2\u52A0\u8F7D ${sessionCount} \u4E2A\u4F1A\u8BDD \xB7 \u5F53\u524D\u4F1A\u8BDD ${runCount} \u8F6E\u8FD0\u884C`
|
|
35516
36172
|
);
|
|
@@ -35726,7 +36382,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35726
36382
|
window.CodexOverleafPanelMaintenance = { create };
|
|
35727
36383
|
})();
|
|
35728
36384
|
}).call(globalThis, void 0, void 0, void 0);
|
|
35729
|
-
(function
|
|
36385
|
+
(function runClassicContentModule98(module, exports, require2) {
|
|
35730
36386
|
(function initCodexOverleafUpdateIdle(root) {
|
|
35731
36387
|
"use strict";
|
|
35732
36388
|
function create(options2 = {}) {
|
|
@@ -35794,7 +36450,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
35794
36450
|
root.CodexOverleafUpdateIdle = Object.freeze({ create });
|
|
35795
36451
|
})(typeof window !== "undefined" ? window : globalThis);
|
|
35796
36452
|
}).call(globalThis, void 0, void 0, void 0);
|
|
35797
|
-
(function
|
|
36453
|
+
(function runClassicContentModule99(module, exports, require2) {
|
|
35798
36454
|
(function initCodexOverleafUpdateNotice(root, factory) {
|
|
35799
36455
|
if (typeof module === "object" && module.exports) {
|
|
35800
36456
|
module.exports = factory(require2("../shared/managedUpdateProjection"));
|
|
@@ -36259,7 +36915,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
36259
36915
|
return Object.freeze({ mount });
|
|
36260
36916
|
});
|
|
36261
36917
|
}).call(globalThis, void 0, void 0, void 0);
|
|
36262
|
-
(function
|
|
36918
|
+
(function runClassicContentModule100(module, exports, require2) {
|
|
36263
36919
|
(function initCodexOverleafContentRuntime(root) {
|
|
36264
36920
|
"use strict";
|
|
36265
36921
|
function init(dependencies2) {
|
|
@@ -36312,6 +36968,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
36312
36968
|
"mirror.sync",
|
|
36313
36969
|
"mirror.patchFiles",
|
|
36314
36970
|
"mirror.confirmWriteback",
|
|
36971
|
+
"mirror.invalidate",
|
|
36315
36972
|
"mirror.scanSensitive",
|
|
36316
36973
|
"codex.history.clearPlugin",
|
|
36317
36974
|
"skills.list",
|
|
@@ -36812,6 +37469,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
36812
37469
|
RUN_SNAPSHOT_ZIP_TIMEOUT_MS,
|
|
36813
37470
|
getState: () => state,
|
|
36814
37471
|
getCurrentRunView: () => currentRunView,
|
|
37472
|
+
appendRunRecordEvent,
|
|
36815
37473
|
onMirrorRefreshSettled: runSettlementPersistence.settleMirrorRefresh
|
|
36816
37474
|
});
|
|
36817
37475
|
const {
|
|
@@ -37013,6 +37671,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
37013
37671
|
},
|
|
37014
37672
|
saveState,
|
|
37015
37673
|
saveStateSoon,
|
|
37674
|
+
onProjectFilesReady: refreshHistoricalProjectReferences,
|
|
37016
37675
|
updateActiveSession,
|
|
37017
37676
|
callPageBridge,
|
|
37018
37677
|
getCurrentProjectId,
|
|
@@ -38483,15 +39142,19 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
38483
39142
|
setRunning(false);
|
|
38484
39143
|
nativeChannel.clearActiveRequest();
|
|
38485
39144
|
stopRunElapsedTick();
|
|
38486
|
-
if (isExperimentalOtEnabled()) {
|
|
38487
|
-
await resumeOtWarmMirror("run-settled");
|
|
38488
|
-
}
|
|
38489
39145
|
await flushQueuedSaveState().catch(() => {
|
|
38490
39146
|
});
|
|
38491
39147
|
currentRunView = null;
|
|
38492
39148
|
runCancellationRequested = false;
|
|
38493
39149
|
runCancellationController = null;
|
|
38494
39150
|
activeTurnControl.release(settlement.requestId);
|
|
39151
|
+
if (isExperimentalOtEnabled()) {
|
|
39152
|
+
try {
|
|
39153
|
+
await resumeOtWarmMirror("run-settled");
|
|
39154
|
+
} catch (_error) {
|
|
39155
|
+
updateOtStatusDisplay("unavailable");
|
|
39156
|
+
}
|
|
39157
|
+
}
|
|
38495
39158
|
if (settlement.requestId) {
|
|
38496
39159
|
activeTurnControl.acknowledge(settlement.requestId).catch(() => {
|
|
38497
39160
|
});
|
|
@@ -41060,6 +41723,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41060
41723
|
title: session.title || "",
|
|
41061
41724
|
titleSource: session.titleSource || "auto",
|
|
41062
41725
|
focusFiles: session.focusFiles || [],
|
|
41726
|
+
projectReferenceFiles: session.projectReferenceFiles || [],
|
|
41063
41727
|
codexThreadId: session.codexThreadId || "",
|
|
41064
41728
|
createdAt: session.createdAt,
|
|
41065
41729
|
updatedAt: session.updatedAt,
|
|
@@ -41125,6 +41789,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41125
41789
|
const urlProjectId = getCurrentProjectId();
|
|
41126
41790
|
const projectId = projectIdOverride || urlProjectId;
|
|
41127
41791
|
if (!projectId) {
|
|
41792
|
+
if (options2?.reviewRunIds?.length) throw new Error("Review persistence lost its project.");
|
|
41128
41793
|
return;
|
|
41129
41794
|
}
|
|
41130
41795
|
const liveRunView = readLiveRunViewForSaveStateGuard();
|
|
@@ -41133,6 +41798,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41133
41798
|
"Skipped saveState: run is in flight on a different project than the current URL; settlement owns persistence.",
|
|
41134
41799
|
"\u5DF2\u8DF3\u8FC7 saveState\uFF1A\u672C\u6B21\u8FD0\u884C\u6240\u5C5E\u9879\u76EE\u4E0E\u5F53\u524D URL \u4E0D\u4E00\u81F4\uFF0C\u5199\u56DE\u7531 settlement \u8D1F\u8D23\u3002"
|
|
41135
41800
|
));
|
|
41801
|
+
if (options2?.reviewRunIds?.length) throw new Error("Review persistence project changed.");
|
|
41136
41802
|
return;
|
|
41137
41803
|
}
|
|
41138
41804
|
const compactState = prepareStateForStorage(state, { onAggressive: notifyAggressiveCompactionOnce });
|
|
@@ -41150,6 +41816,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41150
41816
|
compactState: compactStateSnapshot,
|
|
41151
41817
|
projectId,
|
|
41152
41818
|
deletedSessionIds: options2?.deletedSessionIds,
|
|
41819
|
+
reviewRunIds: options2?.reviewRunIds,
|
|
41153
41820
|
Migration,
|
|
41154
41821
|
StorageDb,
|
|
41155
41822
|
SessionPersistence: Modules.SessionPersistence,
|
|
@@ -41175,17 +41842,17 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41175
41842
|
},
|
|
41176
41843
|
persistScopedState
|
|
41177
41844
|
);
|
|
41178
|
-
if (!committed.ok && (options2?.queueMutation || options2?.queueMutations?.length || committed.reason !== "stale_view")) {
|
|
41845
|
+
if (!committed.ok && (options2?.reviewRunIds?.length || options2?.queueMutation || options2?.queueMutations?.length || committed.reason !== "stale_view")) {
|
|
41179
41846
|
throw Object.assign(new Error(`Scoped persistence failed: ${committed.reason}`), {
|
|
41180
41847
|
code: committed.reason
|
|
41181
41848
|
});
|
|
41182
41849
|
}
|
|
41183
41850
|
}
|
|
41184
41851
|
} catch (error) {
|
|
41185
|
-
if (error?.code === "account_scope_unavailable" && !options2?.queueMutation && !(Array.isArray(options2?.queueMutations) && options2.queueMutations.length)) {
|
|
41852
|
+
if (error?.code === "account_scope_unavailable" && !options2?.reviewRunIds?.length && !options2?.queueMutation && !(Array.isArray(options2?.queueMutations) && options2.queueMutations.length)) {
|
|
41186
41853
|
return;
|
|
41187
41854
|
}
|
|
41188
|
-
if (options2?.queueMutation || options2?.queueMutations?.length) {
|
|
41855
|
+
if (options2?.reviewRunIds?.length || options2?.queueMutation || options2?.queueMutations?.length) {
|
|
41189
41856
|
throw error;
|
|
41190
41857
|
}
|
|
41191
41858
|
let fallbackError = null;
|
|
@@ -41284,6 +41951,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41284
41951
|
if (isStorageQuotaError(error)) {
|
|
41285
41952
|
emitStorageQuotaFailure(error, null);
|
|
41286
41953
|
}
|
|
41954
|
+
if (persistenceOptions?.reviewRunIds?.length) throw error;
|
|
41287
41955
|
appendPlainLog(tx(`Failed to save session state: ${formatStateSaveError(error)}`, `\u4FDD\u5B58\u4F1A\u8BDD\u72B6\u6001\u5931\u8D25\uFF1A${formatStateSaveError(error)}`));
|
|
41288
41956
|
}).finally(() => {
|
|
41289
41957
|
if (saveStateInFlightPromise === runPromise) {
|
|
@@ -41330,6 +41998,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41330
41998
|
...current || {},
|
|
41331
41999
|
...incoming,
|
|
41332
42000
|
queueMutation: void 0,
|
|
42001
|
+
reviewRunIds: Array.from(/* @__PURE__ */ new Set([...current?.reviewRunIds || [], ...incoming?.reviewRunIds || []])),
|
|
41333
42002
|
queueMutations,
|
|
41334
42003
|
deletedSessionIds: Array.from(/* @__PURE__ */ new Set([
|
|
41335
42004
|
...current?.deletedSessionIds || [],
|
|
@@ -41371,15 +42040,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41371
42040
|
renderSessionList();
|
|
41372
42041
|
}
|
|
41373
42042
|
function getRenderedModelEntries() {
|
|
41374
|
-
return
|
|
41375
|
-
id: option.value,
|
|
41376
|
-
label: option.textContent,
|
|
41377
|
-
reasoningEfforts: (option.dataset.reasoningEfforts || "").split(",").filter(Boolean),
|
|
41378
|
-
defaultReasoningEffort: option.dataset.defaultReasoningEffort || "",
|
|
41379
|
-
reasoningPresentation: option.dataset.reasoningPresentation || "",
|
|
41380
|
-
speedTiers: (option.dataset.speedTiers || "standard").split(",").filter(Boolean),
|
|
41381
|
-
defaultSpeedTier: option.dataset.defaultSpeedTier || "standard"
|
|
41382
|
-
}));
|
|
42043
|
+
return Modules.ModelPickerSupport.getRenderedModelEntries(panel);
|
|
41383
42044
|
}
|
|
41384
42045
|
async function selectMode(mode) {
|
|
41385
42046
|
if (!["ask", "auto"].includes(mode)) {
|
|
@@ -41500,6 +42161,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41500
42161
|
applySessionLabel();
|
|
41501
42162
|
renderSessionList();
|
|
41502
42163
|
renderRunHistory(options2);
|
|
42164
|
+
getTrackedChangeCaptureController().schedule();
|
|
41503
42165
|
renderContextSelection();
|
|
41504
42166
|
renderContextSummary();
|
|
41505
42167
|
if (!composerAttachmentsRestoredOnce && Array.isArray(state.composerAttachments) && state.composerAttachments.length && !composerAttachmentController.getAttachmentsForRun?.().length && typeof composerAttachmentController.restorePersistedAttachments === "function") {
|
|
@@ -41578,6 +42240,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41578
42240
|
undoStatus: "",
|
|
41579
42241
|
queueItemId,
|
|
41580
42242
|
nativeRequestId: "",
|
|
42243
|
+
codexThreadId: "",
|
|
41581
42244
|
codexTurnId: "",
|
|
41582
42245
|
nativeEventSeq: 0,
|
|
41583
42246
|
executionSnapshot: executionSnapshot ? RunExecutionSnapshot.cloneSnapshot(executionSnapshot) : void 0,
|
|
@@ -41716,6 +42379,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
41716
42379
|
currentRunView.activeTurn = { threadId, turnId };
|
|
41717
42380
|
const record = findRunRecord(currentRunView.recordId, currentRunView.sessionId);
|
|
41718
42381
|
if (record) {
|
|
42382
|
+
record.codexThreadId = threadId;
|
|
41719
42383
|
record.codexTurnId = turnId;
|
|
41720
42384
|
record.nativeEventSeq = Math.max(Number(record.nativeEventSeq || 0), Number(journalSeq || 0));
|
|
41721
42385
|
}
|
|
@@ -42029,6 +42693,12 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42029
42693
|
}
|
|
42030
42694
|
return files;
|
|
42031
42695
|
}
|
|
42696
|
+
function refreshHistoricalProjectReferences(project) {
|
|
42697
|
+
if (!project?.id || String(project.id) !== getCurrentProjectId()) return;
|
|
42698
|
+
state = updateActiveSession(state, { projectReferenceFiles: captureProjectReferenceFiles(project) });
|
|
42699
|
+
saveStateSoon();
|
|
42700
|
+
if (!currentRunView && !trackedChangeInFlight.size) renderRunHistory({ preserveScroll: true });
|
|
42701
|
+
}
|
|
42032
42702
|
function persistCurrentProjectReferenceFiles(project) {
|
|
42033
42703
|
const projectFiles = captureProjectReferenceFiles(project);
|
|
42034
42704
|
if (currentRunView) {
|
|
@@ -42143,6 +42813,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42143
42813
|
runProjectId: getRunProjectIdForWriteback(run)
|
|
42144
42814
|
});
|
|
42145
42815
|
const undoApplied = isUndoResultEffectivelyApplied(run, result);
|
|
42816
|
+
writebackOrchestrator.invalidateMirrorAfterUndo(runId, getRunProjectIdForWriteback(run), result);
|
|
42146
42817
|
appendUndoReviewingPolicyEvent(runId, result.reviewingPolicy);
|
|
42147
42818
|
appendRunRecordEvent(runId, {
|
|
42148
42819
|
title: tr("undoResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
@@ -42194,46 +42865,50 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42194
42865
|
status: "running",
|
|
42195
42866
|
detail: { [tr("detailWillUndo")]: trackedUndo ? formatTrackedChangeFiles(run.undoTrackedChanges) : formatTrackedUndoFiles(run) }
|
|
42196
42867
|
});
|
|
42197
|
-
let result;
|
|
42198
42868
|
try {
|
|
42199
|
-
|
|
42869
|
+
const trackedUndoPostFilesAtDispatch = buildTrackedUndoPostFiles(run);
|
|
42870
|
+
const result = await callPageBridge("rejectTrackedChanges", {
|
|
42200
42871
|
trackedChanges: run.undoTrackedChanges || [],
|
|
42201
42872
|
expectedFiles: run.undoExpectedFiles || [],
|
|
42202
|
-
postFiles:
|
|
42873
|
+
postFiles: trackedUndoPostFilesAtDispatch,
|
|
42874
|
+
untrackedUndo: run.executionSnapshot ? run.executionSnapshot.requireReviewing === false && ["submitted", "legacy-captured"].includes(run.executionSnapshot.source) : getTrackedChangeCaptureController().hasLegacyUntrackedCheckpoint(run),
|
|
42203
42875
|
// Welcome-panel + write-guard:
|
|
42204
42876
|
// bind the reject to the run's original project. If the user has
|
|
42205
42877
|
// navigated away the page-side guard refuses with
|
|
42206
42878
|
// `aborted_project_changed` and the document is left untouched.
|
|
42207
42879
|
runProjectId: getRunProjectIdForWriteback(run)
|
|
42208
42880
|
});
|
|
42881
|
+
writebackOrchestrator.invalidateMirrorAfterUndo(runId, getRunProjectIdForWriteback(run), result);
|
|
42882
|
+
appendRunRecordEvent(runId, {
|
|
42883
|
+
title: trackedUndo ? tr("undoTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }) : tr("undoNativeResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42884
|
+
status: result.skipped?.length ? "failed" : "completed",
|
|
42885
|
+
detail: {
|
|
42886
|
+
[trackedUndo ? tr("detailRejected") : tr("detailUndone")]: (result.applied || []).map((item) => ({
|
|
42887
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42888
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42889
|
+
})),
|
|
42890
|
+
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42891
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42892
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42893
|
+
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42894
|
+
}))
|
|
42895
|
+
}
|
|
42896
|
+
});
|
|
42897
|
+
if (lifecycleReject) {
|
|
42898
|
+
WritebackSettlement.attachUndoNotVerifiedFailure(run, result, {
|
|
42899
|
+
buildFailure: buildContentFailure,
|
|
42900
|
+
postFiles: trackedUndoPostFilesAtDispatch
|
|
42901
|
+
});
|
|
42902
|
+
await applyTrackedChangeSettlement(runId, "reject", result);
|
|
42903
|
+
return;
|
|
42904
|
+
}
|
|
42905
|
+
applyLegacyUndoSettlement(runId, result.skipped?.length ? "partial" : "applied", result);
|
|
42209
42906
|
} finally {
|
|
42210
42907
|
if (lifecycleReject) {
|
|
42211
42908
|
trackedChangeInFlight.delete(runId);
|
|
42909
|
+
refreshRunCardControls(runId);
|
|
42212
42910
|
}
|
|
42213
42911
|
}
|
|
42214
|
-
appendRunRecordEvent(runId, {
|
|
42215
|
-
title: trackedUndo ? tr("undoTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }) : tr("undoNativeResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42216
|
-
status: result.skipped?.length ? "failed" : "completed",
|
|
42217
|
-
detail: {
|
|
42218
|
-
[trackedUndo ? tr("detailRejected") : tr("detailUndone")]: (result.applied || []).map((item) => ({
|
|
42219
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42220
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42221
|
-
})),
|
|
42222
|
-
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42223
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42224
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42225
|
-
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42226
|
-
}))
|
|
42227
|
-
}
|
|
42228
|
-
});
|
|
42229
|
-
if (lifecycleReject) {
|
|
42230
|
-
WritebackSettlement.attachUndoNotVerifiedFailure(run, result, {
|
|
42231
|
-
buildFailure: buildContentFailure
|
|
42232
|
-
});
|
|
42233
|
-
applyTrackedChangeSettlement(runId, "reject", result);
|
|
42234
|
-
return;
|
|
42235
|
-
}
|
|
42236
|
-
applyLegacyUndoSettlement(runId, result.skipped?.length ? "partial" : "applied", result);
|
|
42237
42912
|
}
|
|
42238
42913
|
async function acceptRun(runId) {
|
|
42239
42914
|
const run = findRunRecord(runId);
|
|
@@ -42257,50 +42932,50 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42257
42932
|
status: "running",
|
|
42258
42933
|
detail: { [tr("detailAccepted")]: formatTrackedChangeFiles(run.undoTrackedChanges) }
|
|
42259
42934
|
});
|
|
42260
|
-
let result;
|
|
42261
42935
|
try {
|
|
42262
|
-
result = await callPageBridge("acceptTrackedChanges", {
|
|
42936
|
+
const result = await callPageBridge("acceptTrackedChanges", {
|
|
42263
42937
|
trackedChanges: run.undoTrackedChanges || [],
|
|
42264
42938
|
expectedFiles: run.undoExpectedFiles || [],
|
|
42265
42939
|
postFiles: buildTrackedUndoPostFiles(run),
|
|
42266
42940
|
appliedOperations: Array.isArray(run.appliedOperations) ? run.appliedOperations : [],
|
|
42267
42941
|
runProjectId: getRunProjectIdForWriteback(run)
|
|
42268
42942
|
});
|
|
42269
|
-
|
|
42270
|
-
trackedChangeInFlight.delete(runId);
|
|
42271
|
-
}
|
|
42272
|
-
appendAcceptDiagnosticEvents(runId, Array.isArray(result.diagnostics) ? result.diagnostics : []);
|
|
42273
|
-
appendRunRecordEvent(runId, {
|
|
42274
|
-
title: tr("runAcceptTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42275
|
-
status: result.skipped?.length ? "failed" : "completed",
|
|
42276
|
-
detail: {
|
|
42277
|
-
[tr("detailAccepted")]: (result.applied || []).map((item) => ({
|
|
42278
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42279
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42280
|
-
})),
|
|
42281
|
-
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42282
|
-
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42283
|
-
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42284
|
-
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42285
|
-
}))
|
|
42286
|
-
}
|
|
42287
|
-
});
|
|
42288
|
-
if (result.ok === false) {
|
|
42943
|
+
appendAcceptDiagnosticEvents(runId, Array.isArray(result.diagnostics) ? result.diagnostics : []);
|
|
42289
42944
|
appendRunRecordEvent(runId, {
|
|
42290
|
-
title: tr("
|
|
42291
|
-
status: "failed",
|
|
42945
|
+
title: tr("runAcceptTrackedResult", { applied: result.applied?.length || 0, skipped: result.skipped?.length || 0 }),
|
|
42946
|
+
status: result.skipped?.length ? "failed" : "completed",
|
|
42292
42947
|
detail: {
|
|
42293
|
-
[tr("
|
|
42948
|
+
[tr("detailAccepted")]: (result.applied || []).map((item) => ({
|
|
42949
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42950
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key
|
|
42951
|
+
})),
|
|
42952
|
+
[tr("detailSkipped")]: (result.skipped || []).map((item) => ({
|
|
42953
|
+
[tr("detailFile")]: item.trackedChange?.path || tr("unknownFile"),
|
|
42954
|
+
[tr("detailRecord")]: item.trackedChange?.label || item.trackedChange?.id || item.trackedChange?.key || "",
|
|
42955
|
+
[tr("detailReason")]: formatBridgeResultReason(item.result, item.trackedChange?.path)
|
|
42956
|
+
}))
|
|
42294
42957
|
}
|
|
42295
42958
|
});
|
|
42296
|
-
if (
|
|
42297
|
-
|
|
42959
|
+
if (result.ok === false) {
|
|
42960
|
+
appendRunRecordEvent(runId, {
|
|
42961
|
+
title: tr("runAcceptTrackedFailed"),
|
|
42962
|
+
status: "failed",
|
|
42963
|
+
detail: {
|
|
42964
|
+
[tr("detailReason")]: tr("runAcceptTrackedFailedReason")
|
|
42965
|
+
}
|
|
42966
|
+
});
|
|
42967
|
+
if (!WritebackSettlement.isSuccessfulTrackedChangeSettlement(result)) {
|
|
42968
|
+
refreshRunCardControls(runId);
|
|
42969
|
+
}
|
|
42298
42970
|
}
|
|
42971
|
+
WritebackSettlement.attachAcceptNotVerifiedFailure(run, result, {
|
|
42972
|
+
buildFailure: buildContentFailure
|
|
42973
|
+
});
|
|
42974
|
+
await applyTrackedChangeSettlement(runId, "accept", result);
|
|
42975
|
+
} finally {
|
|
42976
|
+
trackedChangeInFlight.delete(runId);
|
|
42977
|
+
refreshRunCardControls(runId);
|
|
42299
42978
|
}
|
|
42300
|
-
WritebackSettlement.attachAcceptNotVerifiedFailure(run, result, {
|
|
42301
|
-
buildFailure: buildContentFailure
|
|
42302
|
-
});
|
|
42303
|
-
applyTrackedChangeSettlement(runId, "accept", result);
|
|
42304
42979
|
}
|
|
42305
42980
|
function getRunProjectIdForWriteback(run) {
|
|
42306
42981
|
return typeof run?.runProjectId === "string" && run.runProjectId ? run.runProjectId : "";
|
|
@@ -42331,7 +43006,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42331
43006
|
FailureReasons
|
|
42332
43007
|
);
|
|
42333
43008
|
}
|
|
42334
|
-
function applyTrackedChangeSettlement(runId, kind, result) {
|
|
43009
|
+
async function applyTrackedChangeSettlement(runId, kind, result) {
|
|
42335
43010
|
const run = findRunRecord(runId);
|
|
42336
43011
|
const settlement = WritebackSettlement.settleTrackedChangeLifecycle({
|
|
42337
43012
|
kind,
|
|
@@ -42340,12 +43015,14 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42340
43015
|
failureReasons: FailureReasons
|
|
42341
43016
|
});
|
|
42342
43017
|
if (settlement.decision === "blocked") {
|
|
42343
|
-
refreshRunCardControls(runId);
|
|
42344
43018
|
return;
|
|
42345
43019
|
}
|
|
42346
|
-
|
|
42347
|
-
|
|
42348
|
-
|
|
43020
|
+
await Modules.ScopedPersistenceCoordinator.applyReviewTransition({
|
|
43021
|
+
getState: () => state,
|
|
43022
|
+
runId,
|
|
43023
|
+
transition: WritebackSettlement.applySettlementTransition(run, settlement),
|
|
43024
|
+
persist: flushQueuedSaveState
|
|
43025
|
+
});
|
|
42349
43026
|
}
|
|
42350
43027
|
function getRunUndoCount(run) {
|
|
42351
43028
|
if (!run) {
|
|
@@ -42408,6 +43085,28 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42408
43085
|
function attachVerifiedContentToOperation(operation, result) {
|
|
42409
43086
|
return WritebackSettlement.attachVerifiedContentToOperation(operation, result);
|
|
42410
43087
|
}
|
|
43088
|
+
let trackedChangeCaptureController = null;
|
|
43089
|
+
function getTrackedChangeCaptureController() {
|
|
43090
|
+
return trackedChangeCaptureController || (trackedChangeCaptureController = Modules.TrackedChangeCaptureController.create({
|
|
43091
|
+
getRuns: () => (state.sessions || []).flatMap((session) => session.runs || []),
|
|
43092
|
+
getProjectId: () => window.location.pathname.match(/^\/project\/([^/]+)/)?.[1] || "",
|
|
43093
|
+
buildExpectedFilesAfterOperations,
|
|
43094
|
+
normalizeTrackedChanges: normalizeApplyTrackedChanges,
|
|
43095
|
+
callPageBridge,
|
|
43096
|
+
persist: () => flushQueuedSaveState({ preserveRunActionPayload: true }),
|
|
43097
|
+
refresh: (run) => refreshRunCardControls(run.id),
|
|
43098
|
+
notify: (run, kind, detail) => appendRunRecordEvent(run.id, {
|
|
43099
|
+
title: {
|
|
43100
|
+
pending: tx("Files written; confirming tracked changes.", "\u6587\u4EF6\u5DF2\u5199\u5165\uFF0C\u6B63\u5728\u786E\u8BA4\u7559\u75D5\u8BB0\u5F55\u3002"),
|
|
43101
|
+
observed: tx("Tracked changes confirmed; Accept is available.", "\u7559\u75D5\u8BB0\u5F55\u5DF2\u786E\u8BA4\uFF0C\u53EF\u4EE5\u63A5\u53D7\u6539\u52A8\u3002"),
|
|
43102
|
+
needs_review: tx("Tracked changes could not be safely attributed. Review them in Overleaf; Undo is preserved.", "\u7559\u75D5\u5F52\u5C5E\u5C1A\u672A\u786E\u8BA4\uFF0C\u8BF7\u5728 Overleaf \u5BA1\u9605\uFF1B\u539F\u6709\u64A4\u9500\u80FD\u529B\u5DF2\u4FDD\u7559\u3002")
|
|
43103
|
+
}[kind],
|
|
43104
|
+
status: "info",
|
|
43105
|
+
detail
|
|
43106
|
+
}),
|
|
43107
|
+
onError: (error) => appendPlainLog(tx("Tracked-change confirmation unavailable: ", "\u7559\u75D5\u786E\u8BA4\u6682\u4E0D\u53EF\u7528\uFF1A") + error.message)
|
|
43108
|
+
}));
|
|
43109
|
+
}
|
|
42411
43110
|
function recordUndoFromApply(project, applyResult) {
|
|
42412
43111
|
const appliedEntries = getAppliedEntries(applyResult);
|
|
42413
43112
|
if (!currentRunView?.recordId || !appliedEntries.length) {
|
|
@@ -42444,6 +43143,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42444
43143
|
if (combinedTrackedChanges.length) {
|
|
42445
43144
|
record.trackedChangeStatus = "pending";
|
|
42446
43145
|
}
|
|
43146
|
+
getTrackedChangeCaptureController().record(record, applyResult?.trackedChangeCaptures);
|
|
42447
43147
|
refreshRunCardControls(record.id);
|
|
42448
43148
|
if (combinedTrackedChanges.length) {
|
|
42449
43149
|
appendRunEvent({
|
|
@@ -42505,28 +43205,10 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
|
|
|
42505
43205
|
return WritebackSettlement.normalizeApplyTrackedChanges(changes);
|
|
42506
43206
|
}
|
|
42507
43207
|
function selectExpectedFilesForTrackedUndo(project, operations = [], trackedChanges = [], previousExpectedFiles = []) {
|
|
42508
|
-
return WritebackSettlement.selectExpectedFilesForTrackedUndo(
|
|
42509
|
-
project,
|
|
42510
|
-
operations,
|
|
42511
|
-
trackedChanges,
|
|
42512
|
-
previousExpectedFiles
|
|
42513
|
-
);
|
|
43208
|
+
return WritebackSettlement.selectExpectedFilesForTrackedUndo(project, operations, trackedChanges, previousExpectedFiles);
|
|
42514
43209
|
}
|
|
42515
43210
|
function buildTrackedUndoPostFiles(run) {
|
|
42516
|
-
|
|
42517
|
-
const appliedOperations = Array.isArray(run?.appliedOperations) ? run.appliedOperations : [];
|
|
42518
|
-
if (!expectedFiles.length || !appliedOperations.length) {
|
|
42519
|
-
return [];
|
|
42520
|
-
}
|
|
42521
|
-
const postFilesByPath = buildExpectedFilesAfterOperations(
|
|
42522
|
-
{ files: expectedFiles },
|
|
42523
|
-
appliedOperations
|
|
42524
|
-
);
|
|
42525
|
-
const expectedPaths = new Set(expectedFiles.map((file) => file?.path).filter(Boolean));
|
|
42526
|
-
return Array.from(postFilesByPath.entries()).filter(([path, content]) => expectedPaths.has(path) && typeof content === "string").map(([path, content]) => ({
|
|
42527
|
-
path,
|
|
42528
|
-
content
|
|
42529
|
-
}));
|
|
43211
|
+
return getTrackedChangeCaptureController().buildPostFiles(run);
|
|
42530
43212
|
}
|
|
42531
43213
|
function hasTrackedEditorUndo(run) {
|
|
42532
43214
|
return buildTrackedUndoPostFiles(run).length > 0;
|
|
@@ -43103,7 +43785,7 @@ Reason: ${item.reason || "No reason provided"}`),
|
|
|
43103
43785
|
root.CodexOverleafContentRuntime = { init };
|
|
43104
43786
|
})(typeof window !== "undefined" ? window : globalThis);
|
|
43105
43787
|
}).call(globalThis, void 0, void 0, void 0);
|
|
43106
|
-
(function
|
|
43788
|
+
(function runClassicContentModule101(module, exports, require2) {
|
|
43107
43789
|
(function initCodexOverleafLegacyGlobalRegistry(root, factory) {
|
|
43108
43790
|
"use strict";
|
|
43109
43791
|
const api = factory();
|
|
@@ -43179,6 +43861,7 @@ Reason: ${item.reason || "No reason provided"}`),
|
|
|
43179
43861
|
"StorageMigration",
|
|
43180
43862
|
"Summary",
|
|
43181
43863
|
"Theme",
|
|
43864
|
+
"TrackedChangeCaptureController",
|
|
43182
43865
|
"UndoOperations",
|
|
43183
43866
|
"UpdateIdle",
|
|
43184
43867
|
"UpdateNotice",
|