@burdenoff/microfe-botmanor 2026.819.1 → 2026.925.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.
Files changed (72) hide show
  1. package/dist/botlit/BotlitRoutes.js.map +1 -1
  2. package/dist/botlit/BotmanorRoot.js.map +1 -1
  3. package/dist/botlit/BotmanorRootInner.js +4 -4
  4. package/dist/botlit/BotmanorRootInner.js.map +1 -1
  5. package/dist/botlit/components/ErrorState.js +33 -29
  6. package/dist/botlit/components/ErrorState.js.map +1 -1
  7. package/dist/botlit/components/RouteLoader.js +52 -48
  8. package/dist/botlit/components/RouteLoader.js.map +1 -1
  9. package/dist/botlit/components/VersionHistoryPanel.js +74 -77
  10. package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
  11. package/dist/botlit/components/WorkspaceRequired.js +31 -30
  12. package/dist/botlit/components/WorkspaceRequired.js.map +1 -1
  13. package/dist/botlit/hooks/internal/workspaceGateway.js.map +1 -1
  14. package/dist/botlit/hooks/useConversations.js.map +1 -1
  15. package/dist/botlit/hooks/useLLMProviders.js.map +1 -1
  16. package/dist/botlit/hooks/useMCPServers.js +60 -49
  17. package/dist/botlit/hooks/useMCPServers.js.map +1 -1
  18. package/dist/botlit/pages/A2AAgentDetailPage.js +1 -1
  19. package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -1
  20. package/dist/botlit/pages/A2ARegistryPage.js +116 -124
  21. package/dist/botlit/pages/A2ARegistryPage.js.map +1 -1
  22. package/dist/botlit/pages/AgentDetailPage.js +169 -172
  23. package/dist/botlit/pages/AgentDetailPage.js.map +1 -1
  24. package/dist/botlit/pages/AgentsListPage.js +96 -90
  25. package/dist/botlit/pages/AgentsListPage.js.map +1 -1
  26. package/dist/botlit/pages/BotChannelsTab.js.map +1 -1
  27. package/dist/botlit/pages/BotDetailPage.js +228 -231
  28. package/dist/botlit/pages/BotDetailPage.js.map +1 -1
  29. package/dist/botlit/pages/BotWorkflowTab.js +84 -87
  30. package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
  31. package/dist/botlit/pages/BotsListPage.js +144 -147
  32. package/dist/botlit/pages/BotsListPage.js.map +1 -1
  33. package/dist/botlit/pages/BucketsPage.js +3 -3
  34. package/dist/botlit/pages/BucketsPage.js.map +1 -1
  35. package/dist/botlit/pages/ChannelDetailPage.js +1 -1
  36. package/dist/botlit/pages/ChannelDetailPage.js.map +1 -1
  37. package/dist/botlit/pages/ChannelsPage.js +156 -149
  38. package/dist/botlit/pages/ChannelsPage.js.map +1 -1
  39. package/dist/botlit/pages/ChatPage.js +126 -129
  40. package/dist/botlit/pages/ChatPage.js.map +1 -1
  41. package/dist/botlit/pages/DashboardPage.js +111 -114
  42. package/dist/botlit/pages/DashboardPage.js.map +1 -1
  43. package/dist/botlit/pages/ExecutionsPage.js +163 -159
  44. package/dist/botlit/pages/ExecutionsPage.js.map +1 -1
  45. package/dist/botlit/pages/InstalledPackagesPage.js +3 -3
  46. package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -1
  47. package/dist/botlit/pages/KnowledgeBasesPage.js +84 -78
  48. package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -1
  49. package/dist/botlit/pages/MCPServerDetailPage.js +295 -238
  50. package/dist/botlit/pages/MCPServerDetailPage.js.map +1 -1
  51. package/dist/botlit/pages/MCPServersPage.js +159 -154
  52. package/dist/botlit/pages/MCPServersPage.js.map +1 -1
  53. package/dist/botlit/pages/PoliciesPage.js +119 -114
  54. package/dist/botlit/pages/PoliciesPage.js.map +1 -1
  55. package/dist/botlit/pages/RetrievalProfilesPage.js +102 -109
  56. package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -1
  57. package/dist/botlit/pages/SettingsPage.js +144 -159
  58. package/dist/botlit/pages/SettingsPage.js.map +1 -1
  59. package/dist/botlit/pages/SkillsPage.js +122 -105
  60. package/dist/botlit/pages/SkillsPage.js.map +1 -1
  61. package/dist/botlit/pages/StorePage.js +176 -175
  62. package/dist/botlit/pages/StorePage.js.map +1 -1
  63. package/dist/botlit/providers/BotlitProvider.js.map +1 -1
  64. package/dist/botlit/store/botlitStore.js +1 -1
  65. package/dist/botlit/store/botlitStore.js.map +1 -1
  66. package/dist/botlit/utils/navigation.js.map +1 -1
  67. package/dist/generated/wspace-operations.js +45 -29
  68. package/dist/generated/wspace-operations.js.map +1 -1
  69. package/dist/generated/wspace-types.js.map +1 -1
  70. package/dist/shared/hooks/useTr.js +14 -0
  71. package/dist/shared/hooks/useTr.js.map +1 -0
  72. package/package.json +33 -9
@@ -1 +1 @@
1
- {"version":3,"file":"InstalledPackagesPage.js","names":[],"sources":["../../../src/botlit/pages/InstalledPackagesPage.tsx"],"sourcesContent":["/**\n * Installed Packages Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { Link } from 'react-router';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport {\n Package,\n Download,\n RefreshCw,\n Trash2,\n GitBranch,\n Link2,\n Copy,\n Settings,\n ArrowUpCircle,\n Search,\n ExternalLink,\n} from 'lucide-react';\nimport { toast } from 'sonner';\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 } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport {\n useInstalledPackages,\n useUninstallPackage,\n useUpdateInstalledPackage,\n usePinPackageVersion,\n storePackageName,\n type InstalledPackageRecord,\n} from '../hooks';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { PackageKind as GqlPackageKind } from '../../generated/wspace-types';\nimport type { Environment, PackageKind } from '../types';\n\nconst ENVIRONMENTS: Environment[] = ['DEV', 'STAGING', 'PROD'];\n\nconst PACKAGE_KIND_CONFIG: Record<string, { label: string; icon: string }> = {\n APP: { label: 'Bot', icon: '📱' },\n AGENT: { label: 'Agent', icon: '🤖' },\n SKILL: { label: 'Skill', icon: '⚡' },\n MCP_PACK: { label: 'MCP Pack', icon: '🔧' },\n PROMPT_TEMPLATE: { label: 'Template', icon: '📝' },\n PROMPT: { label: 'Prompt', icon: '📝' },\n RETRIEVAL_PROFILE: { label: 'Retrieval', icon: '🔍' },\n POLICY_BUNDLE: { label: 'Policy', icon: '🛡️' },\n CHANNEL_TEMPLATE: { label: 'Channel', icon: '📡' },\n A2A_AGENT: { label: 'A2A Agent', icon: '🔗' },\n KB_TEMPLATE: { label: 'KB Template', icon: '📚' },\n KNOWLEDGE_BASE: { label: 'Knowledge Base', icon: '📚' },\n INTEGRATION: { label: 'Integration', icon: '🔌' },\n TEMPLATE: { label: 'Template', icon: '📝' },\n TOOL: { label: 'Tool', icon: '🔧' },\n WORKFLOW: { label: 'Workflow', icon: '🔀' },\n};\n\nconst UNKNOWN_KIND = { label: 'Package', icon: '📦' };\n\n/** Store slug for an install, falling back to the package id when unresolved. */\nfunction installSlug(pkg: InstalledPackageRecord): string {\n return pkg.package?.slug ?? pkg.packageId;\n}\n\nfunction installKind(pkg: InstalledPackageRecord): string | undefined {\n return pkg.package?.kind;\n}\n\nfunction kindConfigFor(pkg: InstalledPackageRecord) {\n const kind = installKind(pkg);\n return (kind && PACKAGE_KIND_CONFIG[kind]) || UNKNOWN_KIND;\n}\n\nfunction hasUpdate(pkg: InstalledPackageRecord): boolean {\n const latest = pkg.package?.version;\n return Boolean(latest && latest !== pkg.installedVersion);\n}\n\n/** `pinnedByEnv` is free-form JSON — read one environment's pin defensively. */\nfunction pinnedVersionFor(pkg: InstalledPackageRecord, env: Environment): string | undefined {\n const value = pkg.pinnedByEnv?.[env];\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nexport const InstalledPackagesPage: FC = () => {\n const { navigateTo, getPath } = useBotlit();\n const { data: packages, loading, error, refetch } = useInstalledPackages();\n const { uninstall, loading: uninstallLoading } = useUninstallPackage();\n const { update, loading: updateLoading } = useUpdateInstalledPackage();\n const { pin } = usePinPackageVersion();\n\n const [search, setSearch] = useState('');\n const [refreshing, setRefreshing] = useState(false);\n const [kindFilter, setKindFilter] = useState<PackageKind | 'all'>('all');\n const [selectedPackageId, setSelectedPackageId] = useState<string | null>(null);\n\n const filteredPackages = useMemo(() => {\n const needle = search.trim().toLowerCase();\n return packages.filter((pkg) => {\n const matchesSearch =\n !needle ||\n installSlug(pkg).toLowerCase().includes(needle) ||\n storePackageName(pkg.package).toLowerCase().includes(needle);\n const matchesKind = kindFilter === 'all' || installKind(pkg) === kindFilter;\n return matchesSearch && matchesKind;\n });\n }, [packages, search, kindFilter]);\n\n const selectedPackage = useMemo(\n () => packages.find((pkg) => pkg.id === selectedPackageId) ?? null,\n [packages, selectedPackageId]\n );\n\n const updatesAvailable = useMemo(() => packages.filter(hasUpdate).length, [packages]);\n\n const handleCheckUpdates = async () => {\n setRefreshing(true);\n try {\n await refetch();\n } finally {\n setRefreshing(false);\n }\n };\n\n const handleUninstall = async (pkg: InstalledPackageRecord) => {\n if (!confirm('Are you sure you want to uninstall this package?')) return;\n try {\n await uninstall(pkg.id);\n toast.success(`Uninstalled \"${storePackageName(pkg.package) || installSlug(pkg)}\"`);\n setSelectedPackageId(null);\n void refetch();\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to uninstall package');\n }\n };\n\n const handleUpdate = async (pkg: InstalledPackageRecord) => {\n const latest = pkg.package?.version;\n if (!latest) return;\n try {\n await update({ installedId: pkg.id, input: { installedVersion: latest } });\n toast.success(`Updated to v${latest}`);\n void refetch();\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to update package');\n }\n };\n\n const handlePinVersion = async (\n pkg: InstalledPackageRecord,\n env: Environment,\n version: string\n ) => {\n try {\n await pin({\n installedId: pkg.id,\n environment: env,\n version,\n pinnedByEnv: pkg.pinnedByEnv,\n });\n toast.success(version ? `Pinned ${env} to v${version}` : `Unpinned ${env}`);\n void refetch();\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to change version pin');\n }\n };\n\n const getModeIcon = (mode: string) =>\n mode === 'LINKED' ? (\n <Link2 className=\"h-4 w-4 text-status-info-text\" />\n ) : (\n <Copy className=\"h-4 w-4 text-status-warning-text\" />\n );\n\n const PackageCard: FC<{ pkg: InstalledPackageRecord }> = ({ pkg }) => {\n const kindConfig = kindConfigFor(pkg);\n const slug = installSlug(pkg);\n const updateAvailable = hasUpdate(pkg);\n const pinnedEnvironments = ENVIRONMENTS.filter((env) => pinnedVersionFor(pkg, env));\n\n return (\n <Card\n className=\"hover:shadow-md transition-shadow cursor-pointer\"\n onClick={() => setSelectedPackageId(pkg.id)}\n >\n <CardContent className=\"pt-6\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n <div className=\"p-2 rounded-lg bg-bg-sunken text-2xl\">{kindConfig.icon}</div>\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-semibold\">{storePackageName(pkg.package) || slug}</h3>\n {updateAvailable && (\n <Badge variant=\"warning\" className=\"gap-1\">\n <ArrowUpCircle className=\"h-3 w-3\" />\n Update\n </Badge>\n )}\n </div>\n <p className=\"text-sm text-text-secondary font-mono\">{slug}</p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {getModeIcon(pkg.mode)}\n <Badge variant=\"outline\">{kindConfig.label}</Badge>\n </div>\n </div>\n\n <div className=\"mt-4 grid grid-cols-3 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">Installed Version</p>\n <p className=\"font-medium font-mono\">v{pkg.installedVersion}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Mode</p>\n <p className=\"font-medium flex items-center gap-1\">\n {getModeIcon(pkg.mode)}\n {pkg.mode}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Installed</p>\n <p className=\"font-medium\">{formatRelativeTime(pkg.installedAt)}</p>\n </div>\n </div>\n\n {/* Environment Pins */}\n {pinnedEnvironments.length > 0 && (\n <div className=\"mt-4 pt-4 border-t border-border-subtle\">\n <p className=\"text-xs text-text-secondary mb-2\">Pinned Versions</p>\n <div className=\"flex gap-2\">\n {ENVIRONMENTS.map((env) => {\n const pinnedVersion = pinnedVersionFor(pkg, env);\n return (\n <Badge\n key={env}\n variant={pinnedVersion ? 'default' : 'outline'}\n className=\"text-xs\"\n >\n {env}: {pinnedVersion ?? 'latest'}\n </Badge>\n );\n })}\n </div>\n </div>\n )}\n\n <div className=\"mt-4 flex justify-end gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n navigateTo(`store/package/${slug}`);\n }}\n >\n <ExternalLink className=\"h-4 w-4 mr-1\" />\n View in Store\n </Button>\n {updateAvailable && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n void handleUpdate(pkg);\n }}\n isLoading={updateLoading}\n >\n <ArrowUpCircle className=\"h-4 w-4 mr-1\" />\n Update\n </Button>\n )}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Uninstall package\"\n className=\"text-status-error-text hover:text-status-error-text\"\n onClick={(e) => {\n e.stopPropagation();\n void handleUninstall(pkg);\n }}\n isLoading={uninstallLoading}\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n };\n\n const PackageDetailModal: FC<{ pkg: InstalledPackageRecord; onClose: () => void }> = ({\n pkg,\n onClose,\n }) => {\n const kindConfig = kindConfigFor(pkg);\n const slug = installSlug(pkg);\n const bindings = pkg.bindings ?? {};\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div className=\"bg-bg-surface rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto\">\n <div className=\"p-6 border-b border-border-subtle\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n <div className=\"p-3 rounded-lg bg-bg-sunken text-3xl\">{kindConfig.icon}</div>\n <div>\n <h2 className=\"text-xl font-bold\">{storePackageName(pkg.package) || slug}</h2>\n <p className=\"text-sm text-text-secondary font-mono\">{slug}</p>\n </div>\n </div>\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Close\" onClick={onClose}>\n ×\n </Button>\n </div>\n </div>\n\n <div className=\"p-6 space-y-6\">\n {/* Version Info */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Version Information</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Installed Version</p>\n <p className=\"font-mono font-medium\">v{pkg.installedVersion}</p>\n </div>\n {pkg.package && (\n <div>\n <p className=\"text-sm text-text-secondary\">Latest Version</p>\n <p className=\"font-mono font-medium\">v{pkg.package.version}</p>\n </div>\n )}\n </div>\n\n <div>\n <p className=\"text-sm text-text-secondary mb-2\">Installation Mode</p>\n <div className=\"flex items-center gap-2\">\n {getModeIcon(pkg.mode)}\n <span className=\"font-medium\">{pkg.mode}</span>\n <span className=\"text-sm text-text-secondary\">\n {pkg.mode === 'LINKED'\n ? '- Receives updates automatically'\n : '- Independent copy, no auto-updates'}\n </span>\n </div>\n </div>\n </CardContent>\n </Card>\n\n {/* Environment Pinning */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <GitBranch className=\"h-4 w-4\" />\n Environment Version Pins\n </CardTitle>\n <CardDescription>Pin specific versions for each environment</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {ENVIRONMENTS.map((env) => {\n const pinnedVersion = pinnedVersionFor(pkg, env);\n return (\n <div\n key={env}\n className=\"flex items-center justify-between p-3 bg-bg-sunken rounded-lg\"\n >\n <div>\n <p className=\"font-medium\">{env}</p>\n <p className=\"text-sm text-text-secondary font-mono\">\n {pinnedVersion ? `v${pinnedVersion}` : 'Using latest'}\n </p>\n </div>\n <div className=\"flex gap-2\">\n {pinnedVersion ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handlePinVersion(pkg, env, '')}\n >\n Unpin\n </Button>\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handlePinVersion(pkg, env, pkg.installedVersion)}\n >\n Pin Current\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n {/* Bindings */}\n {Object.keys(bindings).length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n Configuration Bindings\n </CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n {Object.entries(bindings).map(([key, value]) => (\n <div key={key} className=\"flex justify-between p-2 bg-bg-sunken rounded\">\n <span className=\"font-mono text-sm\">{key}</span>\n <span className=\"font-mono text-sm text-text-secondary\">\n {typeof value === 'string' ? value : JSON.stringify(value)}\n </span>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Metadata */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Metadata</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">Installed At</p>\n <p className=\"font-medium\">{formatRelativeTime(pkg.installedAt)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Installed By</p>\n <p className=\"font-medium\">{pkg.installedBy}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Package ID</p>\n <p className=\"font-mono text-xs\">{pkg.packageId}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Installation ID</p>\n <p className=\"font-mono text-xs\">{pkg.id}</p>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"p-6 border-t border-border-subtle flex justify-between\">\n <Button variant=\"destructive\" onClick={() => void handleUninstall(pkg)}>\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Uninstall\n </Button>\n <div className=\"flex gap-2\">\n <Link to={getPath(`store/package/${slug}`)}>\n <Button variant=\"outline\">View in Store</Button>\n </Link>\n <Button variant=\"outline\" onClick={onClose}>\n Close\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n };\n\n if (loading) {\n return (\n <PageLayout title=\"Installed Packages\" description=\"Manage installed store packages\">\n <div className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ))}\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Installed Packages\"\n description=\"Manage packages installed from the Botlit Store\"\n actions={\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n leftIcon={<RefreshCw size={16} />}\n onClick={() => void handleCheckUpdates()}\n isLoading={refreshing}\n >\n Check Updates\n </Button>\n <Button leftIcon={<Package size={16} />} onClick={() => navigateTo('store')}>\n Browse Store\n </Button>\n </div>\n }\n >\n <PagePurpose className=\"mb-6\" icon={<Package size={18} />}>\n These are the packages you have installed from the Botlit Store and how they are wired into\n your workspace. Manage each one&rsquo;s installation mode (linked, so it auto-updates, or\n forked as an independent copy), pin specific versions per environment, and update or\n uninstall — this is your dependency manager for everything you pulled from the store.\n </PagePurpose>\n\n {error ? (\n <ErrorState resource=\"installed packages\" error={error} onRetry={() => void refetch()} />\n ) : (\n <>\n {/* Summary Cards */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 mb-6\">\n <GlassCard treatment=\"glass\" glow className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">{packages.length}</p>\n <p className=\"text-sm text-text-secondary\">Total Installed</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">\n {packages.filter((pkg) => pkg.mode === 'LINKED').length}\n </p>\n <p className=\"text-sm text-text-secondary\">Linked</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">\n {packages.filter((pkg) => pkg.mode === 'FORKED').length}\n </p>\n <p className=\"text-sm text-text-secondary\">Forked</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">\n {updatesAvailable}\n </p>\n <p className=\"text-sm text-text-secondary\">Updates Available</p>\n </GlassCard>\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-col md:flex-row gap-4 mb-6\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder=\"Search packages...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n <div className=\"flex gap-2\">\n <select\n aria-label=\"Filter by package type\"\n className=\"flex h-10 rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value as PackageKind | 'all')}\n >\n <option value=\"all\">All Types</option>\n <option value={GqlPackageKind.Agent}>Agents</option>\n <option value={GqlPackageKind.Skill}>Skills</option>\n <option value={GqlPackageKind.McpPack}>MCP Packs</option>\n <option value={GqlPackageKind.PromptTemplate}>Templates</option>\n <option value={GqlPackageKind.RetrievalProfile}>Retrieval Profiles</option>\n </select>\n </div>\n </div>\n\n {/* Package List */}\n {filteredPackages.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filteredPackages.map((pkg) => (\n <PackageCard key={pkg.id} pkg={pkg} />\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title={\n search || kindFilter !== 'all' ? 'No matching packages' : 'No packages installed'\n }\n description={\n search || kindFilter !== 'all'\n ? 'Try adjusting your search or type filter.'\n : 'Browse the Botlit Store to find agents, skills, and tools to install.'\n }\n action={\n <Button\n onClick={() => navigateTo('store')}\n leftIcon={<Download className=\"h-4 w-4\" />}\n >\n Browse Store\n </Button>\n }\n />\n )}\n </>\n )}\n\n {/* Detail Modal */}\n {selectedPackage && (\n <PackageDetailModal pkg={selectedPackage} onClose={() => setSelectedPackageId(null)} />\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"InstalledPackagesPage.js","names":[],"sources":["../../../src/botlit/pages/InstalledPackagesPage.tsx"],"sourcesContent":["/**\n * Installed Packages Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useMemo, useState } from 'react';\nimport { Link } from 'react-router';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport {\n Package,\n Download,\n RefreshCw,\n Trash2,\n GitBranch,\n Link2,\n Copy,\n Settings,\n ArrowUpCircle,\n Search,\n ExternalLink,\n} from 'lucide-react';\nimport { toast } from 'sonner';\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 } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport {\n useInstalledPackages,\n useUninstallPackage,\n useUpdateInstalledPackage,\n usePinPackageVersion,\n storePackageName,\n type InstalledPackageRecord,\n} from '../hooks';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { PackageKind as GqlPackageKind } from '../../generated/wspace-types';\nimport type { Environment, PackageKind } from '../types';\n\nconst ENVIRONMENTS: Environment[] = ['DEV', 'STAGING', 'PROD'];\n\nconst PACKAGE_KIND_CONFIG: Record<string, { label: string; icon: string }> = {\n APP: { label: 'Bot', icon: '📱' },\n AGENT: { label: 'Agent', icon: '🤖' },\n SKILL: { label: 'Skill', icon: '⚡' },\n MCP_PACK: { label: 'MCP Pack', icon: '🔧' },\n PROMPT_TEMPLATE: { label: 'Template', icon: '📝' },\n PROMPT: { label: 'Prompt', icon: '📝' },\n RETRIEVAL_PROFILE: { label: 'Retrieval', icon: '🔍' },\n POLICY_BUNDLE: { label: 'Policy', icon: '🛡️' },\n CHANNEL_TEMPLATE: { label: 'Channel', icon: '📡' },\n A2A_AGENT: { label: 'A2A Agent', icon: '🔗' },\n KB_TEMPLATE: { label: 'KB Template', icon: '📚' },\n KNOWLEDGE_BASE: { label: 'Knowledge Base', icon: '📚' },\n INTEGRATION: { label: 'Integration', icon: '🔌' },\n TEMPLATE: { label: 'Template', icon: '📝' },\n TOOL: { label: 'Tool', icon: '🔧' },\n WORKFLOW: { label: 'Workflow', icon: '🔀' },\n};\n\nconst UNKNOWN_KIND = { label: 'Package', icon: '📦' };\n\n/** Store slug for an install, falling back to the package id when unresolved. */\nfunction installSlug(pkg: InstalledPackageRecord): string {\n return pkg.package?.slug ?? pkg.packageId;\n}\n\nfunction installKind(pkg: InstalledPackageRecord): string | undefined {\n return pkg.package?.kind;\n}\n\nfunction kindConfigFor(pkg: InstalledPackageRecord) {\n const kind = installKind(pkg);\n return (kind && PACKAGE_KIND_CONFIG[kind]) || UNKNOWN_KIND;\n}\n\nfunction hasUpdate(pkg: InstalledPackageRecord): boolean {\n const latest = pkg.package?.version;\n return Boolean(latest && latest !== pkg.installedVersion);\n}\n\n/** `pinnedByEnv` is free-form JSON — read one environment's pin defensively. */\nfunction pinnedVersionFor(pkg: InstalledPackageRecord, env: Environment): string | undefined {\n const value = pkg.pinnedByEnv?.[env];\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nexport const InstalledPackagesPage: FC = () => {\n const { navigateTo, getPath } = useBotlit();\n const { data: packages, loading, error, refetch } = useInstalledPackages();\n const { uninstall, loading: uninstallLoading } = useUninstallPackage();\n const { update, loading: updateLoading } = useUpdateInstalledPackage();\n const { pin } = usePinPackageVersion();\n\n const [search, setSearch] = useState('');\n const [refreshing, setRefreshing] = useState(false);\n const [kindFilter, setKindFilter] = useState<PackageKind | 'all'>('all');\n const [selectedPackageId, setSelectedPackageId] = useState<string | null>(null);\n\n const filteredPackages = useMemo(() => {\n const needle = search.trim().toLowerCase();\n return packages.filter((pkg) => {\n const matchesSearch =\n !needle ||\n installSlug(pkg).toLowerCase().includes(needle) ||\n storePackageName(pkg.package).toLowerCase().includes(needle);\n const matchesKind = kindFilter === 'all' || installKind(pkg) === kindFilter;\n return matchesSearch && matchesKind;\n });\n }, [packages, search, kindFilter]);\n\n const selectedPackage = useMemo(\n () => packages.find((pkg) => pkg.id === selectedPackageId) ?? null,\n [packages, selectedPackageId]\n );\n\n const updatesAvailable = useMemo(() => packages.filter(hasUpdate).length, [packages]);\n\n const handleCheckUpdates = async () => {\n setRefreshing(true);\n try {\n await refetch();\n } finally {\n setRefreshing(false);\n }\n };\n\n const handleUninstall = async (pkg: InstalledPackageRecord) => {\n if (!confirm('Are you sure you want to uninstall this package?')) return;\n try {\n await uninstall(pkg.id);\n toast.success(`Uninstalled \"${storePackageName(pkg.package) || installSlug(pkg)}\"`);\n setSelectedPackageId(null);\n void refetch();\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to uninstall package');\n }\n };\n\n const handleUpdate = async (pkg: InstalledPackageRecord) => {\n const latest = pkg.package?.version;\n if (!latest) return;\n try {\n await update({ installedId: pkg.id, input: { installedVersion: latest } });\n toast.success(`Updated to v${latest}`);\n void refetch();\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to update package');\n }\n };\n\n const handlePinVersion = async (\n pkg: InstalledPackageRecord,\n env: Environment,\n version: string\n ) => {\n try {\n await pin({\n installedId: pkg.id,\n environment: env,\n version,\n pinnedByEnv: pkg.pinnedByEnv,\n });\n toast.success(version ? `Pinned ${env} to v${version}` : `Unpinned ${env}`);\n void refetch();\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to change version pin');\n }\n };\n\n const getModeIcon = (mode: string) =>\n mode === 'LINKED' ? (\n <Link2 className=\"h-4 w-4 text-status-info-text\" />\n ) : (\n <Copy className=\"h-4 w-4 text-status-warning-text\" />\n );\n\n const PackageCard: FC<{ pkg: InstalledPackageRecord }> = ({ pkg }) => {\n const kindConfig = kindConfigFor(pkg);\n const slug = installSlug(pkg);\n const updateAvailable = hasUpdate(pkg);\n const pinnedEnvironments = ENVIRONMENTS.filter((env) => pinnedVersionFor(pkg, env));\n\n return (\n <Card\n className=\"hover:shadow-md transition-shadow cursor-pointer\"\n onClick={() => setSelectedPackageId(pkg.id)}\n >\n <CardContent className=\"pt-6\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n <div className=\"p-2 rounded-lg bg-bg-sunken text-2xl\">{kindConfig.icon}</div>\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-semibold\">{storePackageName(pkg.package) || slug}</h3>\n {updateAvailable && (\n <Badge variant=\"warning\" className=\"gap-1\">\n <ArrowUpCircle className=\"h-3 w-3\" />\n Update\n </Badge>\n )}\n </div>\n <p className=\"text-sm text-text-secondary font-mono\">{slug}</p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {getModeIcon(pkg.mode)}\n <Badge variant=\"outline\">{kindConfig.label}</Badge>\n </div>\n </div>\n\n <div className=\"mt-4 grid grid-cols-3 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">Installed Version</p>\n <p className=\"font-medium font-mono\">v{pkg.installedVersion}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Mode</p>\n <p className=\"font-medium flex items-center gap-1\">\n {getModeIcon(pkg.mode)}\n {pkg.mode}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Installed</p>\n <p className=\"font-medium\">{formatRelativeTime(pkg.installedAt)}</p>\n </div>\n </div>\n\n {/* Environment Pins */}\n {pinnedEnvironments.length > 0 && (\n <div className=\"mt-4 pt-4 border-t border-border-subtle\">\n <p className=\"text-xs text-text-secondary mb-2\">Pinned Versions</p>\n <div className=\"flex gap-2\">\n {ENVIRONMENTS.map((env) => {\n const pinnedVersion = pinnedVersionFor(pkg, env);\n return (\n <Badge\n key={env}\n variant={pinnedVersion ? 'default' : 'outline'}\n className=\"text-xs\"\n >\n {env}: {pinnedVersion ?? 'latest'}\n </Badge>\n );\n })}\n </div>\n </div>\n )}\n\n <div className=\"mt-4 flex justify-end gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n navigateTo(`store/package/${slug}`);\n }}\n >\n <ExternalLink className=\"h-4 w-4 mr-1\" />\n View in Store\n </Button>\n {updateAvailable && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n void handleUpdate(pkg);\n }}\n isLoading={updateLoading}\n >\n <ArrowUpCircle className=\"h-4 w-4 mr-1\" />\n Update\n </Button>\n )}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Uninstall package\"\n className=\"text-status-error-text hover:text-status-error-text\"\n onClick={(e) => {\n e.stopPropagation();\n void handleUninstall(pkg);\n }}\n isLoading={uninstallLoading}\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n };\n\n const PackageDetailModal: FC<{ pkg: InstalledPackageRecord; onClose: () => void }> = ({\n pkg,\n onClose,\n }) => {\n const kindConfig = kindConfigFor(pkg);\n const slug = installSlug(pkg);\n const bindings = pkg.bindings ?? {};\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div className=\"bg-bg-surface rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto\">\n <div className=\"p-6 border-b border-border-subtle\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n <div className=\"p-3 rounded-lg bg-bg-sunken text-3xl\">{kindConfig.icon}</div>\n <div>\n <h2 className=\"text-xl font-bold\">{storePackageName(pkg.package) || slug}</h2>\n <p className=\"text-sm text-text-secondary font-mono\">{slug}</p>\n </div>\n </div>\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Close\" onClick={onClose}>\n ×\n </Button>\n </div>\n </div>\n\n <div className=\"p-6 space-y-6\">\n {/* Version Info */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Version Information</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Installed Version</p>\n <p className=\"font-mono font-medium\">v{pkg.installedVersion}</p>\n </div>\n {pkg.package && (\n <div>\n <p className=\"text-sm text-text-secondary\">Latest Version</p>\n <p className=\"font-mono font-medium\">v{pkg.package.version}</p>\n </div>\n )}\n </div>\n\n <div>\n <p className=\"text-sm text-text-secondary mb-2\">Installation Mode</p>\n <div className=\"flex items-center gap-2\">\n {getModeIcon(pkg.mode)}\n <span className=\"font-medium\">{pkg.mode}</span>\n <span className=\"text-sm text-text-secondary\">\n {pkg.mode === 'LINKED'\n ? '- Receives updates automatically'\n : '- Independent copy, no auto-updates'}\n </span>\n </div>\n </div>\n </CardContent>\n </Card>\n\n {/* Environment Pinning */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <GitBranch className=\"h-4 w-4\" />\n Environment Version Pins\n </CardTitle>\n <CardDescription>Pin specific versions for each environment</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {ENVIRONMENTS.map((env) => {\n const pinnedVersion = pinnedVersionFor(pkg, env);\n return (\n <div\n key={env}\n className=\"flex items-center justify-between p-3 bg-bg-sunken rounded-lg\"\n >\n <div>\n <p className=\"font-medium\">{env}</p>\n <p className=\"text-sm text-text-secondary font-mono\">\n {pinnedVersion ? `v${pinnedVersion}` : 'Using latest'}\n </p>\n </div>\n <div className=\"flex gap-2\">\n {pinnedVersion ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handlePinVersion(pkg, env, '')}\n >\n Unpin\n </Button>\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handlePinVersion(pkg, env, pkg.installedVersion)}\n >\n Pin Current\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n {/* Bindings */}\n {Object.keys(bindings).length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n Configuration Bindings\n </CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n {Object.entries(bindings).map(([key, value]) => (\n <div key={key} className=\"flex justify-between p-2 bg-bg-sunken rounded\">\n <span className=\"font-mono text-sm\">{key}</span>\n <span className=\"font-mono text-sm text-text-secondary\">\n {typeof value === 'string' ? value : JSON.stringify(value)}\n </span>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Metadata */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Metadata</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">Installed At</p>\n <p className=\"font-medium\">{formatRelativeTime(pkg.installedAt)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Installed By</p>\n <p className=\"font-medium\">{pkg.installedBy}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Package ID</p>\n <p className=\"font-mono text-xs\">{pkg.packageId}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Installation ID</p>\n <p className=\"font-mono text-xs\">{pkg.id}</p>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"p-6 border-t border-border-subtle flex justify-between\">\n <Button variant=\"destructive\" onClick={() => void handleUninstall(pkg)}>\n <Trash2 className=\"h-4 w-4 mr-2\" />\n Uninstall\n </Button>\n <div className=\"flex gap-2\">\n <Link to={getPath(`store/package/${slug}`)}>\n <Button variant=\"outline\">View in Store</Button>\n </Link>\n <Button variant=\"outline\" onClick={onClose}>\n Close\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n };\n\n if (loading) {\n return (\n <PageLayout title=\"Installed Packages\" description=\"Manage installed store packages\">\n <div className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n ))}\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Installed Packages\"\n description=\"Manage packages installed from the BotManor Store\"\n actions={\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n leftIcon={<RefreshCw size={16} />}\n onClick={() => void handleCheckUpdates()}\n isLoading={refreshing}\n >\n Check Updates\n </Button>\n <Button leftIcon={<Package size={16} />} onClick={() => navigateTo('store')}>\n Browse Store\n </Button>\n </div>\n }\n >\n <PagePurpose className=\"mb-6\" icon={<Package size={18} />}>\n These are the packages you have installed from the BotManor Store and how they are wired\n into your workspace. Manage each one&rsquo;s installation mode (linked, so it auto-updates,\n or forked as an independent copy), pin specific versions per environment, and update or\n uninstall — this is your dependency manager for everything you pulled from the store.\n </PagePurpose>\n\n {error ? (\n <ErrorState resource=\"installed packages\" error={error} onRetry={() => void refetch()} />\n ) : (\n <>\n {/* Summary Cards */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 mb-6\">\n <GlassCard treatment=\"glass\" glow className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">{packages.length}</p>\n <p className=\"text-sm text-text-secondary\">Total Installed</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">\n {packages.filter((pkg) => pkg.mode === 'LINKED').length}\n </p>\n <p className=\"text-sm text-text-secondary\">Linked</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">\n {packages.filter((pkg) => pkg.mode === 'FORKED').length}\n </p>\n <p className=\"text-sm text-text-secondary\">Forked</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-6 text-center\">\n <p className=\"text-3xl font-bold tabular-nums text-text-primary\">\n {updatesAvailable}\n </p>\n <p className=\"text-sm text-text-secondary\">Updates Available</p>\n </GlassCard>\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-col md:flex-row gap-4 mb-6\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder=\"Search packages...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"pl-9\"\n />\n </div>\n <div className=\"flex gap-2\">\n <select\n aria-label=\"Filter by package type\"\n className=\"flex h-10 rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value as PackageKind | 'all')}\n >\n <option value=\"all\">All Types</option>\n <option value={GqlPackageKind.Agent}>Agents</option>\n <option value={GqlPackageKind.Skill}>Skills</option>\n <option value={GqlPackageKind.McpPack}>MCP Packs</option>\n <option value={GqlPackageKind.PromptTemplate}>Templates</option>\n <option value={GqlPackageKind.RetrievalProfile}>Retrieval Profiles</option>\n </select>\n </div>\n </div>\n\n {/* Package List */}\n {filteredPackages.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filteredPackages.map((pkg) => (\n <PackageCard key={pkg.id} pkg={pkg} />\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title={\n search || kindFilter !== 'all' ? 'No matching packages' : 'No packages installed'\n }\n description={\n search || kindFilter !== 'all'\n ? 'Try adjusting your search or type filter.'\n : 'Browse the BotManor Store to find agents, skills, and tools to install.'\n }\n action={\n <Button\n onClick={() => navigateTo('store')}\n leftIcon={<Download className=\"h-4 w-4\" />}\n >\n Browse Store\n </Button>\n }\n />\n )}\n </>\n )}\n\n {/* Detail Modal */}\n {selectedPackage && (\n <PackageDetailModal pkg={selectedPackage} onClose={() => setSelectedPackageId(null)} />\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -1,143 +1,149 @@
1
- import { useBotlit as e } from "../providers/BotlitProvider.js";
2
- import { useKnowledgeBases as t } from "../hooks/useKnowledgeBases.js";
3
- import { formatRelativeTime as n } from "../utils/formatters.js";
4
- import { PageLayout as r } from "../components/PageLayout.js";
5
- import { Card as i, CardContent as a } from "../components/Card.js";
6
- import { Button as o } from "../components/Button.js";
7
- import { StatusBadge as s } from "../components/Badge.js";
8
- import { EmptyState as c } from "../components/EmptyState.js";
9
- import { Input as l } from "../components/Input.js";
10
- import { ErrorState as u } from "../components/ErrorState.js";
11
- import { GlassCard as d, PagePurpose as f } from "@burdenoff/fe-libs/ui";
12
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
13
- import { useParams as h } from "react-router";
14
- import { BookOpen as g, FileText as _, Plus as v, Search as y } from "lucide-react";
1
+ import { useTr as e } from "../../shared/hooks/useTr.js";
2
+ import { useBotlit as t } from "../providers/BotlitProvider.js";
3
+ import { useKnowledgeBases as n } from "../hooks/useKnowledgeBases.js";
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 } from "../components/Card.js";
7
+ import { Button as s } from "../components/Button.js";
8
+ import { StatusBadge as c } from "../components/Badge.js";
9
+ import { EmptyState as l } from "../components/EmptyState.js";
10
+ import { Input as u } from "../components/Input.js";
11
+ import { ErrorState as d } from "../components/ErrorState.js";
12
+ import { GlassCard as f, PagePurpose as p } from "@burdenoff/fe-libs/ui";
13
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
14
+ import { useParams as g } from "react-router";
15
+ import { BookOpen as _, FileText as v, Plus as y, Search as b } from "lucide-react";
15
16
  //#region src/botlit/pages/KnowledgeBasesPage.tsx
16
- var b = () => {
17
- let { botId: b } = h(), { navigateTo: x } = e(), { data: S, loading: C, error: w, refetch: T } = t(b ? { search: b } : void 0);
18
- return /* @__PURE__ */ p(r, {
19
- title: "Knowledge Bases",
20
- description: "Manage knowledge sources for your AI agents",
21
- actions: /* @__PURE__ */ p(o, {
22
- leftIcon: /* @__PURE__ */ p(v, { size: 16 }),
23
- onClick: () => x("knowledge/new"),
24
- children: "Create Knowledge Base"
17
+ var x = () => {
18
+ let x = e(), { botId: S } = g(), { navigateTo: C } = t(), { data: w, loading: T, error: E, refetch: D } = n(S ? { search: S } : void 0);
19
+ return /* @__PURE__ */ m(i, {
20
+ title: x("botlit.knowledgeBases.title", "Knowledge Bases"),
21
+ description: x("botlit.knowledgeBases.description", "Manage knowledge sources for your AI agents"),
22
+ actions: /* @__PURE__ */ m(s, {
23
+ leftIcon: /* @__PURE__ */ m(y, { size: 16 }),
24
+ onClick: () => C("knowledge/new"),
25
+ children: x("botlit.knowledgeBases.actions.create", "Create Knowledge Base")
25
26
  }),
26
- children: /* @__PURE__ */ m("div", {
27
+ children: /* @__PURE__ */ h("div", {
27
28
  className: "space-y-6",
28
29
  children: [
29
- /* @__PURE__ */ p(f, {
30
- icon: /* @__PURE__ */ p(g, { size: 18 }),
31
- children: "A knowledge base is the private library your agents read from to answer questions about your business. Upload documents, FAQs, policies or product data here, and they get indexed so agents can retrieve and cite the right passage instead of guessing. Create a knowledge base whenever you want answers grounded in your own content rather than the model’s general training."
30
+ /* @__PURE__ */ m(p, {
31
+ icon: /* @__PURE__ */ m(_, { size: 18 }),
32
+ children: x("botlit.knowledgeBases.purpose", "A knowledge base is the private library your agents read from to answer questions about your business. Upload documents, FAQs, policies or product data here, and they get indexed so agents can retrieve and cite the right passage instead of guessing. Create a knowledge base whenever you want answers grounded in your own content rather than the model's general training.")
32
33
  }),
33
- S.length > 0 ? /* @__PURE__ */ m("div", {
34
+ w.length > 0 ? /* @__PURE__ */ h("div", {
34
35
  className: "grid grid-cols-2 gap-4 sm:grid-cols-3",
35
- children: [/* @__PURE__ */ m(d, {
36
+ children: [/* @__PURE__ */ h(f, {
36
37
  treatment: "glass",
37
38
  glow: !0,
38
39
  className: "p-4",
39
- children: [/* @__PURE__ */ p("p", {
40
+ children: [/* @__PURE__ */ m("p", {
40
41
  className: "text-sm text-text-secondary",
41
- children: "Knowledge bases"
42
- }), /* @__PURE__ */ p("p", {
42
+ children: x("botlit.knowledgeBases.summary.knowledgeBases", "Knowledge bases")
43
+ }), /* @__PURE__ */ m("p", {
43
44
  className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
44
- children: S.length
45
+ children: w.length
45
46
  })]
46
- }), /* @__PURE__ */ m(d, {
47
+ }), /* @__PURE__ */ h(f, {
47
48
  treatment: "metric",
48
49
  className: "col-span-2 p-4 sm:col-span-2",
49
- children: [/* @__PURE__ */ p("p", {
50
+ children: [/* @__PURE__ */ m("p", {
50
51
  className: "text-sm text-text-secondary",
51
- children: "Total documents"
52
- }), /* @__PURE__ */ p("p", {
52
+ children: x("botlit.knowledgeBases.summary.totalDocuments", "Total documents")
53
+ }), /* @__PURE__ */ m("p", {
53
54
  className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
54
- children: S.reduce((e, t) => e + (t.totalDocuments ?? t.documentCount ?? 0), 0)
55
+ children: w.reduce((e, t) => e + (t.totalDocuments ?? t.documentCount ?? 0), 0)
55
56
  })]
56
57
  })]
57
58
  }) : null,
58
- /* @__PURE__ */ p("div", {
59
+ /* @__PURE__ */ m("div", {
59
60
  className: "flex items-center gap-4",
60
- children: /* @__PURE__ */ m("div", {
61
+ children: /* @__PURE__ */ h("div", {
61
62
  className: "relative flex-1 max-w-md",
62
- children: [/* @__PURE__ */ p(y, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ p(l, {
63
- placeholder: "Search knowledge bases...",
63
+ children: [/* @__PURE__ */ m(b, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ m(u, {
64
+ placeholder: x("botlit.knowledgeBases.searchPlaceholder", "Search knowledge bases..."),
64
65
  className: "pl-9"
65
66
  })]
66
67
  })
67
68
  }),
68
- C ? /* @__PURE__ */ p("div", {
69
+ T ? /* @__PURE__ */ m("div", {
69
70
  className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
70
71
  children: [
71
72
  1,
72
73
  2,
73
74
  3
74
- ].map((e) => /* @__PURE__ */ p("div", { className: "h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }, e))
75
- }) : w ? /* @__PURE__ */ p(u, {
75
+ ].map((e) => /* @__PURE__ */ m("div", { className: "h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }, e))
76
+ }) : E ? /* @__PURE__ */ m(d, {
76
77
  resource: "knowledge bases",
77
- error: w,
78
- onRetry: () => void T()
79
- }) : S.length > 0 ? /* @__PURE__ */ m("div", {
78
+ error: E,
79
+ onRetry: () => void D()
80
+ }) : w.length > 0 ? /* @__PURE__ */ h("div", {
80
81
  className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
81
- children: [S.map((e) => /* @__PURE__ */ p(i, {
82
+ children: [w.map((e) => /* @__PURE__ */ m(a, {
82
83
  className: "hover:shadow-md transition-shadow cursor-pointer",
83
- onClick: () => x(`knowledge/${e.id}`),
84
- children: /* @__PURE__ */ m(a, {
84
+ onClick: () => C(`knowledge/${e.id}`),
85
+ children: /* @__PURE__ */ h(o, {
85
86
  className: "pt-6",
86
87
  children: [
87
- /* @__PURE__ */ m("div", {
88
+ /* @__PURE__ */ h("div", {
88
89
  className: "flex items-start justify-between mb-4",
89
- children: [/* @__PURE__ */ p("div", {
90
+ children: [/* @__PURE__ */ m("div", {
90
91
  className: "p-3 rounded-lg bg-action-primary-bg/10",
91
- children: /* @__PURE__ */ p(g, { className: "h-6 w-6 text-primary" })
92
- }), /* @__PURE__ */ p(s, { status: e.indexStatus || e.status || "UNKNOWN" })]
92
+ children: /* @__PURE__ */ m(_, { className: "h-6 w-6 text-primary" })
93
+ }), /* @__PURE__ */ m(c, { status: e.indexStatus || e.status || "UNKNOWN" })]
93
94
  }),
94
- /* @__PURE__ */ p("h3", {
95
+ /* @__PURE__ */ m("h3", {
95
96
  className: "font-semibold text-text-primary mb-1",
96
97
  children: e.name
97
98
  }),
98
- /* @__PURE__ */ p("p", {
99
+ /* @__PURE__ */ m("p", {
99
100
  className: "text-sm text-text-secondary line-clamp-2 mb-4",
100
101
  children: e.description
101
102
  }),
102
- /* @__PURE__ */ p("div", {
103
+ /* @__PURE__ */ m("div", {
103
104
  className: "flex items-center gap-4 text-xs text-text-secondary",
104
- children: /* @__PURE__ */ m("span", {
105
+ children: /* @__PURE__ */ h("span", {
105
106
  className: "flex items-center gap-1",
106
107
  children: [
107
- /* @__PURE__ */ p(_, { size: 14 }),
108
+ /* @__PURE__ */ m(v, { size: 14 }),
108
109
  e.totalDocuments ?? e.documentCount ?? 0,
109
- " documents"
110
+ " ",
111
+ x("botlit.knowledgeBases.documentLabel", "documents")
110
112
  ]
111
113
  })
112
114
  }),
113
- /* @__PURE__ */ m("div", {
115
+ /* @__PURE__ */ h("div", {
114
116
  className: "mt-3 pt-3 border-t border-border-subtle text-xs text-text-secondary",
115
- children: ["Created ", n(e.createdAt)]
117
+ children: [
118
+ x("botlit.botsList.createdLabel", "Created"),
119
+ " ",
120
+ r(e.createdAt)
121
+ ]
116
122
  })
117
123
  ]
118
124
  })
119
- }, e.id)), /* @__PURE__ */ p(i, {
125
+ }, e.id)), /* @__PURE__ */ m(a, {
120
126
  className: "border-dashed cursor-pointer hover:border-primary/50 transition-colors",
121
- onClick: () => x("knowledge/new"),
122
- children: /* @__PURE__ */ m(a, {
127
+ onClick: () => C("knowledge/new"),
128
+ children: /* @__PURE__ */ h(o, {
123
129
  className: "h-full flex flex-col items-center justify-center py-12",
124
- children: [/* @__PURE__ */ p("div", {
130
+ children: [/* @__PURE__ */ m("div", {
125
131
  className: "p-4 rounded-full bg-bg-sunken mb-4",
126
- children: /* @__PURE__ */ p(v, { className: "h-8 w-8 text-text-secondary" })
127
- }), /* @__PURE__ */ p("p", {
132
+ children: /* @__PURE__ */ m(y, { className: "h-8 w-8 text-text-secondary" })
133
+ }), /* @__PURE__ */ m("p", {
128
134
  className: "font-medium text-text-secondary",
129
- children: "Add Knowledge Base"
135
+ children: x("botlit.knowledgeBases.actions.add", "Add Knowledge Base")
130
136
  })]
131
137
  })
132
138
  })]
133
- }) : /* @__PURE__ */ p(c, {
139
+ }) : /* @__PURE__ */ m(l, {
134
140
  illustration: "empty-files",
135
- title: "No knowledge bases yet",
136
- description: "Create a knowledge base to give your agents access to your documents and data.",
137
- action: /* @__PURE__ */ p(o, {
138
- leftIcon: /* @__PURE__ */ p(v, { size: 16 }),
139
- onClick: () => x("knowledge/new"),
140
- children: "Create Knowledge Base"
141
+ title: x("botlit.knowledgeBases.empty.title", "No knowledge bases yet"),
142
+ description: x("botlit.knowledgeBases.empty.description", "Create a knowledge base to give your agents access to your documents and data."),
143
+ action: /* @__PURE__ */ m(s, {
144
+ leftIcon: /* @__PURE__ */ m(y, { size: 16 }),
145
+ onClick: () => C("knowledge/new"),
146
+ children: x("botlit.knowledgeBases.actions.create", "Create Knowledge Base")
141
147
  })
142
148
  })
143
149
  ]
@@ -145,6 +151,6 @@ var b = () => {
145
151
  });
146
152
  };
147
153
  //#endregion
148
- export { b as KnowledgeBasesPage };
154
+ export { x as KnowledgeBasesPage };
149
155
 
150
156
  //# sourceMappingURL=KnowledgeBasesPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"KnowledgeBasesPage.js","names":[],"sources":["../../../src/botlit/pages/KnowledgeBasesPage.tsx"],"sourcesContent":["/**\n * Knowledge Bases Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useParams } from 'react-router';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { Plus, Search, BookOpen, FileText } from 'lucide-react';\nimport { PagePurpose, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardContent } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Input } from '../components/Input';\nimport { StatusBadge } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport { useKnowledgeBases } from '../hooks/useKnowledgeBases';\nimport { formatRelativeTime } from '../utils/formatters';\n\nexport const KnowledgeBasesPage: FC = () => {\n const { botId } = useParams();\n const { navigateTo } = useBotlit();\n const {\n data: knowledgeBases,\n loading,\n error,\n refetch,\n } = useKnowledgeBases(botId ? { search: botId } : undefined);\n\n return (\n <PageLayout\n title=\"Knowledge Bases\"\n description=\"Manage knowledge sources for your AI agents\"\n actions={\n <Button leftIcon={<Plus size={16} />} onClick={() => navigateTo('knowledge/new')}>\n Create Knowledge Base\n </Button>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<BookOpen size={18} />}>\n A knowledge base is the private library your agents read from to answer questions about\n your business. Upload documents, FAQs, policies or product data here, and they get indexed\n so agents can retrieve and cite the right passage instead of guessing. Create a knowledge\n base whenever you want answers grounded in your own content rather than the model&rsquo;s\n general training.\n </PagePurpose>\n\n {/* Summary */}\n {knowledgeBases.length > 0 ? (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">Knowledge bases</p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {knowledgeBases.length}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"col-span-2 p-4 sm:col-span-2\">\n <p className=\"text-sm text-text-secondary\">Total documents</p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {knowledgeBases.reduce(\n (\n sum: number,\n kb: { totalDocuments?: number | null; documentCount?: number | null }\n ) => sum + (kb.totalDocuments ?? kb.documentCount ?? 0),\n 0\n )}\n </p>\n </GlassCard>\n </div>\n ) : null}\n\n {/* Toolbar */}\n <div className=\"flex items-center gap-4\">\n <div className=\"relative flex-1 max-w-md\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input placeholder=\"Search knowledge bases...\" className=\"pl-9\" />\n </div>\n </div>\n\n {/* Content */}\n {loading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {[1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\"\n />\n ))}\n </div>\n ) : error ? (\n <ErrorState resource=\"knowledge bases\" error={error} onRetry={() => void refetch()} />\n ) : knowledgeBases.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {knowledgeBases.map(\n (kb: {\n id: string;\n name: string;\n description?: string | null;\n status?: string;\n indexStatus?: string;\n totalDocuments?: number | null;\n documentCount?: number | null;\n createdAt: string;\n }) => (\n <Card\n key={kb.id}\n className=\"hover:shadow-md transition-shadow cursor-pointer\"\n onClick={() => navigateTo(`knowledge/${kb.id}`)}\n >\n <CardContent className=\"pt-6\">\n <div className=\"flex items-start justify-between mb-4\">\n <div className=\"p-3 rounded-lg bg-action-primary-bg/10\">\n <BookOpen className=\"h-6 w-6 text-primary\" />\n </div>\n <StatusBadge status={kb.indexStatus || kb.status || 'UNKNOWN'} />\n </div>\n <h3 className=\"font-semibold text-text-primary mb-1\">{kb.name}</h3>\n <p className=\"text-sm text-text-secondary line-clamp-2 mb-4\">\n {kb.description}\n </p>\n <div className=\"flex items-center gap-4 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <FileText size={14} />\n {kb.totalDocuments ?? kb.documentCount ?? 0} documents\n </span>\n </div>\n <div className=\"mt-3 pt-3 border-t border-border-subtle text-xs text-text-secondary\">\n Created {formatRelativeTime(kb.createdAt)}\n </div>\n </CardContent>\n </Card>\n )\n )}\n\n {/* Add New Card */}\n <Card\n className=\"border-dashed cursor-pointer hover:border-primary/50 transition-colors\"\n onClick={() => navigateTo('knowledge/new')}\n >\n <CardContent className=\"h-full flex flex-col items-center justify-center py-12\">\n <div className=\"p-4 rounded-full bg-bg-sunken mb-4\">\n <Plus className=\"h-8 w-8 text-text-secondary\" />\n </div>\n <p className=\"font-medium text-text-secondary\">Add Knowledge Base</p>\n </CardContent>\n </Card>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-files\"\n title=\"No knowledge bases yet\"\n description=\"Create a knowledge base to give your agents access to your documents and data.\"\n action={\n <Button leftIcon={<Plus size={16} />} onClick={() => navigateTo('knowledge/new')}>\n Create Knowledge Base\n </Button>\n }\n />\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"KnowledgeBasesPage.js","names":[],"sources":["../../../src/botlit/pages/KnowledgeBasesPage.tsx"],"sourcesContent":["/**\n * Knowledge Bases Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useParams } from 'react-router';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { Plus, Search, BookOpen, FileText } from 'lucide-react';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PagePurpose, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardContent } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Input } from '../components/Input';\nimport { StatusBadge } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport { useKnowledgeBases } from '../hooks/useKnowledgeBases';\nimport { formatRelativeTime } from '../utils/formatters';\n\nexport const KnowledgeBasesPage: FC = () => {\n const t = useTr();\n const { botId } = useParams();\n const { navigateTo } = useBotlit();\n const {\n data: knowledgeBases,\n loading,\n error,\n refetch,\n } = useKnowledgeBases(botId ? { search: botId } : undefined);\n\n return (\n <PageLayout\n title={t('botlit.knowledgeBases.title', 'Knowledge Bases')}\n description={t(\n 'botlit.knowledgeBases.description',\n 'Manage knowledge sources for your AI agents'\n )}\n actions={\n <Button leftIcon={<Plus size={16} />} onClick={() => navigateTo('knowledge/new')}>\n {t('botlit.knowledgeBases.actions.create', 'Create Knowledge Base')}\n </Button>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<BookOpen size={18} />}>\n {t(\n 'botlit.knowledgeBases.purpose',\n \"A knowledge base is the private library your agents read from to answer questions about your business. Upload documents, FAQs, policies or product data here, and they get indexed so agents can retrieve and cite the right passage instead of guessing. Create a knowledge base whenever you want answers grounded in your own content rather than the model's general training.\"\n )}\n </PagePurpose>\n\n {/* Summary */}\n {knowledgeBases.length > 0 ? (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.knowledgeBases.summary.knowledgeBases', 'Knowledge bases')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {knowledgeBases.length}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"col-span-2 p-4 sm:col-span-2\">\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.knowledgeBases.summary.totalDocuments', 'Total documents')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {knowledgeBases.reduce(\n (\n sum: number,\n kb: { totalDocuments?: number | null; documentCount?: number | null }\n ) => sum + (kb.totalDocuments ?? kb.documentCount ?? 0),\n 0\n )}\n </p>\n </GlassCard>\n </div>\n ) : null}\n\n {/* Toolbar */}\n <div className=\"flex items-center gap-4\">\n <div className=\"relative flex-1 max-w-md\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder={t(\n 'botlit.knowledgeBases.searchPlaceholder',\n 'Search knowledge bases...'\n )}\n className=\"pl-9\"\n />\n </div>\n </div>\n\n {/* Content */}\n {loading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {[1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\"\n />\n ))}\n </div>\n ) : error ? (\n <ErrorState resource=\"knowledge bases\" error={error} onRetry={() => void refetch()} />\n ) : knowledgeBases.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {knowledgeBases.map(\n (kb: {\n id: string;\n name: string;\n description?: string | null;\n status?: string;\n indexStatus?: string;\n totalDocuments?: number | null;\n documentCount?: number | null;\n createdAt: string;\n }) => (\n <Card\n key={kb.id}\n className=\"hover:shadow-md transition-shadow cursor-pointer\"\n onClick={() => navigateTo(`knowledge/${kb.id}`)}\n >\n <CardContent className=\"pt-6\">\n <div className=\"flex items-start justify-between mb-4\">\n <div className=\"p-3 rounded-lg bg-action-primary-bg/10\">\n <BookOpen className=\"h-6 w-6 text-primary\" />\n </div>\n <StatusBadge status={kb.indexStatus || kb.status || 'UNKNOWN'} />\n </div>\n <h3 className=\"font-semibold text-text-primary mb-1\">{kb.name}</h3>\n <p className=\"text-sm text-text-secondary line-clamp-2 mb-4\">\n {kb.description}\n </p>\n <div className=\"flex items-center gap-4 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <FileText size={14} />\n {kb.totalDocuments ?? kb.documentCount ?? 0}{' '}\n {t('botlit.knowledgeBases.documentLabel', 'documents')}\n </span>\n </div>\n <div className=\"mt-3 pt-3 border-t border-border-subtle text-xs text-text-secondary\">\n {t('botlit.botsList.createdLabel', 'Created')}{' '}\n {formatRelativeTime(kb.createdAt)}\n </div>\n </CardContent>\n </Card>\n )\n )}\n\n {/* Add New Card */}\n <Card\n className=\"border-dashed cursor-pointer hover:border-primary/50 transition-colors\"\n onClick={() => navigateTo('knowledge/new')}\n >\n <CardContent className=\"h-full flex flex-col items-center justify-center py-12\">\n <div className=\"p-4 rounded-full bg-bg-sunken mb-4\">\n <Plus className=\"h-8 w-8 text-text-secondary\" />\n </div>\n <p className=\"font-medium text-text-secondary\">\n {t('botlit.knowledgeBases.actions.add', 'Add Knowledge Base')}\n </p>\n </CardContent>\n </Card>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-files\"\n title={t('botlit.knowledgeBases.empty.title', 'No knowledge bases yet')}\n description={t(\n 'botlit.knowledgeBases.empty.description',\n 'Create a knowledge base to give your agents access to your documents and data.'\n )}\n action={\n <Button leftIcon={<Plus size={16} />} onClick={() => navigateTo('knowledge/new')}>\n {t('botlit.knowledgeBases.actions.create', 'Create Knowledge Base')}\n </Button>\n }\n />\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}