@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
|
@@ -23,6 +23,7 @@ const mockResume = vi.fn();
|
|
|
23
23
|
const mockRecover = vi.fn();
|
|
24
24
|
const mockSubmitApproval = vi.fn();
|
|
25
25
|
const mockSubmitWorkflowTaskApproval = vi.fn();
|
|
26
|
+
const mockSubmitFileDecision = vi.fn();
|
|
26
27
|
|
|
27
28
|
function makeMockClient(): Stigmer {
|
|
28
29
|
return {
|
|
@@ -34,6 +35,7 @@ function makeMockClient(): Stigmer {
|
|
|
34
35
|
recover: mockRecover,
|
|
35
36
|
submitApproval: mockSubmitApproval,
|
|
36
37
|
submitWorkflowTaskApproval: mockSubmitWorkflowTaskApproval,
|
|
38
|
+
submitFileDecision: mockSubmitFileDecision,
|
|
37
39
|
},
|
|
38
40
|
} as unknown as Stigmer;
|
|
39
41
|
}
|
|
@@ -278,3 +280,277 @@ describe("onSuccess callback", () => {
|
|
|
278
280
|
}
|
|
279
281
|
});
|
|
280
282
|
});
|
|
283
|
+
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
// Per-gate approval state (keyed; separate from the lifecycle scalar)
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
|
|
288
|
+
describe("per-gate approval state", () => {
|
|
289
|
+
it("tracks an in-flight tool approval keyed by toolCallId, not the lifecycle scalar", async () => {
|
|
290
|
+
let resolve!: (v: unknown) => void;
|
|
291
|
+
mockSubmitApproval.mockReturnValueOnce(new Promise((r) => (resolve = r)));
|
|
292
|
+
|
|
293
|
+
const { result } = renderHook(
|
|
294
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
295
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
let pending: Promise<unknown>;
|
|
299
|
+
act(() => {
|
|
300
|
+
pending = result.current.submitApproval("tc-1", 1 as any);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
expect(result.current.approvalSubmittingToolCallIds.has("tc-1")).toBe(true);
|
|
304
|
+
// The lifecycle scalar is untouched by an approval.
|
|
305
|
+
expect(result.current.isSubmitting).toBe(false);
|
|
306
|
+
|
|
307
|
+
await act(async () => {
|
|
308
|
+
resolve(makeExecution());
|
|
309
|
+
await pending;
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
expect(result.current.approvalSubmittingToolCallIds.size).toBe(0);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("records a failed tool approval in the keyed map, not the lifecycle scalar, and resolves null", async () => {
|
|
316
|
+
mockSubmitApproval.mockRejectedValueOnce(new Error("gate already resolved"));
|
|
317
|
+
|
|
318
|
+
const { result } = renderHook(
|
|
319
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
320
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
let returned: any;
|
|
324
|
+
await act(async () => {
|
|
325
|
+
returned = await result.current.submitApproval("tc-1", 1 as any);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
expect(returned).toBeNull();
|
|
329
|
+
expect(result.current.approvalErrorsByToolCallId.get("tc-1")?.message).toBe(
|
|
330
|
+
"gate already resolved",
|
|
331
|
+
);
|
|
332
|
+
// The lifecycle scalar (header banner) must NOT pick up an approval failure.
|
|
333
|
+
expect(result.current.error).toBeNull();
|
|
334
|
+
expect(result.current.isSubmitting).toBe(false);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it("records a failed task approval keyed by taskName, not the lifecycle scalar", async () => {
|
|
338
|
+
mockSubmitWorkflowTaskApproval.mockRejectedValueOnce(new Error("signal failed"));
|
|
339
|
+
|
|
340
|
+
const { result } = renderHook(
|
|
341
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
342
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
let returned: any;
|
|
346
|
+
await act(async () => {
|
|
347
|
+
returned = await result.current.submitTaskApproval("review_task", "approved");
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
expect(returned).toBeNull();
|
|
351
|
+
expect(result.current.taskApprovalErrorsByTaskName.get("review_task")?.message).toBe(
|
|
352
|
+
"signal failed",
|
|
353
|
+
);
|
|
354
|
+
expect(result.current.error).toBeNull();
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it("keeps tool and task approval errors in separate keyed spaces", async () => {
|
|
358
|
+
mockSubmitApproval.mockRejectedValueOnce(new Error("tool fail"));
|
|
359
|
+
mockSubmitWorkflowTaskApproval.mockRejectedValueOnce(new Error("task fail"));
|
|
360
|
+
|
|
361
|
+
const { result } = renderHook(
|
|
362
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
363
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
await act(async () => {
|
|
367
|
+
await result.current.submitApproval("tc-1", 1 as any);
|
|
368
|
+
});
|
|
369
|
+
await act(async () => {
|
|
370
|
+
await result.current.submitTaskApproval("review_task", "approved");
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
expect(result.current.approvalErrorsByToolCallId.get("tc-1")?.message).toBe("tool fail");
|
|
374
|
+
expect(result.current.taskApprovalErrorsByTaskName.get("review_task")?.message).toBe("task fail");
|
|
375
|
+
// Neither keyed failure crosses into the other space or the scalar.
|
|
376
|
+
expect(result.current.approvalErrorsByToolCallId.has("review_task")).toBe(false);
|
|
377
|
+
expect(result.current.taskApprovalErrorsByTaskName.has("tc-1")).toBe(false);
|
|
378
|
+
expect(result.current.error).toBeNull();
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it("keeps a failed lifecycle action in the scalar, never in the keyed approval maps", async () => {
|
|
382
|
+
mockCancel.mockRejectedValueOnce(new Error("temporal down"));
|
|
383
|
+
|
|
384
|
+
const { result } = renderHook(
|
|
385
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
386
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
await act(async () => {
|
|
390
|
+
await result.current.cancel();
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
expect(result.current.error?.message).toBe("temporal down");
|
|
394
|
+
expect(result.current.approvalErrorsByToolCallId.size).toBe(0);
|
|
395
|
+
expect(result.current.taskApprovalErrorsByTaskName.size).toBe(0);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it("null executionId returns null without recording keyed state", async () => {
|
|
399
|
+
const { result } = renderHook(
|
|
400
|
+
() => useWorkflowExecutionActions(null),
|
|
401
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
let returned: any;
|
|
405
|
+
await act(async () => {
|
|
406
|
+
returned = await result.current.submitApproval("tc-1", 1 as any);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
expect(returned).toBeNull();
|
|
410
|
+
expect(mockSubmitApproval).not.toHaveBeenCalled();
|
|
411
|
+
expect(result.current.approvalSubmittingToolCallIds.size).toBe(0);
|
|
412
|
+
expect(result.current.approvalErrorsByToolCallId.size).toBe(0);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it("keeps a stable return reference across renders when nothing changes", () => {
|
|
416
|
+
const { result, rerender } = renderHook(
|
|
417
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
418
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
const first = result.current;
|
|
422
|
+
rerender();
|
|
423
|
+
expect(result.current).toBe(first);
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
// ---------------------------------------------------------------------------
|
|
428
|
+
// Per-gate file-decision state (forwarding + keyed like FileReviewCard)
|
|
429
|
+
// ---------------------------------------------------------------------------
|
|
430
|
+
|
|
431
|
+
describe("submitFileDecision (workflow-parent file review)", () => {
|
|
432
|
+
it("forwards a CHANGE_SET decision with explicit child routing", async () => {
|
|
433
|
+
mockSubmitFileDecision.mockResolvedValueOnce(makeExecution());
|
|
434
|
+
|
|
435
|
+
const { result } = renderHook(
|
|
436
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
437
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
await act(async () => {
|
|
441
|
+
await result.current.submitFileDecision("aex-child", "fcs-1", 1 /* APPROVE */ as any, {
|
|
442
|
+
expectedDigest: "sha256:agg",
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
expect(mockSubmitFileDecision).toHaveBeenCalledTimes(1);
|
|
447
|
+
const input = mockSubmitFileDecision.mock.calls[0][0];
|
|
448
|
+
expect(input.executionId).toBe("wex-001");
|
|
449
|
+
expect(input.childAgentExecutionId).toBe("aex-child");
|
|
450
|
+
expect(input.changeSetId).toBe("fcs-1");
|
|
451
|
+
expect(input.scope).toBe(1 /* CHANGE_SET */);
|
|
452
|
+
expect(input.fileChangeId).toBe("");
|
|
453
|
+
expect(input.action).toBe(1 /* APPROVE */);
|
|
454
|
+
expect(input.expectedDigest).toBe("sha256:agg");
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it("derives FILE scope when a fileChangeId is supplied", async () => {
|
|
458
|
+
mockSubmitFileDecision.mockResolvedValueOnce(makeExecution());
|
|
459
|
+
|
|
460
|
+
const { result } = renderHook(
|
|
461
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
462
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
await act(async () => {
|
|
466
|
+
await result.current.submitFileDecision("aex-child", "fcs-1", 2 /* REJECT */ as any, {
|
|
467
|
+
fileChangeId: "fc-9",
|
|
468
|
+
expectedDigest: "sha256:file",
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
const input = mockSubmitFileDecision.mock.calls[0][0];
|
|
473
|
+
expect(input.scope).toBe(2 /* FILE */);
|
|
474
|
+
expect(input.fileChangeId).toBe("fc-9");
|
|
475
|
+
expect(input.action).toBe(2 /* REJECT */);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it("tracks in-flight state keyed like FileReviewCard (changeSetId, then changeSetId:fileChangeId)", async () => {
|
|
479
|
+
let resolve!: (v: unknown) => void;
|
|
480
|
+
mockSubmitFileDecision.mockReturnValueOnce(new Promise((r) => (resolve = r)));
|
|
481
|
+
|
|
482
|
+
const { result } = renderHook(
|
|
483
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
484
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
let pending: Promise<unknown>;
|
|
488
|
+
act(() => {
|
|
489
|
+
pending = result.current.submitFileDecision("aex-child", "fcs-1", 1 as any);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
expect(result.current.fileDecisionSubmittingKeys.has("fcs-1")).toBe(true);
|
|
493
|
+
expect(result.current.isSubmitting).toBe(false); // lifecycle scalar untouched
|
|
494
|
+
|
|
495
|
+
await act(async () => {
|
|
496
|
+
resolve(makeExecution());
|
|
497
|
+
await pending;
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
expect(result.current.fileDecisionSubmittingKeys.size).toBe(0);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
it("records a failed decision in the keyed map (not the scalar) and resolves null", async () => {
|
|
504
|
+
mockSubmitFileDecision.mockRejectedValueOnce(new Error("expected_digest mismatch"));
|
|
505
|
+
|
|
506
|
+
const { result } = renderHook(
|
|
507
|
+
() => useWorkflowExecutionActions("wex-001"),
|
|
508
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
let returned: any;
|
|
512
|
+
await act(async () => {
|
|
513
|
+
returned = await result.current.submitFileDecision("aex-child", "fcs-1", 1 as any, {
|
|
514
|
+
fileChangeId: "fc-9",
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
expect(returned).toBeNull();
|
|
519
|
+
expect(result.current.fileDecisionErrorsByKey.get("fcs-1:fc-9")?.message).toBe(
|
|
520
|
+
"expected_digest mismatch",
|
|
521
|
+
);
|
|
522
|
+
expect(result.current.error).toBeNull(); // header banner unaffected
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
it("does not fire onSuccess", async () => {
|
|
526
|
+
mockSubmitFileDecision.mockResolvedValueOnce(makeExecution());
|
|
527
|
+
const onSuccess = vi.fn();
|
|
528
|
+
|
|
529
|
+
const { result } = renderHook(
|
|
530
|
+
() => useWorkflowExecutionActions("wex-001", { onSuccess }),
|
|
531
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
532
|
+
);
|
|
533
|
+
|
|
534
|
+
await act(async () => {
|
|
535
|
+
await result.current.submitFileDecision("aex-child", "fcs-1", 1 as any);
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
expect(onSuccess).not.toHaveBeenCalled();
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
it("null executionId returns null without calling the SDK", async () => {
|
|
542
|
+
const { result } = renderHook(
|
|
543
|
+
() => useWorkflowExecutionActions(null),
|
|
544
|
+
{ wrapper: createWrapper(makeMockClient()) },
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
let returned: any;
|
|
548
|
+
await act(async () => {
|
|
549
|
+
returned = await result.current.submitFileDecision("aex-child", "fcs-1", 1 as any);
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
expect(returned).toBeNull();
|
|
553
|
+
expect(mockSubmitFileDecision).not.toHaveBeenCalled();
|
|
554
|
+
expect(result.current.fileDecisionSubmittingKeys.size).toBe(0);
|
|
555
|
+
});
|
|
556
|
+
});
|
|
@@ -35,8 +35,17 @@ export interface ExecutionInspectorProps {
|
|
|
35
35
|
readonly pendingApprovals?: readonly WorkflowPendingApproval[];
|
|
36
36
|
/** Callback to submit an agent tool approval decision. */
|
|
37
37
|
readonly onSubmitApproval?: (toolCallId: string, action: ApprovalAction, comment?: string) => Promise<unknown>;
|
|
38
|
-
/**
|
|
39
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Tool-call ids whose agent-tool approval is in flight, keyed by `toolCallId`
|
|
40
|
+
* so deciding one gate never spins another. Supply
|
|
41
|
+
* {@link useWorkflowExecutionActions}'s `approvalSubmittingToolCallIds`.
|
|
42
|
+
*/
|
|
43
|
+
readonly approvalSubmittingToolCallIds?: ReadonlySet<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Per-gate agent-tool approval failures, keyed by `toolCallId`. Supply
|
|
46
|
+
* {@link useWorkflowExecutionActions}'s `approvalErrorsByToolCallId`.
|
|
47
|
+
*/
|
|
48
|
+
readonly approvalErrorsByToolCallId?: ReadonlyMap<string, Error>;
|
|
40
49
|
/** Callback to submit a workflow-level human_input task decision. */
|
|
41
50
|
readonly onSubmitTaskApproval?: (
|
|
42
51
|
taskName: string,
|
|
@@ -44,8 +53,16 @@ export interface ExecutionInspectorProps {
|
|
|
44
53
|
formData?: Record<string, unknown>,
|
|
45
54
|
comment?: string,
|
|
46
55
|
) => Promise<unknown>;
|
|
47
|
-
/**
|
|
48
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Task names whose human_input approval is in flight, keyed by `taskName`.
|
|
58
|
+
* Supply {@link useWorkflowExecutionActions}'s `taskApprovalSubmittingTaskNames`.
|
|
59
|
+
*/
|
|
60
|
+
readonly taskApprovalSubmittingTaskNames?: ReadonlySet<string>;
|
|
61
|
+
/**
|
|
62
|
+
* Per-gate human_input approval failures, keyed by `taskName`. Supply
|
|
63
|
+
* {@link useWorkflowExecutionActions}'s `taskApprovalErrorsByTaskName`.
|
|
64
|
+
*/
|
|
65
|
+
readonly taskApprovalErrorsByTaskName?: ReadonlyMap<string, Error>;
|
|
49
66
|
/** Additional CSS class names. */
|
|
50
67
|
readonly className?: string;
|
|
51
68
|
}
|
|
@@ -89,9 +106,11 @@ export const ExecutionInspector = memo(function ExecutionInspector({
|
|
|
89
106
|
onNavigateToAgentExecution,
|
|
90
107
|
pendingApprovals,
|
|
91
108
|
onSubmitApproval,
|
|
92
|
-
|
|
109
|
+
approvalSubmittingToolCallIds,
|
|
110
|
+
approvalErrorsByToolCallId,
|
|
93
111
|
onSubmitTaskApproval,
|
|
94
|
-
|
|
112
|
+
taskApprovalSubmittingTaskNames,
|
|
113
|
+
taskApprovalErrorsByTaskName,
|
|
95
114
|
className,
|
|
96
115
|
}: ExecutionInspectorProps) {
|
|
97
116
|
const { detail } = useExecutionTaskDetail({
|
|
@@ -212,17 +231,21 @@ export const ExecutionInspector = memo(function ExecutionInspector({
|
|
|
212
231
|
)}
|
|
213
232
|
{effectiveTab === "approval" && taskApprovals.length > 0 && onSubmitApproval && (
|
|
214
233
|
<div className="space-y-2">
|
|
215
|
-
{taskApprovals.map((pa) =>
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
234
|
+
{taskApprovals.map((pa) => {
|
|
235
|
+
const toolCallId = pa.approval?.toolCallId ?? "";
|
|
236
|
+
return (
|
|
237
|
+
<WorkflowExecutionApprovalCard
|
|
238
|
+
key={toolCallId || pa.childAgentExecutionId}
|
|
239
|
+
prompt={pa.approval?.message || `Tool "${pa.approval?.toolName}" requires approval`}
|
|
240
|
+
toolCallId={toolCallId}
|
|
241
|
+
approvers={[]}
|
|
242
|
+
timeoutSeconds={0}
|
|
243
|
+
onSubmitApproval={onSubmitApproval}
|
|
244
|
+
isSubmitting={approvalSubmittingToolCallIds?.has(toolCallId) ?? false}
|
|
245
|
+
error={approvalErrorsByToolCallId?.get(toolCallId) ?? null}
|
|
246
|
+
/>
|
|
247
|
+
);
|
|
248
|
+
})}
|
|
226
249
|
</div>
|
|
227
250
|
)}
|
|
228
251
|
{effectiveTab === "approval" && detail.approval && (
|
|
@@ -234,7 +257,8 @@ export const ExecutionInspector = memo(function ExecutionInspector({
|
|
|
234
257
|
outcomes={detail.approval.outcomes}
|
|
235
258
|
formSchema={detail.approval.formSchema ?? undefined}
|
|
236
259
|
onSubmit={onSubmitTaskApproval}
|
|
237
|
-
isSubmitting={
|
|
260
|
+
isSubmitting={taskApprovalSubmittingTaskNames?.has(detail.taskName) ?? false}
|
|
261
|
+
error={taskApprovalErrorsByTaskName?.get(detail.taskName) ?? null}
|
|
238
262
|
/>
|
|
239
263
|
) : (
|
|
240
264
|
// Gate resolved — present the captured decision read-only so a
|
package/src/workflow/index.ts
CHANGED
|
@@ -208,6 +208,11 @@ export {
|
|
|
208
208
|
WorkflowExecutionApprovalCard,
|
|
209
209
|
type WorkflowExecutionApprovalCardProps,
|
|
210
210
|
} from "./WorkflowExecutionApprovalCard";
|
|
211
|
+
export {
|
|
212
|
+
WorkflowFileReviewList,
|
|
213
|
+
type WorkflowFileReviewListProps,
|
|
214
|
+
type WorkflowFileDecisionSubmit,
|
|
215
|
+
} from "./WorkflowFileReviewList";
|
|
211
216
|
|
|
212
217
|
export {
|
|
213
218
|
WorkflowTaskApprovalCard,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useRef, useState } from "react";
|
|
3
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
4
4
|
import type { WorkflowExecution } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/api_pb";
|
|
5
|
-
import type { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
5
|
+
import type { ApprovalAction, FileDecisionAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
6
|
+
import { FileDecisionScope } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
6
7
|
import { create, type JsonObject } from "@bufbuild/protobuf";
|
|
7
8
|
import {
|
|
8
9
|
CancelWorkflowExecutionInputSchema,
|
|
@@ -12,9 +13,12 @@ import {
|
|
|
12
13
|
RecoverWorkflowExecutionInputSchema,
|
|
13
14
|
SubmitWorkflowApprovalInputSchema,
|
|
14
15
|
SubmitWorkflowTaskApprovalInputSchema,
|
|
16
|
+
SubmitWorkflowFileDecisionInputSchema,
|
|
15
17
|
} from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/io_pb";
|
|
16
18
|
import { useStigmer } from "../hooks";
|
|
17
19
|
import { toError } from "../internal/toError";
|
|
20
|
+
import { useKeyedSubmission } from "../internal/useKeyedSubmission";
|
|
21
|
+
import { fileDecisionKey, type FileDecisionOptions } from "../execution/useFileReview";
|
|
18
22
|
|
|
19
23
|
/** Options for {@link useWorkflowExecutionActions}. */
|
|
20
24
|
export interface UseWorkflowExecutionActionsOptions {
|
|
@@ -71,12 +75,74 @@ export interface UseWorkflowExecutionActionsReturn {
|
|
|
71
75
|
formData?: Record<string, unknown>,
|
|
72
76
|
comment?: string,
|
|
73
77
|
) => Promise<WorkflowExecution | null>;
|
|
74
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Submit a keep/discard decision for a child agent's file review, surfaced on
|
|
80
|
+
* this workflow via `status.pending_file_reviews`. The file-review sibling of
|
|
81
|
+
* {@link submitApproval}: the server forwards it to the child's
|
|
82
|
+
* `AgentExecution.submitFileDecision`.
|
|
83
|
+
*
|
|
84
|
+
* `childAgentExecutionId` comes from the surfaced
|
|
85
|
+
* `WorkflowPendingFileReview` reference. `options` carries the same
|
|
86
|
+
* per-decision detail as {@link FileReviewCard}'s `onSubmit` (scope,
|
|
87
|
+
* `fileChangeId`, `expectedDigest`, `reason`, `acknowledgeUnreviewable`).
|
|
88
|
+
*/
|
|
89
|
+
readonly submitFileDecision: (
|
|
90
|
+
childAgentExecutionId: string,
|
|
91
|
+
changeSetId: string,
|
|
92
|
+
action: FileDecisionAction,
|
|
93
|
+
options?: FileDecisionOptions,
|
|
94
|
+
) => Promise<WorkflowExecution | null>;
|
|
95
|
+
/**
|
|
96
|
+
* `true` while a **lifecycle** action (cancel/terminate/pause/resume/recover)
|
|
97
|
+
* is in flight. Approvals are excluded — they are per-gate, so read their
|
|
98
|
+
* in-flight state from {@link approvalSubmittingToolCallIds} /
|
|
99
|
+
* {@link taskApprovalSubmittingTaskNames} instead.
|
|
100
|
+
*/
|
|
75
101
|
readonly isSubmitting: boolean;
|
|
76
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* Error from the last failed **lifecycle** action, or `null`. Approval
|
|
104
|
+
* failures are per-gate and live in {@link approvalErrorsByToolCallId} /
|
|
105
|
+
* {@link taskApprovalErrorsByTaskName} so each surfaces beside the gate that
|
|
106
|
+
* failed — never in this shared scalar (which backs the header banner).
|
|
107
|
+
*/
|
|
77
108
|
readonly error: Error | null;
|
|
78
|
-
/** Reset
|
|
109
|
+
/** Reset the lifecycle {@link error} to `null`. */
|
|
79
110
|
readonly clearError: () => void;
|
|
111
|
+
/**
|
|
112
|
+
* Tool-call ids whose agent-tool approval is currently being submitted, keyed
|
|
113
|
+
* exactly like {@link approvalErrorsByToolCallId}. A workflow can hold many
|
|
114
|
+
* concurrent gates, so deciding one must not spin or disable the others.
|
|
115
|
+
*/
|
|
116
|
+
readonly approvalSubmittingToolCallIds: ReadonlySet<string>;
|
|
117
|
+
/**
|
|
118
|
+
* Per-gate agent-tool approval failures, keyed by `toolCallId`. Consumed by
|
|
119
|
+
* {@link WorkflowExecutionApprovalCard} to surface the failure in-card,
|
|
120
|
+
* beside the gate that failed. Cleared for a gate when it is retried.
|
|
121
|
+
*/
|
|
122
|
+
readonly approvalErrorsByToolCallId: ReadonlyMap<string, Error>;
|
|
123
|
+
/**
|
|
124
|
+
* Task names whose human_input task approval is currently being submitted,
|
|
125
|
+
* keyed exactly like {@link taskApprovalErrorsByTaskName}.
|
|
126
|
+
*/
|
|
127
|
+
readonly taskApprovalSubmittingTaskNames: ReadonlySet<string>;
|
|
128
|
+
/**
|
|
129
|
+
* Per-gate human_input task approval failures, keyed by `taskName`. Consumed
|
|
130
|
+
* by `WorkflowTaskApprovalCard` to surface the failure in-card, beside
|
|
131
|
+
* the gate that failed. Cleared for a gate when it is retried.
|
|
132
|
+
*/
|
|
133
|
+
readonly taskApprovalErrorsByTaskName: ReadonlyMap<string, Error>;
|
|
134
|
+
/**
|
|
135
|
+
* Decision keys currently being submitted for file reviews, keyed exactly like
|
|
136
|
+
* {@link FileReviewCard}'s `submittingDecisionKeys` (via {@link fileDecisionKey}
|
|
137
|
+
* — the change set id for a whole-set decision, `changeSetId:fileChangeId` for a
|
|
138
|
+
* per-file one). Pass straight through to each surfaced card.
|
|
139
|
+
*/
|
|
140
|
+
readonly fileDecisionSubmittingKeys: ReadonlySet<string>;
|
|
141
|
+
/**
|
|
142
|
+
* Per-decision file-review failures, keyed like {@link fileDecisionSubmittingKeys}.
|
|
143
|
+
* Pass straight through to {@link FileReviewCard}'s `decisionErrors`.
|
|
144
|
+
*/
|
|
145
|
+
readonly fileDecisionErrorsByKey: ReadonlyMap<string, Error>;
|
|
80
146
|
}
|
|
81
147
|
|
|
82
148
|
/**
|
|
@@ -107,6 +173,14 @@ export function useWorkflowExecutionActions(
|
|
|
107
173
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
108
174
|
const [error, setError] = useState<Error | null>(null);
|
|
109
175
|
|
|
176
|
+
// Approvals are per-gate (a workflow can hold many at once), so each kind gets
|
|
177
|
+
// its own keyed in-flight + error state — keyed by tool-call id for agent-tool
|
|
178
|
+
// approvals and by task name for human_input task approvals. The lifecycle
|
|
179
|
+
// actions below stay on the shared scalar (they are header singletons).
|
|
180
|
+
const approvals = useKeyedSubmission<WorkflowExecution>();
|
|
181
|
+
const taskApprovals = useKeyedSubmission<WorkflowExecution>();
|
|
182
|
+
const fileDecisions = useKeyedSubmission<WorkflowExecution>();
|
|
183
|
+
|
|
110
184
|
const executionIdRef = useRef(executionId);
|
|
111
185
|
executionIdRef.current = executionId;
|
|
112
186
|
const stigmerRef = useRef(stigmer);
|
|
@@ -202,10 +276,15 @@ export function useWorkflowExecutionActions(
|
|
|
202
276
|
[wrap],
|
|
203
277
|
);
|
|
204
278
|
|
|
279
|
+
// Approvals do NOT go through `wrap`: their in-flight + error state is keyed
|
|
280
|
+
// (per gate), and the keyed primitive re-throws after recording, so we swallow
|
|
281
|
+
// to `null` here to keep the `WorkflowExecution | null` contract. They never
|
|
282
|
+
// fire `onSuccess` — their effects arrive via the event stream.
|
|
205
283
|
const submitApproval = useCallback(
|
|
206
|
-
(toolCallId: string, action: ApprovalAction, comment?: string) =>
|
|
207
|
-
|
|
208
|
-
|
|
284
|
+
(toolCallId: string, action: ApprovalAction, comment?: string) => {
|
|
285
|
+
if (!executionIdRef.current) return Promise.resolve(null);
|
|
286
|
+
return approvals
|
|
287
|
+
.run(toolCallId, () =>
|
|
209
288
|
stigmerRef.current.workflowExecution.submitApproval(
|
|
210
289
|
create(SubmitWorkflowApprovalInputSchema, {
|
|
211
290
|
executionId: executionIdRef.current!,
|
|
@@ -214,15 +293,17 @@ export function useWorkflowExecutionActions(
|
|
|
214
293
|
comment: comment ?? "",
|
|
215
294
|
}),
|
|
216
295
|
),
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
296
|
+
)
|
|
297
|
+
.catch(() => null);
|
|
298
|
+
},
|
|
299
|
+
[approvals.run],
|
|
220
300
|
);
|
|
221
301
|
|
|
222
302
|
const submitTaskApproval = useCallback(
|
|
223
|
-
(taskName: string, outcome: string, formData?: Record<string, unknown>, comment?: string) =>
|
|
224
|
-
|
|
225
|
-
|
|
303
|
+
(taskName: string, outcome: string, formData?: Record<string, unknown>, comment?: string) => {
|
|
304
|
+
if (!executionIdRef.current) return Promise.resolve(null);
|
|
305
|
+
return taskApprovals
|
|
306
|
+
.run(taskName, () =>
|
|
226
307
|
stigmerRef.current.workflowExecution.submitWorkflowTaskApproval(
|
|
227
308
|
create(SubmitWorkflowTaskApprovalInputSchema, {
|
|
228
309
|
executionId: executionIdRef.current!,
|
|
@@ -233,21 +314,88 @@ export function useWorkflowExecutionActions(
|
|
|
233
314
|
comment: comment ?? "",
|
|
234
315
|
}),
|
|
235
316
|
),
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
317
|
+
)
|
|
318
|
+
.catch(() => null);
|
|
319
|
+
},
|
|
320
|
+
[taskApprovals.run],
|
|
239
321
|
);
|
|
240
322
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
323
|
+
// File decisions are per-target (a workflow can surface many change sets across
|
|
324
|
+
// parallel children), so they use the keyed primitive keyed exactly like
|
|
325
|
+
// FileReviewCard expects (fileDecisionKey). Never fires onSuccess — the effect
|
|
326
|
+
// arrives via the execution stream.
|
|
327
|
+
const submitFileDecision = useCallback(
|
|
328
|
+
(
|
|
329
|
+
childAgentExecutionId: string,
|
|
330
|
+
changeSetId: string,
|
|
331
|
+
action: FileDecisionAction,
|
|
332
|
+
options?: FileDecisionOptions,
|
|
333
|
+
) => {
|
|
334
|
+
if (!executionIdRef.current) return Promise.resolve(null);
|
|
335
|
+
const fileChangeId = options?.fileChangeId ?? "";
|
|
336
|
+
const scope =
|
|
337
|
+
options?.scope ??
|
|
338
|
+
(fileChangeId ? FileDecisionScope.FILE : FileDecisionScope.CHANGE_SET);
|
|
339
|
+
const key = fileDecisionKey(changeSetId, fileChangeId || undefined);
|
|
340
|
+
return fileDecisions
|
|
341
|
+
.run(key, () =>
|
|
342
|
+
stigmerRef.current.workflowExecution.submitFileDecision(
|
|
343
|
+
create(SubmitWorkflowFileDecisionInputSchema, {
|
|
344
|
+
executionId: executionIdRef.current!,
|
|
345
|
+
childAgentExecutionId,
|
|
346
|
+
changeSetId,
|
|
347
|
+
scope,
|
|
348
|
+
fileChangeId,
|
|
349
|
+
action,
|
|
350
|
+
expectedDigest: options?.expectedDigest ?? "",
|
|
351
|
+
reason: options?.reason ?? "",
|
|
352
|
+
acknowledgeUnreviewable: options?.acknowledgeUnreviewable ?? false,
|
|
353
|
+
}),
|
|
354
|
+
),
|
|
355
|
+
)
|
|
356
|
+
.catch(() => null);
|
|
357
|
+
},
|
|
358
|
+
[fileDecisions.run],
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
return useMemo(
|
|
362
|
+
() => ({
|
|
363
|
+
cancel,
|
|
364
|
+
terminate,
|
|
365
|
+
pause,
|
|
366
|
+
resume,
|
|
367
|
+
recover,
|
|
368
|
+
submitApproval,
|
|
369
|
+
submitTaskApproval,
|
|
370
|
+
submitFileDecision,
|
|
371
|
+
isSubmitting,
|
|
372
|
+
error,
|
|
373
|
+
clearError,
|
|
374
|
+
approvalSubmittingToolCallIds: approvals.submittingKeys,
|
|
375
|
+
approvalErrorsByToolCallId: approvals.errorsByKey,
|
|
376
|
+
taskApprovalSubmittingTaskNames: taskApprovals.submittingKeys,
|
|
377
|
+
taskApprovalErrorsByTaskName: taskApprovals.errorsByKey,
|
|
378
|
+
fileDecisionSubmittingKeys: fileDecisions.submittingKeys,
|
|
379
|
+
fileDecisionErrorsByKey: fileDecisions.errorsByKey,
|
|
380
|
+
}),
|
|
381
|
+
[
|
|
382
|
+
cancel,
|
|
383
|
+
terminate,
|
|
384
|
+
pause,
|
|
385
|
+
resume,
|
|
386
|
+
recover,
|
|
387
|
+
submitApproval,
|
|
388
|
+
submitTaskApproval,
|
|
389
|
+
submitFileDecision,
|
|
390
|
+
isSubmitting,
|
|
391
|
+
error,
|
|
392
|
+
clearError,
|
|
393
|
+
approvals.submittingKeys,
|
|
394
|
+
approvals.errorsByKey,
|
|
395
|
+
taskApprovals.submittingKeys,
|
|
396
|
+
taskApprovals.errorsByKey,
|
|
397
|
+
fileDecisions.submittingKeys,
|
|
398
|
+
fileDecisions.errorsByKey,
|
|
399
|
+
],
|
|
400
|
+
);
|
|
253
401
|
}
|