@stigmer/react 3.0.9-dev.20260616060535 → 3.1.0

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/execution/ApprovalCard.d.ts +47 -3
  2. package/execution/ApprovalCard.d.ts.map +1 -1
  3. package/execution/ApprovalCard.js +138 -70
  4. package/execution/ApprovalCard.js.map +1 -1
  5. package/execution/ApprovalContext.d.ts +72 -0
  6. package/execution/ApprovalContext.d.ts.map +1 -0
  7. package/execution/ApprovalContext.js +41 -0
  8. package/execution/ApprovalContext.js.map +1 -0
  9. package/execution/ArtifactCard.d.ts.map +1 -1
  10. package/execution/ArtifactCard.js +3 -1
  11. package/execution/ArtifactCard.js.map +1 -1
  12. package/execution/ArtifactPreviewModal.d.ts.map +1 -1
  13. package/execution/ArtifactPreviewModal.js +5 -3
  14. package/execution/ArtifactPreviewModal.js.map +1 -1
  15. package/execution/EmptyChangeNotice.d.ts +38 -0
  16. package/execution/EmptyChangeNotice.d.ts.map +1 -0
  17. package/execution/EmptyChangeNotice.js +27 -0
  18. package/execution/EmptyChangeNotice.js.map +1 -0
  19. package/execution/FileChangesView.d.ts +81 -0
  20. package/execution/FileChangesView.d.ts.map +1 -0
  21. package/execution/FileChangesView.js +164 -0
  22. package/execution/FileChangesView.js.map +1 -0
  23. package/execution/FilePathLink.d.ts +24 -4
  24. package/execution/FilePathLink.d.ts.map +1 -1
  25. package/execution/FilePathLink.js +31 -9
  26. package/execution/FilePathLink.js.map +1 -1
  27. package/execution/FileReviewCard.d.ts +111 -0
  28. package/execution/FileReviewCard.d.ts.map +1 -0
  29. package/execution/FileReviewCard.js +558 -0
  30. package/execution/FileReviewCard.js.map +1 -0
  31. package/execution/FileReviewContext.d.ts +35 -0
  32. package/execution/FileReviewContext.d.ts.map +1 -0
  33. package/execution/FileReviewContext.js +23 -0
  34. package/execution/FileReviewContext.js.map +1 -0
  35. package/execution/FileReviewDock.d.ts +73 -0
  36. package/execution/FileReviewDock.d.ts.map +1 -0
  37. package/execution/FileReviewDock.js +65 -0
  38. package/execution/FileReviewDock.js.map +1 -0
  39. package/execution/McpToolDetail.d.ts.map +1 -1
  40. package/execution/McpToolDetail.js +38 -5
  41. package/execution/McpToolDetail.js.map +1 -1
  42. package/execution/MessageThread.d.ts +42 -3
  43. package/execution/MessageThread.d.ts.map +1 -1
  44. package/execution/MessageThread.js +263 -18
  45. package/execution/MessageThread.js.map +1 -1
  46. package/execution/PlanArtifactCard.d.ts.map +1 -1
  47. package/execution/PlanArtifactCard.js +3 -1
  48. package/execution/PlanArtifactCard.js.map +1 -1
  49. package/execution/PlanCompletionCard.d.ts +1 -1
  50. package/execution/PlanCompletionCard.js +1 -1
  51. package/execution/ResultView.d.ts +19 -1
  52. package/execution/ResultView.d.ts.map +1 -1
  53. package/execution/ResultView.js +141 -40
  54. package/execution/ResultView.js.map +1 -1
  55. package/execution/SubAgentSection.d.ts.map +1 -1
  56. package/execution/SubAgentSection.js +45 -6
  57. package/execution/SubAgentSection.js.map +1 -1
  58. package/execution/TerminalSession.d.ts +34 -0
  59. package/execution/TerminalSession.d.ts.map +1 -0
  60. package/execution/TerminalSession.js +34 -0
  61. package/execution/TerminalSession.js.map +1 -0
  62. package/execution/TodoCard.d.ts +53 -0
  63. package/execution/TodoCard.d.ts.map +1 -0
  64. package/execution/TodoCard.js +77 -0
  65. package/execution/TodoCard.js.map +1 -0
  66. package/execution/ToolArgsView.d.ts +7 -1
  67. package/execution/ToolArgsView.d.ts.map +1 -1
  68. package/execution/ToolArgsView.js +10 -9
  69. package/execution/ToolArgsView.js.map +1 -1
  70. package/execution/ToolCallDetail.d.ts +10 -1
  71. package/execution/ToolCallDetail.d.ts.map +1 -1
  72. package/execution/ToolCallDetail.js +66 -19
  73. package/execution/ToolCallDetail.js.map +1 -1
  74. package/execution/ToolCallGroup.d.ts +28 -18
  75. package/execution/ToolCallGroup.d.ts.map +1 -1
  76. package/execution/ToolCallGroup.js +39 -148
  77. package/execution/ToolCallGroup.js.map +1 -1
  78. package/execution/ToolCallItem.d.ts +36 -8
  79. package/execution/ToolCallItem.d.ts.map +1 -1
  80. package/execution/ToolCallItem.js +140 -21
  81. package/execution/ToolCallItem.js.map +1 -1
  82. package/execution/ToolRunGroup.d.ts +48 -0
  83. package/execution/ToolRunGroup.d.ts.map +1 -0
  84. package/execution/ToolRunGroup.js +168 -0
  85. package/execution/ToolRunGroup.js.map +1 -0
  86. package/execution/approval-provenance.d.ts +2 -0
  87. package/execution/approval-provenance.d.ts.map +1 -0
  88. package/execution/approval-provenance.js +6 -0
  89. package/execution/approval-provenance.js.map +1 -0
  90. package/execution/artifact-utils.d.ts +0 -10
  91. package/execution/artifact-utils.d.ts.map +1 -1
  92. package/execution/artifact-utils.js +0 -17
  93. package/execution/artifact-utils.js.map +1 -1
  94. package/execution/execution-phases.d.ts +1 -6
  95. package/execution/execution-phases.d.ts.map +1 -1
  96. package/execution/execution-phases.js +4 -14
  97. package/execution/execution-phases.js.map +1 -1
  98. package/execution/file-path-resolver.d.ts +28 -0
  99. package/execution/file-path-resolver.d.ts.map +1 -1
  100. package/execution/file-path-resolver.js +24 -0
  101. package/execution/file-path-resolver.js.map +1 -1
  102. package/execution/file-review-status.d.ts +127 -0
  103. package/execution/file-review-status.d.ts.map +1 -0
  104. package/execution/file-review-status.js +135 -0
  105. package/execution/file-review-status.js.map +1 -0
  106. package/execution/index.d.ts +39 -5
  107. package/execution/index.d.ts.map +1 -1
  108. package/execution/index.js +23 -3
  109. package/execution/index.js.map +1 -1
  110. package/execution/segment-tool-calls.d.ts +46 -0
  111. package/execution/segment-tool-calls.d.ts.map +1 -0
  112. package/execution/segment-tool-calls.js +71 -0
  113. package/execution/segment-tool-calls.js.map +1 -0
  114. package/execution/tool-categories.d.ts +62 -1
  115. package/execution/tool-categories.d.ts.map +1 -1
  116. package/execution/tool-categories.js +96 -2
  117. package/execution/tool-categories.js.map +1 -1
  118. package/execution/tool-presenter.d.ts +38 -2
  119. package/execution/tool-presenter.d.ts.map +1 -1
  120. package/execution/tool-presenter.js +23 -1
  121. package/execution/tool-presenter.js.map +1 -1
  122. package/execution/tool-rendering-primitives.d.ts.map +1 -1
  123. package/execution/tool-rendering-primitives.js +3 -2
  124. package/execution/tool-rendering-primitives.js.map +1 -1
  125. package/execution/useArtifactDownload.d.ts +44 -0
  126. package/execution/useArtifactDownload.d.ts.map +1 -0
  127. package/execution/useArtifactDownload.js +80 -0
  128. package/execution/useArtifactDownload.js.map +1 -0
  129. package/execution/useArtifactDownloadUrl.d.ts +67 -0
  130. package/execution/useArtifactDownloadUrl.d.ts.map +1 -0
  131. package/execution/useArtifactDownloadUrl.js +59 -0
  132. package/execution/useArtifactDownloadUrl.js.map +1 -0
  133. package/execution/useFileChangeContent.d.ts +61 -0
  134. package/execution/useFileChangeContent.d.ts.map +1 -0
  135. package/execution/useFileChangeContent.js +89 -0
  136. package/execution/useFileChangeContent.js.map +1 -0
  137. package/execution/useFileReview.d.ts +89 -0
  138. package/execution/useFileReview.d.ts.map +1 -0
  139. package/execution/useFileReview.js +106 -0
  140. package/execution/useFileReview.js.map +1 -0
  141. package/execution/useSubmitApproval.d.ts +17 -2
  142. package/execution/useSubmitApproval.d.ts.map +1 -1
  143. package/execution/useSubmitApproval.js +27 -23
  144. package/execution/useSubmitApproval.js.map +1 -1
  145. package/execution/useToolOutputContent.d.ts +44 -0
  146. package/execution/useToolOutputContent.d.ts.map +1 -0
  147. package/execution/useToolOutputContent.js +31 -0
  148. package/execution/useToolOutputContent.js.map +1 -0
  149. package/index.d.ts +6 -6
  150. package/index.d.ts.map +1 -1
  151. package/index.js +3 -3
  152. package/index.js.map +1 -1
  153. package/internal/ApprovalPeekBar.d.ts +23 -0
  154. package/internal/ApprovalPeekBar.d.ts.map +1 -0
  155. package/internal/ApprovalPeekBar.js +25 -0
  156. package/internal/ApprovalPeekBar.js.map +1 -0
  157. package/internal/BoundedContent.d.ts +49 -0
  158. package/internal/BoundedContent.d.ts.map +1 -0
  159. package/internal/BoundedContent.js +50 -0
  160. package/internal/BoundedContent.js.map +1 -0
  161. package/internal/DecisionButton.d.ts +47 -0
  162. package/internal/DecisionButton.d.ts.map +1 -0
  163. package/internal/DecisionButton.js +42 -0
  164. package/internal/DecisionButton.js.map +1 -0
  165. package/internal/InCardDecisionError.d.ts +31 -0
  166. package/internal/InCardDecisionError.d.ts.map +1 -0
  167. package/internal/InCardDecisionError.js +23 -0
  168. package/internal/InCardDecisionError.js.map +1 -0
  169. package/internal/RevealToggle.d.ts +36 -0
  170. package/internal/RevealToggle.d.ts.map +1 -0
  171. package/internal/RevealToggle.js +32 -0
  172. package/internal/RevealToggle.js.map +1 -0
  173. package/internal/VirtualizedThread.d.ts +7 -1
  174. package/internal/VirtualizedThread.d.ts.map +1 -1
  175. package/internal/VirtualizedThread.js +7 -3
  176. package/internal/VirtualizedThread.js.map +1 -1
  177. package/internal/useAutoDisclosure.d.ts +34 -0
  178. package/internal/useAutoDisclosure.d.ts.map +1 -0
  179. package/internal/useAutoDisclosure.js +53 -0
  180. package/internal/useAutoDisclosure.js.map +1 -0
  181. package/internal/useElapsedSince.d.ts +30 -0
  182. package/internal/useElapsedSince.d.ts.map +1 -0
  183. package/internal/useElapsedSince.js +70 -0
  184. package/internal/useElapsedSince.js.map +1 -0
  185. package/internal/useIsOverflowing.d.ts +30 -0
  186. package/internal/useIsOverflowing.d.ts.map +1 -0
  187. package/internal/useIsOverflowing.js +47 -0
  188. package/internal/useIsOverflowing.js.map +1 -0
  189. package/internal/useIsTextTruncated.d.ts +24 -0
  190. package/internal/useIsTextTruncated.d.ts.map +1 -0
  191. package/internal/useIsTextTruncated.js +41 -0
  192. package/internal/useIsTextTruncated.js.map +1 -0
  193. package/internal/useKeyedSubmission.d.ts +49 -0
  194. package/internal/useKeyedSubmission.d.ts.map +1 -0
  195. package/internal/useKeyedSubmission.js +67 -0
  196. package/internal/useKeyedSubmission.js.map +1 -0
  197. package/package.json +4 -4
  198. package/session/SessionViewer.d.ts +2 -2
  199. package/session/SessionViewer.d.ts.map +1 -1
  200. package/session/SessionViewer.js +10 -4
  201. package/session/SessionViewer.js.map +1 -1
  202. package/session/index.d.ts +2 -0
  203. package/session/index.d.ts.map +1 -1
  204. package/session/index.js +1 -0
  205. package/session/index.js.map +1 -1
  206. package/session/inspector/ChangesTab.d.ts +8 -5
  207. package/session/inspector/ChangesTab.d.ts.map +1 -1
  208. package/session/inspector/ChangesTab.js +11 -8
  209. package/session/inspector/ChangesTab.js.map +1 -1
  210. package/session/inspector/SessionInspector.d.ts +4 -4
  211. package/session/inspector/SessionInspector.d.ts.map +1 -1
  212. package/session/inspector/SessionInspector.js +4 -4
  213. package/session/inspector/SessionInspector.js.map +1 -1
  214. package/session/inspector/index.d.ts +0 -2
  215. package/session/inspector/index.d.ts.map +1 -1
  216. package/session/inspector/index.js +0 -1
  217. package/session/inspector/index.js.map +1 -1
  218. package/session/inspector/useSessionInspector.d.ts +8 -4
  219. package/session/inspector/useSessionInspector.d.ts.map +1 -1
  220. package/session/inspector/useSessionInspector.js +27 -20
  221. package/session/inspector/useSessionInspector.js.map +1 -1
  222. package/session/useSessionConversation.d.ts +37 -3
  223. package/session/useSessionConversation.d.ts.map +1 -1
  224. package/session/useSessionConversation.js +18 -2
  225. package/session/useSessionConversation.js.map +1 -1
  226. package/session/useSessionFileChanges.d.ts +74 -0
  227. package/session/useSessionFileChanges.d.ts.map +1 -0
  228. package/session/useSessionFileChanges.js +178 -0
  229. package/session/useSessionFileChanges.js.map +1 -0
  230. package/src/__tests__/styles-border-layer-invariant.test.ts +105 -0
  231. package/src/execution/ApprovalCard.tsx +368 -230
  232. package/src/execution/ApprovalContext.ts +109 -0
  233. package/src/execution/ArtifactCard.tsx +10 -6
  234. package/src/execution/ArtifactPreviewModal.tsx +12 -6
  235. package/src/execution/EmptyChangeNotice.tsx +62 -0
  236. package/src/execution/FileChangesView.tsx +383 -0
  237. package/src/execution/FilePathLink.tsx +65 -12
  238. package/src/execution/FileReviewCard.tsx +1118 -0
  239. package/src/execution/FileReviewContext.ts +53 -0
  240. package/src/execution/FileReviewDock.tsx +157 -0
  241. package/src/execution/McpToolDetail.tsx +98 -32
  242. package/src/execution/MessageThread.tsx +374 -9
  243. package/src/execution/PlanArtifactCard.tsx +9 -6
  244. package/src/execution/PlanCompletionCard.tsx +1 -1
  245. package/src/execution/ResultView.tsx +333 -162
  246. package/src/execution/SubAgentSection.tsx +58 -11
  247. package/src/execution/TerminalSession.tsx +91 -0
  248. package/src/execution/TodoCard.tsx +186 -0
  249. package/src/execution/ToolArgsView.tsx +28 -17
  250. package/src/execution/ToolCallDetail.tsx +137 -26
  251. package/src/execution/ToolCallGroup.tsx +68 -296
  252. package/src/execution/ToolCallItem.tsx +265 -67
  253. package/src/execution/ToolRunGroup.tsx +302 -0
  254. package/src/execution/__tests__/ApprovalCard.test.tsx +395 -5
  255. package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +0 -1
  256. package/src/execution/__tests__/EmptyChangeNotice.test.tsx +24 -0
  257. package/src/execution/__tests__/FileChangesView.test.tsx +296 -0
  258. package/src/execution/__tests__/FilePathLink.test.tsx +92 -0
  259. package/src/execution/__tests__/FileReviewCard.test.tsx +1044 -0
  260. package/src/execution/__tests__/FileReviewDock.test.tsx +134 -0
  261. package/src/execution/__tests__/McpToolDetail.test.tsx +79 -0
  262. package/src/execution/__tests__/MessageThread.test.tsx +324 -0
  263. package/src/execution/__tests__/PlanArtifactCard.test.tsx +37 -16
  264. package/src/execution/__tests__/ResultView.test.tsx +280 -2
  265. package/src/execution/__tests__/SubAgentSection.test.tsx +180 -0
  266. package/src/execution/__tests__/TerminalSession.test.tsx +72 -0
  267. package/src/execution/__tests__/TodoCard.test.tsx +102 -0
  268. package/src/execution/__tests__/ToolArgsView.test.tsx +48 -0
  269. package/src/execution/__tests__/ToolCallDetail.test.tsx +195 -0
  270. package/src/execution/__tests__/ToolCallGroup.test.tsx +132 -0
  271. package/src/execution/__tests__/ToolCallItem.test.tsx +521 -0
  272. package/src/execution/__tests__/ToolRunGroup.test.tsx +137 -0
  273. package/src/execution/__tests__/blanked-narration.test.tsx +149 -0
  274. package/src/execution/__tests__/buildThreadItems-approvals.test.ts +304 -0
  275. package/src/execution/__tests__/buildThreadItems-file-review.test.ts +331 -0
  276. package/src/execution/__tests__/file-path-resolver.test.ts +44 -0
  277. package/src/execution/__tests__/file-review-status.test.ts +343 -0
  278. package/src/execution/__tests__/segment-tool-calls.test.ts +124 -0
  279. package/src/execution/__tests__/subagent-file-review-badge.test.tsx +273 -0
  280. package/src/execution/__tests__/thread-keys.test.ts +195 -0
  281. package/src/execution/__tests__/tool-presenter.test.tsx +95 -0
  282. package/src/execution/__tests__/useArtifactDownload.test.tsx +67 -0
  283. package/src/execution/__tests__/useArtifactDownloadUrl.test.tsx +51 -0
  284. package/src/execution/__tests__/useFileChangeContent.test.tsx +240 -0
  285. package/src/execution/__tests__/useFileReview.test.tsx +236 -0
  286. package/src/execution/__tests__/useSubmitApproval.test.tsx +165 -0
  287. package/src/execution/__tests__/useToolOutputContent.test.tsx +82 -0
  288. package/src/execution/approval-provenance.ts +8 -0
  289. package/src/execution/artifact-utils.ts +0 -18
  290. package/src/execution/execution-phases.ts +4 -16
  291. package/src/execution/file-path-resolver.ts +38 -0
  292. package/src/execution/file-review-status.ts +219 -0
  293. package/src/execution/index.ts +84 -4
  294. package/src/execution/segment-tool-calls.ts +101 -0
  295. package/src/execution/tool-categories.ts +128 -1
  296. package/src/execution/tool-presenter.ts +58 -3
  297. package/src/execution/tool-rendering-primitives.tsx +11 -14
  298. package/src/execution/useArtifactDownload.ts +109 -0
  299. package/src/execution/useArtifactDownloadUrl.ts +116 -0
  300. package/src/execution/useFileChangeContent.ts +149 -0
  301. package/src/execution/useFileReview.ts +197 -0
  302. package/src/execution/useSubmitApproval.ts +49 -27
  303. package/src/execution/useToolOutputContent.ts +70 -0
  304. package/src/index.ts +60 -1
  305. package/src/internal/ApprovalPeekBar.tsx +73 -0
  306. package/src/internal/BoundedContent.tsx +97 -0
  307. package/src/internal/DecisionButton.tsx +127 -0
  308. package/src/internal/InCardDecisionError.tsx +47 -0
  309. package/src/internal/RevealToggle.tsx +91 -0
  310. package/src/internal/VirtualizedThread.tsx +28 -2
  311. package/src/internal/__tests__/ApprovalPeekBar.test.tsx +34 -0
  312. package/src/internal/__tests__/BoundedContent.test.tsx +92 -0
  313. package/src/internal/__tests__/DecisionButton.test.tsx +107 -0
  314. package/src/internal/__tests__/RevealToggle.test.tsx +61 -0
  315. package/src/internal/__tests__/useAutoDisclosure.test.ts +74 -0
  316. package/src/internal/__tests__/useElapsedSince.test.tsx +68 -0
  317. package/src/internal/__tests__/useIsOverflowing.test.ts +36 -0
  318. package/src/internal/__tests__/useKeyedSubmission.test.tsx +126 -0
  319. package/src/internal/useAutoDisclosure.ts +58 -0
  320. package/src/internal/useElapsedSince.ts +72 -0
  321. package/src/internal/useIsOverflowing.ts +61 -0
  322. package/src/internal/useIsTextTruncated.ts +55 -0
  323. package/src/internal/useKeyedSubmission.ts +101 -0
  324. package/src/session/SessionViewer.tsx +21 -4
  325. package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +198 -0
  326. package/src/session/__tests__/audienceWiring.test.tsx +4 -0
  327. package/src/session/__tests__/useSessionFileChanges.test.ts +303 -0
  328. package/src/session/index.ts +3 -0
  329. package/src/session/inspector/ChangesTab.tsx +20 -17
  330. package/src/session/inspector/SessionInspector.tsx +12 -10
  331. package/src/session/inspector/__tests__/ArtifactsTab.test.tsx +0 -1
  332. package/src/session/inspector/__tests__/ChangesTab.test.tsx +38 -0
  333. package/src/session/inspector/__tests__/useSessionInspector.test.ts +46 -61
  334. package/src/session/inspector/index.ts +0 -3
  335. package/src/session/inspector/useSessionInspector.ts +27 -20
  336. package/src/session/useSessionConversation.ts +80 -3
  337. package/src/session/useSessionFileChanges.ts +207 -0
  338. package/src/styles.css +35 -10
  339. package/src/version-history/DiffViewer.tsx +10 -7
  340. package/src/version-history/UnifiedDiffView.tsx +66 -0
  341. package/src/version-history/__tests__/DiffViewer.test.tsx +57 -0
  342. package/src/version-history/__tests__/UnifiedDiffView.test.tsx +50 -0
  343. package/src/version-history/__tests__/computeDiff.test.ts +35 -0
  344. package/src/version-history/__tests__/parseUnifiedDiff.test.ts +82 -0
  345. package/src/version-history/computeDiff.ts +6 -37
  346. package/src/version-history/diff-hunks.ts +63 -0
  347. package/src/version-history/index.ts +1 -0
  348. package/src/version-history/parseUnifiedDiff.ts +34 -0
  349. package/src/workflow/WorkflowExecutionApprovalCard.tsx +49 -24
  350. package/src/workflow/WorkflowExecutionTimeline.tsx +15 -4
  351. package/src/workflow/WorkflowExecutionTimelineEvent.tsx +8 -3
  352. package/src/workflow/WorkflowExecutionViewer.tsx +72 -28
  353. package/src/workflow/WorkflowFileReviewList.tsx +152 -0
  354. package/src/workflow/WorkflowTaskApprovalCard.tsx +37 -85
  355. package/src/workflow/__tests__/ExecutionInspector.test.tsx +30 -2
  356. package/src/workflow/__tests__/WorkflowExecutionApprovalCard.test.tsx +129 -0
  357. package/src/workflow/__tests__/WorkflowFileReviewList.test.tsx +129 -0
  358. package/src/workflow/__tests__/WorkflowTaskApprovalCard.test.tsx +43 -11
  359. package/src/workflow/__tests__/useWorkflowExecutionActions.test.tsx +276 -0
  360. package/src/workflow/execution-inspector/ExecutionInspector.tsx +42 -18
  361. package/src/workflow/index.ts +5 -0
  362. package/src/workflow/useWorkflowExecutionActions.ts +177 -29
  363. package/styles.css +1 -1
  364. package/version-history/DiffViewer.d.ts.map +1 -1
  365. package/version-history/DiffViewer.js +9 -3
  366. package/version-history/DiffViewer.js.map +1 -1
  367. package/version-history/UnifiedDiffView.d.ts +29 -0
  368. package/version-history/UnifiedDiffView.d.ts.map +1 -0
  369. package/version-history/UnifiedDiffView.js +36 -0
  370. package/version-history/UnifiedDiffView.js.map +1 -0
  371. package/version-history/computeDiff.d.ts +3 -1
  372. package/version-history/computeDiff.d.ts.map +1 -1
  373. package/version-history/computeDiff.js +5 -35
  374. package/version-history/computeDiff.js.map +1 -1
  375. package/version-history/diff-hunks.d.ts +21 -0
  376. package/version-history/diff-hunks.d.ts.map +1 -0
  377. package/version-history/diff-hunks.js +58 -0
  378. package/version-history/diff-hunks.js.map +1 -0
  379. package/version-history/index.d.ts +1 -0
  380. package/version-history/index.d.ts.map +1 -1
  381. package/version-history/index.js +1 -0
  382. package/version-history/index.js.map +1 -1
  383. package/version-history/parseUnifiedDiff.d.ts +22 -0
  384. package/version-history/parseUnifiedDiff.d.ts.map +1 -0
  385. package/version-history/parseUnifiedDiff.js +34 -0
  386. package/version-history/parseUnifiedDiff.js.map +1 -0
  387. package/workflow/WorkflowExecutionApprovalCard.d.ts +8 -1
  388. package/workflow/WorkflowExecutionApprovalCard.d.ts.map +1 -1
  389. package/workflow/WorkflowExecutionApprovalCard.js +17 -3
  390. package/workflow/WorkflowExecutionApprovalCard.js.map +1 -1
  391. package/workflow/WorkflowExecutionTimeline.d.ts +11 -2
  392. package/workflow/WorkflowExecutionTimeline.d.ts.map +1 -1
  393. package/workflow/WorkflowExecutionTimeline.js +2 -2
  394. package/workflow/WorkflowExecutionTimeline.js.map +1 -1
  395. package/workflow/WorkflowExecutionTimelineEvent.d.ts +4 -1
  396. package/workflow/WorkflowExecutionTimelineEvent.d.ts.map +1 -1
  397. package/workflow/WorkflowExecutionTimelineEvent.js +2 -2
  398. package/workflow/WorkflowExecutionTimelineEvent.js.map +1 -1
  399. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
  400. package/workflow/WorkflowExecutionViewer.js +18 -10
  401. package/workflow/WorkflowExecutionViewer.js.map +1 -1
  402. package/workflow/WorkflowFileReviewList.d.ts +46 -0
  403. package/workflow/WorkflowFileReviewList.d.ts.map +1 -0
  404. package/workflow/WorkflowFileReviewList.js +48 -0
  405. package/workflow/WorkflowFileReviewList.js.map +1 -0
  406. package/workflow/WorkflowTaskApprovalCard.d.ts +8 -1
  407. package/workflow/WorkflowTaskApprovalCard.d.ts.map +1 -1
  408. package/workflow/WorkflowTaskApprovalCard.js +12 -19
  409. package/workflow/WorkflowTaskApprovalCard.js.map +1 -1
  410. package/workflow/execution-inspector/ExecutionInspector.d.ts +21 -4
  411. package/workflow/execution-inspector/ExecutionInspector.d.ts.map +1 -1
  412. package/workflow/execution-inspector/ExecutionInspector.js +6 -3
  413. package/workflow/execution-inspector/ExecutionInspector.js.map +1 -1
  414. package/workflow/index.d.ts +1 -0
  415. package/workflow/index.d.ts.map +1 -1
  416. package/workflow/index.js +1 -0
  417. package/workflow/index.js.map +1 -1
  418. package/workflow/useWorkflowExecutionActions.d.ts +62 -4
  419. package/workflow/useWorkflowExecutionActions.d.ts.map +1 -1
  420. package/workflow/useWorkflowExecutionActions.js +94 -18
  421. package/workflow/useWorkflowExecutionActions.js.map +1 -1
  422. package/session/inspector/PlanTab.d.ts +0 -15
  423. package/session/inspector/PlanTab.d.ts.map +0 -1
  424. package/session/inspector/PlanTab.js +0 -19
  425. package/session/inspector/PlanTab.js.map +0 -1
  426. package/src/session/inspector/PlanTab.tsx +0 -31
@@ -9,34 +9,37 @@ export interface ChangesTabProps {
9
9
  }
10
10
 
11
11
  /**
12
- * Changes facet for the SessionInspector.
12
+ * Changes facet for the SessionInspector — the session's git write-backs
13
+ * (branch/commit/PR), one `WriteBackCard` per entry.
13
14
  *
14
- * Wraps the existing `useSessionWriteBacks` hook and renders
15
- * `WriteBackCard` per write-back entry the same content as
16
- * `WriteBacksWidget` but without its section heading (the tab
17
- * label provides that context).
15
+ * Local file changes deliberately do NOT render here: they live in the
16
+ * transcript, where each stamped edit row shows its diff in place and the
17
+ * per-turn decision bar carries the review controls and file list
18
+ * (`FileReviewCard`). Duplicating them in a side panel gave the same change a
19
+ * third rendering with no added authority. The tab therefore only surfaces
20
+ * once a write-back exists (see `buildVisibleTabs`).
18
21
  */
19
22
  export function ChangesTab({ executions }: ChangesTabProps) {
20
23
  const { writeBacks, hasWriteBacks } = useSessionWriteBacks(executions);
21
24
 
22
- if (!hasWriteBacks) {
25
+ if (hasWriteBacks) {
23
26
  return (
24
- <div className="flex flex-col items-center justify-center px-4 py-8 text-center">
25
- <p className="text-xs text-muted-foreground">
26
- No pull requests yet. Changes will appear here when the agent
27
- writes back to a workspace.
28
- </p>
27
+ <div role="list" className="space-y-2">
28
+ {writeBacks.map((entry) => (
29
+ <div key={entry.writeBack.workspaceEntryName} role="listitem">
30
+ <WriteBackCard writeBack={entry.writeBack} />
31
+ </div>
32
+ ))}
29
33
  </div>
30
34
  );
31
35
  }
32
36
 
33
37
  return (
34
- <div role="list" className="space-y-2">
35
- {writeBacks.map((entry) => (
36
- <div key={entry.writeBack.workspaceEntryName} role="listitem">
37
- <WriteBackCard writeBack={entry.writeBack} />
38
- </div>
39
- ))}
38
+ <div className="flex flex-col items-center justify-center px-4 py-8 text-center">
39
+ <p className="text-xs text-muted-foreground">
40
+ No changes yet. Pull requests will appear here once the agent pushes
41
+ its work back to your repository.
42
+ </p>
40
43
  </div>
41
44
  );
42
45
  }
@@ -10,7 +10,6 @@ import { useSessionArtifacts } from "../useSessionArtifacts";
10
10
  import { useSessionWriteBacks } from "../useSessionWriteBacks";
11
11
  import { useSessionUsage } from "../useSessionUsage";
12
12
  import { useSessionInspector } from "./useSessionInspector";
13
- import { PlanTab } from "./PlanTab";
14
13
  import { ChangesTab } from "./ChangesTab";
15
14
  import { ArtifactsTab } from "./ArtifactsTab";
16
15
  import { UsageTab } from "./UsageTab";
@@ -24,8 +23,7 @@ import type { ApplyResourceResult } from "../../library/useApplyResource";
24
23
  export interface SessionInspectorProps {
25
24
  /**
26
25
  * The most relevant execution — the active streaming execution,
27
- * or the last completed one. Drives the run-status header and
28
- * the Plan facet.
26
+ * or the last completed one. Drives the run-status header (phase badge).
29
27
  */
30
28
  readonly displayExecution: AgentExecution | null;
31
29
  /**
@@ -65,8 +63,9 @@ export interface SessionInspectorProps {
65
63
  * Tabbed right-side inspector panel for agent sessions.
66
64
  *
67
65
  * Displays an always-visible run-status header (phase badge) above
68
- * contextual tabs: Plan, Changes, Artifacts, Usage, and Inspect
69
- * (when a thread item is selected).
66
+ * contextual tabs: Workspace, Config, Changes, Artifacts, Usage, and
67
+ * Inspect (when a thread item is selected). The agent's plan/todos render
68
+ * inline in the message thread (see {@link TodoCard}), not as a tab here.
70
69
  *
71
70
  * Mirrors the `ExecutionInspector` architecture from the workflow
72
71
  * view — same `Tabs` primitive, same tab-FSM behavior hook, same
@@ -109,8 +108,14 @@ export const SessionInspector = memo(function SessionInspector({
109
108
 
110
109
  return (
111
110
  <div className={cn("flex h-full flex-col", className)}>
112
- {/* Always-visible run-status header */}
113
- <div className="flex items-center gap-2 border-b border-border px-3 py-2.5">
111
+ {/* Always-visible run-status header. Labeled as a region so the phase
112
+ badge is reachable as "Execution progress" by assistive tech and
113
+ E2E selectors, independent of which tab is active. */}
114
+ <div
115
+ role="region"
116
+ aria-label="Execution progress"
117
+ className="flex items-center gap-2 border-b border-border px-3 py-2.5"
118
+ >
114
119
  {phase !== ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED ? (
115
120
  <ExecutionPhaseBadge phase={phase} />
116
121
  ) : (
@@ -133,9 +138,6 @@ export const SessionInspector = memo(function SessionInspector({
133
138
  {activeTab === "configure" && sessionConfig && (
134
139
  <SetupTab {...sessionConfig} />
135
140
  )}
136
- {activeTab === "plan" && (
137
- <PlanTab execution={displayExecution} />
138
- )}
139
141
  {activeTab === "changes" && (
140
142
  <ChangesTab executions={allExecutions} />
141
143
  )}
@@ -18,7 +18,6 @@ function artifact(name: string) {
18
18
  sizeBytes: 1024n,
19
19
  sandboxPath: `.stigmer/${name}`,
20
20
  storageKey: `artifacts/aex_1/${name}`,
21
- downloadUrl: `https://example.test/${name}`,
22
21
  });
23
22
  }
24
23
 
@@ -0,0 +1,38 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { render, screen, cleanup } from "@testing-library/react";
3
+
4
+ const writeBacksReturn = { writeBacks: [] as Array<{ writeBack: { workspaceEntryName: string } }>, hasWriteBacks: false };
5
+
6
+ vi.mock("../../useSessionWriteBacks", () => ({
7
+ useSessionWriteBacks: () => writeBacksReturn,
8
+ }));
9
+ vi.mock("../../../execution/WriteBackCard", () => ({
10
+ WriteBackCard: () => <div data-testid="write-back-card" />,
11
+ }));
12
+
13
+ const { ChangesTab } = await import("../ChangesTab");
14
+
15
+ beforeEach(() => {
16
+ writeBacksReturn.writeBacks = [];
17
+ writeBacksReturn.hasWriteBacks = false;
18
+ });
19
+
20
+ afterEach(() => cleanup());
21
+
22
+ describe("ChangesTab", () => {
23
+ it("renders write-back (PR) cards", () => {
24
+ writeBacksReturn.writeBacks = [{ writeBack: { workspaceEntryName: "w1" } }];
25
+ writeBacksReturn.hasWriteBacks = true;
26
+
27
+ render(<ChangesTab executions={[]} />);
28
+ expect(screen.getByTestId("write-back-card")).toBeTruthy();
29
+ });
30
+
31
+ // Local file changes render in the transcript (edit rows + decision bar),
32
+ // never here — the tab is exclusively the write-back (PR) surface.
33
+ it("renders the PR-oriented empty state when no write-back exists", () => {
34
+ render(<ChangesTab executions={[]} />);
35
+ expect(screen.getByText(/no changes yet/i)).toBeTruthy();
36
+ expect(screen.getByText(/pull requests/i)).toBeTruthy();
37
+ });
38
+ });
@@ -20,25 +20,32 @@ function defaultOpts(overrides?: Partial<UseSessionInspectorOptions>): UseSessio
20
20
  };
21
21
  }
22
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
+
23
37
  // ---------------------------------------------------------------------------
24
38
  // buildVisibleTabs
25
39
  // ---------------------------------------------------------------------------
26
40
 
27
41
  describe("buildVisibleTabs", () => {
28
- it("always includes Workspace, Config, Plan, and Usage", () => {
29
- const tabs = buildVisibleTabs({
30
- hasWriteBacks: false,
31
- writeBackCount: 0,
32
- hasArtifacts: false,
33
- artifactCount: 0,
34
- hasUsage: false,
35
- selectedItem: null,
36
- });
42
+ it("always includes Workspace, Config, and Usage (Plan is gone — todos render inline)", () => {
43
+ const tabs = buildVisibleTabs(tabOpts());
37
44
  const ids = tabs.map((t) => t.id);
38
45
  expect(ids).toContain("workspace");
39
46
  expect(ids).toContain("configure");
40
- expect(ids).toContain("plan");
41
47
  expect(ids).toContain("usage");
48
+ expect(ids).not.toContain("plan");
42
49
  expect(ids).not.toContain("changes");
43
50
  expect(ids).not.toContain("artifacts");
44
51
  expect(ids).not.toContain("inspect");
@@ -47,74 +54,52 @@ describe("buildVisibleTabs", () => {
47
54
  expect(configTab?.label).toBe("Config");
48
55
  });
49
56
 
50
- it("includes Changes with badge when write-backs exist", () => {
51
- const tabs = buildVisibleTabs({
52
- hasWriteBacks: true,
53
- writeBackCount: 3,
54
- hasArtifacts: false,
55
- artifactCount: 0,
56
- hasUsage: false,
57
- selectedItem: null,
58
- });
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 }));
59
62
  const changesTab = tabs.find((t) => t.id === "changes");
60
63
  expect(changesTab).toBeDefined();
61
64
  expect(changesTab?.badge).toBe(3);
62
65
  });
63
66
 
64
67
  it("includes Artifacts with badge when artifacts exist", () => {
65
- const tabs = buildVisibleTabs({
66
- hasWriteBacks: false,
67
- writeBackCount: 0,
68
- hasArtifacts: true,
69
- artifactCount: 7,
70
- hasUsage: false,
71
- selectedItem: null,
72
- });
68
+ const tabs = buildVisibleTabs(tabOpts({ hasArtifacts: true, artifactCount: 7 }));
73
69
  const artifactsTab = tabs.find((t) => t.id === "artifacts");
74
70
  expect(artifactsTab).toBeDefined();
75
71
  expect(artifactsTab?.badge).toBe(7);
76
72
  });
77
73
 
78
74
  it("includes Inspect when a thread item is selected", () => {
79
- const tabs = buildVisibleTabs({
80
- hasWriteBacks: false,
81
- writeBackCount: 0,
82
- hasArtifacts: false,
83
- artifactCount: 0,
84
- hasUsage: false,
85
- selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
86
- });
75
+ const tabs = buildVisibleTabs(
76
+ tabOpts({ selectedItem: { kind: "tool-call", toolCallId: "tc-1" } }),
77
+ );
87
78
  const inspectTab = tabs.find((t) => t.id === "inspect");
88
79
  expect(inspectTab).toBeDefined();
89
80
  });
90
81
 
91
- it("orders tabs as Workspace, Config, Plan, then Usage with Inspect last", () => {
92
- const tabs = buildVisibleTabs({
93
- hasWriteBacks: true,
94
- writeBackCount: 2,
95
- hasArtifacts: true,
96
- artifactCount: 1,
97
- hasUsage: true,
98
- selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
99
- });
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
+ );
100
93
  const ids = tabs.map((t) => t.id);
101
94
  expect(ids.indexOf("workspace")).toBeLessThan(ids.indexOf("configure"));
102
- expect(ids.indexOf("configure")).toBeLessThan(ids.indexOf("plan"));
103
- expect(ids.indexOf("plan")).toBeLessThan(ids.indexOf("usage"));
95
+ expect(ids.indexOf("configure")).toBeLessThan(ids.indexOf("usage"));
104
96
  expect(ids.indexOf("usage")).toBeLessThan(ids.indexOf("inspect"));
105
97
  });
106
98
 
107
99
  it("base tabs are present even when no optional tabs exist", () => {
108
- const tabs = buildVisibleTabs({
109
- hasWriteBacks: false,
110
- writeBackCount: 0,
111
- hasArtifacts: false,
112
- artifactCount: 0,
113
- hasUsage: false,
114
- selectedItem: null,
115
- });
100
+ const tabs = buildVisibleTabs(tabOpts());
116
101
  const ids = tabs.map((t) => t.id);
117
- expect(ids).toEqual(["workspace", "configure", "plan", "usage"]);
102
+ expect(ids).toEqual(["workspace", "configure", "usage"]);
118
103
  });
119
104
  });
120
105
 
@@ -137,13 +122,13 @@ describe("useSessionInspector", () => {
137
122
  expect(result.current.activeTab).toBe("workspace");
138
123
  });
139
124
 
140
- it("defaults to plan while execution is running", () => {
125
+ it("defaults to workspace while execution is running (todos render inline, not in a tab)", () => {
141
126
  const { result } = renderHook(() =>
142
127
  useSessionInspector(
143
128
  defaultOpts({ phase: ExecutionPhase.EXECUTION_IN_PROGRESS }),
144
129
  ),
145
130
  );
146
- expect(result.current.activeTab).toBe("plan");
131
+ expect(result.current.activeTab).toBe("workspace");
147
132
  });
148
133
 
149
134
  it("auto-switches to inspect when a thread item is selected", () => {
@@ -174,7 +159,7 @@ describe("useSessionInspector", () => {
174
159
  expect(result.current.activeTab).toBe("workspace");
175
160
  });
176
161
 
177
- it("reverts to plan when selection is cleared while execution is running", () => {
162
+ it("reverts to workspace when selection is cleared while execution is running", () => {
178
163
  const { result, rerender } = renderHook(
179
164
  (props: UseSessionInspectorOptions) => useSessionInspector(props),
180
165
  {
@@ -192,7 +177,7 @@ describe("useSessionInspector", () => {
192
177
  selectedItem: null,
193
178
  }),
194
179
  );
195
- expect(result.current.activeTab).toBe("plan");
180
+ expect(result.current.activeTab).toBe("workspace");
196
181
  });
197
182
 
198
183
  it("keeps user-picked tab sticky", () => {
@@ -247,7 +232,7 @@ describe("useSessionInspector", () => {
247
232
  expect(result.current.activeTab).toBe("workspace");
248
233
  });
249
234
 
250
- it("switches to workspace when execution transitions to terminal phase", () => {
235
+ it("stays on workspace across the running terminal transition", () => {
251
236
  const { result, rerender } = renderHook(
252
237
  (props: UseSessionInspectorOptions) => useSessionInspector(props),
253
238
  {
@@ -256,7 +241,7 @@ describe("useSessionInspector", () => {
256
241
  }),
257
242
  },
258
243
  );
259
- expect(result.current.activeTab).toBe("plan");
244
+ expect(result.current.activeTab).toBe("workspace");
260
245
 
261
246
  rerender(
262
247
  defaultOpts({ phase: ExecutionPhase.EXECUTION_COMPLETED }),
@@ -8,9 +8,6 @@ export type {
8
8
  UseSessionInspectorReturn,
9
9
  } from "./useSessionInspector";
10
10
 
11
- export { PlanTab } from "./PlanTab";
12
- export type { PlanTabProps } from "./PlanTab";
13
-
14
11
  export { ChangesTab } from "./ChangesTab";
15
12
  export type { ChangesTabProps } from "./ChangesTab";
16
13
 
@@ -9,7 +9,6 @@ import type { SelectedThreadItem } from "../../internal/store/selection-store";
9
9
  export type SessionInspectorTabId =
10
10
  | "workspace"
11
11
  | "configure"
12
- | "plan"
13
12
  | "changes"
14
13
  | "artifacts"
15
14
  | "usage"
@@ -32,29 +31,34 @@ export interface UseSessionInspectorReturn {
32
31
  }
33
32
 
34
33
  /**
35
- * Compute the system-suggested tab from execution phase and selection.
34
+ * Compute the system-suggested tab from selection.
36
35
  *
37
36
  * Priority:
38
37
  * 1. Thread item selected -> "inspect"
39
- * 2. No execution or terminal phase (idle / ready for follow-up) -> "workspace"
40
- * 3. Actively running -> "plan"
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.
41
43
  */
42
44
  function deriveAutoTab(
43
- phase: ExecutionPhase | null,
44
45
  selectedItem: SelectedThreadItem | null,
45
46
  ): SessionInspectorTabId {
46
47
  if (selectedItem) return "inspect";
47
- if (phase === null || isTerminalPhase(phase)) return "workspace";
48
- return "plan";
48
+ return "workspace";
49
49
  }
50
50
 
51
51
  /**
52
52
  * Build the contextual tab list with badges.
53
53
  *
54
54
  * Tab order follows the user's mental model — context before output:
55
- * Workspace → Config → Plan → Usage. Changes and Artifacts appear
56
- * after Plan when data exists; Inspect appears last when a thread item
57
- * is selected.
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.
58
62
  */
59
63
  export function buildVisibleTabs(opts: {
60
64
  hasWriteBacks: boolean;
@@ -67,7 +71,6 @@ export function buildVisibleTabs(opts: {
67
71
  const tabs: TabItem[] = [
68
72
  { id: "workspace", label: "Workspace" },
69
73
  { id: "configure", label: "Config" },
70
- { id: "plan", label: "Plan" },
71
74
  ];
72
75
 
73
76
  if (opts.hasWriteBacks) {
@@ -111,12 +114,16 @@ export function useSessionInspector(
111
114
 
112
115
  const tabs = buildVisibleTabs({ hasWriteBacks, writeBackCount, hasArtifacts, artifactCount, hasUsage, selectedItem });
113
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
+
114
121
  const [activeTab, setActiveTab] = useState<SessionInspectorTabId>(
115
- () => deriveAutoTab(phase, selectedItem),
122
+ () => deriveAutoTab(selectedItem),
116
123
  );
117
124
  const [prevPhase, setPrevPhase] = useState(phase);
118
125
  const [prevSelected, setPrevSelected] = useState(selectedItem);
119
- const [prevHasWriteBacks, setPrevHasWriteBacks] = useState(hasWriteBacks);
126
+ const [prevHasChanges, setPrevHasChanges] = useState(hasChanges);
120
127
  const userPickedTabRef = useRef(false);
121
128
 
122
129
  // Selection changed → auto-switch to inspect (unless user picked)
@@ -126,7 +133,7 @@ export function useSessionInspector(
126
133
  setActiveTab("inspect");
127
134
  }
128
135
  if (!selectedItem && activeTab === "inspect") {
129
- setActiveTab(deriveAutoTab(phase, null));
136
+ setActiveTab(deriveAutoTab(null));
130
137
  userPickedTabRef.current = false;
131
138
  }
132
139
  }
@@ -138,25 +145,25 @@ export function useSessionInspector(
138
145
  setPrevPhase(phase);
139
146
  if (wasTerminal !== isNowTerminal) {
140
147
  userPickedTabRef.current = false;
141
- setActiveTab(deriveAutoTab(phase, selectedItem));
148
+ setActiveTab(deriveAutoTab(selectedItem));
142
149
  }
143
150
  }
144
151
 
145
152
  // First write-back arrived → auto-switch to changes
146
- if (hasWriteBacks && !prevHasWriteBacks) {
147
- setPrevHasWriteBacks(hasWriteBacks);
153
+ if (hasChanges && !prevHasChanges) {
154
+ setPrevHasChanges(hasChanges);
148
155
  if (!userPickedTabRef.current) {
149
156
  setActiveTab("changes");
150
157
  }
151
158
  }
152
- if (hasWriteBacks !== prevHasWriteBacks) {
153
- setPrevHasWriteBacks(hasWriteBacks);
159
+ if (hasChanges !== prevHasChanges) {
160
+ setPrevHasChanges(hasChanges);
154
161
  }
155
162
 
156
163
  // Ensure active tab is valid (the selected tab may have been removed)
157
164
  const effectiveTab = tabs.some((t) => t.id === activeTab)
158
165
  ? activeTab
159
- : deriveAutoTab(phase, selectedItem);
166
+ : deriveAutoTab(selectedItem);
160
167
 
161
168
  const onTabChange = useCallback((tabId: string) => {
162
169
  userPickedTabRef.current = true;
@@ -3,7 +3,8 @@
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
5
5
  import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
6
- import { ApprovalAction, ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
6
+ import type { FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
7
+ import { ApprovalAction, ExecutionPhase, FileChangeSetStatus, FileDecisionAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
7
8
  import type { Session } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
8
9
  import type { McpServerUsage as ProtoMcpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
9
10
  import type { WorkspaceEntry as ProtoWorkspaceEntry } from "@stigmer/protos/ai/stigmer/agentic/session/v1/workspace_pb";
@@ -23,6 +24,7 @@ import { useCreateAgentExecution } from "../execution/useCreateAgentExecution";
23
24
  import { useExecutionStream } from "../execution/useExecutionStream";
24
25
  import { useAgentExecutionActions } from "../execution/useAgentExecutionActions";
25
26
  import { useSubmitApproval } from "../execution/useSubmitApproval";
27
+ import { useFileReview, type FileDecisionOptions } from "../execution/useFileReview";
26
28
  import { useSession } from "./useSession";
27
29
  import { useSessionExecutions } from "./useSessionExecutions";
28
30
  import { useUpdateSession } from "./useUpdateSession";
@@ -196,11 +198,48 @@ export interface UseSessionConversationReturn {
196
198
  ) => Promise<void>;
197
199
  /** Set of tool call IDs currently being submitted for approval. */
198
200
  readonly submittingApprovalIds: ReadonlySet<string>;
199
- /** Error from the last approval submission, or `null` when healthy. */
201
+ /**
202
+ * Per-tool-call approval failures, keyed by `toolCallId` — surfaced in-card by
203
+ * {@link MessageThread}/{@link ApprovalCard} beside the gate that failed
204
+ * (inline row or bottom backstop). The keyed parallel of
205
+ * {@link submittingApprovalIds}.
206
+ */
207
+ readonly approvalErrors: ReadonlyMap<string, Error>;
208
+ /**
209
+ * Error from the last approval submission, or `null` when healthy — the scalar
210
+ * mirror of {@link approvalErrors} (symmetric with `fileReviewError`), for a
211
+ * headless consumer wanting a single error value (e.g. the `ink` surface).
212
+ */
200
213
  readonly approvalError: Error | null;
201
- /** Reset `approvalError` to `null`. */
214
+ /** Reset every approval error (both {@link approvalErrors} and `approvalError`). */
202
215
  readonly clearApprovalError: () => void;
203
216
 
217
+ /** Captured change sets awaiting file review on the active execution, empty when none. */
218
+ readonly fileChangeSets: readonly FileChangeSet[];
219
+ /** Submit a file-review decision for a change set. The executionId is managed internally. */
220
+ readonly submitFileDecision: (
221
+ changeSetId: string,
222
+ action: FileDecisionAction,
223
+ options?: FileDecisionOptions,
224
+ ) => Promise<void>;
225
+ /** Decision keys ({@link fileDecisionKey}) currently being submitted. */
226
+ readonly submittingFileDecisionKeys: ReadonlySet<string>;
227
+ /**
228
+ * Per-decision failures, keyed by {@link fileDecisionKey} — surfaced in-card
229
+ * by {@link MessageThread}/{@link FileReviewCard} beside the failed control.
230
+ */
231
+ readonly fileDecisionErrors: ReadonlyMap<string, Error>;
232
+ /** Clear the error for one decision key (e.g. before a retry of that target). */
233
+ readonly clearFileDecisionError: (key: string) => void;
234
+ /**
235
+ * The most-recent file-review failure, or `null` when healthy — the scalar
236
+ * mirror of {@link fileDecisionErrors} (symmetric with `approvalError`), for a
237
+ * headless consumer wanting a single error value.
238
+ */
239
+ readonly fileReviewError: Error | null;
240
+ /** Reset every file-review error (both {@link fileDecisionErrors} and `fileReviewError`). */
241
+ readonly clearFileReviewError: () => void;
242
+
204
243
  /**
205
244
  * `true` when the active execution can be stopped — i.e. it is in a phase
206
245
  * the backend accepts a cancel/terminate from (`PENDING` or `IN_PROGRESS`).
@@ -337,9 +376,18 @@ export function useSessionConversation(
337
376
  const {
338
377
  submitApproval: rawSubmitApproval,
339
378
  submittingToolCallIds,
379
+ errorsByToolCallId: approvalErrors,
340
380
  error: approvalError,
341
381
  clearError: clearApprovalError,
342
382
  } = useSubmitApproval();
383
+ const {
384
+ submitFileDecision: rawSubmitFileDecision,
385
+ submittingDecisionKeys,
386
+ decisionErrors: fileDecisionErrors,
387
+ clearDecisionError: clearFileDecisionError,
388
+ error: fileReviewError,
389
+ clearError: clearFileReviewError,
390
+ } = useFileReview();
343
391
 
344
392
  // Local execution: attach the session's runner worker while it is open and
345
393
  // detach it on close. No-op for cloud sessions or when no adapter is set.
@@ -578,6 +626,26 @@ export function useSessionConversation(
578
626
  [activeExecutionId, rawSubmitApproval],
579
627
  );
580
628
 
629
+ const fileChangeSets = useMemo<readonly FileChangeSet[]>(
630
+ () =>
631
+ (activeStreamExecution?.status?.fileChangeSets ?? []).filter(
632
+ (cs) => cs.status === FileChangeSetStatus.AWAITING_REVIEW,
633
+ ),
634
+ [activeStreamExecution],
635
+ );
636
+
637
+ const submitFileDecision = useCallback(
638
+ async (
639
+ changeSetId: string,
640
+ action: FileDecisionAction,
641
+ options?: FileDecisionOptions,
642
+ ): Promise<void> => {
643
+ if (!activeExecutionId) return;
644
+ await rawSubmitFileDecision(activeExecutionId, changeSetId, action, options);
645
+ },
646
+ [activeExecutionId, rawSubmitFileDecision],
647
+ );
648
+
581
649
  const isLoading = sessionLoading || executionsLoading;
582
650
  const loadError = sessionError || executionsError;
583
651
 
@@ -605,9 +673,18 @@ export function useSessionConversation(
605
673
  pendingApprovals,
606
674
  submitApproval,
607
675
  submittingApprovalIds: submittingToolCallIds,
676
+ approvalErrors,
608
677
  approvalError,
609
678
  clearApprovalError,
610
679
 
680
+ fileChangeSets,
681
+ submitFileDecision,
682
+ submittingFileDecisionKeys: submittingDecisionKeys,
683
+ fileDecisionErrors,
684
+ clearFileDecisionError,
685
+ fileReviewError,
686
+ clearFileReviewError,
687
+
611
688
  isStoppable,
612
689
  stop,
613
690
  isStopping: stopActions.isSubmitting,