@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
|
@@ -14,6 +14,12 @@ export interface PlanArtifactCardProps {
|
|
|
14
14
|
readonly executionId: string;
|
|
15
15
|
/** The published `plan.md` artifact (from `findPlanArtifact`). */
|
|
16
16
|
readonly artifact: ExecutionArtifact;
|
|
17
|
+
/**
|
|
18
|
+
* The plan's title (its leading `# H1`). The card is the plan's compact
|
|
19
|
+
* stand-in in the thread, so the title is what makes it recognizable.
|
|
20
|
+
* Falls back to "Plan" when omitted.
|
|
21
|
+
*/
|
|
22
|
+
readonly title?: string;
|
|
17
23
|
/**
|
|
18
24
|
* Organization slug. Required for the "Open full" modal (the shared
|
|
19
25
|
* {@link ArtifactPreviewModal} uses it for its detection/apply pipeline and
|
|
@@ -23,33 +29,36 @@ export interface PlanArtifactCardProps {
|
|
|
23
29
|
readonly org?: string;
|
|
24
30
|
/** Called when the user clicks "Build from plan". Hidden when omitted. */
|
|
25
31
|
readonly onImplement?: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Opens the plan in the session panel's plan document tab — the
|
|
34
|
+
* side-by-side review/refine surface. When provided it REPLACES the
|
|
35
|
+
* modal-based "Open full" secondary with "Open plan" (one review
|
|
36
|
+
* affordance, not two). When omitted (hosts without a session panel) the
|
|
37
|
+
* modal remains.
|
|
38
|
+
*/
|
|
39
|
+
readonly onOpenPlan?: () => void;
|
|
26
40
|
/** Disables the primary CTA (e.g., while an execution is active). */
|
|
27
41
|
readonly disabled?: boolean;
|
|
42
|
+
/** When true, the primary button reads "Starting build…" (upload in flight). */
|
|
43
|
+
readonly buildPending?: boolean;
|
|
28
44
|
/** Additional CSS classes for the root element. */
|
|
29
45
|
readonly className?: string;
|
|
30
46
|
}
|
|
31
47
|
|
|
32
48
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* shows the plan as rich markdown — the message renderer unwraps a model's
|
|
38
|
-
* enclosing markdown fence), so this card deliberately holds **no** plan
|
|
39
|
-
* content: the message is the document and this is its action bar. Rendering
|
|
40
|
-
* the plan a second time here would duplicate the same text the message and the
|
|
41
|
-
* "Open full" modal already show.
|
|
49
|
+
* The compact plan card — a completed Plan turn's sole representation in the
|
|
50
|
+
* thread. The plan document itself lives in the session panel's plan tab
|
|
51
|
+
* (`PlanEditor`), Cursor-style: chat carries a recognizable, actionable card;
|
|
52
|
+
* the panel carries the document.
|
|
42
53
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* first-class plan block.
|
|
54
|
+
* Anatomy: a document-style identity block (plan icon, the plan's title, a
|
|
55
|
+
* `plan.md · size` meta line) with the actions trailing — **Open plan** and
|
|
56
|
+
* **Download** as subdued secondaries and one prominent, themeable primary,
|
|
57
|
+
* **Build from plan** — so the next step is unmistakable.
|
|
48
58
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* remount.
|
|
59
|
+
* Only the LATEST plan's card carries `onImplement`; a superseded plan's card
|
|
60
|
+
* is review-only (its `onOpenPlan` opens the document read-only), so a stale
|
|
61
|
+
* plan can never be implemented by accident.
|
|
53
62
|
*
|
|
54
63
|
* All visual properties flow through `--stgm-*` tokens; the component is
|
|
55
64
|
* self-contained and embeddable.
|
|
@@ -57,9 +66,12 @@ export interface PlanArtifactCardProps {
|
|
|
57
66
|
export const PlanArtifactCard = memo(function PlanArtifactCard({
|
|
58
67
|
executionId,
|
|
59
68
|
artifact,
|
|
69
|
+
title,
|
|
60
70
|
org,
|
|
61
71
|
onImplement,
|
|
72
|
+
onOpenPlan,
|
|
62
73
|
disabled,
|
|
74
|
+
buildPending,
|
|
63
75
|
className,
|
|
64
76
|
}: PlanArtifactCardProps) {
|
|
65
77
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
@@ -69,35 +81,55 @@ export const PlanArtifactCard = memo(function PlanArtifactCard({
|
|
|
69
81
|
return (
|
|
70
82
|
<div
|
|
71
83
|
role="region"
|
|
72
|
-
aria-label="Plan
|
|
84
|
+
aria-label="Plan"
|
|
73
85
|
onKeyDown={handleKeyDown}
|
|
74
86
|
className={cn(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"mx-4 -mt-2 flex flex-wrap items-center gap-x-3 gap-y-2 rounded-md",
|
|
78
|
-
"border border-border-muted bg-muted-faint px-3 py-2",
|
|
87
|
+
"mx-4 flex flex-wrap items-center gap-x-3 gap-y-2 rounded-lg",
|
|
88
|
+
"border border-border-muted bg-card px-3 py-2.5",
|
|
79
89
|
className,
|
|
80
90
|
)}
|
|
81
91
|
>
|
|
82
92
|
<PlanIcon />
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
<div className="min-w-0 flex-1 basis-48">
|
|
94
|
+
<div className="truncate text-sm font-medium text-foreground">
|
|
95
|
+
{title ?? "Plan"}
|
|
96
|
+
</div>
|
|
97
|
+
<div className="text-[0.65rem] text-muted-foreground-faint">
|
|
98
|
+
{artifact.name}
|
|
99
|
+
<span aria-hidden="true"> · </span>
|
|
100
|
+
<span className="tabular-nums">
|
|
101
|
+
{formatArtifactSize(artifact.sizeBytes)}
|
|
102
|
+
</span>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
87
105
|
|
|
88
106
|
<div className="ml-auto flex flex-wrap items-center gap-x-3 gap-y-1.5">
|
|
89
|
-
{
|
|
107
|
+
{onOpenPlan ? (
|
|
90
108
|
<button
|
|
91
109
|
type="button"
|
|
92
|
-
onClick={
|
|
110
|
+
onClick={onOpenPlan}
|
|
93
111
|
className={cn(
|
|
94
112
|
"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground",
|
|
95
113
|
FOCUS_RING,
|
|
96
114
|
)}
|
|
97
115
|
>
|
|
98
116
|
<ExpandIcon />
|
|
99
|
-
Open
|
|
117
|
+
Open plan
|
|
100
118
|
</button>
|
|
119
|
+
) : (
|
|
120
|
+
org && (
|
|
121
|
+
<button
|
|
122
|
+
type="button"
|
|
123
|
+
onClick={() => setPreviewOpen(true)}
|
|
124
|
+
className={cn(
|
|
125
|
+
"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground",
|
|
126
|
+
FOCUS_RING,
|
|
127
|
+
)}
|
|
128
|
+
>
|
|
129
|
+
<ExpandIcon />
|
|
130
|
+
Open full
|
|
131
|
+
</button>
|
|
132
|
+
)
|
|
101
133
|
)}
|
|
102
134
|
<button
|
|
103
135
|
type="button"
|
|
@@ -125,7 +157,7 @@ export const PlanArtifactCard = memo(function PlanArtifactCard({
|
|
|
125
157
|
)}
|
|
126
158
|
>
|
|
127
159
|
<ImplementIcon />
|
|
128
|
-
Build from plan
|
|
160
|
+
{buildPending ? "Starting build…" : "Build from plan"}
|
|
129
161
|
</button>
|
|
130
162
|
)}
|
|
131
163
|
</div>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { memo, useMemo } from "react";
|
|
4
|
+
import { Streamdown } from "streamdown";
|
|
5
|
+
import { cn } from "@stigmer/theme";
|
|
6
|
+
import {
|
|
7
|
+
PLAN_DOCUMENT_MARKDOWN_COMPONENTS,
|
|
8
|
+
extractLeadingH1,
|
|
9
|
+
unwrapEnclosingMarkdownFence,
|
|
10
|
+
} from "../internal/markdown-components.js";
|
|
11
|
+
|
|
12
|
+
/** Props for {@link PlanDocumentMessage}. */
|
|
13
|
+
export interface PlanDocumentMessageProps {
|
|
14
|
+
/** The plan message's markdown content (the agent's final Plan-mode reply). */
|
|
15
|
+
readonly content: string;
|
|
16
|
+
/** Additional CSS class names for the root container. */
|
|
17
|
+
readonly className?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Renders a Plan-mode turn's plan as a first-class document instead of a chat
|
|
22
|
+
* bubble: a bordered card with a title header (the plan's leading `# H1`,
|
|
23
|
+
* lifted out of the prose) and document-grade typography
|
|
24
|
+
* ({@link PLAN_DOCUMENT_MARKDOWN_COMPONENTS}).
|
|
25
|
+
*
|
|
26
|
+
* This is the thread's NO-ARTIFACT fallback: a completed Plan turn that never
|
|
27
|
+
* published `plan.md` (older executions, a failed upload) keeps its plan
|
|
28
|
+
* inline via this component — the message is the only copy of the plan, so it
|
|
29
|
+
* must stay readable in place. A turn that DID publish the artifact collapses
|
|
30
|
+
* its plan message into the compact `PlanArtifactCard` instead, and the
|
|
31
|
+
* document renders in the session panel's plan tab (`PlanEditor`) with the
|
|
32
|
+
* same typography.
|
|
33
|
+
*
|
|
34
|
+
* Fence handling is plan-scoped: a plan wrapped in a whole-body fence is
|
|
35
|
+
* unwrapped even when the fence carries no language tag (`allowBareFence`) —
|
|
36
|
+
* a Plan turn's output is a markdown document by contract, so an enclosing
|
|
37
|
+
* bare fence is wrapping, not code. Render-time only; the transcript and the
|
|
38
|
+
* published artifact stay byte-faithful.
|
|
39
|
+
*
|
|
40
|
+
* Purely presentational — no data fetching, no state.
|
|
41
|
+
* All visual properties flow through `--stgm-*` tokens.
|
|
42
|
+
*/
|
|
43
|
+
export const PlanDocumentMessage = memo(function PlanDocumentMessage({
|
|
44
|
+
content,
|
|
45
|
+
className,
|
|
46
|
+
}: PlanDocumentMessageProps) {
|
|
47
|
+
const { title, body } = useMemo(
|
|
48
|
+
() => extractLeadingH1(unwrapEnclosingMarkdownFence(content, true)),
|
|
49
|
+
[content],
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
role="article"
|
|
55
|
+
aria-label="Plan document"
|
|
56
|
+
className={cn("mx-4", className)}
|
|
57
|
+
>
|
|
58
|
+
<div className="overflow-hidden rounded-lg border border-border-muted bg-card">
|
|
59
|
+
<header className="flex items-center gap-2 border-b border-border-muted bg-muted-faint px-4 py-2.5">
|
|
60
|
+
<PlanDocIcon />
|
|
61
|
+
<span className="min-w-0 flex-1 truncate text-sm font-semibold text-foreground">
|
|
62
|
+
{title ?? "Plan"}
|
|
63
|
+
</span>
|
|
64
|
+
</header>
|
|
65
|
+
<div className="stgm-prose px-4 py-4">
|
|
66
|
+
<Streamdown
|
|
67
|
+
components={PLAN_DOCUMENT_MARKDOWN_COMPONENTS}
|
|
68
|
+
isAnimating={false}
|
|
69
|
+
>
|
|
70
|
+
{body}
|
|
71
|
+
</Streamdown>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
function PlanDocIcon() {
|
|
79
|
+
return (
|
|
80
|
+
<svg
|
|
81
|
+
width="14"
|
|
82
|
+
height="14"
|
|
83
|
+
viewBox="0 0 16 16"
|
|
84
|
+
fill="none"
|
|
85
|
+
stroke="currentColor"
|
|
86
|
+
strokeWidth="1.5"
|
|
87
|
+
strokeLinecap="round"
|
|
88
|
+
strokeLinejoin="round"
|
|
89
|
+
className="shrink-0 text-muted-foreground"
|
|
90
|
+
aria-hidden="true"
|
|
91
|
+
>
|
|
92
|
+
<path d="M3 4h10M3 8h7M3 12h8" />
|
|
93
|
+
<path d="M12.5 10.5l1.5 1.5-1.5 1.5" />
|
|
94
|
+
</svg>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { memo } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { PLAN_ARTIFACT_NAME } from "../library/detect-plan-artifact.js";
|
|
6
|
+
import { formatArtifactSize } from "./artifact-utils.js";
|
|
7
|
+
|
|
8
|
+
/** Props for {@link PlanStreamingCard}. */
|
|
9
|
+
export interface PlanStreamingCardProps {
|
|
10
|
+
/**
|
|
11
|
+
* The plan's title (its leading `# H1`), streaming in live. Falls back to
|
|
12
|
+
* "Writing plan…" until the title has arrived.
|
|
13
|
+
*/
|
|
14
|
+
readonly title?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Live size of the plan text streamed so far. An approximation (UTF-16
|
|
17
|
+
* length, not encoded bytes) — it exists to show growth while the agent
|
|
18
|
+
* writes, not to state the artifact's final size.
|
|
19
|
+
*/
|
|
20
|
+
readonly sizeBytes: number;
|
|
21
|
+
/**
|
|
22
|
+
* Opens the panel's plan document tab, where the plan is rendering live.
|
|
23
|
+
* Always provided in practice: the thread only collapses a streaming plan
|
|
24
|
+
* behind this card when the host wired `onOpenPlan` (see `MessageThread`'s
|
|
25
|
+
* `collapseStreamingPlan` gate) — without a document surface there is
|
|
26
|
+
* nothing for the card to open, and the plan streams inline instead.
|
|
27
|
+
*/
|
|
28
|
+
readonly onOpenPlan?: () => void;
|
|
29
|
+
/** Additional CSS classes for the root element. */
|
|
30
|
+
readonly className?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The live counterpart of {@link PlanArtifactCard} — a streaming Plan turn's
|
|
35
|
+
* compact stand-in in the thread while the plan document renders live in the
|
|
36
|
+
* session panel's plan tab. Same anatomy as the completed card (icon, title,
|
|
37
|
+
* `plan.md · size` meta, trailing actions) so the completion handoff reads as
|
|
38
|
+
* the same card settling, not a new element appearing.
|
|
39
|
+
*
|
|
40
|
+
* Deliberately action-light: "Open plan" is the only affordance. Download and
|
|
41
|
+
* Build require the published artifact, which does not exist until the turn
|
|
42
|
+
* completes — at which point `buildThreadItems` swaps this item for the
|
|
43
|
+
* `plan-completion` item under the same list key.
|
|
44
|
+
*
|
|
45
|
+
* The pulsing icon is the progress affordance: a CSS animation inside `.stgm`,
|
|
46
|
+
* covered by the stylesheet's global `prefers-reduced-motion` rule (DD-015),
|
|
47
|
+
* and safe under virtualization (no `@starting-style`).
|
|
48
|
+
*
|
|
49
|
+
* All visual properties flow through `--stgm-*` tokens; the component is
|
|
50
|
+
* self-contained and embeddable.
|
|
51
|
+
*/
|
|
52
|
+
export const PlanStreamingCard = memo(function PlanStreamingCard({
|
|
53
|
+
title,
|
|
54
|
+
sizeBytes,
|
|
55
|
+
onOpenPlan,
|
|
56
|
+
className,
|
|
57
|
+
}: PlanStreamingCardProps) {
|
|
58
|
+
return (
|
|
59
|
+
<div
|
|
60
|
+
role="region"
|
|
61
|
+
aria-label="Plan being written"
|
|
62
|
+
aria-busy="true"
|
|
63
|
+
className={cn(
|
|
64
|
+
"mx-4 flex flex-wrap items-center gap-x-3 gap-y-2 rounded-lg",
|
|
65
|
+
"border border-border-muted bg-card px-3 py-2.5",
|
|
66
|
+
className,
|
|
67
|
+
)}
|
|
68
|
+
>
|
|
69
|
+
<PlanIcon className="animate-pulse" />
|
|
70
|
+
<div className="min-w-0 flex-1 basis-48">
|
|
71
|
+
<div className="truncate text-sm font-medium text-foreground">
|
|
72
|
+
{title ?? "Writing plan…"}
|
|
73
|
+
</div>
|
|
74
|
+
<div className="text-[0.65rem] text-muted-foreground-faint">
|
|
75
|
+
{PLAN_ARTIFACT_NAME}
|
|
76
|
+
<span aria-hidden="true"> · </span>
|
|
77
|
+
<span role="status">Writing…</span>
|
|
78
|
+
<span aria-hidden="true"> · </span>
|
|
79
|
+
<span className="tabular-nums">{formatArtifactSize(sizeBytes)}</span>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
{onOpenPlan && (
|
|
84
|
+
<button
|
|
85
|
+
type="button"
|
|
86
|
+
onClick={onOpenPlan}
|
|
87
|
+
className={cn(
|
|
88
|
+
"ml-auto inline-flex items-center gap-1 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground",
|
|
89
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-sm",
|
|
90
|
+
)}
|
|
91
|
+
>
|
|
92
|
+
<ExpandIcon />
|
|
93
|
+
Open plan
|
|
94
|
+
</button>
|
|
95
|
+
)}
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
function PlanIcon({ className }: { readonly className?: string }) {
|
|
101
|
+
return (
|
|
102
|
+
<svg
|
|
103
|
+
width="16"
|
|
104
|
+
height="16"
|
|
105
|
+
viewBox="0 0 16 16"
|
|
106
|
+
fill="none"
|
|
107
|
+
stroke="currentColor"
|
|
108
|
+
strokeWidth="1.5"
|
|
109
|
+
strokeLinecap="round"
|
|
110
|
+
strokeLinejoin="round"
|
|
111
|
+
className={cn("shrink-0 text-muted-foreground-faint", className)}
|
|
112
|
+
aria-hidden="true"
|
|
113
|
+
>
|
|
114
|
+
<path d="M3 4h10M3 8h7M3 12h8" />
|
|
115
|
+
<path d="M12.5 10.5l1.5 1.5-1.5 1.5" />
|
|
116
|
+
</svg>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function ExpandIcon() {
|
|
121
|
+
return (
|
|
122
|
+
<svg
|
|
123
|
+
width="10"
|
|
124
|
+
height="10"
|
|
125
|
+
viewBox="0 0 12 12"
|
|
126
|
+
fill="none"
|
|
127
|
+
stroke="currentColor"
|
|
128
|
+
strokeWidth="1.5"
|
|
129
|
+
strokeLinecap="round"
|
|
130
|
+
strokeLinejoin="round"
|
|
131
|
+
className="shrink-0"
|
|
132
|
+
aria-hidden="true"
|
|
133
|
+
>
|
|
134
|
+
<path d="M7 1.5h3.5V5M10.5 1.5L6.5 5.5M5 10.5H1.5V7M1.5 10.5l4-4" />
|
|
135
|
+
</svg>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from "vitest";
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
2
|
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
|
|
3
3
|
import { ArtifactContentRenderer } from "../ArtifactContentRenderer";
|
|
4
4
|
|
|
@@ -60,3 +60,82 @@ describe("ArtifactContentRenderer — markdown", () => {
|
|
|
60
60
|
).toBeGreaterThan(0);
|
|
61
61
|
});
|
|
62
62
|
});
|
|
63
|
+
|
|
64
|
+
describe("ArtifactContentRenderer — reveal (jump-to-line)", () => {
|
|
65
|
+
let scrollIntoView: ReturnType<typeof vi.fn>;
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
// happy-dom lacks a real scrollIntoView; the hook calls it optionally.
|
|
68
|
+
scrollIntoView = vi.fn();
|
|
69
|
+
Element.prototype.scrollIntoView =
|
|
70
|
+
scrollIntoView as unknown as typeof Element.prototype.scrollIntoView;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("renders addressable lines and highlights the target row for plain text", () => {
|
|
74
|
+
const { container } = render(
|
|
75
|
+
<ArtifactContentRenderer
|
|
76
|
+
content={"one\ntwo\nthree"}
|
|
77
|
+
fileName="notes.txt"
|
|
78
|
+
reveal={{ line: 2, nonce: 1 }}
|
|
79
|
+
/>,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Every line is addressable; exactly the target row carries the highlight.
|
|
83
|
+
expect(container.querySelectorAll("[data-line]").length).toBe(3);
|
|
84
|
+
const target = container.querySelector('[data-line="2"]');
|
|
85
|
+
expect(target?.className).toContain("bg-primary-subtle");
|
|
86
|
+
expect(container.querySelectorAll(".bg-primary-subtle").length).toBe(1);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("does not highlight anything when the target line is out of range", () => {
|
|
90
|
+
const { container } = render(
|
|
91
|
+
<ArtifactContentRenderer
|
|
92
|
+
content={"one\ntwo"}
|
|
93
|
+
fileName="notes.txt"
|
|
94
|
+
reveal={{ line: 99, nonce: 1 }}
|
|
95
|
+
/>,
|
|
96
|
+
);
|
|
97
|
+
expect(container.querySelectorAll(".bg-primary-subtle").length).toBe(0);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("forces Markdown to its Source (line-faithful) view when revealing", () => {
|
|
101
|
+
const { container } = render(
|
|
102
|
+
<ArtifactContentRenderer
|
|
103
|
+
content={"# Heading\n\ntext"}
|
|
104
|
+
fileName="doc.md"
|
|
105
|
+
reveal={{ line: 1, nonce: 1 }}
|
|
106
|
+
/>,
|
|
107
|
+
);
|
|
108
|
+
// Source is line-numbered <pre>, not the rendered <h1>.
|
|
109
|
+
expect(container.querySelector("h1")).toBeNull();
|
|
110
|
+
expect(container.querySelector("pre")).not.toBeNull();
|
|
111
|
+
expect(container.querySelector('[data-line="1"]')).not.toBeNull();
|
|
112
|
+
// The Rendered/Source toggle is still offered.
|
|
113
|
+
expect(screen.getByRole("tab", { name: "Source" })).toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("renders JSON raw (not reformatted) when revealing, so line numbers hold", () => {
|
|
117
|
+
// Minified single-line JSON: pretty-printing would expand it to many lines
|
|
118
|
+
// and shift line 1. Raw rendering keeps it one addressable row.
|
|
119
|
+
const { container } = render(
|
|
120
|
+
<ArtifactContentRenderer
|
|
121
|
+
content={'{"a":1,"b":2}'}
|
|
122
|
+
fileName="data.json"
|
|
123
|
+
reveal={{ line: 1, nonce: 1 }}
|
|
124
|
+
/>,
|
|
125
|
+
);
|
|
126
|
+
const rows = container.querySelectorAll("[data-line]");
|
|
127
|
+
expect(rows.length).toBe(1);
|
|
128
|
+
expect(rows[0].textContent).toContain('{"a":1,"b":2}');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("scrolls the target line into view", () => {
|
|
132
|
+
render(
|
|
133
|
+
<ArtifactContentRenderer
|
|
134
|
+
content={"one\ntwo\nthree"}
|
|
135
|
+
fileName="notes.txt"
|
|
136
|
+
reveal={{ line: 3, nonce: 1 }}
|
|
137
|
+
/>,
|
|
138
|
+
);
|
|
139
|
+
expect(scrollIntoView).toHaveBeenCalled();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
WorkspaceEntrySchema,
|
|
6
6
|
WorkspaceSourceSchema,
|
|
7
7
|
LocalPathSourceSchema,
|
|
8
|
+
GitRepoSourceSchema,
|
|
8
9
|
} from "@stigmer/protos/ai/stigmer/agentic/session/v1/workspace_pb";
|
|
9
10
|
import type { WorkspaceEntry } from "@stigmer/protos/ai/stigmer/agentic/session/v1/workspace_pb";
|
|
10
11
|
import { FilePathLink } from "../FilePathLink";
|
|
@@ -89,4 +90,90 @@ describe("FilePathLink interaction", () => {
|
|
|
89
90
|
expect(onFilePathClick.mock.calls[0][0]).toBe("src/main.go");
|
|
90
91
|
expect(onFilePathClick.mock.calls[0][1].action).toBe("copy");
|
|
91
92
|
});
|
|
93
|
+
|
|
94
|
+
it("falls back to copy when a copy-action handler declines (returns false)", async () => {
|
|
95
|
+
const writeText = vi.fn().mockResolvedValue(undefined);
|
|
96
|
+
vi.stubGlobal("navigator", { clipboard: { writeText } });
|
|
97
|
+
const onFilePathClick = vi.fn().mockReturnValue(false);
|
|
98
|
+
render(
|
|
99
|
+
<FilePathContext.Provider value={{ workspaceEntries: [], onFilePathClick }}>
|
|
100
|
+
<FilePathLink path="src/main.go" />
|
|
101
|
+
</FilePathContext.Provider>,
|
|
102
|
+
);
|
|
103
|
+
fireEvent.click(screen.getByRole("button"));
|
|
104
|
+
expect(onFilePathClick).toHaveBeenCalledTimes(1);
|
|
105
|
+
expect(writeText).toHaveBeenCalledWith("src/main.go");
|
|
106
|
+
vi.unstubAllGlobals();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("suppresses the copy default when a copy-action handler returns void", () => {
|
|
110
|
+
const writeText = vi.fn().mockResolvedValue(undefined);
|
|
111
|
+
vi.stubGlobal("navigator", { clipboard: { writeText } });
|
|
112
|
+
const onFilePathClick = vi.fn(); // returns undefined -> handled
|
|
113
|
+
render(
|
|
114
|
+
<FilePathContext.Provider value={{ workspaceEntries: [], onFilePathClick }}>
|
|
115
|
+
<FilePathLink path="src/main.go" />
|
|
116
|
+
</FilePathContext.Provider>,
|
|
117
|
+
);
|
|
118
|
+
fireEvent.click(screen.getByRole("button"));
|
|
119
|
+
expect(onFilePathClick).toHaveBeenCalledTimes(1);
|
|
120
|
+
expect(writeText).not.toHaveBeenCalled();
|
|
121
|
+
vi.unstubAllGlobals();
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe("FilePathLink link-action with an injected handler", () => {
|
|
126
|
+
const gitEntries = [
|
|
127
|
+
create(WorkspaceEntrySchema, {
|
|
128
|
+
name: "acme/app",
|
|
129
|
+
source: create(WorkspaceSourceSchema, {
|
|
130
|
+
source: {
|
|
131
|
+
case: "gitRepo",
|
|
132
|
+
value: create(GitRepoSourceSchema, {
|
|
133
|
+
url: "https://github.com/acme/app.git",
|
|
134
|
+
branch: "main",
|
|
135
|
+
}),
|
|
136
|
+
},
|
|
137
|
+
}),
|
|
138
|
+
}),
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
it("renders a real <a href> even when a handler is present (native link semantics)", () => {
|
|
142
|
+
const onFilePathClick = vi.fn().mockReturnValue(true);
|
|
143
|
+
render(
|
|
144
|
+
<FilePathContext.Provider value={{ workspaceEntries: gitEntries, onFilePathClick }}>
|
|
145
|
+
<FilePathLink path="src/main.go" />
|
|
146
|
+
</FilePathContext.Provider>,
|
|
147
|
+
);
|
|
148
|
+
const anchor = screen.getByRole("link");
|
|
149
|
+
expect(anchor.getAttribute("href")).toBe(
|
|
150
|
+
"https://github.com/acme/app/blob/main/src/main.go",
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("prevents native navigation when the handler opens it in-app (returns true)", () => {
|
|
155
|
+
const onFilePathClick = vi.fn().mockReturnValue(true);
|
|
156
|
+
render(
|
|
157
|
+
<FilePathContext.Provider value={{ workspaceEntries: gitEntries, onFilePathClick }}>
|
|
158
|
+
<FilePathLink path="src/main.go" />
|
|
159
|
+
</FilePathContext.Provider>,
|
|
160
|
+
);
|
|
161
|
+
const evt = new MouseEvent("click", { bubbles: true, cancelable: true });
|
|
162
|
+
screen.getByRole("link").dispatchEvent(evt);
|
|
163
|
+
expect(onFilePathClick).toHaveBeenCalledTimes(1);
|
|
164
|
+
expect(evt.defaultPrevented).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("leaves native navigation intact when the handler declines (returns false)", () => {
|
|
168
|
+
const onFilePathClick = vi.fn().mockReturnValue(false);
|
|
169
|
+
render(
|
|
170
|
+
<FilePathContext.Provider value={{ workspaceEntries: gitEntries, onFilePathClick }}>
|
|
171
|
+
<FilePathLink path="src/main.go" />
|
|
172
|
+
</FilePathContext.Provider>,
|
|
173
|
+
);
|
|
174
|
+
const evt = new MouseEvent("click", { bubbles: true, cancelable: true });
|
|
175
|
+
screen.getByRole("link").dispatchEvent(evt);
|
|
176
|
+
expect(onFilePathClick).toHaveBeenCalledTimes(1);
|
|
177
|
+
expect(evt.defaultPrevented).toBe(false);
|
|
178
|
+
});
|
|
92
179
|
});
|