@stigmer/react 3.1.1 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/composer/SessionComposer.d.ts +24 -1
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +19 -8
- package/composer/SessionComposer.js.map +1 -1
- package/execution/ArtifactContentRenderer.d.ts +11 -1
- package/execution/ArtifactContentRenderer.d.ts.map +1 -1
- package/execution/ArtifactContentRenderer.js +39 -15
- package/execution/ArtifactContentRenderer.js.map +1 -1
- package/execution/FilePathContext.d.ts +8 -1
- package/execution/FilePathContext.d.ts.map +1 -1
- package/execution/FilePathContext.js.map +1 -1
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +21 -6
- package/execution/FilePathLink.js.map +1 -1
- package/execution/MessageEntry.d.ts +29 -0
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +29 -5
- package/execution/MessageEntry.js.map +1 -1
- package/execution/MessageThread.d.ts +76 -13
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +178 -24
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts +27 -18
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +13 -23
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/PlanDocumentMessage.d.ts +32 -0
- package/execution/PlanDocumentMessage.d.ts.map +1 -0
- package/execution/PlanDocumentMessage.js +37 -0
- package/execution/PlanDocumentMessage.js.map +1 -0
- package/execution/PlanStreamingCard.d.ts +45 -0
- package/execution/PlanStreamingCard.d.ts.map +1 -0
- package/execution/PlanStreamingCard.js +35 -0
- package/execution/PlanStreamingCard.js.map +1 -0
- package/execution/index.d.ts +5 -1
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +2 -0
- package/execution/index.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +10 -0
- package/execution/useCreateAgentExecution.d.ts.map +1 -1
- package/execution/useCreateAgentExecution.js +5 -1
- package/execution/useCreateAgentExecution.js.map +1 -1
- package/github/decodeGitHubContent.d.ts +29 -0
- package/github/decodeGitHubContent.d.ts.map +1 -0
- package/github/decodeGitHubContent.js +72 -0
- package/github/decodeGitHubContent.js.map +1 -0
- package/github/index.d.ts +1 -0
- package/github/index.d.ts.map +1 -1
- package/github/index.js +1 -0
- package/github/index.js.map +1 -1
- package/github/useGitHubFileReader.d.ts +26 -0
- package/github/useGitHubFileReader.d.ts.map +1 -0
- package/github/useGitHubFileReader.js +106 -0
- package/github/useGitHubFileReader.js.map +1 -0
- package/github/useGitHubTreeLister.d.ts.map +1 -1
- package/github/useGitHubTreeLister.js +6 -2
- package/github/useGitHubTreeLister.js.map +1 -1
- package/index.d.ts +9 -9
- package/index.d.ts.map +1 -1
- package/index.js +5 -5
- package/index.js.map +1 -1
- package/internal/ResizableSplit.d.ts +72 -22
- package/internal/ResizableSplit.d.ts.map +1 -1
- package/internal/ResizableSplit.js +96 -38
- package/internal/ResizableSplit.js.map +1 -1
- package/internal/VirtualizedThread.d.ts +5 -3
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +6 -4
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/file-icons/index.d.ts +17 -0
- package/internal/file-icons/index.d.ts.map +1 -0
- package/internal/file-icons/index.js +60 -0
- package/internal/file-icons/index.js.map +1 -0
- package/internal/file-tree/FileTreeNode.d.ts +18 -1
- package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
- package/internal/file-tree/FileTreeNode.js +11 -2
- package/internal/file-tree/FileTreeNode.js.map +1 -1
- package/internal/markdown-components.d.ts +38 -1
- package/internal/markdown-components.d.ts.map +1 -1
- package/internal/markdown-components.js +86 -11
- package/internal/markdown-components.js.map +1 -1
- package/{workflow → internal}/motion-preference.d.ts +7 -4
- package/internal/motion-preference.d.ts.map +1 -0
- package/{workflow → internal}/motion-preference.js +7 -4
- package/internal/motion-preference.js.map +1 -0
- package/internal/store/index.d.ts +33 -0
- package/internal/store/index.d.ts.map +1 -1
- package/internal/store/index.js +59 -0
- package/internal/store/index.js.map +1 -1
- package/internal/store/workspace-editors-store.d.ts +145 -0
- package/internal/store/workspace-editors-store.d.ts.map +1 -0
- package/internal/store/workspace-editors-store.js +208 -0
- package/internal/store/workspace-editors-store.js.map +1 -0
- package/internal/store/workspace-file-selection-store.d.ts +38 -0
- package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
- package/internal/store/workspace-file-selection-store.js +62 -0
- package/internal/store/workspace-file-selection-store.js.map +1 -0
- package/internal/useRevealLine.d.ts +49 -0
- package/internal/useRevealLine.d.ts.map +1 -0
- package/internal/useRevealLine.js +43 -0
- package/internal/useRevealLine.js.map +1 -0
- package/library/detect-plan-artifact.d.ts +21 -0
- package/library/detect-plan-artifact.d.ts.map +1 -1
- package/library/detect-plan-artifact.js +20 -0
- package/library/detect-plan-artifact.js.map +1 -1
- package/library/detect-streaming-plan.d.ts +45 -0
- package/library/detect-streaming-plan.d.ts.map +1 -0
- package/library/detect-streaming-plan.js +83 -0
- package/library/detect-streaming-plan.js.map +1 -0
- package/library/index.d.ts +4 -1
- package/library/index.d.ts.map +1 -1
- package/library/index.js +2 -1
- package/library/index.js.map +1 -1
- package/package.json +4 -4
- package/session/NewSessionViewer.d.ts +19 -4
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +52 -25
- package/session/NewSessionViewer.js.map +1 -1
- package/session/PlanEditor.d.ts +55 -0
- package/session/PlanEditor.d.ts.map +1 -0
- package/session/PlanEditor.js +88 -0
- package/session/PlanEditor.js.map +1 -0
- package/session/PlanStreamingDocument.d.ts +30 -0
- package/session/PlanStreamingDocument.d.ts.map +1 -0
- package/session/PlanStreamingDocument.js +37 -0
- package/session/PlanStreamingDocument.js.map +1 -0
- package/session/SessionPanelChip.d.ts +26 -0
- package/session/SessionPanelChip.d.ts.map +1 -0
- package/session/SessionPanelChip.js +40 -0
- package/session/SessionPanelChip.js.map +1 -0
- package/session/SessionViewer.d.ts +34 -7
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +315 -33
- package/session/SessionViewer.js.map +1 -1
- package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
- package/session/facets/ArtifactsTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ArtifactsTab.js +8 -3
- package/session/facets/ArtifactsTab.js.map +1 -0
- package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
- package/session/facets/ChangesTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ChangesTab.js +3 -3
- package/session/facets/ChangesTab.js.map +1 -0
- package/session/facets/InspectTab.d.ts.map +1 -0
- package/session/facets/InspectTab.js.map +1 -0
- package/session/{inspector → facets}/SetupTab.d.ts +11 -2
- package/session/facets/SetupTab.d.ts.map +1 -0
- package/session/{inspector → facets}/SetupTab.js +4 -3
- package/session/facets/SetupTab.js.map +1 -0
- package/session/{inspector → facets}/UsageTab.d.ts +1 -1
- package/session/facets/UsageTab.d.ts.map +1 -0
- package/session/{inspector → facets}/UsageTab.js +1 -1
- package/session/facets/UsageTab.js.map +1 -0
- package/session/{inspector → facets}/index.d.ts +0 -6
- package/session/facets/index.d.ts.map +1 -0
- package/session/{inspector → facets}/index.js +0 -3
- package/session/facets/index.js.map +1 -0
- package/session/index.d.ts +11 -2
- package/session/index.d.ts.map +1 -1
- package/session/index.js +15 -2
- package/session/index.js.map +1 -1
- package/session/plan-document.d.ts +9 -0
- package/session/plan-document.d.ts.map +1 -0
- package/session/plan-document.js +17 -0
- package/session/plan-document.js.map +1 -0
- package/session/useOpenFileChange.d.ts +20 -0
- package/session/useOpenFileChange.d.ts.map +1 -0
- package/session/useOpenFileChange.js +31 -0
- package/session/useOpenFileChange.js.map +1 -0
- package/session/usePlanDraft.d.ts +52 -0
- package/session/usePlanDraft.d.ts.map +1 -0
- package/session/usePlanDraft.js +63 -0
- package/session/usePlanDraft.js.map +1 -0
- package/session/useSessionConversation.d.ts +6 -0
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +1 -0
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +1 -0
- package/session/useSessionPageFlow.js.map +1 -1
- package/session/useSessionPanel.d.ts +120 -0
- package/session/useSessionPanel.d.ts.map +1 -0
- package/session/useSessionPanel.js +130 -0
- package/session/useSessionPanel.js.map +1 -0
- package/session/useSessionRailViews.d.ts +45 -0
- package/session/useSessionRailViews.d.ts.map +1 -0
- package/session/useSessionRailViews.js +105 -0
- package/session/useSessionRailViews.js.map +1 -0
- package/src/composer/SessionComposer.tsx +52 -10
- package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
- package/src/execution/ArtifactContentRenderer.tsx +101 -24
- package/src/execution/FilePathContext.tsx +8 -1
- package/src/execution/FilePathLink.tsx +22 -6
- package/src/execution/MessageEntry.tsx +111 -1
- package/src/execution/MessageThread.tsx +291 -36
- package/src/execution/PlanArtifactCard.tsx +63 -31
- package/src/execution/PlanDocumentMessage.tsx +96 -0
- package/src/execution/PlanStreamingCard.tsx +137 -0
- package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
- package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
- package/src/execution/__tests__/MessageThread.test.tsx +101 -0
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +66 -12
- package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
- package/src/execution/__tests__/PlanStreamingCard.test.tsx +49 -0
- package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +504 -22
- package/src/execution/__tests__/message-entry.test.tsx +48 -0
- package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
- package/src/execution/index.ts +7 -1
- package/src/execution/useCreateAgentExecution.ts +16 -1
- package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
- package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
- package/src/github/decodeGitHubContent.ts +83 -0
- package/src/github/index.ts +1 -0
- package/src/github/useGitHubFileReader.ts +152 -0
- package/src/github/useGitHubTreeLister.ts +6 -2
- package/src/index.ts +63 -9
- package/src/internal/ResizableSplit.tsx +184 -51
- package/src/internal/VirtualizedThread.tsx +12 -4
- package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
- package/src/internal/__tests__/markdown-components.test.tsx +68 -0
- package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
- package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
- package/src/internal/file-icons/index.tsx +137 -0
- package/src/internal/file-tree/FileTreeNode.tsx +43 -3
- package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
- package/src/internal/markdown-components.tsx +116 -11
- package/src/{workflow → internal}/motion-preference.ts +7 -4
- package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
- package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
- package/src/internal/store/index.ts +94 -0
- package/src/internal/store/workspace-editors-store.ts +315 -0
- package/src/internal/store/workspace-file-selection-store.ts +88 -0
- package/src/internal/useRevealLine.ts +81 -0
- package/src/library/__tests__/detect-plan-artifact.test.ts +48 -0
- package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
- package/src/library/detect-plan-artifact.ts +35 -0
- package/src/library/detect-streaming-plan.ts +108 -0
- package/src/library/index.ts +5 -0
- package/src/session/NewSessionViewer.tsx +123 -55
- package/src/session/PlanEditor.tsx +361 -0
- package/src/session/PlanStreamingDocument.tsx +97 -0
- package/src/session/SessionPanelChip.tsx +103 -0
- package/src/session/SessionViewer.tsx +617 -90
- package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
- package/src/session/__tests__/PlanEditor.test.tsx +217 -0
- package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
- package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
- package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +9 -4
- package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
- package/src/session/__tests__/audienceWiring.test.tsx +55 -19
- package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
- package/src/session/__tests__/usePlanDraft.test.ts +102 -0
- package/src/session/__tests__/useSessionPanel.test.ts +298 -0
- package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
- package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
- package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
- package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
- package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
- package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +35 -1
- package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
- package/src/session/{inspector → facets}/index.ts +0 -16
- package/src/session/index.ts +30 -13
- package/src/session/plan-document.ts +19 -0
- package/src/session/useOpenFileChange.ts +53 -0
- package/src/session/usePlanDraft.ts +109 -0
- package/src/session/useSessionConversation.ts +7 -0
- package/src/session/useSessionPageFlow.ts +1 -0
- package/src/session/useSessionPanel.ts +288 -0
- package/src/session/useSessionRailViews.tsx +200 -0
- package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
- package/src/workflow/index.ts +1 -1
- package/src/workflow/useFollowExecution.ts +1 -1
- package/src/workspace/EditorTabs.tsx +145 -0
- package/src/workspace/ExplorerTree.tsx +247 -0
- package/src/workspace/FileViewer.tsx +516 -0
- package/src/workspace/WorkspaceContentSearch.tsx +478 -0
- package/src/workspace/WorkspaceContentSearcher.ts +70 -0
- package/src/workspace/WorkspaceFileLister.ts +11 -0
- package/src/workspace/WorkspaceFileReader.ts +57 -0
- package/src/workspace/WorkspaceFileSearch.tsx +429 -0
- package/src/workspace/WorkspaceSurface.tsx +781 -0
- package/src/workspace/__tests__/EditorTabs.test.tsx +100 -0
- package/src/workspace/__tests__/ExplorerTree.test.tsx +152 -0
- package/src/workspace/__tests__/FileViewer.test.tsx +421 -0
- package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +196 -0
- package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +206 -0
- package/src/workspace/__tests__/WorkspaceSurface.test.tsx +348 -0
- package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
- package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
- package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
- package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
- package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
- package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
- package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
- package/src/workspace/findChangeForSelection.ts +61 -0
- package/src/workspace/index.ts +56 -2
- package/src/workspace/matchContentPreview.ts +51 -0
- package/src/workspace/matchWorkspaceFiles.ts +86 -0
- package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
- package/src/workspace/useWorkspaceContentSearch.ts +228 -0
- package/src/workspace/useWorkspaceFileContent.ts +129 -0
- package/src/workspace/useWorkspaceFileSearch.ts +184 -0
- package/src/workspace/useWorkspaceFiles.ts +27 -27
- package/src/workspace/workspaceListingCache.ts +93 -0
- package/styles.css +1 -1
- package/workflow/WorkflowExecutionGraph.js +1 -1
- package/workflow/WorkflowExecutionGraph.js.map +1 -1
- package/workflow/index.d.ts +1 -1
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -1
- package/workflow/index.js.map +1 -1
- package/workflow/useFollowExecution.js +1 -1
- package/workflow/useFollowExecution.js.map +1 -1
- package/workspace/EditorTabs.d.ts +29 -0
- package/workspace/EditorTabs.d.ts.map +1 -0
- package/workspace/EditorTabs.js +66 -0
- package/workspace/EditorTabs.js.map +1 -0
- package/workspace/ExplorerTree.d.ts +32 -0
- package/workspace/ExplorerTree.d.ts.map +1 -0
- package/workspace/ExplorerTree.js +45 -0
- package/workspace/ExplorerTree.js.map +1 -0
- package/workspace/FileViewer.d.ts +93 -0
- package/workspace/FileViewer.d.ts.map +1 -0
- package/workspace/FileViewer.js +182 -0
- package/workspace/FileViewer.js.map +1 -0
- package/workspace/WorkspaceContentSearch.d.ts +41 -0
- package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearch.js +195 -0
- package/workspace/WorkspaceContentSearch.js.map +1 -0
- package/workspace/WorkspaceContentSearcher.d.ts +59 -0
- package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearcher.js +7 -0
- package/workspace/WorkspaceContentSearcher.js.map +1 -0
- package/workspace/WorkspaceFileLister.d.ts +11 -0
- package/workspace/WorkspaceFileLister.d.ts.map +1 -1
- package/workspace/WorkspaceFileReader.d.ts +48 -0
- package/workspace/WorkspaceFileReader.d.ts.map +1 -0
- package/workspace/WorkspaceFileReader.js +11 -0
- package/workspace/WorkspaceFileReader.js.map +1 -0
- package/workspace/WorkspaceFileSearch.d.ts +32 -0
- package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/WorkspaceFileSearch.js +155 -0
- package/workspace/WorkspaceFileSearch.js.map +1 -0
- package/workspace/WorkspaceSurface.d.ts +151 -0
- package/workspace/WorkspaceSurface.d.ts.map +1 -0
- package/workspace/WorkspaceSurface.js +184 -0
- package/workspace/WorkspaceSurface.js.map +1 -0
- package/workspace/findChangeForSelection.d.ts +19 -0
- package/workspace/findChangeForSelection.d.ts.map +1 -0
- package/workspace/findChangeForSelection.js +46 -0
- package/workspace/findChangeForSelection.js.map +1 -0
- package/workspace/index.d.ts +24 -2
- package/workspace/index.d.ts.map +1 -1
- package/workspace/index.js +13 -1
- package/workspace/index.js.map +1 -1
- package/workspace/matchContentPreview.d.ts +21 -0
- package/workspace/matchContentPreview.d.ts.map +1 -0
- package/workspace/matchContentPreview.js +36 -0
- package/workspace/matchContentPreview.js.map +1 -0
- package/workspace/matchWorkspaceFiles.d.ts +30 -0
- package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
- package/workspace/matchWorkspaceFiles.js +58 -0
- package/workspace/matchWorkspaceFiles.js.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.js +115 -0
- package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
- package/workspace/useWorkspaceContentSearch.d.ts +69 -0
- package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceContentSearch.js +154 -0
- package/workspace/useWorkspaceContentSearch.js.map +1 -0
- package/workspace/useWorkspaceFileContent.d.ts +73 -0
- package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
- package/workspace/useWorkspaceFileContent.js +57 -0
- package/workspace/useWorkspaceFileContent.js.map +1 -0
- package/workspace/useWorkspaceFileSearch.d.ts +61 -0
- package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceFileSearch.js +119 -0
- package/workspace/useWorkspaceFileSearch.js.map +1 -0
- package/workspace/useWorkspaceFiles.d.ts +13 -5
- package/workspace/useWorkspaceFiles.d.ts.map +1 -1
- package/workspace/useWorkspaceFiles.js +18 -19
- package/workspace/useWorkspaceFiles.js.map +1 -1
- package/workspace/workspaceListingCache.d.ts +47 -0
- package/workspace/workspaceListingCache.d.ts.map +1 -0
- package/workspace/workspaceListingCache.js +55 -0
- package/workspace/workspaceListingCache.js.map +1 -0
- package/session/inspector/ArtifactsTab.d.ts.map +0 -1
- package/session/inspector/ArtifactsTab.js.map +0 -1
- package/session/inspector/ChangesTab.d.ts.map +0 -1
- package/session/inspector/ChangesTab.js.map +0 -1
- package/session/inspector/InspectTab.d.ts.map +0 -1
- package/session/inspector/InspectTab.js.map +0 -1
- package/session/inspector/SessionInspector.d.ts +0 -64
- package/session/inspector/SessionInspector.d.ts.map +0 -1
- package/session/inspector/SessionInspector.js +0 -53
- package/session/inspector/SessionInspector.js.map +0 -1
- package/session/inspector/SetupTab.d.ts.map +0 -1
- package/session/inspector/SetupTab.js.map +0 -1
- package/session/inspector/UsageTab.d.ts.map +0 -1
- package/session/inspector/UsageTab.js.map +0 -1
- package/session/inspector/WorkspaceTab.d.ts +0 -35
- package/session/inspector/WorkspaceTab.d.ts.map +0 -1
- package/session/inspector/WorkspaceTab.js +0 -75
- package/session/inspector/WorkspaceTab.js.map +0 -1
- package/session/inspector/index.d.ts.map +0 -1
- package/session/inspector/index.js.map +0 -1
- package/session/inspector/useSessionInspector.d.ts +0 -49
- package/session/inspector/useSessionInspector.d.ts.map +0 -1
- package/session/inspector/useSessionInspector.js +0 -122
- package/session/inspector/useSessionInspector.js.map +0 -1
- package/src/session/inspector/SessionInspector.tsx +0 -162
- package/src/session/inspector/WorkspaceTab.tsx +0 -245
- package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
- package/src/session/inspector/useSessionInspector.ts +0 -178
- package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
- package/workflow/motion-preference.d.ts.map +0 -1
- package/workflow/motion-preference.js.map +0 -1
- package/workspace/WorkspaceEntryFiles.d.ts +0 -22
- package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
- package/workspace/WorkspaceEntryFiles.js +0 -58
- package/workspace/WorkspaceEntryFiles.js.map +0 -1
- /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
- /package/session/{inspector → facets}/InspectTab.js +0 -0
- /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
- /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
- /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
|
@@ -9,14 +9,16 @@ import {
|
|
|
9
9
|
AgentExecutionSpecSchema,
|
|
10
10
|
ExecutionConfigSchema,
|
|
11
11
|
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
|
|
12
|
+
import { ExecutionArtifactSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/artifact_pb";
|
|
12
13
|
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
13
14
|
import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
14
15
|
import {
|
|
16
|
+
ExecutionArtifactKind,
|
|
15
17
|
ExecutionPhase,
|
|
16
18
|
InteractionMode,
|
|
17
19
|
MessageType,
|
|
18
20
|
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
19
|
-
import { buildThreadItems } from "../MessageThread";
|
|
21
|
+
import { buildThreadItems, type ThreadItem } from "../MessageThread";
|
|
20
22
|
|
|
21
23
|
function makeMessage(type: MessageType, content: string) {
|
|
22
24
|
const msg = create(AgentMessageSchema);
|
|
@@ -25,12 +27,22 @@ function makeMessage(type: MessageType, content: string) {
|
|
|
25
27
|
return msg;
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
function makePlanArtifact(executionId: string) {
|
|
31
|
+
const artifact = create(ExecutionArtifactSchema);
|
|
32
|
+
artifact.name = "plan.md";
|
|
33
|
+
artifact.kind = ExecutionArtifactKind.FILE;
|
|
34
|
+
artifact.storageKey = `artifacts/${executionId}/plan.md`;
|
|
35
|
+
return artifact;
|
|
36
|
+
}
|
|
37
|
+
|
|
28
38
|
function makeExecution(opts: {
|
|
29
39
|
id: string;
|
|
30
40
|
specMessage?: string;
|
|
31
41
|
phase?: ExecutionPhase;
|
|
32
42
|
interactionMode?: InteractionMode;
|
|
43
|
+
buildFromPlan?: boolean;
|
|
33
44
|
messages?: ReturnType<typeof makeMessage>[];
|
|
45
|
+
withPlanArtifact?: boolean;
|
|
34
46
|
}): AgentExecution {
|
|
35
47
|
const exec = create(AgentExecutionSchema);
|
|
36
48
|
|
|
@@ -40,9 +52,14 @@ function makeExecution(opts: {
|
|
|
40
52
|
|
|
41
53
|
const spec = create(AgentExecutionSpecSchema);
|
|
42
54
|
spec.message = opts.specMessage ?? "test message";
|
|
43
|
-
if (opts.interactionMode !== undefined) {
|
|
55
|
+
if (opts.interactionMode !== undefined || opts.buildFromPlan !== undefined) {
|
|
44
56
|
const config = create(ExecutionConfigSchema);
|
|
45
|
-
|
|
57
|
+
if (opts.interactionMode !== undefined) {
|
|
58
|
+
config.interactionMode = opts.interactionMode;
|
|
59
|
+
}
|
|
60
|
+
if (opts.buildFromPlan !== undefined) {
|
|
61
|
+
config.buildFromPlan = opts.buildFromPlan;
|
|
62
|
+
}
|
|
46
63
|
spec.executionConfig = config;
|
|
47
64
|
}
|
|
48
65
|
exec.spec = spec;
|
|
@@ -52,11 +69,21 @@ function makeExecution(opts: {
|
|
|
52
69
|
if (opts.messages) {
|
|
53
70
|
status.messages = opts.messages;
|
|
54
71
|
}
|
|
72
|
+
if (opts.withPlanArtifact) {
|
|
73
|
+
status.artifacts = [makePlanArtifact(opts.id)];
|
|
74
|
+
}
|
|
55
75
|
exec.status = status;
|
|
56
76
|
|
|
57
77
|
return exec;
|
|
58
78
|
}
|
|
59
79
|
|
|
80
|
+
function planItems(items: readonly ThreadItem[]) {
|
|
81
|
+
return items.filter(
|
|
82
|
+
(i): i is Extract<ThreadItem, { kind: "plan-completion" }> =>
|
|
83
|
+
i.kind === "plan-completion",
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
60
87
|
describe("buildThreadItems plan-completion variant", () => {
|
|
61
88
|
it("emits plan-completion for COMPLETED Plan-mode execution", () => {
|
|
62
89
|
const exec = makeExecution({
|
|
@@ -67,10 +94,11 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
67
94
|
});
|
|
68
95
|
|
|
69
96
|
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
70
|
-
const
|
|
97
|
+
const cards = planItems(items);
|
|
71
98
|
|
|
72
|
-
expect(
|
|
73
|
-
expect(
|
|
99
|
+
expect(cards).toHaveLength(1);
|
|
100
|
+
expect(cards[0].key).toBe("exec-plan-plan-completion");
|
|
101
|
+
expect(cards[0].isLatestPlan).toBe(true);
|
|
74
102
|
});
|
|
75
103
|
|
|
76
104
|
it("does NOT emit plan-completion for COMPLETED Agent-mode execution", () => {
|
|
@@ -82,9 +110,8 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
82
110
|
});
|
|
83
111
|
|
|
84
112
|
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
85
|
-
const planItem = items.find((i) => i.kind === "plan-completion");
|
|
86
113
|
|
|
87
|
-
expect(
|
|
114
|
+
expect(planItems(items)).toHaveLength(0);
|
|
88
115
|
});
|
|
89
116
|
|
|
90
117
|
it("does NOT emit plan-completion for COMPLETED execution with no interactionMode", () => {
|
|
@@ -95,9 +122,8 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
95
122
|
});
|
|
96
123
|
|
|
97
124
|
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
98
|
-
const planItem = items.find((i) => i.kind === "plan-completion");
|
|
99
125
|
|
|
100
|
-
expect(
|
|
126
|
+
expect(planItems(items)).toHaveLength(0);
|
|
101
127
|
});
|
|
102
128
|
|
|
103
129
|
it("does NOT emit plan-completion for FAILED Plan-mode execution", () => {
|
|
@@ -109,9 +135,8 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
109
135
|
});
|
|
110
136
|
|
|
111
137
|
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
112
|
-
const planItem = items.find((i) => i.kind === "plan-completion");
|
|
113
138
|
|
|
114
|
-
expect(
|
|
139
|
+
expect(planItems(items)).toHaveLength(0);
|
|
115
140
|
});
|
|
116
141
|
|
|
117
142
|
it("does NOT emit plan-completion for TERMINATED Plan-mode execution", () => {
|
|
@@ -122,9 +147,8 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
122
147
|
});
|
|
123
148
|
|
|
124
149
|
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
125
|
-
const planItem = items.find((i) => i.kind === "plan-completion");
|
|
126
150
|
|
|
127
|
-
expect(
|
|
151
|
+
expect(planItems(items)).toHaveLength(0);
|
|
128
152
|
});
|
|
129
153
|
|
|
130
154
|
it("does NOT emit plan-completion when a Plan execution is actively streaming", () => {
|
|
@@ -136,12 +160,11 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
136
160
|
});
|
|
137
161
|
|
|
138
162
|
const items = buildThreadItems([], exec, null, false, undefined);
|
|
139
|
-
const planItem = items.find((i) => i.kind === "plan-completion");
|
|
140
163
|
|
|
141
|
-
expect(
|
|
164
|
+
expect(planItems(items)).toHaveLength(0);
|
|
142
165
|
});
|
|
143
166
|
|
|
144
|
-
it("emits
|
|
167
|
+
it("emits one card, attached to the plan segment, for [agent, plan]", () => {
|
|
145
168
|
const agentExec = makeExecution({
|
|
146
169
|
id: "exec-1",
|
|
147
170
|
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
@@ -163,17 +186,21 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
163
186
|
false,
|
|
164
187
|
undefined,
|
|
165
188
|
);
|
|
166
|
-
const
|
|
189
|
+
const cards = planItems(items);
|
|
167
190
|
|
|
168
|
-
expect(
|
|
191
|
+
expect(cards).toHaveLength(1);
|
|
192
|
+
expect(cards[0].isLatestPlan).toBe(true);
|
|
169
193
|
});
|
|
170
194
|
|
|
171
|
-
it("
|
|
195
|
+
it("keeps the plan card (with build authority) after a later Agent turn", () => {
|
|
196
|
+
// The plan is still the thread's latest plan — an intervening Agent turn
|
|
197
|
+
// must not strip the review card or its Build action.
|
|
172
198
|
const planExec = makeExecution({
|
|
173
199
|
id: "exec-plan",
|
|
174
200
|
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
175
201
|
interactionMode: InteractionMode.PLAN,
|
|
176
202
|
messages: [makeMessage(MessageType.MESSAGE_AI, "Here is the plan")],
|
|
203
|
+
withPlanArtifact: true,
|
|
177
204
|
});
|
|
178
205
|
|
|
179
206
|
const agentExec = makeExecution({
|
|
@@ -190,8 +217,463 @@ describe("buildThreadItems plan-completion variant", () => {
|
|
|
190
217
|
false,
|
|
191
218
|
undefined,
|
|
192
219
|
);
|
|
193
|
-
const
|
|
220
|
+
const cards = planItems(items);
|
|
221
|
+
|
|
222
|
+
expect(cards).toHaveLength(1);
|
|
223
|
+
expect(cards[0].key).toBe("exec-plan-plan-completion");
|
|
224
|
+
expect(cards[0].isLatestPlan).toBe(true);
|
|
225
|
+
// The card closes the plan's own segment — it precedes the agent turn.
|
|
226
|
+
const cardIndex = items.indexOf(cards[0]);
|
|
227
|
+
const agentSpecIndex = items.findIndex((i) => i.key === "exec-impl-spec");
|
|
228
|
+
expect(cardIndex).toBeLessThan(agentSpecIndex);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("emits a card per plan; only the newest carries isLatestPlan", () => {
|
|
232
|
+
const planA = makeExecution({
|
|
233
|
+
id: "exec-plan-a",
|
|
234
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
235
|
+
interactionMode: InteractionMode.PLAN,
|
|
236
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Plan A")],
|
|
237
|
+
withPlanArtifact: true,
|
|
238
|
+
});
|
|
239
|
+
const planB = makeExecution({
|
|
240
|
+
id: "exec-plan-b",
|
|
241
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
242
|
+
interactionMode: InteractionMode.PLAN,
|
|
243
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Plan B")],
|
|
244
|
+
withPlanArtifact: true,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const items = buildThreadItems([planA, planB], null, null, false, undefined);
|
|
248
|
+
const cards = planItems(items);
|
|
249
|
+
|
|
250
|
+
expect(cards).toHaveLength(2);
|
|
251
|
+
expect(cards[0].key).toBe("exec-plan-a-plan-completion");
|
|
252
|
+
expect(cards[0].isLatestPlan).toBe(false);
|
|
253
|
+
expect(cards[1].key).toBe("exec-plan-b-plan-completion");
|
|
254
|
+
expect(cards[1].isLatestPlan).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("skips a superseded plan that never published an artifact", () => {
|
|
258
|
+
// No artifact and no build authority → the card would be an empty shell.
|
|
259
|
+
const planA = makeExecution({
|
|
260
|
+
id: "exec-plan-a",
|
|
261
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
262
|
+
interactionMode: InteractionMode.PLAN,
|
|
263
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Plan A")],
|
|
264
|
+
withPlanArtifact: false,
|
|
265
|
+
});
|
|
266
|
+
const planB = makeExecution({
|
|
267
|
+
id: "exec-plan-b",
|
|
268
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
269
|
+
interactionMode: InteractionMode.PLAN,
|
|
270
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Plan B")],
|
|
271
|
+
withPlanArtifact: false,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const items = buildThreadItems([planA, planB], null, null, false, undefined);
|
|
275
|
+
const cards = planItems(items);
|
|
276
|
+
|
|
277
|
+
// Only the latest (artifact-less) plan renders — as the fallback CTA.
|
|
278
|
+
expect(cards).toHaveLength(1);
|
|
279
|
+
expect(cards[0].key).toBe("exec-plan-b-plan-completion");
|
|
280
|
+
expect(cards[0].isLatestPlan).toBe(true);
|
|
281
|
+
expect(cards[0].planArtifact).toBeUndefined();
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it("carries the plan artifact on the item when published", () => {
|
|
285
|
+
const exec = makeExecution({
|
|
286
|
+
id: "exec-plan",
|
|
287
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
288
|
+
interactionMode: InteractionMode.PLAN,
|
|
289
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Here is the plan")],
|
|
290
|
+
withPlanArtifact: true,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
294
|
+
const card = planItems(items)[0];
|
|
295
|
+
|
|
296
|
+
expect(card.planArtifact?.name).toBe("plan.md");
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
describe("buildThreadItems plan-message collapse (artifact published)", () => {
|
|
301
|
+
function messageItems(items: readonly ThreadItem[]) {
|
|
302
|
+
return items.filter(
|
|
303
|
+
(i): i is Extract<ThreadItem, { kind: "message" }> =>
|
|
304
|
+
i.kind === "message",
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
it("removes the plan message from the thread — the card is the turn's sole plan representation", () => {
|
|
309
|
+
const exec = makeExecution({
|
|
310
|
+
id: "exec-plan",
|
|
311
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
312
|
+
interactionMode: InteractionMode.PLAN,
|
|
313
|
+
messages: [
|
|
314
|
+
makeMessage(MessageType.MESSAGE_AI, "Let me look around first."),
|
|
315
|
+
makeMessage(MessageType.MESSAGE_AI, "# The Plan\n\n1. Do the thing"),
|
|
316
|
+
],
|
|
317
|
+
withPlanArtifact: true,
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
321
|
+
|
|
322
|
+
// The opening narration stays; the plan message (m1) is collapsed.
|
|
323
|
+
const keys = messageItems(items).map((i) => i.key);
|
|
324
|
+
expect(keys).toContain("exec-plan-m0");
|
|
325
|
+
expect(keys).not.toContain("exec-plan-m1");
|
|
326
|
+
expect(planItems(items)).toHaveLength(1);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it("lifts the plan's leading H1 onto the card as its title", () => {
|
|
330
|
+
const exec = makeExecution({
|
|
331
|
+
id: "exec-plan",
|
|
332
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
333
|
+
interactionMode: InteractionMode.PLAN,
|
|
334
|
+
messages: [
|
|
335
|
+
makeMessage(MessageType.MESSAGE_AI, "# Refactor auth\n\nSteps…"),
|
|
336
|
+
],
|
|
337
|
+
withPlanArtifact: true,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
341
|
+
expect(planItems(items)[0].planTitle).toBe("Refactor auth");
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it("extracts the title through a plan-scoped enclosing fence (bare fence included)", () => {
|
|
345
|
+
// Same unwrap the document renderers apply, so card and plan tab agree.
|
|
346
|
+
const exec = makeExecution({
|
|
347
|
+
id: "exec-plan",
|
|
348
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
349
|
+
interactionMode: InteractionMode.PLAN,
|
|
350
|
+
messages: [
|
|
351
|
+
makeMessage(MessageType.MESSAGE_AI, "```\n# Fenced Plan\n\nBody\n```"),
|
|
352
|
+
],
|
|
353
|
+
withPlanArtifact: true,
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
357
|
+
expect(planItems(items)[0].planTitle).toBe("Fenced Plan");
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it("leaves the title undefined when the plan has no leading H1", () => {
|
|
361
|
+
const exec = makeExecution({
|
|
362
|
+
id: "exec-plan",
|
|
363
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
364
|
+
interactionMode: InteractionMode.PLAN,
|
|
365
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Just prose, no title")],
|
|
366
|
+
withPlanArtifact: true,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
370
|
+
expect(planItems(items)[0].planTitle).toBeUndefined();
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it("never stamps isPlanDocument when the message collapsed into the card", () => {
|
|
374
|
+
const exec = makeExecution({
|
|
375
|
+
id: "exec-plan",
|
|
376
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
377
|
+
interactionMode: InteractionMode.PLAN,
|
|
378
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "# The Plan")],
|
|
379
|
+
withPlanArtifact: true,
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
383
|
+
expect(
|
|
384
|
+
messageItems(items).filter((i) => i.isPlanDocument === true),
|
|
385
|
+
).toHaveLength(0);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it("keeps the plan message inline while streaming (no artifact yet)", () => {
|
|
389
|
+
const exec = makeExecution({
|
|
390
|
+
id: "exec-live",
|
|
391
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
392
|
+
interactionMode: InteractionMode.PLAN,
|
|
393
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "# Draft so far")],
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const items = buildThreadItems([], exec, null, false, undefined);
|
|
397
|
+
expect(messageItems(items).map((i) => i.key)).toContain("exec-live-m0");
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
describe("buildThreadItems plan-document stamping (no-artifact fallback)", () => {
|
|
402
|
+
function planDocumentItems(items: readonly ThreadItem[]) {
|
|
403
|
+
return items.filter(
|
|
404
|
+
(i): i is Extract<ThreadItem, { kind: "message" }> =>
|
|
405
|
+
i.kind === "message" && i.isPlanDocument === true,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
it("stamps the last AI message with content of a completed Plan execution", () => {
|
|
410
|
+
const exec = makeExecution({
|
|
411
|
+
id: "exec-plan",
|
|
412
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
413
|
+
interactionMode: InteractionMode.PLAN,
|
|
414
|
+
messages: [
|
|
415
|
+
makeMessage(MessageType.MESSAGE_AI, "Let me look around first."),
|
|
416
|
+
makeMessage(MessageType.MESSAGE_AI, "# The Plan\n\n1. Do the thing"),
|
|
417
|
+
],
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
421
|
+
const docs = planDocumentItems(items);
|
|
422
|
+
|
|
423
|
+
expect(docs).toHaveLength(1);
|
|
424
|
+
expect(docs[0].key).toBe("exec-plan-m1");
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it("does not stamp any message on an Agent-mode execution", () => {
|
|
428
|
+
const exec = makeExecution({
|
|
429
|
+
id: "exec-agent",
|
|
430
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
431
|
+
interactionMode: InteractionMode.AGENT,
|
|
432
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "# Not a plan")],
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
436
|
+
|
|
437
|
+
expect(planDocumentItems(items)).toHaveLength(0);
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
it("does not stamp while the Plan execution is still streaming", () => {
|
|
441
|
+
const exec = makeExecution({
|
|
442
|
+
id: "exec-live",
|
|
443
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
444
|
+
interactionMode: InteractionMode.PLAN,
|
|
445
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Draft so far...")],
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
const items = buildThreadItems([], exec, null, false, undefined);
|
|
449
|
+
|
|
450
|
+
expect(planDocumentItems(items)).toHaveLength(0);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
it("skips trailing empty AI messages when selecting the plan message", () => {
|
|
454
|
+
// Mirrors the runner's extractFinalPlanText: the plan is the last AI
|
|
455
|
+
// message WITH content, not merely the last AI message.
|
|
456
|
+
const exec = makeExecution({
|
|
457
|
+
id: "exec-plan",
|
|
458
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
459
|
+
interactionMode: InteractionMode.PLAN,
|
|
460
|
+
messages: [
|
|
461
|
+
makeMessage(MessageType.MESSAGE_AI, "# The Plan"),
|
|
462
|
+
makeMessage(MessageType.MESSAGE_AI, " "),
|
|
463
|
+
],
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
467
|
+
const docs = planDocumentItems(items);
|
|
468
|
+
|
|
469
|
+
expect(docs).toHaveLength(1);
|
|
470
|
+
expect(docs[0].key).toBe("exec-plan-m0");
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
describe("buildThreadItems plan-writing (live streaming collapse)", () => {
|
|
475
|
+
function messageItems(items: readonly ThreadItem[]) {
|
|
476
|
+
return items.filter(
|
|
477
|
+
(i): i is Extract<ThreadItem, { kind: "message" }> =>
|
|
478
|
+
i.kind === "message",
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function planWritingItems(items: readonly ThreadItem[]) {
|
|
483
|
+
return items.filter(
|
|
484
|
+
(i): i is Extract<ThreadItem, { kind: "plan-writing" }> =>
|
|
485
|
+
i.kind === "plan-writing",
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/** buildThreadItems with the collapseStreamingPlan opt-in enabled. */
|
|
490
|
+
function buildWithLiveCollapse(
|
|
491
|
+
executions: AgentExecution[],
|
|
492
|
+
activeStreamExecution: AgentExecution | null,
|
|
493
|
+
) {
|
|
494
|
+
return buildThreadItems(
|
|
495
|
+
executions,
|
|
496
|
+
activeStreamExecution,
|
|
497
|
+
null,
|
|
498
|
+
false,
|
|
499
|
+
undefined,
|
|
500
|
+
undefined,
|
|
501
|
+
false,
|
|
502
|
+
false,
|
|
503
|
+
false,
|
|
504
|
+
true,
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const streamingPlanExec = () =>
|
|
509
|
+
makeExecution({
|
|
510
|
+
id: "exec-live",
|
|
511
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
512
|
+
interactionMode: InteractionMode.PLAN,
|
|
513
|
+
messages: [
|
|
514
|
+
makeMessage(MessageType.MESSAGE_AI, "Let me look around first."),
|
|
515
|
+
makeMessage(MessageType.MESSAGE_AI, "# Live Plan\n\nDraft body"),
|
|
516
|
+
],
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it("suppresses the streaming plan message and emits a plan-writing card", () => {
|
|
520
|
+
const items = buildWithLiveCollapse([], streamingPlanExec());
|
|
521
|
+
|
|
522
|
+
const keys = messageItems(items).map((i) => i.key);
|
|
523
|
+
expect(keys).toContain("exec-live-m0"); // narration stays
|
|
524
|
+
expect(keys).not.toContain("exec-live-m1"); // the live plan is collapsed
|
|
525
|
+
|
|
526
|
+
const cards = planWritingItems(items);
|
|
527
|
+
expect(cards).toHaveLength(1);
|
|
528
|
+
expect(cards[0].executionId).toBe("exec-live");
|
|
529
|
+
expect(cards[0].planTitle).toBe("Live Plan");
|
|
530
|
+
expect(cards[0].planSize).toBe("# Live Plan\n\nDraft body".length);
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it("shares the completion item's key, so the card holds one thread position across the handoff", () => {
|
|
534
|
+
const liveItems = buildWithLiveCollapse([], streamingPlanExec());
|
|
535
|
+
|
|
536
|
+
const completedExec = makeExecution({
|
|
537
|
+
id: "exec-live",
|
|
538
|
+
phase: ExecutionPhase.EXECUTION_COMPLETED,
|
|
539
|
+
interactionMode: InteractionMode.PLAN,
|
|
540
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "# Live Plan\n\nDraft body")],
|
|
541
|
+
withPlanArtifact: true,
|
|
542
|
+
});
|
|
543
|
+
const settledItems = buildWithLiveCollapse([completedExec], null);
|
|
544
|
+
|
|
545
|
+
const liveCard = planWritingItems(liveItems)[0];
|
|
546
|
+
const settledCard = planItems(settledItems)[0];
|
|
547
|
+
expect(liveCard.key).toBe(settledCard.key);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it("keeps the plan streaming inline when the host has no plan surface (collapseStreamingPlan=false)", () => {
|
|
551
|
+
const items = buildThreadItems([], streamingPlanExec(), null, false, undefined);
|
|
552
|
+
|
|
553
|
+
expect(planWritingItems(items)).toHaveLength(0);
|
|
554
|
+
expect(messageItems(items).map((i) => i.key)).toContain("exec-live-m1");
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
it("never collapses a non-terminal Plan execution that is NOT the active stream", () => {
|
|
558
|
+
// The transient completed-list/active-stream skew must not sprout a live
|
|
559
|
+
// card for a stale copy of the execution.
|
|
560
|
+
const items = buildWithLiveCollapse([streamingPlanExec()], null);
|
|
561
|
+
|
|
562
|
+
expect(planWritingItems(items)).toHaveLength(0);
|
|
563
|
+
expect(messageItems(items).map((i) => i.key)).toContain("exec-live-m1");
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
it("does not collapse streaming narration (no leading H1)", () => {
|
|
567
|
+
const exec = makeExecution({
|
|
568
|
+
id: "exec-live",
|
|
569
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
570
|
+
interactionMode: InteractionMode.PLAN,
|
|
571
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Exploring the repo…")],
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
const items = buildWithLiveCollapse([], exec);
|
|
575
|
+
|
|
576
|
+
expect(planWritingItems(items)).toHaveLength(0);
|
|
577
|
+
expect(messageItems(items).map((i) => i.key)).toContain("exec-live-m0");
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
it("does not collapse an Agent-mode streaming turn, even with a plan-shaped message", () => {
|
|
581
|
+
const exec = makeExecution({
|
|
582
|
+
id: "exec-agent",
|
|
583
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
584
|
+
interactionMode: InteractionMode.AGENT,
|
|
585
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "# Looks like a plan")],
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
const items = buildWithLiveCollapse([], exec);
|
|
589
|
+
|
|
590
|
+
expect(planWritingItems(items)).toHaveLength(0);
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
it("reverts to inline text when the turn stops without completing", () => {
|
|
594
|
+
// Cancelled mid-plan: no live card (turn is terminal), no completion card
|
|
595
|
+
// (not COMPLETED) — the partial plan renders inline, an honest record.
|
|
596
|
+
const exec = makeExecution({
|
|
597
|
+
id: "exec-live",
|
|
598
|
+
phase: ExecutionPhase.EXECUTION_CANCELLED,
|
|
599
|
+
interactionMode: InteractionMode.PLAN,
|
|
600
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "# Live Plan\n\nPartial")],
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
const items = buildWithLiveCollapse([exec], null);
|
|
604
|
+
|
|
605
|
+
expect(planWritingItems(items)).toHaveLength(0);
|
|
606
|
+
expect(planItems(items)).toHaveLength(0);
|
|
607
|
+
expect(messageItems(items).map((i) => i.key)).toContain("exec-live-m0");
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it("extracts the live title through an unterminated plan fence", () => {
|
|
611
|
+
const exec = makeExecution({
|
|
612
|
+
id: "exec-live",
|
|
613
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
614
|
+
interactionMode: InteractionMode.PLAN,
|
|
615
|
+
messages: [
|
|
616
|
+
makeMessage(MessageType.MESSAGE_AI, "```markdown\n# Fenced Live Plan\n\nBody"),
|
|
617
|
+
],
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
const items = buildWithLiveCollapse([], exec);
|
|
621
|
+
expect(planWritingItems(items)[0]?.planTitle).toBe("Fenced Live Plan");
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it("leaves the title undefined while only the H1's first characters have streamed", () => {
|
|
625
|
+
const exec = makeExecution({
|
|
626
|
+
id: "exec-live",
|
|
627
|
+
phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
628
|
+
interactionMode: InteractionMode.PLAN,
|
|
629
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "# Re")],
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
const items = buildWithLiveCollapse([], exec);
|
|
633
|
+
const cards = planWritingItems(items);
|
|
634
|
+
expect(cards).toHaveLength(1);
|
|
635
|
+
// extractLeadingH1 matches at end-of-input, so even a partial title
|
|
636
|
+
// resolves; "Re" is the growing title, not undefined.
|
|
637
|
+
expect(cards[0].planTitle).toBe("Re");
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
describe("buildThreadItems build-from-plan prompt", () => {
|
|
642
|
+
function promptItem(items: readonly ThreadItem[], execId: string) {
|
|
643
|
+
return items.find(
|
|
644
|
+
(i): i is Extract<ThreadItem, { kind: "message" }> =>
|
|
645
|
+
i.kind === "message" && i.key === `${execId}-spec`,
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
it("stamps isBuildFromPlan on the prompt of a build turn", () => {
|
|
650
|
+
const exec = makeExecution({
|
|
651
|
+
id: "exec-build",
|
|
652
|
+
specMessage: "Build from plan",
|
|
653
|
+
interactionMode: InteractionMode.AGENT,
|
|
654
|
+
buildFromPlan: true,
|
|
655
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Implementing…")],
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
659
|
+
const prompt = promptItem(items, "exec-build");
|
|
660
|
+
|
|
661
|
+
expect(prompt).toBeDefined();
|
|
662
|
+
expect(prompt!.isBuildFromPlan).toBe(true);
|
|
663
|
+
expect(prompt!.message.content).toBe("Build from plan");
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it("leaves the flag unset on an ordinary prompt (renders as a normal bubble)", () => {
|
|
667
|
+
const exec = makeExecution({
|
|
668
|
+
id: "exec-normal",
|
|
669
|
+
interactionMode: InteractionMode.AGENT,
|
|
670
|
+
messages: [makeMessage(MessageType.MESSAGE_AI, "Done")],
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
const items = buildThreadItems([exec], null, null, false, undefined);
|
|
674
|
+
const prompt = promptItem(items, "exec-normal");
|
|
194
675
|
|
|
195
|
-
expect(
|
|
676
|
+
expect(prompt).toBeDefined();
|
|
677
|
+
expect(prompt!.isBuildFromPlan).toBeUndefined();
|
|
196
678
|
});
|
|
197
679
|
});
|
|
@@ -194,6 +194,54 @@ describe("MessageEntry — Human messages", () => {
|
|
|
194
194
|
});
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// Build-from-plan chip — the flagged human turn renders as a compact pill
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
|
|
201
|
+
describe("MessageEntry — Build-from-plan chip", () => {
|
|
202
|
+
it("renders a compact chip instead of a prompt bubble when flagged", () => {
|
|
203
|
+
const msg = makeMessage(MessageType.MESSAGE_HUMAN, "Build from plan");
|
|
204
|
+
const { container } = render(
|
|
205
|
+
<MessageEntry message={msg} isBuildFromPlan />,
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const chip = queryArticle(container, "Build from plan");
|
|
209
|
+
expect(chip).not.toBeNull();
|
|
210
|
+
expect(chip!.textContent).toContain("Build from plan");
|
|
211
|
+
// The ordinary prompt bubble must not render alongside the chip.
|
|
212
|
+
expect(queryArticle(container, "User message")).toBeNull();
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("keeps the ordinary bubble when the flag is absent", () => {
|
|
216
|
+
const msg = makeMessage(MessageType.MESSAGE_HUMAN, "Build from plan");
|
|
217
|
+
const { container } = render(<MessageEntry message={msg} />);
|
|
218
|
+
|
|
219
|
+
expect(queryArticle(container, "User message")).not.toBeNull();
|
|
220
|
+
expect(queryArticle(container, "Build from plan")).toBeNull();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("never offers Edit on the chip (the label is not user prose)", () => {
|
|
224
|
+
const msg = makeMessage(MessageType.MESSAGE_HUMAN, "Build from plan");
|
|
225
|
+
const { container } = render(
|
|
226
|
+
<MessageEntry message={msg} isBuildFromPlan onEdit={() => {}} />,
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
expect(
|
|
230
|
+
container.querySelector('[aria-label="Edit message"]'),
|
|
231
|
+
).toBeNull();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("ignores the flag on non-human messages", () => {
|
|
235
|
+
const msg = makeMessage(MessageType.MESSAGE_AI, "Implementing…");
|
|
236
|
+
const { container } = render(
|
|
237
|
+
<MessageEntry message={msg} isBuildFromPlan />,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
expect(queryArticle(container, "AI response")).not.toBeNull();
|
|
241
|
+
expect(queryArticle(container, "Build from plan")).toBeNull();
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
197
245
|
// ---------------------------------------------------------------------------
|
|
198
246
|
// System messages — unchanged
|
|
199
247
|
// ---------------------------------------------------------------------------
|