@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,245 +0,0 @@
1
- "use client";
2
-
3
- import { useCallback, useState } from "react";
4
- import { cn } from "@stigmer/theme";
5
- import type { UseWorkspaceEntriesReturn, WorkspaceEntry } from "../../workspace/useWorkspaceEntries.js";
6
- import type { WorkspaceFileLister } from "../../workspace/WorkspaceFileLister.js";
7
- import { WorkspaceEntryFiles } from "../../workspace/WorkspaceEntryFiles.js";
8
- import type { UseGitHubConnectionReturn } from "../../github/useGitHubConnection.js";
9
-
10
- /**
11
- * Interactive workspace actions required by the Workspace tab.
12
- * Mirrors the shape from SetupTab for consistency but is the
13
- * primary owner going forward.
14
- */
15
- export interface WorkspaceTabActions {
16
- readonly workspace: UseWorkspaceEntriesReturn;
17
- readonly enableGitHub?: boolean;
18
- readonly enableLocal?: boolean;
19
- readonly gitHubConnection?: UseGitHubConnectionReturn;
20
- readonly onBrowseLocalFolder?: () => Promise<string | null>;
21
- readonly workspaceFileLister?: WorkspaceFileLister;
22
- }
23
-
24
- /** Props for {@link WorkspaceTab}. */
25
- export interface WorkspaceTabProps {
26
- readonly actions: WorkspaceTabActions;
27
- }
28
-
29
- /**
30
- * Dedicated workspace tab for the SessionInspector.
31
- *
32
- * Provides a full-height layout for managing workspace entries:
33
- * - Entry list with expandable file trees (accordion, one at a time)
34
- * - Add actions: Browse Folder and Connect GitHub
35
- * - Short display names with full path on hover
36
- *
37
- * Entries start collapsed by default to avoid expensive file-listing
38
- * fetches until the user explicitly expands one.
39
- *
40
- * All visual properties flow through `--stgm-*` tokens (DD-005).
41
- */
42
- export function WorkspaceTab({ actions }: WorkspaceTabProps) {
43
- const {
44
- workspace,
45
- enableGitHub = true,
46
- enableLocal = false,
47
- onBrowseLocalFolder,
48
- workspaceFileLister,
49
- } = actions;
50
-
51
- const canBrowse = enableLocal && onBrowseLocalFolder;
52
- const hasEntries = workspace.entries.length > 0;
53
-
54
- return (
55
- <div className="flex h-full flex-col gap-3">
56
- {hasEntries && (
57
- <WorkspaceEntryList
58
- entries={workspace.entries}
59
- onRemove={workspace.remove}
60
- lister={workspaceFileLister}
61
- />
62
- )}
63
-
64
- {!hasEntries && (
65
- <EmptyState />
66
- )}
67
-
68
- <div className="flex flex-col gap-0.5">
69
- {canBrowse && (
70
- <button
71
- type="button"
72
- onClick={async () => {
73
- const path = await onBrowseLocalFolder();
74
- if (path) workspace.addLocalPath(path);
75
- }}
76
- className="flex w-full items-center gap-2 rounded-md px-2.5 py-2 text-xs text-foreground transition-colors hover:bg-accent-hover"
77
- >
78
- <FolderPlusIcon />
79
- <span className="flex-1 text-left">Browse Folder</span>
80
- </button>
81
- )}
82
- {enableGitHub && (
83
- <button
84
- type="button"
85
- onClick={() => {
86
- /* GitHub picker is handled via the composer's Configure menu.
87
- This button is a placeholder affordance for visual parity. */
88
- }}
89
- className="flex w-full items-center gap-2 rounded-md px-2.5 py-2 text-xs text-foreground transition-colors hover:bg-accent-hover"
90
- >
91
- <GitHubIcon />
92
- <span className="flex-1 text-left">Connect GitHub</span>
93
- </button>
94
- )}
95
- </div>
96
- </div>
97
- );
98
- }
99
-
100
- // ---------------------------------------------------------------------------
101
- // Workspace entry list — accordion with file tree expansion
102
- // ---------------------------------------------------------------------------
103
-
104
- function WorkspaceEntryList({
105
- entries,
106
- onRemove,
107
- lister,
108
- }: {
109
- readonly entries: readonly WorkspaceEntry[];
110
- readonly onRemove: (id: string) => void;
111
- readonly lister: WorkspaceFileLister | undefined;
112
- }) {
113
- const [expandedId, setExpandedId] = useState<string | null>(null);
114
-
115
- const toggleExpand = useCallback((id: string) => {
116
- setExpandedId((prev) => (prev === id ? null : id));
117
- }, []);
118
-
119
- return (
120
- <div className="flex flex-col gap-1.5">
121
- {entries.map((entry) => {
122
- const isExpandable = !!lister;
123
- const isExpanded = expandedId === entry.id;
124
-
125
- return (
126
- <div key={entry.id} className="flex flex-col">
127
- <div
128
- className={cn(
129
- "flex items-center gap-2 rounded-md border border-border bg-muted-faint px-2.5 py-2 text-xs",
130
- isExpandable && "cursor-pointer hover:bg-muted transition-colors",
131
- )}
132
- onClick={isExpandable ? () => toggleExpand(entry.id) : undefined}
133
- role={isExpandable ? "button" : undefined}
134
- aria-expanded={isExpandable ? isExpanded : undefined}
135
- tabIndex={isExpandable ? 0 : undefined}
136
- onKeyDown={isExpandable ? (e) => {
137
- if (e.key === "Enter" || e.key === " ") {
138
- e.preventDefault();
139
- toggleExpand(entry.id);
140
- }
141
- } : undefined}
142
- >
143
- {isExpandable && (
144
- <span className="shrink-0 text-[10px] text-muted-foreground-subtle">
145
- {isExpanded ? "▼" : "▶"}
146
- </span>
147
- )}
148
- {entry.type === "git" ? (
149
- <GitHubIcon />
150
- ) : (
151
- <FolderIcon />
152
- )}
153
- <div className="min-w-0 flex-1">
154
- <span
155
- className="block truncate font-medium text-foreground"
156
- title={entry.type === "local" ? entry.localPath : entry.gitUrl}
157
- >
158
- {entry.name}
159
- </span>
160
- {entry.type === "git" && entry.gitBranch && (
161
- <span className="block truncate text-[0.6rem] text-muted-foreground">
162
- {entry.gitBranch}
163
- </span>
164
- )}
165
- </div>
166
- <button
167
- type="button"
168
- onClick={(e) => {
169
- e.stopPropagation();
170
- onRemove(entry.id);
171
- }}
172
- className="shrink-0 text-muted-foreground hover:text-destructive transition-colors"
173
- aria-label={`Remove ${entry.name}`}
174
- >
175
- <XIcon />
176
- </button>
177
- </div>
178
- {isExpandable && lister && (
179
- <WorkspaceEntryFiles
180
- entry={entry}
181
- lister={lister}
182
- isExpanded={isExpanded}
183
- />
184
- )}
185
- </div>
186
- );
187
- })}
188
- </div>
189
- );
190
- }
191
-
192
- // ---------------------------------------------------------------------------
193
- // Empty state
194
- // ---------------------------------------------------------------------------
195
-
196
- function EmptyState() {
197
- return (
198
- <div className="flex flex-col items-center justify-center gap-2 py-8 text-center">
199
- <FolderIcon className="h-8 w-8 text-muted-foreground/40" />
200
- <div className="space-y-1">
201
- <p className="text-xs font-medium text-foreground">No workspace attached</p>
202
- <p className="text-[0.65rem] text-muted-foreground">
203
- Add a folder or GitHub repo for the agent to work with.
204
- </p>
205
- </div>
206
- </div>
207
- );
208
- }
209
-
210
- // ---------------------------------------------------------------------------
211
- // Inline SVG icons (SDK independence — no lucide dependency)
212
- // ---------------------------------------------------------------------------
213
-
214
- function XIcon() {
215
- return (
216
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
217
- <path d="M4 4L10 10M10 4L4 10" />
218
- </svg>
219
- );
220
- }
221
-
222
- function FolderIcon({ className: cls }: { className?: string }) {
223
- return (
224
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className={cn("shrink-0 text-muted-foreground", cls)}>
225
- <path d="M1.5 3.5V11a1 1 0 001 1h9a1 1 0 001-1V5.5a1 1 0 00-1-1H7L5.5 3H2.5a1 1 0 00-1 .5z" />
226
- </svg>
227
- );
228
- }
229
-
230
- function FolderPlusIcon() {
231
- return (
232
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className="shrink-0 text-muted-foreground">
233
- <path d="M1.5 3.5V11a1 1 0 001 1h9a1 1 0 001-1V5.5a1 1 0 00-1-1H7L5.5 3H2.5a1 1 0 00-1 .5z" />
234
- <path d="M7 7v3M5.5 8.5h3" />
235
- </svg>
236
- );
237
- }
238
-
239
- function GitHubIcon() {
240
- return (
241
- <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" className="shrink-0 text-muted-foreground">
242
- <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
243
- </svg>
244
- );
245
- }
@@ -1,251 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { renderHook, act } from "@testing-library/react";
3
- import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
4
- import {
5
- useSessionInspector,
6
- buildVisibleTabs,
7
- type UseSessionInspectorOptions,
8
- } from "../useSessionInspector";
9
-
10
- function defaultOpts(overrides?: Partial<UseSessionInspectorOptions>): UseSessionInspectorOptions {
11
- return {
12
- phase: null,
13
- hasWriteBacks: false,
14
- writeBackCount: 0,
15
- hasArtifacts: false,
16
- artifactCount: 0,
17
- hasUsage: false,
18
- selectedItem: null,
19
- ...overrides,
20
- };
21
- }
22
-
23
- function tabOpts(
24
- overrides?: Partial<Parameters<typeof buildVisibleTabs>[0]>,
25
- ): Parameters<typeof buildVisibleTabs>[0] {
26
- return {
27
- hasWriteBacks: false,
28
- writeBackCount: 0,
29
- hasArtifacts: false,
30
- artifactCount: 0,
31
- hasUsage: false,
32
- selectedItem: null,
33
- ...overrides,
34
- };
35
- }
36
-
37
- // ---------------------------------------------------------------------------
38
- // buildVisibleTabs
39
- // ---------------------------------------------------------------------------
40
-
41
- describe("buildVisibleTabs", () => {
42
- it("always includes Workspace, Config, and Usage (Plan is gone — todos render inline)", () => {
43
- const tabs = buildVisibleTabs(tabOpts());
44
- const ids = tabs.map((t) => t.id);
45
- expect(ids).toContain("workspace");
46
- expect(ids).toContain("configure");
47
- expect(ids).toContain("usage");
48
- expect(ids).not.toContain("plan");
49
- expect(ids).not.toContain("changes");
50
- expect(ids).not.toContain("artifacts");
51
- expect(ids).not.toContain("inspect");
52
-
53
- const configTab = tabs.find((t) => t.id === "configure");
54
- expect(configTab?.label).toBe("Config");
55
- });
56
-
57
- // The Changes tab is exclusively the write-back (PR) surface: local file
58
- // changes render in the transcript (edit rows + decision bar) and no longer
59
- // surface — or badge — a tab.
60
- it("includes Changes with badge only when write-backs exist", () => {
61
- const tabs = buildVisibleTabs(tabOpts({ hasWriteBacks: true, writeBackCount: 3 }));
62
- const changesTab = tabs.find((t) => t.id === "changes");
63
- expect(changesTab).toBeDefined();
64
- expect(changesTab?.badge).toBe(3);
65
- });
66
-
67
- it("includes Artifacts with badge when artifacts exist", () => {
68
- const tabs = buildVisibleTabs(tabOpts({ hasArtifacts: true, artifactCount: 7 }));
69
- const artifactsTab = tabs.find((t) => t.id === "artifacts");
70
- expect(artifactsTab).toBeDefined();
71
- expect(artifactsTab?.badge).toBe(7);
72
- });
73
-
74
- it("includes Inspect when a thread item is selected", () => {
75
- const tabs = buildVisibleTabs(
76
- tabOpts({ selectedItem: { kind: "tool-call", toolCallId: "tc-1" } }),
77
- );
78
- const inspectTab = tabs.find((t) => t.id === "inspect");
79
- expect(inspectTab).toBeDefined();
80
- });
81
-
82
- it("orders tabs as Workspace, Config, then Usage with Inspect last", () => {
83
- const tabs = buildVisibleTabs(
84
- tabOpts({
85
- hasWriteBacks: true,
86
- writeBackCount: 2,
87
- hasArtifacts: true,
88
- artifactCount: 1,
89
- hasUsage: true,
90
- selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
91
- }),
92
- );
93
- const ids = tabs.map((t) => t.id);
94
- expect(ids.indexOf("workspace")).toBeLessThan(ids.indexOf("configure"));
95
- expect(ids.indexOf("configure")).toBeLessThan(ids.indexOf("usage"));
96
- expect(ids.indexOf("usage")).toBeLessThan(ids.indexOf("inspect"));
97
- });
98
-
99
- it("base tabs are present even when no optional tabs exist", () => {
100
- const tabs = buildVisibleTabs(tabOpts());
101
- const ids = tabs.map((t) => t.id);
102
- expect(ids).toEqual(["workspace", "configure", "usage"]);
103
- });
104
- });
105
-
106
- // ---------------------------------------------------------------------------
107
- // useSessionInspector FSM
108
- // ---------------------------------------------------------------------------
109
-
110
- describe("useSessionInspector", () => {
111
- it("defaults to workspace when no execution is active (phase=null)", () => {
112
- const { result } = renderHook(() => useSessionInspector(defaultOpts()));
113
- expect(result.current.activeTab).toBe("workspace");
114
- });
115
-
116
- it("defaults to workspace when execution is terminal", () => {
117
- const { result } = renderHook(() =>
118
- useSessionInspector(
119
- defaultOpts({ phase: ExecutionPhase.EXECUTION_COMPLETED }),
120
- ),
121
- );
122
- expect(result.current.activeTab).toBe("workspace");
123
- });
124
-
125
- it("defaults to workspace while execution is running (todos render inline, not in a tab)", () => {
126
- const { result } = renderHook(() =>
127
- useSessionInspector(
128
- defaultOpts({ phase: ExecutionPhase.EXECUTION_IN_PROGRESS }),
129
- ),
130
- );
131
- expect(result.current.activeTab).toBe("workspace");
132
- });
133
-
134
- it("auto-switches to inspect when a thread item is selected", () => {
135
- const { result, rerender } = renderHook(
136
- (props: UseSessionInspectorOptions) => useSessionInspector(props),
137
- { initialProps: defaultOpts() },
138
- );
139
- expect(result.current.activeTab).toBe("workspace");
140
-
141
- rerender(
142
- defaultOpts({ selectedItem: { kind: "tool-call", toolCallId: "tc-1" } }),
143
- );
144
- expect(result.current.activeTab).toBe("inspect");
145
- });
146
-
147
- it("reverts to workspace when selection is cleared (phase=null) and user did not pick a tab", () => {
148
- const { result, rerender } = renderHook(
149
- (props: UseSessionInspectorOptions) => useSessionInspector(props),
150
- {
151
- initialProps: defaultOpts({
152
- selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
153
- }),
154
- },
155
- );
156
- expect(result.current.activeTab).toBe("inspect");
157
-
158
- rerender(defaultOpts({ selectedItem: null }));
159
- expect(result.current.activeTab).toBe("workspace");
160
- });
161
-
162
- it("reverts to workspace when selection is cleared while execution is running", () => {
163
- const { result, rerender } = renderHook(
164
- (props: UseSessionInspectorOptions) => useSessionInspector(props),
165
- {
166
- initialProps: defaultOpts({
167
- phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
168
- selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
169
- }),
170
- },
171
- );
172
- expect(result.current.activeTab).toBe("inspect");
173
-
174
- rerender(
175
- defaultOpts({
176
- phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
177
- selectedItem: null,
178
- }),
179
- );
180
- expect(result.current.activeTab).toBe("workspace");
181
- });
182
-
183
- it("keeps user-picked tab sticky", () => {
184
- const { result, rerender } = renderHook(
185
- (props: UseSessionInspectorOptions) => useSessionInspector(props),
186
- { initialProps: defaultOpts({ hasUsage: true }) },
187
- );
188
-
189
- act(() => {
190
- result.current.onTabChange("usage");
191
- });
192
- expect(result.current.activeTab).toBe("usage");
193
-
194
- rerender(
195
- defaultOpts({
196
- hasUsage: true,
197
- selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
198
- }),
199
- );
200
- expect(result.current.activeTab).toBe("usage");
201
- });
202
-
203
- it("auto-switches to changes when first write-back arrives", () => {
204
- const { result, rerender } = renderHook(
205
- (props: UseSessionInspectorOptions) => useSessionInspector(props),
206
- { initialProps: defaultOpts() },
207
- );
208
- expect(result.current.activeTab).toBe("workspace");
209
-
210
- rerender(
211
- defaultOpts({ hasWriteBacks: true, writeBackCount: 1 }),
212
- );
213
- expect(result.current.activeTab).toBe("changes");
214
- });
215
-
216
- it("falls back to workspace when active tab is removed from visible tabs (phase=null)", () => {
217
- const { result, rerender } = renderHook(
218
- (props: UseSessionInspectorOptions) => useSessionInspector(props),
219
- {
220
- initialProps: defaultOpts({
221
- selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
222
- }),
223
- },
224
- );
225
- expect(result.current.activeTab).toBe("inspect");
226
-
227
- act(() => {
228
- result.current.onTabChange("inspect");
229
- });
230
-
231
- rerender(defaultOpts({ selectedItem: null }));
232
- expect(result.current.activeTab).toBe("workspace");
233
- });
234
-
235
- it("stays on workspace across the running → terminal transition", () => {
236
- const { result, rerender } = renderHook(
237
- (props: UseSessionInspectorOptions) => useSessionInspector(props),
238
- {
239
- initialProps: defaultOpts({
240
- phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
241
- }),
242
- },
243
- );
244
- expect(result.current.activeTab).toBe("workspace");
245
-
246
- rerender(
247
- defaultOpts({ phase: ExecutionPhase.EXECUTION_COMPLETED }),
248
- );
249
- expect(result.current.activeTab).toBe("workspace");
250
- });
251
- });
@@ -1,178 +0,0 @@
1
- "use client";
2
-
3
- import { useCallback, useRef, useState } from "react";
4
- import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
- import type { TabItem } from "../../tabs/Tabs.js";
6
- import { isTerminalPhase } from "../../execution/execution-phases.js";
7
- import type { SelectedThreadItem } from "../../internal/store/selection-store.js";
8
-
9
- export type SessionInspectorTabId =
10
- | "workspace"
11
- | "configure"
12
- | "changes"
13
- | "artifacts"
14
- | "usage"
15
- | "inspect";
16
-
17
- export interface UseSessionInspectorOptions {
18
- readonly phase: ExecutionPhase | null;
19
- readonly hasWriteBacks: boolean;
20
- readonly writeBackCount: number;
21
- readonly hasArtifacts: boolean;
22
- readonly artifactCount: number;
23
- readonly hasUsage: boolean;
24
- readonly selectedItem: SelectedThreadItem | null;
25
- }
26
-
27
- export interface UseSessionInspectorReturn {
28
- readonly tabs: readonly TabItem[];
29
- readonly activeTab: SessionInspectorTabId;
30
- readonly onTabChange: (tabId: string) => void;
31
- }
32
-
33
- /**
34
- * Compute the system-suggested tab from selection.
35
- *
36
- * Priority:
37
- * 1. Thread item selected -> "inspect"
38
- * 2. Otherwise -> "workspace"
39
- *
40
- * Live execution progress (the agent's plan and todos) now renders inline in
41
- * the message thread as a {@link TodoCard}, not in a sidebar tab — so a running
42
- * execution no longer steers the inspector to a dedicated facet.
43
- */
44
- function deriveAutoTab(
45
- selectedItem: SelectedThreadItem | null,
46
- ): SessionInspectorTabId {
47
- if (selectedItem) return "inspect";
48
- return "workspace";
49
- }
50
-
51
- /**
52
- * Build the contextual tab list with badges.
53
- *
54
- * Tab order follows the user's mental model — context before output:
55
- * Workspace → Config → Usage. Changes and Artifacts appear after Config
56
- * when data exists; Inspect appears last when a thread item is selected.
57
- *
58
- * The Changes tab surfaces only when git write-backs (PRs) exist, badged
59
- * with their count. Local-workspace file edits never surface a tab: they
60
- * render in the transcript (stamped edit rows + the per-turn decision bar),
61
- * which is their single review surface.
62
- */
63
- export function buildVisibleTabs(opts: {
64
- hasWriteBacks: boolean;
65
- writeBackCount: number;
66
- hasArtifacts: boolean;
67
- artifactCount: number;
68
- hasUsage: boolean;
69
- selectedItem: SelectedThreadItem | null;
70
- }): TabItem[] {
71
- const tabs: TabItem[] = [
72
- { id: "workspace", label: "Workspace" },
73
- { id: "configure", label: "Config" },
74
- ];
75
-
76
- if (opts.hasWriteBacks) {
77
- tabs.push({
78
- id: "changes",
79
- label: "Changes",
80
- badge: opts.writeBackCount,
81
- });
82
- }
83
-
84
- if (opts.hasArtifacts) {
85
- tabs.push({
86
- id: "artifacts",
87
- label: "Artifacts",
88
- badge: opts.artifactCount,
89
- });
90
- }
91
-
92
- tabs.push({ id: "usage", label: "Usage" });
93
-
94
- if (opts.selectedItem) {
95
- tabs.push({ id: "inspect", label: "Inspect" });
96
- }
97
-
98
- return tabs;
99
- }
100
-
101
- /**
102
- * Behavior hook for SessionInspector tab state management.
103
- *
104
- * Uses the "adjust state during render" pattern from the workflow
105
- * `ExecutionInspector`: shadow `prevPhase`/`prevSelected` state,
106
- * `userPickedTabRef` for sticky manual picks, and `deriveAutoTab`
107
- * for system suggestions. Keeps the user's tab pick sticky until
108
- * a meaningful state change resets it.
109
- */
110
- export function useSessionInspector(
111
- opts: UseSessionInspectorOptions,
112
- ): UseSessionInspectorReturn {
113
- const { phase, hasWriteBacks, writeBackCount, hasArtifacts, artifactCount, hasUsage, selectedItem } = opts;
114
-
115
- const tabs = buildVisibleTabs({ hasWriteBacks, writeBackCount, hasArtifacts, artifactCount, hasUsage, selectedItem });
116
-
117
- // A write-back (the session's only tab-worthy change source) surfaces and
118
- // auto-selects the Changes tab on first arrival.
119
- const hasChanges = hasWriteBacks;
120
-
121
- const [activeTab, setActiveTab] = useState<SessionInspectorTabId>(
122
- () => deriveAutoTab(selectedItem),
123
- );
124
- const [prevPhase, setPrevPhase] = useState(phase);
125
- const [prevSelected, setPrevSelected] = useState(selectedItem);
126
- const [prevHasChanges, setPrevHasChanges] = useState(hasChanges);
127
- const userPickedTabRef = useRef(false);
128
-
129
- // Selection changed → auto-switch to inspect (unless user picked)
130
- if (selectedItem !== prevSelected) {
131
- setPrevSelected(selectedItem);
132
- if (selectedItem && !userPickedTabRef.current) {
133
- setActiveTab("inspect");
134
- }
135
- if (!selectedItem && activeTab === "inspect") {
136
- setActiveTab(deriveAutoTab(null));
137
- userPickedTabRef.current = false;
138
- }
139
- }
140
-
141
- // Phase changed → reset user pick if transitioning from non-terminal to terminal or vice versa
142
- if (phase !== prevPhase) {
143
- const wasTerminal = prevPhase !== null && isTerminalPhase(prevPhase);
144
- const isNowTerminal = phase !== null && isTerminalPhase(phase);
145
- setPrevPhase(phase);
146
- if (wasTerminal !== isNowTerminal) {
147
- userPickedTabRef.current = false;
148
- setActiveTab(deriveAutoTab(selectedItem));
149
- }
150
- }
151
-
152
- // First write-back arrived → auto-switch to changes
153
- if (hasChanges && !prevHasChanges) {
154
- setPrevHasChanges(hasChanges);
155
- if (!userPickedTabRef.current) {
156
- setActiveTab("changes");
157
- }
158
- }
159
- if (hasChanges !== prevHasChanges) {
160
- setPrevHasChanges(hasChanges);
161
- }
162
-
163
- // Ensure active tab is valid (the selected tab may have been removed)
164
- const effectiveTab = tabs.some((t) => t.id === activeTab)
165
- ? activeTab
166
- : deriveAutoTab(selectedItem);
167
-
168
- const onTabChange = useCallback((tabId: string) => {
169
- userPickedTabRef.current = true;
170
- setActiveTab(tabId as SessionInspectorTabId);
171
- }, []);
172
-
173
- return {
174
- tabs,
175
- activeTab: effectiveTab,
176
- onTabChange,
177
- };
178
- }