@stigmer/react 3.1.1 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/composer/SessionComposer.d.ts +25 -1
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +19 -8
- package/composer/SessionComposer.js.map +1 -1
- package/execution/ArtifactContentRenderer.d.ts +11 -1
- package/execution/ArtifactContentRenderer.d.ts.map +1 -1
- package/execution/ArtifactContentRenderer.js +39 -15
- package/execution/ArtifactContentRenderer.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts +5 -5
- package/execution/ArtifactPreviewModal.js +4 -4
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/FileChangeProgressBar.d.ts +47 -0
- package/execution/FileChangeProgressBar.d.ts.map +1 -0
- package/execution/FileChangeProgressBar.js +49 -0
- package/execution/FileChangeProgressBar.js.map +1 -0
- package/execution/FileChangesView.d.ts.map +1 -1
- package/execution/FileChangesView.js +19 -4
- package/execution/FileChangesView.js.map +1 -1
- package/execution/FilePathContext.d.ts +8 -1
- package/execution/FilePathContext.d.ts.map +1 -1
- package/execution/FilePathContext.js.map +1 -1
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +21 -6
- package/execution/FilePathLink.js.map +1 -1
- package/execution/FileReviewAtoms.d.ts +27 -0
- package/execution/FileReviewAtoms.d.ts.map +1 -0
- package/execution/FileReviewAtoms.js +64 -0
- package/execution/FileReviewAtoms.js.map +1 -0
- package/execution/FileReviewCard.d.ts +2 -2
- package/execution/FileReviewCard.d.ts.map +1 -1
- package/execution/FileReviewCard.js +32 -62
- package/execution/FileReviewCard.js.map +1 -1
- package/execution/MessageEntry.d.ts +20 -0
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +19 -5
- package/execution/MessageEntry.js.map +1 -1
- package/execution/MessageThread.d.ts +75 -13
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +195 -27
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts +36 -21
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +39 -25
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/PlanCompletionCard.d.ts +4 -4
- package/execution/PlanCompletionCard.d.ts.map +1 -1
- package/execution/PlanCompletionCard.js +4 -4
- package/execution/PlanCompletionCard.js.map +1 -1
- package/execution/PlanDocumentMessage.d.ts +32 -0
- package/execution/PlanDocumentMessage.d.ts.map +1 -0
- package/execution/PlanDocumentMessage.js +37 -0
- package/execution/PlanDocumentMessage.js.map +1 -0
- package/execution/PlanStreamingCard.d.ts +50 -0
- package/execution/PlanStreamingCard.d.ts.map +1 -0
- package/execution/PlanStreamingCard.js +40 -0
- package/execution/PlanStreamingCard.js.map +1 -0
- package/execution/index.d.ts +9 -1
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +4 -0
- package/execution/index.js.map +1 -1
- package/execution/use-build-from-plan-hotkey.d.ts +1 -1
- package/execution/use-build-from-plan-hotkey.js +1 -1
- package/execution/useArtifactCopy.d.ts +51 -0
- package/execution/useArtifactCopy.d.ts.map +1 -0
- package/execution/useArtifactCopy.js +75 -0
- package/execution/useArtifactCopy.js.map +1 -0
- package/execution/useArtifactDownload.d.ts.map +1 -1
- package/execution/useArtifactDownload.js +17 -5
- package/execution/useArtifactDownload.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +12 -0
- package/execution/useCreateAgentExecution.d.ts.map +1 -1
- package/execution/useCreateAgentExecution.js +5 -1
- package/execution/useCreateAgentExecution.js.map +1 -1
- package/github/decodeGitHubContent.d.ts +29 -0
- package/github/decodeGitHubContent.d.ts.map +1 -0
- package/github/decodeGitHubContent.js +72 -0
- package/github/decodeGitHubContent.js.map +1 -0
- package/github/index.d.ts +1 -0
- package/github/index.d.ts.map +1 -1
- package/github/index.js +1 -0
- package/github/index.js.map +1 -1
- package/github/useGitHubFileReader.d.ts +26 -0
- package/github/useGitHubFileReader.d.ts.map +1 -0
- package/github/useGitHubFileReader.js +106 -0
- package/github/useGitHubFileReader.js.map +1 -0
- package/github/useGitHubTreeLister.d.ts.map +1 -1
- package/github/useGitHubTreeLister.js +6 -2
- package/github/useGitHubTreeLister.js.map +1 -1
- package/index.d.ts +9 -9
- package/index.d.ts.map +1 -1
- package/index.js +5 -5
- package/index.js.map +1 -1
- package/internal/ResizableSplit.d.ts +72 -22
- package/internal/ResizableSplit.d.ts.map +1 -1
- package/internal/ResizableSplit.js +96 -38
- package/internal/ResizableSplit.js.map +1 -1
- package/internal/VirtualizedThread.d.ts +5 -3
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +6 -4
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/file-icons/index.d.ts +17 -0
- package/internal/file-icons/index.d.ts.map +1 -0
- package/internal/file-icons/index.js +60 -0
- package/internal/file-icons/index.js.map +1 -0
- package/internal/file-tree/FileTreeNode.d.ts +18 -1
- package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
- package/internal/file-tree/FileTreeNode.js +11 -2
- package/internal/file-tree/FileTreeNode.js.map +1 -1
- package/internal/markdown-components.d.ts +38 -1
- package/internal/markdown-components.d.ts.map +1 -1
- package/internal/markdown-components.js +86 -11
- package/internal/markdown-components.js.map +1 -1
- package/{workflow → internal}/motion-preference.d.ts +7 -4
- package/internal/motion-preference.d.ts.map +1 -0
- package/{workflow → internal}/motion-preference.js +7 -4
- package/internal/motion-preference.js.map +1 -0
- package/internal/store/index.d.ts +33 -0
- package/internal/store/index.d.ts.map +1 -1
- package/internal/store/index.js +59 -0
- package/internal/store/index.js.map +1 -1
- package/internal/store/workspace-editors-store.d.ts +145 -0
- package/internal/store/workspace-editors-store.d.ts.map +1 -0
- package/internal/store/workspace-editors-store.js +208 -0
- package/internal/store/workspace-editors-store.js.map +1 -0
- package/internal/store/workspace-file-selection-store.d.ts +38 -0
- package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
- package/internal/store/workspace-file-selection-store.js +62 -0
- package/internal/store/workspace-file-selection-store.js.map +1 -0
- package/internal/useRevealLine.d.ts +49 -0
- package/internal/useRevealLine.d.ts.map +1 -0
- package/internal/useRevealLine.js +43 -0
- package/internal/useRevealLine.js.map +1 -0
- package/library/detect-plan-artifact.d.ts +43 -4
- package/library/detect-plan-artifact.d.ts.map +1 -1
- package/library/detect-plan-artifact.js +45 -5
- package/library/detect-plan-artifact.js.map +1 -1
- package/library/detect-streaming-plan.d.ts +45 -0
- package/library/detect-streaming-plan.d.ts.map +1 -0
- package/library/detect-streaming-plan.js +83 -0
- package/library/detect-streaming-plan.js.map +1 -0
- package/library/index.d.ts +4 -1
- package/library/index.d.ts.map +1 -1
- package/library/index.js +2 -1
- package/library/index.js.map +1 -1
- package/package.json +4 -4
- package/session/NewSessionViewer.d.ts +19 -4
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +52 -25
- package/session/NewSessionViewer.js.map +1 -1
- package/session/PlanEditor.d.ts +55 -0
- package/session/PlanEditor.d.ts.map +1 -0
- package/session/PlanEditor.js +88 -0
- package/session/PlanEditor.js.map +1 -0
- package/session/PlanStreamingDocument.d.ts +30 -0
- package/session/PlanStreamingDocument.d.ts.map +1 -0
- package/session/PlanStreamingDocument.js +37 -0
- package/session/PlanStreamingDocument.js.map +1 -0
- package/session/SessionPanelChip.d.ts +26 -0
- package/session/SessionPanelChip.d.ts.map +1 -0
- package/session/SessionPanelChip.js +40 -0
- package/session/SessionPanelChip.js.map +1 -0
- package/session/SessionViewer.d.ts +34 -7
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +334 -33
- package/session/SessionViewer.js.map +1 -1
- package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
- package/session/facets/ArtifactsTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ArtifactsTab.js +8 -3
- package/session/facets/ArtifactsTab.js.map +1 -0
- package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
- package/session/facets/ChangesTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ChangesTab.js +3 -3
- package/session/facets/ChangesTab.js.map +1 -0
- package/session/facets/InspectTab.d.ts.map +1 -0
- package/session/facets/InspectTab.js.map +1 -0
- package/session/{inspector → facets}/SetupTab.d.ts +11 -2
- package/session/facets/SetupTab.d.ts.map +1 -0
- package/session/{inspector → facets}/SetupTab.js +4 -3
- package/session/facets/SetupTab.js.map +1 -0
- package/session/{inspector → facets}/UsageTab.d.ts +1 -1
- package/session/facets/UsageTab.d.ts.map +1 -0
- package/session/{inspector → facets}/UsageTab.js +1 -1
- package/session/facets/UsageTab.js.map +1 -0
- package/session/{inspector → facets}/index.d.ts +0 -6
- package/session/facets/index.d.ts.map +1 -0
- package/session/{inspector → facets}/index.js +0 -3
- package/session/facets/index.js.map +1 -0
- package/session/index.d.ts +11 -2
- package/session/index.d.ts.map +1 -1
- package/session/index.js +15 -2
- package/session/index.js.map +1 -1
- package/session/plan-document.d.ts +21 -0
- package/session/plan-document.d.ts.map +1 -0
- package/session/plan-document.js +28 -0
- package/session/plan-document.js.map +1 -0
- package/session/useOpenFileChange.d.ts +20 -0
- package/session/useOpenFileChange.d.ts.map +1 -0
- package/session/useOpenFileChange.js +31 -0
- package/session/useOpenFileChange.js.map +1 -0
- package/session/usePlanDraft.d.ts +52 -0
- package/session/usePlanDraft.d.ts.map +1 -0
- package/session/usePlanDraft.js +63 -0
- package/session/usePlanDraft.js.map +1 -0
- package/session/useSessionConversation.d.ts +14 -1
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +20 -2
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +1 -0
- package/session/useSessionPageFlow.js.map +1 -1
- package/session/useSessionPanel.d.ts +120 -0
- package/session/useSessionPanel.d.ts.map +1 -0
- package/session/useSessionPanel.js +130 -0
- package/session/useSessionPanel.js.map +1 -0
- package/session/useSessionRailViews.d.ts +45 -0
- package/session/useSessionRailViews.d.ts.map +1 -0
- package/session/useSessionRailViews.js +105 -0
- package/session/useSessionRailViews.js.map +1 -0
- package/src/composer/SessionComposer.tsx +53 -10
- package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
- package/src/execution/ArtifactContentRenderer.tsx +101 -24
- package/src/execution/ArtifactPreviewModal.tsx +9 -9
- package/src/execution/FileChangeProgressBar.tsx +121 -0
- package/src/execution/FileChangesView.tsx +18 -4
- package/src/execution/FilePathContext.tsx +8 -1
- package/src/execution/FilePathLink.tsx +22 -6
- package/src/execution/FileReviewAtoms.tsx +89 -0
- package/src/execution/FileReviewCard.tsx +57 -90
- package/src/execution/MessageEntry.tsx +49 -1
- package/src/execution/MessageThread.tsx +308 -39
- package/src/execution/PlanArtifactCard.tsx +174 -64
- package/src/execution/PlanCompletionCard.tsx +5 -5
- package/src/execution/PlanDocumentMessage.tsx +96 -0
- package/src/execution/PlanStreamingCard.tsx +141 -0
- package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
- package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +6 -6
- package/src/execution/__tests__/FileChangeProgressBar.test.tsx +125 -0
- package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
- package/src/execution/__tests__/FileReviewCard.test.tsx +66 -7
- package/src/execution/__tests__/MessageThread.test.tsx +102 -1
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +114 -26
- package/src/execution/__tests__/PlanCompletionCard.test.tsx +2 -2
- package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
- package/src/execution/__tests__/PlanStreamingCard.test.tsx +56 -0
- package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +600 -22
- package/src/execution/__tests__/message-entry.test.tsx +17 -0
- package/src/execution/__tests__/useArtifactCopy.test.tsx +90 -0
- package/src/execution/__tests__/useArtifactDownload.test.tsx +2 -0
- package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
- package/src/execution/index.ts +13 -1
- package/src/execution/use-build-from-plan-hotkey.ts +1 -1
- package/src/execution/useArtifactCopy.ts +109 -0
- package/src/execution/useArtifactDownload.ts +17 -5
- package/src/execution/useCreateAgentExecution.ts +18 -1
- package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
- package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
- package/src/github/decodeGitHubContent.ts +83 -0
- package/src/github/index.ts +1 -0
- package/src/github/useGitHubFileReader.ts +152 -0
- package/src/github/useGitHubTreeLister.ts +6 -2
- package/src/index.ts +69 -9
- package/src/internal/ResizableSplit.tsx +184 -51
- package/src/internal/VirtualizedThread.tsx +12 -4
- package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
- package/src/internal/__tests__/markdown-components.test.tsx +68 -0
- package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
- package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
- package/src/internal/file-icons/index.tsx +137 -0
- package/src/internal/file-tree/FileTreeNode.tsx +56 -5
- package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
- package/src/internal/markdown-components.tsx +116 -11
- package/src/{workflow → internal}/motion-preference.ts +7 -4
- package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
- package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
- package/src/internal/store/index.ts +94 -0
- package/src/internal/store/workspace-editors-store.ts +315 -0
- package/src/internal/store/workspace-file-selection-store.ts +88 -0
- package/src/internal/useRevealLine.ts +81 -0
- package/src/library/__tests__/detect-plan-artifact.test.ts +69 -0
- package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
- package/src/library/detect-plan-artifact.ts +62 -5
- package/src/library/detect-streaming-plan.ts +108 -0
- package/src/library/index.ts +7 -0
- package/src/session/NewSessionViewer.tsx +123 -55
- package/src/session/PlanEditor.tsx +361 -0
- package/src/session/PlanStreamingDocument.tsx +97 -0
- package/src/session/SessionPanelChip.tsx +103 -0
- package/src/session/SessionViewer.tsx +655 -96
- package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
- package/src/session/__tests__/PlanEditor.test.tsx +217 -0
- package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
- package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
- package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +66 -4
- package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
- package/src/session/__tests__/audienceWiring.test.tsx +55 -19
- package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
- package/src/session/__tests__/usePlanDraft.test.ts +102 -0
- package/src/session/__tests__/useSessionConversation.test.tsx +44 -0
- package/src/session/__tests__/useSessionPanel.test.ts +298 -0
- package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
- package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
- package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
- package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
- package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
- package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +42 -8
- package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
- package/src/session/{inspector → facets}/index.ts +0 -16
- package/src/session/index.ts +30 -13
- package/src/session/plan-document.ts +30 -0
- package/src/session/useOpenFileChange.ts +53 -0
- package/src/session/usePlanDraft.ts +109 -0
- package/src/session/useSessionConversation.ts +38 -3
- package/src/session/useSessionPageFlow.ts +1 -0
- package/src/session/useSessionPanel.ts +288 -0
- package/src/session/useSessionRailViews.tsx +200 -0
- package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
- package/src/workflow/index.ts +1 -1
- package/src/workflow/useFollowExecution.ts +1 -1
- package/src/workspace/EditorTabs.tsx +174 -0
- package/src/workspace/ExplorerTree.tsx +253 -0
- package/src/workspace/FileViewer.tsx +537 -0
- package/src/workspace/WorkspaceContentSearch.tsx +502 -0
- package/src/workspace/WorkspaceContentSearcher.ts +70 -0
- package/src/workspace/WorkspaceEditor.tsx +19 -16
- package/src/workspace/WorkspaceFileLister.ts +11 -0
- package/src/workspace/WorkspaceFileReader.ts +57 -0
- package/src/workspace/WorkspaceFileSearch.tsx +452 -0
- package/src/workspace/WorkspaceSurface.tsx +839 -0
- package/src/workspace/__tests__/EditorTabs.test.tsx +102 -0
- package/src/workspace/__tests__/ExplorerTree.test.tsx +204 -0
- package/src/workspace/__tests__/FileViewer.test.tsx +439 -0
- package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +229 -0
- package/src/workspace/__tests__/WorkspaceEditor-initialPanel.test.tsx +19 -0
- package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +227 -0
- package/src/workspace/__tests__/WorkspaceSurface.test.tsx +418 -0
- package/src/workspace/__tests__/a11y/harness.tsx +140 -0
- package/src/workspace/__tests__/a11y/mock-capabilities.ts +138 -0
- package/src/workspace/__tests__/a11y/workspace-editor.a11y.test.tsx +65 -0
- package/src/workspace/__tests__/a11y/workspace-explorer-search.a11y.test.tsx +112 -0
- package/src/workspace/__tests__/a11y/workspace-viewer-tabs.a11y.test.tsx +69 -0
- package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
- package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
- package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
- package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
- package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
- package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
- package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
- package/src/workspace/findChangeForSelection.ts +61 -0
- package/src/workspace/index.ts +56 -2
- package/src/workspace/matchContentPreview.ts +51 -0
- package/src/workspace/matchWorkspaceFiles.ts +86 -0
- package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
- package/src/workspace/useWorkspaceContentSearch.ts +228 -0
- package/src/workspace/useWorkspaceFileContent.ts +129 -0
- package/src/workspace/useWorkspaceFileSearch.ts +184 -0
- package/src/workspace/useWorkspaceFiles.ts +27 -27
- package/src/workspace/workspaceListingCache.ts +93 -0
- package/styles.css +1 -1
- package/workflow/WorkflowExecutionGraph.js +1 -1
- package/workflow/WorkflowExecutionGraph.js.map +1 -1
- package/workflow/index.d.ts +1 -1
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -1
- package/workflow/index.js.map +1 -1
- package/workflow/useFollowExecution.js +1 -1
- package/workflow/useFollowExecution.js.map +1 -1
- package/workspace/EditorTabs.d.ts +47 -0
- package/workspace/EditorTabs.d.ts.map +1 -0
- package/workspace/EditorTabs.js +78 -0
- package/workspace/EditorTabs.js.map +1 -0
- package/workspace/ExplorerTree.d.ts +32 -0
- package/workspace/ExplorerTree.d.ts.map +1 -0
- package/workspace/ExplorerTree.js +49 -0
- package/workspace/ExplorerTree.js.map +1 -0
- package/workspace/FileViewer.d.ts +93 -0
- package/workspace/FileViewer.d.ts.map +1 -0
- package/workspace/FileViewer.js +193 -0
- package/workspace/FileViewer.js.map +1 -0
- package/workspace/WorkspaceContentSearch.d.ts +41 -0
- package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearch.js +216 -0
- package/workspace/WorkspaceContentSearch.js.map +1 -0
- package/workspace/WorkspaceContentSearcher.d.ts +59 -0
- package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearcher.js +7 -0
- package/workspace/WorkspaceContentSearcher.js.map +1 -0
- package/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/workspace/WorkspaceEditor.js +8 -10
- package/workspace/WorkspaceEditor.js.map +1 -1
- package/workspace/WorkspaceFileLister.d.ts +11 -0
- package/workspace/WorkspaceFileLister.d.ts.map +1 -1
- package/workspace/WorkspaceFileReader.d.ts +48 -0
- package/workspace/WorkspaceFileReader.d.ts.map +1 -0
- package/workspace/WorkspaceFileReader.js +11 -0
- package/workspace/WorkspaceFileReader.js.map +1 -0
- package/workspace/WorkspaceFileSearch.d.ts +32 -0
- package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/WorkspaceFileSearch.js +175 -0
- package/workspace/WorkspaceFileSearch.js.map +1 -0
- package/workspace/WorkspaceSurface.d.ts +151 -0
- package/workspace/WorkspaceSurface.d.ts.map +1 -0
- package/workspace/WorkspaceSurface.js +220 -0
- package/workspace/WorkspaceSurface.js.map +1 -0
- package/workspace/findChangeForSelection.d.ts +19 -0
- package/workspace/findChangeForSelection.d.ts.map +1 -0
- package/workspace/findChangeForSelection.js +46 -0
- package/workspace/findChangeForSelection.js.map +1 -0
- package/workspace/index.d.ts +24 -2
- package/workspace/index.d.ts.map +1 -1
- package/workspace/index.js +13 -1
- package/workspace/index.js.map +1 -1
- package/workspace/matchContentPreview.d.ts +21 -0
- package/workspace/matchContentPreview.d.ts.map +1 -0
- package/workspace/matchContentPreview.js +36 -0
- package/workspace/matchContentPreview.js.map +1 -0
- package/workspace/matchWorkspaceFiles.d.ts +30 -0
- package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
- package/workspace/matchWorkspaceFiles.js +58 -0
- package/workspace/matchWorkspaceFiles.js.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.js +115 -0
- package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
- package/workspace/useWorkspaceContentSearch.d.ts +69 -0
- package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceContentSearch.js +154 -0
- package/workspace/useWorkspaceContentSearch.js.map +1 -0
- package/workspace/useWorkspaceFileContent.d.ts +73 -0
- package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
- package/workspace/useWorkspaceFileContent.js +57 -0
- package/workspace/useWorkspaceFileContent.js.map +1 -0
- package/workspace/useWorkspaceFileSearch.d.ts +61 -0
- package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceFileSearch.js +119 -0
- package/workspace/useWorkspaceFileSearch.js.map +1 -0
- package/workspace/useWorkspaceFiles.d.ts +13 -5
- package/workspace/useWorkspaceFiles.d.ts.map +1 -1
- package/workspace/useWorkspaceFiles.js +18 -19
- package/workspace/useWorkspaceFiles.js.map +1 -1
- package/workspace/workspaceListingCache.d.ts +47 -0
- package/workspace/workspaceListingCache.d.ts.map +1 -0
- package/workspace/workspaceListingCache.js +55 -0
- package/workspace/workspaceListingCache.js.map +1 -0
- package/session/inspector/ArtifactsTab.d.ts.map +0 -1
- package/session/inspector/ArtifactsTab.js.map +0 -1
- package/session/inspector/ChangesTab.d.ts.map +0 -1
- package/session/inspector/ChangesTab.js.map +0 -1
- package/session/inspector/InspectTab.d.ts.map +0 -1
- package/session/inspector/InspectTab.js.map +0 -1
- package/session/inspector/SessionInspector.d.ts +0 -64
- package/session/inspector/SessionInspector.d.ts.map +0 -1
- package/session/inspector/SessionInspector.js +0 -53
- package/session/inspector/SessionInspector.js.map +0 -1
- package/session/inspector/SetupTab.d.ts.map +0 -1
- package/session/inspector/SetupTab.js.map +0 -1
- package/session/inspector/UsageTab.d.ts.map +0 -1
- package/session/inspector/UsageTab.js.map +0 -1
- package/session/inspector/WorkspaceTab.d.ts +0 -35
- package/session/inspector/WorkspaceTab.d.ts.map +0 -1
- package/session/inspector/WorkspaceTab.js +0 -75
- package/session/inspector/WorkspaceTab.js.map +0 -1
- package/session/inspector/index.d.ts.map +0 -1
- package/session/inspector/index.js.map +0 -1
- package/session/inspector/useSessionInspector.d.ts +0 -49
- package/session/inspector/useSessionInspector.d.ts.map +0 -1
- package/session/inspector/useSessionInspector.js +0 -122
- package/session/inspector/useSessionInspector.js.map +0 -1
- package/src/session/inspector/SessionInspector.tsx +0 -162
- package/src/session/inspector/WorkspaceTab.tsx +0 -245
- package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
- package/src/session/inspector/useSessionInspector.ts +0 -178
- package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
- package/workflow/motion-preference.d.ts.map +0 -1
- package/workflow/motion-preference.js.map +0 -1
- package/workspace/WorkspaceEntryFiles.d.ts +0 -22
- package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
- package/workspace/WorkspaceEntryFiles.js +0 -58
- package/workspace/WorkspaceEntryFiles.js.map +0 -1
- /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
- /package/session/{inspector → facets}/InspectTab.js +0 -0
- /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
- /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
- /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Resolve a transcript tool-call file path to an openable workspace-file
|
|
2
|
+
// selection. This is the seam that lets a click on a path in the message thread
|
|
3
|
+
// route to the same read-only Viewer a file-tree click drives (Slice 3).
|
|
4
|
+
//
|
|
5
|
+
// The hard part is NOT identity ("which entry") but PATH FORM. The reader and
|
|
6
|
+
// lister contracts are strict: `WorkspaceFileReader` / the GitHub Trees lister
|
|
7
|
+
// speak repo-root-relative (git) or root-relative (local) paths — the exact
|
|
8
|
+
// strings a file-tree node carries. Transcript tool-call paths are not
|
|
9
|
+
// guaranteed to be in that form: depending on harness and workspace layout they
|
|
10
|
+
// arrive workspace-relative, subdir-prefixed, or absolute (see
|
|
11
|
+
// `execution/file-review-status.ts` `changeForRowPath`, which documents the
|
|
12
|
+
// same variance and treats path matching as presentation-only).
|
|
13
|
+
//
|
|
14
|
+
// Rather than fuzzy-match, this resolver normalizes deterministically using only
|
|
15
|
+
// anchors the client already holds, grounded in how the runner provisions the
|
|
16
|
+
// workspace (`backend/.../workspace/provisioner.ts`):
|
|
17
|
+
// - Single entry -> cloned at the workspace root, so a (humanized) tool-call
|
|
18
|
+
// path is already repo/root-relative. Identity transform.
|
|
19
|
+
// - Multiple git -> each cloned into `<root>/<entry.name>/`, so the path is
|
|
20
|
+
// prefixed by the subdir name; strip it.
|
|
21
|
+
// - Local (desktop) -> the native reader joins `entry.localPath` + a
|
|
22
|
+
// root-relative path; local tool paths may be absolute, so
|
|
23
|
+
// strip the known `entry.localPath` prefix.
|
|
24
|
+
// - Cloud absolute -> strip the known `sandboxWorkspaceRoot` first.
|
|
25
|
+
// Anything that does not resolve to a definite relative path returns `null` so
|
|
26
|
+
// the caller keeps its existing copy/GitHub-link behavior — a wrong file can
|
|
27
|
+
// never open. Extending this to arbitrary/absolute paths belongs to a later
|
|
28
|
+
// slice that resolves against the authoritative file-tree index.
|
|
29
|
+
import { classifyPath } from "../execution/file-path-resolver.js";
|
|
30
|
+
/** Forward-slash-normalize and drop any leading slashes for prefix comparison. */
|
|
31
|
+
function normalize(path) {
|
|
32
|
+
return path.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns the portion of `path` beneath `anchor`, or `null` when `path` does
|
|
36
|
+
* not sit under `anchor`. An exact match (the anchor itself, a directory) yields
|
|
37
|
+
* `""` — the caller rejects it, since a directory is not a viewable file.
|
|
38
|
+
*/
|
|
39
|
+
function relativeTo(path, anchor) {
|
|
40
|
+
if (!anchor)
|
|
41
|
+
return null;
|
|
42
|
+
if (path === anchor)
|
|
43
|
+
return "";
|
|
44
|
+
if (path.startsWith(anchor + "/"))
|
|
45
|
+
return path.slice(anchor.length + 1);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolves a transcript tool-call file path to the {@link SelectedWorkspaceFile}
|
|
50
|
+
* that opens it in the read-only Viewer, or `null` when it cannot be resolved to
|
|
51
|
+
* a definite repo/root-relative file (caller keeps copy/GitHub-link fallback).
|
|
52
|
+
*
|
|
53
|
+
* `entries` are the client-side workspace entries (`useWorkspaceEntries`), the
|
|
54
|
+
* same list the Viewer resolves against, so the returned `entryId` is directly
|
|
55
|
+
* usable. `sandboxWorkspaceRoot` (when the session has git-repo entries, e.g.
|
|
56
|
+
* `/home/daytona/workspace`) is stripped first so cloud-absolute paths reduce to
|
|
57
|
+
* workspace-relative before per-entry anchoring.
|
|
58
|
+
*
|
|
59
|
+
* The result `path` is guaranteed to match what the file tree / lister emits for
|
|
60
|
+
* the same file, so opening from the transcript and from the tree produce an
|
|
61
|
+
* identical selection (and hit the same content fetch/cache).
|
|
62
|
+
*/
|
|
63
|
+
export function resolveWorkspaceFileSelection(path, entries, sandboxWorkspaceRoot) {
|
|
64
|
+
if (!path || entries.length === 0)
|
|
65
|
+
return null;
|
|
66
|
+
// 1. Reduce a cloud-absolute path to workspace-relative using the known root.
|
|
67
|
+
let work = normalize(path);
|
|
68
|
+
if (sandboxWorkspaceRoot) {
|
|
69
|
+
const root = normalize(sandboxWorkspaceRoot);
|
|
70
|
+
const relToRoot = relativeTo(work, root);
|
|
71
|
+
if (relToRoot !== null)
|
|
72
|
+
work = relToRoot;
|
|
73
|
+
}
|
|
74
|
+
// The bare workspace root ("" after stripping, or the humanized ".") is not a
|
|
75
|
+
// file.
|
|
76
|
+
if (!work || work === ".")
|
|
77
|
+
return null;
|
|
78
|
+
// 2. The platform mount (`.stigmer/…`) is a virtual namespace, not a workspace
|
|
79
|
+
// file — checked after the root strip so an absolute `<root>/.stigmer/…`
|
|
80
|
+
// is caught too. Keep copy behavior for it.
|
|
81
|
+
if (classifyPath(work).kind === "platform")
|
|
82
|
+
return null;
|
|
83
|
+
// 3. Anchor on the exact per-entry roots the client holds. Local entries
|
|
84
|
+
// anchor on their absolute `localPath`; multi-entry git repos anchor on the
|
|
85
|
+
// provisioning subdir (`entry.name`). A single git entry is cloned at the
|
|
86
|
+
// root, so it falls through to step 4.
|
|
87
|
+
const isMulti = entries.length > 1;
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
let anchor = null;
|
|
90
|
+
if (entry.type === "local" && entry.localPath) {
|
|
91
|
+
anchor = normalize(entry.localPath);
|
|
92
|
+
}
|
|
93
|
+
else if (entry.type === "git" && isMulti) {
|
|
94
|
+
anchor = normalize(entry.name);
|
|
95
|
+
}
|
|
96
|
+
if (anchor === null)
|
|
97
|
+
continue;
|
|
98
|
+
const rel = relativeTo(work, anchor);
|
|
99
|
+
// Exact match is the entry's own root directory, not a viewable file — stop
|
|
100
|
+
// rather than fall through to the single-entry fallback (which would return
|
|
101
|
+
// the raw root path).
|
|
102
|
+
if (rel === "")
|
|
103
|
+
return null;
|
|
104
|
+
if (rel)
|
|
105
|
+
return { entryId: entry.id, path: rel };
|
|
106
|
+
}
|
|
107
|
+
// 4. A single entry whose anchor did not apply (e.g. a git repo at the root, or
|
|
108
|
+
// a local path already root-relative): the path is already repo/root-relative.
|
|
109
|
+
if (entries.length === 1) {
|
|
110
|
+
return { entryId: entries[0].id, path: work };
|
|
111
|
+
}
|
|
112
|
+
// 5. Multi-entry with no anchor match: refuse to guess which entry owns it.
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=resolveWorkspaceFileSelection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveWorkspaceFileSelection.js","sourceRoot":"","sources":["../../src/workspace/resolveWorkspaceFileSelection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { WorkspaceEntry } from "./useWorkspaceEntries.js";
|
|
2
|
+
import type { WorkspaceContentMatch, WorkspaceContentSearcher } from "./WorkspaceContentSearcher.js";
|
|
3
|
+
/** Options for {@link useWorkspaceContentSearch}. */
|
|
4
|
+
export interface UseWorkspaceContentSearchOptions {
|
|
5
|
+
/** All workspace entries to search across. */
|
|
6
|
+
readonly entries: readonly WorkspaceEntry[];
|
|
7
|
+
/** Platform-injected content searcher. `undefined` → content search is unavailable. */
|
|
8
|
+
readonly searcher: WorkspaceContentSearcher | undefined;
|
|
9
|
+
/** Current search query. Trimmed; below {@link minLength} yields no search. */
|
|
10
|
+
readonly query: string;
|
|
11
|
+
/** Debounce delay for query changes in milliseconds. @default 300 */
|
|
12
|
+
readonly debounceMs?: number;
|
|
13
|
+
/** Minimum trimmed query length before a search runs. @default 2 */
|
|
14
|
+
readonly minLength?: number;
|
|
15
|
+
}
|
|
16
|
+
/** Content-search hits (and per-entry status) for one workspace entry. */
|
|
17
|
+
export interface WorkspaceContentSearchGroup {
|
|
18
|
+
/** The workspace entry these matches belong to. */
|
|
19
|
+
readonly entry: WorkspaceEntry;
|
|
20
|
+
/** Line-level matches within this entry, backend-ordered (path, then line). */
|
|
21
|
+
readonly matches: readonly WorkspaceContentMatch[];
|
|
22
|
+
/** `true` when this entry's search was capped (more matches exist than shown). */
|
|
23
|
+
readonly truncated: boolean;
|
|
24
|
+
/** Search error for this entry, if any (isolated — other entries still resolve). */
|
|
25
|
+
readonly error: Error | null;
|
|
26
|
+
}
|
|
27
|
+
/** Return value of {@link useWorkspaceContentSearch}. */
|
|
28
|
+
export interface UseWorkspaceContentSearchReturn {
|
|
29
|
+
/** Entries with something to show (matches, an error, or a truncation notice). */
|
|
30
|
+
readonly groups: readonly WorkspaceContentSearchGroup[];
|
|
31
|
+
/** Total matches across all groups (for a "showing N of M" affordance). */
|
|
32
|
+
readonly totalMatches: number;
|
|
33
|
+
/** `true` during the first search of a query with no prior results to show. */
|
|
34
|
+
readonly isLoading: boolean;
|
|
35
|
+
/** `true` while a new query loads *over* previously-shown results (no blank flash). */
|
|
36
|
+
readonly isRefetching: boolean;
|
|
37
|
+
/** `true` when no substrate can be searched (no searcher, or every entry unsupported). */
|
|
38
|
+
readonly isUnsupported: boolean;
|
|
39
|
+
/** First per-entry error, for a top-level fallback message. `null` when none. */
|
|
40
|
+
readonly error: Error | null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Behavior hook powering workspace-wide content (text) search.
|
|
44
|
+
*
|
|
45
|
+
* The text-grep sibling of
|
|
46
|
+
* {@link useWorkspaceFileSearch}: it keeps
|
|
47
|
+
* that hook's per-entry aggregation, error isolation, and generation guard, and
|
|
48
|
+
* adds the platform's canonical debounce idiom from `useResourceSearch`
|
|
49
|
+
* (`query`/`debouncedQuery` + `setTimeout`). The key difference is that the
|
|
50
|
+
* debounced query is part of the *fetch* — each keystroke hits disk via the
|
|
51
|
+
* injected {@link WorkspaceContentSearcher}, uncached — so a `minLength` guard
|
|
52
|
+
* and a debounce protect the filesystem.
|
|
53
|
+
*
|
|
54
|
+
* Prior results stay visible while a new debounced query loads (`isRefetching`
|
|
55
|
+
* true, results unchanged); only the very first search with nothing to show
|
|
56
|
+
* flips `isLoading`. This avoids a per-keystroke blank flash the cached filename
|
|
57
|
+
* search never had.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* const { groups, totalMatches, isRefetching } = useWorkspaceContentSearch({
|
|
62
|
+
* entries: workspace.entries,
|
|
63
|
+
* searcher: workspaceContentSearcher,
|
|
64
|
+
* query,
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function useWorkspaceContentSearch({ entries, searcher, query, debounceMs, minLength, }: UseWorkspaceContentSearchOptions): UseWorkspaceContentSearchReturn;
|
|
69
|
+
//# sourceMappingURL=useWorkspaceContentSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWorkspaceContentSearch.d.ts","sourceRoot":"","sources":["../../src/workspace/useWorkspaceContentSearch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EACV,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,+BAA+B,CAAC;AAavC,qDAAqD;AACrD,MAAM,WAAW,gCAAgC;IAC/C,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,GAAG,SAAS,CAAC;IACxD,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,0EAA0E;AAC1E,MAAM,WAAW,2BAA2B;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACnD,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAED,yDAAyD;AACzD,MAAM,WAAW,+BAA+B;IAC9C,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,SAAS,2BAA2B,EAAE,CAAC;IACxD,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,0FAA0F;IAC1F,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,QAAQ,EACR,KAAK,EACL,UAAgC,EAChC,SAA8B,GAC/B,EAAE,gCAAgC,GAAG,+BAA+B,CA4HpE"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { toError } from "../internal/toError.js";
|
|
4
|
+
/** Default debounce for content-search query changes — matches `useResourceSearch`. */
|
|
5
|
+
const DEFAULT_DEBOUNCE_MS = 300;
|
|
6
|
+
/**
|
|
7
|
+
* Minimum query length before a disk search fires. Content search hits the
|
|
8
|
+
* filesystem on every query (unlike the cached filename search), so a
|
|
9
|
+
* single-character query would scan the whole tree for a near-useless result.
|
|
10
|
+
* Two characters is a gentle, documented floor — not an arbitrary limit.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_MIN_LENGTH = 2;
|
|
13
|
+
const EMPTY_GROUPS = [];
|
|
14
|
+
/**
|
|
15
|
+
* Behavior hook powering workspace-wide content (text) search.
|
|
16
|
+
*
|
|
17
|
+
* The text-grep sibling of
|
|
18
|
+
* {@link useWorkspaceFileSearch}: it keeps
|
|
19
|
+
* that hook's per-entry aggregation, error isolation, and generation guard, and
|
|
20
|
+
* adds the platform's canonical debounce idiom from `useResourceSearch`
|
|
21
|
+
* (`query`/`debouncedQuery` + `setTimeout`). The key difference is that the
|
|
22
|
+
* debounced query is part of the *fetch* — each keystroke hits disk via the
|
|
23
|
+
* injected {@link WorkspaceContentSearcher}, uncached — so a `minLength` guard
|
|
24
|
+
* and a debounce protect the filesystem.
|
|
25
|
+
*
|
|
26
|
+
* Prior results stay visible while a new debounced query loads (`isRefetching`
|
|
27
|
+
* true, results unchanged); only the very first search with nothing to show
|
|
28
|
+
* flips `isLoading`. This avoids a per-keystroke blank flash the cached filename
|
|
29
|
+
* search never had.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const { groups, totalMatches, isRefetching } = useWorkspaceContentSearch({
|
|
34
|
+
* entries: workspace.entries,
|
|
35
|
+
* searcher: workspaceContentSearcher,
|
|
36
|
+
* query,
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function useWorkspaceContentSearch({ entries, searcher, query, debounceMs = DEFAULT_DEBOUNCE_MS, minLength = DEFAULT_MIN_LENGTH, }) {
|
|
41
|
+
// Settled results per entry, keyed by entry id. Retained across query changes
|
|
42
|
+
// and only swapped wholesale when a new generation fully resolves — so a
|
|
43
|
+
// reload never blanks what the user is already reading.
|
|
44
|
+
const [results, setResults] = useState({});
|
|
45
|
+
const [pending, setPending] = useState(false);
|
|
46
|
+
// Debounce the query into the fetch key (the `useResourceSearch` idiom).
|
|
47
|
+
const [debouncedQuery, setDebouncedQuery] = useState(query);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const timer = setTimeout(() => setDebouncedQuery(query), debounceMs);
|
|
50
|
+
return () => clearTimeout(timer);
|
|
51
|
+
}, [query, debounceMs]);
|
|
52
|
+
// Latest entries read inside the effect without widening its dependency to the
|
|
53
|
+
// (possibly per-render) array identity — the effect keys on the id set instead.
|
|
54
|
+
const entriesRef = useRef(entries);
|
|
55
|
+
entriesRef.current = entries;
|
|
56
|
+
const entriesKey = entries.map((entry) => entry.id).join("\u0000");
|
|
57
|
+
// Ignore resolutions from a superseded run (id set, searcher, or query changed).
|
|
58
|
+
const generationRef = useRef(0);
|
|
59
|
+
const effectiveQuery = debouncedQuery.trim();
|
|
60
|
+
const belowMinLength = effectiveQuery.length < minLength;
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
// No searcher or a too-short query: clear results, nothing in flight. (An
|
|
63
|
+
// in-flight generation is abandoned via the bumped ref.)
|
|
64
|
+
if (!searcher || belowMinLength) {
|
|
65
|
+
generationRef.current += 1;
|
|
66
|
+
setResults({});
|
|
67
|
+
setPending(false);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const currentEntries = entriesRef.current;
|
|
71
|
+
const generation = ++generationRef.current;
|
|
72
|
+
setPending(true);
|
|
73
|
+
Promise.all(currentEntries.map(async (entry) => {
|
|
74
|
+
try {
|
|
75
|
+
const result = await searcher(entry, effectiveQuery);
|
|
76
|
+
if (result === null)
|
|
77
|
+
return [entry.id, { status: "unsupported" }];
|
|
78
|
+
return [
|
|
79
|
+
entry.id,
|
|
80
|
+
{ status: "ready", matches: result.matches, truncated: result.truncated },
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
return [entry.id, { status: "error", error: toError(err) }];
|
|
85
|
+
}
|
|
86
|
+
})).then((settled) => {
|
|
87
|
+
// A newer generation started while this batch was in flight — drop it so
|
|
88
|
+
// stale results never overwrite fresher ones (or clobber a cleared state).
|
|
89
|
+
if (generationRef.current !== generation)
|
|
90
|
+
return;
|
|
91
|
+
const next = {};
|
|
92
|
+
for (const [id, res] of settled)
|
|
93
|
+
next[id] = res;
|
|
94
|
+
setResults(next);
|
|
95
|
+
setPending(false);
|
|
96
|
+
});
|
|
97
|
+
}, [entriesKey, searcher, effectiveQuery, belowMinLength]);
|
|
98
|
+
return useMemo(() => {
|
|
99
|
+
if (!searcher) {
|
|
100
|
+
return {
|
|
101
|
+
groups: EMPTY_GROUPS,
|
|
102
|
+
totalMatches: 0,
|
|
103
|
+
isLoading: false,
|
|
104
|
+
isRefetching: false,
|
|
105
|
+
isUnsupported: true,
|
|
106
|
+
error: null,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const groups = [];
|
|
110
|
+
let totalMatches = 0;
|
|
111
|
+
let firstError = null;
|
|
112
|
+
let unsupportedCount = 0;
|
|
113
|
+
let settledCount = 0;
|
|
114
|
+
for (const entry of entries) {
|
|
115
|
+
const state = results[entry.id];
|
|
116
|
+
if (!state)
|
|
117
|
+
continue;
|
|
118
|
+
settledCount += 1;
|
|
119
|
+
if (state.status === "unsupported") {
|
|
120
|
+
unsupportedCount += 1;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (state.status === "error") {
|
|
124
|
+
if (!firstError)
|
|
125
|
+
firstError = state.error;
|
|
126
|
+
groups.push({ entry, matches: [], truncated: false, error: state.error });
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
totalMatches += state.matches.length;
|
|
130
|
+
// Worth showing only when it carries matches or a truncation notice.
|
|
131
|
+
if (state.matches.length > 0 || state.truncated) {
|
|
132
|
+
groups.push({
|
|
133
|
+
entry,
|
|
134
|
+
matches: state.matches,
|
|
135
|
+
truncated: state.truncated,
|
|
136
|
+
error: null,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const hasPriorResults = settledCount > 0;
|
|
141
|
+
const isUnsupported = entries.length > 0 && unsupportedCount === entries.length;
|
|
142
|
+
return {
|
|
143
|
+
groups,
|
|
144
|
+
totalMatches,
|
|
145
|
+
// First search (nothing settled yet) blanks; a reload over existing
|
|
146
|
+
// results keeps them visible and signals `isRefetching` instead.
|
|
147
|
+
isLoading: pending && !hasPriorResults,
|
|
148
|
+
isRefetching: pending && hasPriorResults,
|
|
149
|
+
isUnsupported,
|
|
150
|
+
error: firstError,
|
|
151
|
+
};
|
|
152
|
+
}, [entries, results, pending, searcher]);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=useWorkspaceContentSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWorkspaceContentSearch.js","sourceRoot":"","sources":["../../src/workspace/useWorkspaceContentSearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { WorkspaceEntry } from "./useWorkspaceEntries.js";
|
|
2
|
+
import type { WorkspaceFileContent, WorkspaceFileReader } from "./WorkspaceFileReader.js";
|
|
3
|
+
/** Options for {@link useWorkspaceFileContent}. */
|
|
4
|
+
export interface UseWorkspaceFileContentOptions {
|
|
5
|
+
/** The workspace entry that owns the file, or `null` when nothing is open. */
|
|
6
|
+
readonly entry: WorkspaceEntry | null;
|
|
7
|
+
/** Repo-relative (git) or root-relative (local) path, or `null` when nothing is open. */
|
|
8
|
+
readonly path: string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Platform-injected content reader. `undefined` when the host app injects
|
|
11
|
+
* no reader at all (e.g. web with no GitHub token) — surfaced as
|
|
12
|
+
* {@link UseWorkspaceFileContentReturn.isUnsupported}, not an error.
|
|
13
|
+
*/
|
|
14
|
+
readonly reader: WorkspaceFileReader | undefined;
|
|
15
|
+
}
|
|
16
|
+
/** Return value of {@link useWorkspaceFileContent}. */
|
|
17
|
+
export interface UseWorkspaceFileContentReturn {
|
|
18
|
+
/**
|
|
19
|
+
* The decoded file content (+ metadata), or `null` while the request is
|
|
20
|
+
* in-flight, skipped, failed, or the substrate is unsupported. A present
|
|
21
|
+
* object with `text === null` is a real file that is binary, too large, or
|
|
22
|
+
* undecodable — distinct from `isUnsupported`.
|
|
23
|
+
*/
|
|
24
|
+
readonly content: WorkspaceFileContent | null;
|
|
25
|
+
/** `true` only on the first load, before any content has arrived. */
|
|
26
|
+
readonly isLoading: boolean;
|
|
27
|
+
/** `true` while a background refetch is in flight and stale content is shown. */
|
|
28
|
+
readonly isRefetching: boolean;
|
|
29
|
+
/** Error from the last failed read (a reader throw), or `null` when healthy. */
|
|
30
|
+
readonly error: Error | null;
|
|
31
|
+
/**
|
|
32
|
+
* `true` when no reader can serve this file — either no reader was injected
|
|
33
|
+
* or the reader reported the entry's substrate as unsupported (git-on-desktop,
|
|
34
|
+
* local-on-web, missing token). This is the honest "not available here" state,
|
|
35
|
+
* never an error.
|
|
36
|
+
*/
|
|
37
|
+
readonly isUnsupported: boolean;
|
|
38
|
+
/** Imperatively re-read the current file. Stale content stays visible. */
|
|
39
|
+
readonly refetch: () => void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Behavior hook that reads a single workspace file's content on demand.
|
|
43
|
+
*
|
|
44
|
+
* The byte-reading peer of {@link useWorkspaceFiles}
|
|
45
|
+
* (which lists the tree), built on the same {@link useFetch} engine as the
|
|
46
|
+
* content-fetch family ({@link useArtifactContent},
|
|
47
|
+
* `useToolOutputContent`, `useFileChangeContent`) so it inherits their
|
|
48
|
+
* stale-while-revalidate, cancellation, and `refetch` semantics for free.
|
|
49
|
+
*
|
|
50
|
+
* Deliberately passes **no** `cacheKey`: file bodies (up to
|
|
51
|
+
* {@link MAX_WORKSPACE_FILE_READ_BYTES})
|
|
52
|
+
* do not belong in the cross-mount metadata cache, which is sized for small,
|
|
53
|
+
* hot resources. Re-opening a file re-reads it — the correct trade for a
|
|
54
|
+
* read-only viewer.
|
|
55
|
+
*
|
|
56
|
+
* Maps the reader's two failure axes onto distinct states:
|
|
57
|
+
* - reader resolves `null` (unsupported substrate) -> {@link UseWorkspaceFileContentReturn.isUnsupported}
|
|
58
|
+
* - reader **throws** (404, network, unreadable) -> {@link UseWorkspaceFileContentReturn.error}
|
|
59
|
+
*
|
|
60
|
+
* Pass `null` for `entry`/`path` (or an `undefined` reader) to stay idle —
|
|
61
|
+
* the established `useFetch` convention.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* const { content, isLoading, error, isUnsupported } = useWorkspaceFileContent({
|
|
66
|
+
* entry,
|
|
67
|
+
* path: "src/index.ts",
|
|
68
|
+
* reader: workspaceFileReader,
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function useWorkspaceFileContent({ entry, path, reader, }: UseWorkspaceFileContentOptions): UseWorkspaceFileContentReturn;
|
|
73
|
+
//# sourceMappingURL=useWorkspaceFileContent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWorkspaceFileContent.d.ts","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFileContent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAElC,mDAAmD;AACnD,MAAM,WAAW,8BAA8B;IAC7C,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAClD;AAED,uDAAuD;AACvD,MAAM,WAAW,6BAA6B;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC9C,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,IAAI,EACJ,MAAM,GACP,EAAE,8BAA8B,GAAG,6BAA6B,CA+BhE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useFetch } from "../internal/useFetch.js";
|
|
4
|
+
const EMPTY_CONTENT = { content: null };
|
|
5
|
+
/**
|
|
6
|
+
* Behavior hook that reads a single workspace file's content on demand.
|
|
7
|
+
*
|
|
8
|
+
* The byte-reading peer of {@link useWorkspaceFiles}
|
|
9
|
+
* (which lists the tree), built on the same {@link useFetch} engine as the
|
|
10
|
+
* content-fetch family ({@link useArtifactContent},
|
|
11
|
+
* `useToolOutputContent`, `useFileChangeContent`) so it inherits their
|
|
12
|
+
* stale-while-revalidate, cancellation, and `refetch` semantics for free.
|
|
13
|
+
*
|
|
14
|
+
* Deliberately passes **no** `cacheKey`: file bodies (up to
|
|
15
|
+
* {@link MAX_WORKSPACE_FILE_READ_BYTES})
|
|
16
|
+
* do not belong in the cross-mount metadata cache, which is sized for small,
|
|
17
|
+
* hot resources. Re-opening a file re-reads it — the correct trade for a
|
|
18
|
+
* read-only viewer.
|
|
19
|
+
*
|
|
20
|
+
* Maps the reader's two failure axes onto distinct states:
|
|
21
|
+
* - reader resolves `null` (unsupported substrate) -> {@link UseWorkspaceFileContentReturn.isUnsupported}
|
|
22
|
+
* - reader **throws** (404, network, unreadable) -> {@link UseWorkspaceFileContentReturn.error}
|
|
23
|
+
*
|
|
24
|
+
* Pass `null` for `entry`/`path` (or an `undefined` reader) to stay idle —
|
|
25
|
+
* the established `useFetch` convention.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* const { content, isLoading, error, isUnsupported } = useWorkspaceFileContent({
|
|
30
|
+
* entry,
|
|
31
|
+
* path: "src/index.ts",
|
|
32
|
+
* reader: workspaceFileReader,
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function useWorkspaceFileContent({ entry, path, reader, }) {
|
|
37
|
+
// The fetch runs only when a reader, an entry, and a path are all present.
|
|
38
|
+
const enabled = !!(reader && entry && path);
|
|
39
|
+
const { data, isLoading, isRefetching, error, refetch } = useFetch(enabled
|
|
40
|
+
? () => reader(entry, path).then((c) => ({ content: c }))
|
|
41
|
+
: null,
|
|
42
|
+
// Identity deps: a change to any of these is a different file to read.
|
|
43
|
+
[entry?.id ?? null, path ?? null, reader], EMPTY_CONTENT);
|
|
44
|
+
// Unsupported = no reader at all, or a completed fetch that resolved to null
|
|
45
|
+
// (the reader's "this substrate isn't mine" signal). In-flight and error
|
|
46
|
+
// states are excluded so the viewer shows loading/error, not "unavailable".
|
|
47
|
+
const isUnsupported = !reader || (enabled && !isLoading && !error && data.content === null);
|
|
48
|
+
return useMemo(() => ({
|
|
49
|
+
content: data.content,
|
|
50
|
+
isLoading,
|
|
51
|
+
isRefetching,
|
|
52
|
+
error,
|
|
53
|
+
isUnsupported,
|
|
54
|
+
refetch,
|
|
55
|
+
}), [data.content, isLoading, isRefetching, error, isUnsupported, refetch]);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=useWorkspaceFileContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWorkspaceFileContent.js","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFileContent.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAyDnD,MAAM,aAAa,GAAoB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,KAAK,EACL,IAAI,EACJ,MAAM,GACyB;IAC/B,2EAA2E;IAC3E,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC;IAE5C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GACrD,QAAQ,CACN,OAAO;QACL,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC,CAAC,IAAI;IACR,uEAAuE;IACvE,CAAC,KAAK,EAAE,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,CAAC,EACzC,aAAa,CACd,CAAC;IAEJ,6EAA6E;IAC7E,yEAAyE;IACzE,4EAA4E;IAC5E,MAAM,aAAa,GACjB,CAAC,MAAM,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;IAExE,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,SAAS;QACT,YAAY;QACZ,KAAK;QACL,aAAa;QACb,OAAO;KACR,CAAC,EACF,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,CACvE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { WorkspaceEntry } from "./useWorkspaceEntries.js";
|
|
2
|
+
import type { WorkspaceFileLister } from "./WorkspaceFileLister.js";
|
|
3
|
+
import { type WorkspaceFileMatch } from "./matchWorkspaceFiles.js";
|
|
4
|
+
/** Options for {@link useWorkspaceFileSearch}. */
|
|
5
|
+
export interface UseWorkspaceFileSearchOptions {
|
|
6
|
+
/** All workspace entries to search across. */
|
|
7
|
+
readonly entries: readonly WorkspaceEntry[];
|
|
8
|
+
/** Platform-injected file lister. `undefined` → nothing is searchable. */
|
|
9
|
+
readonly lister: WorkspaceFileLister | undefined;
|
|
10
|
+
/** Current search query. Empty/whitespace yields no matches (search shows a hint). */
|
|
11
|
+
readonly query: string;
|
|
12
|
+
}
|
|
13
|
+
/** Matches (and per-entry status) for one workspace entry. */
|
|
14
|
+
export interface WorkspaceFileSearchGroup {
|
|
15
|
+
/** The workspace entry these matches belong to. */
|
|
16
|
+
readonly entry: WorkspaceEntry;
|
|
17
|
+
/** Ranked matches within this entry, best-first. */
|
|
18
|
+
readonly matches: readonly WorkspaceFileMatch[];
|
|
19
|
+
/** `true` when this entry's listing was truncated (repository too large). */
|
|
20
|
+
readonly truncated: boolean;
|
|
21
|
+
/** Listing error for this entry, if any (isolated — other entries still resolve). */
|
|
22
|
+
readonly error: Error | null;
|
|
23
|
+
}
|
|
24
|
+
/** Return value of {@link useWorkspaceFileSearch}. */
|
|
25
|
+
export interface UseWorkspaceFileSearchReturn {
|
|
26
|
+
/** Entries with something to show (matches, an error, or a truncation notice). */
|
|
27
|
+
readonly groups: readonly WorkspaceFileSearchGroup[];
|
|
28
|
+
/** Total matches across all groups (for a "showing N of M" affordance). */
|
|
29
|
+
readonly totalMatches: number;
|
|
30
|
+
/** `true` while any entry's listing is still loading. */
|
|
31
|
+
readonly isLoading: boolean;
|
|
32
|
+
/** `true` when no substrate can be searched (no lister, or every entry unsupported). */
|
|
33
|
+
readonly isUnsupported: boolean;
|
|
34
|
+
/** First per-entry error, for a top-level fallback message. `null` when none. */
|
|
35
|
+
readonly error: Error | null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Behavior hook powering workspace-wide filename/path search.
|
|
39
|
+
*
|
|
40
|
+
* Loads each entry's listing through the shared
|
|
41
|
+
* {@link loadEntryFiles} cache (warm from
|
|
42
|
+
* Files browsing → usually free), then ranks matches per entry with the pure
|
|
43
|
+
* {@link matchWorkspaceFiles}. Fetching is keyed by the set of entry ids, so a
|
|
44
|
+
* query change re-ranks the already-loaded listings without re-fetching. Errors
|
|
45
|
+
* are isolated per entry (one failing repo never blanks the rest), and a stale
|
|
46
|
+
* generation's late resolutions are ignored.
|
|
47
|
+
*
|
|
48
|
+
* Meant to be consumed by a component mounted only while Search is active
|
|
49
|
+
* (`WorkspaceFileSearch`), so the Files view incurs no search fetching.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```tsx
|
|
53
|
+
* const { groups, totalMatches, isLoading } = useWorkspaceFileSearch({
|
|
54
|
+
* entries: workspace.entries,
|
|
55
|
+
* lister: workspaceFileLister,
|
|
56
|
+
* query,
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function useWorkspaceFileSearch({ entries, lister, query, }: UseWorkspaceFileSearchOptions): UseWorkspaceFileSearchReturn;
|
|
61
|
+
//# sourceMappingURL=useWorkspaceFileSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWorkspaceFileSearch.d.ts","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFileSearch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAExF,kDAAkD;AAClD,MAAM,WAAW,6BAA6B;IAC5C,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACjD,sFAAsF;IACtF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,8DAA8D;AAC9D,MAAM,WAAW,wBAAwB;IACvC,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAChD,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,qFAAqF;IACrF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAED,sDAAsD;AACtD,MAAM,WAAW,4BAA4B;IAC3C,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACrD,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAWD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,MAAM,EACN,KAAK,GACN,EAAE,6BAA6B,GAAG,4BAA4B,CAsG9D"}
|