@burdenoff/microfe-botmanor 2026.1027.2 → 2026.1027.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/botlit/BotlitRoutes.js +142 -132
  2. package/dist/botlit/BotlitRoutes.js.map +1 -1
  3. package/dist/botlit/components/AgentApprovalPanel.js +144 -126
  4. package/dist/botlit/components/AgentApprovalPanel.js.map +1 -1
  5. package/dist/botlit/components/ModelRegistrationPanel.js +4 -4
  6. package/dist/botlit/components/VersionHistoryPanel.js +92 -83
  7. package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
  8. package/dist/botlit/pages/A2AAgentDetailPage.js +212 -203
  9. package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -1
  10. package/dist/botlit/pages/A2ARegistryPage.js +129 -117
  11. package/dist/botlit/pages/A2ARegistryPage.js.map +1 -1
  12. package/dist/botlit/pages/AgentApprovalsPage.js +122 -110
  13. package/dist/botlit/pages/AgentApprovalsPage.js.map +1 -1
  14. package/dist/botlit/pages/AgentBuilderPage.js +18 -18
  15. package/dist/botlit/pages/AgentDetailPage.js +298 -273
  16. package/dist/botlit/pages/AgentDetailPage.js.map +1 -1
  17. package/dist/botlit/pages/AgentsListPage.js +145 -121
  18. package/dist/botlit/pages/AgentsListPage.js.map +1 -1
  19. package/dist/botlit/pages/BotChannelsTab.js +238 -226
  20. package/dist/botlit/pages/BotChannelsTab.js.map +1 -1
  21. package/dist/botlit/pages/BotDetailPage.js +307 -288
  22. package/dist/botlit/pages/BotDetailPage.js.map +1 -1
  23. package/dist/botlit/pages/BotWorkflowTab.js +125 -116
  24. package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
  25. package/dist/botlit/pages/BotsListPage.js +159 -144
  26. package/dist/botlit/pages/BotsListPage.js.map +1 -1
  27. package/dist/botlit/pages/BucketsPage.js +279 -258
  28. package/dist/botlit/pages/BucketsPage.js.map +1 -1
  29. package/dist/botlit/pages/ChannelDetailPage.js +346 -328
  30. package/dist/botlit/pages/ChannelDetailPage.js.map +1 -1
  31. package/dist/botlit/pages/ChannelRoutesPage.js +10 -10
  32. package/dist/botlit/pages/ChannelsPage.js +163 -148
  33. package/dist/botlit/pages/ChannelsPage.js.map +1 -1
  34. package/dist/botlit/pages/DashboardPage.js +129 -114
  35. package/dist/botlit/pages/DashboardPage.js.map +1 -1
  36. package/dist/botlit/pages/ExecutionDetailPage.js +145 -139
  37. package/dist/botlit/pages/ExecutionDetailPage.js.map +1 -1
  38. package/dist/botlit/pages/ExecutionsPage.js +14 -14
  39. package/dist/botlit/pages/InstalledPackagesPage.js +245 -227
  40. package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -1
  41. package/dist/botlit/pages/KnowledgeBaseDetailPage.js +168 -156
  42. package/dist/botlit/pages/KnowledgeBaseDetailPage.js.map +1 -1
  43. package/dist/botlit/pages/KnowledgeBasesPage.js +91 -79
  44. package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -1
  45. package/dist/botlit/pages/MCPServerDetailPage.js +200 -188
  46. package/dist/botlit/pages/MCPServerDetailPage.js.map +1 -1
  47. package/dist/botlit/pages/MCPServersPage.js +170 -155
  48. package/dist/botlit/pages/MCPServersPage.js.map +1 -1
  49. package/dist/botlit/pages/PoliciesPage.js +113 -104
  50. package/dist/botlit/pages/PoliciesPage.js.map +1 -1
  51. package/dist/botlit/pages/PolicyDetailPage.js +145 -133
  52. package/dist/botlit/pages/PolicyDetailPage.js.map +1 -1
  53. package/dist/botlit/pages/PromptStudioPage.js +106 -97
  54. package/dist/botlit/pages/PromptStudioPage.js.map +1 -1
  55. package/dist/botlit/pages/PromptTemplateDetailPage.js +359 -347
  56. package/dist/botlit/pages/PromptTemplateDetailPage.js.map +1 -1
  57. package/dist/botlit/pages/PromptTemplatesPage.js +127 -112
  58. package/dist/botlit/pages/PromptTemplatesPage.js.map +1 -1
  59. package/dist/botlit/pages/RetrievalProfileDetailPage.js +219 -210
  60. package/dist/botlit/pages/RetrievalProfileDetailPage.js.map +1 -1
  61. package/dist/botlit/pages/RetrievalProfilesPage.js +112 -103
  62. package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -1
  63. package/dist/botlit/pages/SettingsPage.js +264 -252
  64. package/dist/botlit/pages/SettingsPage.js.map +1 -1
  65. package/dist/botlit/pages/SkillDetailPage.js +235 -226
  66. package/dist/botlit/pages/SkillDetailPage.js.map +1 -1
  67. package/dist/botlit/pages/SkillsPage.js +115 -106
  68. package/dist/botlit/pages/SkillsPage.js.map +1 -1
  69. package/dist/botlit/pages/StorePackageDetailPage.js +194 -188
  70. package/dist/botlit/pages/StorePackageDetailPage.js.map +1 -1
  71. package/dist/botlit/pages/StorePage.js +161 -155
  72. package/dist/botlit/pages/StorePage.js.map +1 -1
  73. package/dist/botlit/permissions/PermissionRequired.js +45 -0
  74. package/dist/botlit/permissions/PermissionRequired.js.map +1 -0
  75. package/dist/botlit/permissions/botmanorPermissions.js +72 -0
  76. package/dist/botlit/permissions/botmanorPermissions.js.map +1 -0
  77. package/dist/botlit/permissions/index.js +3 -0
  78. package/dist/botlit/permissions/useBotmanorPermissions.js +19 -0
  79. package/dist/botlit/permissions/useBotmanorPermissions.js.map +1 -0
  80. 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 { PageLayout as i } from "../components/PageLayout.js";
6
- import { Card as a, CardContent as o, CardDescription as s, CardHeader as c, CardTitle as l } from "../components/Card.js";
7
- import { Button as u } from "../components/Button.js";
8
- import { Badge as d } from "../components/Badge.js";
9
- import { ErrorState as f } from "../components/ErrorState.js";
10
- import { useAgentApprovalActions as p, useAgentApprovalRequests as m, useAgentApprovalSettings as h } from "../hooks/useAgentApprovals.js";
11
- import { ApprovalDecisionDialog as g, approvalStatusVariant as _ } from "../components/AgentApprovalPanel.js";
12
- import { useMemo as v, useState as y } from "react";
13
- import { PagePurpose as b } from "@burdenoff/fe-libs/ui";
14
- import { jsx as x, jsxs as S } from "react/jsx-runtime";
15
- import { AlertTriangle as C, ArrowLeft as w, CheckCircle2 as T, ShieldCheck as E, XCircle as D } from "lucide-react";
16
- import { toast as O } from "sonner";
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 k = () => {
19
- let k = e(), { navigateTo: A, currentUser: j } = t(), M = h(), N = m({ status: "PENDING" }), P = m({}), { data: F } = n(), { run: I, pending: L } = p(), [R, z] = y(null), B = v(() => new Map(F.map((e) => [e.id, e.name])), [F]), V = P.data.filter((e) => e.status !== "PENDING").slice(0, 20), H = M.data?.requireActivationApproval === !0, U = (e) => e && e === j?.id ? k("botlit.agentApproval.you", "you") : e ?? "—", W = async () => {
20
- await Promise.all([N.refetch(), P.refetch()]);
21
- }, G = async () => {
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 M.update(!H);
24
- O.success(e.requireActivationApproval ? k("botlit.agentApprovals.toast.enabled", "Agents now need approval before going live") : k("botlit.agentApprovals.toast.disabled", "Activation approval is now optional"));
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
- O.error(e instanceof Error ? e.message : k("botlit.agentApprovals.toast.settingsError", "Failed to update the setting"));
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__ */ S(i, {
30
- title: /* @__PURE__ */ S("div", {
32
+ return /* @__PURE__ */ w(o, {
33
+ title: /* @__PURE__ */ w("div", {
31
34
  className: "flex items-center gap-3",
32
- children: [/* @__PURE__ */ x(u, {
35
+ children: [/* @__PURE__ */ C(s, {
33
36
  variant: "ghost",
34
37
  size: "icon",
35
- onClick: () => A("agents"),
36
- children: /* @__PURE__ */ x(w, { size: 20 })
37
- }), /* @__PURE__ */ x("span", { children: k("botlit.agentApprovals.title", "Agent approvals") })]
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: k("botlit.agentApprovals.description", "Review requests to take agents live"),
40
- children: [/* @__PURE__ */ S("div", {
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__ */ x(b, {
44
- icon: /* @__PURE__ */ x(E, { size: 18 }),
45
- children: k("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
+ /* @__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__ */ x(a, {
50
+ /* @__PURE__ */ C(c, {
48
51
  "data-testid": "agent-approvals-settings",
49
- children: /* @__PURE__ */ S(c, {
52
+ children: /* @__PURE__ */ w(d, {
50
53
  className: "flex flex-row items-start justify-between gap-4",
51
- children: [/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ S(l, {
54
+ children: [/* @__PURE__ */ w("div", { children: [/* @__PURE__ */ w(f, {
52
55
  className: "flex items-center gap-2",
53
- children: [k("botlit.agentApprovals.settings.title", "Require approval before agents go live"), /* @__PURE__ */ x(d, {
54
- variant: H ? "warning" : "outline",
55
- children: H ? k("botlit.agentApprovals.settings.on", "On") : k("botlit.agentApprovals.settings.off", "Off")
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__ */ x(s, { children: k("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__ */ x(u, {
58
- className: "shrink-0 whitespace-nowrap",
59
- variant: H ? "outline" : "default",
60
- isLoading: M.saving,
61
- disabled: M.loading || !M.data,
62
- onClick: () => void G(),
63
- children: H ? k("botlit.agentApprovals.settings.turnOff", "Turn off") : k("botlit.agentApprovals.settings.turnOn", "Turn on")
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__ */ S(a, { children: [/* @__PURE__ */ x(c, { children: /* @__PURE__ */ x(l, { children: k("botlit.agentApprovals.pending.title", "Waiting for review") }) }), /* @__PURE__ */ x(o, { children: N.error ? /* @__PURE__ */ x(f, {
68
- resource: k("botlit.agentApprovals.resource", "activation requests"),
69
- error: N.error,
70
- onRetry: () => void N.refetch()
71
- }) : N.loading && N.data.length === 0 ? /* @__PURE__ */ x("div", { className: "h-24 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }) : N.data.length === 0 ? /* @__PURE__ */ x("p", {
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: k("botlit.agentApprovals.pending.empty", "No agents are waiting for review.")
74
- }) : /* @__PURE__ */ x("ul", {
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: N.data.map((e) => {
78
- let t = e.requestedById === j?.id;
79
- return /* @__PURE__ */ S("li", {
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__ */ S("div", {
88
+ /* @__PURE__ */ w("div", {
83
89
  className: "flex items-center gap-2 flex-wrap",
84
90
  children: [
85
- /* @__PURE__ */ x("button", {
91
+ /* @__PURE__ */ C("button", {
86
92
  type: "button",
87
93
  className: "font-medium text-primary hover:underline",
88
- onClick: () => A(`agents/${e.agentId}`),
89
- children: B.get(e.agentId) ?? e.agentId
94
+ onClick: () => M(`agents/${e.agentId}`),
95
+ children: H.get(e.agentId) ?? e.agentId
90
96
  }),
91
- /* @__PURE__ */ x(d, {
97
+ /* @__PURE__ */ C(p, {
92
98
  variant: "warning",
93
99
  children: e.status
94
100
  }),
95
- /* @__PURE__ */ S("span", {
101
+ /* @__PURE__ */ w("span", {
96
102
  className: "text-sm text-text-secondary",
97
103
  children: [
98
- k("botlit.agentApproval.requestedBy", "Requested by"),
104
+ j("botlit.agentApproval.requestedBy", "Requested by"),
99
105
  " ",
100
- U(e.requestedById),
106
+ G(e.requestedById),
101
107
  " ",
102
108
  r(e.createdAt)
103
109
  ]
104
110
  })
105
111
  ]
106
112
  }),
107
- e.requestNote && /* @__PURE__ */ x("p", {
113
+ e.requestNote && /* @__PURE__ */ C("p", {
108
114
  className: "text-sm break-words",
109
115
  children: e.requestNote
110
116
  }),
111
- e.isStale && /* @__PURE__ */ S("p", {
117
+ e.isStale && /* @__PURE__ */ w("p", {
112
118
  className: "flex items-center gap-2 text-sm text-status-warning-text",
113
- children: [/* @__PURE__ */ x(C, { size: 14 }), k("botlit.agentApproval.stale", "The agent changed after this request. Submit a new request so the reviewer sees the current configuration.")]
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__ */ x("p", {
121
+ t ? /* @__PURE__ */ C("p", {
116
122
  className: "text-xs text-text-secondary",
117
- children: k("botlit.agentApprovals.ownRequest", "You requested this, so another reviewer has to decide it.")
118
- }) : /* @__PURE__ */ S("div", {
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__ */ x(u, {
121
- size: "sm",
122
- leftIcon: /* @__PURE__ */ x(T, { size: 14 }),
123
- disabled: e.isStale,
124
- onClick: () => z({
125
- kind: "approve",
126
- request: e
127
- }),
128
- children: k("botlit.agentApproval.approveAction", "Approve")
129
- }), /* @__PURE__ */ x(u, {
130
- size: "sm",
131
- variant: "destructive",
132
- leftIcon: /* @__PURE__ */ x(D, { size: 14 }),
133
- onClick: () => z({
134
- kind: "reject",
135
- request: e
136
- }),
137
- children: k("botlit.agentApproval.rejectAction", "Reject")
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__ */ S(a, { children: [/* @__PURE__ */ x(c, { children: /* @__PURE__ */ x(l, { children: k("botlit.agentApprovals.history.title", "Recent decisions") }) }), /* @__PURE__ */ x(o, { children: V.length === 0 ? /* @__PURE__ */ x("p", {
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: k("botlit.agentApprovals.history.empty", "No decisions yet.")
147
- }) : /* @__PURE__ */ x("ul", {
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: V.map((e) => /* @__PURE__ */ S("li", {
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__ */ S("div", {
164
+ children: [/* @__PURE__ */ w("div", {
153
165
  className: "flex items-center gap-2 flex-wrap",
154
166
  children: [
155
- /* @__PURE__ */ x("span", {
167
+ /* @__PURE__ */ C("span", {
156
168
  className: "font-medium",
157
- children: B.get(e.agentId) ?? e.agentId
169
+ children: H.get(e.agentId) ?? e.agentId
158
170
  }),
159
- /* @__PURE__ */ x(d, {
160
- variant: _(e.status),
171
+ /* @__PURE__ */ C(p, {
172
+ variant: y(e.status),
161
173
  children: e.status
162
174
  }),
163
- /* @__PURE__ */ S("span", {
175
+ /* @__PURE__ */ w("span", {
164
176
  className: "text-text-secondary",
165
177
  children: [
166
- k("botlit.agentApproval.decidedBy", "by"),
178
+ j("botlit.agentApproval.decidedBy", "by"),
167
179
  " ",
168
- U(e.reviewerId),
180
+ G(e.reviewerId),
169
181
  " ",
170
182
  e.decidedAt ? r(e.decidedAt) : ""
171
183
  ]
172
184
  })
173
185
  ]
174
- }), e.decisionReason && /* @__PURE__ */ x("p", {
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__ */ x(g, {
182
- kind: R?.kind ?? null,
183
- loading: L !== null,
184
- onClose: () => z(null),
193
+ }), /* @__PURE__ */ C(v, {
194
+ kind: B?.kind ?? null,
195
+ loading: z !== null,
196
+ onClose: () => V(null),
185
197
  onConfirm: async (e) => {
186
- if (R) try {
187
- R.kind === "approve" ? (await I({
198
+ if (B) try {
199
+ B.kind === "approve" ? (await R({
188
200
  kind: "approve",
189
- id: R.request.id,
201
+ id: B.request.id,
190
202
  reason: e
191
- }), O.success(k("botlit.agentApproval.toast.approved", "Approved — the agent is live"))) : (await I({
203
+ }), A.success(j("botlit.agentApproval.toast.approved", "Approved — the agent is live"))) : (await R({
192
204
  kind: "reject",
193
- id: R.request.id,
205
+ id: B.request.id,
194
206
  reason: e
195
- }), O.success(k("botlit.agentApproval.toast.rejected", "Activation rejected"))), z(null), await W();
207
+ }), A.success(j("botlit.agentApproval.toast.rejected", "Activation rejected"))), V(null), await K();
196
208
  } catch (e) {
197
- O.error(e instanceof Error ? e.message : k("botlit.agentApproval.toast.error", "Approval action failed"));
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 { k as AgentApprovalsPage };
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":"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"}
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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"}