@stigmer/react 3.1.1 → 3.1.3

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 (483) hide show
  1. package/composer/SessionComposer.d.ts +25 -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/ArtifactPreviewModal.d.ts +5 -5
  10. package/execution/ArtifactPreviewModal.js +4 -4
  11. package/execution/ArtifactPreviewModal.js.map +1 -1
  12. package/execution/FileChangeProgressBar.d.ts +47 -0
  13. package/execution/FileChangeProgressBar.d.ts.map +1 -0
  14. package/execution/FileChangeProgressBar.js +49 -0
  15. package/execution/FileChangeProgressBar.js.map +1 -0
  16. package/execution/FileChangesView.d.ts.map +1 -1
  17. package/execution/FileChangesView.js +19 -4
  18. package/execution/FileChangesView.js.map +1 -1
  19. package/execution/FilePathContext.d.ts +8 -1
  20. package/execution/FilePathContext.d.ts.map +1 -1
  21. package/execution/FilePathContext.js.map +1 -1
  22. package/execution/FilePathLink.d.ts.map +1 -1
  23. package/execution/FilePathLink.js +21 -6
  24. package/execution/FilePathLink.js.map +1 -1
  25. package/execution/FileReviewAtoms.d.ts +27 -0
  26. package/execution/FileReviewAtoms.d.ts.map +1 -0
  27. package/execution/FileReviewAtoms.js +64 -0
  28. package/execution/FileReviewAtoms.js.map +1 -0
  29. package/execution/FileReviewCard.d.ts +2 -2
  30. package/execution/FileReviewCard.d.ts.map +1 -1
  31. package/execution/FileReviewCard.js +32 -62
  32. package/execution/FileReviewCard.js.map +1 -1
  33. package/execution/MessageEntry.d.ts +20 -0
  34. package/execution/MessageEntry.d.ts.map +1 -1
  35. package/execution/MessageEntry.js +19 -5
  36. package/execution/MessageEntry.js.map +1 -1
  37. package/execution/MessageThread.d.ts +75 -13
  38. package/execution/MessageThread.d.ts.map +1 -1
  39. package/execution/MessageThread.js +195 -27
  40. package/execution/MessageThread.js.map +1 -1
  41. package/execution/PlanArtifactCard.d.ts +36 -21
  42. package/execution/PlanArtifactCard.d.ts.map +1 -1
  43. package/execution/PlanArtifactCard.js +39 -25
  44. package/execution/PlanArtifactCard.js.map +1 -1
  45. package/execution/PlanCompletionCard.d.ts +4 -4
  46. package/execution/PlanCompletionCard.d.ts.map +1 -1
  47. package/execution/PlanCompletionCard.js +4 -4
  48. package/execution/PlanCompletionCard.js.map +1 -1
  49. package/execution/PlanDocumentMessage.d.ts +32 -0
  50. package/execution/PlanDocumentMessage.d.ts.map +1 -0
  51. package/execution/PlanDocumentMessage.js +37 -0
  52. package/execution/PlanDocumentMessage.js.map +1 -0
  53. package/execution/PlanStreamingCard.d.ts +50 -0
  54. package/execution/PlanStreamingCard.d.ts.map +1 -0
  55. package/execution/PlanStreamingCard.js +40 -0
  56. package/execution/PlanStreamingCard.js.map +1 -0
  57. package/execution/index.d.ts +9 -1
  58. package/execution/index.d.ts.map +1 -1
  59. package/execution/index.js +4 -0
  60. package/execution/index.js.map +1 -1
  61. package/execution/use-build-from-plan-hotkey.d.ts +1 -1
  62. package/execution/use-build-from-plan-hotkey.js +1 -1
  63. package/execution/useArtifactCopy.d.ts +51 -0
  64. package/execution/useArtifactCopy.d.ts.map +1 -0
  65. package/execution/useArtifactCopy.js +75 -0
  66. package/execution/useArtifactCopy.js.map +1 -0
  67. package/execution/useArtifactDownload.d.ts.map +1 -1
  68. package/execution/useArtifactDownload.js +17 -5
  69. package/execution/useArtifactDownload.js.map +1 -1
  70. package/execution/useCreateAgentExecution.d.ts +12 -0
  71. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  72. package/execution/useCreateAgentExecution.js +5 -1
  73. package/execution/useCreateAgentExecution.js.map +1 -1
  74. package/github/decodeGitHubContent.d.ts +29 -0
  75. package/github/decodeGitHubContent.d.ts.map +1 -0
  76. package/github/decodeGitHubContent.js +72 -0
  77. package/github/decodeGitHubContent.js.map +1 -0
  78. package/github/index.d.ts +1 -0
  79. package/github/index.d.ts.map +1 -1
  80. package/github/index.js +1 -0
  81. package/github/index.js.map +1 -1
  82. package/github/useGitHubFileReader.d.ts +26 -0
  83. package/github/useGitHubFileReader.d.ts.map +1 -0
  84. package/github/useGitHubFileReader.js +106 -0
  85. package/github/useGitHubFileReader.js.map +1 -0
  86. package/github/useGitHubTreeLister.d.ts.map +1 -1
  87. package/github/useGitHubTreeLister.js +6 -2
  88. package/github/useGitHubTreeLister.js.map +1 -1
  89. package/index.d.ts +9 -9
  90. package/index.d.ts.map +1 -1
  91. package/index.js +5 -5
  92. package/index.js.map +1 -1
  93. package/internal/ResizableSplit.d.ts +72 -22
  94. package/internal/ResizableSplit.d.ts.map +1 -1
  95. package/internal/ResizableSplit.js +96 -38
  96. package/internal/ResizableSplit.js.map +1 -1
  97. package/internal/VirtualizedThread.d.ts +5 -3
  98. package/internal/VirtualizedThread.d.ts.map +1 -1
  99. package/internal/VirtualizedThread.js +6 -4
  100. package/internal/VirtualizedThread.js.map +1 -1
  101. package/internal/file-icons/index.d.ts +17 -0
  102. package/internal/file-icons/index.d.ts.map +1 -0
  103. package/internal/file-icons/index.js +60 -0
  104. package/internal/file-icons/index.js.map +1 -0
  105. package/internal/file-tree/FileTreeNode.d.ts +18 -1
  106. package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
  107. package/internal/file-tree/FileTreeNode.js +11 -2
  108. package/internal/file-tree/FileTreeNode.js.map +1 -1
  109. package/internal/markdown-components.d.ts +38 -1
  110. package/internal/markdown-components.d.ts.map +1 -1
  111. package/internal/markdown-components.js +86 -11
  112. package/internal/markdown-components.js.map +1 -1
  113. package/{workflow → internal}/motion-preference.d.ts +7 -4
  114. package/internal/motion-preference.d.ts.map +1 -0
  115. package/{workflow → internal}/motion-preference.js +7 -4
  116. package/internal/motion-preference.js.map +1 -0
  117. package/internal/store/index.d.ts +33 -0
  118. package/internal/store/index.d.ts.map +1 -1
  119. package/internal/store/index.js +59 -0
  120. package/internal/store/index.js.map +1 -1
  121. package/internal/store/workspace-editors-store.d.ts +145 -0
  122. package/internal/store/workspace-editors-store.d.ts.map +1 -0
  123. package/internal/store/workspace-editors-store.js +208 -0
  124. package/internal/store/workspace-editors-store.js.map +1 -0
  125. package/internal/store/workspace-file-selection-store.d.ts +38 -0
  126. package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
  127. package/internal/store/workspace-file-selection-store.js +62 -0
  128. package/internal/store/workspace-file-selection-store.js.map +1 -0
  129. package/internal/useRevealLine.d.ts +49 -0
  130. package/internal/useRevealLine.d.ts.map +1 -0
  131. package/internal/useRevealLine.js +43 -0
  132. package/internal/useRevealLine.js.map +1 -0
  133. package/library/detect-plan-artifact.d.ts +43 -4
  134. package/library/detect-plan-artifact.d.ts.map +1 -1
  135. package/library/detect-plan-artifact.js +45 -5
  136. package/library/detect-plan-artifact.js.map +1 -1
  137. package/library/detect-streaming-plan.d.ts +45 -0
  138. package/library/detect-streaming-plan.d.ts.map +1 -0
  139. package/library/detect-streaming-plan.js +83 -0
  140. package/library/detect-streaming-plan.js.map +1 -0
  141. package/library/index.d.ts +4 -1
  142. package/library/index.d.ts.map +1 -1
  143. package/library/index.js +2 -1
  144. package/library/index.js.map +1 -1
  145. package/package.json +4 -4
  146. package/session/NewSessionViewer.d.ts +19 -4
  147. package/session/NewSessionViewer.d.ts.map +1 -1
  148. package/session/NewSessionViewer.js +52 -25
  149. package/session/NewSessionViewer.js.map +1 -1
  150. package/session/PlanEditor.d.ts +55 -0
  151. package/session/PlanEditor.d.ts.map +1 -0
  152. package/session/PlanEditor.js +88 -0
  153. package/session/PlanEditor.js.map +1 -0
  154. package/session/PlanStreamingDocument.d.ts +30 -0
  155. package/session/PlanStreamingDocument.d.ts.map +1 -0
  156. package/session/PlanStreamingDocument.js +37 -0
  157. package/session/PlanStreamingDocument.js.map +1 -0
  158. package/session/SessionPanelChip.d.ts +26 -0
  159. package/session/SessionPanelChip.d.ts.map +1 -0
  160. package/session/SessionPanelChip.js +40 -0
  161. package/session/SessionPanelChip.js.map +1 -0
  162. package/session/SessionViewer.d.ts +34 -7
  163. package/session/SessionViewer.d.ts.map +1 -1
  164. package/session/SessionViewer.js +334 -33
  165. package/session/SessionViewer.js.map +1 -1
  166. package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
  167. package/session/facets/ArtifactsTab.d.ts.map +1 -0
  168. package/session/{inspector → facets}/ArtifactsTab.js +8 -3
  169. package/session/facets/ArtifactsTab.js.map +1 -0
  170. package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
  171. package/session/facets/ChangesTab.d.ts.map +1 -0
  172. package/session/{inspector → facets}/ChangesTab.js +3 -3
  173. package/session/facets/ChangesTab.js.map +1 -0
  174. package/session/facets/InspectTab.d.ts.map +1 -0
  175. package/session/facets/InspectTab.js.map +1 -0
  176. package/session/{inspector → facets}/SetupTab.d.ts +11 -2
  177. package/session/facets/SetupTab.d.ts.map +1 -0
  178. package/session/{inspector → facets}/SetupTab.js +4 -3
  179. package/session/facets/SetupTab.js.map +1 -0
  180. package/session/{inspector → facets}/UsageTab.d.ts +1 -1
  181. package/session/facets/UsageTab.d.ts.map +1 -0
  182. package/session/{inspector → facets}/UsageTab.js +1 -1
  183. package/session/facets/UsageTab.js.map +1 -0
  184. package/session/{inspector → facets}/index.d.ts +0 -6
  185. package/session/facets/index.d.ts.map +1 -0
  186. package/session/{inspector → facets}/index.js +0 -3
  187. package/session/facets/index.js.map +1 -0
  188. package/session/index.d.ts +11 -2
  189. package/session/index.d.ts.map +1 -1
  190. package/session/index.js +15 -2
  191. package/session/index.js.map +1 -1
  192. package/session/plan-document.d.ts +21 -0
  193. package/session/plan-document.d.ts.map +1 -0
  194. package/session/plan-document.js +28 -0
  195. package/session/plan-document.js.map +1 -0
  196. package/session/useOpenFileChange.d.ts +20 -0
  197. package/session/useOpenFileChange.d.ts.map +1 -0
  198. package/session/useOpenFileChange.js +31 -0
  199. package/session/useOpenFileChange.js.map +1 -0
  200. package/session/usePlanDraft.d.ts +52 -0
  201. package/session/usePlanDraft.d.ts.map +1 -0
  202. package/session/usePlanDraft.js +63 -0
  203. package/session/usePlanDraft.js.map +1 -0
  204. package/session/useSessionConversation.d.ts +14 -1
  205. package/session/useSessionConversation.d.ts.map +1 -1
  206. package/session/useSessionConversation.js +20 -2
  207. package/session/useSessionConversation.js.map +1 -1
  208. package/session/useSessionPageFlow.d.ts.map +1 -1
  209. package/session/useSessionPageFlow.js +1 -0
  210. package/session/useSessionPageFlow.js.map +1 -1
  211. package/session/useSessionPanel.d.ts +120 -0
  212. package/session/useSessionPanel.d.ts.map +1 -0
  213. package/session/useSessionPanel.js +130 -0
  214. package/session/useSessionPanel.js.map +1 -0
  215. package/session/useSessionRailViews.d.ts +45 -0
  216. package/session/useSessionRailViews.d.ts.map +1 -0
  217. package/session/useSessionRailViews.js +105 -0
  218. package/session/useSessionRailViews.js.map +1 -0
  219. package/src/composer/SessionComposer.tsx +53 -10
  220. package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
  221. package/src/execution/ArtifactContentRenderer.tsx +101 -24
  222. package/src/execution/ArtifactPreviewModal.tsx +9 -9
  223. package/src/execution/FileChangeProgressBar.tsx +121 -0
  224. package/src/execution/FileChangesView.tsx +18 -4
  225. package/src/execution/FilePathContext.tsx +8 -1
  226. package/src/execution/FilePathLink.tsx +22 -6
  227. package/src/execution/FileReviewAtoms.tsx +89 -0
  228. package/src/execution/FileReviewCard.tsx +57 -90
  229. package/src/execution/MessageEntry.tsx +49 -1
  230. package/src/execution/MessageThread.tsx +308 -39
  231. package/src/execution/PlanArtifactCard.tsx +174 -64
  232. package/src/execution/PlanCompletionCard.tsx +5 -5
  233. package/src/execution/PlanDocumentMessage.tsx +96 -0
  234. package/src/execution/PlanStreamingCard.tsx +141 -0
  235. package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
  236. package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +6 -6
  237. package/src/execution/__tests__/FileChangeProgressBar.test.tsx +125 -0
  238. package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
  239. package/src/execution/__tests__/FileReviewCard.test.tsx +66 -7
  240. package/src/execution/__tests__/MessageThread.test.tsx +102 -1
  241. package/src/execution/__tests__/PlanArtifactCard.test.tsx +114 -26
  242. package/src/execution/__tests__/PlanCompletionCard.test.tsx +2 -2
  243. package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
  244. package/src/execution/__tests__/PlanStreamingCard.test.tsx +56 -0
  245. package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +600 -22
  246. package/src/execution/__tests__/message-entry.test.tsx +17 -0
  247. package/src/execution/__tests__/useArtifactCopy.test.tsx +90 -0
  248. package/src/execution/__tests__/useArtifactDownload.test.tsx +2 -0
  249. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
  250. package/src/execution/index.ts +13 -1
  251. package/src/execution/use-build-from-plan-hotkey.ts +1 -1
  252. package/src/execution/useArtifactCopy.ts +109 -0
  253. package/src/execution/useArtifactDownload.ts +17 -5
  254. package/src/execution/useCreateAgentExecution.ts +18 -1
  255. package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
  256. package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
  257. package/src/github/decodeGitHubContent.ts +83 -0
  258. package/src/github/index.ts +1 -0
  259. package/src/github/useGitHubFileReader.ts +152 -0
  260. package/src/github/useGitHubTreeLister.ts +6 -2
  261. package/src/index.ts +69 -9
  262. package/src/internal/ResizableSplit.tsx +184 -51
  263. package/src/internal/VirtualizedThread.tsx +12 -4
  264. package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
  265. package/src/internal/__tests__/markdown-components.test.tsx +68 -0
  266. package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
  267. package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
  268. package/src/internal/file-icons/index.tsx +137 -0
  269. package/src/internal/file-tree/FileTreeNode.tsx +56 -5
  270. package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
  271. package/src/internal/markdown-components.tsx +116 -11
  272. package/src/{workflow → internal}/motion-preference.ts +7 -4
  273. package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
  274. package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
  275. package/src/internal/store/index.ts +94 -0
  276. package/src/internal/store/workspace-editors-store.ts +315 -0
  277. package/src/internal/store/workspace-file-selection-store.ts +88 -0
  278. package/src/internal/useRevealLine.ts +81 -0
  279. package/src/library/__tests__/detect-plan-artifact.test.ts +69 -0
  280. package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
  281. package/src/library/detect-plan-artifact.ts +62 -5
  282. package/src/library/detect-streaming-plan.ts +108 -0
  283. package/src/library/index.ts +7 -0
  284. package/src/session/NewSessionViewer.tsx +123 -55
  285. package/src/session/PlanEditor.tsx +361 -0
  286. package/src/session/PlanStreamingDocument.tsx +97 -0
  287. package/src/session/SessionPanelChip.tsx +103 -0
  288. package/src/session/SessionViewer.tsx +655 -96
  289. package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
  290. package/src/session/__tests__/PlanEditor.test.tsx +217 -0
  291. package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
  292. package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
  293. package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +66 -4
  294. package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
  295. package/src/session/__tests__/audienceWiring.test.tsx +55 -19
  296. package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
  297. package/src/session/__tests__/usePlanDraft.test.ts +102 -0
  298. package/src/session/__tests__/useSessionConversation.test.tsx +44 -0
  299. package/src/session/__tests__/useSessionPanel.test.ts +298 -0
  300. package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
  301. package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
  302. package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
  303. package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
  304. package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
  305. package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +42 -8
  306. package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
  307. package/src/session/{inspector → facets}/index.ts +0 -16
  308. package/src/session/index.ts +30 -13
  309. package/src/session/plan-document.ts +30 -0
  310. package/src/session/useOpenFileChange.ts +53 -0
  311. package/src/session/usePlanDraft.ts +109 -0
  312. package/src/session/useSessionConversation.ts +38 -3
  313. package/src/session/useSessionPageFlow.ts +1 -0
  314. package/src/session/useSessionPanel.ts +288 -0
  315. package/src/session/useSessionRailViews.tsx +200 -0
  316. package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
  317. package/src/workflow/index.ts +1 -1
  318. package/src/workflow/useFollowExecution.ts +1 -1
  319. package/src/workspace/EditorTabs.tsx +174 -0
  320. package/src/workspace/ExplorerTree.tsx +253 -0
  321. package/src/workspace/FileViewer.tsx +537 -0
  322. package/src/workspace/WorkspaceContentSearch.tsx +502 -0
  323. package/src/workspace/WorkspaceContentSearcher.ts +70 -0
  324. package/src/workspace/WorkspaceEditor.tsx +19 -16
  325. package/src/workspace/WorkspaceFileLister.ts +11 -0
  326. package/src/workspace/WorkspaceFileReader.ts +57 -0
  327. package/src/workspace/WorkspaceFileSearch.tsx +452 -0
  328. package/src/workspace/WorkspaceSurface.tsx +839 -0
  329. package/src/workspace/__tests__/EditorTabs.test.tsx +102 -0
  330. package/src/workspace/__tests__/ExplorerTree.test.tsx +204 -0
  331. package/src/workspace/__tests__/FileViewer.test.tsx +439 -0
  332. package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +229 -0
  333. package/src/workspace/__tests__/WorkspaceEditor-initialPanel.test.tsx +19 -0
  334. package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +227 -0
  335. package/src/workspace/__tests__/WorkspaceSurface.test.tsx +418 -0
  336. package/src/workspace/__tests__/a11y/harness.tsx +140 -0
  337. package/src/workspace/__tests__/a11y/mock-capabilities.ts +138 -0
  338. package/src/workspace/__tests__/a11y/workspace-editor.a11y.test.tsx +65 -0
  339. package/src/workspace/__tests__/a11y/workspace-explorer-search.a11y.test.tsx +112 -0
  340. package/src/workspace/__tests__/a11y/workspace-viewer-tabs.a11y.test.tsx +69 -0
  341. package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
  342. package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
  343. package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
  344. package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
  345. package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
  346. package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
  347. package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
  348. package/src/workspace/findChangeForSelection.ts +61 -0
  349. package/src/workspace/index.ts +56 -2
  350. package/src/workspace/matchContentPreview.ts +51 -0
  351. package/src/workspace/matchWorkspaceFiles.ts +86 -0
  352. package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
  353. package/src/workspace/useWorkspaceContentSearch.ts +228 -0
  354. package/src/workspace/useWorkspaceFileContent.ts +129 -0
  355. package/src/workspace/useWorkspaceFileSearch.ts +184 -0
  356. package/src/workspace/useWorkspaceFiles.ts +27 -27
  357. package/src/workspace/workspaceListingCache.ts +93 -0
  358. package/styles.css +1 -1
  359. package/workflow/WorkflowExecutionGraph.js +1 -1
  360. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  361. package/workflow/index.d.ts +1 -1
  362. package/workflow/index.d.ts.map +1 -1
  363. package/workflow/index.js +1 -1
  364. package/workflow/index.js.map +1 -1
  365. package/workflow/useFollowExecution.js +1 -1
  366. package/workflow/useFollowExecution.js.map +1 -1
  367. package/workspace/EditorTabs.d.ts +47 -0
  368. package/workspace/EditorTabs.d.ts.map +1 -0
  369. package/workspace/EditorTabs.js +78 -0
  370. package/workspace/EditorTabs.js.map +1 -0
  371. package/workspace/ExplorerTree.d.ts +32 -0
  372. package/workspace/ExplorerTree.d.ts.map +1 -0
  373. package/workspace/ExplorerTree.js +49 -0
  374. package/workspace/ExplorerTree.js.map +1 -0
  375. package/workspace/FileViewer.d.ts +93 -0
  376. package/workspace/FileViewer.d.ts.map +1 -0
  377. package/workspace/FileViewer.js +193 -0
  378. package/workspace/FileViewer.js.map +1 -0
  379. package/workspace/WorkspaceContentSearch.d.ts +41 -0
  380. package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
  381. package/workspace/WorkspaceContentSearch.js +216 -0
  382. package/workspace/WorkspaceContentSearch.js.map +1 -0
  383. package/workspace/WorkspaceContentSearcher.d.ts +59 -0
  384. package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
  385. package/workspace/WorkspaceContentSearcher.js +7 -0
  386. package/workspace/WorkspaceContentSearcher.js.map +1 -0
  387. package/workspace/WorkspaceEditor.d.ts.map +1 -1
  388. package/workspace/WorkspaceEditor.js +8 -10
  389. package/workspace/WorkspaceEditor.js.map +1 -1
  390. package/workspace/WorkspaceFileLister.d.ts +11 -0
  391. package/workspace/WorkspaceFileLister.d.ts.map +1 -1
  392. package/workspace/WorkspaceFileReader.d.ts +48 -0
  393. package/workspace/WorkspaceFileReader.d.ts.map +1 -0
  394. package/workspace/WorkspaceFileReader.js +11 -0
  395. package/workspace/WorkspaceFileReader.js.map +1 -0
  396. package/workspace/WorkspaceFileSearch.d.ts +32 -0
  397. package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
  398. package/workspace/WorkspaceFileSearch.js +175 -0
  399. package/workspace/WorkspaceFileSearch.js.map +1 -0
  400. package/workspace/WorkspaceSurface.d.ts +151 -0
  401. package/workspace/WorkspaceSurface.d.ts.map +1 -0
  402. package/workspace/WorkspaceSurface.js +220 -0
  403. package/workspace/WorkspaceSurface.js.map +1 -0
  404. package/workspace/findChangeForSelection.d.ts +19 -0
  405. package/workspace/findChangeForSelection.d.ts.map +1 -0
  406. package/workspace/findChangeForSelection.js +46 -0
  407. package/workspace/findChangeForSelection.js.map +1 -0
  408. package/workspace/index.d.ts +24 -2
  409. package/workspace/index.d.ts.map +1 -1
  410. package/workspace/index.js +13 -1
  411. package/workspace/index.js.map +1 -1
  412. package/workspace/matchContentPreview.d.ts +21 -0
  413. package/workspace/matchContentPreview.d.ts.map +1 -0
  414. package/workspace/matchContentPreview.js +36 -0
  415. package/workspace/matchContentPreview.js.map +1 -0
  416. package/workspace/matchWorkspaceFiles.d.ts +30 -0
  417. package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
  418. package/workspace/matchWorkspaceFiles.js +58 -0
  419. package/workspace/matchWorkspaceFiles.js.map +1 -0
  420. package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
  421. package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
  422. package/workspace/resolveWorkspaceFileSelection.js +115 -0
  423. package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
  424. package/workspace/useWorkspaceContentSearch.d.ts +69 -0
  425. package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
  426. package/workspace/useWorkspaceContentSearch.js +154 -0
  427. package/workspace/useWorkspaceContentSearch.js.map +1 -0
  428. package/workspace/useWorkspaceFileContent.d.ts +73 -0
  429. package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
  430. package/workspace/useWorkspaceFileContent.js +57 -0
  431. package/workspace/useWorkspaceFileContent.js.map +1 -0
  432. package/workspace/useWorkspaceFileSearch.d.ts +61 -0
  433. package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
  434. package/workspace/useWorkspaceFileSearch.js +119 -0
  435. package/workspace/useWorkspaceFileSearch.js.map +1 -0
  436. package/workspace/useWorkspaceFiles.d.ts +13 -5
  437. package/workspace/useWorkspaceFiles.d.ts.map +1 -1
  438. package/workspace/useWorkspaceFiles.js +18 -19
  439. package/workspace/useWorkspaceFiles.js.map +1 -1
  440. package/workspace/workspaceListingCache.d.ts +47 -0
  441. package/workspace/workspaceListingCache.d.ts.map +1 -0
  442. package/workspace/workspaceListingCache.js +55 -0
  443. package/workspace/workspaceListingCache.js.map +1 -0
  444. package/session/inspector/ArtifactsTab.d.ts.map +0 -1
  445. package/session/inspector/ArtifactsTab.js.map +0 -1
  446. package/session/inspector/ChangesTab.d.ts.map +0 -1
  447. package/session/inspector/ChangesTab.js.map +0 -1
  448. package/session/inspector/InspectTab.d.ts.map +0 -1
  449. package/session/inspector/InspectTab.js.map +0 -1
  450. package/session/inspector/SessionInspector.d.ts +0 -64
  451. package/session/inspector/SessionInspector.d.ts.map +0 -1
  452. package/session/inspector/SessionInspector.js +0 -53
  453. package/session/inspector/SessionInspector.js.map +0 -1
  454. package/session/inspector/SetupTab.d.ts.map +0 -1
  455. package/session/inspector/SetupTab.js.map +0 -1
  456. package/session/inspector/UsageTab.d.ts.map +0 -1
  457. package/session/inspector/UsageTab.js.map +0 -1
  458. package/session/inspector/WorkspaceTab.d.ts +0 -35
  459. package/session/inspector/WorkspaceTab.d.ts.map +0 -1
  460. package/session/inspector/WorkspaceTab.js +0 -75
  461. package/session/inspector/WorkspaceTab.js.map +0 -1
  462. package/session/inspector/index.d.ts.map +0 -1
  463. package/session/inspector/index.js.map +0 -1
  464. package/session/inspector/useSessionInspector.d.ts +0 -49
  465. package/session/inspector/useSessionInspector.d.ts.map +0 -1
  466. package/session/inspector/useSessionInspector.js +0 -122
  467. package/session/inspector/useSessionInspector.js.map +0 -1
  468. package/src/session/inspector/SessionInspector.tsx +0 -162
  469. package/src/session/inspector/WorkspaceTab.tsx +0 -245
  470. package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
  471. package/src/session/inspector/useSessionInspector.ts +0 -178
  472. package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
  473. package/workflow/motion-preference.d.ts.map +0 -1
  474. package/workflow/motion-preference.js.map +0 -1
  475. package/workspace/WorkspaceEntryFiles.d.ts +0 -22
  476. package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
  477. package/workspace/WorkspaceEntryFiles.js +0 -58
  478. package/workspace/WorkspaceEntryFiles.js.map +0 -1
  479. /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
  480. /package/session/{inspector → facets}/InspectTab.js +0 -0
  481. /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
  482. /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
  483. /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
@@ -1,13 +1,3 @@
1
- export { SessionInspector } from "./SessionInspector.js";
2
- export type { SessionInspectorProps } from "./SessionInspector.js";
3
-
4
- export { useSessionInspector, buildVisibleTabs } from "./useSessionInspector.js";
5
- export type {
6
- SessionInspectorTabId,
7
- UseSessionInspectorOptions,
8
- UseSessionInspectorReturn,
9
- } from "./useSessionInspector.js";
10
-
11
1
  export { ChangesTab } from "./ChangesTab.js";
12
2
  export type { ChangesTabProps } from "./ChangesTab.js";
13
3
 
@@ -25,9 +15,3 @@ export type {
25
15
  SetupTabProps,
26
16
  SetupTabMutationCallbacks,
27
17
  } from "./SetupTab.js";
28
-
29
- export { WorkspaceTab } from "./WorkspaceTab.js";
30
- export type {
31
- WorkspaceTabProps,
32
- WorkspaceTabActions,
33
- } from "./WorkspaceTab.js";
@@ -102,24 +102,41 @@ export type { SessionViewerProps } from "./SessionViewer.js";
102
102
  export { NewSessionViewer } from "./NewSessionViewer.js";
103
103
  export type { NewSessionViewerProps } from "./NewSessionViewer.js";
104
104
 
105
- // Selection types (for platform builders using SessionInspector directly)
105
+ // Unified session-panel controller drives the WorkspaceSurface open-editor
106
+ // group, the collapsed/open state, and the rail-view FSM (for platform
107
+ // builders embedding the surface directly).
108
+ export { useSessionPanel } from "./useSessionPanel.js";
109
+ export type {
110
+ SessionPanelController,
111
+ UseSessionPanelOptions,
112
+ } from "./useSessionPanel.js";
113
+
114
+ // Plan draft — viewer-owned in-place edit of the session's current plan
115
+ // (edit-as-input; the published plan.md artifact is never mutated).
116
+ export { usePlanDraft, planDraftKey } from "./usePlanDraft.js";
117
+ export type { PlanDraftController } from "./usePlanDraft.js";
118
+
119
+ // Plan document — the editor-area plan surface (mounted as a virtual document
120
+ // in the workspace surface) and the identity of its tab.
121
+ export { PlanEditor } from "./PlanEditor.js";
122
+ export type { PlanEditorProps } from "./PlanEditor.js";
123
+ export { PlanStreamingDocument } from "./PlanStreamingDocument.js";
124
+ export type { PlanStreamingDocumentProps } from "./PlanStreamingDocument.js";
125
+ export {
126
+ PLAN_DOCUMENT_ENTRY_ID,
127
+ PLAN_DOCUMENT_PATH,
128
+ } from "./plan-document.js";
129
+
130
+ // Selection types (for platform builders composing their own Inspect facet)
106
131
  export type { SelectedThreadItem } from "../internal/store/selection-store.js";
107
132
 
108
- // SessionInspectortabbed right-side inspector panel
109
- export {
110
- SessionInspector,
111
- useSessionInspector,
112
- buildVisibleTabs,
113
- SetupTab,
114
- } from "./inspector/index.js";
133
+ // Session facet components the panel's rail views (Config et al.), also
134
+ // independently importable (DD-003).
135
+ export { SetupTab } from "./facets/index.js";
115
136
  export type {
116
- SessionInspectorProps,
117
- SessionInspectorTabId,
118
- UseSessionInspectorOptions,
119
- UseSessionInspectorReturn,
120
137
  SetupTabProps,
121
138
  SetupTabMutationCallbacks,
122
- } from "./inspector/index.js";
139
+ } from "./facets/index.js";
123
140
 
124
141
  // Session utilities (re-exported from @stigmer/sdk)
125
142
  export { PENDING_SUBJECT, resolvedSubject } from "@stigmer/sdk";
@@ -0,0 +1,30 @@
1
+ // Identity of the session's plan tab in the workspace surface's editor group.
2
+ //
3
+ // Kept in its own module (not in PlanEditor.tsx) so behavior-only consumers —
4
+ // useSessionPanel opens the tab, SessionViewer routes to it — depend on the
5
+ // identity without pulling the component (and its markdown renderer) into
6
+ // their module graph (DD-003 headless-first).
7
+
8
+ import { virtualEntryId } from "../internal/store/index.js";
9
+
10
+ /**
11
+ * Virtual entry id of the plan document tab. One tab per session — the host
12
+ * swaps WHICH plan the tab shows (latest editable, or a superseded plan
13
+ * read-only); the tab itself never multiplies.
14
+ */
15
+ export const PLAN_DOCUMENT_ENTRY_ID = virtualEntryId("plan");
16
+
17
+ /**
18
+ * The plan tab's path — doubles as its tab label.
19
+ *
20
+ * Deliberately plan-AGNOSTIC ("Plan"), not the artifact's filename. The
21
+ * workspace surface identifies a virtual document's tab by
22
+ * `editorKey(entryId, path)`, so `path` is part of the tab's IDENTITY — and the
23
+ * session keeps exactly ONE plan tab that swaps which plan it shows (latest
24
+ * editable, or a superseded plan read-only). Now that plans carry unique,
25
+ * title-derived filenames (`<slug>_<id>.plan.md`), binding this label to any one
26
+ * plan's name would mint a new tab identity per plan and shatter the
27
+ * single-tab design. A stable, generic label is therefore required, not a
28
+ * stylistic choice — do not "fix" it to track the filename.
29
+ */
30
+ export const PLAN_DOCUMENT_PATH = "Plan";
@@ -0,0 +1,53 @@
1
+ "use client";
2
+
3
+ import { useMemo } from "react";
4
+ import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
5
+ import type { FileChange } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
6
+ import type { WorkspaceEntry } from "../workspace/useWorkspaceEntries.js";
7
+ import type { SelectedWorkspaceFile } from "../internal/store/workspace-file-selection-store.js";
8
+ import { findChangeForSelection } from "../workspace/findChangeForSelection.js";
9
+ import { useSessionFileChanges } from "./useSessionFileChanges.js";
10
+
11
+ /**
12
+ * Stable empty executions passed to {@link useSessionFileChanges} while no file
13
+ * is open, so the (fetch-free) net-change fold stays trivial during streaming
14
+ * and only folds once a file is actually being viewed.
15
+ */
16
+ const EMPTY_EXECUTIONS: readonly AgentExecution[] = [];
17
+
18
+ /**
19
+ * Correlate the open workspace file with the one session {@link FileChange} that
20
+ * touched it, so a changed file can default to its authoritative
21
+ * `baseline→candidate` diff (Slice 4 / DD-06).
22
+ *
23
+ * The net-change fold is skipped while no file is open (via `EMPTY_EXECUTIONS`),
24
+ * and the join reuses the same DD-08 resolver + entries + sandbox root that
25
+ * opened the file — so "the diff shown" can never disagree with "the file
26
+ * opened". Both the inspector's Viewer tab and the workspace surface consume
27
+ * this single hook rather than re-deriving the correlation.
28
+ *
29
+ * @returns the matching change, or `null` when the open file was not changed
30
+ * this session (or no file is open).
31
+ */
32
+ export function useOpenFileChange(
33
+ selectedFile: SelectedWorkspaceFile | null | undefined,
34
+ allExecutions: readonly AgentExecution[],
35
+ entries: readonly WorkspaceEntry[] | undefined,
36
+ sandboxWorkspaceRoot: string | undefined,
37
+ ): FileChange | null {
38
+ const { fileChanges } = useSessionFileChanges(
39
+ selectedFile ? allExecutions : EMPTY_EXECUTIONS,
40
+ );
41
+ return useMemo(
42
+ () =>
43
+ selectedFile && entries
44
+ ? findChangeForSelection(
45
+ selectedFile,
46
+ fileChanges,
47
+ entries,
48
+ sandboxWorkspaceRoot,
49
+ ) ?? null
50
+ : null,
51
+ [selectedFile, fileChanges, entries, sandboxWorkspaceRoot],
52
+ );
53
+ }
@@ -0,0 +1,109 @@
1
+ "use client";
2
+
3
+ import { useCallback, useMemo, useRef, useState } from "react";
4
+ import type { SessionPlan } from "../library/detect-plan-artifact.js";
5
+
6
+ /**
7
+ * Identity of a plan for draft scoping: the execution that published it plus
8
+ * the artifact's content hash. A refined plan (new execution) or a republished
9
+ * plan (same key, new hash) produces a NEW identity, which orphans any draft
10
+ * of the previous plan — a draft of plan N must never silently ride along
11
+ * once plan N+1 exists.
12
+ */
13
+ export function planDraftKey(plan: SessionPlan): string {
14
+ return `${plan.executionId}:${plan.artifact.contentHash}`;
15
+ }
16
+
17
+ /** Controller returned by {@link usePlanDraft}. */
18
+ export interface PlanDraftController {
19
+ /**
20
+ * The user's in-place edit of the current plan, or `null` when the plan is
21
+ * unedited. Always scoped to the CURRENT plan — a draft made against a
22
+ * superseded plan reads as `null` here (it is dropped, never migrated).
23
+ */
24
+ readonly draftText: string | null;
25
+ /** True when the current plan has an active draft. */
26
+ readonly isEdited: boolean;
27
+ /**
28
+ * Set (or update) the draft for the current plan. Pass `null` to revert to
29
+ * the published plan. No-ops when the session has no plan.
30
+ */
31
+ readonly setDraft: (text: string | null) => void;
32
+ /**
33
+ * Snapshot reader for submit-time consumers: returns the current draft (or
34
+ * `null`) without the caller depending on draft state. Referentially stable
35
+ * for the lifetime of the component (DD-010) — the "Build" action reads the
36
+ * draft through this at click time, so per-keystroke draft updates never
37
+ * re-bind the build callback or re-render the conversation column.
38
+ */
39
+ readonly readDraft: () => string | null;
40
+ }
41
+
42
+ interface DraftState {
43
+ readonly key: string;
44
+ readonly text: string;
45
+ }
46
+
47
+ /**
48
+ * Owns the local draft of the session's current plan (Phase: refine before
49
+ * build). The draft is a client-side overlay — the published `plan.md`
50
+ * artifact is immutable and is never written back (edit-as-input, not
51
+ * artifact mutation). The approved plan (draft if edited, else the artifact
52
+ * text) is delivered to the implement execution as an attachment.
53
+ *
54
+ * Ownership lives at the viewer level, NOT inside the plan document tab's
55
+ * editor: the panel subtree unmounts wholesale on collapse (and the editor
56
+ * remounts per plan identity), so editor-local state would be destroyed by
57
+ * every collapse or tab switch — silently losing the user's edits.
58
+ *
59
+ * Supersession is derived, not synchronized: the draft is stored with the
60
+ * plan identity it was made against ({@link planDraftKey}), and reads resolve
61
+ * against the CURRENT plan's identity. When a newer plan arrives the old
62
+ * draft simply stops matching — no effect, no cleanup, no stale-flush race.
63
+ */
64
+ export function usePlanDraft(
65
+ plan: SessionPlan | undefined,
66
+ ): PlanDraftController {
67
+ const [draft, setDraftState] = useState<DraftState | null>(null);
68
+
69
+ const currentKey = plan ? planDraftKey(plan) : null;
70
+ const draftText =
71
+ draft !== null && currentKey !== null && draft.key === currentKey
72
+ ? draft.text
73
+ : null;
74
+
75
+ // Render-synced mirrors so `readDraft` stays referentially stable while
76
+ // always observing the latest draft/plan (the useSessionPanel viewRef
77
+ // pattern).
78
+ const draftRef = useRef(draft);
79
+ draftRef.current = draft;
80
+ const currentKeyRef = useRef(currentKey);
81
+ currentKeyRef.current = currentKey;
82
+
83
+ const setDraft = useCallback(
84
+ (text: string | null) => {
85
+ const key = currentKeyRef.current;
86
+ if (!key) return;
87
+ setDraftState(text === null ? null : { key, text });
88
+ },
89
+ [],
90
+ );
91
+
92
+ const readDraft = useCallback((): string | null => {
93
+ const current = draftRef.current;
94
+ const key = currentKeyRef.current;
95
+ return current !== null && key !== null && current.key === key
96
+ ? current.text
97
+ : null;
98
+ }, []);
99
+
100
+ return useMemo(
101
+ () => ({
102
+ draftText,
103
+ isEdited: draftText !== null,
104
+ setDraft,
105
+ readDraft,
106
+ }),
107
+ [draftText, setDraft, readDraft],
108
+ );
109
+ }
@@ -3,7 +3,7 @@
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
5
5
  import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
6
- import type { FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
6
+ import type { FileChangeProgress, FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
7
7
  import { ApprovalAction, ExecutionPhase, FileChangeSetStatus, FileDecisionAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
8
8
  import type { Session } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
9
9
  import type { McpServerUsage as ProtoMcpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
@@ -96,6 +96,12 @@ export interface SendFollowUpOptions {
96
96
  * - `"plan"`: read-only analysis, no file mutations.
97
97
  */
98
98
  readonly interactionMode?: "agent" | "plan";
99
+ /**
100
+ * Marks this execution as a Build-from-plan turn.
101
+ *
102
+ * @see {@link CreateAgentExecutionInput.buildFromPlan}
103
+ */
104
+ readonly buildFromPlan?: boolean;
99
105
  /**
100
106
  * Auto-approve every tool call for this execution (bypass the HITL gate).
101
107
  *
@@ -216,6 +222,13 @@ export interface UseSessionConversationReturn {
216
222
 
217
223
  /** Captured change sets awaiting file review on the active execution, empty when none. */
218
224
  readonly fileChangeSets: readonly FileChangeSet[];
225
+ /**
226
+ * Mid-run live capture (DD-32): the transient, non-authoritative snapshot of the
227
+ * workspace delta accumulating during the active turn ("N files changed so far").
228
+ * Undefined when no turn is currently capturing. Never decidable — the reviewed
229
+ * diff is {@link fileChangeSets}.
230
+ */
231
+ readonly fileChangeProgress: FileChangeProgress | undefined;
219
232
  /** Submit a file-review decision for a change set. The executionId is managed internally. */
220
233
  readonly submitFileDecision: (
221
234
  changeSetId: string,
@@ -548,7 +561,14 @@ export function useSessionConversation(
548
561
  // Capture for retry and clear any prior failure before the new attempt.
549
562
  lastSendRef.current = { message, options };
550
563
  setSendError(null);
551
- setPendingUserMessage(message);
564
+ // A Build-from-plan turn shows no optimistic bubble: its message is a
565
+ // machine-written label, not user prose, and the thread hides the turn
566
+ // entirely (the plan card's "Starting build…" state covers the send
567
+ // window). It is still set on FAILURE below, so a failed build send
568
+ // renders the failed-with-retry bubble instead of vanishing.
569
+ if (!options?.buildFromPlan) {
570
+ setPendingUserMessage(message);
571
+ }
552
572
 
553
573
  try {
554
574
  const needsSessionUpdate =
@@ -581,6 +601,7 @@ export function useSessionConversation(
581
601
  runtimeEnv: options?.runtimeEnv,
582
602
  attachments: options?.attachments,
583
603
  interactionMode: options?.interactionMode,
604
+ buildFromPlan: options?.buildFromPlan,
584
605
  autoApproveAll: options?.autoApproveAll,
585
606
  workspaceFileRefs: options?.workspaceFileRefs,
586
607
  });
@@ -589,7 +610,10 @@ export function useSessionConversation(
589
610
  } catch (err) {
590
611
  // Surface the failure and KEEP the user's message visible (do not clear
591
612
  // pendingUserMessage) so the turn renders as failed-with-retry instead
592
- // of vanishing. Covers both the update() and create() paths.
613
+ // of vanishing. Covers both the update() and create() paths. For a
614
+ // build turn this is the FIRST time the message is set — failure is
615
+ // the one case where its label must become visible.
616
+ setPendingUserMessage(message);
593
617
  setSendError(toError(err));
594
618
  if (process.env.NODE_ENV !== "production") {
595
619
  console.error("[useSessionConversation] sendFollowUp failed:", err);
@@ -634,6 +658,16 @@ export function useSessionConversation(
634
658
  [activeStreamExecution],
635
659
  );
636
660
 
661
+ // Mid-run live capture (DD-32): the transient, non-authoritative "N files
662
+ // changed so far" snapshot for the active turn. The server clears it once the
663
+ // turn's change set leaves CAPTURING, so its mere presence means a turn is
664
+ // still accumulating changes. Reference-stable per DD-010 (it rides the
665
+ // structurally-shared live status).
666
+ const fileChangeProgress = useMemo<FileChangeProgress | undefined>(
667
+ () => activeStreamExecution?.status?.fileChangeProgress,
668
+ [activeStreamExecution],
669
+ );
670
+
637
671
  const submitFileDecision = useCallback(
638
672
  async (
639
673
  changeSetId: string,
@@ -678,6 +712,7 @@ export function useSessionConversation(
678
712
  clearApprovalError,
679
713
 
680
714
  fileChangeSets,
715
+ fileChangeProgress,
681
716
  submitFileDecision,
682
717
  submittingFileDecisionKeys: submittingDecisionKeys,
683
718
  fileDecisionErrors,
@@ -405,6 +405,7 @@ export function useSessionPageFlow(
405
405
  runtimeEnv,
406
406
  attachments: context?.attachments,
407
407
  interactionMode: context?.interactionMode,
408
+ buildFromPlan: context?.buildFromPlan,
408
409
  // Sourced from the session-scoped preference set at the approval gate,
409
410
  // not from the composer (the pre-arm toggle was removed).
410
411
  autoApproveAll: autoApproveAll || undefined,
@@ -0,0 +1,288 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import type { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
+ import { isTerminalPhase } from "../execution/execution-phases.js";
6
+ import type { SelectedThreadItem } from "../internal/store/selection-store.js";
7
+ import {
8
+ useWorkspaceEditorsStoreRef,
9
+ type OpenFileOptions,
10
+ type WorkspaceEditorsStore,
11
+ } from "../internal/store/index.js";
12
+ import { PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH } from "./plan-document.js";
13
+
14
+ /** Options for {@link useSessionPanel}. */
15
+ export interface UseSessionPanelOptions {
16
+ /**
17
+ * The display execution's phase, or `null` before any execution exists.
18
+ * A transition between running and terminal resets the user's sticky view
19
+ * pick (mirroring the retired inspector-tab FSM).
20
+ */
21
+ readonly phase: ExecutionPhase | null;
22
+ /**
23
+ * Whether the session has git write-backs. The first arrival auto-surfaces
24
+ * the Changes view — but only while the panel is open; a collapsed panel
25
+ * signals through badges instead of pulling the user out of the chat.
26
+ */
27
+ readonly hasChanges: boolean;
28
+ /**
29
+ * Identity of the session's current plan, or `null` when none exists. Two
30
+ * identity families, supplied by the viewer: `<executionId>:streaming`
31
+ * while the active turn is WRITING a plan (see `findStreamingPlan`), then
32
+ * the published identity (`planDraftKey`) once the artifact exists. A NEW
33
+ * identity — a plan starting to stream, the first published plan, or a
34
+ * refined plan superseding it — auto-opens the plan document tab (see
35
+ * {@link SessionPanelController.openPlanDocument}), expanding a collapsed
36
+ * panel. This deliberately breaks the Changes/Inspect "never open a
37
+ * collapsed panel" convention: a plan is not ambient state, it is the
38
+ * deliverable of the turn the user just requested, and with the thread
39
+ * showing only a compact card there is no other review surface — live or
40
+ * settled. The streaming→published transition is itself a new identity,
41
+ * harmlessly re-firing the (idempotent) open as the tab's content settles.
42
+ * Keyed on plan IDENTITY, not presence, so a refined plan re-surfaces too;
43
+ * the identity present at mount is swallowed (loading a session with an
44
+ * old plan — or mid-stream — never hijacks the layout).
45
+ */
46
+ readonly planKey?: string | null;
47
+ /**
48
+ * The panel's home view — the view it opens on and the one every automatic
49
+ * reset returns to (running⇄terminal transition, selection cleared). Defaults
50
+ * to `"files"` (the Explorer), which suits the session viewer. The launcher
51
+ * passes `"configure"`: pre-session there is no workspace, so the Config
52
+ * facet — carrying the run defaults (harness/model) — is the useful landing
53
+ * view. Auto-switches (Changes/Inspect) and explicit rail picks still
54
+ * take over from here exactly as before.
55
+ *
56
+ * @default "files"
57
+ */
58
+ readonly defaultView?: string;
59
+ }
60
+
61
+ /**
62
+ * State + actions for the unified session panel, shared by every viewer that
63
+ * hosts it (session + launcher) so they behave identically (DD-016).
64
+ *
65
+ * The panel is the one right-side surface: a workspace surface whose activity
66
+ * rail hosts the session facets (see `useSessionRailViews`). It replaces the
67
+ * former two-view model (narrow inspector ⇄ workspace-mode flip): the panel is
68
+ * **collapsed by default** to a top-right chip, and `isOpen` + `view` describe
69
+ * it fully.
70
+ *
71
+ * Owns the {@link WorkspaceEditorsStore} (the open-editor group) and the view
72
+ * FSM ported from the retired inspector tabs: explicit picks are sticky until
73
+ * a meaningful state change (selection cleared, running⇄terminal transition)
74
+ * resets them back to the `defaultView`. Both are decoupled from any store
75
+ * subscription at the owner level: callbacks mutate imperatively so a file
76
+ * open/switch re-renders only the subscribing panel subtree, never the
77
+ * streaming conversation column (DD-009/DD-010, invariant 2).
78
+ */
79
+ export interface SessionPanelController {
80
+ /** The open-editor group store; subscribe with `useWorkspaceEditors`. */
81
+ readonly editorsStore: WorkspaceEditorsStore;
82
+ /** Whether the panel is expanded (chat narrow) or collapsed to the chip. */
83
+ readonly isOpen: boolean;
84
+ /** The active rail view id (`"files"`, `"search"`, or an injected facet). */
85
+ readonly view: string;
86
+ /** Expand the panel, restoring the previous view (or Inspect if a thread item is selected). */
87
+ readonly openPanel: () => void;
88
+ /** Collapse the panel to the chip, preserving editors and view. */
89
+ readonly closePanel: () => void;
90
+ /** Explicit view pick from the rail — sticky against auto-switching. */
91
+ readonly setView: (viewId: string) => void;
92
+ /**
93
+ * Open a file as a preview tab and expand the panel. Pass `options.line` to
94
+ * jump to and highlight a specific 1-based line (e.g. a content-search hit) —
95
+ * the file opens in its line-faithful File view scrolled to that line.
96
+ */
97
+ readonly openFile: (
98
+ entryId: string,
99
+ path: string,
100
+ options?: OpenFileOptions,
101
+ ) => void;
102
+ /** Focus an already-open editor tab. */
103
+ readonly activateEditor: (entryId: string, path: string) => void;
104
+ /** Pin an editor tab (clear its preview state). */
105
+ readonly pinEditor: (entryId: string, path: string) => void;
106
+ /**
107
+ * Close an editor tab. The panel stays open even when the group empties —
108
+ * unlike the retired workspace-mode flip, the panel is more than files.
109
+ */
110
+ readonly closeEditor: (entryId: string, path: string) => void;
111
+ /**
112
+ * Open (or focus) the plan document tab and expand the panel. The tab is
113
+ * **pinned**, never the recyclable preview slot — file browsing must not
114
+ * evict the plan — and it activates, replacing the focused tab: the plan is
115
+ * the deliverable being reviewed. Fired by the thread cards' "Open plan"
116
+ * (the live `PlanStreamingCard` and the settled `PlanArtifactCard`), the
117
+ * Artifacts facet's `plan.md`, and the new-plan auto-open — which triggers
118
+ * both when a plan STARTS STREAMING and when it publishes (see `planKey`).
119
+ */
120
+ readonly openPlanDocument: () => void;
121
+ /**
122
+ * Report the current thread-item selection. Called from an effect inside the
123
+ * panel subtree (the level that subscribes to the selection store), keeping
124
+ * the owner subscription-free. While the panel is open, a new selection
125
+ * auto-switches to the Inspect view (unless the user picked one explicitly);
126
+ * a collapsed panel deliberately ignores selections — Inspect has no
127
+ * auto-open (it must never pull the user out of the chat).
128
+ */
129
+ readonly notifySelection: (item: SelectedThreadItem | null) => void;
130
+ }
131
+
132
+ /**
133
+ * Create a {@link SessionPanelController} for a viewer instance.
134
+ */
135
+ export function useSessionPanel({
136
+ phase,
137
+ hasChanges,
138
+ planKey = null,
139
+ defaultView = "files",
140
+ }: UseSessionPanelOptions): SessionPanelController {
141
+ const editorsStore = useWorkspaceEditorsStoreRef();
142
+ const [isOpen, setIsOpen] = useState(false);
143
+ const [view, setViewState] = useState(defaultView);
144
+
145
+ // Sticky explicit pick (rail click) — auto-switching yields to it until a
146
+ // meaningful state change resets it. Same semantics as the retired tab FSM.
147
+ const userPickedViewRef = useRef(false);
148
+ // Render-synced mirror so imperative callbacks read the current view without
149
+ // re-binding on every view change.
150
+ const viewRef = useRef(view);
151
+ viewRef.current = view;
152
+ // Last selection reported by the panel subtree; consulted by transitions that
153
+ // fire at the owner level (open, phase change) where selection state is
154
+ // deliberately not subscribed.
155
+ const selectionRef = useRef<SelectedThreadItem | null>(null);
156
+
157
+ // Running⇄terminal transition → reset the sticky pick and re-derive the view.
158
+ // Adjust-state-during-render (the established ResizableSplit pattern) so it
159
+ // lands before paint without an effect.
160
+ const [prevPhase, setPrevPhase] = useState(phase);
161
+ if (phase !== prevPhase) {
162
+ const wasTerminal = prevPhase !== null && isTerminalPhase(prevPhase);
163
+ const isNowTerminal = phase !== null && isTerminalPhase(phase);
164
+ setPrevPhase(phase);
165
+ if (wasTerminal !== isNowTerminal) {
166
+ userPickedViewRef.current = false;
167
+ setViewState(selectionRef.current ? "inspect" : defaultView);
168
+ }
169
+ }
170
+
171
+ // First write-back arrived → surface Changes, but only in an open panel and
172
+ // never over an explicit pick. Collapsed panels signal via badges alone.
173
+ const [prevHasChanges, setPrevHasChanges] = useState(hasChanges);
174
+ if (hasChanges !== prevHasChanges) {
175
+ setPrevHasChanges(hasChanges);
176
+ if (hasChanges && isOpen && !userPickedViewRef.current) {
177
+ setViewState("changes");
178
+ }
179
+ }
180
+
181
+ const openPlanDocument = useCallback(() => {
182
+ editorsStore.openPinned(PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH);
183
+ setIsOpen(true);
184
+ }, [editorsStore]);
185
+
186
+ // A new plan arrived (first plan, or a refinement superseding it) → open the
187
+ // plan document tab, expanding a collapsed panel (see the planKey option doc
188
+ // for why this one trigger may open the panel). An effect, NOT the
189
+ // render-adjust idiom the phase/changes triggers use: those set this
190
+ // component's own state, which the idiom permits — this one mutates the
191
+ // external editors store (notifying subscribers), which is illegal during
192
+ // render. The ref (not effect-less prev-state) swallows the identity present
193
+ // at mount: loading a session with an old plan never hijacks the layout.
194
+ const prevPlanKeyRef = useRef(planKey);
195
+ useEffect(() => {
196
+ if (planKey === prevPlanKeyRef.current) return;
197
+ prevPlanKeyRef.current = planKey;
198
+ if (planKey !== null) {
199
+ openPlanDocument();
200
+ }
201
+ }, [planKey, openPlanDocument]);
202
+
203
+ const openPanel = useCallback(() => {
204
+ setIsOpen(true);
205
+ // Re-derive the auto view on entry: a selection made while collapsed
206
+ // surfaces as Inspect now (the collapsed panel ignored it by design).
207
+ if (!userPickedViewRef.current && selectionRef.current) {
208
+ setViewState("inspect");
209
+ }
210
+ }, []);
211
+
212
+ const closePanel = useCallback(() => setIsOpen(false), []);
213
+
214
+ const setView = useCallback((viewId: string) => {
215
+ userPickedViewRef.current = true;
216
+ setViewState(viewId);
217
+ }, []);
218
+
219
+ const openFile = useCallback(
220
+ (entryId: string, path: string, options?: OpenFileOptions) => {
221
+ editorsStore.openPreview(entryId, path, options);
222
+ setIsOpen(true);
223
+ },
224
+ [editorsStore],
225
+ );
226
+
227
+ const activateEditor = useCallback(
228
+ (entryId: string, path: string) => editorsStore.activate(entryId, path),
229
+ [editorsStore],
230
+ );
231
+
232
+ const pinEditor = useCallback(
233
+ (entryId: string, path: string) => editorsStore.pin(entryId, path),
234
+ [editorsStore],
235
+ );
236
+
237
+ const closeEditor = useCallback(
238
+ (entryId: string, path: string) => editorsStore.close(entryId, path),
239
+ [editorsStore],
240
+ );
241
+
242
+ const notifySelection = useCallback(
243
+ (item: SelectedThreadItem | null) => {
244
+ if (item === selectionRef.current) return;
245
+ selectionRef.current = item;
246
+ if (item) {
247
+ if (isOpen && !userPickedViewRef.current) setViewState("inspect");
248
+ } else if (viewRef.current === "inspect") {
249
+ // Selection cleared: leave Inspect (its content is gone) and unstick,
250
+ // returning to the panel's home view.
251
+ userPickedViewRef.current = false;
252
+ setViewState(defaultView);
253
+ }
254
+ },
255
+ [isOpen, defaultView],
256
+ );
257
+
258
+ return useMemo(
259
+ () => ({
260
+ editorsStore,
261
+ isOpen,
262
+ view,
263
+ openPanel,
264
+ closePanel,
265
+ setView,
266
+ openFile,
267
+ activateEditor,
268
+ pinEditor,
269
+ closeEditor,
270
+ openPlanDocument,
271
+ notifySelection,
272
+ }),
273
+ [
274
+ editorsStore,
275
+ isOpen,
276
+ view,
277
+ openPanel,
278
+ closePanel,
279
+ setView,
280
+ openFile,
281
+ activateEditor,
282
+ pinEditor,
283
+ closeEditor,
284
+ openPlanDocument,
285
+ notifySelection,
286
+ ],
287
+ );
288
+ }