@stigmer/react 3.1.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (426) hide show
  1. package/composer/SessionComposer.d.ts +24 -1
  2. package/composer/SessionComposer.d.ts.map +1 -1
  3. package/composer/SessionComposer.js +19 -8
  4. package/composer/SessionComposer.js.map +1 -1
  5. package/execution/ArtifactContentRenderer.d.ts +11 -1
  6. package/execution/ArtifactContentRenderer.d.ts.map +1 -1
  7. package/execution/ArtifactContentRenderer.js +39 -15
  8. package/execution/ArtifactContentRenderer.js.map +1 -1
  9. package/execution/FilePathContext.d.ts +8 -1
  10. package/execution/FilePathContext.d.ts.map +1 -1
  11. package/execution/FilePathContext.js.map +1 -1
  12. package/execution/FilePathLink.d.ts.map +1 -1
  13. package/execution/FilePathLink.js +21 -6
  14. package/execution/FilePathLink.js.map +1 -1
  15. package/execution/MessageEntry.d.ts +29 -0
  16. package/execution/MessageEntry.d.ts.map +1 -1
  17. package/execution/MessageEntry.js +29 -5
  18. package/execution/MessageEntry.js.map +1 -1
  19. package/execution/MessageThread.d.ts +76 -13
  20. package/execution/MessageThread.d.ts.map +1 -1
  21. package/execution/MessageThread.js +178 -24
  22. package/execution/MessageThread.js.map +1 -1
  23. package/execution/PlanArtifactCard.d.ts +27 -18
  24. package/execution/PlanArtifactCard.d.ts.map +1 -1
  25. package/execution/PlanArtifactCard.js +13 -23
  26. package/execution/PlanArtifactCard.js.map +1 -1
  27. package/execution/PlanDocumentMessage.d.ts +32 -0
  28. package/execution/PlanDocumentMessage.d.ts.map +1 -0
  29. package/execution/PlanDocumentMessage.js +37 -0
  30. package/execution/PlanDocumentMessage.js.map +1 -0
  31. package/execution/PlanStreamingCard.d.ts +45 -0
  32. package/execution/PlanStreamingCard.d.ts.map +1 -0
  33. package/execution/PlanStreamingCard.js +35 -0
  34. package/execution/PlanStreamingCard.js.map +1 -0
  35. package/execution/index.d.ts +5 -1
  36. package/execution/index.d.ts.map +1 -1
  37. package/execution/index.js +2 -0
  38. package/execution/index.js.map +1 -1
  39. package/execution/useCreateAgentExecution.d.ts +10 -0
  40. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  41. package/execution/useCreateAgentExecution.js +5 -1
  42. package/execution/useCreateAgentExecution.js.map +1 -1
  43. package/github/decodeGitHubContent.d.ts +29 -0
  44. package/github/decodeGitHubContent.d.ts.map +1 -0
  45. package/github/decodeGitHubContent.js +72 -0
  46. package/github/decodeGitHubContent.js.map +1 -0
  47. package/github/index.d.ts +1 -0
  48. package/github/index.d.ts.map +1 -1
  49. package/github/index.js +1 -0
  50. package/github/index.js.map +1 -1
  51. package/github/useGitHubFileReader.d.ts +26 -0
  52. package/github/useGitHubFileReader.d.ts.map +1 -0
  53. package/github/useGitHubFileReader.js +106 -0
  54. package/github/useGitHubFileReader.js.map +1 -0
  55. package/github/useGitHubTreeLister.d.ts.map +1 -1
  56. package/github/useGitHubTreeLister.js +6 -2
  57. package/github/useGitHubTreeLister.js.map +1 -1
  58. package/index.d.ts +9 -9
  59. package/index.d.ts.map +1 -1
  60. package/index.js +5 -5
  61. package/index.js.map +1 -1
  62. package/internal/ResizableSplit.d.ts +72 -22
  63. package/internal/ResizableSplit.d.ts.map +1 -1
  64. package/internal/ResizableSplit.js +96 -38
  65. package/internal/ResizableSplit.js.map +1 -1
  66. package/internal/VirtualizedThread.d.ts +5 -3
  67. package/internal/VirtualizedThread.d.ts.map +1 -1
  68. package/internal/VirtualizedThread.js +6 -4
  69. package/internal/VirtualizedThread.js.map +1 -1
  70. package/internal/file-icons/index.d.ts +17 -0
  71. package/internal/file-icons/index.d.ts.map +1 -0
  72. package/internal/file-icons/index.js +60 -0
  73. package/internal/file-icons/index.js.map +1 -0
  74. package/internal/file-tree/FileTreeNode.d.ts +18 -1
  75. package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
  76. package/internal/file-tree/FileTreeNode.js +11 -2
  77. package/internal/file-tree/FileTreeNode.js.map +1 -1
  78. package/internal/markdown-components.d.ts +38 -1
  79. package/internal/markdown-components.d.ts.map +1 -1
  80. package/internal/markdown-components.js +86 -11
  81. package/internal/markdown-components.js.map +1 -1
  82. package/{workflow → internal}/motion-preference.d.ts +7 -4
  83. package/internal/motion-preference.d.ts.map +1 -0
  84. package/{workflow → internal}/motion-preference.js +7 -4
  85. package/internal/motion-preference.js.map +1 -0
  86. package/internal/store/index.d.ts +33 -0
  87. package/internal/store/index.d.ts.map +1 -1
  88. package/internal/store/index.js +59 -0
  89. package/internal/store/index.js.map +1 -1
  90. package/internal/store/workspace-editors-store.d.ts +145 -0
  91. package/internal/store/workspace-editors-store.d.ts.map +1 -0
  92. package/internal/store/workspace-editors-store.js +208 -0
  93. package/internal/store/workspace-editors-store.js.map +1 -0
  94. package/internal/store/workspace-file-selection-store.d.ts +38 -0
  95. package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
  96. package/internal/store/workspace-file-selection-store.js +62 -0
  97. package/internal/store/workspace-file-selection-store.js.map +1 -0
  98. package/internal/useRevealLine.d.ts +49 -0
  99. package/internal/useRevealLine.d.ts.map +1 -0
  100. package/internal/useRevealLine.js +43 -0
  101. package/internal/useRevealLine.js.map +1 -0
  102. package/library/detect-plan-artifact.d.ts +21 -0
  103. package/library/detect-plan-artifact.d.ts.map +1 -1
  104. package/library/detect-plan-artifact.js +20 -0
  105. package/library/detect-plan-artifact.js.map +1 -1
  106. package/library/detect-streaming-plan.d.ts +45 -0
  107. package/library/detect-streaming-plan.d.ts.map +1 -0
  108. package/library/detect-streaming-plan.js +83 -0
  109. package/library/detect-streaming-plan.js.map +1 -0
  110. package/library/index.d.ts +4 -1
  111. package/library/index.d.ts.map +1 -1
  112. package/library/index.js +2 -1
  113. package/library/index.js.map +1 -1
  114. package/package.json +4 -4
  115. package/session/NewSessionViewer.d.ts +19 -4
  116. package/session/NewSessionViewer.d.ts.map +1 -1
  117. package/session/NewSessionViewer.js +52 -25
  118. package/session/NewSessionViewer.js.map +1 -1
  119. package/session/PlanEditor.d.ts +55 -0
  120. package/session/PlanEditor.d.ts.map +1 -0
  121. package/session/PlanEditor.js +88 -0
  122. package/session/PlanEditor.js.map +1 -0
  123. package/session/PlanStreamingDocument.d.ts +30 -0
  124. package/session/PlanStreamingDocument.d.ts.map +1 -0
  125. package/session/PlanStreamingDocument.js +37 -0
  126. package/session/PlanStreamingDocument.js.map +1 -0
  127. package/session/SessionPanelChip.d.ts +26 -0
  128. package/session/SessionPanelChip.d.ts.map +1 -0
  129. package/session/SessionPanelChip.js +40 -0
  130. package/session/SessionPanelChip.js.map +1 -0
  131. package/session/SessionViewer.d.ts +34 -7
  132. package/session/SessionViewer.d.ts.map +1 -1
  133. package/session/SessionViewer.js +315 -33
  134. package/session/SessionViewer.js.map +1 -1
  135. package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
  136. package/session/facets/ArtifactsTab.d.ts.map +1 -0
  137. package/session/{inspector → facets}/ArtifactsTab.js +8 -3
  138. package/session/facets/ArtifactsTab.js.map +1 -0
  139. package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
  140. package/session/facets/ChangesTab.d.ts.map +1 -0
  141. package/session/{inspector → facets}/ChangesTab.js +3 -3
  142. package/session/facets/ChangesTab.js.map +1 -0
  143. package/session/facets/InspectTab.d.ts.map +1 -0
  144. package/session/facets/InspectTab.js.map +1 -0
  145. package/session/{inspector → facets}/SetupTab.d.ts +11 -2
  146. package/session/facets/SetupTab.d.ts.map +1 -0
  147. package/session/{inspector → facets}/SetupTab.js +4 -3
  148. package/session/facets/SetupTab.js.map +1 -0
  149. package/session/{inspector → facets}/UsageTab.d.ts +1 -1
  150. package/session/facets/UsageTab.d.ts.map +1 -0
  151. package/session/{inspector → facets}/UsageTab.js +1 -1
  152. package/session/facets/UsageTab.js.map +1 -0
  153. package/session/{inspector → facets}/index.d.ts +0 -6
  154. package/session/facets/index.d.ts.map +1 -0
  155. package/session/{inspector → facets}/index.js +0 -3
  156. package/session/facets/index.js.map +1 -0
  157. package/session/index.d.ts +11 -2
  158. package/session/index.d.ts.map +1 -1
  159. package/session/index.js +15 -2
  160. package/session/index.js.map +1 -1
  161. package/session/plan-document.d.ts +9 -0
  162. package/session/plan-document.d.ts.map +1 -0
  163. package/session/plan-document.js +17 -0
  164. package/session/plan-document.js.map +1 -0
  165. package/session/useOpenFileChange.d.ts +20 -0
  166. package/session/useOpenFileChange.d.ts.map +1 -0
  167. package/session/useOpenFileChange.js +31 -0
  168. package/session/useOpenFileChange.js.map +1 -0
  169. package/session/usePlanDraft.d.ts +52 -0
  170. package/session/usePlanDraft.d.ts.map +1 -0
  171. package/session/usePlanDraft.js +63 -0
  172. package/session/usePlanDraft.js.map +1 -0
  173. package/session/useSessionConversation.d.ts +6 -0
  174. package/session/useSessionConversation.d.ts.map +1 -1
  175. package/session/useSessionConversation.js +1 -0
  176. package/session/useSessionConversation.js.map +1 -1
  177. package/session/useSessionPageFlow.d.ts.map +1 -1
  178. package/session/useSessionPageFlow.js +1 -0
  179. package/session/useSessionPageFlow.js.map +1 -1
  180. package/session/useSessionPanel.d.ts +120 -0
  181. package/session/useSessionPanel.d.ts.map +1 -0
  182. package/session/useSessionPanel.js +130 -0
  183. package/session/useSessionPanel.js.map +1 -0
  184. package/session/useSessionRailViews.d.ts +45 -0
  185. package/session/useSessionRailViews.d.ts.map +1 -0
  186. package/session/useSessionRailViews.js +105 -0
  187. package/session/useSessionRailViews.js.map +1 -0
  188. package/src/composer/SessionComposer.tsx +52 -10
  189. package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
  190. package/src/execution/ArtifactContentRenderer.tsx +101 -24
  191. package/src/execution/FilePathContext.tsx +8 -1
  192. package/src/execution/FilePathLink.tsx +22 -6
  193. package/src/execution/MessageEntry.tsx +111 -1
  194. package/src/execution/MessageThread.tsx +291 -36
  195. package/src/execution/PlanArtifactCard.tsx +63 -31
  196. package/src/execution/PlanDocumentMessage.tsx +96 -0
  197. package/src/execution/PlanStreamingCard.tsx +137 -0
  198. package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
  199. package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
  200. package/src/execution/__tests__/MessageThread.test.tsx +101 -0
  201. package/src/execution/__tests__/PlanArtifactCard.test.tsx +66 -12
  202. package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
  203. package/src/execution/__tests__/PlanStreamingCard.test.tsx +49 -0
  204. package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +504 -22
  205. package/src/execution/__tests__/message-entry.test.tsx +48 -0
  206. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
  207. package/src/execution/index.ts +7 -1
  208. package/src/execution/useCreateAgentExecution.ts +16 -1
  209. package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
  210. package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
  211. package/src/github/decodeGitHubContent.ts +83 -0
  212. package/src/github/index.ts +1 -0
  213. package/src/github/useGitHubFileReader.ts +152 -0
  214. package/src/github/useGitHubTreeLister.ts +6 -2
  215. package/src/index.ts +63 -9
  216. package/src/internal/ResizableSplit.tsx +184 -51
  217. package/src/internal/VirtualizedThread.tsx +12 -4
  218. package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
  219. package/src/internal/__tests__/markdown-components.test.tsx +68 -0
  220. package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
  221. package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
  222. package/src/internal/file-icons/index.tsx +137 -0
  223. package/src/internal/file-tree/FileTreeNode.tsx +43 -3
  224. package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
  225. package/src/internal/markdown-components.tsx +116 -11
  226. package/src/{workflow → internal}/motion-preference.ts +7 -4
  227. package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
  228. package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
  229. package/src/internal/store/index.ts +94 -0
  230. package/src/internal/store/workspace-editors-store.ts +315 -0
  231. package/src/internal/store/workspace-file-selection-store.ts +88 -0
  232. package/src/internal/useRevealLine.ts +81 -0
  233. package/src/library/__tests__/detect-plan-artifact.test.ts +48 -0
  234. package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
  235. package/src/library/detect-plan-artifact.ts +35 -0
  236. package/src/library/detect-streaming-plan.ts +108 -0
  237. package/src/library/index.ts +5 -0
  238. package/src/session/NewSessionViewer.tsx +123 -55
  239. package/src/session/PlanEditor.tsx +361 -0
  240. package/src/session/PlanStreamingDocument.tsx +97 -0
  241. package/src/session/SessionPanelChip.tsx +103 -0
  242. package/src/session/SessionViewer.tsx +617 -90
  243. package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
  244. package/src/session/__tests__/PlanEditor.test.tsx +217 -0
  245. package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
  246. package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
  247. package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +9 -4
  248. package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
  249. package/src/session/__tests__/audienceWiring.test.tsx +55 -19
  250. package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
  251. package/src/session/__tests__/usePlanDraft.test.ts +102 -0
  252. package/src/session/__tests__/useSessionPanel.test.ts +298 -0
  253. package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
  254. package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
  255. package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
  256. package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
  257. package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
  258. package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +35 -1
  259. package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
  260. package/src/session/{inspector → facets}/index.ts +0 -16
  261. package/src/session/index.ts +30 -13
  262. package/src/session/plan-document.ts +19 -0
  263. package/src/session/useOpenFileChange.ts +53 -0
  264. package/src/session/usePlanDraft.ts +109 -0
  265. package/src/session/useSessionConversation.ts +7 -0
  266. package/src/session/useSessionPageFlow.ts +1 -0
  267. package/src/session/useSessionPanel.ts +288 -0
  268. package/src/session/useSessionRailViews.tsx +200 -0
  269. package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
  270. package/src/workflow/index.ts +1 -1
  271. package/src/workflow/useFollowExecution.ts +1 -1
  272. package/src/workspace/EditorTabs.tsx +145 -0
  273. package/src/workspace/ExplorerTree.tsx +247 -0
  274. package/src/workspace/FileViewer.tsx +516 -0
  275. package/src/workspace/WorkspaceContentSearch.tsx +478 -0
  276. package/src/workspace/WorkspaceContentSearcher.ts +70 -0
  277. package/src/workspace/WorkspaceFileLister.ts +11 -0
  278. package/src/workspace/WorkspaceFileReader.ts +57 -0
  279. package/src/workspace/WorkspaceFileSearch.tsx +429 -0
  280. package/src/workspace/WorkspaceSurface.tsx +781 -0
  281. package/src/workspace/__tests__/EditorTabs.test.tsx +100 -0
  282. package/src/workspace/__tests__/ExplorerTree.test.tsx +152 -0
  283. package/src/workspace/__tests__/FileViewer.test.tsx +421 -0
  284. package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +196 -0
  285. package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +206 -0
  286. package/src/workspace/__tests__/WorkspaceSurface.test.tsx +348 -0
  287. package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
  288. package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
  289. package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
  290. package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
  291. package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
  292. package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
  293. package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
  294. package/src/workspace/findChangeForSelection.ts +61 -0
  295. package/src/workspace/index.ts +56 -2
  296. package/src/workspace/matchContentPreview.ts +51 -0
  297. package/src/workspace/matchWorkspaceFiles.ts +86 -0
  298. package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
  299. package/src/workspace/useWorkspaceContentSearch.ts +228 -0
  300. package/src/workspace/useWorkspaceFileContent.ts +129 -0
  301. package/src/workspace/useWorkspaceFileSearch.ts +184 -0
  302. package/src/workspace/useWorkspaceFiles.ts +27 -27
  303. package/src/workspace/workspaceListingCache.ts +93 -0
  304. package/styles.css +1 -1
  305. package/workflow/WorkflowExecutionGraph.js +1 -1
  306. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  307. package/workflow/index.d.ts +1 -1
  308. package/workflow/index.d.ts.map +1 -1
  309. package/workflow/index.js +1 -1
  310. package/workflow/index.js.map +1 -1
  311. package/workflow/useFollowExecution.js +1 -1
  312. package/workflow/useFollowExecution.js.map +1 -1
  313. package/workspace/EditorTabs.d.ts +29 -0
  314. package/workspace/EditorTabs.d.ts.map +1 -0
  315. package/workspace/EditorTabs.js +66 -0
  316. package/workspace/EditorTabs.js.map +1 -0
  317. package/workspace/ExplorerTree.d.ts +32 -0
  318. package/workspace/ExplorerTree.d.ts.map +1 -0
  319. package/workspace/ExplorerTree.js +45 -0
  320. package/workspace/ExplorerTree.js.map +1 -0
  321. package/workspace/FileViewer.d.ts +93 -0
  322. package/workspace/FileViewer.d.ts.map +1 -0
  323. package/workspace/FileViewer.js +182 -0
  324. package/workspace/FileViewer.js.map +1 -0
  325. package/workspace/WorkspaceContentSearch.d.ts +41 -0
  326. package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
  327. package/workspace/WorkspaceContentSearch.js +195 -0
  328. package/workspace/WorkspaceContentSearch.js.map +1 -0
  329. package/workspace/WorkspaceContentSearcher.d.ts +59 -0
  330. package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
  331. package/workspace/WorkspaceContentSearcher.js +7 -0
  332. package/workspace/WorkspaceContentSearcher.js.map +1 -0
  333. package/workspace/WorkspaceFileLister.d.ts +11 -0
  334. package/workspace/WorkspaceFileLister.d.ts.map +1 -1
  335. package/workspace/WorkspaceFileReader.d.ts +48 -0
  336. package/workspace/WorkspaceFileReader.d.ts.map +1 -0
  337. package/workspace/WorkspaceFileReader.js +11 -0
  338. package/workspace/WorkspaceFileReader.js.map +1 -0
  339. package/workspace/WorkspaceFileSearch.d.ts +32 -0
  340. package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
  341. package/workspace/WorkspaceFileSearch.js +155 -0
  342. package/workspace/WorkspaceFileSearch.js.map +1 -0
  343. package/workspace/WorkspaceSurface.d.ts +151 -0
  344. package/workspace/WorkspaceSurface.d.ts.map +1 -0
  345. package/workspace/WorkspaceSurface.js +184 -0
  346. package/workspace/WorkspaceSurface.js.map +1 -0
  347. package/workspace/findChangeForSelection.d.ts +19 -0
  348. package/workspace/findChangeForSelection.d.ts.map +1 -0
  349. package/workspace/findChangeForSelection.js +46 -0
  350. package/workspace/findChangeForSelection.js.map +1 -0
  351. package/workspace/index.d.ts +24 -2
  352. package/workspace/index.d.ts.map +1 -1
  353. package/workspace/index.js +13 -1
  354. package/workspace/index.js.map +1 -1
  355. package/workspace/matchContentPreview.d.ts +21 -0
  356. package/workspace/matchContentPreview.d.ts.map +1 -0
  357. package/workspace/matchContentPreview.js +36 -0
  358. package/workspace/matchContentPreview.js.map +1 -0
  359. package/workspace/matchWorkspaceFiles.d.ts +30 -0
  360. package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
  361. package/workspace/matchWorkspaceFiles.js +58 -0
  362. package/workspace/matchWorkspaceFiles.js.map +1 -0
  363. package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
  364. package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
  365. package/workspace/resolveWorkspaceFileSelection.js +115 -0
  366. package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
  367. package/workspace/useWorkspaceContentSearch.d.ts +69 -0
  368. package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
  369. package/workspace/useWorkspaceContentSearch.js +154 -0
  370. package/workspace/useWorkspaceContentSearch.js.map +1 -0
  371. package/workspace/useWorkspaceFileContent.d.ts +73 -0
  372. package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
  373. package/workspace/useWorkspaceFileContent.js +57 -0
  374. package/workspace/useWorkspaceFileContent.js.map +1 -0
  375. package/workspace/useWorkspaceFileSearch.d.ts +61 -0
  376. package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
  377. package/workspace/useWorkspaceFileSearch.js +119 -0
  378. package/workspace/useWorkspaceFileSearch.js.map +1 -0
  379. package/workspace/useWorkspaceFiles.d.ts +13 -5
  380. package/workspace/useWorkspaceFiles.d.ts.map +1 -1
  381. package/workspace/useWorkspaceFiles.js +18 -19
  382. package/workspace/useWorkspaceFiles.js.map +1 -1
  383. package/workspace/workspaceListingCache.d.ts +47 -0
  384. package/workspace/workspaceListingCache.d.ts.map +1 -0
  385. package/workspace/workspaceListingCache.js +55 -0
  386. package/workspace/workspaceListingCache.js.map +1 -0
  387. package/session/inspector/ArtifactsTab.d.ts.map +0 -1
  388. package/session/inspector/ArtifactsTab.js.map +0 -1
  389. package/session/inspector/ChangesTab.d.ts.map +0 -1
  390. package/session/inspector/ChangesTab.js.map +0 -1
  391. package/session/inspector/InspectTab.d.ts.map +0 -1
  392. package/session/inspector/InspectTab.js.map +0 -1
  393. package/session/inspector/SessionInspector.d.ts +0 -64
  394. package/session/inspector/SessionInspector.d.ts.map +0 -1
  395. package/session/inspector/SessionInspector.js +0 -53
  396. package/session/inspector/SessionInspector.js.map +0 -1
  397. package/session/inspector/SetupTab.d.ts.map +0 -1
  398. package/session/inspector/SetupTab.js.map +0 -1
  399. package/session/inspector/UsageTab.d.ts.map +0 -1
  400. package/session/inspector/UsageTab.js.map +0 -1
  401. package/session/inspector/WorkspaceTab.d.ts +0 -35
  402. package/session/inspector/WorkspaceTab.d.ts.map +0 -1
  403. package/session/inspector/WorkspaceTab.js +0 -75
  404. package/session/inspector/WorkspaceTab.js.map +0 -1
  405. package/session/inspector/index.d.ts.map +0 -1
  406. package/session/inspector/index.js.map +0 -1
  407. package/session/inspector/useSessionInspector.d.ts +0 -49
  408. package/session/inspector/useSessionInspector.d.ts.map +0 -1
  409. package/session/inspector/useSessionInspector.js +0 -122
  410. package/session/inspector/useSessionInspector.js.map +0 -1
  411. package/src/session/inspector/SessionInspector.tsx +0 -162
  412. package/src/session/inspector/WorkspaceTab.tsx +0 -245
  413. package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
  414. package/src/session/inspector/useSessionInspector.ts +0 -178
  415. package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
  416. package/workflow/motion-preference.d.ts.map +0 -1
  417. package/workflow/motion-preference.js.map +0 -1
  418. package/workspace/WorkspaceEntryFiles.d.ts +0 -22
  419. package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
  420. package/workspace/WorkspaceEntryFiles.js +0 -58
  421. package/workspace/WorkspaceEntryFiles.js.map +0 -1
  422. /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
  423. /package/session/{inspector → facets}/InspectTab.js +0 -0
  424. /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
  425. /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
  426. /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
@@ -0,0 +1,288 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import type { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
+ import { isTerminalPhase } from "../execution/execution-phases.js";
6
+ import type { SelectedThreadItem } from "../internal/store/selection-store.js";
7
+ import {
8
+ useWorkspaceEditorsStoreRef,
9
+ type OpenFileOptions,
10
+ type WorkspaceEditorsStore,
11
+ } from "../internal/store/index.js";
12
+ import { PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH } from "./plan-document.js";
13
+
14
+ /** Options for {@link useSessionPanel}. */
15
+ export interface UseSessionPanelOptions {
16
+ /**
17
+ * The display execution's phase, or `null` before any execution exists.
18
+ * A transition between running and terminal resets the user's sticky view
19
+ * pick (mirroring the retired inspector-tab FSM).
20
+ */
21
+ readonly phase: ExecutionPhase | null;
22
+ /**
23
+ * Whether the session has git write-backs. The first arrival auto-surfaces
24
+ * the Changes view — but only while the panel is open; a collapsed panel
25
+ * signals through badges instead of pulling the user out of the chat.
26
+ */
27
+ readonly hasChanges: boolean;
28
+ /**
29
+ * Identity of the session's current plan, or `null` when none exists. Two
30
+ * identity families, supplied by the viewer: `<executionId>:streaming`
31
+ * while the active turn is WRITING a plan (see `findStreamingPlan`), then
32
+ * the published identity (`planDraftKey`) once the artifact exists. A NEW
33
+ * identity — a plan starting to stream, the first published plan, or a
34
+ * refined plan superseding it — auto-opens the plan document tab (see
35
+ * {@link SessionPanelController.openPlanDocument}), expanding a collapsed
36
+ * panel. This deliberately breaks the Changes/Inspect "never open a
37
+ * collapsed panel" convention: a plan is not ambient state, it is the
38
+ * deliverable of the turn the user just requested, and with the thread
39
+ * showing only a compact card there is no other review surface — live or
40
+ * settled. The streaming→published transition is itself a new identity,
41
+ * harmlessly re-firing the (idempotent) open as the tab's content settles.
42
+ * Keyed on plan IDENTITY, not presence, so a refined plan re-surfaces too;
43
+ * the identity present at mount is swallowed (loading a session with an
44
+ * old plan — or mid-stream — never hijacks the layout).
45
+ */
46
+ readonly planKey?: string | null;
47
+ /**
48
+ * The panel's home view — the view it opens on and the one every automatic
49
+ * reset returns to (running⇄terminal transition, selection cleared). Defaults
50
+ * to `"files"` (the Explorer), which suits the session viewer. The launcher
51
+ * passes `"configure"`: pre-session there is no workspace, so the Config
52
+ * facet — carrying the run defaults (harness/model) — is the useful landing
53
+ * view. Auto-switches (Changes/Inspect) and explicit rail picks still
54
+ * take over from here exactly as before.
55
+ *
56
+ * @default "files"
57
+ */
58
+ readonly defaultView?: string;
59
+ }
60
+
61
+ /**
62
+ * State + actions for the unified session panel, shared by every viewer that
63
+ * hosts it (session + launcher) so they behave identically (DD-016).
64
+ *
65
+ * The panel is the one right-side surface: a workspace surface whose activity
66
+ * rail hosts the session facets (see `useSessionRailViews`). It replaces the
67
+ * former two-view model (narrow inspector ⇄ workspace-mode flip): the panel is
68
+ * **collapsed by default** to a top-right chip, and `isOpen` + `view` describe
69
+ * it fully.
70
+ *
71
+ * Owns the {@link WorkspaceEditorsStore} (the open-editor group) and the view
72
+ * FSM ported from the retired inspector tabs: explicit picks are sticky until
73
+ * a meaningful state change (selection cleared, running⇄terminal transition)
74
+ * resets them back to the `defaultView`. Both are decoupled from any store
75
+ * subscription at the owner level: callbacks mutate imperatively so a file
76
+ * open/switch re-renders only the subscribing panel subtree, never the
77
+ * streaming conversation column (DD-009/DD-010, invariant 2).
78
+ */
79
+ export interface SessionPanelController {
80
+ /** The open-editor group store; subscribe with `useWorkspaceEditors`. */
81
+ readonly editorsStore: WorkspaceEditorsStore;
82
+ /** Whether the panel is expanded (chat narrow) or collapsed to the chip. */
83
+ readonly isOpen: boolean;
84
+ /** The active rail view id (`"files"`, `"search"`, or an injected facet). */
85
+ readonly view: string;
86
+ /** Expand the panel, restoring the previous view (or Inspect if a thread item is selected). */
87
+ readonly openPanel: () => void;
88
+ /** Collapse the panel to the chip, preserving editors and view. */
89
+ readonly closePanel: () => void;
90
+ /** Explicit view pick from the rail — sticky against auto-switching. */
91
+ readonly setView: (viewId: string) => void;
92
+ /**
93
+ * Open a file as a preview tab and expand the panel. Pass `options.line` to
94
+ * jump to and highlight a specific 1-based line (e.g. a content-search hit) —
95
+ * the file opens in its line-faithful File view scrolled to that line.
96
+ */
97
+ readonly openFile: (
98
+ entryId: string,
99
+ path: string,
100
+ options?: OpenFileOptions,
101
+ ) => void;
102
+ /** Focus an already-open editor tab. */
103
+ readonly activateEditor: (entryId: string, path: string) => void;
104
+ /** Pin an editor tab (clear its preview state). */
105
+ readonly pinEditor: (entryId: string, path: string) => void;
106
+ /**
107
+ * Close an editor tab. The panel stays open even when the group empties —
108
+ * unlike the retired workspace-mode flip, the panel is more than files.
109
+ */
110
+ readonly closeEditor: (entryId: string, path: string) => void;
111
+ /**
112
+ * Open (or focus) the plan document tab and expand the panel. The tab is
113
+ * **pinned**, never the recyclable preview slot — file browsing must not
114
+ * evict the plan — and it activates, replacing the focused tab: the plan is
115
+ * the deliverable being reviewed. Fired by the thread cards' "Open plan"
116
+ * (the live `PlanStreamingCard` and the settled `PlanArtifactCard`), the
117
+ * Artifacts facet's `plan.md`, and the new-plan auto-open — which triggers
118
+ * both when a plan STARTS STREAMING and when it publishes (see `planKey`).
119
+ */
120
+ readonly openPlanDocument: () => void;
121
+ /**
122
+ * Report the current thread-item selection. Called from an effect inside the
123
+ * panel subtree (the level that subscribes to the selection store), keeping
124
+ * the owner subscription-free. While the panel is open, a new selection
125
+ * auto-switches to the Inspect view (unless the user picked one explicitly);
126
+ * a collapsed panel deliberately ignores selections — Inspect has no
127
+ * auto-open (it must never pull the user out of the chat).
128
+ */
129
+ readonly notifySelection: (item: SelectedThreadItem | null) => void;
130
+ }
131
+
132
+ /**
133
+ * Create a {@link SessionPanelController} for a viewer instance.
134
+ */
135
+ export function useSessionPanel({
136
+ phase,
137
+ hasChanges,
138
+ planKey = null,
139
+ defaultView = "files",
140
+ }: UseSessionPanelOptions): SessionPanelController {
141
+ const editorsStore = useWorkspaceEditorsStoreRef();
142
+ const [isOpen, setIsOpen] = useState(false);
143
+ const [view, setViewState] = useState(defaultView);
144
+
145
+ // Sticky explicit pick (rail click) — auto-switching yields to it until a
146
+ // meaningful state change resets it. Same semantics as the retired tab FSM.
147
+ const userPickedViewRef = useRef(false);
148
+ // Render-synced mirror so imperative callbacks read the current view without
149
+ // re-binding on every view change.
150
+ const viewRef = useRef(view);
151
+ viewRef.current = view;
152
+ // Last selection reported by the panel subtree; consulted by transitions that
153
+ // fire at the owner level (open, phase change) where selection state is
154
+ // deliberately not subscribed.
155
+ const selectionRef = useRef<SelectedThreadItem | null>(null);
156
+
157
+ // Running⇄terminal transition → reset the sticky pick and re-derive the view.
158
+ // Adjust-state-during-render (the established ResizableSplit pattern) so it
159
+ // lands before paint without an effect.
160
+ const [prevPhase, setPrevPhase] = useState(phase);
161
+ if (phase !== prevPhase) {
162
+ const wasTerminal = prevPhase !== null && isTerminalPhase(prevPhase);
163
+ const isNowTerminal = phase !== null && isTerminalPhase(phase);
164
+ setPrevPhase(phase);
165
+ if (wasTerminal !== isNowTerminal) {
166
+ userPickedViewRef.current = false;
167
+ setViewState(selectionRef.current ? "inspect" : defaultView);
168
+ }
169
+ }
170
+
171
+ // First write-back arrived → surface Changes, but only in an open panel and
172
+ // never over an explicit pick. Collapsed panels signal via badges alone.
173
+ const [prevHasChanges, setPrevHasChanges] = useState(hasChanges);
174
+ if (hasChanges !== prevHasChanges) {
175
+ setPrevHasChanges(hasChanges);
176
+ if (hasChanges && isOpen && !userPickedViewRef.current) {
177
+ setViewState("changes");
178
+ }
179
+ }
180
+
181
+ const openPlanDocument = useCallback(() => {
182
+ editorsStore.openPinned(PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH);
183
+ setIsOpen(true);
184
+ }, [editorsStore]);
185
+
186
+ // A new plan arrived (first plan, or a refinement superseding it) → open the
187
+ // plan document tab, expanding a collapsed panel (see the planKey option doc
188
+ // for why this one trigger may open the panel). An effect, NOT the
189
+ // render-adjust idiom the phase/changes triggers use: those set this
190
+ // component's own state, which the idiom permits — this one mutates the
191
+ // external editors store (notifying subscribers), which is illegal during
192
+ // render. The ref (not effect-less prev-state) swallows the identity present
193
+ // at mount: loading a session with an old plan never hijacks the layout.
194
+ const prevPlanKeyRef = useRef(planKey);
195
+ useEffect(() => {
196
+ if (planKey === prevPlanKeyRef.current) return;
197
+ prevPlanKeyRef.current = planKey;
198
+ if (planKey !== null) {
199
+ openPlanDocument();
200
+ }
201
+ }, [planKey, openPlanDocument]);
202
+
203
+ const openPanel = useCallback(() => {
204
+ setIsOpen(true);
205
+ // Re-derive the auto view on entry: a selection made while collapsed
206
+ // surfaces as Inspect now (the collapsed panel ignored it by design).
207
+ if (!userPickedViewRef.current && selectionRef.current) {
208
+ setViewState("inspect");
209
+ }
210
+ }, []);
211
+
212
+ const closePanel = useCallback(() => setIsOpen(false), []);
213
+
214
+ const setView = useCallback((viewId: string) => {
215
+ userPickedViewRef.current = true;
216
+ setViewState(viewId);
217
+ }, []);
218
+
219
+ const openFile = useCallback(
220
+ (entryId: string, path: string, options?: OpenFileOptions) => {
221
+ editorsStore.openPreview(entryId, path, options);
222
+ setIsOpen(true);
223
+ },
224
+ [editorsStore],
225
+ );
226
+
227
+ const activateEditor = useCallback(
228
+ (entryId: string, path: string) => editorsStore.activate(entryId, path),
229
+ [editorsStore],
230
+ );
231
+
232
+ const pinEditor = useCallback(
233
+ (entryId: string, path: string) => editorsStore.pin(entryId, path),
234
+ [editorsStore],
235
+ );
236
+
237
+ const closeEditor = useCallback(
238
+ (entryId: string, path: string) => editorsStore.close(entryId, path),
239
+ [editorsStore],
240
+ );
241
+
242
+ const notifySelection = useCallback(
243
+ (item: SelectedThreadItem | null) => {
244
+ if (item === selectionRef.current) return;
245
+ selectionRef.current = item;
246
+ if (item) {
247
+ if (isOpen && !userPickedViewRef.current) setViewState("inspect");
248
+ } else if (viewRef.current === "inspect") {
249
+ // Selection cleared: leave Inspect (its content is gone) and unstick,
250
+ // returning to the panel's home view.
251
+ userPickedViewRef.current = false;
252
+ setViewState(defaultView);
253
+ }
254
+ },
255
+ [isOpen, defaultView],
256
+ );
257
+
258
+ return useMemo(
259
+ () => ({
260
+ editorsStore,
261
+ isOpen,
262
+ view,
263
+ openPanel,
264
+ closePanel,
265
+ setView,
266
+ openFile,
267
+ activateEditor,
268
+ pinEditor,
269
+ closeEditor,
270
+ openPlanDocument,
271
+ notifySelection,
272
+ }),
273
+ [
274
+ editorsStore,
275
+ isOpen,
276
+ view,
277
+ openPanel,
278
+ closePanel,
279
+ setView,
280
+ openFile,
281
+ activateEditor,
282
+ pinEditor,
283
+ closeEditor,
284
+ openPlanDocument,
285
+ notifySelection,
286
+ ],
287
+ );
288
+ }
@@ -0,0 +1,200 @@
1
+ "use client";
2
+
3
+ import { useMemo } from "react";
4
+ import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
5
+ import type { SurfaceRailView } from "../workspace/WorkspaceSurface.js";
6
+ import type { SelectedThreadItem } from "../internal/store/selection-store.js";
7
+ import type { ApplyResourceResult } from "../library/useApplyResource.js";
8
+ import { useSessionWriteBacks } from "./useSessionWriteBacks.js";
9
+ import { useSessionArtifacts } from "./useSessionArtifacts.js";
10
+ import { SetupTab, type SetupTabProps } from "./facets/SetupTab.js";
11
+ import { ChangesTab } from "./facets/ChangesTab.js";
12
+ import { ArtifactsTab } from "./facets/ArtifactsTab.js";
13
+ import { UsageTab } from "./facets/UsageTab.js";
14
+ import { InspectTab } from "./facets/InspectTab.js";
15
+
16
+ /** Options for {@link useSessionRailViews}. */
17
+ export interface UseSessionRailViewsOptions {
18
+ /** All executions in the session — drives Changes/Artifacts/Usage. */
19
+ readonly allExecutions: readonly AgentExecution[];
20
+ /** Organization slug for artifact Apply CTA. */
21
+ readonly org: string;
22
+ /** Session configuration for the Config facet. */
23
+ readonly sessionConfig: SetupTabProps | undefined;
24
+ /** Currently selected thread item — surfaces the Inspect facet. */
25
+ readonly selectedItem: SelectedThreadItem | null;
26
+ /** Called after a resource is applied from the Artifacts facet. */
27
+ readonly onApplied?: (result: ApplyResourceResult) => void;
28
+ /** Implement a plan — the Artifacts facet's preview action for `plan.md`. */
29
+ readonly onImplementPlan?: () => void;
30
+ /**
31
+ * Open a plan in the panel's plan document tab. Routed to the Artifacts
32
+ * facet so clicking `plan.md` there opens the editor-area document instead
33
+ * of the preview modal.
34
+ */
35
+ readonly onOpenPlan?: (executionId: string) => void;
36
+ /**
37
+ * Whether to offer the execution-derived facets (Changes / Artifacts /
38
+ * Usage). The launcher passes `false` — before a session exists there are no
39
+ * executions to aggregate, so only Config applies.
40
+ * @default true
41
+ */
42
+ readonly includeExecutionFacets?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Composes the session facets (Config / Changes / Artifacts / Usage / Inspect)
47
+ * as {@link SurfaceRailView}s for the workspace surface's activity rail.
48
+ *
49
+ * This is the session-domain half of the unified panel: the surface stays a
50
+ * domain-pure workspace organism and these views are injected into its rail
51
+ * (DD-004 composition). Contextual visibility mirrors the retired inspector's
52
+ * tab rules — Changes/Artifacts surface only when data exists (with count
53
+ * badges), Inspect only when a thread item is selected.
54
+ */
55
+ export function useSessionRailViews({
56
+ allExecutions,
57
+ org,
58
+ sessionConfig,
59
+ selectedItem,
60
+ onApplied,
61
+ onImplementPlan,
62
+ onOpenPlan,
63
+ includeExecutionFacets = true,
64
+ }: UseSessionRailViewsOptions): readonly SurfaceRailView[] {
65
+ const { hasWriteBacks, writeBackCount } = useSessionWriteBacks(allExecutions);
66
+ const { hasArtifacts, artifactCount } = useSessionArtifacts(allExecutions);
67
+
68
+ return useMemo(() => {
69
+ const views: SurfaceRailView[] = [];
70
+
71
+ if (sessionConfig) {
72
+ views.push({
73
+ id: "configure",
74
+ label: "Config",
75
+ icon: <GearIcon />,
76
+ content: <SetupTab {...sessionConfig} />,
77
+ });
78
+ }
79
+
80
+ if (includeExecutionFacets) {
81
+ if (hasWriteBacks) {
82
+ views.push({
83
+ id: "changes",
84
+ label: "Changes",
85
+ icon: <ChangesIcon />,
86
+ badge: writeBackCount,
87
+ content: <ChangesTab executions={allExecutions} />,
88
+ });
89
+ }
90
+
91
+ if (hasArtifacts) {
92
+ views.push({
93
+ id: "artifacts",
94
+ label: "Artifacts",
95
+ icon: <ArtifactsIcon />,
96
+ badge: artifactCount,
97
+ content: (
98
+ <ArtifactsTab
99
+ executions={allExecutions}
100
+ org={org}
101
+ onApplied={onApplied}
102
+ onImplementPlan={onImplementPlan}
103
+ onOpenPlan={onOpenPlan}
104
+ />
105
+ ),
106
+ });
107
+ }
108
+
109
+ views.push({
110
+ id: "usage",
111
+ label: "Usage",
112
+ icon: <UsageIcon />,
113
+ content: <UsageTab executions={allExecutions} />,
114
+ });
115
+ }
116
+
117
+ if (selectedItem) {
118
+ views.push({
119
+ id: "inspect",
120
+ label: "Inspect",
121
+ icon: <InspectIcon />,
122
+ content: <InspectTab selectedItem={selectedItem} />,
123
+ });
124
+ }
125
+
126
+ return views;
127
+ }, [
128
+ sessionConfig,
129
+ includeExecutionFacets,
130
+ hasWriteBacks,
131
+ writeBackCount,
132
+ hasArtifacts,
133
+ artifactCount,
134
+ allExecutions,
135
+ org,
136
+ onApplied,
137
+ onImplementPlan,
138
+ onOpenPlan,
139
+ selectedItem,
140
+ ]);
141
+ }
142
+
143
+ // ---------------------------------------------------------------------------
144
+ // Inline SVG icons — monochrome, `currentColor`-tinted (DD-005; SDK
145
+ // independence — no lucide dependency)
146
+ // ---------------------------------------------------------------------------
147
+
148
+ function GearIcon() {
149
+ return (
150
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
151
+ <circle cx="12" cy="12" r="3" />
152
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h.01a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h.01a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v.01a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
153
+ </svg>
154
+ );
155
+ }
156
+
157
+ /** Source-control style branch glyph — the session's git write-backs. */
158
+ function ChangesIcon() {
159
+ return (
160
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
161
+ <circle cx="6" cy="6" r="2.5" />
162
+ <circle cx="6" cy="18" r="2.5" />
163
+ <circle cx="18" cy="8" r="2.5" />
164
+ <path d="M6 8.5v7" />
165
+ <path d="M18 10.5a7 7 0 0 1-7 5H8.5" />
166
+ </svg>
167
+ );
168
+ }
169
+
170
+ function ArtifactsIcon() {
171
+ return (
172
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
173
+ <path d="M21 8l-9-5-9 5v8l9 5 9-5z" />
174
+ <path d="M3 8l9 5 9-5" />
175
+ <path d="M12 13v9" />
176
+ </svg>
177
+ );
178
+ }
179
+
180
+ function UsageIcon() {
181
+ return (
182
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
183
+ <path d="M3 20h18" />
184
+ <path d="M6 20v-6" />
185
+ <path d="M11 20V9" />
186
+ <path d="M16 20v-9" />
187
+ <path d="M21 20V5" />
188
+ </svg>
189
+ );
190
+ }
191
+
192
+ /** Crosshair glyph — inspecting a selected thread item. */
193
+ function InspectIcon() {
194
+ return (
195
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
196
+ <circle cx="12" cy="12" r="7" />
197
+ <path d="M12 2v4M12 18v4M2 12h4M18 12h4" />
198
+ </svg>
199
+ );
200
+ }
@@ -26,7 +26,7 @@ import { useFollowExecution, computeFollowSelection } from "./useFollowExecution
26
26
  import { useActiveTaskName } from "./useActiveTaskName.js";
27
27
  import { useExecutionAnnouncements } from "./useExecutionAnnouncements.js";
28
28
  import { ExecutionActiveTaskIndicator } from "./ExecutionActiveTaskIndicator.js";
29
- import { getAnimationDuration } from "./motion-preference.js";
29
+ import { getAnimationDuration } from "../internal/motion-preference.js";
30
30
 
31
31
  /** Props for {@link WorkflowExecutionGraph}. */
32
32
  export interface WorkflowExecutionGraphProps {
@@ -531,7 +531,7 @@ export {
531
531
  type ExecutionActiveTaskIndicatorProps,
532
532
  } from "./ExecutionActiveTaskIndicator.js";
533
533
  export { useExecutionAnnouncements } from "./useExecutionAnnouncements.js";
534
- export { getAnimationDuration, prefersReducedMotion } from "./motion-preference.js";
534
+ export { getAnimationDuration, prefersReducedMotion } from "../internal/motion-preference.js";
535
535
 
536
536
  // T05: Shared formatting utilities
537
537
  export {
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import type { Node, Viewport } from "@xyflow/react";
5
5
  import { useReactFlow } from "@xyflow/react";
6
6
  import type { CanvasTaskNodeData } from "./workflow-graph-conversions.js";
7
- import { getAnimationDuration } from "./motion-preference.js";
7
+ import { getAnimationDuration } from "../internal/motion-preference.js";
8
8
 
9
9
  /**
10
10
  * Follow-execution state machine states.
@@ -0,0 +1,145 @@
1
+ "use client";
2
+
3
+ import { useCallback, type KeyboardEvent, type MouseEvent } from "react";
4
+ import { cn } from "@stigmer/theme";
5
+ import { editorKey, type OpenEditor } from "../internal/store/index.js";
6
+
7
+ /** Props for {@link EditorTabs}. */
8
+ export interface EditorTabsProps {
9
+ /** Open editors in tab order. */
10
+ readonly editors: readonly OpenEditor[];
11
+ /** Key of the active editor (`editorKey(entryId, path)`), or `null`. */
12
+ readonly activeKey: string | null;
13
+ /** Focus an open editor (single click). */
14
+ readonly onActivate: (entryId: string, path: string) => void;
15
+ /** Pin an editor (double-click) so it stops being the reusable preview tab. */
16
+ readonly onPin: (entryId: string, path: string) => void;
17
+ /** Close an editor (close button or middle click). */
18
+ readonly onClose: (entryId: string, path: string) => void;
19
+ /** Additional CSS classes for the root element. */
20
+ readonly className?: string;
21
+ }
22
+
23
+ /**
24
+ * The editor group's tab strip, following VS Code preview-tab semantics:
25
+ * a single-click preview tab renders in italics and is reused as the user
26
+ * browses; double-clicking a tab pins it (persistent). Each tab has a close
27
+ * control, also reachable by middle-click.
28
+ *
29
+ * A `role="tablist"` of `role="tab"` items; the matching `tabpanel` is the
30
+ * editor body rendered by the surface. Arrow keys move focus between tabs and
31
+ * activate; the per-tab close button is a nested control. All visual properties
32
+ * flow through `--stgm-*` tokens (DD-005).
33
+ */
34
+ export function EditorTabs({
35
+ editors,
36
+ activeKey,
37
+ onActivate,
38
+ onPin,
39
+ onClose,
40
+ className,
41
+ }: EditorTabsProps) {
42
+ const move = useCallback(
43
+ (from: number, delta: number) => {
44
+ const next = from + delta;
45
+ if (next < 0 || next >= editors.length) return;
46
+ const editor = editors[next];
47
+ onActivate(editor.entryId, editor.path);
48
+ },
49
+ [editors, onActivate],
50
+ );
51
+
52
+ return (
53
+ <div
54
+ role="tablist"
55
+ aria-label="Open editors"
56
+ aria-orientation="horizontal"
57
+ className={cn(
58
+ "flex shrink-0 items-stretch overflow-x-auto border-b border-border",
59
+ className,
60
+ )}
61
+ >
62
+ {editors.map((editor, index) => {
63
+ const key = editorKey(editor.entryId, editor.path);
64
+ const isActive = key === activeKey;
65
+ const lastSlash = editor.path.lastIndexOf("/");
66
+ const basename =
67
+ lastSlash >= 0 ? editor.path.slice(lastSlash + 1) : editor.path;
68
+
69
+ const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
70
+ if (e.key === "ArrowRight") {
71
+ e.preventDefault();
72
+ move(index, 1);
73
+ } else if (e.key === "ArrowLeft") {
74
+ e.preventDefault();
75
+ move(index, -1);
76
+ } else if (e.key === "Enter" || e.key === " ") {
77
+ e.preventDefault();
78
+ onActivate(editor.entryId, editor.path);
79
+ } else if (e.key === "Delete" || e.key === "Backspace") {
80
+ e.preventDefault();
81
+ onClose(editor.entryId, editor.path);
82
+ }
83
+ };
84
+
85
+ const handleAuxClick = (e: MouseEvent<HTMLDivElement>) => {
86
+ // Middle click closes, matching browser/editor tab conventions.
87
+ if (e.button === 1) {
88
+ e.preventDefault();
89
+ onClose(editor.entryId, editor.path);
90
+ }
91
+ };
92
+
93
+ return (
94
+ <div
95
+ key={key}
96
+ role="tab"
97
+ aria-selected={isActive}
98
+ tabIndex={isActive ? 0 : -1}
99
+ title={editor.path}
100
+ onClick={() => onActivate(editor.entryId, editor.path)}
101
+ onDoubleClick={() => onPin(editor.entryId, editor.path)}
102
+ onAuxClick={handleAuxClick}
103
+ onKeyDown={handleKeyDown}
104
+ className={cn(
105
+ "group flex max-w-[12rem] shrink-0 cursor-pointer items-center gap-1.5 border-r border-border px-3 py-1.5 text-xs transition-colors",
106
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
107
+ isActive
108
+ ? "bg-background text-foreground"
109
+ : "bg-muted-faint text-muted-foreground hover:bg-muted hover:text-foreground",
110
+ )}
111
+ >
112
+ <span className={cn("truncate", editor.preview && "italic")}>
113
+ {basename}
114
+ </span>
115
+ <button
116
+ type="button"
117
+ onClick={(e) => {
118
+ e.stopPropagation();
119
+ onClose(editor.entryId, editor.path);
120
+ }}
121
+ aria-label={`Close ${basename}`}
122
+ tabIndex={-1}
123
+ className={cn(
124
+ "shrink-0 rounded p-0.5 text-muted-foreground transition-opacity hover:bg-accent-hover hover:text-foreground",
125
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
126
+ isActive ? "opacity-100" : "opacity-0 group-hover:opacity-100",
127
+ )}
128
+ >
129
+ <CloseIcon />
130
+ </button>
131
+ </div>
132
+ );
133
+ })}
134
+ </div>
135
+ );
136
+ }
137
+
138
+ function CloseIcon() {
139
+ return (
140
+ <svg width="12" height="12" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
141
+ <path d="M3.5 3.5L10.5 10.5" />
142
+ <path d="M10.5 3.5L3.5 10.5" />
143
+ </svg>
144
+ );
145
+ }