@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.
- package/execution/ApprovalCard.d.ts +47 -3
- package/execution/ApprovalCard.d.ts.map +1 -1
- package/execution/ApprovalCard.js +138 -70
- package/execution/ApprovalCard.js.map +1 -1
- package/execution/ApprovalContext.d.ts +72 -0
- package/execution/ApprovalContext.d.ts.map +1 -0
- package/execution/ApprovalContext.js +41 -0
- package/execution/ApprovalContext.js.map +1 -0
- package/execution/ArtifactCard.d.ts.map +1 -1
- package/execution/ArtifactCard.js +3 -1
- package/execution/ArtifactCard.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts.map +1 -1
- package/execution/ArtifactPreviewModal.js +5 -3
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/EmptyChangeNotice.d.ts +38 -0
- package/execution/EmptyChangeNotice.d.ts.map +1 -0
- package/execution/EmptyChangeNotice.js +27 -0
- package/execution/EmptyChangeNotice.js.map +1 -0
- package/execution/FileChangesView.d.ts +81 -0
- package/execution/FileChangesView.d.ts.map +1 -0
- package/execution/FileChangesView.js +164 -0
- package/execution/FileChangesView.js.map +1 -0
- package/execution/FilePathLink.d.ts +24 -4
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +31 -9
- package/execution/FilePathLink.js.map +1 -1
- package/execution/FileReviewCard.d.ts +111 -0
- package/execution/FileReviewCard.d.ts.map +1 -0
- package/execution/FileReviewCard.js +558 -0
- package/execution/FileReviewCard.js.map +1 -0
- package/execution/FileReviewContext.d.ts +35 -0
- package/execution/FileReviewContext.d.ts.map +1 -0
- package/execution/FileReviewContext.js +23 -0
- package/execution/FileReviewContext.js.map +1 -0
- package/execution/FileReviewDock.d.ts +73 -0
- package/execution/FileReviewDock.d.ts.map +1 -0
- package/execution/FileReviewDock.js +65 -0
- package/execution/FileReviewDock.js.map +1 -0
- package/execution/McpToolDetail.d.ts.map +1 -1
- package/execution/McpToolDetail.js +38 -5
- package/execution/McpToolDetail.js.map +1 -1
- package/execution/MessageThread.d.ts +42 -3
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +263 -18
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +3 -1
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/PlanCompletionCard.d.ts +1 -1
- package/execution/PlanCompletionCard.js +1 -1
- package/execution/ResultView.d.ts +19 -1
- package/execution/ResultView.d.ts.map +1 -1
- package/execution/ResultView.js +141 -40
- package/execution/ResultView.js.map +1 -1
- package/execution/SubAgentSection.d.ts.map +1 -1
- package/execution/SubAgentSection.js +45 -6
- package/execution/SubAgentSection.js.map +1 -1
- package/execution/TerminalSession.d.ts +34 -0
- package/execution/TerminalSession.d.ts.map +1 -0
- package/execution/TerminalSession.js +34 -0
- package/execution/TerminalSession.js.map +1 -0
- package/execution/TodoCard.d.ts +53 -0
- package/execution/TodoCard.d.ts.map +1 -0
- package/execution/TodoCard.js +77 -0
- package/execution/TodoCard.js.map +1 -0
- package/execution/ToolArgsView.d.ts +7 -1
- package/execution/ToolArgsView.d.ts.map +1 -1
- package/execution/ToolArgsView.js +10 -9
- package/execution/ToolArgsView.js.map +1 -1
- package/execution/ToolCallDetail.d.ts +10 -1
- package/execution/ToolCallDetail.d.ts.map +1 -1
- package/execution/ToolCallDetail.js +66 -19
- package/execution/ToolCallDetail.js.map +1 -1
- package/execution/ToolCallGroup.d.ts +28 -18
- package/execution/ToolCallGroup.d.ts.map +1 -1
- package/execution/ToolCallGroup.js +39 -148
- package/execution/ToolCallGroup.js.map +1 -1
- package/execution/ToolCallItem.d.ts +36 -8
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +140 -21
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/ToolRunGroup.d.ts +48 -0
- package/execution/ToolRunGroup.d.ts.map +1 -0
- package/execution/ToolRunGroup.js +168 -0
- package/execution/ToolRunGroup.js.map +1 -0
- package/execution/approval-provenance.d.ts +2 -0
- package/execution/approval-provenance.d.ts.map +1 -0
- package/execution/approval-provenance.js +6 -0
- package/execution/approval-provenance.js.map +1 -0
- package/execution/artifact-utils.d.ts +0 -10
- package/execution/artifact-utils.d.ts.map +1 -1
- package/execution/artifact-utils.js +0 -17
- package/execution/artifact-utils.js.map +1 -1
- package/execution/execution-phases.d.ts +1 -6
- package/execution/execution-phases.d.ts.map +1 -1
- package/execution/execution-phases.js +4 -14
- package/execution/execution-phases.js.map +1 -1
- package/execution/file-path-resolver.d.ts +28 -0
- package/execution/file-path-resolver.d.ts.map +1 -1
- package/execution/file-path-resolver.js +24 -0
- package/execution/file-path-resolver.js.map +1 -1
- package/execution/file-review-status.d.ts +127 -0
- package/execution/file-review-status.d.ts.map +1 -0
- package/execution/file-review-status.js +135 -0
- package/execution/file-review-status.js.map +1 -0
- package/execution/index.d.ts +39 -5
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +23 -3
- package/execution/index.js.map +1 -1
- package/execution/segment-tool-calls.d.ts +46 -0
- package/execution/segment-tool-calls.d.ts.map +1 -0
- package/execution/segment-tool-calls.js +71 -0
- package/execution/segment-tool-calls.js.map +1 -0
- package/execution/tool-categories.d.ts +62 -1
- package/execution/tool-categories.d.ts.map +1 -1
- package/execution/tool-categories.js +96 -2
- package/execution/tool-categories.js.map +1 -1
- package/execution/tool-presenter.d.ts +38 -2
- package/execution/tool-presenter.d.ts.map +1 -1
- package/execution/tool-presenter.js +23 -1
- package/execution/tool-presenter.js.map +1 -1
- package/execution/tool-rendering-primitives.d.ts.map +1 -1
- package/execution/tool-rendering-primitives.js +3 -2
- package/execution/tool-rendering-primitives.js.map +1 -1
- package/execution/useArtifactDownload.d.ts +44 -0
- package/execution/useArtifactDownload.d.ts.map +1 -0
- package/execution/useArtifactDownload.js +80 -0
- package/execution/useArtifactDownload.js.map +1 -0
- package/execution/useArtifactDownloadUrl.d.ts +67 -0
- package/execution/useArtifactDownloadUrl.d.ts.map +1 -0
- package/execution/useArtifactDownloadUrl.js +59 -0
- package/execution/useArtifactDownloadUrl.js.map +1 -0
- package/execution/useFileChangeContent.d.ts +61 -0
- package/execution/useFileChangeContent.d.ts.map +1 -0
- package/execution/useFileChangeContent.js +89 -0
- package/execution/useFileChangeContent.js.map +1 -0
- package/execution/useFileReview.d.ts +89 -0
- package/execution/useFileReview.d.ts.map +1 -0
- package/execution/useFileReview.js +106 -0
- package/execution/useFileReview.js.map +1 -0
- package/execution/useSubmitApproval.d.ts +17 -2
- package/execution/useSubmitApproval.d.ts.map +1 -1
- package/execution/useSubmitApproval.js +27 -23
- package/execution/useSubmitApproval.js.map +1 -1
- package/execution/useToolOutputContent.d.ts +44 -0
- package/execution/useToolOutputContent.d.ts.map +1 -0
- package/execution/useToolOutputContent.js +31 -0
- package/execution/useToolOutputContent.js.map +1 -0
- package/index.d.ts +6 -6
- package/index.d.ts.map +1 -1
- package/index.js +3 -3
- package/index.js.map +1 -1
- package/internal/ApprovalPeekBar.d.ts +23 -0
- package/internal/ApprovalPeekBar.d.ts.map +1 -0
- package/internal/ApprovalPeekBar.js +25 -0
- package/internal/ApprovalPeekBar.js.map +1 -0
- package/internal/BoundedContent.d.ts +49 -0
- package/internal/BoundedContent.d.ts.map +1 -0
- package/internal/BoundedContent.js +50 -0
- package/internal/BoundedContent.js.map +1 -0
- package/internal/DecisionButton.d.ts +47 -0
- package/internal/DecisionButton.d.ts.map +1 -0
- package/internal/DecisionButton.js +42 -0
- package/internal/DecisionButton.js.map +1 -0
- package/internal/InCardDecisionError.d.ts +31 -0
- package/internal/InCardDecisionError.d.ts.map +1 -0
- package/internal/InCardDecisionError.js +23 -0
- package/internal/InCardDecisionError.js.map +1 -0
- package/internal/RevealToggle.d.ts +36 -0
- package/internal/RevealToggle.d.ts.map +1 -0
- package/internal/RevealToggle.js +32 -0
- package/internal/RevealToggle.js.map +1 -0
- package/internal/VirtualizedThread.d.ts +7 -1
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +7 -3
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/useAutoDisclosure.d.ts +34 -0
- package/internal/useAutoDisclosure.d.ts.map +1 -0
- package/internal/useAutoDisclosure.js +53 -0
- package/internal/useAutoDisclosure.js.map +1 -0
- package/internal/useElapsedSince.d.ts +30 -0
- package/internal/useElapsedSince.d.ts.map +1 -0
- package/internal/useElapsedSince.js +70 -0
- package/internal/useElapsedSince.js.map +1 -0
- package/internal/useIsOverflowing.d.ts +30 -0
- package/internal/useIsOverflowing.d.ts.map +1 -0
- package/internal/useIsOverflowing.js +47 -0
- package/internal/useIsOverflowing.js.map +1 -0
- package/internal/useIsTextTruncated.d.ts +24 -0
- package/internal/useIsTextTruncated.d.ts.map +1 -0
- package/internal/useIsTextTruncated.js +41 -0
- package/internal/useIsTextTruncated.js.map +1 -0
- package/internal/useKeyedSubmission.d.ts +49 -0
- package/internal/useKeyedSubmission.d.ts.map +1 -0
- package/internal/useKeyedSubmission.js +67 -0
- package/internal/useKeyedSubmission.js.map +1 -0
- package/package.json +4 -4
- package/session/SessionViewer.d.ts +2 -2
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +10 -4
- package/session/SessionViewer.js.map +1 -1
- package/session/index.d.ts +2 -0
- package/session/index.d.ts.map +1 -1
- package/session/index.js +1 -0
- package/session/index.js.map +1 -1
- package/session/inspector/ChangesTab.d.ts +8 -5
- package/session/inspector/ChangesTab.d.ts.map +1 -1
- package/session/inspector/ChangesTab.js +11 -8
- package/session/inspector/ChangesTab.js.map +1 -1
- package/session/inspector/SessionInspector.d.ts +4 -4
- package/session/inspector/SessionInspector.d.ts.map +1 -1
- package/session/inspector/SessionInspector.js +4 -4
- package/session/inspector/SessionInspector.js.map +1 -1
- package/session/inspector/index.d.ts +0 -2
- package/session/inspector/index.d.ts.map +1 -1
- package/session/inspector/index.js +0 -1
- package/session/inspector/index.js.map +1 -1
- package/session/inspector/useSessionInspector.d.ts +8 -4
- package/session/inspector/useSessionInspector.d.ts.map +1 -1
- package/session/inspector/useSessionInspector.js +27 -20
- package/session/inspector/useSessionInspector.js.map +1 -1
- package/session/useSessionConversation.d.ts +37 -3
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +18 -2
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionFileChanges.d.ts +74 -0
- package/session/useSessionFileChanges.d.ts.map +1 -0
- package/session/useSessionFileChanges.js +178 -0
- package/session/useSessionFileChanges.js.map +1 -0
- package/src/__tests__/styles-border-layer-invariant.test.ts +105 -0
- package/src/execution/ApprovalCard.tsx +368 -230
- package/src/execution/ApprovalContext.ts +109 -0
- package/src/execution/ArtifactCard.tsx +10 -6
- package/src/execution/ArtifactPreviewModal.tsx +12 -6
- package/src/execution/EmptyChangeNotice.tsx +62 -0
- package/src/execution/FileChangesView.tsx +383 -0
- package/src/execution/FilePathLink.tsx +65 -12
- package/src/execution/FileReviewCard.tsx +1118 -0
- package/src/execution/FileReviewContext.ts +53 -0
- package/src/execution/FileReviewDock.tsx +157 -0
- package/src/execution/McpToolDetail.tsx +98 -32
- package/src/execution/MessageThread.tsx +374 -9
- package/src/execution/PlanArtifactCard.tsx +9 -6
- package/src/execution/PlanCompletionCard.tsx +1 -1
- package/src/execution/ResultView.tsx +333 -162
- package/src/execution/SubAgentSection.tsx +58 -11
- package/src/execution/TerminalSession.tsx +91 -0
- package/src/execution/TodoCard.tsx +186 -0
- package/src/execution/ToolArgsView.tsx +28 -17
- package/src/execution/ToolCallDetail.tsx +137 -26
- package/src/execution/ToolCallGroup.tsx +68 -296
- package/src/execution/ToolCallItem.tsx +265 -67
- package/src/execution/ToolRunGroup.tsx +302 -0
- package/src/execution/__tests__/ApprovalCard.test.tsx +395 -5
- package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +0 -1
- package/src/execution/__tests__/EmptyChangeNotice.test.tsx +24 -0
- package/src/execution/__tests__/FileChangesView.test.tsx +296 -0
- package/src/execution/__tests__/FilePathLink.test.tsx +92 -0
- package/src/execution/__tests__/FileReviewCard.test.tsx +1044 -0
- package/src/execution/__tests__/FileReviewDock.test.tsx +134 -0
- package/src/execution/__tests__/McpToolDetail.test.tsx +79 -0
- package/src/execution/__tests__/MessageThread.test.tsx +324 -0
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +37 -16
- package/src/execution/__tests__/ResultView.test.tsx +280 -2
- package/src/execution/__tests__/SubAgentSection.test.tsx +180 -0
- package/src/execution/__tests__/TerminalSession.test.tsx +72 -0
- package/src/execution/__tests__/TodoCard.test.tsx +102 -0
- package/src/execution/__tests__/ToolArgsView.test.tsx +48 -0
- package/src/execution/__tests__/ToolCallDetail.test.tsx +195 -0
- package/src/execution/__tests__/ToolCallGroup.test.tsx +132 -0
- package/src/execution/__tests__/ToolCallItem.test.tsx +521 -0
- package/src/execution/__tests__/ToolRunGroup.test.tsx +137 -0
- package/src/execution/__tests__/blanked-narration.test.tsx +149 -0
- package/src/execution/__tests__/buildThreadItems-approvals.test.ts +304 -0
- package/src/execution/__tests__/buildThreadItems-file-review.test.ts +331 -0
- package/src/execution/__tests__/file-path-resolver.test.ts +44 -0
- package/src/execution/__tests__/file-review-status.test.ts +343 -0
- package/src/execution/__tests__/segment-tool-calls.test.ts +124 -0
- package/src/execution/__tests__/subagent-file-review-badge.test.tsx +273 -0
- package/src/execution/__tests__/thread-keys.test.ts +195 -0
- package/src/execution/__tests__/tool-presenter.test.tsx +95 -0
- package/src/execution/__tests__/useArtifactDownload.test.tsx +67 -0
- package/src/execution/__tests__/useArtifactDownloadUrl.test.tsx +51 -0
- package/src/execution/__tests__/useFileChangeContent.test.tsx +240 -0
- package/src/execution/__tests__/useFileReview.test.tsx +236 -0
- package/src/execution/__tests__/useSubmitApproval.test.tsx +165 -0
- package/src/execution/__tests__/useToolOutputContent.test.tsx +82 -0
- package/src/execution/approval-provenance.ts +8 -0
- package/src/execution/artifact-utils.ts +0 -18
- package/src/execution/execution-phases.ts +4 -16
- package/src/execution/file-path-resolver.ts +38 -0
- package/src/execution/file-review-status.ts +219 -0
- package/src/execution/index.ts +84 -4
- package/src/execution/segment-tool-calls.ts +101 -0
- package/src/execution/tool-categories.ts +128 -1
- package/src/execution/tool-presenter.ts +58 -3
- package/src/execution/tool-rendering-primitives.tsx +11 -14
- package/src/execution/useArtifactDownload.ts +109 -0
- package/src/execution/useArtifactDownloadUrl.ts +116 -0
- package/src/execution/useFileChangeContent.ts +149 -0
- package/src/execution/useFileReview.ts +197 -0
- package/src/execution/useSubmitApproval.ts +49 -27
- package/src/execution/useToolOutputContent.ts +70 -0
- package/src/index.ts +60 -1
- package/src/internal/ApprovalPeekBar.tsx +73 -0
- package/src/internal/BoundedContent.tsx +97 -0
- package/src/internal/DecisionButton.tsx +127 -0
- package/src/internal/InCardDecisionError.tsx +47 -0
- package/src/internal/RevealToggle.tsx +91 -0
- package/src/internal/VirtualizedThread.tsx +28 -2
- package/src/internal/__tests__/ApprovalPeekBar.test.tsx +34 -0
- package/src/internal/__tests__/BoundedContent.test.tsx +92 -0
- package/src/internal/__tests__/DecisionButton.test.tsx +107 -0
- package/src/internal/__tests__/RevealToggle.test.tsx +61 -0
- package/src/internal/__tests__/useAutoDisclosure.test.ts +74 -0
- package/src/internal/__tests__/useElapsedSince.test.tsx +68 -0
- package/src/internal/__tests__/useIsOverflowing.test.ts +36 -0
- package/src/internal/__tests__/useKeyedSubmission.test.tsx +126 -0
- package/src/internal/useAutoDisclosure.ts +58 -0
- package/src/internal/useElapsedSince.ts +72 -0
- package/src/internal/useIsOverflowing.ts +61 -0
- package/src/internal/useIsTextTruncated.ts +55 -0
- package/src/internal/useKeyedSubmission.ts +101 -0
- package/src/session/SessionViewer.tsx +21 -4
- package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +198 -0
- package/src/session/__tests__/audienceWiring.test.tsx +4 -0
- package/src/session/__tests__/useSessionFileChanges.test.ts +303 -0
- package/src/session/index.ts +3 -0
- package/src/session/inspector/ChangesTab.tsx +20 -17
- package/src/session/inspector/SessionInspector.tsx +12 -10
- package/src/session/inspector/__tests__/ArtifactsTab.test.tsx +0 -1
- package/src/session/inspector/__tests__/ChangesTab.test.tsx +38 -0
- package/src/session/inspector/__tests__/useSessionInspector.test.ts +46 -61
- package/src/session/inspector/index.ts +0 -3
- package/src/session/inspector/useSessionInspector.ts +27 -20
- package/src/session/useSessionConversation.ts +80 -3
- package/src/session/useSessionFileChanges.ts +207 -0
- package/src/styles.css +35 -10
- package/src/version-history/DiffViewer.tsx +10 -7
- package/src/version-history/UnifiedDiffView.tsx +66 -0
- package/src/version-history/__tests__/DiffViewer.test.tsx +57 -0
- package/src/version-history/__tests__/UnifiedDiffView.test.tsx +50 -0
- package/src/version-history/__tests__/computeDiff.test.ts +35 -0
- package/src/version-history/__tests__/parseUnifiedDiff.test.ts +82 -0
- package/src/version-history/computeDiff.ts +6 -37
- package/src/version-history/diff-hunks.ts +63 -0
- package/src/version-history/index.ts +1 -0
- package/src/version-history/parseUnifiedDiff.ts +34 -0
- package/src/workflow/WorkflowExecutionApprovalCard.tsx +49 -24
- package/src/workflow/WorkflowExecutionTimeline.tsx +15 -4
- package/src/workflow/WorkflowExecutionTimelineEvent.tsx +8 -3
- package/src/workflow/WorkflowExecutionViewer.tsx +72 -28
- package/src/workflow/WorkflowFileReviewList.tsx +152 -0
- package/src/workflow/WorkflowTaskApprovalCard.tsx +37 -85
- package/src/workflow/__tests__/ExecutionInspector.test.tsx +30 -2
- package/src/workflow/__tests__/WorkflowExecutionApprovalCard.test.tsx +129 -0
- package/src/workflow/__tests__/WorkflowFileReviewList.test.tsx +129 -0
- package/src/workflow/__tests__/WorkflowTaskApprovalCard.test.tsx +43 -11
- package/src/workflow/__tests__/useWorkflowExecutionActions.test.tsx +276 -0
- package/src/workflow/execution-inspector/ExecutionInspector.tsx +42 -18
- package/src/workflow/index.ts +5 -0
- package/src/workflow/useWorkflowExecutionActions.ts +177 -29
- package/styles.css +1 -1
- package/version-history/DiffViewer.d.ts.map +1 -1
- package/version-history/DiffViewer.js +9 -3
- package/version-history/DiffViewer.js.map +1 -1
- package/version-history/UnifiedDiffView.d.ts +29 -0
- package/version-history/UnifiedDiffView.d.ts.map +1 -0
- package/version-history/UnifiedDiffView.js +36 -0
- package/version-history/UnifiedDiffView.js.map +1 -0
- package/version-history/computeDiff.d.ts +3 -1
- package/version-history/computeDiff.d.ts.map +1 -1
- package/version-history/computeDiff.js +5 -35
- package/version-history/computeDiff.js.map +1 -1
- package/version-history/diff-hunks.d.ts +21 -0
- package/version-history/diff-hunks.d.ts.map +1 -0
- package/version-history/diff-hunks.js +58 -0
- package/version-history/diff-hunks.js.map +1 -0
- package/version-history/index.d.ts +1 -0
- package/version-history/index.d.ts.map +1 -1
- package/version-history/index.js +1 -0
- package/version-history/index.js.map +1 -1
- package/version-history/parseUnifiedDiff.d.ts +22 -0
- package/version-history/parseUnifiedDiff.d.ts.map +1 -0
- package/version-history/parseUnifiedDiff.js +34 -0
- package/version-history/parseUnifiedDiff.js.map +1 -0
- package/workflow/WorkflowExecutionApprovalCard.d.ts +8 -1
- package/workflow/WorkflowExecutionApprovalCard.d.ts.map +1 -1
- package/workflow/WorkflowExecutionApprovalCard.js +17 -3
- package/workflow/WorkflowExecutionApprovalCard.js.map +1 -1
- package/workflow/WorkflowExecutionTimeline.d.ts +11 -2
- package/workflow/WorkflowExecutionTimeline.d.ts.map +1 -1
- package/workflow/WorkflowExecutionTimeline.js +2 -2
- package/workflow/WorkflowExecutionTimeline.js.map +1 -1
- package/workflow/WorkflowExecutionTimelineEvent.d.ts +4 -1
- package/workflow/WorkflowExecutionTimelineEvent.d.ts.map +1 -1
- package/workflow/WorkflowExecutionTimelineEvent.js +2 -2
- package/workflow/WorkflowExecutionTimelineEvent.js.map +1 -1
- package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
- package/workflow/WorkflowExecutionViewer.js +18 -10
- package/workflow/WorkflowExecutionViewer.js.map +1 -1
- package/workflow/WorkflowFileReviewList.d.ts +46 -0
- package/workflow/WorkflowFileReviewList.d.ts.map +1 -0
- package/workflow/WorkflowFileReviewList.js +48 -0
- package/workflow/WorkflowFileReviewList.js.map +1 -0
- package/workflow/WorkflowTaskApprovalCard.d.ts +8 -1
- package/workflow/WorkflowTaskApprovalCard.d.ts.map +1 -1
- package/workflow/WorkflowTaskApprovalCard.js +12 -19
- package/workflow/WorkflowTaskApprovalCard.js.map +1 -1
- package/workflow/execution-inspector/ExecutionInspector.d.ts +21 -4
- package/workflow/execution-inspector/ExecutionInspector.d.ts.map +1 -1
- package/workflow/execution-inspector/ExecutionInspector.js +6 -3
- package/workflow/execution-inspector/ExecutionInspector.js.map +1 -1
- package/workflow/index.d.ts +1 -0
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -0
- package/workflow/index.js.map +1 -1
- package/workflow/useWorkflowExecutionActions.d.ts +62 -4
- package/workflow/useWorkflowExecutionActions.d.ts.map +1 -1
- package/workflow/useWorkflowExecutionActions.js +94 -18
- package/workflow/useWorkflowExecutionActions.js.map +1 -1
- package/session/inspector/PlanTab.d.ts +0 -15
- package/session/inspector/PlanTab.d.ts.map +0 -1
- package/session/inspector/PlanTab.js +0 -19
- package/session/inspector/PlanTab.js.map +0 -1
- package/src/session/inspector/PlanTab.tsx +0 -31
|
@@ -7,14 +7,18 @@ import type { AgentMessage, ToolCall } from "@stigmer/protos/ai/stigmer/agentic/
|
|
|
7
7
|
import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
8
8
|
import type { SubAgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
|
|
9
9
|
import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
|
|
10
|
+
import type { FileChangeSet } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
|
|
10
11
|
import type { ExecutionArtifact } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/artifact_pb";
|
|
12
|
+
import type { TodoItem } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/todo_pb";
|
|
11
13
|
import {
|
|
12
14
|
ApprovalAction,
|
|
13
15
|
ExecutionPhase,
|
|
16
|
+
FileChangeSetStatus,
|
|
14
17
|
InteractionMode,
|
|
15
18
|
MessageType,
|
|
16
19
|
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
17
20
|
import type { WorkspaceEntry } from "@stigmer/protos/ai/stigmer/agentic/session/v1/workspace_pb";
|
|
21
|
+
import { displayFileChangeSets } from "@stigmer/sdk";
|
|
18
22
|
import { cn } from "@stigmer/theme";
|
|
19
23
|
import { isTerminalPhase } from "./execution-phases";
|
|
20
24
|
import { MessageEntry } from "./MessageEntry";
|
|
@@ -23,18 +27,23 @@ import { SubAgentSection } from "./SubAgentSection";
|
|
|
23
27
|
import { ExecutionPhaseBadge } from "./ExecutionPhaseBadge";
|
|
24
28
|
import { SetupProgress } from "./SetupProgress";
|
|
25
29
|
import { ApprovalCard } from "./ApprovalCard";
|
|
30
|
+
import { FileReviewCard } from "./FileReviewCard";
|
|
26
31
|
import { SummarizationCard } from "./SummarizationCard";
|
|
27
32
|
import { PlanCompletionCard } from "./PlanCompletionCard";
|
|
28
33
|
import { PlanArtifactCard } from "./PlanArtifactCard";
|
|
34
|
+
import { TodoCard } from "./TodoCard";
|
|
29
35
|
import { findPlanArtifact } from "../library/detect-plan-artifact";
|
|
30
36
|
import type { SummarizationEventView } from "./useContextWindow";
|
|
31
|
-
import { isInternalTool } from "./tool-categories";
|
|
37
|
+
import { isInternalTool, isCollapsedToolCall } from "./tool-categories";
|
|
32
38
|
import { FilePathContext, type FilePathContextValue } from "./FilePathContext";
|
|
33
39
|
import type { ResolvedPathAction } from "./file-path-resolver";
|
|
34
40
|
import { SandboxContext, type SandboxContextValue } from "./SandboxContext";
|
|
41
|
+
import { ApprovalContext, type ApprovalContextValue } from "./ApprovalContext";
|
|
42
|
+
import { FileReviewContext, type FileReviewContextValue } from "./FileReviewContext";
|
|
35
43
|
import { useRenderTracer, useKeyStability, useDomNodeCount, DevProfiler } from "../internal/dev";
|
|
36
44
|
import { useAutoScroll } from "../internal/useAutoScroll";
|
|
37
45
|
import { JumpToLatestButton } from "../internal/JumpToLatestButton";
|
|
46
|
+
import { ApprovalPeekBar } from "../internal/ApprovalPeekBar";
|
|
38
47
|
import { ThreadItemWrapper } from "../internal/ThreadItemWrapper";
|
|
39
48
|
|
|
40
49
|
const LazyVirtualizedThread = lazy(() =>
|
|
@@ -43,6 +52,11 @@ const LazyVirtualizedThread = lazy(() =>
|
|
|
43
52
|
})),
|
|
44
53
|
);
|
|
45
54
|
|
|
55
|
+
/** Stable empty collections so an approval-free thread keeps referential identity. */
|
|
56
|
+
const EMPTY_APPROVALS: readonly PendingApproval[] = [];
|
|
57
|
+
const EMPTY_SUBMITTING_IDS: ReadonlySet<string> = new Set();
|
|
58
|
+
const EMPTY_APPROVAL_ERRORS: ReadonlyMap<string, Error> = new Map();
|
|
59
|
+
|
|
46
60
|
/** Props for {@link MessageThread}. */
|
|
47
61
|
export interface MessageThreadProps {
|
|
48
62
|
/** Completed executions in chronological order. */
|
|
@@ -116,6 +130,31 @@ export interface MessageThreadProps {
|
|
|
116
130
|
* `onApprovalSubmit` is provided.
|
|
117
131
|
*/
|
|
118
132
|
readonly submittingApprovalIds?: ReadonlySet<string>;
|
|
133
|
+
/**
|
|
134
|
+
* Per-tool-call approval failures, keyed by `toolCallId` — surfaced in-card
|
|
135
|
+
* beside the gate that failed (an inline tool row or the bottom backstop
|
|
136
|
+
* card). Supply {@link useSubmitApproval}'s `errorsByToolCallId`. Only
|
|
137
|
+
* meaningful when `onApprovalSubmit` is provided.
|
|
138
|
+
*/
|
|
139
|
+
readonly approvalErrors?: ReadonlyMap<string, Error>;
|
|
140
|
+
/**
|
|
141
|
+
* Render each *settled* captured change set as a read-only record card at
|
|
142
|
+
* its anchor in the thread (after the set's last stamped edit row) — the
|
|
143
|
+
* durable history of what changed and how it was decided. This is the only
|
|
144
|
+
* in-thread trace for a set with no stamped rows (e.g. changes made by shell
|
|
145
|
+
* commands), so the surface that owns the session history should enable it.
|
|
146
|
+
*
|
|
147
|
+
* The thread never renders *decision* controls: a pending (AWAITING_REVIEW)
|
|
148
|
+
* set on a live execution is deliberately NOT emitted here — its decision
|
|
149
|
+
* surface is the composer-docked {@link FileReviewDock}, which cannot scroll
|
|
150
|
+
* out of view. The stamped rows' badges carry the pending state in-thread.
|
|
151
|
+
*
|
|
152
|
+
* Opt-in with a backward-compatible default (DD-011); `SessionViewer`
|
|
153
|
+
* enables it.
|
|
154
|
+
*
|
|
155
|
+
* @default false
|
|
156
|
+
*/
|
|
157
|
+
readonly showFileReviewRecords?: boolean;
|
|
119
158
|
/**
|
|
120
159
|
* Workspace entries from the session spec. When provided, file
|
|
121
160
|
* paths in tool call rendering become interactive — git-sourced
|
|
@@ -216,8 +255,15 @@ export type ThreadItem =
|
|
|
216
255
|
| { readonly kind: "phase-badge"; readonly phase: ExecutionPhase; readonly key: string }
|
|
217
256
|
| { readonly kind: "execution-error"; readonly error: string; readonly retryMessage?: string; readonly key: string }
|
|
218
257
|
| { readonly kind: "approval-request"; readonly pendingApproval: PendingApproval; readonly key: string }
|
|
258
|
+
| { readonly kind: "file-review-record"; readonly fileChangeSet: FileChangeSet; readonly key: string }
|
|
219
259
|
| { readonly kind: "setup-progress"; readonly workspaceEntries: readonly WorkspaceEntry[]; readonly serverPhase?: string; readonly isAwaitingResponse?: boolean; readonly key: string }
|
|
220
260
|
| { readonly kind: "context-compacted"; readonly event: SummarizationEventView; readonly key: string }
|
|
261
|
+
| {
|
|
262
|
+
readonly kind: "todos";
|
|
263
|
+
readonly key: string;
|
|
264
|
+
readonly executionId: string;
|
|
265
|
+
readonly todos: { readonly [id: string]: TodoItem };
|
|
266
|
+
}
|
|
221
267
|
| {
|
|
222
268
|
readonly kind: "plan-completion";
|
|
223
269
|
readonly key: string;
|
|
@@ -249,6 +295,90 @@ function hasStartedResponding(execution: AgentExecution): boolean {
|
|
|
249
295
|
});
|
|
250
296
|
}
|
|
251
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Adds the tool-call ids that a sub-agent renders as nested rows (the same
|
|
300
|
+
* non-internal AI tool calls {@link SubAgentSection} surfaces) to `target`,
|
|
301
|
+
* so their approvals are treated as inline and skip the bottom backstop.
|
|
302
|
+
*/
|
|
303
|
+
function collectSubAgentInlineToolCallIds(
|
|
304
|
+
sub: SubAgentExecution,
|
|
305
|
+
target: Set<string>,
|
|
306
|
+
): void {
|
|
307
|
+
for (const msg of sub.messages) {
|
|
308
|
+
if (msg.type !== MessageType.MESSAGE_AI) continue;
|
|
309
|
+
for (const tc of msg.toolCalls) {
|
|
310
|
+
if (tc.id && !isInternalTool(tc.name)) target.add(tc.id);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Records, for each change set referenced by a just-pushed tool-group item, the
|
|
317
|
+
* item's index — later groups overwrite, so the map converges on each set's
|
|
318
|
+
* LAST stamped row. That index is where the set's decision bar anchors: the
|
|
319
|
+
* review surface appears where the turn's editing activity ended, not at the
|
|
320
|
+
* thread tail.
|
|
321
|
+
*/
|
|
322
|
+
function recordFileReviewAnchors(
|
|
323
|
+
toolCalls: readonly ToolCall[],
|
|
324
|
+
itemIndex: number,
|
|
325
|
+
anchorIndexBySetId: Map<string, number>,
|
|
326
|
+
): void {
|
|
327
|
+
for (const tc of toolCalls) {
|
|
328
|
+
if (tc.fileChangeSetId) anchorIndexBySetId.set(tc.fileChangeSetId, itemIndex);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Inserts one execution's settled file-review records into its own thread
|
|
334
|
+
* segment: each change set's read-only `file-review-record` item is spliced
|
|
335
|
+
* immediately after the set's last stamped tool row
|
|
336
|
+
* ({@link recordFileReviewAnchors}); a set with no stamped row (its changes
|
|
337
|
+
* were made by shell commands, or the rows predate stamping) falls back to the
|
|
338
|
+
* segment's tail — this record is that set's ONLY in-thread trace, so it is
|
|
339
|
+
* never dropped.
|
|
340
|
+
*
|
|
341
|
+
* A *pending* set — AWAITING_REVIEW on a live (non-terminal) execution — is
|
|
342
|
+
* deliberately NOT emitted: its decision surface is the composer-docked
|
|
343
|
+
* `FileReviewDock`, which cannot scroll out of view, and the stamped rows'
|
|
344
|
+
* badges carry the pending state in place. The same set re-enters here as a
|
|
345
|
+
* record the moment it settles (or its execution terminates mid-review — an
|
|
346
|
+
* honest "not reviewed" record). A CAPTURING set (baseline only, no diff yet)
|
|
347
|
+
* has nothing to show and is skipped.
|
|
348
|
+
*/
|
|
349
|
+
function insertFileReviewItems(
|
|
350
|
+
items: ThreadItem[],
|
|
351
|
+
changeSets: readonly FileChangeSet[],
|
|
352
|
+
anchorIndexBySetId: ReadonlyMap<string, number>,
|
|
353
|
+
execTerminal: boolean,
|
|
354
|
+
): void {
|
|
355
|
+
const anchored: { index: number; item: ThreadItem }[] = [];
|
|
356
|
+
const tail: ThreadItem[] = [];
|
|
357
|
+
for (const changeSet of changeSets) {
|
|
358
|
+
if (changeSet.changes.length === 0) continue;
|
|
359
|
+
const pending =
|
|
360
|
+
!execTerminal && changeSet.status === FileChangeSetStatus.AWAITING_REVIEW;
|
|
361
|
+
if (pending) continue;
|
|
362
|
+
const item: ThreadItem = {
|
|
363
|
+
kind: "file-review-record",
|
|
364
|
+
fileChangeSet: changeSet,
|
|
365
|
+
key: `file-review-${changeSet.id}`,
|
|
366
|
+
};
|
|
367
|
+
const index = anchorIndexBySetId.get(changeSet.id);
|
|
368
|
+
if (index !== undefined) anchored.push({ index, item });
|
|
369
|
+
else tail.push(item);
|
|
370
|
+
}
|
|
371
|
+
// Splice in ascending anchor order with a running offset so earlier inserts
|
|
372
|
+
// do not displace later anchors.
|
|
373
|
+
anchored.sort((a, b) => a.index - b.index);
|
|
374
|
+
let offset = 0;
|
|
375
|
+
for (const { index, item } of anchored) {
|
|
376
|
+
items.splice(index + 1 + offset, 0, item);
|
|
377
|
+
offset++;
|
|
378
|
+
}
|
|
379
|
+
items.push(...tail);
|
|
380
|
+
}
|
|
381
|
+
|
|
252
382
|
/**
|
|
253
383
|
* Builds a flat list of renderable thread items from execution data.
|
|
254
384
|
*
|
|
@@ -266,10 +396,32 @@ export function buildThreadItems(
|
|
|
266
396
|
summarizationEvents?: readonly SummarizationEventView[],
|
|
267
397
|
pendingMessageFailed = false,
|
|
268
398
|
editableActiveTurn = false,
|
|
399
|
+
includeFileReviewRecords = false,
|
|
269
400
|
): ThreadItem[] {
|
|
270
401
|
const items: ThreadItem[] = [];
|
|
402
|
+
// Tool-call ids that render as an inline-approval-capable ToolCallItem (a
|
|
403
|
+
// regular parent tool, or a sub-agent's nested tool). Their approvals show
|
|
404
|
+
// inline on the row, so they are excluded from the bottom backstop below —
|
|
405
|
+
// a task-spawn call (rendered as a SubAgentSection, not a tool row) is NOT
|
|
406
|
+
// collected, so its spawn-gate approval still surfaces at the bottom.
|
|
407
|
+
const inlineToolCallIds = new Set<string>();
|
|
408
|
+
// Dedupe by execution id, with activeStreamExecution authoritative for its own
|
|
409
|
+
// id. The hook passes `completedExecutions` (filtered on activeExecutionId),
|
|
410
|
+
// but that filter and activeStreamExecution (stream.execution ??
|
|
411
|
+
// fetchedActiveExecution) derive from different sources, so a transient skew
|
|
412
|
+
// can leave the active execution in BOTH lists. Concatenating blindly then
|
|
413
|
+
// emits the same execution twice → duplicate React keys → React silently drops
|
|
414
|
+
// one subtree, intermittently the one carrying a live ApprovalCard (the gate
|
|
415
|
+
// buttons vanish). Dropping any prior entry sharing the active id keeps the
|
|
416
|
+
// streamed copy as the single source of truth and the append-at-end invariant
|
|
417
|
+
// (activeStreamIndex === last) intact.
|
|
271
418
|
const allExecutions = activeStreamExecution
|
|
272
|
-
? [
|
|
419
|
+
? [
|
|
420
|
+
...executions.filter(
|
|
421
|
+
(e) => e.metadata?.id !== activeStreamExecution.metadata?.id,
|
|
422
|
+
),
|
|
423
|
+
activeStreamExecution,
|
|
424
|
+
]
|
|
273
425
|
: executions;
|
|
274
426
|
const activeStreamIndex = activeStreamExecution
|
|
275
427
|
? allExecutions.length - 1
|
|
@@ -306,6 +458,36 @@ export function buildThreadItems(
|
|
|
306
458
|
const messages = exec.status?.messages ?? [];
|
|
307
459
|
const subAgents = exec.status?.subAgentExecutions ?? [];
|
|
308
460
|
|
|
461
|
+
// This execution's settled change sets render as read-only records inside
|
|
462
|
+
// its own segment, anchored to the last stamped edit row of each set. The
|
|
463
|
+
// display seam reads the server's live projection when present and folds
|
|
464
|
+
// the durable ledger for a terminal execution (whose projection is nil),
|
|
465
|
+
// so records surface for EVERY execution, not just the last. Pending sets
|
|
466
|
+
// are excluded inside insertFileReviewItems — the composer dock owns them.
|
|
467
|
+
const execChangeSets = includeFileReviewRecords
|
|
468
|
+
? displayFileChangeSets(exec.status)
|
|
469
|
+
: [];
|
|
470
|
+
const fileReviewAnchors = new Map<string, number>();
|
|
471
|
+
|
|
472
|
+
// The agent's plan renders as one inline card per turn, anchored to the
|
|
473
|
+
// first of: the opening AI/thinking message, the first unit of work
|
|
474
|
+
// (tool-group / sub-agent), or — as a backstop — the turn's tail. We carry
|
|
475
|
+
// the live `status.todos` reference (structural sharing keeps it stable),
|
|
476
|
+
// so the card updates in place and a settled card skips re-renders.
|
|
477
|
+
const execTodos = exec.status?.todos;
|
|
478
|
+
const hasTodos = execTodos != null && Object.keys(execTodos).length > 0;
|
|
479
|
+
let todosEmitted = false;
|
|
480
|
+
function emitTodos(): void {
|
|
481
|
+
if (todosEmitted || !hasTodos) return;
|
|
482
|
+
todosEmitted = true;
|
|
483
|
+
items.push({
|
|
484
|
+
kind: "todos",
|
|
485
|
+
executionId: execId,
|
|
486
|
+
todos: execTodos!,
|
|
487
|
+
key: `${execId}-todos`,
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
309
491
|
const specMessage = exec.spec?.message;
|
|
310
492
|
if (specMessage && specMessage !== "execute") {
|
|
311
493
|
const syntheticHumanMsg = create(AgentMessageSchema);
|
|
@@ -348,20 +530,43 @@ export function buildThreadItems(
|
|
|
348
530
|
message: msg,
|
|
349
531
|
key: `${execId}-m${mi}`,
|
|
350
532
|
});
|
|
533
|
+
// Anchor (1): the plan sits right under the agent's opening narration.
|
|
534
|
+
if (
|
|
535
|
+
msg.type === MessageType.MESSAGE_AI ||
|
|
536
|
+
msg.type === MessageType.MESSAGE_THINKING
|
|
537
|
+
) {
|
|
538
|
+
emitTodos();
|
|
539
|
+
}
|
|
351
540
|
}
|
|
352
541
|
|
|
542
|
+
// Runner-collapsed duplicates (a superseded same-turn denial twin of an
|
|
543
|
+
// approval gate) are not rendered — they are kept in the transcript only to
|
|
544
|
+
// satisfy the backend's append-only guard. Filtering them here keeps a
|
|
545
|
+
// message whose tool calls are ALL collapsed from emitting an empty group.
|
|
546
|
+
// Preserve the original array reference when nothing is collapsed (the
|
|
547
|
+
// common case) so structural sharing / memoization (T04) is not defeated by
|
|
548
|
+
// a fresh array on every build.
|
|
549
|
+
const renderableToolCalls =
|
|
550
|
+
msg.type === MessageType.MESSAGE_AI && msg.toolCalls.some(isCollapsedToolCall)
|
|
551
|
+
? msg.toolCalls.filter((tc) => !isCollapsedToolCall(tc))
|
|
552
|
+
: msg.toolCalls;
|
|
553
|
+
|
|
353
554
|
if (
|
|
354
555
|
msg.type === MessageType.MESSAGE_AI &&
|
|
355
|
-
|
|
556
|
+
renderableToolCalls.length > 0
|
|
356
557
|
) {
|
|
357
|
-
|
|
558
|
+
// Anchor (2): if work begins before any rendered narration, the plan
|
|
559
|
+
// still leads it.
|
|
560
|
+
emitTodos();
|
|
561
|
+
|
|
562
|
+
const needsSplit = renderableToolCalls.some(
|
|
358
563
|
(tc) => tc.name === "task" || isInternalTool(tc.name),
|
|
359
564
|
);
|
|
360
565
|
|
|
361
566
|
if (needsSplit) {
|
|
362
567
|
const regularTools: ToolCall[] = [];
|
|
363
568
|
const matchedSubAgents: SubAgentExecution[] = [];
|
|
364
|
-
for (const tc of
|
|
569
|
+
for (const tc of renderableToolCalls) {
|
|
365
570
|
if (tc.name === "task") {
|
|
366
571
|
const matched = subAgents.find((sa) => sa.id === tc.id);
|
|
367
572
|
if (matched) matchedSubAgents.push(matched);
|
|
@@ -376,6 +581,10 @@ export function buildThreadItems(
|
|
|
376
581
|
subAgentExecutions: subAgents,
|
|
377
582
|
key: `${execId}-m${mi}-tc`,
|
|
378
583
|
});
|
|
584
|
+
recordFileReviewAnchors(regularTools, items.length - 1, fileReviewAnchors);
|
|
585
|
+
for (const tc of regularTools) {
|
|
586
|
+
if (tc.id) inlineToolCallIds.add(tc.id);
|
|
587
|
+
}
|
|
379
588
|
}
|
|
380
589
|
for (const sa of matchedSubAgents) {
|
|
381
590
|
items.push({
|
|
@@ -383,17 +592,36 @@ export function buildThreadItems(
|
|
|
383
592
|
subAgentExecution: sa,
|
|
384
593
|
key: `sa-${sa.id}`,
|
|
385
594
|
});
|
|
595
|
+
collectSubAgentInlineToolCallIds(sa, inlineToolCallIds);
|
|
386
596
|
}
|
|
387
597
|
} else {
|
|
388
598
|
items.push({
|
|
389
599
|
kind: "tool-group",
|
|
390
|
-
toolCalls:
|
|
600
|
+
toolCalls: renderableToolCalls,
|
|
391
601
|
subAgentExecutions: subAgents,
|
|
392
602
|
key: `${execId}-m${mi}-tc`,
|
|
393
603
|
});
|
|
604
|
+
recordFileReviewAnchors(renderableToolCalls, items.length - 1, fileReviewAnchors);
|
|
605
|
+
for (const tc of renderableToolCalls) {
|
|
606
|
+
if (tc.id) inlineToolCallIds.add(tc.id);
|
|
607
|
+
}
|
|
394
608
|
}
|
|
395
609
|
}
|
|
396
610
|
}
|
|
611
|
+
|
|
612
|
+
// Anchor (3): a plan that produced no rendered narration or work item still
|
|
613
|
+
// surfaces — never silently dropped.
|
|
614
|
+
emitTodos();
|
|
615
|
+
|
|
616
|
+
// Settled records land inside this execution's segment, at their anchors.
|
|
617
|
+
if (execChangeSets.length > 0) {
|
|
618
|
+
insertFileReviewItems(
|
|
619
|
+
items,
|
|
620
|
+
execChangeSets,
|
|
621
|
+
fileReviewAnchors,
|
|
622
|
+
isTerminalPhase(exec.status?.phase ?? ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED),
|
|
623
|
+
);
|
|
624
|
+
}
|
|
397
625
|
}
|
|
398
626
|
|
|
399
627
|
// Flush any remaining summarization events that occurred after all messages
|
|
@@ -477,9 +705,17 @@ export function buildThreadItems(
|
|
|
477
705
|
}
|
|
478
706
|
|
|
479
707
|
if (includeApprovals) {
|
|
708
|
+
// Backstop only: an approval whose tool call renders inline shows its gate
|
|
709
|
+
// on that row (see ApprovalContext / ToolCallItem). We emit a bottom card
|
|
710
|
+
// ONLY for an approval with no inline home — a true orphan, or a task-spawn
|
|
711
|
+
// approval that precedes its SubAgentExecution — so a pending gate is never
|
|
712
|
+
// invisible, and never duplicated.
|
|
480
713
|
const allApprovals = lastExec?.status?.pendingApprovals ?? [];
|
|
481
714
|
for (let ai = 0; ai < allApprovals.length; ai++) {
|
|
482
715
|
const approval = allApprovals[ai];
|
|
716
|
+
if (approval.toolCallId && inlineToolCallIds.has(approval.toolCallId)) {
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
483
719
|
items.push({
|
|
484
720
|
kind: "approval-request",
|
|
485
721
|
pendingApproval: approval,
|
|
@@ -488,6 +724,11 @@ export function buildThreadItems(
|
|
|
488
724
|
}
|
|
489
725
|
}
|
|
490
726
|
|
|
727
|
+
// File-review records are emitted inside each execution's segment (see
|
|
728
|
+
// insertFileReviewItems in the loop above) — anchored to the last stamped
|
|
729
|
+
// edit row, never appended at the thread tail. Pending decision bars are
|
|
730
|
+
// not thread items at all: they live in the composer-docked FileReviewDock.
|
|
731
|
+
|
|
491
732
|
if (pendingUserMessage) {
|
|
492
733
|
const alreadySynthesized =
|
|
493
734
|
lastExec?.spec?.message === pendingUserMessage;
|
|
@@ -545,6 +786,8 @@ export function MessageThread({
|
|
|
545
786
|
formatToolCallSummary,
|
|
546
787
|
onApprovalSubmit,
|
|
547
788
|
submittingApprovalIds,
|
|
789
|
+
approvalErrors,
|
|
790
|
+
showFileReviewRecords = false,
|
|
548
791
|
workspaceEntries,
|
|
549
792
|
onFilePathClick,
|
|
550
793
|
sandboxWorkspaceRoot,
|
|
@@ -560,8 +803,8 @@ export function MessageThread({
|
|
|
560
803
|
const includeApprovals = onApprovalSubmit != null;
|
|
561
804
|
const editableActiveTurn = onEditMessage != null;
|
|
562
805
|
const items = useMemo(
|
|
563
|
-
() => buildThreadItems(executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn),
|
|
564
|
-
[executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn],
|
|
806
|
+
() => buildThreadItems(executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn, showFileReviewRecords),
|
|
807
|
+
[executions, activeStreamExecution, pendingUserMessage, includeApprovals, workspaceEntries, summarizationEvents, pendingMessageFailed, editableActiveTurn, showFileReviewRecords],
|
|
565
808
|
);
|
|
566
809
|
|
|
567
810
|
useKeyStability(items);
|
|
@@ -579,6 +822,57 @@ export function MessageThread({
|
|
|
579
822
|
[sandboxWorkspaceRoot],
|
|
580
823
|
);
|
|
581
824
|
|
|
825
|
+
// Pending approvals live on the latest execution. We project them into a
|
|
826
|
+
// tool-call-id-keyed map so each gated tool row can render its own approval
|
|
827
|
+
// inline (see ApprovalContext); buildThreadItems still emits a bottom card
|
|
828
|
+
// for any approval with no matching inline row (orphan backstop).
|
|
829
|
+
const lastExec = activeStreamExecution ?? executions[executions.length - 1];
|
|
830
|
+
const pendingApprovals = includeApprovals
|
|
831
|
+
? lastExec?.status?.pendingApprovals ?? EMPTY_APPROVALS
|
|
832
|
+
: EMPTY_APPROVALS;
|
|
833
|
+
|
|
834
|
+
const approvalsByToolCallId = useMemo(() => {
|
|
835
|
+
const map = new Map<string, PendingApproval>();
|
|
836
|
+
for (const approval of pendingApprovals) {
|
|
837
|
+
if (approval.toolCallId) map.set(approval.toolCallId, approval);
|
|
838
|
+
}
|
|
839
|
+
return map;
|
|
840
|
+
}, [pendingApprovals]);
|
|
841
|
+
|
|
842
|
+
const approvalCtx = useMemo<ApprovalContextValue>(
|
|
843
|
+
() => ({
|
|
844
|
+
approvalsByToolCallId,
|
|
845
|
+
onSubmit: onApprovalSubmit,
|
|
846
|
+
submittingIds: submittingApprovalIds ?? EMPTY_SUBMITTING_IDS,
|
|
847
|
+
errorsByToolCallId: approvalErrors ?? EMPTY_APPROVAL_ERRORS,
|
|
848
|
+
}),
|
|
849
|
+
[approvalsByToolCallId, onApprovalSubmit, submittingApprovalIds, approvalErrors],
|
|
850
|
+
);
|
|
851
|
+
|
|
852
|
+
// Every displayable change set across the session, keyed by id, so a stamped
|
|
853
|
+
// edit row (ToolCall.file_change_set_id) can badge its set's live review
|
|
854
|
+
// state wherever it renders (parent thread or nested groups). The map is
|
|
855
|
+
// rebuilt only when the execution list reference changes; structural sharing
|
|
856
|
+
// keeps each FileChangeSet reference stable across streaming frames, so
|
|
857
|
+
// subscribing rows re-render on review events, not every snapshot.
|
|
858
|
+
const fileReviewCtx = useMemo<FileReviewContextValue>(() => {
|
|
859
|
+
const map = new Map<string, FileChangeSet>();
|
|
860
|
+
const all = activeStreamExecution
|
|
861
|
+
? [...executions, activeStreamExecution]
|
|
862
|
+
: executions;
|
|
863
|
+
for (const exec of all) {
|
|
864
|
+
for (const changeSet of displayFileChangeSets(exec.status)) {
|
|
865
|
+
// Later wins: the active stream's copy supersedes a stale fetched one.
|
|
866
|
+
map.set(changeSet.id, changeSet);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
return { changeSetsById: map };
|
|
870
|
+
}, [executions, activeStreamExecution]);
|
|
871
|
+
|
|
872
|
+
// Drives the global "approval needed" peek affordance — a count, not the
|
|
873
|
+
// cards, so the bar reuses the existing scroll machine without a new observer.
|
|
874
|
+
const unresolvedApprovalCount = pendingApprovals.length;
|
|
875
|
+
|
|
582
876
|
if (virtualized) {
|
|
583
877
|
return (
|
|
584
878
|
<div className={cn("relative min-h-0", className)}>
|
|
@@ -588,8 +882,12 @@ export function MessageThread({
|
|
|
588
882
|
formatToolCallSummary={formatToolCallSummary}
|
|
589
883
|
onApprovalSubmit={onApprovalSubmit}
|
|
590
884
|
submittingApprovalIds={submittingApprovalIds}
|
|
885
|
+
approvalErrors={approvalErrors}
|
|
591
886
|
filePathCtx={filePathCtx}
|
|
592
887
|
sandboxCtx={sandboxCtx}
|
|
888
|
+
approvalCtx={approvalCtx}
|
|
889
|
+
fileReviewCtx={fileReviewCtx}
|
|
890
|
+
unresolvedApprovalCount={unresolvedApprovalCount}
|
|
593
891
|
onBuildFromPlan={onBuildFromPlan}
|
|
594
892
|
org={org}
|
|
595
893
|
planActionsDisabled={planActionsDisabled}
|
|
@@ -611,8 +909,12 @@ export function MessageThread({
|
|
|
611
909
|
formatToolCallSummary={formatToolCallSummary}
|
|
612
910
|
onApprovalSubmit={onApprovalSubmit}
|
|
613
911
|
submittingApprovalIds={submittingApprovalIds}
|
|
912
|
+
approvalErrors={approvalErrors}
|
|
614
913
|
filePathCtx={filePathCtx}
|
|
615
914
|
sandboxCtx={sandboxCtx}
|
|
915
|
+
approvalCtx={approvalCtx}
|
|
916
|
+
fileReviewCtx={fileReviewCtx}
|
|
917
|
+
unresolvedApprovalCount={unresolvedApprovalCount}
|
|
616
918
|
onBuildFromPlan={onBuildFromPlan}
|
|
617
919
|
org={org}
|
|
618
920
|
planActionsDisabled={planActionsDisabled}
|
|
@@ -638,8 +940,12 @@ interface NonVirtualizedThreadProps {
|
|
|
638
940
|
comment?: string,
|
|
639
941
|
) => void;
|
|
640
942
|
readonly submittingApprovalIds?: ReadonlySet<string>;
|
|
943
|
+
readonly approvalErrors?: ReadonlyMap<string, Error>;
|
|
641
944
|
readonly filePathCtx: FilePathContextValue;
|
|
642
945
|
readonly sandboxCtx: SandboxContextValue;
|
|
946
|
+
readonly approvalCtx: ApprovalContextValue;
|
|
947
|
+
readonly fileReviewCtx: FileReviewContextValue;
|
|
948
|
+
readonly unresolvedApprovalCount: number;
|
|
643
949
|
readonly onBuildFromPlan?: () => void;
|
|
644
950
|
readonly org?: string;
|
|
645
951
|
readonly planActionsDisabled?: boolean;
|
|
@@ -655,8 +961,12 @@ function NonVirtualizedThread({
|
|
|
655
961
|
formatToolCallSummary,
|
|
656
962
|
onApprovalSubmit,
|
|
657
963
|
submittingApprovalIds,
|
|
964
|
+
approvalErrors,
|
|
658
965
|
filePathCtx,
|
|
659
966
|
sandboxCtx,
|
|
967
|
+
approvalCtx,
|
|
968
|
+
fileReviewCtx,
|
|
969
|
+
unresolvedApprovalCount,
|
|
660
970
|
onBuildFromPlan,
|
|
661
971
|
org,
|
|
662
972
|
planActionsDisabled,
|
|
@@ -686,6 +996,8 @@ function NonVirtualizedThread({
|
|
|
686
996
|
>
|
|
687
997
|
<SandboxContext.Provider value={sandboxCtx}>
|
|
688
998
|
<FilePathContext.Provider value={filePathCtx}>
|
|
999
|
+
<ApprovalContext.Provider value={approvalCtx}>
|
|
1000
|
+
<FileReviewContext.Provider value={fileReviewCtx}>
|
|
689
1001
|
<DevProfiler id="MessageThread">
|
|
690
1002
|
<div ref={contentRef} className={cn("flex flex-col gap-4", centerContent && "mx-auto w-full max-w-3xl px-4")}>
|
|
691
1003
|
{items.map((item) => (
|
|
@@ -695,6 +1007,7 @@ function NonVirtualizedThread({
|
|
|
695
1007
|
formatToolCallSummary={formatToolCallSummary}
|
|
696
1008
|
onApprovalSubmit={onApprovalSubmit}
|
|
697
1009
|
submittingApprovalIds={submittingApprovalIds}
|
|
1010
|
+
approvalErrors={approvalErrors}
|
|
698
1011
|
onBuildFromPlan={onBuildFromPlan}
|
|
699
1012
|
org={org}
|
|
700
1013
|
planActionsDisabled={planActionsDisabled}
|
|
@@ -706,11 +1019,23 @@ function NonVirtualizedThread({
|
|
|
706
1019
|
))}
|
|
707
1020
|
</div>
|
|
708
1021
|
</DevProfiler>
|
|
1022
|
+
</FileReviewContext.Provider>
|
|
1023
|
+
</ApprovalContext.Provider>
|
|
709
1024
|
</FilePathContext.Provider>
|
|
710
1025
|
</SandboxContext.Provider>
|
|
711
1026
|
<div ref={sentinelRef} aria-hidden="true" />
|
|
712
1027
|
</div>
|
|
713
|
-
|
|
1028
|
+
{/* The peek bar takes the jump button's slot while approvals are pending,
|
|
1029
|
+
so the two never overlap — a gate is the louder of the two signals. */}
|
|
1030
|
+
<JumpToLatestButton
|
|
1031
|
+
onClick={jumpToLatest}
|
|
1032
|
+
visible={!isFollowing && unresolvedApprovalCount === 0}
|
|
1033
|
+
/>
|
|
1034
|
+
<ApprovalPeekBar
|
|
1035
|
+
visible={!isFollowing && unresolvedApprovalCount > 0}
|
|
1036
|
+
count={unresolvedApprovalCount}
|
|
1037
|
+
onClick={jumpToLatest}
|
|
1038
|
+
/>
|
|
714
1039
|
</div>
|
|
715
1040
|
);
|
|
716
1041
|
}
|
|
@@ -734,6 +1059,7 @@ export interface ThreadItemRendererProps {
|
|
|
734
1059
|
comment?: string,
|
|
735
1060
|
) => void;
|
|
736
1061
|
readonly submittingApprovalIds?: ReadonlySet<string>;
|
|
1062
|
+
readonly approvalErrors?: ReadonlyMap<string, Error>;
|
|
737
1063
|
readonly onBuildFromPlan?: () => void;
|
|
738
1064
|
readonly org?: string;
|
|
739
1065
|
readonly planActionsDisabled?: boolean;
|
|
@@ -758,6 +1084,7 @@ export function ThreadItemRenderer({
|
|
|
758
1084
|
formatToolCallSummary,
|
|
759
1085
|
onApprovalSubmit,
|
|
760
1086
|
submittingApprovalIds,
|
|
1087
|
+
approvalErrors,
|
|
761
1088
|
onBuildFromPlan,
|
|
762
1089
|
org,
|
|
763
1090
|
planActionsDisabled,
|
|
@@ -819,8 +1146,11 @@ export function ThreadItemRenderer({
|
|
|
819
1146
|
pendingApproval={item.pendingApproval}
|
|
820
1147
|
onApprovalSubmit={onApprovalSubmit!}
|
|
821
1148
|
isSubmitting={submittingApprovalIds?.has(item.pendingApproval.toolCallId) ?? false}
|
|
1149
|
+
error={approvalErrors?.get(item.pendingApproval.toolCallId) ?? null}
|
|
822
1150
|
/>
|
|
823
1151
|
);
|
|
1152
|
+
case "file-review-record":
|
|
1153
|
+
return <FileReviewRecordRow fileChangeSet={item.fileChangeSet} />;
|
|
824
1154
|
case "setup-progress":
|
|
825
1155
|
return (
|
|
826
1156
|
<SetupProgress
|
|
@@ -831,6 +1161,8 @@ export function ThreadItemRenderer({
|
|
|
831
1161
|
);
|
|
832
1162
|
case "context-compacted":
|
|
833
1163
|
return <SummarizationCard event={item.event} />;
|
|
1164
|
+
case "todos":
|
|
1165
|
+
return <TodoCard todos={item.todos} className="mx-4" />;
|
|
834
1166
|
case "plan-completion":
|
|
835
1167
|
// When the plan was published as an artifact, show the richer reviewable
|
|
836
1168
|
// card (preview / copy / download / implement). Otherwise fall back to the
|
|
@@ -983,12 +1315,16 @@ interface ApprovalCardRowProps {
|
|
|
983
1315
|
comment?: string,
|
|
984
1316
|
) => void;
|
|
985
1317
|
readonly isSubmitting: boolean;
|
|
1318
|
+
// This gate's last failed decision, or null — a stable ref from the
|
|
1319
|
+
// approvalErrors map, so the row re-renders only when its error appears/clears.
|
|
1320
|
+
readonly error?: Error | null;
|
|
986
1321
|
}
|
|
987
1322
|
|
|
988
1323
|
const ApprovalCardRow = memo(function ApprovalCardRow({
|
|
989
1324
|
pendingApproval,
|
|
990
1325
|
onApprovalSubmit,
|
|
991
1326
|
isSubmitting,
|
|
1327
|
+
error = null,
|
|
992
1328
|
}: ApprovalCardRowProps) {
|
|
993
1329
|
const handleSubmit = useCallback(
|
|
994
1330
|
(action: ApprovalAction, comment?: string) => {
|
|
@@ -1002,6 +1338,35 @@ const ApprovalCardRow = memo(function ApprovalCardRow({
|
|
|
1002
1338
|
pendingApproval={pendingApproval}
|
|
1003
1339
|
onSubmit={handleSubmit}
|
|
1004
1340
|
isSubmitting={isSubmitting}
|
|
1341
|
+
error={error}
|
|
1342
|
+
className="mx-4"
|
|
1343
|
+
/>
|
|
1344
|
+
);
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1347
|
+
// ---------------------------------------------------------------------------
|
|
1348
|
+
// FileReviewRecordRow — a settled change set's read-only in-thread record
|
|
1349
|
+
// ---------------------------------------------------------------------------
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* Renders a settled change set as a read-only record at its position in the
|
|
1353
|
+
* transcript — what changed and how it was decided ("2 kept · 1 discarded").
|
|
1354
|
+
* Never interactive: the pending decision surface is the composer-docked
|
|
1355
|
+
* `FileReviewDock`, not a thread item (see {@link insertFileReviewItems}).
|
|
1356
|
+
*/
|
|
1357
|
+
const FileReviewRecordRow = memo(function FileReviewRecordRow({
|
|
1358
|
+
fileChangeSet,
|
|
1359
|
+
}: {
|
|
1360
|
+
readonly fileChangeSet: FileChangeSet;
|
|
1361
|
+
}) {
|
|
1362
|
+
return (
|
|
1363
|
+
<FileReviewCard
|
|
1364
|
+
fileChangeSet={fileChangeSet}
|
|
1365
|
+
interactive={false}
|
|
1366
|
+
// The thread's stamped edit rows already show every diff in place, so
|
|
1367
|
+
// the record renders its compact file-list body — the history never
|
|
1368
|
+
// duplicates the transcript's diffs.
|
|
1369
|
+
showDiffs={false}
|
|
1005
1370
|
className="mx-4"
|
|
1006
1371
|
/>
|
|
1007
1372
|
);
|
|
@@ -5,6 +5,7 @@ import { cn } from "@stigmer/theme";
|
|
|
5
5
|
import type { ExecutionArtifact } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/artifact_pb";
|
|
6
6
|
import { ArtifactPreviewModal } from "./ArtifactPreviewModal";
|
|
7
7
|
import { formatArtifactSize } from "./artifact-utils";
|
|
8
|
+
import { useArtifactDownload } from "./useArtifactDownload";
|
|
8
9
|
import { useBuildFromPlanHotkey } from "./use-build-from-plan-hotkey";
|
|
9
10
|
|
|
10
11
|
/** Props for {@link PlanArtifactCard}. */
|
|
@@ -63,6 +64,7 @@ export const PlanArtifactCard = memo(function PlanArtifactCard({
|
|
|
63
64
|
}: PlanArtifactCardProps) {
|
|
64
65
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
65
66
|
const handleKeyDown = useBuildFromPlanHotkey(onImplement, disabled);
|
|
67
|
+
const { download, isDownloading } = useArtifactDownload(executionId);
|
|
66
68
|
|
|
67
69
|
return (
|
|
68
70
|
<div
|
|
@@ -97,17 +99,18 @@ export const PlanArtifactCard = memo(function PlanArtifactCard({
|
|
|
97
99
|
Open full
|
|
98
100
|
</button>
|
|
99
101
|
)}
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
<button
|
|
103
|
+
type="button"
|
|
104
|
+
onClick={() => download(artifact.storageKey, artifact.name)}
|
|
105
|
+
disabled={isDownloading}
|
|
103
106
|
className={cn(
|
|
104
|
-
"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground",
|
|
107
|
+
"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground disabled:opacity-50",
|
|
105
108
|
FOCUS_RING,
|
|
106
109
|
)}
|
|
107
110
|
>
|
|
108
111
|
<DownloadIcon />
|
|
109
|
-
Download
|
|
110
|
-
</
|
|
112
|
+
{isDownloading ? "Preparing…" : "Download"}
|
|
113
|
+
</button>
|
|
111
114
|
{onImplement && (
|
|
112
115
|
<button
|
|
113
116
|
type="button"
|