@stigmer/react 3.0.9-dev.20260616060535 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/execution/ApprovalCard.d.ts +47 -3
- package/execution/ApprovalCard.d.ts.map +1 -1
- package/execution/ApprovalCard.js +138 -70
- package/execution/ApprovalCard.js.map +1 -1
- package/execution/ApprovalContext.d.ts +72 -0
- package/execution/ApprovalContext.d.ts.map +1 -0
- package/execution/ApprovalContext.js +41 -0
- package/execution/ApprovalContext.js.map +1 -0
- package/execution/ArtifactCard.d.ts.map +1 -1
- package/execution/ArtifactCard.js +3 -1
- package/execution/ArtifactCard.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts.map +1 -1
- package/execution/ArtifactPreviewModal.js +5 -3
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/EmptyChangeNotice.d.ts +38 -0
- package/execution/EmptyChangeNotice.d.ts.map +1 -0
- package/execution/EmptyChangeNotice.js +27 -0
- package/execution/EmptyChangeNotice.js.map +1 -0
- package/execution/FileChangesView.d.ts +81 -0
- package/execution/FileChangesView.d.ts.map +1 -0
- package/execution/FileChangesView.js +164 -0
- package/execution/FileChangesView.js.map +1 -0
- package/execution/FilePathLink.d.ts +24 -4
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +31 -9
- package/execution/FilePathLink.js.map +1 -1
- package/execution/FileReviewCard.d.ts +111 -0
- package/execution/FileReviewCard.d.ts.map +1 -0
- package/execution/FileReviewCard.js +558 -0
- package/execution/FileReviewCard.js.map +1 -0
- package/execution/FileReviewContext.d.ts +35 -0
- package/execution/FileReviewContext.d.ts.map +1 -0
- package/execution/FileReviewContext.js +23 -0
- package/execution/FileReviewContext.js.map +1 -0
- package/execution/FileReviewDock.d.ts +73 -0
- package/execution/FileReviewDock.d.ts.map +1 -0
- package/execution/FileReviewDock.js +65 -0
- package/execution/FileReviewDock.js.map +1 -0
- package/execution/McpToolDetail.d.ts.map +1 -1
- package/execution/McpToolDetail.js +38 -5
- package/execution/McpToolDetail.js.map +1 -1
- package/execution/MessageThread.d.ts +42 -3
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +263 -18
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +3 -1
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/PlanCompletionCard.d.ts +1 -1
- package/execution/PlanCompletionCard.js +1 -1
- package/execution/ResultView.d.ts +19 -1
- package/execution/ResultView.d.ts.map +1 -1
- package/execution/ResultView.js +141 -40
- package/execution/ResultView.js.map +1 -1
- package/execution/SubAgentSection.d.ts.map +1 -1
- package/execution/SubAgentSection.js +45 -6
- package/execution/SubAgentSection.js.map +1 -1
- package/execution/TerminalSession.d.ts +34 -0
- package/execution/TerminalSession.d.ts.map +1 -0
- package/execution/TerminalSession.js +34 -0
- package/execution/TerminalSession.js.map +1 -0
- package/execution/TodoCard.d.ts +53 -0
- package/execution/TodoCard.d.ts.map +1 -0
- package/execution/TodoCard.js +77 -0
- package/execution/TodoCard.js.map +1 -0
- package/execution/ToolArgsView.d.ts +7 -1
- package/execution/ToolArgsView.d.ts.map +1 -1
- package/execution/ToolArgsView.js +10 -9
- package/execution/ToolArgsView.js.map +1 -1
- package/execution/ToolCallDetail.d.ts +10 -1
- package/execution/ToolCallDetail.d.ts.map +1 -1
- package/execution/ToolCallDetail.js +66 -19
- package/execution/ToolCallDetail.js.map +1 -1
- package/execution/ToolCallGroup.d.ts +28 -18
- package/execution/ToolCallGroup.d.ts.map +1 -1
- package/execution/ToolCallGroup.js +39 -148
- package/execution/ToolCallGroup.js.map +1 -1
- package/execution/ToolCallItem.d.ts +36 -8
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +140 -21
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/ToolRunGroup.d.ts +48 -0
- package/execution/ToolRunGroup.d.ts.map +1 -0
- package/execution/ToolRunGroup.js +168 -0
- package/execution/ToolRunGroup.js.map +1 -0
- package/execution/approval-provenance.d.ts +2 -0
- package/execution/approval-provenance.d.ts.map +1 -0
- package/execution/approval-provenance.js +6 -0
- package/execution/approval-provenance.js.map +1 -0
- package/execution/artifact-utils.d.ts +0 -10
- package/execution/artifact-utils.d.ts.map +1 -1
- package/execution/artifact-utils.js +0 -17
- package/execution/artifact-utils.js.map +1 -1
- package/execution/execution-phases.d.ts +1 -6
- package/execution/execution-phases.d.ts.map +1 -1
- package/execution/execution-phases.js +4 -14
- package/execution/execution-phases.js.map +1 -1
- package/execution/file-path-resolver.d.ts +28 -0
- package/execution/file-path-resolver.d.ts.map +1 -1
- package/execution/file-path-resolver.js +24 -0
- package/execution/file-path-resolver.js.map +1 -1
- package/execution/file-review-status.d.ts +127 -0
- package/execution/file-review-status.d.ts.map +1 -0
- package/execution/file-review-status.js +135 -0
- package/execution/file-review-status.js.map +1 -0
- package/execution/index.d.ts +39 -5
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +23 -3
- package/execution/index.js.map +1 -1
- package/execution/segment-tool-calls.d.ts +46 -0
- package/execution/segment-tool-calls.d.ts.map +1 -0
- package/execution/segment-tool-calls.js +71 -0
- package/execution/segment-tool-calls.js.map +1 -0
- package/execution/tool-categories.d.ts +62 -1
- package/execution/tool-categories.d.ts.map +1 -1
- package/execution/tool-categories.js +96 -2
- package/execution/tool-categories.js.map +1 -1
- package/execution/tool-presenter.d.ts +38 -2
- package/execution/tool-presenter.d.ts.map +1 -1
- package/execution/tool-presenter.js +23 -1
- package/execution/tool-presenter.js.map +1 -1
- package/execution/tool-rendering-primitives.d.ts.map +1 -1
- package/execution/tool-rendering-primitives.js +3 -2
- package/execution/tool-rendering-primitives.js.map +1 -1
- package/execution/useArtifactDownload.d.ts +44 -0
- package/execution/useArtifactDownload.d.ts.map +1 -0
- package/execution/useArtifactDownload.js +80 -0
- package/execution/useArtifactDownload.js.map +1 -0
- package/execution/useArtifactDownloadUrl.d.ts +67 -0
- package/execution/useArtifactDownloadUrl.d.ts.map +1 -0
- package/execution/useArtifactDownloadUrl.js +59 -0
- package/execution/useArtifactDownloadUrl.js.map +1 -0
- package/execution/useFileChangeContent.d.ts +61 -0
- package/execution/useFileChangeContent.d.ts.map +1 -0
- package/execution/useFileChangeContent.js +89 -0
- package/execution/useFileChangeContent.js.map +1 -0
- package/execution/useFileReview.d.ts +89 -0
- package/execution/useFileReview.d.ts.map +1 -0
- package/execution/useFileReview.js +106 -0
- package/execution/useFileReview.js.map +1 -0
- package/execution/useSubmitApproval.d.ts +17 -2
- package/execution/useSubmitApproval.d.ts.map +1 -1
- package/execution/useSubmitApproval.js +27 -23
- package/execution/useSubmitApproval.js.map +1 -1
- package/execution/useToolOutputContent.d.ts +44 -0
- package/execution/useToolOutputContent.d.ts.map +1 -0
- package/execution/useToolOutputContent.js +31 -0
- package/execution/useToolOutputContent.js.map +1 -0
- package/index.d.ts +6 -6
- package/index.d.ts.map +1 -1
- package/index.js +3 -3
- package/index.js.map +1 -1
- package/internal/ApprovalPeekBar.d.ts +23 -0
- package/internal/ApprovalPeekBar.d.ts.map +1 -0
- package/internal/ApprovalPeekBar.js +25 -0
- package/internal/ApprovalPeekBar.js.map +1 -0
- package/internal/BoundedContent.d.ts +49 -0
- package/internal/BoundedContent.d.ts.map +1 -0
- package/internal/BoundedContent.js +50 -0
- package/internal/BoundedContent.js.map +1 -0
- package/internal/DecisionButton.d.ts +47 -0
- package/internal/DecisionButton.d.ts.map +1 -0
- package/internal/DecisionButton.js +42 -0
- package/internal/DecisionButton.js.map +1 -0
- package/internal/InCardDecisionError.d.ts +31 -0
- package/internal/InCardDecisionError.d.ts.map +1 -0
- package/internal/InCardDecisionError.js +23 -0
- package/internal/InCardDecisionError.js.map +1 -0
- package/internal/RevealToggle.d.ts +36 -0
- package/internal/RevealToggle.d.ts.map +1 -0
- package/internal/RevealToggle.js +32 -0
- package/internal/RevealToggle.js.map +1 -0
- package/internal/VirtualizedThread.d.ts +7 -1
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +7 -3
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/useAutoDisclosure.d.ts +34 -0
- package/internal/useAutoDisclosure.d.ts.map +1 -0
- package/internal/useAutoDisclosure.js +53 -0
- package/internal/useAutoDisclosure.js.map +1 -0
- package/internal/useElapsedSince.d.ts +30 -0
- package/internal/useElapsedSince.d.ts.map +1 -0
- package/internal/useElapsedSince.js +70 -0
- package/internal/useElapsedSince.js.map +1 -0
- package/internal/useIsOverflowing.d.ts +30 -0
- package/internal/useIsOverflowing.d.ts.map +1 -0
- package/internal/useIsOverflowing.js +47 -0
- package/internal/useIsOverflowing.js.map +1 -0
- package/internal/useIsTextTruncated.d.ts +24 -0
- package/internal/useIsTextTruncated.d.ts.map +1 -0
- package/internal/useIsTextTruncated.js +41 -0
- package/internal/useIsTextTruncated.js.map +1 -0
- package/internal/useKeyedSubmission.d.ts +49 -0
- package/internal/useKeyedSubmission.d.ts.map +1 -0
- package/internal/useKeyedSubmission.js +67 -0
- package/internal/useKeyedSubmission.js.map +1 -0
- package/package.json +4 -4
- package/session/SessionViewer.d.ts +2 -2
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +10 -4
- package/session/SessionViewer.js.map +1 -1
- package/session/index.d.ts +2 -0
- package/session/index.d.ts.map +1 -1
- package/session/index.js +1 -0
- package/session/index.js.map +1 -1
- package/session/inspector/ChangesTab.d.ts +8 -5
- package/session/inspector/ChangesTab.d.ts.map +1 -1
- package/session/inspector/ChangesTab.js +11 -8
- package/session/inspector/ChangesTab.js.map +1 -1
- package/session/inspector/SessionInspector.d.ts +4 -4
- package/session/inspector/SessionInspector.d.ts.map +1 -1
- package/session/inspector/SessionInspector.js +4 -4
- package/session/inspector/SessionInspector.js.map +1 -1
- package/session/inspector/index.d.ts +0 -2
- package/session/inspector/index.d.ts.map +1 -1
- package/session/inspector/index.js +0 -1
- package/session/inspector/index.js.map +1 -1
- package/session/inspector/useSessionInspector.d.ts +8 -4
- package/session/inspector/useSessionInspector.d.ts.map +1 -1
- package/session/inspector/useSessionInspector.js +27 -20
- package/session/inspector/useSessionInspector.js.map +1 -1
- package/session/useSessionConversation.d.ts +37 -3
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +18 -2
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionFileChanges.d.ts +74 -0
- package/session/useSessionFileChanges.d.ts.map +1 -0
- package/session/useSessionFileChanges.js +178 -0
- package/session/useSessionFileChanges.js.map +1 -0
- package/src/__tests__/styles-border-layer-invariant.test.ts +105 -0
- package/src/execution/ApprovalCard.tsx +368 -230
- package/src/execution/ApprovalContext.ts +109 -0
- package/src/execution/ArtifactCard.tsx +10 -6
- package/src/execution/ArtifactPreviewModal.tsx +12 -6
- package/src/execution/EmptyChangeNotice.tsx +62 -0
- package/src/execution/FileChangesView.tsx +383 -0
- package/src/execution/FilePathLink.tsx +65 -12
- package/src/execution/FileReviewCard.tsx +1118 -0
- package/src/execution/FileReviewContext.ts +53 -0
- package/src/execution/FileReviewDock.tsx +157 -0
- package/src/execution/McpToolDetail.tsx +98 -32
- package/src/execution/MessageThread.tsx +374 -9
- package/src/execution/PlanArtifactCard.tsx +9 -6
- package/src/execution/PlanCompletionCard.tsx +1 -1
- package/src/execution/ResultView.tsx +333 -162
- package/src/execution/SubAgentSection.tsx +58 -11
- package/src/execution/TerminalSession.tsx +91 -0
- package/src/execution/TodoCard.tsx +186 -0
- package/src/execution/ToolArgsView.tsx +28 -17
- package/src/execution/ToolCallDetail.tsx +137 -26
- package/src/execution/ToolCallGroup.tsx +68 -296
- package/src/execution/ToolCallItem.tsx +265 -67
- package/src/execution/ToolRunGroup.tsx +302 -0
- package/src/execution/__tests__/ApprovalCard.test.tsx +395 -5
- package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +0 -1
- package/src/execution/__tests__/EmptyChangeNotice.test.tsx +24 -0
- package/src/execution/__tests__/FileChangesView.test.tsx +296 -0
- package/src/execution/__tests__/FilePathLink.test.tsx +92 -0
- package/src/execution/__tests__/FileReviewCard.test.tsx +1044 -0
- package/src/execution/__tests__/FileReviewDock.test.tsx +134 -0
- package/src/execution/__tests__/McpToolDetail.test.tsx +79 -0
- package/src/execution/__tests__/MessageThread.test.tsx +324 -0
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +37 -16
- package/src/execution/__tests__/ResultView.test.tsx +280 -2
- package/src/execution/__tests__/SubAgentSection.test.tsx +180 -0
- package/src/execution/__tests__/TerminalSession.test.tsx +72 -0
- package/src/execution/__tests__/TodoCard.test.tsx +102 -0
- package/src/execution/__tests__/ToolArgsView.test.tsx +48 -0
- package/src/execution/__tests__/ToolCallDetail.test.tsx +195 -0
- package/src/execution/__tests__/ToolCallGroup.test.tsx +132 -0
- package/src/execution/__tests__/ToolCallItem.test.tsx +521 -0
- package/src/execution/__tests__/ToolRunGroup.test.tsx +137 -0
- package/src/execution/__tests__/blanked-narration.test.tsx +149 -0
- package/src/execution/__tests__/buildThreadItems-approvals.test.ts +304 -0
- package/src/execution/__tests__/buildThreadItems-file-review.test.ts +331 -0
- package/src/execution/__tests__/file-path-resolver.test.ts +44 -0
- package/src/execution/__tests__/file-review-status.test.ts +343 -0
- package/src/execution/__tests__/segment-tool-calls.test.ts +124 -0
- package/src/execution/__tests__/subagent-file-review-badge.test.tsx +273 -0
- package/src/execution/__tests__/thread-keys.test.ts +195 -0
- package/src/execution/__tests__/tool-presenter.test.tsx +95 -0
- package/src/execution/__tests__/useArtifactDownload.test.tsx +67 -0
- package/src/execution/__tests__/useArtifactDownloadUrl.test.tsx +51 -0
- package/src/execution/__tests__/useFileChangeContent.test.tsx +240 -0
- package/src/execution/__tests__/useFileReview.test.tsx +236 -0
- package/src/execution/__tests__/useSubmitApproval.test.tsx +165 -0
- package/src/execution/__tests__/useToolOutputContent.test.tsx +82 -0
- package/src/execution/approval-provenance.ts +8 -0
- package/src/execution/artifact-utils.ts +0 -18
- package/src/execution/execution-phases.ts +4 -16
- package/src/execution/file-path-resolver.ts +38 -0
- package/src/execution/file-review-status.ts +219 -0
- package/src/execution/index.ts +84 -4
- package/src/execution/segment-tool-calls.ts +101 -0
- package/src/execution/tool-categories.ts +128 -1
- package/src/execution/tool-presenter.ts +58 -3
- package/src/execution/tool-rendering-primitives.tsx +11 -14
- package/src/execution/useArtifactDownload.ts +109 -0
- package/src/execution/useArtifactDownloadUrl.ts +116 -0
- package/src/execution/useFileChangeContent.ts +149 -0
- package/src/execution/useFileReview.ts +197 -0
- package/src/execution/useSubmitApproval.ts +49 -27
- package/src/execution/useToolOutputContent.ts +70 -0
- package/src/index.ts +60 -1
- package/src/internal/ApprovalPeekBar.tsx +73 -0
- package/src/internal/BoundedContent.tsx +97 -0
- package/src/internal/DecisionButton.tsx +127 -0
- package/src/internal/InCardDecisionError.tsx +47 -0
- package/src/internal/RevealToggle.tsx +91 -0
- package/src/internal/VirtualizedThread.tsx +28 -2
- package/src/internal/__tests__/ApprovalPeekBar.test.tsx +34 -0
- package/src/internal/__tests__/BoundedContent.test.tsx +92 -0
- package/src/internal/__tests__/DecisionButton.test.tsx +107 -0
- package/src/internal/__tests__/RevealToggle.test.tsx +61 -0
- package/src/internal/__tests__/useAutoDisclosure.test.ts +74 -0
- package/src/internal/__tests__/useElapsedSince.test.tsx +68 -0
- package/src/internal/__tests__/useIsOverflowing.test.ts +36 -0
- package/src/internal/__tests__/useKeyedSubmission.test.tsx +126 -0
- package/src/internal/useAutoDisclosure.ts +58 -0
- package/src/internal/useElapsedSince.ts +72 -0
- package/src/internal/useIsOverflowing.ts +61 -0
- package/src/internal/useIsTextTruncated.ts +55 -0
- package/src/internal/useKeyedSubmission.ts +101 -0
- package/src/session/SessionViewer.tsx +21 -4
- package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +198 -0
- package/src/session/__tests__/audienceWiring.test.tsx +4 -0
- package/src/session/__tests__/useSessionFileChanges.test.ts +303 -0
- package/src/session/index.ts +3 -0
- package/src/session/inspector/ChangesTab.tsx +20 -17
- package/src/session/inspector/SessionInspector.tsx +12 -10
- package/src/session/inspector/__tests__/ArtifactsTab.test.tsx +0 -1
- package/src/session/inspector/__tests__/ChangesTab.test.tsx +38 -0
- package/src/session/inspector/__tests__/useSessionInspector.test.ts +46 -61
- package/src/session/inspector/index.ts +0 -3
- package/src/session/inspector/useSessionInspector.ts +27 -20
- package/src/session/useSessionConversation.ts +80 -3
- package/src/session/useSessionFileChanges.ts +207 -0
- package/src/styles.css +35 -10
- package/src/version-history/DiffViewer.tsx +10 -7
- package/src/version-history/UnifiedDiffView.tsx +66 -0
- package/src/version-history/__tests__/DiffViewer.test.tsx +57 -0
- package/src/version-history/__tests__/UnifiedDiffView.test.tsx +50 -0
- package/src/version-history/__tests__/computeDiff.test.ts +35 -0
- package/src/version-history/__tests__/parseUnifiedDiff.test.ts +82 -0
- package/src/version-history/computeDiff.ts +6 -37
- package/src/version-history/diff-hunks.ts +63 -0
- package/src/version-history/index.ts +1 -0
- package/src/version-history/parseUnifiedDiff.ts +34 -0
- package/src/workflow/WorkflowExecutionApprovalCard.tsx +49 -24
- package/src/workflow/WorkflowExecutionTimeline.tsx +15 -4
- package/src/workflow/WorkflowExecutionTimelineEvent.tsx +8 -3
- package/src/workflow/WorkflowExecutionViewer.tsx +72 -28
- package/src/workflow/WorkflowFileReviewList.tsx +152 -0
- package/src/workflow/WorkflowTaskApprovalCard.tsx +37 -85
- package/src/workflow/__tests__/ExecutionInspector.test.tsx +30 -2
- package/src/workflow/__tests__/WorkflowExecutionApprovalCard.test.tsx +129 -0
- package/src/workflow/__tests__/WorkflowFileReviewList.test.tsx +129 -0
- package/src/workflow/__tests__/WorkflowTaskApprovalCard.test.tsx +43 -11
- package/src/workflow/__tests__/useWorkflowExecutionActions.test.tsx +276 -0
- package/src/workflow/execution-inspector/ExecutionInspector.tsx +42 -18
- package/src/workflow/index.ts +5 -0
- package/src/workflow/useWorkflowExecutionActions.ts +177 -29
- package/styles.css +1 -1
- package/version-history/DiffViewer.d.ts.map +1 -1
- package/version-history/DiffViewer.js +9 -3
- package/version-history/DiffViewer.js.map +1 -1
- package/version-history/UnifiedDiffView.d.ts +29 -0
- package/version-history/UnifiedDiffView.d.ts.map +1 -0
- package/version-history/UnifiedDiffView.js +36 -0
- package/version-history/UnifiedDiffView.js.map +1 -0
- package/version-history/computeDiff.d.ts +3 -1
- package/version-history/computeDiff.d.ts.map +1 -1
- package/version-history/computeDiff.js +5 -35
- package/version-history/computeDiff.js.map +1 -1
- package/version-history/diff-hunks.d.ts +21 -0
- package/version-history/diff-hunks.d.ts.map +1 -0
- package/version-history/diff-hunks.js +58 -0
- package/version-history/diff-hunks.js.map +1 -0
- package/version-history/index.d.ts +1 -0
- package/version-history/index.d.ts.map +1 -1
- package/version-history/index.js +1 -0
- package/version-history/index.js.map +1 -1
- package/version-history/parseUnifiedDiff.d.ts +22 -0
- package/version-history/parseUnifiedDiff.d.ts.map +1 -0
- package/version-history/parseUnifiedDiff.js +34 -0
- package/version-history/parseUnifiedDiff.js.map +1 -0
- package/workflow/WorkflowExecutionApprovalCard.d.ts +8 -1
- package/workflow/WorkflowExecutionApprovalCard.d.ts.map +1 -1
- package/workflow/WorkflowExecutionApprovalCard.js +17 -3
- package/workflow/WorkflowExecutionApprovalCard.js.map +1 -1
- package/workflow/WorkflowExecutionTimeline.d.ts +11 -2
- package/workflow/WorkflowExecutionTimeline.d.ts.map +1 -1
- package/workflow/WorkflowExecutionTimeline.js +2 -2
- package/workflow/WorkflowExecutionTimeline.js.map +1 -1
- package/workflow/WorkflowExecutionTimelineEvent.d.ts +4 -1
- package/workflow/WorkflowExecutionTimelineEvent.d.ts.map +1 -1
- package/workflow/WorkflowExecutionTimelineEvent.js +2 -2
- package/workflow/WorkflowExecutionTimelineEvent.js.map +1 -1
- package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
- package/workflow/WorkflowExecutionViewer.js +18 -10
- package/workflow/WorkflowExecutionViewer.js.map +1 -1
- package/workflow/WorkflowFileReviewList.d.ts +46 -0
- package/workflow/WorkflowFileReviewList.d.ts.map +1 -0
- package/workflow/WorkflowFileReviewList.js +48 -0
- package/workflow/WorkflowFileReviewList.js.map +1 -0
- package/workflow/WorkflowTaskApprovalCard.d.ts +8 -1
- package/workflow/WorkflowTaskApprovalCard.d.ts.map +1 -1
- package/workflow/WorkflowTaskApprovalCard.js +12 -19
- package/workflow/WorkflowTaskApprovalCard.js.map +1 -1
- package/workflow/execution-inspector/ExecutionInspector.d.ts +21 -4
- package/workflow/execution-inspector/ExecutionInspector.d.ts.map +1 -1
- package/workflow/execution-inspector/ExecutionInspector.js +6 -3
- package/workflow/execution-inspector/ExecutionInspector.js.map +1 -1
- package/workflow/index.d.ts +1 -0
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -0
- package/workflow/index.js.map +1 -1
- package/workflow/useWorkflowExecutionActions.d.ts +62 -4
- package/workflow/useWorkflowExecutionActions.d.ts.map +1 -1
- package/workflow/useWorkflowExecutionActions.js +94 -18
- package/workflow/useWorkflowExecutionActions.js.map +1 -1
- package/session/inspector/PlanTab.d.ts +0 -15
- package/session/inspector/PlanTab.d.ts.map +0 -1
- package/session/inspector/PlanTab.js +0 -19
- package/session/inspector/PlanTab.js.map +0 -1
- package/src/session/inspector/PlanTab.tsx +0 -31
|
@@ -18,7 +18,7 @@ export interface PlanCompletionCardProps {
|
|
|
18
18
|
* Fallback CTA shown in the {@link MessageThread} after a completed Plan-mode
|
|
19
19
|
* execution that did **not** publish a `plan.md` artifact (older executions, or
|
|
20
20
|
* a plan whose upload failed). When a plan artifact exists, the richer
|
|
21
|
-
*
|
|
21
|
+
* `PlanArtifactCard` is shown instead.
|
|
22
22
|
*
|
|
23
23
|
* Mirrors `PlanArtifactCard`'s hierarchy — one prominent, themeable "Build from
|
|
24
24
|
* plan" primary action with the same card-scoped `Cmd/Ctrl+Enter` accelerator —
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
// blocks — instead of a raw JSON dump. The json/text variants are the graceful
|
|
6
6
|
// fallbacks, so unknown tools are still readable.
|
|
7
7
|
|
|
8
|
-
import { useMemo } from "react";
|
|
8
|
+
import { useMemo, useState } from "react";
|
|
9
|
+
import type { ReactNode } from "react";
|
|
9
10
|
import type {
|
|
10
11
|
ToolResultView,
|
|
11
12
|
ToolSearchMatch,
|
|
@@ -13,15 +14,40 @@ import type {
|
|
|
13
14
|
} from "@stigmer/sdk";
|
|
14
15
|
import { cn } from "@stigmer/theme";
|
|
15
16
|
import { computeDiff } from "../version-history/computeDiff";
|
|
17
|
+
import { DiffViewer } from "../version-history/DiffViewer";
|
|
18
|
+
import { UnifiedDiffView } from "../version-history/UnifiedDiffView";
|
|
16
19
|
import type { DiffHunk } from "../version-history/types";
|
|
17
20
|
import { CollapsibleCode, CollapsiblePre, formatJson } from "./tool-rendering-primitives";
|
|
18
21
|
import { FilePathLink } from "./FilePathLink";
|
|
19
|
-
import {
|
|
22
|
+
import { EmptyChangeNotice } from "./EmptyChangeNotice";
|
|
23
|
+
import { TerminalSession } from "./TerminalSession";
|
|
24
|
+
import { execIdFromStorageKey } from "./useFileChangeContent";
|
|
25
|
+
import { useArtifactDownloadUrl } from "./useArtifactDownloadUrl";
|
|
26
|
+
import { useArtifactDownload } from "./useArtifactDownload";
|
|
27
|
+
import { useToolOutputContent } from "./useToolOutputContent";
|
|
20
28
|
|
|
21
29
|
/** Props for {@link ResultView}. */
|
|
22
30
|
export interface ResultViewProps {
|
|
23
31
|
/** The normalized result view to render. */
|
|
24
32
|
readonly view: ToolResultView;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the file/diff variants render the filename header. Defaults to
|
|
35
|
+
* `true`. Set to `false` where an ancestor already names the file (a tool-call
|
|
36
|
+
* row whose header shows the path) so the body is not captioned with a path
|
|
37
|
+
* the user just read; the `+N -M` stats still render.
|
|
38
|
+
*/
|
|
39
|
+
readonly showFileName?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the result body renders its headline summary stat — the diff's
|
|
42
|
+
* `+N -M`, or a search/list's `N files` / `N matches` / `N items` count.
|
|
43
|
+
* Defaults to `true`. Set to `false` where an ancestor row already shows the
|
|
44
|
+
* summary (a tool-call row that renders `summarizeResultView`) so the body does
|
|
45
|
+
* not repeat the count the user just read. A search/list still surfaces a
|
|
46
|
+
* truncation note when suppressed, since that is information the row header does
|
|
47
|
+
* not carry. Orthogonal to {@link showFileName}: the approval gate suppresses
|
|
48
|
+
* the name but keeps the stats.
|
|
49
|
+
*/
|
|
50
|
+
readonly showStats?: boolean;
|
|
25
51
|
/** Additional CSS class names for the root container. */
|
|
26
52
|
readonly className?: string;
|
|
27
53
|
}
|
|
@@ -34,18 +60,18 @@ export interface ResultViewProps {
|
|
|
34
60
|
* this component renders it. Importable on its own by platform builders who
|
|
35
61
|
* compose custom tool UIs.
|
|
36
62
|
*/
|
|
37
|
-
export function ResultView({ view, className }: ResultViewProps) {
|
|
63
|
+
export function ResultView({ view, showFileName = true, showStats = true, className }: ResultViewProps) {
|
|
38
64
|
switch (view.type) {
|
|
39
65
|
case "diff":
|
|
40
|
-
return <DiffResultView view={view} className={className} />;
|
|
66
|
+
return <DiffResultView view={view} showFileName={showFileName} showStats={showStats} className={className} />;
|
|
41
67
|
case "terminal":
|
|
42
68
|
return <TerminalResultView view={view} className={className} />;
|
|
43
69
|
case "search":
|
|
44
|
-
return <SearchResultView
|
|
70
|
+
return <SearchResultView view={view} showCount={showStats} className={className} />;
|
|
45
71
|
case "list":
|
|
46
|
-
return <ListResultView entries={view.entries} count={view.count} className={className} />;
|
|
72
|
+
return <ListResultView entries={view.entries} count={view.count} showCount={showStats} className={className} />;
|
|
47
73
|
case "file":
|
|
48
|
-
return <FileResultView view={view} className={className} />;
|
|
74
|
+
return <FileResultView view={view} showFileName={showFileName} className={className} />;
|
|
49
75
|
case "contentBlocks":
|
|
50
76
|
return <ContentBlocksResultView blocks={view.blocks} className={className} />;
|
|
51
77
|
case "outputRef":
|
|
@@ -75,7 +101,7 @@ export function summarizeResultView(view: ToolResultView): string | null {
|
|
|
75
101
|
case "terminal":
|
|
76
102
|
return view.exitCode !== undefined && view.exitCode !== 0 ? `exit ${view.exitCode}` : null;
|
|
77
103
|
case "search":
|
|
78
|
-
return
|
|
104
|
+
return searchCountLabel(view.count, view.kind);
|
|
79
105
|
case "list":
|
|
80
106
|
return `${view.count} ${view.count === 1 ? "item" : "items"}`;
|
|
81
107
|
default:
|
|
@@ -119,7 +145,17 @@ function diffStats(view: DiffView): DiffStats | null {
|
|
|
119
145
|
return null;
|
|
120
146
|
}
|
|
121
147
|
|
|
122
|
-
function DiffResultView({
|
|
148
|
+
function DiffResultView({
|
|
149
|
+
view,
|
|
150
|
+
showFileName = true,
|
|
151
|
+
showStats = true,
|
|
152
|
+
className,
|
|
153
|
+
}: {
|
|
154
|
+
view: DiffView;
|
|
155
|
+
showFileName?: boolean;
|
|
156
|
+
showStats?: boolean;
|
|
157
|
+
className?: string;
|
|
158
|
+
}) {
|
|
123
159
|
// The native engine returns no diff, so we compute hunks from args (old/new).
|
|
124
160
|
// The Cursor envelope provides a ready unified-diff string we render directly.
|
|
125
161
|
const hunks = useMemo<readonly DiffHunk[]>(() => {
|
|
@@ -137,122 +173,60 @@ function DiffResultView({ view, className }: { view: DiffView; className?: strin
|
|
|
137
173
|
return hunks.length > 0 ? countHunks(hunks) : null;
|
|
138
174
|
}, [view.linesAdded, view.linesRemoved, hunks]);
|
|
139
175
|
|
|
176
|
+
const showPath = showFileName && Boolean(view.path);
|
|
177
|
+
const showStatsRow = showStats && stats != null;
|
|
178
|
+
|
|
179
|
+
// One diff family across every surface: computed hunks render through the
|
|
180
|
+
// canonical, accessible DiffViewer (line numbers + --stgm-diff-* tokens); a
|
|
181
|
+
// ready hunk-only patch (Cursor envelope) is parsed into the same DiffViewer
|
|
182
|
+
// table by UnifiedDiffView (raw fallback only if unparseable). The header
|
|
183
|
+
// (path + ± stats) is this view's own, so the DiffViewer is used without its
|
|
184
|
+
// filePath header to avoid a duplicate path.
|
|
140
185
|
return (
|
|
141
|
-
<div className={cn("space-y-1", className)}>
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
186
|
+
<div className={cn("space-y-1", className)} data-cursor-target="file-diff">
|
|
187
|
+
{(showPath || showStatsRow) && (
|
|
188
|
+
<div className="flex items-center gap-2 text-muted-foreground">
|
|
189
|
+
{showPath && (
|
|
190
|
+
<FilePathLink path={view.path} dirDisplay="dim" className="text-xs" />
|
|
191
|
+
)}
|
|
192
|
+
{showStatsRow && stats && (
|
|
193
|
+
<span className="shrink-0 tabular-nums text-xs">
|
|
194
|
+
<span className="text-diff-added-fg">+{stats.added}</span>{" "}
|
|
195
|
+
<span className="text-diff-removed-fg">-{stats.removed}</span>
|
|
196
|
+
</span>
|
|
197
|
+
)}
|
|
198
|
+
</div>
|
|
199
|
+
)}
|
|
151
200
|
|
|
152
201
|
{hunks.length > 0 ? (
|
|
153
|
-
<
|
|
202
|
+
<DiffViewer hunks={hunks} />
|
|
154
203
|
) : view.unifiedDiff ? (
|
|
155
|
-
<
|
|
156
|
-
) :
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function DiffHunks({ hunks }: { hunks: readonly DiffHunk[] }) {
|
|
162
|
-
return (
|
|
163
|
-
<div className="overflow-auto rounded-md border border-border bg-muted-subtle font-mono text-xs">
|
|
164
|
-
{hunks.map((hunk, hi) => (
|
|
165
|
-
<div key={hi} className="border-b border-border-muted last:border-b-0">
|
|
166
|
-
{hunk.lines.map((line, li) => (
|
|
167
|
-
<div
|
|
168
|
-
key={li}
|
|
169
|
-
className={cn(
|
|
170
|
-
"whitespace-pre-wrap break-words px-2 py-0.5",
|
|
171
|
-
line.type === "added" && "bg-success-subtle text-success",
|
|
172
|
-
line.type === "removed" && "bg-destructive-subtle text-destructive",
|
|
173
|
-
line.type === "context" && "text-muted-foreground",
|
|
174
|
-
)}
|
|
175
|
-
>
|
|
176
|
-
{/* Screen readers get the change type as words; sighted users get
|
|
177
|
-
the +/- sign and color. Never color-only. */}
|
|
178
|
-
{line.type !== "context" && (
|
|
179
|
-
<span className="sr-only">
|
|
180
|
-
{line.type === "added" ? "Added: " : "Removed: "}
|
|
181
|
-
</span>
|
|
182
|
-
)}
|
|
183
|
-
<span className="select-none" aria-hidden="true">
|
|
184
|
-
{line.type === "added" ? "+" : line.type === "removed" ? "-" : " "}
|
|
185
|
-
</span>
|
|
186
|
-
{line.content}
|
|
187
|
-
</div>
|
|
188
|
-
))}
|
|
189
|
-
</div>
|
|
190
|
-
))}
|
|
204
|
+
<UnifiedDiffView patch={view.unifiedDiff} />
|
|
205
|
+
) : (
|
|
206
|
+
<EmptyChangeNotice kind="no-preview" />
|
|
207
|
+
)}
|
|
191
208
|
</div>
|
|
192
209
|
);
|
|
193
210
|
}
|
|
194
211
|
|
|
195
|
-
// Renders a raw unified-diff patch string (Cursor envelope) with +/- coloring.
|
|
196
|
-
function UnifiedDiffText({ patch }: { patch: string }) {
|
|
197
|
-
const lines = patch.split("\n");
|
|
198
|
-
return (
|
|
199
|
-
<pre className="max-h-80 overflow-auto whitespace-pre-wrap break-words rounded-md border border-border bg-muted-subtle p-2 font-mono text-xs">
|
|
200
|
-
{lines.map((line, i) => (
|
|
201
|
-
<div
|
|
202
|
-
key={i}
|
|
203
|
-
className={cn(
|
|
204
|
-
line.startsWith("+") && !line.startsWith("+++") && "text-success",
|
|
205
|
-
line.startsWith("-") && !line.startsWith("---") && "text-destructive",
|
|
206
|
-
line.startsWith("@@") && "text-primary",
|
|
207
|
-
)}
|
|
208
|
-
>
|
|
209
|
-
{line || " "}
|
|
210
|
-
</div>
|
|
211
|
-
))}
|
|
212
|
-
</pre>
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
212
|
// ---------------------------------------------------------------------------
|
|
217
213
|
// Terminal
|
|
218
214
|
// ---------------------------------------------------------------------------
|
|
219
215
|
|
|
220
216
|
type TerminalView = Extract<ToolResultView, { type: "terminal" }>;
|
|
221
217
|
|
|
218
|
+
// A shell result IS a terminal session: the command prompt line plus its
|
|
219
|
+
// output, rendered as one block by the shared TerminalSession (no separate
|
|
220
|
+
// "Output" caption or command box).
|
|
222
221
|
function TerminalResultView({ view, className }: { view: TerminalView; className?: string }) {
|
|
223
|
-
const normalize = useSandboxNormalize();
|
|
224
|
-
const failed = view.exitCode !== undefined && view.exitCode !== 0;
|
|
225
|
-
|
|
226
222
|
return (
|
|
227
|
-
<
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
failed ? "bg-destructive-subtle text-destructive" : "bg-success-subtle text-success",
|
|
235
|
-
)}
|
|
236
|
-
>
|
|
237
|
-
exit {view.exitCode}
|
|
238
|
-
</span>
|
|
239
|
-
)}
|
|
240
|
-
</div>
|
|
241
|
-
<div className="rounded-md border border-border bg-[var(--stgm-terminal-bg,#1a1a2e)] p-2.5">
|
|
242
|
-
{view.stdout && (
|
|
243
|
-
<CollapsiblePre
|
|
244
|
-
content={normalize(view.stdout)}
|
|
245
|
-
className="text-[var(--stgm-terminal-fg,#e0e0e0)]"
|
|
246
|
-
/>
|
|
247
|
-
)}
|
|
248
|
-
{view.stderr && (
|
|
249
|
-
<CollapsiblePre
|
|
250
|
-
content={normalize(view.stderr)}
|
|
251
|
-
className="text-destructive"
|
|
252
|
-
/>
|
|
253
|
-
)}
|
|
254
|
-
</div>
|
|
255
|
-
</div>
|
|
223
|
+
<TerminalSession
|
|
224
|
+
command={view.command}
|
|
225
|
+
stdout={view.stdout}
|
|
226
|
+
stderr={view.stderr}
|
|
227
|
+
exitCode={view.exitCode}
|
|
228
|
+
className={className}
|
|
229
|
+
/>
|
|
256
230
|
);
|
|
257
231
|
}
|
|
258
232
|
|
|
@@ -260,42 +234,158 @@ function TerminalResultView({ view, className }: { view: TerminalView; className
|
|
|
260
234
|
// Search / List
|
|
261
235
|
// ---------------------------------------------------------------------------
|
|
262
236
|
|
|
237
|
+
type SearchView = Extract<ToolResultView, { type: "search" }>;
|
|
238
|
+
|
|
239
|
+
/** "N files" / "N matches" — the noun follows the search subtype. */
|
|
240
|
+
function searchCountLabel(count: number, kind: SearchView["kind"]): string {
|
|
241
|
+
if (kind === "files") {
|
|
242
|
+
return `${count} ${count === 1 ? "file" : "files"}`;
|
|
243
|
+
}
|
|
244
|
+
return `${count} ${count === 1 ? "match" : "matches"}`;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Renders a search result with a subtype-aware treatment.
|
|
249
|
+
*
|
|
250
|
+
* - **File-name search** (`kind: "files"` — glob / file_search): the matches are
|
|
251
|
+
* paths, rendered as a clickable {@link FilePathLink} list (filename-first,
|
|
252
|
+
* full path on hover, opens on GitHub or copies locally).
|
|
253
|
+
* - **Content search** (`kind: "content"` — grep): the matches are lines,
|
|
254
|
+
* grouped under their file with `line: text` rows; matches with no file
|
|
255
|
+
* association (the native grep shape) render as a flat monospace list.
|
|
256
|
+
*
|
|
257
|
+
* The count header uses the engine's authoritative `count` (which can exceed the
|
|
258
|
+
* returned matches when `truncated`), and a "showing first N" note makes a
|
|
259
|
+
* capped result honest instead of silently partial. Empty results name the
|
|
260
|
+
* subtype ("No files found" vs "No matches") — the query lives in the owning row
|
|
261
|
+
* header, so it is not restated here.
|
|
262
|
+
*/
|
|
263
263
|
function SearchResultView({
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
view,
|
|
265
|
+
showCount = true,
|
|
266
266
|
className,
|
|
267
267
|
}: {
|
|
268
|
-
|
|
269
|
-
|
|
268
|
+
view: SearchView;
|
|
269
|
+
showCount?: boolean;
|
|
270
270
|
className?: string;
|
|
271
271
|
}) {
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
const { matches, count, kind, truncated } = view;
|
|
273
|
+
|
|
274
|
+
if (count === 0 && matches.length === 0) {
|
|
275
|
+
return (
|
|
276
|
+
<p className={cn("text-xs text-muted-foreground", className)}>
|
|
277
|
+
{kind === "files" ? "No files found" : "No matches"}
|
|
278
|
+
</p>
|
|
279
|
+
);
|
|
274
280
|
}
|
|
281
|
+
|
|
282
|
+
// The owning row header already shows the count (summarizeResultView), so when
|
|
283
|
+
// suppressed the body shows only the truncation note — the one fact the header
|
|
284
|
+
// does not carry. When standalone (showCount), it leads with the full count.
|
|
285
|
+
const header = showCount
|
|
286
|
+
? `${searchCountLabel(count, kind)}${truncated ? ` \u00b7 showing first ${matches.length}` : ""}`
|
|
287
|
+
: truncated
|
|
288
|
+
? `Showing first ${matches.length} of ${count}`
|
|
289
|
+
: null;
|
|
290
|
+
|
|
275
291
|
return (
|
|
276
292
|
<div className={cn("space-y-1", className)}>
|
|
277
|
-
<span className="font-medium text-muted-foreground">
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
{matches
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
293
|
+
{header && <span className="font-medium text-muted-foreground">{header}</span>}
|
|
294
|
+
{kind === "files" ? (
|
|
295
|
+
<SearchFileList matches={matches} />
|
|
296
|
+
) : (
|
|
297
|
+
<SearchContentMatches matches={matches} />
|
|
298
|
+
)}
|
|
299
|
+
</div>
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Bounded, scrollable shell shared by both search result treatments. */
|
|
304
|
+
function SearchResultBox({ children }: { children: ReactNode }) {
|
|
305
|
+
return (
|
|
306
|
+
<div className="max-h-80 overflow-auto rounded-md border border-border bg-muted-subtle text-xs">
|
|
307
|
+
{children}
|
|
288
308
|
</div>
|
|
289
309
|
);
|
|
290
310
|
}
|
|
291
311
|
|
|
312
|
+
/** A clickable list of file-name search hits. */
|
|
313
|
+
function SearchFileList({ matches }: { matches: readonly ToolSearchMatch[] }) {
|
|
314
|
+
return (
|
|
315
|
+
<SearchResultBox>
|
|
316
|
+
{matches.map((m, i) => (
|
|
317
|
+
<div
|
|
318
|
+
key={i}
|
|
319
|
+
className="border-b border-border-muted px-2 py-0.5 last:border-b-0"
|
|
320
|
+
>
|
|
321
|
+
<FilePathLink path={m.file ?? m.text} dirDisplay="dim" className="text-xs" />
|
|
322
|
+
</div>
|
|
323
|
+
))}
|
|
324
|
+
</SearchResultBox>
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/** Content (grep) matches, grouped under their file when one is provided. */
|
|
329
|
+
function SearchContentMatches({ matches }: { matches: readonly ToolSearchMatch[] }) {
|
|
330
|
+
const groups = useMemo(() => groupMatchesByFile(matches), [matches]);
|
|
331
|
+
return (
|
|
332
|
+
<SearchResultBox>
|
|
333
|
+
{groups.map((group, gi) => (
|
|
334
|
+
<div key={gi} className="border-b border-border-muted last:border-b-0">
|
|
335
|
+
{group.file && (
|
|
336
|
+
<div className="bg-muted-faint px-2 py-0.5">
|
|
337
|
+
<FilePathLink path={group.file} dirDisplay="dim" className="text-xs" />
|
|
338
|
+
</div>
|
|
339
|
+
)}
|
|
340
|
+
{group.matches.map((m, i) => (
|
|
341
|
+
<div
|
|
342
|
+
key={i}
|
|
343
|
+
className="whitespace-pre-wrap break-words px-2 py-0.5 font-mono text-foreground"
|
|
344
|
+
>
|
|
345
|
+
{m.line !== undefined && (
|
|
346
|
+
<span className="select-none text-muted-foreground-subtle">{m.line}: </span>
|
|
347
|
+
)}
|
|
348
|
+
{m.text}
|
|
349
|
+
</div>
|
|
350
|
+
))}
|
|
351
|
+
</div>
|
|
352
|
+
))}
|
|
353
|
+
</SearchResultBox>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
interface MatchGroup {
|
|
358
|
+
readonly file?: string;
|
|
359
|
+
readonly matches: ToolSearchMatch[];
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Groups consecutive matches that share a file into one group, preserving order.
|
|
364
|
+
* Matches with no file association fall into their own file-less group so the
|
|
365
|
+
* native grep shape (line text only) still renders as a flat list.
|
|
366
|
+
*/
|
|
367
|
+
function groupMatchesByFile(matches: readonly ToolSearchMatch[]): MatchGroup[] {
|
|
368
|
+
const groups: MatchGroup[] = [];
|
|
369
|
+
for (const m of matches) {
|
|
370
|
+
const last = groups[groups.length - 1];
|
|
371
|
+
if (last && last.file === m.file) {
|
|
372
|
+
last.matches.push(m);
|
|
373
|
+
} else {
|
|
374
|
+
groups.push({ file: m.file, matches: [m] });
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return groups;
|
|
378
|
+
}
|
|
379
|
+
|
|
292
380
|
function ListResultView({
|
|
293
381
|
entries,
|
|
294
382
|
count,
|
|
383
|
+
showCount = true,
|
|
295
384
|
className,
|
|
296
385
|
}: {
|
|
297
386
|
entries: readonly string[];
|
|
298
387
|
count: number;
|
|
388
|
+
showCount?: boolean;
|
|
299
389
|
className?: string;
|
|
300
390
|
}) {
|
|
301
391
|
if (count === 0) {
|
|
@@ -303,9 +393,11 @@ function ListResultView({
|
|
|
303
393
|
}
|
|
304
394
|
return (
|
|
305
395
|
<div className={cn("space-y-1", className)}>
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
396
|
+
{showCount && (
|
|
397
|
+
<span className="font-medium text-muted-foreground">
|
|
398
|
+
{count} {count === 1 ? "item" : "items"}
|
|
399
|
+
</span>
|
|
400
|
+
)}
|
|
309
401
|
<div className="max-h-80 overflow-auto rounded-md border border-border bg-muted-subtle font-mono text-xs">
|
|
310
402
|
{entries.map((e, i) => (
|
|
311
403
|
<div key={i} className="truncate px-2 py-0.5 text-foreground">
|
|
@@ -323,17 +415,35 @@ function ListResultView({
|
|
|
323
415
|
|
|
324
416
|
type FileView = Extract<ToolResultView, { type: "file" }>;
|
|
325
417
|
|
|
326
|
-
function FileResultView({
|
|
418
|
+
function FileResultView({
|
|
419
|
+
view,
|
|
420
|
+
showFileName = true,
|
|
421
|
+
className,
|
|
422
|
+
}: {
|
|
423
|
+
view: FileView;
|
|
424
|
+
showFileName?: boolean;
|
|
425
|
+
className?: string;
|
|
426
|
+
}) {
|
|
327
427
|
if (!view.content) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
428
|
+
// No body. When the filename is shown elsewhere (showFileName=false), an
|
|
429
|
+
// empty write fallback degrades honestly to a neutral notice rather than a
|
|
430
|
+
// bare, redundant path; otherwise the path itself is the information (a read).
|
|
431
|
+
if (showFileName && view.path) {
|
|
432
|
+
return (
|
|
433
|
+
<div className={cn("flex items-center gap-1.5 text-xs", className)}>
|
|
434
|
+
<FilePathLink path={view.path} className="text-xs" />
|
|
435
|
+
</div>
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
return showFileName ? null : (
|
|
439
|
+
<EmptyChangeNotice kind="no-preview" className={className} />
|
|
440
|
+
);
|
|
333
441
|
}
|
|
334
442
|
return (
|
|
335
443
|
<div className={cn("space-y-1", className)}>
|
|
336
|
-
{
|
|
444
|
+
{showFileName && view.path && (
|
|
445
|
+
<FilePathLink path={view.path} className="text-xs" />
|
|
446
|
+
)}
|
|
337
447
|
<CollapsibleCode label={view.truncated ? "Content (truncated)" : "Content"} content={view.content} />
|
|
338
448
|
</div>
|
|
339
449
|
);
|
|
@@ -369,49 +479,110 @@ function formatBytes(n: number): string {
|
|
|
369
479
|
}
|
|
370
480
|
|
|
371
481
|
/**
|
|
372
|
-
* Renders a tool result whose bytes were offloaded to artifact storage.
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
482
|
+
* Renders a tool result whose bytes were offloaded to artifact storage. The
|
|
483
|
+
* bytes are resolved on demand from the stable `storageKey` at view time — the
|
|
484
|
+
* URL once baked into the persisted status expired after an hour, so it is no
|
|
485
|
+
* longer trusted. Images (e.g. computer-use screenshots) render inline via a
|
|
486
|
+
* freshly minted URL; other large output expands its full text in-app, with a
|
|
487
|
+
* download fallback when the server truncates it.
|
|
376
488
|
*/
|
|
377
489
|
function OutputRefResultView({ view, className }: { view: OutputRefView; className?: string }) {
|
|
378
490
|
if (view.isImage) {
|
|
491
|
+
return <OutputRefImage storageKey={view.storageKey} className={className} />;
|
|
492
|
+
}
|
|
493
|
+
return <OutputRefText view={view} className={className} />;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/** Offloaded image output, rendered from an always-fresh presigned URL. */
|
|
497
|
+
function OutputRefImage({ storageKey, className }: { storageKey: string; className?: string }) {
|
|
498
|
+
const executionId = useMemo(() => execIdFromStorageKey(storageKey), [storageKey]);
|
|
499
|
+
const { url, error } = useArtifactDownloadUrl(executionId, storageKey);
|
|
500
|
+
|
|
501
|
+
if (error) {
|
|
502
|
+
return <p className={cn("text-xs text-destructive", className)}>Couldn't load image output.</p>;
|
|
503
|
+
}
|
|
504
|
+
if (!url) {
|
|
379
505
|
return (
|
|
380
|
-
<div
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
className="inline-block focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
386
|
-
>
|
|
387
|
-
<img
|
|
388
|
-
src={view.downloadUrl}
|
|
389
|
-
alt="Tool output screenshot"
|
|
390
|
-
loading="lazy"
|
|
391
|
-
className="max-h-96 w-auto rounded-md border border-border"
|
|
392
|
-
/>
|
|
393
|
-
</a>
|
|
394
|
-
</div>
|
|
506
|
+
<div
|
|
507
|
+
className={cn("h-40 w-64 animate-pulse rounded-md border border-border bg-muted", className)}
|
|
508
|
+
aria-busy="true"
|
|
509
|
+
aria-label="Loading image output"
|
|
510
|
+
/>
|
|
395
511
|
);
|
|
396
512
|
}
|
|
397
|
-
|
|
398
513
|
return (
|
|
399
514
|
<div className={cn("space-y-1", className)}>
|
|
400
|
-
{view.preview && (
|
|
401
|
-
<CollapsiblePre content={view.preview} className="text-foreground" />
|
|
402
|
-
)}
|
|
403
515
|
<a
|
|
404
|
-
href={
|
|
516
|
+
href={url}
|
|
405
517
|
target="_blank"
|
|
406
518
|
rel="noreferrer"
|
|
407
|
-
className="inline-block
|
|
519
|
+
className="inline-block focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
408
520
|
>
|
|
409
|
-
|
|
521
|
+
<img
|
|
522
|
+
src={url}
|
|
523
|
+
alt="Tool output screenshot"
|
|
524
|
+
loading="lazy"
|
|
525
|
+
className="max-h-96 w-auto rounded-md border border-border"
|
|
526
|
+
/>
|
|
410
527
|
</a>
|
|
411
528
|
</div>
|
|
412
529
|
);
|
|
413
530
|
}
|
|
414
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Offloaded text output. Shows a preview head with a "View full output" toggle
|
|
534
|
+
* that lazily fetches the full content in-app (CORS-safe). If the server
|
|
535
|
+
* truncates it, offers a full download via a freshly minted URL.
|
|
536
|
+
*/
|
|
537
|
+
function OutputRefText({ view, className }: { view: OutputRefView; className?: string }) {
|
|
538
|
+
const [expanded, setExpanded] = useState(false);
|
|
539
|
+
const executionId = useMemo(() => execIdFromStorageKey(view.storageKey), [view.storageKey]);
|
|
540
|
+
const { content, isLoading, isTruncated, error } = useToolOutputContent(
|
|
541
|
+
{ storageKey: view.storageKey, contentHash: view.contentHash },
|
|
542
|
+
expanded,
|
|
543
|
+
);
|
|
544
|
+
const { download, isDownloading } = useArtifactDownload(executionId);
|
|
545
|
+
|
|
546
|
+
const sizeSuffix = view.sizeBytes ? ` (${formatBytes(view.sizeBytes)})` : "";
|
|
547
|
+
|
|
548
|
+
return (
|
|
549
|
+
<div className={cn("space-y-1", className)}>
|
|
550
|
+
{!expanded ? (
|
|
551
|
+
<>
|
|
552
|
+
{view.preview && (
|
|
553
|
+
<CollapsiblePre content={view.preview} className="text-foreground" />
|
|
554
|
+
)}
|
|
555
|
+
<button
|
|
556
|
+
type="button"
|
|
557
|
+
onClick={() => setExpanded(true)}
|
|
558
|
+
className="inline-block text-xs font-medium text-primary underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
559
|
+
>
|
|
560
|
+
View full output{sizeSuffix}
|
|
561
|
+
</button>
|
|
562
|
+
</>
|
|
563
|
+
) : isLoading ? (
|
|
564
|
+
<p className="text-xs text-muted-foreground">Loading full output…</p>
|
|
565
|
+
) : error ? (
|
|
566
|
+
<p className="text-xs text-destructive">Couldn't load full output. Try again.</p>
|
|
567
|
+
) : content !== null ? (
|
|
568
|
+
<div className="space-y-1">
|
|
569
|
+
<CollapsiblePre content={content} className="text-foreground" />
|
|
570
|
+
{isTruncated && (
|
|
571
|
+
<button
|
|
572
|
+
type="button"
|
|
573
|
+
onClick={() => download(view.storageKey)}
|
|
574
|
+
disabled={isDownloading}
|
|
575
|
+
className="inline-block text-xs font-medium text-primary underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50"
|
|
576
|
+
>
|
|
577
|
+
{isDownloading ? "Preparing download…" : `Output truncated — download full file${sizeSuffix}`}
|
|
578
|
+
</button>
|
|
579
|
+
)}
|
|
580
|
+
</div>
|
|
581
|
+
) : null}
|
|
582
|
+
</div>
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
415
586
|
function ErrorResultView({ message, className }: { message: string; className?: string }) {
|
|
416
587
|
return (
|
|
417
588
|
<div className={cn("space-y-1", className)}>
|