@stigmer/react 3.1.1 → 3.1.2
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 +24 -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/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/MessageEntry.d.ts +29 -0
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +29 -5
- package/execution/MessageEntry.js.map +1 -1
- package/execution/MessageThread.d.ts +76 -13
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +178 -24
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts +27 -18
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +13 -23
- package/execution/PlanArtifactCard.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 +45 -0
- package/execution/PlanStreamingCard.d.ts.map +1 -0
- package/execution/PlanStreamingCard.js +35 -0
- package/execution/PlanStreamingCard.js.map +1 -0
- package/execution/index.d.ts +5 -1
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +2 -0
- package/execution/index.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +10 -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 +21 -0
- package/library/detect-plan-artifact.d.ts.map +1 -1
- package/library/detect-plan-artifact.js +20 -0
- 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 +315 -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 +9 -0
- package/session/plan-document.d.ts.map +1 -0
- package/session/plan-document.js +17 -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 +6 -0
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +1 -0
- 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 +52 -10
- package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
- package/src/execution/ArtifactContentRenderer.tsx +101 -24
- package/src/execution/FilePathContext.tsx +8 -1
- package/src/execution/FilePathLink.tsx +22 -6
- package/src/execution/MessageEntry.tsx +111 -1
- package/src/execution/MessageThread.tsx +291 -36
- package/src/execution/PlanArtifactCard.tsx +63 -31
- package/src/execution/PlanDocumentMessage.tsx +96 -0
- package/src/execution/PlanStreamingCard.tsx +137 -0
- package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
- package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
- package/src/execution/__tests__/MessageThread.test.tsx +101 -0
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +66 -12
- package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
- package/src/execution/__tests__/PlanStreamingCard.test.tsx +49 -0
- package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +504 -22
- package/src/execution/__tests__/message-entry.test.tsx +48 -0
- package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
- package/src/execution/index.ts +7 -1
- package/src/execution/useCreateAgentExecution.ts +16 -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 +63 -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 +43 -3
- 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 +48 -0
- package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
- package/src/library/detect-plan-artifact.ts +35 -0
- package/src/library/detect-streaming-plan.ts +108 -0
- package/src/library/index.ts +5 -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 +617 -90
- 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 +9 -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__/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 +35 -1
- 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 +19 -0
- package/src/session/useOpenFileChange.ts +53 -0
- package/src/session/usePlanDraft.ts +109 -0
- package/src/session/useSessionConversation.ts +7 -0
- 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 +145 -0
- package/src/workspace/ExplorerTree.tsx +247 -0
- package/src/workspace/FileViewer.tsx +516 -0
- package/src/workspace/WorkspaceContentSearch.tsx +478 -0
- package/src/workspace/WorkspaceContentSearcher.ts +70 -0
- package/src/workspace/WorkspaceFileLister.ts +11 -0
- package/src/workspace/WorkspaceFileReader.ts +57 -0
- package/src/workspace/WorkspaceFileSearch.tsx +429 -0
- package/src/workspace/WorkspaceSurface.tsx +781 -0
- package/src/workspace/__tests__/EditorTabs.test.tsx +100 -0
- package/src/workspace/__tests__/ExplorerTree.test.tsx +152 -0
- package/src/workspace/__tests__/FileViewer.test.tsx +421 -0
- package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +196 -0
- package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +206 -0
- package/src/workspace/__tests__/WorkspaceSurface.test.tsx +348 -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 +29 -0
- package/workspace/EditorTabs.d.ts.map +1 -0
- package/workspace/EditorTabs.js +66 -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 +45 -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 +182 -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 +195 -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/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 +155 -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 +184 -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
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { render, screen, cleanup } from "@testing-library/react";
|
|
2
|
+
import { render, screen, cleanup, fireEvent } from "@testing-library/react";
|
|
3
3
|
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
5
|
-
// Wiring-contract tests for the `audience` preset
|
|
5
|
+
// Wiring-contract tests for the `audience` preset and the host slots on the
|
|
6
|
+
// session organisms.
|
|
6
7
|
//
|
|
7
|
-
// The composer and
|
|
8
|
-
// tests assert exactly what `audience="endUser"`
|
|
9
|
-
// unwired MCP/skill/session-variable pickers, and a
|
|
8
|
+
// The composer and the Config facet (SetupTab) are replaced with
|
|
9
|
+
// prop-capturing probes so the tests assert exactly what `audience="endUser"`
|
|
10
|
+
// maps to: a locked agent, unwired MCP/skill/session-variable pickers, and a
|
|
11
|
+
// read-only Config facet. The Config facet lives in the session panel's rail,
|
|
12
|
+
// so the probe is reached by opening the panel (chip) and picking Config.
|
|
10
13
|
// The molecules' own behavior is covered by their co-located tests.
|
|
11
14
|
// ---------------------------------------------------------------------------
|
|
12
15
|
|
|
@@ -24,11 +27,11 @@ vi.mock("../../composer", async (importOriginal) => {
|
|
|
24
27
|
};
|
|
25
28
|
});
|
|
26
29
|
|
|
27
|
-
const
|
|
28
|
-
vi.mock("../
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return <div data-testid="
|
|
30
|
+
const setupTabProps: CapturedProps[] = [];
|
|
31
|
+
vi.mock("../facets/SetupTab", () => ({
|
|
32
|
+
SetupTab: (props: CapturedProps) => {
|
|
33
|
+
setupTabProps.push(props);
|
|
34
|
+
return <div data-testid="setup-probe" />;
|
|
32
35
|
},
|
|
33
36
|
}));
|
|
34
37
|
|
|
@@ -137,6 +140,15 @@ vi.mock("../useSessionPageFlow", () => ({
|
|
|
137
140
|
useSessionPageFlow: (options: unknown) => mockUseSessionPageFlow(options),
|
|
138
141
|
}));
|
|
139
142
|
|
|
143
|
+
vi.mock("../../hooks", () => ({
|
|
144
|
+
useStigmer: () => ({
|
|
145
|
+
agentExecution: {
|
|
146
|
+
uploadAttachment: vi.fn(),
|
|
147
|
+
getArtifactContent: vi.fn(),
|
|
148
|
+
},
|
|
149
|
+
}),
|
|
150
|
+
}));
|
|
151
|
+
|
|
140
152
|
import { NewSessionViewer } from "../NewSessionViewer";
|
|
141
153
|
import { SessionViewer } from "../SessionViewer";
|
|
142
154
|
|
|
@@ -147,14 +159,21 @@ function lastComposerProps(): CapturedProps {
|
|
|
147
159
|
return composerProps.at(-1)!;
|
|
148
160
|
}
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Reach the Config facet through the unified panel: expand it via the
|
|
164
|
+
* top-right chip, pick Config in the rail, and return the props the (mocked)
|
|
165
|
+
* SetupTab received.
|
|
166
|
+
*/
|
|
167
|
+
function openedConfigFacet(): { mutations?: unknown } {
|
|
168
|
+
fireEvent.click(screen.getByRole("button", { name: "Show panel" }));
|
|
169
|
+
fireEvent.click(screen.getByRole("radio", { name: "Config" }));
|
|
170
|
+
expect(setupTabProps.length).toBeGreaterThan(0);
|
|
171
|
+
return setupTabProps.at(-1)!;
|
|
153
172
|
}
|
|
154
173
|
|
|
155
174
|
beforeEach(() => {
|
|
156
175
|
composerProps.length = 0;
|
|
157
|
-
|
|
176
|
+
setupTabProps.length = 0;
|
|
158
177
|
stubSessionPageFlow.submitError = null;
|
|
159
178
|
});
|
|
160
179
|
|
|
@@ -178,7 +197,7 @@ describe("NewSessionViewer — audience wiring", () => {
|
|
|
178
197
|
expect(props.onMcpServerUsagesChange).toBeDefined();
|
|
179
198
|
expect(props.onSkillRefsChange).toBeDefined();
|
|
180
199
|
expect(props.sessionVariables).toBeDefined();
|
|
181
|
-
expect(
|
|
200
|
+
expect(openedConfigFacet().mutations).toBeDefined();
|
|
182
201
|
});
|
|
183
202
|
|
|
184
203
|
it("endUser with a pinned agent: locked agent, integrator pickers unwired", () => {
|
|
@@ -199,8 +218,8 @@ describe("NewSessionViewer — audience wiring", () => {
|
|
|
199
218
|
// End-user controls survive the curation.
|
|
200
219
|
expect(props.showHarnessSelector).toBe(true);
|
|
201
220
|
expect(props.showInteractionModePicker).toBe(true);
|
|
202
|
-
//
|
|
203
|
-
expect(
|
|
221
|
+
// Config facet is read-only: no remove affordances for pinned config.
|
|
222
|
+
expect(openedConfigFacet().mutations).toBeUndefined();
|
|
204
223
|
});
|
|
205
224
|
|
|
206
225
|
it("endUser without a pinned agent: pickers hidden but agent not locked", () => {
|
|
@@ -241,7 +260,7 @@ describe("SessionViewer — audience wiring", () => {
|
|
|
241
260
|
expect(props.onMcpServerUsagesChange).toBeDefined();
|
|
242
261
|
expect(props.onSkillRefsChange).toBeDefined();
|
|
243
262
|
expect(props.sessionVariables).toBeDefined();
|
|
244
|
-
expect(
|
|
263
|
+
expect(openedConfigFacet().mutations).toBeDefined();
|
|
245
264
|
});
|
|
246
265
|
|
|
247
266
|
it("endUser: locked agent, integrator pickers unwired, read-only Setup tab", () => {
|
|
@@ -254,7 +273,7 @@ describe("SessionViewer — audience wiring", () => {
|
|
|
254
273
|
expect(props.sessionVariables).toBeUndefined();
|
|
255
274
|
// End-user controls survive the curation.
|
|
256
275
|
expect(props.showInteractionModePicker).toBe(true);
|
|
257
|
-
expect(
|
|
276
|
+
expect(openedConfigFacet().mutations).toBeUndefined();
|
|
258
277
|
});
|
|
259
278
|
|
|
260
279
|
it("forwards getRuntimeEnv to the flow", () => {
|
|
@@ -268,6 +287,23 @@ describe("SessionViewer — audience wiring", () => {
|
|
|
268
287
|
);
|
|
269
288
|
});
|
|
270
289
|
|
|
290
|
+
it("threads accessSlot into the Config facet, not the header", () => {
|
|
291
|
+
render(
|
|
292
|
+
<SessionViewer
|
|
293
|
+
sessionId="ses_1"
|
|
294
|
+
org="acme"
|
|
295
|
+
accessSlot={<button type="button">Manage access</button>}
|
|
296
|
+
/>,
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
// Collapsed panel: the slot must not surface anywhere (the header carries
|
|
300
|
+
// only headerActions and the chip).
|
|
301
|
+
expect(screen.queryByRole("button", { name: "Manage access" })).toBeNull();
|
|
302
|
+
|
|
303
|
+
const facet = openedConfigFacet() as { accessSlot?: unknown };
|
|
304
|
+
expect(facet.accessSlot).toBeDefined();
|
|
305
|
+
});
|
|
306
|
+
|
|
271
307
|
it("renders the flow's submitError through the send-error banner", () => {
|
|
272
308
|
stubSessionPageFlow.submitError = new Error("token mint failed");
|
|
273
309
|
render(<SessionViewer sessionId="ses_1" org="acme" />);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { renderHook } from "@testing-library/react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import {
|
|
5
|
+
FileChangeSchema,
|
|
6
|
+
type FileChange,
|
|
7
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
8
|
+
import { FileChangeType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
9
|
+
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// useOpenFileChange correlates the open file with the ONE session change that
|
|
13
|
+
// touched it (diff-as-default source, DD-06) — the contract that used to live on
|
|
14
|
+
// the inspector's Viewer tab and now feeds the workspace surface. The fold
|
|
15
|
+
// (useSessionFileChanges) is mocked; the join (findChangeForSelection) is real.
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
let mockFileChanges: FileChange[] = [];
|
|
19
|
+
vi.mock("../useSessionFileChanges", () => ({
|
|
20
|
+
useSessionFileChanges: (executions: readonly unknown[]) => ({
|
|
21
|
+
// Honor the EMPTY_EXECUTIONS gate: no executions in → no changes out.
|
|
22
|
+
fileChanges: executions.length > 0 ? mockFileChanges : [],
|
|
23
|
+
hasFileChanges: executions.length > 0 && mockFileChanges.length > 0,
|
|
24
|
+
fileChangeCount: executions.length > 0 ? mockFileChanges.length : 0,
|
|
25
|
+
}),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
import { useOpenFileChange } from "../useOpenFileChange";
|
|
29
|
+
|
|
30
|
+
const gitEntry = {
|
|
31
|
+
id: "e1",
|
|
32
|
+
name: "acme/app",
|
|
33
|
+
type: "git" as const,
|
|
34
|
+
gitUrl: "https://github.com/acme/app.git",
|
|
35
|
+
gitBranch: "main",
|
|
36
|
+
};
|
|
37
|
+
const entries = [gitEntry] as never;
|
|
38
|
+
const allExecutions = [{} as AgentExecution];
|
|
39
|
+
const root = "/home/daytona/workspace";
|
|
40
|
+
|
|
41
|
+
function modifyChange(path: string): FileChange {
|
|
42
|
+
return create(FileChangeSchema, { path, changeType: FileChangeType.MODIFY });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
mockFileChanges = [];
|
|
47
|
+
});
|
|
48
|
+
afterEach(() => vi.clearAllMocks());
|
|
49
|
+
|
|
50
|
+
describe("useOpenFileChange", () => {
|
|
51
|
+
it("returns the matching change for the open file", () => {
|
|
52
|
+
mockFileChanges = [modifyChange("src/a.ts")];
|
|
53
|
+
const { result } = renderHook(() =>
|
|
54
|
+
useOpenFileChange({ entryId: "e1", path: "src/a.ts" }, allExecutions, entries, root),
|
|
55
|
+
);
|
|
56
|
+
expect(result.current).toBe(mockFileChanges[0]);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("returns null when the open file was not changed this session", () => {
|
|
60
|
+
mockFileChanges = [modifyChange("src/a.ts")];
|
|
61
|
+
const { result } = renderHook(() =>
|
|
62
|
+
useOpenFileChange({ entryId: "e1", path: "src/other.ts" }, allExecutions, entries, root),
|
|
63
|
+
);
|
|
64
|
+
expect(result.current).toBeNull();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("returns null when no file is open (fold is skipped)", () => {
|
|
68
|
+
mockFileChanges = [modifyChange("src/a.ts")];
|
|
69
|
+
const { result } = renderHook(() =>
|
|
70
|
+
useOpenFileChange(null, allExecutions, entries, root),
|
|
71
|
+
);
|
|
72
|
+
expect(result.current).toBeNull();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("returns null when the session has no changes", () => {
|
|
76
|
+
mockFileChanges = [];
|
|
77
|
+
const { result } = renderHook(() =>
|
|
78
|
+
useOpenFileChange({ entryId: "e1", path: "src/a.ts" }, allExecutions, entries, root),
|
|
79
|
+
);
|
|
80
|
+
expect(result.current).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from "vitest";
|
|
2
|
+
import { renderHook, act, cleanup } from "@testing-library/react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import { ExecutionArtifactSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/artifact_pb";
|
|
5
|
+
import { ExecutionArtifactKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
6
|
+
import type { SessionPlan } from "../../library/detect-plan-artifact";
|
|
7
|
+
import { usePlanDraft, planDraftKey } from "../usePlanDraft";
|
|
8
|
+
|
|
9
|
+
afterEach(cleanup);
|
|
10
|
+
|
|
11
|
+
function plan(executionId: string, contentHash: string): SessionPlan {
|
|
12
|
+
return {
|
|
13
|
+
executionId,
|
|
14
|
+
artifact: create(ExecutionArtifactSchema, {
|
|
15
|
+
name: "plan.md",
|
|
16
|
+
kind: ExecutionArtifactKind.FILE,
|
|
17
|
+
storageKey: `artifacts/${executionId}/plan.md`,
|
|
18
|
+
contentHash,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe("planDraftKey", () => {
|
|
24
|
+
it("keys by execution AND content hash", () => {
|
|
25
|
+
expect(planDraftKey(plan("e1", "aaa"))).toBe("e1:aaa");
|
|
26
|
+
expect(planDraftKey(plan("e1", "bbb"))).not.toBe(planDraftKey(plan("e1", "aaa")));
|
|
27
|
+
expect(planDraftKey(plan("e2", "aaa"))).not.toBe(planDraftKey(plan("e1", "aaa")));
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("usePlanDraft", () => {
|
|
32
|
+
it("starts unedited and holds a draft for the current plan", () => {
|
|
33
|
+
const { result } = renderHook(({ p }) => usePlanDraft(p), {
|
|
34
|
+
initialProps: { p: plan("e1", "aaa") as SessionPlan | undefined },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(result.current.isEdited).toBe(false);
|
|
38
|
+
expect(result.current.draftText).toBeNull();
|
|
39
|
+
|
|
40
|
+
act(() => result.current.setDraft("# Edited plan"));
|
|
41
|
+
expect(result.current.isEdited).toBe(true);
|
|
42
|
+
expect(result.current.draftText).toBe("# Edited plan");
|
|
43
|
+
expect(result.current.readDraft()).toBe("# Edited plan");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("reverts to the published plan when the draft is cleared", () => {
|
|
47
|
+
const { result } = renderHook(({ p }) => usePlanDraft(p), {
|
|
48
|
+
initialProps: { p: plan("e1", "aaa") as SessionPlan | undefined },
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
act(() => result.current.setDraft("edit"));
|
|
52
|
+
act(() => result.current.setDraft(null));
|
|
53
|
+
expect(result.current.isEdited).toBe(false);
|
|
54
|
+
expect(result.current.readDraft()).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("drops the draft when a newer plan supersedes it (new execution)", () => {
|
|
58
|
+
const { result, rerender } = renderHook(({ p }) => usePlanDraft(p), {
|
|
59
|
+
initialProps: { p: plan("e1", "aaa") as SessionPlan | undefined },
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
act(() => result.current.setDraft("draft of plan 1"));
|
|
63
|
+
rerender({ p: plan("e2", "bbb") });
|
|
64
|
+
|
|
65
|
+
expect(result.current.isEdited).toBe(false);
|
|
66
|
+
expect(result.current.draftText).toBeNull();
|
|
67
|
+
expect(result.current.readDraft()).toBeNull();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("drops the draft when the same plan is republished with new content", () => {
|
|
71
|
+
const { result, rerender } = renderHook(({ p }) => usePlanDraft(p), {
|
|
72
|
+
initialProps: { p: plan("e1", "aaa") as SessionPlan | undefined },
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
act(() => result.current.setDraft("stale draft"));
|
|
76
|
+
rerender({ p: plan("e1", "bbb") });
|
|
77
|
+
|
|
78
|
+
expect(result.current.readDraft()).toBeNull();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("no-ops setDraft when the session has no plan", () => {
|
|
82
|
+
const { result } = renderHook(({ p }) => usePlanDraft(p), {
|
|
83
|
+
initialProps: { p: undefined as SessionPlan | undefined },
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
act(() => result.current.setDraft("nowhere to go"));
|
|
87
|
+
expect(result.current.isEdited).toBe(false);
|
|
88
|
+
expect(result.current.readDraft()).toBeNull();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("keeps readDraft referentially stable across draft edits (DD-010)", () => {
|
|
92
|
+
const { result, rerender } = renderHook(({ p }) => usePlanDraft(p), {
|
|
93
|
+
initialProps: { p: plan("e1", "aaa") as SessionPlan | undefined },
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const readBefore = result.current.readDraft;
|
|
97
|
+
act(() => result.current.setDraft("edit 1"));
|
|
98
|
+
rerender({ p: plan("e1", "aaa") });
|
|
99
|
+
expect(result.current.readDraft).toBe(readBefore);
|
|
100
|
+
expect(result.current.readDraft()).toBe("edit 1");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -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
|
+
});
|