@stigmer/react 3.12.2 → 3.12.4
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/access/ManageAccessDialog.d.ts.map +1 -1
- package/access/ManageAccessDialog.js +3 -19
- package/access/ManageAccessDialog.js.map +1 -1
- package/agent/steps/IdentityStep.d.ts.map +1 -1
- package/agent/steps/IdentityStep.js +2 -1
- package/agent/steps/IdentityStep.js.map +1 -1
- package/agent-instance/AgentInstanceDetailPanel.d.ts.map +1 -1
- package/agent-instance/AgentInstanceDetailPanel.js +2 -1
- package/agent-instance/AgentInstanceDetailPanel.js.map +1 -1
- package/agent-instance/CreateAgentInstanceDialog.d.ts.map +1 -1
- package/agent-instance/CreateAgentInstanceDialog.js +7 -20
- package/agent-instance/CreateAgentInstanceDialog.js.map +1 -1
- package/api-key/CreateApiKeyForm.d.ts.map +1 -1
- package/api-key/CreateApiKeyForm.js +2 -1
- package/api-key/CreateApiKeyForm.js.map +1 -1
- package/attachment/AttachmentImageLightbox.d.ts.map +1 -1
- package/attachment/AttachmentImageLightbox.js +8 -23
- package/attachment/AttachmentImageLightbox.js.map +1 -1
- package/channel/ChannelConversationsDialog.d.ts.map +1 -1
- package/channel/ChannelConversationsDialog.js +5 -20
- package/channel/ChannelConversationsDialog.js.map +1 -1
- package/channel/ChannelCredentialsDialog.d.ts.map +1 -1
- package/channel/ChannelCredentialsDialog.js +3 -19
- package/channel/ChannelCredentialsDialog.js.map +1 -1
- package/channel/ChannelTemplatesDialog.d.ts.map +1 -1
- package/channel/ChannelTemplatesDialog.js +6 -21
- package/channel/ChannelTemplatesDialog.js.map +1 -1
- package/channel/ConnectSlackDialog.d.ts.map +1 -1
- package/channel/ConnectSlackDialog.js +5 -22
- package/channel/ConnectSlackDialog.js.map +1 -1
- package/channel/ConnectWhatsAppDialog.d.ts.map +1 -1
- package/channel/ConnectWhatsAppDialog.js +3 -21
- package/channel/ConnectWhatsAppDialog.js.map +1 -1
- package/channel/connect/ServingAppSection.d.ts.map +1 -1
- package/channel/connect/ServingAppSection.js +2 -1
- package/channel/connect/ServingAppSection.js.map +1 -1
- package/channel-app/CreateChannelAppForm.d.ts.map +1 -1
- package/channel-app/CreateChannelAppForm.js +2 -1
- package/channel-app/CreateChannelAppForm.js.map +1 -1
- package/conversation/ConversationAttentionBanner.d.ts +23 -6
- package/conversation/ConversationAttentionBanner.d.ts.map +1 -1
- package/conversation/ConversationAttentionBanner.js +25 -10
- package/conversation/ConversationAttentionBanner.js.map +1 -1
- package/conversation/ConversationListPane.d.ts.map +1 -1
- package/conversation/ConversationListPane.js +26 -6
- package/conversation/ConversationListPane.js.map +1 -1
- package/conversation/ConversationTimelineView.d.ts.map +1 -1
- package/conversation/ConversationTimelineView.js +2 -1
- package/conversation/ConversationTimelineView.js.map +1 -1
- package/conversation/ConversationsWorkbench.d.ts.map +1 -1
- package/conversation/ConversationsWorkbench.js +1 -1
- package/conversation/ConversationsWorkbench.js.map +1 -1
- package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -1
- package/cursor-accounts/CursorAccountsConsole.js +2 -1
- package/cursor-accounts/CursorAccountsConsole.js.map +1 -1
- package/cursor-accounts/MemberKeysPanel.d.ts.map +1 -1
- package/cursor-accounts/MemberKeysPanel.js +2 -1
- package/cursor-accounts/MemberKeysPanel.js.map +1 -1
- package/dashboard/DashboardFailedRuns.d.ts.map +1 -1
- package/dashboard/DashboardFailedRuns.js +2 -1
- package/dashboard/DashboardFailedRuns.js.map +1 -1
- package/dependency-graph/DependencyGraph.d.ts.map +1 -1
- package/dependency-graph/DependencyGraph.js +2 -1
- package/dependency-graph/DependencyGraph.js.map +1 -1
- package/dependency-graph/DependencyTreeNode.d.ts.map +1 -1
- package/dependency-graph/DependencyTreeNode.js +2 -1
- package/dependency-graph/DependencyTreeNode.js.map +1 -1
- package/environment/EnvironmentPicker.d.ts.map +1 -1
- package/environment/EnvironmentPicker.js +2 -1
- package/environment/EnvironmentPicker.js.map +1 -1
- package/error/SecretFlowErrorGuide.d.ts.map +1 -1
- package/error/SecretFlowErrorGuide.js +2 -1
- package/error/SecretFlowErrorGuide.js.map +1 -1
- package/execution/ApprovalCard.d.ts.map +1 -1
- package/execution/ApprovalCard.js +13 -3
- package/execution/ApprovalCard.js.map +1 -1
- package/execution/ArtifactContentBody.d.ts.map +1 -1
- package/execution/ArtifactContentBody.js +2 -1
- package/execution/ArtifactContentBody.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts.map +1 -1
- package/execution/ArtifactPreviewModal.js +11 -17
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/ArtifactsWidget.d.ts.map +1 -1
- package/execution/ArtifactsWidget.js +2 -1
- package/execution/ArtifactsWidget.js.map +1 -1
- package/execution/FileChangeProgressBar.d.ts.map +1 -1
- package/execution/FileChangeProgressBar.js +2 -1
- package/execution/FileChangeProgressBar.js.map +1 -1
- package/execution/TodoList.d.ts.map +1 -1
- package/execution/TodoList.js +2 -1
- package/execution/TodoList.js.map +1 -1
- package/execution/ToolCallItem.d.ts +3 -1
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +19 -7
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/WriteBacksWidget.d.ts.map +1 -1
- package/execution/WriteBacksWidget.js +2 -1
- package/execution/WriteBacksWidget.js.map +1 -1
- package/execution/index.d.ts +1 -1
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +1 -1
- package/execution/index.js.map +1 -1
- package/execution/tool-categories.d.ts +37 -3
- package/execution/tool-categories.d.ts.map +1 -1
- package/execution/tool-categories.js +74 -2
- package/execution/tool-categories.js.map +1 -1
- package/execution/tool-presenter.d.ts +15 -0
- package/execution/tool-presenter.d.ts.map +1 -1
- package/execution/tool-presenter.js +7 -2
- package/execution/tool-presenter.js.map +1 -1
- package/iam-policy/PeopleWithAccess.d.ts.map +1 -1
- package/iam-policy/PeopleWithAccess.js +2 -1
- package/iam-policy/PeopleWithAccess.js.map +1 -1
- package/iam-policy/PrincipalPicker.d.ts.map +1 -1
- package/iam-policy/PrincipalPicker.js +2 -1
- package/iam-policy/PrincipalPicker.js.map +1 -1
- package/iam-policy/RoleSelector.d.ts.map +1 -1
- package/iam-policy/RoleSelector.js +2 -1
- package/iam-policy/RoleSelector.js.map +1 -1
- package/identity-provider/CreateIdentityProviderForm.d.ts.map +1 -1
- package/identity-provider/CreateIdentityProviderForm.js +2 -1
- package/identity-provider/CreateIdentityProviderForm.js.map +1 -1
- package/identity-provider/IdentityProviderDetailPanel.d.ts.map +1 -1
- package/identity-provider/IdentityProviderDetailPanel.js +2 -1
- package/identity-provider/IdentityProviderDetailPanel.js.map +1 -1
- package/identity-provider/IdentityProviderWizard.d.ts.map +1 -1
- package/identity-provider/IdentityProviderWizard.js +2 -1
- package/identity-provider/IdentityProviderWizard.js.map +1 -1
- package/index.d.ts +4 -2
- package/index.d.ts.map +1 -1
- package/index.js +4 -1
- package/index.js.map +1 -1
- package/internal/DialogShell.d.ts +77 -0
- package/internal/DialogShell.d.ts.map +1 -0
- package/internal/DialogShell.js +77 -0
- package/internal/DialogShell.js.map +1 -0
- package/internal/element-resets.d.ts +17 -0
- package/internal/element-resets.d.ts.map +1 -0
- package/internal/element-resets.js +32 -0
- package/internal/element-resets.js.map +1 -0
- package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
- package/internal/file-tree/FileTreeNode.js +2 -1
- package/internal/file-tree/FileTreeNode.js.map +1 -1
- package/internal/markdown-components.d.ts +7 -0
- package/internal/markdown-components.d.ts.map +1 -1
- package/internal/markdown-components.js +15 -5
- package/internal/markdown-components.js.map +1 -1
- package/invitation/InvitationManager.d.ts.map +1 -1
- package/invitation/InvitationManager.js +2 -1
- package/invitation/InvitationManager.js.map +1 -1
- package/manifest/ApplyManifestDialog.d.ts.map +1 -1
- package/manifest/ApplyManifestDialog.js +8 -17
- package/manifest/ApplyManifestDialog.js.map +1 -1
- package/manifest/EditResourceYamlDialog.d.ts.map +1 -1
- package/manifest/EditResourceYamlDialog.js +3 -19
- package/manifest/EditResourceYamlDialog.js.map +1 -1
- package/mcp-server/McpServerConnectDialog.d.ts.map +1 -1
- package/mcp-server/McpServerConnectDialog.js +8 -20
- package/mcp-server/McpServerConnectDialog.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +4 -15
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/steps/IdentityTransportStep.d.ts.map +1 -1
- package/mcp-server/steps/IdentityTransportStep.js +2 -1
- package/mcp-server/steps/IdentityTransportStep.js.map +1 -1
- package/package.json +4 -4
- package/platform-client/CreatePlatformClientForm.d.ts.map +1 -1
- package/platform-client/CreatePlatformClientForm.js +2 -1
- package/platform-client/CreatePlatformClientForm.js.map +1 -1
- package/platform-client/PlatformClientDetailPanel.d.ts.map +1 -1
- package/platform-client/PlatformClientDetailPanel.js +2 -1
- package/platform-client/PlatformClientDetailPanel.js.map +1 -1
- package/pricing-governance/BaselineEditor.d.ts.map +1 -1
- package/pricing-governance/BaselineEditor.js +2 -1
- package/pricing-governance/BaselineEditor.js.map +1 -1
- package/pricing-governance/PricingGovernanceConsole.d.ts.map +1 -1
- package/pricing-governance/PricingGovernanceConsole.js +2 -1
- package/pricing-governance/PricingGovernanceConsole.js.map +1 -1
- package/provider-standing/ProviderStandingAccessNotice.d.ts +11 -0
- package/provider-standing/ProviderStandingAccessNotice.d.ts.map +1 -0
- package/provider-standing/ProviderStandingAccessNotice.js +14 -0
- package/provider-standing/ProviderStandingAccessNotice.js.map +1 -0
- package/provider-standing/ProviderStandingConsole.d.ts +24 -0
- package/provider-standing/ProviderStandingConsole.d.ts.map +1 -0
- package/provider-standing/ProviderStandingConsole.js +98 -0
- package/provider-standing/ProviderStandingConsole.js.map +1 -0
- package/provider-standing/index.d.ts +6 -0
- package/provider-standing/index.d.ts.map +1 -0
- package/provider-standing/index.js +6 -0
- package/provider-standing/index.js.map +1 -0
- package/provider-standing/useProviderStanding.d.ts +34 -0
- package/provider-standing/useProviderStanding.d.ts.map +1 -0
- package/provider-standing/useProviderStanding.js +26 -0
- package/provider-standing/useProviderStanding.js.map +1 -0
- package/provider.d.ts +12 -0
- package/provider.d.ts.map +1 -1
- package/provider.js +12 -0
- package/provider.js.map +1 -1
- package/resource-creation/StepIndicator.d.ts.map +1 -1
- package/resource-creation/StepIndicator.js +2 -1
- package/resource-creation/StepIndicator.js.map +1 -1
- package/resource-detail/ConfirmDialog.d.ts +2 -3
- package/resource-detail/ConfirmDialog.d.ts.map +1 -1
- package/resource-detail/ConfirmDialog.js +8 -20
- package/resource-detail/ConfirmDialog.js.map +1 -1
- package/schedule/ScheduleDetailView.d.ts.map +1 -1
- package/schedule/ScheduleDetailView.js +3 -2
- package/schedule/ScheduleDetailView.js.map +1 -1
- package/schedule/ScheduleRunsTable.d.ts.map +1 -1
- package/schedule/ScheduleRunsTable.js +2 -1
- package/schedule/ScheduleRunsTable.js.map +1 -1
- package/session/facets/ArtifactsTab.d.ts.map +1 -1
- package/session/facets/ArtifactsTab.js +2 -1
- package/session/facets/ArtifactsTab.js.map +1 -1
- package/session/facets/ChangesTab.d.ts.map +1 -1
- package/session/facets/ChangesTab.js +2 -1
- package/session/facets/ChangesTab.js.map +1 -1
- package/session/facets/UsageTab.d.ts +10 -3
- package/session/facets/UsageTab.d.ts.map +1 -1
- package/session/facets/UsageTab.js +42 -6
- package/session/facets/UsageTab.js.map +1 -1
- package/session/index.d.ts +1 -1
- package/session/index.d.ts.map +1 -1
- package/session/index.js.map +1 -1
- package/session/useSessionUsage.d.ts +25 -0
- package/session/useSessionUsage.d.ts.map +1 -1
- package/session/useSessionUsage.js +11 -0
- package/session/useSessionUsage.js.map +1 -1
- package/settings/settings-nav.d.ts.map +1 -1
- package/settings/settings-nav.js +7 -1
- package/settings/settings-nav.js.map +1 -1
- package/settings/useSettingsNavGroups.d.ts.map +1 -1
- package/settings/useSettingsNavGroups.js +4 -1
- package/settings/useSettingsNavGroups.js.map +1 -1
- package/sharing/ShareAgentDialog.d.ts.map +1 -1
- package/sharing/ShareAgentDialog.js +4 -21
- package/sharing/ShareAgentDialog.js.map +1 -1
- package/sidebar/WorkspaceSidebar.d.ts.map +1 -1
- package/sidebar/WorkspaceSidebar.js +2 -1
- package/sidebar/WorkspaceSidebar.js.map +1 -1
- package/skill/SkillDiffDialog.d.ts.map +1 -1
- package/skill/SkillDiffDialog.js +5 -21
- package/skill/SkillDiffDialog.js.map +1 -1
- package/skill/SkillFileBrowser.d.ts.map +1 -1
- package/skill/SkillFileBrowser.js +2 -1
- package/skill/SkillFileBrowser.js.map +1 -1
- package/skill/internal/fetchAndUnpackArtifact.d.ts +1 -1
- package/skill/internal/fetchAndUnpackArtifact.d.ts.map +1 -1
- package/skill/internal/fetchAndUnpackArtifact.js +47 -3
- package/skill/internal/fetchAndUnpackArtifact.js.map +1 -1
- package/skill/useSkillDiff.d.ts.map +1 -1
- package/skill/useSkillDiff.js +7 -1
- package/skill/useSkillDiff.js.map +1 -1
- package/skill/useSkillUpload.d.ts.map +1 -1
- package/skill/useSkillUpload.js +22 -4
- package/skill/useSkillUpload.js.map +1 -1
- package/src/__tests__/bare-host-resets.layout.test.tsx +184 -0
- package/src/access/ManageAccessDialog.tsx +7 -27
- package/src/agent/steps/IdentityStep.tsx +2 -1
- package/src/agent-instance/AgentInstanceDetailPanel.tsx +2 -1
- package/src/agent-instance/CreateAgentInstanceDialog.tsx +14 -27
- package/src/api-key/CreateApiKeyForm.tsx +2 -1
- package/src/attachment/AttachmentImageLightbox.tsx +13 -36
- package/src/channel/ChannelConversationsDialog.tsx +10 -28
- package/src/channel/ChannelCredentialsDialog.tsx +8 -28
- package/src/channel/ChannelTemplatesDialog.tsx +12 -30
- package/src/channel/ConnectSlackDialog.tsx +10 -31
- package/src/channel/ConnectWhatsAppDialog.tsx +8 -30
- package/src/channel/connect/ServingAppSection.tsx +2 -1
- package/src/channel-app/CreateChannelAppForm.tsx +2 -1
- package/src/conversation/ConversationAttentionBanner.tsx +64 -19
- package/src/conversation/ConversationListPane.tsx +39 -17
- package/src/conversation/ConversationTimelineView.tsx +2 -1
- package/src/conversation/ConversationsWorkbench.tsx +1 -0
- package/src/conversation/__tests__/ConversationAttentionBanner.test.tsx +76 -2
- package/src/conversation/__tests__/ConversationListPane.test.tsx +15 -4
- package/src/cursor-accounts/CursorAccountsConsole.tsx +2 -1
- package/src/cursor-accounts/MemberKeysPanel.tsx +2 -1
- package/src/dashboard/DashboardFailedRuns.tsx +2 -1
- package/src/dependency-graph/DependencyGraph.tsx +2 -1
- package/src/dependency-graph/DependencyTreeNode.tsx +2 -1
- package/src/environment/EnvironmentPicker.tsx +2 -1
- package/src/error/SecretFlowErrorGuide.tsx +3 -2
- package/src/execution/ApprovalCard.tsx +23 -2
- package/src/execution/ArtifactContentBody.tsx +2 -1
- package/src/execution/ArtifactPreviewModal.tsx +15 -27
- package/src/execution/ArtifactsWidget.tsx +2 -1
- package/src/execution/FileChangeProgressBar.tsx +2 -1
- package/src/execution/TodoList.tsx +2 -1
- package/src/execution/ToolCallItem.tsx +19 -8
- package/src/execution/WriteBacksWidget.tsx +2 -1
- package/src/execution/__tests__/intent-title.test.tsx +221 -0
- package/src/execution/index.ts +3 -0
- package/src/execution/tool-categories.ts +103 -5
- package/src/execution/tool-presenter.ts +22 -1
- package/src/iam-policy/PeopleWithAccess.tsx +2 -1
- package/src/iam-policy/PrincipalPicker.tsx +2 -0
- package/src/iam-policy/RoleSelector.tsx +2 -1
- package/src/identity-provider/CreateIdentityProviderForm.tsx +2 -1
- package/src/identity-provider/IdentityProviderDetailPanel.tsx +2 -1
- package/src/identity-provider/IdentityProviderWizard.tsx +2 -1
- package/src/index.ts +16 -0
- package/src/internal/DialogShell.tsx +169 -0
- package/src/internal/__tests__/DialogShell.test.tsx +223 -0
- package/src/internal/element-resets.ts +33 -0
- package/src/internal/file-tree/FileTreeNode.tsx +2 -1
- package/src/internal/markdown-components.tsx +15 -5
- package/src/invitation/InvitationManager.tsx +3 -2
- package/src/manifest/ApplyManifestDialog.tsx +10 -27
- package/src/manifest/EditResourceYamlDialog.tsx +4 -31
- package/src/mcp-server/McpServerConnectDialog.tsx +15 -29
- package/src/mcp-server/McpServerDetailView.tsx +12 -24
- package/src/mcp-server/steps/IdentityTransportStep.tsx +3 -2
- package/src/platform-client/CreatePlatformClientForm.tsx +4 -3
- package/src/platform-client/PlatformClientDetailPanel.tsx +4 -3
- package/src/pricing-governance/BaselineEditor.tsx +3 -2
- package/src/pricing-governance/PricingGovernanceConsole.tsx +2 -1
- package/src/provider-standing/ProviderStandingAccessNotice.tsx +36 -0
- package/src/provider-standing/ProviderStandingConsole.tsx +216 -0
- package/src/provider-standing/__tests__/ProviderStandingConsole.test.tsx +143 -0
- package/src/provider-standing/index.ts +8 -0
- package/src/provider-standing/useProviderStanding.ts +50 -0
- package/src/provider.tsx +12 -0
- package/src/resource-creation/StepIndicator.tsx +2 -1
- package/src/resource-detail/ConfirmDialog.tsx +9 -30
- package/src/schedule/ScheduleDetailView.tsx +3 -2
- package/src/schedule/ScheduleRunsTable.tsx +2 -1
- package/src/session/__tests__/UsageTab.test.tsx +136 -0
- package/src/session/__tests__/useSessionUsage.test.ts +19 -0
- package/src/session/facets/ArtifactsTab.tsx +2 -1
- package/src/session/facets/ChangesTab.tsx +2 -1
- package/src/session/facets/UsageTab.tsx +98 -6
- package/src/session/index.ts +1 -0
- package/src/session/useSessionUsage.ts +37 -0
- package/src/settings/__tests__/useSettingsNavGroups.test.tsx +11 -1
- package/src/settings/settings-nav.ts +7 -0
- package/src/settings/useSettingsNavGroups.ts +8 -1
- package/src/sharing/ShareAgentDialog.tsx +9 -30
- package/src/sidebar/WorkspaceSidebar.tsx +2 -1
- package/src/skill/SkillDiffDialog.tsx +13 -36
- package/src/skill/SkillFileBrowser.tsx +2 -1
- package/src/skill/__tests__/SkillFileBrowser.test.tsx +10 -2
- package/src/skill/__tests__/fetchAndUnpackArtifact.test.ts +90 -0
- package/src/skill/__tests__/useSkillUpload.test.ts +69 -0
- package/src/skill/internal/fetchAndUnpackArtifact.ts +54 -4
- package/src/skill/useSkillDiff.ts +7 -1
- package/src/skill/useSkillUpload.ts +25 -6
- package/src/workflow/FailedRunsWidget.tsx +2 -1
- package/src/workflow/PendingApprovalsWidget.tsx +2 -1
- package/src/workflow/ViewYamlDialog.tsx +18 -37
- package/src/workflow/WorkflowArchitectDialog.tsx +11 -43
- package/src/workflow/WorkflowExplainDialog.tsx +11 -37
- package/src/workflow/WorkflowGraphFullscreenDialog.tsx +14 -26
- package/src/workflow/WorkflowRunDialog.tsx +21 -48
- package/src/workflow/execution-comparison/ExecutionComparisonPicker.tsx +14 -31
- package/src/workflow/facets/WorkflowArtifactsTab.tsx +2 -1
- package/src/workflow/facets/WorkflowUsageTab.tsx +2 -1
- package/src/workflow/inspector/WorkflowSummaryPanel.tsx +2 -1
- package/src/workflow/inspector/tabs/BranchesTab.tsx +2 -1
- package/src/workflow/inspector/tabs/IterationTab.tsx +2 -1
- package/src/workflow/instance/CreateWorkflowInstanceDialog.tsx +14 -27
- package/src/workflow/instance/WorkflowInstanceDetailPanel.tsx +2 -1
- package/src/workflow/templates/WorkflowTemplatePreview.tsx +18 -28
- package/src/workspace/ExplorerTree.tsx +2 -1
- package/src/workspace/WorkspaceContentSearch.tsx +2 -1
- package/src/workspace/WorkspaceFileSearch.tsx +2 -1
- package/src/workspace/WorkspaceSummary.tsx +2 -1
- package/styles.css +1 -1
- package/workflow/FailedRunsWidget.d.ts.map +1 -1
- package/workflow/FailedRunsWidget.js +2 -1
- package/workflow/FailedRunsWidget.js.map +1 -1
- package/workflow/PendingApprovalsWidget.d.ts.map +1 -1
- package/workflow/PendingApprovalsWidget.js +2 -1
- package/workflow/PendingApprovalsWidget.js.map +1 -1
- package/workflow/ViewYamlDialog.d.ts.map +1 -1
- package/workflow/ViewYamlDialog.js +10 -29
- package/workflow/ViewYamlDialog.js.map +1 -1
- package/workflow/WorkflowArchitectDialog.d.ts.map +1 -1
- package/workflow/WorkflowArchitectDialog.js +5 -24
- package/workflow/WorkflowArchitectDialog.js.map +1 -1
- package/workflow/WorkflowExplainDialog.d.ts.map +1 -1
- package/workflow/WorkflowExplainDialog.js +5 -21
- package/workflow/WorkflowExplainDialog.js.map +1 -1
- package/workflow/WorkflowGraphFullscreenDialog.d.ts.map +1 -1
- package/workflow/WorkflowGraphFullscreenDialog.js +11 -17
- package/workflow/WorkflowGraphFullscreenDialog.js.map +1 -1
- package/workflow/WorkflowRunDialog.d.ts.map +1 -1
- package/workflow/WorkflowRunDialog.js +13 -29
- package/workflow/WorkflowRunDialog.js.map +1 -1
- package/workflow/execution-comparison/ExecutionComparisonPicker.d.ts.map +1 -1
- package/workflow/execution-comparison/ExecutionComparisonPicker.js +8 -26
- package/workflow/execution-comparison/ExecutionComparisonPicker.js.map +1 -1
- package/workflow/facets/WorkflowArtifactsTab.d.ts.map +1 -1
- package/workflow/facets/WorkflowArtifactsTab.js +2 -1
- package/workflow/facets/WorkflowArtifactsTab.js.map +1 -1
- package/workflow/facets/WorkflowUsageTab.d.ts.map +1 -1
- package/workflow/facets/WorkflowUsageTab.js +2 -1
- package/workflow/facets/WorkflowUsageTab.js.map +1 -1
- package/workflow/inspector/WorkflowSummaryPanel.d.ts.map +1 -1
- package/workflow/inspector/WorkflowSummaryPanel.js +2 -1
- package/workflow/inspector/WorkflowSummaryPanel.js.map +1 -1
- package/workflow/inspector/tabs/BranchesTab.d.ts.map +1 -1
- package/workflow/inspector/tabs/BranchesTab.js +2 -1
- package/workflow/inspector/tabs/BranchesTab.js.map +1 -1
- package/workflow/inspector/tabs/IterationTab.d.ts.map +1 -1
- package/workflow/inspector/tabs/IterationTab.js +2 -1
- package/workflow/inspector/tabs/IterationTab.js.map +1 -1
- package/workflow/instance/CreateWorkflowInstanceDialog.d.ts.map +1 -1
- package/workflow/instance/CreateWorkflowInstanceDialog.js +7 -20
- package/workflow/instance/CreateWorkflowInstanceDialog.js.map +1 -1
- package/workflow/instance/WorkflowInstanceDetailPanel.d.ts.map +1 -1
- package/workflow/instance/WorkflowInstanceDetailPanel.js +2 -1
- package/workflow/instance/WorkflowInstanceDetailPanel.js.map +1 -1
- package/workflow/templates/WorkflowTemplatePreview.d.ts +1 -1
- package/workflow/templates/WorkflowTemplatePreview.d.ts.map +1 -1
- package/workflow/templates/WorkflowTemplatePreview.js +10 -22
- package/workflow/templates/WorkflowTemplatePreview.js.map +1 -1
- package/workspace/ExplorerTree.d.ts.map +1 -1
- package/workspace/ExplorerTree.js +2 -1
- package/workspace/ExplorerTree.js.map +1 -1
- package/workspace/WorkspaceContentSearch.d.ts.map +1 -1
- package/workspace/WorkspaceContentSearch.js +2 -1
- package/workspace/WorkspaceContentSearch.js.map +1 -1
- package/workspace/WorkspaceFileSearch.d.ts.map +1 -1
- package/workspace/WorkspaceFileSearch.js +2 -1
- package/workspace/WorkspaceFileSearch.js.map +1 -1
- package/workspace/WorkspaceSummary.d.ts.map +1 -1
- package/workspace/WorkspaceSummary.js +2 -1
- package/workspace/WorkspaceSummary.js.map +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ServiceTier } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
5
|
+
import { useSessionUsage, type ExecutionUsageEntry } from "../useSessionUsage.js";
|
|
6
|
+
import { UsageWidget, formatCost } from "../../execution/UsageWidget.js";
|
|
6
7
|
|
|
7
8
|
export interface UsageTabProps {
|
|
8
9
|
readonly executions: readonly AgentExecution[];
|
|
@@ -11,9 +12,16 @@ export interface UsageTabProps {
|
|
|
11
12
|
/**
|
|
12
13
|
* Usage facet for the session panel (a `useSessionRailViews` rail view).
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Renders the session totals ({@link UsageWidget}) plus the #362 model
|
|
16
|
+
* provenance list: per execution, the billing-RESOLVED model with its
|
|
17
|
+
* cost — for a Cursor Auto run, the only honest answer to "which model
|
|
18
|
+
* actually ran and what did it cost", since the requested model is empty
|
|
19
|
+
* by definition there — paired with the tier the runner REQUESTED (the
|
|
20
|
+
* streaming summary's audit record that the account default was never
|
|
21
|
+
* left in control). Requested-vs-billed divergence is a platform alarm
|
|
22
|
+
* (`stigmer.billing.service_tier.mismatch`), not a per-row UI concern.
|
|
23
|
+
*
|
|
24
|
+
* Shows an empty state when no usage data is available.
|
|
17
25
|
*/
|
|
18
26
|
export function UsageTab({ executions }: UsageTabProps) {
|
|
19
27
|
const usage = useSessionUsage(executions);
|
|
@@ -28,5 +36,89 @@ export function UsageTab({ executions }: UsageTabProps) {
|
|
|
28
36
|
);
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
return
|
|
39
|
+
return (
|
|
40
|
+
<div className="stg:flex stg:flex-col stg:gap-4">
|
|
41
|
+
<UsageWidget executions={executions} />
|
|
42
|
+
{usage.executionBreakdown.length > 0 && (
|
|
43
|
+
<ExecutionModelList
|
|
44
|
+
entries={usage.executionBreakdown}
|
|
45
|
+
executions={executions}
|
|
46
|
+
/>
|
|
47
|
+
)}
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Per-execution model provenance rows, in the report's chronological
|
|
54
|
+
* order: `#N resolved-model [tier requested] [Estimated] $cost`.
|
|
55
|
+
*/
|
|
56
|
+
function ExecutionModelList({
|
|
57
|
+
entries,
|
|
58
|
+
executions,
|
|
59
|
+
}: {
|
|
60
|
+
readonly entries: readonly ExecutionUsageEntry[];
|
|
61
|
+
readonly executions: readonly AgentExecution[];
|
|
62
|
+
}) {
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
className="stg:flex stg:flex-col stg:gap-1"
|
|
66
|
+
role="list"
|
|
67
|
+
aria-label="Per-execution model and tier"
|
|
68
|
+
>
|
|
69
|
+
<div className="stg:text-xs stg:font-medium stg:text-foreground">
|
|
70
|
+
Models per run
|
|
71
|
+
</div>
|
|
72
|
+
{entries.map((entry, index) => {
|
|
73
|
+
const requestedTier = requestedTierLabel(executions, entry.executionId);
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
key={entry.executionId}
|
|
77
|
+
className="stg:flex stg:items-baseline stg:justify-between stg:gap-2 stg:text-xs stg:text-muted-foreground"
|
|
78
|
+
role="listitem"
|
|
79
|
+
>
|
|
80
|
+
<span className="stg:truncate">
|
|
81
|
+
<span className="stg:tabular-nums">#{index + 1}</span>{" "}
|
|
82
|
+
{entry.resolvedModel || "—"}
|
|
83
|
+
{requestedTier && (
|
|
84
|
+
<span className="stg:ml-1 stg:rounded stg:bg-muted stg:px-1 stg:py-0.5 stg:text-[10px] stg:font-medium stg:leading-none">
|
|
85
|
+
{requestedTier} requested
|
|
86
|
+
</span>
|
|
87
|
+
)}
|
|
88
|
+
{entry.isEstimated && (
|
|
89
|
+
<span className="stg:ml-1 stg:rounded stg:bg-muted stg:px-1 stg:py-0.5 stg:text-[10px] stg:font-medium stg:leading-none">
|
|
90
|
+
Estimated
|
|
91
|
+
</span>
|
|
92
|
+
)}
|
|
93
|
+
</span>
|
|
94
|
+
<span className="stg:shrink-0 stg:tabular-nums">
|
|
95
|
+
{formatCost(entry.billableCostUsd)}
|
|
96
|
+
</span>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
})}
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The tier the runner requested for one execution, from its streaming
|
|
106
|
+
* usage summary — present once the runner has translated the execution
|
|
107
|
+
* config, absent for executions that predate the tier attribute. Never
|
|
108
|
+
* "unspecified": the runner records the RESOLVED tier (#357's audit
|
|
109
|
+
* contract).
|
|
110
|
+
*/
|
|
111
|
+
function requestedTierLabel(
|
|
112
|
+
executions: readonly AgentExecution[],
|
|
113
|
+
executionId: string,
|
|
114
|
+
): string | null {
|
|
115
|
+
const match = executions.find((e) => e.metadata?.id === executionId);
|
|
116
|
+
switch (match?.status?.streamingUsage?.requestedServiceTier) {
|
|
117
|
+
case ServiceTier.FAST:
|
|
118
|
+
return "fast";
|
|
119
|
+
case ServiceTier.STANDARD:
|
|
120
|
+
return "standard";
|
|
121
|
+
default:
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
32
124
|
}
|
package/src/session/index.ts
CHANGED
|
@@ -41,6 +41,25 @@ export interface ModelCostEntry {
|
|
|
41
41
|
readonly callCount: number;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Per-execution model provenance from billing records (stigmer/stigmer#362).
|
|
46
|
+
*/
|
|
47
|
+
export interface ExecutionUsageEntry {
|
|
48
|
+
/** Execution identifier (`metadata.id`). */
|
|
49
|
+
readonly executionId: string;
|
|
50
|
+
/**
|
|
51
|
+
* Billing-resolved primary model — what the provider actually served.
|
|
52
|
+
* For a Cursor Auto execution this is the after-the-fact answer to
|
|
53
|
+
* "which model did Auto pick", which the requested model (empty by
|
|
54
|
+
* definition there) can never give.
|
|
55
|
+
*/
|
|
56
|
+
readonly resolvedModel: string;
|
|
57
|
+
/** Billable cost in USD for this execution. */
|
|
58
|
+
readonly billableCostUsd: number;
|
|
59
|
+
/** `true` while this execution's records are still provisional. */
|
|
60
|
+
readonly isEstimated: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
44
63
|
/** Return value of {@link useSessionUsage}. */
|
|
45
64
|
export interface UseSessionUsageReturn {
|
|
46
65
|
/** Aggregate estimated cost in USD across all models. */
|
|
@@ -59,6 +78,13 @@ export interface UseSessionUsageReturn {
|
|
|
59
78
|
readonly llmCallCount: number;
|
|
60
79
|
/** Per-model cost and token breakdown. */
|
|
61
80
|
readonly modelBreakdown: readonly ModelCostEntry[];
|
|
81
|
+
/**
|
|
82
|
+
* Per-execution resolved model + cost, chronological, from billing
|
|
83
|
+
* records (#362). Empty until the first authoritative record lands —
|
|
84
|
+
* the streaming fallback deliberately contributes none, because the
|
|
85
|
+
* runner only knows what it REQUESTED, never what the provider served.
|
|
86
|
+
*/
|
|
87
|
+
readonly executionBreakdown: readonly ExecutionUsageEntry[];
|
|
62
88
|
/** Model with the highest usage in this session. */
|
|
63
89
|
readonly primaryModel: string;
|
|
64
90
|
/** Provider of the primary model. */
|
|
@@ -82,6 +108,7 @@ const EMPTY: UseSessionUsageReturn = {
|
|
|
82
108
|
cacheCreationTokens: 0,
|
|
83
109
|
llmCallCount: 0,
|
|
84
110
|
modelBreakdown: [],
|
|
111
|
+
executionBreakdown: [],
|
|
85
112
|
primaryModel: "",
|
|
86
113
|
primaryProvider: "",
|
|
87
114
|
hasUsage: false,
|
|
@@ -122,6 +149,12 @@ function mapReport(report: GetSessionUsageReportOutput): UseSessionUsageReturn {
|
|
|
122
149
|
cacheCreationTokens: Number(agg.cacheCreationInputTokens),
|
|
123
150
|
llmCallCount,
|
|
124
151
|
modelBreakdown: report.modelBreakdown.map(mapModelUsage),
|
|
152
|
+
executionBreakdown: report.executions.map((e) => ({
|
|
153
|
+
executionId: e.executionId,
|
|
154
|
+
resolvedModel: e.primaryModel,
|
|
155
|
+
billableCostUsd: microsToUsd(e.billableCostMicros),
|
|
156
|
+
isEstimated: e.isEstimated,
|
|
157
|
+
})),
|
|
125
158
|
primaryModel: agg.primaryModel,
|
|
126
159
|
primaryProvider: agg.primaryProvider,
|
|
127
160
|
hasUsage: llmCallCount > 0 || totalTokens > 0 || billableCost > 0,
|
|
@@ -169,6 +202,10 @@ function aggregateStreamingUsage(
|
|
|
169
202
|
cacheReadTokens,
|
|
170
203
|
cacheCreationTokens,
|
|
171
204
|
llmCallCount: turnCount,
|
|
205
|
+
// No executionBreakdown here on purpose: the runner only knows the
|
|
206
|
+
// REQUESTED model; resolved-model rows exist only once billing
|
|
207
|
+
// records land (#362).
|
|
208
|
+
executionBreakdown: [],
|
|
172
209
|
modelBreakdown: model
|
|
173
210
|
? [
|
|
174
211
|
{
|
|
@@ -48,6 +48,7 @@ describe("useSettingsNavGroups", () => {
|
|
|
48
48
|
verdicts = {
|
|
49
49
|
can_manage_model_pricing: true,
|
|
50
50
|
can_manage_cursor_accounts: true,
|
|
51
|
+
can_view_provider_standing: true,
|
|
51
52
|
};
|
|
52
53
|
render(<GroupsProbe />);
|
|
53
54
|
|
|
@@ -56,7 +57,7 @@ describe("useSettingsNavGroups", () => {
|
|
|
56
57
|
`${BASE_LABELS},${PLATFORM_SETTINGS_NAV_GROUP.label}`,
|
|
57
58
|
);
|
|
58
59
|
expect(el.getAttribute("data-platform-items")).toBe(
|
|
59
|
-
"Pricing Governance,Cursor Accounts",
|
|
60
|
+
"Pricing Governance,Cursor Accounts,Provider Standing",
|
|
60
61
|
);
|
|
61
62
|
});
|
|
62
63
|
|
|
@@ -78,6 +79,15 @@ describe("useSettingsNavGroups", () => {
|
|
|
78
79
|
);
|
|
79
80
|
});
|
|
80
81
|
|
|
82
|
+
it("filters per item: standing-only operator sees only Provider Standing", () => {
|
|
83
|
+
verdicts = { can_view_provider_standing: true };
|
|
84
|
+
render(<GroupsProbe />);
|
|
85
|
+
|
|
86
|
+
expect(screen.getByTestId("groups").getAttribute("data-platform-items")).toBe(
|
|
87
|
+
"Provider Standing",
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
81
91
|
it("returns exactly the base groups when not authorized", () => {
|
|
82
92
|
function IdentityProbe() {
|
|
83
93
|
const groups = useSettingsNavGroups();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ComponentType } from "react";
|
|
2
2
|
import {
|
|
3
|
+
Activity,
|
|
3
4
|
AppWindow,
|
|
4
5
|
BarChart3,
|
|
5
6
|
Box,
|
|
@@ -123,5 +124,11 @@ export const PLATFORM_SETTINGS_NAV_GROUP: SettingsNavGroup = {
|
|
|
123
124
|
icon: MousePointerClick,
|
|
124
125
|
requiredPermission: "can_manage_cursor_accounts",
|
|
125
126
|
},
|
|
127
|
+
{
|
|
128
|
+
href: "/settings/provider-standing",
|
|
129
|
+
label: "Provider Standing",
|
|
130
|
+
icon: Activity,
|
|
131
|
+
requiredPermission: "can_view_provider_standing",
|
|
132
|
+
},
|
|
126
133
|
],
|
|
127
134
|
};
|
|
@@ -52,14 +52,21 @@ export function useSettingsNavGroups(): readonly SettingsNavGroup[] {
|
|
|
52
52
|
"can_manage_cursor_accounts",
|
|
53
53
|
{ fail: "closed" },
|
|
54
54
|
);
|
|
55
|
+
const providerStanding = useCheckPermission(
|
|
56
|
+
PLATFORM_RESOURCE,
|
|
57
|
+
"can_view_provider_standing",
|
|
58
|
+
{ fail: "closed" },
|
|
59
|
+
);
|
|
55
60
|
|
|
56
61
|
const pricingAllowed = pricing.allowed;
|
|
57
62
|
const cursorAccountsAllowed = cursorAccounts.allowed;
|
|
63
|
+
const providerStandingAllowed = providerStanding.allowed;
|
|
58
64
|
|
|
59
65
|
return useMemo(() => {
|
|
60
66
|
const verdicts: Record<string, boolean> = {
|
|
61
67
|
can_manage_model_pricing: pricingAllowed,
|
|
62
68
|
can_manage_cursor_accounts: cursorAccountsAllowed,
|
|
69
|
+
can_view_provider_standing: providerStandingAllowed,
|
|
63
70
|
};
|
|
64
71
|
|
|
65
72
|
const visibleItems = PLATFORM_SETTINGS_NAV_GROUP.items.filter(
|
|
@@ -77,5 +84,5 @@ export function useSettingsNavGroups(): readonly SettingsNavGroup[] {
|
|
|
77
84
|
...SETTINGS_NAV_GROUPS,
|
|
78
85
|
{ ...PLATFORM_SETTINGS_NAV_GROUP, items: visibleItems },
|
|
79
86
|
];
|
|
80
|
-
}, [pricingAllowed, cursorAccountsAllowed]);
|
|
87
|
+
}, [pricingAllowed, cursorAccountsAllowed, providerStandingAllowed]);
|
|
81
88
|
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useId, useMemo, useRef, useState, type FormEvent } from "react";
|
|
4
4
|
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { DialogShell } from "../internal/DialogShell.js";
|
|
6
|
+
import { UNSTYLED_LIST } from "../internal/element-resets.js";
|
|
5
7
|
import {
|
|
6
8
|
MAX_ALLOWED_ORIGINS,
|
|
7
9
|
StigmerError,
|
|
@@ -137,8 +139,6 @@ export function ShareAgentDialog({
|
|
|
137
139
|
onSharingChanged,
|
|
138
140
|
modal = true,
|
|
139
141
|
}: ShareAgentDialogProps) {
|
|
140
|
-
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
141
|
-
|
|
142
142
|
// Instance-scoped title id (oss#593): a reusable component must not
|
|
143
143
|
// hardcode DOM ids — hosts legitimately mount this dialog more than once
|
|
144
144
|
// per page (e.g. zone-cached detail pages), and duplicate ids break the
|
|
@@ -146,36 +146,15 @@ export function ShareAgentDialog({
|
|
|
146
146
|
const titleId = useId();
|
|
147
147
|
|
|
148
148
|
const handleClose = useCallback(() => {
|
|
149
|
-
dialogRef.current?.close();
|
|
150
149
|
onOpenChange(false);
|
|
151
150
|
}, [onOpenChange]);
|
|
152
151
|
|
|
153
|
-
// Sync native dialog open state (matches the SDK dialog convention).
|
|
154
|
-
// Non-modal hosts pass `open` as a plain attribute instead — the dialog
|
|
155
|
-
// renders in-flow with no top layer to manage.
|
|
156
|
-
const prevOpenRef = useRef(false);
|
|
157
|
-
if (modal && open !== prevOpenRef.current) {
|
|
158
|
-
prevOpenRef.current = open;
|
|
159
|
-
if (open) {
|
|
160
|
-
requestAnimationFrame(() => {
|
|
161
|
-
if (dialogRef.current && !dialogRef.current.open) {
|
|
162
|
-
dialogRef.current.showModal();
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
} else if (dialogRef.current?.open) {
|
|
166
|
-
dialogRef.current.close();
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
152
|
return (
|
|
171
|
-
<
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"stg:w-full stg:max-w-lg stg:rounded-xl stg:border stg:border-border stg:bg-popover stg:p-0 stg:shadow-xl",
|
|
177
|
-
modal ? "stg:fixed stg:inset-0 stg:m-auto stg:backdrop:bg-backdrop" : "stg:relative",
|
|
178
|
-
)}
|
|
153
|
+
<DialogShell
|
|
154
|
+
open={open}
|
|
155
|
+
onOpenChange={onOpenChange}
|
|
156
|
+
modal={modal}
|
|
157
|
+
width="lg"
|
|
179
158
|
aria-labelledby={titleId}
|
|
180
159
|
>
|
|
181
160
|
{/* Body mounts only while open so its draft state resets per
|
|
@@ -191,7 +170,7 @@ export function ShareAgentDialog({
|
|
|
191
170
|
titleId={titleId}
|
|
192
171
|
/>
|
|
193
172
|
)}
|
|
194
|
-
</
|
|
173
|
+
</DialogShell>
|
|
195
174
|
);
|
|
196
175
|
}
|
|
197
176
|
|
|
@@ -1338,7 +1317,7 @@ function OriginsEditor({
|
|
|
1338
1317
|
</p>
|
|
1339
1318
|
|
|
1340
1319
|
{draft.allowedOrigins.length > 0 && (
|
|
1341
|
-
<ul className="stg:mt-2 stg:flex stg:flex-col stg:divide-y stg:divide-border stg:rounded-md stg:border stg:border-border">
|
|
1320
|
+
<ul className={cn(UNSTYLED_LIST, "stg:mt-2 stg:flex stg:flex-col stg:divide-y stg:divide-border stg:rounded-md stg:border stg:border-border")}>
|
|
1342
1321
|
{draft.allowedOrigins.map((origin) => (
|
|
1343
1322
|
<li
|
|
1344
1323
|
key={origin}
|
|
@@ -15,6 +15,7 @@ import type { RecentActivityEntry, RecentActivityGroup } from "../activity/types
|
|
|
15
15
|
import { groupRecentActivityByTime } from "../activity/group-activity.js";
|
|
16
16
|
import { formatRelativeTime } from "../activity/format-relative-time.js";
|
|
17
17
|
import { recentActivityStatusBadge } from "../activity/entry-status-badge.js";
|
|
18
|
+
import { UNSTYLED_LIST } from "../internal/element-resets.js";
|
|
18
19
|
import { ScrollArea } from "../internal/scroll-area.js";
|
|
19
20
|
import {
|
|
20
21
|
Tooltip,
|
|
@@ -313,7 +314,7 @@ function ActivityGroupList({
|
|
|
313
314
|
<p className="stg:text-sidebar-muted-foreground stg:mb-1 stg:px-2 stg:text-[10px] stg:font-medium stg:tracking-wider stg:uppercase">
|
|
314
315
|
{group.label}
|
|
315
316
|
</p>
|
|
316
|
-
<ul className=
|
|
317
|
+
<ul className={`${UNSTYLED_LIST} stg:space-y-0.5`} role="list">
|
|
317
318
|
{group.entries.map((entry) => (
|
|
318
319
|
<ActivityEntry
|
|
319
320
|
key={entry.id}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useCallback
|
|
3
|
+
import { useCallback } from "react";
|
|
4
4
|
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { DialogShell } from "../internal/DialogShell.js";
|
|
5
6
|
import { useSkillDiff } from "./useSkillDiff.js";
|
|
6
7
|
import { MultiFileDiffView } from "../version-history/MultiFileDiffView.js";
|
|
7
8
|
import { ErrorMessage } from "../error/ErrorMessage.js";
|
|
@@ -57,31 +58,9 @@ export interface SkillDiffDialogProps {
|
|
|
57
58
|
* ```
|
|
58
59
|
*/
|
|
59
60
|
export function SkillDiffDialog({ state, onClose }: SkillDiffDialogProps) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const dialog = dialogRef.current;
|
|
64
|
-
if (!dialog) return;
|
|
65
|
-
if (state && !dialog.open) {
|
|
66
|
-
dialog.showModal();
|
|
67
|
-
} else if (!state && dialog.open) {
|
|
68
|
-
dialog.close();
|
|
69
|
-
}
|
|
70
|
-
}, [state]);
|
|
71
|
-
|
|
72
|
-
const handleDialogCancel = useCallback(
|
|
73
|
-
(e: React.SyntheticEvent) => {
|
|
74
|
-
e.preventDefault();
|
|
75
|
-
onClose();
|
|
76
|
-
},
|
|
77
|
-
[onClose],
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const handleBackdropClick = useCallback(
|
|
81
|
-
(e: React.MouseEvent<HTMLDialogElement>) => {
|
|
82
|
-
if (e.target === e.currentTarget) {
|
|
83
|
-
onClose();
|
|
84
|
-
}
|
|
61
|
+
const handleOpenChange = useCallback(
|
|
62
|
+
(open: boolean) => {
|
|
63
|
+
if (!open) onClose();
|
|
85
64
|
},
|
|
86
65
|
[onClose],
|
|
87
66
|
);
|
|
@@ -94,15 +73,13 @@ export function SkillDiffDialog({ state, onClose }: SkillDiffDialogProps) {
|
|
|
94
73
|
if (!state) return null;
|
|
95
74
|
|
|
96
75
|
return (
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
"stg:open:animate-in stg:open:fade-in-0 stg:open:zoom-in-95",
|
|
105
|
-
)}
|
|
76
|
+
<DialogShell
|
|
77
|
+
open
|
|
78
|
+
onOpenChange={handleOpenChange}
|
|
79
|
+
width="4xl"
|
|
80
|
+
dismissOnBackdrop
|
|
81
|
+
className="stg:h-[85vh]"
|
|
82
|
+
aria-label="Skill version diff"
|
|
106
83
|
>
|
|
107
84
|
<div className="stg:flex stg:h-full stg:flex-col">
|
|
108
85
|
{/* Header */}
|
|
@@ -142,7 +119,7 @@ export function SkillDiffDialog({ state, onClose }: SkillDiffDialogProps) {
|
|
|
142
119
|
) : null}
|
|
143
120
|
</div>
|
|
144
121
|
</div>
|
|
145
|
-
</
|
|
122
|
+
</DialogShell>
|
|
146
123
|
);
|
|
147
124
|
}
|
|
148
125
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useMemo, useState } from "react";
|
|
4
4
|
import Markdown from "react-markdown";
|
|
5
5
|
import { cn } from "@stigmer/theme";
|
|
6
|
+
import { UNSTYLED_LIST } from "../internal/element-resets.js";
|
|
6
7
|
import { MARKDOWN_COMPONENTS, REMARK_PLUGINS, stripFrontmatter } from "../internal/markdown-components.js";
|
|
7
8
|
import { buildFileTree, FileTreeNode } from "../internal/file-tree/index.js";
|
|
8
9
|
import { useSkillArtifact } from "./useSkillArtifact.js";
|
|
@@ -132,7 +133,7 @@ export function SkillFileBrowser({
|
|
|
132
133
|
className="stg:border-b stg:border-border stg:md:border-b-0 stg:md:border-r stg:overflow-y-auto"
|
|
133
134
|
aria-label="Skill package file tree"
|
|
134
135
|
>
|
|
135
|
-
<ul className="stg:py-1" role="tree">
|
|
136
|
+
<ul className={cn(UNSTYLED_LIST, "stg:py-1")} role="tree">
|
|
136
137
|
{treeNodes.map((node) => (
|
|
137
138
|
<FileTreeNode
|
|
138
139
|
key={node.path}
|
|
@@ -2,7 +2,7 @@ import { describe, it, expect, vi, afterEach } from "vitest";
|
|
|
2
2
|
import { render, screen, fireEvent } from "@testing-library/react";
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
import { zipSync, strToU8 } from "fflate";
|
|
5
|
-
import type
|
|
5
|
+
import { StigmerError, type Stigmer } from "@stigmer/sdk";
|
|
6
6
|
import { StigmerContext } from "../../context";
|
|
7
7
|
import { SkillFileBrowser } from "../SkillFileBrowser";
|
|
8
8
|
|
|
@@ -12,14 +12,22 @@ function wrapperFor(stigmer: Stigmer) {
|
|
|
12
12
|
);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/** Connect's Unimplemented code — what a pre-transfer-lane server answers. */
|
|
16
|
+
const CODE_UNIMPLEMENTED = 12;
|
|
17
|
+
|
|
15
18
|
/**
|
|
16
19
|
* Builds a real ZIP (via fflate, the same library the unpacker uses) and a
|
|
17
20
|
* Stigmer client whose `skill.getArtifact` serves it — so tests exercise the
|
|
18
21
|
* genuine fetch → unzip → browse path instead of stubbing the unpacker.
|
|
22
|
+
* The download-URL mint answers Unimplemented (a pre-transfer-lane server),
|
|
23
|
+
* pinning that the browser degrades to the unary lane it always used.
|
|
19
24
|
*/
|
|
20
25
|
function makeStigmerServing(files: Record<string, Uint8Array>) {
|
|
21
26
|
const getArtifact = vi.fn().mockResolvedValue({ artifact: zipSync(files) });
|
|
22
|
-
|
|
27
|
+
const getArtifactDownloadUrl = vi
|
|
28
|
+
.fn()
|
|
29
|
+
.mockRejectedValue(new StigmerError("unknown", "unimplemented", CODE_UNIMPLEMENTED));
|
|
30
|
+
return { skill: { getArtifact, getArtifactDownloadUrl } } as unknown as Stigmer;
|
|
23
31
|
}
|
|
24
32
|
|
|
25
33
|
function renderBrowser(stigmer: Stigmer) {
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Pins for the artifact fetch lane selection (stigmer#701): URL-first via
|
|
2
|
+
// getArtifactDownloadUrl, with the two deliberate browser degrade arms —
|
|
3
|
+
// Unimplemented mint (pre-lane server) and a failed URL fetch (the shape a
|
|
4
|
+
// missing bucket CORS policy takes in a browser).
|
|
5
|
+
import { describe, expect, it, vi } from "vitest";
|
|
6
|
+
import { strToU8, zipSync } from "fflate";
|
|
7
|
+
import { StigmerError, type Stigmer } from "@stigmer/sdk";
|
|
8
|
+
import { fetchAndUnpackArtifact } from "../internal/fetchAndUnpackArtifact.js";
|
|
9
|
+
|
|
10
|
+
const CODE_UNIMPLEMENTED = 12;
|
|
11
|
+
const ZIP = zipSync({ "SKILL.md": strToU8("# hi") });
|
|
12
|
+
|
|
13
|
+
function stigmerWith(overrides: {
|
|
14
|
+
mint?: ReturnType<typeof vi.fn>;
|
|
15
|
+
unary?: ReturnType<typeof vi.fn>;
|
|
16
|
+
fetch?: unknown;
|
|
17
|
+
}): Stigmer {
|
|
18
|
+
return {
|
|
19
|
+
skill: {
|
|
20
|
+
getArtifactDownloadUrl: overrides.mint,
|
|
21
|
+
getArtifact: overrides.unary,
|
|
22
|
+
},
|
|
23
|
+
fetch: overrides.fetch,
|
|
24
|
+
} as unknown as Stigmer;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("fetchAndUnpackArtifact lane selection", () => {
|
|
28
|
+
it("fetches via the minted download URL, never the unary lane", async () => {
|
|
29
|
+
const mint = vi.fn().mockResolvedValue({ url: "https://r2.example/skills/get" });
|
|
30
|
+
const unary = vi.fn();
|
|
31
|
+
const fetchImpl = vi.fn(async () => new Response(new Uint8Array(ZIP).buffer, { status: 200 }));
|
|
32
|
+
|
|
33
|
+
const result = await fetchAndUnpackArtifact(
|
|
34
|
+
stigmerWith({ mint, unary, fetch: fetchImpl }),
|
|
35
|
+
"skills/org/skill/hash.zip",
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
expect(fetchImpl).toHaveBeenCalledWith("https://r2.example/skills/get");
|
|
39
|
+
expect(unary).not.toHaveBeenCalled();
|
|
40
|
+
expect(result.contentMap.get("SKILL.md")).toBe("# hi");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("degrades to the unary lane when the mint answers Unimplemented (pre-lane server)", async () => {
|
|
44
|
+
const mint = vi
|
|
45
|
+
.fn()
|
|
46
|
+
.mockRejectedValue(new StigmerError("unknown", "unimplemented", CODE_UNIMPLEMENTED));
|
|
47
|
+
const unary = vi.fn().mockResolvedValue({ artifact: ZIP });
|
|
48
|
+
|
|
49
|
+
const result = await fetchAndUnpackArtifact(
|
|
50
|
+
stigmerWith({ mint, unary }),
|
|
51
|
+
"skills/org/skill/hash.zip",
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(unary).toHaveBeenCalledTimes(1);
|
|
55
|
+
expect(result.contentMap.get("SKILL.md")).toBe("# hi");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("degrades to the unary lane when the URL fetch itself fails (browser CORS shape), warning once", async () => {
|
|
59
|
+
const mint = vi.fn().mockResolvedValue({ url: "https://r2.example/skills/get" });
|
|
60
|
+
const unary = vi.fn().mockResolvedValue({ artifact: ZIP });
|
|
61
|
+
const fetchImpl = vi.fn(async () => {
|
|
62
|
+
throw new TypeError("Failed to fetch");
|
|
63
|
+
});
|
|
64
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const result = await fetchAndUnpackArtifact(
|
|
68
|
+
stigmerWith({ mint, unary, fetch: fetchImpl }),
|
|
69
|
+
"skills/org/skill/hash.zip",
|
|
70
|
+
);
|
|
71
|
+
expect(unary).toHaveBeenCalledTimes(1);
|
|
72
|
+
expect(warn).toHaveBeenCalledTimes(1);
|
|
73
|
+
expect(result.contentMap.get("SKILL.md")).toBe("# hi");
|
|
74
|
+
} finally {
|
|
75
|
+
warn.mockRestore();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("propagates a non-Unimplemented mint failure — a real error must not be masked", async () => {
|
|
80
|
+
const mint = vi
|
|
81
|
+
.fn()
|
|
82
|
+
.mockRejectedValue(new StigmerError("not-found", "no such artifact", 5));
|
|
83
|
+
const unary = vi.fn();
|
|
84
|
+
|
|
85
|
+
await expect(
|
|
86
|
+
fetchAndUnpackArtifact(stigmerWith({ mint, unary }), "skills/org/skill/hash.zip"),
|
|
87
|
+
).rejects.toThrow(/no such artifact/);
|
|
88
|
+
expect(unary).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { renderHook, act } from "@testing-library/react";
|
|
3
|
+
import { zipSync, strToU8 } from "fflate";
|
|
4
|
+
import { useSkillUpload } from "../useSkillUpload";
|
|
5
|
+
|
|
6
|
+
const SKILL_MD = "---\nname: my-skill\ndescription: A test skill\n---\n# My Skill\n";
|
|
7
|
+
|
|
8
|
+
/** Build a real ZIP (fflate, the same library the hook unpacks with) as a File. */
|
|
9
|
+
function zipFile(files: Record<string, Uint8Array>): File {
|
|
10
|
+
return new File([zipSync(files)], "skill.zip", { type: "application/zip" });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function process(files: Record<string, Uint8Array>) {
|
|
14
|
+
const { result } = renderHook(() => useSkillUpload());
|
|
15
|
+
await act(() => result.current.processFile(zipFile(files)));
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("useSkillUpload", () => {
|
|
20
|
+
it("accepts a root SKILL.md and produces a preview", async () => {
|
|
21
|
+
const result = await process({
|
|
22
|
+
"SKILL.md": strToU8(SKILL_MD),
|
|
23
|
+
"references/schema.md": strToU8("# Schema"),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
expect(result.current.validationError).toBeNull();
|
|
27
|
+
expect(result.current.preview?.name).toBe("my-skill");
|
|
28
|
+
expect(result.current.preview?.description).toBe("A test skill");
|
|
29
|
+
expect(result.current.artifact).not.toBeNull();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// The layout contract is root-only on both editions (DD-018, #452). The
|
|
33
|
+
// preview exists to catch the "zipped the folder instead of its contents"
|
|
34
|
+
// mistake BEFORE upload — accepting nested here and failing at push is the
|
|
35
|
+
// exact confusion issue #684 pins.
|
|
36
|
+
it("rejects a nested-only SKILL.md with the zip-the-contents hint", async () => {
|
|
37
|
+
const result = await process({
|
|
38
|
+
"my-skill/SKILL.md": strToU8(SKILL_MD),
|
|
39
|
+
"my-skill/references/schema.md": strToU8("# Schema"),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
expect(result.current.preview).toBeNull();
|
|
43
|
+
expect(result.current.artifact).toBeNull();
|
|
44
|
+
expect(result.current.validationError).toBe(
|
|
45
|
+
"Found my-skill/SKILL.md — SKILL.md must be at the archive root. " +
|
|
46
|
+
"Zip the skill folder's contents, not the folder itself.",
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("detects a deeply nested SKILL.md for the hint (any depth, server parity)", async () => {
|
|
51
|
+
const result = await process({
|
|
52
|
+
"wrapper/my-skill/SKILL.md": strToU8(SKILL_MD),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
expect(result.current.preview).toBeNull();
|
|
56
|
+
expect(result.current.validationError).toContain("Found wrapper/my-skill/SKILL.md");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("rejects an archive with no SKILL.md anywhere with the plain root-level message", async () => {
|
|
60
|
+
const result = await process({
|
|
61
|
+
"README.md": strToU8("# Not a skill"),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(result.current.preview).toBeNull();
|
|
65
|
+
expect(result.current.validationError).toBe(
|
|
66
|
+
"ZIP must contain a SKILL.md file at the root level",
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
});
|