@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,303 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { renderHook } from "@testing-library/react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import {
|
|
5
|
+
AgentExecutionSchema,
|
|
6
|
+
AgentExecutionStatusSchema,
|
|
7
|
+
type AgentExecution,
|
|
8
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
9
|
+
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
10
|
+
import { FileContentSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
11
|
+
import {
|
|
12
|
+
CapturedFileChangeSchema,
|
|
13
|
+
FileChangeSetSchema,
|
|
14
|
+
FileReviewBaselineCapturedSchema,
|
|
15
|
+
FileReviewCandidateCapturedSchema,
|
|
16
|
+
FileReviewEventSchema,
|
|
17
|
+
FileReviewEventStreamSchema,
|
|
18
|
+
type CapturedFileChange,
|
|
19
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
|
|
20
|
+
import {
|
|
21
|
+
ExecutionPhase,
|
|
22
|
+
FileChangeCaptureLevel,
|
|
23
|
+
FileChangeKind,
|
|
24
|
+
FileChangeSetStatus,
|
|
25
|
+
FileChangeType,
|
|
26
|
+
FileReviewEventType,
|
|
27
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
28
|
+
import { useSessionFileChanges } from "../useSessionFileChanges";
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Fixtures
|
|
32
|
+
//
|
|
33
|
+
// Under apply-then-review the hook sources exclusively from the file-review
|
|
34
|
+
// ledger (the live `file_change_sets` projection, or the folded
|
|
35
|
+
// `file_review_event_stream` for a terminal execution). The tool-call-coupled
|
|
36
|
+
// `ToolCall.file_changes` (message.proto field 22) was removed in Phase 5
|
|
37
|
+
// Slice 4, so every fixture here is a CapturedFileChange.
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
function inlineSide(value: string) {
|
|
41
|
+
return create(FileContentSchema, { body: { case: "inline", value } });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function captured(opts: {
|
|
45
|
+
id: string;
|
|
46
|
+
pathBefore?: string;
|
|
47
|
+
pathAfter?: string;
|
|
48
|
+
before?: string;
|
|
49
|
+
after?: string;
|
|
50
|
+
kind?: FileChangeKind;
|
|
51
|
+
}): CapturedFileChange {
|
|
52
|
+
const pathBefore = opts.pathBefore ?? opts.pathAfter ?? "";
|
|
53
|
+
const pathAfter = opts.pathAfter ?? opts.pathBefore ?? "";
|
|
54
|
+
return create(CapturedFileChangeSchema, {
|
|
55
|
+
id: opts.id,
|
|
56
|
+
pathBefore,
|
|
57
|
+
pathAfter,
|
|
58
|
+
kind: opts.kind ?? FileChangeKind.MODIFY,
|
|
59
|
+
before: opts.before !== undefined ? inlineSide(opts.before) : undefined,
|
|
60
|
+
after: opts.after !== undefined ? inlineSide(opts.after) : undefined,
|
|
61
|
+
diffComplete: true,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function execWith(id: string): AgentExecution {
|
|
66
|
+
const exec = create(AgentExecutionSchema);
|
|
67
|
+
exec.metadata = create(ApiResourceMetadataSchema, { id });
|
|
68
|
+
exec.status = create(AgentExecutionStatusSchema);
|
|
69
|
+
return exec;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** An execution carrying a live server projection of one change set. */
|
|
73
|
+
function execWithProjection(id: string, changes: CapturedFileChange[]): AgentExecution {
|
|
74
|
+
const exec = execWith(id);
|
|
75
|
+
exec.status!.fileChangeSets = [
|
|
76
|
+
create(FileChangeSetSchema, {
|
|
77
|
+
id: `${id}:0`,
|
|
78
|
+
status: FileChangeSetStatus.AWAITING_REVIEW,
|
|
79
|
+
changes,
|
|
80
|
+
}),
|
|
81
|
+
];
|
|
82
|
+
return exec;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** A terminal execution: empty projection, changes only in the durable ledger. */
|
|
86
|
+
function execWithLedger(id: string, changes: CapturedFileChange[]): AgentExecution {
|
|
87
|
+
const exec = execWith(id);
|
|
88
|
+
exec.status!.phase = ExecutionPhase.EXECUTION_COMPLETED;
|
|
89
|
+
exec.status!.fileChangeSets = [];
|
|
90
|
+
const changeSetId = `${id}:0`;
|
|
91
|
+
exec.status!.fileReviewEventStream = create(FileReviewEventStreamSchema, {
|
|
92
|
+
executionId: id,
|
|
93
|
+
events: [
|
|
94
|
+
create(FileReviewEventSchema, {
|
|
95
|
+
changeSetId,
|
|
96
|
+
eventType: FileReviewEventType.BASELINE_CAPTURED,
|
|
97
|
+
payload: {
|
|
98
|
+
case: "baselineCaptured",
|
|
99
|
+
value: create(FileReviewBaselineCapturedSchema, { changeSetId }),
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
create(FileReviewEventSchema, {
|
|
103
|
+
changeSetId,
|
|
104
|
+
eventType: FileReviewEventType.CANDIDATE_CAPTURED,
|
|
105
|
+
payload: {
|
|
106
|
+
case: "candidateCaptured",
|
|
107
|
+
value: create(FileReviewCandidateCapturedSchema, { changeSetId, changes }),
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
],
|
|
111
|
+
});
|
|
112
|
+
return exec;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function run(executions: readonly AgentExecution[]) {
|
|
116
|
+
return renderHook(() => useSessionFileChanges(executions)).result.current;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// Tests
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
|
|
123
|
+
describe("useSessionFileChanges", () => {
|
|
124
|
+
it("returns empty for no executions", () => {
|
|
125
|
+
const r = run([]);
|
|
126
|
+
expect(r.hasFileChanges).toBe(false);
|
|
127
|
+
expect(r.fileChangeCount).toBe(0);
|
|
128
|
+
expect(r.fileChanges).toEqual([]);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("returns empty when an execution has no file-review changes", () => {
|
|
132
|
+
const r = run([execWith("e1")]);
|
|
133
|
+
expect(r.hasFileChanges).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("collects a single change from the live projection", () => {
|
|
137
|
+
const r = run([
|
|
138
|
+
execWithProjection("e1", [
|
|
139
|
+
captured({ id: "fc1", pathAfter: "src/a.ts", before: "a", after: "b" }),
|
|
140
|
+
]),
|
|
141
|
+
]);
|
|
142
|
+
expect(r.fileChangeCount).toBe(1);
|
|
143
|
+
expect(r.fileChanges[0].path).toBe("src/a.ts");
|
|
144
|
+
expect(r.fileChanges[0].captureLevel).toBe(FileChangeCaptureLevel.WHOLE_FILE);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("collects changes from the durable ledger for a terminal execution", () => {
|
|
148
|
+
const r = run([
|
|
149
|
+
execWithLedger("e1", [
|
|
150
|
+
captured({ id: "fc1", pathAfter: "src/term.ts", before: "a", after: "b" }),
|
|
151
|
+
]),
|
|
152
|
+
]);
|
|
153
|
+
expect(r.fileChangeCount).toBe(1);
|
|
154
|
+
expect(r.fileChanges[0].path).toBe("src/term.ts");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("net-diffs multiple edits to the same path: first.before -> last.after", () => {
|
|
158
|
+
const r = run([
|
|
159
|
+
execWithProjection("e1", [
|
|
160
|
+
captured({ id: "fc1", pathAfter: "src/a.ts", before: "v0", after: "v1" }),
|
|
161
|
+
captured({ id: "fc2", pathAfter: "src/a.ts", before: "v1", after: "v2" }),
|
|
162
|
+
]),
|
|
163
|
+
]);
|
|
164
|
+
expect(r.fileChangeCount).toBe(1);
|
|
165
|
+
const net = r.fileChanges[0];
|
|
166
|
+
expect(net.before?.body.case === "inline" && net.before.body.value).toBe("v0");
|
|
167
|
+
expect(net.after?.body.case === "inline" && net.after.body.value).toBe("v2");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("reconciles create-then-modify on the same path to CREATE", () => {
|
|
171
|
+
const r = run([
|
|
172
|
+
execWithProjection("e1", [
|
|
173
|
+
captured({ id: "fc1", pathAfter: "src/new.ts", after: "first", kind: FileChangeKind.ADD }),
|
|
174
|
+
captured({ id: "fc2", pathAfter: "src/new.ts", before: "first", after: "second", kind: FileChangeKind.MODIFY }),
|
|
175
|
+
]),
|
|
176
|
+
]);
|
|
177
|
+
expect(r.fileChanges[0].changeType).toBe(FileChangeType.CREATE);
|
|
178
|
+
expect(r.fileChanges[0].after?.body.case === "inline" && r.fileChanges[0].after.body.value).toBe("second");
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("reconciles modify-then-delete on the same path to DELETE", () => {
|
|
182
|
+
const r = run([
|
|
183
|
+
execWithProjection("e1", [
|
|
184
|
+
captured({ id: "fc1", pathAfter: "src/x.ts", before: "a", after: "b" }),
|
|
185
|
+
captured({ id: "fc2", pathBefore: "src/x.ts", pathAfter: "src/x.ts", before: "b", kind: FileChangeKind.DELETE }),
|
|
186
|
+
]),
|
|
187
|
+
]);
|
|
188
|
+
expect(r.fileChanges[0].changeType).toBe(FileChangeType.DELETE);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("reconciles create-then-delete on the same path to DELETE (path is not hidden)", () => {
|
|
192
|
+
const r = run([
|
|
193
|
+
execWithProjection("e1", [
|
|
194
|
+
captured({ id: "fc1", pathAfter: "src/tmp.ts", after: "scratch", kind: FileChangeKind.ADD }),
|
|
195
|
+
captured({ id: "fc2", pathBefore: "src/tmp.ts", pathAfter: "src/tmp.ts", before: "scratch", kind: FileChangeKind.DELETE }),
|
|
196
|
+
]),
|
|
197
|
+
]);
|
|
198
|
+
// A file created and removed within one session still surfaces, as a DELETE
|
|
199
|
+
// anchored on the first change's (empty) before — it is not silently dropped.
|
|
200
|
+
expect(r.fileChangeCount).toBe(1);
|
|
201
|
+
expect(r.fileChanges[0].changeType).toBe(FileChangeType.DELETE);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("reconciles rename-then-modify on the same path to RENAME, preserving rename_from", () => {
|
|
205
|
+
const r = run([
|
|
206
|
+
execWithProjection("e1", [
|
|
207
|
+
captured({ id: "fc1", pathBefore: "src/old-name.ts", pathAfter: "src/new-name.ts", before: "a", after: "a", kind: FileChangeKind.RENAME }),
|
|
208
|
+
captured({ id: "fc2", pathAfter: "src/new-name.ts", before: "a", after: "b", kind: FileChangeKind.MODIFY }),
|
|
209
|
+
]),
|
|
210
|
+
]);
|
|
211
|
+
expect(r.fileChanges[0].changeType).toBe(FileChangeType.RENAME);
|
|
212
|
+
expect(r.fileChanges[0].renameFrom).toBe("src/old-name.ts");
|
|
213
|
+
expect(r.fileChanges[0].after?.body.case === "inline" && r.fileChanges[0].after.body.value).toBe("b");
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("groups changes across change sets by path (the execution-scoped ledger covers sub-agents)", () => {
|
|
217
|
+
const exec = execWith("e1");
|
|
218
|
+
exec.status!.fileChangeSets = [
|
|
219
|
+
create(FileChangeSetSchema, {
|
|
220
|
+
id: "e1:0",
|
|
221
|
+
status: FileChangeSetStatus.RECONCILED,
|
|
222
|
+
changes: [captured({ id: "fc1", pathAfter: "src/shared.ts", before: "v0", after: "v1" })],
|
|
223
|
+
}),
|
|
224
|
+
create(FileChangeSetSchema, {
|
|
225
|
+
id: "e1:1",
|
|
226
|
+
status: FileChangeSetStatus.AWAITING_REVIEW,
|
|
227
|
+
changes: [captured({ id: "fc2", pathAfter: "src/shared.ts", before: "v1", after: "v2" })],
|
|
228
|
+
}),
|
|
229
|
+
];
|
|
230
|
+
const r = run([exec]);
|
|
231
|
+
expect(r.fileChangeCount).toBe(1);
|
|
232
|
+
const net = r.fileChanges[0];
|
|
233
|
+
expect(net.before?.body.case === "inline" && net.before.body.value).toBe("v0");
|
|
234
|
+
expect(net.after?.body.case === "inline" && net.after.body.value).toBe("v2");
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("passes a single change through with its bytes intact (no synthesis)", () => {
|
|
238
|
+
const r = run([
|
|
239
|
+
execWithProjection("e1", [
|
|
240
|
+
captured({ id: "fc1", pathAfter: "src/a.ts", before: "a", after: "b" }),
|
|
241
|
+
]),
|
|
242
|
+
]);
|
|
243
|
+
expect(r.fileChangeCount).toBe(1);
|
|
244
|
+
const only = r.fileChanges[0];
|
|
245
|
+
expect(only.path).toBe("src/a.ts");
|
|
246
|
+
expect(only.before?.body.case === "inline" && only.before.body.value).toBe("a");
|
|
247
|
+
expect(only.after?.body.case === "inline" && only.after.body.value).toBe("b");
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it("sorts modified before created/renamed before deleted, then alpha", () => {
|
|
251
|
+
const r = run([
|
|
252
|
+
execWithProjection("e1", [
|
|
253
|
+
captured({ id: "fc1", pathBefore: "z-del.ts", pathAfter: "z-del.ts", before: "x", kind: FileChangeKind.DELETE }),
|
|
254
|
+
captured({ id: "fc2", pathAfter: "a-new.ts", after: "x", kind: FileChangeKind.ADD }),
|
|
255
|
+
captured({ id: "fc3", pathAfter: "m-mod.ts", before: "x", after: "y", kind: FileChangeKind.MODIFY }),
|
|
256
|
+
captured({ id: "fc4", pathAfter: "b-mod.ts", before: "x", after: "y", kind: FileChangeKind.MODIFY }),
|
|
257
|
+
]),
|
|
258
|
+
]);
|
|
259
|
+
expect(r.fileChanges.map((c) => c.path)).toEqual([
|
|
260
|
+
"b-mod.ts",
|
|
261
|
+
"m-mod.ts",
|
|
262
|
+
"a-new.ts",
|
|
263
|
+
"z-del.ts",
|
|
264
|
+
]);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("net-diffs captures across turns from the ledger", () => {
|
|
268
|
+
// Two change sets touching the same path: first.before -> last.after.
|
|
269
|
+
const exec = execWith("e1");
|
|
270
|
+
exec.status!.fileChangeSets = [
|
|
271
|
+
create(FileChangeSetSchema, {
|
|
272
|
+
id: "e1:0",
|
|
273
|
+
status: FileChangeSetStatus.RECONCILED,
|
|
274
|
+
changes: [captured({ id: "fc1", pathAfter: "src/a.ts", before: "v0", after: "v1" })],
|
|
275
|
+
}),
|
|
276
|
+
create(FileChangeSetSchema, {
|
|
277
|
+
id: "e1:1",
|
|
278
|
+
status: FileChangeSetStatus.AWAITING_REVIEW,
|
|
279
|
+
changes: [captured({ id: "fc2", pathAfter: "src/a.ts", before: "v1", after: "v2" })],
|
|
280
|
+
}),
|
|
281
|
+
];
|
|
282
|
+
const r = run([exec]);
|
|
283
|
+
expect(r.fileChangeCount).toBe(1);
|
|
284
|
+
const net = r.fileChanges[0];
|
|
285
|
+
expect(net.before?.body.case === "inline" && net.before.body.value).toBe("v0");
|
|
286
|
+
expect(net.after?.body.case === "inline" && net.after.body.value).toBe("v2");
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("preserves referential stability across re-renders for the same executions", () => {
|
|
290
|
+
const executions = [
|
|
291
|
+
execWithProjection("e1", [
|
|
292
|
+
captured({ id: "fc1", pathAfter: "src/a.ts", before: "a", after: "b" }),
|
|
293
|
+
]),
|
|
294
|
+
];
|
|
295
|
+
const { result, rerender } = renderHook(
|
|
296
|
+
(e: readonly AgentExecution[]) => useSessionFileChanges(e),
|
|
297
|
+
{ initialProps: executions },
|
|
298
|
+
);
|
|
299
|
+
const first = result.current;
|
|
300
|
+
rerender(executions);
|
|
301
|
+
expect(result.current).toBe(first);
|
|
302
|
+
});
|
|
303
|
+
});
|
package/src/session/index.ts
CHANGED
|
@@ -45,6 +45,9 @@ export type {
|
|
|
45
45
|
UseSessionWriteBacksReturn,
|
|
46
46
|
} from "./useSessionWriteBacks";
|
|
47
47
|
|
|
48
|
+
export { useSessionFileChanges } from "./useSessionFileChanges";
|
|
49
|
+
export type { UseSessionFileChangesReturn } from "./useSessionFileChanges";
|
|
50
|
+
|
|
48
51
|
export { useSessionUsage } from "./useSessionUsage";
|
|
49
52
|
export type {
|
|
50
53
|
ModelCostEntry,
|
|
@@ -9,34 +9,37 @@ export interface ChangesTabProps {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Changes facet for the SessionInspector
|
|
12
|
+
* Changes facet for the SessionInspector — the session's git write-backs
|
|
13
|
+
* (branch/commit/PR), one `WriteBackCard` per entry.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Local file changes deliberately do NOT render here: they live in the
|
|
16
|
+
* transcript, where each stamped edit row shows its diff in place and the
|
|
17
|
+
* per-turn decision bar carries the review controls and file list
|
|
18
|
+
* (`FileReviewCard`). Duplicating them in a side panel gave the same change a
|
|
19
|
+
* third rendering with no added authority. The tab therefore only surfaces
|
|
20
|
+
* once a write-back exists (see `buildVisibleTabs`).
|
|
18
21
|
*/
|
|
19
22
|
export function ChangesTab({ executions }: ChangesTabProps) {
|
|
20
23
|
const { writeBacks, hasWriteBacks } = useSessionWriteBacks(executions);
|
|
21
24
|
|
|
22
|
-
if (
|
|
25
|
+
if (hasWriteBacks) {
|
|
23
26
|
return (
|
|
24
|
-
<div className="
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
<div role="list" className="space-y-2">
|
|
28
|
+
{writeBacks.map((entry) => (
|
|
29
|
+
<div key={entry.writeBack.workspaceEntryName} role="listitem">
|
|
30
|
+
<WriteBackCard writeBack={entry.writeBack} />
|
|
31
|
+
</div>
|
|
32
|
+
))}
|
|
29
33
|
</div>
|
|
30
34
|
);
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
return (
|
|
34
|
-
<div
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
))}
|
|
38
|
+
<div className="flex flex-col items-center justify-center px-4 py-8 text-center">
|
|
39
|
+
<p className="text-xs text-muted-foreground">
|
|
40
|
+
No changes yet. Pull requests will appear here once the agent pushes
|
|
41
|
+
its work back to your repository.
|
|
42
|
+
</p>
|
|
40
43
|
</div>
|
|
41
44
|
);
|
|
42
45
|
}
|
|
@@ -10,7 +10,6 @@ import { useSessionArtifacts } from "../useSessionArtifacts";
|
|
|
10
10
|
import { useSessionWriteBacks } from "../useSessionWriteBacks";
|
|
11
11
|
import { useSessionUsage } from "../useSessionUsage";
|
|
12
12
|
import { useSessionInspector } from "./useSessionInspector";
|
|
13
|
-
import { PlanTab } from "./PlanTab";
|
|
14
13
|
import { ChangesTab } from "./ChangesTab";
|
|
15
14
|
import { ArtifactsTab } from "./ArtifactsTab";
|
|
16
15
|
import { UsageTab } from "./UsageTab";
|
|
@@ -24,8 +23,7 @@ import type { ApplyResourceResult } from "../../library/useApplyResource";
|
|
|
24
23
|
export interface SessionInspectorProps {
|
|
25
24
|
/**
|
|
26
25
|
* The most relevant execution — the active streaming execution,
|
|
27
|
-
* or the last completed one. Drives the run-status header
|
|
28
|
-
* the Plan facet.
|
|
26
|
+
* or the last completed one. Drives the run-status header (phase badge).
|
|
29
27
|
*/
|
|
30
28
|
readonly displayExecution: AgentExecution | null;
|
|
31
29
|
/**
|
|
@@ -65,8 +63,9 @@ export interface SessionInspectorProps {
|
|
|
65
63
|
* Tabbed right-side inspector panel for agent sessions.
|
|
66
64
|
*
|
|
67
65
|
* Displays an always-visible run-status header (phase badge) above
|
|
68
|
-
* contextual tabs:
|
|
69
|
-
* (when a thread item is selected).
|
|
66
|
+
* contextual tabs: Workspace, Config, Changes, Artifacts, Usage, and
|
|
67
|
+
* Inspect (when a thread item is selected). The agent's plan/todos render
|
|
68
|
+
* inline in the message thread (see {@link TodoCard}), not as a tab here.
|
|
70
69
|
*
|
|
71
70
|
* Mirrors the `ExecutionInspector` architecture from the workflow
|
|
72
71
|
* view — same `Tabs` primitive, same tab-FSM behavior hook, same
|
|
@@ -109,8 +108,14 @@ export const SessionInspector = memo(function SessionInspector({
|
|
|
109
108
|
|
|
110
109
|
return (
|
|
111
110
|
<div className={cn("flex h-full flex-col", className)}>
|
|
112
|
-
{/* Always-visible run-status header
|
|
113
|
-
|
|
111
|
+
{/* Always-visible run-status header. Labeled as a region so the phase
|
|
112
|
+
badge is reachable as "Execution progress" by assistive tech and
|
|
113
|
+
E2E selectors, independent of which tab is active. */}
|
|
114
|
+
<div
|
|
115
|
+
role="region"
|
|
116
|
+
aria-label="Execution progress"
|
|
117
|
+
className="flex items-center gap-2 border-b border-border px-3 py-2.5"
|
|
118
|
+
>
|
|
114
119
|
{phase !== ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED ? (
|
|
115
120
|
<ExecutionPhaseBadge phase={phase} />
|
|
116
121
|
) : (
|
|
@@ -133,9 +138,6 @@ export const SessionInspector = memo(function SessionInspector({
|
|
|
133
138
|
{activeTab === "configure" && sessionConfig && (
|
|
134
139
|
<SetupTab {...sessionConfig} />
|
|
135
140
|
)}
|
|
136
|
-
{activeTab === "plan" && (
|
|
137
|
-
<PlanTab execution={displayExecution} />
|
|
138
|
-
)}
|
|
139
141
|
{activeTab === "changes" && (
|
|
140
142
|
<ChangesTab executions={allExecutions} />
|
|
141
143
|
)}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { render, screen, cleanup } from "@testing-library/react";
|
|
3
|
+
|
|
4
|
+
const writeBacksReturn = { writeBacks: [] as Array<{ writeBack: { workspaceEntryName: string } }>, hasWriteBacks: false };
|
|
5
|
+
|
|
6
|
+
vi.mock("../../useSessionWriteBacks", () => ({
|
|
7
|
+
useSessionWriteBacks: () => writeBacksReturn,
|
|
8
|
+
}));
|
|
9
|
+
vi.mock("../../../execution/WriteBackCard", () => ({
|
|
10
|
+
WriteBackCard: () => <div data-testid="write-back-card" />,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const { ChangesTab } = await import("../ChangesTab");
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
writeBacksReturn.writeBacks = [];
|
|
17
|
+
writeBacksReturn.hasWriteBacks = false;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => cleanup());
|
|
21
|
+
|
|
22
|
+
describe("ChangesTab", () => {
|
|
23
|
+
it("renders write-back (PR) cards", () => {
|
|
24
|
+
writeBacksReturn.writeBacks = [{ writeBack: { workspaceEntryName: "w1" } }];
|
|
25
|
+
writeBacksReturn.hasWriteBacks = true;
|
|
26
|
+
|
|
27
|
+
render(<ChangesTab executions={[]} />);
|
|
28
|
+
expect(screen.getByTestId("write-back-card")).toBeTruthy();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Local file changes render in the transcript (edit rows + decision bar),
|
|
32
|
+
// never here — the tab is exclusively the write-back (PR) surface.
|
|
33
|
+
it("renders the PR-oriented empty state when no write-back exists", () => {
|
|
34
|
+
render(<ChangesTab executions={[]} />);
|
|
35
|
+
expect(screen.getByText(/no changes yet/i)).toBeTruthy();
|
|
36
|
+
expect(screen.getByText(/pull requests/i)).toBeTruthy();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -20,25 +20,32 @@ function defaultOpts(overrides?: Partial<UseSessionInspectorOptions>): UseSessio
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
function tabOpts(
|
|
24
|
+
overrides?: Partial<Parameters<typeof buildVisibleTabs>[0]>,
|
|
25
|
+
): Parameters<typeof buildVisibleTabs>[0] {
|
|
26
|
+
return {
|
|
27
|
+
hasWriteBacks: false,
|
|
28
|
+
writeBackCount: 0,
|
|
29
|
+
hasArtifacts: false,
|
|
30
|
+
artifactCount: 0,
|
|
31
|
+
hasUsage: false,
|
|
32
|
+
selectedItem: null,
|
|
33
|
+
...overrides,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
23
37
|
// ---------------------------------------------------------------------------
|
|
24
38
|
// buildVisibleTabs
|
|
25
39
|
// ---------------------------------------------------------------------------
|
|
26
40
|
|
|
27
41
|
describe("buildVisibleTabs", () => {
|
|
28
|
-
it("always includes Workspace, Config, Plan
|
|
29
|
-
const tabs = buildVisibleTabs(
|
|
30
|
-
hasWriteBacks: false,
|
|
31
|
-
writeBackCount: 0,
|
|
32
|
-
hasArtifacts: false,
|
|
33
|
-
artifactCount: 0,
|
|
34
|
-
hasUsage: false,
|
|
35
|
-
selectedItem: null,
|
|
36
|
-
});
|
|
42
|
+
it("always includes Workspace, Config, and Usage (Plan is gone — todos render inline)", () => {
|
|
43
|
+
const tabs = buildVisibleTabs(tabOpts());
|
|
37
44
|
const ids = tabs.map((t) => t.id);
|
|
38
45
|
expect(ids).toContain("workspace");
|
|
39
46
|
expect(ids).toContain("configure");
|
|
40
|
-
expect(ids).toContain("plan");
|
|
41
47
|
expect(ids).toContain("usage");
|
|
48
|
+
expect(ids).not.toContain("plan");
|
|
42
49
|
expect(ids).not.toContain("changes");
|
|
43
50
|
expect(ids).not.toContain("artifacts");
|
|
44
51
|
expect(ids).not.toContain("inspect");
|
|
@@ -47,74 +54,52 @@ describe("buildVisibleTabs", () => {
|
|
|
47
54
|
expect(configTab?.label).toBe("Config");
|
|
48
55
|
});
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
artifactCount: 0,
|
|
56
|
-
hasUsage: false,
|
|
57
|
-
selectedItem: null,
|
|
58
|
-
});
|
|
57
|
+
// The Changes tab is exclusively the write-back (PR) surface: local file
|
|
58
|
+
// changes render in the transcript (edit rows + decision bar) and no longer
|
|
59
|
+
// surface — or badge — a tab.
|
|
60
|
+
it("includes Changes with badge only when write-backs exist", () => {
|
|
61
|
+
const tabs = buildVisibleTabs(tabOpts({ hasWriteBacks: true, writeBackCount: 3 }));
|
|
59
62
|
const changesTab = tabs.find((t) => t.id === "changes");
|
|
60
63
|
expect(changesTab).toBeDefined();
|
|
61
64
|
expect(changesTab?.badge).toBe(3);
|
|
62
65
|
});
|
|
63
66
|
|
|
64
67
|
it("includes Artifacts with badge when artifacts exist", () => {
|
|
65
|
-
const tabs = buildVisibleTabs({
|
|
66
|
-
hasWriteBacks: false,
|
|
67
|
-
writeBackCount: 0,
|
|
68
|
-
hasArtifacts: true,
|
|
69
|
-
artifactCount: 7,
|
|
70
|
-
hasUsage: false,
|
|
71
|
-
selectedItem: null,
|
|
72
|
-
});
|
|
68
|
+
const tabs = buildVisibleTabs(tabOpts({ hasArtifacts: true, artifactCount: 7 }));
|
|
73
69
|
const artifactsTab = tabs.find((t) => t.id === "artifacts");
|
|
74
70
|
expect(artifactsTab).toBeDefined();
|
|
75
71
|
expect(artifactsTab?.badge).toBe(7);
|
|
76
72
|
});
|
|
77
73
|
|
|
78
74
|
it("includes Inspect when a thread item is selected", () => {
|
|
79
|
-
const tabs = buildVisibleTabs(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
hasArtifacts: false,
|
|
83
|
-
artifactCount: 0,
|
|
84
|
-
hasUsage: false,
|
|
85
|
-
selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
|
|
86
|
-
});
|
|
75
|
+
const tabs = buildVisibleTabs(
|
|
76
|
+
tabOpts({ selectedItem: { kind: "tool-call", toolCallId: "tc-1" } }),
|
|
77
|
+
);
|
|
87
78
|
const inspectTab = tabs.find((t) => t.id === "inspect");
|
|
88
79
|
expect(inspectTab).toBeDefined();
|
|
89
80
|
});
|
|
90
81
|
|
|
91
|
-
it("orders tabs as Workspace, Config,
|
|
92
|
-
const tabs = buildVisibleTabs(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
82
|
+
it("orders tabs as Workspace, Config, then Usage with Inspect last", () => {
|
|
83
|
+
const tabs = buildVisibleTabs(
|
|
84
|
+
tabOpts({
|
|
85
|
+
hasWriteBacks: true,
|
|
86
|
+
writeBackCount: 2,
|
|
87
|
+
hasArtifacts: true,
|
|
88
|
+
artifactCount: 1,
|
|
89
|
+
hasUsage: true,
|
|
90
|
+
selectedItem: { kind: "tool-call", toolCallId: "tc-1" },
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
100
93
|
const ids = tabs.map((t) => t.id);
|
|
101
94
|
expect(ids.indexOf("workspace")).toBeLessThan(ids.indexOf("configure"));
|
|
102
|
-
expect(ids.indexOf("configure")).toBeLessThan(ids.indexOf("
|
|
103
|
-
expect(ids.indexOf("plan")).toBeLessThan(ids.indexOf("usage"));
|
|
95
|
+
expect(ids.indexOf("configure")).toBeLessThan(ids.indexOf("usage"));
|
|
104
96
|
expect(ids.indexOf("usage")).toBeLessThan(ids.indexOf("inspect"));
|
|
105
97
|
});
|
|
106
98
|
|
|
107
99
|
it("base tabs are present even when no optional tabs exist", () => {
|
|
108
|
-
const tabs = buildVisibleTabs(
|
|
109
|
-
hasWriteBacks: false,
|
|
110
|
-
writeBackCount: 0,
|
|
111
|
-
hasArtifacts: false,
|
|
112
|
-
artifactCount: 0,
|
|
113
|
-
hasUsage: false,
|
|
114
|
-
selectedItem: null,
|
|
115
|
-
});
|
|
100
|
+
const tabs = buildVisibleTabs(tabOpts());
|
|
116
101
|
const ids = tabs.map((t) => t.id);
|
|
117
|
-
expect(ids).toEqual(["workspace", "configure", "
|
|
102
|
+
expect(ids).toEqual(["workspace", "configure", "usage"]);
|
|
118
103
|
});
|
|
119
104
|
});
|
|
120
105
|
|
|
@@ -137,13 +122,13 @@ describe("useSessionInspector", () => {
|
|
|
137
122
|
expect(result.current.activeTab).toBe("workspace");
|
|
138
123
|
});
|
|
139
124
|
|
|
140
|
-
it("defaults to
|
|
125
|
+
it("defaults to workspace while execution is running (todos render inline, not in a tab)", () => {
|
|
141
126
|
const { result } = renderHook(() =>
|
|
142
127
|
useSessionInspector(
|
|
143
128
|
defaultOpts({ phase: ExecutionPhase.EXECUTION_IN_PROGRESS }),
|
|
144
129
|
),
|
|
145
130
|
);
|
|
146
|
-
expect(result.current.activeTab).toBe("
|
|
131
|
+
expect(result.current.activeTab).toBe("workspace");
|
|
147
132
|
});
|
|
148
133
|
|
|
149
134
|
it("auto-switches to inspect when a thread item is selected", () => {
|
|
@@ -174,7 +159,7 @@ describe("useSessionInspector", () => {
|
|
|
174
159
|
expect(result.current.activeTab).toBe("workspace");
|
|
175
160
|
});
|
|
176
161
|
|
|
177
|
-
it("reverts to
|
|
162
|
+
it("reverts to workspace when selection is cleared while execution is running", () => {
|
|
178
163
|
const { result, rerender } = renderHook(
|
|
179
164
|
(props: UseSessionInspectorOptions) => useSessionInspector(props),
|
|
180
165
|
{
|
|
@@ -192,7 +177,7 @@ describe("useSessionInspector", () => {
|
|
|
192
177
|
selectedItem: null,
|
|
193
178
|
}),
|
|
194
179
|
);
|
|
195
|
-
expect(result.current.activeTab).toBe("
|
|
180
|
+
expect(result.current.activeTab).toBe("workspace");
|
|
196
181
|
});
|
|
197
182
|
|
|
198
183
|
it("keeps user-picked tab sticky", () => {
|
|
@@ -247,7 +232,7 @@ describe("useSessionInspector", () => {
|
|
|
247
232
|
expect(result.current.activeTab).toBe("workspace");
|
|
248
233
|
});
|
|
249
234
|
|
|
250
|
-
it("
|
|
235
|
+
it("stays on workspace across the running → terminal transition", () => {
|
|
251
236
|
const { result, rerender } = renderHook(
|
|
252
237
|
(props: UseSessionInspectorOptions) => useSessionInspector(props),
|
|
253
238
|
{
|
|
@@ -256,7 +241,7 @@ describe("useSessionInspector", () => {
|
|
|
256
241
|
}),
|
|
257
242
|
},
|
|
258
243
|
);
|
|
259
|
-
expect(result.current.activeTab).toBe("
|
|
244
|
+
expect(result.current.activeTab).toBe("workspace");
|
|
260
245
|
|
|
261
246
|
rerender(
|
|
262
247
|
defaultOpts({ phase: ExecutionPhase.EXECUTION_COMPLETED }),
|
|
@@ -8,9 +8,6 @@ export type {
|
|
|
8
8
|
UseSessionInspectorReturn,
|
|
9
9
|
} from "./useSessionInspector";
|
|
10
10
|
|
|
11
|
-
export { PlanTab } from "./PlanTab";
|
|
12
|
-
export type { PlanTabProps } from "./PlanTab";
|
|
13
|
-
|
|
14
11
|
export { ChangesTab } from "./ChangesTab";
|
|
15
12
|
export type { ChangesTabProps } from "./ChangesTab";
|
|
16
13
|
|