codex-overleaf-link 2.4.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/README.md +272 -314
  2. package/README.zh-CN.md +287 -329
  3. package/extension/bootstrap/background.js +47 -10
  4. package/extension/bootstrap/manifest.template.json +9 -4
  5. package/extension/bootstrap/popup.html +10 -16
  6. package/extension/bootstrap/update.js +25 -2
  7. package/extension/runtime-manifest.json +3 -1
  8. package/extension/src/background.js +28 -3
  9. package/extension/src/backgroundSharedSessions.js +380 -0
  10. package/extension/src/backgroundUpdateCoordinator.js +442 -379
  11. package/extension/src/content/activeTurnControl.js +8 -0
  12. package/extension/src/content/assetTransferBroker.js +186 -12
  13. package/extension/src/content/changeHistoryView.js +175 -0
  14. package/extension/src/content/composerAttachments.js +24 -22
  15. package/extension/src/content/composerPanel.js +23 -8
  16. package/extension/src/content/contentRuntime.js +507 -507
  17. package/extension/src/content/diagnosticsController.js +1 -2
  18. package/extension/src/content/diagnosticsExport.js +222 -0
  19. package/extension/src/content/diagnosticsPanel.js +48 -19
  20. package/extension/src/content/diffReviewPanel.js +8 -5
  21. package/extension/src/content/generated/content.bundle.js +8330 -1349
  22. package/extension/src/content/generated/content.bundle.meta.json +22 -3
  23. package/extension/src/content/legacyGlobalRegistry.js +19 -1
  24. package/extension/src/content/localSkillsPanel.js +42 -7
  25. package/extension/src/content/markdownDomRenderer.js +9 -4
  26. package/extension/src/content/modelPicker.js +1 -1
  27. package/extension/src/content/pageBridgeClient.js +18 -3
  28. package/extension/src/content/panelMaintenance.js +48 -121
  29. package/extension/src/content/panelRenderer.js +4 -0
  30. package/extension/src/content/pendingInputView.js +109 -76
  31. package/extension/src/content/providerSettingsCoordinator.js +17 -6
  32. package/extension/src/content/providerSettingsDialog.js +661 -108
  33. package/extension/src/content/recentProjects.js +10 -1
  34. package/extension/src/content/runActivitySummary.js +631 -0
  35. package/extension/src/content/runController.js +3 -1
  36. package/extension/src/content/runFailureNotice.js +14 -1
  37. package/extension/src/content/runGuidanceController.js +4 -3
  38. package/extension/src/content/runPresence.js +306 -0
  39. package/extension/src/content/runQueueScheduler.js +2 -1
  40. package/extension/src/content/runResultActions.js +123 -3
  41. package/extension/src/content/runTimelineView.js +186 -154
  42. package/extension/src/content/selectionContextView.js +300 -0
  43. package/extension/src/content/sessionPersistence.js +6 -1
  44. package/extension/src/content/settingsPanel.js +77 -52
  45. package/extension/src/content/settingsWorkbench.js +374 -0
  46. package/extension/src/content/sharedSessionViewSync.js +72 -0
  47. package/extension/src/content/subagentActivityView.js +195 -0
  48. package/extension/src/content/trackedChangeCaptureController.js +7 -3
  49. package/extension/src/content/updateNotice.js +121 -50
  50. package/extension/src/content/writebackController.js +257 -0
  51. package/extension/src/content/writebackOrchestrator.js +146 -141
  52. package/extension/src/content/writebackPlan.js +231 -0
  53. package/extension/src/content/writebackRecovery.js +122 -0
  54. package/extension/src/content/writingStyleSettings.js +576 -0
  55. package/extension/src/content/writtenChangesView.js +152 -0
  56. package/extension/src/page/binaryAssetUploader.js +97 -19
  57. package/extension/src/page/overleafProjectSnapshot.js +1 -0
  58. package/extension/src/page/referenceProjects.js +148 -0
  59. package/extension/src/page/saveState.js +14 -2
  60. package/extension/src/page/snapshotRouter.js +44 -13
  61. package/extension/src/page/textCoordinates.js +102 -0
  62. package/extension/src/page/textFileCreator.js +350 -59
  63. package/extension/src/page/trackedChangeCapture.js +42 -56
  64. package/extension/src/page/trackedChangeOwnership.js +198 -0
  65. package/extension/src/page/trackedChangeReplay.js +164 -0
  66. package/extension/src/page/trackedChangesLifecycle.js +135 -149
  67. package/extension/src/page/treeOperations.js +26 -2
  68. package/extension/src/page/writebackReceiptJournal.js +112 -0
  69. package/extension/src/page/writebackRouter.js +175 -135
  70. package/extension/src/pageBridge.js +56 -101
  71. package/extension/src/popup.js +203 -59
  72. package/extension/src/shared/agentTranscript.js +18 -4
  73. package/extension/src/shared/auditRecords.js +71 -0
  74. package/extension/src/shared/changeHistoryModel.js +94 -0
  75. package/extension/src/shared/compatibility.js +1 -1
  76. package/extension/src/shared/compileAdapter.js +42 -0
  77. package/extension/src/shared/failureReasons.js +20 -0
  78. package/extension/src/shared/globalPreferences.js +1 -1
  79. package/extension/src/shared/i18n.js +93 -25
  80. package/extension/src/shared/managedUpdateProjection.js +6 -3
  81. package/extension/src/shared/pageRpcContract.js +7 -1
  82. package/extension/src/shared/providerProfiles.js +109 -0
  83. package/extension/src/shared/runActivityModel.js +361 -0
  84. package/extension/src/shared/runExecutionSnapshot.js +8 -2
  85. package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
  86. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
  87. package/extension/src/shared/selectionContext.js +28 -0
  88. package/extension/src/shared/sessionState.js +97 -6
  89. package/extension/src/shared/sharedSessionBridge.js +288 -0
  90. package/extension/src/shared/storageDb.js +22 -55
  91. package/extension/src/shared/storageMigration.js +3 -0
  92. package/extension/src/shared/storageRunActions.js +10 -4
  93. package/extension/src/shared/storageValuePruning.js +40 -0
  94. package/extension/src/shared/subagentActivityModel.js +174 -0
  95. package/extension/src/shared/undoOperations.js +87 -0
  96. package/extension/src/shared/updateConsent.js +37 -8
  97. package/extension/src/shared/writebackIntent.js +62 -0
  98. package/extension/src/shared/writebackSettlement.js +29 -10
  99. package/extension/src/shared/writingStyle.js +33 -0
  100. package/extension/styles/panel.css +1972 -384
  101. package/extension/styles/popup.css +110 -0
  102. package/native-host/src/anthropicBridgeRequest.js +2 -1
  103. package/native-host/src/codexModelRecovery.js +107 -0
  104. package/native-host/src/codexPromptAssembly.js +2 -0
  105. package/native-host/src/codexProviderLaunch.js +3 -3
  106. package/native-host/src/codexRuntimeIdentity.js +1 -0
  107. package/native-host/src/codexSessionRunner.js +106 -140
  108. package/native-host/src/codexSessionTiming.js +3 -0
  109. package/native-host/src/managedInstall.js +5 -4
  110. package/native-host/src/nativeEnvironment.js +70 -0
  111. package/native-host/src/nativeQuotas.js +15 -8
  112. package/native-host/src/overleafWorkspaceRules.js +16 -0
  113. package/native-host/src/processStopBarrier.js +80 -0
  114. package/native-host/src/providerModelCatalog.js +4 -3
  115. package/native-host/src/providerProfile.js +13 -1
  116. package/native-host/src/providerReasoning.js +9 -5
  117. package/native-host/src/providerStore.js +4 -0
  118. package/native-host/src/releaseTransport.js +14 -5
  119. package/native-host/src/selectionScope.js +58 -0
  120. package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
  121. package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
  122. package/native-host/src/subagentBroker.js +102 -98
  123. package/native-host/src/subagentTelemetry.js +316 -0
  124. package/native-host/src/subagentWorkspace.js +103 -0
  125. package/native-host/src/subagentWorkspacePath.js +31 -0
  126. package/native-host/src/taskRunnerRuntime.js +55 -5
  127. package/native-host/src/turnAttachments.js +113 -0
  128. package/native-host/src/updateManager.js +122 -12
  129. package/native-host/src/updateNetworkControl.js +75 -0
  130. package/native-host/src/updateTrust.js +21 -2
  131. package/native-host/src/vendor/pdfjs/LICENSE +177 -0
  132. package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
  133. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  134. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  135. package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  136. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  137. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  138. package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  139. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  140. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  141. package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  142. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  143. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  144. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  145. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  146. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  147. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  148. package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  149. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  150. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  151. package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  152. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  153. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  154. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  155. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  156. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  157. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  158. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  159. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  160. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  161. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  162. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  163. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  164. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  165. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  166. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  167. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  168. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  169. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  170. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  171. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  172. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  173. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  174. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  175. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  176. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  177. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  178. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  179. package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  180. package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  181. package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  182. package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  183. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  184. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  185. package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  186. package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  187. package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  188. package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  189. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  190. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  191. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  192. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  193. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  194. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  195. package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  196. package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  197. package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  198. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  199. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  200. package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  201. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  202. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  203. package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  204. package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  205. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  206. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  207. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  208. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  209. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  210. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  211. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  212. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  213. package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  214. package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  215. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  216. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  217. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  218. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  219. package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
  220. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  221. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  222. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  223. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  224. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  225. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  226. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  227. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  228. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  229. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  230. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  231. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  232. package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  233. package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  234. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  235. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  236. package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  237. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  238. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  239. package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  240. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  241. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  242. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  243. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  244. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  245. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  246. package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  247. package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
  248. package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  249. package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  250. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  251. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  252. package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  253. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  254. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  255. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  256. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  257. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  258. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  259. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  260. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  261. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  262. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  263. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  264. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  265. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  266. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  267. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  268. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  269. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  270. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  271. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  272. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  273. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  274. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  275. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  276. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  277. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  278. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  279. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  280. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  281. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  282. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  283. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  284. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  285. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  286. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  287. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  288. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  289. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  290. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  291. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  292. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  293. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  294. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  295. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  296. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  297. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  298. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  299. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  300. package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
  301. package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  302. package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
  303. package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
  304. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  305. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  306. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  307. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  308. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  309. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  310. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  311. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  312. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  313. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  314. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  315. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  316. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  317. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  318. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  319. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  320. package/native-host/src/writingStyleEvidence.js +102 -0
  321. package/native-host/src/writingStylePdfWorker.js +35 -0
  322. package/native-host/src/writingStyleProfile.js +165 -0
  323. package/native-host/src/writingStyleRuntime.js +447 -0
  324. package/package.json +1 -1
@@ -1,17 +1,14 @@
1
1
  (function initCodexOverleafRunTimelineView() {
2
2
  'use strict';
3
3
 
4
- // Run-timeline view — the timeline render pipeline carved out of
5
- // contentRuntime.js (v1.4.6 structural-debt phase 2): the scroll engine +
6
- // jump-to-latest button, the live-elapsed tick and collapsed-header summary,
7
- // run-card / stream-event / activity rendering, the completion report, and
8
- // the run-card Undo/Accept controls. Code moved verbatim (original
9
- // indentation kept); runtime collaborators are factory-injected and mutable
10
- // runtime state (panel, panel state, the live run view) is read through lazy
11
- // getters. The view-local scroll/timer state below moved here with the code
12
- // that owns it.
4
+ // Owns scroll, cards, reports and mature run actions. The optional activity
5
+ // presenter projects stored events without taking ownership of settlement.
13
6
  function create(deps = {}) {
14
7
  const {
8
+ RunActivitySummary,
9
+ RunPresence,
10
+ RunActivityModel,
11
+ SubagentActivityView,
15
12
  RunGuidanceView,
16
13
  RunResultActions,
17
14
  RunScrollLayout,
@@ -25,6 +22,7 @@
25
22
  formatEventDetail,
26
23
  formatEventTime,
27
24
  renderAttachmentPreviewList,
25
+ renderSentSelection,
28
26
  formatModeLabel,
29
27
  undoRun,
30
28
  acceptRun,
@@ -41,11 +39,15 @@
41
39
  getState,
42
40
  getCurrentRunView,
43
41
  refillComposerForRetry,
42
+ canEditRun,
43
+ retryWriteback,
44
44
  showNativeSetupGuidance,
45
45
  openProjectFileForFailure,
46
46
  openStorageSettings,
47
47
  trackedChangeInFlight,
48
- projectRunSettlement
48
+ projectRunSettlement,
49
+ getCurrentProjectId,
50
+ getProjectName
49
51
  } = deps;
50
52
 
51
53
  let logAutoFollow = true;
@@ -59,9 +61,7 @@
59
61
  let scrollLogPendingForce = false;
60
62
  let jumpToLatestButton = null;
61
63
  let unreadSinceDetach = 0;
62
- // Live-elapsed tick for the sticky run-process header. Without it the header
63
- // reads a static "Processing…" and the user can't tell a working run from a
64
- // hung one — the single highest-value streaming signal per competitor UX.
64
+ // Elapsed time belongs to the run; tool rows retain their own lifecycle.
65
65
  let runElapsedTimer = null;
66
66
  const scrollLayout = RunScrollLayout?.create({
67
67
  getScroller: getLogScrollContainer,
@@ -69,6 +69,13 @@
69
69
  onLayoutChange: scroller => logAutoFollow ? scrollLogToBottom() : updateJumpToLatestButton(scroller)
70
70
  });
71
71
  const failureNotice = RunFailureNotice?.create({ tr, projectRunSettlement, sanitizeText: sanitizeAssistantVisibleText });
72
+ const presence = RunPresence?.create({ tx, getLocale, formatElapsed });
73
+ const displayRun = run => RunFailureNotice?.projectResolvedUndo?.(run) || run;
74
+ const activitySummary = RunActivitySummary?.create({ RunActivityModel, SubagentActivityView, tx, findRunRecord: (...args) => displayRun(findRunRecord(...args)), getPanel, cssEscape,
75
+ formatEventTime, formatElapsed, renderMarkdownBlockText, renderRunEvent, formatEventDetail,
76
+ presence, classifyStatus: classifyRunPresence, getProjectId: () => getCurrentProjectId?.() || '',
77
+ summarizeCommand: RunPresence?.commandSummary,
78
+ isGuidance: event => Boolean(RunGuidanceView.getGuidanceText(event)), sanitizeAssistantVisibleText });
72
79
 
73
80
  // Re-arm auto-follow (called by the runtime when a new run starts, so the
74
81
  // log snaps back to following the live stream).
@@ -187,6 +194,7 @@
187
194
  }
188
195
 
189
196
  function scrollLogToBottom(options = {}) {
197
+ if (activitySummary?.isSubagentViewOpen?.()) return;
190
198
  const scroller = getLogScrollContainer();
191
199
  if (!scroller) {
192
200
  return;
@@ -237,6 +245,7 @@
237
245
  scroller.scrollTop = scroller.scrollHeight;
238
246
  }
239
247
  function collapseRunProcess(view, statusText) {
248
+ if (activitySummary) { activitySummary.settle(view, statusText); return; }
240
249
  const runProcess = view?.runProcess || view?.root?.querySelector('[data-run-process]');
241
250
  if (runProcess) {
242
251
  runProcess.open = false;
@@ -245,23 +254,15 @@
245
254
  if (statusEl) {
246
255
  // Append the step count to the collapsed header ("Processed 18s · 6 steps")
247
256
  // so the user sees how much work the run did without expanding it.
248
- const stepCount = countRunActivitySteps(view);
257
+ const record = view?.recordId ? findRunRecord(view.recordId, view.sessionId) : null;
258
+ const stepCount = (record?.events || []).filter(event => (event.kind || 'activity') === 'activity').length;
249
259
  statusEl.textContent = stepCount > 0
250
260
  ? `${statusText} · ${tx(`${stepCount} steps`, `${stepCount} 步`)}`
251
261
  : statusText;
252
262
  }
253
263
  }
254
264
 
255
- function countRunActivitySteps(view) {
256
- const record = view?.recordId ? findRunRecord(view.recordId, view.sessionId) : null;
257
- if (!Array.isArray(record?.events)) {
258
- return 0;
259
- }
260
- return record.events.filter(event => (event.kind || 'activity') === 'activity').length;
261
- }
262
-
263
- // The sticky run-process header shows a live "Processing… {elapsed}" while a
264
- // run is in flight so the user can distinguish a working run from a hung one.
265
+ // Keep elapsed labels live without creating new activity records.
265
266
  function startRunElapsedTick() {
266
267
  stopRunElapsedTick();
267
268
  if (typeof window.setInterval !== 'function') {
@@ -272,6 +273,7 @@
272
273
  stopRunElapsedTick();
273
274
  return;
274
275
  }
276
+ if (activitySummary?.update(getCurrentRunView()) && presence) return;
275
277
  const statusEl = getCurrentRunView().status
276
278
  || getCurrentRunView().root?.querySelector('[data-run-status]');
277
279
  if (statusEl) {
@@ -289,6 +291,13 @@
289
291
  runElapsedTimer = null;
290
292
  }
291
293
 
294
+ function classifyRunPresence(run = {}) {
295
+ if (run.retryingWriteback) return 'plain';
296
+ if (run.status === 'completed') return 'done';
297
+ if (run.status === 'cancelled' || run.status === 'rejected') return 'stopped';
298
+ return run.status === 'failed' || run.status === 'abandoned_after_navigation' ? 'failed' : 'plain';
299
+ }
300
+
292
301
  function formatProcessedSummary(status, elapsedMs) {
293
302
  const elapsed = formatElapsed(elapsedMs);
294
303
  if (status === 'failed') {
@@ -303,6 +312,7 @@
303
312
  return tr('processed', { elapsed });
304
313
  }
305
314
  function renderRunHistory(options = {}) {
315
+ activitySummary?.closeSubagentView?.();
306
316
  const log = getPanel()?.querySelector('[data-log]');
307
317
  if (!log) {
308
318
  return;
@@ -323,7 +333,12 @@
323
333
  const hint = document.createElement('div');
324
334
  hint.className = 'empty-runs-hint';
325
335
  hint.textContent = tr('emptyRunsHint');
336
+ label.className = 'empty-runs-title';
326
337
  empty.append(icon, label, hint);
338
+ if (presence) {
339
+ icon.remove();
340
+ presence.decorateEmpty(empty, { projectName: getProjectName?.() || '' });
341
+ }
327
342
  log.append(empty);
328
343
  return;
329
344
  }
@@ -342,6 +357,7 @@
342
357
  }
343
358
 
344
359
  function renderRunCard(run) {
360
+ run = displayRun(run);
345
361
  const root = document.createElement('section');
346
362
  root.className = 'transcript-turn run-card';
347
363
  root.dataset.status = run.status || 'completed';
@@ -356,11 +372,14 @@
356
372
  root.innerHTML = `
357
373
  <div class="transcript-turn-main">
358
374
  <div class="run-attachments codex-attachment-preview-list" data-run-attachments hidden></div>
375
+ <div class="run-selection" data-run-selection hidden></div>
359
376
  <div class="run-prompt" data-run-task></div>
360
377
  <div class="run-guidance-list" data-run-guidance></div>
361
378
  <div class="run-turn-meta">
362
379
  <button type="button" data-run-accept hidden title="Accept this run's tracked changes in Overleaf">Accept changes</button>
363
380
  <button type="button" data-run-undo hidden title="Undo this run's writes to Overleaf">Undo</button>
381
+ <button type="button" class="run-copy-action run-edit-action" data-run-edit hidden></button>
382
+ <button type="button" class="run-copy-action run-sync-action" data-run-sync-retry hidden></button>
364
383
  </div>
365
384
  <details class="run-process" data-run-process>
366
385
  <summary data-run-process-summary>
@@ -379,6 +398,7 @@
379
398
  `;
380
399
 
381
400
  renderAttachmentPreviewList(run.attachments, root.querySelector('[data-run-attachments]'), { readonly: true });
401
+ renderSentSelection?.(root.querySelector('[data-run-selection]'), run.executionSnapshot?.selectionContext, { document, tx });
382
402
  const runTask = root.querySelector('[data-run-task]');
383
403
  runTask.classList.add('run-user-message');
384
404
  runTask.textContent = run.task || '';
@@ -398,7 +418,7 @@
398
418
  truncated.textContent = tr('eventsTruncatedNote');
399
419
  events.append(truncated);
400
420
  }
401
- const guidanceTarget = run.status === 'running' ? events : guidance;
421
+ const guidanceTarget = guidance;
402
422
  const renderedGuidanceIds = new Set();
403
423
  const completedLegacyGuidance = new Set((run.events || [])
404
424
  .filter(event => event.kind === 'guidance' && !event.guidanceId && event.status === 'completed')
@@ -407,7 +427,7 @@
407
427
  if (event.kind === 'report') {
408
428
  report.hidden = false;
409
429
  report.replaceChildren(renderCompletionReport(event, run));
410
- } else if (event.kind === 'technical') {
430
+ } else if (activitySummary || event.kind === 'technical') {
411
431
  continue;
412
432
  } else if (RunGuidanceView.getGuidanceText(event)) {
413
433
  if (event.guidanceId && renderedGuidanceIds.has(event.guidanceId)) {
@@ -423,17 +443,21 @@
423
443
  } else if (event.kind === 'stream') {
424
444
  upsertStreamEvent({ events }, event);
425
445
  } else {
426
- events.append(renderRunEvent(event));
446
+ appendActivityDetail({ events }, renderRunEvent(event), event);
427
447
  }
428
448
  }
429
449
 
430
450
  RunResultActions.configureResultActions(root, run);
431
451
  configureAcceptButton(root, run);
432
452
  configureUndoButton(root, run);
453
+ configureEditButton(root, run);
454
+ configureWritebackButton(root, run);
455
+ activitySummary?.mount(root, run);
433
456
  return root;
434
457
  }
435
458
 
436
459
  function getRunStatusText(run = {}) {
460
+ if (run.retryingWriteback) return tx('Checking file sync', '正在检查文件同步');
437
461
  if (run.statusText) {
438
462
  return run.statusText;
439
463
  }
@@ -461,6 +485,7 @@
461
485
  if (!view?.events) {
462
486
  return;
463
487
  }
488
+ if (activitySummary?.update(view, event)) return;
464
489
  const streamKey = event.streamKey || event.streamRole || 'codex-stream';
465
490
  const selector = `[data-stream-key="${cssEscape(streamKey)}"]`;
466
491
  const existing = view.events.querySelector(selector);
@@ -477,7 +502,12 @@
477
502
  }
478
503
  return;
479
504
  }
480
- view.events.append(renderStreamEvent({ ...event, streamKey }));
505
+ appendActivityDetail(view, renderStreamEvent({ ...event, streamKey }), event);
506
+ }
507
+
508
+ function appendActivityDetail(view, row, event) {
509
+ if (activitySummary) activitySummary.appendDetail(view, row, event);
510
+ else view.events.append(row);
481
511
  }
482
512
 
483
513
  function renderStreamEvent(input) {
@@ -543,54 +573,8 @@
543
573
  return row;
544
574
  }
545
575
 
546
- function hasNonEmptyDetail(value) {
547
- if (value === undefined || value === null || value === '') {
548
- return false;
549
- }
550
- if (Array.isArray(value)) {
551
- return value.length > 0;
552
- }
553
- if (typeof value === 'object') {
554
- return Object.keys(value).length > 0;
555
- }
556
- return true;
557
- }
558
-
559
- function renderTechnicalEvent(event) {
560
- const block = document.createElement('section');
561
- block.className = 'run-technical-event';
562
- block.dataset.status = event.status || 'info';
563
576
 
564
- const title = document.createElement('div');
565
- title.className = 'run-technical-event-title';
566
- title.textContent = event.title || tr('technicalDetails');
567
577
 
568
- const body = document.createElement('pre');
569
- body.textContent = formatEventDetail(buildTechnicalEventDetail(event));
570
- block.append(title, body);
571
- return block;
572
- }
573
-
574
- function buildTechnicalEventDetail(event) {
575
- if (event?.kind === 'technical') {
576
- return event.detail || {};
577
- }
578
-
579
- const detail = {
580
- [tx('Step', '步骤')]: event?.title || '',
581
- [tx('Status', '状态')]: event?.status || ''
582
- };
583
- if (event?.timestamp) {
584
- detail[tx('Time', '时间')] = formatEventTime(event.timestamp);
585
- }
586
- if (hasNonEmptyDetail(event?.detail)) {
587
- detail[tx('Content', '内容')] = event.detail;
588
- }
589
- if (hasNonEmptyDetail(event?.technicalDetail)) {
590
- detail[tx('Raw event', '原始事件')] = event.technicalDetail;
591
- }
592
- return detail;
593
- }
594
578
 
595
579
  function buildActivityTooltip(event) {
596
580
  return [
@@ -599,71 +583,72 @@
599
583
  ].filter(Boolean).join('\n');
600
584
  }
601
585
 
602
- // The trailing status sections emitted by formatHumanReport (agentTranscript):
603
- // run metadata, not part of Codex's answer. Each entry matches the bilingual
604
- // "Label: value" line so the flat-text fallback can split them out of the
605
- // body and demote them into the same muted meta block the structured render
606
- // uses. Order mirrors the structured meta order.
607
- const FLAT_REPORT_STATUS_SECTIONS = [
608
- { key: 'unchangedReason', prefixes: ['Why nothing changed:', '未修改原因:'], en: 'Why nothing changed', zh: '未修改原因' },
609
- { key: 'writeResult', prefixes: ['Write result:', '写入结果:'], en: 'Write result', zh: '写入结果' },
610
- { key: 'undo', prefixes: ['Undo:', '可撤销:'], en: 'Undo', zh: '可撤销' },
611
- { key: 'nextStep', prefixes: ['Next:', '下一步:'], en: 'Next', zh: '下一步' }
612
- ];
613
-
614
- // Splits a flat completion-report string (formatHumanReport output) into the
615
- // answer body and the demoted meta rows. Only single-line sections whose head
616
- // matches a known status label are demoted, so a multi-paragraph conclusion
617
- // that happens to contain "Next: …" prose stays in the body.
618
- function splitFlatCompletionReport(text) {
619
- const raw = typeof text === 'string' ? text : '';
620
- if (!raw.trim()) {
621
- return { body: raw, meta: [] };
622
- }
623
- const bodySections = [];
624
- const meta = [];
625
- for (const section of raw.split(/\n{2,}/)) {
626
- const trimmed = section.trim();
627
- if (!trimmed) continue;
628
- const entry = trimmed.includes('\n')
629
- ? null
630
- : FLAT_REPORT_STATUS_SECTIONS.find(item => item.prefixes.some(prefix => trimmed.startsWith(prefix)));
631
- if (entry) {
632
- const prefix = entry.prefixes.find(p => trimmed.startsWith(p));
633
- const value = trimmed.slice(prefix.length).trim();
634
- if (value) {
635
- meta.push({ key: entry.key, label: tx(entry.en, entry.zh), value });
636
- continue;
637
- }
638
- }
639
- bodySections.push(trimmed);
640
- }
641
- return { body: bodySections.join('\n\n'), meta };
642
- }
586
+ // The result presenter owns parsing and current lifecycle metadata.
587
+ const splitFlatCompletionReport = text => RunResultActions.splitFlatCompletionReport(text, tx);
588
+ const projectCompletionMeta = (meta, run) => RunResultActions.projectCompletionMeta(meta, run, {
589
+ tx, trackedChangeInFlight, isTrackedChangeLifecycleRun, projectRunSettlement
590
+ });
643
591
 
644
- // Renders the demoted run-metadata block (Why nothing changed / Write result /
645
- // Undo / Next) beneath the answer. Shared by the structured and flat-fallback
646
- // render paths so both demote identically.
647
- function appendCompletionMetaBlock(report, meta) {
592
+ // The user's own open/closed choice per run survives card re-renders.
593
+ const metaOpenChoices = new Map();
594
+
595
+ // Renders the run-metadata rows (Why nothing changed / Write result / Undo /
596
+ // Next) behind a one-line summary beneath the answer. Shared by the
597
+ // structured and flat-fallback render paths so both demote identically.
598
+ function appendCompletionMetaBlock(report, meta, run) {
648
599
  if (!Array.isArray(meta) || !meta.length) {
649
600
  return;
650
601
  }
602
+ const rows = projectCompletionMeta(meta, run).filter(row => row?.label && row.value)
603
+ .map(row => ({ ...row, shown: failureNotice?.formatMetaValue(report, row) ?? row.value }));
604
+ if (!rows.length) return;
605
+ const summary = RunResultActions.summarizeCompletionMeta(rows, run, {
606
+ tx, failed: report.dataset.status === 'failed', unconfirmed: rows.some(row => row.shown !== row.value)
607
+ });
651
608
  const metaBlock = document.createElement('dl');
652
609
  metaBlock.className = 'run-final-answer__meta';
653
- for (const row of meta) {
654
- if (!row || !row.label || !row.value) continue;
610
+ metaBlock.id = `codex-run-meta-${String(run?.id || 'report').replace(/[^a-zA-Z0-9_-]/g, '-')}`;
611
+ for (const row of rows) {
655
612
  const dt = document.createElement('dt');
656
613
  dt.className = 'run-final-answer__meta-label';
657
614
  dt.textContent = row.label;
658
615
  if (row.key) dt.dataset.metaKey = row.key;
659
616
  const dd = document.createElement('dd');
660
617
  dd.className = 'run-final-answer__meta-value';
661
- dd.textContent = failureNotice?.formatMetaValue(report, row) ?? row.value;
618
+ dd.textContent = row.shown;
619
+ if (summary.warnKeys.has(row.key)) dt.dataset.tone = dd.dataset.tone = 'warn';
662
620
  metaBlock.append(dt, dd);
663
621
  }
664
- if (metaBlock.children.length) {
665
- report.append(metaBlock);
666
- }
622
+ const facts = document.createElement('div');
623
+ facts.className = 'run-final-answer__facts';
624
+ const toggle = document.createElement('button');
625
+ toggle.type = 'button';
626
+ toggle.className = 'run-final-answer__facts-sum';
627
+ toggle.setAttribute('aria-controls', metaBlock.id);
628
+ summary.facts.forEach((fact, index) => {
629
+ if (index) toggle.append(Object.assign(document.createElement('span'), { className: 'run-final-answer__facts-sep', textContent: '·' }));
630
+ const item = Object.assign(document.createElement('span'), { className: 'run-final-answer__fact', textContent: fact.text });
631
+ if (fact.tone) item.dataset.tone = fact.tone;
632
+ item.dataset.fact = fact.key;
633
+ toggle.append(item);
634
+ });
635
+ const more = Object.assign(document.createElement('span'), { className: 'run-final-answer__facts-more' });
636
+ toggle.append(Object.assign(document.createElement('span'), { className: 'run-final-answer__facts-sep', textContent: '·' }), more);
637
+ const setOpen = open => {
638
+ facts.dataset.open = String(open);
639
+ metaBlock.hidden = !open;
640
+ toggle.setAttribute('aria-expanded', String(open));
641
+ more.innerHTML = `${open ? tx('Hide', '收起') : tx('Details', '详情')}<svg class="codex-glyph" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path d="m6 4 4 4-4 4"/></svg>`;
642
+ };
643
+ setOpen(metaOpenChoices.get(run?.id) ?? summary.open);
644
+ toggle.addEventListener('click', event => {
645
+ event.stopPropagation();
646
+ const open = facts.dataset.open !== 'true';
647
+ if (run?.id) metaOpenChoices.set(run.id, open);
648
+ setOpen(open);
649
+ });
650
+ facts.append(toggle, metaBlock);
651
+ report.append(facts);
667
652
  }
668
653
 
669
654
  function renderCompletionReport(input, run) {
@@ -724,7 +709,7 @@
724
709
  main.className = 'run-final-answer';
725
710
  const mainSections = [];
726
711
  if (structured.conclusion) {
727
- mainSections.push(formatConclusionMarkdown(structured.conclusion));
712
+ mainSections.push(String(structured.conclusion));
728
713
  }
729
714
  if (structured.body) {
730
715
  mainSections.push(structured.body);
@@ -736,7 +721,7 @@
736
721
  }
737
722
 
738
723
  failureNotice?.append(report, event, run);
739
- appendCompletionMetaBlock(report, structured.meta);
724
+ appendCompletionMetaBlock(report, structured.meta, run);
740
725
  appendCompileFix(report);
741
726
  appendRejectedRedo(report);
742
727
  appendRecoveryActionForFailure(report, event, run);
@@ -758,24 +743,11 @@
758
743
  appendCompileFix(report);
759
744
  appendRejectedRedo(report);
760
745
  failureNotice?.append(report, event, run);
761
- appendCompletionMetaBlock(report, split.meta);
746
+ appendCompletionMetaBlock(report, split.meta, run);
762
747
  appendRecoveryActionForFailure(report, event, run);
763
748
  return report;
764
749
  }
765
750
 
766
- function formatConclusionMarkdown(value) {
767
- const conclusion = String(value || '');
768
- const label = getLocale() === 'zh' ? '结论:' : 'Conclusion:';
769
- return hasLeadingMarkdownBlock(conclusion)
770
- ? `${label}\n${conclusion}`
771
- : `${label} ${conclusion}`;
772
- }
773
-
774
- function hasLeadingMarkdownBlock(value) {
775
- const firstLine = String(value || '').trimStart().split(/\r?\n/, 1)[0];
776
- return /^(?:#{1,6}\s+\S|```|~~~|(?:[-+*]|\d+[.)])\s+\S|\*\*[^*]+\*\*:?\s*$)/.test(firstLine);
777
- }
778
-
779
751
  // For failure codes that have an actionable recovery path the user can
780
752
  // invoke directly from the run card, append a button inside the completion
781
753
  // report. Today's only consumer is codex_project_locked → "Force-release
@@ -815,20 +787,24 @@
815
787
  return button;
816
788
  }
817
789
 
790
+ function appendEditAndResend(report, run, actionKey) {
791
+ const retry = buildRecoveryButton(actionKey,
792
+ tx('Edit & resend', '编辑后重发'),
793
+ tx('Put this run\u2019s task back into the composer so you can adjust and resend it.', '把本轮任务填回输入框,修改后可直接重发。'));
794
+ retry.addEventListener('click', clickEvent => {
795
+ clickEvent.stopPropagation();
796
+ refillComposerForRetry(run || null);
797
+ });
798
+ report.append(retry);
799
+ }
800
+
818
801
  function appendRecoveryActionForFailure(report, event, run) {
819
802
  const recovery = failureNotice?.prepareRecovery(report, { openFile: openProjectFileForFailure });
803
+ const failureCode = event?.failure?.code || '';
820
804
  if (recovery?.handled) return;
821
805
  report = recovery?.target || report;
822
- const failureCode = event?.failure?.code || '';
823
806
  if (RETRYABLE_FAILURE_CODES.has(failureCode) && typeof refillComposerForRetry === 'function') {
824
- const retry = buildRecoveryButton(failureCode,
825
- tx('Edit & resend', '编辑后重发'),
826
- tx('Put this run\u2019s task back into the composer so you can adjust and resend it.', '把本轮任务填回输入框,修改后可直接重发。'));
827
- retry.addEventListener('click', clickEvent => {
828
- clickEvent.stopPropagation();
829
- refillComposerForRetry(run || null);
830
- });
831
- report.append(retry);
807
+ appendEditAndResend(report, run, failureCode);
832
808
  return;
833
809
  }
834
810
  if (NATIVE_SETUP_FAILURE_CODES.has(failureCode) && typeof showNativeSetupGuidance === 'function') {
@@ -917,6 +893,47 @@
917
893
  return Array.isArray(run.undoTrackedChanges) && run.undoTrackedChanges.length > 0;
918
894
  }
919
895
 
896
+ function configureEditButton(root, run, options = {}) {
897
+ const existing = root.querySelector('[data-run-edit]');
898
+ if (!existing) return;
899
+ const button = existing.cloneNode(true);
900
+ existing.replaceWith(button);
901
+ const available = ['cancelled', 'rejected'].includes(run?.status)
902
+ && Boolean(String(run?.task || '').trim())
903
+ && typeof canEditRun === 'function' && canEditRun(run)
904
+ && typeof refillComposerForRetry === 'function';
905
+ button.hidden = !available;
906
+ if (!available) return;
907
+ button.disabled = typeof options.running === 'boolean'
908
+ ? options.running : Boolean(getCurrentRunView?.());
909
+ button.title = tx('Edit & resend', '编辑后重发');
910
+ button.setAttribute('aria-label', button.title);
911
+ button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><path d="m12.8 3.2 4 4M3.5 16.5l4.2-.9 9-9a1.7 1.7 0 0 0 0-2.4l-.9-.9a1.7 1.7 0 0 0-2.4 0l-9 9z"/></svg>';
912
+ button.addEventListener('click', event => {
913
+ event.stopPropagation();
914
+ if (getCurrentRunView?.()) return;
915
+ refillComposerForRetry(run);
916
+ });
917
+ }
918
+
919
+ function configureWritebackButton(root, run, options = {}) {
920
+ const existing = root.querySelector('[data-run-sync-retry]');
921
+ if (!existing) return;
922
+ const button = existing.cloneNode(true);
923
+ existing.replaceWith(button);
924
+ const count = run?.retryWriteback?.operations?.length || 0;
925
+ const available = !run?.forkSnapshot && (count || run?.saveCheck?.files?.length)
926
+ && run.undoStatus !== 'applied' && run.trackedChangeStatus !== 'rejected' && typeof retryWriteback === 'function';
927
+ button.hidden = !available;
928
+ if (!available) return;
929
+ button.disabled = typeof options.running === 'boolean' ? options.running : Boolean(getCurrentRunView?.());
930
+ button.title = count ? tx('Retry sync (' + count + ' files)', '重试同步(' + count + ' 个文件)')
931
+ : tx('Check save status', '检查保存状态');
932
+ button.setAttribute('aria-label', button.title);
933
+ button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M16.5 7A7 7 0 0 0 4 5L2 7m0-4v4h4M3.5 13A7 7 0 0 0 16 15l2-2m0 4v-4h-4"/></svg>';
934
+ button.addEventListener('click', event => { event.stopPropagation(); if (!getCurrentRunView?.()) void retryWriteback(run.id); });
935
+ }
936
+
920
937
  function configureUndoButton(root, run) {
921
938
  const existing = root.querySelector('[data-run-undo]');
922
939
  const button = existing.cloneNode(true);
@@ -1028,7 +1045,11 @@
1028
1045
  }
1029
1046
 
1030
1047
  if (!isTrackedChangeLifecycleRun(run)) {
1031
- button.hidden = true;
1048
+ const captures = run.undoStatus !== 'applied' && Array.isArray(run.trackedChangeCaptures) ? run.trackedChangeCaptures.filter(c => c && c.state !== 'observed') : [];
1049
+ button.hidden = !captures.length; button.disabled = true;
1050
+ button.textContent = tr('runAcceptTracked');
1051
+ button.title = captures.length ? tx('Tracked-change ownership is unconfirmed. Check the reasons below.', '本轮留痕归属尚未确认,请先核对下方原因。')
1052
+ + '\n' + captures.map(c => c.path + ': ' + (c.reason || c.state) + (c.diagnostics?.sourceReason ? ' / ' + c.diagnostics.sourceReason : '')).join('\n') : tr('runAcceptTrackedTitle');
1032
1053
  return;
1033
1054
  }
1034
1055
 
@@ -1125,13 +1146,22 @@
1125
1146
  const log = getPanel()?.querySelector('[data-log]');
1126
1147
  const existing = log?.querySelector(`[data-run-id="${cssEscape(runId)}"]`);
1127
1148
  const run = findRunRecord(runId);
1128
- if (!log || !existing || !run) {
1129
- return;
1149
+ if (!log || !existing || !run || displayRun(run) === run) {
1150
+ return false;
1130
1151
  }
1131
- existing.replaceWith(renderRunCard(run));
1152
+ const reading = scrollLayout?.snapshot(), open = existing.querySelector('[data-run-process]')?.open;
1153
+ const next = renderRunCard(run);
1154
+ const process = next.querySelector('[data-run-process]');
1155
+ if (process && typeof open === 'boolean') process.open = open;
1156
+ existing.replaceWith(next);
1157
+ if (reading) scrollLayout?.restore(reading);
1158
+ return true;
1132
1159
  }
1133
1160
 
1134
1161
  return {
1162
+ refreshResolvedUndo: refreshRunCard,
1163
+ refreshActivitySummary: activitySummary?.update,
1164
+ appendActivityDetail,
1135
1165
  resetAutoFollow,
1136
1166
  bindLogAutoFollow,
1137
1167
  bumpUnreadIfDetached,
@@ -1147,6 +1177,8 @@
1147
1177
  upsertStreamEvent,
1148
1178
  renderCompletionReport,
1149
1179
  isTrackedChangeLifecycleRun,
1180
+ configureEditButton,
1181
+ configureWritebackButton,
1150
1182
  configureUndoButton,
1151
1183
  configureAcceptButton
1152
1184
  };