@burdenoff/microfe-botmanor 2026.1027.2 → 2026.1028.1
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/dist/botlit/BotlitRoutes.js +142 -132
- package/dist/botlit/BotlitRoutes.js.map +1 -1
- package/dist/botlit/components/AgentApprovalPanel.js +144 -126
- package/dist/botlit/components/AgentApprovalPanel.js.map +1 -1
- package/dist/botlit/components/ModelRegistrationPanel.js +4 -4
- package/dist/botlit/components/RetentionStatusPanel.js +95 -0
- package/dist/botlit/components/RetentionStatusPanel.js.map +1 -0
- package/dist/botlit/components/VersionHistoryPanel.js +92 -83
- package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
- package/dist/botlit/hooks/index.js +1 -0
- package/dist/botlit/hooks/useRetention.js +31 -0
- package/dist/botlit/hooks/useRetention.js.map +1 -0
- package/dist/botlit/pages/A2AAgentDetailPage.js +212 -203
- package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -1
- package/dist/botlit/pages/A2ARegistryPage.js +129 -117
- package/dist/botlit/pages/A2ARegistryPage.js.map +1 -1
- package/dist/botlit/pages/AgentApprovalsPage.js +122 -110
- package/dist/botlit/pages/AgentApprovalsPage.js.map +1 -1
- package/dist/botlit/pages/AgentBuilderPage.js +18 -18
- package/dist/botlit/pages/AgentDetailPage.js +298 -273
- package/dist/botlit/pages/AgentDetailPage.js.map +1 -1
- package/dist/botlit/pages/AgentsListPage.js +145 -121
- package/dist/botlit/pages/AgentsListPage.js.map +1 -1
- package/dist/botlit/pages/BotChannelsTab.js +238 -226
- package/dist/botlit/pages/BotChannelsTab.js.map +1 -1
- package/dist/botlit/pages/BotDetailPage.js +307 -288
- package/dist/botlit/pages/BotDetailPage.js.map +1 -1
- package/dist/botlit/pages/BotWorkflowTab.js +125 -116
- package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
- package/dist/botlit/pages/BotsListPage.js +159 -144
- package/dist/botlit/pages/BotsListPage.js.map +1 -1
- package/dist/botlit/pages/BucketsPage.js +279 -258
- package/dist/botlit/pages/BucketsPage.js.map +1 -1
- package/dist/botlit/pages/ChannelDetailPage.js +346 -328
- package/dist/botlit/pages/ChannelDetailPage.js.map +1 -1
- package/dist/botlit/pages/ChannelRoutesPage.js +10 -10
- package/dist/botlit/pages/ChannelsPage.js +163 -148
- package/dist/botlit/pages/ChannelsPage.js.map +1 -1
- package/dist/botlit/pages/DashboardPage.js +129 -114
- package/dist/botlit/pages/DashboardPage.js.map +1 -1
- package/dist/botlit/pages/ExecutionDetailPage.js +145 -139
- package/dist/botlit/pages/ExecutionDetailPage.js.map +1 -1
- package/dist/botlit/pages/ExecutionsPage.js +14 -14
- package/dist/botlit/pages/InstalledPackagesPage.js +245 -227
- package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -1
- package/dist/botlit/pages/KnowledgeBaseDetailPage.js +168 -156
- package/dist/botlit/pages/KnowledgeBaseDetailPage.js.map +1 -1
- package/dist/botlit/pages/KnowledgeBasesPage.js +91 -79
- package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -1
- package/dist/botlit/pages/MCPServerDetailPage.js +200 -188
- package/dist/botlit/pages/MCPServerDetailPage.js.map +1 -1
- package/dist/botlit/pages/MCPServersPage.js +170 -155
- package/dist/botlit/pages/MCPServersPage.js.map +1 -1
- package/dist/botlit/pages/PoliciesPage.js +115 -104
- package/dist/botlit/pages/PoliciesPage.js.map +1 -1
- package/dist/botlit/pages/PolicyDetailPage.js +368 -324
- package/dist/botlit/pages/PolicyDetailPage.js.map +1 -1
- package/dist/botlit/pages/PromptStudioPage.js +106 -97
- package/dist/botlit/pages/PromptStudioPage.js.map +1 -1
- package/dist/botlit/pages/PromptTemplateDetailPage.js +359 -347
- package/dist/botlit/pages/PromptTemplateDetailPage.js.map +1 -1
- package/dist/botlit/pages/PromptTemplatesPage.js +127 -112
- package/dist/botlit/pages/PromptTemplatesPage.js.map +1 -1
- package/dist/botlit/pages/RetrievalProfileDetailPage.js +219 -210
- package/dist/botlit/pages/RetrievalProfileDetailPage.js.map +1 -1
- package/dist/botlit/pages/RetrievalProfilesPage.js +112 -103
- package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -1
- package/dist/botlit/pages/SettingsPage.js +264 -252
- package/dist/botlit/pages/SettingsPage.js.map +1 -1
- package/dist/botlit/pages/SkillDetailPage.js +235 -226
- package/dist/botlit/pages/SkillDetailPage.js.map +1 -1
- package/dist/botlit/pages/SkillsPage.js +115 -106
- package/dist/botlit/pages/SkillsPage.js.map +1 -1
- package/dist/botlit/pages/StorePackageDetailPage.js +194 -188
- package/dist/botlit/pages/StorePackageDetailPage.js.map +1 -1
- package/dist/botlit/pages/StorePage.js +161 -155
- package/dist/botlit/pages/StorePage.js.map +1 -1
- package/dist/botlit/permissions/PermissionRequired.js +45 -0
- package/dist/botlit/permissions/PermissionRequired.js.map +1 -0
- package/dist/botlit/permissions/botmanorPermissions.js +72 -0
- package/dist/botlit/permissions/botmanorPermissions.js.map +1 -0
- package/dist/botlit/permissions/index.js +3 -0
- package/dist/botlit/permissions/useBotmanorPermissions.js +19 -0
- package/dist/botlit/permissions/useBotmanorPermissions.js.map +1 -0
- package/dist/botlit/utils/policyConfig.js +67 -42
- package/dist/botlit/utils/policyConfig.js.map +1 -1
- package/dist/generated/global-types.js.map +1 -1
- package/dist/generated/wspace-operations.js +90 -54
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"A2ARegistryPage.js","names":[],"sources":["../../../src/botlit/pages/A2ARegistryPage.tsx"],"sourcesContent":["/**\n * A2A Registry Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState } from 'react';\nimport { Link } from 'react-router';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport {\n Plus,\n Search as SearchIcon,\n Filter,\n Globe,\n Shield,\n CheckCircle,\n AlertCircle,\n ExternalLink,\n Zap,\n} from 'lucide-react';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PagePurpose, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Input } from '../components/Input';\nimport { Badge, StatusBadge } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport { useA2AAgents, a2aAgentSkillCount, type A2AAgentRecord } from '../hooks';\nimport { formatRelativeTime, MISSING_VALUE } from '../utils/formatters';\n\nconst TrustBadge: FC<{ level: string; t: ReturnType<typeof useTr> }> = ({ level, t }) => {\n switch (level) {\n case 'INTERNAL':\n return (\n <Badge variant=\"success\" className=\"flex items-center gap-1\">\n <Shield size={12} />\n {t('botlit.a2aRegistry.trustBadge.internal', 'Internal')}\n </Badge>\n );\n case 'VERIFIED_PUBLISHER':\n return (\n <Badge variant=\"default\" className=\"flex items-center gap-1\">\n <CheckCircle size={12} />\n {t('botlit.a2aRegistry.trustBadge.verified', 'Verified')}\n </Badge>\n );\n case 'UNVERIFIED':\n default:\n return (\n <Badge variant=\"outline\" className=\"flex items-center gap-1\">\n <AlertCircle size={12} />\n {t('botlit.a2aRegistry.trustBadge.unverified', 'Unverified')}\n </Badge>\n );\n }\n};\n\nexport const A2ARegistryPage: FC = () => {\n const t = useTr();\n const { getPath } = useBotlit();\n const [search, setSearch] = useState('');\n const { data: agents, loading, error, refetch } = useA2AAgents({ search });\n\n return (\n <PageLayout\n title={t('botlit.a2aRegistry.title', 'A2A Registry')}\n description={t(\n 'botlit.a2aRegistry.description',\n 'Discover and connect to external agents via the Agent-to-Agent protocol'\n )}\n actions={\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('a2a/register')}>\n {t('botlit.a2aRegistry.actions.registerAgent', 'Register Agent')}\n </Link>\n </Button>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Globe size={18} />}>\n {t(\n 'botlit.a2aRegistry.purpose',\n 'The A2A (Agent-to-Agent) registry lets your bots collaborate with external agents — your own or third-party — over a shared open protocol. Register an agent by its /.well-known/agent.json card to discover its skills, set how much you trust it, and let your agents delegate tasks to it. Use this page to curate that network of partner agents.'\n )}\n </PagePurpose>\n\n {/* Search */}\n <div className=\"flex items-center gap-4\">\n <div className=\"relative flex-1 max-w-md\">\n <SearchIcon className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder={t('botlit.a2aRegistry.searchPlaceholder', 'Search A2A agents...')}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n <Button variant=\"outline\" leftIcon={<Filter size={16} />}>\n {t('botlit.a2aRegistry.actions.filters', 'Filters')}\n </Button>\n </div>\n\n {/* Agents List */}\n {loading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {[1, 2, 3, 4].map((i) => (\n <div\n key={i}\n className=\"h-56 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\"\n />\n ))}\n </div>\n ) : error ? (\n <ErrorState resource=\"the A2A registry\" error={error} onRetry={() => void refetch()} />\n ) : agents.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {agents.map((agent: A2AAgentRecord) => (\n <Link key={agent.id} to={getPath(`a2a/${agent.id}`)}>\n <Card className=\"h-full hover:border-primary/50 transition-colors cursor-pointer\">\n <CardHeader>\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2 bg-action-primary-bg/10 rounded-lg\">\n <Globe className=\"h-5 w-5 text-primary\" />\n </div>\n <div>\n <CardTitle className=\"text-base\">{agent.name}</CardTitle>\n <CardDescription className=\"text-xs line-clamp-2\">\n {agent.description}\n </CardDescription>\n </div>\n </div>\n <StatusBadge status={agent.status} />\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {/* Trust Level */}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.a2aRegistry.list.trustLevel', 'Trust Level')}\n </span>\n <TrustBadge level={agent.trustLevel} t={t} />\n </div>\n\n {/* Skills Count */}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.a2aRegistry.list.availableSkills', 'Available Skills')}\n </span>\n <Badge variant=\"secondary\">\n {t('botlit.a2aRegistry.list.skillsCount', '{{count}} skills', {\n count: a2aAgentSkillCount(agent),\n })}\n </Badge>\n </div>\n\n {/* Well-known URL */}\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <ExternalLink size={14} />\n <span className=\"truncate\">{agent.wellKnownUrl ?? MISSING_VALUE}</span>\n </div>\n\n {/* Footer */}\n <div className=\"pt-3 border-t border-border-subtle flex items-center justify-between text-xs text-text-secondary\">\n <span>\n {t('botlit.a2aRegistry.list.added', 'Added')}{' '}\n {formatRelativeTime(agent.createdAt)}\n </span>\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs\">\n <Zap size={12} className=\"mr-1\" />\n {t('botlit.a2aRegistry.actions.test', 'Test')}\n </Button>\n </div>\n </div>\n </CardContent>\n </Card>\n </Link>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n title={t('botlit.a2aRegistry.empty.title', 'No A2A agents registered')}\n description={t(\n 'botlit.a2aRegistry.empty.description',\n 'Register external agents to enable agent-to-agent communication and delegation.'\n )}\n action={\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('a2a/register')}>\n {t('botlit.a2aRegistry.actions.registerAgent', 'Register Agent')}\n </Link>\n </Button>\n }\n />\n )}\n\n {/* A2A Protocol Info */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <div className=\"mb-4\">\n <h2 className=\"flex items-center gap-2 text-lg font-semibold tracking-tight text-text-primary\">\n <Globe size={18} />\n {t('botlit.a2aRegistry.overview.title', 'Agent-to-Agent Protocol')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'botlit.a2aRegistry.overview.description',\n 'A2A enables secure communication between agents across different systems'\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <Shield size={16} className=\"text-primary\" />\n {t('botlit.a2aRegistry.overview.trustTitle', 'Trust Levels')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.a2aRegistry.overview.trustDescription',\n 'Internal: your own agents; Verified: publisher verified by BotManor; Unverified: community agents.'\n )}\n </li>\n </ul>\n </div>\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <Zap size={16} className=\"text-primary\" />\n {t('botlit.a2aRegistry.overview.capabilitiesTitle', 'Capabilities')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.a2aRegistry.overview.capabilitiesDescription',\n 'Skill discovery via agent cards, secure task delegation, and structured input/output modes.'\n )}\n </li>\n </ul>\n </div>\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <ExternalLink size={16} className=\"text-primary\" />\n {t('botlit.a2aRegistry.overview.integrationTitle', 'Integration')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.a2aRegistry.overview.integrationDescription',\n 'Discover via /.well-known/agent.json, automatic capability negotiation, and entitlement-based access control.'\n )}\n </li>\n </ul>\n </div>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"A2ARegistryPage.js","names":[],"sources":["../../../src/botlit/pages/A2ARegistryPage.tsx"],"sourcesContent":["/**\n * A2A Registry Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState } from 'react';\nimport { Link } from 'react-router';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport {\n Plus,\n Search as SearchIcon,\n Filter,\n Globe,\n Shield,\n CheckCircle,\n AlertCircle,\n ExternalLink,\n Zap,\n} from 'lucide-react';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PagePurpose, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Input } from '../components/Input';\nimport { Badge, StatusBadge } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport { useA2AAgents, a2aAgentSkillCount, type A2AAgentRecord } from '../hooks';\nimport { formatRelativeTime, MISSING_VALUE } from '../utils/formatters';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\n\nconst TrustBadge: FC<{ level: string; t: ReturnType<typeof useTr> }> = ({ level, t }) => {\n switch (level) {\n case 'INTERNAL':\n return (\n <Badge variant=\"success\" className=\"flex items-center gap-1\">\n <Shield size={12} />\n {t('botlit.a2aRegistry.trustBadge.internal', 'Internal')}\n </Badge>\n );\n case 'VERIFIED_PUBLISHER':\n return (\n <Badge variant=\"default\" className=\"flex items-center gap-1\">\n <CheckCircle size={12} />\n {t('botlit.a2aRegistry.trustBadge.verified', 'Verified')}\n </Badge>\n );\n case 'UNVERIFIED':\n default:\n return (\n <Badge variant=\"outline\" className=\"flex items-center gap-1\">\n <AlertCircle size={12} />\n {t('botlit.a2aRegistry.trustBadge.unverified', 'Unverified')}\n </Badge>\n );\n }\n};\n\nexport const A2ARegistryPage: FC = () => {\n const t = useTr();\n const { getPath } = useBotlit();\n const [search, setSearch] = useState('');\n const { data: agents, loading, error, refetch } = useA2AAgents({ search });\n\n return (\n <PageLayout\n title={t('botlit.a2aRegistry.title', 'A2A Registry')}\n description={t(\n 'botlit.a2aRegistry.description',\n 'Discover and connect to external agents via the Agent-to-Agent protocol'\n )}\n actions={\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.A2A_REGISTRY_CREATE}>\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('a2a/register')}>\n {t('botlit.a2aRegistry.actions.registerAgent', 'Register Agent')}\n </Link>\n </Button>\n </BotmanorPermissionGate>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Globe size={18} />}>\n {t(\n 'botlit.a2aRegistry.purpose',\n 'The A2A (Agent-to-Agent) registry lets your bots collaborate with external agents — your own or third-party — over a shared open protocol. Register an agent by its /.well-known/agent.json card to discover its skills, set how much you trust it, and let your agents delegate tasks to it. Use this page to curate that network of partner agents.'\n )}\n </PagePurpose>\n\n {/* Search */}\n <div className=\"flex items-center gap-4\">\n <div className=\"relative flex-1 max-w-md\">\n <SearchIcon className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder={t('botlit.a2aRegistry.searchPlaceholder', 'Search A2A agents...')}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n <Button variant=\"outline\" leftIcon={<Filter size={16} />}>\n {t('botlit.a2aRegistry.actions.filters', 'Filters')}\n </Button>\n </div>\n\n {/* Agents List */}\n {loading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {[1, 2, 3, 4].map((i) => (\n <div\n key={i}\n className=\"h-56 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\"\n />\n ))}\n </div>\n ) : error ? (\n <ErrorState resource=\"the A2A registry\" error={error} onRetry={() => void refetch()} />\n ) : agents.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {agents.map((agent: A2AAgentRecord) => (\n <Link key={agent.id} to={getPath(`a2a/${agent.id}`)}>\n <Card className=\"h-full hover:border-primary/50 transition-colors cursor-pointer\">\n <CardHeader>\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2 bg-action-primary-bg/10 rounded-lg\">\n <Globe className=\"h-5 w-5 text-primary\" />\n </div>\n <div>\n <CardTitle className=\"text-base\">{agent.name}</CardTitle>\n <CardDescription className=\"text-xs line-clamp-2\">\n {agent.description}\n </CardDescription>\n </div>\n </div>\n <StatusBadge status={agent.status} />\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {/* Trust Level */}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.a2aRegistry.list.trustLevel', 'Trust Level')}\n </span>\n <TrustBadge level={agent.trustLevel} t={t} />\n </div>\n\n {/* Skills Count */}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.a2aRegistry.list.availableSkills', 'Available Skills')}\n </span>\n <Badge variant=\"secondary\">\n {t('botlit.a2aRegistry.list.skillsCount', '{{count}} skills', {\n count: a2aAgentSkillCount(agent),\n })}\n </Badge>\n </div>\n\n {/* Well-known URL */}\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <ExternalLink size={14} />\n <span className=\"truncate\">{agent.wellKnownUrl ?? MISSING_VALUE}</span>\n </div>\n\n {/* Footer */}\n <div className=\"pt-3 border-t border-border-subtle flex items-center justify-between text-xs text-text-secondary\">\n <span>\n {t('botlit.a2aRegistry.list.added', 'Added')}{' '}\n {formatRelativeTime(agent.createdAt)}\n </span>\n <BotmanorPermissionGate\n permission={BOTMANOR_PERMISSIONS.A2A_REGISTRY_UPDATE}\n >\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs\">\n <Zap size={12} className=\"mr-1\" />\n {t('botlit.a2aRegistry.actions.test', 'Test')}\n </Button>\n </BotmanorPermissionGate>\n </div>\n </div>\n </CardContent>\n </Card>\n </Link>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n title={t('botlit.a2aRegistry.empty.title', 'No A2A agents registered')}\n description={t(\n 'botlit.a2aRegistry.empty.description',\n 'Register external agents to enable agent-to-agent communication and delegation.'\n )}\n action={\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.A2A_REGISTRY_CREATE}>\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('a2a/register')}>\n {t('botlit.a2aRegistry.actions.registerAgent', 'Register Agent')}\n </Link>\n </Button>\n </BotmanorPermissionGate>\n }\n />\n )}\n\n {/* A2A Protocol Info */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <div className=\"mb-4\">\n <h2 className=\"flex items-center gap-2 text-lg font-semibold tracking-tight text-text-primary\">\n <Globe size={18} />\n {t('botlit.a2aRegistry.overview.title', 'Agent-to-Agent Protocol')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'botlit.a2aRegistry.overview.description',\n 'A2A enables secure communication between agents across different systems'\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <Shield size={16} className=\"text-primary\" />\n {t('botlit.a2aRegistry.overview.trustTitle', 'Trust Levels')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.a2aRegistry.overview.trustDescription',\n 'Internal: your own agents; Verified: publisher verified by BotManor; Unverified: community agents.'\n )}\n </li>\n </ul>\n </div>\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <Zap size={16} className=\"text-primary\" />\n {t('botlit.a2aRegistry.overview.capabilitiesTitle', 'Capabilities')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.a2aRegistry.overview.capabilitiesDescription',\n 'Skill discovery via agent cards, secure task delegation, and structured input/output modes.'\n )}\n </li>\n </ul>\n </div>\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <ExternalLink size={16} className=\"text-primary\" />\n {t('botlit.a2aRegistry.overview.integrationTitle', 'Integration')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.a2aRegistry.overview.integrationDescription',\n 'Discover via /.well-known/agent.json, automatic capability negotiation, and entitlement-based access control.'\n )}\n </li>\n </ul>\n </div>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -2,205 +2,217 @@ import { useTr as e } from "../../shared/hooks/useTr.js";
|
|
|
2
2
|
import { useBotlit as t } from "../providers/BotlitProvider.js";
|
|
3
3
|
import { useAgents as n } from "../hooks/useAgents.js";
|
|
4
4
|
import { formatRelativeTime as r } from "../utils/formatters.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
5
|
+
import { BOTMANOR_PERMISSIONS as i } from "../permissions/botmanorPermissions.js";
|
|
6
|
+
import { BotmanorPermissionGate as a } from "../permissions/useBotmanorPermissions.js";
|
|
7
|
+
import { PageLayout as o } from "../components/PageLayout.js";
|
|
8
|
+
import { Button as s } from "../components/Button.js";
|
|
9
|
+
import "../permissions/index.js";
|
|
10
|
+
import { Card as c, CardContent as l, CardDescription as u, CardHeader as d, CardTitle as f } from "../components/Card.js";
|
|
11
|
+
import { Badge as p } from "../components/Badge.js";
|
|
12
|
+
import { ErrorState as m } from "../components/ErrorState.js";
|
|
13
|
+
import { useAgentApprovalActions as h, useAgentApprovalRequests as g, useAgentApprovalSettings as _ } from "../hooks/useAgentApprovals.js";
|
|
14
|
+
import { ApprovalDecisionDialog as v, approvalStatusVariant as y } from "../components/AgentApprovalPanel.js";
|
|
15
|
+
import { useMemo as b, useState as x } from "react";
|
|
16
|
+
import { PagePurpose as S } from "@burdenoff/fe-libs/ui";
|
|
17
|
+
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
18
|
+
import { AlertTriangle as T, ArrowLeft as E, CheckCircle2 as D, ShieldCheck as O, XCircle as k } from "lucide-react";
|
|
19
|
+
import { toast as A } from "sonner";
|
|
17
20
|
//#region src/botlit/pages/AgentApprovalsPage.tsx
|
|
18
|
-
var
|
|
19
|
-
let
|
|
20
|
-
await Promise.all([
|
|
21
|
-
},
|
|
21
|
+
var j = () => {
|
|
22
|
+
let j = e(), { navigateTo: M, currentUser: N } = t(), P = _(), F = g({ status: "PENDING" }), I = g({}), { data: L } = n(), { run: R, pending: z } = h(), [B, V] = x(null), H = b(() => new Map(L.map((e) => [e.id, e.name])), [L]), U = I.data.filter((e) => e.status !== "PENDING").slice(0, 20), W = P.data?.requireActivationApproval === !0, G = (e) => e && e === N?.id ? j("botlit.agentApproval.you", "you") : e ?? "—", K = async () => {
|
|
23
|
+
await Promise.all([F.refetch(), I.refetch()]);
|
|
24
|
+
}, q = async () => {
|
|
22
25
|
try {
|
|
23
|
-
let e = await
|
|
24
|
-
|
|
26
|
+
let e = await P.update(!W);
|
|
27
|
+
A.success(e.requireActivationApproval ? j("botlit.agentApprovals.toast.enabled", "Agents now need approval before going live") : j("botlit.agentApprovals.toast.disabled", "Activation approval is now optional"));
|
|
25
28
|
} catch (e) {
|
|
26
|
-
|
|
29
|
+
A.error(e instanceof Error ? e.message : j("botlit.agentApprovals.toast.settingsError", "Failed to update the setting"));
|
|
27
30
|
}
|
|
28
31
|
};
|
|
29
|
-
return /* @__PURE__ */
|
|
30
|
-
title: /* @__PURE__ */
|
|
32
|
+
return /* @__PURE__ */ w(o, {
|
|
33
|
+
title: /* @__PURE__ */ w("div", {
|
|
31
34
|
className: "flex items-center gap-3",
|
|
32
|
-
children: [/* @__PURE__ */
|
|
35
|
+
children: [/* @__PURE__ */ C(s, {
|
|
33
36
|
variant: "ghost",
|
|
34
37
|
size: "icon",
|
|
35
|
-
onClick: () =>
|
|
36
|
-
children: /* @__PURE__ */
|
|
37
|
-
}), /* @__PURE__ */
|
|
38
|
+
onClick: () => M("agents"),
|
|
39
|
+
children: /* @__PURE__ */ C(E, { size: 20 })
|
|
40
|
+
}), /* @__PURE__ */ C("span", { children: j("botlit.agentApprovals.title", "Agent approvals") })]
|
|
38
41
|
}),
|
|
39
|
-
description:
|
|
40
|
-
children: [/* @__PURE__ */
|
|
42
|
+
description: j("botlit.agentApprovals.description", "Review requests to take agents live"),
|
|
43
|
+
children: [/* @__PURE__ */ w("div", {
|
|
41
44
|
className: "space-y-6",
|
|
42
45
|
children: [
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
-
icon: /* @__PURE__ */
|
|
45
|
-
children:
|
|
46
|
+
/* @__PURE__ */ C(S, {
|
|
47
|
+
icon: /* @__PURE__ */ C(O, { size: 18 }),
|
|
48
|
+
children: j("botlit.agentApprovals.purpose", "A reviewer checks an agent's prompt, model, tools and limits before it goes live. The person who requested activation cannot approve their own request, and every decision is kept in the history below.")
|
|
46
49
|
}),
|
|
47
|
-
/* @__PURE__ */
|
|
50
|
+
/* @__PURE__ */ C(c, {
|
|
48
51
|
"data-testid": "agent-approvals-settings",
|
|
49
|
-
children: /* @__PURE__ */
|
|
52
|
+
children: /* @__PURE__ */ w(d, {
|
|
50
53
|
className: "flex flex-row items-start justify-between gap-4",
|
|
51
|
-
children: [/* @__PURE__ */
|
|
54
|
+
children: [/* @__PURE__ */ w("div", { children: [/* @__PURE__ */ w(f, {
|
|
52
55
|
className: "flex items-center gap-2",
|
|
53
|
-
children: [
|
|
54
|
-
variant:
|
|
55
|
-
children:
|
|
56
|
+
children: [j("botlit.agentApprovals.settings.title", "Require approval before agents go live"), /* @__PURE__ */ C(p, {
|
|
57
|
+
variant: W ? "warning" : "outline",
|
|
58
|
+
children: W ? j("botlit.agentApprovals.settings.on", "On") : j("botlit.agentApprovals.settings.off", "Off")
|
|
56
59
|
})]
|
|
57
|
-
}), /* @__PURE__ */
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
}), /* @__PURE__ */ C(u, { children: j("botlit.agentApprovals.settings.description", "When on, activating an agent, publishing a new version, or editing the prompt, model or tools of a live agent needs an approved request. Rolling a live agent back to an earlier version stays available for emergencies.") })] }), /* @__PURE__ */ C(a, {
|
|
61
|
+
permission: i.AGENT_APPROVE,
|
|
62
|
+
children: /* @__PURE__ */ C(s, {
|
|
63
|
+
className: "shrink-0 whitespace-nowrap",
|
|
64
|
+
variant: W ? "outline" : "default",
|
|
65
|
+
isLoading: P.saving,
|
|
66
|
+
disabled: P.loading || !P.data,
|
|
67
|
+
onClick: () => void q(),
|
|
68
|
+
children: W ? j("botlit.agentApprovals.settings.turnOff", "Turn off") : j("botlit.agentApprovals.settings.turnOn", "Turn on")
|
|
69
|
+
})
|
|
64
70
|
})]
|
|
65
71
|
})
|
|
66
72
|
}),
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
-
resource:
|
|
69
|
-
error:
|
|
70
|
-
onRetry: () => void
|
|
71
|
-
}) :
|
|
73
|
+
/* @__PURE__ */ w(c, { children: [/* @__PURE__ */ C(d, { children: /* @__PURE__ */ C(f, { children: j("botlit.agentApprovals.pending.title", "Waiting for review") }) }), /* @__PURE__ */ C(l, { children: F.error ? /* @__PURE__ */ C(m, {
|
|
74
|
+
resource: j("botlit.agentApprovals.resource", "activation requests"),
|
|
75
|
+
error: F.error,
|
|
76
|
+
onRetry: () => void F.refetch()
|
|
77
|
+
}) : F.loading && F.data.length === 0 ? /* @__PURE__ */ C("div", { className: "h-24 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }) : F.data.length === 0 ? /* @__PURE__ */ C("p", {
|
|
72
78
|
className: "text-sm text-text-secondary",
|
|
73
|
-
children:
|
|
74
|
-
}) : /* @__PURE__ */
|
|
79
|
+
children: j("botlit.agentApprovals.pending.empty", "No agents are waiting for review.")
|
|
80
|
+
}) : /* @__PURE__ */ C("ul", {
|
|
75
81
|
className: "space-y-3",
|
|
76
82
|
"data-testid": "agent-approvals-pending",
|
|
77
|
-
children:
|
|
78
|
-
let t = e.requestedById ===
|
|
79
|
-
return /* @__PURE__ */
|
|
83
|
+
children: F.data.map((e) => {
|
|
84
|
+
let t = e.requestedById === N?.id;
|
|
85
|
+
return /* @__PURE__ */ w("li", {
|
|
80
86
|
className: "p-4 border border-border-subtle rounded-lg space-y-2",
|
|
81
87
|
children: [
|
|
82
|
-
/* @__PURE__ */
|
|
88
|
+
/* @__PURE__ */ w("div", {
|
|
83
89
|
className: "flex items-center gap-2 flex-wrap",
|
|
84
90
|
children: [
|
|
85
|
-
/* @__PURE__ */
|
|
91
|
+
/* @__PURE__ */ C("button", {
|
|
86
92
|
type: "button",
|
|
87
93
|
className: "font-medium text-primary hover:underline",
|
|
88
|
-
onClick: () =>
|
|
89
|
-
children:
|
|
94
|
+
onClick: () => M(`agents/${e.agentId}`),
|
|
95
|
+
children: H.get(e.agentId) ?? e.agentId
|
|
90
96
|
}),
|
|
91
|
-
/* @__PURE__ */
|
|
97
|
+
/* @__PURE__ */ C(p, {
|
|
92
98
|
variant: "warning",
|
|
93
99
|
children: e.status
|
|
94
100
|
}),
|
|
95
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ w("span", {
|
|
96
102
|
className: "text-sm text-text-secondary",
|
|
97
103
|
children: [
|
|
98
|
-
|
|
104
|
+
j("botlit.agentApproval.requestedBy", "Requested by"),
|
|
99
105
|
" ",
|
|
100
|
-
|
|
106
|
+
G(e.requestedById),
|
|
101
107
|
" ",
|
|
102
108
|
r(e.createdAt)
|
|
103
109
|
]
|
|
104
110
|
})
|
|
105
111
|
]
|
|
106
112
|
}),
|
|
107
|
-
e.requestNote && /* @__PURE__ */
|
|
113
|
+
e.requestNote && /* @__PURE__ */ C("p", {
|
|
108
114
|
className: "text-sm break-words",
|
|
109
115
|
children: e.requestNote
|
|
110
116
|
}),
|
|
111
|
-
e.isStale && /* @__PURE__ */
|
|
117
|
+
e.isStale && /* @__PURE__ */ w("p", {
|
|
112
118
|
className: "flex items-center gap-2 text-sm text-status-warning-text",
|
|
113
|
-
children: [/* @__PURE__ */
|
|
119
|
+
children: [/* @__PURE__ */ C(T, { size: 14 }), j("botlit.agentApproval.stale", "The agent changed after this request. Submit a new request so the reviewer sees the current configuration.")]
|
|
114
120
|
}),
|
|
115
|
-
t ? /* @__PURE__ */
|
|
121
|
+
t ? /* @__PURE__ */ C("p", {
|
|
116
122
|
className: "text-xs text-text-secondary",
|
|
117
|
-
children:
|
|
118
|
-
}) : /* @__PURE__ */
|
|
123
|
+
children: j("botlit.agentApprovals.ownRequest", "You requested this, so another reviewer has to decide it.")
|
|
124
|
+
}) : /* @__PURE__ */ w("div", {
|
|
119
125
|
className: "flex gap-2",
|
|
120
|
-
children: [/* @__PURE__ */
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
126
|
+
children: [/* @__PURE__ */ C(a, {
|
|
127
|
+
permission: i.AGENT_APPROVE,
|
|
128
|
+
children: /* @__PURE__ */ C(s, {
|
|
129
|
+
size: "sm",
|
|
130
|
+
leftIcon: /* @__PURE__ */ C(D, { size: 14 }),
|
|
131
|
+
disabled: e.isStale,
|
|
132
|
+
onClick: () => V({
|
|
133
|
+
kind: "approve",
|
|
134
|
+
request: e
|
|
135
|
+
}),
|
|
136
|
+
children: j("botlit.agentApproval.approveAction", "Approve")
|
|
137
|
+
})
|
|
138
|
+
}), /* @__PURE__ */ C(a, {
|
|
139
|
+
permission: i.AGENT_APPROVE,
|
|
140
|
+
children: /* @__PURE__ */ C(s, {
|
|
141
|
+
size: "sm",
|
|
142
|
+
variant: "destructive",
|
|
143
|
+
leftIcon: /* @__PURE__ */ C(k, { size: 14 }),
|
|
144
|
+
onClick: () => V({
|
|
145
|
+
kind: "reject",
|
|
146
|
+
request: e
|
|
147
|
+
}),
|
|
148
|
+
children: j("botlit.agentApproval.rejectAction", "Reject")
|
|
149
|
+
})
|
|
138
150
|
})]
|
|
139
151
|
})
|
|
140
152
|
]
|
|
141
153
|
}, e.id);
|
|
142
154
|
})
|
|
143
155
|
}) })] }),
|
|
144
|
-
/* @__PURE__ */
|
|
156
|
+
/* @__PURE__ */ w(c, { children: [/* @__PURE__ */ C(d, { children: /* @__PURE__ */ C(f, { children: j("botlit.agentApprovals.history.title", "Recent decisions") }) }), /* @__PURE__ */ C(l, { children: U.length === 0 ? /* @__PURE__ */ C("p", {
|
|
145
157
|
className: "text-sm text-text-secondary",
|
|
146
|
-
children:
|
|
147
|
-
}) : /* @__PURE__ */
|
|
158
|
+
children: j("botlit.agentApprovals.history.empty", "No decisions yet.")
|
|
159
|
+
}) : /* @__PURE__ */ C("ul", {
|
|
148
160
|
className: "space-y-2",
|
|
149
161
|
"data-testid": "agent-approvals-history",
|
|
150
|
-
children:
|
|
162
|
+
children: U.map((e) => /* @__PURE__ */ w("li", {
|
|
151
163
|
className: "p-3 border border-border-subtle rounded-lg text-sm space-y-1",
|
|
152
|
-
children: [/* @__PURE__ */
|
|
164
|
+
children: [/* @__PURE__ */ w("div", {
|
|
153
165
|
className: "flex items-center gap-2 flex-wrap",
|
|
154
166
|
children: [
|
|
155
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ C("span", {
|
|
156
168
|
className: "font-medium",
|
|
157
|
-
children:
|
|
169
|
+
children: H.get(e.agentId) ?? e.agentId
|
|
158
170
|
}),
|
|
159
|
-
/* @__PURE__ */
|
|
160
|
-
variant:
|
|
171
|
+
/* @__PURE__ */ C(p, {
|
|
172
|
+
variant: y(e.status),
|
|
161
173
|
children: e.status
|
|
162
174
|
}),
|
|
163
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ w("span", {
|
|
164
176
|
className: "text-text-secondary",
|
|
165
177
|
children: [
|
|
166
|
-
|
|
178
|
+
j("botlit.agentApproval.decidedBy", "by"),
|
|
167
179
|
" ",
|
|
168
|
-
|
|
180
|
+
G(e.reviewerId),
|
|
169
181
|
" ",
|
|
170
182
|
e.decidedAt ? r(e.decidedAt) : ""
|
|
171
183
|
]
|
|
172
184
|
})
|
|
173
185
|
]
|
|
174
|
-
}), e.decisionReason && /* @__PURE__ */
|
|
186
|
+
}), e.decisionReason && /* @__PURE__ */ C("p", {
|
|
175
187
|
className: "break-words",
|
|
176
188
|
children: e.decisionReason
|
|
177
189
|
})]
|
|
178
190
|
}, e.id))
|
|
179
191
|
}) })] })
|
|
180
192
|
]
|
|
181
|
-
}), /* @__PURE__ */
|
|
182
|
-
kind:
|
|
183
|
-
loading:
|
|
184
|
-
onClose: () =>
|
|
193
|
+
}), /* @__PURE__ */ C(v, {
|
|
194
|
+
kind: B?.kind ?? null,
|
|
195
|
+
loading: z !== null,
|
|
196
|
+
onClose: () => V(null),
|
|
185
197
|
onConfirm: async (e) => {
|
|
186
|
-
if (
|
|
187
|
-
|
|
198
|
+
if (B) try {
|
|
199
|
+
B.kind === "approve" ? (await R({
|
|
188
200
|
kind: "approve",
|
|
189
|
-
id:
|
|
201
|
+
id: B.request.id,
|
|
190
202
|
reason: e
|
|
191
|
-
}),
|
|
203
|
+
}), A.success(j("botlit.agentApproval.toast.approved", "Approved — the agent is live"))) : (await R({
|
|
192
204
|
kind: "reject",
|
|
193
|
-
id:
|
|
205
|
+
id: B.request.id,
|
|
194
206
|
reason: e
|
|
195
|
-
}),
|
|
207
|
+
}), A.success(j("botlit.agentApproval.toast.rejected", "Activation rejected"))), V(null), await K();
|
|
196
208
|
} catch (e) {
|
|
197
|
-
|
|
209
|
+
A.error(e instanceof Error ? e.message : j("botlit.agentApproval.toast.error", "Approval action failed"));
|
|
198
210
|
}
|
|
199
211
|
}
|
|
200
212
|
})]
|
|
201
213
|
});
|
|
202
214
|
};
|
|
203
215
|
//#endregion
|
|
204
|
-
export {
|
|
216
|
+
export { j as AgentApprovalsPage };
|
|
205
217
|
|
|
206
218
|
//# sourceMappingURL=AgentApprovalsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentApprovalsPage.js","names":[],"sources":["../../../src/botlit/pages/AgentApprovalsPage.tsx"],"sourcesContent":["/**\n * Agent Activation Approvals Page (BOFF-9682)\n * @module botlit/pages\n *\n * Reviewer queue for the workspace: every pending request to take an agent\n * live, with approve / reject, the recent decisions, and the workspace switch\n * that makes review mandatory. Approving publishes the agent's draft and sets\n * it ACTIVE; a request whose agent changed after it was submitted is flagged\n * stale and cannot be approved.\n */\n\nimport { useMemo, useState, type FC } from 'react';\nimport { AlertTriangle, ArrowLeft, CheckCircle2, ShieldCheck, XCircle } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Badge } from '../components/Badge';\nimport { ErrorState } from '../components/ErrorState';\nimport { ApprovalDecisionDialog, approvalStatusVariant } from '../components/AgentApprovalPanel';\nimport { useAgents } from '../hooks/useAgents';\nimport {\n useAgentApprovalActions,\n useAgentApprovalRequests,\n useAgentApprovalSettings,\n type AgentApprovalRequestRecord,\n} from '../hooks/useAgentApprovals';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { formatRelativeTime } from '../utils/formatters';\n\nexport const AgentApprovalsPage: FC = () => {\n const t = useTr();\n const { navigateTo, currentUser } = useBotlit();\n const settings = useAgentApprovalSettings();\n const pendingRequests = useAgentApprovalRequests({ status: 'PENDING' });\n const allRequests = useAgentApprovalRequests({});\n const { data: agents } = useAgents();\n const { run, pending } = useAgentApprovalActions();\n const [dialog, setDialog] = useState<{\n kind: 'approve' | 'reject';\n request: AgentApprovalRequestRecord;\n } | null>(null);\n\n const agentNames = useMemo(\n () => new Map(agents.map((agent) => [agent.id, agent.name])),\n [agents]\n );\n const decided = allRequests.data.filter((request) => request.status !== 'PENDING').slice(0, 20);\n const required = settings.data?.requireActivationApproval === true;\n const who = (id?: string | null): string =>\n id && id === currentUser?.id ? t('botlit.agentApproval.you', 'you') : (id ?? '—');\n\n const refreshAll = async (): Promise<void> => {\n await Promise.all([pendingRequests.refetch(), allRequests.refetch()]);\n };\n\n const toggleRequired = async (): Promise<void> => {\n try {\n const next = await settings.update(!required);\n toast.success(\n next.requireActivationApproval\n ? t('botlit.agentApprovals.toast.enabled', 'Agents now need approval before going live')\n : t('botlit.agentApprovals.toast.disabled', 'Activation approval is now optional')\n );\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApprovals.toast.settingsError', 'Failed to update the setting')\n );\n }\n };\n\n const confirm = async (text: string): Promise<void> => {\n if (!dialog) return;\n try {\n if (dialog.kind === 'approve') {\n await run({ kind: 'approve', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.approved', 'Approved — the agent is live'));\n } else {\n await run({ kind: 'reject', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.rejected', 'Activation rejected'));\n }\n setDialog(null);\n await refreshAll();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApproval.toast.error', 'Approval action failed')\n );\n }\n };\n\n return (\n <PageLayout\n title={\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => navigateTo('agents')}>\n <ArrowLeft size={20} />\n </Button>\n <span>{t('botlit.agentApprovals.title', 'Agent approvals')}</span>\n </div>\n }\n description={t('botlit.agentApprovals.description', 'Review requests to take agents live')}\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<ShieldCheck size={18} />}>\n {t(\n 'botlit.agentApprovals.purpose',\n \"A reviewer checks an agent's prompt, model, tools and limits before it goes live. The person who requested activation cannot approve their own request, and every decision is kept in the history below.\"\n )}\n </PagePurpose>\n\n <Card data-testid=\"agent-approvals-settings\">\n <CardHeader className=\"flex flex-row items-start justify-between gap-4\">\n <div>\n <CardTitle className=\"flex items-center gap-2\">\n {t(\n 'botlit.agentApprovals.settings.title',\n 'Require approval before agents go live'\n )}\n <Badge variant={required ? 'warning' : 'outline'}>\n {required\n ? t('botlit.agentApprovals.settings.on', 'On')\n : t('botlit.agentApprovals.settings.off', 'Off')}\n </Badge>\n </CardTitle>\n <CardDescription>\n {t(\n 'botlit.agentApprovals.settings.description',\n 'When on, activating an agent, publishing a new version, or editing the prompt, model or tools of a live agent needs an approved request. Rolling a live agent back to an earlier version stays available for emergencies.'\n )}\n </CardDescription>\n </div>\n <Button\n className=\"shrink-0 whitespace-nowrap\"\n variant={required ? 'outline' : 'default'}\n isLoading={settings.saving}\n disabled={settings.loading || !settings.data}\n onClick={() => void toggleRequired()}\n >\n {required\n ? t('botlit.agentApprovals.settings.turnOff', 'Turn off')\n : t('botlit.agentApprovals.settings.turnOn', 'Turn on')}\n </Button>\n </CardHeader>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>{t('botlit.agentApprovals.pending.title', 'Waiting for review')}</CardTitle>\n </CardHeader>\n <CardContent>\n {pendingRequests.error ? (\n <ErrorState\n resource={t('botlit.agentApprovals.resource', 'activation requests')}\n error={pendingRequests.error}\n onRetry={() => void pendingRequests.refetch()}\n />\n ) : pendingRequests.loading && pendingRequests.data.length === 0 ? (\n <div className=\"h-24 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ) : pendingRequests.data.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.agentApprovals.pending.empty', 'No agents are waiting for review.')}\n </p>\n ) : (\n <ul className=\"space-y-3\" data-testid=\"agent-approvals-pending\">\n {pendingRequests.data.map((request) => {\n const own = request.requestedById === currentUser?.id;\n return (\n <li\n key={request.id}\n className=\"p-4 border border-border-subtle rounded-lg space-y-2\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n type=\"button\"\n className=\"font-medium text-primary hover:underline\"\n onClick={() => navigateTo(`agents/${request.agentId}`)}\n >\n {agentNames.get(request.agentId) ?? request.agentId}\n </button>\n <Badge variant=\"warning\">{request.status}</Badge>\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.agentApproval.requestedBy', 'Requested by')}{' '}\n {who(request.requestedById)} {formatRelativeTime(request.createdAt)}\n </span>\n </div>\n {request.requestNote && (\n <p className=\"text-sm break-words\">{request.requestNote}</p>\n )}\n {request.isStale && (\n <p className=\"flex items-center gap-2 text-sm text-status-warning-text\">\n <AlertTriangle size={14} />\n {t(\n 'botlit.agentApproval.stale',\n 'The agent changed after this request. Submit a new request so the reviewer sees the current configuration.'\n )}\n </p>\n )}\n {own ? (\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'botlit.agentApprovals.ownRequest',\n 'You requested this, so another reviewer has to decide it.'\n )}\n </p>\n ) : (\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n leftIcon={<CheckCircle2 size={14} />}\n disabled={request.isStale}\n onClick={() => setDialog({ kind: 'approve', request })}\n >\n {t('botlit.agentApproval.approveAction', 'Approve')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n leftIcon={<XCircle size={14} />}\n onClick={() => setDialog({ kind: 'reject', request })}\n >\n {t('botlit.agentApproval.rejectAction', 'Reject')}\n </Button>\n </div>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>{t('botlit.agentApprovals.history.title', 'Recent decisions')}</CardTitle>\n </CardHeader>\n <CardContent>\n {decided.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.agentApprovals.history.empty', 'No decisions yet.')}\n </p>\n ) : (\n <ul className=\"space-y-2\" data-testid=\"agent-approvals-history\">\n {decided.map((request) => (\n <li\n key={request.id}\n className=\"p-3 border border-border-subtle rounded-lg text-sm space-y-1\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-medium\">\n {agentNames.get(request.agentId) ?? request.agentId}\n </span>\n <Badge variant={approvalStatusVariant(request.status)}>\n {request.status}\n </Badge>\n <span className=\"text-text-secondary\">\n {t('botlit.agentApproval.decidedBy', 'by')} {who(request.reviewerId)}{' '}\n {request.decidedAt ? formatRelativeTime(request.decidedAt) : ''}\n </span>\n </div>\n {request.decisionReason && (\n <p className=\"break-words\">{request.decisionReason}</p>\n )}\n </li>\n ))}\n </ul>\n )}\n </CardContent>\n </Card>\n </div>\n\n <ApprovalDecisionDialog\n kind={dialog?.kind ?? null}\n loading={pending !== null}\n onClose={() => setDialog(null)}\n onConfirm={confirm}\n />\n </PageLayout>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,IAAa,UAA+B;CAC1C,IAAM,IAAI,GAAO,EACX,EAAE,eAAY,mBAAgB,GAAW,EACzC,IAAW,GAA0B,EACrC,IAAkB,EAAyB,EAAE,QAAQ,WAAW,CAAC,EACjE,IAAc,EAAyB,EAAE,CAAC,EAC1C,EAAE,MAAM,MAAW,GAAW,EAC9B,EAAE,QAAK,eAAY,GAAyB,EAC5C,CAAC,GAAQ,KAAa,EAGlB,KAAK,EAET,IAAa,QACX,IAAI,IAAI,EAAO,KAAK,MAAU,CAAC,EAAM,IAAI,EAAM,KAAK,CAAC,CAAC,EAC5D,CAAC,EAAO,CACT,EACK,IAAU,EAAY,KAAK,QAAQ,MAAY,EAAQ,WAAW,UAAU,CAAC,MAAM,GAAG,GAAG,EACzF,IAAW,EAAS,MAAM,8BAA8B,IACxD,KAAO,MACX,KAAM,MAAO,GAAa,KAAK,EAAE,4BAA4B,MAAM,GAAI,KAAM,KAEzE,IAAa,YAA2B;AAC5C,QAAM,QAAQ,IAAI,CAAC,EAAgB,SAAS,EAAE,EAAY,SAAS,CAAC,CAAC;IAGjE,IAAiB,YAA2B;AAChD,MAAI;GACF,IAAM,IAAO,MAAM,EAAS,OAAO,CAAC,EAAS;AAC7C,KAAM,QACJ,EAAK,4BACD,EAAE,uCAAuC,6CAA6C,GACtF,EAAE,wCAAwC,sCAAsC,CACrF;WACM,GAAc;AACrB,KAAM,MACJ,aAAe,QACX,EAAI,UACJ,EAAE,6CAA6C,+BAA+B,CACnF;;;AAyBL,QACE,kBAAC,GAAD;EACE,OACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IAAQ,SAAQ;IAAQ,MAAK;IAAO,eAAe,EAAW,SAAS;cACrE,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;IAChB,CAAA,EACT,kBAAC,QAAD,EAAA,UAAO,EAAE,+BAA+B,kBAAkB,EAAQ,CAAA,CAC9D;;EAER,aAAa,EAAE,qCAAqC,sCAAsC;YAT5F,CAWE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KAAa,MAAM,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA;eACzC,EACC,iCACA,2MACD;KACW,CAAA;IAEd,kBAAC,GAAD;KAAM,eAAY;eAChB,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD;OAAW,WAAU;iBAArB,CACG,EACC,wCACA,yCACD,EACD,kBAAC,GAAD;QAAO,SAAS,IAAW,YAAY;kBACpC,IACG,EAAE,qCAAqC,KAAK,GAC5C,EAAE,sCAAsC,MAAM;QAC5C,CAAA,CACE;UACZ,kBAAC,GAAD,EAAA,UACG,EACC,8CACA,4NACD,EACe,CAAA,CACd,EAAA,CAAA,EACN,kBAAC,GAAD;OACE,WAAU;OACV,SAAS,IAAW,YAAY;OAChC,WAAW,EAAS;OACpB,UAAU,EAAS,WAAW,CAAC,EAAS;OACxC,eAAe,KAAK,GAAgB;iBAEnC,IACG,EAAE,0CAA0C,WAAW,GACvD,EAAE,yCAAyC,UAAU;OAClD,CAAA,CACE;;KACR,CAAA;IAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAY,EAAE,uCAAuC,qBAAqB,EAAa,CAAA,EAC5E,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,EAAgB,QACf,kBAAC,GAAD;KACE,UAAU,EAAE,kCAAkC,sBAAsB;KACpE,OAAO,EAAgB;KACvB,eAAe,KAAK,EAAgB,SAAS;KAC7C,CAAA,GACA,EAAgB,WAAW,EAAgB,KAAK,WAAW,IAC7D,kBAAC,OAAD,EAAK,WAAU,+DAAgE,CAAA,GAC7E,EAAgB,KAAK,WAAW,IAClC,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,uCAAuC,oCAAoC;KAC5E,CAAA,GAEJ,kBAAC,MAAD;KAAI,WAAU;KAAY,eAAY;eACnC,EAAgB,KAAK,KAAK,MAAY;MACrC,IAAM,IAAM,EAAQ,kBAAkB,GAAa;AACnD,aACE,kBAAC,MAAD;OAEE,WAAU;iBAFZ;QAIE,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,UAAD;WACE,MAAK;WACL,WAAU;WACV,eAAe,EAAW,UAAU,EAAQ,UAAU;qBAErD,EAAW,IAAI,EAAQ,QAAQ,IAAI,EAAQ;WACrC,CAAA;UACT,kBAAC,GAAD;WAAO,SAAQ;qBAAW,EAAQ;WAAe,CAAA;UACjD,kBAAC,QAAD;WAAM,WAAU;qBAAhB;YACG,EAAE,oCAAoC,eAAe;YAAE;YACvD,EAAI,EAAQ,cAAc;YAAC;YAAE,EAAmB,EAAQ,UAAU;YAC9D;;UACH;;QACL,EAAQ,eACP,kBAAC,KAAD;SAAG,WAAU;mBAAuB,EAAQ;SAAgB,CAAA;QAE7D,EAAQ,WACP,kBAAC,KAAD;SAAG,WAAU;mBAAb,CACE,kBAAC,GAAD,EAAe,MAAM,IAAM,CAAA,EAC1B,EACC,8BACA,6GACD,CACC;;QAEL,IACC,kBAAC,KAAD;SAAG,WAAU;mBACV,EACC,oCACA,4DACD;SACC,CAAA,GAEJ,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,UAAU,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA;UACpC,UAAU,EAAQ;UAClB,eAAe,EAAU;WAAE,MAAM;WAAW;WAAS,CAAC;oBAErD,EAAE,sCAAsC,UAAU;UAC5C,CAAA,EACT,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,UAAU,kBAAC,GAAD,EAAS,MAAM,IAAM,CAAA;UAC/B,eAAe,EAAU;WAAE,MAAM;WAAU;WAAS,CAAC;oBAEpD,EAAE,qCAAqC,SAAS;UAC1C,CAAA,CACL;;QAEL;SAxDE,EAAQ,GAwDV;OAEP;KACC,CAAA,EAEK,CAAA,CACT,EAAA,CAAA;IAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAY,EAAE,uCAAuC,mBAAmB,EAAa,CAAA,EAC1E,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,EAAQ,WAAW,IAClB,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,uCAAuC,oBAAoB;KAC5D,CAAA,GAEJ,kBAAC,MAAD;KAAI,WAAU;KAAY,eAAY;eACnC,EAAQ,KAAK,MACZ,kBAAC,MAAD;MAEE,WAAU;gBAFZ,CAIE,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAW,IAAI,EAAQ,QAAQ,IAAI,EAAQ;SACvC,CAAA;QACP,kBAAC,GAAD;SAAO,SAAS,EAAsB,EAAQ,OAAO;mBAClD,EAAQ;SACH,CAAA;QACR,kBAAC,QAAD;SAAM,WAAU;mBAAhB;UACG,EAAE,kCAAkC,KAAK;UAAC;UAAE,EAAI,EAAQ,WAAW;UAAE;UACrE,EAAQ,YAAY,EAAmB,EAAQ,UAAU,GAAG;UACxD;;QACH;UACL,EAAQ,kBACP,kBAAC,KAAD;OAAG,WAAU;iBAAe,EAAQ;OAAmB,CAAA,CAEtD;QAlBE,EAAQ,GAkBV,CACL;KACC,CAAA,EAEK,CAAA,CACT,EAAA,CAAA;IACH;MAEN,kBAAC,GAAD;GACE,MAAM,GAAQ,QAAQ;GACtB,SAAS,MAAY;GACrB,eAAe,EAAU,KAAK;GAC9B,WA9MU,OAAO,MAAgC;AAChD,UACL,KAAI;AASF,KARI,EAAO,SAAS,aAClB,MAAM,EAAI;MAAE,MAAM;MAAW,IAAI,EAAO,QAAQ;MAAI,QAAQ;MAAM,CAAC,EACnE,EAAM,QAAQ,EAAE,uCAAuC,+BAA+B,CAAC,KAEvF,MAAM,EAAI;MAAE,MAAM;MAAU,IAAI,EAAO,QAAQ;MAAI,QAAQ;MAAM,CAAC,EAClE,EAAM,QAAQ,EAAE,uCAAuC,sBAAsB,CAAC,GAEhF,EAAU,KAAK,EACf,MAAM,GAAY;aACX,GAAc;AACrB,OAAM,MACJ,aAAe,QACX,EAAI,UACJ,EAAE,oCAAoC,yBAAyB,CACpE;;;GA8LC,CAAA,CACS"}
|
|
1
|
+
{"version":3,"file":"AgentApprovalsPage.js","names":[],"sources":["../../../src/botlit/pages/AgentApprovalsPage.tsx"],"sourcesContent":["/**\n * Agent Activation Approvals Page (BOFF-9682)\n * @module botlit/pages\n *\n * Reviewer queue for the workspace: every pending request to take an agent\n * live, with approve / reject, the recent decisions, and the workspace switch\n * that makes review mandatory. Approving publishes the agent's draft and sets\n * it ACTIVE; a request whose agent changed after it was submitted is flagged\n * stale and cannot be approved.\n */\n\nimport { useMemo, useState, type FC } from 'react';\nimport { AlertTriangle, ArrowLeft, CheckCircle2, ShieldCheck, XCircle } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Badge } from '../components/Badge';\nimport { ErrorState } from '../components/ErrorState';\nimport { ApprovalDecisionDialog, approvalStatusVariant } from '../components/AgentApprovalPanel';\nimport { useAgents } from '../hooks/useAgents';\nimport {\n useAgentApprovalActions,\n useAgentApprovalRequests,\n useAgentApprovalSettings,\n type AgentApprovalRequestRecord,\n} from '../hooks/useAgentApprovals';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\n\nexport const AgentApprovalsPage: FC = () => {\n const t = useTr();\n const { navigateTo, currentUser } = useBotlit();\n const settings = useAgentApprovalSettings();\n const pendingRequests = useAgentApprovalRequests({ status: 'PENDING' });\n const allRequests = useAgentApprovalRequests({});\n const { data: agents } = useAgents();\n const { run, pending } = useAgentApprovalActions();\n const [dialog, setDialog] = useState<{\n kind: 'approve' | 'reject';\n request: AgentApprovalRequestRecord;\n } | null>(null);\n\n const agentNames = useMemo(\n () => new Map(agents.map((agent) => [agent.id, agent.name])),\n [agents]\n );\n const decided = allRequests.data.filter((request) => request.status !== 'PENDING').slice(0, 20);\n const required = settings.data?.requireActivationApproval === true;\n const who = (id?: string | null): string =>\n id && id === currentUser?.id ? t('botlit.agentApproval.you', 'you') : (id ?? '—');\n\n const refreshAll = async (): Promise<void> => {\n await Promise.all([pendingRequests.refetch(), allRequests.refetch()]);\n };\n\n const toggleRequired = async (): Promise<void> => {\n try {\n const next = await settings.update(!required);\n toast.success(\n next.requireActivationApproval\n ? t('botlit.agentApprovals.toast.enabled', 'Agents now need approval before going live')\n : t('botlit.agentApprovals.toast.disabled', 'Activation approval is now optional')\n );\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApprovals.toast.settingsError', 'Failed to update the setting')\n );\n }\n };\n\n const confirm = async (text: string): Promise<void> => {\n if (!dialog) return;\n try {\n if (dialog.kind === 'approve') {\n await run({ kind: 'approve', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.approved', 'Approved — the agent is live'));\n } else {\n await run({ kind: 'reject', id: dialog.request.id, reason: text });\n toast.success(t('botlit.agentApproval.toast.rejected', 'Activation rejected'));\n }\n setDialog(null);\n await refreshAll();\n } catch (err: unknown) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.agentApproval.toast.error', 'Approval action failed')\n );\n }\n };\n\n return (\n <PageLayout\n title={\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => navigateTo('agents')}>\n <ArrowLeft size={20} />\n </Button>\n <span>{t('botlit.agentApprovals.title', 'Agent approvals')}</span>\n </div>\n }\n description={t('botlit.agentApprovals.description', 'Review requests to take agents live')}\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<ShieldCheck size={18} />}>\n {t(\n 'botlit.agentApprovals.purpose',\n \"A reviewer checks an agent's prompt, model, tools and limits before it goes live. The person who requested activation cannot approve their own request, and every decision is kept in the history below.\"\n )}\n </PagePurpose>\n\n <Card data-testid=\"agent-approvals-settings\">\n <CardHeader className=\"flex flex-row items-start justify-between gap-4\">\n <div>\n <CardTitle className=\"flex items-center gap-2\">\n {t(\n 'botlit.agentApprovals.settings.title',\n 'Require approval before agents go live'\n )}\n <Badge variant={required ? 'warning' : 'outline'}>\n {required\n ? t('botlit.agentApprovals.settings.on', 'On')\n : t('botlit.agentApprovals.settings.off', 'Off')}\n </Badge>\n </CardTitle>\n <CardDescription>\n {t(\n 'botlit.agentApprovals.settings.description',\n 'When on, activating an agent, publishing a new version, or editing the prompt, model or tools of a live agent needs an approved request. Rolling a live agent back to an earlier version stays available for emergencies.'\n )}\n </CardDescription>\n </div>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_APPROVE}>\n <Button\n className=\"shrink-0 whitespace-nowrap\"\n variant={required ? 'outline' : 'default'}\n isLoading={settings.saving}\n disabled={settings.loading || !settings.data}\n onClick={() => void toggleRequired()}\n >\n {required\n ? t('botlit.agentApprovals.settings.turnOff', 'Turn off')\n : t('botlit.agentApprovals.settings.turnOn', 'Turn on')}\n </Button>\n </BotmanorPermissionGate>\n </CardHeader>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>{t('botlit.agentApprovals.pending.title', 'Waiting for review')}</CardTitle>\n </CardHeader>\n <CardContent>\n {pendingRequests.error ? (\n <ErrorState\n resource={t('botlit.agentApprovals.resource', 'activation requests')}\n error={pendingRequests.error}\n onRetry={() => void pendingRequests.refetch()}\n />\n ) : pendingRequests.loading && pendingRequests.data.length === 0 ? (\n <div className=\"h-24 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ) : pendingRequests.data.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.agentApprovals.pending.empty', 'No agents are waiting for review.')}\n </p>\n ) : (\n <ul className=\"space-y-3\" data-testid=\"agent-approvals-pending\">\n {pendingRequests.data.map((request) => {\n const own = request.requestedById === currentUser?.id;\n return (\n <li\n key={request.id}\n className=\"p-4 border border-border-subtle rounded-lg space-y-2\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n type=\"button\"\n className=\"font-medium text-primary hover:underline\"\n onClick={() => navigateTo(`agents/${request.agentId}`)}\n >\n {agentNames.get(request.agentId) ?? request.agentId}\n </button>\n <Badge variant=\"warning\">{request.status}</Badge>\n <span className=\"text-sm text-text-secondary\">\n {t('botlit.agentApproval.requestedBy', 'Requested by')}{' '}\n {who(request.requestedById)} {formatRelativeTime(request.createdAt)}\n </span>\n </div>\n {request.requestNote && (\n <p className=\"text-sm break-words\">{request.requestNote}</p>\n )}\n {request.isStale && (\n <p className=\"flex items-center gap-2 text-sm text-status-warning-text\">\n <AlertTriangle size={14} />\n {t(\n 'botlit.agentApproval.stale',\n 'The agent changed after this request. Submit a new request so the reviewer sees the current configuration.'\n )}\n </p>\n )}\n {own ? (\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'botlit.agentApprovals.ownRequest',\n 'You requested this, so another reviewer has to decide it.'\n )}\n </p>\n ) : (\n <div className=\"flex gap-2\">\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_APPROVE}>\n <Button\n size=\"sm\"\n leftIcon={<CheckCircle2 size={14} />}\n disabled={request.isStale}\n onClick={() => setDialog({ kind: 'approve', request })}\n >\n {t('botlit.agentApproval.approveAction', 'Approve')}\n </Button>\n </BotmanorPermissionGate>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.AGENT_APPROVE}>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n leftIcon={<XCircle size={14} />}\n onClick={() => setDialog({ kind: 'reject', request })}\n >\n {t('botlit.agentApproval.rejectAction', 'Reject')}\n </Button>\n </BotmanorPermissionGate>\n </div>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>{t('botlit.agentApprovals.history.title', 'Recent decisions')}</CardTitle>\n </CardHeader>\n <CardContent>\n {decided.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.agentApprovals.history.empty', 'No decisions yet.')}\n </p>\n ) : (\n <ul className=\"space-y-2\" data-testid=\"agent-approvals-history\">\n {decided.map((request) => (\n <li\n key={request.id}\n className=\"p-3 border border-border-subtle rounded-lg text-sm space-y-1\"\n >\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-medium\">\n {agentNames.get(request.agentId) ?? request.agentId}\n </span>\n <Badge variant={approvalStatusVariant(request.status)}>\n {request.status}\n </Badge>\n <span className=\"text-text-secondary\">\n {t('botlit.agentApproval.decidedBy', 'by')} {who(request.reviewerId)}{' '}\n {request.decidedAt ? formatRelativeTime(request.decidedAt) : ''}\n </span>\n </div>\n {request.decisionReason && (\n <p className=\"break-words\">{request.decisionReason}</p>\n )}\n </li>\n ))}\n </ul>\n )}\n </CardContent>\n </Card>\n </div>\n\n <ApprovalDecisionDialog\n kind={dialog?.kind ?? null}\n loading={pending !== null}\n onClose={() => setDialog(null)}\n onConfirm={confirm}\n />\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|