@stigmer/react 3.1.1 → 3.1.3
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/composer/SessionComposer.d.ts +25 -1
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +19 -8
- package/composer/SessionComposer.js.map +1 -1
- package/execution/ArtifactContentRenderer.d.ts +11 -1
- package/execution/ArtifactContentRenderer.d.ts.map +1 -1
- package/execution/ArtifactContentRenderer.js +39 -15
- package/execution/ArtifactContentRenderer.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts +5 -5
- package/execution/ArtifactPreviewModal.js +4 -4
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/FileChangeProgressBar.d.ts +47 -0
- package/execution/FileChangeProgressBar.d.ts.map +1 -0
- package/execution/FileChangeProgressBar.js +49 -0
- package/execution/FileChangeProgressBar.js.map +1 -0
- package/execution/FileChangesView.d.ts.map +1 -1
- package/execution/FileChangesView.js +19 -4
- package/execution/FileChangesView.js.map +1 -1
- package/execution/FilePathContext.d.ts +8 -1
- package/execution/FilePathContext.d.ts.map +1 -1
- package/execution/FilePathContext.js.map +1 -1
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +21 -6
- package/execution/FilePathLink.js.map +1 -1
- package/execution/FileReviewAtoms.d.ts +27 -0
- package/execution/FileReviewAtoms.d.ts.map +1 -0
- package/execution/FileReviewAtoms.js +64 -0
- package/execution/FileReviewAtoms.js.map +1 -0
- package/execution/FileReviewCard.d.ts +2 -2
- package/execution/FileReviewCard.d.ts.map +1 -1
- package/execution/FileReviewCard.js +32 -62
- package/execution/FileReviewCard.js.map +1 -1
- package/execution/MessageEntry.d.ts +20 -0
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +19 -5
- package/execution/MessageEntry.js.map +1 -1
- package/execution/MessageThread.d.ts +75 -13
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +195 -27
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts +36 -21
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +39 -25
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/PlanCompletionCard.d.ts +4 -4
- package/execution/PlanCompletionCard.d.ts.map +1 -1
- package/execution/PlanCompletionCard.js +4 -4
- package/execution/PlanCompletionCard.js.map +1 -1
- package/execution/PlanDocumentMessage.d.ts +32 -0
- package/execution/PlanDocumentMessage.d.ts.map +1 -0
- package/execution/PlanDocumentMessage.js +37 -0
- package/execution/PlanDocumentMessage.js.map +1 -0
- package/execution/PlanStreamingCard.d.ts +50 -0
- package/execution/PlanStreamingCard.d.ts.map +1 -0
- package/execution/PlanStreamingCard.js +40 -0
- package/execution/PlanStreamingCard.js.map +1 -0
- package/execution/index.d.ts +9 -1
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +4 -0
- package/execution/index.js.map +1 -1
- package/execution/use-build-from-plan-hotkey.d.ts +1 -1
- package/execution/use-build-from-plan-hotkey.js +1 -1
- package/execution/useArtifactCopy.d.ts +51 -0
- package/execution/useArtifactCopy.d.ts.map +1 -0
- package/execution/useArtifactCopy.js +75 -0
- package/execution/useArtifactCopy.js.map +1 -0
- package/execution/useArtifactDownload.d.ts.map +1 -1
- package/execution/useArtifactDownload.js +17 -5
- package/execution/useArtifactDownload.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +12 -0
- package/execution/useCreateAgentExecution.d.ts.map +1 -1
- package/execution/useCreateAgentExecution.js +5 -1
- package/execution/useCreateAgentExecution.js.map +1 -1
- package/github/decodeGitHubContent.d.ts +29 -0
- package/github/decodeGitHubContent.d.ts.map +1 -0
- package/github/decodeGitHubContent.js +72 -0
- package/github/decodeGitHubContent.js.map +1 -0
- package/github/index.d.ts +1 -0
- package/github/index.d.ts.map +1 -1
- package/github/index.js +1 -0
- package/github/index.js.map +1 -1
- package/github/useGitHubFileReader.d.ts +26 -0
- package/github/useGitHubFileReader.d.ts.map +1 -0
- package/github/useGitHubFileReader.js +106 -0
- package/github/useGitHubFileReader.js.map +1 -0
- package/github/useGitHubTreeLister.d.ts.map +1 -1
- package/github/useGitHubTreeLister.js +6 -2
- package/github/useGitHubTreeLister.js.map +1 -1
- package/index.d.ts +9 -9
- package/index.d.ts.map +1 -1
- package/index.js +5 -5
- package/index.js.map +1 -1
- package/internal/ResizableSplit.d.ts +72 -22
- package/internal/ResizableSplit.d.ts.map +1 -1
- package/internal/ResizableSplit.js +96 -38
- package/internal/ResizableSplit.js.map +1 -1
- package/internal/VirtualizedThread.d.ts +5 -3
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +6 -4
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/file-icons/index.d.ts +17 -0
- package/internal/file-icons/index.d.ts.map +1 -0
- package/internal/file-icons/index.js +60 -0
- package/internal/file-icons/index.js.map +1 -0
- package/internal/file-tree/FileTreeNode.d.ts +18 -1
- package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
- package/internal/file-tree/FileTreeNode.js +11 -2
- package/internal/file-tree/FileTreeNode.js.map +1 -1
- package/internal/markdown-components.d.ts +38 -1
- package/internal/markdown-components.d.ts.map +1 -1
- package/internal/markdown-components.js +86 -11
- package/internal/markdown-components.js.map +1 -1
- package/{workflow → internal}/motion-preference.d.ts +7 -4
- package/internal/motion-preference.d.ts.map +1 -0
- package/{workflow → internal}/motion-preference.js +7 -4
- package/internal/motion-preference.js.map +1 -0
- package/internal/store/index.d.ts +33 -0
- package/internal/store/index.d.ts.map +1 -1
- package/internal/store/index.js +59 -0
- package/internal/store/index.js.map +1 -1
- package/internal/store/workspace-editors-store.d.ts +145 -0
- package/internal/store/workspace-editors-store.d.ts.map +1 -0
- package/internal/store/workspace-editors-store.js +208 -0
- package/internal/store/workspace-editors-store.js.map +1 -0
- package/internal/store/workspace-file-selection-store.d.ts +38 -0
- package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
- package/internal/store/workspace-file-selection-store.js +62 -0
- package/internal/store/workspace-file-selection-store.js.map +1 -0
- package/internal/useRevealLine.d.ts +49 -0
- package/internal/useRevealLine.d.ts.map +1 -0
- package/internal/useRevealLine.js +43 -0
- package/internal/useRevealLine.js.map +1 -0
- package/library/detect-plan-artifact.d.ts +43 -4
- package/library/detect-plan-artifact.d.ts.map +1 -1
- package/library/detect-plan-artifact.js +45 -5
- package/library/detect-plan-artifact.js.map +1 -1
- package/library/detect-streaming-plan.d.ts +45 -0
- package/library/detect-streaming-plan.d.ts.map +1 -0
- package/library/detect-streaming-plan.js +83 -0
- package/library/detect-streaming-plan.js.map +1 -0
- package/library/index.d.ts +4 -1
- package/library/index.d.ts.map +1 -1
- package/library/index.js +2 -1
- package/library/index.js.map +1 -1
- package/package.json +4 -4
- package/session/NewSessionViewer.d.ts +19 -4
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +52 -25
- package/session/NewSessionViewer.js.map +1 -1
- package/session/PlanEditor.d.ts +55 -0
- package/session/PlanEditor.d.ts.map +1 -0
- package/session/PlanEditor.js +88 -0
- package/session/PlanEditor.js.map +1 -0
- package/session/PlanStreamingDocument.d.ts +30 -0
- package/session/PlanStreamingDocument.d.ts.map +1 -0
- package/session/PlanStreamingDocument.js +37 -0
- package/session/PlanStreamingDocument.js.map +1 -0
- package/session/SessionPanelChip.d.ts +26 -0
- package/session/SessionPanelChip.d.ts.map +1 -0
- package/session/SessionPanelChip.js +40 -0
- package/session/SessionPanelChip.js.map +1 -0
- package/session/SessionViewer.d.ts +34 -7
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +334 -33
- package/session/SessionViewer.js.map +1 -1
- package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
- package/session/facets/ArtifactsTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ArtifactsTab.js +8 -3
- package/session/facets/ArtifactsTab.js.map +1 -0
- package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
- package/session/facets/ChangesTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ChangesTab.js +3 -3
- package/session/facets/ChangesTab.js.map +1 -0
- package/session/facets/InspectTab.d.ts.map +1 -0
- package/session/facets/InspectTab.js.map +1 -0
- package/session/{inspector → facets}/SetupTab.d.ts +11 -2
- package/session/facets/SetupTab.d.ts.map +1 -0
- package/session/{inspector → facets}/SetupTab.js +4 -3
- package/session/facets/SetupTab.js.map +1 -0
- package/session/{inspector → facets}/UsageTab.d.ts +1 -1
- package/session/facets/UsageTab.d.ts.map +1 -0
- package/session/{inspector → facets}/UsageTab.js +1 -1
- package/session/facets/UsageTab.js.map +1 -0
- package/session/{inspector → facets}/index.d.ts +0 -6
- package/session/facets/index.d.ts.map +1 -0
- package/session/{inspector → facets}/index.js +0 -3
- package/session/facets/index.js.map +1 -0
- package/session/index.d.ts +11 -2
- package/session/index.d.ts.map +1 -1
- package/session/index.js +15 -2
- package/session/index.js.map +1 -1
- package/session/plan-document.d.ts +21 -0
- package/session/plan-document.d.ts.map +1 -0
- package/session/plan-document.js +28 -0
- package/session/plan-document.js.map +1 -0
- package/session/useOpenFileChange.d.ts +20 -0
- package/session/useOpenFileChange.d.ts.map +1 -0
- package/session/useOpenFileChange.js +31 -0
- package/session/useOpenFileChange.js.map +1 -0
- package/session/usePlanDraft.d.ts +52 -0
- package/session/usePlanDraft.d.ts.map +1 -0
- package/session/usePlanDraft.js +63 -0
- package/session/usePlanDraft.js.map +1 -0
- package/session/useSessionConversation.d.ts +14 -1
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +20 -2
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +1 -0
- package/session/useSessionPageFlow.js.map +1 -1
- package/session/useSessionPanel.d.ts +120 -0
- package/session/useSessionPanel.d.ts.map +1 -0
- package/session/useSessionPanel.js +130 -0
- package/session/useSessionPanel.js.map +1 -0
- package/session/useSessionRailViews.d.ts +45 -0
- package/session/useSessionRailViews.d.ts.map +1 -0
- package/session/useSessionRailViews.js +105 -0
- package/session/useSessionRailViews.js.map +1 -0
- package/src/composer/SessionComposer.tsx +53 -10
- package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
- package/src/execution/ArtifactContentRenderer.tsx +101 -24
- package/src/execution/ArtifactPreviewModal.tsx +9 -9
- package/src/execution/FileChangeProgressBar.tsx +121 -0
- package/src/execution/FileChangesView.tsx +18 -4
- package/src/execution/FilePathContext.tsx +8 -1
- package/src/execution/FilePathLink.tsx +22 -6
- package/src/execution/FileReviewAtoms.tsx +89 -0
- package/src/execution/FileReviewCard.tsx +57 -90
- package/src/execution/MessageEntry.tsx +49 -1
- package/src/execution/MessageThread.tsx +308 -39
- package/src/execution/PlanArtifactCard.tsx +174 -64
- package/src/execution/PlanCompletionCard.tsx +5 -5
- package/src/execution/PlanDocumentMessage.tsx +96 -0
- package/src/execution/PlanStreamingCard.tsx +141 -0
- package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
- package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +6 -6
- package/src/execution/__tests__/FileChangeProgressBar.test.tsx +125 -0
- package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
- package/src/execution/__tests__/FileReviewCard.test.tsx +66 -7
- package/src/execution/__tests__/MessageThread.test.tsx +102 -1
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +114 -26
- package/src/execution/__tests__/PlanCompletionCard.test.tsx +2 -2
- package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
- package/src/execution/__tests__/PlanStreamingCard.test.tsx +56 -0
- package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +600 -22
- package/src/execution/__tests__/message-entry.test.tsx +17 -0
- package/src/execution/__tests__/useArtifactCopy.test.tsx +90 -0
- package/src/execution/__tests__/useArtifactDownload.test.tsx +2 -0
- package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
- package/src/execution/index.ts +13 -1
- package/src/execution/use-build-from-plan-hotkey.ts +1 -1
- package/src/execution/useArtifactCopy.ts +109 -0
- package/src/execution/useArtifactDownload.ts +17 -5
- package/src/execution/useCreateAgentExecution.ts +18 -1
- package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
- package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
- package/src/github/decodeGitHubContent.ts +83 -0
- package/src/github/index.ts +1 -0
- package/src/github/useGitHubFileReader.ts +152 -0
- package/src/github/useGitHubTreeLister.ts +6 -2
- package/src/index.ts +69 -9
- package/src/internal/ResizableSplit.tsx +184 -51
- package/src/internal/VirtualizedThread.tsx +12 -4
- package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
- package/src/internal/__tests__/markdown-components.test.tsx +68 -0
- package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
- package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
- package/src/internal/file-icons/index.tsx +137 -0
- package/src/internal/file-tree/FileTreeNode.tsx +56 -5
- package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
- package/src/internal/markdown-components.tsx +116 -11
- package/src/{workflow → internal}/motion-preference.ts +7 -4
- package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
- package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
- package/src/internal/store/index.ts +94 -0
- package/src/internal/store/workspace-editors-store.ts +315 -0
- package/src/internal/store/workspace-file-selection-store.ts +88 -0
- package/src/internal/useRevealLine.ts +81 -0
- package/src/library/__tests__/detect-plan-artifact.test.ts +69 -0
- package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
- package/src/library/detect-plan-artifact.ts +62 -5
- package/src/library/detect-streaming-plan.ts +108 -0
- package/src/library/index.ts +7 -0
- package/src/session/NewSessionViewer.tsx +123 -55
- package/src/session/PlanEditor.tsx +361 -0
- package/src/session/PlanStreamingDocument.tsx +97 -0
- package/src/session/SessionPanelChip.tsx +103 -0
- package/src/session/SessionViewer.tsx +655 -96
- package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
- package/src/session/__tests__/PlanEditor.test.tsx +217 -0
- package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
- package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
- package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +66 -4
- package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
- package/src/session/__tests__/audienceWiring.test.tsx +55 -19
- package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
- package/src/session/__tests__/usePlanDraft.test.ts +102 -0
- package/src/session/__tests__/useSessionConversation.test.tsx +44 -0
- package/src/session/__tests__/useSessionPanel.test.ts +298 -0
- package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
- package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
- package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
- package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
- package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
- package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +42 -8
- package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
- package/src/session/{inspector → facets}/index.ts +0 -16
- package/src/session/index.ts +30 -13
- package/src/session/plan-document.ts +30 -0
- package/src/session/useOpenFileChange.ts +53 -0
- package/src/session/usePlanDraft.ts +109 -0
- package/src/session/useSessionConversation.ts +38 -3
- package/src/session/useSessionPageFlow.ts +1 -0
- package/src/session/useSessionPanel.ts +288 -0
- package/src/session/useSessionRailViews.tsx +200 -0
- package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
- package/src/workflow/index.ts +1 -1
- package/src/workflow/useFollowExecution.ts +1 -1
- package/src/workspace/EditorTabs.tsx +174 -0
- package/src/workspace/ExplorerTree.tsx +253 -0
- package/src/workspace/FileViewer.tsx +537 -0
- package/src/workspace/WorkspaceContentSearch.tsx +502 -0
- package/src/workspace/WorkspaceContentSearcher.ts +70 -0
- package/src/workspace/WorkspaceEditor.tsx +19 -16
- package/src/workspace/WorkspaceFileLister.ts +11 -0
- package/src/workspace/WorkspaceFileReader.ts +57 -0
- package/src/workspace/WorkspaceFileSearch.tsx +452 -0
- package/src/workspace/WorkspaceSurface.tsx +839 -0
- package/src/workspace/__tests__/EditorTabs.test.tsx +102 -0
- package/src/workspace/__tests__/ExplorerTree.test.tsx +204 -0
- package/src/workspace/__tests__/FileViewer.test.tsx +439 -0
- package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +229 -0
- package/src/workspace/__tests__/WorkspaceEditor-initialPanel.test.tsx +19 -0
- package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +227 -0
- package/src/workspace/__tests__/WorkspaceSurface.test.tsx +418 -0
- package/src/workspace/__tests__/a11y/harness.tsx +140 -0
- package/src/workspace/__tests__/a11y/mock-capabilities.ts +138 -0
- package/src/workspace/__tests__/a11y/workspace-editor.a11y.test.tsx +65 -0
- package/src/workspace/__tests__/a11y/workspace-explorer-search.a11y.test.tsx +112 -0
- package/src/workspace/__tests__/a11y/workspace-viewer-tabs.a11y.test.tsx +69 -0
- package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
- package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
- package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
- package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
- package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
- package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
- package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
- package/src/workspace/findChangeForSelection.ts +61 -0
- package/src/workspace/index.ts +56 -2
- package/src/workspace/matchContentPreview.ts +51 -0
- package/src/workspace/matchWorkspaceFiles.ts +86 -0
- package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
- package/src/workspace/useWorkspaceContentSearch.ts +228 -0
- package/src/workspace/useWorkspaceFileContent.ts +129 -0
- package/src/workspace/useWorkspaceFileSearch.ts +184 -0
- package/src/workspace/useWorkspaceFiles.ts +27 -27
- package/src/workspace/workspaceListingCache.ts +93 -0
- package/styles.css +1 -1
- package/workflow/WorkflowExecutionGraph.js +1 -1
- package/workflow/WorkflowExecutionGraph.js.map +1 -1
- package/workflow/index.d.ts +1 -1
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -1
- package/workflow/index.js.map +1 -1
- package/workflow/useFollowExecution.js +1 -1
- package/workflow/useFollowExecution.js.map +1 -1
- package/workspace/EditorTabs.d.ts +47 -0
- package/workspace/EditorTabs.d.ts.map +1 -0
- package/workspace/EditorTabs.js +78 -0
- package/workspace/EditorTabs.js.map +1 -0
- package/workspace/ExplorerTree.d.ts +32 -0
- package/workspace/ExplorerTree.d.ts.map +1 -0
- package/workspace/ExplorerTree.js +49 -0
- package/workspace/ExplorerTree.js.map +1 -0
- package/workspace/FileViewer.d.ts +93 -0
- package/workspace/FileViewer.d.ts.map +1 -0
- package/workspace/FileViewer.js +193 -0
- package/workspace/FileViewer.js.map +1 -0
- package/workspace/WorkspaceContentSearch.d.ts +41 -0
- package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearch.js +216 -0
- package/workspace/WorkspaceContentSearch.js.map +1 -0
- package/workspace/WorkspaceContentSearcher.d.ts +59 -0
- package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearcher.js +7 -0
- package/workspace/WorkspaceContentSearcher.js.map +1 -0
- package/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/workspace/WorkspaceEditor.js +8 -10
- package/workspace/WorkspaceEditor.js.map +1 -1
- package/workspace/WorkspaceFileLister.d.ts +11 -0
- package/workspace/WorkspaceFileLister.d.ts.map +1 -1
- package/workspace/WorkspaceFileReader.d.ts +48 -0
- package/workspace/WorkspaceFileReader.d.ts.map +1 -0
- package/workspace/WorkspaceFileReader.js +11 -0
- package/workspace/WorkspaceFileReader.js.map +1 -0
- package/workspace/WorkspaceFileSearch.d.ts +32 -0
- package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/WorkspaceFileSearch.js +175 -0
- package/workspace/WorkspaceFileSearch.js.map +1 -0
- package/workspace/WorkspaceSurface.d.ts +151 -0
- package/workspace/WorkspaceSurface.d.ts.map +1 -0
- package/workspace/WorkspaceSurface.js +220 -0
- package/workspace/WorkspaceSurface.js.map +1 -0
- package/workspace/findChangeForSelection.d.ts +19 -0
- package/workspace/findChangeForSelection.d.ts.map +1 -0
- package/workspace/findChangeForSelection.js +46 -0
- package/workspace/findChangeForSelection.js.map +1 -0
- package/workspace/index.d.ts +24 -2
- package/workspace/index.d.ts.map +1 -1
- package/workspace/index.js +13 -1
- package/workspace/index.js.map +1 -1
- package/workspace/matchContentPreview.d.ts +21 -0
- package/workspace/matchContentPreview.d.ts.map +1 -0
- package/workspace/matchContentPreview.js +36 -0
- package/workspace/matchContentPreview.js.map +1 -0
- package/workspace/matchWorkspaceFiles.d.ts +30 -0
- package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
- package/workspace/matchWorkspaceFiles.js +58 -0
- package/workspace/matchWorkspaceFiles.js.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.js +115 -0
- package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
- package/workspace/useWorkspaceContentSearch.d.ts +69 -0
- package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceContentSearch.js +154 -0
- package/workspace/useWorkspaceContentSearch.js.map +1 -0
- package/workspace/useWorkspaceFileContent.d.ts +73 -0
- package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
- package/workspace/useWorkspaceFileContent.js +57 -0
- package/workspace/useWorkspaceFileContent.js.map +1 -0
- package/workspace/useWorkspaceFileSearch.d.ts +61 -0
- package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceFileSearch.js +119 -0
- package/workspace/useWorkspaceFileSearch.js.map +1 -0
- package/workspace/useWorkspaceFiles.d.ts +13 -5
- package/workspace/useWorkspaceFiles.d.ts.map +1 -1
- package/workspace/useWorkspaceFiles.js +18 -19
- package/workspace/useWorkspaceFiles.js.map +1 -1
- package/workspace/workspaceListingCache.d.ts +47 -0
- package/workspace/workspaceListingCache.d.ts.map +1 -0
- package/workspace/workspaceListingCache.js +55 -0
- package/workspace/workspaceListingCache.js.map +1 -0
- package/session/inspector/ArtifactsTab.d.ts.map +0 -1
- package/session/inspector/ArtifactsTab.js.map +0 -1
- package/session/inspector/ChangesTab.d.ts.map +0 -1
- package/session/inspector/ChangesTab.js.map +0 -1
- package/session/inspector/InspectTab.d.ts.map +0 -1
- package/session/inspector/InspectTab.js.map +0 -1
- package/session/inspector/SessionInspector.d.ts +0 -64
- package/session/inspector/SessionInspector.d.ts.map +0 -1
- package/session/inspector/SessionInspector.js +0 -53
- package/session/inspector/SessionInspector.js.map +0 -1
- package/session/inspector/SetupTab.d.ts.map +0 -1
- package/session/inspector/SetupTab.js.map +0 -1
- package/session/inspector/UsageTab.d.ts.map +0 -1
- package/session/inspector/UsageTab.js.map +0 -1
- package/session/inspector/WorkspaceTab.d.ts +0 -35
- package/session/inspector/WorkspaceTab.d.ts.map +0 -1
- package/session/inspector/WorkspaceTab.js +0 -75
- package/session/inspector/WorkspaceTab.js.map +0 -1
- package/session/inspector/index.d.ts.map +0 -1
- package/session/inspector/index.js.map +0 -1
- package/session/inspector/useSessionInspector.d.ts +0 -49
- package/session/inspector/useSessionInspector.d.ts.map +0 -1
- package/session/inspector/useSessionInspector.js +0 -122
- package/session/inspector/useSessionInspector.js.map +0 -1
- package/src/session/inspector/SessionInspector.tsx +0 -162
- package/src/session/inspector/WorkspaceTab.tsx +0 -245
- package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
- package/src/session/inspector/useSessionInspector.ts +0 -178
- package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
- package/workflow/motion-preference.d.ts.map +0 -1
- package/workflow/motion-preference.js.map +0 -1
- package/workspace/WorkspaceEntryFiles.d.ts +0 -22
- package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
- package/workspace/WorkspaceEntryFiles.js +0 -58
- package/workspace/WorkspaceEntryFiles.js.map +0 -1
- /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
- /package/session/{inspector → facets}/InspectTab.js +0 -0
- /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
- /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
- /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import { renderHook, act, cleanup } from "@testing-library/react";
|
|
3
|
+
import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
4
|
+
import { useSessionPanel, type UseSessionPanelOptions } from "../useSessionPanel";
|
|
5
|
+
import { PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH } from "../plan-document";
|
|
6
|
+
import type { SelectedThreadItem } from "../../internal/store/selection-store";
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// The unified-panel controller: collapsed-by-default state, the open-editor
|
|
10
|
+
// group, and the rail-view FSM ported from the retired inspector tabs. The
|
|
11
|
+
// FSM rules under test: explicit picks are sticky; auto-switching happens only
|
|
12
|
+
// in an OPEN panel (arrivals/selections never auto-open); running⇄terminal
|
|
13
|
+
// transitions reset stickiness.
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
const item = { kind: "toolCall" } as unknown as SelectedThreadItem;
|
|
17
|
+
|
|
18
|
+
function renderPanel(initial?: Partial<UseSessionPanelOptions>) {
|
|
19
|
+
return renderHook(
|
|
20
|
+
(opts: UseSessionPanelOptions) => useSessionPanel(opts),
|
|
21
|
+
{
|
|
22
|
+
initialProps: {
|
|
23
|
+
phase: null,
|
|
24
|
+
hasChanges: false,
|
|
25
|
+
...initial,
|
|
26
|
+
} as UseSessionPanelOptions,
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
afterEach(cleanup);
|
|
32
|
+
|
|
33
|
+
describe("useSessionPanel — open/collapse", () => {
|
|
34
|
+
it("starts collapsed on the Explorer view", () => {
|
|
35
|
+
const { result } = renderPanel();
|
|
36
|
+
expect(result.current.isOpen).toBe(false);
|
|
37
|
+
expect(result.current.view).toBe("files");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("opens via openPanel and collapses via closePanel, preserving the view", () => {
|
|
41
|
+
const { result } = renderPanel();
|
|
42
|
+
act(() => result.current.openPanel());
|
|
43
|
+
expect(result.current.isOpen).toBe(true);
|
|
44
|
+
act(() => result.current.setView("usage"));
|
|
45
|
+
act(() => result.current.closePanel());
|
|
46
|
+
expect(result.current.isOpen).toBe(false);
|
|
47
|
+
act(() => result.current.openPanel());
|
|
48
|
+
expect(result.current.view).toBe("usage");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("openFile opens the panel with a preview tab", () => {
|
|
52
|
+
const { result } = renderPanel();
|
|
53
|
+
act(() => result.current.openFile("e1", "src/main.go"));
|
|
54
|
+
expect(result.current.isOpen).toBe(true);
|
|
55
|
+
expect(result.current.editorsStore.getSnapshot().editors).toEqual([
|
|
56
|
+
{ entryId: "e1", path: "src/main.go", preview: true },
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("keeps the panel open when the last editor closes (the panel is more than files)", () => {
|
|
61
|
+
const { result } = renderPanel();
|
|
62
|
+
act(() => result.current.openFile("e1", "a.ts"));
|
|
63
|
+
act(() => result.current.closeEditor("e1", "a.ts"));
|
|
64
|
+
expect(result.current.editorsStore.getSnapshot().editors).toEqual([]);
|
|
65
|
+
expect(result.current.isOpen).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("useSessionPanel — selection (Inspect)", () => {
|
|
70
|
+
it("auto-surfaces Inspect for a selection while the panel is open", () => {
|
|
71
|
+
const { result } = renderPanel();
|
|
72
|
+
act(() => result.current.openPanel());
|
|
73
|
+
act(() => result.current.notifySelection(item));
|
|
74
|
+
expect(result.current.view).toBe("inspect");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("never auto-opens a collapsed panel on selection", () => {
|
|
78
|
+
const { result } = renderPanel();
|
|
79
|
+
act(() => result.current.notifySelection(item));
|
|
80
|
+
expect(result.current.isOpen).toBe(false);
|
|
81
|
+
expect(result.current.view).toBe("files");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("surfaces a selection made while collapsed when the panel opens", () => {
|
|
85
|
+
const { result } = renderPanel();
|
|
86
|
+
act(() => result.current.notifySelection(item));
|
|
87
|
+
act(() => result.current.openPanel());
|
|
88
|
+
expect(result.current.view).toBe("inspect");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("yields to an explicit pick (sticky) over selection auto-switch", () => {
|
|
92
|
+
const { result } = renderPanel();
|
|
93
|
+
act(() => result.current.openPanel());
|
|
94
|
+
act(() => result.current.setView("usage"));
|
|
95
|
+
act(() => result.current.notifySelection(item));
|
|
96
|
+
expect(result.current.view).toBe("usage");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("leaves Inspect (and unsticks) when the selection clears", () => {
|
|
100
|
+
const { result } = renderPanel();
|
|
101
|
+
act(() => result.current.openPanel());
|
|
102
|
+
act(() => result.current.notifySelection(item));
|
|
103
|
+
expect(result.current.view).toBe("inspect");
|
|
104
|
+
act(() => result.current.notifySelection(null));
|
|
105
|
+
expect(result.current.view).toBe("files");
|
|
106
|
+
// Unstuck: the next selection auto-surfaces Inspect again.
|
|
107
|
+
act(() => result.current.notifySelection(item));
|
|
108
|
+
expect(result.current.view).toBe("inspect");
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("useSessionPanel — arrivals and phase", () => {
|
|
113
|
+
it("auto-surfaces Changes on first write-back while the panel is open", () => {
|
|
114
|
+
const { result, rerender } = renderPanel();
|
|
115
|
+
act(() => result.current.openPanel());
|
|
116
|
+
rerender({ phase: null, hasChanges: true });
|
|
117
|
+
expect(result.current.view).toBe("changes");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("never auto-opens (or re-routes) a collapsed panel on a write-back — badge only", () => {
|
|
121
|
+
const { result, rerender } = renderPanel();
|
|
122
|
+
rerender({ phase: null, hasChanges: true });
|
|
123
|
+
expect(result.current.isOpen).toBe(false);
|
|
124
|
+
expect(result.current.view).toBe("files");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("respects a sticky pick when a write-back arrives", () => {
|
|
128
|
+
const { result, rerender } = renderPanel();
|
|
129
|
+
act(() => result.current.openPanel());
|
|
130
|
+
act(() => result.current.setView("usage"));
|
|
131
|
+
rerender({ phase: null, hasChanges: true });
|
|
132
|
+
expect(result.current.view).toBe("usage");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("resets the sticky pick on a running→terminal transition", () => {
|
|
136
|
+
const { result, rerender } = renderPanel({
|
|
137
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
138
|
+
});
|
|
139
|
+
act(() => result.current.openPanel());
|
|
140
|
+
act(() => result.current.setView("usage"));
|
|
141
|
+
rerender({
|
|
142
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
143
|
+
hasChanges: false,
|
|
144
|
+
});
|
|
145
|
+
expect(result.current.view).toBe("files");
|
|
146
|
+
// Unstuck: a selection now auto-surfaces Inspect.
|
|
147
|
+
act(() => result.current.notifySelection(item));
|
|
148
|
+
expect(result.current.view).toBe("inspect");
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe("useSessionPanel — plan document tab", () => {
|
|
153
|
+
const planTab = {
|
|
154
|
+
entryId: PLAN_DOCUMENT_ENTRY_ID,
|
|
155
|
+
path: PLAN_DOCUMENT_PATH,
|
|
156
|
+
preview: false,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
function planEditors(result: { current: ReturnType<typeof useSessionPanel> }) {
|
|
160
|
+
return result.current.editorsStore.getSnapshot().editors;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
it("openPlanDocument opens the panel with a pinned plan tab", () => {
|
|
164
|
+
const { result } = renderPanel();
|
|
165
|
+
act(() => result.current.openPlanDocument());
|
|
166
|
+
expect(result.current.isOpen).toBe(true);
|
|
167
|
+
expect(planEditors(result)).toEqual([planTab]);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("keeps the plan tab pinned across preview browsing (never evicted)", () => {
|
|
171
|
+
const { result } = renderPanel();
|
|
172
|
+
act(() => result.current.openPlanDocument());
|
|
173
|
+
// Preview browsing reuses the single preview slot; the pinned plan tab
|
|
174
|
+
// must survive it untouched.
|
|
175
|
+
act(() => result.current.openFile("e1", "a.ts"));
|
|
176
|
+
act(() => result.current.openFile("e1", "b.ts"));
|
|
177
|
+
expect(planEditors(result)).toEqual([
|
|
178
|
+
planTab,
|
|
179
|
+
{ entryId: "e1", path: "b.ts", preview: true },
|
|
180
|
+
]);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("auto-opens the plan tab when a plan arrives — even from a collapsed panel", () => {
|
|
184
|
+
// The one deliberate exception to the "never open a collapsed panel"
|
|
185
|
+
// arrival convention: a completing plan is the turn's deliverable, and
|
|
186
|
+
// with the thread showing only a compact card there is no other review
|
|
187
|
+
// surface.
|
|
188
|
+
const { result, rerender } = renderPanel();
|
|
189
|
+
expect(result.current.isOpen).toBe(false);
|
|
190
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
191
|
+
expect(result.current.isOpen).toBe(true);
|
|
192
|
+
expect(planEditors(result)).toEqual([planTab]);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("activates (focuses) the plan tab on arrival, over the open file", () => {
|
|
196
|
+
const { result, rerender } = renderPanel();
|
|
197
|
+
act(() => result.current.openFile("e1", "a.ts"));
|
|
198
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
199
|
+
const { activeFile } = result.current.editorsStore.getSnapshot();
|
|
200
|
+
expect(activeFile).toEqual({
|
|
201
|
+
entryId: PLAN_DOCUMENT_ENTRY_ID,
|
|
202
|
+
path: PLAN_DOCUMENT_PATH,
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it("re-opens the plan tab when a refined plan supersedes the current one (new identity)", () => {
|
|
207
|
+
const { result, rerender } = renderPanel();
|
|
208
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
209
|
+
act(() =>
|
|
210
|
+
result.current.closeEditor(PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH),
|
|
211
|
+
);
|
|
212
|
+
expect(planEditors(result)).toEqual([]);
|
|
213
|
+
rerender({ phase: null, hasChanges: false, planKey: "e2:hash-b" });
|
|
214
|
+
expect(planEditors(result)).toEqual([planTab]);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("opens on the streaming identity, then idempotently re-fires when the plan publishes", () => {
|
|
218
|
+
// The viewer feeds `<executionId>:streaming` while the plan is being
|
|
219
|
+
// written, then the artifact identity once published — two identities,
|
|
220
|
+
// one pinned tab: the transition must not duplicate it or disturb it.
|
|
221
|
+
const { result, rerender } = renderPanel();
|
|
222
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:streaming" });
|
|
223
|
+
expect(result.current.isOpen).toBe(true);
|
|
224
|
+
expect(planEditors(result)).toEqual([planTab]);
|
|
225
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
226
|
+
expect(planEditors(result)).toEqual([planTab]);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("does not re-open the plan tab for an unchanged identity", () => {
|
|
230
|
+
const { result, rerender } = renderPanel();
|
|
231
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
232
|
+
act(() =>
|
|
233
|
+
result.current.closeEditor(PLAN_DOCUMENT_ENTRY_ID, PLAN_DOCUMENT_PATH),
|
|
234
|
+
);
|
|
235
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
236
|
+
expect(planEditors(result)).toEqual([]);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("does not open anything for a plan that existed at mount", () => {
|
|
240
|
+
// Loading a session with an old plan must not hijack the layout.
|
|
241
|
+
const { result, rerender } = renderPanel({ planKey: "e1:hash-a" });
|
|
242
|
+
expect(result.current.isOpen).toBe(false);
|
|
243
|
+
expect(planEditors(result)).toEqual([]);
|
|
244
|
+
// …and the mount identity doesn't count as "new" on later rerenders.
|
|
245
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
246
|
+
expect(planEditors(result)).toEqual([]);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("leaves the rail view alone (the tab lives in the editor area)", () => {
|
|
250
|
+
const { result, rerender } = renderPanel();
|
|
251
|
+
act(() => result.current.openPanel());
|
|
252
|
+
act(() => result.current.setView("usage"));
|
|
253
|
+
rerender({ phase: null, hasChanges: false, planKey: "e1:hash-a" });
|
|
254
|
+
expect(result.current.view).toBe("usage");
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe("useSessionPanel — defaultView (home view)", () => {
|
|
259
|
+
it("seeds the view to the provided defaultView (launcher homes on Config)", () => {
|
|
260
|
+
const { result } = renderPanel({ defaultView: "configure" });
|
|
261
|
+
expect(result.current.view).toBe("configure");
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it("returns to defaultView (not files) on a running→terminal reset", () => {
|
|
265
|
+
const { result, rerender } = renderPanel({
|
|
266
|
+
defaultView: "configure",
|
|
267
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
268
|
+
});
|
|
269
|
+
act(() => result.current.openPanel());
|
|
270
|
+
act(() => result.current.setView("usage"));
|
|
271
|
+
rerender({
|
|
272
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
273
|
+
hasChanges: false,
|
|
274
|
+
defaultView: "configure",
|
|
275
|
+
});
|
|
276
|
+
expect(result.current.view).toBe("configure");
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it("returns to defaultView (not files) when a selection clears", () => {
|
|
280
|
+
const { result } = renderPanel({ defaultView: "configure" });
|
|
281
|
+
act(() => result.current.openPanel());
|
|
282
|
+
act(() => result.current.notifySelection(item));
|
|
283
|
+
expect(result.current.view).toBe("inspect");
|
|
284
|
+
act(() => result.current.notifySelection(null));
|
|
285
|
+
expect(result.current.view).toBe("configure");
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("defaults the home view to Explorer (files) when omitted", () => {
|
|
289
|
+
const { result, rerender } = renderPanel({
|
|
290
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
291
|
+
});
|
|
292
|
+
expect(result.current.view).toBe("files");
|
|
293
|
+
act(() => result.current.openPanel());
|
|
294
|
+
act(() => result.current.setView("usage"));
|
|
295
|
+
rerender({ phase: ExecutionPhase.EXECUTION_COMPLETED, hasChanges: false });
|
|
296
|
+
expect(result.current.view).toBe("files");
|
|
297
|
+
});
|
|
298
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
|
+
import { renderHook, cleanup } from "@testing-library/react";
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// useSessionRailViews composes the session facets as injected rail views for
|
|
6
|
+
// the workspace surface. The facet components themselves have their own
|
|
7
|
+
// suites; here we prove the composition rules — ordering, contextual
|
|
8
|
+
// visibility (Changes/Artifacts only with data, Inspect only with a
|
|
9
|
+
// selection), and count badges — by mocking the aggregation hooks.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
const writeBacksState = { hasWriteBacks: false, writeBackCount: 0 };
|
|
13
|
+
const artifactsState = { hasArtifacts: false, artifactCount: 0 };
|
|
14
|
+
|
|
15
|
+
vi.mock("../useSessionWriteBacks", () => ({
|
|
16
|
+
useSessionWriteBacks: () => writeBacksState,
|
|
17
|
+
}));
|
|
18
|
+
vi.mock("../useSessionArtifacts", () => ({
|
|
19
|
+
useSessionArtifacts: () => artifactsState,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
import { useSessionRailViews } from "../useSessionRailViews";
|
|
23
|
+
import type { SetupTabProps } from "../facets/SetupTab";
|
|
24
|
+
import type { SelectedThreadItem } from "../../internal/store/selection-store";
|
|
25
|
+
|
|
26
|
+
const sessionConfig = {
|
|
27
|
+
agentRef: null,
|
|
28
|
+
isDefaultAgent: true,
|
|
29
|
+
mcpServerUsages: [],
|
|
30
|
+
skillRefs: [],
|
|
31
|
+
sessionVariables: null,
|
|
32
|
+
harness: "native",
|
|
33
|
+
executionTarget: undefined,
|
|
34
|
+
modelId: undefined,
|
|
35
|
+
} as SetupTabProps;
|
|
36
|
+
|
|
37
|
+
function renderViews(
|
|
38
|
+
overrides: Partial<Parameters<typeof useSessionRailViews>[0]> = {},
|
|
39
|
+
) {
|
|
40
|
+
return renderHook(() =>
|
|
41
|
+
useSessionRailViews({
|
|
42
|
+
allExecutions: [],
|
|
43
|
+
org: "acme",
|
|
44
|
+
sessionConfig,
|
|
45
|
+
selectedItem: null,
|
|
46
|
+
...overrides,
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
cleanup();
|
|
53
|
+
writeBacksState.hasWriteBacks = false;
|
|
54
|
+
writeBacksState.writeBackCount = 0;
|
|
55
|
+
artifactsState.hasArtifacts = false;
|
|
56
|
+
artifactsState.artifactCount = 0;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("useSessionRailViews", () => {
|
|
60
|
+
it("always offers Config and Usage; Changes/Artifacts/Inspect are contextual", () => {
|
|
61
|
+
const { result } = renderViews();
|
|
62
|
+
expect(result.current.map((v) => v.id)).toEqual(["configure", "usage"]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("omits Config when no session configuration is provided", () => {
|
|
66
|
+
const { result } = renderViews({ sessionConfig: undefined });
|
|
67
|
+
expect(result.current.map((v) => v.id)).toEqual(["usage"]);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("surfaces Changes with a write-back count badge", () => {
|
|
71
|
+
writeBacksState.hasWriteBacks = true;
|
|
72
|
+
writeBacksState.writeBackCount = 2;
|
|
73
|
+
const { result } = renderViews();
|
|
74
|
+
const changes = result.current.find((v) => v.id === "changes");
|
|
75
|
+
expect(changes?.badge).toBe(2);
|
|
76
|
+
expect(result.current.map((v) => v.id)).toEqual([
|
|
77
|
+
"configure",
|
|
78
|
+
"changes",
|
|
79
|
+
"usage",
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("surfaces Artifacts with a count badge", () => {
|
|
84
|
+
artifactsState.hasArtifacts = true;
|
|
85
|
+
artifactsState.artifactCount = 4;
|
|
86
|
+
const { result } = renderViews();
|
|
87
|
+
const artifacts = result.current.find((v) => v.id === "artifacts");
|
|
88
|
+
expect(artifacts?.badge).toBe(4);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("surfaces Inspect only while a thread item is selected", () => {
|
|
92
|
+
const selectedItem = { kind: "toolCall" } as unknown as SelectedThreadItem;
|
|
93
|
+
const { result, rerender } = renderHook(
|
|
94
|
+
({ item }: { item: SelectedThreadItem | null }) =>
|
|
95
|
+
useSessionRailViews({
|
|
96
|
+
allExecutions: [],
|
|
97
|
+
org: "acme",
|
|
98
|
+
sessionConfig,
|
|
99
|
+
selectedItem: item,
|
|
100
|
+
}),
|
|
101
|
+
{ initialProps: { item: selectedItem as SelectedThreadItem | null } },
|
|
102
|
+
);
|
|
103
|
+
expect(result.current.some((v) => v.id === "inspect")).toBe(true);
|
|
104
|
+
rerender({ item: null });
|
|
105
|
+
expect(result.current.some((v) => v.id === "inspect")).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("keeps full inspector ordering: Config, Changes, Artifacts, Usage, Inspect", () => {
|
|
109
|
+
writeBacksState.hasWriteBacks = true;
|
|
110
|
+
writeBacksState.writeBackCount = 1;
|
|
111
|
+
artifactsState.hasArtifacts = true;
|
|
112
|
+
artifactsState.artifactCount = 1;
|
|
113
|
+
const { result } = renderViews({
|
|
114
|
+
selectedItem: { kind: "toolCall" } as unknown as SelectedThreadItem,
|
|
115
|
+
});
|
|
116
|
+
expect(result.current.map((v) => v.id)).toEqual([
|
|
117
|
+
"configure",
|
|
118
|
+
"changes",
|
|
119
|
+
"artifacts",
|
|
120
|
+
"usage",
|
|
121
|
+
"inspect",
|
|
122
|
+
]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -21,22 +21,44 @@ export interface ArtifactsTabProps {
|
|
|
21
21
|
* action as the message-thread plan card.
|
|
22
22
|
*/
|
|
23
23
|
readonly onImplementPlan?: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Open a plan in the session panel's plan document tab. When provided, a
|
|
26
|
+
* `plan.md` artifact routes there instead of the preview modal — the plan
|
|
27
|
+
* is a first-class document, not a popup. Non-plan artifacts keep the
|
|
28
|
+
* modal. When omitted (hosts without the plan tab) the modal remains for
|
|
29
|
+
* every artifact.
|
|
30
|
+
*/
|
|
31
|
+
readonly onOpenPlan?: (executionId: string) => void;
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
/**
|
|
27
|
-
* Artifacts facet for the
|
|
35
|
+
* Artifacts facet for the session panel (a `useSessionRailViews` rail view).
|
|
28
36
|
*
|
|
29
37
|
* Wraps `useSessionArtifacts` → `ArtifactCard` list with
|
|
30
38
|
* `ArtifactPreviewModal` — the same content as `ArtifactsWidget`
|
|
31
39
|
* without the section heading.
|
|
32
40
|
*/
|
|
33
|
-
export function ArtifactsTab({
|
|
41
|
+
export function ArtifactsTab({
|
|
42
|
+
executions,
|
|
43
|
+
org,
|
|
44
|
+
onApplied,
|
|
45
|
+
onImplementPlan,
|
|
46
|
+
onOpenPlan,
|
|
47
|
+
}: ArtifactsTabProps) {
|
|
34
48
|
const { artifacts, hasArtifacts } = useSessionArtifacts(executions);
|
|
35
49
|
const [previewEntry, setPreviewEntry] = useState<SessionArtifactEntry | null>(null);
|
|
36
50
|
|
|
37
|
-
const handlePreview = useCallback(
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
const handlePreview = useCallback(
|
|
52
|
+
(entry: SessionArtifactEntry) => {
|
|
53
|
+
// The plan opens as a document (the panel's plan tab), never a popup.
|
|
54
|
+
if (onOpenPlan && isPlanArtifact(entry.artifact)) {
|
|
55
|
+
onOpenPlan(entry.executionId);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
setPreviewEntry(entry);
|
|
59
|
+
},
|
|
60
|
+
[onOpenPlan],
|
|
61
|
+
);
|
|
40
62
|
|
|
41
63
|
const handleClosePreview = useCallback(() => {
|
|
42
64
|
setPreviewEntry(null);
|
|
@@ -9,15 +9,15 @@ export interface ChangesTabProps {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Changes facet for the
|
|
12
|
+
* Changes facet for the session panel — the session's git write-backs
|
|
13
13
|
* (branch/commit/PR), one `WriteBackCard` per entry.
|
|
14
14
|
*
|
|
15
15
|
* Local file changes deliberately do NOT render here: they live in the
|
|
16
16
|
* transcript, where each stamped edit row shows its diff in place and the
|
|
17
17
|
* per-turn decision bar carries the review controls and file list
|
|
18
18
|
* (`FileReviewCard`). Duplicating them in a side panel gave the same change a
|
|
19
|
-
* third rendering with no added authority. The
|
|
20
|
-
* once a write-back exists (see `
|
|
19
|
+
* third rendering with no added authority. The facet therefore only surfaces
|
|
20
|
+
* once a write-back exists (see `useSessionRailViews`).
|
|
21
21
|
*/
|
|
22
22
|
export function ChangesTab({ executions }: ChangesTabProps) {
|
|
23
23
|
const { writeBacks, hasWriteBacks } = useSessionWriteBacks(executions);
|
|
@@ -32,11 +32,20 @@ export interface SetupTabProps {
|
|
|
32
32
|
* buttons. When absent, sections are read-only (DD-011).
|
|
33
33
|
*/
|
|
34
34
|
readonly mutations?: SetupTabMutationCallbacks;
|
|
35
|
+
/**
|
|
36
|
+
* Host-injected access management control (e.g. the Console's
|
|
37
|
+
* `ManageAccessButton`) rendered as the facet's final section. A slot keeps
|
|
38
|
+
* the SDK auth-agnostic (DD-004); the injected control owns its own
|
|
39
|
+
* visibility (permission gating), so this section renders no chrome of its
|
|
40
|
+
* own — an empty heading over a denied control would read as breakage.
|
|
41
|
+
*/
|
|
42
|
+
readonly accessSlot?: React.ReactNode;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
/**
|
|
38
46
|
* Persistent session configuration panel (Configure tab) — shows agent,
|
|
39
|
-
* MCP servers, skills, run config, and
|
|
47
|
+
* MCP servers, skills, run config, session variables, and the host's
|
|
48
|
+
* access management control (via `accessSlot`).
|
|
40
49
|
*
|
|
41
50
|
* Workspace management has moved to the dedicated Workspace tab.
|
|
42
51
|
*
|
|
@@ -56,6 +65,7 @@ export function SetupTab({
|
|
|
56
65
|
executionTarget,
|
|
57
66
|
modelId,
|
|
58
67
|
mutations,
|
|
68
|
+
accessSlot,
|
|
59
69
|
}: SetupTabProps) {
|
|
60
70
|
const hasSessionVars = sessionVariables != null && !sessionVariables.isEmpty;
|
|
61
71
|
|
|
@@ -86,6 +96,8 @@ export function SetupTab({
|
|
|
86
96
|
{hasSessionVars && (
|
|
87
97
|
<SessionVarsSection entries={sessionVariables.entries} />
|
|
88
98
|
)}
|
|
99
|
+
|
|
100
|
+
{accessSlot && <section>{accessSlot}</section>}
|
|
89
101
|
</div>
|
|
90
102
|
);
|
|
91
103
|
}
|
|
@@ -9,7 +9,7 @@ export interface UsageTabProps {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Usage facet for the
|
|
12
|
+
* Usage facet for the session panel (a `useSessionRailViews` rail view).
|
|
13
13
|
*
|
|
14
14
|
* Uses `useSessionUsage` to determine if data exists, then delegates
|
|
15
15
|
* rendering to the existing `UsageWidget`. Shows an empty state when
|
|
@@ -38,13 +38,17 @@ function createStigmerMock(): Stigmer {
|
|
|
38
38
|
} as unknown as Stigmer;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function renderTab(
|
|
41
|
+
function renderTab(
|
|
42
|
+
onImplementPlan?: () => void,
|
|
43
|
+
onOpenPlan?: (executionId: string) => void,
|
|
44
|
+
) {
|
|
42
45
|
return render(
|
|
43
46
|
<StigmerContext.Provider value={createStigmerMock()}>
|
|
44
47
|
<ArtifactsTab
|
|
45
48
|
executions={[execution]}
|
|
46
49
|
org="acme"
|
|
47
50
|
onImplementPlan={onImplementPlan}
|
|
51
|
+
onOpenPlan={onOpenPlan}
|
|
48
52
|
/>
|
|
49
53
|
</StigmerContext.Provider>,
|
|
50
54
|
);
|
|
@@ -57,33 +61,63 @@ function openPreviewFor(name: string) {
|
|
|
57
61
|
|
|
58
62
|
afterEach(cleanup);
|
|
59
63
|
|
|
60
|
-
describe("ArtifactsTab — plan 'Build
|
|
61
|
-
it("shows 'Build
|
|
64
|
+
describe("ArtifactsTab — plan 'Build' wiring", () => {
|
|
65
|
+
it("shows 'Build' in the preview of a plan.md artifact", () => {
|
|
62
66
|
renderTab(vi.fn());
|
|
63
67
|
|
|
64
68
|
openPreviewFor("plan.md");
|
|
65
69
|
|
|
66
70
|
const dialog = document.querySelector("dialog")!;
|
|
67
|
-
expect(within(dialog).getByText("Build
|
|
71
|
+
expect(within(dialog).getByText("Build")).toBeTruthy();
|
|
68
72
|
});
|
|
69
73
|
|
|
70
|
-
it("does not show 'Build
|
|
74
|
+
it("does not show 'Build' in the preview of a non-plan artifact", () => {
|
|
71
75
|
renderTab(vi.fn());
|
|
72
76
|
|
|
73
77
|
openPreviewFor("notes.md");
|
|
74
78
|
|
|
75
79
|
const dialog = document.querySelector("dialog")!;
|
|
76
|
-
expect(within(dialog).queryByText("Build
|
|
80
|
+
expect(within(dialog).queryByText("Build")).toBeNull();
|
|
77
81
|
});
|
|
78
82
|
|
|
79
|
-
it("invokes onImplementPlan when 'Build
|
|
83
|
+
it("invokes onImplementPlan when 'Build' is clicked for a plan", () => {
|
|
80
84
|
const onImplementPlan = vi.fn();
|
|
81
85
|
renderTab(onImplementPlan);
|
|
82
86
|
|
|
83
87
|
openPreviewFor("plan.md");
|
|
84
88
|
const dialog = document.querySelector("dialog")!;
|
|
85
|
-
fireEvent.click(within(dialog).getByText("Build
|
|
89
|
+
fireEvent.click(within(dialog).getByText("Build"));
|
|
86
90
|
|
|
87
91
|
expect(onImplementPlan).toHaveBeenCalledTimes(1);
|
|
88
92
|
});
|
|
89
93
|
});
|
|
94
|
+
|
|
95
|
+
describe("ArtifactsTab — plan routes to the plan document tab", () => {
|
|
96
|
+
it("routes a plan.md preview to onOpenPlan (no modal) when provided", () => {
|
|
97
|
+
const onOpenPlan = vi.fn();
|
|
98
|
+
renderTab(vi.fn(), onOpenPlan);
|
|
99
|
+
|
|
100
|
+
openPreviewFor("plan.md");
|
|
101
|
+
|
|
102
|
+
expect(onOpenPlan).toHaveBeenCalledWith("aex_1");
|
|
103
|
+
expect(document.querySelector("dialog")).toBeNull();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("keeps the modal for non-plan artifacts even when onOpenPlan is provided", () => {
|
|
107
|
+
const onOpenPlan = vi.fn();
|
|
108
|
+
renderTab(vi.fn(), onOpenPlan);
|
|
109
|
+
|
|
110
|
+
openPreviewFor("notes.md");
|
|
111
|
+
|
|
112
|
+
expect(onOpenPlan).not.toHaveBeenCalled();
|
|
113
|
+
expect(document.querySelector("dialog")).toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("keeps the modal for plan.md when onOpenPlan is omitted (hosts without the plan tab)", () => {
|
|
117
|
+
renderTab(vi.fn());
|
|
118
|
+
|
|
119
|
+
openPreviewFor("plan.md");
|
|
120
|
+
|
|
121
|
+
expect(document.querySelector("dialog")).toBeTruthy();
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import { render, screen, cleanup } from "@testing-library/react";
|
|
3
|
+
import { SetupTab, type SetupTabProps } from "../SetupTab";
|
|
4
|
+
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// The Config facet's access section: a host-injected slot with no chrome of
|
|
7
|
+
// its own — the injected control (e.g. the Console's ManageAccessButton) owns
|
|
8
|
+
// its visibility, so the facet must render nothing extra when the slot is
|
|
9
|
+
// absent or the control gates itself away.
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
afterEach(cleanup);
|
|
13
|
+
|
|
14
|
+
const BASE_PROPS: SetupTabProps = {
|
|
15
|
+
agentRef: null,
|
|
16
|
+
isDefaultAgent: false,
|
|
17
|
+
mcpServerUsages: [],
|
|
18
|
+
skillRefs: [],
|
|
19
|
+
sessionVariables: null,
|
|
20
|
+
harness: "native",
|
|
21
|
+
executionTarget: undefined,
|
|
22
|
+
modelId: undefined,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
describe("SetupTab — access slot", () => {
|
|
26
|
+
it("renders the injected access control", () => {
|
|
27
|
+
render(
|
|
28
|
+
<SetupTab
|
|
29
|
+
{...BASE_PROPS}
|
|
30
|
+
accessSlot={<button type="button">Manage access</button>}
|
|
31
|
+
/>,
|
|
32
|
+
);
|
|
33
|
+
expect(
|
|
34
|
+
screen.getByRole("button", { name: "Manage access" }),
|
|
35
|
+
).toBeDefined();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("renders no access section when the slot is absent", () => {
|
|
39
|
+
const { container } = render(<SetupTab {...BASE_PROPS} />);
|
|
40
|
+
expect(screen.queryByRole("button", { name: "Manage access" })).toBeNull();
|
|
41
|
+
// Only the four always-on sections (run config, agent, MCP, skills).
|
|
42
|
+
expect(container.querySelectorAll("section")).toHaveLength(4);
|
|
43
|
+
});
|
|
44
|
+
});
|