@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
@@ -92,15 +92,26 @@ export function FilePathLink({
92
92
  // (ToolCallItem's role=button header); copying/opening a path must not
93
93
  // also expand the row.
94
94
  e.stopPropagation();
95
+
96
+ // Offer the click to the injected handler first. It returns `false` to
97
+ // DECLINE (e.g. an in-app viewer that can't open this particular path),
98
+ // in which case we fall through to the default action below. A `true`/
99
+ // `void` return means it fully handled the click.
95
100
  if (onFilePathClick) {
96
- e.preventDefault();
97
- onFilePathClick(path, resolved);
98
- return;
101
+ const handled = onFilePathClick(path, resolved);
102
+ if (handled !== false) {
103
+ // For a link, also stop the browser from navigating (the file opened
104
+ // in-app instead). A modifier/middle-click bypasses this onClick, so
105
+ // the real <a href> still opens the target in a new tab.
106
+ if (resolved.action === "link") e.preventDefault();
107
+ return;
108
+ }
99
109
  }
110
+
100
111
  if (resolved.action === "copy") {
101
112
  handleCopy();
102
113
  }
103
- // For "link" action the <a> default navigation handles it.
114
+ // For a declined/un-handled "link", the <a>'s native navigation runs.
104
115
  },
105
116
  [onFilePathClick, path, resolved, handleCopy],
106
117
  );
@@ -125,13 +136,18 @@ export function FilePathLink({
125
136
  </>
126
137
  );
127
138
 
128
- if (resolved.action === "link" && !onFilePathClick) {
139
+ // A link-action path always renders a real anchor — even when an
140
+ // `onFilePathClick` handler is present — so native link affordances
141
+ // (middle-click, open-in-new-tab, copy-link-address) survive. `handleClick`
142
+ // intercepts a plain left-click to route it through the handler (e.g. into an
143
+ // in-app viewer) and only calls `preventDefault` when the handler took it.
144
+ if (resolved.action === "link") {
129
145
  return (
130
146
  <a
131
147
  href={resolved.url}
132
148
  target="_blank"
133
149
  rel="noopener noreferrer"
134
- onClick={(e) => e.stopPropagation()}
150
+ onClick={handleClick}
135
151
  aria-label={ariaLabel}
136
152
  title={title}
137
153
  className={cn(sharedClasses, "group/fpl")}
@@ -0,0 +1,89 @@
1
+ "use client";
2
+
3
+ import { FileChangeKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
4
+ import { cn } from "@stigmer/theme";
5
+
6
+ /**
7
+ * Shared presentational atoms for the file-review surfaces — the single source
8
+ * for the `+N −M` stat and the change-kind marker, so the review card, the
9
+ * compact list, and the mid-run progress bar can never drift in how they render
10
+ * a file's magnitude or kind.
11
+ */
12
+
13
+ /**
14
+ * The `+N −M` stat for one file (or a whole set), in the same visual vocabulary
15
+ * as the tool-row diff stats. Renders nothing when both counts are zero — the
16
+ * honest signal that no count exists (binary or secret-withheld changes, records
17
+ * captured before counts were stamped) — rather than a misleading `+0 −0`.
18
+ */
19
+ export function FileLineStats({
20
+ linesAdded,
21
+ linesRemoved,
22
+ }: {
23
+ readonly linesAdded: number;
24
+ readonly linesRemoved: number;
25
+ }) {
26
+ if (linesAdded === 0 && linesRemoved === 0) return null;
27
+ return (
28
+ <span
29
+ className="shrink-0 text-xs tabular-nums"
30
+ aria-label={`${linesAdded} added, ${linesRemoved} removed`}
31
+ data-cursor-target="file-review-line-stats"
32
+ >
33
+ <span className="text-diff-added-fg">+{linesAdded}</span>{" "}
34
+ <span className="text-diff-removed-fg">-{linesRemoved}</span>
35
+ </span>
36
+ );
37
+ }
38
+
39
+ /** The kind letter, tone, and a11y name for each wire {@link FileChangeKind}. */
40
+ const KIND_BADGE: Partial<
41
+ Record<FileChangeKind, { letter: string; colorClass: string; label: string }>
42
+ > = {
43
+ [FileChangeKind.ADD]: {
44
+ letter: "A",
45
+ colorClass: "text-diff-added-fg",
46
+ label: "added",
47
+ },
48
+ [FileChangeKind.MODIFY]: {
49
+ letter: "M",
50
+ colorClass: "text-diff-hunk-header-fg",
51
+ label: "modified",
52
+ },
53
+ [FileChangeKind.DELETE]: {
54
+ letter: "D",
55
+ colorClass: "text-diff-removed-fg",
56
+ label: "deleted",
57
+ },
58
+ [FileChangeKind.RENAME]: {
59
+ letter: "R",
60
+ colorClass: "text-diff-hunk-header-fg",
61
+ label: "renamed",
62
+ },
63
+ // A binary change is a modification whose diff is not text; the letter stays
64
+ // M and the binary-ness is told by the row's "Keep anyway" + reason note.
65
+ [FileChangeKind.BINARY_CHANGE]: {
66
+ letter: "M",
67
+ colorClass: "text-diff-hunk-header-fg",
68
+ label: "modified (binary)",
69
+ },
70
+ };
71
+
72
+ /**
73
+ * The single-letter change-kind marker — the same M/A/D visual vocabulary as
74
+ * the version-history `DiffFileList`, extended with R for captured renames.
75
+ * The letter itself is the non-color channel; the full word is exposed to
76
+ * assistive tech. An UNSPECIFIED kind renders nothing rather than guessing.
77
+ */
78
+ export function FileKindBadge({ kind }: { kind: FileChangeKind }) {
79
+ const badge = KIND_BADGE[kind];
80
+ if (!badge) return null;
81
+ return (
82
+ <span
83
+ className={cn("shrink-0 font-mono text-[10px] font-bold", badge.colorClass)}
84
+ aria-label={badge.label}
85
+ >
86
+ {badge.letter}
87
+ </span>
88
+ );
89
+ }
@@ -16,10 +16,11 @@ import {
16
16
  import { toDisplayFileChange } from "@stigmer/sdk";
17
17
  import { cn } from "@stigmer/theme";
18
18
  import { FileChangeDiff } from "./FileChangesView.js";
19
+ import { FileKindBadge, FileLineStats } from "./FileReviewAtoms.js";
20
+ import { FilePathLink } from "./FilePathLink.js";
19
21
  import { DiffSummary } from "../version-history/DiffSummary.js";
20
22
  import { DecisionButton } from "../internal/DecisionButton.js";
21
23
  import { InCardDecisionError } from "../internal/InCardDecisionError.js";
22
- import { splitDisplayPath } from "./file-path-resolver.js";
23
24
  import { fileDecisionKey, type FileDecisionOptions } from "./useFileReview.js";
24
25
  import {
25
26
  changeSetReviewability,
@@ -62,8 +63,8 @@ export interface FileReviewCardProps {
62
63
  *
63
64
  * `MessageThread` passes `false`: the transcript's stamped edit rows already
64
65
  * show every diff in place, so the expanded body collapses to a compact file
65
- * list (kind letter + path + per-file controls) and the card stays purely
66
- * the decision surface. Decision semantics — digests, scopes,
66
+ * list (kind letter + linked path + `+N −M` + per-file controls) and the card
67
+ * stays purely the decision surface. Decision semantics — digests, scopes,
67
68
  * acknowledgments — are identical in both modes; this is presentation only
68
69
  * (opt-in with a backward-compatible default, DD-011).
69
70
  */
@@ -194,11 +195,18 @@ export const FileReviewCard = memo(function FileReviewCard({
194
195
 
195
196
  // The bar starts expanded exactly when the collapsed bar cannot honestly carry
196
197
  // the decision: an incomplete set (binary acknowledgment / blocked files need
197
- // their per-file context) or a review already in progress. A complete set and
198
- // a settled record start collapsed the transcript's stamped rows already
199
- // show what changed, and the expander reveals the per-file detail on demand.
198
+ // their per-file context), a review already in progress, or a multi-file set
199
+ // in compact-list mode its honest decision surface includes the per-file
200
+ // Keep/Discard controls, which must be visible without hunting behind the
201
+ // expander (the docked strip bounds the height, so expanding is cheap there).
202
+ // Diff-rich mode (`showDiffs`) deliberately stays collapsed for a complete
203
+ // multi-file set: its expanded body is every full diff with no height cap
204
+ // (the workflow file-review list), where "Review" is the act of opening it.
205
+ // A settled record always starts collapsed — the transcript's stamped rows
206
+ // already show what changed, and the expander reveals detail on demand.
200
207
  const [expanded, setExpanded] = useState(
201
- () => interactive && (incomplete || decidedCount > 0),
208
+ () =>
209
+ interactive && (incomplete || decidedCount > 0 || (total > 1 && !showDiffs)),
202
210
  );
203
211
  const bodyId = useId();
204
212
 
@@ -251,12 +259,18 @@ export const FileReviewCard = memo(function FileReviewCard({
251
259
  [onSubmit],
252
260
  );
253
261
 
262
+ // The set's aggregate `+N −M`, summed from the capture-time per-file counts
263
+ // (linesAdded/linesRemoved are stamped by the runner with the same diff
264
+ // algorithm the renderers use — see CapturedFileChange). A file with no
265
+ // counts (binary, secret-withheld, or a record predating the fields)
266
+ // contributes zero; when NO file has counts the aggregate is hidden rather
267
+ // than shown as a dishonest "+0 −0".
254
268
  const totals = useMemo(() => {
255
269
  let additions = 0;
256
270
  let deletions = 0;
257
271
  for (const c of changes) {
258
- if (c.kind === FileChangeKind.ADD) additions += 1;
259
- else if (c.kind === FileChangeKind.DELETE) deletions += 1;
272
+ additions += c.linesAdded;
273
+ deletions += c.linesRemoved;
260
274
  }
261
275
  return { additions, deletions };
262
276
  }, [changes]);
@@ -311,8 +325,16 @@ export const FileReviewCard = memo(function FileReviewCard({
311
325
  <span className="shrink-0 font-medium text-foreground">
312
326
  {interactive ? "Review file changes" : "File changes"}
313
327
  </span>
314
- <span className="min-w-0 flex-1 truncate text-muted-foreground">
315
- {summary}
328
+ {/* The flexible middle: the summary (truncating) plus the set's
329
+ aggregate +N −M, visible even while collapsed so the bar carries
330
+ the magnitude of what is being decided, not just the file count.
331
+ Hidden when no file has counts (FileLineStats). */}
332
+ <span className="flex min-w-0 flex-1 items-center gap-2">
333
+ <span className="min-w-0 truncate text-muted-foreground">{summary}</span>
334
+ <FileLineStats
335
+ linesAdded={totals.additions}
336
+ linesRemoved={totals.deletions}
337
+ />
316
338
  </span>
317
339
 
318
340
  {interactive && showBulkControls && (
@@ -390,9 +412,11 @@ export const FileReviewCard = memo(function FileReviewCard({
390
412
  id={bodyId}
391
413
  className="space-y-2 border-t border-border-muted px-3 py-2.5"
392
414
  >
393
- {/* The list body carries no summary header: the collapsed bar's
394
- file count is the summary, and per-file counts would require
395
- fetching offloaded bodies just to decorate a list. */}
415
+ {/* The list body carries no summary header: the bar already shows
416
+ the file count and the aggregate +N −M (per-file counts are
417
+ capture-time facts on the wire linesAdded/linesRemoved so no
418
+ body fetch is ever needed to decorate the list). Diff mode keeps
419
+ its fuller DiffSummary line above the rendered diffs. */}
396
420
  {showDiffs && (
397
421
  <DiffSummary
398
422
  fileCount={total}
@@ -640,15 +664,17 @@ function CapturedChangeDiff({ change }: { change: CapturedFileChange }) {
640
664
  // ---------------------------------------------------------------------------
641
665
 
642
666
  /**
643
- * One file of the change set as a compact, deliberately inert list line: kind
644
- * letter, path, provenance badge, and an optional trailing slot (the verdict
667
+ * One file of the change set as a compact list line: kind letter, linked path,
668
+ * `+N −M` stats, provenance badge, and an optional trailing slot (the verdict
645
669
  * control while reviewing; the committed verdict once settled).
646
670
  *
647
- * The path is plain text — not `FilePathLink` — because the list is an
648
- * inventory of what the decision covers, not a navigation surface: the diffs
649
- * live on the transcript's stamped edit rows. The full path stays available on
650
- * hover via `title`. A rename shows its source path so the move reads in one
651
- * line.
671
+ * The path renders through `FilePathLink` — the platform-wide path idiom — so
672
+ * a reviewer can jump from the list to the file itself (the session viewer
673
+ * routes the click into the panel's diff-first viewer; GitHub/copy is the
674
+ * fallback) without leaving the decision surface. Deciding and navigating
675
+ * coexist: the link stops click propagation, so opening a file never fights
676
+ * the row's Keep/Discard controls. A rename shows its source path so the move
677
+ * reads in one line.
652
678
  */
653
679
  function FileListRow({
654
680
  change,
@@ -658,7 +684,6 @@ function FileListRow({
658
684
  readonly trailing?: React.ReactNode;
659
685
  }) {
660
686
  const path = change.pathAfter || change.pathBefore;
661
- const { dir, base } = splitDisplayPath(path);
662
687
  const renamedFrom =
663
688
  change.kind === FileChangeKind.RENAME && change.pathBefore !== change.pathAfter
664
689
  ? change.pathBefore
@@ -669,80 +694,22 @@ function FileListRow({
669
694
  data-cursor-target="file-review-list-row"
670
695
  >
671
696
  <FileKindBadge kind={change.kind} />
672
- {/* The directory truncates (context); the base never shrinks (identity) —
673
- the same filename-first rule FilePathLink established. */}
674
- <span
675
- className="flex min-w-0 flex-1 items-center font-mono text-xs text-foreground"
676
- title={path}
677
- >
678
- {renamedFrom && (
679
- <span className="min-w-0 truncate text-muted-foreground-faint">
680
- {renamedFrom}&nbsp;→&nbsp;
681
- </span>
682
- )}
683
- {dir && (
684
- <span className="min-w-0 truncate text-muted-foreground-faint">{dir}</span>
685
- )}
686
- <span className="shrink-0">{base}</span>
687
- </span>
697
+ {renamedFrom && (
698
+ <span className="min-w-0 truncate font-mono text-xs text-muted-foreground-faint">
699
+ {renamedFrom}&nbsp;→&nbsp;
700
+ </span>
701
+ )}
702
+ <FilePathLink path={path} dirDisplay="dim" className="min-w-0 flex-1 text-xs" />
703
+ <FileLineStats
704
+ linesAdded={change.linesAdded}
705
+ linesRemoved={change.linesRemoved}
706
+ />
688
707
  <CaptureBadge change={change} />
689
708
  {trailing}
690
709
  </div>
691
710
  );
692
711
  }
693
712
 
694
- /** The kind letter, tone, and a11y name for each wire {@link FileChangeKind}. */
695
- const KIND_BADGE: Partial<
696
- Record<FileChangeKind, { letter: string; colorClass: string; label: string }>
697
- > = {
698
- [FileChangeKind.ADD]: {
699
- letter: "A",
700
- colorClass: "text-diff-added-fg",
701
- label: "added",
702
- },
703
- [FileChangeKind.MODIFY]: {
704
- letter: "M",
705
- colorClass: "text-diff-hunk-header-fg",
706
- label: "modified",
707
- },
708
- [FileChangeKind.DELETE]: {
709
- letter: "D",
710
- colorClass: "text-diff-removed-fg",
711
- label: "deleted",
712
- },
713
- [FileChangeKind.RENAME]: {
714
- letter: "R",
715
- colorClass: "text-diff-hunk-header-fg",
716
- label: "renamed",
717
- },
718
- // A binary change is a modification whose diff is not text; the letter stays
719
- // M and the binary-ness is told by the row's "Keep anyway" + reason note.
720
- [FileChangeKind.BINARY_CHANGE]: {
721
- letter: "M",
722
- colorClass: "text-diff-hunk-header-fg",
723
- label: "modified (binary)",
724
- },
725
- };
726
-
727
- /**
728
- * The single-letter change-kind marker — the same M/A/D visual vocabulary as
729
- * the version-history `DiffFileList`, extended with R for captured renames.
730
- * The letter itself is the non-color channel; the full word is exposed to
731
- * assistive tech. An UNSPECIFIED kind renders nothing rather than guessing.
732
- */
733
- function FileKindBadge({ kind }: { kind: FileChangeKind }) {
734
- const badge = KIND_BADGE[kind];
735
- if (!badge) return null;
736
- return (
737
- <span
738
- className={cn("shrink-0 font-mono text-[10px] font-bold", badge.colorClass)}
739
- aria-label={badge.label}
740
- >
741
- {badge.letter}
742
- </span>
743
- );
744
- }
745
-
746
713
  /**
747
714
  * A change's committed verdict as a static badge: APPROVE reads "Kept" (the
748
715
  * bytes were reconciled into the workspace), REJECT reads "Discarded" (reverted
@@ -3,12 +3,17 @@
3
3
  import { memo, useMemo, useState } from "react";
4
4
  import { Streamdown } from "streamdown";
5
5
  import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
6
- import { MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
6
+ import {
7
+ MessageType,
8
+ type InteractionMode,
9
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
7
10
  import { cn } from "@stigmer/theme";
8
11
  import {
9
12
  MARKDOWN_COMPONENTS,
10
13
  unwrapEnclosingMarkdownFence,
11
14
  } from "../internal/markdown-components.js";
15
+ import { InteractionModeBadge } from "./InteractionModeBadge.js";
16
+ import { PlanDocumentMessage } from "./PlanDocumentMessage.js";
12
17
  import { useRenderTracer } from "../internal/dev/index.js";
13
18
 
14
19
  /** Props for {@link MessageEntry}. */
@@ -24,6 +29,25 @@ export interface MessageEntryProps {
24
29
  * this message for editing. Ignored for non-human messages.
25
30
  */
26
31
  readonly onEdit?: () => void;
32
+ /**
33
+ * Renders a `MESSAGE_AI` entry as a first-class plan document
34
+ * ({@link PlanDocumentMessage}) instead of a chat bubble. Set by the thread
35
+ * builder only on the NO-ARTIFACT fallback path: a completed Plan turn that
36
+ * never published `plan.md` (older executions, failed upload) keeps its
37
+ * plan inline — the message is the only copy of the plan. A turn that
38
+ * published the artifact collapses the message into the compact plan card
39
+ * instead (the document lives in the panel's plan tab). Ignored for non-AI
40
+ * messages.
41
+ */
42
+ readonly isPlanDocument?: boolean;
43
+ /**
44
+ * The turn's interaction mode, stamped by the thread builder on the
45
+ * synthetic prompt bubble (`MESSAGE_HUMAN`). Renders the
46
+ * {@link InteractionModeBadge} for non-default modes (a "Plan" pill), so
47
+ * the transcript reads unambiguously after mode switches. Ignored for
48
+ * non-human messages.
49
+ */
50
+ readonly interactionMode?: InteractionMode;
27
51
  }
28
52
 
29
53
  /**
@@ -54,6 +78,8 @@ export const MessageEntry = memo(function MessageEntry({
54
78
  message,
55
79
  className,
56
80
  onEdit,
81
+ isPlanDocument,
82
+ interactionMode,
57
83
  }: MessageEntryProps) {
58
84
  useRenderTracer("MessageEntry", {
59
85
  messageType: message.type,
@@ -68,9 +94,17 @@ export const MessageEntry = memo(function MessageEntry({
68
94
  content={message.content}
69
95
  className={className}
70
96
  onEdit={onEdit}
97
+ interactionMode={interactionMode}
71
98
  />
72
99
  );
73
100
  case MessageType.MESSAGE_AI:
101
+ // A completed Plan turn's plan is a document, not a bubble. The flag is
102
+ // only ever set on a settled message, so the streaming path is untouched.
103
+ if (isPlanDocument) {
104
+ return (
105
+ <PlanDocumentMessage content={message.content} className={className} />
106
+ );
107
+ }
74
108
  return (
75
109
  <AiMessage
76
110
  content={message.content}
@@ -97,10 +131,12 @@ function HumanMessage({
97
131
  content,
98
132
  className,
99
133
  onEdit,
134
+ interactionMode,
100
135
  }: {
101
136
  content: string;
102
137
  className?: string;
103
138
  onEdit?: () => void;
139
+ interactionMode?: InteractionMode;
104
140
  }) {
105
141
  return (
106
142
  <div
@@ -111,6 +147,11 @@ function HumanMessage({
111
147
  className,
112
148
  )}
113
149
  >
150
+ {/* The badge renders only for non-default modes (a "Plan" pill), so
151
+ ordinary Agent turns carry no extra chrome. */}
152
+ {interactionMode !== undefined && (
153
+ <InteractionModeBadge mode={interactionMode} className="mb-1.5" />
154
+ )}
114
155
  <p className="text-sm text-foreground whitespace-pre-wrap">{content}</p>
115
156
  {onEdit && (
116
157
  <button
@@ -133,6 +174,13 @@ function HumanMessage({
133
174
  );
134
175
  }
135
176
 
177
+ /**
178
+ * The Build-from-plan turn's user entry: a compact pill in the user-turn
179
+ * position (right-aligned, like the prompt bubble it replaces) carrying the
180
+ * plan glyph and the turn's short label. Deliberately not editable — the
181
+ * label is not user prose to rephrase; refining the plan happens in the plan
182
+ * document, and the build is re-triggered from its card.
183
+ */
136
184
  function EditIcon() {
137
185
  return (
138
186
  <svg