@stigmer/react 3.1.1 → 3.1.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 (426) hide show
  1. package/composer/SessionComposer.d.ts +24 -1
  2. package/composer/SessionComposer.d.ts.map +1 -1
  3. package/composer/SessionComposer.js +19 -8
  4. package/composer/SessionComposer.js.map +1 -1
  5. package/execution/ArtifactContentRenderer.d.ts +11 -1
  6. package/execution/ArtifactContentRenderer.d.ts.map +1 -1
  7. package/execution/ArtifactContentRenderer.js +39 -15
  8. package/execution/ArtifactContentRenderer.js.map +1 -1
  9. package/execution/FilePathContext.d.ts +8 -1
  10. package/execution/FilePathContext.d.ts.map +1 -1
  11. package/execution/FilePathContext.js.map +1 -1
  12. package/execution/FilePathLink.d.ts.map +1 -1
  13. package/execution/FilePathLink.js +21 -6
  14. package/execution/FilePathLink.js.map +1 -1
  15. package/execution/MessageEntry.d.ts +29 -0
  16. package/execution/MessageEntry.d.ts.map +1 -1
  17. package/execution/MessageEntry.js +29 -5
  18. package/execution/MessageEntry.js.map +1 -1
  19. package/execution/MessageThread.d.ts +76 -13
  20. package/execution/MessageThread.d.ts.map +1 -1
  21. package/execution/MessageThread.js +178 -24
  22. package/execution/MessageThread.js.map +1 -1
  23. package/execution/PlanArtifactCard.d.ts +27 -18
  24. package/execution/PlanArtifactCard.d.ts.map +1 -1
  25. package/execution/PlanArtifactCard.js +13 -23
  26. package/execution/PlanArtifactCard.js.map +1 -1
  27. package/execution/PlanDocumentMessage.d.ts +32 -0
  28. package/execution/PlanDocumentMessage.d.ts.map +1 -0
  29. package/execution/PlanDocumentMessage.js +37 -0
  30. package/execution/PlanDocumentMessage.js.map +1 -0
  31. package/execution/PlanStreamingCard.d.ts +45 -0
  32. package/execution/PlanStreamingCard.d.ts.map +1 -0
  33. package/execution/PlanStreamingCard.js +35 -0
  34. package/execution/PlanStreamingCard.js.map +1 -0
  35. package/execution/index.d.ts +5 -1
  36. package/execution/index.d.ts.map +1 -1
  37. package/execution/index.js +2 -0
  38. package/execution/index.js.map +1 -1
  39. package/execution/useCreateAgentExecution.d.ts +10 -0
  40. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  41. package/execution/useCreateAgentExecution.js +5 -1
  42. package/execution/useCreateAgentExecution.js.map +1 -1
  43. package/github/decodeGitHubContent.d.ts +29 -0
  44. package/github/decodeGitHubContent.d.ts.map +1 -0
  45. package/github/decodeGitHubContent.js +72 -0
  46. package/github/decodeGitHubContent.js.map +1 -0
  47. package/github/index.d.ts +1 -0
  48. package/github/index.d.ts.map +1 -1
  49. package/github/index.js +1 -0
  50. package/github/index.js.map +1 -1
  51. package/github/useGitHubFileReader.d.ts +26 -0
  52. package/github/useGitHubFileReader.d.ts.map +1 -0
  53. package/github/useGitHubFileReader.js +106 -0
  54. package/github/useGitHubFileReader.js.map +1 -0
  55. package/github/useGitHubTreeLister.d.ts.map +1 -1
  56. package/github/useGitHubTreeLister.js +6 -2
  57. package/github/useGitHubTreeLister.js.map +1 -1
  58. package/index.d.ts +9 -9
  59. package/index.d.ts.map +1 -1
  60. package/index.js +5 -5
  61. package/index.js.map +1 -1
  62. package/internal/ResizableSplit.d.ts +72 -22
  63. package/internal/ResizableSplit.d.ts.map +1 -1
  64. package/internal/ResizableSplit.js +96 -38
  65. package/internal/ResizableSplit.js.map +1 -1
  66. package/internal/VirtualizedThread.d.ts +5 -3
  67. package/internal/VirtualizedThread.d.ts.map +1 -1
  68. package/internal/VirtualizedThread.js +6 -4
  69. package/internal/VirtualizedThread.js.map +1 -1
  70. package/internal/file-icons/index.d.ts +17 -0
  71. package/internal/file-icons/index.d.ts.map +1 -0
  72. package/internal/file-icons/index.js +60 -0
  73. package/internal/file-icons/index.js.map +1 -0
  74. package/internal/file-tree/FileTreeNode.d.ts +18 -1
  75. package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
  76. package/internal/file-tree/FileTreeNode.js +11 -2
  77. package/internal/file-tree/FileTreeNode.js.map +1 -1
  78. package/internal/markdown-components.d.ts +38 -1
  79. package/internal/markdown-components.d.ts.map +1 -1
  80. package/internal/markdown-components.js +86 -11
  81. package/internal/markdown-components.js.map +1 -1
  82. package/{workflow → internal}/motion-preference.d.ts +7 -4
  83. package/internal/motion-preference.d.ts.map +1 -0
  84. package/{workflow → internal}/motion-preference.js +7 -4
  85. package/internal/motion-preference.js.map +1 -0
  86. package/internal/store/index.d.ts +33 -0
  87. package/internal/store/index.d.ts.map +1 -1
  88. package/internal/store/index.js +59 -0
  89. package/internal/store/index.js.map +1 -1
  90. package/internal/store/workspace-editors-store.d.ts +145 -0
  91. package/internal/store/workspace-editors-store.d.ts.map +1 -0
  92. package/internal/store/workspace-editors-store.js +208 -0
  93. package/internal/store/workspace-editors-store.js.map +1 -0
  94. package/internal/store/workspace-file-selection-store.d.ts +38 -0
  95. package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
  96. package/internal/store/workspace-file-selection-store.js +62 -0
  97. package/internal/store/workspace-file-selection-store.js.map +1 -0
  98. package/internal/useRevealLine.d.ts +49 -0
  99. package/internal/useRevealLine.d.ts.map +1 -0
  100. package/internal/useRevealLine.js +43 -0
  101. package/internal/useRevealLine.js.map +1 -0
  102. package/library/detect-plan-artifact.d.ts +21 -0
  103. package/library/detect-plan-artifact.d.ts.map +1 -1
  104. package/library/detect-plan-artifact.js +20 -0
  105. package/library/detect-plan-artifact.js.map +1 -1
  106. package/library/detect-streaming-plan.d.ts +45 -0
  107. package/library/detect-streaming-plan.d.ts.map +1 -0
  108. package/library/detect-streaming-plan.js +83 -0
  109. package/library/detect-streaming-plan.js.map +1 -0
  110. package/library/index.d.ts +4 -1
  111. package/library/index.d.ts.map +1 -1
  112. package/library/index.js +2 -1
  113. package/library/index.js.map +1 -1
  114. package/package.json +4 -4
  115. package/session/NewSessionViewer.d.ts +19 -4
  116. package/session/NewSessionViewer.d.ts.map +1 -1
  117. package/session/NewSessionViewer.js +52 -25
  118. package/session/NewSessionViewer.js.map +1 -1
  119. package/session/PlanEditor.d.ts +55 -0
  120. package/session/PlanEditor.d.ts.map +1 -0
  121. package/session/PlanEditor.js +88 -0
  122. package/session/PlanEditor.js.map +1 -0
  123. package/session/PlanStreamingDocument.d.ts +30 -0
  124. package/session/PlanStreamingDocument.d.ts.map +1 -0
  125. package/session/PlanStreamingDocument.js +37 -0
  126. package/session/PlanStreamingDocument.js.map +1 -0
  127. package/session/SessionPanelChip.d.ts +26 -0
  128. package/session/SessionPanelChip.d.ts.map +1 -0
  129. package/session/SessionPanelChip.js +40 -0
  130. package/session/SessionPanelChip.js.map +1 -0
  131. package/session/SessionViewer.d.ts +34 -7
  132. package/session/SessionViewer.d.ts.map +1 -1
  133. package/session/SessionViewer.js +315 -33
  134. package/session/SessionViewer.js.map +1 -1
  135. package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
  136. package/session/facets/ArtifactsTab.d.ts.map +1 -0
  137. package/session/{inspector → facets}/ArtifactsTab.js +8 -3
  138. package/session/facets/ArtifactsTab.js.map +1 -0
  139. package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
  140. package/session/facets/ChangesTab.d.ts.map +1 -0
  141. package/session/{inspector → facets}/ChangesTab.js +3 -3
  142. package/session/facets/ChangesTab.js.map +1 -0
  143. package/session/facets/InspectTab.d.ts.map +1 -0
  144. package/session/facets/InspectTab.js.map +1 -0
  145. package/session/{inspector → facets}/SetupTab.d.ts +11 -2
  146. package/session/facets/SetupTab.d.ts.map +1 -0
  147. package/session/{inspector → facets}/SetupTab.js +4 -3
  148. package/session/facets/SetupTab.js.map +1 -0
  149. package/session/{inspector → facets}/UsageTab.d.ts +1 -1
  150. package/session/facets/UsageTab.d.ts.map +1 -0
  151. package/session/{inspector → facets}/UsageTab.js +1 -1
  152. package/session/facets/UsageTab.js.map +1 -0
  153. package/session/{inspector → facets}/index.d.ts +0 -6
  154. package/session/facets/index.d.ts.map +1 -0
  155. package/session/{inspector → facets}/index.js +0 -3
  156. package/session/facets/index.js.map +1 -0
  157. package/session/index.d.ts +11 -2
  158. package/session/index.d.ts.map +1 -1
  159. package/session/index.js +15 -2
  160. package/session/index.js.map +1 -1
  161. package/session/plan-document.d.ts +9 -0
  162. package/session/plan-document.d.ts.map +1 -0
  163. package/session/plan-document.js +17 -0
  164. package/session/plan-document.js.map +1 -0
  165. package/session/useOpenFileChange.d.ts +20 -0
  166. package/session/useOpenFileChange.d.ts.map +1 -0
  167. package/session/useOpenFileChange.js +31 -0
  168. package/session/useOpenFileChange.js.map +1 -0
  169. package/session/usePlanDraft.d.ts +52 -0
  170. package/session/usePlanDraft.d.ts.map +1 -0
  171. package/session/usePlanDraft.js +63 -0
  172. package/session/usePlanDraft.js.map +1 -0
  173. package/session/useSessionConversation.d.ts +6 -0
  174. package/session/useSessionConversation.d.ts.map +1 -1
  175. package/session/useSessionConversation.js +1 -0
  176. package/session/useSessionConversation.js.map +1 -1
  177. package/session/useSessionPageFlow.d.ts.map +1 -1
  178. package/session/useSessionPageFlow.js +1 -0
  179. package/session/useSessionPageFlow.js.map +1 -1
  180. package/session/useSessionPanel.d.ts +120 -0
  181. package/session/useSessionPanel.d.ts.map +1 -0
  182. package/session/useSessionPanel.js +130 -0
  183. package/session/useSessionPanel.js.map +1 -0
  184. package/session/useSessionRailViews.d.ts +45 -0
  185. package/session/useSessionRailViews.d.ts.map +1 -0
  186. package/session/useSessionRailViews.js +105 -0
  187. package/session/useSessionRailViews.js.map +1 -0
  188. package/src/composer/SessionComposer.tsx +52 -10
  189. package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
  190. package/src/execution/ArtifactContentRenderer.tsx +101 -24
  191. package/src/execution/FilePathContext.tsx +8 -1
  192. package/src/execution/FilePathLink.tsx +22 -6
  193. package/src/execution/MessageEntry.tsx +111 -1
  194. package/src/execution/MessageThread.tsx +291 -36
  195. package/src/execution/PlanArtifactCard.tsx +63 -31
  196. package/src/execution/PlanDocumentMessage.tsx +96 -0
  197. package/src/execution/PlanStreamingCard.tsx +137 -0
  198. package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
  199. package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
  200. package/src/execution/__tests__/MessageThread.test.tsx +101 -0
  201. package/src/execution/__tests__/PlanArtifactCard.test.tsx +66 -12
  202. package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
  203. package/src/execution/__tests__/PlanStreamingCard.test.tsx +49 -0
  204. package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +504 -22
  205. package/src/execution/__tests__/message-entry.test.tsx +48 -0
  206. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
  207. package/src/execution/index.ts +7 -1
  208. package/src/execution/useCreateAgentExecution.ts +16 -1
  209. package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
  210. package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
  211. package/src/github/decodeGitHubContent.ts +83 -0
  212. package/src/github/index.ts +1 -0
  213. package/src/github/useGitHubFileReader.ts +152 -0
  214. package/src/github/useGitHubTreeLister.ts +6 -2
  215. package/src/index.ts +63 -9
  216. package/src/internal/ResizableSplit.tsx +184 -51
  217. package/src/internal/VirtualizedThread.tsx +12 -4
  218. package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
  219. package/src/internal/__tests__/markdown-components.test.tsx +68 -0
  220. package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
  221. package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
  222. package/src/internal/file-icons/index.tsx +137 -0
  223. package/src/internal/file-tree/FileTreeNode.tsx +43 -3
  224. package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
  225. package/src/internal/markdown-components.tsx +116 -11
  226. package/src/{workflow → internal}/motion-preference.ts +7 -4
  227. package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
  228. package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
  229. package/src/internal/store/index.ts +94 -0
  230. package/src/internal/store/workspace-editors-store.ts +315 -0
  231. package/src/internal/store/workspace-file-selection-store.ts +88 -0
  232. package/src/internal/useRevealLine.ts +81 -0
  233. package/src/library/__tests__/detect-plan-artifact.test.ts +48 -0
  234. package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
  235. package/src/library/detect-plan-artifact.ts +35 -0
  236. package/src/library/detect-streaming-plan.ts +108 -0
  237. package/src/library/index.ts +5 -0
  238. package/src/session/NewSessionViewer.tsx +123 -55
  239. package/src/session/PlanEditor.tsx +361 -0
  240. package/src/session/PlanStreamingDocument.tsx +97 -0
  241. package/src/session/SessionPanelChip.tsx +103 -0
  242. package/src/session/SessionViewer.tsx +617 -90
  243. package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
  244. package/src/session/__tests__/PlanEditor.test.tsx +217 -0
  245. package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
  246. package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
  247. package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +9 -4
  248. package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
  249. package/src/session/__tests__/audienceWiring.test.tsx +55 -19
  250. package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
  251. package/src/session/__tests__/usePlanDraft.test.ts +102 -0
  252. package/src/session/__tests__/useSessionPanel.test.ts +298 -0
  253. package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
  254. package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
  255. package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
  256. package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
  257. package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
  258. package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +35 -1
  259. package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
  260. package/src/session/{inspector → facets}/index.ts +0 -16
  261. package/src/session/index.ts +30 -13
  262. package/src/session/plan-document.ts +19 -0
  263. package/src/session/useOpenFileChange.ts +53 -0
  264. package/src/session/usePlanDraft.ts +109 -0
  265. package/src/session/useSessionConversation.ts +7 -0
  266. package/src/session/useSessionPageFlow.ts +1 -0
  267. package/src/session/useSessionPanel.ts +288 -0
  268. package/src/session/useSessionRailViews.tsx +200 -0
  269. package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
  270. package/src/workflow/index.ts +1 -1
  271. package/src/workflow/useFollowExecution.ts +1 -1
  272. package/src/workspace/EditorTabs.tsx +145 -0
  273. package/src/workspace/ExplorerTree.tsx +247 -0
  274. package/src/workspace/FileViewer.tsx +516 -0
  275. package/src/workspace/WorkspaceContentSearch.tsx +478 -0
  276. package/src/workspace/WorkspaceContentSearcher.ts +70 -0
  277. package/src/workspace/WorkspaceFileLister.ts +11 -0
  278. package/src/workspace/WorkspaceFileReader.ts +57 -0
  279. package/src/workspace/WorkspaceFileSearch.tsx +429 -0
  280. package/src/workspace/WorkspaceSurface.tsx +781 -0
  281. package/src/workspace/__tests__/EditorTabs.test.tsx +100 -0
  282. package/src/workspace/__tests__/ExplorerTree.test.tsx +152 -0
  283. package/src/workspace/__tests__/FileViewer.test.tsx +421 -0
  284. package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +196 -0
  285. package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +206 -0
  286. package/src/workspace/__tests__/WorkspaceSurface.test.tsx +348 -0
  287. package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
  288. package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
  289. package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
  290. package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
  291. package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
  292. package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
  293. package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
  294. package/src/workspace/findChangeForSelection.ts +61 -0
  295. package/src/workspace/index.ts +56 -2
  296. package/src/workspace/matchContentPreview.ts +51 -0
  297. package/src/workspace/matchWorkspaceFiles.ts +86 -0
  298. package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
  299. package/src/workspace/useWorkspaceContentSearch.ts +228 -0
  300. package/src/workspace/useWorkspaceFileContent.ts +129 -0
  301. package/src/workspace/useWorkspaceFileSearch.ts +184 -0
  302. package/src/workspace/useWorkspaceFiles.ts +27 -27
  303. package/src/workspace/workspaceListingCache.ts +93 -0
  304. package/styles.css +1 -1
  305. package/workflow/WorkflowExecutionGraph.js +1 -1
  306. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  307. package/workflow/index.d.ts +1 -1
  308. package/workflow/index.d.ts.map +1 -1
  309. package/workflow/index.js +1 -1
  310. package/workflow/index.js.map +1 -1
  311. package/workflow/useFollowExecution.js +1 -1
  312. package/workflow/useFollowExecution.js.map +1 -1
  313. package/workspace/EditorTabs.d.ts +29 -0
  314. package/workspace/EditorTabs.d.ts.map +1 -0
  315. package/workspace/EditorTabs.js +66 -0
  316. package/workspace/EditorTabs.js.map +1 -0
  317. package/workspace/ExplorerTree.d.ts +32 -0
  318. package/workspace/ExplorerTree.d.ts.map +1 -0
  319. package/workspace/ExplorerTree.js +45 -0
  320. package/workspace/ExplorerTree.js.map +1 -0
  321. package/workspace/FileViewer.d.ts +93 -0
  322. package/workspace/FileViewer.d.ts.map +1 -0
  323. package/workspace/FileViewer.js +182 -0
  324. package/workspace/FileViewer.js.map +1 -0
  325. package/workspace/WorkspaceContentSearch.d.ts +41 -0
  326. package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
  327. package/workspace/WorkspaceContentSearch.js +195 -0
  328. package/workspace/WorkspaceContentSearch.js.map +1 -0
  329. package/workspace/WorkspaceContentSearcher.d.ts +59 -0
  330. package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
  331. package/workspace/WorkspaceContentSearcher.js +7 -0
  332. package/workspace/WorkspaceContentSearcher.js.map +1 -0
  333. package/workspace/WorkspaceFileLister.d.ts +11 -0
  334. package/workspace/WorkspaceFileLister.d.ts.map +1 -1
  335. package/workspace/WorkspaceFileReader.d.ts +48 -0
  336. package/workspace/WorkspaceFileReader.d.ts.map +1 -0
  337. package/workspace/WorkspaceFileReader.js +11 -0
  338. package/workspace/WorkspaceFileReader.js.map +1 -0
  339. package/workspace/WorkspaceFileSearch.d.ts +32 -0
  340. package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
  341. package/workspace/WorkspaceFileSearch.js +155 -0
  342. package/workspace/WorkspaceFileSearch.js.map +1 -0
  343. package/workspace/WorkspaceSurface.d.ts +151 -0
  344. package/workspace/WorkspaceSurface.d.ts.map +1 -0
  345. package/workspace/WorkspaceSurface.js +184 -0
  346. package/workspace/WorkspaceSurface.js.map +1 -0
  347. package/workspace/findChangeForSelection.d.ts +19 -0
  348. package/workspace/findChangeForSelection.d.ts.map +1 -0
  349. package/workspace/findChangeForSelection.js +46 -0
  350. package/workspace/findChangeForSelection.js.map +1 -0
  351. package/workspace/index.d.ts +24 -2
  352. package/workspace/index.d.ts.map +1 -1
  353. package/workspace/index.js +13 -1
  354. package/workspace/index.js.map +1 -1
  355. package/workspace/matchContentPreview.d.ts +21 -0
  356. package/workspace/matchContentPreview.d.ts.map +1 -0
  357. package/workspace/matchContentPreview.js +36 -0
  358. package/workspace/matchContentPreview.js.map +1 -0
  359. package/workspace/matchWorkspaceFiles.d.ts +30 -0
  360. package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
  361. package/workspace/matchWorkspaceFiles.js +58 -0
  362. package/workspace/matchWorkspaceFiles.js.map +1 -0
  363. package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
  364. package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
  365. package/workspace/resolveWorkspaceFileSelection.js +115 -0
  366. package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
  367. package/workspace/useWorkspaceContentSearch.d.ts +69 -0
  368. package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
  369. package/workspace/useWorkspaceContentSearch.js +154 -0
  370. package/workspace/useWorkspaceContentSearch.js.map +1 -0
  371. package/workspace/useWorkspaceFileContent.d.ts +73 -0
  372. package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
  373. package/workspace/useWorkspaceFileContent.js +57 -0
  374. package/workspace/useWorkspaceFileContent.js.map +1 -0
  375. package/workspace/useWorkspaceFileSearch.d.ts +61 -0
  376. package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
  377. package/workspace/useWorkspaceFileSearch.js +119 -0
  378. package/workspace/useWorkspaceFileSearch.js.map +1 -0
  379. package/workspace/useWorkspaceFiles.d.ts +13 -5
  380. package/workspace/useWorkspaceFiles.d.ts.map +1 -1
  381. package/workspace/useWorkspaceFiles.js +18 -19
  382. package/workspace/useWorkspaceFiles.js.map +1 -1
  383. package/workspace/workspaceListingCache.d.ts +47 -0
  384. package/workspace/workspaceListingCache.d.ts.map +1 -0
  385. package/workspace/workspaceListingCache.js +55 -0
  386. package/workspace/workspaceListingCache.js.map +1 -0
  387. package/session/inspector/ArtifactsTab.d.ts.map +0 -1
  388. package/session/inspector/ArtifactsTab.js.map +0 -1
  389. package/session/inspector/ChangesTab.d.ts.map +0 -1
  390. package/session/inspector/ChangesTab.js.map +0 -1
  391. package/session/inspector/InspectTab.d.ts.map +0 -1
  392. package/session/inspector/InspectTab.js.map +0 -1
  393. package/session/inspector/SessionInspector.d.ts +0 -64
  394. package/session/inspector/SessionInspector.d.ts.map +0 -1
  395. package/session/inspector/SessionInspector.js +0 -53
  396. package/session/inspector/SessionInspector.js.map +0 -1
  397. package/session/inspector/SetupTab.d.ts.map +0 -1
  398. package/session/inspector/SetupTab.js.map +0 -1
  399. package/session/inspector/UsageTab.d.ts.map +0 -1
  400. package/session/inspector/UsageTab.js.map +0 -1
  401. package/session/inspector/WorkspaceTab.d.ts +0 -35
  402. package/session/inspector/WorkspaceTab.d.ts.map +0 -1
  403. package/session/inspector/WorkspaceTab.js +0 -75
  404. package/session/inspector/WorkspaceTab.js.map +0 -1
  405. package/session/inspector/index.d.ts.map +0 -1
  406. package/session/inspector/index.js.map +0 -1
  407. package/session/inspector/useSessionInspector.d.ts +0 -49
  408. package/session/inspector/useSessionInspector.d.ts.map +0 -1
  409. package/session/inspector/useSessionInspector.js +0 -122
  410. package/session/inspector/useSessionInspector.js.map +0 -1
  411. package/src/session/inspector/SessionInspector.tsx +0 -162
  412. package/src/session/inspector/WorkspaceTab.tsx +0 -245
  413. package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
  414. package/src/session/inspector/useSessionInspector.ts +0 -178
  415. package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
  416. package/workflow/motion-preference.d.ts.map +0 -1
  417. package/workflow/motion-preference.js.map +0 -1
  418. package/workspace/WorkspaceEntryFiles.d.ts +0 -22
  419. package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
  420. package/workspace/WorkspaceEntryFiles.js +0 -58
  421. package/workspace/WorkspaceEntryFiles.js.map +0 -1
  422. /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
  423. /package/session/{inspector → facets}/InspectTab.js +0 -0
  424. /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
  425. /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
  426. /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
@@ -31,8 +31,10 @@ import { FileReviewCard } from "./FileReviewCard.js";
31
31
  import { SummarizationCard } from "./SummarizationCard.js";
32
32
  import { PlanCompletionCard } from "./PlanCompletionCard.js";
33
33
  import { PlanArtifactCard } from "./PlanArtifactCard.js";
34
+ import { PlanStreamingCard } from "./PlanStreamingCard.js";
34
35
  import { TodoCard } from "./TodoCard.js";
35
36
  import { findPlanArtifact } from "../library/detect-plan-artifact.js";
37
+ import { findStreamingPlan } from "../library/detect-streaming-plan.js";
36
38
  import type { SummarizationEventView } from "./useContextWindow.js";
37
39
  import { isInternalTool, isCollapsedToolCall } from "./tool-categories.js";
38
40
  import { FilePathContext, type FilePathContextValue } from "./FilePathContext.js";
@@ -40,6 +42,10 @@ import type { ResolvedPathAction } from "./file-path-resolver.js";
40
42
  import { SandboxContext, type SandboxContextValue } from "./SandboxContext.js";
41
43
  import { ApprovalContext, type ApprovalContextValue } from "./ApprovalContext.js";
42
44
  import { FileReviewContext, type FileReviewContextValue } from "./FileReviewContext.js";
45
+ import {
46
+ extractLeadingH1,
47
+ unwrapEnclosingMarkdownFence,
48
+ } from "../internal/markdown-components.js";
43
49
  import { useRenderTracer, useKeyStability, useDomNodeCount, DevProfiler } from "../internal/dev/index.js";
44
50
  import { useAutoScroll } from "../internal/useAutoScroll.js";
45
51
  import { JumpToLatestButton } from "../internal/JumpToLatestButton.js";
@@ -172,7 +178,7 @@ export interface MessageThreadProps {
172
178
  readonly onFilePathClick?: (
173
179
  path: string,
174
180
  resolved: ResolvedPathAction,
175
- ) => void;
181
+ ) => boolean | void;
176
182
  /**
177
183
  * Absolute sandbox workspace root (e.g. `/home/daytona/workspace`).
178
184
  * When provided, shell commands and tool output normalize absolute
@@ -212,6 +218,21 @@ export interface MessageThreadProps {
212
218
  * compatible — existing consumers see no change.
213
219
  */
214
220
  readonly onBuildFromPlan?: () => void;
221
+ /**
222
+ * Opens a plan in the session panel's plan document tab — the side-by-side
223
+ * review/refine surface. Wired to EVERY plan card: the latest opens
224
+ * editable/buildable, a superseded plan opens read-only (the host decides
225
+ * from the execution id). When omitted, cards fall back to the "Open full"
226
+ * preview modal (hosts without a panel).
227
+ *
228
+ * Providing this also opts the thread into LIVE plan collapse: while a
229
+ * Plan-mode turn streams its plan (detected via `findStreamingPlan`), the
230
+ * plan message is suppressed behind a compact {@link PlanStreamingCard}
231
+ * whose "Open plan" routes here — the host is expected to render the
232
+ * streaming document in its plan surface. Hosts without one (this prop
233
+ * omitted) keep the plan streaming inline, where it stays readable.
234
+ */
235
+ readonly onOpenPlan?: (executionId: string) => void;
215
236
  /**
216
237
  * Organization slug. Required for the plan completion card's
217
238
  * "Review plan" action, which opens the shared artifact preview
@@ -225,18 +246,37 @@ export interface MessageThreadProps {
225
246
  * disabled submit.
226
247
  */
227
248
  readonly planActionsDisabled?: boolean;
249
+ /** True while the approved plan is being uploaded ahead of the build turn. */
250
+ readonly planBuildPending?: boolean;
228
251
  /**
229
- * Center thread content within a max-width reading column.
230
- *
231
- * When `true`, items are constrained to `max-w-3xl` (768 px) and
232
- * horizontally centered. The scroll container stays full-width so
233
- * the scrollbar remains at the viewport edge.
252
+ * Constrain thread content to a max-width reading column
253
+ * (`max-w-3xl`, 768 px) inside the full-width scroll container —
254
+ * the scrollbar stays at the viewport edge.
234
255
  *
235
- * Opt-in per DD-011 existing consumers see no layout change.
256
+ * - `"center"`column horizontally centered (classic chat reading view).
257
+ * - `"start"` — column anchored to the left edge, so the thread's left
258
+ * edge stays put when a sibling panel opens/closes beside it.
236
259
  *
237
- * @default false
260
+ * When omitted, content spans the full width. Opt-in per DD-011 —
261
+ * existing consumers see no layout change.
238
262
  */
239
- readonly centerContent?: boolean;
263
+ readonly contentColumn?: ThreadContentColumn;
264
+ }
265
+
266
+ /** Reading-column alignment for {@link MessageThread} content. */
267
+ export type ThreadContentColumn = "center" | "start";
268
+
269
+ /**
270
+ * Class set for the optional reading column — one definition shared by both
271
+ * render paths (non-virtualized and virtualized) so their geometry can never
272
+ * drift.
273
+ *
274
+ * @internal
275
+ */
276
+ export function threadContentColumnClass(
277
+ column: ThreadContentColumn | undefined,
278
+ ): string | false {
279
+ return column != null && cn("w-full max-w-3xl px-4", column === "center" && "mx-auto");
240
280
  }
241
281
 
242
282
  /**
@@ -249,7 +289,7 @@ export interface MessageThreadProps {
249
289
  * part of the public API.
250
290
  */
251
291
  export type ThreadItem =
252
- | { readonly kind: "message"; readonly message: AgentMessage; readonly key: string; readonly isPending?: boolean; readonly isFailed?: boolean; readonly isEditable?: boolean }
292
+ | { readonly kind: "message"; readonly message: AgentMessage; readonly key: string; readonly isPending?: boolean; readonly isFailed?: boolean; readonly isEditable?: boolean; readonly isPlanDocument?: boolean; readonly interactionMode?: InteractionMode; readonly isBuildFromPlan?: boolean }
253
293
  | { readonly kind: "tool-group"; readonly toolCalls: readonly ToolCall[]; readonly subAgentExecutions: readonly SubAgentExecution[]; readonly key: string }
254
294
  | { readonly kind: "sub-agent"; readonly subAgentExecution: SubAgentExecution; readonly key: string }
255
295
  | { readonly kind: "phase-badge"; readonly phase: ExecutionPhase; readonly key: string }
@@ -269,6 +309,36 @@ export type ThreadItem =
269
309
  readonly key: string;
270
310
  readonly executionId: string;
271
311
  readonly planArtifact?: ExecutionArtifact;
312
+ /**
313
+ * The plan's title (its leading `# H1`), lifted from the plan message at
314
+ * build time — no fetch. Present only when the turn published an
315
+ * artifact (the collapsed-card path); the card falls back to "Plan".
316
+ */
317
+ readonly planTitle?: string;
318
+ /**
319
+ * True for the most recent completed Plan execution in the thread — the
320
+ * only plan whose card carries the primary "Build from plan" action.
321
+ * Superseded plans keep their review actions (open/download) but never a
322
+ * build CTA, so a stale plan can't be implemented by accident.
323
+ */
324
+ readonly isLatestPlan: boolean;
325
+ }
326
+ | {
327
+ /**
328
+ * A plan the active Plan-mode execution is writing RIGHT NOW: the
329
+ * streaming plan message is suppressed and this compact card stands in
330
+ * while the document renders live in the panel's plan tab. On
331
+ * completion the item becomes `plan-completion` — a different kind
332
+ * under the SAME key, so the card holds one thread position and the
333
+ * swap reads as the card settling.
334
+ */
335
+ readonly kind: "plan-writing";
336
+ readonly key: string;
337
+ readonly executionId: string;
338
+ /** Live title (the plan's leading `# H1`), growing as it streams. */
339
+ readonly planTitle?: string;
340
+ /** Length of the plan text streamed so far (drives the live size). */
341
+ readonly planSize: number;
272
342
  };
273
343
 
274
344
  /**
@@ -295,6 +365,45 @@ function hasStartedResponding(execution: AgentExecution): boolean {
295
365
  });
296
366
  }
297
367
 
368
+ /**
369
+ * True for an execution that ran in Plan mode and completed — the only kind of
370
+ * execution that has a reviewable plan (streaming/failed/terminated Plan turns
371
+ * have nothing final to review or build from).
372
+ */
373
+ function isCompletedPlanExecution(execution: AgentExecution): boolean {
374
+ return (
375
+ execution.status?.phase === ExecutionPhase.EXECUTION_COMPLETED &&
376
+ execution.spec?.executionConfig?.interactionMode === InteractionMode.PLAN
377
+ );
378
+ }
379
+
380
+ /**
381
+ * Index of the message that IS the plan in a completed Plan execution: the
382
+ * last AI message with content — the SAME selection rule the runner's
383
+ * `extractFinalPlanText` uses to publish `plan.md`, so the message promoted to
384
+ * a document in the thread is byte-identical to the published artifact.
385
+ * Returns -1 when no such message exists.
386
+ */
387
+ function findPlanMessageIndex(messages: readonly AgentMessage[]): number {
388
+ for (let i = messages.length - 1; i >= 0; i--) {
389
+ const msg = messages[i];
390
+ if (msg.type === MessageType.MESSAGE_AI && msg.content.trim().length > 0) {
391
+ return i;
392
+ }
393
+ }
394
+ return -1;
395
+ }
396
+
397
+ /**
398
+ * The plan's title for its compact card: the leading `# H1` of the plan
399
+ * message, after the same plan-scoped bare-fence unwrap the document renderers
400
+ * apply — so the card and the plan tab always agree on the title. `undefined`
401
+ * when the plan has no H1 (the card falls back to "Plan").
402
+ */
403
+ function extractPlanTitle(content: string): string | undefined {
404
+ return extractLeadingH1(unwrapEnclosingMarkdownFence(content, true)).title ?? undefined;
405
+ }
406
+
298
407
  /**
299
408
  * Adds the tool-call ids that a sub-agent renders as nested rows (the same
300
409
  * non-internal AI tool calls {@link SubAgentSection} surfaces) to `target`,
@@ -397,6 +506,7 @@ export function buildThreadItems(
397
506
  pendingMessageFailed = false,
398
507
  editableActiveTurn = false,
399
508
  includeFileReviewRecords = false,
509
+ collapseStreamingPlan = false,
400
510
  ): ThreadItem[] {
401
511
  const items: ThreadItem[] = [];
402
512
  // Tool-call ids that render as an inline-approval-capable ToolCallItem (a
@@ -427,6 +537,17 @@ export function buildThreadItems(
427
537
  ? allExecutions.length - 1
428
538
  : -1;
429
539
 
540
+ // The most recent completed Plan execution owns the primary "Build from
541
+ // plan" action; every earlier plan renders as a review-only record. Resolved
542
+ // up front so each segment can stamp its own card with the right authority.
543
+ let latestPlanExecutionId: string | null = null;
544
+ for (let i = allExecutions.length - 1; i >= 0; i--) {
545
+ if (isCompletedPlanExecution(allExecutions[i])) {
546
+ latestPlanExecutionId = allExecutions[i].metadata?.id ?? `_e${i}`;
547
+ break;
548
+ }
549
+ }
550
+
430
551
  // Build a queue of summarization events to interleave by timestamp.
431
552
  // Events are consumed as messages pass their timestamp.
432
553
  const pendingEvents = summarizationEvents?.length
@@ -458,6 +579,44 @@ export function buildThreadItems(
458
579
  const messages = exec.status?.messages ?? [];
459
580
  const subAgents = exec.status?.subAgentExecutions ?? [];
460
581
 
582
+ // A completed Plan turn collapses its plan message into the compact plan
583
+ // card (the plan-completion item): the document lives in the panel's plan
584
+ // tab, not the thread. While the plan is still streaming, the same
585
+ // treatment applies live when the host has a plan surface (streamingPlan
586
+ // below): the in-flight plan message is suppressed behind a plan-writing
587
+ // card while the panel's plan tab renders it as it streams — the content
588
+ // moves, it doesn't disappear. Completion swaps the live card for the
589
+ // settled one (same key), and the paired auto-open (useSessionPanel's
590
+ // planKey trigger) keeps the document side-by-side. Collapse of a
591
+ // COMPLETED plan is gated on the ARTIFACT existing: a plan that never
592
+ // published (older executions, failed upload) exists only in the message,
593
+ // so that path keeps the inline document promotion (isPlanDocument) —
594
+ // collapsing it would orphan the plan behind a card with nothing to open.
595
+ const isCompletedPlanExec = isCompletedPlanExecution(exec);
596
+ const planMessageIndex = isCompletedPlanExec
597
+ ? findPlanMessageIndex(messages)
598
+ : -1;
599
+ const planArtifact = isCompletedPlanExec
600
+ ? findPlanArtifact(exec)
601
+ : undefined;
602
+ const collapsePlanMessage =
603
+ planMessageIndex >= 0 && planArtifact !== undefined;
604
+
605
+ // The plan the active Plan-mode turn is writing RIGHT NOW (detected by
606
+ // the H1 convention — see findStreamingPlan). Its message is suppressed
607
+ // in favor of a live plan-writing card, mirroring the completed-turn
608
+ // collapse above, while the panel's plan tab renders the document live.
609
+ // Two gates: collapseStreamingPlan (the host wired onOpenPlan — without a
610
+ // document surface the plan must keep streaming inline, DD-011) and
611
+ // isActiveStreamExec (a stale non-terminal execution left in the
612
+ // completed list by the transient skew documented above must never
613
+ // sprout a live card). Mutually exclusive with collapsePlanMessage by
614
+ // construction: one requires a terminal phase, the other forbids it.
615
+ const streamingPlan =
616
+ collapseStreamingPlan && isActiveStreamExec
617
+ ? findStreamingPlan(exec)
618
+ : undefined;
619
+
461
620
  // This execution's settled change sets render as read-only records inside
462
621
  // its own segment, anchored to the last stamped edit row of each set. The
463
622
  // display seam reads the server's live projection when present and folds
@@ -509,6 +668,13 @@ export function buildThreadItems(
509
668
  // The active execution's prompt is the one a user can edit-and-resubmit
510
669
  // (stop + rephrase). Only mark it when the consumer enabled editing.
511
670
  isEditable: isActiveStreamExec && editableActiveTurn,
671
+ // The turn's mode marks the prompt bubble (a "Plan" pill on Plan
672
+ // turns) so the transcript reads unambiguously after mode switches.
673
+ interactionMode: exec.spec?.executionConfig?.interactionMode,
674
+ // A Build-from-plan turn's prompt renders as a compact chip, not the
675
+ // message text — the text is a short label; the real instruction is
676
+ // runner-injected from the same flag.
677
+ isBuildFromPlan: exec.spec?.executionConfig?.buildFromPlan || undefined,
512
678
  });
513
679
  }
514
680
 
@@ -525,11 +691,23 @@ export function buildThreadItems(
525
691
  msg.type === MessageType.MESSAGE_AI && !msg.content.trim();
526
692
 
527
693
  if (!isEmptyAi) {
528
- items.push({
529
- kind: "message",
530
- message: msg,
531
- key: `${execId}-m${mi}`,
532
- });
694
+ // The collapsed plan message is not rendered — the plan-completion
695
+ // card at the segment's end is the turn's sole plan representation.
696
+ // Its tool calls (below) and the todo anchor still process normally.
697
+ // A STREAMING plan message is suppressed the same way: its stand-in
698
+ // is the plan-writing card at the segment's end, and the document
699
+ // renders live in the panel's plan tab.
700
+ const suppressAsPlan =
701
+ (collapsePlanMessage && mi === planMessageIndex) ||
702
+ mi === streamingPlan?.messageIndex;
703
+ if (!suppressAsPlan) {
704
+ items.push({
705
+ kind: "message",
706
+ message: msg,
707
+ key: `${execId}-m${mi}`,
708
+ isPlanDocument: !collapsePlanMessage && mi === planMessageIndex,
709
+ });
710
+ }
533
711
  // Anchor (1): the plan sits right under the agent's opening narration.
534
712
  if (
535
713
  msg.type === MessageType.MESSAGE_AI ||
@@ -609,6 +787,42 @@ export function buildThreadItems(
609
787
  }
610
788
  }
611
789
 
790
+ // A completed Plan turn closes its segment with the plan card — the
791
+ // compact stand-in for the collapsed plan message, carrying the title the
792
+ // message would have shown. Every plan stays reviewable forever; only the
793
+ // latest carries the build authority (isLatestPlan). A superseded plan
794
+ // that never published an artifact is skipped — with no artifact and no
795
+ // build CTA it would render an empty shell.
796
+ if (isCompletedPlanExec) {
797
+ const isLatestPlan = execId === latestPlanExecutionId;
798
+ if (planArtifact || isLatestPlan) {
799
+ items.push({
800
+ kind: "plan-completion",
801
+ key: `${execId}-plan-completion`,
802
+ executionId: exec.metadata?.id ?? "",
803
+ planArtifact,
804
+ planTitle: collapsePlanMessage
805
+ ? extractPlanTitle(messages[planMessageIndex].content)
806
+ : undefined,
807
+ isLatestPlan,
808
+ });
809
+ }
810
+ } else if (streamingPlan) {
811
+ // The live stand-in for the suppressed streaming plan message. It
812
+ // deliberately SHARES the completion item's key: on completion this
813
+ // item becomes the plan-completion item above (a kind change under a
814
+ // stable key), so the card holds one thread position and the handoff
815
+ // reads as the card settling rather than a new element appearing.
816
+ items.push({
817
+ kind: "plan-writing",
818
+ key: `${execId}-plan-completion`,
819
+ executionId: exec.metadata?.id ?? "",
820
+ planTitle:
821
+ extractLeadingH1(streamingPlan.displayText).title ?? undefined,
822
+ planSize: streamingPlan.displayText.length,
823
+ });
824
+ }
825
+
612
826
  // Anchor (3): a plan that produced no rendered narration or work item still
613
827
  // surfaces — never silently dropped.
614
828
  emitTodos();
@@ -692,17 +906,9 @@ export function buildThreadItems(
692
906
  }
693
907
  }
694
908
 
695
- if (
696
- lastPhase === ExecutionPhase.EXECUTION_COMPLETED &&
697
- lastExec?.spec?.executionConfig?.interactionMode === InteractionMode.PLAN
698
- ) {
699
- items.push({
700
- kind: "plan-completion",
701
- key: "plan-completion",
702
- executionId: lastExec?.metadata?.id ?? "",
703
- planArtifact: findPlanArtifact(lastExec),
704
- });
705
- }
909
+ // Plan cards are emitted inside each execution's segment (see the
910
+ // isCompletedPlanExec block in the loop above) — attached to their plan
911
+ // document, persistent across later turns, never appended at the tail.
706
912
 
707
913
  if (includeApprovals) {
708
914
  // Backstop only: an approval whose tool call renders inline shows its gate
@@ -794,17 +1000,23 @@ export function MessageThread({
794
1000
  summarizationEvents,
795
1001
  virtualized = false,
796
1002
  onBuildFromPlan,
1003
+ onOpenPlan,
797
1004
  org,
798
1005
  planActionsDisabled,
799
- centerContent = false,
1006
+ planBuildPending,
1007
+ contentColumn,
800
1008
  }: MessageThreadProps) {
801
1009
  useRenderTracer("MessageThread", { executions, activeStreamExecution });
802
1010
 
803
1011
  const includeApprovals = onApprovalSubmit != null;
804
1012
  const editableActiveTurn = onEditMessage != null;
1013
+ // A streaming plan is collapsed behind its live card only when the host can
1014
+ // open the plan document surface — a panel-less host (no onOpenPlan) keeps
1015
+ // the plan streaming inline, where it remains readable (DD-011).
1016
+ const collapseStreamingPlan = onOpenPlan != null;
805
1017
  const items = useMemo(
806
- () => buildThreadItems(executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn, showFileReviewRecords),
807
- [executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn, showFileReviewRecords],
1018
+ () => buildThreadItems(executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn, showFileReviewRecords, collapseStreamingPlan),
1019
+ [executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn, showFileReviewRecords, collapseStreamingPlan],
808
1020
  );
809
1021
 
810
1022
  useKeyStability(items);
@@ -889,9 +1101,11 @@ export function MessageThread({
889
1101
  fileReviewCtx={fileReviewCtx}
890
1102
  unresolvedApprovalCount={unresolvedApprovalCount}
891
1103
  onBuildFromPlan={onBuildFromPlan}
1104
+ onOpenPlan={onOpenPlan}
892
1105
  org={org}
893
1106
  planActionsDisabled={planActionsDisabled}
894
- centerContent={centerContent}
1107
+ planBuildPending={planBuildPending}
1108
+ contentColumn={contentColumn}
895
1109
  onRetrySend={onRetrySend}
896
1110
  onRetryExecution={onRetryExecution}
897
1111
  onEditMessage={onEditMessage}
@@ -905,7 +1119,7 @@ export function MessageThread({
905
1119
  <NonVirtualizedThread
906
1120
  items={items}
907
1121
  className={className}
908
- centerContent={centerContent}
1122
+ contentColumn={contentColumn}
909
1123
  formatToolCallSummary={formatToolCallSummary}
910
1124
  onApprovalSubmit={onApprovalSubmit}
911
1125
  submittingApprovalIds={submittingApprovalIds}
@@ -916,8 +1130,10 @@ export function MessageThread({
916
1130
  fileReviewCtx={fileReviewCtx}
917
1131
  unresolvedApprovalCount={unresolvedApprovalCount}
918
1132
  onBuildFromPlan={onBuildFromPlan}
1133
+ onOpenPlan={onOpenPlan}
919
1134
  org={org}
920
1135
  planActionsDisabled={planActionsDisabled}
1136
+ planBuildPending={planBuildPending}
921
1137
  onRetrySend={onRetrySend}
922
1138
  onRetryExecution={onRetryExecution}
923
1139
  onEditMessage={onEditMessage}
@@ -932,7 +1148,7 @@ export function MessageThread({
932
1148
  interface NonVirtualizedThreadProps {
933
1149
  readonly items: readonly ThreadItem[];
934
1150
  readonly className?: string;
935
- readonly centerContent?: boolean;
1151
+ readonly contentColumn?: ThreadContentColumn;
936
1152
  readonly formatToolCallSummary?: (toolCalls: readonly ToolCall[]) => string;
937
1153
  readonly onApprovalSubmit?: (
938
1154
  toolCallId: string,
@@ -947,8 +1163,11 @@ interface NonVirtualizedThreadProps {
947
1163
  readonly fileReviewCtx: FileReviewContextValue;
948
1164
  readonly unresolvedApprovalCount: number;
949
1165
  readonly onBuildFromPlan?: () => void;
1166
+ readonly onOpenPlan?: (executionId: string) => void;
950
1167
  readonly org?: string;
951
1168
  readonly planActionsDisabled?: boolean;
1169
+ /** True while the approved plan is being uploaded ahead of the build turn. */
1170
+ readonly planBuildPending?: boolean;
952
1171
  readonly onRetrySend?: () => void;
953
1172
  readonly onRetryExecution?: (message: string) => void;
954
1173
  readonly onEditMessage?: (text: string) => void;
@@ -957,7 +1176,7 @@ interface NonVirtualizedThreadProps {
957
1176
  function NonVirtualizedThread({
958
1177
  items,
959
1178
  className,
960
- centerContent,
1179
+ contentColumn,
961
1180
  formatToolCallSummary,
962
1181
  onApprovalSubmit,
963
1182
  submittingApprovalIds,
@@ -968,8 +1187,10 @@ function NonVirtualizedThread({
968
1187
  fileReviewCtx,
969
1188
  unresolvedApprovalCount,
970
1189
  onBuildFromPlan,
1190
+ onOpenPlan,
971
1191
  org,
972
1192
  planActionsDisabled,
1193
+ planBuildPending,
973
1194
  onRetrySend,
974
1195
  onRetryExecution,
975
1196
  onEditMessage,
@@ -999,7 +1220,7 @@ function NonVirtualizedThread({
999
1220
  <ApprovalContext.Provider value={approvalCtx}>
1000
1221
  <FileReviewContext.Provider value={fileReviewCtx}>
1001
1222
  <DevProfiler id="MessageThread">
1002
- <div ref={contentRef} className={cn("flex flex-col gap-4", centerContent && "mx-auto w-full max-w-3xl px-4")}>
1223
+ <div ref={contentRef} className={cn("flex flex-col gap-4", threadContentColumnClass(contentColumn))}>
1003
1224
  {items.map((item) => (
1004
1225
  <ThreadItemWrapper key={item.key} animate>
1005
1226
  <ThreadItemRenderer
@@ -1009,8 +1230,10 @@ function NonVirtualizedThread({
1009
1230
  submittingApprovalIds={submittingApprovalIds}
1010
1231
  approvalErrors={approvalErrors}
1011
1232
  onBuildFromPlan={onBuildFromPlan}
1233
+ onOpenPlan={onOpenPlan}
1012
1234
  org={org}
1013
1235
  planActionsDisabled={planActionsDisabled}
1236
+ planBuildPending={planBuildPending}
1014
1237
  onRetrySend={onRetrySend}
1015
1238
  onRetryExecution={onRetryExecution}
1016
1239
  onEditMessage={onEditMessage}
@@ -1061,8 +1284,11 @@ export interface ThreadItemRendererProps {
1061
1284
  readonly submittingApprovalIds?: ReadonlySet<string>;
1062
1285
  readonly approvalErrors?: ReadonlyMap<string, Error>;
1063
1286
  readonly onBuildFromPlan?: () => void;
1287
+ readonly onOpenPlan?: (executionId: string) => void;
1064
1288
  readonly org?: string;
1065
1289
  readonly planActionsDisabled?: boolean;
1290
+ /** True while the approved plan is being uploaded ahead of the build turn. */
1291
+ readonly planBuildPending?: boolean;
1066
1292
  readonly onRetrySend?: () => void;
1067
1293
  readonly onRetryExecution?: (message: string) => void;
1068
1294
  readonly onEditMessage?: (text: string) => void;
@@ -1086,8 +1312,10 @@ export function ThreadItemRenderer({
1086
1312
  submittingApprovalIds,
1087
1313
  approvalErrors,
1088
1314
  onBuildFromPlan,
1315
+ onOpenPlan,
1089
1316
  org,
1090
1317
  planActionsDisabled,
1318
+ planBuildPending,
1091
1319
  onRetrySend,
1092
1320
  onRetryExecution,
1093
1321
  onEditMessage,
@@ -1103,6 +1331,9 @@ export function ThreadItemRenderer({
1103
1331
  <MessageEntry
1104
1332
  message={item.message}
1105
1333
  className={item.isPending ? "opacity-70" : undefined}
1334
+ isPlanDocument={item.isPlanDocument}
1335
+ interactionMode={item.interactionMode}
1336
+ isBuildFromPlan={item.isBuildFromPlan}
1106
1337
  onEdit={
1107
1338
  item.isEditable && onEditMessage
1108
1339
  ? () => onEditMessage(item.message.content)
@@ -1167,20 +1398,44 @@ export function ThreadItemRenderer({
1167
1398
  // When the plan was published as an artifact, show the richer reviewable
1168
1399
  // card (preview / copy / download / implement). Otherwise fall back to the
1169
1400
  // bare Implement CTA (older executions, or a plan that failed to publish).
1401
+ // Only the latest plan receives the build action — a superseded plan's
1402
+ // card is review-only, so a stale plan can never be implemented from it.
1170
1403
  return item.planArtifact && item.executionId ? (
1171
1404
  <PlanArtifactCard
1172
1405
  executionId={item.executionId}
1173
1406
  artifact={item.planArtifact}
1407
+ title={item.planTitle}
1174
1408
  org={org}
1175
- onImplement={onBuildFromPlan}
1409
+ onImplement={item.isLatestPlan ? onBuildFromPlan : undefined}
1410
+ // Every card routes to the plan document tab — the host renders a
1411
+ // superseded plan read-only there (it receives the execution id).
1412
+ onOpenPlan={
1413
+ onOpenPlan
1414
+ ? () => onOpenPlan(item.executionId)
1415
+ : undefined
1416
+ }
1176
1417
  disabled={planActionsDisabled}
1418
+ buildPending={planBuildPending}
1177
1419
  />
1178
1420
  ) : (
1179
1421
  <PlanCompletionCard
1180
- onImplement={onBuildFromPlan}
1422
+ onImplement={item.isLatestPlan ? onBuildFromPlan : undefined}
1181
1423
  disabled={planActionsDisabled}
1182
1424
  />
1183
1425
  );
1426
+ case "plan-writing":
1427
+ // The live stand-in for a plan the active turn is writing. Emitted only
1428
+ // when onOpenPlan is wired (see buildThreadItems' collapseStreamingPlan
1429
+ // gate), so the action is always available in practice.
1430
+ return (
1431
+ <PlanStreamingCard
1432
+ title={item.planTitle}
1433
+ sizeBytes={item.planSize}
1434
+ onOpenPlan={
1435
+ onOpenPlan ? () => onOpenPlan(item.executionId) : undefined
1436
+ }
1437
+ />
1438
+ );
1184
1439
  }
1185
1440
  }
1186
1441