@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,205 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { render, screen, cleanup, act, fireEvent } from "@testing-library/react";
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Wiring-contract test for transcript click-to-open: the onFilePathClick
|
|
6
|
+
// SessionViewer hands to MessageThread resolves a tool-call path, writes the
|
|
7
|
+
// open-editor store, AND expands the session panel — so the resolved file
|
|
8
|
+
// surfaces in the WorkspaceSurface. MessageThread and WorkspaceSurface render
|
|
9
|
+
// as prop-capturing probes; the store + SessionPanelRegion wire between them
|
|
10
|
+
// is the subject under test.
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
type CapturedProps = Record<string, unknown>;
|
|
14
|
+
|
|
15
|
+
const threadProps: CapturedProps[] = [];
|
|
16
|
+
vi.mock("../../execution/MessageThread", () => ({
|
|
17
|
+
MessageThread: (props: CapturedProps) => {
|
|
18
|
+
threadProps.push(props);
|
|
19
|
+
return <div data-testid="thread-probe" />;
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
const surfaceProps: CapturedProps[] = [];
|
|
24
|
+
vi.mock("../../workspace/WorkspaceSurface", () => ({
|
|
25
|
+
WorkspaceSurface: (props: CapturedProps) => {
|
|
26
|
+
surfaceProps.push(props);
|
|
27
|
+
return <div data-testid="surface-probe" />;
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
vi.mock("../../composer", async (importOriginal) => {
|
|
32
|
+
const actual = await importOriginal<typeof import("../../composer")>();
|
|
33
|
+
return {
|
|
34
|
+
...actual,
|
|
35
|
+
SessionComposer: () => <div data-testid="composer-probe" />,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const gitEntry = {
|
|
40
|
+
id: "e1",
|
|
41
|
+
name: "acme/app",
|
|
42
|
+
type: "git" as const,
|
|
43
|
+
gitUrl: "https://github.com/acme/app.git",
|
|
44
|
+
gitBranch: "main",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const stubWorkspace = {
|
|
48
|
+
entries: [gitEntry],
|
|
49
|
+
hasEntries: true,
|
|
50
|
+
toInput: vi.fn().mockReturnValue([]),
|
|
51
|
+
addGitRepo: vi.fn(),
|
|
52
|
+
addLocalPath: vi.fn(),
|
|
53
|
+
remove: vi.fn(),
|
|
54
|
+
clear: vi.fn(),
|
|
55
|
+
clearLocal: vi.fn(),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const stubConv = {
|
|
59
|
+
session: { spec: {} },
|
|
60
|
+
isLoading: false,
|
|
61
|
+
loadError: null,
|
|
62
|
+
completedExecutions: [],
|
|
63
|
+
activeStreamExecution: null,
|
|
64
|
+
pendingUserMessage: null,
|
|
65
|
+
workspaceEntries: [],
|
|
66
|
+
fileChangeSets: [],
|
|
67
|
+
submitFileDecision: vi.fn(),
|
|
68
|
+
submittingFileDecisionKeys: new Set<string>(),
|
|
69
|
+
fileDecisionErrors: new Map<string, Error>(),
|
|
70
|
+
sendError: null,
|
|
71
|
+
stopError: null,
|
|
72
|
+
streamError: null,
|
|
73
|
+
reconnectStream: vi.fn(),
|
|
74
|
+
submittingApprovalIds: new Set<string>(),
|
|
75
|
+
approvalErrors: new Map<string, Error>(),
|
|
76
|
+
isStoppable: false,
|
|
77
|
+
isStopping: false,
|
|
78
|
+
isSending: false,
|
|
79
|
+
canSendFollowUp: true,
|
|
80
|
+
isReconnecting: false,
|
|
81
|
+
connectTimedOut: false,
|
|
82
|
+
isSlow: false,
|
|
83
|
+
stop: vi.fn(),
|
|
84
|
+
retryLastSend: vi.fn(),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const stubSessionPageFlow = {
|
|
88
|
+
conv: stubConv,
|
|
89
|
+
harness: "native" as const,
|
|
90
|
+
executionTarget: undefined,
|
|
91
|
+
model: [undefined, vi.fn()] as const,
|
|
92
|
+
interactionMode: ["agent" as const, vi.fn()] as const,
|
|
93
|
+
agentRef: { org: "acme", slug: "support-bot" },
|
|
94
|
+
setAgentRef: vi.fn(),
|
|
95
|
+
resolution: null,
|
|
96
|
+
setResolution: vi.fn(),
|
|
97
|
+
isDefaultAgent: false,
|
|
98
|
+
mcpServerUsages: [],
|
|
99
|
+
setMcpServerUsages: vi.fn(),
|
|
100
|
+
skillRefs: [],
|
|
101
|
+
setSkillRefs: vi.fn(),
|
|
102
|
+
workspace: stubWorkspace,
|
|
103
|
+
sessionVariables: { entries: [], isEmpty: true, clear: vi.fn() },
|
|
104
|
+
autoApproveAll: false,
|
|
105
|
+
setAutoApproveAll: vi.fn(),
|
|
106
|
+
handleSubmit: vi.fn(),
|
|
107
|
+
submitError: null as Error | null,
|
|
108
|
+
displayExecution: null,
|
|
109
|
+
allExecutions: [],
|
|
110
|
+
sandboxWorkspaceRoot: "/home/daytona/workspace",
|
|
111
|
+
};
|
|
112
|
+
vi.mock("../useSessionPageFlow", () => ({
|
|
113
|
+
useSessionPageFlow: () => stubSessionPageFlow,
|
|
114
|
+
}));
|
|
115
|
+
|
|
116
|
+
vi.mock("../../hooks", () => ({
|
|
117
|
+
useStigmer: () => ({
|
|
118
|
+
agentExecution: {
|
|
119
|
+
uploadAttachment: vi.fn(),
|
|
120
|
+
getArtifactContent: vi.fn(),
|
|
121
|
+
},
|
|
122
|
+
}),
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
import { SessionViewer } from "../SessionViewer";
|
|
126
|
+
|
|
127
|
+
/** The onFilePathClick handler threaded down to the (mocked) MessageThread. */
|
|
128
|
+
function capturedOnFilePathClick(): (path: string) => boolean {
|
|
129
|
+
const props = threadProps.at(-1);
|
|
130
|
+
return props?.onFilePathClick as (path: string) => boolean;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** The latest selectedFile the (mocked) WorkspaceSurface received, if rendered. */
|
|
134
|
+
function latestSurfaceSelectedFile(): unknown {
|
|
135
|
+
return surfaceProps.at(-1)?.selectedFile ?? null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
beforeEach(() => {
|
|
139
|
+
threadProps.length = 0;
|
|
140
|
+
surfaceProps.length = 0;
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
afterEach(() => {
|
|
144
|
+
cleanup();
|
|
145
|
+
vi.clearAllMocks();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe("SessionViewer — transcript click-to-open wiring", () => {
|
|
149
|
+
it("threads an onFilePathClick to the message thread", () => {
|
|
150
|
+
render(<SessionViewer sessionId="ses_1" org="acme" />);
|
|
151
|
+
expect(typeof capturedOnFilePathClick()).toBe("function");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("opens a resolvable tool-call path in the session panel", () => {
|
|
155
|
+
render(<SessionViewer sessionId="ses_1" org="acme" />);
|
|
156
|
+
// Before any click: panel collapsed — the surface is not rendered.
|
|
157
|
+
expect(surfaceProps.length).toBe(0);
|
|
158
|
+
|
|
159
|
+
let handled: boolean | undefined;
|
|
160
|
+
act(() => {
|
|
161
|
+
handled = capturedOnFilePathClick()("/home/daytona/workspace/src/main.go");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(handled).toBe(true);
|
|
165
|
+
// Opening expands the panel and routes the resolved selection into the
|
|
166
|
+
// surface — the SAME selection a tree click yields.
|
|
167
|
+
expect(latestSurfaceSelectedFile()).toEqual({
|
|
168
|
+
entryId: "e1",
|
|
169
|
+
path: "src/main.go",
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("declines a platform path (returns false) and opens nothing", () => {
|
|
174
|
+
render(<SessionViewer sessionId="ses_1" org="acme" />);
|
|
175
|
+
|
|
176
|
+
let handled: boolean | undefined;
|
|
177
|
+
act(() => {
|
|
178
|
+
handled = capturedOnFilePathClick()(".stigmer/skills/x.md");
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
expect(handled).toBe(false);
|
|
182
|
+
// The panel stays collapsed: no surface rendered.
|
|
183
|
+
expect(surfaceProps.length).toBe(0);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("collapses back to full-width chat via the chip without losing the editor group", () => {
|
|
187
|
+
render(<SessionViewer sessionId="ses_1" org="acme" />);
|
|
188
|
+
act(() => {
|
|
189
|
+
capturedOnFilePathClick()("/home/daytona/workspace/src/main.go");
|
|
190
|
+
});
|
|
191
|
+
expect(latestSurfaceSelectedFile()).toEqual({ entryId: "e1", path: "src/main.go" });
|
|
192
|
+
|
|
193
|
+
// Chip is the hide affordance while open …
|
|
194
|
+
fireEvent.click(screen.getByRole("button", { name: "Hide panel" }));
|
|
195
|
+
const countBefore = surfaceProps.length;
|
|
196
|
+
|
|
197
|
+
// … and the show affordance while collapsed; the editor group survives.
|
|
198
|
+
fireEvent.click(screen.getByRole("button", { name: "Show panel" }));
|
|
199
|
+
expect(surfaceProps.length).toBeGreaterThan(countBefore);
|
|
200
|
+
expect(latestSurfaceSelectedFile()).toEqual({
|
|
201
|
+
entryId: "e1",
|
|
202
|
+
path: "src/main.go",
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
@@ -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
|
+
});
|
|
@@ -312,6 +312,50 @@ describe("useSessionConversation", () => {
|
|
|
312
312
|
});
|
|
313
313
|
});
|
|
314
314
|
|
|
315
|
+
it("sets NO optimistic pendingUserMessage for a buildFromPlan send (the thread hides the turn)", async () => {
|
|
316
|
+
methods.listBySession.mockResolvedValue({ entries: [] });
|
|
317
|
+
const newExec = makeExecution("new-exec", ExecutionPhase.EXECUTION_PENDING);
|
|
318
|
+
newExec.metadata!.id = "new-exec";
|
|
319
|
+
methods.executionCreate.mockResolvedValue(newExec);
|
|
320
|
+
|
|
321
|
+
const { result } = renderHook(
|
|
322
|
+
() => useSessionConversation("session-1", "org"),
|
|
323
|
+
{ wrapper: createWrapper(mockStigmer) },
|
|
324
|
+
);
|
|
325
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
326
|
+
|
|
327
|
+
await act(async () => {
|
|
328
|
+
await result.current.sendFollowUp("Build from plan", {
|
|
329
|
+
buildFromPlan: true,
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
expect(result.current.pendingUserMessage).toBeNull();
|
|
334
|
+
expect(methods.executionCreate).toHaveBeenCalledWith(
|
|
335
|
+
expect.objectContaining({ message: "Build from plan" }),
|
|
336
|
+
);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it("sets pendingUserMessage when a buildFromPlan send FAILS (failure must be visible)", async () => {
|
|
340
|
+
methods.listBySession.mockResolvedValue({ entries: [] });
|
|
341
|
+
methods.executionCreate.mockRejectedValue(new Error("create boom"));
|
|
342
|
+
|
|
343
|
+
const { result } = renderHook(
|
|
344
|
+
() => useSessionConversation("session-1", "org"),
|
|
345
|
+
{ wrapper: createWrapper(mockStigmer) },
|
|
346
|
+
);
|
|
347
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
348
|
+
|
|
349
|
+
await act(async () => {
|
|
350
|
+
await result.current.sendFollowUp("Build from plan", {
|
|
351
|
+
buildFromPlan: true,
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
expect(result.current.sendError?.message).toBe("create boom");
|
|
356
|
+
expect(result.current.pendingUserMessage).toBe("Build from plan");
|
|
357
|
+
});
|
|
358
|
+
|
|
315
359
|
it("preserves the message and surfaces sendError when the send fails", async () => {
|
|
316
360
|
methods.listBySession.mockResolvedValue({ entries: [] });
|
|
317
361
|
methods.executionCreate.mockRejectedValue(new Error("create boom"));
|