@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,149 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import { render, cleanup } from "@testing-library/react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import {
|
|
5
|
+
AgentExecutionSchema,
|
|
6
|
+
AgentExecutionStatusSchema,
|
|
7
|
+
type AgentExecution,
|
|
8
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
9
|
+
import { AgentExecutionSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
|
|
10
|
+
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
11
|
+
import {
|
|
12
|
+
AgentMessageSchema,
|
|
13
|
+
ToolCallSchema,
|
|
14
|
+
type AgentMessage,
|
|
15
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
16
|
+
import {
|
|
17
|
+
ExecutionPhase,
|
|
18
|
+
MessageType,
|
|
19
|
+
ToolCallStatus,
|
|
20
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
21
|
+
import { buildThreadItems } from "../MessageThread";
|
|
22
|
+
import { MessageEntry } from "../MessageEntry";
|
|
23
|
+
|
|
24
|
+
afterEach(cleanup);
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Phase 5 — Cursor deny-only normalization (append-only by construction).
|
|
28
|
+
//
|
|
29
|
+
// When a Cursor turn pauses for approval, the runner BLANKS (clears the content
|
|
30
|
+
// of) the model's provisional post-denial narration in place rather than
|
|
31
|
+
// removing the messages — so the WAITING_FOR_APPROVAL finalize is append-only
|
|
32
|
+
// and the backend needs no shrink exception. The cleanliness then lives in the
|
|
33
|
+
// DATA: the SDK's existing empty-message handling renders the blanked messages
|
|
34
|
+
// as nothing, so no per-harness UI special-casing is required.
|
|
35
|
+
//
|
|
36
|
+
// These tests LOCK that existing handling. If a future refactor "un-hides"
|
|
37
|
+
// empty messages, these fail loudly — the runner's blanked narration must never
|
|
38
|
+
// silently leak back into any surface.
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
function aiText(content: string): AgentMessage {
|
|
42
|
+
return create(AgentMessageSchema, { type: MessageType.MESSAGE_AI, content });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function thinking(content: string): AgentMessage {
|
|
46
|
+
return create(AgentMessageSchema, { type: MessageType.MESSAGE_THINKING, content });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function gatedAiMessage(): AgentMessage {
|
|
50
|
+
return create(AgentMessageSchema, {
|
|
51
|
+
type: MessageType.MESSAGE_AI,
|
|
52
|
+
content: "",
|
|
53
|
+
toolCalls: [
|
|
54
|
+
create(ToolCallSchema, {
|
|
55
|
+
id: "c1",
|
|
56
|
+
name: "edit",
|
|
57
|
+
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
58
|
+
}),
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The exact transcript the runner persists after redaction: pre-tool text, the
|
|
65
|
+
* gated tool call (WAITING_APPROVAL), then the blanked provisional narration
|
|
66
|
+
* (a THINKING and an AI message, both with empty content). Count preserved.
|
|
67
|
+
*/
|
|
68
|
+
function waitingForApprovalExecution(): AgentExecution {
|
|
69
|
+
const exec = create(AgentExecutionSchema);
|
|
70
|
+
exec.metadata = create(ApiResourceMetadataSchema, { id: "exec-hitl" });
|
|
71
|
+
exec.spec = create(AgentExecutionSpecSchema, { message: "make the change" });
|
|
72
|
+
exec.status = create(AgentExecutionStatusSchema, {
|
|
73
|
+
phase: ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL,
|
|
74
|
+
messages: [
|
|
75
|
+
aiText("Let me create the file."),
|
|
76
|
+
gatedAiMessage(),
|
|
77
|
+
thinking(""), // blanked provisional reasoning
|
|
78
|
+
aiText(""), // blanked provisional verdict
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
return exec;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
describe("buildThreadItems — blanked post-denial narration (Phase 5)", () => {
|
|
85
|
+
it("surfaces the approval tool-group but emits no narration message item", () => {
|
|
86
|
+
const exec = waitingForApprovalExecution();
|
|
87
|
+
|
|
88
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
89
|
+
|
|
90
|
+
// The approval surface is driven by the WAITING_APPROVAL tool call — its
|
|
91
|
+
// tool-group is present.
|
|
92
|
+
const toolGroups = items.filter((i) => i.kind === "tool-group");
|
|
93
|
+
expect(toolGroups).toHaveLength(1);
|
|
94
|
+
expect(toolGroups[0].kind === "tool-group" && toolGroups[0].toolCalls[0].status).toBe(
|
|
95
|
+
ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// The pre-tool text survives as the only non-empty AI message item; the
|
|
99
|
+
// blanked AI verdict is gone.
|
|
100
|
+
const messageItems = items.filter((i) => i.kind === "message");
|
|
101
|
+
const nonEmptyAi = messageItems.filter(
|
|
102
|
+
(i) =>
|
|
103
|
+
i.kind === "message" &&
|
|
104
|
+
i.message.type === MessageType.MESSAGE_AI &&
|
|
105
|
+
i.message.content.trim().length > 0,
|
|
106
|
+
);
|
|
107
|
+
expect(nonEmptyAi).toHaveLength(1);
|
|
108
|
+
expect(nonEmptyAi[0].kind === "message" && nonEmptyAi[0].message.content).toBe(
|
|
109
|
+
"Let me create the file.",
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// No message item carries the provisional narration text. The empty AI
|
|
113
|
+
// verdict is skipped entirely; the empty THINKING (if emitted) carries no
|
|
114
|
+
// content and renders nothing (asserted below at the render layer).
|
|
115
|
+
for (const item of messageItems) {
|
|
116
|
+
if (item.kind !== "message") continue;
|
|
117
|
+
expect(item.message.content).not.toContain("enable the hook");
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("the empty AI verdict is skipped and the empty THINKING carries no content", () => {
|
|
122
|
+
const exec = waitingForApprovalExecution();
|
|
123
|
+
|
|
124
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
125
|
+
const messageItems = items.filter((i) => i.kind === "message");
|
|
126
|
+
|
|
127
|
+
// The empty AI verdict is dropped from the item list entirely (empty-AI
|
|
128
|
+
// skip). Any surviving message item (e.g. the empty THINKING) has no
|
|
129
|
+
// content, so the render layer hides it (asserted below).
|
|
130
|
+
for (const item of messageItems) {
|
|
131
|
+
if (item.kind !== "message") continue;
|
|
132
|
+
if (item.message.type === MessageType.MESSAGE_AI) {
|
|
133
|
+
expect(item.message.content.trim().length).toBeGreaterThan(0);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe("MessageEntry — blanked narration renders nothing (Phase 5)", () => {
|
|
140
|
+
it("renders nothing for a blanked AI narration message", () => {
|
|
141
|
+
const { container } = render(<MessageEntry message={aiText("")} />);
|
|
142
|
+
expect(container.textContent?.trim()).toBe("");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("renders nothing for a blanked THINKING narration message", () => {
|
|
146
|
+
const { container } = render(<MessageEntry message={thinking("")} />);
|
|
147
|
+
expect(container.innerHTML).toBe("");
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { create } from "@bufbuild/protobuf";
|
|
3
|
+
import {
|
|
4
|
+
AgentExecutionSchema,
|
|
5
|
+
AgentExecutionStatusSchema,
|
|
6
|
+
type AgentExecution,
|
|
7
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
8
|
+
import { AgentExecutionSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
|
|
9
|
+
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
10
|
+
import {
|
|
11
|
+
AgentMessageSchema,
|
|
12
|
+
ToolCallSchema,
|
|
13
|
+
type AgentMessage,
|
|
14
|
+
type ToolCall,
|
|
15
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
16
|
+
import {
|
|
17
|
+
PendingApprovalSchema,
|
|
18
|
+
type PendingApproval,
|
|
19
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
|
|
20
|
+
import {
|
|
21
|
+
SubAgentExecutionSchema,
|
|
22
|
+
type SubAgentExecution,
|
|
23
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
|
|
24
|
+
import {
|
|
25
|
+
ExecutionPhase,
|
|
26
|
+
MessageType,
|
|
27
|
+
ToolCallStatus,
|
|
28
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
29
|
+
import { buildThreadItems, type ThreadItem } from "../MessageThread";
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Helpers
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
function toolCall(id: string, name: string): ToolCall {
|
|
36
|
+
return create(ToolCallSchema, {
|
|
37
|
+
id,
|
|
38
|
+
name,
|
|
39
|
+
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function aiWithTools(toolCalls: ToolCall[]): AgentMessage {
|
|
44
|
+
return create(AgentMessageSchema, {
|
|
45
|
+
type: MessageType.MESSAGE_AI,
|
|
46
|
+
content: "",
|
|
47
|
+
toolCalls,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function approval(toolCallId: string, toolName: string): PendingApproval {
|
|
52
|
+
return create(PendingApprovalSchema, {
|
|
53
|
+
toolCallId,
|
|
54
|
+
toolName,
|
|
55
|
+
argsPreview: "{}",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function execution(opts: {
|
|
60
|
+
messages?: AgentMessage[];
|
|
61
|
+
subAgents?: SubAgentExecution[];
|
|
62
|
+
pendingApprovals?: PendingApproval[];
|
|
63
|
+
}): AgentExecution {
|
|
64
|
+
return create(AgentExecutionSchema, {
|
|
65
|
+
metadata: create(ApiResourceMetadataSchema, { id: "aex-1" }),
|
|
66
|
+
spec: create(AgentExecutionSpecSchema, { message: "go" }),
|
|
67
|
+
status: create(AgentExecutionStatusSchema, {
|
|
68
|
+
phase: ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL,
|
|
69
|
+
messages: opts.messages ?? [],
|
|
70
|
+
subAgentExecutions: opts.subAgents ?? [],
|
|
71
|
+
pendingApprovals: opts.pendingApprovals ?? [],
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function approvalItems(items: ThreadItem[]): ThreadItem[] {
|
|
77
|
+
return items.filter((i) => i.kind === "approval-request");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Tests
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
describe("buildThreadItems — inline vs. bottom approval partition", () => {
|
|
85
|
+
it("does NOT emit a bottom card for an approval rendered inline on a regular tool", () => {
|
|
86
|
+
const tc = toolCall("tc-edit", "edit_file");
|
|
87
|
+
const exec = execution({
|
|
88
|
+
messages: [aiWithTools([tc])],
|
|
89
|
+
pendingApprovals: [approval("tc-edit", "edit_file")],
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
93
|
+
|
|
94
|
+
// The tool renders in a group → its gate shows inline → no bottom card.
|
|
95
|
+
expect(approvalItems(items)).toHaveLength(0);
|
|
96
|
+
expect(items.some((i) => i.kind === "tool-group")).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("emits a bottom card for an orphan approval with no matching tool row", () => {
|
|
100
|
+
const tc = toolCall("tc-edit", "edit_file");
|
|
101
|
+
const exec = execution({
|
|
102
|
+
messages: [aiWithTools([tc])],
|
|
103
|
+
pendingApprovals: [approval("tc-ghost", "phantom_tool")],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
107
|
+
|
|
108
|
+
const bottom = approvalItems(items);
|
|
109
|
+
expect(bottom).toHaveLength(1);
|
|
110
|
+
expect(
|
|
111
|
+
bottom[0].kind === "approval-request" && bottom[0].pendingApproval.toolCallId,
|
|
112
|
+
).toBe("tc-ghost");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("emits a bottom card for a task-spawn approval (rendered as a sub-agent, not a tool row)", () => {
|
|
116
|
+
// A `task` call with a matching SubAgentExecution renders as a SubAgentSection,
|
|
117
|
+
// not an approval-capable ToolCallItem — so its spawn gate must surface below.
|
|
118
|
+
const task = toolCall("tc-task", "task");
|
|
119
|
+
const sub = create(SubAgentExecutionSchema, { id: "tc-task", name: "researcher" });
|
|
120
|
+
const exec = execution({
|
|
121
|
+
messages: [aiWithTools([task])],
|
|
122
|
+
subAgents: [sub],
|
|
123
|
+
pendingApprovals: [approval("tc-task", "task")],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
127
|
+
|
|
128
|
+
expect(items.some((i) => i.kind === "sub-agent")).toBe(true);
|
|
129
|
+
expect(approvalItems(items)).toHaveLength(1);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("does NOT emit a bottom card for an approval on a sub-agent's nested tool", () => {
|
|
133
|
+
const task = toolCall("tc-task", "task");
|
|
134
|
+
const sub = create(SubAgentExecutionSchema, {
|
|
135
|
+
id: "tc-task",
|
|
136
|
+
name: "researcher",
|
|
137
|
+
messages: [aiWithTools([toolCall("tc-nested", "fetch")])],
|
|
138
|
+
});
|
|
139
|
+
const exec = execution({
|
|
140
|
+
messages: [aiWithTools([task])],
|
|
141
|
+
subAgents: [sub],
|
|
142
|
+
pendingApprovals: [approval("tc-nested", "fetch")],
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
146
|
+
|
|
147
|
+
// The nested tool renders inside the sub-agent section → inline gate → no bottom card.
|
|
148
|
+
expect(approvalItems(items)).toHaveLength(0);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("emits no approval items at all when approvals are disabled", () => {
|
|
152
|
+
const tc = toolCall("tc-edit", "edit_file");
|
|
153
|
+
const exec = execution({
|
|
154
|
+
messages: [aiWithTools([tc])],
|
|
155
|
+
pendingApprovals: [approval("tc-ghost", "phantom_tool")],
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
159
|
+
|
|
160
|
+
expect(approvalItems(items)).toHaveLength(0);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// Triangulation (CLIENT boundary)
|
|
166
|
+
//
|
|
167
|
+
// The runner boundary (hitl-resume-approve-all.test.ts) and the server boundary
|
|
168
|
+
// (Go controller update_status tests) are covered elsewhere. This pins that the
|
|
169
|
+
// SDK thread derivation is a faithful PASSTHROUGH of the persisted transcript:
|
|
170
|
+
// every persisted thinking block and tool call must surface as a thread item,
|
|
171
|
+
// across both the gated (approval pending) state and the decided/leased resume
|
|
172
|
+
// state the user reported. A passing test here exonerates the client and
|
|
173
|
+
// localizes the reported "vanishing thinking + first tool call" upstream (the
|
|
174
|
+
// server merge); a failing test would indict the derivation instead.
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
function thinkingMsg(content: string): AgentMessage {
|
|
178
|
+
return create(AgentMessageSchema, {
|
|
179
|
+
type: MessageType.MESSAGE_THINKING,
|
|
180
|
+
content,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function aiText(content: string): AgentMessage {
|
|
185
|
+
return create(AgentMessageSchema, {
|
|
186
|
+
type: MessageType.MESSAGE_AI,
|
|
187
|
+
content,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function completedToolCall(id: string, name: string): ToolCall {
|
|
192
|
+
return create(ToolCallSchema, {
|
|
193
|
+
id,
|
|
194
|
+
name,
|
|
195
|
+
status: ToolCallStatus.TOOL_CALL_COMPLETED,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function execAtPhase(
|
|
200
|
+
phase: ExecutionPhase,
|
|
201
|
+
messages: AgentMessage[],
|
|
202
|
+
pendingApprovals: PendingApproval[] = [],
|
|
203
|
+
): AgentExecution {
|
|
204
|
+
return create(AgentExecutionSchema, {
|
|
205
|
+
metadata: create(ApiResourceMetadataSchema, { id: "aex-1" }),
|
|
206
|
+
spec: create(AgentExecutionSpecSchema, { message: "Self-DM me" }),
|
|
207
|
+
status: create(AgentExecutionStatusSchema, {
|
|
208
|
+
phase,
|
|
209
|
+
messages,
|
|
210
|
+
pendingApprovals,
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function hasThinkingItem(items: ThreadItem[], content: string): boolean {
|
|
216
|
+
return items.some(
|
|
217
|
+
(i) =>
|
|
218
|
+
i.kind === "message" &&
|
|
219
|
+
i.message.type === MessageType.MESSAGE_THINKING &&
|
|
220
|
+
i.message.content === content,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function hasToolInGroup(items: ThreadItem[], toolCallId: string): boolean {
|
|
225
|
+
return items.some(
|
|
226
|
+
(i) => i.kind === "tool-group" && i.toolCalls.some((tc) => tc.id === toolCallId),
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
describe("buildThreadItems — approve-all transcript renders faithfully (client triangulation)", () => {
|
|
231
|
+
it("renders the leading thinking block and the gated tool while approval is pending", () => {
|
|
232
|
+
const exec = execAtPhase(
|
|
233
|
+
ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL,
|
|
234
|
+
[
|
|
235
|
+
thinkingMsg("planning the self-DM"),
|
|
236
|
+
aiWithTools([toolCall("tc-getappstate", "getAppState")]),
|
|
237
|
+
],
|
|
238
|
+
[approval("tc-getappstate", "getAppState")],
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
242
|
+
|
|
243
|
+
expect(hasThinkingItem(items, "planning the self-DM")).toBe(true);
|
|
244
|
+
expect(hasToolInGroup(items, "tc-getappstate")).toBe(true);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("renders thinking + first tool + appended leased tools after approve-all resume", () => {
|
|
248
|
+
const exec = execAtPhase(ExecutionPhase.EXECUTION_IN_PROGRESS, [
|
|
249
|
+
thinkingMsg("planning the self-DM"),
|
|
250
|
+
aiWithTools([completedToolCall("tc-getappstate", "getAppState")]),
|
|
251
|
+
aiWithTools([completedToolCall("tc-click", "click")]),
|
|
252
|
+
aiText("Captured the app state and clicked the element."),
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
const items = buildThreadItems([exec], null, null, true, undefined);
|
|
256
|
+
|
|
257
|
+
// The leading thinking block and the FIRST tool call survive rendering...
|
|
258
|
+
expect(hasThinkingItem(items, "planning the self-DM")).toBe(true);
|
|
259
|
+
expect(hasToolInGroup(items, "tc-getappstate")).toBe(true);
|
|
260
|
+
// ...alongside the appended leased tool and the final assistant turn.
|
|
261
|
+
expect(hasToolInGroup(items, "tc-click")).toBe(true);
|
|
262
|
+
expect(
|
|
263
|
+
items.some(
|
|
264
|
+
(i) =>
|
|
265
|
+
i.kind === "message" &&
|
|
266
|
+
i.message.content === "Captured the app state and clicked the element.",
|
|
267
|
+
),
|
|
268
|
+
).toBe(true);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// ---------------------------------------------------------------------------
|
|
273
|
+
// Active-execution dedupe (regression for the duplicate-key flake)
|
|
274
|
+
//
|
|
275
|
+
// The hook passes `completedExecutions` (filtered on activeExecutionId) plus
|
|
276
|
+
// `activeStreamExecution` (resolved from stream.execution ??
|
|
277
|
+
// fetchedActiveExecution). A transient skew between those two sources can leave
|
|
278
|
+
// the active execution in BOTH inputs. Without deduping, the same execution is
|
|
279
|
+
// emitted twice → duplicate React keys → React drops one subtree, intermittently
|
|
280
|
+
// the one carrying a live ApprovalCard, so the gate buttons vanish ("0 approvals
|
|
281
|
+
// needed"). buildThreadItems must treat activeStreamExecution as authoritative
|
|
282
|
+
// for its id and emit each execution exactly once.
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
|
|
285
|
+
describe("buildThreadItems — active-execution dedupe", () => {
|
|
286
|
+
it("emits each execution once when the active one is in BOTH inputs (no duplicate keys)", () => {
|
|
287
|
+
const exec = execution({
|
|
288
|
+
messages: [aiWithTools([toolCall("tc-edit", "edit_file")])],
|
|
289
|
+
pendingApprovals: [approval("tc-edit", "edit_file")],
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// Same execution arrives via the list AND as the active stream copy.
|
|
293
|
+
const items = buildThreadItems([exec], exec, null, true, undefined);
|
|
294
|
+
|
|
295
|
+
const keys = items.map((i) => i.key);
|
|
296
|
+
expect(new Set(keys).size).toBe(keys.length); // all keys unique
|
|
297
|
+
// Exactly one synthetic spec message and one tool group survive.
|
|
298
|
+
expect(items.filter((i) => i.kind === "message")).toHaveLength(1);
|
|
299
|
+
expect(items.filter((i) => i.kind === "tool-group")).toHaveLength(1);
|
|
300
|
+
// The inline gate is preserved (not dropped with a duplicated subtree).
|
|
301
|
+
expect(hasToolInGroup(items, "tc-edit")).toBe(true);
|
|
302
|
+
expect(approvalItems(items)).toHaveLength(0);
|
|
303
|
+
});
|
|
304
|
+
});
|