@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
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
4
5
|
import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
|
|
5
|
-
import { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
6
|
+
import { ApprovalAction, ToolKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
6
7
|
import { cn } from "@stigmer/theme";
|
|
8
|
+
import {
|
|
9
|
+
describeApprovalPolicySource,
|
|
10
|
+
isInformativePolicySource,
|
|
11
|
+
} from "./approval-provenance";
|
|
7
12
|
import {
|
|
8
13
|
resolveToolCategoryFromKind,
|
|
9
14
|
extractPrimaryArgFromPreview,
|
|
15
|
+
extractWriteContentFromPreview,
|
|
16
|
+
isFileCategory,
|
|
17
|
+
type ToolCategory,
|
|
10
18
|
} from "./tool-categories";
|
|
11
19
|
import { CATEGORY_ICON } from "./ToolCallItem";
|
|
12
20
|
import { ToolArgsView } from "./ToolArgsView";
|
|
21
|
+
import { EmptyChangeNotice } from "./EmptyChangeNotice";
|
|
22
|
+
import { FilePathLink } from "./FilePathLink";
|
|
23
|
+
import { DecisionButton } from "../internal/DecisionButton";
|
|
24
|
+
import { InCardDecisionError } from "../internal/InCardDecisionError";
|
|
25
|
+
import { useElapsedSince, formatElapsed } from "../internal/useElapsedSince";
|
|
13
26
|
|
|
14
27
|
/** Props for {@link ApprovalCard}. */
|
|
15
28
|
export interface ApprovalCardProps {
|
|
@@ -24,6 +37,14 @@ export interface ApprovalCardProps {
|
|
|
24
37
|
readonly onSubmit: (action: ApprovalAction, comment?: string) => void;
|
|
25
38
|
/** True while the RPC for this specific tool call is in flight. */
|
|
26
39
|
readonly isSubmitting?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* This gate's last failed decision, or `null` — surfaced in-card, beside the
|
|
42
|
+
* action buttons (the optimistic spinner reverts on failure, so this explains
|
|
43
|
+
* the snap-back). A thread can hold many gates; the error must name the one it
|
|
44
|
+
* belongs to, which a single global banner cannot do. Supply the entry from
|
|
45
|
+
* {@link useSubmitApproval}'s `errorsByToolCallId` for this `toolCallId`.
|
|
46
|
+
*/
|
|
47
|
+
readonly error?: Error | null;
|
|
27
48
|
/** Additional CSS class names for the root container. */
|
|
28
49
|
readonly className?: string;
|
|
29
50
|
}
|
|
@@ -35,9 +56,11 @@ export interface ApprovalCardProps {
|
|
|
35
56
|
* The compact header row matches the ToolCallItem layout:
|
|
36
57
|
* [CategoryIcon] Label primaryArg [⏳ waiting Xm]
|
|
37
58
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
59
|
+
* The body shows the proposed change from the tool args (the
|
|
60
|
+
* pre-execution deny-gate has no captured `FileChangeSet` yet): the
|
|
61
|
+
* write/edit content when present, an {@link EmptyChangeNotice} when
|
|
62
|
+
* only a path is known, otherwise the shared {@link ToolArgsView}
|
|
63
|
+
* dispatch, keeping pixel-level parity with the detail view.
|
|
41
64
|
*
|
|
42
65
|
* Wrapped in `React.memo` — structural sharing (T04) preserves the
|
|
43
66
|
* `PendingApproval` reference when unchanged, so approval cards
|
|
@@ -56,32 +79,69 @@ export const ApprovalCard = memo(function ApprovalCard({
|
|
|
56
79
|
pendingApproval,
|
|
57
80
|
onSubmit,
|
|
58
81
|
isSubmitting = false,
|
|
82
|
+
error = null,
|
|
59
83
|
className,
|
|
60
84
|
}: ApprovalCardProps) {
|
|
61
|
-
|
|
85
|
+
// Prefer the denormalized wire tool_kind (populated by the server-side
|
|
86
|
+
// PendingApproval projection); fall back to the name for legacy executions.
|
|
87
|
+
const categoryInfo = resolveToolCategoryFromKind(
|
|
88
|
+
pendingApproval.toolKind,
|
|
89
|
+
pendingApproval.toolName,
|
|
90
|
+
pendingApproval.mcpServerSlug,
|
|
91
|
+
);
|
|
62
92
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
93
|
+
// Cursor-grade chrome: a thin neutral card (no amber "brown" fill), with the
|
|
94
|
+
// gate's "needs your decision" signal carried by one restrained cue — a 2px
|
|
95
|
+
// left accent bar — plus the warning-colored clock/elapsed in the header. A
|
|
96
|
+
// destructive (delete) gate keeps a red accent as a hard safety signal.
|
|
97
|
+
const accentClass =
|
|
98
|
+
categoryInfo.category === "delete"
|
|
99
|
+
? "border-l-2 border-l-destructive"
|
|
100
|
+
: "border-l-2 border-l-warning";
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<div
|
|
104
|
+
role="alert"
|
|
105
|
+
aria-label={`Approval required for ${pendingApproval.toolName}`}
|
|
106
|
+
className={cn(
|
|
107
|
+
"rounded-lg border border-border-prominent",
|
|
108
|
+
accentClass,
|
|
109
|
+
className,
|
|
110
|
+
)}
|
|
111
|
+
>
|
|
112
|
+
<ApprovalCardHeader pendingApproval={pendingApproval} bordered />
|
|
113
|
+
<ApprovalCardBody
|
|
114
|
+
pendingApproval={pendingApproval}
|
|
115
|
+
onSubmit={onSubmit}
|
|
116
|
+
isSubmitting={isSubmitting}
|
|
117
|
+
error={error}
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
69
120
|
);
|
|
121
|
+
});
|
|
70
122
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
123
|
+
/** Props for {@link ApprovalCardHeader}. */
|
|
124
|
+
export interface ApprovalCardHeaderProps {
|
|
125
|
+
/** The pending approval to summarize. */
|
|
126
|
+
readonly pendingApproval: PendingApproval;
|
|
127
|
+
/** Adds a bottom divider, for use above {@link ApprovalCardBody}. */
|
|
128
|
+
readonly bordered?: boolean;
|
|
129
|
+
}
|
|
76
130
|
|
|
77
|
-
|
|
78
|
-
|
|
131
|
+
/**
|
|
132
|
+
* The compact summary row of an approval — `[icon] Label primaryArg [via sub]
|
|
133
|
+
* [⏳ Xm]`. Used as the standalone {@link ApprovalCard}'s header. Not rendered
|
|
134
|
+
* inline on a {@link ToolCallItem}, whose own row already serves as the header.
|
|
135
|
+
*/
|
|
136
|
+
export function ApprovalCardHeader({
|
|
137
|
+
pendingApproval,
|
|
138
|
+
bordered = false,
|
|
139
|
+
}: ApprovalCardHeaderProps) {
|
|
79
140
|
const categoryInfo = resolveToolCategoryFromKind(
|
|
80
141
|
pendingApproval.toolKind,
|
|
81
142
|
pendingApproval.toolName,
|
|
82
143
|
pendingApproval.mcpServerSlug,
|
|
83
144
|
);
|
|
84
|
-
|
|
85
145
|
const CategoryIcon = CATEGORY_ICON[categoryInfo.category];
|
|
86
146
|
|
|
87
147
|
const primaryArg = useMemo(
|
|
@@ -90,14 +150,114 @@ export const ApprovalCard = memo(function ApprovalCard({
|
|
|
90
150
|
pendingApproval.toolName,
|
|
91
151
|
pendingApproval.argsPreview,
|
|
92
152
|
pendingApproval.mcpServerSlug,
|
|
153
|
+
pendingApproval.toolKind,
|
|
93
154
|
),
|
|
94
155
|
[
|
|
95
156
|
pendingApproval.toolName,
|
|
96
157
|
pendingApproval.argsPreview,
|
|
97
158
|
pendingApproval.mcpServerSlug,
|
|
159
|
+
pendingApproval.toolKind,
|
|
98
160
|
],
|
|
99
161
|
);
|
|
100
162
|
|
|
163
|
+
return (
|
|
164
|
+
<div
|
|
165
|
+
className={cn(
|
|
166
|
+
"flex items-center gap-2 px-2.5 py-1.5 text-xs",
|
|
167
|
+
bordered && "border-b border-border-muted",
|
|
168
|
+
)}
|
|
169
|
+
>
|
|
170
|
+
<span className="shrink-0 text-warning" aria-hidden="true">
|
|
171
|
+
<CategoryIcon />
|
|
172
|
+
</span>
|
|
173
|
+
|
|
174
|
+
<span className="min-w-0 flex-1 flex items-center gap-1.5 overflow-hidden">
|
|
175
|
+
<span className="shrink-0 font-medium text-foreground">
|
|
176
|
+
{categoryInfo.label}
|
|
177
|
+
</span>
|
|
178
|
+
{primaryArg &&
|
|
179
|
+
categoryInfo.category !== "shell" &&
|
|
180
|
+
(isFileCategory(categoryInfo.category) ? (
|
|
181
|
+
// A file tool's primary arg is a path — render it filename-first
|
|
182
|
+
// with the full path on hover, matching the ToolCallItem header.
|
|
183
|
+
<FilePathLink
|
|
184
|
+
path={primaryArg}
|
|
185
|
+
className="min-w-0 text-xs text-muted-foreground"
|
|
186
|
+
/>
|
|
187
|
+
) : (
|
|
188
|
+
// Shell is the exception: its command is shown in the body's
|
|
189
|
+
// terminal session, so the header stays minimal (icon + label).
|
|
190
|
+
<span className="min-w-0 truncate font-mono text-muted-foreground">
|
|
191
|
+
{primaryArg}
|
|
192
|
+
</span>
|
|
193
|
+
))}
|
|
194
|
+
</span>
|
|
195
|
+
|
|
196
|
+
{pendingApproval.fromSubAgent && pendingApproval.subAgentName && (
|
|
197
|
+
<span className="shrink-0 rounded bg-muted px-1 py-0.5 font-mono text-muted-foreground">
|
|
198
|
+
via {pendingApproval.subAgentSubject || pendingApproval.subAgentName}
|
|
199
|
+
</span>
|
|
200
|
+
)}
|
|
201
|
+
|
|
202
|
+
<WaitingDuration requestedAt={pendingApproval.requestedAt} />
|
|
203
|
+
|
|
204
|
+
<span className="shrink-0 text-warning" aria-hidden="true">
|
|
205
|
+
<ClockIcon />
|
|
206
|
+
</span>
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Props for {@link ApprovalCardBody}. */
|
|
212
|
+
export interface ApprovalCardBodyProps {
|
|
213
|
+
/** The pending approval to render a decision panel for. */
|
|
214
|
+
readonly pendingApproval: PendingApproval;
|
|
215
|
+
/** Called when the user picks Approve / Approve-all / Skip / Reject. */
|
|
216
|
+
readonly onSubmit: (action: ApprovalAction, comment?: string) => void;
|
|
217
|
+
/** True while the RPC for this tool call is in flight. */
|
|
218
|
+
readonly isSubmitting?: boolean;
|
|
219
|
+
/** This gate's last failed decision, or `null` — surfaced in-card below the actions. */
|
|
220
|
+
readonly error?: Error | null;
|
|
221
|
+
/** Additional CSS class names for the body container. */
|
|
222
|
+
readonly className?: string;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* The decision panel of an approval: the optional message and gate reason, the
|
|
227
|
+
* file-changes / args preview, and the action buttons. Reused in two places —
|
|
228
|
+
* the standalone {@link ApprovalCard} (with {@link ApprovalCardHeader} above
|
|
229
|
+
* it) and inline inside a gated {@link ToolCallItem}'s expanded panel, where
|
|
230
|
+
* the item's own row is the header. One body, identical preview in both.
|
|
231
|
+
*/
|
|
232
|
+
export function ApprovalCardBody({
|
|
233
|
+
pendingApproval,
|
|
234
|
+
onSubmit,
|
|
235
|
+
isSubmitting = false,
|
|
236
|
+
error = null,
|
|
237
|
+
className,
|
|
238
|
+
}: ApprovalCardBodyProps) {
|
|
239
|
+
const [activeAction, setActiveAction] = useState<ApprovalAction | null>(null);
|
|
240
|
+
|
|
241
|
+
const handleAction = useCallback(
|
|
242
|
+
(action: ApprovalAction) => {
|
|
243
|
+
setActiveAction(action);
|
|
244
|
+
onSubmit(action);
|
|
245
|
+
},
|
|
246
|
+
[onSubmit],
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
if (!isSubmitting) {
|
|
251
|
+
setActiveAction(null);
|
|
252
|
+
}
|
|
253
|
+
}, [isSubmitting]);
|
|
254
|
+
|
|
255
|
+
const categoryInfo = resolveToolCategoryFromKind(
|
|
256
|
+
pendingApproval.toolKind,
|
|
257
|
+
pendingApproval.toolName,
|
|
258
|
+
pendingApproval.mcpServerSlug,
|
|
259
|
+
);
|
|
260
|
+
|
|
101
261
|
const parsedArgs = useMemo<Record<string, unknown> | null>(() => {
|
|
102
262
|
if (!pendingApproval.argsPreview) return null;
|
|
103
263
|
try {
|
|
@@ -111,198 +271,211 @@ export const ApprovalCard = memo(function ApprovalCard({
|
|
|
111
271
|
}
|
|
112
272
|
}, [pendingApproval.argsPreview]);
|
|
113
273
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
274
|
+
// APPROVE_ALL now grants a run-lifetime lease scoped to the clicked tool's
|
|
275
|
+
// CLASS — its MCP server for an MCP tool, else its approval category (where
|
|
276
|
+
// write and edit collapse to one "file edits" class, mirroring the runner's
|
|
277
|
+
// toolApprovalCategory). The label must name that exact class so the button
|
|
278
|
+
// never over-promises: it does NOT silence other classes.
|
|
279
|
+
const approveAllLabel = useMemo(
|
|
280
|
+
() => buildApproveAllLabel(categoryInfo.category, pendingApproval.mcpServerSlug),
|
|
281
|
+
[categoryInfo.category, pendingApproval.mcpServerSlug],
|
|
282
|
+
);
|
|
118
283
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
>
|
|
132
|
-
<span className="shrink-0 text-warning" aria-hidden="true">
|
|
133
|
-
<CategoryIcon />
|
|
134
|
-
</span>
|
|
284
|
+
// Why-gated: the authorization provenance the server projected onto the
|
|
285
|
+
// PendingApproval (approval_policy_source). Smart-suppressed — the everyday
|
|
286
|
+
// "this category needs approval" default is noise next to the action it gates,
|
|
287
|
+
// so only a genuinely informative provenance (an explicit override, a
|
|
288
|
+
// server-marked destructive tighten) earns a line; the full phrase is on hover.
|
|
289
|
+
const gateReason = useMemo(
|
|
290
|
+
() => describeApprovalPolicySource(pendingApproval.approvalPolicySource),
|
|
291
|
+
[pendingApproval.approvalPolicySource],
|
|
292
|
+
);
|
|
293
|
+
const showGateReason =
|
|
294
|
+
gateReason != null &&
|
|
295
|
+
isInformativePolicySource(pendingApproval.approvalPolicySource);
|
|
135
296
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
)}
|
|
145
|
-
</span>
|
|
297
|
+
// The runner's message for a file tool ("Write file: <path>") only restates
|
|
298
|
+
// the header + diff, so it is suppressed; a message is shown only when it adds
|
|
299
|
+
// information (e.g. an MCP tool's human-authored prompt). Shell shows its
|
|
300
|
+
// command in the args view, never a message.
|
|
301
|
+
const showMessage =
|
|
302
|
+
Boolean(pendingApproval.message) &&
|
|
303
|
+
categoryInfo.category !== "shell" &&
|
|
304
|
+
!isFileCategory(categoryInfo.category);
|
|
146
305
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
via {pendingApproval.subAgentSubject || pendingApproval.subAgentName}
|
|
150
|
-
</span>
|
|
151
|
-
)}
|
|
306
|
+
const isWriteEdit =
|
|
307
|
+
categoryInfo.category === "write" || categoryInfo.category === "edit";
|
|
152
308
|
|
|
153
|
-
|
|
309
|
+
// The proposed write/edit content from the args preview, when the gate carries
|
|
310
|
+
// no authoritative file_changes capture. Drives the three-way fallback below.
|
|
311
|
+
const writeContent = useMemo(
|
|
312
|
+
() => extractWriteContentFromPreview(pendingApproval.argsPreview),
|
|
313
|
+
[pendingApproval.argsPreview],
|
|
314
|
+
);
|
|
154
315
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
316
|
+
// The decision-relevant preview. The pre-execution deny-gate is an
|
|
317
|
+
// apply-then-review exception: the change has not been captured yet (the tool
|
|
318
|
+
// is DENIED, awaiting approval), so there is no `FileChangeSet` to render.
|
|
319
|
+
// Instead the gate shows the PROPOSED change from the tool args: the write/edit
|
|
320
|
+
// content when the args carry it (path suppressed — the header has it); a
|
|
321
|
+
// neutral "no preview" notice when only a path is known (the resume placeholder
|
|
322
|
+
// case); otherwise the shared args view for non-file tools. (Captured
|
|
323
|
+
// file-review — the apply-then-review path — renders via FileReviewCard, not
|
|
324
|
+
// here.)
|
|
325
|
+
let preview: ReactNode = null;
|
|
326
|
+
if (isWriteEdit && writeContent === null) {
|
|
327
|
+
// No proposed content in the args. A whole-file write is modeled as a create
|
|
328
|
+
// throughout the runner (FILE_WRITE -> CREATE), so the authoritative toolKind
|
|
329
|
+
// lets the gate say plainly that a new file is being written rather than the
|
|
330
|
+
// misleading non-committal "no preview". An edit (modify) cannot be proven a
|
|
331
|
+
// create, so it keeps the non-committal notice.
|
|
332
|
+
const kind =
|
|
333
|
+
pendingApproval.toolKind === ToolKind.FILE_WRITE ? "create" : "no-preview";
|
|
334
|
+
preview = <EmptyChangeNotice kind={kind} />;
|
|
335
|
+
} else if (parsedArgs) {
|
|
336
|
+
preview = (
|
|
337
|
+
<ToolArgsView
|
|
338
|
+
toolName={pendingApproval.toolName}
|
|
339
|
+
args={parsedArgs}
|
|
340
|
+
mcpServerSlug={pendingApproval.mcpServerSlug}
|
|
341
|
+
showFileName={!isWriteEdit}
|
|
342
|
+
/>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
159
345
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
</p>
|
|
166
|
-
)}
|
|
167
|
-
|
|
168
|
-
{/* Category-specific args preview — shared with ToolCallDetail */}
|
|
169
|
-
{parsedArgs && (
|
|
170
|
-
<ToolArgsView
|
|
171
|
-
toolName={pendingApproval.toolName}
|
|
172
|
-
args={parsedArgs}
|
|
173
|
-
mcpServerSlug={pendingApproval.mcpServerSlug}
|
|
174
|
-
/>
|
|
175
|
-
)}
|
|
176
|
-
|
|
177
|
-
{/* Action buttons */}
|
|
178
|
-
<div className="flex items-center gap-2 pt-1">
|
|
179
|
-
<ActionButton
|
|
180
|
-
label="Approve"
|
|
181
|
-
action={ApprovalAction.APPROVE}
|
|
182
|
-
activeAction={activeAction}
|
|
183
|
-
isSubmitting={isSubmitting}
|
|
184
|
-
onClick={handleAction}
|
|
185
|
-
variant="approve"
|
|
186
|
-
cursorTarget="approve-button"
|
|
187
|
-
/>
|
|
188
|
-
{/* Subordinate escalation: approve this call and stop asking for the
|
|
189
|
-
rest of the run. Kept visually quieter than the primary Approve so
|
|
190
|
-
it never competes with the per-call decision the user is making. */}
|
|
191
|
-
<ActionButton
|
|
192
|
-
label="Approve & don't ask again"
|
|
193
|
-
action={ApprovalAction.APPROVE_ALL}
|
|
194
|
-
activeAction={activeAction}
|
|
195
|
-
isSubmitting={isSubmitting}
|
|
196
|
-
onClick={handleAction}
|
|
197
|
-
variant="approveAll"
|
|
198
|
-
cursorTarget="approve-all-button"
|
|
199
|
-
/>
|
|
200
|
-
<ActionButton
|
|
201
|
-
label="Skip"
|
|
202
|
-
action={ApprovalAction.SKIP}
|
|
203
|
-
activeAction={activeAction}
|
|
204
|
-
isSubmitting={isSubmitting}
|
|
205
|
-
onClick={handleAction}
|
|
206
|
-
variant="skip"
|
|
207
|
-
/>
|
|
208
|
-
<ActionButton
|
|
209
|
-
label="Reject"
|
|
210
|
-
action={ApprovalAction.REJECT}
|
|
211
|
-
activeAction={activeAction}
|
|
212
|
-
isSubmitting={isSubmitting}
|
|
213
|
-
onClick={handleAction}
|
|
214
|
-
variant="reject"
|
|
215
|
-
/>
|
|
216
|
-
</div>
|
|
217
|
-
</div>
|
|
218
|
-
</div>
|
|
219
|
-
);
|
|
220
|
-
});
|
|
346
|
+
return (
|
|
347
|
+
<div className={cn("px-3 py-2.5 space-y-2", className)}>
|
|
348
|
+
{showMessage && (
|
|
349
|
+
<p className="text-xs text-foreground">{pendingApproval.message}</p>
|
|
350
|
+
)}
|
|
221
351
|
|
|
222
|
-
|
|
223
|
-
// Internal sub-components
|
|
224
|
-
// ---------------------------------------------------------------------------
|
|
352
|
+
{preview}
|
|
225
353
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
activeAction: ApprovalAction | null;
|
|
238
|
-
isSubmitting: boolean;
|
|
239
|
-
onClick: (action: ApprovalAction) => void;
|
|
240
|
-
variant: "approve" | "approveAll" | "skip" | "reject";
|
|
241
|
-
cursorTarget?: string;
|
|
242
|
-
}) {
|
|
243
|
-
const isActive = activeAction === action;
|
|
244
|
-
const disabled = isSubmitting;
|
|
245
|
-
|
|
246
|
-
const variantClasses: Record<typeof variant, string> = {
|
|
247
|
-
approve: cn(
|
|
248
|
-
"bg-success text-success-foreground hover:bg-success/90",
|
|
249
|
-
"disabled:bg-success/50 disabled:text-success-foreground/70",
|
|
250
|
-
),
|
|
251
|
-
approveAll: cn(
|
|
252
|
-
"text-success hover:bg-success/10",
|
|
253
|
-
"disabled:text-success/50",
|
|
254
|
-
),
|
|
255
|
-
skip: cn(
|
|
256
|
-
"border border-border bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
257
|
-
"disabled:bg-muted-faint disabled:text-muted-foreground-faint",
|
|
258
|
-
),
|
|
259
|
-
reject: cn(
|
|
260
|
-
"bg-destructive text-destructive-foreground hover:bg-destructive-hover",
|
|
261
|
-
"disabled:bg-destructive-subtle0 disabled:text-destructive-foreground/70",
|
|
262
|
-
),
|
|
263
|
-
};
|
|
354
|
+
{/* Consent stated at grant time (DD-28): approving a shell command covers
|
|
355
|
+
the files it creates or changes — when the turn's mutations all come
|
|
356
|
+
from approved commands, the file-change set is kept automatically and
|
|
357
|
+
never re-gates. A mixed turn (commands + file-tool edits) still
|
|
358
|
+
reviews everything, so this line under-promises rather than over-. */}
|
|
359
|
+
{categoryInfo.category === "shell" && (
|
|
360
|
+
<p className="text-[11px] italic text-muted-foreground">
|
|
361
|
+
Files this command creates or changes are covered by this approval —
|
|
362
|
+
they are kept automatically, with no second review.
|
|
363
|
+
</p>
|
|
364
|
+
)}
|
|
264
365
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
366
|
+
{/* Decision actions — quiet, Cursor-grade hierarchy: one neutral-chip
|
|
367
|
+
primary (Approve), ghost Skip, ghost-danger Reject. The broad
|
|
368
|
+
run-lifetime lease (Approve all) is demoted to the far right via
|
|
369
|
+
`ml-auto` so it never competes with — or is mis-clicked for — the
|
|
370
|
+
per-call Approve (Fitts/Hick). */}
|
|
371
|
+
<div className="flex items-center gap-2 pt-1">
|
|
372
|
+
<DecisionButton
|
|
373
|
+
label="Approve"
|
|
374
|
+
variant="primary"
|
|
375
|
+
onClick={() => handleAction(ApprovalAction.APPROVE)}
|
|
376
|
+
isActive={activeAction === ApprovalAction.APPROVE}
|
|
377
|
+
isSubmitting={isSubmitting}
|
|
378
|
+
cursorTarget="approve-button"
|
|
379
|
+
/>
|
|
380
|
+
<DecisionButton
|
|
381
|
+
label="Skip"
|
|
382
|
+
variant="ghost"
|
|
383
|
+
onClick={() => handleAction(ApprovalAction.SKIP)}
|
|
384
|
+
isActive={activeAction === ApprovalAction.SKIP}
|
|
385
|
+
isSubmitting={isSubmitting}
|
|
386
|
+
/>
|
|
387
|
+
<DecisionButton
|
|
388
|
+
label="Reject"
|
|
389
|
+
variant="danger"
|
|
390
|
+
onClick={() => handleAction(ApprovalAction.REJECT)}
|
|
391
|
+
isActive={activeAction === ApprovalAction.REJECT}
|
|
392
|
+
isSubmitting={isSubmitting}
|
|
393
|
+
/>
|
|
394
|
+
{/* Subordinate escalation: approve this call AND stop asking for THIS
|
|
395
|
+
CLASS of tool for the rest of the run (its MCP server, or its file
|
|
396
|
+
edit / delete / shell category) — other classes keep prompting. The
|
|
397
|
+
label names the leased class so the scope is never a surprise. */}
|
|
398
|
+
<DecisionButton
|
|
399
|
+
label={approveAllLabel}
|
|
400
|
+
variant="ghost"
|
|
401
|
+
onClick={() => handleAction(ApprovalAction.APPROVE_ALL)}
|
|
402
|
+
isActive={activeAction === ApprovalAction.APPROVE_ALL}
|
|
403
|
+
isSubmitting={isSubmitting}
|
|
404
|
+
className="ml-auto"
|
|
405
|
+
cursorTarget="approve-all-button"
|
|
406
|
+
/>
|
|
407
|
+
</div>
|
|
408
|
+
|
|
409
|
+
{/* De-emphasized provenance, trailing the decision it explains. Only the
|
|
410
|
+
informative reasons reach here (see showGateReason); the full phrase is
|
|
411
|
+
on hover. */}
|
|
412
|
+
{showGateReason && (
|
|
413
|
+
<p
|
|
414
|
+
className="text-[11px] italic text-muted-foreground"
|
|
415
|
+
title={gateReason ?? undefined}
|
|
416
|
+
data-cursor-target="approval-gate-reason"
|
|
417
|
+
>
|
|
418
|
+
{gateReason}
|
|
419
|
+
</p>
|
|
277
420
|
)}
|
|
278
|
-
|
|
279
|
-
{
|
|
280
|
-
|
|
281
|
-
|
|
421
|
+
|
|
422
|
+
{/* A failed decision is surfaced HERE, in-card, beside the actions — not
|
|
423
|
+
via the session's global banner. A thread can hold many gates (each
|
|
424
|
+
inline tool row, plus the bottom backstop), so a failure must name the
|
|
425
|
+
one it belongs to; the optimistic spinner has already reverted, and
|
|
426
|
+
this explains the snap-back. Shared with FileReviewCard. */}
|
|
427
|
+
{error && (
|
|
428
|
+
<InCardDecisionError
|
|
429
|
+
error={error}
|
|
430
|
+
leadIn="submit decision"
|
|
431
|
+
cursorTarget="approval-error"
|
|
432
|
+
/>
|
|
433
|
+
)}
|
|
434
|
+
</div>
|
|
282
435
|
);
|
|
283
436
|
}
|
|
284
437
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const t = new Date(requestedAt).getTime();
|
|
289
|
-
return Number.isNaN(t) ? null : t;
|
|
290
|
-
}, [requestedAt]);
|
|
438
|
+
// ---------------------------------------------------------------------------
|
|
439
|
+
// Internal helpers
|
|
440
|
+
// ---------------------------------------------------------------------------
|
|
291
441
|
|
|
292
|
-
|
|
442
|
+
/**
|
|
443
|
+
* Builds the truthful APPROVE_ALL button label for a tool's lease class.
|
|
444
|
+
*
|
|
445
|
+
* The lease an APPROVE_ALL grants is scoped to ONE class: the MCP server for an
|
|
446
|
+
* MCP tool, otherwise the approval category (write/delete/shell) — where the
|
|
447
|
+
* presentation "write" and "edit" categories collapse to a single "file edits"
|
|
448
|
+
* class, exactly as the runner's `toolApprovalCategory` collapses FILE_WRITE and
|
|
449
|
+
* FILE_EDIT to "write". The label names that class so the button never implies a
|
|
450
|
+
* broader effect than the lease actually has. The generic fallback only applies
|
|
451
|
+
* to a tool with no leasable class, which is not normally gated for approval.
|
|
452
|
+
*/
|
|
453
|
+
function buildApproveAllLabel(
|
|
454
|
+
category: ToolCategory,
|
|
455
|
+
mcpServerSlug: string,
|
|
456
|
+
): string {
|
|
457
|
+
if (mcpServerSlug) {
|
|
458
|
+
return `Approve all ${mcpServerSlug} tools`;
|
|
459
|
+
}
|
|
460
|
+
switch (category) {
|
|
461
|
+
case "shell":
|
|
462
|
+
return "Approve all shell commands";
|
|
463
|
+
case "delete":
|
|
464
|
+
return "Approve all file deletions";
|
|
465
|
+
case "write":
|
|
466
|
+
case "edit":
|
|
467
|
+
return "Approve all file edits";
|
|
468
|
+
default:
|
|
469
|
+
return "Approve all of this kind";
|
|
470
|
+
}
|
|
471
|
+
}
|
|
293
472
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
setElapsed(Math.max(0, Date.now() - startMs));
|
|
300
|
-
const id = setInterval(() => {
|
|
301
|
-
setElapsed(Math.max(0, Date.now() - startMs));
|
|
302
|
-
}, 1000);
|
|
303
|
-
return () => clearInterval(id);
|
|
304
|
-
}, [startMs]);
|
|
473
|
+
// ---------------------------------------------------------------------------
|
|
474
|
+
// Internal sub-components
|
|
475
|
+
// ---------------------------------------------------------------------------
|
|
305
476
|
|
|
477
|
+
function WaitingDuration({ requestedAt }: { requestedAt: string }) {
|
|
478
|
+
const elapsed = useElapsedSince(requestedAt);
|
|
306
479
|
if (elapsed === null) return null;
|
|
307
480
|
|
|
308
481
|
return (
|
|
@@ -312,24 +485,6 @@ function WaitingDuration({ requestedAt }: { requestedAt: string }) {
|
|
|
312
485
|
);
|
|
313
486
|
}
|
|
314
487
|
|
|
315
|
-
function formatElapsed(ms: number): string {
|
|
316
|
-
if (ms < 1000) return "just now";
|
|
317
|
-
const seconds = Math.floor(ms / 1000);
|
|
318
|
-
if (seconds < 60) return `${seconds}s`;
|
|
319
|
-
const minutes = Math.floor(seconds / 60);
|
|
320
|
-
const remainingSeconds = seconds % 60;
|
|
321
|
-
if (minutes < 60) {
|
|
322
|
-
return remainingSeconds > 0
|
|
323
|
-
? `${minutes}m ${remainingSeconds}s`
|
|
324
|
-
: `${minutes}m`;
|
|
325
|
-
}
|
|
326
|
-
const hours = Math.floor(minutes / 60);
|
|
327
|
-
const remainingMinutes = minutes % 60;
|
|
328
|
-
return remainingMinutes > 0
|
|
329
|
-
? `${hours}h ${remainingMinutes}m`
|
|
330
|
-
: `${hours}h`;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
488
|
// ---------------------------------------------------------------------------
|
|
334
489
|
// Inline SVG icons
|
|
335
490
|
// ---------------------------------------------------------------------------
|
|
@@ -351,20 +506,3 @@ function ClockIcon() {
|
|
|
351
506
|
</svg>
|
|
352
507
|
);
|
|
353
508
|
}
|
|
354
|
-
|
|
355
|
-
function SpinnerIcon() {
|
|
356
|
-
return (
|
|
357
|
-
<svg
|
|
358
|
-
width="10"
|
|
359
|
-
height="10"
|
|
360
|
-
viewBox="0 0 12 12"
|
|
361
|
-
fill="none"
|
|
362
|
-
stroke="currentColor"
|
|
363
|
-
strokeWidth="1.5"
|
|
364
|
-
className="animate-spin"
|
|
365
|
-
aria-hidden="true"
|
|
366
|
-
>
|
|
367
|
-
<path d="M6 1.5A4.5 4.5 0 1 1 1.5 6" strokeLinecap="round" />
|
|
368
|
-
</svg>
|
|
369
|
-
);
|
|
370
|
-
}
|