@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,82 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { renderHook } from "@testing-library/react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import { ToolCallOutputRefSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
5
|
+
import type { UseArtifactContentReturn } from "../useArtifactContent";
|
|
6
|
+
|
|
7
|
+
// Mock the underlying content fetch so the test asserts the derivation logic
|
|
8
|
+
// (execId from storageKey) and the lazy `enabled` gate, not the network.
|
|
9
|
+
const responses = new Map<string, Partial<UseArtifactContentReturn>>();
|
|
10
|
+
const calls: Array<{
|
|
11
|
+
executionId: string | null;
|
|
12
|
+
storageKey: string | null;
|
|
13
|
+
contentHash?: string;
|
|
14
|
+
}> = [];
|
|
15
|
+
|
|
16
|
+
vi.mock("../useArtifactContent", () => ({
|
|
17
|
+
useArtifactContent: (
|
|
18
|
+
executionId: string | null,
|
|
19
|
+
storageKey: string | null,
|
|
20
|
+
_entryPath?: string | null,
|
|
21
|
+
contentHash?: string,
|
|
22
|
+
) => {
|
|
23
|
+
calls.push({ executionId, storageKey, contentHash });
|
|
24
|
+
const base: UseArtifactContentReturn = {
|
|
25
|
+
content: null,
|
|
26
|
+
contentType: null,
|
|
27
|
+
isTruncated: false,
|
|
28
|
+
isLoading: false,
|
|
29
|
+
isRefetching: false,
|
|
30
|
+
error: null,
|
|
31
|
+
refetch: () => {},
|
|
32
|
+
};
|
|
33
|
+
if (!storageKey) return base;
|
|
34
|
+
return { ...base, ...responses.get(storageKey) };
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
const { useToolOutputContent } = await import("../useToolOutputContent");
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
responses.clear();
|
|
42
|
+
calls.length = 0;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
function ref(storageKey: string, contentHash = "h") {
|
|
46
|
+
return create(ToolCallOutputRefSchema, { storageKey, contentHash });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe("useToolOutputContent", () => {
|
|
50
|
+
it("stays idle until enabled (lazy expand)", () => {
|
|
51
|
+
const { result } = renderHook(() =>
|
|
52
|
+
useToolOutputContent(ref("artifacts/exec-1/toolcalls/tc.txt"), false),
|
|
53
|
+
);
|
|
54
|
+
expect(result.current.content).toBeNull();
|
|
55
|
+
// The underlying fetch is skipped (null storage key passed through).
|
|
56
|
+
expect(calls.every((c) => c.storageKey === null)).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("derives the execId from the storage key and fetches when enabled", () => {
|
|
60
|
+
const key = "artifacts/exec-9/toolcalls/tc.txt";
|
|
61
|
+
responses.set(key, { content: "FULL", isTruncated: false });
|
|
62
|
+
const { result } = renderHook(() => useToolOutputContent(ref(key), true));
|
|
63
|
+
|
|
64
|
+
expect(result.current.content).toBe("FULL");
|
|
65
|
+
const call = calls.find((c) => c.storageKey === key);
|
|
66
|
+
expect(call?.executionId).toBe("exec-9");
|
|
67
|
+
expect(call?.contentHash).toBe("h");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("passes through truncation", () => {
|
|
71
|
+
const key = "artifacts/exec-9/toolcalls/tc.txt";
|
|
72
|
+
responses.set(key, { content: "head", isTruncated: true });
|
|
73
|
+
const { result } = renderHook(() => useToolOutputContent(ref(key), true));
|
|
74
|
+
expect(result.current.isTruncated).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("skips when the ref is null", () => {
|
|
78
|
+
const { result } = renderHook(() => useToolOutputContent(null, true));
|
|
79
|
+
expect(result.current.content).toBeNull();
|
|
80
|
+
expect(calls.every((c) => c.storageKey === null)).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Re-export the framework-agnostic provenance label from @stigmer/sdk so the
|
|
2
|
+
// React surface (ApprovalCard "why-gated" line, ToolCallDetail) shares one
|
|
3
|
+
// source of truth with @stigmer/ink and the Go CLI. See the sdk module for the
|
|
4
|
+
// mapping rationale.
|
|
5
|
+
export {
|
|
6
|
+
describeApprovalPolicySource,
|
|
7
|
+
isInformativePolicySource,
|
|
8
|
+
} from "@stigmer/sdk";
|
|
@@ -80,24 +80,6 @@ export function isTextArtifact(artifact: ExecutionArtifact): boolean {
|
|
|
80
80
|
return TEXT_EXTENSIONS.has(ext);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
/**
|
|
84
|
-
* Checks whether an artifact's pre-signed download URL has expired.
|
|
85
|
-
*
|
|
86
|
-
* Returns `true` when:
|
|
87
|
-
* - `expiresAt` is empty or cannot be parsed as a valid date
|
|
88
|
-
* - The current time is past the expiration timestamp
|
|
89
|
-
*
|
|
90
|
-
* Expired URLs can be refreshed via `stigmer.agentExecution.getArtifactDownloadUrl()`.
|
|
91
|
-
*/
|
|
92
|
-
export function isArtifactExpired(artifact: ExecutionArtifact): boolean {
|
|
93
|
-
if (!artifact.expiresAt) return true;
|
|
94
|
-
|
|
95
|
-
const expiresMs = Date.parse(artifact.expiresAt);
|
|
96
|
-
if (Number.isNaN(expiresMs)) return true;
|
|
97
|
-
|
|
98
|
-
return Date.now() >= expiresMs;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
83
|
// ---------------------------------------------------------------------------
|
|
102
84
|
// Render mode classification
|
|
103
85
|
// ---------------------------------------------------------------------------
|
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ExecutionPhase.EXECUTION_FAILED,
|
|
6
|
-
ExecutionPhase.EXECUTION_CANCELLED,
|
|
7
|
-
ExecutionPhase.EXECUTION_TERMINATED,
|
|
8
|
-
]);
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Returns `true` when the given phase represents a final, immutable
|
|
12
|
-
* execution state — no further updates will arrive from the server.
|
|
13
|
-
*/
|
|
14
|
-
export function isTerminalPhase(phase: ExecutionPhase): boolean {
|
|
15
|
-
return TERMINAL_PHASES.has(phase);
|
|
16
|
-
}
|
|
1
|
+
// Re-export the framework-agnostic execution-phase predicates from @stigmer/sdk
|
|
2
|
+
// so the React surface shares one source of truth with @stigmer/ink and the pure
|
|
3
|
+
// SDK logic (e.g. the file-review fold). See the sdk module for the definitions.
|
|
4
|
+
export { isTerminalPhase } from "@stigmer/sdk";
|
|
@@ -41,6 +41,44 @@ export function classifyPath(path: string): PathClassification {
|
|
|
41
41
|
return { kind: "workspace", remainder: clean };
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/** A file path split into its directory prefix and final segment for display. */
|
|
45
|
+
export interface DisplayPath {
|
|
46
|
+
/**
|
|
47
|
+
* The directory portion including the trailing slash (e.g. `"src/app/"`), or
|
|
48
|
+
* `""` when the path has no directory. Rendered dimmed and allowed to
|
|
49
|
+
* truncate — it is context, not identity.
|
|
50
|
+
*/
|
|
51
|
+
readonly dir: string;
|
|
52
|
+
/**
|
|
53
|
+
* The final path segment — the file name (e.g. `"main.ts"`). This is the
|
|
54
|
+
* identity of the change and must never be clipped.
|
|
55
|
+
*/
|
|
56
|
+
readonly base: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Splits a file path into `{ dir, base }` for filename-first display.
|
|
61
|
+
*
|
|
62
|
+
* The motivation: a raw tool-call path is frequently an absolute, deeply-nested
|
|
63
|
+
* string (`/Users/me/scm/.../notes.md`), and naive CSS `truncate` on the whole
|
|
64
|
+
* path clips the *end* — hiding the file name, the one part that identifies the
|
|
65
|
+
* change. Splitting lets the renderer keep the base name always visible and
|
|
66
|
+
* truncate only the (dimmed) directory.
|
|
67
|
+
*
|
|
68
|
+
* Pure (no React) so it is unit-testable in isolation and reusable by any
|
|
69
|
+
* surface. A trailing slash is tolerated (a directory path keeps its last
|
|
70
|
+
* segment as the base); a path with no slash is all base.
|
|
71
|
+
*/
|
|
72
|
+
export function splitDisplayPath(path: string): DisplayPath {
|
|
73
|
+
if (!path) return { dir: "", base: "" };
|
|
74
|
+
const trimmed = path.replace(/\/+$/, "");
|
|
75
|
+
const idx = trimmed.lastIndexOf("/");
|
|
76
|
+
if (idx < 0) return { dir: "", base: trimmed };
|
|
77
|
+
const base = trimmed.slice(idx + 1);
|
|
78
|
+
// A path that was only slashes collapses to the original — never an empty base.
|
|
79
|
+
return base ? { dir: trimmed.slice(0, idx + 1), base } : { dir: "", base: trimmed };
|
|
80
|
+
}
|
|
81
|
+
|
|
44
82
|
/**
|
|
45
83
|
* Constructs a browsable GitHub blob URL from a git clone URL.
|
|
46
84
|
*
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CapturedFileChange,
|
|
3
|
+
FileChangeSet,
|
|
4
|
+
FileDecision,
|
|
5
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
|
|
6
|
+
import {
|
|
7
|
+
DiffCompleteness,
|
|
8
|
+
FileChangeSetStatus,
|
|
9
|
+
FileDecisionAction,
|
|
10
|
+
FileDecisionScope,
|
|
11
|
+
FileReviewBlockReason,
|
|
12
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Why an `"unavailable"` file cannot be reviewed — the honest per-file cause the
|
|
16
|
+
* runner records on `CapturedFileChange.blocked_reason` (design doc 15).
|
|
17
|
+
*
|
|
18
|
+
* - `"secret"` — the path looks like a secret; the bytes were deliberately never
|
|
19
|
+
* captured (there is nothing to review, by design).
|
|
20
|
+
* - `"size"` — the diff was captured but its bodies were dropped to keep the
|
|
21
|
+
* persisted status under its size limit.
|
|
22
|
+
* - `"unknown"` — incomplete for a reason the wire does not name (a defensive
|
|
23
|
+
* catch-all; historical rows and future/unmapped causes land here).
|
|
24
|
+
*/
|
|
25
|
+
export type FileBlockReason = "secret" | "size" | "unknown";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* How completely a single captured file change can be reviewed before a decision
|
|
29
|
+
* is made — the classification that decides whether a file can be kept. A
|
|
30
|
+
* discriminated union so every consumer handles each case exhaustively and reads
|
|
31
|
+
* the block reason from one place (no "classify, then separately look up why").
|
|
32
|
+
*
|
|
33
|
+
* - `{ kind: "reviewable" }` — the full before/after diff is available; the
|
|
34
|
+
* reviewer can see exactly what changed and Keep or Discard it.
|
|
35
|
+
* - `{ kind: "binary" }` — a binary file changed; there is no text diff to
|
|
36
|
+
* review (the bytes are captured and flagged, but a byte diff is not
|
|
37
|
+
* human-reviewable). Binary is proven by `FileContent.is_binary`, not by the
|
|
38
|
+
* block reason.
|
|
39
|
+
* - `{ kind: "unavailable"; reason }` — the diff is not available to review at
|
|
40
|
+
* all, with the honest {@link FileBlockReason} the runner recorded.
|
|
41
|
+
*
|
|
42
|
+
* Both `"binary"` and `"unavailable"` are non-reviewable: the file cannot be
|
|
43
|
+
* approved (kept), only discarded. This mirrors the server, which blocks
|
|
44
|
+
* approval of any change set that is not fully complete.
|
|
45
|
+
*/
|
|
46
|
+
export type FileReviewability =
|
|
47
|
+
| { readonly kind: "reviewable" }
|
|
48
|
+
| { readonly kind: "binary" }
|
|
49
|
+
| { readonly kind: "unavailable"; readonly reason: FileBlockReason };
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Classify a {@link CapturedFileChange} by how completely it can be reviewed,
|
|
53
|
+
* from the signals the runner authors onto the change (see the file-review
|
|
54
|
+
* producer in the runner's `shared/filereview`).
|
|
55
|
+
*
|
|
56
|
+
* The mapping is derived from three proto signals, in order:
|
|
57
|
+
*
|
|
58
|
+
* 1. `diff_complete === true` → `"reviewable"`. The change set can only be
|
|
59
|
+
* `COMPLETE` when every file is complete, so a complete file is always
|
|
60
|
+
* reviewable.
|
|
61
|
+
* 2. otherwise, a binary side (`before.is_binary` or `after.is_binary`) →
|
|
62
|
+
* `"binary"`. The runner marks a git-tracked file incomplete precisely
|
|
63
|
+
* because a side is binary (`diff_complete = !binary`); a CAS file carries
|
|
64
|
+
* `is_binary` on its blob ref. `is_binary` is preserved when a large body is
|
|
65
|
+
* offloaded from an inline value to a storage ref, so this holds regardless
|
|
66
|
+
* of offload. Binary is therefore derived here, never duplicated onto the
|
|
67
|
+
* block reason (doc 15).
|
|
68
|
+
* 3. otherwise → `"unavailable"` with the honest cause from
|
|
69
|
+
* `blocked_reason`: `SECRET_WITHHELD → "secret"`, `SIZE_ELIDED → "size"`,
|
|
70
|
+
* else `"unknown"`. Before doc 15 this bucket was cause-agnostic (the wire
|
|
71
|
+
* could not prove secret-withheld vs size-dropped); the runner now records
|
|
72
|
+
* the cause at capture time, so the UI can say *why* rather than only *that*
|
|
73
|
+
* the diff is unavailable.
|
|
74
|
+
*/
|
|
75
|
+
export function fileReviewability(change: CapturedFileChange): FileReviewability {
|
|
76
|
+
if (change.diffComplete) return { kind: "reviewable" };
|
|
77
|
+
if (change.before?.isBinary || change.after?.isBinary) return { kind: "binary" };
|
|
78
|
+
return { kind: "unavailable", reason: blockReasonOf(change.blockedReason) };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Map the proto {@link FileReviewBlockReason} to the UI {@link FileBlockReason}. */
|
|
82
|
+
function blockReasonOf(reason: FileReviewBlockReason): FileBlockReason {
|
|
83
|
+
switch (reason) {
|
|
84
|
+
case FileReviewBlockReason.SECRET_WITHHELD:
|
|
85
|
+
return "secret";
|
|
86
|
+
case FileReviewBlockReason.SIZE_ELIDED:
|
|
87
|
+
return "size";
|
|
88
|
+
default:
|
|
89
|
+
return "unknown";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* How completely a whole {@link FileChangeSet} can be reviewed — the set-level
|
|
95
|
+
* sibling of {@link FileReviewability} that decides whether the set can be kept
|
|
96
|
+
* in one action. Drives the card's bulk affordance and keeps headless builders
|
|
97
|
+
* on the same classification.
|
|
98
|
+
*
|
|
99
|
+
* - `"complete"` — every file is reviewable; the set can be approved as-is.
|
|
100
|
+
* - `"binary-only"` — the set's ONLY blocker is binary files (every non-binary
|
|
101
|
+
* file is fully reviewable). No text diff for the binaries, but their exact
|
|
102
|
+
* bytes are captured and reconcilable, so the whole set can be KEPT in one
|
|
103
|
+
* acknowledged action ("Keep all"). Includes mixed sets (text edits + images).
|
|
104
|
+
* - `"blocked"` — at least one file is unavailable to review with no keepable
|
|
105
|
+
* bytes (secret-withheld / size-elided / uncapturable), so the set cannot be
|
|
106
|
+
* approved at once; it must be resolved per file.
|
|
107
|
+
*/
|
|
108
|
+
export type ChangeSetReviewability = "complete" | "binary-only" | "blocked";
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Classify a {@link FileChangeSet} from its server-derived `diff_completeness`
|
|
112
|
+
* rollup (the field exists precisely so clients need not re-fold the per-file
|
|
113
|
+
* signals). The runner and the size backstop both derive that value from the
|
|
114
|
+
* same rule the backend gate re-checks, so this classification, the per-file
|
|
115
|
+
* {@link fileReviewability} fold, and the server gate agree by construction.
|
|
116
|
+
*/
|
|
117
|
+
export function changeSetReviewability(set: FileChangeSet): ChangeSetReviewability {
|
|
118
|
+
switch (set.diffCompleteness) {
|
|
119
|
+
case DiffCompleteness.COMPLETE:
|
|
120
|
+
return "complete";
|
|
121
|
+
case DiffCompleteness.BINARY_SUMMARY_ONLY:
|
|
122
|
+
return "binary-only";
|
|
123
|
+
default:
|
|
124
|
+
return "blocked";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Each file's EFFECTIVE verdict for a settled set, folding the decisions the
|
|
130
|
+
* way the runner reconcile does (most-specific-wins): the last CHANGE_SET
|
|
131
|
+
* decision is the baseline for every file, and a later-or-earlier FILE decision
|
|
132
|
+
* overrides it for that file (FILE > CHANGE_SET regardless of ledger order;
|
|
133
|
+
* within a scope, last write wins).
|
|
134
|
+
*
|
|
135
|
+
* This is the fold for DISPLAYING history — a set decided via "Keep all"
|
|
136
|
+
* correctly reads every file as kept. The interactive per-file selected state
|
|
137
|
+
* deliberately uses the FILE-only fold instead (a CHANGE_SET decision cannot
|
|
138
|
+
* coexist with an open review, so it never pre-selects anything there).
|
|
139
|
+
*/
|
|
140
|
+
export function deriveEffectiveVerdicts(
|
|
141
|
+
set: FileChangeSet,
|
|
142
|
+
): ReadonlyMap<string, FileDecisionAction> {
|
|
143
|
+
let bulk: FileDecisionAction | null = null;
|
|
144
|
+
const byFileId = new Map<string, FileDecisionAction>();
|
|
145
|
+
for (const d of set.decisions as readonly FileDecision[]) {
|
|
146
|
+
if (d.scope === FileDecisionScope.CHANGE_SET) bulk = d.action;
|
|
147
|
+
else if (d.scope === FileDecisionScope.FILE && d.fileChangeId) {
|
|
148
|
+
byFileId.set(d.fileChangeId, d.action);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const effective = new Map<string, FileDecisionAction>();
|
|
152
|
+
for (const c of set.changes) {
|
|
153
|
+
const verdict = byFileId.get(c.id) ?? bulk;
|
|
154
|
+
if (verdict != null) effective.set(c.id, verdict);
|
|
155
|
+
}
|
|
156
|
+
return effective;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The captured change a transcript row's file path refers to, or `null`. The
|
|
161
|
+
* row's path may be absolute (harness tool args) while captured paths are
|
|
162
|
+
* workspace-root-relative, so the match accepts an exact match or a
|
|
163
|
+
* `/`-boundary suffix. Presentation-only — never a correlation key.
|
|
164
|
+
*/
|
|
165
|
+
export function changeForRowPath(
|
|
166
|
+
set: FileChangeSet,
|
|
167
|
+
rowPath: string,
|
|
168
|
+
): CapturedFileChange | null {
|
|
169
|
+
if (!rowPath) return null;
|
|
170
|
+
const normalized = rowPath.replace(/\\/g, "/");
|
|
171
|
+
for (const c of set.changes) {
|
|
172
|
+
const path = c.pathAfter || c.pathBefore;
|
|
173
|
+
if (path && (normalized === path || normalized.endsWith(`/${path}`))) {
|
|
174
|
+
return c;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The review state a stamped transcript row should badge — how this file edit
|
|
182
|
+
* stands in its change set's review lifecycle. `null` means "show no badge",
|
|
183
|
+
* chosen over guessing: a missing set (not yet projected), a CAPTURING set, or
|
|
184
|
+
* a row whose file is absent from the set (its edit was superseded or fully
|
|
185
|
+
* reverted within the turn) renders unbadged, never mislabeled.
|
|
186
|
+
*
|
|
187
|
+
* - `"pending"` — the set is AWAITING_REVIEW; this edit's net result is on the
|
|
188
|
+
* decision surface now.
|
|
189
|
+
* - `"kept"` / `"discarded"` — the set is decided/reconciled and this file's
|
|
190
|
+
* effective verdict is known ({@link deriveEffectiveVerdicts}).
|
|
191
|
+
* - `"failed"` — the set's reconcile failed; the workspace outcome for this
|
|
192
|
+
* edit is not the reviewed one.
|
|
193
|
+
*/
|
|
194
|
+
export type FileReviewRowState = "pending" | "kept" | "discarded" | "failed";
|
|
195
|
+
|
|
196
|
+
export function fileReviewRowState(
|
|
197
|
+
set: FileChangeSet | undefined,
|
|
198
|
+
rowPath: string | null,
|
|
199
|
+
): FileReviewRowState | null {
|
|
200
|
+
if (!set) return null;
|
|
201
|
+
switch (set.status) {
|
|
202
|
+
case FileChangeSetStatus.AWAITING_REVIEW:
|
|
203
|
+
return "pending";
|
|
204
|
+
case FileChangeSetStatus.FAILED:
|
|
205
|
+
return "failed";
|
|
206
|
+
case FileChangeSetStatus.DECIDED:
|
|
207
|
+
case FileChangeSetStatus.RECONCILED: {
|
|
208
|
+
if (!rowPath) return null;
|
|
209
|
+
const change = changeForRowPath(set, rowPath);
|
|
210
|
+
if (!change) return null;
|
|
211
|
+
const verdict = deriveEffectiveVerdicts(set).get(change.id);
|
|
212
|
+
if (verdict === FileDecisionAction.APPROVE) return "kept";
|
|
213
|
+
if (verdict === FileDecisionAction.REJECT) return "discarded";
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
default:
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
package/src/execution/index.ts
CHANGED
|
@@ -47,15 +47,38 @@ export type { UseExecutionArtifactsReturn } from "./useExecutionArtifacts";
|
|
|
47
47
|
export { useArtifactContent } from "./useArtifactContent";
|
|
48
48
|
export type { UseArtifactContentReturn } from "./useArtifactContent";
|
|
49
49
|
|
|
50
|
+
export { useArtifactDownloadUrl } from "./useArtifactDownloadUrl";
|
|
51
|
+
export type {
|
|
52
|
+
UseArtifactDownloadUrlReturn,
|
|
53
|
+
UseArtifactDownloadUrlOptions,
|
|
54
|
+
} from "./useArtifactDownloadUrl";
|
|
55
|
+
|
|
56
|
+
export { useArtifactDownload } from "./useArtifactDownload";
|
|
57
|
+
export type { UseArtifactDownloadReturn } from "./useArtifactDownload";
|
|
58
|
+
|
|
59
|
+
export { useToolOutputContent } from "./useToolOutputContent";
|
|
60
|
+
export type {
|
|
61
|
+
UseToolOutputContentReturn,
|
|
62
|
+
ToolOutputRefLike,
|
|
63
|
+
} from "./useToolOutputContent";
|
|
64
|
+
|
|
65
|
+
export { useFileChangeContent, execIdFromStorageKey } from "./useFileChangeContent";
|
|
66
|
+
export type { UseFileChangeContentReturn } from "./useFileChangeContent";
|
|
67
|
+
|
|
50
68
|
export { useWorkspaceWriteBacks } from "./useWorkspaceWriteBacks";
|
|
51
69
|
export type { UseWorkspaceWriteBacksReturn } from "./useWorkspaceWriteBacks";
|
|
52
70
|
|
|
53
71
|
export { WriteBackCard } from "./WriteBackCard";
|
|
54
72
|
export type { WriteBackCardProps } from "./WriteBackCard";
|
|
55
73
|
|
|
74
|
+
export { FileChangesView, FileChangeDiff } from "./FileChangesView";
|
|
75
|
+
export type { FileChangesViewProps, FileChangeDiffProps } from "./FileChangesView";
|
|
76
|
+
|
|
77
|
+
export { EmptyChangeNotice } from "./EmptyChangeNotice";
|
|
78
|
+
export type { EmptyChangeNoticeProps, EmptyChangeKind } from "./EmptyChangeNotice";
|
|
79
|
+
|
|
56
80
|
export {
|
|
57
81
|
isTextArtifact,
|
|
58
|
-
isArtifactExpired,
|
|
59
82
|
formatArtifactSize,
|
|
60
83
|
getArtifactExtension,
|
|
61
84
|
getFileExtension,
|
|
@@ -75,9 +98,17 @@ export type { SetupProgressProps } from "./SetupProgress";
|
|
|
75
98
|
export { ToolCallGroup } from "./ToolCallGroup";
|
|
76
99
|
export type { ToolCallGroupProps } from "./ToolCallGroup";
|
|
77
100
|
|
|
101
|
+
export { ToolRunGroup } from "./ToolRunGroup";
|
|
102
|
+
export type { ToolRunGroupProps } from "./ToolRunGroup";
|
|
103
|
+
|
|
104
|
+
export { segmentToolCalls } from "./segment-tool-calls";
|
|
105
|
+
export type { ToolSegment } from "./segment-tool-calls";
|
|
106
|
+
|
|
78
107
|
export { ToolCallDetail, formatDuration } from "./ToolCallDetail";
|
|
79
108
|
export type { ToolCallDetailProps } from "./ToolCallDetail";
|
|
80
109
|
|
|
110
|
+
export { describeApprovalPolicySource } from "./approval-provenance";
|
|
111
|
+
|
|
81
112
|
export { McpToolDetail, McpArgsView, McpMetadataRow, parseMcpResult } from "./McpToolDetail";
|
|
82
113
|
export type {
|
|
83
114
|
McpToolDetailProps,
|
|
@@ -91,6 +122,9 @@ export type { ToolArgsViewProps } from "./ToolArgsView";
|
|
|
91
122
|
export { ResultView, summarizeResultView } from "./ResultView";
|
|
92
123
|
export type { ResultViewProps } from "./ResultView";
|
|
93
124
|
|
|
125
|
+
export { TerminalSession } from "./TerminalSession";
|
|
126
|
+
export type { TerminalSessionProps } from "./TerminalSession";
|
|
127
|
+
|
|
94
128
|
export {
|
|
95
129
|
useToolPresentation,
|
|
96
130
|
registerToolPresenter,
|
|
@@ -145,12 +179,56 @@ export {
|
|
|
145
179
|
} from "./TodoList";
|
|
146
180
|
export type { TodoListProps } from "./TodoList";
|
|
147
181
|
|
|
182
|
+
export { TodoCard } from "./TodoCard";
|
|
183
|
+
export type { TodoCardProps } from "./TodoCard";
|
|
184
|
+
|
|
148
185
|
|
|
149
186
|
export { useSubmitApproval } from "./useSubmitApproval";
|
|
150
187
|
export type { UseSubmitApprovalReturn } from "./useSubmitApproval";
|
|
151
188
|
|
|
152
|
-
export {
|
|
153
|
-
export type {
|
|
189
|
+
export { useFileReview, fileDecisionKey } from "./useFileReview";
|
|
190
|
+
export type { UseFileReviewReturn, FileDecisionOptions } from "./useFileReview";
|
|
191
|
+
|
|
192
|
+
export {
|
|
193
|
+
fileReviewability,
|
|
194
|
+
changeSetReviewability,
|
|
195
|
+
deriveEffectiveVerdicts,
|
|
196
|
+
changeForRowPath,
|
|
197
|
+
fileReviewRowState,
|
|
198
|
+
} from "./file-review-status";
|
|
199
|
+
export type {
|
|
200
|
+
FileReviewability,
|
|
201
|
+
FileBlockReason,
|
|
202
|
+
ChangeSetReviewability,
|
|
203
|
+
FileReviewRowState,
|
|
204
|
+
} from "./file-review-status";
|
|
205
|
+
|
|
206
|
+
// Settled/historical file-review display: the ledger fold + its read seam +
|
|
207
|
+
// the display-projection adapter, re-exported from @stigmer/sdk (pure, shared).
|
|
208
|
+
export {
|
|
209
|
+
foldFileReviewEventStream,
|
|
210
|
+
displayFileChangeSets,
|
|
211
|
+
toDisplayFileChange,
|
|
212
|
+
} from "@stigmer/sdk";
|
|
213
|
+
|
|
214
|
+
export { ApprovalCard, ApprovalCardHeader, ApprovalCardBody } from "./ApprovalCard";
|
|
215
|
+
export type {
|
|
216
|
+
ApprovalCardProps,
|
|
217
|
+
ApprovalCardHeaderProps,
|
|
218
|
+
ApprovalCardBodyProps,
|
|
219
|
+
} from "./ApprovalCard";
|
|
220
|
+
|
|
221
|
+
export { FileReviewCard } from "./FileReviewCard";
|
|
222
|
+
export type { FileReviewCardProps } from "./FileReviewCard";
|
|
223
|
+
|
|
224
|
+
export { FileReviewDock } from "./FileReviewDock";
|
|
225
|
+
export type { FileReviewDockProps } from "./FileReviewDock";
|
|
226
|
+
|
|
227
|
+
export { ApprovalContext, useApproval } from "./ApprovalContext";
|
|
228
|
+
export type { ApprovalContextValue, UseApprovalResult } from "./ApprovalContext";
|
|
229
|
+
|
|
230
|
+
export { FileReviewContext, useFileReviewRowState } from "./FileReviewContext";
|
|
231
|
+
export type { FileReviewContextValue } from "./FileReviewContext";
|
|
154
232
|
|
|
155
233
|
export { ArtifactCard } from "./ArtifactCard";
|
|
156
234
|
export type { ArtifactCardProps } from "./ArtifactCard";
|
|
@@ -175,8 +253,10 @@ export {
|
|
|
175
253
|
extractPrimaryArg,
|
|
176
254
|
extractPrimaryArgFromPreview,
|
|
177
255
|
humanizeToolName,
|
|
256
|
+
defaultDisclosureForCategory,
|
|
257
|
+
isRunGroupableCategory,
|
|
178
258
|
} from "./tool-categories";
|
|
179
|
-
export type { ToolCategory, ToolCategoryInfo } from "./tool-categories";
|
|
259
|
+
export type { ToolCategory, ToolCategoryInfo, ToolDisclosure } from "./tool-categories";
|
|
180
260
|
|
|
181
261
|
export { FilePathLink } from "./FilePathLink";
|
|
182
262
|
export type { FilePathLinkProps } from "./FilePathLink";
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
2
|
+
import { resolveToolCategoryFromCall } from "./tool-categories";
|
|
3
|
+
import type { ToolCategory } from "./tool-categories";
|
|
4
|
+
import { resolveRunGroupable } from "./tool-presenter";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Minimum number of consecutive same-category groupable calls before they fold
|
|
8
|
+
* into a chip. A lone groupable call (e.g. a single `Read foo.ts`) reads better
|
|
9
|
+
* as its own row than as a one-item "Read 1 file" chip, so grouping only kicks
|
|
10
|
+
* in at two or more.
|
|
11
|
+
*/
|
|
12
|
+
const MIN_RUN_LENGTH = 2;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* One renderable unit of a turn's tool activity.
|
|
16
|
+
*
|
|
17
|
+
* - `row` — a single tool call rendered as a persistent timeline row.
|
|
18
|
+
* - `run` — a maximal run of >= {@link MIN_RUN_LENGTH} consecutive low-signal
|
|
19
|
+
* same-category calls (e.g. reads), folded into one collapsible chip.
|
|
20
|
+
*/
|
|
21
|
+
export type ToolSegment =
|
|
22
|
+
| { readonly kind: "row"; readonly toolCall: ToolCall; readonly key: string }
|
|
23
|
+
| {
|
|
24
|
+
readonly kind: "run";
|
|
25
|
+
readonly category: ToolCategory;
|
|
26
|
+
readonly toolCalls: readonly ToolCall[];
|
|
27
|
+
readonly key: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Stable key for a single tool-call row (mirrors the prior group keying). */
|
|
31
|
+
function rowKey(toolCall: ToolCall): string {
|
|
32
|
+
return toolCall.id || toolCall.name;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Partitions a turn's tool calls into a chronological sequence of {@link
|
|
37
|
+
* ToolSegment}s: maximal runs of consecutive low-signal same-category calls
|
|
38
|
+
* (read / list / search) fold into one `run` chip, while every other call —
|
|
39
|
+
* and any groupable call that has no same-kind neighbour — stays a persistent
|
|
40
|
+
* `row`.
|
|
41
|
+
*
|
|
42
|
+
* This is the layout pass behind the "persistent-row timeline": instead of
|
|
43
|
+
* hiding a whole turn behind one collapse, only repetitive noise is compressed,
|
|
44
|
+
* and high-signal rows (edits, shell, MCP, sub-agents) always remain visible.
|
|
45
|
+
* Chronology is preserved — a run never reorders calls, and an interleaving of
|
|
46
|
+
* categories (read, search, read) yields three separate segments, not one.
|
|
47
|
+
*
|
|
48
|
+
* Pure and dependency-light so it can be unit-tested exhaustively and memoized
|
|
49
|
+
* by the caller; groupability is resolved through {@link resolveRunGroupable},
|
|
50
|
+
* so a consumer's registry override is honoured here exactly as in the
|
|
51
|
+
* component layer.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // read, read, read, edit -> [run(read x3), row(edit)]
|
|
56
|
+
* // read, search, read -> [row(read), row(search), row(read)]
|
|
57
|
+
* const segments = segmentToolCalls(message.toolCalls);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function segmentToolCalls(
|
|
61
|
+
toolCalls: readonly ToolCall[],
|
|
62
|
+
): ToolSegment[] {
|
|
63
|
+
const segments: ToolSegment[] = [];
|
|
64
|
+
|
|
65
|
+
// Resolve category + groupability once per call so the scan below is a cheap
|
|
66
|
+
// index walk rather than repeated kind resolution.
|
|
67
|
+
const categories = toolCalls.map(
|
|
68
|
+
(tc) => resolveToolCategoryFromCall(tc).category,
|
|
69
|
+
);
|
|
70
|
+
const groupable = toolCalls.map((tc) => resolveRunGroupable(tc));
|
|
71
|
+
|
|
72
|
+
let i = 0;
|
|
73
|
+
while (i < toolCalls.length) {
|
|
74
|
+
const category = categories[i];
|
|
75
|
+
|
|
76
|
+
if (groupable[i]) {
|
|
77
|
+
// Extend the run while the next call is the same groupable category.
|
|
78
|
+
let j = i + 1;
|
|
79
|
+
while (j < toolCalls.length && groupable[j] && categories[j] === category) {
|
|
80
|
+
j++;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (j - i >= MIN_RUN_LENGTH) {
|
|
84
|
+
const run = toolCalls.slice(i, j);
|
|
85
|
+
segments.push({
|
|
86
|
+
kind: "run",
|
|
87
|
+
category,
|
|
88
|
+
toolCalls: run,
|
|
89
|
+
key: `run-${category}-${rowKey(run[0])}`,
|
|
90
|
+
});
|
|
91
|
+
i = j;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
segments.push({ kind: "row", toolCall: toolCalls[i], key: rowKey(toolCalls[i]) });
|
|
97
|
+
i++;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return segments;
|
|
101
|
+
}
|