@burdenoff/microfe-botmanor 2026.821.1 → 2026.925.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/botlit/BotlitRoutes.js.map +1 -1
- package/dist/botlit/BotmanorRoot.js.map +1 -1
- package/dist/botlit/BotmanorRootInner.js +4 -4
- package/dist/botlit/BotmanorRootInner.js.map +1 -1
- package/dist/botlit/components/ErrorState.js +33 -29
- package/dist/botlit/components/ErrorState.js.map +1 -1
- package/dist/botlit/components/RouteLoader.js +52 -48
- package/dist/botlit/components/RouteLoader.js.map +1 -1
- package/dist/botlit/components/VersionHistoryPanel.js +74 -77
- package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
- package/dist/botlit/components/WorkspaceRequired.js +31 -30
- package/dist/botlit/components/WorkspaceRequired.js.map +1 -1
- package/dist/botlit/hooks/internal/workspaceGateway.js.map +1 -1
- package/dist/botlit/hooks/useConversations.js.map +1 -1
- package/dist/botlit/hooks/useLLMProviders.js.map +1 -1
- package/dist/botlit/pages/A2AAgentDetailPage.js +1 -1
- package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -1
- package/dist/botlit/pages/A2ARegistryPage.js +116 -124
- package/dist/botlit/pages/A2ARegistryPage.js.map +1 -1
- package/dist/botlit/pages/AgentDetailPage.js +169 -172
- package/dist/botlit/pages/AgentDetailPage.js.map +1 -1
- package/dist/botlit/pages/AgentsListPage.js +96 -90
- package/dist/botlit/pages/AgentsListPage.js.map +1 -1
- package/dist/botlit/pages/BotChannelsTab.js.map +1 -1
- package/dist/botlit/pages/BotDetailPage.js +228 -231
- package/dist/botlit/pages/BotDetailPage.js.map +1 -1
- package/dist/botlit/pages/BotWorkflowTab.js +84 -87
- package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
- package/dist/botlit/pages/BotsListPage.js +144 -147
- package/dist/botlit/pages/BotsListPage.js.map +1 -1
- package/dist/botlit/pages/BucketsPage.js +3 -3
- package/dist/botlit/pages/BucketsPage.js.map +1 -1
- package/dist/botlit/pages/ChannelDetailPage.js +1 -1
- package/dist/botlit/pages/ChannelDetailPage.js.map +1 -1
- package/dist/botlit/pages/ChannelsPage.js +156 -149
- package/dist/botlit/pages/ChannelsPage.js.map +1 -1
- package/dist/botlit/pages/ChatPage.js +126 -129
- package/dist/botlit/pages/ChatPage.js.map +1 -1
- package/dist/botlit/pages/DashboardPage.js +111 -114
- package/dist/botlit/pages/DashboardPage.js.map +1 -1
- package/dist/botlit/pages/ExecutionsPage.js +163 -159
- package/dist/botlit/pages/ExecutionsPage.js.map +1 -1
- package/dist/botlit/pages/InstalledPackagesPage.js +3 -3
- package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -1
- package/dist/botlit/pages/KnowledgeBasesPage.js +84 -78
- package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -1
- package/dist/botlit/pages/MCPServersPage.js +159 -154
- package/dist/botlit/pages/MCPServersPage.js.map +1 -1
- package/dist/botlit/pages/PoliciesPage.js +119 -114
- package/dist/botlit/pages/PoliciesPage.js.map +1 -1
- package/dist/botlit/pages/RetrievalProfilesPage.js +102 -109
- package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -1
- package/dist/botlit/pages/SettingsPage.js +144 -159
- package/dist/botlit/pages/SettingsPage.js.map +1 -1
- package/dist/botlit/pages/SkillsPage.js +122 -105
- package/dist/botlit/pages/SkillsPage.js.map +1 -1
- package/dist/botlit/pages/StorePage.js +176 -175
- package/dist/botlit/pages/StorePage.js.map +1 -1
- package/dist/botlit/providers/BotlitProvider.js.map +1 -1
- package/dist/botlit/store/botlitStore.js +1 -1
- package/dist/botlit/store/botlitStore.js.map +1 -1
- package/dist/botlit/utils/navigation.js.map +1 -1
- package/dist/shared/hooks/useTr.js +14 -0
- package/dist/shared/hooks/useTr.js.map +1 -0
- package/package.json +33 -9
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
1
|
+
import { useTr as e } from "../../shared/hooks/useTr.js";
|
|
2
|
+
import { useConfigureLLMProvider as t, useLLMModels as n, useLLMProviders as r } from "../hooks/useLLMProviders.js";
|
|
3
|
+
import { cn as i } from "../utils/cn.js";
|
|
4
|
+
import { PageLayout as a } from "../components/PageLayout.js";
|
|
5
|
+
import { Card as o, CardContent as s, CardDescription as c, CardHeader as l, CardTitle as u } from "../components/Card.js";
|
|
6
|
+
import { Button as d } from "../components/Button.js";
|
|
7
|
+
import { Badge as f } from "../components/Badge.js";
|
|
8
|
+
import { FormField as p, Input as m } from "../components/Input.js";
|
|
9
|
+
import { toUnion as h } from "../utils/unions.js";
|
|
10
|
+
import { useState as g } from "react";
|
|
11
|
+
import { PagePurpose as _ } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
import { jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
13
|
+
import { Brain as b, ExternalLink as x, Key as S, Link2 as C, Save as w } from "lucide-react";
|
|
14
|
+
import { toast as T } from "sonner";
|
|
14
15
|
//#region src/botlit/pages/SettingsPage.tsx
|
|
15
|
-
var
|
|
16
|
+
var E = [
|
|
16
17
|
"OPENAI",
|
|
17
18
|
"ANTHROPIC",
|
|
18
19
|
"GOOGLE",
|
|
@@ -20,295 +21,279 @@ var T = [
|
|
|
20
21
|
"AWS_BEDROCK",
|
|
21
22
|
"CUSTOM"
|
|
22
23
|
];
|
|
23
|
-
function
|
|
24
|
-
return
|
|
24
|
+
function D(e) {
|
|
25
|
+
return h(e.toUpperCase(), E, "CUSTOM");
|
|
25
26
|
}
|
|
26
|
-
var
|
|
27
|
-
let { data:
|
|
28
|
-
return /* @__PURE__ */
|
|
29
|
-
title: "Settings",
|
|
30
|
-
description: "Configure your
|
|
31
|
-
children: /* @__PURE__ */
|
|
27
|
+
var O = () => {
|
|
28
|
+
let h = e(), { data: E, refetch: O } = r(), { configureProvider: k, isConfiguring: A } = t(), { data: j } = n(), [M, N] = g(""), [P, F] = g("openai"), [I, L] = g(null), [R, z] = g("apikey"), [B, V] = g("");
|
|
29
|
+
return /* @__PURE__ */ v(a, {
|
|
30
|
+
title: h("botlit.settings.title", "Settings"),
|
|
31
|
+
description: h("botlit.settings.description", "Configure your BotManor workspace settings"),
|
|
32
|
+
children: /* @__PURE__ */ y("div", {
|
|
32
33
|
className: "space-y-6",
|
|
33
34
|
children: [
|
|
34
|
-
/* @__PURE__ */ _
|
|
35
|
-
icon: /* @__PURE__ */
|
|
36
|
-
children: "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."
|
|
35
|
+
/* @__PURE__ */ v(_, {
|
|
36
|
+
icon: /* @__PURE__ */ v(S, { size: 18 }),
|
|
37
|
+
children: h("botlit.settings.purpose", "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.")
|
|
37
38
|
}),
|
|
38
|
-
/* @__PURE__ */
|
|
39
|
+
/* @__PURE__ */ y(o, {
|
|
39
40
|
treatment: "glass",
|
|
40
41
|
glow: !0,
|
|
41
|
-
children: [/* @__PURE__ */
|
|
42
|
+
children: [/* @__PURE__ */ y(l, { children: [/* @__PURE__ */ v(u, { children: h("botlit.settings.providers.title", "LLM Providers") }), /* @__PURE__ */ v(c, { children: h("botlit.settings.providers.description", "Configure API keys for AI model providers") })] }), /* @__PURE__ */ v(s, {
|
|
42
43
|
className: "space-y-4",
|
|
43
|
-
children:
|
|
44
|
+
children: E?.map((e) => /* @__PURE__ */ y("div", {
|
|
44
45
|
className: "flex items-center justify-between p-4 border border-border-subtle rounded-lg",
|
|
45
|
-
children: [/* @__PURE__ */
|
|
46
|
+
children: [/* @__PURE__ */ y("div", {
|
|
46
47
|
className: "flex items-center gap-4",
|
|
47
|
-
children: [/* @__PURE__ */
|
|
48
|
+
children: [/* @__PURE__ */ v("div", {
|
|
48
49
|
className: "p-2 bg-action-primary-bg/10 rounded-lg",
|
|
49
|
-
children: e.connectionId ? /* @__PURE__ */
|
|
50
|
-
}), /* @__PURE__ */
|
|
51
|
-
/* @__PURE__ */
|
|
50
|
+
children: e.connectionId ? /* @__PURE__ */ v(C, { className: "h-5 w-5 text-primary" }) : /* @__PURE__ */ v(S, { className: "h-5 w-5 text-primary" })
|
|
51
|
+
}), /* @__PURE__ */ y("div", { children: [
|
|
52
|
+
/* @__PURE__ */ v("p", {
|
|
52
53
|
className: "font-medium",
|
|
53
54
|
children: e.name
|
|
54
55
|
}),
|
|
55
56
|
/* @__PURE__ */ v("p", {
|
|
56
57
|
className: "text-sm text-text-secondary",
|
|
57
|
-
children:
|
|
58
|
+
children: h("botlit.settings.providers.type", "Type: {{type}}", { type: e.type })
|
|
58
59
|
}),
|
|
59
|
-
e.connectionId && /* @__PURE__ */
|
|
60
|
+
e.connectionId && /* @__PURE__ */ v("p", {
|
|
60
61
|
className: "text-xs text-text-secondary mt-0.5",
|
|
61
|
-
children: "Connected via Integrations"
|
|
62
|
+
children: h("botlit.settings.providers.connectedViaIntegrations", "Connected via Integrations")
|
|
62
63
|
}),
|
|
63
|
-
!e.connectionId && e.credentialsHash && /* @__PURE__ */
|
|
64
|
+
!e.connectionId && e.credentialsHash && /* @__PURE__ */ v("p", {
|
|
64
65
|
className: "text-xs text-text-secondary mt-0.5",
|
|
65
|
-
children: "API key stored locally"
|
|
66
|
+
children: h("botlit.settings.providers.apiKeyStored", "API key stored locally")
|
|
66
67
|
})
|
|
67
68
|
] })]
|
|
68
|
-
}), /* @__PURE__ */
|
|
69
|
+
}), /* @__PURE__ */ y("div", {
|
|
69
70
|
className: "flex items-center gap-3",
|
|
70
71
|
children: [
|
|
71
|
-
e.connectionId && /* @__PURE__ */
|
|
72
|
+
e.connectionId && /* @__PURE__ */ v(f, {
|
|
72
73
|
variant: "default",
|
|
73
|
-
children: "Integration"
|
|
74
|
+
children: h("botlit.settings.providers.integrationBadge", "Integration")
|
|
74
75
|
}),
|
|
75
|
-
/* @__PURE__ */
|
|
76
|
+
/* @__PURE__ */ v(f, {
|
|
76
77
|
variant: e.isActive ? "success" : "secondary",
|
|
77
|
-
children: e.isActive ? "Active" : "Inactive"
|
|
78
|
+
children: e.isActive ? h("botlit.settings.providers.active", "Active") : h("botlit.settings.providers.inactive", "Inactive")
|
|
78
79
|
}),
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
+
/* @__PURE__ */ v(d, {
|
|
80
81
|
variant: "outline",
|
|
81
82
|
size: "sm",
|
|
82
83
|
onClick: () => {
|
|
83
|
-
|
|
84
|
+
L(e.id), F(e.type.toLowerCase()), N(""), V(e.connectionId || ""), z(e.connectionId ? "integration" : "apikey"), document.getElementById("provider-form")?.scrollIntoView({ behavior: "smooth" });
|
|
84
85
|
},
|
|
85
|
-
children: "Configure"
|
|
86
|
+
children: h("botlit.settings.actions.configure", "Configure")
|
|
86
87
|
})
|
|
87
88
|
]
|
|
88
89
|
})]
|
|
89
90
|
}, e.id))
|
|
90
91
|
})]
|
|
91
92
|
}),
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
+
/* @__PURE__ */ y(o, { children: [/* @__PURE__ */ y(l, { children: [/* @__PURE__ */ v(u, { children: h("botlit.settings.models.title", "LLM Models") }), /* @__PURE__ */ v(c, { children: h("botlit.settings.models.description", "Registered models across your providers") })] }), /* @__PURE__ */ v(s, {
|
|
93
94
|
className: "space-y-4",
|
|
94
|
-
children:
|
|
95
|
-
let t =
|
|
96
|
-
return /* @__PURE__ */
|
|
95
|
+
children: j && j.length > 0 ? j.map((e) => {
|
|
96
|
+
let t = E?.find((t) => t.id === e.providerId)?.name;
|
|
97
|
+
return /* @__PURE__ */ y("div", {
|
|
97
98
|
className: "flex items-center justify-between p-4 border border-border-subtle rounded-lg",
|
|
98
|
-
children: [/* @__PURE__ */
|
|
99
|
+
children: [/* @__PURE__ */ y("div", {
|
|
99
100
|
className: "flex items-center gap-4",
|
|
100
|
-
children: [/* @__PURE__ */
|
|
101
|
+
children: [/* @__PURE__ */ v("div", {
|
|
101
102
|
className: "p-2 bg-purple-500/10 rounded-lg",
|
|
102
|
-
children: /* @__PURE__ */
|
|
103
|
-
}), /* @__PURE__ */
|
|
104
|
-
/* @__PURE__ */
|
|
103
|
+
children: /* @__PURE__ */ v(b, { className: "h-5 w-5 text-purple-500" })
|
|
104
|
+
}), /* @__PURE__ */ y("div", { children: [
|
|
105
|
+
/* @__PURE__ */ v("p", {
|
|
105
106
|
className: "font-medium",
|
|
106
107
|
children: e.name
|
|
107
108
|
}),
|
|
108
|
-
/* @__PURE__ */
|
|
109
|
+
/* @__PURE__ */ y("p", {
|
|
109
110
|
className: "text-sm text-text-secondary",
|
|
110
111
|
children: [e.modelId, t && ` · ${t}`]
|
|
111
112
|
}),
|
|
112
|
-
/* @__PURE__ */
|
|
113
|
+
/* @__PURE__ */ y("div", {
|
|
113
114
|
className: "flex gap-3 mt-1 text-xs text-text-secondary",
|
|
114
115
|
children: [
|
|
115
|
-
e.contextWindow != null && /* @__PURE__ */ v("span", { children:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
] }),
|
|
120
|
-
e.maxOutputTokens != null && /* @__PURE__ */ v("span", { children: [
|
|
121
|
-
"Max out: ",
|
|
122
|
-
(e.maxOutputTokens / 1e3).toFixed(0),
|
|
123
|
-
"K"
|
|
124
|
-
] }),
|
|
125
|
-
e.inputPricePerMToken != null && /* @__PURE__ */ v("span", { children: [
|
|
126
|
-
"$",
|
|
127
|
-
e.inputPricePerMToken,
|
|
128
|
-
"/M in"
|
|
129
|
-
] }),
|
|
130
|
-
e.outputPricePerMToken != null && /* @__PURE__ */ v("span", { children: [
|
|
131
|
-
"$",
|
|
132
|
-
e.outputPricePerMToken,
|
|
133
|
-
"/M out"
|
|
134
|
-
] })
|
|
116
|
+
e.contextWindow != null && /* @__PURE__ */ v("span", { children: h("botlit.settings.models.context", "Context: {{value}}K", { value: (e.contextWindow / 1e3).toFixed(0) }) }),
|
|
117
|
+
e.maxOutputTokens != null && /* @__PURE__ */ v("span", { children: h("botlit.settings.models.maxOut", "Max out: {{value}}K", { value: (e.maxOutputTokens / 1e3).toFixed(0) }) }),
|
|
118
|
+
e.inputPricePerMToken != null && /* @__PURE__ */ v("span", { children: h("botlit.settings.models.priceIn", "${{value}}/M in", { value: e.inputPricePerMToken }) }),
|
|
119
|
+
e.outputPricePerMToken != null && /* @__PURE__ */ v("span", { children: h("botlit.settings.models.priceOut", "${{value}}/M out", { value: e.outputPricePerMToken }) })
|
|
135
120
|
]
|
|
136
121
|
})
|
|
137
122
|
] })]
|
|
138
|
-
}), /* @__PURE__ */
|
|
123
|
+
}), /* @__PURE__ */ v(f, {
|
|
139
124
|
variant: e.isActive ? "success" : "secondary",
|
|
140
|
-
children: e.isActive ? "Active" : "Inactive"
|
|
125
|
+
children: e.isActive ? h("botlit.settings.providers.active", "Active") : h("botlit.settings.providers.inactive", "Inactive")
|
|
141
126
|
})]
|
|
142
127
|
}, e.id);
|
|
143
|
-
}) : /* @__PURE__ */
|
|
128
|
+
}) : /* @__PURE__ */ v("p", {
|
|
144
129
|
className: "text-sm text-text-secondary text-center py-4",
|
|
145
|
-
children: "No models registered yet."
|
|
130
|
+
children: h("botlit.settings.models.empty", "No models registered yet.")
|
|
146
131
|
})
|
|
147
132
|
})] }),
|
|
148
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ y(o, {
|
|
149
134
|
id: "provider-form",
|
|
150
|
-
children: [/* @__PURE__ */
|
|
135
|
+
children: [/* @__PURE__ */ y(l, { children: [/* @__PURE__ */ v(u, { children: I ? h("botlit.settings.form.updateTitle", "Update Provider") : h("botlit.settings.form.addTitle", "Add Provider") }), /* @__PURE__ */ v(c, { children: I ? h("botlit.settings.form.updateDescription", "Update credentials for this provider") : h("botlit.settings.form.addDescription", "Configure a new LLM provider") })] }), /* @__PURE__ */ y(s, {
|
|
151
136
|
className: "space-y-4",
|
|
152
137
|
children: [
|
|
153
|
-
/* @__PURE__ */
|
|
154
|
-
label: "Provider",
|
|
155
|
-
children: /* @__PURE__ */
|
|
138
|
+
/* @__PURE__ */ v(p, {
|
|
139
|
+
label: h("botlit.settings.form.providerLabel", "Provider"),
|
|
140
|
+
children: /* @__PURE__ */ y("select", {
|
|
156
141
|
className: "flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm",
|
|
157
|
-
value:
|
|
158
|
-
onChange: (e) =>
|
|
142
|
+
value: P,
|
|
143
|
+
onChange: (e) => F(e.target.value),
|
|
159
144
|
children: [
|
|
160
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ v("option", {
|
|
161
146
|
value: "openai",
|
|
162
147
|
children: "OpenAI"
|
|
163
148
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
149
|
+
/* @__PURE__ */ v("option", {
|
|
165
150
|
value: "anthropic",
|
|
166
151
|
children: "Anthropic"
|
|
167
152
|
}),
|
|
168
|
-
/* @__PURE__ */
|
|
153
|
+
/* @__PURE__ */ v("option", {
|
|
169
154
|
value: "google",
|
|
170
155
|
children: "Google AI"
|
|
171
156
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
157
|
+
/* @__PURE__ */ v("option", {
|
|
173
158
|
value: "azure_openai",
|
|
174
159
|
children: "Azure OpenAI"
|
|
175
160
|
}),
|
|
176
|
-
/* @__PURE__ */
|
|
161
|
+
/* @__PURE__ */ v("option", {
|
|
177
162
|
value: "aws_bedrock",
|
|
178
163
|
children: "AWS Bedrock"
|
|
179
164
|
}),
|
|
180
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ v("option", {
|
|
181
166
|
value: "custom",
|
|
182
167
|
children: "Custom"
|
|
183
168
|
})
|
|
184
169
|
]
|
|
185
170
|
})
|
|
186
171
|
}),
|
|
187
|
-
/* @__PURE__ */
|
|
188
|
-
label: "Credential Method",
|
|
189
|
-
children: /* @__PURE__ */
|
|
172
|
+
/* @__PURE__ */ v(p, {
|
|
173
|
+
label: h("botlit.settings.form.credentialMethod", "Credential Method"),
|
|
174
|
+
children: /* @__PURE__ */ y("div", {
|
|
190
175
|
className: "flex gap-3",
|
|
191
|
-
children: [/* @__PURE__ */
|
|
192
|
-
className:
|
|
193
|
-
children: [/* @__PURE__ */
|
|
176
|
+
children: [/* @__PURE__ */ y("label", {
|
|
177
|
+
className: i("flex items-center gap-2 px-4 py-3 border rounded-lg cursor-pointer transition-colors flex-1", R === "integration" ? "border-primary bg-action-primary-bg/5" : "border-border-subtle hover:border-primary/50"),
|
|
178
|
+
children: [/* @__PURE__ */ v("input", {
|
|
194
179
|
type: "radio",
|
|
195
180
|
name: "credentialMethod",
|
|
196
181
|
value: "integration",
|
|
197
|
-
checked:
|
|
198
|
-
onChange: () =>
|
|
182
|
+
checked: R === "integration",
|
|
183
|
+
onChange: () => z("integration"),
|
|
199
184
|
className: "h-4 w-4"
|
|
200
|
-
}), /* @__PURE__ */
|
|
185
|
+
}), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
|
|
201
186
|
className: "font-medium text-sm",
|
|
202
|
-
children: "Connect via Integrations"
|
|
203
|
-
}), /* @__PURE__ */
|
|
187
|
+
children: h("botlit.settings.form.integrationOption", "Connect via Integrations")
|
|
188
|
+
}), /* @__PURE__ */ v("p", {
|
|
204
189
|
className: "text-xs text-text-secondary",
|
|
205
|
-
children: "Managed credentials (recommended)"
|
|
190
|
+
children: h("botlit.settings.form.integrationHint", "Managed credentials (recommended)")
|
|
206
191
|
})] })]
|
|
207
|
-
}), /* @__PURE__ */
|
|
208
|
-
className:
|
|
209
|
-
children: [/* @__PURE__ */
|
|
192
|
+
}), /* @__PURE__ */ y("label", {
|
|
193
|
+
className: i("flex items-center gap-2 px-4 py-3 border rounded-lg cursor-pointer transition-colors flex-1", R === "apikey" ? "border-primary bg-action-primary-bg/5" : "border-border-subtle hover:border-primary/50"),
|
|
194
|
+
children: [/* @__PURE__ */ v("input", {
|
|
210
195
|
type: "radio",
|
|
211
196
|
name: "credentialMethod",
|
|
212
197
|
value: "apikey",
|
|
213
|
-
checked:
|
|
214
|
-
onChange: () =>
|
|
198
|
+
checked: R === "apikey",
|
|
199
|
+
onChange: () => z("apikey"),
|
|
215
200
|
className: "h-4 w-4"
|
|
216
|
-
}), /* @__PURE__ */
|
|
201
|
+
}), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
|
|
217
202
|
className: "font-medium text-sm",
|
|
218
|
-
children: "Enter API Key"
|
|
219
|
-
}), /* @__PURE__ */
|
|
203
|
+
children: h("botlit.settings.form.apiKeyOption", "Enter API Key")
|
|
204
|
+
}), /* @__PURE__ */ v("p", {
|
|
220
205
|
className: "text-xs text-text-secondary",
|
|
221
|
-
children: "Paste key directly (legacy)"
|
|
206
|
+
children: h("botlit.settings.form.apiKeyHint", "Paste key directly (legacy)")
|
|
222
207
|
})] })]
|
|
223
208
|
})]
|
|
224
209
|
})
|
|
225
210
|
}),
|
|
226
|
-
|
|
211
|
+
R === "integration" && /* @__PURE__ */ y("div", {
|
|
227
212
|
className: "space-y-3",
|
|
228
|
-
children: [/* @__PURE__ */
|
|
213
|
+
children: [/* @__PURE__ */ v("div", {
|
|
229
214
|
className: "p-4 bg-bg-sunken/50 border border-border-subtle rounded-lg",
|
|
230
|
-
children: /* @__PURE__ */
|
|
215
|
+
children: /* @__PURE__ */ y("div", {
|
|
231
216
|
className: "flex items-start gap-3",
|
|
232
|
-
children: [/* @__PURE__ */
|
|
217
|
+
children: [/* @__PURE__ */ v(C, { className: "h-5 w-5 text-primary mt-0.5 flex-shrink-0" }), /* @__PURE__ */ y("div", {
|
|
233
218
|
className: "space-y-2 flex-1",
|
|
234
219
|
children: [
|
|
235
|
-
/* @__PURE__ */
|
|
220
|
+
/* @__PURE__ */ v("p", {
|
|
236
221
|
className: "text-sm font-medium",
|
|
237
|
-
children: "Integration Connection"
|
|
222
|
+
children: h("botlit.settings.form.integrationTitle", "Integration Connection")
|
|
238
223
|
}),
|
|
239
|
-
/* @__PURE__ */
|
|
224
|
+
/* @__PURE__ */ v("p", {
|
|
240
225
|
className: "text-xs text-text-secondary",
|
|
241
|
-
children: "Create a connection in the Integrations module, then paste the Connection ID here. This stores your API key securely in the Integrations vault."
|
|
226
|
+
children: h("botlit.settings.form.integrationDescription", "Create a connection in the Integrations module, then paste the Connection ID here. This stores your API key securely in the Integrations vault.")
|
|
242
227
|
}),
|
|
243
|
-
/* @__PURE__ */
|
|
228
|
+
/* @__PURE__ */ v("div", {
|
|
244
229
|
className: "flex gap-2 mt-2",
|
|
245
|
-
children: /* @__PURE__ */
|
|
230
|
+
children: /* @__PURE__ */ y(d, {
|
|
246
231
|
variant: "outline",
|
|
247
232
|
size: "sm",
|
|
248
233
|
onClick: () => {
|
|
249
234
|
window.open("/integrations/connections", "_blank");
|
|
250
235
|
},
|
|
251
|
-
children: [/* @__PURE__ */
|
|
236
|
+
children: [/* @__PURE__ */ v(x, {
|
|
252
237
|
size: 14,
|
|
253
238
|
className: "mr-1.5"
|
|
254
|
-
}), "Open Integrations"]
|
|
239
|
+
}), h("botlit.settings.form.openIntegrations", "Open Integrations")]
|
|
255
240
|
})
|
|
256
241
|
})
|
|
257
242
|
]
|
|
258
243
|
})]
|
|
259
244
|
})
|
|
260
|
-
}), /* @__PURE__ */
|
|
261
|
-
label: "Connection ID",
|
|
262
|
-
children: /* @__PURE__ */
|
|
263
|
-
placeholder: "Paste connection ID from Integrations...",
|
|
264
|
-
value:
|
|
265
|
-
onChange: (e) =>
|
|
245
|
+
}), /* @__PURE__ */ v(p, {
|
|
246
|
+
label: h("botlit.settings.form.connectionIdPlaceholder", "Connection ID"),
|
|
247
|
+
children: /* @__PURE__ */ v(m, {
|
|
248
|
+
placeholder: h("botlit.settings.form.connectionIdPlaceholder", "Paste connection ID from Integrations..."),
|
|
249
|
+
value: B,
|
|
250
|
+
onChange: (e) => V(e.target.value)
|
|
266
251
|
})
|
|
267
252
|
})]
|
|
268
253
|
}),
|
|
269
|
-
|
|
270
|
-
label: "API Key",
|
|
271
|
-
children: /* @__PURE__ */
|
|
254
|
+
R === "apikey" && /* @__PURE__ */ v(p, {
|
|
255
|
+
label: h("botlit.settings.form.apiKeyLabel", "API Key"),
|
|
256
|
+
children: /* @__PURE__ */ v(m, {
|
|
272
257
|
type: "password",
|
|
273
|
-
placeholder: "sk-...",
|
|
274
|
-
value:
|
|
275
|
-
onChange: (e) =>
|
|
258
|
+
placeholder: h("botlit.settings.form.apiKeyPlaceholder", "sk-..."),
|
|
259
|
+
value: M,
|
|
260
|
+
onChange: (e) => N(e.target.value)
|
|
276
261
|
})
|
|
277
262
|
}),
|
|
278
|
-
/* @__PURE__ */
|
|
263
|
+
/* @__PURE__ */ y("div", {
|
|
279
264
|
className: "flex gap-2",
|
|
280
|
-
children: [/* @__PURE__ */
|
|
281
|
-
leftIcon: /* @__PURE__ */
|
|
282
|
-
isLoading:
|
|
283
|
-
disabled:
|
|
265
|
+
children: [/* @__PURE__ */ v(d, {
|
|
266
|
+
leftIcon: /* @__PURE__ */ v(w, { size: 16 }),
|
|
267
|
+
isLoading: A,
|
|
268
|
+
disabled: R === "apikey" ? !M : !B,
|
|
284
269
|
onClick: async () => {
|
|
285
270
|
try {
|
|
286
|
-
let e =
|
|
287
|
-
|
|
271
|
+
let e = P.charAt(0).toUpperCase() + P.slice(1), t = R === "integration" ? void 0 : M ? { apiKey: M } : void 0, n = R === "integration" ? B : void 0;
|
|
272
|
+
I ? await k({
|
|
288
273
|
name: e,
|
|
289
|
-
type:
|
|
274
|
+
type: D(P),
|
|
290
275
|
connectionId: n,
|
|
291
276
|
credentials: t
|
|
292
|
-
},
|
|
277
|
+
}, I) : await k({
|
|
293
278
|
name: e,
|
|
294
|
-
type:
|
|
279
|
+
type: D(P),
|
|
295
280
|
connectionId: n,
|
|
296
281
|
credentials: t
|
|
297
|
-
}),
|
|
298
|
-
let r =
|
|
299
|
-
|
|
282
|
+
}), N(""), V(""), L(null), await O();
|
|
283
|
+
let r = P.charAt(0).toUpperCase() + P.slice(1);
|
|
284
|
+
T.success(I ? h("botlit.settings.form.updateSuccess", "{{provider}} provider updated successfully", { provider: r }) : h("botlit.settings.form.addSuccess", "{{provider}} provider added successfully", { provider: r }));
|
|
300
285
|
} catch (e) {
|
|
301
|
-
let t = e instanceof Error ? e.message : "Failed to save provider";
|
|
302
|
-
|
|
286
|
+
let t = e instanceof Error ? e.message : h("botlit.settings.form.saveError", "Failed to save provider");
|
|
287
|
+
T.error(t);
|
|
303
288
|
}
|
|
304
289
|
},
|
|
305
|
-
children:
|
|
306
|
-
}),
|
|
290
|
+
children: I ? h("botlit.settings.form.updateProvider", "Update Provider") : h("botlit.settings.form.saveProvider", "Save Provider")
|
|
291
|
+
}), I && /* @__PURE__ */ v(d, {
|
|
307
292
|
variant: "outline",
|
|
308
293
|
onClick: () => {
|
|
309
|
-
|
|
294
|
+
L(null), N(""), V(""), z("apikey"), F("openai");
|
|
310
295
|
},
|
|
311
|
-
children: "Cancel"
|
|
296
|
+
children: h("botlit.settings.form.cancel", "Cancel")
|
|
312
297
|
})]
|
|
313
298
|
})
|
|
314
299
|
]
|
|
@@ -319,6 +304,6 @@ var D = () => {
|
|
|
319
304
|
});
|
|
320
305
|
};
|
|
321
306
|
//#endregion
|
|
322
|
-
export {
|
|
307
|
+
export { O as SettingsPage };
|
|
323
308
|
|
|
324
309
|
//# sourceMappingURL=SettingsPage.js.map
|
|
@@ -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 { 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 { 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 title=\"Settings\" description=\"Configure your Botlit workspace settings\">\n <div className=\"space-y-6\">\n <PagePurpose icon={<Key size={18} />}>\n Workspace-wide settings for LLM Providers — connect at least one model provider (OpenAI,\n Anthropic, Google and others) so your agents have a brain to think with.\n </PagePurpose>\n\n <Card treatment=\"glass\" glow>\n <CardHeader>\n <CardTitle>LLM Providers</CardTitle>\n <CardDescription>Configure API keys for AI model providers</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\">Type: {provider.type}</p>\n {provider.connectionId && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Connected via Integrations\n </p>\n )}\n {!provider.connectionId && provider.credentialsHash && (\n <p className=\"text-xs text-text-secondary mt-0.5\">API key stored locally</p>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n {provider.connectionId && <Badge variant=\"default\">Integration</Badge>}\n <Badge variant={provider.isActive ? 'success' : 'secondary'}>\n {provider.isActive ? 'Active' : '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 Configure\n </Button>\n </div>\n </div>\n )\n )}\n </CardContent>\n </Card>\n\n {/* LLM Models List */}\n <Card>\n <CardHeader>\n <CardTitle>LLM Models</CardTitle>\n <CardDescription>Registered models across your providers</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>Context: {(model.contextWindow / 1000).toFixed(0)}K</span>\n )}\n {model.maxOutputTokens != null && (\n <span>Max out: {(model.maxOutputTokens / 1000).toFixed(0)}K</span>\n )}\n {model.inputPricePerMToken != null && (\n <span>${model.inputPricePerMToken}/M in</span>\n )}\n {model.outputPricePerMToken != null && (\n <span>${model.outputPricePerMToken}/M out</span>\n )}\n </div>\n </div>\n </div>\n <Badge variant={model.isActive ? 'success' : 'secondary'}>\n {model.isActive ? 'Active' : 'Inactive'}\n </Badge>\n </div>\n );\n }\n )\n ) : (\n <p className=\"text-sm text-text-secondary text-center py-4\">\n No models registered yet.\n </p>\n )}\n </CardContent>\n </Card>\n\n <Card id=\"provider-form\">\n <CardHeader>\n <CardTitle>{editingProviderId ? 'Update Provider' : 'Add Provider'}</CardTitle>\n <CardDescription>\n {editingProviderId\n ? 'Update credentials for this provider'\n : 'Configure a new LLM provider'}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <FormField label=\"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=\"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\">Connect via Integrations</p>\n <p className=\"text-xs text-text-secondary\">Managed credentials (recommended)</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\">Enter API Key</p>\n <p className=\"text-xs text-text-secondary\">Paste key directly (legacy)</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\">Integration Connection</p>\n <p className=\"text-xs text-text-secondary\">\n Create a connection in the Integrations module, then paste the Connection ID\n here. This stores your API key securely in the Integrations vault.\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 Open Integrations\n </Button>\n </div>\n </div>\n </div>\n </div>\n <FormField label=\"Connection ID\">\n <Input\n placeholder=\"Paste connection ID from Integrations...\"\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=\"API Key\">\n <Input\n type=\"password\"\n placeholder=\"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 ? `${providerLabel} provider updated successfully`\n : `${providerLabel} provider added successfully`\n );\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : 'Failed to save provider';\n toast.error(message);\n }\n }}\n >\n {editingProviderId ? 'Update Provider' : '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 Cancel\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAoBA,IAAM,IAAiB;CACrB;CACA;CACA;CACA;CACA;CACA;CACD;AAGD,SAAS,EAAe,GAAgD;AACtE,QAAO,EAAQ,EAAM,aAAa,EAAE,GAAgB,SAAS;;AAG/D,IAAa,UAAyB;CACpC,IAAM,EAAE,MAAM,GAAW,SAAS,MAAqB,GAAiB,EAClE,EAAE,sBAAmB,qBAAkB,GAAyB,EAChE,EAAE,MAAM,MAAc,GAAc,EACpC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAsB,KAA2B,EAAS,SAAS,EACpE,CAAC,GAAmB,KAAwB,EAAwB,KAAK,EAEzE,CAAC,GAAkB,KAAuB,EAAmC,SAAS,EACtF,CAAC,GAAc,KAAmB,EAAS,GAAG;AAEpD,QACE,kBAAC,GAAD;EAAY,OAAM;EAAW,aAAY;YACvC,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KAAa,MAAM,kBAAC,GAAD,EAAK,MAAM,IAAM,CAAA;eAAE;KAGxB,CAAA;IAEd,kBAAC,GAAD;KAAM,WAAU;KAAQ,MAAA;eAAxB,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,iBAAyB,CAAA,EACpC,kBAAC,GAAD,EAAA,UAAiB,6CAA2D,CAAA,CACjE,EAAA,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,GAAW,KACT,MAQC,kBAAC,OAAD;OAEE,WAAU;iBAFZ,CAIE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAS,eACR,kBAAC,GAAD,EAAO,WAAU,wBAAyB,CAAA,GAE1C,kBAAC,GAAD,EAAK,WAAU,wBAAyB,CAAA;SAEtC,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA;SACE,kBAAC,KAAD;UAAG,WAAU;oBAAe,EAAS;UAAS,CAAA;SAC9C,kBAAC,KAAD;UAAG,WAAU;oBAAb,CAA2C,UAAO,EAAS,KAAS;;SACnE,EAAS,gBACR,kBAAC,KAAD;UAAG,WAAU;oBAAqC;UAE9C,CAAA;SAEL,CAAC,EAAS,gBAAgB,EAAS,mBAClC,kBAAC,KAAD;UAAG,WAAU;oBAAqC;UAA0B,CAAA;SAE1E,EAAA,CAAA,CACF;WACN,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACG,EAAS,gBAAgB,kBAAC,GAAD;UAAO,SAAQ;oBAAU;UAAmB,CAAA;SACtE,kBAAC,GAAD;UAAO,SAAS,EAAS,WAAW,YAAY;oBAC7C,EAAS,WAAW,WAAW;UAC1B,CAAA;SACR,kBAAC,GAAD;UACE,SAAQ;UACR,MAAK;UACL,eAAe;AAOb,WANA,EAAqB,EAAS,GAAG,EACjC,EAAwB,EAAS,KAAK,aAAa,CAAC,EACpD,EAAU,GAAG,EACb,EAAgB,EAAS,gBAAgB,GAAG,EAC5C,EAAoB,EAAS,eAAe,gBAAgB,SAAS,EAErE,SACG,eAAe,gBAAgB,EAC9B,eAAe,EAAE,UAAU,UAAU,CAAC;;oBAE7C;UAEQ,CAAA;SACL;UACF;SA/CC,EAAS,GA+CV,CAET;MACW,CAAA,CACT;;IAGP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,cAAsB,CAAA,EACjC,kBAAC,GAAD,EAAA,UAAiB,2CAAyD,CAAA,CAC/D,EAAA,CAAA,EACb,kBAAC,GAAD;KAAa,WAAU;eACpB,KAAa,EAAU,SAAS,IAC/B,EAAU,KACP,MAUK;MACJ,IAAM,IAAe,GAAW,MAC7B,MAAoC,EAAE,OAAO,EAAM,WACrD,EAAE;AACH,aACE,kBAAC,OAAD;OAEE,WAAU;iBAFZ,CAIE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,GAAD,EAAO,WAAU,2BAA4B,CAAA;SACzC,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA;SACE,kBAAC,KAAD;UAAG,WAAU;oBAAe,EAAM;UAAS,CAAA;SAC3C,kBAAC,KAAD;UAAG,WAAU;oBAAb,CACG,EAAM,SACN,KAAgB,MAAM,IACrB;;SACJ,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACG,EAAM,iBAAiB,QACtB,kBAAC,QAAD,EAAA,UAAA;YAAM;aAAW,EAAM,gBAAgB,KAAM,QAAQ,EAAE;YAAC;YAAQ,EAAA,CAAA;WAEjE,EAAM,mBAAmB,QACxB,kBAAC,QAAD,EAAA,UAAA;YAAM;aAAW,EAAM,kBAAkB,KAAM,QAAQ,EAAE;YAAC;YAAQ,EAAA,CAAA;WAEnE,EAAM,uBAAuB,QAC5B,kBAAC,QAAD,EAAA,UAAA;YAAM;YAAE,EAAM;YAAoB;YAAY,EAAA,CAAA;WAE/C,EAAM,wBAAwB,QAC7B,kBAAC,QAAD,EAAA,UAAA;YAAM;YAAE,EAAM;YAAqB;YAAa,EAAA,CAAA;WAE9C;;SACF,EAAA,CAAA,CACF;WACN,kBAAC,GAAD;QAAO,SAAS,EAAM,WAAW,YAAY;kBAC1C,EAAM,WAAW,WAAW;QACvB,CAAA,CACJ;SAhCC,EAAM,GAgCP;OAGX,GAED,kBAAC,KAAD;MAAG,WAAU;gBAA+C;MAExD,CAAA;KAEM,CAAA,CACT,EAAA,CAAA;IAEP,kBAAC,GAAD;KAAM,IAAG;eAAT,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAY,IAAoB,oBAAoB,gBAA2B,CAAA,EAC/E,kBAAC,GAAD,EAAA,UACG,IACG,yCACA,gCACY,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB;OACE,kBAAC,GAAD;QAAW,OAAM;kBACf,kBAAC,UAAD;SACE,WAAU;SACV,OAAO;SACP,WAAW,MAAM,EAAwB,EAAE,OAAO,MAAM;mBAH1D;UAKE,kBAAC,UAAD;WAAQ,OAAM;qBAAS;WAAe,CAAA;UACtC,kBAAC,UAAD;WAAQ,OAAM;qBAAY;WAAkB,CAAA;UAC5C,kBAAC,UAAD;WAAQ,OAAM;qBAAS;WAAkB,CAAA;UACzC,kBAAC,UAAD;WAAQ,OAAM;qBAAe;WAAqB,CAAA;UAClD,kBAAC,UAAD;WAAQ,OAAM;qBAAc;WAAoB,CAAA;UAChD,kBAAC,UAAD;WAAQ,OAAM;qBAAS;WAAe,CAAA;UAC/B;;QACC,CAAA;OAGZ,kBAAC,GAAD;QAAW,OAAM;kBACf,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,SAAD;UACE,WAAW,EACT,+FACA,MAAqB,gBACjB,0CACA,+CACL;oBANH,CAQE,kBAAC,SAAD;WACE,MAAK;WACL,MAAK;WACL,OAAM;WACN,SAAS,MAAqB;WAC9B,gBAAgB,EAAoB,cAAc;WAClD,WAAU;WACV,CAAA,EACF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAsB;WAA4B,CAAA,EAC/D,kBAAC,KAAD;WAAG,WAAU;qBAA8B;WAAqC,CAAA,CAC5E,EAAA,CAAA,CACA;aACR,kBAAC,SAAD;UACE,WAAW,EACT,+FACA,MAAqB,WACjB,0CACA,+CACL;oBANH,CAQE,kBAAC,SAAD;WACE,MAAK;WACL,MAAK;WACL,OAAM;WACN,SAAS,MAAqB;WAC9B,gBAAgB,EAAoB,SAAS;WAC7C,WAAU;WACV,CAAA,EACF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAsB;WAAiB,CAAA,EACpD,kBAAC,KAAD;WAAG,WAAU;qBAA8B;WAA+B,CAAA,CACtE,EAAA,CAAA,CACA;YACJ;;QACI,CAAA;OAGX,MAAqB,iBACpB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,6CAA8C,CAAA,EAC/D,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,KAAD;aAAG,WAAU;uBAAsB;aAA0B,CAAA;YAC7D,kBAAC,KAAD;aAAG,WAAU;uBAA8B;aAGvC,CAAA;YACJ,kBAAC,OAAD;aAAK,WAAU;uBACb,kBAAC,GAAD;cACE,SAAQ;cACR,MAAK;cACL,eAAe;AACb,sBAAO,KAAK,6BAA6B,SAAS;;wBAJtD,CAOE,kBAAC,GAAD;eAAc,MAAM;eAAI,WAAU;eAAW,CAAA,EAAA,oBAEtC;;aACL,CAAA;YACF;aACF;;SACF,CAAA,EACN,kBAAC,GAAD;SAAW,OAAM;mBACf,kBAAC,GAAD;UACE,aAAY;UACZ,OAAO;UACP,WAAW,MAAM,EAAgB,EAAE,OAAO,MAAM;UAChD,CAAA;SACQ,CAAA,CACR;;OAIP,MAAqB,YACpB,kBAAC,GAAD;QAAW,OAAM;kBACf,kBAAC,GAAD;SACE,MAAK;SACL,aAAY;SACZ,OAAO;SACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;SAC1C,CAAA;QACQ,CAAA;OAGd,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SACE,UAAU,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;SAC5B,WAAW;SACX,UAAU,MAAqB,WAAW,CAAC,IAAS,CAAC;SACrD,SAAS,YAAY;AACnB,cAAI;WACF,IAAM,IACJ,EAAqB,OAAO,EAAE,CAAC,aAAa,GAAG,EAAqB,MAAM,EAAE,EAKxE,IACJ,MAAqB,gBACjB,KAAA,IACA,IACE,EAAE,WAAQ,GACV,KAAA,GACF,IACJ,MAAqB,gBAAgB,IAAe,KAAA;AAwBtD,WAtBI,IACF,MAAM,EACJ;YACE,MAAM;YACN,MAAM,EAAe,EAAqB;YAC1C,cAAc;YACd;YACD,EACD,EACD,GAED,MAAM,EAAkB;YACtB,MAAM;YACN,MAAM,EAAe,EAAqB;YAC1C,cAAc;YACd;YACD,CAAC,EAGJ,EAAU,GAAG,EACb,EAAgB,GAAG,EACnB,EAAqB,KAAK,EAC1B,MAAM,GAAkB;WACxB,IAAM,IACJ,EAAqB,OAAO,EAAE,CAAC,aAAa,GAAG,EAAqB,MAAM,EAAE;AAC9E,aAAM,QACJ,IACI,GAAG,EAAc,kCACjB,GAAG,EAAc,8BACtB;mBACM,GAAc;WACrB,IAAM,IAAU,aAAe,QAAQ,EAAI,UAAU;AACrD,aAAM,MAAM,EAAQ;;;mBAIvB,IAAoB,oBAAoB;SAClC,CAAA,EACR,KACC,kBAAC,GAAD;SACE,SAAQ;SACR,eAAe;AAKb,UAJA,EAAqB,KAAK,EAC1B,EAAU,GAAG,EACb,EAAgB,GAAG,EACnB,EAAoB,SAAS,EAC7B,EAAwB,SAAS;;mBAEpC;SAEQ,CAAA,CAEP;;OACM;QACT;;IACH;;EACK,CAAA"}
|
|
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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"}
|