@stigmer/react 3.0.9-dev.20260615153829 → 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/code-highlight.d.ts +24 -0
- package/internal/code-highlight.d.ts.map +1 -0
- package/internal/code-highlight.js +115 -0
- package/internal/code-highlight.js.map +1 -0
- package/internal/markdown-components.d.ts.map +1 -1
- package/internal/markdown-components.js +13 -2
- package/internal/markdown-components.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 +7 -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__/ArtifactContentRenderer.test.tsx +15 -0
- 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__/message-entry.test.tsx +16 -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__/code-highlight.test.tsx +59 -0
- package/src/internal/__tests__/markdown-components.test.tsx +68 -2
- 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/code-highlight.tsx +120 -0
- package/src/internal/markdown-components.tsx +20 -3
- 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 +123 -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
|
@@ -20,7 +20,8 @@ import { ExecutionInspector } from "./execution-inspector";
|
|
|
20
20
|
import { ExecutionComparisonPicker } from "./execution-comparison/ExecutionComparisonPicker";
|
|
21
21
|
import { ExecutionComparisonView } from "./execution-comparison/ExecutionComparisonView";
|
|
22
22
|
import { WorkflowExecutionApprovalCard } from "./WorkflowExecutionApprovalCard";
|
|
23
|
-
import type
|
|
23
|
+
import { WorkflowFileReviewList, type WorkflowFileDecisionSubmit } from "./WorkflowFileReviewList";
|
|
24
|
+
import type { WorkflowPendingApproval, WorkflowPendingFileReview } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/api_pb";
|
|
24
25
|
import type { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
25
26
|
import { ResizableSplit } from "../internal/ResizableSplit";
|
|
26
27
|
|
|
@@ -287,7 +288,9 @@ export const WorkflowExecutionViewer = memo(function WorkflowExecutionViewer({
|
|
|
287
288
|
onClose={handleCloseComparePicker}
|
|
288
289
|
/>
|
|
289
290
|
|
|
290
|
-
{/* Action error banner
|
|
291
|
+
{/* Action error banner — lifecycle actions only (cancel/terminate/pause/
|
|
292
|
+
resume/recover). Approval failures are per-gate and surface in-card on
|
|
293
|
+
the failing approval card, never here. */}
|
|
291
294
|
{actions.error && (
|
|
292
295
|
<div className="flex items-center gap-2 border-b border-destructive/20 bg-destructive/5 px-4 py-2">
|
|
293
296
|
<p className="flex-1 text-xs text-destructive">{actions.error.message}</p>
|
|
@@ -365,9 +368,11 @@ export const WorkflowExecutionViewer = memo(function WorkflowExecutionViewer({
|
|
|
365
368
|
onNavigateToAgentExecution={onNavigateToAgentExecution}
|
|
366
369
|
pendingApprovals={execution?.status?.pendingApprovals}
|
|
367
370
|
onSubmitApproval={actions.submitApproval}
|
|
368
|
-
|
|
371
|
+
approvalSubmittingToolCallIds={actions.approvalSubmittingToolCallIds}
|
|
372
|
+
approvalErrorsByToolCallId={actions.approvalErrorsByToolCallId}
|
|
369
373
|
onSubmitTaskApproval={actions.submitTaskApproval}
|
|
370
|
-
|
|
374
|
+
taskApprovalSubmittingTaskNames={actions.taskApprovalSubmittingTaskNames}
|
|
375
|
+
taskApprovalErrorsByTaskName={actions.taskApprovalErrorsByTaskName}
|
|
371
376
|
className="min-h-0 flex-1"
|
|
372
377
|
/>
|
|
373
378
|
|
|
@@ -403,9 +408,16 @@ export const WorkflowExecutionViewer = memo(function WorkflowExecutionViewer({
|
|
|
403
408
|
onNavigateToAgentExecution={onNavigateToAgentExecution}
|
|
404
409
|
taskStates={effectiveTaskStates}
|
|
405
410
|
onSubmitTaskApproval={actions.submitTaskApproval}
|
|
406
|
-
|
|
411
|
+
taskApprovalSubmittingTaskNames={actions.taskApprovalSubmittingTaskNames}
|
|
412
|
+
taskApprovalErrorsByTaskName={actions.taskApprovalErrorsByTaskName}
|
|
407
413
|
pendingApprovals={execution?.status?.pendingApprovals}
|
|
408
414
|
onSubmitApproval={actions.submitApproval}
|
|
415
|
+
approvalSubmittingToolCallIds={actions.approvalSubmittingToolCallIds}
|
|
416
|
+
approvalErrorsByToolCallId={actions.approvalErrorsByToolCallId}
|
|
417
|
+
pendingFileReviews={execution?.status?.pendingFileReviews}
|
|
418
|
+
onSubmitFileDecision={actions.submitFileDecision}
|
|
419
|
+
fileDecisionSubmittingKeys={actions.fileDecisionSubmittingKeys}
|
|
420
|
+
fileDecisionErrorsByKey={actions.fileDecisionErrorsByKey}
|
|
409
421
|
/>
|
|
410
422
|
</div>
|
|
411
423
|
</>
|
|
@@ -449,9 +461,16 @@ function ExecutionBottomPanel({
|
|
|
449
461
|
onNavigateToAgentExecution,
|
|
450
462
|
taskStates,
|
|
451
463
|
onSubmitTaskApproval,
|
|
452
|
-
|
|
464
|
+
taskApprovalSubmittingTaskNames,
|
|
465
|
+
taskApprovalErrorsByTaskName,
|
|
453
466
|
pendingApprovals,
|
|
454
467
|
onSubmitApproval,
|
|
468
|
+
approvalSubmittingToolCallIds,
|
|
469
|
+
approvalErrorsByToolCallId,
|
|
470
|
+
pendingFileReviews,
|
|
471
|
+
onSubmitFileDecision,
|
|
472
|
+
fileDecisionSubmittingKeys,
|
|
473
|
+
fileDecisionErrorsByKey,
|
|
455
474
|
}: {
|
|
456
475
|
events: WorkflowExecutionTimelineProps["events"];
|
|
457
476
|
streamState: WorkflowExecutionTimelineProps["streamState"];
|
|
@@ -462,28 +481,39 @@ function ExecutionBottomPanel({
|
|
|
462
481
|
onNavigateToAgentExecution?: (id: string) => void;
|
|
463
482
|
taskStates: ReadonlyMap<string, DerivedTaskState>;
|
|
464
483
|
onSubmitTaskApproval: WorkflowExecutionTimelineProps["onSubmitTaskApproval"];
|
|
465
|
-
|
|
484
|
+
taskApprovalSubmittingTaskNames: ReadonlySet<string>;
|
|
485
|
+
taskApprovalErrorsByTaskName: ReadonlyMap<string, Error>;
|
|
466
486
|
pendingApprovals?: readonly WorkflowPendingApproval[];
|
|
467
487
|
onSubmitApproval?: (toolCallId: string, action: ApprovalAction, comment?: string) => Promise<unknown>;
|
|
488
|
+
approvalSubmittingToolCallIds: ReadonlySet<string>;
|
|
489
|
+
approvalErrorsByToolCallId: ReadonlyMap<string, Error>;
|
|
490
|
+
pendingFileReviews?: readonly WorkflowPendingFileReview[];
|
|
491
|
+
onSubmitFileDecision: WorkflowFileDecisionSubmit;
|
|
492
|
+
fileDecisionSubmittingKeys: ReadonlySet<string>;
|
|
493
|
+
fileDecisionErrorsByKey: ReadonlyMap<string, Error>;
|
|
468
494
|
}) {
|
|
469
495
|
const [collapsed, setCollapsed] = useState(false);
|
|
470
496
|
const [activeTab, setActiveTab] = useState<BottomTab>("waterfall");
|
|
471
|
-
const
|
|
497
|
+
const prevHitlCountRef = useRef(0);
|
|
472
498
|
|
|
473
499
|
const approvalCount = pendingApprovals?.length ?? 0;
|
|
474
|
-
const
|
|
500
|
+
const fileReviewCount = pendingFileReviews?.length ?? 0;
|
|
501
|
+
// Both HITL kinds (tool approvals + file reviews) share the one "Approvals" tab.
|
|
502
|
+
const hitlCount = approvalCount + fileReviewCount;
|
|
503
|
+
const hasHitl = hitlCount > 0;
|
|
475
504
|
|
|
476
|
-
// Auto-switch to Approvals tab when new
|
|
505
|
+
// Auto-switch to the Approvals tab when a new HITL gate (approval or file
|
|
506
|
+
// review) arrives; leave it when everything is resolved.
|
|
477
507
|
useEffect(() => {
|
|
478
|
-
if (
|
|
508
|
+
if (hitlCount > prevHitlCountRef.current && hitlCount > 0) {
|
|
479
509
|
setActiveTab("approvals");
|
|
480
510
|
setCollapsed(false);
|
|
481
511
|
}
|
|
482
|
-
if (
|
|
512
|
+
if (hitlCount === 0 && activeTab === "approvals") {
|
|
483
513
|
setActiveTab("waterfall");
|
|
484
514
|
}
|
|
485
|
-
|
|
486
|
-
}, [
|
|
515
|
+
prevHitlCountRef.current = hitlCount;
|
|
516
|
+
}, [hitlCount, activeTab]);
|
|
487
517
|
|
|
488
518
|
return (
|
|
489
519
|
<div className="border-t border-[var(--stgm-border,#e5e5e5)]">
|
|
@@ -516,9 +546,9 @@ function ExecutionBottomPanel({
|
|
|
516
546
|
isActive={activeTab === "events"}
|
|
517
547
|
onClick={() => { setActiveTab("events"); setCollapsed(false); }}
|
|
518
548
|
/>
|
|
519
|
-
{
|
|
549
|
+
{hasHitl && (
|
|
520
550
|
<TabButton
|
|
521
|
-
label={`Approvals (${
|
|
551
|
+
label={`Approvals (${hitlCount})`}
|
|
522
552
|
isActive={activeTab === "approvals"}
|
|
523
553
|
onClick={() => { setActiveTab("approvals"); setCollapsed(false); }}
|
|
524
554
|
/>
|
|
@@ -546,24 +576,38 @@ function ExecutionBottomPanel({
|
|
|
546
576
|
onNavigateToAgentExecution={onNavigateToAgentExecution}
|
|
547
577
|
taskStates={taskStates}
|
|
548
578
|
onSubmitTaskApproval={onSubmitTaskApproval}
|
|
549
|
-
|
|
579
|
+
taskApprovalSubmittingTaskNames={taskApprovalSubmittingTaskNames}
|
|
580
|
+
taskApprovalErrorsByTaskName={taskApprovalErrorsByTaskName}
|
|
550
581
|
className="h-full"
|
|
551
582
|
/>
|
|
552
583
|
)}
|
|
553
|
-
{activeTab === "approvals" &&
|
|
584
|
+
{activeTab === "approvals" && (
|
|
554
585
|
<div className="h-full overflow-y-auto px-4 py-3">
|
|
555
586
|
<div className="space-y-3">
|
|
556
|
-
{pendingApprovals.map((pa) =>
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
587
|
+
{pendingApprovals && onSubmitApproval && pendingApprovals.map((pa) => {
|
|
588
|
+
const toolCallId = pa.approval?.toolCallId ?? "";
|
|
589
|
+
return (
|
|
590
|
+
<WorkflowExecutionApprovalCard
|
|
591
|
+
key={toolCallId || pa.childAgentExecutionId}
|
|
592
|
+
prompt={pa.approval?.message || `Tool "${pa.approval?.toolName}" requires approval`}
|
|
593
|
+
toolCallId={toolCallId}
|
|
594
|
+
approvers={[]}
|
|
595
|
+
timeoutSeconds={0}
|
|
596
|
+
onSubmitApproval={onSubmitApproval}
|
|
597
|
+
isSubmitting={approvalSubmittingToolCallIds.has(toolCallId)}
|
|
598
|
+
error={approvalErrorsByToolCallId.get(toolCallId) ?? null}
|
|
599
|
+
/>
|
|
600
|
+
);
|
|
601
|
+
})}
|
|
602
|
+
{pendingFileReviews && pendingFileReviews.length > 0 && (
|
|
603
|
+
<WorkflowFileReviewList
|
|
604
|
+
pendingFileReviews={pendingFileReviews}
|
|
605
|
+
onSubmitFileDecision={onSubmitFileDecision}
|
|
606
|
+
submittingDecisionKeys={fileDecisionSubmittingKeys}
|
|
607
|
+
decisionErrors={fileDecisionErrorsByKey}
|
|
608
|
+
onNavigateToAgentExecution={onNavigateToAgentExecution}
|
|
565
609
|
/>
|
|
566
|
-
)
|
|
610
|
+
)}
|
|
567
611
|
</div>
|
|
568
612
|
</div>
|
|
569
613
|
)}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import {
|
|
5
|
+
FileChangeSetStatus,
|
|
6
|
+
type FileDecisionAction,
|
|
7
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
8
|
+
import type { WorkflowPendingFileReview } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/api_pb";
|
|
9
|
+
import { displayFileChangeSets } from "@stigmer/sdk";
|
|
10
|
+
import { cn } from "@stigmer/theme";
|
|
11
|
+
import { FileReviewCard } from "../execution/FileReviewCard";
|
|
12
|
+
import type { FileDecisionOptions } from "../execution/useFileReview";
|
|
13
|
+
import { useExecutionStream } from "../execution/useExecutionStream";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Submit handler for a workflow-level file decision, matching
|
|
17
|
+
* `useWorkflowExecutionActions().submitFileDecision`. The child id is bound per
|
|
18
|
+
* card so the surface only needs the card-level `(action, options)`.
|
|
19
|
+
*/
|
|
20
|
+
export type WorkflowFileDecisionSubmit = (
|
|
21
|
+
childAgentExecutionId: string,
|
|
22
|
+
changeSetId: string,
|
|
23
|
+
action: FileDecisionAction,
|
|
24
|
+
options?: FileDecisionOptions,
|
|
25
|
+
) => void;
|
|
26
|
+
|
|
27
|
+
/** Props for {@link WorkflowFileReviewList}. */
|
|
28
|
+
export interface WorkflowFileReviewListProps {
|
|
29
|
+
/**
|
|
30
|
+
* The parent workflow's surfaced file-review references
|
|
31
|
+
* (`status.pending_file_reviews`) — one entry per child agent execution.
|
|
32
|
+
*/
|
|
33
|
+
readonly pendingFileReviews: readonly WorkflowPendingFileReview[];
|
|
34
|
+
/** Forwards a decision to the child (see {@link WorkflowFileDecisionSubmit}). */
|
|
35
|
+
readonly onSubmitFileDecision: WorkflowFileDecisionSubmit;
|
|
36
|
+
/** In-flight decision keys (pass `fileDecisionSubmittingKeys` straight through). */
|
|
37
|
+
readonly submittingDecisionKeys?: ReadonlySet<string>;
|
|
38
|
+
/** Per-decision failures (pass `fileDecisionErrorsByKey` straight through). */
|
|
39
|
+
readonly decisionErrors?: ReadonlyMap<string, Error>;
|
|
40
|
+
/**
|
|
41
|
+
* Optional deep-link to open the child agent execution in its own view. When
|
|
42
|
+
* provided, each child's review renders a "View agent execution" affordance.
|
|
43
|
+
* Routing is the host's responsibility (DD-004).
|
|
44
|
+
*/
|
|
45
|
+
readonly onNavigateToAgentExecution?: (agentExecutionId: string) => void;
|
|
46
|
+
/** Additional CSS class names for the root container. */
|
|
47
|
+
readonly className?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Renders the child agent file reviews surfaced on a parent WorkflowExecution.
|
|
52
|
+
*
|
|
53
|
+
* Reference-only, derive-from-child: the parent status carries only
|
|
54
|
+
* {@link WorkflowPendingFileReview} references (child id + change set ids). This
|
|
55
|
+
* list mounts one {@link WorkflowChildFileReview} per referenced child, which
|
|
56
|
+
* streams that child's execution and reuses the agent-level {@link FileReviewCard}
|
|
57
|
+
* to render the actual diff — the heavy content stays single-sourced on the child.
|
|
58
|
+
* A decision is forwarded to the child via `WorkflowExecution.submitFileDecision`.
|
|
59
|
+
*
|
|
60
|
+
* This is the file-review sibling of the workflow tool-approval surface
|
|
61
|
+
* (`WorkflowExecutionApprovalCard`). Empty `pendingFileReviews` renders nothing.
|
|
62
|
+
*/
|
|
63
|
+
export function WorkflowFileReviewList({
|
|
64
|
+
pendingFileReviews,
|
|
65
|
+
onSubmitFileDecision,
|
|
66
|
+
submittingDecisionKeys,
|
|
67
|
+
decisionErrors,
|
|
68
|
+
onNavigateToAgentExecution,
|
|
69
|
+
className,
|
|
70
|
+
}: WorkflowFileReviewListProps): React.ReactElement | null {
|
|
71
|
+
if (pendingFileReviews.length === 0) return null;
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div className={cn("stgm space-y-3", className)}>
|
|
75
|
+
{pendingFileReviews.map((ref) => (
|
|
76
|
+
<WorkflowChildFileReview
|
|
77
|
+
key={ref.childAgentExecutionId}
|
|
78
|
+
reference={ref}
|
|
79
|
+
onSubmitFileDecision={onSubmitFileDecision}
|
|
80
|
+
submittingDecisionKeys={submittingDecisionKeys}
|
|
81
|
+
decisionErrors={decisionErrors}
|
|
82
|
+
onNavigateToAgentExecution={onNavigateToAgentExecution}
|
|
83
|
+
/>
|
|
84
|
+
))}
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface WorkflowChildFileReviewProps {
|
|
90
|
+
readonly reference: WorkflowPendingFileReview;
|
|
91
|
+
readonly onSubmitFileDecision: WorkflowFileDecisionSubmit;
|
|
92
|
+
readonly submittingDecisionKeys?: ReadonlySet<string>;
|
|
93
|
+
readonly decisionErrors?: ReadonlyMap<string, Error>;
|
|
94
|
+
readonly onNavigateToAgentExecution?: (agentExecutionId: string) => void;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Streams a single referenced child agent execution and renders its
|
|
99
|
+
* AWAITING_REVIEW change sets (intersected with the parent's surfaced reference,
|
|
100
|
+
* so a decision always targets a gate the workflow has actually surfaced).
|
|
101
|
+
*/
|
|
102
|
+
function WorkflowChildFileReview({
|
|
103
|
+
reference,
|
|
104
|
+
onSubmitFileDecision,
|
|
105
|
+
submittingDecisionKeys,
|
|
106
|
+
decisionErrors,
|
|
107
|
+
onNavigateToAgentExecution,
|
|
108
|
+
}: WorkflowChildFileReviewProps): React.ReactElement | null {
|
|
109
|
+
const childId = reference.childAgentExecutionId;
|
|
110
|
+
const { execution } = useExecutionStream(childId);
|
|
111
|
+
|
|
112
|
+
const changeSets = useMemo(() => {
|
|
113
|
+
const referenced = new Set(reference.changeSetId);
|
|
114
|
+
return displayFileChangeSets(execution?.status).filter(
|
|
115
|
+
(cs) =>
|
|
116
|
+
cs.status === FileChangeSetStatus.AWAITING_REVIEW &&
|
|
117
|
+
referenced.has(cs.id) &&
|
|
118
|
+
cs.changes.length > 0,
|
|
119
|
+
);
|
|
120
|
+
}, [execution?.status, reference.changeSetId]);
|
|
121
|
+
|
|
122
|
+
// Nothing to show yet (child still loading, or its projection has not caught up
|
|
123
|
+
// to the reference). The parent list already signals "review pending" for this
|
|
124
|
+
// child by virtue of the reference existing.
|
|
125
|
+
if (changeSets.length === 0) return null;
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<div className="space-y-2">
|
|
129
|
+
{onNavigateToAgentExecution && (
|
|
130
|
+
<button
|
|
131
|
+
type="button"
|
|
132
|
+
onClick={() => onNavigateToAgentExecution(childId)}
|
|
133
|
+
className="text-xs text-muted-foreground hover:text-foreground underline underline-offset-2"
|
|
134
|
+
>
|
|
135
|
+
View agent execution
|
|
136
|
+
</button>
|
|
137
|
+
)}
|
|
138
|
+
{changeSets.map((changeSet) => (
|
|
139
|
+
<FileReviewCard
|
|
140
|
+
key={changeSet.id}
|
|
141
|
+
fileChangeSet={changeSet}
|
|
142
|
+
interactive
|
|
143
|
+
submittingDecisionKeys={submittingDecisionKeys}
|
|
144
|
+
decisionErrors={decisionErrors}
|
|
145
|
+
onSubmit={(action, options) =>
|
|
146
|
+
onSubmitFileDecision(childId, changeSet.id, action, options)
|
|
147
|
+
}
|
|
148
|
+
/>
|
|
149
|
+
))}
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
@@ -4,6 +4,8 @@ import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
|
4
4
|
import Markdown from "react-markdown";
|
|
5
5
|
import { cn } from "@stigmer/theme";
|
|
6
6
|
import { MARKDOWN_COMPONENTS, REMARK_PLUGINS } from "../internal/markdown-components";
|
|
7
|
+
import { DecisionButton, type DecisionVariant } from "../internal/DecisionButton";
|
|
8
|
+
import { InCardDecisionError } from "../internal/InCardDecisionError";
|
|
7
9
|
|
|
8
10
|
/** Outcome descriptor for UI rendering. */
|
|
9
11
|
export interface TaskOutcome {
|
|
@@ -44,8 +46,15 @@ export interface WorkflowTaskApprovalCardProps {
|
|
|
44
46
|
formData?: Record<string, unknown>,
|
|
45
47
|
comment?: string,
|
|
46
48
|
) => Promise<unknown>;
|
|
47
|
-
/** True while
|
|
49
|
+
/** True while this gate's submission RPC is in flight. */
|
|
48
50
|
readonly isSubmitting: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* This gate's last failed decision, or `null`. Surfaced in-card beside the
|
|
53
|
+
* outcome buttons (via the shared {@link InCardDecisionError}) — supply
|
|
54
|
+
* {@link useWorkflowExecutionActions}'s `taskApprovalErrorsByTaskName` for
|
|
55
|
+
* this `taskName`.
|
|
56
|
+
*/
|
|
57
|
+
readonly error?: Error | null;
|
|
49
58
|
/** Additional CSS class names for the root container. */
|
|
50
59
|
readonly className?: string;
|
|
51
60
|
}
|
|
@@ -92,6 +101,7 @@ export const WorkflowTaskApprovalCard = memo(function WorkflowTaskApprovalCard({
|
|
|
92
101
|
formSchema,
|
|
93
102
|
onSubmit,
|
|
94
103
|
isSubmitting,
|
|
104
|
+
error,
|
|
95
105
|
className,
|
|
96
106
|
}: WorkflowTaskApprovalCardProps) {
|
|
97
107
|
const outcomes = outcomesProp.length > 0 ? outcomesProp : DEFAULT_OUTCOMES;
|
|
@@ -134,8 +144,10 @@ export const WorkflowTaskApprovalCard = memo(function WorkflowTaskApprovalCard({
|
|
|
134
144
|
role="form"
|
|
135
145
|
aria-label={`Approval decision for ${taskName}`}
|
|
136
146
|
aria-busy={isSubmitting}
|
|
147
|
+
// Neutral card + 2px warning left accent — the quiet Cursor-grade chrome
|
|
148
|
+
// shared with ApprovalCard. (Replaces the old amber `bg-warning/5` fill.)
|
|
137
149
|
className={cn(
|
|
138
|
-
"mt-2 rounded-lg border border-
|
|
150
|
+
"mt-2 rounded-lg border border-border-prominent border-l-2 border-l-warning p-3",
|
|
139
151
|
className,
|
|
140
152
|
)}
|
|
141
153
|
>
|
|
@@ -198,75 +210,34 @@ export const WorkflowTaskApprovalCard = memo(function WorkflowTaskApprovalCard({
|
|
|
198
210
|
|
|
199
211
|
<div className="flex flex-wrap gap-2">
|
|
200
212
|
{outcomes.map((outcome, index) => (
|
|
201
|
-
<
|
|
213
|
+
<DecisionButton
|
|
202
214
|
key={outcome.name}
|
|
203
215
|
label={outcome.label || capitalize(outcome.name)}
|
|
204
|
-
outcomeName={outcome.name}
|
|
205
216
|
variant={resolveVariant(outcome.name, index, outcomes.length)}
|
|
217
|
+
onClick={() => handleSubmit(outcome.name)}
|
|
206
218
|
isActive={activeOutcome === outcome.name}
|
|
207
219
|
isSubmitting={isSubmitting}
|
|
208
|
-
onClick={handleSubmit}
|
|
209
220
|
/>
|
|
210
221
|
))}
|
|
211
222
|
</div>
|
|
212
|
-
</div>
|
|
213
|
-
);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// ---------------------------------------------------------------------------
|
|
217
|
-
// Internal sub-components
|
|
218
|
-
// ---------------------------------------------------------------------------
|
|
219
223
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
readonly isActive: boolean;
|
|
234
|
-
readonly isSubmitting: boolean;
|
|
235
|
-
readonly onClick: (name: string) => void;
|
|
236
|
-
}) {
|
|
237
|
-
const variantClasses: Record<ButtonVariant, string> = {
|
|
238
|
-
primary: cn(
|
|
239
|
-
"bg-success text-success-foreground hover:bg-success/90",
|
|
240
|
-
"disabled:bg-success/50 disabled:text-success-foreground/70",
|
|
241
|
-
),
|
|
242
|
-
destructive: cn(
|
|
243
|
-
"bg-destructive text-destructive-foreground hover:bg-destructive-hover",
|
|
244
|
-
"disabled:bg-destructive-subtle0 disabled:text-destructive-foreground/70",
|
|
245
|
-
),
|
|
246
|
-
secondary: cn(
|
|
247
|
-
"border border-border bg-background text-foreground hover:bg-muted",
|
|
248
|
-
"disabled:bg-muted-faint disabled:text-muted-foreground-faint",
|
|
249
|
-
),
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
return (
|
|
253
|
-
<button
|
|
254
|
-
type="button"
|
|
255
|
-
disabled={isSubmitting}
|
|
256
|
-
onClick={() => onClick(outcomeName)}
|
|
257
|
-
aria-label={label}
|
|
258
|
-
className={cn(
|
|
259
|
-
"inline-flex items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
|
|
260
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
261
|
-
"disabled:cursor-not-allowed",
|
|
262
|
-
variantClasses[variant],
|
|
224
|
+
{/* A failed decision surfaces HERE, beside this gate's outcome buttons —
|
|
225
|
+
not in the viewer's lifecycle banner. A workflow can hold many gates at
|
|
226
|
+
once, so a failure must name the one it belongs to; the optimistic
|
|
227
|
+
spinner has already reverted, and this explains the snap-back. Shared
|
|
228
|
+
with the agent ApprovalCard / FileReviewCard via InCardDecisionError. */}
|
|
229
|
+
{error && (
|
|
230
|
+
<div className="mt-2">
|
|
231
|
+
<InCardDecisionError
|
|
232
|
+
error={error}
|
|
233
|
+
leadIn="submit decision"
|
|
234
|
+
cursorTarget="wf-task-approval-error"
|
|
235
|
+
/>
|
|
236
|
+
</div>
|
|
263
237
|
)}
|
|
264
|
-
>
|
|
265
|
-
{isActive && isSubmitting ? <SpinnerIcon /> : null}
|
|
266
|
-
{label}
|
|
267
|
-
</button>
|
|
238
|
+
</div>
|
|
268
239
|
);
|
|
269
|
-
}
|
|
240
|
+
});
|
|
270
241
|
|
|
271
242
|
// ---------------------------------------------------------------------------
|
|
272
243
|
// Helpers
|
|
@@ -296,42 +267,23 @@ function resolveVariant(
|
|
|
296
267
|
outcomeName: string,
|
|
297
268
|
index: number,
|
|
298
269
|
total: number,
|
|
299
|
-
):
|
|
270
|
+
): DecisionVariant {
|
|
271
|
+
// The first outcome is the recommended action (the quiet neutral chip).
|
|
300
272
|
if (index === 0) return "primary";
|
|
301
273
|
|
|
302
274
|
const lower = outcomeName.toLowerCase();
|
|
303
275
|
if (lower === "reject" || lower === "deny" || lower.includes("reject")) {
|
|
304
|
-
return "
|
|
276
|
+
return "danger";
|
|
305
277
|
}
|
|
306
278
|
|
|
279
|
+
// In a simple two-outcome form, the trailing outcome is the negative one.
|
|
307
280
|
if (index === total - 1 && total === 2) {
|
|
308
|
-
return "
|
|
281
|
+
return "danger";
|
|
309
282
|
}
|
|
310
283
|
|
|
311
|
-
return "
|
|
284
|
+
return "ghost";
|
|
312
285
|
}
|
|
313
286
|
|
|
314
287
|
function capitalize(s: string): string {
|
|
315
288
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
316
289
|
}
|
|
317
|
-
|
|
318
|
-
// ---------------------------------------------------------------------------
|
|
319
|
-
// Inline SVG icons
|
|
320
|
-
// ---------------------------------------------------------------------------
|
|
321
|
-
|
|
322
|
-
function SpinnerIcon() {
|
|
323
|
-
return (
|
|
324
|
-
<svg
|
|
325
|
-
width="10"
|
|
326
|
-
height="10"
|
|
327
|
-
viewBox="0 0 12 12"
|
|
328
|
-
fill="none"
|
|
329
|
-
stroke="currentColor"
|
|
330
|
-
strokeWidth="1.5"
|
|
331
|
-
className="animate-spin"
|
|
332
|
-
aria-hidden="true"
|
|
333
|
-
>
|
|
334
|
-
<path d="M6 1.5A4.5 4.5 0 1 1 1.5 6" strokeLinecap="round" />
|
|
335
|
-
</svg>
|
|
336
|
-
);
|
|
337
|
-
}
|
|
@@ -88,7 +88,6 @@ describe("ExecutionInspector — approval gating", () => {
|
|
|
88
88
|
events={[approvalRequested]}
|
|
89
89
|
taskStates={new Map([[TASK, makeTaskState(TASK, "waiting_approval")]])}
|
|
90
90
|
onSubmitTaskApproval={vi.fn().mockResolvedValue(undefined)}
|
|
91
|
-
isSubmittingTaskApproval={false}
|
|
92
91
|
/>,
|
|
93
92
|
);
|
|
94
93
|
|
|
@@ -97,6 +96,36 @@ describe("ExecutionInspector — approval gating", () => {
|
|
|
97
96
|
expect(screen.getByRole("button", { name: "Reject" })).toBeTruthy();
|
|
98
97
|
});
|
|
99
98
|
|
|
99
|
+
it("surfaces this gate's keyed failure in-card, beside the outcome buttons", () => {
|
|
100
|
+
render(
|
|
101
|
+
<ExecutionInspector
|
|
102
|
+
selectedTaskName={TASK}
|
|
103
|
+
events={[approvalRequested]}
|
|
104
|
+
taskStates={new Map([[TASK, makeTaskState(TASK, "waiting_approval")]])}
|
|
105
|
+
onSubmitTaskApproval={vi.fn().mockResolvedValue(undefined)}
|
|
106
|
+
taskApprovalErrorsByTaskName={new Map([[TASK, new Error("signal failed")]])}
|
|
107
|
+
/>,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
expect(screen.getByText(/Couldn.t submit decision — signal failed/)).toBeTruthy();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("marks only this gate's buttons as submitting via the keyed set", () => {
|
|
114
|
+
render(
|
|
115
|
+
<ExecutionInspector
|
|
116
|
+
selectedTaskName={TASK}
|
|
117
|
+
events={[approvalRequested]}
|
|
118
|
+
taskStates={new Map([[TASK, makeTaskState(TASK, "waiting_approval")]])}
|
|
119
|
+
onSubmitTaskApproval={vi.fn().mockResolvedValue(undefined)}
|
|
120
|
+
taskApprovalSubmittingTaskNames={new Set([TASK])}
|
|
121
|
+
/>,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(
|
|
125
|
+
(screen.getByRole("button", { name: "Approve Plan" }) as HTMLButtonElement).disabled,
|
|
126
|
+
).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
|
|
100
129
|
it("renders the read-only decision summary once the gate is resolved", () => {
|
|
101
130
|
render(
|
|
102
131
|
<ExecutionInspector
|
|
@@ -111,7 +140,6 @@ describe("ExecutionInspector — approval gating", () => {
|
|
|
111
140
|
}),
|
|
112
141
|
]}
|
|
113
142
|
onSubmitTaskApproval={vi.fn().mockResolvedValue(undefined)}
|
|
114
|
-
isSubmittingTaskApproval={false}
|
|
115
143
|
/>,
|
|
116
144
|
);
|
|
117
145
|
|