dsh-plugin-core 0.33.1 → 0.33.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (638) hide show
  1. package/README.md +9 -9
  2. package/dist/adv/explorer/open.js +4 -4
  3. package/dist/adv/explorer/open.js.map +1 -1
  4. package/dist/ui/feedback/host-toast.d.ts +1 -1
  5. package/dist/ui/feedback/host-toast.js +1 -1
  6. package/docs/help/explorer.doc.ts +1 -1
  7. package/docs/help/explorer.md +1 -1
  8. package/docs/help/integration.doc.ts +2 -2
  9. package/docs/help/integration.md +2 -2
  10. package/docs/help/session.doc.ts +1 -1
  11. package/docs/help/session.md +1 -1
  12. package/docs/help/ui.doc.ts +1 -1
  13. package/docs/help/ui.md +1 -1
  14. package/package.json +16 -16
  15. package/dist/explorer/ExplorerPanel.d.ts +0 -25
  16. package/dist/explorer/ExplorerPanel.d.ts.map +0 -1
  17. package/dist/explorer/ExplorerPanel.js +0 -111
  18. package/dist/explorer/ExplorerPanel.js.map +0 -1
  19. package/dist/explorer/FileBrowser.d.ts +0 -58
  20. package/dist/explorer/FileBrowser.d.ts.map +0 -1
  21. package/dist/explorer/FileBrowser.js +0 -632
  22. package/dist/explorer/FileBrowser.js.map +0 -1
  23. package/dist/explorer/crumb-nav.d.ts +0 -45
  24. package/dist/explorer/crumb-nav.d.ts.map +0 -1
  25. package/dist/explorer/crumb-nav.js +0 -78
  26. package/dist/explorer/crumb-nav.js.map +0 -1
  27. package/dist/explorer/crumbs-menu.d.ts +0 -37
  28. package/dist/explorer/crumbs-menu.d.ts.map +0 -1
  29. package/dist/explorer/crumbs-menu.js +0 -102
  30. package/dist/explorer/crumbs-menu.js.map +0 -1
  31. package/dist/explorer/explorer-css.d.ts +0 -2
  32. package/dist/explorer/explorer-css.d.ts.map +0 -1
  33. package/dist/explorer/explorer-css.generated.d.ts +0 -2
  34. package/dist/explorer/explorer-css.generated.d.ts.map +0 -1
  35. package/dist/explorer/explorer-css.generated.js +0 -4
  36. package/dist/explorer/explorer-css.generated.js.map +0 -1
  37. package/dist/explorer/explorer-css.js +0 -3
  38. package/dist/explorer/explorer-css.js.map +0 -1
  39. package/dist/explorer/fs-face.d.ts +0 -36
  40. package/dist/explorer/fs-face.d.ts.map +0 -1
  41. package/dist/explorer/fs-face.js +0 -74
  42. package/dist/explorer/fs-face.js.map +0 -1
  43. package/dist/explorer/index.d.ts +0 -6
  44. package/dist/explorer/index.d.ts.map +0 -1
  45. package/dist/explorer/index.js +0 -6
  46. package/dist/explorer/index.js.map +0 -1
  47. package/dist/explorer/landing.d.ts +0 -26
  48. package/dist/explorer/landing.d.ts.map +0 -1
  49. package/dist/explorer/landing.js +0 -43
  50. package/dist/explorer/landing.js.map +0 -1
  51. package/dist/explorer/open.d.ts +0 -137
  52. package/dist/explorer/open.d.ts.map +0 -1
  53. package/dist/explorer/open.js +0 -350
  54. package/dist/explorer/open.js.map +0 -1
  55. package/dist/explorer/picker-placement.d.ts +0 -69
  56. package/dist/explorer/picker-placement.d.ts.map +0 -1
  57. package/dist/explorer/picker-placement.js +0 -122
  58. package/dist/explorer/picker-placement.js.map +0 -1
  59. package/dist/explorer/preview/BytesPreview.d.ts +0 -12
  60. package/dist/explorer/preview/BytesPreview.d.ts.map +0 -1
  61. package/dist/explorer/preview/BytesPreview.js +0 -60
  62. package/dist/explorer/preview/BytesPreview.js.map +0 -1
  63. package/dist/explorer/preview/HtmlPreview.d.ts +0 -17
  64. package/dist/explorer/preview/HtmlPreview.d.ts.map +0 -1
  65. package/dist/explorer/preview/HtmlPreview.js +0 -113
  66. package/dist/explorer/preview/HtmlPreview.js.map +0 -1
  67. package/dist/explorer/preview/OfficePreview.d.ts +0 -12
  68. package/dist/explorer/preview/OfficePreview.d.ts.map +0 -1
  69. package/dist/explorer/preview/OfficePreview.js +0 -63
  70. package/dist/explorer/preview/OfficePreview.js.map +0 -1
  71. package/dist/explorer/preview/TextPreview.d.ts +0 -18
  72. package/dist/explorer/preview/TextPreview.d.ts.map +0 -1
  73. package/dist/explorer/preview/TextPreview.js +0 -122
  74. package/dist/explorer/preview/TextPreview.js.map +0 -1
  75. package/dist/explorer/preview/index.d.ts +0 -24
  76. package/dist/explorer/preview/index.d.ts.map +0 -1
  77. package/dist/explorer/preview/index.js +0 -58
  78. package/dist/explorer/preview/index.js.map +0 -1
  79. package/dist/explorer/preview/md-labels.d.ts +0 -3
  80. package/dist/explorer/preview/md-labels.d.ts.map +0 -1
  81. package/dist/explorer/preview/md-labels.js +0 -12
  82. package/dist/explorer/preview/md-labels.js.map +0 -1
  83. package/dist/explorer/preview-title-bar.d.ts +0 -26
  84. package/dist/explorer/preview-title-bar.d.ts.map +0 -1
  85. package/dist/explorer/preview-title-bar.js +0 -48
  86. package/dist/explorer/preview-title-bar.js.map +0 -1
  87. package/dist/explorer/types.d.ts +0 -259
  88. package/dist/explorer/types.d.ts.map +0 -1
  89. package/dist/explorer/types.js +0 -379
  90. package/dist/explorer/types.js.map +0 -1
  91. package/dist/session/SessionViewModal.d.ts +0 -37
  92. package/dist/session/SessionViewModal.d.ts.map +0 -1
  93. package/dist/session/SessionViewModal.js +0 -1133
  94. package/dist/session/SessionViewModal.js.map +0 -1
  95. package/dist/session/changes.d.ts +0 -73
  96. package/dist/session/changes.d.ts.map +0 -1
  97. package/dist/session/changes.js +0 -134
  98. package/dist/session/changes.js.map +0 -1
  99. package/dist/session/faces.d.ts +0 -244
  100. package/dist/session/faces.d.ts.map +0 -1
  101. package/dist/session/faces.js +0 -17
  102. package/dist/session/faces.js.map +0 -1
  103. package/dist/session/index.d.ts +0 -7
  104. package/dist/session/index.d.ts.map +0 -1
  105. package/dist/session/index.js +0 -27
  106. package/dist/session/index.js.map +0 -1
  107. package/dist/session/mirror/AskCard.d.ts +0 -35
  108. package/dist/session/mirror/AskCard.d.ts.map +0 -1
  109. package/dist/session/mirror/AskCard.js +0 -131
  110. package/dist/session/mirror/AskCard.js.map +0 -1
  111. package/dist/session/mirror/BashRow.d.ts +0 -14
  112. package/dist/session/mirror/BashRow.d.ts.map +0 -1
  113. package/dist/session/mirror/BashRow.js +0 -143
  114. package/dist/session/mirror/BashRow.js.map +0 -1
  115. package/dist/session/mirror/ChangedFileDiff.d.ts +0 -25
  116. package/dist/session/mirror/ChangedFileDiff.d.ts.map +0 -1
  117. package/dist/session/mirror/ChangedFileDiff.js +0 -178
  118. package/dist/session/mirror/ChangedFileDiff.js.map +0 -1
  119. package/dist/session/mirror/ChangedFilesCard.d.ts +0 -18
  120. package/dist/session/mirror/ChangedFilesCard.d.ts.map +0 -1
  121. package/dist/session/mirror/ChangedFilesCard.js +0 -165
  122. package/dist/session/mirror/ChangedFilesCard.js.map +0 -1
  123. package/dist/session/mirror/ChatGroupSeat.d.ts +0 -24
  124. package/dist/session/mirror/ChatGroupSeat.d.ts.map +0 -1
  125. package/dist/session/mirror/ChatGroupSeat.js +0 -135
  126. package/dist/session/mirror/ChatGroupSeat.js.map +0 -1
  127. package/dist/session/mirror/ChatNodeSeat.d.ts +0 -43
  128. package/dist/session/mirror/ChatNodeSeat.d.ts.map +0 -1
  129. package/dist/session/mirror/ChatNodeSeat.js +0 -133
  130. package/dist/session/mirror/ChatNodeSeat.js.map +0 -1
  131. package/dist/session/mirror/ChatView.d.ts +0 -47
  132. package/dist/session/mirror/ChatView.d.ts.map +0 -1
  133. package/dist/session/mirror/ChatView.js +0 -138
  134. package/dist/session/mirror/ChatView.js.map +0 -1
  135. package/dist/session/mirror/CommandCard.d.ts +0 -20
  136. package/dist/session/mirror/CommandCard.d.ts.map +0 -1
  137. package/dist/session/mirror/CommandCard.js +0 -69
  138. package/dist/session/mirror/CommandCard.js.map +0 -1
  139. package/dist/session/mirror/ContextInjectionRow.d.ts +0 -18
  140. package/dist/session/mirror/ContextInjectionRow.d.ts.map +0 -1
  141. package/dist/session/mirror/ContextInjectionRow.js +0 -50
  142. package/dist/session/mirror/ContextInjectionRow.js.map +0 -1
  143. package/dist/session/mirror/Deliverables.d.ts +0 -24
  144. package/dist/session/mirror/Deliverables.d.ts.map +0 -1
  145. package/dist/session/mirror/Deliverables.js +0 -175
  146. package/dist/session/mirror/Deliverables.js.map +0 -1
  147. package/dist/session/mirror/GenericCommandCard.d.ts +0 -136
  148. package/dist/session/mirror/GenericCommandCard.d.ts.map +0 -1
  149. package/dist/session/mirror/GenericCommandCard.js +0 -948
  150. package/dist/session/mirror/GenericCommandCard.js.map +0 -1
  151. package/dist/session/mirror/MessageIconActions.d.ts +0 -16
  152. package/dist/session/mirror/MessageIconActions.d.ts.map +0 -1
  153. package/dist/session/mirror/MessageIconActions.js +0 -69
  154. package/dist/session/mirror/MessageIconActions.js.map +0 -1
  155. package/dist/session/mirror/MessageItem.d.ts +0 -93
  156. package/dist/session/mirror/MessageItem.d.ts.map +0 -1
  157. package/dist/session/mirror/MessageItem.js +0 -194
  158. package/dist/session/mirror/MessageItem.js.map +0 -1
  159. package/dist/session/mirror/ReasoningRow.d.ts +0 -11
  160. package/dist/session/mirror/ReasoningRow.d.ts.map +0 -1
  161. package/dist/session/mirror/ReasoningRow.js +0 -111
  162. package/dist/session/mirror/ReasoningRow.js.map +0 -1
  163. package/dist/session/mirror/RunningStatus.d.ts +0 -12
  164. package/dist/session/mirror/RunningStatus.d.ts.map +0 -1
  165. package/dist/session/mirror/RunningStatus.js +0 -57
  166. package/dist/session/mirror/RunningStatus.js.map +0 -1
  167. package/dist/session/mirror/StatDialog.d.ts +0 -20
  168. package/dist/session/mirror/StatDialog.d.ts.map +0 -1
  169. package/dist/session/mirror/StatDialog.js +0 -49
  170. package/dist/session/mirror/StatDialog.js.map +0 -1
  171. package/dist/session/mirror/ToolDetails.d.ts +0 -65
  172. package/dist/session/mirror/ToolDetails.d.ts.map +0 -1
  173. package/dist/session/mirror/ToolDetails.js +0 -268
  174. package/dist/session/mirror/ToolDetails.js.map +0 -1
  175. package/dist/session/mirror/TurnProcessNodeView.d.ts +0 -10
  176. package/dist/session/mirror/TurnProcessNodeView.d.ts.map +0 -1
  177. package/dist/session/mirror/TurnProcessNodeView.js +0 -57
  178. package/dist/session/mirror/TurnProcessNodeView.js.map +0 -1
  179. package/dist/session/mirror/TurnTailNodeView.d.ts +0 -57
  180. package/dist/session/mirror/TurnTailNodeView.d.ts.map +0 -1
  181. package/dist/session/mirror/TurnTailNodeView.js +0 -106
  182. package/dist/session/mirror/TurnTailNodeView.js.map +0 -1
  183. package/dist/session/mirror/TurnTriggerNodeView.d.ts +0 -16
  184. package/dist/session/mirror/TurnTriggerNodeView.d.ts.map +0 -1
  185. package/dist/session/mirror/TurnTriggerNodeView.js +0 -103
  186. package/dist/session/mirror/TurnTriggerNodeView.js.map +0 -1
  187. package/dist/session/mirror/TurnUsagePanel.d.ts +0 -21
  188. package/dist/session/mirror/TurnUsagePanel.d.ts.map +0 -1
  189. package/dist/session/mirror/TurnUsagePanel.js +0 -41
  190. package/dist/session/mirror/TurnUsagePanel.js.map +0 -1
  191. package/dist/session/mirror/control-details.d.ts +0 -9
  192. package/dist/session/mirror/control-details.d.ts.map +0 -1
  193. package/dist/session/mirror/control-details.js +0 -549
  194. package/dist/session/mirror/control-details.js.map +0 -1
  195. package/dist/session/mirror/detail-i18n.d.ts +0 -4
  196. package/dist/session/mirror/detail-i18n.d.ts.map +0 -1
  197. package/dist/session/mirror/detail-i18n.js +0 -153
  198. package/dist/session/mirror/detail-i18n.js.map +0 -1
  199. package/dist/session/mirror/message-chrome.d.ts +0 -39
  200. package/dist/session/mirror/message-chrome.d.ts.map +0 -1
  201. package/dist/session/mirror/message-chrome.js +0 -153
  202. package/dist/session/mirror/message-chrome.js.map +0 -1
  203. package/dist/session/mirror/process-groups.d.ts +0 -56
  204. package/dist/session/mirror/process-groups.d.ts.map +0 -1
  205. package/dist/session/mirror/process-groups.js +0 -202
  206. package/dist/session/mirror/process-groups.js.map +0 -1
  207. package/dist/session/official-classes.d.ts +0 -28
  208. package/dist/session/official-classes.d.ts.map +0 -1
  209. package/dist/session/official-classes.js +0 -152
  210. package/dist/session/official-classes.js.map +0 -1
  211. package/dist/session/open-review.d.ts +0 -13
  212. package/dist/session/open-review.d.ts.map +0 -1
  213. package/dist/session/open-review.js +0 -32
  214. package/dist/session/open-review.js.map +0 -1
  215. package/dist/session/open-session-view.d.ts +0 -19
  216. package/dist/session/open-session-view.d.ts.map +0 -1
  217. package/dist/session/open-session-view.js +0 -147
  218. package/dist/session/open-session-view.js.map +0 -1
  219. package/dist/session/pending-inputs.d.ts +0 -33
  220. package/dist/session/pending-inputs.d.ts.map +0 -1
  221. package/dist/session/pending-inputs.js +0 -130
  222. package/dist/session/pending-inputs.js.map +0 -1
  223. package/dist/session/session-css.d.ts +0 -2
  224. package/dist/session/session-css.d.ts.map +0 -1
  225. package/dist/session/session-css.generated.d.ts +0 -2
  226. package/dist/session/session-css.generated.d.ts.map +0 -1
  227. package/dist/session/session-css.generated.js +0 -4
  228. package/dist/session/session-css.generated.js.map +0 -1
  229. package/dist/session/session-css.js +0 -3
  230. package/dist/session/session-css.js.map +0 -1
  231. package/dist/session/tail-follow.d.ts +0 -29
  232. package/dist/session/tail-follow.d.ts.map +0 -1
  233. package/dist/session/tail-follow.js +0 -106
  234. package/dist/session/tail-follow.js.map +0 -1
  235. package/dist/session/types.d.ts +0 -28
  236. package/dist/session/types.d.ts.map +0 -1
  237. package/dist/session/types.js +0 -12
  238. package/dist/session/types.js.map +0 -1
  239. package/dist/ui/AlertModal.d.ts +0 -41
  240. package/dist/ui/AlertModal.d.ts.map +0 -1
  241. package/dist/ui/AlertModal.js +0 -45
  242. package/dist/ui/AlertModal.js.map +0 -1
  243. package/dist/ui/Button.d.ts +0 -102
  244. package/dist/ui/Button.d.ts.map +0 -1
  245. package/dist/ui/Button.js +0 -233
  246. package/dist/ui/Button.js.map +0 -1
  247. package/dist/ui/Card.d.ts +0 -65
  248. package/dist/ui/Card.d.ts.map +0 -1
  249. package/dist/ui/Card.js +0 -109
  250. package/dist/ui/Card.js.map +0 -1
  251. package/dist/ui/Checkbox.d.ts +0 -24
  252. package/dist/ui/Checkbox.d.ts.map +0 -1
  253. package/dist/ui/Checkbox.js +0 -35
  254. package/dist/ui/Checkbox.js.map +0 -1
  255. package/dist/ui/Chip.d.ts +0 -28
  256. package/dist/ui/Chip.d.ts.map +0 -1
  257. package/dist/ui/Chip.js +0 -36
  258. package/dist/ui/Chip.js.map +0 -1
  259. package/dist/ui/CodeViewer.d.ts +0 -38
  260. package/dist/ui/CodeViewer.d.ts.map +0 -1
  261. package/dist/ui/CodeViewer.js +0 -107
  262. package/dist/ui/CodeViewer.js.map +0 -1
  263. package/dist/ui/ConfirmModal.d.ts +0 -50
  264. package/dist/ui/ConfirmModal.d.ts.map +0 -1
  265. package/dist/ui/ConfirmModal.js +0 -47
  266. package/dist/ui/ConfirmModal.js.map +0 -1
  267. package/dist/ui/DateTimePicker.d.ts +0 -45
  268. package/dist/ui/DateTimePicker.d.ts.map +0 -1
  269. package/dist/ui/DateTimePicker.js +0 -462
  270. package/dist/ui/DateTimePicker.js.map +0 -1
  271. package/dist/ui/EmptyState.d.ts +0 -12
  272. package/dist/ui/EmptyState.d.ts.map +0 -1
  273. package/dist/ui/EmptyState.js +0 -10
  274. package/dist/ui/EmptyState.js.map +0 -1
  275. package/dist/ui/Field.d.ts +0 -125
  276. package/dist/ui/Field.d.ts.map +0 -1
  277. package/dist/ui/Field.js +0 -175
  278. package/dist/ui/Field.js.map +0 -1
  279. package/dist/ui/FieldHint.d.ts +0 -18
  280. package/dist/ui/FieldHint.d.ts.map +0 -1
  281. package/dist/ui/FieldHint.js +0 -40
  282. package/dist/ui/FieldHint.js.map +0 -1
  283. package/dist/ui/FlipText.d.ts +0 -43
  284. package/dist/ui/FlipText.d.ts.map +0 -1
  285. package/dist/ui/FlipText.js +0 -59
  286. package/dist/ui/FlipText.js.map +0 -1
  287. package/dist/ui/InputGroup.d.ts +0 -91
  288. package/dist/ui/InputGroup.d.ts.map +0 -1
  289. package/dist/ui/InputGroup.js +0 -125
  290. package/dist/ui/InputGroup.js.map +0 -1
  291. package/dist/ui/LiveText.d.ts +0 -13
  292. package/dist/ui/LiveText.d.ts.map +0 -1
  293. package/dist/ui/LiveText.js +0 -19
  294. package/dist/ui/LiveText.js.map +0 -1
  295. package/dist/ui/Loader.d.ts +0 -49
  296. package/dist/ui/Loader.d.ts.map +0 -1
  297. package/dist/ui/Loader.js +0 -79
  298. package/dist/ui/Loader.js.map +0 -1
  299. package/dist/ui/LoaderBar.d.ts +0 -38
  300. package/dist/ui/LoaderBar.d.ts.map +0 -1
  301. package/dist/ui/LoaderBar.js +0 -79
  302. package/dist/ui/LoaderBar.js.map +0 -1
  303. package/dist/ui/Loading.d.ts +0 -69
  304. package/dist/ui/Loading.d.ts.map +0 -1
  305. package/dist/ui/Loading.js +0 -164
  306. package/dist/ui/Loading.js.map +0 -1
  307. package/dist/ui/MarqueeText.d.ts +0 -22
  308. package/dist/ui/MarqueeText.d.ts.map +0 -1
  309. package/dist/ui/MarqueeText.js +0 -52
  310. package/dist/ui/MarqueeText.js.map +0 -1
  311. package/dist/ui/Modal.d.ts +0 -73
  312. package/dist/ui/Modal.d.ts.map +0 -1
  313. package/dist/ui/Modal.js +0 -83
  314. package/dist/ui/Modal.js.map +0 -1
  315. package/dist/ui/ModelPicker.d.ts +0 -48
  316. package/dist/ui/ModelPicker.d.ts.map +0 -1
  317. package/dist/ui/ModelPicker.js +0 -101
  318. package/dist/ui/ModelPicker.js.map +0 -1
  319. package/dist/ui/Pagination.d.ts +0 -59
  320. package/dist/ui/Pagination.d.ts.map +0 -1
  321. package/dist/ui/Pagination.js +0 -112
  322. package/dist/ui/Pagination.js.map +0 -1
  323. package/dist/ui/PanelDock.d.ts +0 -132
  324. package/dist/ui/PanelDock.d.ts.map +0 -1
  325. package/dist/ui/PanelDock.js +0 -390
  326. package/dist/ui/PanelDock.js.map +0 -1
  327. package/dist/ui/Picker.d.ts +0 -56
  328. package/dist/ui/Picker.d.ts.map +0 -1
  329. package/dist/ui/Picker.js +0 -244
  330. package/dist/ui/Picker.js.map +0 -1
  331. package/dist/ui/QuickToolbar.d.ts +0 -54
  332. package/dist/ui/QuickToolbar.d.ts.map +0 -1
  333. package/dist/ui/QuickToolbar.js +0 -254
  334. package/dist/ui/QuickToolbar.js.map +0 -1
  335. package/dist/ui/SectionHead.d.ts +0 -35
  336. package/dist/ui/SectionHead.d.ts.map +0 -1
  337. package/dist/ui/SectionHead.js +0 -45
  338. package/dist/ui/SectionHead.js.map +0 -1
  339. package/dist/ui/Segmented.d.ts +0 -99
  340. package/dist/ui/Segmented.d.ts.map +0 -1
  341. package/dist/ui/Segmented.js +0 -135
  342. package/dist/ui/Segmented.js.map +0 -1
  343. package/dist/ui/SideSheet.d.ts +0 -70
  344. package/dist/ui/SideSheet.d.ts.map +0 -1
  345. package/dist/ui/SideSheet.js +0 -130
  346. package/dist/ui/SideSheet.js.map +0 -1
  347. package/dist/ui/SplitGroup.d.ts +0 -37
  348. package/dist/ui/SplitGroup.d.ts.map +0 -1
  349. package/dist/ui/SplitGroup.js +0 -36
  350. package/dist/ui/SplitGroup.js.map +0 -1
  351. package/dist/ui/Surface.d.ts +0 -43
  352. package/dist/ui/Surface.d.ts.map +0 -1
  353. package/dist/ui/Surface.js +0 -39
  354. package/dist/ui/Surface.js.map +0 -1
  355. package/dist/ui/Table.d.ts +0 -30
  356. package/dist/ui/Table.d.ts.map +0 -1
  357. package/dist/ui/Table.js +0 -96
  358. package/dist/ui/Table.js.map +0 -1
  359. package/dist/ui/Textarea.d.ts +0 -36
  360. package/dist/ui/Textarea.d.ts.map +0 -1
  361. package/dist/ui/Textarea.js +0 -35
  362. package/dist/ui/Textarea.js.map +0 -1
  363. package/dist/ui/Toast.d.ts +0 -45
  364. package/dist/ui/Toast.d.ts.map +0 -1
  365. package/dist/ui/Toast.js +0 -225
  366. package/dist/ui/Toast.js.map +0 -1
  367. package/dist/ui/WorkspacePicker.d.ts +0 -35
  368. package/dist/ui/WorkspacePicker.d.ts.map +0 -1
  369. package/dist/ui/WorkspacePicker.js +0 -39
  370. package/dist/ui/WorkspacePicker.js.map +0 -1
  371. package/dist/ui/card-css.d.ts +0 -2
  372. package/dist/ui/card-css.d.ts.map +0 -1
  373. package/dist/ui/card-css.generated.d.ts +0 -2
  374. package/dist/ui/card-css.generated.d.ts.map +0 -1
  375. package/dist/ui/card-css.generated.js +0 -4
  376. package/dist/ui/card-css.generated.js.map +0 -1
  377. package/dist/ui/card-css.js +0 -5
  378. package/dist/ui/card-css.js.map +0 -1
  379. package/dist/ui/chevron.d.ts +0 -22
  380. package/dist/ui/chevron.d.ts.map +0 -1
  381. package/dist/ui/chevron.js +0 -33
  382. package/dist/ui/chevron.js.map +0 -1
  383. package/dist/ui/chip-css.d.ts +0 -2
  384. package/dist/ui/chip-css.d.ts.map +0 -1
  385. package/dist/ui/chip-css.generated.d.ts +0 -2
  386. package/dist/ui/chip-css.generated.d.ts.map +0 -1
  387. package/dist/ui/chip-css.generated.js +0 -4
  388. package/dist/ui/chip-css.generated.js.map +0 -1
  389. package/dist/ui/chip-css.js +0 -12
  390. package/dist/ui/chip-css.js.map +0 -1
  391. package/dist/ui/code-viewer-css.d.ts +0 -2
  392. package/dist/ui/code-viewer-css.d.ts.map +0 -1
  393. package/dist/ui/code-viewer-css.generated.d.ts +0 -2
  394. package/dist/ui/code-viewer-css.generated.d.ts.map +0 -1
  395. package/dist/ui/code-viewer-css.generated.js +0 -4
  396. package/dist/ui/code-viewer-css.generated.js.map +0 -1
  397. package/dist/ui/code-viewer-css.js +0 -3
  398. package/dist/ui/code-viewer-css.js.map +0 -1
  399. package/dist/ui/code-viewer-lang.d.ts +0 -15
  400. package/dist/ui/code-viewer-lang.d.ts.map +0 -1
  401. package/dist/ui/code-viewer-lang.js +0 -190
  402. package/dist/ui/code-viewer-lang.js.map +0 -1
  403. package/dist/ui/code-viewer-theme.d.ts +0 -5
  404. package/dist/ui/code-viewer-theme.d.ts.map +0 -1
  405. package/dist/ui/code-viewer-theme.js +0 -138
  406. package/dist/ui/code-viewer-theme.js.map +0 -1
  407. package/dist/ui/controls/button-css.generated.d.ts +0 -2
  408. package/dist/ui/controls/button-css.generated.d.ts.map +0 -1
  409. package/dist/ui/controls/button-css.generated.js +0 -4
  410. package/dist/ui/controls/button-css.generated.js.map +0 -1
  411. package/dist/ui/controls/datetime-css.generated.d.ts +0 -2
  412. package/dist/ui/controls/datetime-css.generated.d.ts.map +0 -1
  413. package/dist/ui/controls/datetime-css.generated.js +0 -4
  414. package/dist/ui/controls/datetime-css.generated.js.map +0 -1
  415. package/dist/ui/controls/field-css.generated.d.ts +0 -2
  416. package/dist/ui/controls/field-css.generated.d.ts.map +0 -1
  417. package/dist/ui/controls/field-css.generated.js +0 -4
  418. package/dist/ui/controls/field-css.generated.js.map +0 -1
  419. package/dist/ui/controls/hint-css.generated.d.ts +0 -2
  420. package/dist/ui/controls/hint-css.generated.d.ts.map +0 -1
  421. package/dist/ui/controls/hint-css.generated.js +0 -4
  422. package/dist/ui/controls/hint-css.generated.js.map +0 -1
  423. package/dist/ui/controls/input-group-css.generated.d.ts +0 -2
  424. package/dist/ui/controls/input-group-css.generated.d.ts.map +0 -1
  425. package/dist/ui/controls/input-group-css.generated.js +0 -4
  426. package/dist/ui/controls/input-group-css.generated.js.map +0 -1
  427. package/dist/ui/controls/loader-bar-css.generated.d.ts +0 -2
  428. package/dist/ui/controls/loader-bar-css.generated.d.ts.map +0 -1
  429. package/dist/ui/controls/loader-bar-css.generated.js +0 -4
  430. package/dist/ui/controls/loader-bar-css.generated.js.map +0 -1
  431. package/dist/ui/controls/loader-css.generated.d.ts +0 -2
  432. package/dist/ui/controls/loader-css.generated.d.ts.map +0 -1
  433. package/dist/ui/controls/loader-css.generated.js +0 -4
  434. package/dist/ui/controls/loader-css.generated.js.map +0 -1
  435. package/dist/ui/controls/loading-css.generated.d.ts +0 -2
  436. package/dist/ui/controls/loading-css.generated.d.ts.map +0 -1
  437. package/dist/ui/controls/loading-css.generated.js +0 -4
  438. package/dist/ui/controls/loading-css.generated.js.map +0 -1
  439. package/dist/ui/controls/pagination-css.generated.d.ts +0 -2
  440. package/dist/ui/controls/pagination-css.generated.d.ts.map +0 -1
  441. package/dist/ui/controls/pagination-css.generated.js +0 -4
  442. package/dist/ui/controls/pagination-css.generated.js.map +0 -1
  443. package/dist/ui/controls/quick-toolbar-css.generated.d.ts +0 -2
  444. package/dist/ui/controls/quick-toolbar-css.generated.d.ts.map +0 -1
  445. package/dist/ui/controls/quick-toolbar-css.generated.js +0 -4
  446. package/dist/ui/controls/quick-toolbar-css.generated.js.map +0 -1
  447. package/dist/ui/controls/section-head-css.generated.d.ts +0 -2
  448. package/dist/ui/controls/section-head-css.generated.d.ts.map +0 -1
  449. package/dist/ui/controls/section-head-css.generated.js +0 -4
  450. package/dist/ui/controls/section-head-css.generated.js.map +0 -1
  451. package/dist/ui/controls/segmented-css.generated.d.ts +0 -2
  452. package/dist/ui/controls/segmented-css.generated.d.ts.map +0 -1
  453. package/dist/ui/controls/segmented-css.generated.js +0 -4
  454. package/dist/ui/controls/segmented-css.generated.js.map +0 -1
  455. package/dist/ui/controls/split-group-css.generated.d.ts +0 -2
  456. package/dist/ui/controls/split-group-css.generated.d.ts.map +0 -1
  457. package/dist/ui/controls/split-group-css.generated.js +0 -4
  458. package/dist/ui/controls/split-group-css.generated.js.map +0 -1
  459. package/dist/ui/controls/table-css.generated.d.ts +0 -2
  460. package/dist/ui/controls/table-css.generated.d.ts.map +0 -1
  461. package/dist/ui/controls/table-css.generated.js +0 -4
  462. package/dist/ui/controls/table-css.generated.js.map +0 -1
  463. package/dist/ui/controls/table-plain-css.generated.d.ts +0 -2
  464. package/dist/ui/controls/table-plain-css.generated.d.ts.map +0 -1
  465. package/dist/ui/controls/table-plain-css.generated.js +0 -4
  466. package/dist/ui/controls/table-plain-css.generated.js.map +0 -1
  467. package/dist/ui/controls-css.d.ts +0 -16
  468. package/dist/ui/controls-css.d.ts.map +0 -1
  469. package/dist/ui/controls-css.js +0 -26
  470. package/dist/ui/controls-css.js.map +0 -1
  471. package/dist/ui/css.d.ts +0 -35
  472. package/dist/ui/css.d.ts.map +0 -1
  473. package/dist/ui/css.js +0 -52
  474. package/dist/ui/css.js.map +0 -1
  475. package/dist/ui/datetime-logic.d.ts +0 -102
  476. package/dist/ui/datetime-logic.d.ts.map +0 -1
  477. package/dist/ui/datetime-logic.js +0 -200
  478. package/dist/ui/datetime-logic.js.map +0 -1
  479. package/dist/ui/feedback-css.d.ts +0 -2
  480. package/dist/ui/feedback-css.d.ts.map +0 -1
  481. package/dist/ui/feedback-css.generated.d.ts +0 -2
  482. package/dist/ui/feedback-css.generated.d.ts.map +0 -1
  483. package/dist/ui/feedback-css.generated.js +0 -4
  484. package/dist/ui/feedback-css.generated.js.map +0 -1
  485. package/dist/ui/feedback-css.js +0 -4
  486. package/dist/ui/feedback-css.js.map +0 -1
  487. package/dist/ui/flip-css.d.ts +0 -2
  488. package/dist/ui/flip-css.d.ts.map +0 -1
  489. package/dist/ui/flip-css.generated.d.ts +0 -2
  490. package/dist/ui/flip-css.generated.d.ts.map +0 -1
  491. package/dist/ui/flip-css.generated.js +0 -4
  492. package/dist/ui/flip-css.generated.js.map +0 -1
  493. package/dist/ui/flip-css.js +0 -4
  494. package/dist/ui/flip-css.js.map +0 -1
  495. package/dist/ui/host-data.d.ts +0 -119
  496. package/dist/ui/host-data.d.ts.map +0 -1
  497. package/dist/ui/host-data.js +0 -122
  498. package/dist/ui/host-data.js.map +0 -1
  499. package/dist/ui/host-toast.d.ts +0 -23
  500. package/dist/ui/host-toast.d.ts.map +0 -1
  501. package/dist/ui/host-toast.js +0 -34
  502. package/dist/ui/host-toast.js.map +0 -1
  503. package/dist/ui/loader-bar-art.d.ts +0 -6
  504. package/dist/ui/loader-bar-art.d.ts.map +0 -1
  505. package/dist/ui/loader-bar-art.js +0 -6
  506. package/dist/ui/loader-bar-art.js.map +0 -1
  507. package/dist/ui/loading-host.d.ts +0 -49
  508. package/dist/ui/loading-host.d.ts.map +0 -1
  509. package/dist/ui/loading-host.js +0 -57
  510. package/dist/ui/loading-host.js.map +0 -1
  511. package/dist/ui/locale.d.ts +0 -4
  512. package/dist/ui/locale.d.ts.map +0 -1
  513. package/dist/ui/locale.js +0 -17
  514. package/dist/ui/locale.js.map +0 -1
  515. package/dist/ui/marquee-css.d.ts +0 -2
  516. package/dist/ui/marquee-css.d.ts.map +0 -1
  517. package/dist/ui/marquee-css.generated.d.ts +0 -2
  518. package/dist/ui/marquee-css.generated.d.ts.map +0 -1
  519. package/dist/ui/marquee-css.generated.js +0 -4
  520. package/dist/ui/marquee-css.generated.js.map +0 -1
  521. package/dist/ui/marquee-css.js +0 -4
  522. package/dist/ui/marquee-css.js.map +0 -1
  523. package/dist/ui/modal-host.d.ts +0 -51
  524. package/dist/ui/modal-host.d.ts.map +0 -1
  525. package/dist/ui/modal-host.js +0 -170
  526. package/dist/ui/modal-host.js.map +0 -1
  527. package/dist/ui/overlay-css.d.ts +0 -2
  528. package/dist/ui/overlay-css.d.ts.map +0 -1
  529. package/dist/ui/overlay-css.generated.d.ts +0 -2
  530. package/dist/ui/overlay-css.generated.d.ts.map +0 -1
  531. package/dist/ui/overlay-css.generated.js +0 -4
  532. package/dist/ui/overlay-css.generated.js.map +0 -1
  533. package/dist/ui/overlay-css.js +0 -2
  534. package/dist/ui/overlay-css.js.map +0 -1
  535. package/dist/ui/overlay.d.ts +0 -62
  536. package/dist/ui/overlay.d.ts.map +0 -1
  537. package/dist/ui/overlay.js +0 -94
  538. package/dist/ui/overlay.js.map +0 -1
  539. package/dist/ui/pagination-logic.d.ts +0 -36
  540. package/dist/ui/pagination-logic.d.ts.map +0 -1
  541. package/dist/ui/pagination-logic.js +0 -73
  542. package/dist/ui/pagination-logic.js.map +0 -1
  543. package/dist/ui/panel-css.d.ts +0 -2
  544. package/dist/ui/panel-css.d.ts.map +0 -1
  545. package/dist/ui/panel-css.generated.d.ts +0 -2
  546. package/dist/ui/panel-css.generated.d.ts.map +0 -1
  547. package/dist/ui/panel-css.generated.js +0 -4
  548. package/dist/ui/panel-css.generated.js.map +0 -1
  549. package/dist/ui/panel-css.js +0 -2
  550. package/dist/ui/panel-css.js.map +0 -1
  551. package/dist/ui/panel-dock-css.d.ts +0 -2
  552. package/dist/ui/panel-dock-css.d.ts.map +0 -1
  553. package/dist/ui/panel-dock-css.generated.d.ts +0 -2
  554. package/dist/ui/panel-dock-css.generated.d.ts.map +0 -1
  555. package/dist/ui/panel-dock-css.generated.js +0 -4
  556. package/dist/ui/panel-dock-css.generated.js.map +0 -1
  557. package/dist/ui/panel-dock-css.js +0 -4
  558. package/dist/ui/panel-dock-css.js.map +0 -1
  559. package/dist/ui/panel-dock-logic.d.ts +0 -67
  560. package/dist/ui/panel-dock-logic.d.ts.map +0 -1
  561. package/dist/ui/panel-dock-logic.js +0 -110
  562. package/dist/ui/panel-dock-logic.js.map +0 -1
  563. package/dist/ui/panel.d.ts +0 -41
  564. package/dist/ui/panel.d.ts.map +0 -1
  565. package/dist/ui/panel.js +0 -37
  566. package/dist/ui/panel.js.map +0 -1
  567. package/dist/ui/picker-css.d.ts +0 -2
  568. package/dist/ui/picker-css.d.ts.map +0 -1
  569. package/dist/ui/picker-css.generated.d.ts +0 -2
  570. package/dist/ui/picker-css.generated.d.ts.map +0 -1
  571. package/dist/ui/picker-css.generated.js +0 -4
  572. package/dist/ui/picker-css.generated.js.map +0 -1
  573. package/dist/ui/picker-css.js +0 -4
  574. package/dist/ui/picker-css.js.map +0 -1
  575. package/dist/ui/picker-icons.d.ts +0 -12
  576. package/dist/ui/picker-icons.d.ts.map +0 -1
  577. package/dist/ui/picker-icons.js +0 -29
  578. package/dist/ui/picker-icons.js.map +0 -1
  579. package/dist/ui/picker-logic.d.ts +0 -33
  580. package/dist/ui/picker-logic.d.ts.map +0 -1
  581. package/dist/ui/picker-logic.js +0 -68
  582. package/dist/ui/picker-logic.js.map +0 -1
  583. package/dist/ui/quick-toolbar-logic.d.ts +0 -76
  584. package/dist/ui/quick-toolbar-logic.d.ts.map +0 -1
  585. package/dist/ui/quick-toolbar-logic.js +0 -40
  586. package/dist/ui/quick-toolbar-logic.js.map +0 -1
  587. package/dist/ui/resizer.d.ts +0 -29
  588. package/dist/ui/resizer.d.ts.map +0 -1
  589. package/dist/ui/resizer.js +0 -42
  590. package/dist/ui/resizer.js.map +0 -1
  591. package/dist/ui/side-panel-css.d.ts +0 -2
  592. package/dist/ui/side-panel-css.d.ts.map +0 -1
  593. package/dist/ui/side-panel-css.generated.d.ts +0 -2
  594. package/dist/ui/side-panel-css.generated.d.ts.map +0 -1
  595. package/dist/ui/side-panel-css.generated.js +0 -4
  596. package/dist/ui/side-panel-css.generated.js.map +0 -1
  597. package/dist/ui/side-panel-css.js +0 -2
  598. package/dist/ui/side-panel-css.js.map +0 -1
  599. package/dist/ui/side-sheet-css.d.ts +0 -2
  600. package/dist/ui/side-sheet-css.d.ts.map +0 -1
  601. package/dist/ui/side-sheet-css.generated.d.ts +0 -2
  602. package/dist/ui/side-sheet-css.generated.d.ts.map +0 -1
  603. package/dist/ui/side-sheet-css.generated.js +0 -4
  604. package/dist/ui/side-sheet-css.generated.js.map +0 -1
  605. package/dist/ui/side-sheet-css.js +0 -2
  606. package/dist/ui/side-sheet-css.js.map +0 -1
  607. package/dist/ui/surface-css.d.ts +0 -2
  608. package/dist/ui/surface-css.d.ts.map +0 -1
  609. package/dist/ui/surface-css.generated.d.ts +0 -2
  610. package/dist/ui/surface-css.generated.d.ts.map +0 -1
  611. package/dist/ui/surface-css.generated.js +0 -4
  612. package/dist/ui/surface-css.generated.js.map +0 -1
  613. package/dist/ui/surface-css.js +0 -7
  614. package/dist/ui/surface-css.js.map +0 -1
  615. package/dist/ui/table-logic.d.ts +0 -110
  616. package/dist/ui/table-logic.d.ts.map +0 -1
  617. package/dist/ui/table-logic.js +0 -81
  618. package/dist/ui/table-logic.js.map +0 -1
  619. package/dist/ui/table-shared.d.ts +0 -101
  620. package/dist/ui/table-shared.d.ts.map +0 -1
  621. package/dist/ui/table-shared.js +0 -229
  622. package/dist/ui/table-shared.js.map +0 -1
  623. package/dist/ui/thenable.d.ts +0 -9
  624. package/dist/ui/thenable.d.ts.map +0 -1
  625. package/dist/ui/thenable.js +0 -15
  626. package/dist/ui/thenable.js.map +0 -1
  627. package/dist/ui/ticker.d.ts +0 -8
  628. package/dist/ui/ticker.d.ts.map +0 -1
  629. package/dist/ui/ticker.js +0 -49
  630. package/dist/ui/ticker.js.map +0 -1
  631. package/dist/ui/toast-host.d.ts +0 -24
  632. package/dist/ui/toast-host.d.ts.map +0 -1
  633. package/dist/ui/toast-host.js +0 -20
  634. package/dist/ui/toast-host.js.map +0 -1
  635. package/dist/ui/tooltip.d.ts +0 -29
  636. package/dist/ui/tooltip.d.ts.map +0 -1
  637. package/dist/ui/tooltip.js +0 -10
  638. package/dist/ui/tooltip.js.map +0 -1
@@ -1,1133 +0,0 @@
1
- // 面板内只读会话弹窗(移植自兄弟项目 session-view.ts:决策 28 数据链 + 决策 34 渲染)。
2
- // 「官方零件 + 自绘容器」,组件按官方文件名一一对应放在 ./mirror/。
3
- //
4
- // 与兄弟项目版本的差异(定制剥离,见 worklog 20261022-1148):
5
- // · 不搬:顶部「接收/随附」输入区、outputs/processOutputs、ProcessFiles、标题任务名入口、
6
- // 冷读探测、/api/present.host 桌面可用性、U11 页面级预览 dock(core 用 onOpenFile 出口)。
7
- // · 交付卡数据源只取快照 turn 级 deliverables.presented 同源推导(不接任务 DB)。
8
- // · 新增:底部**暂存输入框**(期4 用户流程)——打字 → 确定 → onContinue(message),
9
- // 由调用方完成 fork + host 侧 agent.send 起轮次 + 跳官方视图(官方能力,无歪门邪道)。
10
- // · retain source 参数化在 open-session-view.ts。
11
- import { Fragment, createElement as h, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
12
- import { IconArchiveOutlineRegular, IconBranchOutlineRegular, IconNewChatOutlineRegular, MarkdownDelegateProvider } from '../ui/official.js';
13
- import { Modal } from '../ui/Modal.js';
14
- import { Button } from '../ui/Button.js';
15
- import { t as coreT } from '../utils/i18n.js';
16
- import { ChatHint, ChatNodeListMirror, ChatOlderButton, ChatViewFrame } from './mirror/ChatView.js';
17
- import { GenericCommandCard } from './mirror/GenericCommandCard.js';
18
- import { CommandCard } from './mirror/CommandCard.js';
19
- import { MessageIconActionsMirror } from './mirror/MessageIconActions.js';
20
- import { AssistantMarkdown, CompactionItemMirror, ModelRetryItemMirror, TurnErrorItemMirror, TurnMaxTokensItemMirror, UserMessage } from './mirror/MessageItem.js';
21
- import { BashRowMirror } from './mirror/BashRow.js';
22
- import { ContextInjectionRowMirror } from './mirror/ContextInjectionRow.js';
23
- import { ReasoningRowMirror } from './mirror/ReasoningRow.js';
24
- import { RunningStatusMirror } from './mirror/RunningStatus.js';
25
- import { TurnProcessNodeViewMirror } from './mirror/TurnProcessNodeView.js';
26
- import { buildTurnTailFacts, TurnTailNodeViewMirror } from './mirror/TurnTailNodeView.js';
27
- import { TurnTriggerNodeViewMirror } from './mirror/TurnTriggerNodeView.js';
28
- import { DeliverablesGridMirror, PresentRowMirror } from './mirror/Deliverables.js';
29
- import { ChangedFilesCard } from './mirror/ChangedFilesCard.js';
30
- import { turnDeliverablesChangesSeq, turnDeliverablesValue } from './changes.js';
31
- import { buildProcessGroups } from './mirror/process-groups.js';
32
- import { observedRpcIds, waitingUserRows } from './pending-inputs.js';
33
- import { officialClass, officialModuleCount } from './official-classes.js';
34
- import { t as defaultT } from '../utils/i18n.js';
35
- import { ensureComponentStyles } from '../ui/css.js';
36
- import { SESSION_CSS } from './session-css.js';
37
- import { createTailFollower } from './tail-follow.js';
38
- import { workspaceList } from '../ui/host-data.js';
39
- /** 稳定的空序列(避免默认值每次新建数组)。 */
40
- const EMPTY_ORDER = [];
41
- /** SSR / 数据面未接线时的归档态:如实按未归档,不编造。 */
42
- const NOT_ARCHIVED = () => false;
43
- /** SSR / 宿主未注册 inbox 投影时按能力缺席,不编造等待期消息。 */
44
- const NO_INBOX = () => undefined;
45
- /** 官方样式缺失告警只打一次(避免每次渲染刷屏)。 */
46
- let officialWarned = false;
47
- // ─────────────────────────── 纯函数:内容块 → 可读文本 / 文件 ───────────────────────────
48
- /** JSON 安全序列化(循环引用 / 特殊值不抛)。 */
49
- function safeJson(value) {
50
- try {
51
- return JSON.stringify(value, null, 2) ?? String(value);
52
- }
53
- catch {
54
- return String(value);
55
- }
56
- }
57
- /** 提取内容块的可读文本:text 拼接、图片占位(官方 ContentBlock 是 merge-extensible map)。 */
58
- function contentText(blocks) {
59
- if (blocks === undefined)
60
- return '';
61
- const parts = blocks.map((block) => {
62
- if (block !== null && typeof block === 'object' && block.type === 'text' && typeof block.text === 'string')
63
- return block.text;
64
- if (block !== null && typeof block === 'object' && block.type === 'image')
65
- return coreT('sessionImage');
66
- return '';
67
- }).filter(part => part !== '');
68
- return parts.join('\n');
69
- }
70
- /**
71
- * 提取内容块里的**官方 file 块**(2026-10-03 核实):随附文件以官方附件形式发进会话后,
72
- * 会话快照的 user 节点 content 里就是它 ⇒ 弹窗里照样渲染成附件卡(与官方页一致)。
73
- * 拿不到(宿主投影未透传)⇒ 空数组:附件卡不渲染,**绝不造一个假卡**。
74
- *
75
- * @returns `files` = 去重后要画的附件;`hadFiles` = 该轮**原本**有没有 file 块
76
- * (去重让位后可能为空 —— 调用方据此判断该轮要不要渲染,不能因为让位把整条消息吞掉)。
77
- */
78
- function contentFiles(blocks,
79
- /** 已解析出路径的文件名 ⇒ 这里让位,避免同一个文件同屏出现两次。 */
80
- exclude) {
81
- if (blocks === undefined)
82
- return { files: [], hadFiles: false };
83
- const out = [];
84
- let hadFiles = false;
85
- for (const block of blocks) {
86
- if (block === null || typeof block !== 'object' || block.type !== 'file')
87
- continue;
88
- const attachment = block.attachment;
89
- if (typeof attachment !== 'object' || attachment === null)
90
- continue;
91
- hadFiles = true;
92
- const name = typeof attachment.name === 'string' && attachment.name !== '' ? attachment.name : 'file';
93
- if (exclude?.has(name) === true)
94
- continue;
95
- out.push({ name, bytes: typeof attachment.bytes === 'number' ? attachment.bytes : 0 });
96
- }
97
- return { files: out, hadFiles };
98
- }
99
- /** legacy assistant 节点的纯文本(复制按钮用)。 */
100
- function assistantText(node) {
101
- return (node.blocks ?? []).map(block => block.kind === 'text' ? block.text : '').join('');
102
- }
103
- // ─────────────────────────── keyed 节点流的数据读取助手 ───────────────────────────
104
- /** keyed 节点的 data(官方 ChatNodeDataMap[kind])。 */
105
- function dataOf(node) {
106
- return node.data ?? {};
107
- }
108
- /** 节点位置 → turn 位置(官方 node.location 收窄,ChatNodeSeat.tsx:1660 的反向)。 */
109
- function turnLocationOf(node) {
110
- const location = node.location;
111
- return location?.kind === 'turn' || location?.kind === 'step' ? location.turn : undefined;
112
- }
113
- /** 官方 AssistantChatData.blocks(ui-chat contract/chat-nodes.d.ts:22)。 */
114
- function blocksOf(value) {
115
- return Array.isArray(value) ? value : undefined;
116
- }
117
- /**
118
- * 官方 ToolCallBlock(uic contract/records.d.ts:140)→ 工具卡 props。
119
- * running 半截(phase: preparing/start)只有 name/argsRaw;settled(kind: tool-result)带输出与错误。
120
- */
121
- function toolCallCard(node, t, onOpenFile) {
122
- const root = dataOf(node).root;
123
- if (root === undefined || root === null)
124
- return null;
125
- const settled = root.kind === 'tool-result';
126
- const call = settled ? root.call : root;
127
- const error = root.error;
128
- return {
129
- name: typeof call?.name === 'string' ? call.name : 'tool',
130
- argsRaw: typeof call?.argsRaw === 'string' ? call.argsRaw : '',
131
- output: settled ? contentText(root.content) : '',
132
- isError: root.isError === true,
133
- errorName: error?.name,
134
- meta: root.meta,
135
- settled,
136
- phase: settled ? undefined : root.phase === 'preparing' ? 'preparing' : 'start',
137
- interrupted: error?.code === 'interrupted',
138
- errorCode: error?.code,
139
- onOpenFile,
140
- t,
141
- };
142
- }
143
- /** 官方 Tool / ToolResult block 是否为 present 调用(交付文件行专属渲染;running 名在顶层,结算名在 call 里)。 */
144
- function isPresentRoot(root) {
145
- if (typeof root !== 'object' || root === null)
146
- return false;
147
- const r = root;
148
- if (r.name === 'present')
149
- return true;
150
- return r.kind === 'tool-result' && r.call !== null && typeof r.call === 'object' && r.call.name === 'present';
151
- }
152
- /** 官方 present 调用参数里的 files(deliverables/presented 事件同源数据)。 */
153
- function presentFiles(root) {
154
- if (typeof root !== 'object' || root === null)
155
- return [];
156
- const r = root;
157
- const settled = r.kind === 'tool-result';
158
- if (r.isError === true)
159
- return [];
160
- const raw = settled ? r.call?.argsRaw : r.argsRaw;
161
- if (typeof raw !== 'string')
162
- return [];
163
- try {
164
- const parsed = JSON.parse(raw);
165
- const files = parsed?.files;
166
- if (!Array.isArray(files))
167
- return [];
168
- const out = [];
169
- for (const file of files) {
170
- if (typeof file !== 'object' || file === null)
171
- continue;
172
- const path = file.path;
173
- if (typeof path !== 'string' || path.trim() === '')
174
- continue;
175
- const description = file.description;
176
- out.push(typeof description === 'string' && description.trim() !== '' ? { path, description } : { path });
177
- }
178
- return out;
179
- }
180
- catch {
181
- return [];
182
- }
183
- }
184
- /**
185
- * keyed 节点 → 视图(等价于官方 slot "conversation.chat.node" 的按 kind 分发)。
186
- * @param node - keyed ChatNode。
187
- * @param turnProcess - seat 下发的过程席位(turn-process / 折叠答案节点要用)。
188
- * @param t - 翻译席位。
189
- * @param onBranchAt - 消息行分支按钮(以该轮 tail seq 开分支;undefined = 不渲染按钮)。
190
- * @param fileOpen - 文件打开上下文(undefined = 链接全部降级为纯文本)。
191
- * @param groupPart - 过程分组侧('response' | 'reasoning')。
192
- * @returns 节点视图;null = 决策 28 过滤的噪音 kind。
193
- */
194
- function renderKeyedNode(node, turnProcess, t, onBranchAt, fileOpen, groupPart,
195
- /** 交付文件(快照 turn 级 deliverables.presented 同源推导);undefined/空 = 不渲染网格。 */
196
- deliverFiles,
197
- /** 最后一轮 turn-tail 的 turn 号:交付卡只挂在这里(官方 DeliverablesTail 位置 = 每轮收尾之后)。 */
198
- lastTailTurn,
199
- /** 最后一轮 `workspace/changes` 公告 seq:官方 ChangedFiles 卡挂这里;undefined = 本轮没改文件。 */
200
- changesSeq,
201
- /** 会话 id(ChangedFiles 卡拉宿主 changes.summary 路由要用)。 */
202
- sessionId,
203
- /** 变更文件点击出口(官方 openReview 等价):带改动身份;undefined = 变更卡不可点。 */
204
- onOpenReview,
205
- /** 官方 endsWithResponse / hasLaterChatNode(尾部操作行常显与分支可用性)。 */
206
- tailFacts) {
207
- switch (node.kind) {
208
- case 'turn-trigger':
209
- return h(TurnTriggerNodeViewMirror, { data: node.data, t });
210
- case 'turn-process':
211
- return turnProcess === undefined ? null : h(TurnProcessNodeViewMirror, {
212
- turn: turnLocationOf(node),
213
- turnProcess,
214
- t,
215
- });
216
- case 'turn-tail': {
217
- // 官方 turnTail 插槽(DeliverablesTail 同位):变更卡 + 交付卡网格都渲染在
218
- // TurnTailNodeView 的 tailSlot 里(操作行之前)——**顺序与官方 Deliverables 一致:
219
- // ChangedFiles 卡在前、presented 网格在后**(官方 lib/client.js:Fragment >
220
- // [ChangedFiles, Deliverables.root(网格)])。曾把变更卡挂到 tail 之后(操作行下方),
221
- // 与官方结构漂移且触发展示异常(真机 2026-10-23:卡内标题被切、计数拆行)。
222
- // 数据 = 快照 turn 级 deliverables.presented 同源推导,只挂最后一轮 tail。
223
- const data = node.data;
224
- const turn = data?.turn ?? turnLocationOf(node)?.turn;
225
- const atLastTail = turn !== undefined && lastTailTurn !== undefined && turn === lastTailTurn;
226
- const showGrid = deliverFiles !== undefined && deliverFiles.length > 0 && atLastTail;
227
- // 官方 ChangedFiles 卡(ui-deliverables):`workspace/changes` 公告 + 宿主
228
- // api/changes.summary ⇒ 「已编辑 x.md / +N -M」。数据不在快照里,单独拉(见 changes.ts)。
229
- const changesCard = atLastTail && changesSeq !== undefined && sessionId !== undefined
230
- ? h(ChangedFilesCard, { sessionId, seq: changesSeq, onOpenReview, t })
231
- : null;
232
- const tailSlot = changesCard === null && !showGrid
233
- ? null
234
- : h(Fragment, null, changesCard, showGrid ? h(DeliverablesGridMirror, { files: deliverFiles, onOpen: fileOpen?.open, t }) : null);
235
- const tail = data === undefined || data.closing === null || data.closing === undefined
236
- ? null
237
- : h(TurnTailNodeViewMirror, { data, onBranchAt, tailSlot, facts: tailFacts, t });
238
- return tail;
239
- }
240
- case 'assistant-step': {
241
- // 官方块渲染器(lib/client.js:5818-5871):
242
- // · 整步只有 tool-call 块 ⇒ 整步不渲染(工具调用由独立的 tool-call 节点画);
243
- // · tool-call 块一律跳过(case "tool-call": break)——重复渲染卡片即真机踩过的「编辑/写入×2」;
244
- // · groupPart 'reasoning' 只画思考块、'response' 跳过思考块;未分组全画(除工具块)。
245
- const nodeData = dataOf(node);
246
- const blocks = blocksOf(nodeData.blocks) ?? [];
247
- const streaming = nodeData.status === 'running';
248
- const interrupted = nodeData.status === 'interrupted';
249
- const contentBlocks = blocks.filter(block => block.kind !== 'tool-call');
250
- // 官方 AssistantMarkdown 提前返回:整步只有 tool-call(且非流式 / 非中断)⇒ 不渲染。
251
- if (!(streaming || interrupted || blocks.some(block => block.kind !== 'tool-call')))
252
- return null;
253
- const visible = groupPart === 'reasoning'
254
- ? contentBlocks.filter(block => block.kind === 'reasoning')
255
- : groupPart === 'response'
256
- ? contentBlocks.filter(block => block.kind !== 'reasoning')
257
- : contentBlocks;
258
- const parts = assistantBlocks(visible, t, fileOpen?.mentions, streaming);
259
- return parts.length === 0 ? null : h('div', { className: 'dshpc-sv-assistant' }, parts);
260
- }
261
- case 'tool-call': {
262
- // present(交付文件)走官方 tool.call.toolview 槽位 key='present' 的专属 PresentRow
263
- // (标题「交付文件」+ 状态词 + 路径列表;不经通用工具卡)。
264
- const root = dataOf(node).root;
265
- if (isPresentRoot(root))
266
- return h(PresentRowMirror, { block: root, t });
267
- const card = toolCallCard(node, t, fileOpen?.open);
268
- if (card === null)
269
- return null;
270
- // 官方 tool.call.toolview 槽位按工具名分派:bash / pwsh 走专属 BashRow(独立卡片,无 DisclosureRow)。
271
- return card.name === 'bash' || card.name === 'pwsh'
272
- ? h(BashRowMirror, card)
273
- : h(GenericCommandCard, card);
274
- }
275
- case 'command': {
276
- // 官方 CommandNodeView → GenericCommandCard(ui-chat/chat/GenericCommandCard.tsx 原样复刻)。
277
- // 斜杠命令生命周期节点(records.d.ts:name/args/outcome);走 CommandCard:标题=裸命令名、
278
- // 摘要=outcome 落定 text、仅多行才展开。之前漏接 ⇒ 落 default 显示「未支持的节点类型: command」。
279
- return h(CommandCard, { node: dataOf(node), t });
280
- }
281
- case 'user':
282
- case 'steering': {
283
- const blocks = dataOf(node).content;
284
- const text = contentText(blocks);
285
- // 随附文件(官方 file 块):没有文本但有附件时**照样渲染**(不能整条消失)。
286
- const { files, hadFiles } = contentFiles(blocks);
287
- if (text === '' && !hadFiles)
288
- return null;
289
- return h(UserMessage, {
290
- text,
291
- files,
292
- referenceLabels: dataOf(node).referenceLabels,
293
- skillNames: dataOf(node).skillNames,
294
- t,
295
- });
296
- }
297
- case 'turn-error':
298
- return h(TurnErrorItemMirror, { node: dataOf(node), t });
299
- case 'turn-max-tokens':
300
- return h(TurnMaxTokensItemMirror, { t });
301
- case 'model-retry': {
302
- // 官方 RetryNodeView(lib/client.js:1493):只画 data.current(链上最近一次尝试),
303
- // active = retryState === 'scheduled'。keyed 节点 data = { attempts, current };
304
- // 数据薄时兜底取 attempts 末项(与官方 buildViewNode 的 current 取法同构)。
305
- const data = dataOf(node);
306
- const attempts = Array.isArray(data.attempts) ? data.attempts : [];
307
- const current = (typeof data.current === 'object' && data.current !== null
308
- ? data.current
309
- : attempts[attempts.length - 1]);
310
- if (current === undefined)
311
- return null;
312
- return h(ModelRetryItemMirror, { node: current, active: current.retryState === 'scheduled', t });
313
- }
314
- // 决策 28:context(系统注入)/ unknown 仍默认过滤;
315
- // 0.2.x compaction 节点走官方 CompactionItem(此前漏渲染 ⇒ 压缩段整段消失)。
316
- case 'compaction':
317
- case 'manual-compaction':
318
- return h(CompactionItemMirror, { node: dataOf(node), t });
319
- case 'context':
320
- return h(ContextInjectionRowMirror, { node: dataOf(node), t });
321
- case 'unknown':
322
- return null;
323
- default:
324
- // 决策 28:不认识的 kind 一律 fallback(折叠原文),升级不白屏。
325
- return h('details', { className: 'dshpc-sv-tool' }, h('summary', { className: 'dshpc-sv-notice' }, `${t('sessionUnknownKind')} ${node.kind}`), h('pre', null, safeJson(node.data)));
326
- }
327
- }
328
- /**
329
- * assistant 内容块 → 子元素数组(官方块渲染器 lib/client.js:5826-5870 的同构):
330
- * text → 官方 MarkdownText、reasoning → 官方 ReasoningRow(标题「思考」)、image 占位;
331
- * tool-call 块一律跳过(官方 case "tool-call": break——由独立工具节点渲染,重复画 = ×2);
332
- * 未知块折叠原文。
333
- */
334
- function assistantBlocks(blocks, t, fileMentions,
335
- /** 官方 streaming(节点 data.status === 'running'):正文按流式尾渲染、末块思考行走 shimmer。 */
336
- streaming = false) {
337
- if (blocks === undefined)
338
- return [];
339
- const parts = [];
340
- const last = blocks.length - 1;
341
- blocks.forEach((block, index) => {
342
- switch (block.kind) {
343
- case 'text':
344
- if (block.text.trim() !== '') {
345
- parts.push(h(AssistantMarkdown, { key: `t${index}`, text: block.text, streaming, fileMentions }));
346
- }
347
- break;
348
- case 'reasoning':
349
- if (block.text.trim() !== '') {
350
- // 官方 running = streaming && i === last(原始块下标,不是过滤后的)。
351
- parts.push(h(ReasoningRowMirror, { key: `r${index}`, text: block.text, running: streaming && index === last, t }));
352
- }
353
- break;
354
- case 'image':
355
- parts.push(h('div', { key: `i${index}`, className: 'dshpc-sv-image' }, t('sessionImage')));
356
- break;
357
- case 'tool-call':
358
- break;
359
- default:
360
- // 未知 block:折叠原文,升级不白屏。
361
- parts.push(h('details', { key: `o${index}`, className: 'dshpc-sv-tool' }, h('summary', null, t('sessionUnknownKind')), h('pre', null, safeJson(block.block))));
362
- }
363
- });
364
- return parts;
365
- }
366
- // ─────────────────────────── legacy 兜底渲染(order 缺失时) ───────────────────────────
367
- /**
368
- * legacy 兜底渲染:官方兼容投影(老 kind 名)的单个节点;返回 null = 按决策 28 过滤的噪音 kind。
369
- * 仅在 keyed `order` 缺失时使用(正常路径见 renderKeyedNode)。
370
- */
371
- function renderLegacyNode(node, t, fileOpen) {
372
- switch (node.kind) {
373
- case 'user':
374
- case 'steering': {
375
- const text = contentText(node.content);
376
- const { files, hadFiles } = contentFiles(node.content);
377
- if (text === '' && !hadFiles)
378
- return null;
379
- return h(UserMessage, { key: node.seq, text, files, t });
380
- }
381
- case 'assistant': {
382
- const parts = assistantBlocks(node.blocks, t, fileOpen?.mentions);
383
- return parts.length === 0 ? null : h('div', { key: node.seq, className: 'dshpc-sv-assistant' }, parts);
384
- }
385
- case 'tool-result': {
386
- if (node.call?.name === 'present')
387
- return h(PresentRowMirror, { key: node.seq, block: node, t });
388
- return h(GenericCommandCard, {
389
- key: node.seq,
390
- name: node.call?.name ?? 'tool',
391
- argsRaw: node.call?.argsRaw ?? '',
392
- output: contentText(node.content),
393
- isError: node.isError === true,
394
- errorName: node.error?.name,
395
- meta: node.meta,
396
- settled: true,
397
- interrupted: node.error?.code === 'interrupted',
398
- onOpenFile: fileOpen?.open,
399
- t,
400
- });
401
- }
402
- case 'command': {
403
- return h(GenericCommandCard, {
404
- key: node.seq,
405
- name: `/${node.name ?? '?'}`,
406
- argsRaw: node.args ?? '',
407
- output: node.outcome?.text ?? '',
408
- isError: node.outcome?.kind === 'error',
409
- t,
410
- });
411
- }
412
- case 'turn-error':
413
- return h(TurnErrorItemMirror, { key: node.seq, node, t });
414
- case 'turn-max-tokens':
415
- return h(TurnMaxTokensItemMirror, { key: node.seq, t });
416
- case 'model-retry':
417
- // legacy 兼容投影的 model-retry = 单次尝试(ModelRetryNode 扁平节点)。
418
- return h(ModelRetryItemMirror, { key: node.seq, node, active: node.retryState === 'scheduled', t });
419
- // 决策 28:默认过滤的噪音 kind —— context(系统注入)、compaction(压缩标记)、
420
- // unknown(未知事件面)。assistant 里的 reasoning 由 mirror/ReasoningRow 折叠渲染。
421
- // ⚠ ui-map §十一-B:系统提示/上下文注入行(官方 ContextInjectionRow)待实施——届时从这里放行。
422
- case 'context':
423
- case 'compaction':
424
- case 'unknown':
425
- return null;
426
- default:
427
- // 决策 28:不认识的 kind 一律 fallback(折叠原文),升级不白屏。
428
- return h('details', { key: node.seq, className: 'dshpc-sv-tool' }, h('summary', { className: 'dshpc-sv-notice' }, `${t('sessionUnknownKind')} ${node.kind}`), h('pre', null, safeJson(node)));
429
- }
430
- }
431
- /**
432
- * 把连续的 tool-result / command 收成一个「过程」组——官方就是把工具调用折进
433
- * turn 的过程块(默认收起),页面才不会变成一列流水账。单个工具不再包组,避免多一层。
434
- */
435
- function groupNodes(list) {
436
- const out = [];
437
- let run = [];
438
- const flush = () => {
439
- if (run.length === 0)
440
- return;
441
- const only = run[0];
442
- if (only === undefined) {
443
- run = [];
444
- return;
445
- }
446
- if (run.length >= 2)
447
- out.push({ kind: 'process', nodes: run });
448
- else
449
- out.push({ kind: 'node', node: only });
450
- run = [];
451
- };
452
- for (const node of list) {
453
- if (node.kind === 'tool-result' || node.kind === 'command') {
454
- run.push(node);
455
- continue;
456
- }
457
- flush();
458
- out.push({ kind: 'node', node });
459
- }
460
- flush();
461
- return out;
462
- }
463
- /** legacy 兜底整流的渲染(keyed order 缺失时才会走到)。 */
464
- function renderLegacyRows(nodes, t, fileOpen) {
465
- const items = groupNodes(nodes);
466
- const rows = [];
467
- items.forEach((entry, index) => {
468
- const parts = [];
469
- if (entry.kind === 'process') {
470
- // legacy 兜底没有 turn 位置 ⇒ 拿不到官方「用时 N 秒」行,退回计数行。
471
- parts.push(h('div', { key: 'lead', className: 'dshpc-sv-notice' }, `${t('sessionProcess')} · ${entry.nodes.length}`));
472
- entry.nodes.forEach((node, i) => {
473
- const rendered = renderLegacyNode(node, t, fileOpen);
474
- if (rendered !== null)
475
- parts.push(h('div', { key: `p${i}` }, rendered));
476
- });
477
- }
478
- else {
479
- const inner = renderLegacyNode(entry.node, t, fileOpen);
480
- if (inner !== null)
481
- parts.push(inner);
482
- if (entry.node.kind === 'assistant') {
483
- const next = items[index + 1];
484
- const isTurnEnd = next === undefined || !(next.kind === 'node' && next.node.kind === 'assistant');
485
- if (isTurnEnd)
486
- parts.push(h(MessageIconActionsMirror, { key: 'act', text: assistantText(entry.node), clock: 'end', t }));
487
- }
488
- }
489
- if (parts.length === 0)
490
- return;
491
- rows.push(h('div', { key: `lg${index}`, className: officialClass('ChatView', 'flowItem') ?? '' }, parts));
492
- });
493
- return rows;
494
- }
495
- /** 路径归一:去 './' 前缀(词表键与 resolve 两侧同规则)。 */
496
- function normalizeFilePath(p) {
497
- let s = p.trim();
498
- while (s.startsWith('./'))
499
- s = s.slice(2);
500
- return s;
501
- }
502
- /** 交付文件词表 / 每轮交付卡的数据读取(真源 = 官方 TurnLocation.data,见 changes.ts)。 */
503
- function turnDeliverablesPresented(face) {
504
- const presented = turnDeliverablesValue(face, 'deliverables')?.presented;
505
- return Array.isArray(presented) ? presented : [];
506
- }
507
- /** 与 turnDeliverablesPresented 对称:读 turn 级 deliverables.produced(工具产出的文件)。
508
- * 官方 chatFileMentions = produced + presented;我们原先只收 presented,导致「只有 produced
509
- * 没有 present/get 参数」的会话里行内文件链接词表为空 —— 这里补齐(字段容错 path/name)。 */
510
- function turnDeliverablesProducedPaths(face) {
511
- const produced = turnDeliverablesValue(face, 'deliverables')?.produced;
512
- if (!Array.isArray(produced))
513
- return [];
514
- const out = [];
515
- for (const item of produced) {
516
- const p = typeof item === 'string' ? item
517
- : (item !== null && typeof item === 'object' ? (item.path ?? item.name) : undefined);
518
- if (typeof p === 'string' && p.trim() !== '')
519
- out.push(p);
520
- }
521
- return out;
522
- }
523
- /**
524
- * 从 keyed 节点流收集真实文件词表(禁模拟:全部来自工具调用参数 / meta.diffs):
525
- * tool-call 节点 argsRaw 的 file_path/path 字段(read/grep/glob/write/edit…)与
526
- * tool-fs 写入 meta.diffs[].path。会话级词表 = 官方 per-turn chatFileMentions 的简化偏差
527
- * (决策 39:resolve 命中才渲链接,解析不出保持惰性 code,永不猜)。
528
- */
529
- function collectFilePaths(order, store, turns) {
530
- if (store === undefined)
531
- return [];
532
- const out = new Set();
533
- // 交付文件(presented):会话 turn 级 deliverables.presented,同源覆盖 present 工具与插件代写。
534
- if (turns !== null && turns !== undefined) {
535
- const map = turns;
536
- for (const [, face] of map) {
537
- const presented = turnDeliverablesPresented(face);
538
- for (const file of presented) {
539
- const path = typeof file?.path === 'string' ? file.path : undefined;
540
- if (path !== undefined && path.trim() !== '')
541
- out.add(normalizeFilePath(path));
542
- }
543
- // 工具产出的文件(deliverables.produced)也进词表:官方 chatFileMentions = produced + presented。
544
- for (const p of turnDeliverablesProducedPaths(face))
545
- out.add(normalizeFilePath(p));
546
- }
547
- }
548
- for (const key of order) {
549
- const node = store.get(key);
550
- if (node === undefined || node.kind !== 'tool-call')
551
- continue;
552
- const root = node.data?.root;
553
- if (root === undefined || root === null || typeof root !== 'object')
554
- continue;
555
- if (isPresentRoot(root)) {
556
- // present(交付文件):files[].path 全进词表(官方 chatFileMentions 同源:produced + presented)。
557
- for (const file of presentFiles(root))
558
- out.add(normalizeFilePath(file.path));
559
- continue;
560
- }
561
- const call = (root.kind === 'tool-result' ? root.call : root);
562
- if (call === null || typeof call !== 'object')
563
- continue;
564
- const raw = typeof call.argsRaw === 'string' ? call.argsRaw.trim() : '';
565
- if (raw.startsWith('{')) {
566
- try {
567
- const parsed = JSON.parse(raw);
568
- for (const field of ['file_path', 'path']) {
569
- const value = parsed[field];
570
- if (typeof value === 'string' && value.trim() !== '')
571
- out.add(normalizeFilePath(value));
572
- }
573
- }
574
- catch { /* 非法 JSON 不进词表 */ }
575
- }
576
- const meta = root.meta;
577
- if (typeof meta === 'object' && meta !== null) {
578
- const diffs = meta.diffs;
579
- if (Array.isArray(diffs)) {
580
- for (const diff of diffs) {
581
- const p = diff?.path;
582
- if (typeof p === 'string' && p.trim() !== '')
583
- out.add(normalizeFilePath(p));
584
- }
585
- }
586
- }
587
- }
588
- return [...out];
589
- }
590
- /**
591
- * 每轮交付文件(官方 DeliverablesTail 同源数据):读会话 turn 级 `deliverables.presented`。
592
- * 按 turn 归组、按路径去重(后者覆盖前者,与官方 presentedForClosing 的 map 语义一致)。
593
- * 纯客户端推导,零额外请求。
594
- */
595
- function collectPresentedByTurn(turns) {
596
- const out = new Map();
597
- if (turns === null || turns === undefined)
598
- return out;
599
- const map = turns;
600
- for (const [key, face] of map) {
601
- const turn = typeof key === 'number' ? key : Number(key);
602
- if (!Number.isInteger(turn) || turn < 1)
603
- continue;
604
- const presented = turnDeliverablesPresented(face);
605
- if (presented.length === 0)
606
- continue;
607
- const files = [];
608
- for (const file of presented) {
609
- const path = typeof file?.path === 'string' ? file.path : undefined;
610
- if (path === undefined || path.trim() === '')
611
- continue;
612
- const description = typeof file?.description === 'string' && file.description.trim() !== '' ? file.description : undefined;
613
- files.push(description === undefined ? { path } : { path, description });
614
- }
615
- if (files.length > 0)
616
- out.set(turn, files);
617
- }
618
- return out;
619
- }
620
- /** 诊断:行内 code 命中真文件时记一行(去重 + 上限),确认 fileMentions 链路活着。 */
621
- const mentionLog = new Set();
622
- function logMentionHit(value, hit) {
623
- const key = `${value}\u0000${hit}`;
624
- if (mentionLog.has(key) || mentionLog.size >= 40)
625
- return;
626
- mentionLog.add(key);
627
- console.log('[preview] mention hit:', value, `→ ${hit}`);
628
- }
629
- /**
630
- * 从候选里挑一条真路径:同一个文件在词表里常有**多种写法**(工具参数是相对式
631
- * `2026Q4/1023/x.txt`,fs 改动事件是绝对式 `/workspace/Temp/2026Q4/1023/x.txt`)。
632
- * 判定 = 候选之间是否互为「尾段」(`longest.endsWith('/' + other)`)⇒ 是同一文件的两种写法,
633
- * 取**最长那条**(工作区根在 Temp,拿相对式去解析会落错根 ⇒ 必须给最完整的,否则预览报「文件不存在」);
634
- * 不是同一文件且不止一条 ⇒ 不可判定,返回 undefined(永不猜)。
635
- */
636
- function pickPath(candidates) {
637
- if (candidates === undefined || candidates.length === 0)
638
- return undefined;
639
- let longest = candidates[0];
640
- for (const p of candidates)
641
- if (p.length > longest.length)
642
- longest = p;
643
- const sameFile = candidates.every((p) => p === longest || longest.endsWith(`/${p}`));
644
- return sameFile ? longest : (candidates.length === 1 ? longest : undefined);
645
- }
646
- /**
647
- * 构建 fileMentions:按「路径尾段」匹配(词表里是绝对路径、markdown 里写的是工作区相对路径时,
648
- * 靠尾段对齐);同一文件的多种写法取最长那条(见 pickPath);不可判定 ⇒ undefined
649
- * ⇒ MarkdownText 保持惰性 code,永不猜。
650
- */
651
- function makeFileMentions(paths, open) {
652
- // 尾段索引:"a/b/c.txt" 同时登记 "a/b/c.txt" / "b/c.txt" / "c.txt"
653
- const bySuffix = new Map();
654
- for (const p of paths) {
655
- const norm = p.replace(/\\/g, '/');
656
- const parts = norm.split('/');
657
- for (let at = 0; at < parts.length; at++) {
658
- const key = parts.slice(at).join('/');
659
- const bucket = bySuffix.get(key);
660
- if (bucket === undefined)
661
- bySuffix.set(key, [norm]);
662
- else if (!bucket.includes(norm))
663
- bucket.push(norm);
664
- }
665
- }
666
- return {
667
- resolve(value) {
668
- const norm = normalizeFilePath(value).replace(/\\/g, '/');
669
- // 全路径本身也登记在尾段索引里(at=0),故只查一张表即可。
670
- const hit = pickPath(bySuffix.get(norm));
671
- // 未命中不打日志:官方对每个行内 code 都会问一次 resolve(含 `2026-10` 这类非文件值),全是噪音。
672
- if (hit === undefined)
673
- return undefined;
674
- logMentionHit(value, hit);
675
- return { label: value, title: hit, open: () => { open(hit); } };
676
- },
677
- };
678
- }
679
- /**
680
- * 面板内只读会话弹窗:只读、不可在框内续聊(底层 keyed 数组是只读快照,官方无写面)。
681
- * 续聊正道 = 头部「继续对话(开分支)」/ 消息行分支 icon(fork → openSession),
682
- * 以及底部暂存输入框(打字 → 确定 → onContinue 带话开分支并起轮次)。
683
- */
684
- export function SessionViewModal(props) {
685
- ensureComponentStyles('session', SESSION_CSS);
686
- const tt = props.t ?? defaultT;
687
- const { heading, sessionId, view, onClose, forkSession, openHostSession, onContinue, onOpenFile } = props;
688
- // 归档态唯一真源 = 官方 `workspaces.list` 快照的 archivedSessionIds(core 的 connectHost 已订阅
689
- // 同一条 follow 流)。弹窗开着期间归档 / 取消归档,徽标与「继续对话」即时跟随,调用方零接线。
690
- const archivedNow = useCallback(() => workspaceList.isSessionArchived(sessionId), [sessionId]);
691
- const isArchived = useSyncExternalStore(workspaceList.subscribe, archivedNow, NOT_ARCHIVED);
692
- const subscribe = useMemo(() => (onChange) => view.target.subscribe(onChange), [view]);
693
- const getSnapshot = useMemo(() => () => view.target.getSnapshot(), [view]);
694
- const chat = useSyncExternalStore(subscribe, getSnapshot);
695
- // 会话生命周期(加载态 / 向前翻页按钮),同样只读订阅。
696
- const sessionSub = useMemo(() => (onChange) => view.session.subscribe(onChange), [view]);
697
- const sessionGet = useMemo(() => () => view.session.getSnapshot(), [view]);
698
- const sessionSnap = useSyncExternalStore(sessionSub, sessionGet);
699
- // host `inbox` 投影(faceOf('inbox')):首轮 durable 事件落盘前用户消息的权威来源,
700
- // 冷读 / 新打开预览时也拿得到;本地回显被 retire 后靠它继续画气泡。
701
- const inboxSub = useMemo(() => (onChange) => view.inbox.subscribe(onChange), [view]);
702
- const inboxGet = useMemo(() => () => view.inbox.getSnapshot(), [view]);
703
- const inboxSnap = useSyncExternalStore(inboxSub, inboxGet, NO_INBOX);
704
- // 折叠状态:turn → 已展开的 answerStep(官方 store 的 storedTurnProcessEntry,同语义)。
705
- const [openTurns, setOpenTurns] = useState(() => new Map());
706
- const onSetOpen = useCallback((turn, answerStep, open) => {
707
- setOpenTurns((prev) => {
708
- const next = new Map(prev);
709
- if (open)
710
- next.set(turn, answerStep);
711
- else
712
- next.delete(turn);
713
- return next;
714
- });
715
- }, []);
716
- // 开分支:确认框显隐 + fork 进行中 + 失败原因。aliveRef 防「fork 在途时用户关弹窗」
717
- // 后仍跳转(await 回来时弹窗已卸载 ⇒ 放弃跳转,不 setState)。
718
- // 「继续对话」按归档状态分化(用户 2026-10-22 拍板):
719
- // 已归档 ⇒ 开分支图标 + 确认框(fork 出子会话再跳官方区;官方策略归档会话不进主视图)
720
- // 未归档 ⇒ 会话图标,点击直跳官方会话页(uiWorkspace.openSession,无确认)
721
- const canFork = forkSession !== undefined && openHostSession !== undefined;
722
- // 「继续对话」只在缺跳转出口时缺席;已归档同样保留按钮(图标变分支 + 开分支确认框),
723
- // 不能因为调用方没接 fork 能力就把按钮抹掉。能力缺席在确认框里如实呈现。
724
- const showContinue = openHostSession !== undefined;
725
- const [forkTarget, setForkTarget] = useState(null);
726
- const [forking, setForking] = useState(false);
727
- const [forkErr, setForkErr] = useState(null);
728
- const aliveRef = useRef(true);
729
- useEffect(() => () => { aliveRef.current = false; }, []);
730
- // 取消归档时收掉「因为归档才弹的」fork 确认框(atSeq 缺省 = 头部按钮触发);
731
- // 消息行分支确认框带 atSeq,fork 在途都不打断。
732
- useEffect(() => {
733
- if (!isArchived && !forking && forkTarget !== null && forkTarget.atSeq === undefined)
734
- setForkTarget(null);
735
- }, [isArchived, forking, forkTarget]);
736
- // 会话区自动贴底(用户 2026-11-04 二次拍板):只有「首次打开」和「有新内容且当时在底部」
737
- // 两种情况允许贴底。状态机是纯逻辑(tail-follow.ts):贴底只由**宿主快照内容版本变化**触发,
738
- // 不再由 ResizeObserver 的「高度变了」反推原因——展开 / 折叠思考行、历史分组是组件本地 state,
739
- // 只改 DOM 高度,不改 chat / sessionSnap,因此永远不会进这条链,视图不会被拽走。
740
- // scroll 事件只记录用户意图(往上滚 = 不跟),程序自己往下滚不会再触发追尾自激。
741
- const flowRef = useRef(null);
742
- const tailRef = useRef(null);
743
- const firstSnapRef = useRef(true);
744
- useLayoutEffect(() => {
745
- const flow = flowRef.current;
746
- const scroller = flow === null ? null : flow.closest('.dshpc-modal__body');
747
- if (scroller === null)
748
- return;
749
- const tail = createTailFollower({
750
- metrics: () => ({
751
- scrollTop: scroller.scrollTop,
752
- scrollHeight: scroller.scrollHeight,
753
- clientHeight: scroller.clientHeight,
754
- }),
755
- setScrollTop: (top) => { scroller.scrollTop = top; },
756
- frame: (fn) => requestAnimationFrame(fn),
757
- cancelFrame: (id) => cancelAnimationFrame(id),
758
- });
759
- tailRef.current = tail;
760
- const onScroll = () => { tail.scrolled(); };
761
- scroller.addEventListener('scroll', onScroll, { passive: true });
762
- tail.open(); // 首屏一把到底(instant)
763
- return () => {
764
- tail.dispose();
765
- tailRef.current = null;
766
- scroller.removeEventListener('scroll', onScroll);
767
- };
768
- }, []);
769
- // 唯一「有新内容」信号 = 宿主快照版本变化(chat / sessionSnap / inboxSnap 引用变了)。
770
- // pending 回显与 inbox 投影出现 / 消失也算(不来自 chat 快照)。首次挂载由 open() 负责。
771
- useLayoutEffect(() => {
772
- if (firstSnapRef.current) {
773
- firstSnapRef.current = false;
774
- return;
775
- }
776
- tailRef.current?.content();
777
- }, [chat, sessionSnap, inboxSnap]);
778
- const onForkAccept = useCallback(() => {
779
- if (forking || forkSession === undefined || openHostSession === undefined)
780
- return;
781
- setForking(true);
782
- setForkErr(null);
783
- void (async () => {
784
- try {
785
- const child = await forkSession(sessionId, forkTarget?.atSeq);
786
- if (!aliveRef.current)
787
- return;
788
- // 先关弹窗(dispose ⇒ release 源会话 scope),再跳宿主会话区(官方导航服务)。
789
- onClose();
790
- openHostSession(child);
791
- }
792
- catch (error) {
793
- if (!aliveRef.current)
794
- return;
795
- setForkErr(error instanceof Error ? error.message : String(error));
796
- }
797
- finally {
798
- if (aliveRef.current)
799
- setForking(false);
800
- }
801
- })();
802
- }, [forking, forkSession, openHostSession, sessionId, forkTarget, onClose]);
803
- // 消息行分支按钮(官方分支 icon 位置):从该轮 tail 消息截断开分支(同样先出确认框)。
804
- const onBranchAt = useCallback((seq) => {
805
- setForkErr(null);
806
- setForkTarget({ atSeq: seq });
807
- }, []);
808
- // 暂存输入框(期4):打字 → 确定 → onContinue(调用方 fork + host send + 跳转)。
809
- const [draft, setDraft] = useState('');
810
- const [sending, setSending] = useState(false);
811
- const [sendErr, setSendErr] = useState(null);
812
- const onSend = useCallback(() => {
813
- const message = draft.trim();
814
- if (sending || message === '' || onContinue === undefined)
815
- return;
816
- setSending(true);
817
- setSendErr(null);
818
- void (async () => {
819
- try {
820
- await onContinue(message);
821
- if (!aliveRef.current)
822
- return;
823
- setDraft('');
824
- }
825
- catch (error) {
826
- if (!aliveRef.current)
827
- return;
828
- setSendErr(error instanceof Error ? error.message : String(error));
829
- }
830
- finally {
831
- if (aliveRef.current)
832
- setSending(false);
833
- }
834
- })();
835
- }, [draft, sending, onContinue]);
836
- // 文件打开上下文:onOpenFile 就位即启用(工具卡 fileLink + md 行内 mention 共用单一入口)。
837
- // 透传本视图的 sessionId,使消费方在「文件所属会话」的正确作用域里打开,而非默认/全局锚点。
838
- const openFile = useCallback((path, options) => { onOpenFile?.(path, sessionId, options); }, [onOpenFile, sessionId]);
839
- const order = chat?.order ?? EMPTY_ORDER;
840
- const store = chat?.nodes;
841
- const keyed = order.length > 0 && store !== undefined;
842
- const turns = chat?.timeline?.turns;
843
- // 官方 ChatFlow 的 pendingRows(ui-chat 0.2.1-rc.5 lib/client.js:2815-2839 / 5686-5706):
844
- // 首轮 durable 事件落盘前,用户消息在 host `inbox` 投影与 session.pendingSubmissions
845
- // 本地回显里,order 里没有 user 节点 ⇒ 两路不补,新会话就只剩「深度求索中」看不到自己发的话。
846
- const observedRpc = useMemo(() => keyed && store !== undefined ? observedRpcIds(order, key => store.get(key)) : new Set(), [keyed, order, store]);
847
- const waitingRows = useMemo(() => waitingUserRows(inboxSnap, sessionSnap?.pendingSubmissions, observedRpc), [inboxSnap, sessionSnap, observedRpc]);
848
- const pendingRows = waitingRows.map(row => h(UserMessage, {
849
- key: row.key,
850
- text: row.text,
851
- files: row.files,
852
- pending: row.pending,
853
- echo: row.echo,
854
- t: tt,
855
- }));
856
- // markdown 行内文件词表(来自 keyed 工具流;onOpenFile 未就位 = 整个上下文不启用)。
857
- const fileOpen = useMemo(() => {
858
- if (onOpenFile === undefined)
859
- return undefined;
860
- return {
861
- open: openFile,
862
- mentions: makeFileMentions(collectFilePaths(order, store, turns), openFile),
863
- };
864
- }, [onOpenFile, openFile, order, store, turns]);
865
- /**
866
- * 官方 markdown **链接**的打开出口(`[名](<路径>)` ⇒ 官方 MarkdownFileLink)。
867
- * 与 `fileMentions`(管行内 code)是两条独立的路:官方只有 `openFile` 就位才把链接渲成
868
- * `fileMention fileLink` 按钮(lib/index.js:11819),否则退回纯文本。
869
- * markdown 里常写工作区相对路径(如 `2026Q4/1023/x.txt`),词表里是 `/workspace/…` 前缀的真路径,
870
- * 故先用同一个词表归一到真路径再交给调用方;词表里没有就原样给(不猜)。
871
- */
872
- const openDelegatedFile = useMemo(() => {
873
- if (fileOpen === undefined)
874
- return () => { };
875
- return (path) => {
876
- const hit = fileOpen.mentions.resolve(path);
877
- if (hit === undefined) {
878
- fileOpen.open(path);
879
- return;
880
- }
881
- hit.open();
882
- };
883
- }, [fileOpen]);
884
- // 每轮交付文件(会话 turn 级 deliverables.presented 同源推导)。
885
- const deliveredByTurn = useMemo(() => collectPresentedByTurn(turns), [turns]);
886
- const deliverFiles = useMemo(() => {
887
- const byPath = new Map();
888
- const add = (file) => {
889
- const key = file.path.trim();
890
- if (key === '' || byPath.has(key))
891
- return;
892
- byPath.set(key, file);
893
- };
894
- for (const files of deliveredByTurn.values())
895
- for (const file of files)
896
- add(file);
897
- return [...byPath.values()];
898
- }, [deliveredByTurn]);
899
- // 最后一轮 turn-tail 的 turn 号:交付卡只挂这里(官方 DeliverablesTail 位置 = 会话底部收尾之后)。
900
- const lastTailTurn = useMemo(() => {
901
- if (!keyed || store === undefined)
902
- return undefined;
903
- for (let i = order.length - 1; i >= 0; i--) {
904
- const key = order[i];
905
- if (key === undefined)
906
- continue;
907
- const node = store.get(key);
908
- if (node?.kind !== 'turn-tail')
909
- continue;
910
- const data = node.data;
911
- const turn = data?.turn ?? turnLocationOf(node)?.turn;
912
- if (typeof turn === 'number')
913
- return turn;
914
- }
915
- return undefined;
916
- }, [keyed, order, store]);
917
- // 全 turn 扫描 `workspace/changes` 公告 seq(取最高 turn 的,官方 changesForClosing 同源)⇒ 挂 ChangedFiles 卡。
918
- // 不再只看最后一轮 turn-tail:changes 事件往往写在"编辑那轮",而 turn-tail 落在更后面的收尾轮,
919
- // 只盯 lastTailTurn 会漏掉(真机「又没了」)。卡仍渲染在最后 turn-tail 位置(见 renderKeyedNode)。
920
- const lastTailChangesSeq = useMemo(() => {
921
- if (turns === null || turns === undefined)
922
- return undefined;
923
- const map = turns;
924
- let best = null;
925
- let bestTurn = -Infinity;
926
- for (const [key, face] of map) {
927
- const seq = turnDeliverablesChangesSeq(face);
928
- if (seq === null)
929
- continue;
930
- const t = typeof key === 'number' ? key : Number(key);
931
- if (!Number.isFinite(t) || t <= bestTurn)
932
- continue;
933
- bestTurn = t;
934
- best = seq;
935
- }
936
- return best ?? undefined;
937
- }, [turns]);
938
- // debug(临时):诊断变化卡 / 交付卡 / 行内链接的数据链到底缺在哪一环
939
- const diagChatRef = useRef(undefined);
940
- useEffect(() => {
941
- if (diagChatRef.current === chat)
942
- return;
943
- diagChatRef.current = chat;
944
- const turnsMap = turns;
945
- const face = turnsMap === undefined ? undefined : (turnsMap.get(lastTailTurn) ?? turnsMap.get(String(lastTailTurn)));
946
- const deliverables = face === undefined ? undefined : turnDeliverablesValue(face, 'deliverables');
947
- const mentionPaths = fileOpen === undefined ? undefined : collectFilePaths(order, store, turns);
948
- // 逐 turn 安全展开(不触碰 data.keys/get 内部:宿主 data 可能是带 get 方法的普通对象,
949
- // 调 .keys() 会崩;这里只走 turnDeliverablesValue 读 deliverables,逐条 try/catch 兜底)。
950
- const turnsDetail = turnsMap === undefined ? [] : [...turnsMap.entries()].map(([k, f]) => {
951
- try {
952
- const dv = f === undefined ? undefined : turnDeliverablesValue(f, 'deliverables');
953
- const changes = dv === undefined ? undefined : dv.changes;
954
- const produced = dv === undefined ? undefined : dv.produced;
955
- const presented = dv === undefined ? undefined : dv.presented;
956
- return {
957
- turn: k,
958
- deliverKeys: dv === undefined ? 'none' : (typeof dv === 'object' && !Array.isArray(dv) ? Object.keys(dv) : Array.isArray(dv) ? 'array' : 'non-object'),
959
- changesSeq: changes && typeof changes === 'object' && 'seq' in changes ? changes.seq : undefined,
960
- producedLen: Array.isArray(produced) ? produced.length : undefined,
961
- presentedLen: Array.isArray(presented) ? presented.length : undefined,
962
- };
963
- }
964
- catch {
965
- return { turn: k, error: true };
966
- }
967
- });
968
- console.log('[preview] diag', {
969
- hasChat: chat !== undefined,
970
- orderLen: order.length,
971
- turns: turnsMap === undefined ? 'undefined' : `Map(${turnsMap.size})`,
972
- turnKeySample: turnsMap === undefined ? [] : [...turnsMap.keys()].slice(0, 6),
973
- lastTailTurn,
974
- lastTailChangesSeq,
975
- deliverablesKeys: deliverables === undefined ? 'none' : Object.keys(deliverables),
976
- deliverFiles: deliverFiles.length,
977
- onOpenFile: onOpenFile !== undefined,
978
- mentionCount: mentionPaths === undefined ? 'no-fileOpen' : mentionPaths.length,
979
- mentionSample: mentionPaths === undefined ? [] : mentionPaths.slice(0, 6),
980
- });
981
- console.log('[preview] turnsDetail', turnsDetail);
982
- }, [chat, order, turns, lastTailTurn, lastTailChangesSeq, deliverFiles, onOpenFile, fileOpen, store]);
983
- // 官方 TurnTailNodeView 的两个判定(操作行常显 / 分支可用)——按 order + 节点仓预计算。
984
- const tailFacts = useMemo(() => (keyed && store !== undefined
985
- ? buildTurnTailFacts({ order, store, lastTurn: lastTailTurn })
986
- : undefined), [keyed, order, store, lastTailTurn]);
987
- const renderNode = useCallback((node, turnProcess, groupPart) => renderKeyedNode(node, turnProcess, tt, onBranchAt, fileOpen, groupPart, deliverFiles, lastTailTurn, lastTailChangesSeq, sessionId, props.onOpenReview, tailFacts), [tt, onBranchAt, fileOpen, deliverFiles, lastTailTurn, lastTailChangesSeq, sessionId, props.onOpenReview, tailFacts]);
988
- // 官方 grouped('chat'):把 keyed 流切成「独立条目 + 过程分组」(二级收折)。
989
- const isTurnClosed = useCallback((turn) => (turns?.get(turn) ?? turns?.get(String(turn)))?.status !== 'open', [turns]);
990
- const groupedView = useMemo(() => keyed ? buildProcessGroups(order, key => store?.get(key), isTurnClosed) : undefined, [keyed, order, store, isTurnClosed]);
991
- // 官方 RunningStatus(0.2.x)的 startTime:流末尾那个节点所属 turn 处于 open 时的开始时间
992
- // (ChatFlow lib/client.js:5645-5649)。没有 open turn ⇒ 不渲染这一行。
993
- const runningStartTime = useMemo(() => {
994
- if (!keyed || store === undefined)
995
- return undefined;
996
- const last = order[order.length - 1];
997
- const location = last === undefined ? undefined : store.get(last)?.location;
998
- if (location?.kind !== 'turn' && location?.kind !== 'step')
999
- return undefined;
1000
- return location.turn?.status === 'open' ? location.turn.start?.time : undefined;
1001
- }, [keyed, order, store]);
1002
- // ChatNodeList 直接调用(无 hook 的纯函数):它产出的是「flowItem 数组」,不是单个元素。
1003
- const rows = keyed
1004
- ? ChatNodeListMirror({
1005
- order,
1006
- store,
1007
- entries: groupedView?.entries,
1008
- groups: groupedView?.groups,
1009
- turns,
1010
- openState: openTurns,
1011
- onSetOpen,
1012
- // 官方 usePresentation(policy => policy.foldCompletedTurns):只读历史视图按「折叠已完成轮次」处理。
1013
- foldCompleted: true,
1014
- renderNode,
1015
- t: tt,
1016
- })
1017
- : renderLegacyRows(chat?.legacy?.nodes ?? [], tt, fileOpen);
1018
- const rendered = rows.filter((row) => row !== null && row !== undefined);
1019
- const officialCount = officialModuleCount();
1020
- if (!officialWarned) {
1021
- officialWarned = true;
1022
- console.info(`[dsh-plugin-core:session] 官方 ui-chat 模块数=${officialCount};类名样例 frame=${officialClass('ChatView', 'frame')} flowItem=${officialClass('ChatView', 'flowItem')} trigger=${officialClass('TurnTriggerNodeView', 'root')} turnProcess=${officialClass('TurnProcessNodeView', 'root')} tail=${officialClass('TurnTailNodeView', 'root')}`);
1023
- if (officialCount === 0) {
1024
- console.warn('[dsh-plugin-core:session] 未发现官方 ui-chat 样式模块 ⇒ 弹窗观感退回自绘样式(功能不受影响)');
1025
- }
1026
- }
1027
- const openState = sessionSnap?.openState;
1028
- const showLoadOlder = sessionSnap?.hasMore !== false;
1029
- // 官方 ChatFlow 的流末尾顺序 = rows → pendingRows → RunningStatus(lib/client.js:5703-5706);
1030
- // 运行态由 SessionSnapshot.running 决定(:5645/:5704),不是从 order 末尾节点反推。
1031
- const runningRow = sessionSnap?.running !== true
1032
- ? null
1033
- : h(RunningStatusMirror, { key: 'running', startTime: runningStartTime, t: tt });
1034
- const body = rendered.length === 0 && pendingRows.length === 0
1035
- ? [
1036
- h(ChatHint, {
1037
- key: 'hint',
1038
- text: openState === 'error' ? tt('sessionFailed')
1039
- : openState === 'loading' || openState === 'cold' ? tt('sessionLoading')
1040
- : tt('sessionEmpty'),
1041
- }),
1042
- runningRow,
1043
- ]
1044
- : [
1045
- showLoadOlder
1046
- ? h(ChatOlderButton, { key: 'older', label: tt('sessionLoadOlder'), onClick: () => { view.loadOlder(); } })
1047
- : null,
1048
- ...rendered,
1049
- ...pendingRows,
1050
- runningRow,
1051
- ];
1052
- const flowChildren = Array.isArray(body) ? body : [body];
1053
- // 外壳 = **核心 Modal**(size lg:min(1120px,100vw-32px) × calc(100%-80px),兄弟项目大弹窗同值);
1054
- // 「继续对话」与确认框按钮一律**核心 Button**,不就地自绘(用户 2026-10-22 拍板)。
1055
- // 会话中间部分 = mirror/ 官方 1:1 复刻(ChatViewFrame:官方类优先,缺失回退自绘)。
1056
- return h(Fragment, null, h(Modal, {
1057
- size: 'lg',
1058
- // 标题 = 调用方给的人话标题(可自定义);会话 id 是**标识**,放标题下方副标题行,不占正文
1059
- // (用户 2026-10-22:一串 MD5 不该出现在正文里)。
1060
- title: heading ?? tt('sessionHeading'),
1061
- subtitle: h(Fragment, null, h('span', null, sessionId),
1062
- // 可见探针:官方样式未命中时直接显示(省得翻控制台)。命中则不显示。
1063
- officialCount === 0
1064
- ? h('span', { className: 'dshpc-sv-probe' }, ' ⚠ ', tt('sessionProbeStyle'))
1065
- : null),
1066
- // 归档标识(官方归档图标 + 「已归档」)走头部右侧小块。
1067
- headerExtra: isArchived
1068
- ? h('span', { className: 'dshpc-sv-archived', title: tt('sessionArchived') }, h(IconArchiveOutlineRegular, { size: 12 }), tt('sessionArchived'))
1069
- : undefined,
1070
- // 「继续对话」:已归档 = 开分支图标 + 确认框;未归档 = 会话图标直跳官方会话页。
1071
- headerActions: showContinue
1072
- ? h(Button, {
1073
- variant: 'outline',
1074
- size: 'sm',
1075
- disabled: forking,
1076
- title: tt('continueBranch'),
1077
- icon: isArchived
1078
- ? h(IconBranchOutlineRegular, { size: 14 })
1079
- : h(IconNewChatOutlineRegular, { size: 14 }),
1080
- onClick: () => {
1081
- // 官方 openForkSource 判据:动作前读权威快照(client 内存,零远端 IO),
1082
- // 避免渲染与快照之间的竞态把已归档会话直开。
1083
- if (archivedNow()) {
1084
- setForkErr(null);
1085
- setForkTarget({});
1086
- }
1087
- else if (openHostSession !== undefined) {
1088
- onClose();
1089
- openHostSession(sessionId);
1090
- }
1091
- },
1092
- }, tt('continueBranch'))
1093
- : undefined,
1094
- onClose,
1095
- translate: tt,
1096
- // 底部暂存输入框走 footer(不随会话区滚动):打字 → 确定 → onContinue 带话开分支跳官方视图。
1097
- footer: onContinue === undefined ? undefined : h('div', { className: 'dshpc-sv-composer' }, h('textarea', {
1098
- value: draft,
1099
- placeholder: tt('composerPlaceholder'),
1100
- disabled: sending,
1101
- onChange: (event) => { setDraft(event.target.value); },
1102
- onKeyDown: (event) => {
1103
- if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
1104
- event.preventDefault();
1105
- onSend();
1106
- }
1107
- },
1108
- }), h(Button, {
1109
- variant: 'primary',
1110
- size: 'sm',
1111
- disabled: sending || draft.trim() === '',
1112
- onClick: onSend,
1113
- }, sending ? tt('forkWorking') : tt('confirm')), h('span', { className: 'dshpc-sv-composer-hint', title: tt('composerHint') }, '⌘/Ctrl + ↵'), sendErr !== null ? h('div', { className: 'dshpc-sv-forkerr' }, sendErr) : null),
1114
- }, h('div', { className: 'dshpc-sv', ref: flowRef },
1115
- // markdown 导航委托:挂上 openFile 后,正文里的本地文件链接才渲成官方
1116
- // `fileMention fileLink` 按钮(不挂 ⇒ 官方自己退回纯文本)。
1117
- fileOpen === undefined
1118
- ? h(ChatViewFrame, { children: flowChildren })
1119
- : h(MarkdownDelegateProvider, { openFile: openDelegatedFile }, h(ChatViewFrame, { children: flowChildren })))),
1120
- // 开分支确认框(用户拍板:必须先确认再 fork,防误点)——核心 Modal + Button。
1121
- forkTarget === null ? null : h(Modal, {
1122
- size: 'sm',
1123
- onClose: () => { if (!forking)
1124
- setForkTarget(null); },
1125
- title: tt('forkConfirmTitle'),
1126
- translate: tt,
1127
- footer: [
1128
- h(Button, { key: 'cancel', variant: 'outline', disabled: forking, onClick: () => { setForkTarget(null); } }, tt('cancel')),
1129
- h(Button, { key: 'accept', variant: 'primary', disabled: forking || !canFork, onClick: onForkAccept }, forking ? tt('forkWorking') : tt('forkConfirmAccept')),
1130
- ],
1131
- }, h('p', { className: 'dshpc-sv-forktext' }, tt('forkConfirmText')), canFork ? null : h('p', { className: 'dshpc-sv-forkerr' }, tt('forkUnavailable')), forkErr !== null ? h('p', { className: 'dshpc-sv-forkerr' }, tt('forkFailed', { error: forkErr })) : null));
1132
- }
1133
- //# sourceMappingURL=SessionViewModal.js.map