@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
|
@@ -58,8 +58,9 @@ import {
|
|
|
58
58
|
*
|
|
59
59
|
* function handleBuildFromPlan() {
|
|
60
60
|
* // Switch to Agent mode and run immediately — no manual Send.
|
|
61
|
-
* composerRef.current?.submit("
|
|
61
|
+
* composerRef.current?.submit("Build from plan", {
|
|
62
62
|
* interactionMode: "agent",
|
|
63
|
+
* buildFromPlan: true,
|
|
63
64
|
* });
|
|
64
65
|
* }
|
|
65
66
|
*
|
|
@@ -83,10 +84,23 @@ export interface SessionComposerHandle {
|
|
|
83
84
|
* @param options.interactionMode - Force the interaction mode for this one
|
|
84
85
|
* submission, overriding the picker. Avoids the same-tick race when the
|
|
85
86
|
* caller also calls `onInteractionModeChange` just before submitting.
|
|
87
|
+
* @param options.attachments - Pre-uploaded attachments (storage keys from
|
|
88
|
+
* `agentExecution.uploadAttachment`) to include with this one submission,
|
|
89
|
+
* in addition to any files attached in the composer. Used by "Build from
|
|
90
|
+
* plan" to deliver the approved `plan.md` to the implement execution.
|
|
91
|
+
* @param options.buildFromPlan - Marks this submission as the implement
|
|
92
|
+
* turn of a Plan → Build handoff (`execution_config.build_from_plan`).
|
|
93
|
+
* The runner injects the implement-plan directive and the thread hides
|
|
94
|
+
* the turn's message; the message stays a short label for surfaces
|
|
95
|
+
* without that treatment (the CLI, history).
|
|
86
96
|
*/
|
|
87
97
|
submit(
|
|
88
98
|
message: string,
|
|
89
|
-
options?: {
|
|
99
|
+
options?: {
|
|
100
|
+
interactionMode?: InteractionModeOption;
|
|
101
|
+
attachments?: AttachmentInput[];
|
|
102
|
+
buildFromPlan?: boolean;
|
|
103
|
+
},
|
|
90
104
|
): void;
|
|
91
105
|
}
|
|
92
106
|
|
|
@@ -142,6 +156,18 @@ export interface SessionComposerSubmitContext {
|
|
|
142
156
|
* Pass to execution creation as `workspaceFileRefs`.
|
|
143
157
|
*/
|
|
144
158
|
readonly workspaceFileRefs?: string[];
|
|
159
|
+
/**
|
|
160
|
+
* The submission is a Build-from-plan turn.
|
|
161
|
+
*
|
|
162
|
+
* Only ever set through {@link SessionComposerHandle.submit} (the thread
|
|
163
|
+
* card / plan editor CTA) — there is no composer UI for it. Pass to
|
|
164
|
+
* execution creation as `execution_config.build_from_plan`; the runner
|
|
165
|
+
* injects the implement-plan directive and the thread hides the turn's
|
|
166
|
+
* machine-written message (the plan card above it is the visible cause).
|
|
167
|
+
*
|
|
168
|
+
* `undefined` for ordinary submissions.
|
|
169
|
+
*/
|
|
170
|
+
readonly buildFromPlan?: boolean;
|
|
145
171
|
}
|
|
146
172
|
|
|
147
173
|
/** Props for {@link SessionComposer}. */
|
|
@@ -724,7 +750,14 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
|
|
|
724
750
|
// ---------------------------------------------------------------------------
|
|
725
751
|
|
|
726
752
|
const handleSubmit = useCallback(
|
|
727
|
-
async (
|
|
753
|
+
async (
|
|
754
|
+
message: string,
|
|
755
|
+
overrides?: {
|
|
756
|
+
interactionMode?: InteractionModeOption;
|
|
757
|
+
attachments?: AttachmentInput[];
|
|
758
|
+
buildFromPlan?: boolean;
|
|
759
|
+
},
|
|
760
|
+
) => {
|
|
728
761
|
// Persist save-for-future manual secrets before building runtimeEnv
|
|
729
762
|
if (sessionVariables?.hasSaveForFutureEntries) {
|
|
730
763
|
const saveVars = sessionVariables.toSaveForFutureEnv();
|
|
@@ -763,27 +796,34 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
|
|
|
763
796
|
Object.assign(env, sessionVariables.toRuntimeEnv());
|
|
764
797
|
}
|
|
765
798
|
|
|
766
|
-
|
|
799
|
+
// Composer-attached files plus caller-supplied extras (e.g. the approved
|
|
800
|
+
// plan.md from a Build-from-plan turn) travel as one attachment list.
|
|
801
|
+
const composerAttachments = enableAttachments
|
|
767
802
|
? attachments.toAttachmentInputs()
|
|
768
|
-
:
|
|
803
|
+
: [];
|
|
804
|
+
const attachmentInputs = [
|
|
805
|
+
...composerAttachments,
|
|
806
|
+
...(overrides?.attachments ?? []),
|
|
807
|
+
];
|
|
769
808
|
|
|
770
809
|
const hasEnv = Object.keys(env).length > 0;
|
|
771
|
-
const hasAttachments =
|
|
772
|
-
attachmentInputs !== undefined && attachmentInputs.length > 0;
|
|
810
|
+
const hasAttachments = attachmentInputs.length > 0;
|
|
773
811
|
const effectiveMode =
|
|
774
|
-
|
|
812
|
+
overrides?.interactionMode ??
|
|
775
813
|
(showInteractionModePicker && interactionMode
|
|
776
814
|
? interactionMode
|
|
777
815
|
: undefined);
|
|
778
816
|
const hasFileRefs = enableFileReferences && fileRefs.hasRefs;
|
|
817
|
+
const buildFromPlan = overrides?.buildFromPlan;
|
|
779
818
|
|
|
780
819
|
const context: SessionComposerSubmitContext | undefined =
|
|
781
|
-
hasEnv || hasAttachments || effectiveMode || hasFileRefs
|
|
820
|
+
hasEnv || hasAttachments || effectiveMode || hasFileRefs || buildFromPlan
|
|
782
821
|
? {
|
|
783
822
|
runtimeEnv: hasEnv ? env : undefined,
|
|
784
823
|
attachments: hasAttachments ? attachmentInputs : undefined,
|
|
785
824
|
interactionMode: effectiveMode,
|
|
786
825
|
workspaceFileRefs: hasFileRefs ? [...fileRefs.refs] : undefined,
|
|
826
|
+
buildFromPlan,
|
|
787
827
|
}
|
|
788
828
|
: undefined;
|
|
789
829
|
|
|
@@ -813,7 +853,7 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
|
|
|
813
853
|
submit: (message, options) => {
|
|
814
854
|
const trimmed = message.trim();
|
|
815
855
|
if (!trimmed || isDisabled) return;
|
|
816
|
-
void handleSubmit(trimmed, options
|
|
856
|
+
void handleSubmit(trimmed, options);
|
|
817
857
|
},
|
|
818
858
|
}), [composer.setMessage, composer.textareaRef, handleSubmit, isDisabled]);
|
|
819
859
|
|
|
@@ -1343,6 +1383,9 @@ const SessionComposerInner = forwardRef<SessionComposerHandle, SessionComposerPr
|
|
|
1343
1383
|
className={cn(
|
|
1344
1384
|
"rounded-xl border border-border bg-card shadow-sm",
|
|
1345
1385
|
"focus-within:ring-2 focus-within:ring-ring",
|
|
1386
|
+
// Plan mode tints the frame so the active mode is visible at a
|
|
1387
|
+
// glance, without opening the picker. Themeable via --stgm-primary-muted.
|
|
1388
|
+
interactionMode === "plan" && "border-primary-muted",
|
|
1346
1389
|
isDisabled && !stopMode && "opacity-50",
|
|
1347
1390
|
isDragOver && "ring-2 ring-primary/50",
|
|
1348
1391
|
)}
|
|
@@ -125,7 +125,7 @@ describe("SessionComposer — public contract", () => {
|
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
describe("SessionComposer — imperative submit (
|
|
128
|
+
describe("SessionComposer — imperative submit (Build from plan)", () => {
|
|
129
129
|
it("submits a message with the interactionMode override, even when the picker is 'plan'", async () => {
|
|
130
130
|
const ref = createRef<SessionComposerHandle>();
|
|
131
131
|
const { onSubmit } = renderComposer({
|
|
@@ -134,13 +134,13 @@ describe("SessionComposer — imperative submit (Implement plan)", () => {
|
|
|
134
134
|
interactionMode: "plan",
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
ref.current!.submit("
|
|
137
|
+
ref.current!.submit("Build from plan", { interactionMode: "agent" });
|
|
138
138
|
|
|
139
139
|
await waitFor(() => {
|
|
140
140
|
expect(onSubmit).toHaveBeenCalledOnce();
|
|
141
141
|
});
|
|
142
142
|
const [message, , context] = onSubmit.mock.calls[0];
|
|
143
|
-
expect(message).toBe("
|
|
143
|
+
expect(message).toBe("Build from plan");
|
|
144
144
|
// The override must win over the current picker value ("plan") so the
|
|
145
145
|
// implement run executes in Agent mode regardless of render timing.
|
|
146
146
|
expect(context?.interactionMode).toBe("agent");
|
|
@@ -150,7 +150,7 @@ describe("SessionComposer — imperative submit (Implement plan)", () => {
|
|
|
150
150
|
const ref = createRef<SessionComposerHandle>();
|
|
151
151
|
const { onSubmit } = renderComposer({ ref, disabled: true });
|
|
152
152
|
|
|
153
|
-
ref.current!.submit("
|
|
153
|
+
ref.current!.submit("Build from plan", { interactionMode: "agent" });
|
|
154
154
|
|
|
155
155
|
expect(onSubmit).not.toHaveBeenCalled();
|
|
156
156
|
});
|
|
@@ -163,4 +163,58 @@ describe("SessionComposer — imperative submit (Implement plan)", () => {
|
|
|
163
163
|
|
|
164
164
|
expect(onSubmit).not.toHaveBeenCalled();
|
|
165
165
|
});
|
|
166
|
+
|
|
167
|
+
it("carries caller-supplied attachments into the submit context (approved plan.md)", async () => {
|
|
168
|
+
const ref = createRef<SessionComposerHandle>();
|
|
169
|
+
const { onSubmit } = renderComposer({ ref });
|
|
170
|
+
|
|
171
|
+
const planAttachment = {
|
|
172
|
+
filename: "plan.md",
|
|
173
|
+
storageKey: "attachments/01ABC/plan.md",
|
|
174
|
+
mountPath: ".stigmer/inputs/plan.md",
|
|
175
|
+
contentType: "text/markdown",
|
|
176
|
+
};
|
|
177
|
+
ref.current!.submit("Build from plan", {
|
|
178
|
+
interactionMode: "agent",
|
|
179
|
+
attachments: [planAttachment],
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
await waitFor(() => {
|
|
183
|
+
expect(onSubmit).toHaveBeenCalledOnce();
|
|
184
|
+
});
|
|
185
|
+
const [, , context] = onSubmit.mock.calls[0];
|
|
186
|
+
expect(context?.attachments).toEqual([planAttachment]);
|
|
187
|
+
expect(context?.interactionMode).toBe("agent");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("carries the buildFromPlan flag into the submit context", async () => {
|
|
191
|
+
const ref = createRef<SessionComposerHandle>();
|
|
192
|
+
const { onSubmit } = renderComposer({ ref });
|
|
193
|
+
|
|
194
|
+
ref.current!.submit("Build from plan", {
|
|
195
|
+
interactionMode: "agent",
|
|
196
|
+
buildFromPlan: true,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
await waitFor(() => {
|
|
200
|
+
expect(onSubmit).toHaveBeenCalledOnce();
|
|
201
|
+
});
|
|
202
|
+
const [, , context] = onSubmit.mock.calls[0];
|
|
203
|
+
expect(context?.buildFromPlan).toBe(true);
|
|
204
|
+
expect(context?.interactionMode).toBe("agent");
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("leaves buildFromPlan unset for ordinary submissions", async () => {
|
|
208
|
+
const { onSubmit } = renderComposer();
|
|
209
|
+
|
|
210
|
+
const textarea = screen.getByRole("textbox");
|
|
211
|
+
fireEvent.change(textarea, { target: { value: "Hello world" } });
|
|
212
|
+
fireEvent.keyDown(textarea, { key: "Enter", shiftKey: false });
|
|
213
|
+
|
|
214
|
+
await waitFor(() => {
|
|
215
|
+
expect(onSubmit).toHaveBeenCalledOnce();
|
|
216
|
+
});
|
|
217
|
+
const [, , context] = onSubmit.mock.calls[0];
|
|
218
|
+
expect(context?.buildFromPlan).toBeUndefined();
|
|
219
|
+
});
|
|
166
220
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useMemo, useState, type ReactNode } from "react";
|
|
3
|
+
import { useEffect, useMemo, useState, type ReactNode } from "react";
|
|
4
4
|
import Markdown from "react-markdown";
|
|
5
5
|
import { cn } from "@stigmer/theme";
|
|
6
6
|
import {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
REMARK_PLUGINS,
|
|
9
9
|
unwrapEnclosingMarkdownFence,
|
|
10
10
|
} from "../internal/markdown-components.js";
|
|
11
|
+
import { useRevealLine, type RevealTarget } from "../internal/useRevealLine.js";
|
|
11
12
|
import {
|
|
12
13
|
getArtifactRenderMode,
|
|
13
14
|
type ArtifactRenderMode,
|
|
@@ -29,6 +30,15 @@ export interface ArtifactContentRendererProps {
|
|
|
29
30
|
readonly contentType?: string | null;
|
|
30
31
|
/** When `true`, shows a truncation warning below the content. */
|
|
31
32
|
readonly isTruncated?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Optional jump-to-line request. When set, the content is rendered
|
|
35
|
+
* **line-faithfully** so the line number maps to the file's real rows —
|
|
36
|
+
* Markdown defaults to its Source view (a line only exists in source) and
|
|
37
|
+
* JSON renders raw rather than pretty-printed (reformatting would shift line
|
|
38
|
+
* numbers) — and the target line is scrolled into view and highlighted. Absent
|
|
39
|
+
* (the default), rendering is unchanged. See {@link RevealTarget}.
|
|
40
|
+
*/
|
|
41
|
+
readonly reveal?: RevealTarget;
|
|
32
42
|
/** Additional CSS classes for the root element. */
|
|
33
43
|
readonly className?: string;
|
|
34
44
|
}
|
|
@@ -76,6 +86,7 @@ export function ArtifactContentRenderer({
|
|
|
76
86
|
fileName,
|
|
77
87
|
contentType,
|
|
78
88
|
isTruncated = false,
|
|
89
|
+
reveal,
|
|
79
90
|
className,
|
|
80
91
|
}: ArtifactContentRendererProps) {
|
|
81
92
|
const mode = getArtifactRenderMode(fileName, contentType);
|
|
@@ -83,13 +94,19 @@ export function ArtifactContentRenderer({
|
|
|
83
94
|
return (
|
|
84
95
|
<div className={cn(className)}>
|
|
85
96
|
{mode === "markdown" ? (
|
|
86
|
-
<MarkdownView content={content} />
|
|
97
|
+
<MarkdownView content={content} reveal={reveal} />
|
|
87
98
|
) : mode === "yaml" ? (
|
|
88
|
-
<YamlView content={content} />
|
|
99
|
+
<YamlView content={content} reveal={reveal} />
|
|
89
100
|
) : mode === "json" ? (
|
|
90
|
-
|
|
101
|
+
// A reveal needs raw, line-faithful JSON: pretty-printing reformats the
|
|
102
|
+
// file and would shift the target line off its real row.
|
|
103
|
+
reveal ? (
|
|
104
|
+
<LineNumberedPre content={content} reveal={reveal} />
|
|
105
|
+
) : (
|
|
106
|
+
<JsonView content={content} />
|
|
107
|
+
)
|
|
91
108
|
) : (
|
|
92
|
-
<PlainTextView content={content} />
|
|
109
|
+
<PlainTextView content={content} reveal={reveal} />
|
|
93
110
|
)}
|
|
94
111
|
|
|
95
112
|
{isTruncated && <TruncationWarning />}
|
|
@@ -103,8 +120,21 @@ export function ArtifactContentRenderer({
|
|
|
103
120
|
|
|
104
121
|
type MarkdownTab = "rendered" | "source";
|
|
105
122
|
|
|
106
|
-
function MarkdownView({
|
|
107
|
-
|
|
123
|
+
function MarkdownView({
|
|
124
|
+
content,
|
|
125
|
+
reveal,
|
|
126
|
+
}: {
|
|
127
|
+
readonly content: string;
|
|
128
|
+
readonly reveal?: RevealTarget;
|
|
129
|
+
}) {
|
|
130
|
+
// A reveal targets a source line (the rendered HTML has no line concept), so
|
|
131
|
+
// default to — and, on every new reveal, return to — the Source view.
|
|
132
|
+
const [tab, setTab] = useState<MarkdownTab>(reveal ? "source" : "rendered");
|
|
133
|
+
// Keyed on the reveal nonce: each fresh jump-to-line returns to Source (where
|
|
134
|
+
// the line exists); switching to Rendered afterward sticks until the next hit.
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
if (reveal) setTab("source");
|
|
137
|
+
}, [reveal?.nonce]);
|
|
108
138
|
|
|
109
139
|
// A `.md` whose entire body is one ```markdown fence (e.g. a model-wrapped
|
|
110
140
|
// plan) would render flat. Unwrap for the Rendered view only — Source stays
|
|
@@ -145,7 +175,7 @@ function MarkdownView({ content }: { readonly content: string }) {
|
|
|
145
175
|
</Markdown>
|
|
146
176
|
</div>
|
|
147
177
|
) : (
|
|
148
|
-
<LineNumberedPre content={content} />
|
|
178
|
+
<LineNumberedPre content={content} reveal={reveal} />
|
|
149
179
|
)}
|
|
150
180
|
</div>
|
|
151
181
|
);
|
|
@@ -197,15 +227,6 @@ function TabButton({
|
|
|
197
227
|
*
|
|
198
228
|
* Values and block scalar content render in the default `text-foreground`.
|
|
199
229
|
*/
|
|
200
|
-
function highlightYaml(content: string): ReactNode {
|
|
201
|
-
return content.split("\n").map((line, i) => (
|
|
202
|
-
<span key={i}>
|
|
203
|
-
{i > 0 && "\n"}
|
|
204
|
-
{highlightYamlLine(line)}
|
|
205
|
-
</span>
|
|
206
|
-
));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
230
|
function highlightYamlLine(line: string): ReactNode {
|
|
210
231
|
if (!line.trim()) return line;
|
|
211
232
|
|
|
@@ -253,10 +274,38 @@ function highlightYamlValue(value: string): ReactNode {
|
|
|
253
274
|
return <>{value}</>;
|
|
254
275
|
}
|
|
255
276
|
|
|
256
|
-
function YamlView({
|
|
277
|
+
function YamlView({
|
|
278
|
+
content,
|
|
279
|
+
reveal,
|
|
280
|
+
}: {
|
|
281
|
+
readonly content: string;
|
|
282
|
+
readonly reveal?: RevealTarget;
|
|
283
|
+
}) {
|
|
284
|
+
const { containerRef, isRevealed } = useRevealLine(reveal);
|
|
285
|
+
const lines = content.split("\n");
|
|
286
|
+
|
|
257
287
|
return (
|
|
258
288
|
<pre className="overflow-x-auto p-4 font-mono text-xs leading-relaxed text-foreground">
|
|
259
|
-
<code
|
|
289
|
+
<code ref={containerRef}>
|
|
290
|
+
{lines.map((line, i) => (
|
|
291
|
+
<span
|
|
292
|
+
key={i}
|
|
293
|
+
data-line={i + 1}
|
|
294
|
+
className={cn(
|
|
295
|
+
// Transparent left border by default so revealing a line only
|
|
296
|
+
// changes its color — never shifts the text (no layout jump).
|
|
297
|
+
"block border-l-2 border-transparent",
|
|
298
|
+
isRevealed(i + 1) && "border-primary bg-primary-subtle",
|
|
299
|
+
)}
|
|
300
|
+
>
|
|
301
|
+
{/* whitespace-pre inner + `\n` fallback preserves indentation and
|
|
302
|
+
the height of blank lines, mirroring LineNumberedPre. */}
|
|
303
|
+
<span className="whitespace-pre">
|
|
304
|
+
{line.trim() ? highlightYamlLine(line) : "\n"}
|
|
305
|
+
</span>
|
|
306
|
+
</span>
|
|
307
|
+
))}
|
|
308
|
+
</code>
|
|
260
309
|
</pre>
|
|
261
310
|
);
|
|
262
311
|
}
|
|
@@ -345,19 +394,47 @@ function JsonView({ content }: { readonly content: string }) {
|
|
|
345
394
|
// Plain text view (monospace + line numbers)
|
|
346
395
|
// ---------------------------------------------------------------------------
|
|
347
396
|
|
|
348
|
-
function PlainTextView({
|
|
349
|
-
|
|
397
|
+
function PlainTextView({
|
|
398
|
+
content,
|
|
399
|
+
reveal,
|
|
400
|
+
}: {
|
|
401
|
+
readonly content: string;
|
|
402
|
+
readonly reveal?: RevealTarget;
|
|
403
|
+
}) {
|
|
404
|
+
return <LineNumberedPre content={content} reveal={reveal} />;
|
|
350
405
|
}
|
|
351
406
|
|
|
352
|
-
|
|
407
|
+
/**
|
|
408
|
+
* Line-numbered monospace view. The single line-faithful primitive behind plain
|
|
409
|
+
* text, Markdown Source, and reveal-mode JSON: every row is addressable
|
|
410
|
+
* (`data-line`), so a {@link RevealTarget} can scroll to and highlight a line
|
|
411
|
+
* (via {@link useRevealLine}). Absent a reveal it renders exactly as before.
|
|
412
|
+
*/
|
|
413
|
+
function LineNumberedPre({
|
|
414
|
+
content,
|
|
415
|
+
reveal,
|
|
416
|
+
}: {
|
|
417
|
+
readonly content: string;
|
|
418
|
+
readonly reveal?: RevealTarget;
|
|
419
|
+
}) {
|
|
420
|
+
const { containerRef, isRevealed } = useRevealLine(reveal);
|
|
353
421
|
const lines = content.split("\n");
|
|
354
422
|
const gutterWidth = String(lines.length).length;
|
|
355
423
|
|
|
356
424
|
return (
|
|
357
425
|
<pre className="overflow-x-auto font-mono text-xs leading-relaxed text-foreground">
|
|
358
|
-
<code>
|
|
426
|
+
<code ref={containerRef}>
|
|
359
427
|
{lines.map((line, i) => (
|
|
360
|
-
<span
|
|
428
|
+
<span
|
|
429
|
+
key={i}
|
|
430
|
+
data-line={i + 1}
|
|
431
|
+
className={cn(
|
|
432
|
+
// Transparent left border by default so a reveal only recolors the
|
|
433
|
+
// row — never shifts its text (no layout jump).
|
|
434
|
+
"flex border-l-2 border-transparent",
|
|
435
|
+
isRevealed(i + 1) && "border-primary bg-primary-subtle",
|
|
436
|
+
)}
|
|
437
|
+
>
|
|
361
438
|
<span
|
|
362
439
|
className="sticky left-0 select-none bg-background pr-4 text-right text-muted-foreground"
|
|
363
440
|
style={{ minWidth: `${gutterWidth + 2}ch` }}
|
|
@@ -47,10 +47,10 @@ export interface ArtifactPreviewContentProps {
|
|
|
47
47
|
*/
|
|
48
48
|
readonly onApplied?: (result: ApplyResourceResult) => void;
|
|
49
49
|
/**
|
|
50
|
-
* Optional plan-build action. When provided, a "Build
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* Optional plan-build action. When provided, a "Build" primary button
|
|
51
|
+
* appears in the action bar (used for plan artifacts: turn the plan into
|
|
52
|
+
* an Agent run). Clicking it calls `onImplement` then closes the modal.
|
|
53
|
+
* Omit for non-actionable artifacts.
|
|
54
54
|
*/
|
|
55
55
|
readonly onImplement?: () => void;
|
|
56
56
|
/** Additional CSS classes for the root container. */
|
|
@@ -228,9 +228,9 @@ export function ArtifactPreviewContent({
|
|
|
228
228
|
ctaLabel = `Push Skill to ${org}`;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
// "Build
|
|
232
|
-
//
|
|
233
|
-
//
|
|
231
|
+
// "Build" runs the plan; closing the modal lets the host's submit pipeline
|
|
232
|
+
// take over (switch to Agent + send). Single combined handler keeps the
|
|
233
|
+
// caller's contract simple ("just give me onImplement").
|
|
234
234
|
const handleImplement = useCallback(() => {
|
|
235
235
|
onImplement?.();
|
|
236
236
|
onClose();
|
|
@@ -329,7 +329,7 @@ export interface ArtifactPreviewModalProps {
|
|
|
329
329
|
readonly onApplied?: (result: ApplyResourceResult) => void;
|
|
330
330
|
/**
|
|
331
331
|
* Optional plan-build action (see {@link ArtifactPreviewContentProps.onImplement}).
|
|
332
|
-
* When provided, a "Build
|
|
332
|
+
* When provided, a "Build" primary button appears; clicking it calls
|
|
333
333
|
* `onImplement` then closes the modal.
|
|
334
334
|
*/
|
|
335
335
|
readonly onImplement?: () => void;
|
|
@@ -701,7 +701,7 @@ function ActionBar({
|
|
|
701
701
|
)}
|
|
702
702
|
>
|
|
703
703
|
<ImplementIcon />
|
|
704
|
-
Build
|
|
704
|
+
Build
|
|
705
705
|
</button>
|
|
706
706
|
)}
|
|
707
707
|
{applyResult ? (
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { memo, useState } from "react";
|
|
4
|
+
import type { FileChangeProgress } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/filereview_pb";
|
|
5
|
+
import { cn } from "@stigmer/theme";
|
|
6
|
+
import { FileKindBadge, FileLineStats } from "./FileReviewAtoms.js";
|
|
7
|
+
import { FilePathLink } from "./FilePathLink.js";
|
|
8
|
+
|
|
9
|
+
/** Props for {@link FileChangeProgressBar}. */
|
|
10
|
+
export interface FileChangeProgressBarProps {
|
|
11
|
+
/**
|
|
12
|
+
* The transient mid-run progress snapshot for the active turn (DD-32). Feed
|
|
13
|
+
* this from `useSessionConversation().fileChangeProgress`. Renders nothing when
|
|
14
|
+
* undefined or when no files have changed yet — the server clears it once the
|
|
15
|
+
* turn's change set leaves CAPTURING, so the bar disappears exactly when the
|
|
16
|
+
* decision surface ({@link FileReviewDock}) takes over.
|
|
17
|
+
*/
|
|
18
|
+
readonly progress: FileChangeProgress | undefined;
|
|
19
|
+
/** Additional CSS class names for the root container. */
|
|
20
|
+
readonly className?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The live "N files changed so far" strip for a turn that is still running.
|
|
25
|
+
*
|
|
26
|
+
* WHY IT EXISTS. The transcript streams per-edit tool rows, but a change made by
|
|
27
|
+
* a shell command (a `sed`, a build step) has no tool row, and there is no
|
|
28
|
+
* running net-of-many-edits rollup until the turn ends. This bar fills that gap:
|
|
29
|
+
* a compact, NON-INTERACTIVE count of the workspace delta accumulating during
|
|
30
|
+
* the turn, pinned above the composer where the {@link FileReviewDock} will later
|
|
31
|
+
* appear. The two are mutually exclusive per turn (progress shows while CAPTURING;
|
|
32
|
+
* the dock shows once AWAITING_REVIEW), so the bar hands off cleanly to the dock.
|
|
33
|
+
*
|
|
34
|
+
* NEVER A DECISION SURFACE. Progress is non-authoritative and carries no file
|
|
35
|
+
* bodies — it is never reviewable or decidable. The reviewed diff is the
|
|
36
|
+
* turn-boundary candidate ({@link FileReviewDock} / the stamped transcript rows).
|
|
37
|
+
* A secret-like path is surfaced by name with its counts withheld (zeroed), so
|
|
38
|
+
* `FileLineStats` renders nothing for it.
|
|
39
|
+
*
|
|
40
|
+
* A11Y. Only the summary count is an `aria-live` region — the per-file list is
|
|
41
|
+
* not — so a screen reader hears "3 files changing" as the count moves, not a
|
|
42
|
+
* per-file barrage on every ~2s refresh.
|
|
43
|
+
*
|
|
44
|
+
* Purely presentational (headless-first, DD-003): the data lives in
|
|
45
|
+
* `useSessionConversation().fileChangeProgress`. `SessionViewer` mounts it above
|
|
46
|
+
* the dock by default.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* const conv = useSessionConversation(sessionId);
|
|
51
|
+
* <FileChangeProgressBar progress={conv.fileChangeProgress} />
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export const FileChangeProgressBar = memo(function FileChangeProgressBar({
|
|
55
|
+
progress,
|
|
56
|
+
className,
|
|
57
|
+
}: FileChangeProgressBarProps) {
|
|
58
|
+
const [expanded, setExpanded] = useState(false);
|
|
59
|
+
|
|
60
|
+
if (!progress || progress.filesChanged === 0) return null;
|
|
61
|
+
|
|
62
|
+
const { filesChanged, linesAdded, linesRemoved, entries } = progress;
|
|
63
|
+
const hiddenCount = filesChanged - entries.length;
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
role="region"
|
|
68
|
+
aria-label="File changes in progress"
|
|
69
|
+
data-cursor-target="file-change-progress-bar"
|
|
70
|
+
className={cn("border-t border-border-muted px-4 py-2", className)}
|
|
71
|
+
>
|
|
72
|
+
<div className="flex items-center gap-2">
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
onClick={() => setExpanded((prev) => !prev)}
|
|
76
|
+
aria-expanded={expanded}
|
|
77
|
+
className="flex min-w-0 flex-1 items-center gap-2 text-left text-xs text-muted-foreground hover:text-foreground"
|
|
78
|
+
>
|
|
79
|
+
<span
|
|
80
|
+
aria-hidden="true"
|
|
81
|
+
className={cn("shrink-0 transition-transform", expanded && "rotate-90")}
|
|
82
|
+
>
|
|
83
|
+
▸
|
|
84
|
+
</span>
|
|
85
|
+
{/* Only the count is live: a screen reader hears the aggregate move,
|
|
86
|
+
not a per-file announcement on every refresh. */}
|
|
87
|
+
<span aria-live="polite" className="min-w-0 truncate">
|
|
88
|
+
{filesChanged} {filesChanged === 1 ? "file" : "files"} changing…
|
|
89
|
+
</span>
|
|
90
|
+
</button>
|
|
91
|
+
<FileLineStats linesAdded={linesAdded} linesRemoved={linesRemoved} />
|
|
92
|
+
</div>
|
|
93
|
+
{expanded && (
|
|
94
|
+
<ul className="mt-2 max-h-[30vh] space-y-1 overflow-y-auto">
|
|
95
|
+
{entries.map((entry) => {
|
|
96
|
+
const path = entry.pathAfter || entry.pathBefore;
|
|
97
|
+
return (
|
|
98
|
+
<li key={path} className="flex items-center gap-2">
|
|
99
|
+
<FileKindBadge kind={entry.kind} />
|
|
100
|
+
<FilePathLink
|
|
101
|
+
path={path}
|
|
102
|
+
dirDisplay="dim"
|
|
103
|
+
className="min-w-0 flex-1 text-xs"
|
|
104
|
+
/>
|
|
105
|
+
<FileLineStats
|
|
106
|
+
linesAdded={entry.linesAdded}
|
|
107
|
+
linesRemoved={entry.linesRemoved}
|
|
108
|
+
/>
|
|
109
|
+
</li>
|
|
110
|
+
);
|
|
111
|
+
})}
|
|
112
|
+
{hiddenCount > 0 && (
|
|
113
|
+
<li className="text-xs text-muted-foreground-faint">
|
|
114
|
+
… and {hiddenCount} more
|
|
115
|
+
</li>
|
|
116
|
+
)}
|
|
117
|
+
</ul>
|
|
118
|
+
)}
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
});
|
|
@@ -167,7 +167,13 @@ export function FileChangeDiff({
|
|
|
167
167
|
if (change.captureLevel === FileChangeCaptureLevel.HUNK_ONLY) {
|
|
168
168
|
return { additions: change.linesAdded, deletions: change.linesRemoved };
|
|
169
169
|
}
|
|
170
|
-
|
|
170
|
+
// Whole-file: count the rendered hunks (what the user actually sees). When
|
|
171
|
+
// there are none to count — the body is offloaded/loading/truncated — fall
|
|
172
|
+
// back to the capture-time counts, which are computed with the same diff
|
|
173
|
+
// algorithm and so agree with the hunks whenever both exist.
|
|
174
|
+
const computed = countHunks(hunks);
|
|
175
|
+
if (computed.additions > 0 || computed.deletions > 0) return computed;
|
|
176
|
+
return { additions: change.linesAdded, deletions: change.linesRemoved };
|
|
171
177
|
}, [change.captureLevel, change.linesAdded, change.linesRemoved, hunks]);
|
|
172
178
|
|
|
173
179
|
const showStatsRow = showStats && (stats.additions > 0 || stats.deletions > 0);
|
|
@@ -343,8 +349,11 @@ function countHunks(hunks: readonly DiffHunk[]): {
|
|
|
343
349
|
* Projects a {@link FileChange} into a {@link FileDiffEntry} for the file list.
|
|
344
350
|
*
|
|
345
351
|
* Counts: hunk-only uses the runner's authoritative numbers; whole-file inline
|
|
346
|
-
* is derived from the content
|
|
347
|
-
*
|
|
352
|
+
* is derived from the content (identical to the runner's capture-time counts by
|
|
353
|
+
* construction — same diff algorithm). A whole-file side with no synchronous
|
|
354
|
+
* content (offloaded / binary) falls back to the runner's capture-time
|
|
355
|
+
* `linesAdded`/`linesRemoved` — zero when no count exists, which the list
|
|
356
|
+
* renders as no stat.
|
|
348
357
|
*/
|
|
349
358
|
function toFileDiffEntry(change: FileChange): FileDiffEntry {
|
|
350
359
|
const changeType =
|
|
@@ -370,7 +379,12 @@ function toFileDiffEntry(change: FileChange): FileDiffEntry {
|
|
|
370
379
|
return { path: change.path, changeType, additions, deletions };
|
|
371
380
|
}
|
|
372
381
|
|
|
373
|
-
return {
|
|
382
|
+
return {
|
|
383
|
+
path: change.path,
|
|
384
|
+
changeType,
|
|
385
|
+
additions: change.linesAdded,
|
|
386
|
+
deletions: change.linesRemoved,
|
|
387
|
+
};
|
|
374
388
|
}
|
|
375
389
|
|
|
376
390
|
/** Inline text of a side, or null when absent/offloaded/binary. */
|
|
@@ -18,11 +18,18 @@ export interface FilePathContextValue {
|
|
|
18
18
|
* `FilePathLink` delegates to this callback instead of opening
|
|
19
19
|
* a URL or copying to clipboard. Platform builders use this to
|
|
20
20
|
* integrate their own file viewer or navigation.
|
|
21
|
+
*
|
|
22
|
+
* Return `false` to **decline** a specific path — `FilePathLink` then falls
|
|
23
|
+
* back to its default action (open the GitHub link / copy the path), so a
|
|
24
|
+
* handler that can only open *some* paths (e.g. resolvable workspace files)
|
|
25
|
+
* leaves the rest behaving as before. Returning `true` or `void` means the
|
|
26
|
+
* click was fully handled and the default is suppressed — preserving the
|
|
27
|
+
* behavior of existing `void`-returning handlers.
|
|
21
28
|
*/
|
|
22
29
|
readonly onFilePathClick?: (
|
|
23
30
|
path: string,
|
|
24
31
|
resolved: ResolvedPathAction,
|
|
25
|
-
) => void;
|
|
32
|
+
) => boolean | void;
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
const DEFAULT_VALUE: FilePathContextValue = {
|