@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
@@ -0,0 +1,82 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { renderHook } from "@testing-library/react";
3
+ import { create } from "@bufbuild/protobuf";
4
+ import { ToolCallOutputRefSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
5
+ import type { UseArtifactContentReturn } from "../useArtifactContent";
6
+
7
+ // Mock the underlying content fetch so the test asserts the derivation logic
8
+ // (execId from storageKey) and the lazy `enabled` gate, not the network.
9
+ const responses = new Map<string, Partial<UseArtifactContentReturn>>();
10
+ const calls: Array<{
11
+ executionId: string | null;
12
+ storageKey: string | null;
13
+ contentHash?: string;
14
+ }> = [];
15
+
16
+ vi.mock("../useArtifactContent", () => ({
17
+ useArtifactContent: (
18
+ executionId: string | null,
19
+ storageKey: string | null,
20
+ _entryPath?: string | null,
21
+ contentHash?: string,
22
+ ) => {
23
+ calls.push({ executionId, storageKey, contentHash });
24
+ const base: UseArtifactContentReturn = {
25
+ content: null,
26
+ contentType: null,
27
+ isTruncated: false,
28
+ isLoading: false,
29
+ isRefetching: false,
30
+ error: null,
31
+ refetch: () => {},
32
+ };
33
+ if (!storageKey) return base;
34
+ return { ...base, ...responses.get(storageKey) };
35
+ },
36
+ }));
37
+
38
+ const { useToolOutputContent } = await import("../useToolOutputContent");
39
+
40
+ beforeEach(() => {
41
+ responses.clear();
42
+ calls.length = 0;
43
+ });
44
+
45
+ function ref(storageKey: string, contentHash = "h") {
46
+ return create(ToolCallOutputRefSchema, { storageKey, contentHash });
47
+ }
48
+
49
+ describe("useToolOutputContent", () => {
50
+ it("stays idle until enabled (lazy expand)", () => {
51
+ const { result } = renderHook(() =>
52
+ useToolOutputContent(ref("artifacts/exec-1/toolcalls/tc.txt"), false),
53
+ );
54
+ expect(result.current.content).toBeNull();
55
+ // The underlying fetch is skipped (null storage key passed through).
56
+ expect(calls.every((c) => c.storageKey === null)).toBe(true);
57
+ });
58
+
59
+ it("derives the execId from the storage key and fetches when enabled", () => {
60
+ const key = "artifacts/exec-9/toolcalls/tc.txt";
61
+ responses.set(key, { content: "FULL", isTruncated: false });
62
+ const { result } = renderHook(() => useToolOutputContent(ref(key), true));
63
+
64
+ expect(result.current.content).toBe("FULL");
65
+ const call = calls.find((c) => c.storageKey === key);
66
+ expect(call?.executionId).toBe("exec-9");
67
+ expect(call?.contentHash).toBe("h");
68
+ });
69
+
70
+ it("passes through truncation", () => {
71
+ const key = "artifacts/exec-9/toolcalls/tc.txt";
72
+ responses.set(key, { content: "head", isTruncated: true });
73
+ const { result } = renderHook(() => useToolOutputContent(ref(key), true));
74
+ expect(result.current.isTruncated).toBe(true);
75
+ });
76
+
77
+ it("skips when the ref is null", () => {
78
+ const { result } = renderHook(() => useToolOutputContent(null, true));
79
+ expect(result.current.content).toBeNull();
80
+ expect(calls.every((c) => c.storageKey === null)).toBe(true);
81
+ });
82
+ });
@@ -0,0 +1,8 @@
1
+ // Re-export the framework-agnostic provenance label from @stigmer/sdk so the
2
+ // React surface (ApprovalCard "why-gated" line, ToolCallDetail) shares one
3
+ // source of truth with @stigmer/ink and the Go CLI. See the sdk module for the
4
+ // mapping rationale.
5
+ export {
6
+ describeApprovalPolicySource,
7
+ isInformativePolicySource,
8
+ } from "@stigmer/sdk";
@@ -80,24 +80,6 @@ export function isTextArtifact(artifact: ExecutionArtifact): boolean {
80
80
  return TEXT_EXTENSIONS.has(ext);
81
81
  }
82
82
 
83
- /**
84
- * Checks whether an artifact's pre-signed download URL has expired.
85
- *
86
- * Returns `true` when:
87
- * - `expiresAt` is empty or cannot be parsed as a valid date
88
- * - The current time is past the expiration timestamp
89
- *
90
- * Expired URLs can be refreshed via `stigmer.agentExecution.getArtifactDownloadUrl()`.
91
- */
92
- export function isArtifactExpired(artifact: ExecutionArtifact): boolean {
93
- if (!artifact.expiresAt) return true;
94
-
95
- const expiresMs = Date.parse(artifact.expiresAt);
96
- if (Number.isNaN(expiresMs)) return true;
97
-
98
- return Date.now() >= expiresMs;
99
- }
100
-
101
83
  // ---------------------------------------------------------------------------
102
84
  // Render mode classification
103
85
  // ---------------------------------------------------------------------------
@@ -1,16 +1,4 @@
1
- import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
2
-
3
- const TERMINAL_PHASES: ReadonlySet<ExecutionPhase> = new Set([
4
- ExecutionPhase.EXECUTION_COMPLETED,
5
- ExecutionPhase.EXECUTION_FAILED,
6
- ExecutionPhase.EXECUTION_CANCELLED,
7
- ExecutionPhase.EXECUTION_TERMINATED,
8
- ]);
9
-
10
- /**
11
- * Returns `true` when the given phase represents a final, immutable
12
- * execution state — no further updates will arrive from the server.
13
- */
14
- export function isTerminalPhase(phase: ExecutionPhase): boolean {
15
- return TERMINAL_PHASES.has(phase);
16
- }
1
+ // Re-export the framework-agnostic execution-phase predicates from @stigmer/sdk
2
+ // so the React surface shares one source of truth with @stigmer/ink and the pure
3
+ // SDK logic (e.g. the file-review fold). See the sdk module for the definitions.
4
+ export { isTerminalPhase } from "@stigmer/sdk";
@@ -41,6 +41,44 @@ export function classifyPath(path: string): PathClassification {
41
41
  return { kind: "workspace", remainder: clean };
42
42
  }
43
43
 
44
+ /** A file path split into its directory prefix and final segment for display. */
45
+ export interface DisplayPath {
46
+ /**
47
+ * The directory portion including the trailing slash (e.g. `"src/app/"`), or
48
+ * `""` when the path has no directory. Rendered dimmed and allowed to
49
+ * truncate — it is context, not identity.
50
+ */
51
+ readonly dir: string;
52
+ /**
53
+ * The final path segment — the file name (e.g. `"main.ts"`). This is the
54
+ * identity of the change and must never be clipped.
55
+ */
56
+ readonly base: string;
57
+ }
58
+
59
+ /**
60
+ * Splits a file path into `{ dir, base }` for filename-first display.
61
+ *
62
+ * The motivation: a raw tool-call path is frequently an absolute, deeply-nested
63
+ * string (`/Users/me/scm/.../notes.md`), and naive CSS `truncate` on the whole
64
+ * path clips the *end* — hiding the file name, the one part that identifies the
65
+ * change. Splitting lets the renderer keep the base name always visible and
66
+ * truncate only the (dimmed) directory.
67
+ *
68
+ * Pure (no React) so it is unit-testable in isolation and reusable by any
69
+ * surface. A trailing slash is tolerated (a directory path keeps its last
70
+ * segment as the base); a path with no slash is all base.
71
+ */
72
+ export function splitDisplayPath(path: string): DisplayPath {
73
+ if (!path) return { dir: "", base: "" };
74
+ const trimmed = path.replace(/\/+$/, "");
75
+ const idx = trimmed.lastIndexOf("/");
76
+ if (idx < 0) return { dir: "", base: trimmed };
77
+ const base = trimmed.slice(idx + 1);
78
+ // A path that was only slashes collapses to the original — never an empty base.
79
+ return base ? { dir: trimmed.slice(0, idx + 1), base } : { dir: "", base: trimmed };
80
+ }
81
+
44
82
  /**
45
83
  * Constructs a browsable GitHub blob URL from a git clone URL.
46
84
  *
@@ -0,0 +1,219 @@
1
+ import type {
2
+ CapturedFileChange,
3
+ FileChangeSet,
4
+ FileDecision,
5
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
6
+ import {
7
+ DiffCompleteness,
8
+ FileChangeSetStatus,
9
+ FileDecisionAction,
10
+ FileDecisionScope,
11
+ FileReviewBlockReason,
12
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
13
+
14
+ /**
15
+ * Why an `"unavailable"` file cannot be reviewed — the honest per-file cause the
16
+ * runner records on `CapturedFileChange.blocked_reason` (design doc 15).
17
+ *
18
+ * - `"secret"` — the path looks like a secret; the bytes were deliberately never
19
+ * captured (there is nothing to review, by design).
20
+ * - `"size"` — the diff was captured but its bodies were dropped to keep the
21
+ * persisted status under its size limit.
22
+ * - `"unknown"` — incomplete for a reason the wire does not name (a defensive
23
+ * catch-all; historical rows and future/unmapped causes land here).
24
+ */
25
+ export type FileBlockReason = "secret" | "size" | "unknown";
26
+
27
+ /**
28
+ * How completely a single captured file change can be reviewed before a decision
29
+ * is made — the classification that decides whether a file can be kept. A
30
+ * discriminated union so every consumer handles each case exhaustively and reads
31
+ * the block reason from one place (no "classify, then separately look up why").
32
+ *
33
+ * - `{ kind: "reviewable" }` — the full before/after diff is available; the
34
+ * reviewer can see exactly what changed and Keep or Discard it.
35
+ * - `{ kind: "binary" }` — a binary file changed; there is no text diff to
36
+ * review (the bytes are captured and flagged, but a byte diff is not
37
+ * human-reviewable). Binary is proven by `FileContent.is_binary`, not by the
38
+ * block reason.
39
+ * - `{ kind: "unavailable"; reason }` — the diff is not available to review at
40
+ * all, with the honest {@link FileBlockReason} the runner recorded.
41
+ *
42
+ * Both `"binary"` and `"unavailable"` are non-reviewable: the file cannot be
43
+ * approved (kept), only discarded. This mirrors the server, which blocks
44
+ * approval of any change set that is not fully complete.
45
+ */
46
+ export type FileReviewability =
47
+ | { readonly kind: "reviewable" }
48
+ | { readonly kind: "binary" }
49
+ | { readonly kind: "unavailable"; readonly reason: FileBlockReason };
50
+
51
+ /**
52
+ * Classify a {@link CapturedFileChange} by how completely it can be reviewed,
53
+ * from the signals the runner authors onto the change (see the file-review
54
+ * producer in the runner's `shared/filereview`).
55
+ *
56
+ * The mapping is derived from three proto signals, in order:
57
+ *
58
+ * 1. `diff_complete === true` → `"reviewable"`. The change set can only be
59
+ * `COMPLETE` when every file is complete, so a complete file is always
60
+ * reviewable.
61
+ * 2. otherwise, a binary side (`before.is_binary` or `after.is_binary`) →
62
+ * `"binary"`. The runner marks a git-tracked file incomplete precisely
63
+ * because a side is binary (`diff_complete = !binary`); a CAS file carries
64
+ * `is_binary` on its blob ref. `is_binary` is preserved when a large body is
65
+ * offloaded from an inline value to a storage ref, so this holds regardless
66
+ * of offload. Binary is therefore derived here, never duplicated onto the
67
+ * block reason (doc 15).
68
+ * 3. otherwise → `"unavailable"` with the honest cause from
69
+ * `blocked_reason`: `SECRET_WITHHELD → "secret"`, `SIZE_ELIDED → "size"`,
70
+ * else `"unknown"`. Before doc 15 this bucket was cause-agnostic (the wire
71
+ * could not prove secret-withheld vs size-dropped); the runner now records
72
+ * the cause at capture time, so the UI can say *why* rather than only *that*
73
+ * the diff is unavailable.
74
+ */
75
+ export function fileReviewability(change: CapturedFileChange): FileReviewability {
76
+ if (change.diffComplete) return { kind: "reviewable" };
77
+ if (change.before?.isBinary || change.after?.isBinary) return { kind: "binary" };
78
+ return { kind: "unavailable", reason: blockReasonOf(change.blockedReason) };
79
+ }
80
+
81
+ /** Map the proto {@link FileReviewBlockReason} to the UI {@link FileBlockReason}. */
82
+ function blockReasonOf(reason: FileReviewBlockReason): FileBlockReason {
83
+ switch (reason) {
84
+ case FileReviewBlockReason.SECRET_WITHHELD:
85
+ return "secret";
86
+ case FileReviewBlockReason.SIZE_ELIDED:
87
+ return "size";
88
+ default:
89
+ return "unknown";
90
+ }
91
+ }
92
+
93
+ /**
94
+ * How completely a whole {@link FileChangeSet} can be reviewed — the set-level
95
+ * sibling of {@link FileReviewability} that decides whether the set can be kept
96
+ * in one action. Drives the card's bulk affordance and keeps headless builders
97
+ * on the same classification.
98
+ *
99
+ * - `"complete"` — every file is reviewable; the set can be approved as-is.
100
+ * - `"binary-only"` — the set's ONLY blocker is binary files (every non-binary
101
+ * file is fully reviewable). No text diff for the binaries, but their exact
102
+ * bytes are captured and reconcilable, so the whole set can be KEPT in one
103
+ * acknowledged action ("Keep all"). Includes mixed sets (text edits + images).
104
+ * - `"blocked"` — at least one file is unavailable to review with no keepable
105
+ * bytes (secret-withheld / size-elided / uncapturable), so the set cannot be
106
+ * approved at once; it must be resolved per file.
107
+ */
108
+ export type ChangeSetReviewability = "complete" | "binary-only" | "blocked";
109
+
110
+ /**
111
+ * Classify a {@link FileChangeSet} from its server-derived `diff_completeness`
112
+ * rollup (the field exists precisely so clients need not re-fold the per-file
113
+ * signals). The runner and the size backstop both derive that value from the
114
+ * same rule the backend gate re-checks, so this classification, the per-file
115
+ * {@link fileReviewability} fold, and the server gate agree by construction.
116
+ */
117
+ export function changeSetReviewability(set: FileChangeSet): ChangeSetReviewability {
118
+ switch (set.diffCompleteness) {
119
+ case DiffCompleteness.COMPLETE:
120
+ return "complete";
121
+ case DiffCompleteness.BINARY_SUMMARY_ONLY:
122
+ return "binary-only";
123
+ default:
124
+ return "blocked";
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Each file's EFFECTIVE verdict for a settled set, folding the decisions the
130
+ * way the runner reconcile does (most-specific-wins): the last CHANGE_SET
131
+ * decision is the baseline for every file, and a later-or-earlier FILE decision
132
+ * overrides it for that file (FILE > CHANGE_SET regardless of ledger order;
133
+ * within a scope, last write wins).
134
+ *
135
+ * This is the fold for DISPLAYING history — a set decided via "Keep all"
136
+ * correctly reads every file as kept. The interactive per-file selected state
137
+ * deliberately uses the FILE-only fold instead (a CHANGE_SET decision cannot
138
+ * coexist with an open review, so it never pre-selects anything there).
139
+ */
140
+ export function deriveEffectiveVerdicts(
141
+ set: FileChangeSet,
142
+ ): ReadonlyMap<string, FileDecisionAction> {
143
+ let bulk: FileDecisionAction | null = null;
144
+ const byFileId = new Map<string, FileDecisionAction>();
145
+ for (const d of set.decisions as readonly FileDecision[]) {
146
+ if (d.scope === FileDecisionScope.CHANGE_SET) bulk = d.action;
147
+ else if (d.scope === FileDecisionScope.FILE && d.fileChangeId) {
148
+ byFileId.set(d.fileChangeId, d.action);
149
+ }
150
+ }
151
+ const effective = new Map<string, FileDecisionAction>();
152
+ for (const c of set.changes) {
153
+ const verdict = byFileId.get(c.id) ?? bulk;
154
+ if (verdict != null) effective.set(c.id, verdict);
155
+ }
156
+ return effective;
157
+ }
158
+
159
+ /**
160
+ * The captured change a transcript row's file path refers to, or `null`. The
161
+ * row's path may be absolute (harness tool args) while captured paths are
162
+ * workspace-root-relative, so the match accepts an exact match or a
163
+ * `/`-boundary suffix. Presentation-only — never a correlation key.
164
+ */
165
+ export function changeForRowPath(
166
+ set: FileChangeSet,
167
+ rowPath: string,
168
+ ): CapturedFileChange | null {
169
+ if (!rowPath) return null;
170
+ const normalized = rowPath.replace(/\\/g, "/");
171
+ for (const c of set.changes) {
172
+ const path = c.pathAfter || c.pathBefore;
173
+ if (path && (normalized === path || normalized.endsWith(`/${path}`))) {
174
+ return c;
175
+ }
176
+ }
177
+ return null;
178
+ }
179
+
180
+ /**
181
+ * The review state a stamped transcript row should badge — how this file edit
182
+ * stands in its change set's review lifecycle. `null` means "show no badge",
183
+ * chosen over guessing: a missing set (not yet projected), a CAPTURING set, or
184
+ * a row whose file is absent from the set (its edit was superseded or fully
185
+ * reverted within the turn) renders unbadged, never mislabeled.
186
+ *
187
+ * - `"pending"` — the set is AWAITING_REVIEW; this edit's net result is on the
188
+ * decision surface now.
189
+ * - `"kept"` / `"discarded"` — the set is decided/reconciled and this file's
190
+ * effective verdict is known ({@link deriveEffectiveVerdicts}).
191
+ * - `"failed"` — the set's reconcile failed; the workspace outcome for this
192
+ * edit is not the reviewed one.
193
+ */
194
+ export type FileReviewRowState = "pending" | "kept" | "discarded" | "failed";
195
+
196
+ export function fileReviewRowState(
197
+ set: FileChangeSet | undefined,
198
+ rowPath: string | null,
199
+ ): FileReviewRowState | null {
200
+ if (!set) return null;
201
+ switch (set.status) {
202
+ case FileChangeSetStatus.AWAITING_REVIEW:
203
+ return "pending";
204
+ case FileChangeSetStatus.FAILED:
205
+ return "failed";
206
+ case FileChangeSetStatus.DECIDED:
207
+ case FileChangeSetStatus.RECONCILED: {
208
+ if (!rowPath) return null;
209
+ const change = changeForRowPath(set, rowPath);
210
+ if (!change) return null;
211
+ const verdict = deriveEffectiveVerdicts(set).get(change.id);
212
+ if (verdict === FileDecisionAction.APPROVE) return "kept";
213
+ if (verdict === FileDecisionAction.REJECT) return "discarded";
214
+ return null;
215
+ }
216
+ default:
217
+ return null;
218
+ }
219
+ }
@@ -47,15 +47,38 @@ export type { UseExecutionArtifactsReturn } from "./useExecutionArtifacts";
47
47
  export { useArtifactContent } from "./useArtifactContent";
48
48
  export type { UseArtifactContentReturn } from "./useArtifactContent";
49
49
 
50
+ export { useArtifactDownloadUrl } from "./useArtifactDownloadUrl";
51
+ export type {
52
+ UseArtifactDownloadUrlReturn,
53
+ UseArtifactDownloadUrlOptions,
54
+ } from "./useArtifactDownloadUrl";
55
+
56
+ export { useArtifactDownload } from "./useArtifactDownload";
57
+ export type { UseArtifactDownloadReturn } from "./useArtifactDownload";
58
+
59
+ export { useToolOutputContent } from "./useToolOutputContent";
60
+ export type {
61
+ UseToolOutputContentReturn,
62
+ ToolOutputRefLike,
63
+ } from "./useToolOutputContent";
64
+
65
+ export { useFileChangeContent, execIdFromStorageKey } from "./useFileChangeContent";
66
+ export type { UseFileChangeContentReturn } from "./useFileChangeContent";
67
+
50
68
  export { useWorkspaceWriteBacks } from "./useWorkspaceWriteBacks";
51
69
  export type { UseWorkspaceWriteBacksReturn } from "./useWorkspaceWriteBacks";
52
70
 
53
71
  export { WriteBackCard } from "./WriteBackCard";
54
72
  export type { WriteBackCardProps } from "./WriteBackCard";
55
73
 
74
+ export { FileChangesView, FileChangeDiff } from "./FileChangesView";
75
+ export type { FileChangesViewProps, FileChangeDiffProps } from "./FileChangesView";
76
+
77
+ export { EmptyChangeNotice } from "./EmptyChangeNotice";
78
+ export type { EmptyChangeNoticeProps, EmptyChangeKind } from "./EmptyChangeNotice";
79
+
56
80
  export {
57
81
  isTextArtifact,
58
- isArtifactExpired,
59
82
  formatArtifactSize,
60
83
  getArtifactExtension,
61
84
  getFileExtension,
@@ -75,9 +98,17 @@ export type { SetupProgressProps } from "./SetupProgress";
75
98
  export { ToolCallGroup } from "./ToolCallGroup";
76
99
  export type { ToolCallGroupProps } from "./ToolCallGroup";
77
100
 
101
+ export { ToolRunGroup } from "./ToolRunGroup";
102
+ export type { ToolRunGroupProps } from "./ToolRunGroup";
103
+
104
+ export { segmentToolCalls } from "./segment-tool-calls";
105
+ export type { ToolSegment } from "./segment-tool-calls";
106
+
78
107
  export { ToolCallDetail, formatDuration } from "./ToolCallDetail";
79
108
  export type { ToolCallDetailProps } from "./ToolCallDetail";
80
109
 
110
+ export { describeApprovalPolicySource } from "./approval-provenance";
111
+
81
112
  export { McpToolDetail, McpArgsView, McpMetadataRow, parseMcpResult } from "./McpToolDetail";
82
113
  export type {
83
114
  McpToolDetailProps,
@@ -91,6 +122,9 @@ export type { ToolArgsViewProps } from "./ToolArgsView";
91
122
  export { ResultView, summarizeResultView } from "./ResultView";
92
123
  export type { ResultViewProps } from "./ResultView";
93
124
 
125
+ export { TerminalSession } from "./TerminalSession";
126
+ export type { TerminalSessionProps } from "./TerminalSession";
127
+
94
128
  export {
95
129
  useToolPresentation,
96
130
  registerToolPresenter,
@@ -145,12 +179,56 @@ export {
145
179
  } from "./TodoList";
146
180
  export type { TodoListProps } from "./TodoList";
147
181
 
182
+ export { TodoCard } from "./TodoCard";
183
+ export type { TodoCardProps } from "./TodoCard";
184
+
148
185
 
149
186
  export { useSubmitApproval } from "./useSubmitApproval";
150
187
  export type { UseSubmitApprovalReturn } from "./useSubmitApproval";
151
188
 
152
- export { ApprovalCard } from "./ApprovalCard";
153
- export type { ApprovalCardProps } from "./ApprovalCard";
189
+ export { useFileReview, fileDecisionKey } from "./useFileReview";
190
+ export type { UseFileReviewReturn, FileDecisionOptions } from "./useFileReview";
191
+
192
+ export {
193
+ fileReviewability,
194
+ changeSetReviewability,
195
+ deriveEffectiveVerdicts,
196
+ changeForRowPath,
197
+ fileReviewRowState,
198
+ } from "./file-review-status";
199
+ export type {
200
+ FileReviewability,
201
+ FileBlockReason,
202
+ ChangeSetReviewability,
203
+ FileReviewRowState,
204
+ } from "./file-review-status";
205
+
206
+ // Settled/historical file-review display: the ledger fold + its read seam +
207
+ // the display-projection adapter, re-exported from @stigmer/sdk (pure, shared).
208
+ export {
209
+ foldFileReviewEventStream,
210
+ displayFileChangeSets,
211
+ toDisplayFileChange,
212
+ } from "@stigmer/sdk";
213
+
214
+ export { ApprovalCard, ApprovalCardHeader, ApprovalCardBody } from "./ApprovalCard";
215
+ export type {
216
+ ApprovalCardProps,
217
+ ApprovalCardHeaderProps,
218
+ ApprovalCardBodyProps,
219
+ } from "./ApprovalCard";
220
+
221
+ export { FileReviewCard } from "./FileReviewCard";
222
+ export type { FileReviewCardProps } from "./FileReviewCard";
223
+
224
+ export { FileReviewDock } from "./FileReviewDock";
225
+ export type { FileReviewDockProps } from "./FileReviewDock";
226
+
227
+ export { ApprovalContext, useApproval } from "./ApprovalContext";
228
+ export type { ApprovalContextValue, UseApprovalResult } from "./ApprovalContext";
229
+
230
+ export { FileReviewContext, useFileReviewRowState } from "./FileReviewContext";
231
+ export type { FileReviewContextValue } from "./FileReviewContext";
154
232
 
155
233
  export { ArtifactCard } from "./ArtifactCard";
156
234
  export type { ArtifactCardProps } from "./ArtifactCard";
@@ -175,8 +253,10 @@ export {
175
253
  extractPrimaryArg,
176
254
  extractPrimaryArgFromPreview,
177
255
  humanizeToolName,
256
+ defaultDisclosureForCategory,
257
+ isRunGroupableCategory,
178
258
  } from "./tool-categories";
179
- export type { ToolCategory, ToolCategoryInfo } from "./tool-categories";
259
+ export type { ToolCategory, ToolCategoryInfo, ToolDisclosure } from "./tool-categories";
180
260
 
181
261
  export { FilePathLink } from "./FilePathLink";
182
262
  export type { FilePathLinkProps } from "./FilePathLink";
@@ -0,0 +1,101 @@
1
+ import type { ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
2
+ import { resolveToolCategoryFromCall } from "./tool-categories";
3
+ import type { ToolCategory } from "./tool-categories";
4
+ import { resolveRunGroupable } from "./tool-presenter";
5
+
6
+ /**
7
+ * Minimum number of consecutive same-category groupable calls before they fold
8
+ * into a chip. A lone groupable call (e.g. a single `Read foo.ts`) reads better
9
+ * as its own row than as a one-item "Read 1 file" chip, so grouping only kicks
10
+ * in at two or more.
11
+ */
12
+ const MIN_RUN_LENGTH = 2;
13
+
14
+ /**
15
+ * One renderable unit of a turn's tool activity.
16
+ *
17
+ * - `row` — a single tool call rendered as a persistent timeline row.
18
+ * - `run` — a maximal run of >= {@link MIN_RUN_LENGTH} consecutive low-signal
19
+ * same-category calls (e.g. reads), folded into one collapsible chip.
20
+ */
21
+ export type ToolSegment =
22
+ | { readonly kind: "row"; readonly toolCall: ToolCall; readonly key: string }
23
+ | {
24
+ readonly kind: "run";
25
+ readonly category: ToolCategory;
26
+ readonly toolCalls: readonly ToolCall[];
27
+ readonly key: string;
28
+ };
29
+
30
+ /** Stable key for a single tool-call row (mirrors the prior group keying). */
31
+ function rowKey(toolCall: ToolCall): string {
32
+ return toolCall.id || toolCall.name;
33
+ }
34
+
35
+ /**
36
+ * Partitions a turn's tool calls into a chronological sequence of {@link
37
+ * ToolSegment}s: maximal runs of consecutive low-signal same-category calls
38
+ * (read / list / search) fold into one `run` chip, while every other call —
39
+ * and any groupable call that has no same-kind neighbour — stays a persistent
40
+ * `row`.
41
+ *
42
+ * This is the layout pass behind the "persistent-row timeline": instead of
43
+ * hiding a whole turn behind one collapse, only repetitive noise is compressed,
44
+ * and high-signal rows (edits, shell, MCP, sub-agents) always remain visible.
45
+ * Chronology is preserved — a run never reorders calls, and an interleaving of
46
+ * categories (read, search, read) yields three separate segments, not one.
47
+ *
48
+ * Pure and dependency-light so it can be unit-tested exhaustively and memoized
49
+ * by the caller; groupability is resolved through {@link resolveRunGroupable},
50
+ * so a consumer's registry override is honoured here exactly as in the
51
+ * component layer.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * // read, read, read, edit -> [run(read x3), row(edit)]
56
+ * // read, search, read -> [row(read), row(search), row(read)]
57
+ * const segments = segmentToolCalls(message.toolCalls);
58
+ * ```
59
+ */
60
+ export function segmentToolCalls(
61
+ toolCalls: readonly ToolCall[],
62
+ ): ToolSegment[] {
63
+ const segments: ToolSegment[] = [];
64
+
65
+ // Resolve category + groupability once per call so the scan below is a cheap
66
+ // index walk rather than repeated kind resolution.
67
+ const categories = toolCalls.map(
68
+ (tc) => resolveToolCategoryFromCall(tc).category,
69
+ );
70
+ const groupable = toolCalls.map((tc) => resolveRunGroupable(tc));
71
+
72
+ let i = 0;
73
+ while (i < toolCalls.length) {
74
+ const category = categories[i];
75
+
76
+ if (groupable[i]) {
77
+ // Extend the run while the next call is the same groupable category.
78
+ let j = i + 1;
79
+ while (j < toolCalls.length && groupable[j] && categories[j] === category) {
80
+ j++;
81
+ }
82
+
83
+ if (j - i >= MIN_RUN_LENGTH) {
84
+ const run = toolCalls.slice(i, j);
85
+ segments.push({
86
+ kind: "run",
87
+ category,
88
+ toolCalls: run,
89
+ key: `run-${category}-${rowKey(run[0])}`,
90
+ });
91
+ i = j;
92
+ continue;
93
+ }
94
+ }
95
+
96
+ segments.push({ kind: "row", toolCall: toolCalls[i], key: rowKey(toolCalls[i]) });
97
+ i++;
98
+ }
99
+
100
+ return segments;
101
+ }