@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,183 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { renderHook } from "@testing-library/react";
|
|
3
|
+
import { useGitHubFileReader } from "../useGitHubFileReader";
|
|
4
|
+
import type { WorkspaceEntry } from "../../workspace/useWorkspaceEntries";
|
|
5
|
+
|
|
6
|
+
function gitEntry(overrides?: Partial<WorkspaceEntry>): WorkspaceEntry {
|
|
7
|
+
return {
|
|
8
|
+
id: "ws-1",
|
|
9
|
+
name: "acme/api",
|
|
10
|
+
type: "git",
|
|
11
|
+
gitUrl: "https://github.com/acme/api",
|
|
12
|
+
gitBranch: "main",
|
|
13
|
+
...overrides,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function localEntry(): WorkspaceEntry {
|
|
18
|
+
return {
|
|
19
|
+
id: "ws-2",
|
|
20
|
+
name: "/Users/dev/project",
|
|
21
|
+
type: "local",
|
|
22
|
+
localPath: "/Users/dev/project",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function b64(s: string): string {
|
|
27
|
+
return Buffer.from(s, "utf-8").toString("base64");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function jsonResponse(body: unknown, status = 200): Response {
|
|
31
|
+
return new Response(JSON.stringify(body), { status });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("useGitHubFileReader", () => {
|
|
35
|
+
const originalFetch = globalThis.fetch;
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
globalThis.fetch = vi.fn();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
globalThis.fetch = originalFetch;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("returns undefined when token is null", () => {
|
|
46
|
+
const { result } = renderHook(() => useGitHubFileReader(null));
|
|
47
|
+
expect(result.current).toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("returns a reader function when a token is provided", () => {
|
|
51
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
52
|
+
expect(typeof result.current).toBe("function");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("returns null for non-git entries without fetching", async () => {
|
|
56
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
57
|
+
const content = await result.current!(localEntry(), "src/index.ts");
|
|
58
|
+
expect(content).toBeNull();
|
|
59
|
+
expect(globalThis.fetch).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("returns null for non-GitHub git URLs", async () => {
|
|
63
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
64
|
+
const content = await result.current!(
|
|
65
|
+
gitEntry({ gitUrl: "https://gitlab.com/acme/api" }),
|
|
66
|
+
"src/index.ts",
|
|
67
|
+
);
|
|
68
|
+
expect(content).toBeNull();
|
|
69
|
+
expect(globalThis.fetch).not.toHaveBeenCalled();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("decodes a base64 text file from the Contents API", async () => {
|
|
73
|
+
vi.mocked(globalThis.fetch).mockResolvedValue(
|
|
74
|
+
jsonResponse({ encoding: "base64", size: 12, content: b64("Hello World!"), sha: "s1" }),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
78
|
+
const content = await result.current!(gitEntry(), "src/index.ts");
|
|
79
|
+
|
|
80
|
+
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
81
|
+
"https://api.github.com/repos/acme/api/contents/src/index.ts?ref=main",
|
|
82
|
+
{ headers: { Authorization: "Bearer ghp_abc" } },
|
|
83
|
+
);
|
|
84
|
+
expect(content).toEqual({
|
|
85
|
+
text: "Hello World!",
|
|
86
|
+
isBinary: false,
|
|
87
|
+
size: 12,
|
|
88
|
+
encoding: "utf-8",
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("encodes the path per segment and the branch", async () => {
|
|
93
|
+
vi.mocked(globalThis.fetch).mockResolvedValue(
|
|
94
|
+
jsonResponse({ encoding: "base64", size: 1, content: b64("x"), sha: "s1" }),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
98
|
+
await result.current!(
|
|
99
|
+
gitEntry({ gitBranch: "feat/my branch" }),
|
|
100
|
+
"src/a b/c#d.ts",
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
104
|
+
"https://api.github.com/repos/acme/api/contents/src/a%20b/c%23d.ts?ref=feat%2Fmy%20branch",
|
|
105
|
+
expect.anything(),
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("defaults to the main branch when gitBranch is undefined", async () => {
|
|
110
|
+
vi.mocked(globalThis.fetch).mockResolvedValue(
|
|
111
|
+
jsonResponse({ encoding: "base64", size: 1, content: b64("x"), sha: "s1" }),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
115
|
+
await result.current!(gitEntry({ gitBranch: undefined }), "f.ts");
|
|
116
|
+
|
|
117
|
+
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
118
|
+
expect.stringContaining("?ref=main"),
|
|
119
|
+
expect.anything(),
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("throws on a non-OK response (404 = failed to load, not unsupported)", async () => {
|
|
124
|
+
vi.mocked(globalThis.fetch).mockResolvedValue(new Response("nope", { status: 404 }));
|
|
125
|
+
|
|
126
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
127
|
+
await expect(result.current!(gitEntry(), "missing.ts")).rejects.toThrow("HTTP 404");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("throws when the path is a directory (Contents API returns an array)", async () => {
|
|
131
|
+
vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([{ name: "index.ts" }]));
|
|
132
|
+
|
|
133
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
134
|
+
await expect(result.current!(gitEntry(), "src")).rejects.toThrow("is a directory");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("falls back to the Blob API when Contents returns encoding:none", async () => {
|
|
138
|
+
const big = "x".repeat(2_000_000); // > 1 MB, ≤ 10 MB ceiling
|
|
139
|
+
vi.mocked(globalThis.fetch)
|
|
140
|
+
.mockResolvedValueOnce(
|
|
141
|
+
jsonResponse({ encoding: "none", size: big.length, content: "", sha: "blobsha" }),
|
|
142
|
+
)
|
|
143
|
+
.mockResolvedValueOnce(
|
|
144
|
+
jsonResponse({ encoding: "base64", size: big.length, content: b64(big) }),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
148
|
+
const content = await result.current!(gitEntry(), "big.txt");
|
|
149
|
+
|
|
150
|
+
expect(vi.mocked(globalThis.fetch).mock.calls[1][0]).toBe(
|
|
151
|
+
"https://api.github.com/repos/acme/api/git/blobs/blobsha",
|
|
152
|
+
);
|
|
153
|
+
expect(content!.size).toBe(big.length);
|
|
154
|
+
expect(content!.truncated).toBe(true);
|
|
155
|
+
expect(content!.text).toHaveLength(1_048_576);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("reports files above the blob ceiling as too-large without downloading", async () => {
|
|
159
|
+
const hugeSize = 50 * 1024 * 1024; // 50 MB > 10 MB ceiling
|
|
160
|
+
vi.mocked(globalThis.fetch).mockResolvedValue(
|
|
161
|
+
jsonResponse({ encoding: "none", size: hugeSize, content: "", sha: "blobsha" }),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
165
|
+
const content = await result.current!(gitEntry(), "huge.bin");
|
|
166
|
+
|
|
167
|
+
expect(globalThis.fetch).toHaveBeenCalledTimes(1); // no blob download
|
|
168
|
+
expect(content).toEqual({
|
|
169
|
+
text: null,
|
|
170
|
+
isBinary: false,
|
|
171
|
+
size: hugeSize,
|
|
172
|
+
encoding: "none",
|
|
173
|
+
truncated: true,
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("returns a stable reader reference across renders", () => {
|
|
178
|
+
const { result, rerender } = renderHook(() => useGitHubFileReader("ghp_abc"));
|
|
179
|
+
const first = result.current;
|
|
180
|
+
rerender();
|
|
181
|
+
expect(result.current).toBe(first);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Pure byte/text decode helpers for the GitHub file reader.
|
|
2
|
+
// Kept free of React and fetch so the Slice 0 spike behavior (base64 decode,
|
|
3
|
+
// binary detection, the 1 MB cap) is unit-testable in isolation.
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
MAX_WORKSPACE_FILE_READ_BYTES,
|
|
7
|
+
type WorkspaceFileContent,
|
|
8
|
+
} from "../workspace/WorkspaceFileReader.js";
|
|
9
|
+
|
|
10
|
+
// Scan only the head for a NUL byte — git uses the first 8000 bytes as its
|
|
11
|
+
// text/binary heuristic, and scanning the whole buffer buys nothing.
|
|
12
|
+
const BINARY_SNIFF_BYTES = 8000;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Decode a GitHub base64 payload to raw bytes.
|
|
16
|
+
*
|
|
17
|
+
* GitHub's Contents API line-wraps its base64 with `\n` every 60 chars, and
|
|
18
|
+
* `atob` rejects embedded newlines in some engines — strip all ASCII
|
|
19
|
+
* whitespace first.
|
|
20
|
+
*/
|
|
21
|
+
export function base64ToBytes(b64: string): Uint8Array {
|
|
22
|
+
const clean = b64.replace(/\s/g, "");
|
|
23
|
+
const binary = atob(clean);
|
|
24
|
+
return Uint8Array.from(binary, (ch) => ch.charCodeAt(0));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Detect binary content via a NUL byte in the head of the buffer. */
|
|
28
|
+
export function detectBinary(bytes: Uint8Array): boolean {
|
|
29
|
+
const limit = Math.min(bytes.length, BINARY_SNIFF_BYTES);
|
|
30
|
+
for (let i = 0; i < limit; i++) {
|
|
31
|
+
if (bytes[i] === 0) return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Decode bytes as strict UTF-8, returning `null` when the sequence is invalid.
|
|
38
|
+
* `{ fatal: true }` makes `TextDecoder` throw rather than emit replacement
|
|
39
|
+
* characters, so undecodable files degrade to the binary/unknown fallback
|
|
40
|
+
* instead of silently rendering mojibake.
|
|
41
|
+
*/
|
|
42
|
+
export function bytesToText(bytes: Uint8Array): string | null {
|
|
43
|
+
try {
|
|
44
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Turn decoded bytes into a {@link WorkspaceFileContent}, applying binary
|
|
52
|
+
* detection and the shared 1 MB display cap.
|
|
53
|
+
*
|
|
54
|
+
* @param bytes the full decoded bytes as delivered by GitHub
|
|
55
|
+
* @param fullSize the file's true size in bytes (GitHub's `size` field), which
|
|
56
|
+
* may exceed `bytes.length` when the caller has already capped
|
|
57
|
+
* the download — reported verbatim as `size`.
|
|
58
|
+
*/
|
|
59
|
+
export function normalizeGitHubContent(
|
|
60
|
+
bytes: Uint8Array,
|
|
61
|
+
fullSize: number,
|
|
62
|
+
): WorkspaceFileContent {
|
|
63
|
+
if (detectBinary(bytes)) {
|
|
64
|
+
return { text: null, isBinary: true, size: fullSize, encoding: "base64" };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Decode the full buffer, then cap the resulting *string* — capping the bytes
|
|
68
|
+
// first could split a multibyte char at the boundary and make the fatal
|
|
69
|
+
// decoder reject an otherwise-valid file.
|
|
70
|
+
const text = bytesToText(bytes);
|
|
71
|
+
if (text === null) {
|
|
72
|
+
return { text: null, isBinary: false, size: fullSize, encoding: "unknown" };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const truncated = bytes.length > MAX_WORKSPACE_FILE_READ_BYTES;
|
|
76
|
+
return {
|
|
77
|
+
text: truncated ? text.slice(0, MAX_WORKSPACE_FILE_READ_BYTES) : text,
|
|
78
|
+
isBinary: false,
|
|
79
|
+
size: fullSize,
|
|
80
|
+
encoding: "utf-8",
|
|
81
|
+
...(truncated ? { truncated: true } : {}),
|
|
82
|
+
};
|
|
83
|
+
}
|
package/src/github/index.ts
CHANGED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
import type { WorkspaceEntry } from "../workspace/useWorkspaceEntries.js";
|
|
5
|
+
import type {
|
|
6
|
+
WorkspaceFileContent,
|
|
7
|
+
WorkspaceFileReader,
|
|
8
|
+
} from "../workspace/WorkspaceFileReader.js";
|
|
9
|
+
import { base64ToBytes, normalizeGitHubContent } from "./decodeGitHubContent.js";
|
|
10
|
+
import { parseGitUrl } from "./parseGitUrl.js";
|
|
11
|
+
|
|
12
|
+
const GITHUB_API = "https://api.github.com/repos";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Upper bound on files we will pull through the Blob API (Gate 1, Option B).
|
|
16
|
+
*
|
|
17
|
+
* The Contents API caps at ~1 MB and signals larger files with
|
|
18
|
+
* `encoding: "none"`; the Blob API then serves them in full (up to GitHub's own
|
|
19
|
+
* ~100 MB blob limit). Since we only ever display the first ~1 MB, downloading
|
|
20
|
+
* a 90 MB blob to show 1 MB is wasteful — so above this ceiling we report the
|
|
21
|
+
* file as too-large
|
|
22
|
+
* (`text: null`, `truncated: true`) using the size GitHub already told us,
|
|
23
|
+
* without downloading anything.
|
|
24
|
+
*/
|
|
25
|
+
const BLOB_FETCH_CEILING_BYTES = 10 * 1024 * 1024; // 10 MiB
|
|
26
|
+
|
|
27
|
+
/** Single-file shape of `GET /repos/{o}/{r}/contents/{path}`. */
|
|
28
|
+
interface GitHubContentsFile {
|
|
29
|
+
readonly encoding: "base64" | "none";
|
|
30
|
+
readonly size: number;
|
|
31
|
+
readonly content: string;
|
|
32
|
+
readonly sha: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Shape of `GET /repos/{o}/{r}/git/blobs/{sha}`. */
|
|
36
|
+
interface GitHubBlob {
|
|
37
|
+
readonly encoding: "base64";
|
|
38
|
+
readonly size: number;
|
|
39
|
+
readonly content: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Encode a repo-relative path per segment, preserving the slashes. */
|
|
43
|
+
function encodePath(path: string): string {
|
|
44
|
+
return path.split("/").map(encodeURIComponent).join("/");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Creates a {@link WorkspaceFileReader} backed by the GitHub Contents API,
|
|
49
|
+
* with a Blob-API fallback for files above the Contents 1 MB cap.
|
|
50
|
+
*
|
|
51
|
+
* Uses the same client-side OAuth token as {@link useGitHubTreeLister}
|
|
52
|
+
* (`Authorization: Bearer`), inheriting its private-repo scope. Returns
|
|
53
|
+
* `undefined` when no token is present, mirroring the tree lister so callers
|
|
54
|
+
* can treat "no reader" and "no lister" identically.
|
|
55
|
+
*
|
|
56
|
+
* The reader itself:
|
|
57
|
+
* - Returns `null` when the entry is not a readable GitHub git repo
|
|
58
|
+
* (non-git entry, missing/unparseable URL) — the "unsupported here" state.
|
|
59
|
+
* - **Throws** on a real failure: a non-OK response, or a directory path
|
|
60
|
+
* (which the Contents API returns as a JSON array). Consumers surface these
|
|
61
|
+
* as an error, distinct from the null "unsupported" state.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* const gitHubConnection = useGitHubConnection(org);
|
|
66
|
+
* const fileReader = useGitHubFileReader(gitHubConnection.token);
|
|
67
|
+
* <SessionViewer workspaceFileReader={fileReader} />
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function useGitHubFileReader(
|
|
71
|
+
token: string | null,
|
|
72
|
+
): WorkspaceFileReader | undefined {
|
|
73
|
+
const reader = useCallback(
|
|
74
|
+
async (
|
|
75
|
+
entry: WorkspaceEntry,
|
|
76
|
+
path: string,
|
|
77
|
+
): Promise<WorkspaceFileContent | null> => {
|
|
78
|
+
if (entry.type !== "git" || !entry.gitUrl || !token) return null;
|
|
79
|
+
|
|
80
|
+
const parsed = parseGitUrl(entry.gitUrl);
|
|
81
|
+
if (!parsed) return null;
|
|
82
|
+
|
|
83
|
+
const branch = entry.gitBranch || "main";
|
|
84
|
+
const url =
|
|
85
|
+
`${GITHUB_API}/${parsed.owner}/${parsed.repo}/contents/${encodePath(path)}` +
|
|
86
|
+
`?ref=${encodeURIComponent(branch)}`;
|
|
87
|
+
|
|
88
|
+
const resp = await fetch(url, {
|
|
89
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
90
|
+
});
|
|
91
|
+
if (!resp.ok) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`GitHub content fetch failed for ${path} (HTTP ${resp.status})`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const data: unknown = await resp.json();
|
|
98
|
+
// The Contents API returns an array for a directory — a misdirected read,
|
|
99
|
+
// not an unsupported substrate, so fail loudly rather than return null.
|
|
100
|
+
if (Array.isArray(data)) {
|
|
101
|
+
throw new Error(`Cannot read "${path}": path is a directory`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const file = data as GitHubContentsFile;
|
|
105
|
+
if (file.encoding === "base64") {
|
|
106
|
+
return normalizeGitHubContent(base64ToBytes(file.content), file.size);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// encoding: "none" is GitHub's signal that the file exceeds the Contents
|
|
110
|
+
// API's ~1 MB cap; the bytes live only behind the Blob API.
|
|
111
|
+
return readViaBlob(parsed, file, token);
|
|
112
|
+
},
|
|
113
|
+
[token],
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (!token) return undefined;
|
|
117
|
+
return reader;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Gate 1 / Option B — size-gated blob fetch for files the Contents API refused
|
|
122
|
+
* (`encoding: "none"`). Isolated so the large-file policy can change without
|
|
123
|
+
* touching the reader's control flow.
|
|
124
|
+
*/
|
|
125
|
+
async function readViaBlob(
|
|
126
|
+
parsed: { owner: string; repo: string },
|
|
127
|
+
file: GitHubContentsFile,
|
|
128
|
+
token: string,
|
|
129
|
+
): Promise<WorkspaceFileContent> {
|
|
130
|
+
// Above the ceiling we never download — GitHub already told us the size, so
|
|
131
|
+
// report it as too-large-to-preview without spending the bandwidth.
|
|
132
|
+
if (file.size > BLOB_FETCH_CEILING_BYTES) {
|
|
133
|
+
return {
|
|
134
|
+
text: null,
|
|
135
|
+
isBinary: false,
|
|
136
|
+
size: file.size,
|
|
137
|
+
encoding: "none",
|
|
138
|
+
truncated: true,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const url = `${GITHUB_API}/${parsed.owner}/${parsed.repo}/git/blobs/${file.sha}`;
|
|
143
|
+
const resp = await fetch(url, {
|
|
144
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
145
|
+
});
|
|
146
|
+
if (!resp.ok) {
|
|
147
|
+
throw new Error(`GitHub blob fetch failed for ${file.sha} (HTTP ${resp.status})`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const blob: GitHubBlob = await resp.json();
|
|
151
|
+
return normalizeGitHubContent(base64ToBytes(blob.content), blob.size);
|
|
152
|
+
}
|
|
@@ -22,12 +22,16 @@ interface GitHubTreeResponse {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* Advisory entry appended to the listing when the GitHub API indicates that the
|
|
26
|
+
* tree was truncated (repository exceeds the API's entry limit). Flagged with
|
|
27
|
+
* `notice: true` so generic consumers treat it as a "results incomplete" banner
|
|
28
|
+
* rather than an openable file (see `workspaceListingCache`) — never a tree leaf,
|
|
29
|
+
* never a search hit.
|
|
27
30
|
*/
|
|
28
31
|
const TRUNCATION_MARKER: WorkspaceFileEntry = {
|
|
29
32
|
path: "... (tree truncated by GitHub — repository has too many files)",
|
|
30
33
|
isDirectory: false,
|
|
34
|
+
notice: true,
|
|
31
35
|
};
|
|
32
36
|
|
|
33
37
|
/**
|
package/src/index.ts
CHANGED
|
@@ -66,23 +66,58 @@ export type {
|
|
|
66
66
|
export {
|
|
67
67
|
useWorkspaceEntries,
|
|
68
68
|
useWorkspaceFiles,
|
|
69
|
+
useWorkspaceFileContent,
|
|
70
|
+
useWorkspaceFileSearch,
|
|
71
|
+
useWorkspaceContentSearch,
|
|
69
72
|
useWorkspaceSources,
|
|
73
|
+
MAX_WORKSPACE_FILE_READ_BYTES,
|
|
70
74
|
WorkspaceEditor,
|
|
71
|
-
|
|
75
|
+
WorkspaceFileSearch,
|
|
76
|
+
WorkspaceContentSearch,
|
|
72
77
|
WorkspaceSummary,
|
|
78
|
+
FileViewer,
|
|
79
|
+
WorkspaceSurface,
|
|
80
|
+
ExplorerTree,
|
|
81
|
+
virtualEntryId,
|
|
82
|
+
isVirtualEntryId,
|
|
73
83
|
} from "./workspace/index.js";
|
|
74
84
|
export type {
|
|
75
85
|
WorkspaceEntry,
|
|
76
86
|
WorkspaceFileEntry,
|
|
77
87
|
WorkspaceFileLister,
|
|
88
|
+
WorkspaceFileContent,
|
|
89
|
+
WorkspaceFileReader,
|
|
78
90
|
UseWorkspaceEntriesReturn,
|
|
79
91
|
UseWorkspaceFilesOptions,
|
|
80
92
|
UseWorkspaceFilesReturn,
|
|
81
|
-
|
|
93
|
+
UseWorkspaceFileContentOptions,
|
|
94
|
+
UseWorkspaceFileContentReturn,
|
|
95
|
+
UseWorkspaceFileSearchOptions,
|
|
96
|
+
UseWorkspaceFileSearchReturn,
|
|
97
|
+
WorkspaceFileSearchGroup,
|
|
98
|
+
WorkspaceFileMatch,
|
|
99
|
+
WorkspaceFileSearchProps,
|
|
100
|
+
WorkspaceContentMatch,
|
|
101
|
+
WorkspaceContentSearchResult,
|
|
102
|
+
WorkspaceContentSearcher,
|
|
103
|
+
UseWorkspaceContentSearchOptions,
|
|
104
|
+
UseWorkspaceContentSearchReturn,
|
|
105
|
+
WorkspaceContentSearchGroup,
|
|
106
|
+
WorkspaceContentSearchProps,
|
|
107
|
+
FileViewerProps,
|
|
108
|
+
FileViewerHandle,
|
|
109
|
+
SelectedWorkspaceFile,
|
|
82
110
|
UseWorkspaceSourcesOptions,
|
|
83
111
|
UseWorkspaceSourcesReturn,
|
|
84
112
|
WorkspaceEditorProps,
|
|
85
113
|
WorkspaceSummaryProps,
|
|
114
|
+
WorkspaceSurfaceProps,
|
|
115
|
+
SurfaceRailView,
|
|
116
|
+
SurfaceVirtualDocument,
|
|
117
|
+
ExplorerTreeProps,
|
|
118
|
+
OpenEditor,
|
|
119
|
+
OpenFileOptions,
|
|
120
|
+
RevealTarget,
|
|
86
121
|
} from "./workspace/index.js";
|
|
87
122
|
|
|
88
123
|
// Session — data hooks, behavior hooks, utilities (Session aggregate + conversation lifecycle)
|
|
@@ -112,9 +147,13 @@ export {
|
|
|
112
147
|
resolvedSubject,
|
|
113
148
|
SessionViewer,
|
|
114
149
|
NewSessionViewer,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
150
|
+
useSessionPanel,
|
|
151
|
+
usePlanDraft,
|
|
152
|
+
planDraftKey,
|
|
153
|
+
PlanEditor,
|
|
154
|
+
PlanStreamingDocument,
|
|
155
|
+
PLAN_DOCUMENT_ENTRY_ID,
|
|
156
|
+
PLAN_DOCUMENT_PATH,
|
|
118
157
|
SetupTab,
|
|
119
158
|
} from "./session/index.js";
|
|
120
159
|
export type {
|
|
@@ -152,13 +191,14 @@ export type {
|
|
|
152
191
|
SearchResultGroup,
|
|
153
192
|
SessionViewerProps,
|
|
154
193
|
NewSessionViewerProps,
|
|
194
|
+
SessionPanelController,
|
|
195
|
+
UseSessionPanelOptions,
|
|
196
|
+
PlanDraftController,
|
|
197
|
+
PlanEditorProps,
|
|
198
|
+
PlanStreamingDocumentProps,
|
|
155
199
|
ExecutionTargetOption,
|
|
156
200
|
RuntimeEnvProvider,
|
|
157
201
|
SessionAudience,
|
|
158
|
-
SessionInspectorProps,
|
|
159
|
-
SessionInspectorTabId,
|
|
160
|
-
UseSessionInspectorOptions,
|
|
161
|
-
UseSessionInspectorReturn,
|
|
162
202
|
SetupTabProps,
|
|
163
203
|
SetupTabMutationCallbacks,
|
|
164
204
|
SelectedThreadItem,
|
|
@@ -208,6 +248,9 @@ export {
|
|
|
208
248
|
SummarizationBadge,
|
|
209
249
|
SummarizationCard,
|
|
210
250
|
PlanCompletionCard,
|
|
251
|
+
PlanArtifactCard,
|
|
252
|
+
PlanStreamingCard,
|
|
253
|
+
PlanDocumentMessage,
|
|
211
254
|
useContextWindow,
|
|
212
255
|
formatCost,
|
|
213
256
|
formatTokenCount,
|
|
@@ -224,6 +267,7 @@ export {
|
|
|
224
267
|
resolveToolCategoryFromKind,
|
|
225
268
|
toolKindToCategoryInfo,
|
|
226
269
|
defaultDisclosureForCategory,
|
|
270
|
+
extractPrimaryArg,
|
|
227
271
|
McpToolDetail,
|
|
228
272
|
parseMcpResult,
|
|
229
273
|
formatDuration,
|
|
@@ -239,6 +283,7 @@ export {
|
|
|
239
283
|
ApprovalCardBody,
|
|
240
284
|
FileReviewCard,
|
|
241
285
|
FileReviewDock,
|
|
286
|
+
FileChangeProgressBar,
|
|
242
287
|
ApprovalContext,
|
|
243
288
|
useApproval,
|
|
244
289
|
FileReviewContext,
|
|
@@ -263,6 +308,7 @@ export {
|
|
|
263
308
|
useArtifactContent,
|
|
264
309
|
useArtifactDownloadUrl,
|
|
265
310
|
useArtifactDownload,
|
|
311
|
+
useArtifactCopy,
|
|
266
312
|
useToolOutputContent,
|
|
267
313
|
useFileChangeContent,
|
|
268
314
|
execIdFromStorageKey,
|
|
@@ -302,6 +348,9 @@ export type {
|
|
|
302
348
|
SummarizationBadgeProps,
|
|
303
349
|
SummarizationCardProps,
|
|
304
350
|
PlanCompletionCardProps,
|
|
351
|
+
PlanArtifactCardProps,
|
|
352
|
+
PlanStreamingCardProps,
|
|
353
|
+
PlanDocumentMessageProps,
|
|
305
354
|
ContextHealth,
|
|
306
355
|
SummarizationEventView,
|
|
307
356
|
UseContextWindowReturn,
|
|
@@ -320,6 +369,7 @@ export type {
|
|
|
320
369
|
SubAgentSectionProps,
|
|
321
370
|
MessageEntryProps,
|
|
322
371
|
MessageThreadProps,
|
|
372
|
+
ThreadContentColumn,
|
|
323
373
|
ThreadSkeletonProps,
|
|
324
374
|
FollowUpInputProps,
|
|
325
375
|
ApprovalCardProps,
|
|
@@ -327,6 +377,7 @@ export type {
|
|
|
327
377
|
ApprovalCardBodyProps,
|
|
328
378
|
FileReviewCardProps,
|
|
329
379
|
FileReviewDockProps,
|
|
380
|
+
FileChangeProgressBarProps,
|
|
330
381
|
ApprovalContextValue,
|
|
331
382
|
UseApprovalResult,
|
|
332
383
|
FileReviewContextValue,
|
|
@@ -349,6 +400,7 @@ export type {
|
|
|
349
400
|
UseArtifactDownloadUrlReturn,
|
|
350
401
|
UseArtifactDownloadUrlOptions,
|
|
351
402
|
UseArtifactDownloadReturn,
|
|
403
|
+
UseArtifactCopyReturn,
|
|
352
404
|
UseToolOutputContentReturn,
|
|
353
405
|
ToolOutputRefLike,
|
|
354
406
|
UseFileChangeContentReturn,
|
|
@@ -519,6 +571,7 @@ export {
|
|
|
519
571
|
useGitHubRepos,
|
|
520
572
|
useGitHubSearch,
|
|
521
573
|
useGitHubTreeLister,
|
|
574
|
+
useGitHubFileReader,
|
|
522
575
|
parseGitUrl,
|
|
523
576
|
GitHubRepoPicker,
|
|
524
577
|
GITHUB_CALLBACK_MESSAGE_TYPE,
|
|
@@ -931,7 +984,12 @@ export {
|
|
|
931
984
|
detectSkillPackage,
|
|
932
985
|
useDetectSkillPackage,
|
|
933
986
|
isPlanArtifact,
|
|
987
|
+
isPlanArtifactName,
|
|
934
988
|
findPlanArtifact,
|
|
989
|
+
findLatestSessionPlan,
|
|
990
|
+
findStreamingPlan,
|
|
991
|
+
PLAN_ARTIFACT_NAME,
|
|
992
|
+
PLAN_ARTIFACT_SUFFIX,
|
|
935
993
|
parseResourceYaml,
|
|
936
994
|
serializeAgentYaml,
|
|
937
995
|
serializeMcpServerYaml,
|
|
@@ -954,6 +1012,8 @@ export type {
|
|
|
954
1012
|
StigmerResourceKind,
|
|
955
1013
|
StigmerResourceDetection,
|
|
956
1014
|
SkillPackageDetection,
|
|
1015
|
+
SessionPlan,
|
|
1016
|
+
StreamingPlan,
|
|
957
1017
|
UseDetectSkillPackageReturn,
|
|
958
1018
|
ParsedResource,
|
|
959
1019
|
UseApplyResourceReturn,
|