@stigmer/react 3.0.9-dev.20260615153829 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/execution/ApprovalCard.d.ts +47 -3
- package/execution/ApprovalCard.d.ts.map +1 -1
- package/execution/ApprovalCard.js +138 -70
- package/execution/ApprovalCard.js.map +1 -1
- package/execution/ApprovalContext.d.ts +72 -0
- package/execution/ApprovalContext.d.ts.map +1 -0
- package/execution/ApprovalContext.js +41 -0
- package/execution/ApprovalContext.js.map +1 -0
- package/execution/ArtifactCard.d.ts.map +1 -1
- package/execution/ArtifactCard.js +3 -1
- package/execution/ArtifactCard.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts.map +1 -1
- package/execution/ArtifactPreviewModal.js +5 -3
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/EmptyChangeNotice.d.ts +38 -0
- package/execution/EmptyChangeNotice.d.ts.map +1 -0
- package/execution/EmptyChangeNotice.js +27 -0
- package/execution/EmptyChangeNotice.js.map +1 -0
- package/execution/FileChangesView.d.ts +81 -0
- package/execution/FileChangesView.d.ts.map +1 -0
- package/execution/FileChangesView.js +164 -0
- package/execution/FileChangesView.js.map +1 -0
- package/execution/FilePathLink.d.ts +24 -4
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +31 -9
- package/execution/FilePathLink.js.map +1 -1
- package/execution/FileReviewCard.d.ts +111 -0
- package/execution/FileReviewCard.d.ts.map +1 -0
- package/execution/FileReviewCard.js +558 -0
- package/execution/FileReviewCard.js.map +1 -0
- package/execution/FileReviewContext.d.ts +35 -0
- package/execution/FileReviewContext.d.ts.map +1 -0
- package/execution/FileReviewContext.js +23 -0
- package/execution/FileReviewContext.js.map +1 -0
- package/execution/FileReviewDock.d.ts +73 -0
- package/execution/FileReviewDock.d.ts.map +1 -0
- package/execution/FileReviewDock.js +65 -0
- package/execution/FileReviewDock.js.map +1 -0
- package/execution/McpToolDetail.d.ts.map +1 -1
- package/execution/McpToolDetail.js +38 -5
- package/execution/McpToolDetail.js.map +1 -1
- package/execution/MessageThread.d.ts +42 -3
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +263 -18
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +3 -1
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/PlanCompletionCard.d.ts +1 -1
- package/execution/PlanCompletionCard.js +1 -1
- package/execution/ResultView.d.ts +19 -1
- package/execution/ResultView.d.ts.map +1 -1
- package/execution/ResultView.js +141 -40
- package/execution/ResultView.js.map +1 -1
- package/execution/SubAgentSection.d.ts.map +1 -1
- package/execution/SubAgentSection.js +45 -6
- package/execution/SubAgentSection.js.map +1 -1
- package/execution/TerminalSession.d.ts +34 -0
- package/execution/TerminalSession.d.ts.map +1 -0
- package/execution/TerminalSession.js +34 -0
- package/execution/TerminalSession.js.map +1 -0
- package/execution/TodoCard.d.ts +53 -0
- package/execution/TodoCard.d.ts.map +1 -0
- package/execution/TodoCard.js +77 -0
- package/execution/TodoCard.js.map +1 -0
- package/execution/ToolArgsView.d.ts +7 -1
- package/execution/ToolArgsView.d.ts.map +1 -1
- package/execution/ToolArgsView.js +10 -9
- package/execution/ToolArgsView.js.map +1 -1
- package/execution/ToolCallDetail.d.ts +10 -1
- package/execution/ToolCallDetail.d.ts.map +1 -1
- package/execution/ToolCallDetail.js +66 -19
- package/execution/ToolCallDetail.js.map +1 -1
- package/execution/ToolCallGroup.d.ts +28 -18
- package/execution/ToolCallGroup.d.ts.map +1 -1
- package/execution/ToolCallGroup.js +39 -148
- package/execution/ToolCallGroup.js.map +1 -1
- package/execution/ToolCallItem.d.ts +36 -8
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +140 -21
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/ToolRunGroup.d.ts +48 -0
- package/execution/ToolRunGroup.d.ts.map +1 -0
- package/execution/ToolRunGroup.js +168 -0
- package/execution/ToolRunGroup.js.map +1 -0
- package/execution/approval-provenance.d.ts +2 -0
- package/execution/approval-provenance.d.ts.map +1 -0
- package/execution/approval-provenance.js +6 -0
- package/execution/approval-provenance.js.map +1 -0
- package/execution/artifact-utils.d.ts +0 -10
- package/execution/artifact-utils.d.ts.map +1 -1
- package/execution/artifact-utils.js +0 -17
- package/execution/artifact-utils.js.map +1 -1
- package/execution/execution-phases.d.ts +1 -6
- package/execution/execution-phases.d.ts.map +1 -1
- package/execution/execution-phases.js +4 -14
- package/execution/execution-phases.js.map +1 -1
- package/execution/file-path-resolver.d.ts +28 -0
- package/execution/file-path-resolver.d.ts.map +1 -1
- package/execution/file-path-resolver.js +24 -0
- package/execution/file-path-resolver.js.map +1 -1
- package/execution/file-review-status.d.ts +127 -0
- package/execution/file-review-status.d.ts.map +1 -0
- package/execution/file-review-status.js +135 -0
- package/execution/file-review-status.js.map +1 -0
- package/execution/index.d.ts +39 -5
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +23 -3
- package/execution/index.js.map +1 -1
- package/execution/segment-tool-calls.d.ts +46 -0
- package/execution/segment-tool-calls.d.ts.map +1 -0
- package/execution/segment-tool-calls.js +71 -0
- package/execution/segment-tool-calls.js.map +1 -0
- package/execution/tool-categories.d.ts +62 -1
- package/execution/tool-categories.d.ts.map +1 -1
- package/execution/tool-categories.js +96 -2
- package/execution/tool-categories.js.map +1 -1
- package/execution/tool-presenter.d.ts +38 -2
- package/execution/tool-presenter.d.ts.map +1 -1
- package/execution/tool-presenter.js +23 -1
- package/execution/tool-presenter.js.map +1 -1
- package/execution/tool-rendering-primitives.d.ts.map +1 -1
- package/execution/tool-rendering-primitives.js +3 -2
- package/execution/tool-rendering-primitives.js.map +1 -1
- package/execution/useArtifactDownload.d.ts +44 -0
- package/execution/useArtifactDownload.d.ts.map +1 -0
- package/execution/useArtifactDownload.js +80 -0
- package/execution/useArtifactDownload.js.map +1 -0
- package/execution/useArtifactDownloadUrl.d.ts +67 -0
- package/execution/useArtifactDownloadUrl.d.ts.map +1 -0
- package/execution/useArtifactDownloadUrl.js +59 -0
- package/execution/useArtifactDownloadUrl.js.map +1 -0
- package/execution/useFileChangeContent.d.ts +61 -0
- package/execution/useFileChangeContent.d.ts.map +1 -0
- package/execution/useFileChangeContent.js +89 -0
- package/execution/useFileChangeContent.js.map +1 -0
- package/execution/useFileReview.d.ts +89 -0
- package/execution/useFileReview.d.ts.map +1 -0
- package/execution/useFileReview.js +106 -0
- package/execution/useFileReview.js.map +1 -0
- package/execution/useSubmitApproval.d.ts +17 -2
- package/execution/useSubmitApproval.d.ts.map +1 -1
- package/execution/useSubmitApproval.js +27 -23
- package/execution/useSubmitApproval.js.map +1 -1
- package/execution/useToolOutputContent.d.ts +44 -0
- package/execution/useToolOutputContent.d.ts.map +1 -0
- package/execution/useToolOutputContent.js +31 -0
- package/execution/useToolOutputContent.js.map +1 -0
- package/index.d.ts +6 -6
- package/index.d.ts.map +1 -1
- package/index.js +3 -3
- package/index.js.map +1 -1
- package/internal/ApprovalPeekBar.d.ts +23 -0
- package/internal/ApprovalPeekBar.d.ts.map +1 -0
- package/internal/ApprovalPeekBar.js +25 -0
- package/internal/ApprovalPeekBar.js.map +1 -0
- package/internal/BoundedContent.d.ts +49 -0
- package/internal/BoundedContent.d.ts.map +1 -0
- package/internal/BoundedContent.js +50 -0
- package/internal/BoundedContent.js.map +1 -0
- package/internal/DecisionButton.d.ts +47 -0
- package/internal/DecisionButton.d.ts.map +1 -0
- package/internal/DecisionButton.js +42 -0
- package/internal/DecisionButton.js.map +1 -0
- package/internal/InCardDecisionError.d.ts +31 -0
- package/internal/InCardDecisionError.d.ts.map +1 -0
- package/internal/InCardDecisionError.js +23 -0
- package/internal/InCardDecisionError.js.map +1 -0
- package/internal/RevealToggle.d.ts +36 -0
- package/internal/RevealToggle.d.ts.map +1 -0
- package/internal/RevealToggle.js +32 -0
- package/internal/RevealToggle.js.map +1 -0
- package/internal/VirtualizedThread.d.ts +7 -1
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +7 -3
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/code-highlight.d.ts +24 -0
- package/internal/code-highlight.d.ts.map +1 -0
- package/internal/code-highlight.js +115 -0
- package/internal/code-highlight.js.map +1 -0
- package/internal/markdown-components.d.ts.map +1 -1
- package/internal/markdown-components.js +13 -2
- package/internal/markdown-components.js.map +1 -1
- package/internal/useAutoDisclosure.d.ts +34 -0
- package/internal/useAutoDisclosure.d.ts.map +1 -0
- package/internal/useAutoDisclosure.js +53 -0
- package/internal/useAutoDisclosure.js.map +1 -0
- package/internal/useElapsedSince.d.ts +30 -0
- package/internal/useElapsedSince.d.ts.map +1 -0
- package/internal/useElapsedSince.js +70 -0
- package/internal/useElapsedSince.js.map +1 -0
- package/internal/useIsOverflowing.d.ts +30 -0
- package/internal/useIsOverflowing.d.ts.map +1 -0
- package/internal/useIsOverflowing.js +47 -0
- package/internal/useIsOverflowing.js.map +1 -0
- package/internal/useIsTextTruncated.d.ts +24 -0
- package/internal/useIsTextTruncated.d.ts.map +1 -0
- package/internal/useIsTextTruncated.js +41 -0
- package/internal/useIsTextTruncated.js.map +1 -0
- package/internal/useKeyedSubmission.d.ts +49 -0
- package/internal/useKeyedSubmission.d.ts.map +1 -0
- package/internal/useKeyedSubmission.js +67 -0
- package/internal/useKeyedSubmission.js.map +1 -0
- package/package.json +7 -4
- package/session/SessionViewer.d.ts +2 -2
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +10 -4
- package/session/SessionViewer.js.map +1 -1
- package/session/index.d.ts +2 -0
- package/session/index.d.ts.map +1 -1
- package/session/index.js +1 -0
- package/session/index.js.map +1 -1
- package/session/inspector/ChangesTab.d.ts +8 -5
- package/session/inspector/ChangesTab.d.ts.map +1 -1
- package/session/inspector/ChangesTab.js +11 -8
- package/session/inspector/ChangesTab.js.map +1 -1
- package/session/inspector/SessionInspector.d.ts +4 -4
- package/session/inspector/SessionInspector.d.ts.map +1 -1
- package/session/inspector/SessionInspector.js +4 -4
- package/session/inspector/SessionInspector.js.map +1 -1
- package/session/inspector/index.d.ts +0 -2
- package/session/inspector/index.d.ts.map +1 -1
- package/session/inspector/index.js +0 -1
- package/session/inspector/index.js.map +1 -1
- package/session/inspector/useSessionInspector.d.ts +8 -4
- package/session/inspector/useSessionInspector.d.ts.map +1 -1
- package/session/inspector/useSessionInspector.js +27 -20
- package/session/inspector/useSessionInspector.js.map +1 -1
- package/session/useSessionConversation.d.ts +37 -3
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +18 -2
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionFileChanges.d.ts +74 -0
- package/session/useSessionFileChanges.d.ts.map +1 -0
- package/session/useSessionFileChanges.js +178 -0
- package/session/useSessionFileChanges.js.map +1 -0
- package/src/__tests__/styles-border-layer-invariant.test.ts +105 -0
- package/src/execution/ApprovalCard.tsx +368 -230
- package/src/execution/ApprovalContext.ts +109 -0
- package/src/execution/ArtifactCard.tsx +10 -6
- package/src/execution/ArtifactPreviewModal.tsx +12 -6
- package/src/execution/EmptyChangeNotice.tsx +62 -0
- package/src/execution/FileChangesView.tsx +383 -0
- package/src/execution/FilePathLink.tsx +65 -12
- package/src/execution/FileReviewCard.tsx +1118 -0
- package/src/execution/FileReviewContext.ts +53 -0
- package/src/execution/FileReviewDock.tsx +157 -0
- package/src/execution/McpToolDetail.tsx +98 -32
- package/src/execution/MessageThread.tsx +374 -9
- package/src/execution/PlanArtifactCard.tsx +9 -6
- package/src/execution/PlanCompletionCard.tsx +1 -1
- package/src/execution/ResultView.tsx +333 -162
- package/src/execution/SubAgentSection.tsx +58 -11
- package/src/execution/TerminalSession.tsx +91 -0
- package/src/execution/TodoCard.tsx +186 -0
- package/src/execution/ToolArgsView.tsx +28 -17
- package/src/execution/ToolCallDetail.tsx +137 -26
- package/src/execution/ToolCallGroup.tsx +68 -296
- package/src/execution/ToolCallItem.tsx +265 -67
- package/src/execution/ToolRunGroup.tsx +302 -0
- package/src/execution/__tests__/ApprovalCard.test.tsx +395 -5
- package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +15 -0
- package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +0 -1
- package/src/execution/__tests__/EmptyChangeNotice.test.tsx +24 -0
- package/src/execution/__tests__/FileChangesView.test.tsx +296 -0
- package/src/execution/__tests__/FilePathLink.test.tsx +92 -0
- package/src/execution/__tests__/FileReviewCard.test.tsx +1044 -0
- package/src/execution/__tests__/FileReviewDock.test.tsx +134 -0
- package/src/execution/__tests__/McpToolDetail.test.tsx +79 -0
- package/src/execution/__tests__/MessageThread.test.tsx +324 -0
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +37 -16
- package/src/execution/__tests__/ResultView.test.tsx +280 -2
- package/src/execution/__tests__/SubAgentSection.test.tsx +180 -0
- package/src/execution/__tests__/TerminalSession.test.tsx +72 -0
- package/src/execution/__tests__/TodoCard.test.tsx +102 -0
- package/src/execution/__tests__/ToolArgsView.test.tsx +48 -0
- package/src/execution/__tests__/ToolCallDetail.test.tsx +195 -0
- package/src/execution/__tests__/ToolCallGroup.test.tsx +132 -0
- package/src/execution/__tests__/ToolCallItem.test.tsx +521 -0
- package/src/execution/__tests__/ToolRunGroup.test.tsx +137 -0
- package/src/execution/__tests__/blanked-narration.test.tsx +149 -0
- package/src/execution/__tests__/buildThreadItems-approvals.test.ts +304 -0
- package/src/execution/__tests__/buildThreadItems-file-review.test.ts +331 -0
- package/src/execution/__tests__/file-path-resolver.test.ts +44 -0
- package/src/execution/__tests__/file-review-status.test.ts +343 -0
- package/src/execution/__tests__/message-entry.test.tsx +16 -0
- package/src/execution/__tests__/segment-tool-calls.test.ts +124 -0
- package/src/execution/__tests__/subagent-file-review-badge.test.tsx +273 -0
- package/src/execution/__tests__/thread-keys.test.ts +195 -0
- package/src/execution/__tests__/tool-presenter.test.tsx +95 -0
- package/src/execution/__tests__/useArtifactDownload.test.tsx +67 -0
- package/src/execution/__tests__/useArtifactDownloadUrl.test.tsx +51 -0
- package/src/execution/__tests__/useFileChangeContent.test.tsx +240 -0
- package/src/execution/__tests__/useFileReview.test.tsx +236 -0
- package/src/execution/__tests__/useSubmitApproval.test.tsx +165 -0
- package/src/execution/__tests__/useToolOutputContent.test.tsx +82 -0
- package/src/execution/approval-provenance.ts +8 -0
- package/src/execution/artifact-utils.ts +0 -18
- package/src/execution/execution-phases.ts +4 -16
- package/src/execution/file-path-resolver.ts +38 -0
- package/src/execution/file-review-status.ts +219 -0
- package/src/execution/index.ts +84 -4
- package/src/execution/segment-tool-calls.ts +101 -0
- package/src/execution/tool-categories.ts +128 -1
- package/src/execution/tool-presenter.ts +58 -3
- package/src/execution/tool-rendering-primitives.tsx +11 -14
- package/src/execution/useArtifactDownload.ts +109 -0
- package/src/execution/useArtifactDownloadUrl.ts +116 -0
- package/src/execution/useFileChangeContent.ts +149 -0
- package/src/execution/useFileReview.ts +197 -0
- package/src/execution/useSubmitApproval.ts +49 -27
- package/src/execution/useToolOutputContent.ts +70 -0
- package/src/index.ts +60 -1
- package/src/internal/ApprovalPeekBar.tsx +73 -0
- package/src/internal/BoundedContent.tsx +97 -0
- package/src/internal/DecisionButton.tsx +127 -0
- package/src/internal/InCardDecisionError.tsx +47 -0
- package/src/internal/RevealToggle.tsx +91 -0
- package/src/internal/VirtualizedThread.tsx +28 -2
- package/src/internal/__tests__/ApprovalPeekBar.test.tsx +34 -0
- package/src/internal/__tests__/BoundedContent.test.tsx +92 -0
- package/src/internal/__tests__/DecisionButton.test.tsx +107 -0
- package/src/internal/__tests__/RevealToggle.test.tsx +61 -0
- package/src/internal/__tests__/code-highlight.test.tsx +59 -0
- package/src/internal/__tests__/markdown-components.test.tsx +68 -2
- package/src/internal/__tests__/useAutoDisclosure.test.ts +74 -0
- package/src/internal/__tests__/useElapsedSince.test.tsx +68 -0
- package/src/internal/__tests__/useIsOverflowing.test.ts +36 -0
- package/src/internal/__tests__/useKeyedSubmission.test.tsx +126 -0
- package/src/internal/code-highlight.tsx +120 -0
- package/src/internal/markdown-components.tsx +20 -3
- package/src/internal/useAutoDisclosure.ts +58 -0
- package/src/internal/useElapsedSince.ts +72 -0
- package/src/internal/useIsOverflowing.ts +61 -0
- package/src/internal/useIsTextTruncated.ts +55 -0
- package/src/internal/useKeyedSubmission.ts +101 -0
- package/src/session/SessionViewer.tsx +21 -4
- package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +198 -0
- package/src/session/__tests__/audienceWiring.test.tsx +4 -0
- package/src/session/__tests__/useSessionFileChanges.test.ts +303 -0
- package/src/session/index.ts +3 -0
- package/src/session/inspector/ChangesTab.tsx +20 -17
- package/src/session/inspector/SessionInspector.tsx +12 -10
- package/src/session/inspector/__tests__/ArtifactsTab.test.tsx +0 -1
- package/src/session/inspector/__tests__/ChangesTab.test.tsx +38 -0
- package/src/session/inspector/__tests__/useSessionInspector.test.ts +46 -61
- package/src/session/inspector/index.ts +0 -3
- package/src/session/inspector/useSessionInspector.ts +27 -20
- package/src/session/useSessionConversation.ts +80 -3
- package/src/session/useSessionFileChanges.ts +207 -0
- package/src/styles.css +123 -10
- package/src/version-history/DiffViewer.tsx +10 -7
- package/src/version-history/UnifiedDiffView.tsx +66 -0
- package/src/version-history/__tests__/DiffViewer.test.tsx +57 -0
- package/src/version-history/__tests__/UnifiedDiffView.test.tsx +50 -0
- package/src/version-history/__tests__/computeDiff.test.ts +35 -0
- package/src/version-history/__tests__/parseUnifiedDiff.test.ts +82 -0
- package/src/version-history/computeDiff.ts +6 -37
- package/src/version-history/diff-hunks.ts +63 -0
- package/src/version-history/index.ts +1 -0
- package/src/version-history/parseUnifiedDiff.ts +34 -0
- package/src/workflow/WorkflowExecutionApprovalCard.tsx +49 -24
- package/src/workflow/WorkflowExecutionTimeline.tsx +15 -4
- package/src/workflow/WorkflowExecutionTimelineEvent.tsx +8 -3
- package/src/workflow/WorkflowExecutionViewer.tsx +72 -28
- package/src/workflow/WorkflowFileReviewList.tsx +152 -0
- package/src/workflow/WorkflowTaskApprovalCard.tsx +37 -85
- package/src/workflow/__tests__/ExecutionInspector.test.tsx +30 -2
- package/src/workflow/__tests__/WorkflowExecutionApprovalCard.test.tsx +129 -0
- package/src/workflow/__tests__/WorkflowFileReviewList.test.tsx +129 -0
- package/src/workflow/__tests__/WorkflowTaskApprovalCard.test.tsx +43 -11
- package/src/workflow/__tests__/useWorkflowExecutionActions.test.tsx +276 -0
- package/src/workflow/execution-inspector/ExecutionInspector.tsx +42 -18
- package/src/workflow/index.ts +5 -0
- package/src/workflow/useWorkflowExecutionActions.ts +177 -29
- package/styles.css +1 -1
- package/version-history/DiffViewer.d.ts.map +1 -1
- package/version-history/DiffViewer.js +9 -3
- package/version-history/DiffViewer.js.map +1 -1
- package/version-history/UnifiedDiffView.d.ts +29 -0
- package/version-history/UnifiedDiffView.d.ts.map +1 -0
- package/version-history/UnifiedDiffView.js +36 -0
- package/version-history/UnifiedDiffView.js.map +1 -0
- package/version-history/computeDiff.d.ts +3 -1
- package/version-history/computeDiff.d.ts.map +1 -1
- package/version-history/computeDiff.js +5 -35
- package/version-history/computeDiff.js.map +1 -1
- package/version-history/diff-hunks.d.ts +21 -0
- package/version-history/diff-hunks.d.ts.map +1 -0
- package/version-history/diff-hunks.js +58 -0
- package/version-history/diff-hunks.js.map +1 -0
- package/version-history/index.d.ts +1 -0
- package/version-history/index.d.ts.map +1 -1
- package/version-history/index.js +1 -0
- package/version-history/index.js.map +1 -1
- package/version-history/parseUnifiedDiff.d.ts +22 -0
- package/version-history/parseUnifiedDiff.d.ts.map +1 -0
- package/version-history/parseUnifiedDiff.js +34 -0
- package/version-history/parseUnifiedDiff.js.map +1 -0
- package/workflow/WorkflowExecutionApprovalCard.d.ts +8 -1
- package/workflow/WorkflowExecutionApprovalCard.d.ts.map +1 -1
- package/workflow/WorkflowExecutionApprovalCard.js +17 -3
- package/workflow/WorkflowExecutionApprovalCard.js.map +1 -1
- package/workflow/WorkflowExecutionTimeline.d.ts +11 -2
- package/workflow/WorkflowExecutionTimeline.d.ts.map +1 -1
- package/workflow/WorkflowExecutionTimeline.js +2 -2
- package/workflow/WorkflowExecutionTimeline.js.map +1 -1
- package/workflow/WorkflowExecutionTimelineEvent.d.ts +4 -1
- package/workflow/WorkflowExecutionTimelineEvent.d.ts.map +1 -1
- package/workflow/WorkflowExecutionTimelineEvent.js +2 -2
- package/workflow/WorkflowExecutionTimelineEvent.js.map +1 -1
- package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
- package/workflow/WorkflowExecutionViewer.js +18 -10
- package/workflow/WorkflowExecutionViewer.js.map +1 -1
- package/workflow/WorkflowFileReviewList.d.ts +46 -0
- package/workflow/WorkflowFileReviewList.d.ts.map +1 -0
- package/workflow/WorkflowFileReviewList.js +48 -0
- package/workflow/WorkflowFileReviewList.js.map +1 -0
- package/workflow/WorkflowTaskApprovalCard.d.ts +8 -1
- package/workflow/WorkflowTaskApprovalCard.d.ts.map +1 -1
- package/workflow/WorkflowTaskApprovalCard.js +12 -19
- package/workflow/WorkflowTaskApprovalCard.js.map +1 -1
- package/workflow/execution-inspector/ExecutionInspector.d.ts +21 -4
- package/workflow/execution-inspector/ExecutionInspector.d.ts.map +1 -1
- package/workflow/execution-inspector/ExecutionInspector.js +6 -3
- package/workflow/execution-inspector/ExecutionInspector.js.map +1 -1
- package/workflow/index.d.ts +1 -0
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -0
- package/workflow/index.js.map +1 -1
- package/workflow/useWorkflowExecutionActions.d.ts +62 -4
- package/workflow/useWorkflowExecutionActions.d.ts.map +1 -1
- package/workflow/useWorkflowExecutionActions.js +94 -18
- package/workflow/useWorkflowExecutionActions.js.map +1 -1
- package/session/inspector/PlanTab.d.ts +0 -15
- package/session/inspector/PlanTab.d.ts.map +0 -1
- package/session/inspector/PlanTab.js +0 -19
- package/session/inspector/PlanTab.js.map +0 -1
- package/src/session/inspector/PlanTab.tsx +0 -31
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { DiffViewer } from "./DiffViewer";
|
|
6
|
+
import { parseUnifiedDiff } from "./parseUnifiedDiff";
|
|
7
|
+
|
|
8
|
+
/** Props for {@link UnifiedDiffView}. */
|
|
9
|
+
export interface UnifiedDiffViewProps {
|
|
10
|
+
/** A unified-diff patch string (e.g. Cursor's hunk-only `diffString`). */
|
|
11
|
+
readonly patch: string;
|
|
12
|
+
/** Additional CSS classes for the root container (e.g. a height cap). */
|
|
13
|
+
readonly className?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The single canonical renderer for a unified-diff patch *string*.
|
|
18
|
+
*
|
|
19
|
+
* It parses the patch into hunks and renders them through {@link DiffViewer} —
|
|
20
|
+
* the same accessible table (line numbers, colored row backgrounds, a narrow
|
|
21
|
+
* `+`/`-` gutter column, `--stgm-diff-*` tokens) that a computed before/after
|
|
22
|
+
* diff uses — so a harness that only emits a ready unified diff (the Cursor
|
|
23
|
+
* harness's `diffString`) looks line-for-line identical to a native whole-file
|
|
24
|
+
* diff. The `---`/`+++`/`@@` preamble parses into metadata and never reaches the
|
|
25
|
+
* screen; a single-hunk diff shows no `@@` separator at all.
|
|
26
|
+
*
|
|
27
|
+
* Fallback: if the patch cannot be parsed into any hunk (a malformed or
|
|
28
|
+
* non-standard payload) it renders verbatim in a `<pre>` so we show something
|
|
29
|
+
* truthful rather than a misleading "No changes". Color is never the sole
|
|
30
|
+
* channel in either path — the gutter marker / literal prefix carries the change
|
|
31
|
+
* type for non-color readers.
|
|
32
|
+
*
|
|
33
|
+
* Internal to the SDK (not barrel-exported); consumed by {@link ResultView} and
|
|
34
|
+
* {@link FileChangeDiff}.
|
|
35
|
+
*/
|
|
36
|
+
export function UnifiedDiffView({ patch, className }: UnifiedDiffViewProps) {
|
|
37
|
+
const hunks = useMemo(() => parseUnifiedDiff(patch), [patch]);
|
|
38
|
+
|
|
39
|
+
if (hunks.length > 0) {
|
|
40
|
+
return <DiffViewer hunks={hunks} className={className} />;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Unparseable but non-empty: show the raw patch rather than nothing.
|
|
44
|
+
const lines = patch.split("\n");
|
|
45
|
+
return (
|
|
46
|
+
<pre
|
|
47
|
+
className={cn(
|
|
48
|
+
"max-h-96 overflow-auto whitespace-pre-wrap break-words rounded-md border border-border bg-muted-subtle p-2 font-mono text-xs",
|
|
49
|
+
className,
|
|
50
|
+
)}
|
|
51
|
+
>
|
|
52
|
+
{lines.map((line, i) => (
|
|
53
|
+
<div
|
|
54
|
+
key={i}
|
|
55
|
+
className={cn(
|
|
56
|
+
line.startsWith("+") && !line.startsWith("+++") && "text-diff-added-fg",
|
|
57
|
+
line.startsWith("-") && !line.startsWith("---") && "text-diff-removed-fg",
|
|
58
|
+
line.startsWith("@@") && "text-diff-hunk-header-fg",
|
|
59
|
+
)}
|
|
60
|
+
>
|
|
61
|
+
{line || " "}
|
|
62
|
+
</div>
|
|
63
|
+
))}
|
|
64
|
+
</pre>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import { render, cleanup } from "@testing-library/react";
|
|
3
|
+
import { DiffViewer } from "../DiffViewer";
|
|
4
|
+
import type { DiffHunk } from "../types";
|
|
5
|
+
|
|
6
|
+
afterEach(cleanup);
|
|
7
|
+
|
|
8
|
+
// A hunk exercising all three line types: an unchanged line, a removal, and an
|
|
9
|
+
// addition — so the single-gutter numbering can be checked per type.
|
|
10
|
+
const hunk: DiffHunk = {
|
|
11
|
+
oldStart: 1,
|
|
12
|
+
oldLines: 2,
|
|
13
|
+
newStart: 1,
|
|
14
|
+
newLines: 2,
|
|
15
|
+
lines: [
|
|
16
|
+
{ type: "context", content: "keep", oldLineNumber: 1, newLineNumber: 1 },
|
|
17
|
+
{ type: "removed", content: "gone", oldLineNumber: 2 },
|
|
18
|
+
{ type: "added", content: "fresh", newLineNumber: 2 },
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** The first cell of a row is the (single) line-number gutter. */
|
|
23
|
+
function gutter(row: Element): string {
|
|
24
|
+
return row.querySelectorAll("td")[0]?.textContent ?? "";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("DiffViewer — single-column gutter (Cursor-style)", () => {
|
|
28
|
+
it("renders exactly one line-number column (3 cells per row, not 4)", () => {
|
|
29
|
+
const { container } = render(<DiffViewer hunks={[hunk]} />);
|
|
30
|
+
const firstRow = container.querySelector("tbody tr")!;
|
|
31
|
+
// gutter + marker + content — the old+new pair is collapsed to one.
|
|
32
|
+
expect(firstRow.querySelectorAll("td")).toHaveLength(3);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("numbers each line from the side it belongs to (new for added/context, old for removed)", () => {
|
|
36
|
+
const { container } = render(<DiffViewer hunks={[hunk]} />);
|
|
37
|
+
const rows = Array.from(container.querySelectorAll("tbody tr"));
|
|
38
|
+
|
|
39
|
+
// context "keep" → its new-file number
|
|
40
|
+
expect(gutter(rows[0])).toBe("1");
|
|
41
|
+
expect(rows[0].textContent).toContain("keep");
|
|
42
|
+
|
|
43
|
+
// removed "gone" → its old-file number (it has no new-side number)
|
|
44
|
+
expect(gutter(rows[1])).toBe("2");
|
|
45
|
+
expect(rows[1].textContent).toContain("gone");
|
|
46
|
+
|
|
47
|
+
// added "fresh" → its new-file number
|
|
48
|
+
expect(gutter(rows[2])).toBe("2");
|
|
49
|
+
expect(rows[2].textContent).toContain("fresh");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("renders a 'No changes' status (no table) for empty hunks", () => {
|
|
53
|
+
const { container } = render(<DiffViewer hunks={[]} />);
|
|
54
|
+
expect(container.querySelector("table")).toBeNull();
|
|
55
|
+
expect(container.textContent).toContain("No changes");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import { render, cleanup } from "@testing-library/react";
|
|
3
|
+
import { UnifiedDiffView } from "../UnifiedDiffView";
|
|
4
|
+
|
|
5
|
+
afterEach(cleanup);
|
|
6
|
+
|
|
7
|
+
describe("UnifiedDiffView", () => {
|
|
8
|
+
it("renders a parseable patch through the DiffViewer table, not a raw dump", () => {
|
|
9
|
+
const patch =
|
|
10
|
+
"--- /dev/null\n+++ b/notes.md\n@@ -0,0 +1,2 @@\n+# Title\n+body\n";
|
|
11
|
+
|
|
12
|
+
const { container } = render(<UnifiedDiffView patch={patch} />);
|
|
13
|
+
|
|
14
|
+
// The accessible table is the renderer — not the old raw <pre>.
|
|
15
|
+
expect(container.querySelector("table")).not.toBeNull();
|
|
16
|
+
// Content is present...
|
|
17
|
+
expect(container.textContent).toContain("# Title");
|
|
18
|
+
expect(container.textContent).toContain("body");
|
|
19
|
+
// ...but the preamble never reaches the screen.
|
|
20
|
+
expect(container.textContent).not.toContain("/dev/null");
|
|
21
|
+
expect(container.textContent).not.toContain("+++");
|
|
22
|
+
// A single hunk shows no @@ separator (DiffViewer omits the first header).
|
|
23
|
+
expect(container.textContent).not.toContain("@@");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("shows the subtle @@ separator only between hunks of a multi-hunk patch", () => {
|
|
27
|
+
const patch =
|
|
28
|
+
"--- a/f\n+++ b/f\n@@ -1,2 +1,2 @@\n ctx1\n-a\n+A\n@@ -10,2 +10,3 @@\n ctx2\n+added\n ctx3\n";
|
|
29
|
+
|
|
30
|
+
const { container } = render(<UnifiedDiffView patch={patch} />);
|
|
31
|
+
|
|
32
|
+
expect(container.querySelector("table")).not.toBeNull();
|
|
33
|
+
// The second hunk's header renders as a separator row.
|
|
34
|
+
expect(container.textContent).toContain("@@ -10,2 +10,3 @@");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("falls back to a raw <pre> for an unparseable but non-empty patch", () => {
|
|
38
|
+
const { container } = render(<UnifiedDiffView patch="totally not a diff" />);
|
|
39
|
+
|
|
40
|
+
expect(container.querySelector("table")).toBeNull();
|
|
41
|
+
expect(container.querySelector("pre")).not.toBeNull();
|
|
42
|
+
expect(container.textContent).toContain("totally not a diff");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("forwards className to the rendered container (e.g. a height cap)", () => {
|
|
46
|
+
const patch = "@@ -1 +1 @@\n-a\n+b\n";
|
|
47
|
+
const { container } = render(<UnifiedDiffView patch={patch} className="max-h-80" />);
|
|
48
|
+
expect(container.querySelector(".max-h-80")).not.toBeNull();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { computeDiff } from "../computeDiff";
|
|
3
|
+
|
|
4
|
+
describe("computeDiff", () => {
|
|
5
|
+
it("returns no hunks for identical text", () => {
|
|
6
|
+
expect(computeDiff("same\n", "same\n")).toEqual([]);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("maps an addition with a new-side line number and no old-side number", () => {
|
|
10
|
+
const hunks = computeDiff("hello\n", "hello\nworld\n");
|
|
11
|
+
expect(hunks).toHaveLength(1);
|
|
12
|
+
const added = hunks[0].lines.find((l) => l.type === "added");
|
|
13
|
+
expect(added).toMatchObject({ type: "added", content: "world" });
|
|
14
|
+
expect(added?.newLineNumber).toBe(2);
|
|
15
|
+
expect(added?.oldLineNumber).toBeUndefined();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("maps a replacement into a removed + added pair with correct numbers", () => {
|
|
19
|
+
const hunks = computeDiff("alpha\n", "beta\n");
|
|
20
|
+
expect(hunks[0].lines).toEqual([
|
|
21
|
+
{ type: "removed", content: "alpha", oldLineNumber: 1 },
|
|
22
|
+
{ type: "added", content: "beta", newLineNumber: 1 },
|
|
23
|
+
]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("skips the no-newline marker when a side lacks a trailing newline", () => {
|
|
27
|
+
// structuredPatch emits "" here; the shared
|
|
28
|
+
// mapper must drop it rather than render it as a spurious context line.
|
|
29
|
+
const hunks = computeDiff("alpha", "beta");
|
|
30
|
+
expect(hunks[0].lines).toEqual([
|
|
31
|
+
{ type: "removed", content: "alpha", oldLineNumber: 1 },
|
|
32
|
+
{ type: "added", content: "beta", newLineNumber: 1 },
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { parseUnifiedDiff } from "../parseUnifiedDiff";
|
|
3
|
+
import { computeDiff } from "../computeDiff";
|
|
4
|
+
|
|
5
|
+
describe("parseUnifiedDiff", () => {
|
|
6
|
+
it("parses a /dev/null create, discarding the ---/+++ preamble", () => {
|
|
7
|
+
// The exact shape the Cursor harness emits for a new file (the screenshot
|
|
8
|
+
// case): the file headers must not survive into the rendered hunks.
|
|
9
|
+
const patch =
|
|
10
|
+
"--- /dev/null\n+++ b/Users/x/notes.md\n@@ -0,0 +1,3 @@\n+# Project Notes\n+\n+Minimal service\n";
|
|
11
|
+
|
|
12
|
+
const hunks = parseUnifiedDiff(patch);
|
|
13
|
+
|
|
14
|
+
expect(hunks).toHaveLength(1);
|
|
15
|
+
const lines = hunks[0].lines;
|
|
16
|
+
expect(lines.map((l) => l.type)).toEqual(["added", "added", "added"]);
|
|
17
|
+
expect(lines.map((l) => l.content)).toEqual(["# Project Notes", "", "Minimal service"]);
|
|
18
|
+
// Added lines carry a new-side number and no old-side number.
|
|
19
|
+
expect(lines.map((l) => l.newLineNumber)).toEqual([1, 2, 3]);
|
|
20
|
+
expect(lines.every((l) => l.oldLineNumber === undefined)).toBe(true);
|
|
21
|
+
// No preamble leaked into any content.
|
|
22
|
+
const allContent = lines.map((l) => l.content).join("\n");
|
|
23
|
+
expect(allContent).not.toContain("/dev/null");
|
|
24
|
+
expect(allContent).not.toContain("+++");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("parses a header-less hunk-only edit with correct line numbers", () => {
|
|
28
|
+
const patch = "@@ -1,3 +1,3 @@\n line one\n-old middle\n+new middle\n line three\n";
|
|
29
|
+
|
|
30
|
+
const hunks = parseUnifiedDiff(patch);
|
|
31
|
+
|
|
32
|
+
expect(hunks).toHaveLength(1);
|
|
33
|
+
expect(hunks[0].lines).toEqual([
|
|
34
|
+
{ type: "context", content: "line one", oldLineNumber: 1, newLineNumber: 1 },
|
|
35
|
+
{ type: "removed", content: "old middle", oldLineNumber: 2 },
|
|
36
|
+
{ type: "added", content: "new middle", newLineNumber: 2 },
|
|
37
|
+
{ type: "context", content: "line three", oldLineNumber: 3, newLineNumber: 3 },
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("skips '\' markers", () => {
|
|
42
|
+
const patch =
|
|
43
|
+
"--- a/f\n+++ b/f\n@@ -1 +1 @@\n-alpha\n\\n+beta\n\\n";
|
|
44
|
+
|
|
45
|
+
const hunks = parseUnifiedDiff(patch);
|
|
46
|
+
|
|
47
|
+
expect(hunks).toHaveLength(1);
|
|
48
|
+
// The two metadata markers are gone; only the real change lines remain.
|
|
49
|
+
expect(hunks[0].lines).toEqual([
|
|
50
|
+
{ type: "removed", content: "alpha", oldLineNumber: 1 },
|
|
51
|
+
{ type: "added", content: "beta", newLineNumber: 1 },
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("parses a multi-hunk patch into independent, correctly-numbered hunks", () => {
|
|
56
|
+
const patch =
|
|
57
|
+
"--- a/f\n+++ b/f\n@@ -1,2 +1,2 @@\n ctx1\n-a\n+A\n@@ -10,2 +10,3 @@\n ctx2\n+added\n ctx3\n";
|
|
58
|
+
|
|
59
|
+
const hunks = parseUnifiedDiff(patch);
|
|
60
|
+
|
|
61
|
+
expect(hunks).toHaveLength(2);
|
|
62
|
+
expect(hunks[1].lines).toEqual([
|
|
63
|
+
{ type: "context", content: "ctx2", oldLineNumber: 10, newLineNumber: 10 },
|
|
64
|
+
{ type: "added", content: "added", newLineNumber: 11 },
|
|
65
|
+
{ type: "context", content: "ctx3", oldLineNumber: 11, newLineNumber: 12 },
|
|
66
|
+
]);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("returns [] for an empty or unparseable patch (caller renders a raw fallback)", () => {
|
|
70
|
+
expect(parseUnifiedDiff("")).toEqual([]);
|
|
71
|
+
expect(parseUnifiedDiff("this is not a diff at all")).toEqual([]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("produces the same line shape as computeDiff for an equivalent change", () => {
|
|
75
|
+
// computeDiff (before/after text) and parseUnifiedDiff (a patch string) must
|
|
76
|
+
// map a change to identical DiffLines — they share mapPatchHunks.
|
|
77
|
+
const computed = computeDiff("alpha\n", "beta\n");
|
|
78
|
+
const parsed = parseUnifiedDiff("@@ -1 +1 @@\n-alpha\n+beta\n");
|
|
79
|
+
|
|
80
|
+
expect(parsed[0].lines).toEqual(computed[0].lines);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { structuredPatch } from "diff";
|
|
2
|
-
import
|
|
2
|
+
import { mapPatchHunks } from "./diff-hunks";
|
|
3
|
+
import type { DiffHunk } from "./types";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Compute a unified diff between two text strings.
|
|
6
7
|
*
|
|
7
8
|
* Returns an array of {@link DiffHunk} objects, each containing the
|
|
8
9
|
* changed and context lines with line numbers. Uses the `diff` library's
|
|
9
|
-
* Myers algorithm internally
|
|
10
|
+
* Myers algorithm internally, then maps the structured hunks through the
|
|
11
|
+
* shared {@link mapPatchHunks} (the same mapper `parseUnifiedDiff` uses), so a
|
|
12
|
+
* computed diff and a parsed unified diff render line-for-line identically.
|
|
10
13
|
*
|
|
11
14
|
* Pure function — no side effects, safe to call outside React.
|
|
12
15
|
*
|
|
@@ -23,39 +26,5 @@ export function computeDiff(
|
|
|
23
26
|
context: contextLines,
|
|
24
27
|
});
|
|
25
28
|
|
|
26
|
-
return patch.hunks
|
|
27
|
-
const lines: DiffLine[] = [];
|
|
28
|
-
let oldLine = hunk.oldStart;
|
|
29
|
-
let newLine = hunk.newStart;
|
|
30
|
-
|
|
31
|
-
for (const raw of hunk.lines) {
|
|
32
|
-
const prefix = raw[0];
|
|
33
|
-
const content = raw.slice(1);
|
|
34
|
-
|
|
35
|
-
if (prefix === "+") {
|
|
36
|
-
lines.push({ type: "added", content, newLineNumber: newLine });
|
|
37
|
-
newLine++;
|
|
38
|
-
} else if (prefix === "-") {
|
|
39
|
-
lines.push({ type: "removed", content, oldLineNumber: oldLine });
|
|
40
|
-
oldLine++;
|
|
41
|
-
} else {
|
|
42
|
-
lines.push({
|
|
43
|
-
type: "context",
|
|
44
|
-
content,
|
|
45
|
-
oldLineNumber: oldLine,
|
|
46
|
-
newLineNumber: newLine,
|
|
47
|
-
});
|
|
48
|
-
oldLine++;
|
|
49
|
-
newLine++;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
oldStart: hunk.oldStart,
|
|
55
|
-
oldLines: hunk.oldLines,
|
|
56
|
-
newStart: hunk.newStart,
|
|
57
|
-
newLines: hunk.newLines,
|
|
58
|
-
lines,
|
|
59
|
-
};
|
|
60
|
-
});
|
|
29
|
+
return mapPatchHunks(patch.hunks);
|
|
61
30
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { StructuredPatchHunk } from "diff";
|
|
2
|
+
import type { DiffHunk, DiffLine } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Maps the `diff` library's structured-patch hunks into our presentation
|
|
6
|
+
* {@link DiffHunk} shape, assigning running old/new line numbers per line.
|
|
7
|
+
*
|
|
8
|
+
* This is the single source of truth for the hunk mapping, shared by
|
|
9
|
+
* {@link computeDiff} (which feeds it `structuredPatch` output computed from
|
|
10
|
+
* before/after text) and `parseUnifiedDiff` (which feeds it `parsePatch` output
|
|
11
|
+
* parsed from a unified-diff string). Both functions in the `diff` library emit
|
|
12
|
+
* the identical {@link StructuredPatchHunk} shape, so one mapper serves both and
|
|
13
|
+
* the two diff sources can never drift in how a `+`/`-`/context line becomes a
|
|
14
|
+
* {@link DiffLine}.
|
|
15
|
+
*
|
|
16
|
+
* `` markers are skipped: they are diff metadata, not
|
|
17
|
+
* content, and would otherwise be mis-rendered as a spurious context line.
|
|
18
|
+
*
|
|
19
|
+
* Pure function — no side effects, safe to call outside React.
|
|
20
|
+
*/
|
|
21
|
+
export function mapPatchHunks(
|
|
22
|
+
hunks: readonly StructuredPatchHunk[],
|
|
23
|
+
): readonly DiffHunk[] {
|
|
24
|
+
return hunks.map((hunk) => {
|
|
25
|
+
const lines: DiffLine[] = [];
|
|
26
|
+
let oldLine = hunk.oldStart;
|
|
27
|
+
let newLine = hunk.newStart;
|
|
28
|
+
|
|
29
|
+
for (const raw of hunk.lines) {
|
|
30
|
+
// "" is a metadata marker, not a real line.
|
|
31
|
+
if (raw.startsWith("\\")) continue;
|
|
32
|
+
|
|
33
|
+
const prefix = raw[0];
|
|
34
|
+
const content = raw.slice(1);
|
|
35
|
+
|
|
36
|
+
if (prefix === "+") {
|
|
37
|
+
lines.push({ type: "added", content, newLineNumber: newLine });
|
|
38
|
+
newLine++;
|
|
39
|
+
} else if (prefix === "-") {
|
|
40
|
+
lines.push({ type: "removed", content, oldLineNumber: oldLine });
|
|
41
|
+
oldLine++;
|
|
42
|
+
} else {
|
|
43
|
+
// A context line (leading space) or an empty raw line.
|
|
44
|
+
lines.push({
|
|
45
|
+
type: "context",
|
|
46
|
+
content,
|
|
47
|
+
oldLineNumber: oldLine,
|
|
48
|
+
newLineNumber: newLine,
|
|
49
|
+
});
|
|
50
|
+
oldLine++;
|
|
51
|
+
newLine++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
oldStart: hunk.oldStart,
|
|
57
|
+
oldLines: hunk.oldLines,
|
|
58
|
+
newStart: hunk.newStart,
|
|
59
|
+
newLines: hunk.newLines,
|
|
60
|
+
lines,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -9,6 +9,7 @@ export type { DiffSummaryProps } from "./DiffSummary";
|
|
|
9
9
|
export { MultiFileDiffView } from "./MultiFileDiffView";
|
|
10
10
|
export type { MultiFileDiffViewProps } from "./MultiFileDiffView";
|
|
11
11
|
export { computeDiff } from "./computeDiff";
|
|
12
|
+
export { parseUnifiedDiff } from "./parseUnifiedDiff";
|
|
12
13
|
export { computeMultiFileDiff } from "./computeMultiFileDiff";
|
|
13
14
|
export type {
|
|
14
15
|
VersionEntry,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parsePatch } from "diff";
|
|
2
|
+
import { mapPatchHunks } from "./diff-hunks";
|
|
3
|
+
import type { DiffHunk } from "./types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses a unified-diff patch *string* into presentation {@link DiffHunk}s.
|
|
7
|
+
*
|
|
8
|
+
* This is the bridge that lets a harness which only emits a ready unified diff
|
|
9
|
+
* (the Cursor harness's `diffString` -> `view.unifiedDiff` / `FileChange.
|
|
10
|
+
* unifiedDiff`) render through the same accessible {@link DiffViewer} table as a
|
|
11
|
+
* computed before/after diff — instead of being dumped as a raw `<pre>` with the
|
|
12
|
+
* `--- /dev/null`, `+++ b/...`, `@@` preamble and inline `+`/`-` prefixes.
|
|
13
|
+
*
|
|
14
|
+
* The `---`/`+++` file headers parse into metadata and are discarded; only the
|
|
15
|
+
* hunks survive, mapped through the shared {@link mapPatchHunks}. A diff input is
|
|
16
|
+
* a single file's patch, but `parsePatch` can return multiple file entries, so
|
|
17
|
+
* their hunks are flattened defensively.
|
|
18
|
+
*
|
|
19
|
+
* Returns `[]` for an empty or unparseable patch, so callers can fall back to a
|
|
20
|
+
* truthful raw rendering rather than showing a misleading "No changes".
|
|
21
|
+
*
|
|
22
|
+
* Pure function — no side effects, safe to call outside React.
|
|
23
|
+
*/
|
|
24
|
+
export function parseUnifiedDiff(patch: string): readonly DiffHunk[] {
|
|
25
|
+
if (!patch) return [];
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
return parsePatch(patch).flatMap((file) => mapPatchHunks(file.hunks));
|
|
29
|
+
} catch {
|
|
30
|
+
// parsePatch can throw on a badly malformed patch; degrade to "no hunks" so
|
|
31
|
+
// the caller renders its raw fallback instead of crashing the thread.
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { memo, useCallback, useState } from "react";
|
|
3
|
+
import { memo, useCallback, useEffect, useState } from "react";
|
|
4
4
|
import type { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
5
5
|
import { cn } from "@stigmer/theme";
|
|
6
|
+
import { DecisionButton } from "../internal/DecisionButton";
|
|
7
|
+
import { InCardDecisionError } from "../internal/InCardDecisionError";
|
|
6
8
|
|
|
7
9
|
/** Props for {@link WorkflowExecutionApprovalCard}. */
|
|
8
10
|
export interface WorkflowExecutionApprovalCardProps {
|
|
@@ -20,8 +22,15 @@ export interface WorkflowExecutionApprovalCardProps {
|
|
|
20
22
|
action: ApprovalAction,
|
|
21
23
|
comment?: string,
|
|
22
24
|
) => Promise<unknown>;
|
|
23
|
-
/** `true` while
|
|
25
|
+
/** `true` while this gate's submission is in flight. */
|
|
24
26
|
readonly isSubmitting: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* This gate's last failed decision, or `null`. Surfaced in-card beside the
|
|
29
|
+
* actions (via the shared {@link InCardDecisionError}) — supply
|
|
30
|
+
* {@link useWorkflowExecutionActions}'s `approvalErrorsByToolCallId` for this
|
|
31
|
+
* `toolCallId`.
|
|
32
|
+
*/
|
|
33
|
+
readonly error?: Error | null;
|
|
25
34
|
/** Additional CSS class names. */
|
|
26
35
|
readonly className?: string;
|
|
27
36
|
}
|
|
@@ -40,16 +49,26 @@ export const WorkflowExecutionApprovalCard = memo(function WorkflowExecutionAppr
|
|
|
40
49
|
timeoutSeconds,
|
|
41
50
|
onSubmitApproval,
|
|
42
51
|
isSubmitting,
|
|
52
|
+
error,
|
|
43
53
|
className,
|
|
44
54
|
}: WorkflowExecutionApprovalCardProps) {
|
|
45
55
|
const [comment, setComment] = useState("");
|
|
56
|
+
// Which action is in flight, so the spinner lands on the clicked button —
|
|
57
|
+
// matching ApprovalCard / WorkflowTaskApprovalCard. Reset once the RPC settles.
|
|
58
|
+
const [active, setActive] = useState<"approve" | "reject" | null>(null);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!isSubmitting) setActive(null);
|
|
62
|
+
}, [isSubmitting]);
|
|
46
63
|
|
|
47
64
|
// ApprovalAction enum values: 0=UNSPECIFIED, 1=APPROVE, 2=SKIP, 3=REJECT
|
|
48
65
|
const handleApprove = useCallback(() => {
|
|
66
|
+
setActive("approve");
|
|
49
67
|
onSubmitApproval(toolCallId, 1 as ApprovalAction, comment || undefined);
|
|
50
68
|
}, [toolCallId, comment, onSubmitApproval]);
|
|
51
69
|
|
|
52
70
|
const handleReject = useCallback(() => {
|
|
71
|
+
setActive("reject");
|
|
53
72
|
onSubmitApproval(toolCallId, 3 as ApprovalAction, comment || undefined);
|
|
54
73
|
}, [toolCallId, comment, onSubmitApproval]);
|
|
55
74
|
|
|
@@ -57,8 +76,10 @@ export const WorkflowExecutionApprovalCard = memo(function WorkflowExecutionAppr
|
|
|
57
76
|
<div
|
|
58
77
|
role="alert"
|
|
59
78
|
aria-label="Approval required"
|
|
79
|
+
// Neutral card + 2px warning left accent — the quiet Cursor-grade chrome
|
|
80
|
+
// shared with ApprovalCard. (Replaces the old amber `bg-warning/5` fill.)
|
|
60
81
|
className={cn(
|
|
61
|
-
"my-1 rounded-lg border border-
|
|
82
|
+
"my-1 rounded-lg border border-border-prominent border-l-2 border-l-warning p-3",
|
|
62
83
|
className,
|
|
63
84
|
)}
|
|
64
85
|
>
|
|
@@ -92,30 +113,34 @@ export const WorkflowExecutionApprovalCard = memo(function WorkflowExecutionAppr
|
|
|
92
113
|
</div>
|
|
93
114
|
|
|
94
115
|
<div className="mt-2 flex gap-2">
|
|
95
|
-
<
|
|
96
|
-
|
|
116
|
+
<DecisionButton
|
|
117
|
+
label="Approve"
|
|
118
|
+
variant="primary"
|
|
97
119
|
onClick={handleApprove}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
>
|
|
105
|
-
Approve
|
|
106
|
-
</button>
|
|
107
|
-
<button
|
|
108
|
-
type="button"
|
|
120
|
+
isActive={active === "approve"}
|
|
121
|
+
isSubmitting={isSubmitting}
|
|
122
|
+
/>
|
|
123
|
+
<DecisionButton
|
|
124
|
+
label="Reject"
|
|
125
|
+
variant="danger"
|
|
109
126
|
onClick={handleReject}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"hover:bg-destructive/10 disabled:pointer-events-none disabled:opacity-50",
|
|
114
|
-
)}
|
|
115
|
-
>
|
|
116
|
-
Reject
|
|
117
|
-
</button>
|
|
127
|
+
isActive={active === "reject"}
|
|
128
|
+
isSubmitting={isSubmitting}
|
|
129
|
+
/>
|
|
118
130
|
</div>
|
|
131
|
+
|
|
132
|
+
{/* A failed decision surfaces HERE, beside this gate's actions — not in the
|
|
133
|
+
viewer's lifecycle banner. A workflow can hold many gates at once, so a
|
|
134
|
+
failure must name the one it belongs to; the optimistic spinner has
|
|
135
|
+
already reverted, and this explains the snap-back. Shared with the
|
|
136
|
+
agent ApprovalCard / FileReviewCard via InCardDecisionError. */}
|
|
137
|
+
{error && (
|
|
138
|
+
<InCardDecisionError
|
|
139
|
+
error={error}
|
|
140
|
+
leadIn="submit decision"
|
|
141
|
+
cursorTarget="wf-approval-error"
|
|
142
|
+
/>
|
|
143
|
+
)}
|
|
119
144
|
</div>
|
|
120
145
|
);
|
|
121
146
|
});
|
|
@@ -23,8 +23,17 @@ export interface WorkflowExecutionTimelineProps {
|
|
|
23
23
|
formData?: Record<string, unknown>,
|
|
24
24
|
comment?: string,
|
|
25
25
|
) => Promise<unknown>;
|
|
26
|
-
/**
|
|
27
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Task names whose human_input approval is currently in flight, keyed by
|
|
28
|
+
* `taskName` so deciding one gate never spins another. Supply
|
|
29
|
+
* {@link useWorkflowExecutionActions}'s `taskApprovalSubmittingTaskNames`.
|
|
30
|
+
*/
|
|
31
|
+
readonly taskApprovalSubmittingTaskNames?: ReadonlySet<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Per-gate human_input approval failures, keyed by `taskName`. Supply
|
|
34
|
+
* {@link useWorkflowExecutionActions}'s `taskApprovalErrorsByTaskName`.
|
|
35
|
+
*/
|
|
36
|
+
readonly taskApprovalErrorsByTaskName?: ReadonlyMap<string, Error>;
|
|
28
37
|
/** Additional CSS class names. */
|
|
29
38
|
readonly className?: string;
|
|
30
39
|
}
|
|
@@ -47,7 +56,8 @@ export const WorkflowExecutionTimeline = memo(function WorkflowExecutionTimeline
|
|
|
47
56
|
onNavigateToAgentExecution,
|
|
48
57
|
taskStates,
|
|
49
58
|
onSubmitTaskApproval,
|
|
50
|
-
|
|
59
|
+
taskApprovalSubmittingTaskNames,
|
|
60
|
+
taskApprovalErrorsByTaskName,
|
|
51
61
|
className,
|
|
52
62
|
}: WorkflowExecutionTimelineProps) {
|
|
53
63
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
@@ -112,7 +122,8 @@ export const WorkflowExecutionTimeline = memo(function WorkflowExecutionTimeline
|
|
|
112
122
|
onNavigateToAgentExecution={onNavigateToAgentExecution}
|
|
113
123
|
taskStates={taskStates}
|
|
114
124
|
onSubmitTaskApproval={onSubmitTaskApproval}
|
|
115
|
-
|
|
125
|
+
taskApprovalSubmittingTaskNames={taskApprovalSubmittingTaskNames}
|
|
126
|
+
taskApprovalErrorsByTaskName={taskApprovalErrorsByTaskName}
|
|
116
127
|
/>
|
|
117
128
|
))}
|
|
118
129
|
|
|
@@ -19,7 +19,10 @@ interface TimelineEventProps {
|
|
|
19
19
|
formData?: Record<string, unknown>,
|
|
20
20
|
comment?: string,
|
|
21
21
|
) => Promise<unknown>;
|
|
22
|
-
|
|
22
|
+
/** Task names whose human_input approval is in flight, keyed by `taskName`. */
|
|
23
|
+
readonly taskApprovalSubmittingTaskNames?: ReadonlySet<string>;
|
|
24
|
+
/** Per-gate human_input approval failures, keyed by `taskName`. */
|
|
25
|
+
readonly taskApprovalErrorsByTaskName?: ReadonlyMap<string, Error>;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
/**
|
|
@@ -37,7 +40,8 @@ export const WorkflowExecutionTimelineEvent = memo(function WorkflowExecutionTim
|
|
|
37
40
|
onNavigateToAgentExecution,
|
|
38
41
|
taskStates,
|
|
39
42
|
onSubmitTaskApproval,
|
|
40
|
-
|
|
43
|
+
taskApprovalSubmittingTaskNames,
|
|
44
|
+
taskApprovalErrorsByTaskName,
|
|
41
45
|
}: TimelineEventProps) {
|
|
42
46
|
const timestamp = formatTimestamp(event.occurredAt);
|
|
43
47
|
const p = event.payload;
|
|
@@ -277,7 +281,8 @@ export const WorkflowExecutionTimelineEvent = memo(function WorkflowExecutionTim
|
|
|
277
281
|
? (p.value.formSchema as unknown as Record<string, unknown>)
|
|
278
282
|
: undefined}
|
|
279
283
|
onSubmit={onSubmitTaskApproval}
|
|
280
|
-
isSubmitting={
|
|
284
|
+
isSubmitting={taskApprovalSubmittingTaskNames?.has(event.taskName) ?? false}
|
|
285
|
+
error={taskApprovalErrorsByTaskName?.get(event.taskName) ?? null}
|
|
281
286
|
/>
|
|
282
287
|
)}
|
|
283
288
|
</EventRow>
|