@burdenoff/microfe-botmanor 2026.819.1 → 2026.925.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/botlit/BotlitRoutes.js.map +1 -1
  2. package/dist/botlit/BotmanorRoot.js.map +1 -1
  3. package/dist/botlit/BotmanorRootInner.js +4 -4
  4. package/dist/botlit/BotmanorRootInner.js.map +1 -1
  5. package/dist/botlit/components/ErrorState.js +33 -29
  6. package/dist/botlit/components/ErrorState.js.map +1 -1
  7. package/dist/botlit/components/RouteLoader.js +52 -48
  8. package/dist/botlit/components/RouteLoader.js.map +1 -1
  9. package/dist/botlit/components/VersionHistoryPanel.js +74 -77
  10. package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
  11. package/dist/botlit/components/WorkspaceRequired.js +31 -30
  12. package/dist/botlit/components/WorkspaceRequired.js.map +1 -1
  13. package/dist/botlit/hooks/internal/workspaceGateway.js.map +1 -1
  14. package/dist/botlit/hooks/useConversations.js.map +1 -1
  15. package/dist/botlit/hooks/useLLMProviders.js.map +1 -1
  16. package/dist/botlit/hooks/useMCPServers.js +60 -49
  17. package/dist/botlit/hooks/useMCPServers.js.map +1 -1
  18. package/dist/botlit/pages/A2AAgentDetailPage.js +1 -1
  19. package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -1
  20. package/dist/botlit/pages/A2ARegistryPage.js +116 -124
  21. package/dist/botlit/pages/A2ARegistryPage.js.map +1 -1
  22. package/dist/botlit/pages/AgentDetailPage.js +169 -172
  23. package/dist/botlit/pages/AgentDetailPage.js.map +1 -1
  24. package/dist/botlit/pages/AgentsListPage.js +96 -90
  25. package/dist/botlit/pages/AgentsListPage.js.map +1 -1
  26. package/dist/botlit/pages/BotChannelsTab.js.map +1 -1
  27. package/dist/botlit/pages/BotDetailPage.js +228 -231
  28. package/dist/botlit/pages/BotDetailPage.js.map +1 -1
  29. package/dist/botlit/pages/BotWorkflowTab.js +84 -87
  30. package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
  31. package/dist/botlit/pages/BotsListPage.js +144 -147
  32. package/dist/botlit/pages/BotsListPage.js.map +1 -1
  33. package/dist/botlit/pages/BucketsPage.js +3 -3
  34. package/dist/botlit/pages/BucketsPage.js.map +1 -1
  35. package/dist/botlit/pages/ChannelDetailPage.js +1 -1
  36. package/dist/botlit/pages/ChannelDetailPage.js.map +1 -1
  37. package/dist/botlit/pages/ChannelsPage.js +156 -149
  38. package/dist/botlit/pages/ChannelsPage.js.map +1 -1
  39. package/dist/botlit/pages/ChatPage.js +126 -129
  40. package/dist/botlit/pages/ChatPage.js.map +1 -1
  41. package/dist/botlit/pages/DashboardPage.js +111 -114
  42. package/dist/botlit/pages/DashboardPage.js.map +1 -1
  43. package/dist/botlit/pages/ExecutionsPage.js +163 -159
  44. package/dist/botlit/pages/ExecutionsPage.js.map +1 -1
  45. package/dist/botlit/pages/InstalledPackagesPage.js +3 -3
  46. package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -1
  47. package/dist/botlit/pages/KnowledgeBasesPage.js +84 -78
  48. package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -1
  49. package/dist/botlit/pages/MCPServerDetailPage.js +295 -238
  50. package/dist/botlit/pages/MCPServerDetailPage.js.map +1 -1
  51. package/dist/botlit/pages/MCPServersPage.js +159 -154
  52. package/dist/botlit/pages/MCPServersPage.js.map +1 -1
  53. package/dist/botlit/pages/PoliciesPage.js +119 -114
  54. package/dist/botlit/pages/PoliciesPage.js.map +1 -1
  55. package/dist/botlit/pages/RetrievalProfilesPage.js +102 -109
  56. package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -1
  57. package/dist/botlit/pages/SettingsPage.js +144 -159
  58. package/dist/botlit/pages/SettingsPage.js.map +1 -1
  59. package/dist/botlit/pages/SkillsPage.js +122 -105
  60. package/dist/botlit/pages/SkillsPage.js.map +1 -1
  61. package/dist/botlit/pages/StorePage.js +176 -175
  62. package/dist/botlit/pages/StorePage.js.map +1 -1
  63. package/dist/botlit/providers/BotlitProvider.js.map +1 -1
  64. package/dist/botlit/store/botlitStore.js +1 -1
  65. package/dist/botlit/store/botlitStore.js.map +1 -1
  66. package/dist/botlit/utils/navigation.js.map +1 -1
  67. package/dist/generated/wspace-operations.js +45 -29
  68. package/dist/generated/wspace-operations.js.map +1 -1
  69. package/dist/generated/wspace-types.js.map +1 -1
  70. package/dist/shared/hooks/useTr.js +14 -0
  71. package/dist/shared/hooks/useTr.js.map +1 -0
  72. package/package.json +33 -9
@@ -1,55 +1,52 @@
1
- import { useBotlit as e } from "../providers/BotlitProvider.js";
2
- import { useAgents as t } from "../hooks/useAgents.js";
3
- import { useSendMessage as n } from "../hooks/useConversations.js";
4
- import { cn as r } from "../utils/cn.js";
5
- import { PageLayout as i } from "../components/PageLayout.js";
6
- import { Card as a, CardContent as o } from "../components/Card.js";
7
- import { Button as s } from "../components/Button.js";
8
- import { Badge as c } from "../components/Badge.js";
9
- import { Textarea as l } from "../components/Input.js";
10
- import { QuotaExhaustedDialog as u } from "../components/QuotaExhaustedDialog.js";
11
- import { useEffect as d, useRef as f, useState as p } from "react";
12
- import { IllustratedEmptyState as m, PagePurpose as h } from "@burdenoff/fe-libs/ui";
13
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
14
- import { useNavigate as v, useParams as y } from "react-router";
15
- import { isQuotaExhaustedError as b } from "@burdenoff/fe-libs/shared/utils";
16
- import { ArrowLeft as x, Bot as S, Loader2 as C, RefreshCw as w, Send as T, Settings as E, User as D } from "lucide-react";
17
- import { useI18n as O } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
1
+ import { useTr as e } from "../../shared/hooks/useTr.js";
2
+ import { useBotlit as t } from "../providers/BotlitProvider.js";
3
+ import { useAgents as n } from "../hooks/useAgents.js";
4
+ import { useSendMessage as r } from "../hooks/useConversations.js";
5
+ import { cn as i } from "../utils/cn.js";
6
+ import { PageLayout as a } from "../components/PageLayout.js";
7
+ import { Card as o, CardContent as s } from "../components/Card.js";
8
+ import { Button as c } from "../components/Button.js";
9
+ import { Badge as l } from "../components/Badge.js";
10
+ import { Textarea as u } from "../components/Input.js";
11
+ import { QuotaExhaustedDialog as d } from "../components/QuotaExhaustedDialog.js";
12
+ import { useEffect as f, useRef as p, useState as m } from "react";
13
+ import { IllustratedEmptyState as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
14
+ import { jsx as _, jsxs as v } from "react/jsx-runtime";
15
+ import { useNavigate as y, useParams as b } from "react-router";
16
+ import { isQuotaExhaustedError as x } from "@burdenoff/fe-libs/shared/utils";
17
+ import { ArrowLeft as S, Bot as C, Loader2 as w, RefreshCw as T, Send as E, Settings as D, User as O } from "lucide-react";
18
18
  //#region src/botlit/pages/ChatPage.tsx
19
19
  var k = () => {
20
- let { t: k } = O(), A = (e, t) => {
21
- let n = k(e);
22
- return n === e ? t : n;
23
- }, { agentId: j } = y(), M = v(), { navigate: N } = e(), { data: P } = t(), { sendMessage: F, isSending: I } = n(), [L, R] = p(j || ""), [z, B] = p(""), [V, H] = p([]), [U, W] = p(), [G, K] = p(!1), q = f(null), J = () => {
24
- if (N) {
25
- N("/billing");
20
+ let k = e(), { agentId: A } = b(), j = y(), { navigate: M } = t(), { data: N } = n(), { sendMessage: P, isSending: F } = r(), [I, L] = m(A || ""), [R, z] = m(""), [B, V] = m([]), [H, U] = m(), [W, G] = m(!1), K = p(null), q = () => {
21
+ if (M) {
22
+ M("/billing");
26
23
  return;
27
24
  }
28
25
  window.location.assign("/billing");
29
- }, Y = () => {
30
- q.current?.scrollIntoView({ behavior: "smooth" });
26
+ }, J = () => {
27
+ K.current?.scrollIntoView({ behavior: "smooth" });
31
28
  };
32
- d(() => {
33
- Y();
34
- }, [V]), d(() => {
35
- j && R(j);
36
- }, [j]);
37
- let X = async () => {
38
- if (!z.trim() || !L) return;
29
+ f(() => {
30
+ J();
31
+ }, [B]), f(() => {
32
+ A && L(A);
33
+ }, [A]);
34
+ let Y = async () => {
35
+ if (!R.trim() || !I) return;
39
36
  let e = {
40
37
  id: `user-${Date.now()}`,
41
38
  role: "user",
42
- content: z,
39
+ content: R,
43
40
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
44
41
  };
45
- H((t) => [...t, e]), B("");
42
+ V((t) => [...t, e]), z("");
46
43
  try {
47
- let e = await F({
48
- conversationId: U,
49
- agentId: L,
50
- content: z
44
+ let e = await P({
45
+ conversationId: H,
46
+ agentId: I,
47
+ content: R
51
48
  });
52
- e.conversationId && W(e.conversationId);
49
+ e.conversationId && U(e.conversationId);
53
50
  let t = {
54
51
  id: `assistant-${e.executionId}`,
55
52
  role: "assistant",
@@ -58,82 +55,82 @@ var k = () => {
58
55
  model: e.model ?? void 0,
59
56
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
60
57
  };
61
- H((e) => [...e, t]);
58
+ V((e) => [...e, t]);
62
59
  } catch (e) {
63
- if (b(e)) {
64
- K(!0);
60
+ if (x(e)) {
61
+ G(!0);
65
62
  return;
66
63
  }
67
64
  let t = {
68
65
  id: `error-${Date.now()}`,
69
66
  role: "assistant",
70
- content: `${A("botlit.chat.send.errorPrefix", "Error")}: ${e instanceof Error ? e.message : A("botlit.chat.send.errorFallback", "Failed to send message")}`,
67
+ content: `${k("botlit.chat.send.errorPrefix", "Error")}: ${e instanceof Error ? e.message : k("botlit.chat.send.errorFallback", "Failed to send message")}`,
71
68
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
72
69
  };
73
- H((e) => [...e, t]), console.error("Failed to send message:", e);
70
+ V((e) => [...e, t]), console.error("Failed to send message:", e);
74
71
  }
75
- }, Z = (e) => {
76
- e.key === "Enter" && !e.shiftKey && (e.preventDefault(), X());
77
- }, Q = () => {
78
- H([]), W(void 0);
79
- }, $ = P?.find((e) => e.id === L);
80
- return /* @__PURE__ */ g(i, {
81
- title: /* @__PURE__ */ _("div", {
72
+ }, X = (e) => {
73
+ e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Y());
74
+ }, Z = () => {
75
+ V([]), U(void 0);
76
+ }, Q = N?.find((e) => e.id === I);
77
+ return /* @__PURE__ */ _(a, {
78
+ title: /* @__PURE__ */ v("div", {
82
79
  className: "flex items-center gap-3",
83
- children: [/* @__PURE__ */ g(s, {
80
+ children: [/* @__PURE__ */ _(c, {
84
81
  variant: "ghost",
85
82
  size: "icon",
86
- onClick: () => M(-1),
87
- children: /* @__PURE__ */ g(x, { size: 20 })
88
- }), $ ? /* @__PURE__ */ _("span", { children: [
89
- A("botlit.chat.title.withAgent", "Chat with"),
83
+ onClick: () => j(-1),
84
+ children: /* @__PURE__ */ _(S, { size: 20 })
85
+ }), Q ? /* @__PURE__ */ v("span", { children: [
86
+ k("botlit.chat.title.withAgent", "Chat with"),
90
87
  " ",
91
- $.name
92
- ] }) : /* @__PURE__ */ g("span", { children: A("botlit.chat.title.default", "AI Chat") })]
88
+ Q.name
89
+ ] }) : /* @__PURE__ */ _("span", { children: k("botlit.chat.title.default", "AI Chat") })]
93
90
  }),
94
- actions: /* @__PURE__ */ _("div", {
91
+ actions: /* @__PURE__ */ v("div", {
95
92
  className: "flex gap-2",
96
- children: [/* @__PURE__ */ g(s, {
93
+ children: [/* @__PURE__ */ _(c, {
97
94
  variant: "outline",
98
95
  size: "sm",
99
- leftIcon: /* @__PURE__ */ g(w, { size: 14 }),
100
- onClick: Q,
101
- children: A("botlit.chat.actions.newChat", "New Chat")
102
- }), L && /* @__PURE__ */ g(s, {
96
+ leftIcon: /* @__PURE__ */ _(T, { size: 14 }),
97
+ onClick: Z,
98
+ children: k("botlit.chat.actions.newChat", "New Chat")
99
+ }), I && /* @__PURE__ */ _(c, {
103
100
  variant: "outline",
104
101
  size: "sm",
105
- leftIcon: /* @__PURE__ */ g(E, { size: 14 }),
106
- children: /* @__PURE__ */ g("a", {
107
- href: `/agents/${L}`,
108
- children: A("botlit.chat.actions.agentSettings", "Agent Settings")
102
+ leftIcon: /* @__PURE__ */ _(D, { size: 14 }),
103
+ children: /* @__PURE__ */ _("a", {
104
+ href: `/agents/${I}`,
105
+ children: k("botlit.chat.actions.agentSettings", "Agent Settings")
109
106
  })
110
107
  })]
111
108
  }),
112
- children: /* @__PURE__ */ _("div", {
109
+ children: /* @__PURE__ */ v("div", {
113
110
  className: "flex flex-col h-[calc(100vh-220px)] max-w-4xl mx-auto",
114
111
  children: [
115
- /* @__PURE__ */ g(h, {
112
+ /* @__PURE__ */ _(g, {
116
113
  className: "mb-4",
117
- icon: /* @__PURE__ */ g(S, { size: 18 }),
118
- children: A("botlit.chat.purpose", "This is a live playground for talking to your agents. Pick an agent and chat with it exactly as a real user would — to sanity-check its answers, tone and tool use before you connect it to a bot or channel. Conversations here are throwaway tests, so experiment freely.")
114
+ icon: /* @__PURE__ */ _(C, { size: 18 }),
115
+ children: k("botlit.chat.purpose", "This is a live playground for talking to your agents. Pick an agent and chat with it exactly as a real user would — to sanity-check its answers, tone and tool use before you connect it to a bot or channel. Conversations here are throwaway tests, so experiment freely.")
119
116
  }),
120
- !j && /* @__PURE__ */ g(a, {
117
+ !A && /* @__PURE__ */ _(o, {
121
118
  className: "mb-4",
122
- children: /* @__PURE__ */ g(o, {
119
+ children: /* @__PURE__ */ _(s, {
123
120
  className: "py-4",
124
- children: /* @__PURE__ */ _("div", {
121
+ children: /* @__PURE__ */ v("div", {
125
122
  className: "flex items-center gap-4",
126
- children: [/* @__PURE__ */ g("label", {
123
+ children: [/* @__PURE__ */ _("label", {
127
124
  className: "text-sm font-medium",
128
- children: A("botlit.chat.selector.label", "Select Agent:")
129
- }), /* @__PURE__ */ _("select", {
125
+ children: k("botlit.chat.selector.label", "Select Agent:")
126
+ }), /* @__PURE__ */ v("select", {
130
127
  className: "flex h-10 flex-1 max-w-md rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm",
131
- value: L,
132
- onChange: (e) => R(e.target.value),
133
- children: [/* @__PURE__ */ g("option", {
128
+ value: I,
129
+ onChange: (e) => L(e.target.value),
130
+ children: [/* @__PURE__ */ _("option", {
134
131
  value: "",
135
- children: A("botlit.chat.selector.placeholder", "Choose an agent...")
136
- }), P?.filter((e) => e.status === "ACTIVE").map((e) => /* @__PURE__ */ g("option", {
132
+ children: k("botlit.chat.selector.placeholder", "Choose an agent...")
133
+ }), N?.filter((e) => e.status === "ACTIVE").map((e) => /* @__PURE__ */ _("option", {
137
134
  value: e.id,
138
135
  children: e.name
139
136
  }, e.id))]
@@ -141,101 +138,101 @@ var k = () => {
141
138
  })
142
139
  })
143
140
  }),
144
- /* @__PURE__ */ g(a, {
141
+ /* @__PURE__ */ _(o, {
145
142
  treatment: "glass",
146
143
  glow: !0,
147
144
  className: "flex-1 overflow-hidden",
148
- children: /* @__PURE__ */ _(o, {
145
+ children: /* @__PURE__ */ v(s, {
149
146
  className: "h-full flex flex-col p-0",
150
- children: [/* @__PURE__ */ _("div", {
147
+ children: [/* @__PURE__ */ v("div", {
151
148
  className: "flex-1 overflow-y-auto p-4 space-y-4",
152
149
  children: [
153
- V.length === 0 ? /* @__PURE__ */ g("div", {
150
+ B.length === 0 ? /* @__PURE__ */ _("div", {
154
151
  className: "flex h-full items-center justify-center",
155
- children: /* @__PURE__ */ g(m, {
152
+ children: /* @__PURE__ */ _(h, {
156
153
  illustration: "onboarding",
157
- title: A("botlit.chat.empty.title", "Start a Conversation"),
158
- description: L ? `${A("botlit.chat.empty.withAgentPrefix", "Type a message below to start chatting with")} ${$?.name || A("botlit.chat.empty.withAgentFallbackName", "the agent")}.` : A("botlit.chat.empty.noAgent", "Select an agent above to start chatting.")
154
+ title: k("botlit.chat.empty.title", "Start a Conversation"),
155
+ description: I ? `${k("botlit.chat.empty.withAgentPrefix", "Type a message below to start chatting with")} ${Q?.name || k("botlit.chat.empty.withAgentFallbackName", "the agent")}.` : k("botlit.chat.empty.noAgent", "Select an agent above to start chatting.")
159
156
  })
160
- }) : V.map((e) => /* @__PURE__ */ _("div", {
161
- className: r("flex gap-3", e.role === "user" ? "justify-end" : "justify-start"),
157
+ }) : B.map((e) => /* @__PURE__ */ v("div", {
158
+ className: i("flex gap-3", e.role === "user" ? "justify-end" : "justify-start"),
162
159
  children: [
163
- e.role !== "user" && /* @__PURE__ */ g("div", {
160
+ e.role !== "user" && /* @__PURE__ */ _("div", {
164
161
  className: "w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center flex-shrink-0",
165
- children: /* @__PURE__ */ g(S, { size: 16 })
162
+ children: /* @__PURE__ */ _(C, { size: 16 })
166
163
  }),
167
- /* @__PURE__ */ _("div", {
168
- className: r("max-w-[80%] rounded-lg px-4 py-3", e.role === "user" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken"),
169
- children: [/* @__PURE__ */ g("div", {
164
+ /* @__PURE__ */ v("div", {
165
+ className: i("max-w-[80%] rounded-lg px-4 py-3", e.role === "user" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-sunken"),
166
+ children: [/* @__PURE__ */ _("div", {
170
167
  className: "whitespace-pre-wrap text-sm",
171
168
  children: e.content
172
- }), e.tokensUsed != null && e.tokensUsed > 0 && /* @__PURE__ */ _("div", {
169
+ }), e.tokensUsed != null && e.tokensUsed > 0 && /* @__PURE__ */ v("div", {
173
170
  className: "mt-2 flex items-center gap-2 text-xs opacity-70",
174
- children: [/* @__PURE__ */ _(c, {
171
+ children: [/* @__PURE__ */ v(l, {
175
172
  variant: "outline",
176
173
  className: "text-[10px]",
177
174
  children: [
178
175
  e.tokensUsed,
179
176
  " ",
180
- A("botlit.chat.tokensLabel", "tokens")
177
+ k("botlit.chat.tokensLabel", "tokens")
181
178
  ]
182
- }), e.model && /* @__PURE__ */ g(c, {
179
+ }), e.model && /* @__PURE__ */ _(l, {
183
180
  variant: "outline",
184
181
  className: "text-[10px]",
185
182
  children: e.model
186
183
  })]
187
184
  })]
188
185
  }),
189
- e.role === "user" && /* @__PURE__ */ g("div", {
186
+ e.role === "user" && /* @__PURE__ */ _("div", {
190
187
  className: "w-8 h-8 rounded-full bg-secondary flex items-center justify-center flex-shrink-0",
191
- children: /* @__PURE__ */ g(D, { size: 16 })
188
+ children: /* @__PURE__ */ _(O, { size: 16 })
192
189
  })
193
190
  ]
194
191
  }, e.id)),
195
- I && /* @__PURE__ */ _("div", {
192
+ F && /* @__PURE__ */ v("div", {
196
193
  className: "flex gap-3",
197
- children: [/* @__PURE__ */ g("div", {
194
+ children: [/* @__PURE__ */ _("div", {
198
195
  className: "w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center",
199
- children: /* @__PURE__ */ g(S, { size: 16 })
200
- }), /* @__PURE__ */ g("div", {
196
+ children: /* @__PURE__ */ _(C, { size: 16 })
197
+ }), /* @__PURE__ */ _("div", {
201
198
  className: "bg-bg-sunken rounded-lg px-4 py-3",
202
- children: /* @__PURE__ */ g(C, { className: "h-5 w-5 animate-spin text-text-secondary" })
199
+ children: /* @__PURE__ */ _(w, { className: "h-5 w-5 animate-spin text-text-secondary" })
203
200
  })]
204
201
  }),
205
- /* @__PURE__ */ g("div", { ref: q })
202
+ /* @__PURE__ */ _("div", { ref: K })
206
203
  ]
207
- }), /* @__PURE__ */ _("div", {
204
+ }), /* @__PURE__ */ v("div", {
208
205
  className: "border-t border-border-subtle p-4",
209
- children: [/* @__PURE__ */ _("div", {
206
+ children: [/* @__PURE__ */ v("div", {
210
207
  className: "flex gap-2",
211
- children: [/* @__PURE__ */ g(l, {
212
- placeholder: L ? A("botlit.chat.input.placeholder", "Type your message...") : A("botlit.chat.input.disabledPlaceholder", "Select an agent to start chatting"),
213
- value: z,
214
- onChange: (e) => B(e.target.value),
215
- onKeyDown: Z,
216
- disabled: !L || I,
208
+ children: [/* @__PURE__ */ _(u, {
209
+ placeholder: I ? k("botlit.chat.input.placeholder", "Type your message...") : k("botlit.chat.input.disabledPlaceholder", "Select an agent to start chatting"),
210
+ value: R,
211
+ onChange: (e) => z(e.target.value),
212
+ onKeyDown: X,
213
+ disabled: !I || F,
217
214
  className: "min-h-[48px] max-h-[200px] resize-none",
218
215
  rows: 1
219
- }), /* @__PURE__ */ g(s, {
220
- onClick: X,
221
- disabled: !z.trim() || !L || I,
216
+ }), /* @__PURE__ */ _(c, {
217
+ onClick: Y,
218
+ disabled: !R.trim() || !I || F,
222
219
  size: "icon",
223
220
  className: "h-12 w-12",
224
- children: I ? /* @__PURE__ */ g(C, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ g(T, { size: 20 })
221
+ children: F ? /* @__PURE__ */ _(w, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ _(E, { size: 20 })
225
222
  })]
226
- }), /* @__PURE__ */ g("p", {
223
+ }), /* @__PURE__ */ _("p", {
227
224
  className: "text-xs text-text-secondary mt-2",
228
- children: A("botlit.chat.input.helper", "Press Enter to send, Shift+Enter for new line")
225
+ children: k("botlit.chat.input.helper", "Press Enter to send, Shift+Enter for new line")
229
226
  })]
230
227
  })]
231
228
  })
232
229
  }),
233
- /* @__PURE__ */ g(u, {
234
- open: G,
235
- title: A("botlit.usage.runQuota.title", "Bot Run Limit Reached"),
236
- description: A("botlit.usage.runQuota.description", "You have reached your bot run limit for this month."),
237
- onClose: () => K(!1),
238
- onViewBilling: J
230
+ /* @__PURE__ */ _(d, {
231
+ open: W,
232
+ title: k("botlit.usage.runQuota.title", "Bot Run Limit Reached"),
233
+ description: k("botlit.usage.runQuota.description", "You have reached your bot run limit for this month."),
234
+ onClose: () => G(!1),
235
+ onViewBilling: q
239
236
  })
240
237
  ]
241
238
  })
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPage.js","names":[],"sources":["../../../src/botlit/pages/ChatPage.tsx"],"sourcesContent":["/**\n * Chat Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState, useRef, useEffect } from 'react';\nimport { isQuotaExhaustedError } from '@burdenoff/fe-libs/shared/utils';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useParams, useNavigate } from 'react-router';\nimport { ArrowLeft, Send, Bot, User, Loader2, RefreshCw, Settings } from 'lucide-react';\nimport { PagePurpose, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardContent } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Textarea } from '../components/Input';\nimport { Badge } from '../components/Badge';\nimport { QuotaExhaustedDialog } from '../components/QuotaExhaustedDialog';\nimport { useAgents } from '../hooks/useAgents';\nimport { useSendMessage } from '../hooks/useConversations';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { cn } from '../utils/cn';\n\ninterface ChatMessage {\n id: string;\n role: 'user' | 'assistant';\n content: string;\n tokensUsed?: number;\n model?: string;\n createdAt: string;\n}\n\nexport const ChatPage: FC = () => {\n const { t: translate } = useI18n();\n const t = (key: string, fallback: string) => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const { agentId } = useParams();\n const navigate = useNavigate();\n const { navigate: shellNavigate } = useBotlit();\n const { data: agents } = useAgents();\n const { sendMessage, isSending } = useSendMessage();\n\n const [selectedAgentId, setSelectedAgentId] = useState(agentId || '');\n const [inputValue, setInputValue] = useState('');\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [conversationId, setConversationId] = useState<string | undefined>();\n const [showQuotaDialog, setShowQuotaDialog] = useState(false);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const handleViewBilling = () => {\n if (shellNavigate) {\n shellNavigate('/billing');\n return;\n }\n window.location.assign('/billing');\n };\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [messages]);\n\n useEffect(() => {\n if (agentId) {\n setSelectedAgentId(agentId);\n }\n }, [agentId]);\n\n const handleSend = async () => {\n if (!inputValue.trim() || !selectedAgentId) return;\n\n const userMessage: ChatMessage = {\n id: `user-${Date.now()}`,\n role: 'user',\n content: inputValue,\n createdAt: new Date().toISOString(),\n };\n\n setMessages((prev) => [...prev, userMessage]);\n setInputValue('');\n\n try {\n const result = await sendMessage({\n conversationId,\n agentId: selectedAgentId,\n content: inputValue,\n });\n\n // Track conversation ID for follow-up messages\n if (result.conversationId) {\n setConversationId(result.conversationId);\n }\n\n const assistantMessage: ChatMessage = {\n id: `assistant-${result.executionId}`,\n role: 'assistant',\n content: result.message,\n tokensUsed: result.tokensUsed ?? undefined,\n model: result.model ?? undefined,\n createdAt: new Date().toISOString(),\n };\n\n setMessages((prev) => [...prev, assistantMessage]);\n } catch (error) {\n if (isQuotaExhaustedError(error)) {\n setShowQuotaDialog(true);\n return;\n }\n // Add error message to chat\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n role: 'assistant',\n content: `${t('botlit.chat.send.errorPrefix', 'Error')}: ${error instanceof Error ? error.message : t('botlit.chat.send.errorFallback', 'Failed to send message')}`,\n createdAt: new Date().toISOString(),\n };\n setMessages((prev) => [...prev, errorMessage]);\n console.error('Failed to send message:', error);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n const handleReset = () => {\n setMessages([]);\n setConversationId(undefined);\n };\n\n const selectedAgent = agents?.find((a: { id: string }) => a.id === selectedAgentId);\n\n return (\n <PageLayout\n title={\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => navigate(-1)}>\n <ArrowLeft size={20} />\n </Button>\n {selectedAgent ? (\n <span>\n {t('botlit.chat.title.withAgent', 'Chat with')} {selectedAgent.name}\n </span>\n ) : (\n <span>{t('botlit.chat.title.default', 'AI Chat')}</span>\n )}\n </div>\n }\n actions={\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n leftIcon={<RefreshCw size={14} />}\n onClick={handleReset}\n >\n {t('botlit.chat.actions.newChat', 'New Chat')}\n </Button>\n {selectedAgentId && (\n <Button variant=\"outline\" size=\"sm\" leftIcon={<Settings size={14} />}>\n <a href={`/agents/${selectedAgentId}`}>\n {t('botlit.chat.actions.agentSettings', 'Agent Settings')}\n </a>\n </Button>\n )}\n </div>\n }\n >\n <div className=\"flex flex-col h-[calc(100vh-220px)] max-w-4xl mx-auto\">\n <PagePurpose className=\"mb-4\" icon={<Bot size={18} />}>\n {t(\n 'botlit.chat.purpose',\n 'This is a live playground for talking to your agents. Pick an agent and chat with it exactly as a real user would — to sanity-check its answers, tone and tool use before you connect it to a bot or channel. Conversations here are throwaway tests, so experiment freely.'\n )}\n </PagePurpose>\n\n {/* Agent Selector */}\n {!agentId && (\n <Card className=\"mb-4\">\n <CardContent className=\"py-4\">\n <div className=\"flex items-center gap-4\">\n <label className=\"text-sm font-medium\">\n {t('botlit.chat.selector.label', 'Select Agent:')}\n </label>\n <select\n className=\"flex h-10 flex-1 max-w-md rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={selectedAgentId}\n onChange={(e) => setSelectedAgentId(e.target.value)}\n >\n <option value=\"\">\n {t('botlit.chat.selector.placeholder', 'Choose an agent...')}\n </option>\n {agents\n ?.filter((a: { status: string }) => a.status === 'ACTIVE')\n .map((a: { id: string; name: string }) => (\n <option key={a.id} value={a.id}>\n {a.name}\n </option>\n ))}\n </select>\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Messages */}\n <Card treatment=\"glass\" glow className=\"flex-1 overflow-hidden\">\n <CardContent className=\"h-full flex flex-col p-0\">\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {messages.length === 0 ? (\n <div className=\"flex h-full items-center justify-center\">\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title={t('botlit.chat.empty.title', 'Start a Conversation')}\n description={\n selectedAgentId\n ? `${t('botlit.chat.empty.withAgentPrefix', 'Type a message below to start chatting with')} ${selectedAgent?.name || t('botlit.chat.empty.withAgentFallbackName', 'the agent')}.`\n : t('botlit.chat.empty.noAgent', 'Select an agent above to start chatting.')\n }\n />\n </div>\n ) : (\n messages.map((message) => (\n <div\n key={message.id}\n className={cn(\n 'flex gap-3',\n message.role === 'user' ? 'justify-end' : 'justify-start'\n )}\n >\n {message.role !== 'user' && (\n <div className=\"w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center flex-shrink-0\">\n <Bot size={16} />\n </div>\n )}\n <div\n className={cn(\n 'max-w-[80%] rounded-lg px-4 py-3',\n message.role === 'user'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken'\n )}\n >\n <div className=\"whitespace-pre-wrap text-sm\">{message.content}</div>\n {message.tokensUsed != null && message.tokensUsed > 0 && (\n <div className=\"mt-2 flex items-center gap-2 text-xs opacity-70\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {message.tokensUsed} {t('botlit.chat.tokensLabel', 'tokens')}\n </Badge>\n {message.model && (\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {message.model}\n </Badge>\n )}\n </div>\n )}\n </div>\n {message.role === 'user' && (\n <div className=\"w-8 h-8 rounded-full bg-secondary flex items-center justify-center flex-shrink-0\">\n <User size={16} />\n </div>\n )}\n </div>\n ))\n )}\n\n {isSending && (\n <div className=\"flex gap-3\">\n <div className=\"w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center\">\n <Bot size={16} />\n </div>\n <div className=\"bg-bg-sunken rounded-lg px-4 py-3\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input */}\n <div className=\"border-t border-border-subtle p-4\">\n <div className=\"flex gap-2\">\n <Textarea\n placeholder={\n selectedAgentId\n ? t('botlit.chat.input.placeholder', 'Type your message...')\n : t(\n 'botlit.chat.input.disabledPlaceholder',\n 'Select an agent to start chatting'\n )\n }\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n disabled={!selectedAgentId || isSending}\n className=\"min-h-[48px] max-h-[200px] resize-none\"\n rows={1}\n />\n <Button\n onClick={handleSend}\n disabled={!inputValue.trim() || !selectedAgentId || isSending}\n size=\"icon\"\n className=\"h-12 w-12\"\n >\n {isSending ? <Loader2 className=\"h-5 w-5 animate-spin\" /> : <Send size={20} />}\n </Button>\n </div>\n <p className=\"text-xs text-text-secondary mt-2\">\n {t('botlit.chat.input.helper', 'Press Enter to send, Shift+Enter for new line')}\n </p>\n </div>\n </CardContent>\n </Card>\n <QuotaExhaustedDialog\n open={showQuotaDialog}\n title={t('botlit.usage.runQuota.title', 'Bot Run Limit Reached')}\n description={t(\n 'botlit.usage.runQuota.description',\n 'You have reached your bot run limit for this month.'\n )}\n onClose={() => setShowQuotaDialog(false)}\n onViewBilling={handleViewBilling}\n />\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ChatPage.js","names":[],"sources":["../../../src/botlit/pages/ChatPage.tsx"],"sourcesContent":["/**\n * Chat Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState, useRef, useEffect } from 'react';\nimport { isQuotaExhaustedError } from '@burdenoff/fe-libs/shared/utils';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { useParams, useNavigate } from 'react-router';\nimport { ArrowLeft, Send, Bot, User, Loader2, RefreshCw, Settings } from 'lucide-react';\nimport { PagePurpose, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardContent } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Textarea } from '../components/Input';\nimport { Badge } from '../components/Badge';\nimport { QuotaExhaustedDialog } from '../components/QuotaExhaustedDialog';\nimport { useAgents } from '../hooks/useAgents';\nimport { useSendMessage } from '../hooks/useConversations';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { cn } from '../utils/cn';\n\ninterface ChatMessage {\n id: string;\n role: 'user' | 'assistant';\n content: string;\n tokensUsed?: number;\n model?: string;\n createdAt: string;\n}\n\nexport const ChatPage: FC = () => {\n const t = useTr();\n const { agentId } = useParams();\n const navigate = useNavigate();\n const { navigate: shellNavigate } = useBotlit();\n const { data: agents } = useAgents();\n const { sendMessage, isSending } = useSendMessage();\n\n const [selectedAgentId, setSelectedAgentId] = useState(agentId || '');\n const [inputValue, setInputValue] = useState('');\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [conversationId, setConversationId] = useState<string | undefined>();\n const [showQuotaDialog, setShowQuotaDialog] = useState(false);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const handleViewBilling = () => {\n if (shellNavigate) {\n shellNavigate('/billing');\n return;\n }\n window.location.assign('/billing');\n };\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [messages]);\n\n useEffect(() => {\n if (agentId) {\n setSelectedAgentId(agentId);\n }\n }, [agentId]);\n\n const handleSend = async () => {\n if (!inputValue.trim() || !selectedAgentId) return;\n\n const userMessage: ChatMessage = {\n id: `user-${Date.now()}`,\n role: 'user',\n content: inputValue,\n createdAt: new Date().toISOString(),\n };\n\n setMessages((prev) => [...prev, userMessage]);\n setInputValue('');\n\n try {\n const result = await sendMessage({\n conversationId,\n agentId: selectedAgentId,\n content: inputValue,\n });\n\n // Track conversation ID for follow-up messages\n if (result.conversationId) {\n setConversationId(result.conversationId);\n }\n\n const assistantMessage: ChatMessage = {\n id: `assistant-${result.executionId}`,\n role: 'assistant',\n content: result.message,\n tokensUsed: result.tokensUsed ?? undefined,\n model: result.model ?? undefined,\n createdAt: new Date().toISOString(),\n };\n\n setMessages((prev) => [...prev, assistantMessage]);\n } catch (error) {\n if (isQuotaExhaustedError(error)) {\n setShowQuotaDialog(true);\n return;\n }\n // Add error message to chat\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n role: 'assistant',\n content: `${t('botlit.chat.send.errorPrefix', 'Error')}: ${error instanceof Error ? error.message : t('botlit.chat.send.errorFallback', 'Failed to send message')}`,\n createdAt: new Date().toISOString(),\n };\n setMessages((prev) => [...prev, errorMessage]);\n console.error('Failed to send message:', error);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n const handleReset = () => {\n setMessages([]);\n setConversationId(undefined);\n };\n\n const selectedAgent = agents?.find((a: { id: string }) => a.id === selectedAgentId);\n\n return (\n <PageLayout\n title={\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={() => navigate(-1)}>\n <ArrowLeft size={20} />\n </Button>\n {selectedAgent ? (\n <span>\n {t('botlit.chat.title.withAgent', 'Chat with')} {selectedAgent.name}\n </span>\n ) : (\n <span>{t('botlit.chat.title.default', 'AI Chat')}</span>\n )}\n </div>\n }\n actions={\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n leftIcon={<RefreshCw size={14} />}\n onClick={handleReset}\n >\n {t('botlit.chat.actions.newChat', 'New Chat')}\n </Button>\n {selectedAgentId && (\n <Button variant=\"outline\" size=\"sm\" leftIcon={<Settings size={14} />}>\n <a href={`/agents/${selectedAgentId}`}>\n {t('botlit.chat.actions.agentSettings', 'Agent Settings')}\n </a>\n </Button>\n )}\n </div>\n }\n >\n <div className=\"flex flex-col h-[calc(100vh-220px)] max-w-4xl mx-auto\">\n <PagePurpose className=\"mb-4\" icon={<Bot size={18} />}>\n {t(\n 'botlit.chat.purpose',\n 'This is a live playground for talking to your agents. Pick an agent and chat with it exactly as a real user would — to sanity-check its answers, tone and tool use before you connect it to a bot or channel. Conversations here are throwaway tests, so experiment freely.'\n )}\n </PagePurpose>\n\n {/* Agent Selector */}\n {!agentId && (\n <Card className=\"mb-4\">\n <CardContent className=\"py-4\">\n <div className=\"flex items-center gap-4\">\n <label className=\"text-sm font-medium\">\n {t('botlit.chat.selector.label', 'Select Agent:')}\n </label>\n <select\n className=\"flex h-10 flex-1 max-w-md rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={selectedAgentId}\n onChange={(e) => setSelectedAgentId(e.target.value)}\n >\n <option value=\"\">\n {t('botlit.chat.selector.placeholder', 'Choose an agent...')}\n </option>\n {agents\n ?.filter((a: { status: string }) => a.status === 'ACTIVE')\n .map((a: { id: string; name: string }) => (\n <option key={a.id} value={a.id}>\n {a.name}\n </option>\n ))}\n </select>\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Messages */}\n <Card treatment=\"glass\" glow className=\"flex-1 overflow-hidden\">\n <CardContent className=\"h-full flex flex-col p-0\">\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {messages.length === 0 ? (\n <div className=\"flex h-full items-center justify-center\">\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title={t('botlit.chat.empty.title', 'Start a Conversation')}\n description={\n selectedAgentId\n ? `${t('botlit.chat.empty.withAgentPrefix', 'Type a message below to start chatting with')} ${selectedAgent?.name || t('botlit.chat.empty.withAgentFallbackName', 'the agent')}.`\n : t('botlit.chat.empty.noAgent', 'Select an agent above to start chatting.')\n }\n />\n </div>\n ) : (\n messages.map((message) => (\n <div\n key={message.id}\n className={cn(\n 'flex gap-3',\n message.role === 'user' ? 'justify-end' : 'justify-start'\n )}\n >\n {message.role !== 'user' && (\n <div className=\"w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center flex-shrink-0\">\n <Bot size={16} />\n </div>\n )}\n <div\n className={cn(\n 'max-w-[80%] rounded-lg px-4 py-3',\n message.role === 'user'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-sunken'\n )}\n >\n <div className=\"whitespace-pre-wrap text-sm\">{message.content}</div>\n {message.tokensUsed != null && message.tokensUsed > 0 && (\n <div className=\"mt-2 flex items-center gap-2 text-xs opacity-70\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {message.tokensUsed} {t('botlit.chat.tokensLabel', 'tokens')}\n </Badge>\n {message.model && (\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {message.model}\n </Badge>\n )}\n </div>\n )}\n </div>\n {message.role === 'user' && (\n <div className=\"w-8 h-8 rounded-full bg-secondary flex items-center justify-center flex-shrink-0\">\n <User size={16} />\n </div>\n )}\n </div>\n ))\n )}\n\n {isSending && (\n <div className=\"flex gap-3\">\n <div className=\"w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center\">\n <Bot size={16} />\n </div>\n <div className=\"bg-bg-sunken rounded-lg px-4 py-3\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input */}\n <div className=\"border-t border-border-subtle p-4\">\n <div className=\"flex gap-2\">\n <Textarea\n placeholder={\n selectedAgentId\n ? t('botlit.chat.input.placeholder', 'Type your message...')\n : t(\n 'botlit.chat.input.disabledPlaceholder',\n 'Select an agent to start chatting'\n )\n }\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n disabled={!selectedAgentId || isSending}\n className=\"min-h-[48px] max-h-[200px] resize-none\"\n rows={1}\n />\n <Button\n onClick={handleSend}\n disabled={!inputValue.trim() || !selectedAgentId || isSending}\n size=\"icon\"\n className=\"h-12 w-12\"\n >\n {isSending ? <Loader2 className=\"h-5 w-5 animate-spin\" /> : <Send size={20} />}\n </Button>\n </div>\n <p className=\"text-xs text-text-secondary mt-2\">\n {t('botlit.chat.input.helper', 'Press Enter to send, Shift+Enter for new line')}\n </p>\n </div>\n </CardContent>\n </Card>\n <QuotaExhaustedDialog\n open={showQuotaDialog}\n title={t('botlit.usage.runQuota.title', 'Bot Run Limit Reached')}\n description={t(\n 'botlit.usage.runQuota.description',\n 'You have reached your bot run limit for this month.'\n )}\n onClose={() => setShowQuotaDialog(false)}\n onViewBilling={handleViewBilling}\n />\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}