@burdenoff/microfe-botmanor 2026.1007.1 → 2026.1009.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/botlit/BotlitRoutes.js +58 -146
- package/dist/botlit/BotlitRoutes.js.map +1 -1
- package/dist/botlit/BotmanorRoot.js.map +1 -1
- package/dist/botlit/BotmanorRootInner.js +39 -67
- package/dist/botlit/BotmanorRootInner.js.map +1 -1
- package/dist/botlit/components/AssistantRuntimeSetupPanel.js +1 -1
- package/dist/botlit/components/AssistantRuntimeSetupPanel.js.map +1 -1
- package/dist/botlit/components/ModelRegistrationPanel.js +174 -0
- package/dist/botlit/components/ModelRegistrationPanel.js.map +1 -0
- package/dist/botlit/hooks/internal/workspaceGateway.js +1 -1
- package/dist/botlit/hooks/useAssistantRuntimeSetup.js +2 -2
- package/dist/botlit/hooks/useAssistantRuntimeSetup.js.map +1 -1
- package/dist/botlit/hooks/useBotWorkflow.js +56 -0
- package/dist/botlit/hooks/useBotWorkflow.js.map +1 -0
- package/dist/botlit/hooks/useLLMProviders.js +94 -50
- package/dist/botlit/hooks/useLLMProviders.js.map +1 -1
- package/dist/botlit/pages/AgentBuilderPage.js +206 -183
- package/dist/botlit/pages/AgentBuilderPage.js.map +1 -1
- package/dist/botlit/pages/BotWorkflowTab.js +33 -33
- package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
- package/dist/botlit/pages/KnowledgeBaseDetailPage.js +162 -145
- package/dist/botlit/pages/KnowledgeBaseDetailPage.js.map +1 -1
- package/dist/botlit/pages/SettingsPage.js +129 -66
- package/dist/botlit/pages/SettingsPage.js.map +1 -1
- package/dist/botlit/providers/BotlitProvider.js +30 -26
- package/dist/botlit/providers/BotlitProvider.js.map +1 -1
- package/dist/botlit/utils/embedding-models.js +36 -0
- package/dist/botlit/utils/embedding-models.js.map +1 -0
- package/dist/generated/wspace-operations.js +58 -36
- package/dist/generated/wspace-operations.js.map +1 -1
- package/package.json +1 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsPage.js","names":[],"sources":["../../../src/botlit/pages/SettingsPage.tsx"],"sourcesContent":["/**\n * Settings Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState } from 'react';\nimport { Key, Save, Brain, Link2, ExternalLink } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PagePurpose } 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, FormField } from '../components/Input';\nimport { Badge } from '../components/Badge';\nimport { useLLMProviders, useConfigureLLMProvider, useLLMModels } from '../hooks/useLLMProviders';\nimport { cn } from '../utils/cn';\nimport { toUnion } from '../utils/unions';\n\n/** Provider kinds the form offers, in the casing the service stores. */\nconst PROVIDER_TYPES = [\n 'OPENAI',\n 'ANTHROPIC',\n 'GOOGLE',\n 'AZURE_OPENAI',\n 'AWS_BEDROCK',\n 'CUSTOM',\n] as const;\n\n/** The `<option>` values are lowercase; the column is the uppercase enum. */\nfunction toProviderType(value: string): (typeof PROVIDER_TYPES)[number] {\n return toUnion(value.toUpperCase(), PROVIDER_TYPES, 'CUSTOM');\n}\n\nexport const SettingsPage: FC = () => {\n const t = useTr();\n const { data: providers, refetch: refetchProviders } = useLLMProviders();\n const { configureProvider, isConfiguring } = useConfigureLLMProvider();\n const { data: llmModels } = useLLMModels();\n const [apiKey, setApiKey] = useState('');\n const [selectedProviderType, setSelectedProviderType] = useState('openai');\n const [editingProviderId, setEditingProviderId] = useState<string | null>(null);\n // Credential method: 'integration' (preferred) or 'apikey' (legacy)\n const [credentialMethod, setCredentialMethod] = useState<'integration' | 'apikey'>('apikey');\n const [connectionId, setConnectionId] = useState('');\n\n return (\n <PageLayout\n title={t('botlit.settings.title', 'Settings')}\n description={t('botlit.settings.description', 'Configure your BotManor workspace settings')}\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Key size={18} />}>\n {t(\n 'botlit.settings.purpose',\n 'Workspace-wide settings for LLM Providers — connect at least one model provider (OpenAI, Anthropic, Google and others) so your agents have a brain to think with.'\n )}\n </PagePurpose>\n\n <Card treatment=\"glass\" glow>\n <CardHeader>\n <CardTitle>{t('botlit.settings.providers.title', 'LLM Providers')}</CardTitle>\n <CardDescription>\n {t(\n 'botlit.settings.providers.description',\n 'Configure API keys for AI model providers'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {providers?.map(\n (provider: {\n id: string;\n name: string;\n type: string;\n isActive: boolean;\n connectionId?: string | null;\n credentialsHash?: string | null;\n }) => (\n <div\n key={provider.id}\n className=\"flex items-center justify-between p-4 border border-border-subtle rounded-lg\"\n >\n <div className=\"flex items-center gap-4\">\n <div className=\"p-2 bg-action-primary-bg/10 rounded-lg\">\n {provider.connectionId ? (\n <Link2 className=\"h-5 w-5 text-primary\" />\n ) : (\n <Key className=\"h-5 w-5 text-primary\" />\n )}\n </div>\n <div>\n <p className=\"font-medium\">{provider.name}</p>\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.settings.providers.type', 'Type: {{type}}', {\n type: provider.type,\n })}\n </p>\n {provider.connectionId && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {t(\n 'botlit.settings.providers.connectedViaIntegrations',\n 'Connected via Integrations'\n )}\n </p>\n )}\n {!provider.connectionId && provider.credentialsHash && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {t('botlit.settings.providers.apiKeyStored', 'API key stored locally')}\n </p>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n {provider.connectionId && (\n <Badge variant=\"default\">\n {t('botlit.settings.providers.integrationBadge', 'Integration')}\n </Badge>\n )}\n <Badge variant={provider.isActive ? 'success' : 'secondary'}>\n {provider.isActive\n ? t('botlit.settings.providers.active', 'Active')\n : t('botlit.settings.providers.inactive', 'Inactive')}\n </Badge>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setEditingProviderId(provider.id);\n setSelectedProviderType(provider.type.toLowerCase());\n setApiKey('');\n setConnectionId(provider.connectionId || '');\n setCredentialMethod(provider.connectionId ? 'integration' : 'apikey');\n // Scroll to the Add Provider form\n document\n .getElementById('provider-form')\n ?.scrollIntoView({ behavior: 'smooth' });\n }}\n >\n {t('botlit.settings.actions.configure', 'Configure')}\n </Button>\n </div>\n </div>\n )\n )}\n </CardContent>\n </Card>\n\n {/* LLM Models List */}\n <Card>\n <CardHeader>\n <CardTitle>{t('botlit.settings.models.title', 'LLM Models')}</CardTitle>\n <CardDescription>\n {t('botlit.settings.models.description', 'Registered models across your providers')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {llmModels && llmModels.length > 0 ? (\n llmModels.map(\n (model: {\n id: string;\n name: string;\n modelId: string;\n providerId: string;\n isActive: boolean;\n contextWindow?: number;\n maxOutputTokens?: number;\n inputPricePerMToken?: number;\n outputPricePerMToken?: number;\n }) => {\n const providerName = providers?.find(\n (p: { id: string; name: string }) => p.id === model.providerId\n )?.name;\n return (\n <div\n key={model.id}\n className=\"flex items-center justify-between p-4 border border-border-subtle rounded-lg\"\n >\n <div className=\"flex items-center gap-4\">\n <div className=\"p-2 bg-purple-500/10 rounded-lg\">\n <Brain className=\"h-5 w-5 text-purple-500\" />\n </div>\n <div>\n <p className=\"font-medium\">{model.name}</p>\n <p className=\"text-sm text-text-secondary\">\n {model.modelId}\n {providerName && ` · ${providerName}`}\n </p>\n <div className=\"flex gap-3 mt-1 text-xs text-text-secondary\">\n {model.contextWindow != null && (\n <span>\n {t('botlit.settings.models.context', 'Context: {{value}}K', {\n value: (model.contextWindow / 1000).toFixed(0),\n })}\n </span>\n )}\n {model.maxOutputTokens != null && (\n <span>\n {t('botlit.settings.models.maxOut', 'Max out: {{value}}K', {\n value: (model.maxOutputTokens / 1000).toFixed(0),\n })}\n </span>\n )}\n {model.inputPricePerMToken != null && (\n <span>\n {t('botlit.settings.models.priceIn', '${{value}}/M in', {\n value: model.inputPricePerMToken,\n })}\n </span>\n )}\n {model.outputPricePerMToken != null && (\n <span>\n {t('botlit.settings.models.priceOut', '${{value}}/M out', {\n value: model.outputPricePerMToken,\n })}\n </span>\n )}\n </div>\n </div>\n </div>\n <Badge variant={model.isActive ? 'success' : 'secondary'}>\n {model.isActive\n ? t('botlit.settings.providers.active', 'Active')\n : t('botlit.settings.providers.inactive', 'Inactive')}\n </Badge>\n </div>\n );\n }\n )\n ) : (\n <p className=\"text-sm text-text-secondary text-center py-4\">\n {t('botlit.settings.models.empty', 'No models registered yet.')}\n </p>\n )}\n </CardContent>\n </Card>\n\n <Card id=\"provider-form\">\n <CardHeader>\n <CardTitle>\n {editingProviderId\n ? t('botlit.settings.form.updateTitle', 'Update Provider')\n : t('botlit.settings.form.addTitle', 'Add Provider')}\n </CardTitle>\n <CardDescription>\n {editingProviderId\n ? t(\n 'botlit.settings.form.updateDescription',\n 'Update credentials for this provider'\n )\n : t('botlit.settings.form.addDescription', 'Configure a new LLM provider')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <FormField label={t('botlit.settings.form.providerLabel', 'Provider')}>\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={selectedProviderType}\n onChange={(e) => setSelectedProviderType(e.target.value)}\n >\n <option value=\"openai\">OpenAI</option>\n <option value=\"anthropic\">Anthropic</option>\n <option value=\"google\">Google AI</option>\n <option value=\"azure_openai\">Azure OpenAI</option>\n <option value=\"aws_bedrock\">AWS Bedrock</option>\n <option value=\"custom\">Custom</option>\n </select>\n </FormField>\n\n {/* Credential method selector */}\n <FormField label={t('botlit.settings.form.credentialMethod', 'Credential Method')}>\n <div className=\"flex gap-3\">\n <label\n className={cn(\n 'flex items-center gap-2 px-4 py-3 border rounded-lg cursor-pointer transition-colors flex-1',\n credentialMethod === 'integration'\n ? 'border-primary bg-action-primary-bg/5'\n : 'border-border-subtle hover:border-primary/50'\n )}\n >\n <input\n type=\"radio\"\n name=\"credentialMethod\"\n value=\"integration\"\n checked={credentialMethod === 'integration'}\n onChange={() => setCredentialMethod('integration')}\n className=\"h-4 w-4\"\n />\n <div>\n <p className=\"font-medium text-sm\">\n {t('botlit.settings.form.integrationOption', 'Connect via Integrations')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'botlit.settings.form.integrationHint',\n 'Managed credentials (recommended)'\n )}\n </p>\n </div>\n </label>\n <label\n className={cn(\n 'flex items-center gap-2 px-4 py-3 border rounded-lg cursor-pointer transition-colors flex-1',\n credentialMethod === 'apikey'\n ? 'border-primary bg-action-primary-bg/5'\n : 'border-border-subtle hover:border-primary/50'\n )}\n >\n <input\n type=\"radio\"\n name=\"credentialMethod\"\n value=\"apikey\"\n checked={credentialMethod === 'apikey'}\n onChange={() => setCredentialMethod('apikey')}\n className=\"h-4 w-4\"\n />\n <div>\n <p className=\"font-medium text-sm\">\n {t('botlit.settings.form.apiKeyOption', 'Enter API Key')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('botlit.settings.form.apiKeyHint', 'Paste key directly (legacy)')}\n </p>\n </div>\n </label>\n </div>\n </FormField>\n\n {/* Integration connection method */}\n {credentialMethod === 'integration' && (\n <div className=\"space-y-3\">\n <div className=\"p-4 bg-bg-sunken/50 border border-border-subtle rounded-lg\">\n <div className=\"flex items-start gap-3\">\n <Link2 className=\"h-5 w-5 text-primary mt-0.5 flex-shrink-0\" />\n <div className=\"space-y-2 flex-1\">\n <p className=\"text-sm font-medium\">\n {t('botlit.settings.form.integrationTitle', 'Integration Connection')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'botlit.settings.form.integrationDescription',\n 'Create a connection in the Integrations module, then paste the Connection ID here. This stores your API key securely in the Integrations vault.'\n )}\n </p>\n <div className=\"flex gap-2 mt-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n window.open('/integrations/connections', '_blank');\n }}\n >\n <ExternalLink size={14} className=\"mr-1.5\" />\n {t('botlit.settings.form.openIntegrations', 'Open Integrations')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n <FormField\n label={t('botlit.settings.form.connectionIdPlaceholder', 'Connection ID')}\n >\n <Input\n placeholder={t(\n 'botlit.settings.form.connectionIdPlaceholder',\n 'Paste connection ID from Integrations...'\n )}\n value={connectionId}\n onChange={(e) => setConnectionId(e.target.value)}\n />\n </FormField>\n </div>\n )}\n\n {/* Legacy API key method */}\n {credentialMethod === 'apikey' && (\n <FormField label={t('botlit.settings.form.apiKeyLabel', 'API Key')}>\n <Input\n type=\"password\"\n placeholder={t('botlit.settings.form.apiKeyPlaceholder', 'sk-...')}\n value={apiKey}\n onChange={(e) => setApiKey(e.target.value)}\n />\n </FormField>\n )}\n\n <div className=\"flex gap-2\">\n <Button\n leftIcon={<Save size={16} />}\n isLoading={isConfiguring}\n disabled={credentialMethod === 'apikey' ? !apiKey : !connectionId}\n onClick={async () => {\n try {\n const providerName =\n selectedProviderType.charAt(0).toUpperCase() + selectedProviderType.slice(1);\n\n // `useConfigureLLMProvider` projects each payload\n // onto the fields its input type declares and adds\n // the workspace id, so only real fields go here.\n const credentials =\n credentialMethod === 'integration'\n ? undefined\n : apiKey\n ? { apiKey }\n : undefined;\n const linkedConnectionId =\n credentialMethod === 'integration' ? connectionId : undefined;\n\n if (editingProviderId) {\n await configureProvider(\n {\n name: providerName,\n type: toProviderType(selectedProviderType),\n connectionId: linkedConnectionId,\n credentials,\n },\n editingProviderId\n );\n } else {\n await configureProvider({\n name: providerName,\n type: toProviderType(selectedProviderType),\n connectionId: linkedConnectionId,\n credentials,\n });\n }\n\n setApiKey('');\n setConnectionId('');\n setEditingProviderId(null);\n await refetchProviders();\n const providerLabel =\n selectedProviderType.charAt(0).toUpperCase() + selectedProviderType.slice(1);\n toast.success(\n editingProviderId\n ? t(\n 'botlit.settings.form.updateSuccess',\n '{{provider}} provider updated successfully',\n { provider: providerLabel }\n )\n : t(\n 'botlit.settings.form.addSuccess',\n '{{provider}} provider added successfully',\n { provider: providerLabel }\n )\n );\n } catch (err: unknown) {\n const message =\n err instanceof Error\n ? err.message\n : t('botlit.settings.form.saveError', 'Failed to save provider');\n toast.error(message);\n }\n }}\n >\n {editingProviderId\n ? t('botlit.settings.form.updateProvider', 'Update Provider')\n : t('botlit.settings.form.saveProvider', 'Save Provider')}\n </Button>\n {editingProviderId && (\n <Button\n variant=\"outline\"\n onClick={() => {\n setEditingProviderId(null);\n setApiKey('');\n setConnectionId('');\n setCredentialMethod('apikey');\n setSelectedProviderType('openai');\n }}\n >\n {t('botlit.settings.form.cancel', 'Cancel')}\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SettingsPage.js","names":[],"sources":["../../../src/botlit/pages/SettingsPage.tsx"],"sourcesContent":["/**\n * Settings Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState } from 'react';\nimport { Key, Save, Brain, Link2, ExternalLink } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PagePurpose } 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, FormField } from '../components/Input';\nimport { Badge } from '../components/Badge';\nimport { ModelRegistrationPanel } from '../components/ModelRegistrationPanel';\nimport { useLLMProviders, useConfigureLLMProvider, useLLMModels } from '../hooks/useLLMProviders';\nimport { cn } from '../utils/cn';\nimport { toUnion } from '../utils/unions';\n\n/** Provider kinds the form offers, in the casing the service stores. */\nconst PROVIDER_TYPES = [\n 'OPENAI',\n 'ANTHROPIC',\n 'GOOGLE',\n 'AZURE_OPENAI',\n 'AWS_BEDROCK',\n 'CUSTOM',\n] as const;\n\n/** The `<option>` values are lowercase; the column is the uppercase enum. */\nfunction toProviderType(value: string): (typeof PROVIDER_TYPES)[number] {\n return toUnion(value.toUpperCase(), PROVIDER_TYPES, 'CUSTOM');\n}\n\nexport const SettingsPage: FC = () => {\n const t = useTr();\n const {\n data: providers,\n refetch: refetchProviders,\n loading: providersLoading,\n error: providersError,\n } = useLLMProviders();\n const { configureProvider, isConfiguring } = useConfigureLLMProvider();\n const {\n data: llmModels,\n refetch: refetchModels,\n loading: modelsLoading,\n error: modelsError,\n } = useLLMModels();\n const catalogLoading = providersLoading || modelsLoading;\n const catalogError = providersError || modelsError;\n const [apiKey, setApiKey] = useState('');\n const [providerEnabled, setProviderEnabled] = useState(true);\n const [selectedProviderType, setSelectedProviderType] = useState('openai');\n const [editingProviderId, setEditingProviderId] = useState<string | null>(null);\n // Credential method: 'integration' (preferred) or 'apikey' (legacy)\n const [credentialMethod, setCredentialMethod] = useState<'integration' | 'apikey' | 'iam'>(\n 'apikey'\n );\n const [connectionId, setConnectionId] = useState('');\n const [region, setRegion] = useState('ap-south-1');\n const isBedrock = selectedProviderType === 'aws_bedrock';\n const usesIam = isBedrock && credentialMethod === 'iam';\n const regionValid = /^[a-z]{2}(?:-[a-z]+)+-\\d+$/.test(region.trim());\n\n return (\n <PageLayout\n title={t('botlit.settings.title', 'Settings')}\n description={t('botlit.settings.description', 'Configure your BotManor workspace settings')}\n >\n <div className=\"space-y-6\">\n {catalogLoading && <p role=\"status\">Loading providers and models…</p>}\n {catalogError && (\n <div role=\"alert\">\n <p>Could not load providers and models. Try loading the catalog again.</p>\n <Button\n variant=\"secondary\"\n onClick={() => {\n void refetchProviders();\n void refetchModels();\n }}\n >\n Retry model catalog\n </Button>\n </div>\n )}\n <PagePurpose icon={<Key size={18} />}>\n {t(\n 'botlit.settings.purpose',\n 'Workspace-wide settings for LLM Providers — connect at least one model provider (OpenAI, Anthropic, Google and others) so your agents have a brain to think with.'\n )}\n </PagePurpose>\n\n <Card treatment=\"glass\" glow>\n <CardHeader>\n <CardTitle>{t('botlit.settings.providers.title', 'LLM Providers')}</CardTitle>\n <CardDescription>\n {t(\n 'botlit.settings.providers.description',\n 'Configure API keys for AI model providers'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {providers?.map(\n (provider: {\n id: string;\n name: string;\n type: string;\n isActive: boolean;\n connectionId?: string | null;\n credentialsHash?: string | null;\n metadata?: Record<string, unknown> | null;\n }) => (\n <div\n key={provider.id}\n className=\"flex items-center justify-between p-4 border border-border-subtle rounded-lg\"\n >\n <div className=\"flex items-center gap-4\">\n <div className=\"p-2 bg-action-primary-bg/10 rounded-lg\">\n {provider.connectionId ? (\n <Link2 className=\"h-5 w-5 text-primary\" />\n ) : (\n <Key className=\"h-5 w-5 text-primary\" />\n )}\n </div>\n <div>\n <p className=\"font-medium\">{provider.name}</p>\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.settings.providers.type', 'Type: {{type}}', {\n type: provider.type,\n })}\n </p>\n {provider.connectionId && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {t(\n 'botlit.settings.providers.connectedViaIntegrations',\n 'Connected via Integrations'\n )}\n </p>\n )}\n {!provider.connectionId && provider.credentialsHash && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {t('botlit.settings.providers.apiKeyStored', 'API key stored locally')}\n </p>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n {provider.connectionId && (\n <Badge variant=\"default\">\n {t('botlit.settings.providers.integrationBadge', 'Integration')}\n </Badge>\n )}\n <Badge variant={provider.isActive ? 'success' : 'secondary'}>\n {provider.isActive\n ? t('botlit.settings.providers.active', 'Active')\n : t('botlit.settings.providers.inactive', 'Inactive')}\n </Badge>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setEditingProviderId(provider.id);\n setProviderEnabled(provider.isActive);\n setSelectedProviderType(provider.type.toLowerCase());\n setApiKey('');\n setConnectionId(provider.connectionId || '');\n setCredentialMethod(\n provider.type === 'AWS_BEDROCK' &&\n provider.metadata?.awsAuthentication === 'iam'\n ? 'iam'\n : provider.connectionId\n ? 'integration'\n : 'apikey'\n );\n setRegion(\n typeof provider.metadata?.region === 'string'\n ? provider.metadata.region\n : 'ap-south-1'\n );\n // Scroll to the Add Provider form\n document\n .getElementById('provider-form')\n ?.scrollIntoView({ behavior: 'smooth' });\n }}\n >\n {t('botlit.settings.actions.configure', 'Configure')}\n </Button>\n </div>\n </div>\n )\n )}\n </CardContent>\n </Card>\n\n {/* LLM Models List */}\n <Card>\n <CardHeader>\n <CardTitle>{t('botlit.settings.models.title', 'LLM Models')}</CardTitle>\n <CardDescription>\n {t('botlit.settings.models.description', 'Registered models across your providers')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {llmModels && llmModels.length > 0 ? (\n llmModels.map(\n (model: {\n id: string;\n name: string;\n modelId: string;\n providerId: string;\n isActive: boolean;\n contextWindow?: number;\n maxOutputTokens?: number;\n inputPricePerMToken?: number;\n outputPricePerMToken?: number;\n }) => {\n const providerName = providers?.find(\n (p: { id: string; name: string }) => p.id === model.providerId\n )?.name;\n return (\n <div\n key={model.id}\n className=\"flex items-center justify-between p-4 border border-border-subtle rounded-lg\"\n >\n <div className=\"flex items-center gap-4\">\n <div className=\"p-2 bg-purple-500/10 rounded-lg\">\n <Brain className=\"h-5 w-5 text-purple-500\" />\n </div>\n <div>\n <p className=\"font-medium\">{model.name}</p>\n <p className=\"text-sm text-text-secondary\">\n {model.modelId}\n {providerName && ` · ${providerName}`}\n </p>\n <div className=\"flex gap-3 mt-1 text-xs text-text-secondary\">\n {model.contextWindow != null && (\n <span>\n {t('botlit.settings.models.context', 'Context: {{value}}K', {\n value: (model.contextWindow / 1000).toFixed(0),\n })}\n </span>\n )}\n {model.maxOutputTokens != null && (\n <span>\n {t('botlit.settings.models.maxOut', 'Max out: {{value}}K', {\n value: (model.maxOutputTokens / 1000).toFixed(0),\n })}\n </span>\n )}\n {model.inputPricePerMToken != null && (\n <span>\n {t('botlit.settings.models.priceIn', '${{value}}/M in', {\n value: model.inputPricePerMToken,\n })}\n </span>\n )}\n {model.outputPricePerMToken != null && (\n <span>\n {t('botlit.settings.models.priceOut', '${{value}}/M out', {\n value: model.outputPricePerMToken,\n })}\n </span>\n )}\n </div>\n </div>\n </div>\n <Badge variant={model.isActive ? 'success' : 'secondary'}>\n {model.isActive\n ? t('botlit.settings.providers.active', 'Active')\n : t('botlit.settings.providers.inactive', 'Inactive')}\n </Badge>\n </div>\n );\n }\n )\n ) : !catalogLoading && !catalogError ? (\n <p className=\"text-sm text-text-secondary text-center py-4\">\n {t('botlit.settings.models.empty', 'No models registered yet.')}\n </p>\n ) : null}\n </CardContent>\n </Card>\n\n {!catalogLoading && !catalogError && (\n <ModelRegistrationPanel\n providers={providers ?? []}\n onCreated={() => void refetchModels()}\n />\n )}\n\n <Card id=\"provider-form\">\n <CardHeader>\n <CardTitle>\n {editingProviderId\n ? t('botlit.settings.form.updateTitle', 'Update Provider')\n : t('botlit.settings.form.addTitle', 'Add Provider')}\n </CardTitle>\n <CardDescription>\n {editingProviderId\n ? t(\n 'botlit.settings.form.updateDescription',\n 'Update credentials for this provider'\n )\n : t('botlit.settings.form.addDescription', 'Configure a new LLM provider')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <FormField label={t('botlit.settings.form.providerLabel', 'Provider')}>\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={selectedProviderType}\n disabled={Boolean(editingProviderId)}\n onChange={(e) => {\n setSelectedProviderType(e.target.value);\n setCredentialMethod(e.target.value === 'aws_bedrock' ? 'iam' : 'apikey');\n setApiKey('');\n setConnectionId('');\n }}\n >\n <option value=\"openai\">OpenAI</option>\n <option value=\"anthropic\">Anthropic</option>\n <option value=\"google\">Google AI</option>\n <option value=\"azure_openai\">Azure OpenAI</option>\n <option value=\"aws_bedrock\">AWS Bedrock</option>\n <option value=\"custom\">Custom</option>\n </select>\n </FormField>\n\n {editingProviderId && (\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={providerEnabled}\n onChange={(event) => setProviderEnabled(event.target.checked)}\n />\n Provider enabled\n </label>\n )}\n {isBedrock && (\n <FormField label=\"AWS region\">\n <Input\n aria-label=\"AWS region\"\n value={region}\n onChange={(event) => setRegion(event.target.value)}\n />\n <p className=\"text-sm text-text-secondary\">\n Managed AWS IAM requires model access enabled for this workspace by your platform\n administrator.\n </p>\n </FormField>\n )}\n\n {/* Credential method selector */}\n <FormField label={t('botlit.settings.form.credentialMethod', 'Credential Method')}>\n <div className=\"flex flex-wrap gap-3\">\n {isBedrock && (\n <label\n className={cn(\n 'flex items-center gap-2 px-4 py-3 border rounded-lg cursor-pointer flex-1',\n usesIam\n ? 'border-primary bg-action-primary-bg/5'\n : 'border-border-subtle hover:border-primary/50'\n )}\n >\n <input\n type=\"radio\"\n name=\"credentialMethod\"\n value=\"iam\"\n checked={usesIam}\n onChange={() => {\n setCredentialMethod('iam');\n setApiKey('');\n setConnectionId('');\n }}\n />\n Managed AWS IAM\n </label>\n )}\n <label\n className={cn(\n 'flex items-center gap-2 px-4 py-3 border rounded-lg cursor-pointer transition-colors flex-1',\n credentialMethod === 'integration'\n ? 'border-primary bg-action-primary-bg/5'\n : 'border-border-subtle hover:border-primary/50'\n )}\n >\n <input\n type=\"radio\"\n name=\"credentialMethod\"\n value=\"integration\"\n checked={credentialMethod === 'integration'}\n onChange={() => setCredentialMethod('integration')}\n className=\"h-4 w-4\"\n />\n <div>\n <p className=\"font-medium text-sm\">\n {t('botlit.settings.form.integrationOption', 'Connect via Integrations')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'botlit.settings.form.integrationHint',\n 'Managed credentials (recommended)'\n )}\n </p>\n </div>\n </label>\n <label\n className={cn(\n 'flex items-center gap-2 px-4 py-3 border rounded-lg cursor-pointer transition-colors flex-1',\n credentialMethod === 'apikey'\n ? 'border-primary bg-action-primary-bg/5'\n : 'border-border-subtle hover:border-primary/50'\n )}\n >\n <input\n type=\"radio\"\n name=\"credentialMethod\"\n value=\"apikey\"\n checked={credentialMethod === 'apikey'}\n onChange={() => setCredentialMethod('apikey')}\n className=\"h-4 w-4\"\n />\n <div>\n <p className=\"font-medium text-sm\">\n {t('botlit.settings.form.apiKeyOption', 'Enter API Key')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('botlit.settings.form.apiKeyHint', 'Paste key directly (legacy)')}\n </p>\n </div>\n </label>\n </div>\n </FormField>\n\n {/* Integration connection method */}\n {credentialMethod === 'integration' && (\n <div className=\"space-y-3\">\n <div className=\"p-4 bg-bg-sunken/50 border border-border-subtle rounded-lg\">\n <div className=\"flex items-start gap-3\">\n <Link2 className=\"h-5 w-5 text-primary mt-0.5 flex-shrink-0\" />\n <div className=\"space-y-2 flex-1\">\n <p className=\"text-sm font-medium\">\n {t('botlit.settings.form.integrationTitle', 'Integration Connection')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'botlit.settings.form.integrationDescription',\n 'Create a connection in the Integrations module, then paste the Connection ID here. This stores your API key securely in the Integrations vault.'\n )}\n </p>\n <div className=\"flex gap-2 mt-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n window.open('/integrations/connections', '_blank');\n }}\n >\n <ExternalLink size={14} className=\"mr-1.5\" />\n {t('botlit.settings.form.openIntegrations', 'Open Integrations')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n <FormField\n label={t('botlit.settings.form.connectionIdPlaceholder', 'Connection ID')}\n >\n <Input\n placeholder={t(\n 'botlit.settings.form.connectionIdPlaceholder',\n 'Paste connection ID from Integrations...'\n )}\n value={connectionId}\n onChange={(e) => setConnectionId(e.target.value)}\n />\n </FormField>\n </div>\n )}\n\n {/* Legacy API key method */}\n {credentialMethod === 'apikey' && (\n <FormField label={t('botlit.settings.form.apiKeyLabel', 'API Key')}>\n <Input\n type=\"password\"\n placeholder={t('botlit.settings.form.apiKeyPlaceholder', 'sk-...')}\n value={apiKey}\n onChange={(e) => setApiKey(e.target.value)}\n />\n </FormField>\n )}\n\n <div className=\"flex gap-2\">\n <Button\n leftIcon={<Save size={16} />}\n isLoading={isConfiguring}\n disabled={\n (isBedrock && !regionValid) ||\n (usesIam\n ? false\n : credentialMethod === 'apikey'\n ? !apiKey.trim()\n : !connectionId.trim())\n }\n onClick={async () => {\n try {\n const providerName =\n selectedProviderType.charAt(0).toUpperCase() + selectedProviderType.slice(1);\n\n // `useConfigureLLMProvider` projects each payload\n // onto the fields its input type declares and adds\n // the workspace id, so only real fields go here.\n const credentials =\n credentialMethod !== 'apikey' ? undefined : apiKey ? { apiKey } : undefined;\n const linkedConnectionId =\n credentialMethod === 'integration' ? connectionId : null;\n const previousMetadata =\n providers?.find((provider) => provider.id === editingProviderId)?.metadata ??\n {};\n const metadata = isBedrock\n ? {\n ...previousMetadata,\n region: region.trim(),\n awsAuthentication: usesIam ? 'iam' : 'credentials',\n }\n : previousMetadata;\n\n if (editingProviderId) {\n await configureProvider(\n {\n name: providerName,\n type: toProviderType(selectedProviderType),\n connectionId: linkedConnectionId,\n credentials,\n metadata,\n isActive: providerEnabled,\n },\n editingProviderId\n );\n } else {\n await configureProvider({\n name: providerName,\n type: toProviderType(selectedProviderType),\n connectionId: linkedConnectionId,\n credentials,\n metadata,\n });\n }\n\n setApiKey('');\n setConnectionId('');\n setEditingProviderId(null);\n await refetchProviders();\n const providerLabel =\n selectedProviderType.charAt(0).toUpperCase() + selectedProviderType.slice(1);\n toast.success(\n editingProviderId\n ? t(\n 'botlit.settings.form.updateSuccess',\n '{{provider}} provider updated successfully',\n { provider: providerLabel }\n )\n : t(\n 'botlit.settings.form.addSuccess',\n '{{provider}} provider added successfully',\n { provider: providerLabel }\n )\n );\n } catch (err: unknown) {\n const message =\n err instanceof Error\n ? err.message\n : t('botlit.settings.form.saveError', 'Failed to save provider');\n toast.error(message);\n }\n }}\n >\n {editingProviderId\n ? t('botlit.settings.form.updateProvider', 'Update Provider')\n : t('botlit.settings.form.saveProvider', 'Save Provider')}\n </Button>\n {editingProviderId && (\n <Button\n variant=\"outline\"\n onClick={() => {\n setEditingProviderId(null);\n setApiKey('');\n setConnectionId('');\n setCredentialMethod('apikey');\n setSelectedProviderType('openai');\n }}\n >\n {t('botlit.settings.form.cancel', 'Cancel')}\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -9,24 +9,25 @@ function l() {
|
|
|
9
9
|
if (!e) throw Error("useBotlit must be used within a BotlitProvider");
|
|
10
10
|
return e;
|
|
11
11
|
}
|
|
12
|
-
var u = ({ children: t, basePath: r, currentUser: o, tenantId: l, workspaceId: u, apiGatewayUrl: d, authToken: f,
|
|
13
|
-
let
|
|
14
|
-
|
|
15
|
-
}, [
|
|
16
|
-
basePath:
|
|
12
|
+
var u = ({ children: t, basePath: r, currentUser: o, tenantId: l, workspaceId: u, apiGatewayUrl: d, authToken: f, productId: p, onBotSelect: m, onAgentSelect: h }) => {
|
|
13
|
+
let g = s(), _ = r || "/", v = n((t) => e(_, t), [_]), y = n((t) => {
|
|
14
|
+
g(e(_, t));
|
|
15
|
+
}, [_, g]), b = i(() => ({
|
|
16
|
+
basePath: _,
|
|
17
17
|
navigate: void 0,
|
|
18
18
|
currentUser: o,
|
|
19
19
|
tenantId: l,
|
|
20
20
|
workspaceId: u,
|
|
21
21
|
apiGatewayUrl: d,
|
|
22
22
|
authToken: f,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
productId: p,
|
|
24
|
+
onBotSelect: m,
|
|
25
|
+
onAgentSelect: h,
|
|
25
26
|
isStandalone: !0,
|
|
26
|
-
navigateTo:
|
|
27
|
-
getPath:
|
|
27
|
+
navigateTo: y,
|
|
28
|
+
getPath: v
|
|
28
29
|
}), [
|
|
29
|
-
|
|
30
|
+
_,
|
|
30
31
|
o,
|
|
31
32
|
l,
|
|
32
33
|
u,
|
|
@@ -34,31 +35,33 @@ var u = ({ children: t, basePath: r, currentUser: o, tenantId: l, workspaceId: u
|
|
|
34
35
|
f,
|
|
35
36
|
p,
|
|
36
37
|
m,
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
h,
|
|
39
|
+
y,
|
|
40
|
+
v
|
|
39
41
|
]);
|
|
40
42
|
return /* @__PURE__ */ a(c.Provider, {
|
|
41
|
-
value:
|
|
43
|
+
value: b,
|
|
42
44
|
children: t
|
|
43
45
|
});
|
|
44
|
-
}, d = ({ children: t, basePath: r, navigate: o, currentUser: s, tenantId: l, workspaceId: u, apiGatewayUrl: d, authToken: f,
|
|
45
|
-
let
|
|
46
|
-
o(e(
|
|
47
|
-
}, [
|
|
48
|
-
basePath:
|
|
46
|
+
}, d = ({ children: t, basePath: r, navigate: o, currentUser: s, tenantId: l, workspaceId: u, apiGatewayUrl: d, authToken: f, productId: p, onBotSelect: m, onAgentSelect: h }) => {
|
|
47
|
+
let g = r || "/", _ = n((t) => e(g, t), [g]), v = n((t) => {
|
|
48
|
+
o(e(g, t));
|
|
49
|
+
}, [g, o]), y = i(() => ({
|
|
50
|
+
basePath: g,
|
|
49
51
|
navigate: o,
|
|
50
52
|
currentUser: s,
|
|
51
53
|
tenantId: l,
|
|
52
54
|
workspaceId: u,
|
|
53
55
|
apiGatewayUrl: d,
|
|
54
56
|
authToken: f,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
productId: p,
|
|
58
|
+
onBotSelect: m,
|
|
59
|
+
onAgentSelect: h,
|
|
57
60
|
isStandalone: !1,
|
|
58
|
-
navigateTo:
|
|
59
|
-
getPath:
|
|
61
|
+
navigateTo: v,
|
|
62
|
+
getPath: _
|
|
60
63
|
}), [
|
|
61
|
-
|
|
64
|
+
g,
|
|
62
65
|
o,
|
|
63
66
|
s,
|
|
64
67
|
l,
|
|
@@ -67,11 +70,12 @@ var u = ({ children: t, basePath: r, currentUser: o, tenantId: l, workspaceId: u
|
|
|
67
70
|
f,
|
|
68
71
|
p,
|
|
69
72
|
m,
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
h,
|
|
74
|
+
v,
|
|
75
|
+
_
|
|
72
76
|
]);
|
|
73
77
|
return /* @__PURE__ */ a(c.Provider, {
|
|
74
|
-
value:
|
|
78
|
+
value: y,
|
|
75
79
|
children: t
|
|
76
80
|
});
|
|
77
81
|
}, f = (e) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BotlitProvider.js","names":[],"sources":["../../../src/botlit/providers/BotlitProvider.tsx"],"sourcesContent":["/**\n * BotManor Context Provider\n * @module botlit/providers\n */\n\nimport type { FC, PropsWithChildren } from 'react';\nimport { createContext, useContext, useMemo, useCallback } from 'react';\nimport { MemoryRouter, useNavigate as useRouterNavigate } from 'react-router';\nimport type { BotmanorRootProps } from '../types';\nimport { joinPath } from '../utils/navigation';\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface BotlitContextValue extends Omit<\n BotmanorRootProps,\n 'registerNavItems' | 'registerFooterItems' | 'navigate'\n> {\n isStandalone: boolean;\n /** Shell's navigate function (only available in integrated mode) */\n navigate?: (path: string) => void;\n /** Navigate to a path relative to basePath */\n navigateTo: (relativePath: string) => void;\n /** Get the full path for a relative path */\n getPath: (relativePath: string) => string;\n}\n\nconst BotlitContext = createContext<BotlitContextValue | null>(null);\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useBotlit(): BotlitContextValue {\n const context = useContext(BotlitContext);\n if (!context) {\n throw new Error('useBotlit must be used within a BotlitProvider');\n }\n return context;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\ntype ProviderProps = Omit<BotmanorRootProps, 'registerNavItems' | 'registerFooterItems'> & {\n isStandalone: boolean;\n};\n\n/** Provider for standalone mode (has access to MemoryRouter) */\nconst StandaloneProviderInner: FC<PropsWithChildren<ProviderProps>> = ({\n children,\n basePath,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n onBotSelect,\n onAgentSelect,\n}) => {\n // Always call hooks unconditionally in this component\n const routerNavigate = useRouterNavigate();\n const effectiveBasePath = basePath || '/';\n\n const getPath = useCallback(\n (relativePath: string) => joinPath(effectiveBasePath, relativePath),\n [effectiveBasePath]\n );\n\n const navigateTo = useCallback(\n (relativePath: string) => {\n const fullPath = joinPath(effectiveBasePath, relativePath);\n routerNavigate(fullPath);\n },\n [effectiveBasePath, routerNavigate]\n );\n\n const contextValue = useMemo<BotlitContextValue>(\n () => ({\n basePath: effectiveBasePath,\n navigate: undefined,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n onBotSelect,\n onAgentSelect,\n isStandalone: true,\n navigateTo,\n getPath,\n }),\n [\n effectiveBasePath,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n onBotSelect,\n onAgentSelect,\n navigateTo,\n getPath,\n ]\n );\n\n return <BotlitContext.Provider value={contextValue}>{children}</BotlitContext.Provider>;\n};\n\n/** Provider for integrated mode (shell provides navigate) */\nconst IntegratedProviderInner: FC<\n PropsWithChildren<ProviderProps & { navigate: (path: string) => void }>\n> = ({\n children,\n basePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n onBotSelect,\n onAgentSelect,\n}) => {\n const effectiveBasePath = basePath || '/';\n\n const getPath = useCallback(\n (relativePath: string) => joinPath(effectiveBasePath, relativePath),\n [effectiveBasePath]\n );\n\n const navigateTo = useCallback(\n (relativePath: string) => {\n const fullPath = joinPath(effectiveBasePath, relativePath);\n navigate(fullPath);\n },\n [effectiveBasePath, navigate]\n );\n\n const contextValue = useMemo<BotlitContextValue>(\n () => ({\n basePath: effectiveBasePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n onBotSelect,\n onAgentSelect,\n isStandalone: false,\n navigateTo,\n getPath,\n }),\n [\n effectiveBasePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n onBotSelect,\n onAgentSelect,\n navigateTo,\n getPath,\n ]\n );\n\n return <BotlitContext.Provider value={contextValue}>{children}</BotlitContext.Provider>;\n};\n\nexport const BotlitProvider: FC<PropsWithChildren<BotmanorRootProps>> = (props) => {\n const { children, navigate } = props;\n // Standalone mode: no navigate function provided (MFE manages its own router)\n // Integrated mode: navigate function provided by shell (shell provides router)\n const isStandalone = !navigate;\n\n // Standalone mode: wrap in MemoryRouter\n if (isStandalone) {\n return (\n <MemoryRouter>\n <StandaloneProviderInner {...props} isStandalone={true}>\n {children}\n </StandaloneProviderInner>\n </MemoryRouter>\n );\n }\n\n // Integrated mode: shell provides router\n return (\n <IntegratedProviderInner {...props} navigate={navigate} isStandalone={false}>\n {children}\n </IntegratedProviderInner>\n );\n};\n"],"mappings":";;;;;AA4BA,IAAM,IAAgB,EAAyC,KAAK;AAMpE,SAAgB,IAAgC;CAC9C,IAAM,IAAU,EAAW,EAAc;AACzC,KAAI,CAAC,EACH,OAAU,MAAM,iDAAiD;AAEnE,QAAO;;AAYT,IAAM,KAAiE,EACrE,aACA,aACA,gBACA,aACA,gBACA,kBACA,cACA,gBACA,uBACI;CAEJ,IAAM,IAAiB,GAAmB,EACpC,IAAoB,KAAY,KAEhC,IAAU,GACb,MAAyB,EAAS,GAAmB,EAAa,EACnE,CAAC,EAAkB,CACpB,EAEK,IAAa,GAChB,MAAyB;AAExB,IADiB,EAAS,GAAmB,EAAa,CAClC;IAE1B,CAAC,GAAmB,EAAe,CACpC,EAEK,IAAe,SACZ;EACL,UAAU;EACV,UAAU,KAAA;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QAAO,kBAAC,EAAc,UAAf;EAAwB,OAAO;EAAe;EAAkC,CAAA;GAInF,KAED,EACH,aACA,aACA,aACA,gBACA,aACA,gBACA,kBACA,cACA,gBACA,uBACI;CACJ,IAAM,IAAoB,KAAY,KAEhC,IAAU,GACb,MAAyB,EAAS,GAAmB,EAAa,EACnE,CAAC,EAAkB,CACpB,EAEK,IAAa,GAChB,MAAyB;AAExB,IADiB,EAAS,GAAmB,EAAa,CACxC;IAEpB,CAAC,GAAmB,EAAS,CAC9B,EAEK,IAAe,SACZ;EACL,UAAU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QAAO,kBAAC,EAAc,UAAf;EAAwB,OAAO;EAAe;EAAkC,CAAA;GAG5E,KAA4D,MAAU;CACjF,IAAM,EAAE,aAAU,gBAAa;AAiB/B,QAdsB,IAepB,kBAAC,GAAD;EAAyB,GAAI;EAAiB;EAAU,cAAc;EACnE;EACuB,CAAA,GAZxB,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EAAyB,GAAI;EAAO,cAAc;EAC/C;EACuB,CAAA,EACb,CAAA"}
|
|
1
|
+
{"version":3,"file":"BotlitProvider.js","names":[],"sources":["../../../src/botlit/providers/BotlitProvider.tsx"],"sourcesContent":["/**\n * BotManor Context Provider\n * @module botlit/providers\n */\n\nimport type { FC, PropsWithChildren } from 'react';\nimport { createContext, useContext, useMemo, useCallback } from 'react';\nimport { MemoryRouter, useNavigate as useRouterNavigate } from 'react-router';\nimport type { BotmanorRootProps } from '../types';\nimport { joinPath } from '../utils/navigation';\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface BotlitContextValue extends Omit<\n BotmanorRootProps,\n 'registerNavItems' | 'registerFooterItems' | 'navigate'\n> {\n isStandalone: boolean;\n /** Shell's navigate function (only available in integrated mode) */\n navigate?: (path: string) => void;\n /** Navigate to a path relative to basePath */\n navigateTo: (relativePath: string) => void;\n /** Get the full path for a relative path */\n getPath: (relativePath: string) => string;\n}\n\nconst BotlitContext = createContext<BotlitContextValue | null>(null);\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useBotlit(): BotlitContextValue {\n const context = useContext(BotlitContext);\n if (!context) {\n throw new Error('useBotlit must be used within a BotlitProvider');\n }\n return context;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\ntype ProviderProps = Omit<BotmanorRootProps, 'registerNavItems' | 'registerFooterItems'> & {\n isStandalone: boolean;\n};\n\n/** Provider for standalone mode (has access to MemoryRouter) */\nconst StandaloneProviderInner: FC<PropsWithChildren<ProviderProps>> = ({\n children,\n basePath,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n productId,\n onBotSelect,\n onAgentSelect,\n}) => {\n // Always call hooks unconditionally in this component\n const routerNavigate = useRouterNavigate();\n const effectiveBasePath = basePath || '/';\n\n const getPath = useCallback(\n (relativePath: string) => joinPath(effectiveBasePath, relativePath),\n [effectiveBasePath]\n );\n\n const navigateTo = useCallback(\n (relativePath: string) => {\n const fullPath = joinPath(effectiveBasePath, relativePath);\n routerNavigate(fullPath);\n },\n [effectiveBasePath, routerNavigate]\n );\n\n const contextValue = useMemo<BotlitContextValue>(\n () => ({\n basePath: effectiveBasePath,\n navigate: undefined,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n productId,\n onBotSelect,\n onAgentSelect,\n isStandalone: true,\n navigateTo,\n getPath,\n }),\n [\n effectiveBasePath,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n productId,\n onBotSelect,\n onAgentSelect,\n navigateTo,\n getPath,\n ]\n );\n\n return <BotlitContext.Provider value={contextValue}>{children}</BotlitContext.Provider>;\n};\n\n/** Provider for integrated mode (shell provides navigate) */\nconst IntegratedProviderInner: FC<\n PropsWithChildren<ProviderProps & { navigate: (path: string) => void }>\n> = ({\n children,\n basePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n productId,\n onBotSelect,\n onAgentSelect,\n}) => {\n const effectiveBasePath = basePath || '/';\n\n const getPath = useCallback(\n (relativePath: string) => joinPath(effectiveBasePath, relativePath),\n [effectiveBasePath]\n );\n\n const navigateTo = useCallback(\n (relativePath: string) => {\n const fullPath = joinPath(effectiveBasePath, relativePath);\n navigate(fullPath);\n },\n [effectiveBasePath, navigate]\n );\n\n const contextValue = useMemo<BotlitContextValue>(\n () => ({\n basePath: effectiveBasePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n productId,\n onBotSelect,\n onAgentSelect,\n isStandalone: false,\n navigateTo,\n getPath,\n }),\n [\n effectiveBasePath,\n navigate,\n currentUser,\n tenantId,\n workspaceId,\n apiGatewayUrl,\n authToken,\n productId,\n onBotSelect,\n onAgentSelect,\n navigateTo,\n getPath,\n ]\n );\n\n return <BotlitContext.Provider value={contextValue}>{children}</BotlitContext.Provider>;\n};\n\nexport const BotlitProvider: FC<PropsWithChildren<BotmanorRootProps>> = (props) => {\n const { children, navigate } = props;\n // Standalone mode: no navigate function provided (MFE manages its own router)\n // Integrated mode: navigate function provided by shell (shell provides router)\n const isStandalone = !navigate;\n\n // Standalone mode: wrap in MemoryRouter\n if (isStandalone) {\n return (\n <MemoryRouter>\n <StandaloneProviderInner {...props} isStandalone={true}>\n {children}\n </StandaloneProviderInner>\n </MemoryRouter>\n );\n }\n\n // Integrated mode: shell provides router\n return (\n <IntegratedProviderInner {...props} navigate={navigate} isStandalone={false}>\n {children}\n </IntegratedProviderInner>\n );\n};\n"],"mappings":";;;;;AA4BA,IAAM,IAAgB,EAAyC,KAAK;AAMpE,SAAgB,IAAgC;CAC9C,IAAM,IAAU,EAAW,EAAc;AACzC,KAAI,CAAC,EACH,OAAU,MAAM,iDAAiD;AAEnE,QAAO;;AAYT,IAAM,KAAiE,EACrE,aACA,aACA,gBACA,aACA,gBACA,kBACA,cACA,cACA,gBACA,uBACI;CAEJ,IAAM,IAAiB,GAAmB,EACpC,IAAoB,KAAY,KAEhC,IAAU,GACb,MAAyB,EAAS,GAAmB,EAAa,EACnE,CAAC,EAAkB,CACpB,EAEK,IAAa,GAChB,MAAyB;AAExB,IADiB,EAAS,GAAmB,EAAa,CAClC;IAE1B,CAAC,GAAmB,EAAe,CACpC,EAEK,IAAe,SACZ;EACL,UAAU;EACV,UAAU,KAAA;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QAAO,kBAAC,EAAc,UAAf;EAAwB,OAAO;EAAe;EAAkC,CAAA;GAInF,KAED,EACH,aACA,aACA,aACA,gBACA,aACA,gBACA,kBACA,cACA,cACA,gBACA,uBACI;CACJ,IAAM,IAAoB,KAAY,KAEhC,IAAU,GACb,MAAyB,EAAS,GAAmB,EAAa,EACnE,CAAC,EAAkB,CACpB,EAEK,IAAa,GAChB,MAAyB;AAExB,IADiB,EAAS,GAAmB,EAAa,CACxC;IAEpB,CAAC,GAAmB,EAAS,CAC9B,EAEK,IAAe,SACZ;EACL,UAAU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QAAO,kBAAC,EAAc,UAAf;EAAwB,OAAO;EAAe;EAAkC,CAAA;GAG5E,KAA4D,MAAU;CACjF,IAAM,EAAE,aAAU,gBAAa;AAiB/B,QAdsB,IAepB,kBAAC,GAAD;EAAyB,GAAI;EAAiB;EAAU,cAAc;EACnE;EACuB,CAAA,GAZxB,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EAAyB,GAAI;EAAO,cAAc;EAC/C;EACuB,CAAA,EACb,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/botlit/utils/embedding-models.ts
|
|
2
|
+
var e = {
|
|
3
|
+
"amazon.titan-embed-text-v2:0": 1024,
|
|
4
|
+
"text-embedding-3-small": 1536,
|
|
5
|
+
"text-embedding-3-large": 3072,
|
|
6
|
+
"text-embedding-ada-002": 1536
|
|
7
|
+
};
|
|
8
|
+
function t(t, n) {
|
|
9
|
+
return t.filter((t) => t.isActive && t.maxOutputTokens > 0 && t.metadata?.purpose !== "embedding" && !e[t.modelId] && n.some((e) => e.id === t.providerId && e.isActive));
|
|
10
|
+
}
|
|
11
|
+
function n(t, n) {
|
|
12
|
+
return t.flatMap((t) => {
|
|
13
|
+
let r = n.find((e) => e.id === t.providerId && e.isActive), i = t.metadata?.purpose === "embedding" ? t.metadata.embeddingDimensions : void 0, a = typeof i == "number" ? i : e[t.modelId];
|
|
14
|
+
if (!t.isActive || !r || !a || t.metadata?.purpose === "answer" || !Number.isInteger(a) || a < 1 || a > 16e3) return [];
|
|
15
|
+
let o = t.modelId === "amazon.titan-embed-text-v2:0";
|
|
16
|
+
if (o ? r.type !== "AWS_BEDROCK" : ![
|
|
17
|
+
"OPENAI",
|
|
18
|
+
"AZURE_OPENAI",
|
|
19
|
+
"CUSTOM"
|
|
20
|
+
].includes(r.type)) return [];
|
|
21
|
+
let s = o ? typeof r.metadata?.embeddingDimensions == "number" ? r.metadata.embeddingDimensions : 1024 : a;
|
|
22
|
+
return o && ![
|
|
23
|
+
256,
|
|
24
|
+
512,
|
|
25
|
+
1024
|
|
26
|
+
].includes(s) ? [] : [{
|
|
27
|
+
id: t.id,
|
|
28
|
+
label: t.name,
|
|
29
|
+
dimensions: s
|
|
30
|
+
}];
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { t as configuredAnswerModels, n as configuredEmbeddingModels };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=embedding-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-models.js","names":[],"sources":["../../../src/botlit/utils/embedding-models.ts"],"sourcesContent":["import type { LLMModelRecord, LLMProviderRecord } from '../hooks/useLLMProviders';\n\nconst DIMENSIONS: Record<string, number> = {\n 'amazon.titan-embed-text-v2:0': 1024,\n 'text-embedding-3-small': 1536,\n 'text-embedding-3-large': 3072,\n 'text-embedding-ada-002': 1536,\n};\n\n/** Embedding registrations must never be offered as answer-generation models. */\nexport function configuredAnswerModels(models: LLMModelRecord[], providers: LLMProviderRecord[]) {\n return models.filter(\n (model) =>\n model.isActive &&\n model.maxOutputTokens > 0 &&\n model.metadata?.purpose !== 'embedding' &&\n !DIMENSIONS[model.modelId] &&\n providers.some((provider) => provider.id === model.providerId && provider.isActive)\n );\n}\n\n/** Use the registered model ID to pin its workspace provider during ingestion. */\nexport function configuredEmbeddingModels(\n models: LLMModelRecord[],\n providers: LLMProviderRecord[]\n) {\n return models.flatMap((model) => {\n const provider = providers.find((entry) => entry.id === model.providerId && entry.isActive);\n const declared =\n model.metadata?.purpose === 'embedding' ? model.metadata.embeddingDimensions : undefined;\n const dimension = typeof declared === 'number' ? declared : DIMENSIONS[model.modelId];\n if (!model.isActive || !provider || !dimension) return [];\n if (\n model.metadata?.purpose === 'answer' ||\n !Number.isInteger(dimension) ||\n dimension < 1 ||\n dimension > 16000\n )\n return [];\n const titan = model.modelId === 'amazon.titan-embed-text-v2:0';\n if (\n titan\n ? provider.type !== 'AWS_BEDROCK'\n : !['OPENAI', 'AZURE_OPENAI', 'CUSTOM'].includes(provider.type)\n )\n return [];\n const dimensions = titan\n ? typeof provider.metadata?.embeddingDimensions === 'number'\n ? provider.metadata.embeddingDimensions\n : 1024\n : dimension;\n if (titan && ![256, 512, 1024].includes(dimensions)) return [];\n return [{ id: model.id, label: model.name, dimensions }];\n });\n}\n"],"mappings":";AAEA,IAAM,IAAqC;CACzC,gCAAgC;CAChC,0BAA0B;CAC1B,0BAA0B;CAC1B,0BAA0B;CAC3B;AAGD,SAAgB,EAAuB,GAA0B,GAAgC;AAC/F,QAAO,EAAO,QACX,MACC,EAAM,YACN,EAAM,kBAAkB,KACxB,EAAM,UAAU,YAAY,eAC5B,CAAC,EAAW,EAAM,YAClB,EAAU,MAAM,MAAa,EAAS,OAAO,EAAM,cAAc,EAAS,SAAS,CACtF;;AAIH,SAAgB,EACd,GACA,GACA;AACA,QAAO,EAAO,SAAS,MAAU;EAC/B,IAAM,IAAW,EAAU,MAAM,MAAU,EAAM,OAAO,EAAM,cAAc,EAAM,SAAS,EACrF,IACJ,EAAM,UAAU,YAAY,cAAc,EAAM,SAAS,sBAAsB,KAAA,GAC3E,IAAY,OAAO,KAAa,WAAW,IAAW,EAAW,EAAM;AAE7E,MADI,CAAC,EAAM,YAAY,CAAC,KAAY,CAAC,KAEnC,EAAM,UAAU,YAAY,YAC5B,CAAC,OAAO,UAAU,EAAU,IAC5B,IAAY,KACZ,IAAY,KAEZ,QAAO,EAAE;EACX,IAAM,IAAQ,EAAM,YAAY;AAChC,MACE,IACI,EAAS,SAAS,gBAClB,CAAC;GAAC;GAAU;GAAgB;GAAS,CAAC,SAAS,EAAS,KAAK,CAEjE,QAAO,EAAE;EACX,IAAM,IAAa,IACf,OAAO,EAAS,UAAU,uBAAwB,WAChD,EAAS,SAAS,sBAClB,OACF;AAEJ,SADI,KAAS,CAAC;GAAC;GAAK;GAAK;GAAK,CAAC,SAAS,EAAW,GAAS,EAAE,GACvD,CAAC;GAAE,IAAI,EAAM;GAAI,OAAO,EAAM;GAAM;GAAY,CAAC;GACxD"}
|