@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":"RetrievalProfileDetailPage.js","names":[],"sources":["../../../src/botlit/pages/RetrievalProfileDetailPage.tsx"],"sourcesContent":["/**\n * Retrieval Profile Detail Page\n * @module botlit/pages\n *\n * `RetrievalProfile` is FLAT on wspace-botlit-svc — `strategyMode`, `topK`,\n * `citationsRequired`, `minRelevanceScore` and friends all sit at the top\n * level. There is no nested `strategy`/`grounding`/`thresholds` object, so the\n * form state below mirrors the create/update inputs field for field and the\n * payload is built explicitly rather than handing the whole record back.\n */\n\nimport type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useParams } from 'react-router';\nimport { toast } from 'sonner';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { isNative, nativeImpact, nativeNotify } from '../../utils/nativeBridge';\nimport {\n ArrowLeft,\n Edit,\n Trash2,\n Search,\n FileText,\n Settings,\n Target,\n CheckSquare,\n} from 'lucide-react';\nimport { PageLayout } from '../components/PageLayout';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { EmptyState } from '../components/EmptyState';\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Badge, StatusBadge } from '../components/Badge';\nimport { Input, Textarea, FormField } from '../components/Input';\nimport {\n useRetrievalProfile,\n useCreateRetrievalProfile,\n useUpdateRetrievalProfile,\n useDeleteRetrievalProfile,\n type CreateRetrievalProfileVariables,\n type RetrievalProfileRecord,\n} from '../hooks/useRetrievalProfiles';\nimport { formatRelativeTime, MISSING_VALUE } from '../utils/formatters';\nimport type { RetrievalMode, RerankerMode } from '../types';\n\ninterface RetrievalProfileDetailPageProps {\n isNew?: boolean;\n}\n\n/** Editable subset of the retrieval profile — one field per input field. */\ninterface RetrievalProfileForm {\n name: string;\n description: string;\n strategyMode: RetrievalMode;\n topK: number;\n reranker: RerankerMode;\n queryRewrite: RerankerMode;\n multiHop: RerankerMode;\n citationsRequired: boolean;\n showSources: boolean;\n minSources: number;\n snippetMaxChars: number;\n citationFormat: string;\n minRelevanceScore: number;\n noAnswerIfBelowThreshold: boolean;\n}\n\nconst DEFAULT_FORM: RetrievalProfileForm = {\n name: '',\n description: '',\n strategyMode: 'HYBRID',\n topK: 10,\n reranker: 'OFF',\n queryRewrite: 'OFF',\n multiHop: 'OFF',\n citationsRequired: true,\n showSources: true,\n minSources: 1,\n snippetMaxChars: 500,\n citationFormat: '[{index}]',\n minRelevanceScore: 0.7,\n noAnswerIfBelowThreshold: true,\n};\n\nconst RETRIEVAL_MODES: RetrievalMode[] = ['VECTOR', 'HYBRID', 'BM25_ONLY'];\n\n/** `reranker`/`queryRewrite`/`multiHop` are free-form strings on the service. */\nfunction toRerankerMode(value: string): RerankerMode {\n return value === 'ON' ? 'ON' : 'OFF';\n}\n\nfunction toRetrievalMode(value: string): RetrievalMode {\n return RETRIEVAL_MODES.includes(value as RetrievalMode) ? (value as RetrievalMode) : 'HYBRID';\n}\n\n/** Seeds the form from a loaded profile. */\nfunction toForm(profile: RetrievalProfileRecord): RetrievalProfileForm {\n return {\n name: profile.name,\n description: profile.description ?? '',\n strategyMode: toRetrievalMode(profile.strategyMode),\n topK: profile.topK,\n reranker: toRerankerMode(profile.reranker),\n queryRewrite: toRerankerMode(profile.queryRewrite),\n multiHop: toRerankerMode(profile.multiHop),\n citationsRequired: profile.citationsRequired,\n showSources: profile.showSources,\n minSources: profile.minSources,\n snippetMaxChars: profile.snippetMaxChars,\n citationFormat: profile.citationFormat ?? DEFAULT_FORM.citationFormat,\n minRelevanceScore: profile.minRelevanceScore ?? DEFAULT_FORM.minRelevanceScore,\n noAnswerIfBelowThreshold: profile.noAnswerIfBelowThreshold,\n };\n}\n\n/**\n * Builds the mutation payload. Every key here is declared by both\n * `CreateRetrievalProfileInput` and `UpdateRetrievalProfileInput`, so the same\n * projection serves create and update.\n */\nfunction toInput(form: RetrievalProfileForm): CreateRetrievalProfileVariables {\n return {\n name: form.name.trim(),\n description: form.description.trim() || null,\n strategyMode: form.strategyMode,\n topK: form.topK,\n reranker: form.reranker,\n queryRewrite: form.queryRewrite,\n multiHop: form.multiHop,\n citationsRequired: form.citationsRequired,\n showSources: form.showSources,\n minSources: form.minSources,\n snippetMaxChars: form.snippetMaxChars,\n citationFormat: form.citationFormat.trim() || null,\n minRelevanceScore: form.minRelevanceScore,\n noAnswerIfBelowThreshold: form.noAnswerIfBelowThreshold,\n };\n}\n\n/** `Number('')` is 0 and `Number('abc')` is NaN — keep the previous value instead. */\nfunction toNumber(value: string, fallback: number): number {\n const parsed = Number(value);\n return value.trim() !== '' && Number.isFinite(parsed) ? parsed : fallback;\n}\n\nexport const RetrievalProfileDetailPage: FC<RetrievalProfileDetailPageProps> = ({\n isNew = false,\n}) => {\n const { profileId } = useParams();\n const { navigateTo } = useBotlit();\n const { data: profile, loading, refetch } = useRetrievalProfile(isNew ? undefined : profileId);\n const { create: createProfile, loading: createLoading } = useCreateRetrievalProfile();\n const { update: updateProfile, loading: updateLoading } = useUpdateRetrievalProfile();\n const { remove: deleteProfile, loading: deleteLoading } = useDeleteRetrievalProfile();\n\n const [isEditing, setIsEditing] = useState(isNew);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [formData, setFormData] = useState<RetrievalProfileForm>(DEFAULT_FORM);\n\n // Seed the form once the profile arrives so \"Edit\" always opens on current values.\n useEffect(() => {\n if (profile && !isNew) {\n setFormData(toForm(profile));\n }\n }, [profile, isNew]);\n\n if (loading && !isNew) {\n return (\n <PageLayout title=\"Loading...\">\n <div className=\"h-96 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n </PageLayout>\n );\n }\n\n if (!profile && !isNew) {\n return (\n <PageLayout title=\"Profile Not Found\">\n <EmptyState\n illustration=\"empty-files\"\n title=\"Profile Not Found\"\n description=\"The retrieval profile doesn't exist.\"\n action={\n <Button onClick={() => navigateTo('retrieval-profiles')}>Back to Profiles</Button>\n }\n />\n </PageLayout>\n );\n }\n\n const handleSave = async () => {\n if (!formData.name.trim()) {\n toast.error('Name is required');\n return;\n }\n try {\n if (isNew) {\n const created = await createProfile(toInput(formData));\n toast.success(`Profile \"${created.name}\" created`);\n navigateTo(`retrieval-profiles/${created.id}`);\n return;\n }\n if (!profileId) return;\n await updateProfile({ profileId, input: toInput(formData) });\n await refetch();\n toast.success('Retrieval profile updated');\n setIsEditing(false);\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to save retrieval profile');\n }\n };\n\n const handleDelete = async () => {\n if (!profileId) return;\n try {\n await deleteProfile(profileId);\n if (isNative()) void nativeNotify('success');\n toast.success('Retrieval profile deleted');\n navigateTo('retrieval-profiles');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n toast.error(err instanceof Error ? err.message : 'Failed to delete retrieval profile');\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('retrieval-profiles')}>\n <ArrowLeft size={20} />\n </Button>\n <Search size={24} className=\"text-primary\" />\n <div>\n <div className=\"flex items-center gap-2\">\n <span>{isNew ? 'New Retrieval Profile' : profile?.name}</span>\n {!isNew && profile && <StatusBadge status={profile.status} />}\n </div>\n {!isNew && profile?.description && (\n <p className=\"text-sm font-normal text-text-secondary\">{profile.description}</p>\n )}\n </div>\n </div>\n }\n actions={\n <div className=\"flex gap-2\">\n {isEditing ? (\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n if (isNew) {\n navigateTo('retrieval-profiles');\n return;\n }\n if (profile) setFormData(toForm(profile));\n setIsEditing(false);\n }}\n >\n Cancel\n </Button>\n <Button onClick={handleSave} isLoading={createLoading || updateLoading}>\n {isNew ? 'Create Profile' : 'Save Changes'}\n </Button>\n </>\n ) : (\n <>\n <Button\n variant=\"outline\"\n leftIcon={<Edit size={16} />}\n onClick={() => {\n if (profile) setFormData(toForm(profile));\n setIsEditing(true);\n }}\n >\n Edit\n </Button>\n {showDeleteConfirm ? (\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => setShowDeleteConfirm(false)}>\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => {\n nativeImpact('medium');\n void handleDelete();\n }}\n isLoading={deleteLoading}\n >\n Confirm Delete\n </Button>\n </div>\n ) : (\n <Button\n variant=\"destructive\"\n leftIcon={<Trash2 size={16} />}\n onClick={() => setShowDeleteConfirm(true)}\n >\n Delete\n </Button>\n )}\n </>\n )}\n </div>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Settings size={18} />}>\n This profile defines exactly how an agent searches your knowledge — the retrieval mode,\n how many results to pull, whether to rerank them and whether to rewrite the query first.\n Adjust the strategy here to dial in the balance between answer accuracy and speed, then\n attach the profile to the agents that should use it.\n </PagePurpose>\n\n {/* Basic Info */}\n {isEditing ? (\n <Card>\n <CardHeader>\n <CardTitle>Basic Information</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <FormField label=\"Name\" required>\n <Input\n value={formData.name}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n placeholder=\"e.g., Default Hybrid Search\"\n />\n </FormField>\n <FormField label=\"Description\">\n <Textarea\n value={formData.description}\n onChange={(e) => setFormData({ ...formData, description: e.target.value })}\n placeholder=\"Describe when to use this profile...\"\n rows={3}\n />\n </FormField>\n </CardContent>\n </Card>\n ) : null}\n\n {/* Strategy Configuration */}\n <Card treatment=\"glass\" glow>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Settings size={18} />\n Retrieval Strategy\n </CardTitle>\n <CardDescription>How documents are searched and ranked</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {isEditing ? (\n <>\n <FormField label=\"Retrieval Mode\">\n <div className=\"flex gap-4\">\n {RETRIEVAL_MODES.map((mode) => (\n <label key={mode} className=\"flex items-center gap-2\">\n <input\n type=\"radio\"\n name=\"strategyMode\"\n checked={formData.strategyMode === mode}\n onChange={() => setFormData({ ...formData, strategyMode: mode })}\n />\n <span className=\"capitalize\">{mode.replace('_', ' ')}</span>\n </label>\n ))}\n </div>\n </FormField>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Top K Results\">\n <Input\n type=\"number\"\n value={formData.topK}\n onChange={(e) =>\n setFormData({\n ...formData,\n topK: toNumber(e.target.value, DEFAULT_FORM.topK),\n })\n }\n />\n </FormField>\n <FormField label=\"Reranker\">\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={formData.reranker}\n onChange={(e) =>\n setFormData({ ...formData, reranker: toRerankerMode(e.target.value) })\n }\n >\n <option value=\"OFF\">Disabled</option>\n <option value=\"ON\">Enabled</option>\n </select>\n </FormField>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Query Rewrite\">\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={formData.queryRewrite}\n onChange={(e) =>\n setFormData({ ...formData, queryRewrite: toRerankerMode(e.target.value) })\n }\n >\n <option value=\"OFF\">Disabled</option>\n <option value=\"ON\">Enabled</option>\n </select>\n </FormField>\n <FormField label=\"Multi-Hop\">\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={formData.multiHop}\n onChange={(e) =>\n setFormData({ ...formData, multiHop: toRerankerMode(e.target.value) })\n }\n >\n <option value=\"OFF\">Disabled</option>\n <option value=\"ON\">Enabled</option>\n </select>\n </FormField>\n </div>\n </>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Mode</p>\n <Badge variant=\"outline\">{profile?.strategyMode}</Badge>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Top K</p>\n <p className=\"font-medium\">{profile?.topK}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Reranker</p>\n <Badge variant={profile?.reranker === 'ON' ? 'success' : 'secondary'}>\n {profile?.reranker}\n </Badge>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Query Rewrite</p>\n <Badge variant={profile?.queryRewrite === 'ON' ? 'success' : 'secondary'}>\n {profile?.queryRewrite}\n </Badge>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Grounding Configuration */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <FileText size={18} />\n Grounding & Citations\n </CardTitle>\n <CardDescription>How sources are cited in responses</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {isEditing ? (\n <>\n <div className=\"flex items-center gap-4\">\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={formData.citationsRequired}\n onChange={(e) =>\n setFormData({ ...formData, citationsRequired: e.target.checked })\n }\n />\n <span>Citations Required</span>\n </label>\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={formData.showSources}\n onChange={(e) => setFormData({ ...formData, showSources: e.target.checked })}\n />\n <span>Show Sources</span>\n </label>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Min Sources\">\n <Input\n type=\"number\"\n value={formData.minSources}\n onChange={(e) =>\n setFormData({\n ...formData,\n minSources: toNumber(e.target.value, DEFAULT_FORM.minSources),\n })\n }\n />\n </FormField>\n <FormField label=\"Max Snippet Chars\">\n <Input\n type=\"number\"\n value={formData.snippetMaxChars}\n onChange={(e) =>\n setFormData({\n ...formData,\n snippetMaxChars: toNumber(e.target.value, DEFAULT_FORM.snippetMaxChars),\n })\n }\n />\n </FormField>\n </div>\n <FormField label=\"Citation Format Template\">\n <Input\n value={formData.citationFormat}\n onChange={(e) => setFormData({ ...formData, citationFormat: e.target.value })}\n placeholder=\"[{index}]\"\n />\n </FormField>\n </>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Citations Required</p>\n <Badge variant={profile?.citationsRequired ? 'success' : 'secondary'}>\n {profile?.citationsRequired ? 'Yes' : 'No'}\n </Badge>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Min Sources</p>\n <p className=\"font-medium\">{profile?.minSources}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Max Snippet</p>\n <p className=\"font-medium\">{profile?.snippetMaxChars} chars</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Citation Format</p>\n <code className=\"text-sm\">{profile?.citationFormat ?? MISSING_VALUE}</code>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Thresholds */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Target size={18} />\n Relevance Thresholds\n </CardTitle>\n <CardDescription>Minimum quality requirements for results</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {isEditing ? (\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Min Relevance Score (0-1)\">\n <Input\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"1\"\n value={formData.minRelevanceScore}\n onChange={(e) =>\n setFormData({\n ...formData,\n minRelevanceScore: toNumber(e.target.value, DEFAULT_FORM.minRelevanceScore),\n })\n }\n />\n </FormField>\n <div className=\"flex items-center\">\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={formData.noAnswerIfBelowThreshold}\n onChange={(e) =>\n setFormData({ ...formData, noAnswerIfBelowThreshold: e.target.checked })\n }\n />\n <span>No Answer if Below Threshold</span>\n </label>\n </div>\n </div>\n ) : (\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Min Relevance Score</p>\n <p className=\"font-medium\">{profile?.minRelevanceScore ?? 'Not set'}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">No Answer Below Threshold</p>\n <Badge variant={profile?.noAnswerIfBelowThreshold ? 'warning' : 'secondary'}>\n {profile?.noAnswerIfBelowThreshold ? 'Yes' : 'No'}\n </Badge>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Metadata (view only) */}\n {!isNew && profile && (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <CheckSquare size={18} />\n Metadata\n </CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">Created</p>\n <p className=\"font-medium\">{formatRelativeTime(profile.createdAt)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Updated</p>\n <p className=\"font-medium\">{formatRelativeTime(profile.updatedAt)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Revision</p>\n <p className=\"font-medium\">{profile.revision}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Visibility</p>\n <Badge variant=\"outline\">{profile.visibility}</Badge>\n </div>\n </div>\n </CardContent>\n </Card>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"RetrievalProfileDetailPage.js","names":[],"sources":["../../../src/botlit/pages/RetrievalProfileDetailPage.tsx"],"sourcesContent":["/**\n * Retrieval Profile Detail Page\n * @module botlit/pages\n *\n * `RetrievalProfile` is FLAT on wspace-botlit-svc — `strategyMode`, `topK`,\n * `citationsRequired`, `minRelevanceScore` and friends all sit at the top\n * level. There is no nested `strategy`/`grounding`/`thresholds` object, so the\n * form state below mirrors the create/update inputs field for field and the\n * payload is built explicitly rather than handing the whole record back.\n */\n\nimport type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useParams } from 'react-router';\nimport { toast } from 'sonner';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { isNative, nativeImpact, nativeNotify } from '../../utils/nativeBridge';\nimport {\n ArrowLeft,\n Edit,\n Trash2,\n Search,\n FileText,\n Settings,\n Target,\n CheckSquare,\n} from 'lucide-react';\nimport { PageLayout } from '../components/PageLayout';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { EmptyState } from '../components/EmptyState';\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Badge, StatusBadge } from '../components/Badge';\nimport { Input, Textarea, FormField } from '../components/Input';\nimport {\n useRetrievalProfile,\n useCreateRetrievalProfile,\n useUpdateRetrievalProfile,\n useDeleteRetrievalProfile,\n type CreateRetrievalProfileVariables,\n type RetrievalProfileRecord,\n} from '../hooks/useRetrievalProfiles';\nimport { formatRelativeTime, MISSING_VALUE } from '../utils/formatters';\nimport type { RetrievalMode, RerankerMode } from '../types';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\n\ninterface RetrievalProfileDetailPageProps {\n isNew?: boolean;\n}\n\n/** Editable subset of the retrieval profile — one field per input field. */\ninterface RetrievalProfileForm {\n name: string;\n description: string;\n strategyMode: RetrievalMode;\n topK: number;\n reranker: RerankerMode;\n queryRewrite: RerankerMode;\n multiHop: RerankerMode;\n citationsRequired: boolean;\n showSources: boolean;\n minSources: number;\n snippetMaxChars: number;\n citationFormat: string;\n minRelevanceScore: number;\n noAnswerIfBelowThreshold: boolean;\n}\n\nconst DEFAULT_FORM: RetrievalProfileForm = {\n name: '',\n description: '',\n strategyMode: 'HYBRID',\n topK: 10,\n reranker: 'OFF',\n queryRewrite: 'OFF',\n multiHop: 'OFF',\n citationsRequired: true,\n showSources: true,\n minSources: 1,\n snippetMaxChars: 500,\n citationFormat: '[{index}]',\n minRelevanceScore: 0.7,\n noAnswerIfBelowThreshold: true,\n};\n\nconst RETRIEVAL_MODES: RetrievalMode[] = ['VECTOR', 'HYBRID', 'BM25_ONLY'];\n\n/** `reranker`/`queryRewrite`/`multiHop` are free-form strings on the service. */\nfunction toRerankerMode(value: string): RerankerMode {\n return value === 'ON' ? 'ON' : 'OFF';\n}\n\nfunction toRetrievalMode(value: string): RetrievalMode {\n return RETRIEVAL_MODES.includes(value as RetrievalMode) ? (value as RetrievalMode) : 'HYBRID';\n}\n\n/** Seeds the form from a loaded profile. */\nfunction toForm(profile: RetrievalProfileRecord): RetrievalProfileForm {\n return {\n name: profile.name,\n description: profile.description ?? '',\n strategyMode: toRetrievalMode(profile.strategyMode),\n topK: profile.topK,\n reranker: toRerankerMode(profile.reranker),\n queryRewrite: toRerankerMode(profile.queryRewrite),\n multiHop: toRerankerMode(profile.multiHop),\n citationsRequired: profile.citationsRequired,\n showSources: profile.showSources,\n minSources: profile.minSources,\n snippetMaxChars: profile.snippetMaxChars,\n citationFormat: profile.citationFormat ?? DEFAULT_FORM.citationFormat,\n minRelevanceScore: profile.minRelevanceScore ?? DEFAULT_FORM.minRelevanceScore,\n noAnswerIfBelowThreshold: profile.noAnswerIfBelowThreshold,\n };\n}\n\n/**\n * Builds the mutation payload. Every key here is declared by both\n * `CreateRetrievalProfileInput` and `UpdateRetrievalProfileInput`, so the same\n * projection serves create and update.\n */\nfunction toInput(form: RetrievalProfileForm): CreateRetrievalProfileVariables {\n return {\n name: form.name.trim(),\n description: form.description.trim() || null,\n strategyMode: form.strategyMode,\n topK: form.topK,\n reranker: form.reranker,\n queryRewrite: form.queryRewrite,\n multiHop: form.multiHop,\n citationsRequired: form.citationsRequired,\n showSources: form.showSources,\n minSources: form.minSources,\n snippetMaxChars: form.snippetMaxChars,\n citationFormat: form.citationFormat.trim() || null,\n minRelevanceScore: form.minRelevanceScore,\n noAnswerIfBelowThreshold: form.noAnswerIfBelowThreshold,\n };\n}\n\n/** `Number('')` is 0 and `Number('abc')` is NaN — keep the previous value instead. */\nfunction toNumber(value: string, fallback: number): number {\n const parsed = Number(value);\n return value.trim() !== '' && Number.isFinite(parsed) ? parsed : fallback;\n}\n\nexport const RetrievalProfileDetailPage: FC<RetrievalProfileDetailPageProps> = ({\n isNew = false,\n}) => {\n const { profileId } = useParams();\n const { navigateTo } = useBotlit();\n const { data: profile, loading, refetch } = useRetrievalProfile(isNew ? undefined : profileId);\n const { create: createProfile, loading: createLoading } = useCreateRetrievalProfile();\n const { update: updateProfile, loading: updateLoading } = useUpdateRetrievalProfile();\n const { remove: deleteProfile, loading: deleteLoading } = useDeleteRetrievalProfile();\n\n const [isEditing, setIsEditing] = useState(isNew);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [formData, setFormData] = useState<RetrievalProfileForm>(DEFAULT_FORM);\n\n // Seed the form once the profile arrives so \"Edit\" always opens on current values.\n useEffect(() => {\n if (profile && !isNew) {\n setFormData(toForm(profile));\n }\n }, [profile, isNew]);\n\n if (loading && !isNew) {\n return (\n <PageLayout title=\"Loading...\">\n <div className=\"h-96 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\" />\n </PageLayout>\n );\n }\n\n if (!profile && !isNew) {\n return (\n <PageLayout title=\"Profile Not Found\">\n <EmptyState\n illustration=\"empty-files\"\n title=\"Profile Not Found\"\n description=\"The retrieval profile doesn't exist.\"\n action={\n <Button onClick={() => navigateTo('retrieval-profiles')}>Back to Profiles</Button>\n }\n />\n </PageLayout>\n );\n }\n\n const handleSave = async () => {\n if (!formData.name.trim()) {\n toast.error('Name is required');\n return;\n }\n try {\n if (isNew) {\n const created = await createProfile(toInput(formData));\n toast.success(`Profile \"${created.name}\" created`);\n navigateTo(`retrieval-profiles/${created.id}`);\n return;\n }\n if (!profileId) return;\n await updateProfile({ profileId, input: toInput(formData) });\n await refetch();\n toast.success('Retrieval profile updated');\n setIsEditing(false);\n } catch (err) {\n toast.error(err instanceof Error ? err.message : 'Failed to save retrieval profile');\n }\n };\n\n const handleDelete = async () => {\n if (!profileId) return;\n try {\n await deleteProfile(profileId);\n if (isNative()) void nativeNotify('success');\n toast.success('Retrieval profile deleted');\n navigateTo('retrieval-profiles');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n toast.error(err instanceof Error ? err.message : 'Failed to delete retrieval profile');\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('retrieval-profiles')}>\n <ArrowLeft size={20} />\n </Button>\n <Search size={24} className=\"text-primary\" />\n <div>\n <div className=\"flex items-center gap-2\">\n <span>{isNew ? 'New Retrieval Profile' : profile?.name}</span>\n {!isNew && profile && <StatusBadge status={profile.status} />}\n </div>\n {!isNew && profile?.description && (\n <p className=\"text-sm font-normal text-text-secondary\">{profile.description}</p>\n )}\n </div>\n </div>\n }\n actions={\n <div className=\"flex gap-2\">\n {isEditing ? (\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n if (isNew) {\n navigateTo('retrieval-profiles');\n return;\n }\n if (profile) setFormData(toForm(profile));\n setIsEditing(false);\n }}\n >\n Cancel\n </Button>\n <Button onClick={handleSave} isLoading={createLoading || updateLoading}>\n {isNew ? 'Create Profile' : 'Save Changes'}\n </Button>\n </>\n ) : (\n <>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.RETRIEVAL_PROFILE_UPDATE}>\n <Button\n variant=\"outline\"\n leftIcon={<Edit size={16} />}\n onClick={() => {\n if (profile) setFormData(toForm(profile));\n setIsEditing(true);\n }}\n >\n Edit\n </Button>\n </BotmanorPermissionGate>\n {showDeleteConfirm ? (\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => setShowDeleteConfirm(false)}>\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => {\n nativeImpact('medium');\n void handleDelete();\n }}\n isLoading={deleteLoading}\n >\n Confirm Delete\n </Button>\n </div>\n ) : (\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.RETRIEVAL_PROFILE_DELETE}>\n <Button\n variant=\"destructive\"\n leftIcon={<Trash2 size={16} />}\n onClick={() => setShowDeleteConfirm(true)}\n >\n Delete\n </Button>\n </BotmanorPermissionGate>\n )}\n </>\n )}\n </div>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Settings size={18} />}>\n This profile defines exactly how an agent searches your knowledge — the retrieval mode,\n how many results to pull, whether to rerank them and whether to rewrite the query first.\n Adjust the strategy here to dial in the balance between answer accuracy and speed, then\n attach the profile to the agents that should use it.\n </PagePurpose>\n\n {/* Basic Info */}\n {isEditing ? (\n <Card>\n <CardHeader>\n <CardTitle>Basic Information</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <FormField label=\"Name\" required>\n <Input\n value={formData.name}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n placeholder=\"e.g., Default Hybrid Search\"\n />\n </FormField>\n <FormField label=\"Description\">\n <Textarea\n value={formData.description}\n onChange={(e) => setFormData({ ...formData, description: e.target.value })}\n placeholder=\"Describe when to use this profile...\"\n rows={3}\n />\n </FormField>\n </CardContent>\n </Card>\n ) : null}\n\n {/* Strategy Configuration */}\n <Card treatment=\"glass\" glow>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Settings size={18} />\n Retrieval Strategy\n </CardTitle>\n <CardDescription>How documents are searched and ranked</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {isEditing ? (\n <>\n <FormField label=\"Retrieval Mode\">\n <div className=\"flex gap-4\">\n {RETRIEVAL_MODES.map((mode) => (\n <label key={mode} className=\"flex items-center gap-2\">\n <input\n type=\"radio\"\n name=\"strategyMode\"\n checked={formData.strategyMode === mode}\n onChange={() => setFormData({ ...formData, strategyMode: mode })}\n />\n <span className=\"capitalize\">{mode.replace('_', ' ')}</span>\n </label>\n ))}\n </div>\n </FormField>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Top K Results\">\n <Input\n type=\"number\"\n value={formData.topK}\n onChange={(e) =>\n setFormData({\n ...formData,\n topK: toNumber(e.target.value, DEFAULT_FORM.topK),\n })\n }\n />\n </FormField>\n <FormField label=\"Reranker\">\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={formData.reranker}\n onChange={(e) =>\n setFormData({ ...formData, reranker: toRerankerMode(e.target.value) })\n }\n >\n <option value=\"OFF\">Disabled</option>\n <option value=\"ON\">Enabled</option>\n </select>\n </FormField>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Query Rewrite\">\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={formData.queryRewrite}\n onChange={(e) =>\n setFormData({ ...formData, queryRewrite: toRerankerMode(e.target.value) })\n }\n >\n <option value=\"OFF\">Disabled</option>\n <option value=\"ON\">Enabled</option>\n </select>\n </FormField>\n <FormField label=\"Multi-Hop\">\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={formData.multiHop}\n onChange={(e) =>\n setFormData({ ...formData, multiHop: toRerankerMode(e.target.value) })\n }\n >\n <option value=\"OFF\">Disabled</option>\n <option value=\"ON\">Enabled</option>\n </select>\n </FormField>\n </div>\n </>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Mode</p>\n <Badge variant=\"outline\">{profile?.strategyMode}</Badge>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Top K</p>\n <p className=\"font-medium\">{profile?.topK}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Reranker</p>\n <Badge variant={profile?.reranker === 'ON' ? 'success' : 'secondary'}>\n {profile?.reranker}\n </Badge>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Query Rewrite</p>\n <Badge variant={profile?.queryRewrite === 'ON' ? 'success' : 'secondary'}>\n {profile?.queryRewrite}\n </Badge>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Grounding Configuration */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <FileText size={18} />\n Grounding & Citations\n </CardTitle>\n <CardDescription>How sources are cited in responses</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {isEditing ? (\n <>\n <div className=\"flex items-center gap-4\">\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={formData.citationsRequired}\n onChange={(e) =>\n setFormData({ ...formData, citationsRequired: e.target.checked })\n }\n />\n <span>Citations Required</span>\n </label>\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={formData.showSources}\n onChange={(e) => setFormData({ ...formData, showSources: e.target.checked })}\n />\n <span>Show Sources</span>\n </label>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Min Sources\">\n <Input\n type=\"number\"\n value={formData.minSources}\n onChange={(e) =>\n setFormData({\n ...formData,\n minSources: toNumber(e.target.value, DEFAULT_FORM.minSources),\n })\n }\n />\n </FormField>\n <FormField label=\"Max Snippet Chars\">\n <Input\n type=\"number\"\n value={formData.snippetMaxChars}\n onChange={(e) =>\n setFormData({\n ...formData,\n snippetMaxChars: toNumber(e.target.value, DEFAULT_FORM.snippetMaxChars),\n })\n }\n />\n </FormField>\n </div>\n <FormField label=\"Citation Format Template\">\n <Input\n value={formData.citationFormat}\n onChange={(e) => setFormData({ ...formData, citationFormat: e.target.value })}\n placeholder=\"[{index}]\"\n />\n </FormField>\n </>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Citations Required</p>\n <Badge variant={profile?.citationsRequired ? 'success' : 'secondary'}>\n {profile?.citationsRequired ? 'Yes' : 'No'}\n </Badge>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Min Sources</p>\n <p className=\"font-medium\">{profile?.minSources}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Max Snippet</p>\n <p className=\"font-medium\">{profile?.snippetMaxChars} chars</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Citation Format</p>\n <code className=\"text-sm\">{profile?.citationFormat ?? MISSING_VALUE}</code>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Thresholds */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Target size={18} />\n Relevance Thresholds\n </CardTitle>\n <CardDescription>Minimum quality requirements for results</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {isEditing ? (\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Min Relevance Score (0-1)\">\n <Input\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"1\"\n value={formData.minRelevanceScore}\n onChange={(e) =>\n setFormData({\n ...formData,\n minRelevanceScore: toNumber(e.target.value, DEFAULT_FORM.minRelevanceScore),\n })\n }\n />\n </FormField>\n <div className=\"flex items-center\">\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={formData.noAnswerIfBelowThreshold}\n onChange={(e) =>\n setFormData({ ...formData, noAnswerIfBelowThreshold: e.target.checked })\n }\n />\n <span>No Answer if Below Threshold</span>\n </label>\n </div>\n </div>\n ) : (\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Min Relevance Score</p>\n <p className=\"font-medium\">{profile?.minRelevanceScore ?? 'Not set'}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">No Answer Below Threshold</p>\n <Badge variant={profile?.noAnswerIfBelowThreshold ? 'warning' : 'secondary'}>\n {profile?.noAnswerIfBelowThreshold ? 'Yes' : 'No'}\n </Badge>\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Metadata (view only) */}\n {!isNew && profile && (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <CheckSquare size={18} />\n Metadata\n </CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">Created</p>\n <p className=\"font-medium\">{formatRelativeTime(profile.createdAt)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Updated</p>\n <p className=\"font-medium\">{formatRelativeTime(profile.updatedAt)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Revision</p>\n <p className=\"font-medium\">{profile.revision}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Visibility</p>\n <Badge variant=\"outline\">{profile.visibility}</Badge>\n </div>\n </div>\n </CardContent>\n </Card>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -1,128 +1,134 @@
1
1
  import { useTr as e } from "../../shared/hooks/useTr.js";
2
2
  import { useBotlit as t } from "../providers/BotlitProvider.js";
3
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, CardDescription as o, CardHeader as s, CardTitle as c } from "../components/Card.js";
6
- import { Button as l } from "../components/Button.js";
7
- import { Badge as u, StatusBadge as d } from "../components/Badge.js";
8
- import { EmptyState as f } from "../components/EmptyState.js";
9
- import { Input as p } from "../components/Input.js";
10
- import { ErrorState as m } from "../components/ErrorState.js";
11
- import { useRetrievalProfiles as h } from "../hooks/useRetrievalProfiles.js";
4
+ import { BOTMANOR_PERMISSIONS as r } from "../permissions/botmanorPermissions.js";
5
+ import { BotmanorPermissionGate as i } from "../permissions/useBotmanorPermissions.js";
6
+ import { PageLayout as a } from "../components/PageLayout.js";
7
+ import { Button as o } from "../components/Button.js";
8
+ import "../permissions/index.js";
9
+ import { Card as s, CardContent as c, CardDescription as l, CardHeader as u, CardTitle as d } from "../components/Card.js";
10
+ import { Badge as f, StatusBadge as p } from "../components/Badge.js";
11
+ import { EmptyState as m } from "../components/EmptyState.js";
12
+ import { Input as h } from "../components/Input.js";
13
+ import { ErrorState as g } from "../components/ErrorState.js";
14
+ import { useRetrievalProfiles as _ } from "../hooks/useRetrievalProfiles.js";
12
15
  import "../hooks/index.js";
13
- import { useState as g } from "react";
14
- import { GlassCard as _, PagePurpose as v } from "@burdenoff/fe-libs/ui";
15
- import { jsx as y, jsxs as b } from "react/jsx-runtime";
16
- import { Link as x } from "react-router";
17
- import { Database as S, Filter as C, Layers as w, Plus as T, Search as E, Settings as D, Zap as O } from "lucide-react";
16
+ import { useState as v } from "react";
17
+ import { GlassCard as y, PagePurpose as b } from "@burdenoff/fe-libs/ui";
18
+ import { jsx as x, jsxs as S } from "react/jsx-runtime";
19
+ import { Link as C } from "react-router";
20
+ import { Database as w, Filter as T, Layers as E, Plus as D, Search as O, Settings as k, Zap as A } from "lucide-react";
18
21
  //#region src/botlit/pages/RetrievalProfilesPage.tsx
19
- var k = () => {
20
- let k = e(), { getPath: A } = t(), [j, M] = g(""), { data: N, loading: P, error: F, refetch: I } = h({ search: j });
21
- return /* @__PURE__ */ y(r, {
22
- title: k("botlit.retrievalProfiles.title", "Retrieval Profiles"),
23
- description: k("botlit.retrievalProfiles.description", "Configure how agents retrieve and rank knowledge from knowledge bases"),
24
- actions: /* @__PURE__ */ y(l, {
25
- leftIcon: /* @__PURE__ */ y(T, { size: 16 }),
26
- children: /* @__PURE__ */ y(x, {
27
- to: A("retrieval-profiles/new"),
28
- children: k("botlit.retrievalProfiles.actions.createProfile", "Create Profile")
22
+ var j = () => {
23
+ let j = e(), { getPath: M } = t(), [N, P] = v(""), { data: F, loading: I, error: L, refetch: R } = _({ search: N });
24
+ return /* @__PURE__ */ x(a, {
25
+ title: j("botlit.retrievalProfiles.title", "Retrieval Profiles"),
26
+ description: j("botlit.retrievalProfiles.description", "Configure how agents retrieve and rank knowledge from knowledge bases"),
27
+ actions: /* @__PURE__ */ x(i, {
28
+ permission: r.RETRIEVAL_PROFILE_CREATE,
29
+ children: /* @__PURE__ */ x(o, {
30
+ leftIcon: /* @__PURE__ */ x(D, { size: 16 }),
31
+ children: /* @__PURE__ */ x(C, {
32
+ to: M("retrieval-profiles/new"),
33
+ children: j("botlit.retrievalProfiles.actions.createProfile", "Create Profile")
34
+ })
29
35
  })
30
36
  }),
31
- children: /* @__PURE__ */ b("div", {
37
+ children: /* @__PURE__ */ S("div", {
32
38
  className: "space-y-6",
33
39
  children: [
34
- /* @__PURE__ */ y(v, {
35
- icon: /* @__PURE__ */ y(S, { size: 18 }),
36
- children: k("botlit.retrievalProfiles.purpose", "A retrieval profile decides how an agent searches your knowledge bases — which search strategy to use (semantic, keyword or hybrid), how many passages to pull back, whether to rerank for relevance and whether answers must cite their sources. Tune a profile here to control the accuracy-versus-speed trade-off of every grounded answer your agents give.")
40
+ /* @__PURE__ */ x(b, {
41
+ icon: /* @__PURE__ */ x(w, { size: 18 }),
42
+ children: j("botlit.retrievalProfiles.purpose", "A retrieval profile decides how an agent searches your knowledge bases — which search strategy to use (semantic, keyword or hybrid), how many passages to pull back, whether to rerank for relevance and whether answers must cite their sources. Tune a profile here to control the accuracy-versus-speed trade-off of every grounded answer your agents give.")
37
43
  }),
38
- /* @__PURE__ */ b("div", {
44
+ /* @__PURE__ */ S("div", {
39
45
  className: "flex items-center gap-4",
40
- children: [/* @__PURE__ */ b("div", {
46
+ children: [/* @__PURE__ */ S("div", {
41
47
  className: "relative flex-1 max-w-md",
42
- children: [/* @__PURE__ */ y(E, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ y(p, {
43
- placeholder: k("botlit.retrievalProfiles.searchPlaceholder", "Search profiles..."),
44
- value: j,
45
- onChange: (e) => M(e.target.value),
48
+ children: [/* @__PURE__ */ x(O, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ x(h, {
49
+ placeholder: j("botlit.retrievalProfiles.searchPlaceholder", "Search profiles..."),
50
+ value: N,
51
+ onChange: (e) => P(e.target.value),
46
52
  className: "pl-9"
47
53
  })]
48
- }), /* @__PURE__ */ y(l, {
54
+ }), /* @__PURE__ */ x(o, {
49
55
  variant: "outline",
50
- leftIcon: /* @__PURE__ */ y(C, { size: 16 }),
51
- children: k("botlit.retrievalProfiles.actions.filters", "Filters")
56
+ leftIcon: /* @__PURE__ */ x(T, { size: 16 }),
57
+ children: j("botlit.retrievalProfiles.actions.filters", "Filters")
52
58
  })]
53
59
  }),
54
- P ? /* @__PURE__ */ y("div", {
60
+ I ? /* @__PURE__ */ x("div", {
55
61
  className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
56
62
  children: [
57
63
  1,
58
64
  2,
59
65
  3
60
- ].map((e) => /* @__PURE__ */ y("div", { className: "h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }, e))
61
- }) : F ? /* @__PURE__ */ y(m, {
66
+ ].map((e) => /* @__PURE__ */ x("div", { className: "h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }, e))
67
+ }) : L ? /* @__PURE__ */ x(g, {
62
68
  resource: "retrieval profiles",
63
- error: F,
64
- onRetry: () => void I()
65
- }) : N.length > 0 ? /* @__PURE__ */ y("div", {
69
+ error: L,
70
+ onRetry: () => void R()
71
+ }) : F.length > 0 ? /* @__PURE__ */ x("div", {
66
72
  className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
67
- children: N.map((e) => /* @__PURE__ */ y(x, {
68
- to: A(`retrieval-profiles/${e.id}`),
69
- children: /* @__PURE__ */ b(i, {
73
+ children: F.map((e) => /* @__PURE__ */ x(C, {
74
+ to: M(`retrieval-profiles/${e.id}`),
75
+ children: /* @__PURE__ */ S(s, {
70
76
  className: "h-full hover:border-primary/50 transition-colors cursor-pointer",
71
- children: [/* @__PURE__ */ y(s, { children: /* @__PURE__ */ b("div", {
77
+ children: [/* @__PURE__ */ x(u, { children: /* @__PURE__ */ S("div", {
72
78
  className: "flex items-start justify-between",
73
- children: [/* @__PURE__ */ b("div", {
79
+ children: [/* @__PURE__ */ S("div", {
74
80
  className: "flex items-center gap-3",
75
- children: [/* @__PURE__ */ y("div", {
81
+ children: [/* @__PURE__ */ x("div", {
76
82
  className: "p-2 bg-action-primary-bg/10 rounded-lg",
77
- children: /* @__PURE__ */ y(S, { className: "h-5 w-5 text-primary" })
78
- }), /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y(c, {
83
+ children: /* @__PURE__ */ x(w, { className: "h-5 w-5 text-primary" })
84
+ }), /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x(d, {
79
85
  className: "text-base",
80
86
  children: e.name
81
- }), /* @__PURE__ */ y(o, {
87
+ }), /* @__PURE__ */ x(l, {
82
88
  className: "text-xs",
83
89
  children: e.description
84
90
  })] })]
85
- }), /* @__PURE__ */ y(d, { status: e.status })]
86
- }) }), /* @__PURE__ */ y(a, { children: /* @__PURE__ */ b("div", {
91
+ }), /* @__PURE__ */ x(p, { status: e.status })]
92
+ }) }), /* @__PURE__ */ x(c, { children: /* @__PURE__ */ S("div", {
87
93
  className: "space-y-3",
88
94
  children: [
89
- /* @__PURE__ */ b("div", {
95
+ /* @__PURE__ */ S("div", {
90
96
  className: "flex items-center gap-2",
91
- children: [/* @__PURE__ */ y(w, {
97
+ children: [/* @__PURE__ */ x(E, {
92
98
  size: 14,
93
99
  className: "text-text-secondary"
94
- }), /* @__PURE__ */ y("span", {
100
+ }), /* @__PURE__ */ x("span", {
95
101
  className: "text-sm capitalize",
96
- children: k("botlit.retrievalProfiles.overview.mode", "{{mode}} mode", { mode: e.strategyMode.toLowerCase().replace("_", " ") })
102
+ children: j("botlit.retrievalProfiles.overview.mode", "{{mode}} mode", { mode: e.strategyMode.toLowerCase().replace("_", " ") })
97
103
  })]
98
104
  }),
99
- /* @__PURE__ */ b("div", {
105
+ /* @__PURE__ */ S("div", {
100
106
  className: "flex items-center gap-2",
101
- children: [/* @__PURE__ */ y(O, {
107
+ children: [/* @__PURE__ */ x(A, {
102
108
  size: 14,
103
109
  className: "text-text-secondary"
104
- }), /* @__PURE__ */ y("span", {
110
+ }), /* @__PURE__ */ x("span", {
105
111
  className: "text-sm",
106
- children: k("botlit.retrievalProfiles.overview.citations", "Citations: {{status}}", { status: e.citationsRequired ? k("botlit.retrievalProfiles.overview.required", "Required") : k("botlit.retrievalProfiles.overview.optional", "Optional") })
112
+ children: j("botlit.retrievalProfiles.overview.citations", "Citations: {{status}}", { status: e.citationsRequired ? j("botlit.retrievalProfiles.overview.required", "Required") : j("botlit.retrievalProfiles.overview.optional", "Optional") })
107
113
  })]
108
114
  }),
109
- /* @__PURE__ */ b("div", {
115
+ /* @__PURE__ */ S("div", {
110
116
  className: "flex items-center gap-2",
111
- children: [/* @__PURE__ */ y(S, {
117
+ children: [/* @__PURE__ */ x(w, {
112
118
  size: 14,
113
119
  className: "text-text-secondary"
114
- }), /* @__PURE__ */ y("span", {
120
+ }), /* @__PURE__ */ x("span", {
115
121
  className: "text-sm",
116
- children: k("botlit.retrievalProfiles.topK", "Top K: {{value}}", { value: e.topK })
122
+ children: j("botlit.retrievalProfiles.topK", "Top K: {{value}}", { value: e.topK })
117
123
  })]
118
124
  }),
119
- /* @__PURE__ */ b("div", {
125
+ /* @__PURE__ */ S("div", {
120
126
  className: "pt-3 border-t border-border-subtle flex items-center justify-between text-xs text-text-secondary",
121
- children: [/* @__PURE__ */ b("span", { children: [
122
- k("botlit.botsList.createdLabel", "Created"),
127
+ children: [/* @__PURE__ */ S("span", { children: [
128
+ j("botlit.botsList.createdLabel", "Created"),
123
129
  " ",
124
130
  n(e.createdAt)
125
- ] }), /* @__PURE__ */ y(u, {
131
+ ] }), /* @__PURE__ */ x(f, {
126
132
  variant: "outline",
127
133
  className: "text-xs capitalize",
128
134
  children: e.strategyMode.toLowerCase().replace("_", " ")
@@ -132,71 +138,74 @@ var k = () => {
132
138
  }) })]
133
139
  })
134
140
  }, e.id))
135
- }) : /* @__PURE__ */ y(f, {
141
+ }) : /* @__PURE__ */ x(m, {
136
142
  illustration: "empty-files",
137
- title: k("botlit.retrievalProfiles.empty.title", "No retrieval profiles"),
138
- description: k("botlit.retrievalProfiles.empty.description", "Create retrieval profiles to customize how agents search and rank knowledge."),
139
- action: /* @__PURE__ */ y(l, {
140
- leftIcon: /* @__PURE__ */ y(T, { size: 16 }),
141
- children: /* @__PURE__ */ y(x, {
142
- to: A("retrieval-profiles/new"),
143
- children: k("botlit.retrievalProfiles.actions.createProfile", "Create Profile")
143
+ title: j("botlit.retrievalProfiles.empty.title", "No retrieval profiles"),
144
+ description: j("botlit.retrievalProfiles.empty.description", "Create retrieval profiles to customize how agents search and rank knowledge."),
145
+ action: /* @__PURE__ */ x(i, {
146
+ permission: r.RETRIEVAL_PROFILE_CREATE,
147
+ children: /* @__PURE__ */ x(o, {
148
+ leftIcon: /* @__PURE__ */ x(D, { size: 16 }),
149
+ children: /* @__PURE__ */ x(C, {
150
+ to: M("retrieval-profiles/new"),
151
+ children: j("botlit.retrievalProfiles.actions.createProfile", "Create Profile")
152
+ })
144
153
  })
145
154
  })
146
155
  }),
147
- /* @__PURE__ */ b(_, {
156
+ /* @__PURE__ */ S(y, {
148
157
  treatment: "glass",
149
158
  glow: !0,
150
159
  className: "p-6",
151
- children: [/* @__PURE__ */ b("div", {
160
+ children: [/* @__PURE__ */ S("div", {
152
161
  className: "mb-4",
153
- children: [/* @__PURE__ */ b("h2", {
162
+ children: [/* @__PURE__ */ S("h2", {
154
163
  className: "flex items-center gap-2 text-lg font-semibold tracking-tight text-text-primary",
155
- children: [/* @__PURE__ */ y(D, { size: 18 }), k("botlit.retrievalProfiles.overview.title", "Retrieval Profile Configuration")]
156
- }), /* @__PURE__ */ y("p", {
164
+ children: [/* @__PURE__ */ x(k, { size: 18 }), j("botlit.retrievalProfiles.overview.title", "Retrieval Profile Configuration")]
165
+ }), /* @__PURE__ */ x("p", {
157
166
  className: "text-sm text-text-secondary",
158
- children: k("botlit.retrievalProfiles.overview.description", "Retrieval profiles control how knowledge is fetched and ranked for agent responses")
167
+ children: j("botlit.retrievalProfiles.overview.description", "Retrieval profiles control how knowledge is fetched and ranked for agent responses")
159
168
  })]
160
- }), /* @__PURE__ */ b("div", {
169
+ }), /* @__PURE__ */ S("div", {
161
170
  className: "grid grid-cols-1 md:grid-cols-3 gap-6",
162
171
  children: [
163
- /* @__PURE__ */ b("div", {
172
+ /* @__PURE__ */ S("div", {
164
173
  className: "space-y-2",
165
- children: [/* @__PURE__ */ b("h4", {
174
+ children: [/* @__PURE__ */ S("h4", {
166
175
  className: "font-medium flex items-center gap-2",
167
- children: [/* @__PURE__ */ y(w, {
176
+ children: [/* @__PURE__ */ x(E, {
168
177
  size: 16,
169
178
  className: "text-primary"
170
- }), k("botlit.retrievalProfiles.overview.modesTitle", "Retrieval Modes")]
171
- }), /* @__PURE__ */ y("ul", {
179
+ }), j("botlit.retrievalProfiles.overview.modesTitle", "Retrieval Modes")]
180
+ }), /* @__PURE__ */ x("ul", {
172
181
  className: "text-sm text-text-secondary space-y-1",
173
- children: /* @__PURE__ */ y("li", { children: k("botlit.retrievalProfiles.overview.modesDescription", "Vector: semantic similarity search; Hybrid: vector + keyword combined; BM25: traditional keyword search.") })
182
+ children: /* @__PURE__ */ x("li", { children: j("botlit.retrievalProfiles.overview.modesDescription", "Vector: semantic similarity search; Hybrid: vector + keyword combined; BM25: traditional keyword search.") })
174
183
  })]
175
184
  }),
176
- /* @__PURE__ */ b("div", {
185
+ /* @__PURE__ */ S("div", {
177
186
  className: "space-y-2",
178
- children: [/* @__PURE__ */ b("h4", {
187
+ children: [/* @__PURE__ */ S("h4", {
179
188
  className: "font-medium flex items-center gap-2",
180
- children: [/* @__PURE__ */ y(O, {
189
+ children: [/* @__PURE__ */ x(A, {
181
190
  size: 16,
182
191
  className: "text-primary"
183
- }), k("botlit.retrievalProfiles.overview.rerankingTitle", "Reranking")]
184
- }), /* @__PURE__ */ y("ul", {
192
+ }), j("botlit.retrievalProfiles.overview.rerankingTitle", "Reranking")]
193
+ }), /* @__PURE__ */ x("ul", {
185
194
  className: "text-sm text-text-secondary space-y-1",
186
- children: /* @__PURE__ */ y("li", { children: k("botlit.retrievalProfiles.overview.rerankingDescription", "Cross-encoder reranking for better relevance; improves precision at the cost of latency; recommended for complex queries.") })
195
+ children: /* @__PURE__ */ x("li", { children: j("botlit.retrievalProfiles.overview.rerankingDescription", "Cross-encoder reranking for better relevance; improves precision at the cost of latency; recommended for complex queries.") })
187
196
  })]
188
197
  }),
189
- /* @__PURE__ */ b("div", {
198
+ /* @__PURE__ */ S("div", {
190
199
  className: "space-y-2",
191
- children: [/* @__PURE__ */ b("h4", {
200
+ children: [/* @__PURE__ */ S("h4", {
192
201
  className: "font-medium flex items-center gap-2",
193
- children: [/* @__PURE__ */ y(S, {
202
+ children: [/* @__PURE__ */ x(w, {
194
203
  size: 16,
195
204
  className: "text-primary"
196
- }), k("botlit.retrievalProfiles.overview.knowledgeSourcesTitle", "Knowledge Sources")]
197
- }), /* @__PURE__ */ y("ul", {
205
+ }), j("botlit.retrievalProfiles.overview.knowledgeSourcesTitle", "Knowledge Sources")]
206
+ }), /* @__PURE__ */ x("ul", {
198
207
  className: "text-sm text-text-secondary space-y-1",
199
- children: /* @__PURE__ */ y("li", { children: k("botlit.retrievalProfiles.overview.knowledgeSourcesDescription", "Bind multiple knowledge bases, configure priority and weights, and set per-KB retrieval limits.") })
208
+ children: /* @__PURE__ */ x("li", { children: j("botlit.retrievalProfiles.overview.knowledgeSourcesDescription", "Bind multiple knowledge bases, configure priority and weights, and set per-KB retrieval limits.") })
200
209
  })]
201
210
  })
202
211
  ]
@@ -207,6 +216,6 @@ var k = () => {
207
216
  });
208
217
  };
209
218
  //#endregion
210
- export { k as RetrievalProfilesPage };
219
+ export { j as RetrievalProfilesPage };
211
220
 
212
221
  //# sourceMappingURL=RetrievalProfilesPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RetrievalProfilesPage.js","names":[],"sources":["../../../src/botlit/pages/RetrievalProfilesPage.tsx"],"sourcesContent":["/**\n * Retrieval Profiles 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 { Plus, Search as SearchIcon, Filter, Database, Layers, Zap, Settings } 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 { useRetrievalProfiles } from '../hooks';\nimport { formatRelativeTime } from '../utils/formatters';\n\nexport const RetrievalProfilesPage: FC = () => {\n const t = useTr();\n const { getPath } = useBotlit();\n const [search, setSearch] = useState('');\n const { data: profiles, loading, error, refetch } = useRetrievalProfiles({ search });\n\n return (\n <PageLayout\n title={t('botlit.retrievalProfiles.title', 'Retrieval Profiles')}\n description={t(\n 'botlit.retrievalProfiles.description',\n 'Configure how agents retrieve and rank knowledge from knowledge bases'\n )}\n actions={\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('retrieval-profiles/new')}>\n {t('botlit.retrievalProfiles.actions.createProfile', 'Create Profile')}\n </Link>\n </Button>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Database size={18} />}>\n {t(\n 'botlit.retrievalProfiles.purpose',\n 'A retrieval profile decides how an agent searches your knowledge bases — which search strategy to use (semantic, keyword or hybrid), how many passages to pull back, whether to rerank for relevance and whether answers must cite their sources. Tune a profile here to control the accuracy-versus-speed trade-off of every grounded answer your agents give.'\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.retrievalProfiles.searchPlaceholder', 'Search profiles...')}\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.retrievalProfiles.actions.filters', 'Filters')}\n </Button>\n </div>\n\n {/* Profiles List */}\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=\"retrieval profiles\" error={error} onRetry={() => void refetch()} />\n ) : profiles.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {profiles.map(\n (profile: {\n id: string;\n name: string;\n description?: string | null;\n status: string;\n strategyMode: string;\n citationsRequired: boolean;\n topK: number;\n createdAt: string;\n }) => (\n <Link key={profile.id} to={getPath(`retrieval-profiles/${profile.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 <Database className=\"h-5 w-5 text-primary\" />\n </div>\n <div>\n <CardTitle className=\"text-base\">{profile.name}</CardTitle>\n <CardDescription className=\"text-xs\">\n {profile.description}\n </CardDescription>\n </div>\n </div>\n <StatusBadge status={profile.status} />\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {/* Retrieval Mode */}\n <div className=\"flex items-center gap-2\">\n <Layers size={14} className=\"text-text-secondary\" />\n <span className=\"text-sm capitalize\">\n {t('botlit.retrievalProfiles.overview.mode', '{{mode}} mode', {\n mode: profile.strategyMode.toLowerCase().replace('_', ' '),\n })}\n </span>\n </div>\n\n {/* Citations */}\n <div className=\"flex items-center gap-2\">\n <Zap size={14} className=\"text-text-secondary\" />\n <span className=\"text-sm\">\n {t(\n 'botlit.retrievalProfiles.overview.citations',\n 'Citations: {{status}}',\n {\n status: profile.citationsRequired\n ? t('botlit.retrievalProfiles.overview.required', 'Required')\n : t('botlit.retrievalProfiles.overview.optional', 'Optional'),\n }\n )}\n </span>\n </div>\n\n {/* Top K */}\n <div className=\"flex items-center gap-2\">\n <Database size={14} className=\"text-text-secondary\" />\n <span className=\"text-sm\">\n {t('botlit.retrievalProfiles.topK', 'Top K: {{value}}', {\n value: profile.topK,\n })}\n </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.botsList.createdLabel', 'Created')}{' '}\n {formatRelativeTime(profile.createdAt)}\n </span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {profile.strategyMode.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n </div>\n </CardContent>\n </Card>\n </Link>\n )\n )}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-files\"\n title={t('botlit.retrievalProfiles.empty.title', 'No retrieval profiles')}\n description={t(\n 'botlit.retrievalProfiles.empty.description',\n 'Create retrieval profiles to customize how agents search and rank knowledge.'\n )}\n action={\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('retrieval-profiles/new')}>\n {t('botlit.retrievalProfiles.actions.createProfile', 'Create Profile')}\n </Link>\n </Button>\n }\n />\n )}\n\n {/* Quick Start Guide */}\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 <Settings size={18} />\n {t('botlit.retrievalProfiles.overview.title', 'Retrieval Profile Configuration')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'botlit.retrievalProfiles.overview.description',\n 'Retrieval profiles control how knowledge is fetched and ranked for agent responses'\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 <Layers size={16} className=\"text-primary\" />\n {t('botlit.retrievalProfiles.overview.modesTitle', 'Retrieval Modes')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.retrievalProfiles.overview.modesDescription',\n 'Vector: semantic similarity search; Hybrid: vector + keyword combined; BM25: traditional keyword search.'\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.retrievalProfiles.overview.rerankingTitle', 'Reranking')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.retrievalProfiles.overview.rerankingDescription',\n 'Cross-encoder reranking for better relevance; improves precision at the cost of latency; recommended for complex queries.'\n )}\n </li>\n </ul>\n </div>\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <Database size={16} className=\"text-primary\" />\n {t('botlit.retrievalProfiles.overview.knowledgeSourcesTitle', 'Knowledge Sources')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.retrievalProfiles.overview.knowledgeSourcesDescription',\n 'Bind multiple knowledge bases, configure priority and weights, and set per-KB retrieval limits.'\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":"RetrievalProfilesPage.js","names":[],"sources":["../../../src/botlit/pages/RetrievalProfilesPage.tsx"],"sourcesContent":["/**\n * Retrieval Profiles 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 { Plus, Search as SearchIcon, Filter, Database, Layers, Zap, Settings } 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 { useRetrievalProfiles } from '../hooks';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\n\nexport const RetrievalProfilesPage: FC = () => {\n const t = useTr();\n const { getPath } = useBotlit();\n const [search, setSearch] = useState('');\n const { data: profiles, loading, error, refetch } = useRetrievalProfiles({ search });\n\n return (\n <PageLayout\n title={t('botlit.retrievalProfiles.title', 'Retrieval Profiles')}\n description={t(\n 'botlit.retrievalProfiles.description',\n 'Configure how agents retrieve and rank knowledge from knowledge bases'\n )}\n actions={\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.RETRIEVAL_PROFILE_CREATE}>\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('retrieval-profiles/new')}>\n {t('botlit.retrievalProfiles.actions.createProfile', 'Create Profile')}\n </Link>\n </Button>\n </BotmanorPermissionGate>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Database size={18} />}>\n {t(\n 'botlit.retrievalProfiles.purpose',\n 'A retrieval profile decides how an agent searches your knowledge bases — which search strategy to use (semantic, keyword or hybrid), how many passages to pull back, whether to rerank for relevance and whether answers must cite their sources. Tune a profile here to control the accuracy-versus-speed trade-off of every grounded answer your agents give.'\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.retrievalProfiles.searchPlaceholder', 'Search profiles...')}\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.retrievalProfiles.actions.filters', 'Filters')}\n </Button>\n </div>\n\n {/* Profiles List */}\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=\"retrieval profiles\" error={error} onRetry={() => void refetch()} />\n ) : profiles.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {profiles.map(\n (profile: {\n id: string;\n name: string;\n description?: string | null;\n status: string;\n strategyMode: string;\n citationsRequired: boolean;\n topK: number;\n createdAt: string;\n }) => (\n <Link key={profile.id} to={getPath(`retrieval-profiles/${profile.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 <Database className=\"h-5 w-5 text-primary\" />\n </div>\n <div>\n <CardTitle className=\"text-base\">{profile.name}</CardTitle>\n <CardDescription className=\"text-xs\">\n {profile.description}\n </CardDescription>\n </div>\n </div>\n <StatusBadge status={profile.status} />\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {/* Retrieval Mode */}\n <div className=\"flex items-center gap-2\">\n <Layers size={14} className=\"text-text-secondary\" />\n <span className=\"text-sm capitalize\">\n {t('botlit.retrievalProfiles.overview.mode', '{{mode}} mode', {\n mode: profile.strategyMode.toLowerCase().replace('_', ' '),\n })}\n </span>\n </div>\n\n {/* Citations */}\n <div className=\"flex items-center gap-2\">\n <Zap size={14} className=\"text-text-secondary\" />\n <span className=\"text-sm\">\n {t(\n 'botlit.retrievalProfiles.overview.citations',\n 'Citations: {{status}}',\n {\n status: profile.citationsRequired\n ? t('botlit.retrievalProfiles.overview.required', 'Required')\n : t('botlit.retrievalProfiles.overview.optional', 'Optional'),\n }\n )}\n </span>\n </div>\n\n {/* Top K */}\n <div className=\"flex items-center gap-2\">\n <Database size={14} className=\"text-text-secondary\" />\n <span className=\"text-sm\">\n {t('botlit.retrievalProfiles.topK', 'Top K: {{value}}', {\n value: profile.topK,\n })}\n </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.botsList.createdLabel', 'Created')}{' '}\n {formatRelativeTime(profile.createdAt)}\n </span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {profile.strategyMode.toLowerCase().replace('_', ' ')}\n </Badge>\n </div>\n </div>\n </CardContent>\n </Card>\n </Link>\n )\n )}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-files\"\n title={t('botlit.retrievalProfiles.empty.title', 'No retrieval profiles')}\n description={t(\n 'botlit.retrievalProfiles.empty.description',\n 'Create retrieval profiles to customize how agents search and rank knowledge.'\n )}\n action={\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.RETRIEVAL_PROFILE_CREATE}>\n <Button leftIcon={<Plus size={16} />}>\n <Link to={getPath('retrieval-profiles/new')}>\n {t('botlit.retrievalProfiles.actions.createProfile', 'Create Profile')}\n </Link>\n </Button>\n </BotmanorPermissionGate>\n }\n />\n )}\n\n {/* Quick Start Guide */}\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 <Settings size={18} />\n {t('botlit.retrievalProfiles.overview.title', 'Retrieval Profile Configuration')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'botlit.retrievalProfiles.overview.description',\n 'Retrieval profiles control how knowledge is fetched and ranked for agent responses'\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 <Layers size={16} className=\"text-primary\" />\n {t('botlit.retrievalProfiles.overview.modesTitle', 'Retrieval Modes')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.retrievalProfiles.overview.modesDescription',\n 'Vector: semantic similarity search; Hybrid: vector + keyword combined; BM25: traditional keyword search.'\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.retrievalProfiles.overview.rerankingTitle', 'Reranking')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.retrievalProfiles.overview.rerankingDescription',\n 'Cross-encoder reranking for better relevance; improves precision at the cost of latency; recommended for complex queries.'\n )}\n </li>\n </ul>\n </div>\n <div className=\"space-y-2\">\n <h4 className=\"font-medium flex items-center gap-2\">\n <Database size={16} className=\"text-primary\" />\n {t('botlit.retrievalProfiles.overview.knowledgeSourcesTitle', 'Knowledge Sources')}\n </h4>\n <ul className=\"text-sm text-text-secondary space-y-1\">\n <li>\n {t(\n 'botlit.retrievalProfiles.overview.knowledgeSourcesDescription',\n 'Bind multiple knowledge bases, configure priority and weights, and set per-KB retrieval limits.'\n )}\n </li>\n </ul>\n </div>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}