@digitalsingularity/agent-ui-chat-components
Version:
Reusable UI components for agent chat and management interfaces
1,358 lines (1,357 loc) • 181 kB
JavaScript
import { jsx as e, jsxs as t, Fragment as Oe } from "react/jsx-runtime";
import { forwardRef as Mt, createElement as vt, useState as O, useRef as Ye, useCallback as w, useEffect as Ce, useMemo as ct } from "react";
const Ca = () => `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`, Ta = (r = {}) => {
const c = r.endpoint || "/api/ai-agents/generate-avatar", N = r.credentials || "include", $ = {
"Content-Type": "application/json",
...r.headers
};
return async (f, x) => {
const U = await fetch(c, {
method: "POST",
headers: $,
credentials: N,
body: JSON.stringify({
prompt: f,
agentName: x
})
});
if (!U.ok)
throw new Error(`Failed to generate avatar: ${U.status} ${U.statusText}`);
const z = await U.json();
if (!z.success || !z.imageUrl)
throw new Error("Invalid response format from avatar generation service");
return {
imageUrl: z.imageUrl
};
};
}, Sa = (r = 2e3) => async (c, N) => {
await new Promise((z) => setTimeout(z, r));
const $ = 200, f = Math.floor(Math.random() * 16777215).toString(16), x = "ffffff", U = encodeURIComponent((N == null ? void 0 : N.substring(0, 2).toUpperCase()) || "AI");
return {
imageUrl: `https://via.placeholder.com/${$}x${$}/${f}/${x}?text=${U}`
};
};
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const ia = (r) => r.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), ra = (r) => r.replace(
/^([A-Z])|[\s-_]+(\w)/g,
(c, N, $) => $ ? $.toUpperCase() : N.toLowerCase()
), zt = (r) => {
const c = ra(r);
return c.charAt(0).toUpperCase() + c.slice(1);
}, Ot = (...r) => r.filter((c, N, $) => !!c && c.trim() !== "" && $.indexOf(c) === N).join(" ").trim(), sa = (r) => {
for (const c in r)
if (c.startsWith("aria-") || c === "role" || c === "title")
return !0;
};
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
var la = {
xmlns: "http://www.w3.org/2000/svg",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: 2,
strokeLinecap: "round",
strokeLinejoin: "round"
};
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const oa = Mt(
({
color: r = "currentColor",
size: c = 24,
strokeWidth: N = 2,
absoluteStrokeWidth: $,
className: f = "",
children: x,
iconNode: U,
...z
}, A) => vt(
"svg",
{
ref: A,
...la,
width: c,
height: c,
stroke: r,
strokeWidth: $ ? Number(N) * 24 / Number(c) : N,
className: Ot("lucide", f),
...!x && !sa(z) && { "aria-hidden": "true" },
...z
},
[
...U.map(([I, E]) => vt(I, E)),
...Array.isArray(x) ? x : [x]
]
)
);
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const dt = (r, c) => {
const N = Mt(
({ className: $, ...f }, x) => vt(oa, {
ref: x,
iconNode: c,
className: Ot(
`lucide-${ia(zt(r))}`,
`lucide-${r}`,
$
),
...f
})
);
return N.displayName = zt(r), N;
};
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const ca = [
["path", { d: "M12 8V4H8", key: "hb8ula" }],
["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
["path", { d: "M2 14h2", key: "vft8re" }],
["path", { d: "M20 14h2", key: "4cs60a" }],
["path", { d: "M15 13v2", key: "1xurst" }],
["path", { d: "M9 13v2", key: "rq6x2g" }]
], ft = dt("bot", ca);
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const da = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]], ua = dt("loader-circle", da);
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const ma = [
[
"path",
{
d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",
key: "1ffxy3"
}
],
["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
], pa = dt("send", ma);
/**
* @license lucide-react v0.511.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/
const ha = [
["path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2", key: "975kel" }],
["circle", { cx: "12", cy: "7", r: "4", key: "17ys0d" }]
], ga = dt("user", ha), ka = ({
agent: r,
isOpen: c,
onClose: N,
uiComponents: $,
agentService: f,
toastService: x,
className: U = "",
maxMessages: z = 100,
enableHistory: A = !0
}) => {
const [I, E] = O([]), [K, ce] = O(""), [j, F] = O(!1), [C, _] = O(null), L = Ye(null), de = Ye(null), Y = Ye(null);
let u = null;
const {
Dialog: q,
DialogContent: D,
DialogHeader: b,
DialogTitle: R,
DialogDescription: G,
Button: P,
Input: ie,
ScrollArea: ee,
Avatar: te,
AvatarFallback: ue,
AvatarImage: B
} = $, p = w((m) => `agent_chat_history_${m}`, []), Z = w(() => {
if (!(!r || I.length === 0 || !A))
try {
const m = p(r.id);
localStorage.setItem(m, JSON.stringify(I));
} catch (m) {
console.error("Error saving chat history:", m);
}
}, [r, I, p, A]), V = w(() => {
if (!(!r || !A))
try {
const m = p(r.id), X = localStorage.getItem(m);
if (X) {
const se = JSON.parse(X);
E(se.slice(-z));
}
} catch (m) {
console.error("Error loading chat history:", m), r && localStorage.removeItem(p(r.id));
}
}, [r, p, A, z]), o = w(() => {
if (r)
try {
const m = p(r.id);
localStorage.removeItem(m), E([]);
} catch (m) {
console.error("Error clearing chat history:", m);
}
}, [r, p]), T = async () => {
try {
if (f.getUserAvatar) {
const m = await f.getUserAvatar();
_(m);
}
} catch (m) {
console.error("Error fetching user profile:", m);
}
}, ae = w(() => {
de.current && de.current.focus();
}, []), k = w(() => {
if (L.current) {
const m = L.current.querySelector("div[data-radix-scroll-area-viewport]");
m && requestAnimationFrame(() => {
m.scrollTop = m.scrollHeight;
});
}
}, []);
Ce(() => {
setTimeout(() => k(), 50);
}, [I, k]), Ce(() => {
I.length > 0 && !j && Z();
}, [I, j, Z]), Ce(() => {
c && r && (I.length === 0 && V(), T());
}, [c, r, V, I.length]), Ce(() => {
var m, X;
return c && r ? (ce(""), F(!1), (m = Y.current) == null || m.abort()) : (X = Y.current) == null || X.abort(), () => {
var se;
(se = Y.current) == null || se.abort();
};
}, [c, r]);
const ne = async () => {
if (!r) return;
const m = K.trim();
if (!m || j) return;
const X = {
id: Date.now().toString(),
role: "user",
content: m
};
E((Q) => [...Q, X]), ce(""), F(!0), Y.current = new AbortController(), u = (Date.now() + 1).toString();
let se = "", le = !1;
try {
await f.sendMessage(
m,
r.id,
// onChunk
(Q) => {
se += Q, le ? E(
(l) => l.map(
(i) => i.id === u ? { ...i, content: se } : i
)
) : (E((l) => [
...l,
{ id: u, role: "assistant", content: se }
]), le = !0);
},
// onError
(Q) => {
console.error("Error sending message:", Q), x == null || x.toast({
title: "Chat Error",
description: `Failed to send message: ${Q.message}`,
variant: "destructive"
});
},
// onCompletion
() => {
F(!1), Y.current = null, u = null, setTimeout(() => k(), 0), setTimeout(() => ae(), 100);
}
);
} catch (Q) {
Q.name !== "AbortError" && (console.error("Error sending message:", Q), x == null || x.toast({
title: "Chat Error",
description: `Failed to send message: ${Q.message}`,
variant: "destructive"
})), F(!1), Y.current = null, u = null;
}
}, re = (m) => {
m.key === "Enter" && !m.shiftKey && (m.preventDefault(), ne());
};
return !c || !r ? null : /* @__PURE__ */ e(q, { open: c, onOpenChange: N, children: /* @__PURE__ */ t(
D,
{
className: `sm:max-w-[600px] md:max-w-[700px] lg:max-w-[800px] flex flex-col max-h-[90vh] ${U}`,
id: "agent-chat-modal-content",
"data-testid": "agent-chat-modal",
"data-component": "AgentChatModal",
"data-agent-id": r == null ? void 0 : r.id,
children: [
/* @__PURE__ */ e(
b,
{
id: "agent-chat-modal-header",
"data-testid": "agent-chat-modal-header",
"data-component": "chat-header",
children: /* @__PURE__ */ t(
"div",
{
className: "flex items-center gap-3",
id: "agent-chat-modal-agent-info",
"data-testid": "agent-info-section",
"data-component": "agent-info",
children: [
/* @__PURE__ */ e(
te,
{
className: "h-10 w-10",
"data-testid": "agent-avatar",
"data-component": "agent-avatar",
children: r.avatarUrl ? /* @__PURE__ */ e(B, { src: r.avatarUrl, alt: r.name }) : /* @__PURE__ */ e(ue, { children: /* @__PURE__ */ e(ft, { size: 24 }) })
}
),
/* @__PURE__ */ t("div", { className: "flex-1", children: [
/* @__PURE__ */ t("div", { className: "flex items-center justify-between", children: [
/* @__PURE__ */ t(R, { children: [
"Chat with Agent: ",
r.name
] }),
A && I.length > 0 && /* @__PURE__ */ e(
P,
{
variant: "outline",
size: "sm",
onClick: o,
className: "text-xs mr-10",
id: "agent-chat-clear-history-btn",
"data-testid": "clear-history-button",
"data-component": "clear-history",
"data-action": "clear-conversation",
children: "Clear History"
}
)
] }),
/* @__PURE__ */ t(G, { children: [
"Model: ",
r.model,
r.temperature && `, Temperature: ${r.temperature.toFixed(1)}`
] })
] })
]
}
)
}
),
/* @__PURE__ */ e(
ee,
{
className: "flex-grow border rounded-md p-4 h-[50vh] bg-background",
ref: L,
id: "agent-chat-messages-area",
"data-testid": "chat-messages-area",
"data-component": "messages-container",
children: /* @__PURE__ */ t(
"div",
{
className: "space-y-4",
id: "agent-chat-messages-container",
"data-testid": "messages-list",
"data-component": "messages-list",
children: [
I.map((m) => /* @__PURE__ */ t(
"div",
{
className: `flex items-start gap-3 ${m.role === "user" ? "justify-end" : ""}`,
id: `agent-chat-message-${m.id}`,
"data-testid": `chat-message-${m.role}`,
"data-component": "chat-message",
"data-message-id": m.id,
"data-message-role": m.role,
children: [
m.role === "assistant" && /* @__PURE__ */ e(
te,
{
className: "h-8 w-8",
"data-testid": "message-assistant-avatar",
"data-component": "message-avatar",
"data-avatar-role": "assistant",
children: r.avatarUrl ? /* @__PURE__ */ e(B, { src: r.avatarUrl, alt: r.name }) : /* @__PURE__ */ e(ue, { children: /* @__PURE__ */ e(ft, { size: 18 }) })
}
),
/* @__PURE__ */ e(
"div",
{
className: `rounded-lg p-3 text-sm max-w-[75%] whitespace-pre-wrap break-words ${m.role === "user" ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
"data-testid": "message-content",
"data-component": "message-bubble",
"data-content-role": m.role,
children: m.content
}
),
m.role === "user" && /* @__PURE__ */ e(
te,
{
className: "h-8 w-8",
"data-testid": "message-user-avatar",
"data-component": "message-avatar",
"data-avatar-role": "user",
children: C ? /* @__PURE__ */ e(B, { src: C, alt: "User" }) : /* @__PURE__ */ e(ue, { children: /* @__PURE__ */ e(ga, { size: 18 }) })
}
)
]
},
m.id
)),
j && !I.some((m) => m.role === "assistant" && m.id === u) && /* @__PURE__ */ t(
"div",
{
className: "flex items-start gap-3",
"data-testid": "loading-message",
"data-component": "loading-indicator",
"data-state": "loading",
children: [
/* @__PURE__ */ e(
te,
{
className: "h-8 w-8",
"data-testid": "loading-avatar",
"data-component": "loading-avatar",
children: r.avatarUrl ? /* @__PURE__ */ e(B, { src: r.avatarUrl, alt: r.name }) : /* @__PURE__ */ e(ue, { children: /* @__PURE__ */ e(ft, { size: 18 }) })
}
),
/* @__PURE__ */ e("div", { className: "rounded-lg p-3 text-sm bg-muted text-muted-foreground", children: /* @__PURE__ */ e(ua, { className: "h-4 w-4 animate-spin" }) })
]
}
)
]
}
)
}
),
/* @__PURE__ */ t(
"div",
{
className: "flex items-center p-1 pt-0 gap-2 border-t pt-4",
id: "agent-chat-input-area",
"data-testid": "chat-input-area",
"data-component": "input-section",
children: [
/* @__PURE__ */ e(
ie,
{
ref: de,
placeholder: "Type your message...",
value: K,
onChange: (m) => ce(m.target.value),
onKeyDown: re,
disabled: j,
className: "flex-grow",
id: "agent-chat-message-input",
"data-testid": "message-input",
"data-component": "message-input",
"data-state": j ? "disabled" : "enabled"
}
),
/* @__PURE__ */ e(
P,
{
onClick: ne,
disabled: j || !K.trim(),
size: "icon",
id: "agent-chat-send-btn",
"data-testid": "send-message-button",
"data-component": "send-button",
"data-action": "send-message",
"data-state": j || !K.trim() ? "disabled" : "enabled",
children: /* @__PURE__ */ e(pa, { className: "h-4 w-4" })
}
)
]
}
)
]
}
) });
}, Et = [
"Formal",
"Creative",
"Technical",
"Friendly",
"Professional",
"Concise",
"Detailed",
"Humorous",
"Serious",
"Analytical"
], It = ({
agentData: r,
setData: c,
documents: N,
handleFileChange: $,
removeFile: f,
isEditDialogOpen: x,
agentDocuments: U,
isLoadingDocuments: z,
handleDeleteDocument: A,
deleteDocumentMutation: I,
personalityOptions: E,
customTag: K,
setCustomTag: ce,
handleAddTag: j,
handleRemoveTag: F,
handleSelectTag: C,
avatarFile: _,
handleAvatarChange: L,
handleGenerateAvatar: de,
isGeneratingAvatar: Y,
avatarPrompt: u,
setAvatarPrompt: q,
showSharingOption: D = !1,
// UI Components
Label: b,
Input: R,
Textarea: G,
Button: P,
Select: ie,
SelectTrigger: ee,
SelectValue: te,
SelectContent: ue,
SelectItem: B,
Slider: p,
Badge: Z,
Tabs: V,
TabsList: o,
TabsTrigger: T,
TabsContent: ae,
Checkbox: k,
Upload: ne,
Bot: re,
Loader2: m,
X,
Trash2: se
}) => {
var le, Q;
return /* @__PURE__ */ t(Oe, { children: [
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ e(b, { htmlFor: "name", children: "Nume Agent" }),
/* @__PURE__ */ e(
R,
{
id: "agent-name-input",
value: r.name || "",
onChange: (l) => {
c((i) => ({ ...i, name: l.target.value }));
},
placeholder: "Ex: Asistent Documente Legale"
}
)
] }),
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ e(b, { children: "Avatar Agent" }),
/* @__PURE__ */ t("div", { className: "flex gap-4 items-start", children: [
/* @__PURE__ */ e("div", { className: "w-24 h-24 bg-muted rounded-md overflow-hidden flex items-center justify-center", id: "agent-avatar-preview", children: r.avatarUrl ? /* @__PURE__ */ e(
"img",
{
src: r.avatarUrl,
alt: `Avatar for ${r.name || "agent"}`,
className: "w-full h-full object-cover"
}
) : _ ? /* @__PURE__ */ e(
"img",
{
src: URL.createObjectURL(_),
alt: "Avatar preview",
className: "w-full h-full object-cover"
}
) : /* @__PURE__ */ e(re, { className: "w-12 h-12 text-muted-foreground" }) }),
/* @__PURE__ */ e("div", { className: "flex-1 space-y-2", children: /* @__PURE__ */ t(V, { defaultValue: "upload", className: "w-full", children: [
/* @__PURE__ */ t(o, { className: "grid w-full grid-cols-2", children: [
/* @__PURE__ */ e(T, { value: "upload", children: "Încarcă Imagine" }),
/* @__PURE__ */ e(T, { value: "generate", children: "Generează cu AI" })
] }),
/* @__PURE__ */ t(ae, { value: "upload", className: "space-y-2", children: [
/* @__PURE__ */ e(R, { id: "agent-avatar-upload-input", type: "file", accept: "image/*", onChange: L, className: "hidden" }),
/* @__PURE__ */ e(P, { asChild: !0, variant: "outline", className: "w-full", id: "agent-avatar-upload-button", children: /* @__PURE__ */ t(b, { htmlFor: "agent-avatar-upload-input", className: "cursor-pointer flex items-center justify-center gap-1", children: [
/* @__PURE__ */ e(ne, { className: "h-4 w-4" }),
" Selectează Imagine"
] }) }),
_ && /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: _.name })
] }),
/* @__PURE__ */ t(ae, { value: "generate", className: "space-y-2", children: [
/* @__PURE__ */ t("div", { className: "flex gap-2", children: [
/* @__PURE__ */ e(
R,
{
id: "agent-avatar-prompt-input",
placeholder: "Prompt pentru generare avatar",
value: u,
onChange: (l) => q(l.target.value)
}
),
/* @__PURE__ */ e(
P,
{
id: "agent-avatar-generate-button",
onClick: de,
disabled: Y || !r.name,
variant: "outline",
children: Y ? /* @__PURE__ */ e(m, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ e(re, { className: "h-4 w-4" })
}
)
] }),
/* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: "Generarea poate dura câteva secunde. Se va folosi numele agentului ca referință." })
] })
] }) })
] })
] }),
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ e(b, { htmlFor: "description", children: "Descriere (Opțional)" }),
/* @__PURE__ */ e(
G,
{
id: "agent-description-textarea",
value: r.description || "",
onChange: (l) => c((i) => ({ ...i, description: l.target.value })),
placeholder: "Ex: Ajută la crearea și revizuirea contractelor"
}
)
] }),
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ e(b, { htmlFor: "systemInstruction", children: "Instrucțiune Sistem" }),
/* @__PURE__ */ e(
G,
{
id: "agent-system-instruction-textarea",
value: r.systemInstruction || "",
onChange: (l) => c((i) => ({ ...i, systemInstruction: l.target.value })),
placeholder: "Ex: Ești un asistent AI specializat în documente legale...",
rows: 5
}
)
] }),
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ e(b, { htmlFor: "model", children: "Model AI" }),
/* @__PURE__ */ t(
ie,
{
value: r.model || "gpt-4",
onValueChange: (l) => c((i) => ({ ...i, model: l })),
children: [
/* @__PURE__ */ e(ee, { children: /* @__PURE__ */ e(te, { placeholder: "Selectează Model" }) }),
/* @__PURE__ */ t(ue, { children: [
/* @__PURE__ */ e(B, { value: "gpt-4o", children: "GPT-4o (Recomandat)" }),
/* @__PURE__ */ e(B, { value: "gpt-4-turbo", children: "GPT-4 Turbo" }),
/* @__PURE__ */ e(B, { value: "gpt-4", children: "GPT-4" }),
/* @__PURE__ */ e(B, { value: "gpt-3.5-turbo", children: "GPT-3.5 Turbo" })
] })
]
}
)
] }),
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ t(b, { htmlFor: "temperature", children: [
"Temperatură: ",
(le = r.temperature) == null ? void 0 : le.toFixed(1)
] }),
/* @__PURE__ */ e(
p,
{
id: "agent-temperature-slider",
min: 0,
max: 1,
step: 0.1,
value: [r.temperature || 0.7],
onValueChange: (l) => c((i) => ({ ...i, temperature: l[0] }))
}
),
/* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: "Controlați caracterul aleatoriu: valori mai mici pentru răspunsuri mai concentrate." })
] }),
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ e(b, { children: "Etichete Personalitate (Opțional)" }),
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-2", children: E.map((l) => {
var i;
return /* @__PURE__ */ e(
Z,
{
variant: (i = r.personalityTags) != null && i.includes(l) ? "default" : "secondary",
onClick: () => C(l),
className: "cursor-pointer",
children: l
},
l
);
}) }),
/* @__PURE__ */ t("div", { className: "flex gap-2 mt-2", children: [
/* @__PURE__ */ e(
R,
{
placeholder: "Adaugă etichetă personalizată",
value: K,
onChange: (l) => ce(l.target.value),
onKeyDown: (l) => {
l.key === "Enter" && (l.preventDefault(), j());
}
}
),
/* @__PURE__ */ e(P, { onClick: j, variant: "outline", size: "sm", children: "Adaugă" })
] }),
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1 mt-1", children: (Q = r.personalityTags) == null ? void 0 : Q.map((l) => /* @__PURE__ */ t(Z, { variant: "outline", children: [
l,
/* @__PURE__ */ e(X, { className: "ml-1 h-3 w-3 cursor-pointer", onClick: () => F(l) })
] }, l)) })
] }),
/* @__PURE__ */ t("div", { className: "grid gap-2", children: [
/* @__PURE__ */ e(b, { htmlFor: "documents", children: "Documente Context (Opțional)" }),
x && U && U.length > 0 && /* @__PURE__ */ t("div", { className: "mt-2 space-y-2", id: "agent-documents-list", children: [
/* @__PURE__ */ e("h4", { className: "text-sm font-medium", children: "Documente Încărcate:" }),
z && /* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: "Se încarcă documentele..." }),
/* @__PURE__ */ e("ul", { className: "list-disc pl-5 text-sm", children: U.map((l) => /* @__PURE__ */ t("li", { className: "flex items-center justify-between", children: [
/* @__PURE__ */ t("span", { title: l.fileName, children: [
l.fileName.length > 40 ? `${l.fileName.substring(0, 37)}...` : l.fileName,
" (",
l.fileSize ? (l.fileSize / 1024).toFixed(1) : "0",
" KB)"
] }),
/* @__PURE__ */ e(
P,
{
variant: "ghost",
size: "icon",
className: "h-6 w-6",
onClick: () => A(l.id),
disabled: I.isPending,
id: `agent-document-delete-${l.id}`,
children: /* @__PURE__ */ e(se, { className: "h-4 w-4 text-red-500" })
}
)
] }, l.id)) })
] }),
!x && N.length > 0 && /* @__PURE__ */ t("div", { className: "mt-2 space-y-2", id: "agent-staged-documents-list", children: [
/* @__PURE__ */ e("h4", { className: "text-sm font-medium", children: "Documente Pregătite:" }),
/* @__PURE__ */ e("ul", { className: "list-disc pl-5 text-sm", children: N.map((l, i) => /* @__PURE__ */ t("li", { className: "flex items-center justify-between", children: [
/* @__PURE__ */ e("span", { title: l.name, children: l.name.length > 40 ? `${l.name.substring(0, 37)}...` : l.name }),
/* @__PURE__ */ e(P, { variant: "ghost", size: "icon", className: "h-6 w-6", onClick: () => f(i), id: `agent-staged-document-delete-${i}`, children: /* @__PURE__ */ e(X, { className: "h-4 w-4 text-red-500" }) })
] }, i)) })
] }),
/* @__PURE__ */ t("div", { className: "flex items-center gap-2 mt-2", children: [
/* @__PURE__ */ e(R, { id: "agent-document-upload-input", type: "file", multiple: !0, onChange: $, className: "hidden" }),
/* @__PURE__ */ e(P, { asChild: !0, variant: "outline", id: "agent-document-upload-button", children: /* @__PURE__ */ t(b, { htmlFor: "agent-document-upload-input", className: "cursor-pointer flex items-center gap-1", children: [
/* @__PURE__ */ e(ne, { className: "h-4 w-4" }),
" Încarcă Documente"
] }) })
] }),
/* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: "Formate suportate pentru extragerea contextului: .txt, .pdf, .docx. Primii 10.000 de caractere din fiecare document vor fi utilizați." })
] }),
D && /* @__PURE__ */ t("div", { className: "flex items-center space-x-2 border p-3 rounded-md bg-muted/20", children: [
/* @__PURE__ */ e(
k,
{
id: "agent-share-checkbox",
checked: !!r.isPublic,
onCheckedChange: (l) => c((i) => ({ ...i, isPublic: l === !0 }))
}
),
/* @__PURE__ */ t("div", { className: "grid gap-1.5 leading-none", children: [
/* @__PURE__ */ t(b, { htmlFor: "agent-share-checkbox", className: "text-sm font-medium leading-none flex items-center", children: [
"Partajează cu toți utilizatorii",
r.isPublic && /* @__PURE__ */ e(Z, { variant: "outline", className: "ml-2 text-xs", children: "Public" })
] }),
/* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: "Alți utilizatori vor putea vedea și folosi acest agent AI, dar nu îl vor putea modifica." })
] })
] })
] });
}, Pa = (r) => {
const {
useLocation: c,
useMutation: N,
useQueryClient: $,
useAiAgents: f,
createAiAgent: x,
updateAiAgent: U,
deleteAiAgent: z,
uploadAiAgentDocument: A,
deleteAiAgentDocument: I,
useAiAgentDocuments: E,
aiAgentKeys: K,
uploadAiAgentAvatar: ce,
generateAiAgentAvatar: j,
shareAiAgent: F,
Card: C,
CardHeader: _,
CardTitle: L,
CardDescription: de,
CardContent: Y,
Table: u,
TableHeader: q,
TableRow: D,
TableHead: b,
TableBody: R,
TableCell: G,
Dialog: P,
DialogContent: ie,
DialogHeader: ee,
DialogTitle: te,
DialogDescription: ue,
DialogFooter: B,
Button: p,
AlertDialog: Z,
AlertDialogAction: V,
AlertDialogCancel: o,
AlertDialogContent: T,
AlertDialogDescription: ae,
AlertDialogFooter: k,
AlertDialogHeader: ne,
AlertDialogTitle: re,
Select: m,
SelectContent: X,
SelectItem: se,
SelectTrigger: le,
SelectValue: Q,
Input: l,
Label: i,
Textarea: Te,
Checkbox: g,
Badge: Ne,
Tabs: he,
TabsContent: ve,
TabsList: Se,
TabsTrigger: $e,
Loader2: be,
Trash2: Ee,
Edit: ze,
Upload: Ie,
X: De,
Bot: S,
MessageSquare: oe,
AlertCircle: Ue,
Share2: xe,
useToast: Fe,
AgentChatModal: je,
Tooltip: Me,
TooltipContent: ke,
TooltipProvider: Ge,
TooltipTrigger: ge,
Slider: Ke,
Alert: qe,
AlertDescription: s,
AlertTitle: a,
ProfileMenu: d,
Avatar: v,
AvatarImage: H,
AvatarFallback: W,
agentService: Be,
toastService: Le,
uiComponents: J
} = r, [ye, we] = O(!1), [fe, rt] = O(!1), [Ut, ut] = O(!1), [y, Pe] = O(null), [Ae, Ze] = O({
name: "",
description: "",
systemInstruction: "",
temperature: 0.7,
model: "gpt-4o",
personalityTags: []
}), [st, Ve] = O([]), [Qe, mt] = O(""), [Ft, Nt] = O(!1), [jt, Lt] = O(null), [Re, Xe] = O(null), [He, pt] = O(""), [xt, yt] = O(!1), { toast: me } = Fe(), _e = $(), [, Rt] = c(), [We, Gt] = O("all"), Kt = w((n) => {
Ze(n);
}, []), _t = w((n) => {
Pe(n);
}, []);
Ce(() => {
window.location.hash === "#create" && we(!0);
}, []);
const {
data: et,
isLoading: qt,
isError: Bt,
error: ht
} = f(), Vt = (y == null ? void 0 : y.id) ?? "", {
data: Qt,
isLoading: Ht,
refetch: bt
} = E(Vt);
Ce(() => {
fe && y && bt();
}, [fe, y, bt]);
const gt = N({
mutationFn: ({ agentId: n, file: h }) => A(n, h),
onSuccess: (n, h) => {
_e.invalidateQueries({ queryKey: ["agentDocuments", h.agentId] }), me({
title: "Document încărcat",
description: `Documentul "${h.file.name}" a fost încărcat.`,
// Use file name from variables
variant: "default"
});
},
onError: (n, h) => {
me({
title: "Eroare Încărcare Document",
description: `Nu s-a putut încărca documentul "${h.file.name}": ${n.message}`,
variant: "destructive"
});
}
}), lt = N({
mutationFn: ({ agentId: n, documentId: h }) => I(n, h),
onSuccess: (n, h) => {
_e.invalidateQueries({ queryKey: ["agentDocuments", h.agentId] }), me({
title: "Document șters",
description: "Documentul a fost șters cu succes.",
variant: "default"
});
},
onError: (n) => {
me({
title: "Eroare Ștergere Document",
description: `Nu s-a putut șterge documentul: ${n.message}`,
variant: "destructive"
});
}
}), tt = N({
mutationFn: ({ id: n, agentData: h }) => U(n, h),
onSuccess: (n) => {
_e.invalidateQueries({ queryKey: K.lists() }), rt(!1), Pe(null), me({
title: "Agent actualizat",
description: `Agentul "${n.name}" a fost actualizat cu succes.`,
variant: "default"
});
},
onError: (n) => {
me({
title: "Eroare Actualizare Agent",
description: `Nu s-a putut actualiza agentul: ${n.message}`,
variant: "destructive"
});
}
}), at = N({
mutationFn: (n) => z(n),
onSuccess: () => {
_e.invalidateQueries({ queryKey: K.lists() }), ut(!1), Pe(null), me({
title: "Agent șters",
description: "Agentul a fost șters cu succes.",
variant: "default"
});
},
onError: (n) => {
me({
title: "Eroare Ștergere Agent",
description: `Nu s-a putut șterge agentul: ${n.message}`,
variant: "destructive"
});
}
}), nt = N({
mutationFn: ({ id: n, isPublic: h }) => F(n, h),
onSuccess: (n) => {
_e.invalidateQueries({ queryKey: K.lists() }), me({
title: n.isPublic ? "Agent partajat" : "Agent privat",
description: n.isPublic ? `Agentul "${n.name}" este acum disponibil pentru toți utilizatorii.` : `Agentul "${n.name}" este acum privat.`,
variant: "default"
});
},
onError: (n) => {
console.error("[Share] Error:", n), me({
title: "Eroare",
description: `Nu s-a putut schimba starea de partajare: ${n.message || "Eroare necunoscută"}`,
variant: "destructive"
});
}
}), it = N({
mutationFn: async (n) => {
const h = {
...n,
description: n.description || null,
temperature: n.temperature ?? 0.7,
model: n.model || "gpt-4o",
personalityTags: n.personalityTags || []
};
return x(h);
},
onSuccess: (n) => {
const h = n.id;
if (_e.invalidateQueries({ queryKey: K.lists() }), st.length > 0 && h) {
const M = st.map(
(pe) => gt.mutateAsync({ agentId: h, file: pe })
);
Promise.allSettled(M).then((pe) => {
const Je = pe.filter((na) => na.status === "rejected");
Je.length > 0 && (console.error("Some documents failed to upload:", Je), me({
title: "Eroare Încărcare Documente",
description: `Nu s-au putut încărca ${Je.length} documente.`,
variant: "destructive"
}));
});
}
Re && h ? ce(h, Re).then((M) => {
console.log("Avatar uploaded successfully:", M), _e.invalidateQueries({ queryKey: K.detail(h) });
}).catch((M) => {
console.error("Failed to upload avatar:", M), me({
title: "Eroare Încărcare Avatar",
description: `Nu s-a putut încărca avatar-ul: ${M.message}`,
variant: "destructive"
});
}) : He && h && !Re && j(h, He).then((M) => {
console.log("Avatar generated successfully:", M), _e.invalidateQueries({ queryKey: K.detail(h) });
}).catch((M) => {
console.error("Failed to generate avatar:", M), me({
title: "Eroare Generare Avatar",
description: `Nu s-a putut genera avatar-ul: ${M.message}`,
variant: "destructive"
});
}), Ze({
name: "",
description: "",
systemInstruction: "",
temperature: 0.7,
model: "gpt-4o",
personalityTags: []
}), Ve([]), Xe(null), pt(""), we(!1), me({
title: "Agent creat",
description: `Agentul "${n.name}" a fost creat cu succes.`,
variant: "default"
});
},
onError: (n) => {
me({
title: "Eroare Creare Agent",
description: `Nu s-a putut crea agentul: ${n.message}`,
variant: "destructive"
});
}
}), Jt = w(() => {
if (!Ae.name || !Ae.systemInstruction) {
me({ title: "Eroare", description: "Numele agentului și instrucțiunea de sistem sunt obligatorii.", variant: "destructive" });
return;
}
it.mutate(Ae);
}, [Ae, me, it]), Yt = w(() => {
y && tt.mutate({ id: y.id, agentData: y });
}, [y, tt]), Zt = w(() => {
y && at.mutate(y.id);
}, [y, at]), wt = w((n) => {
if (n.target.files) {
const h = Array.from(n.target.files);
fe && y ? h.forEach((M) => {
gt.mutate({ agentId: y.id, file: M });
}) : Ve((M) => [...M, ...h]), n.target.value = "";
}
}, [fe, y, gt]), At = w((n) => {
Ve((h) => h.filter((M, pe) => pe !== n));
}, []), Xt = w((n) => {
y && lt.mutate({ agentId: y.id, documentId: n });
}, [y, lt]), Wt = w((n) => {
Pe({ ...n }), Ve([]), rt(!0);
}, []), ea = w((n) => {
Lt(n), Nt(!0);
}, []), Ct = w(() => {
var n;
if (Qe && !((n = Ae.personalityTags) != null && n.includes(Qe))) {
const h = [...Ae.personalityTags || [], Qe];
fe && y ? Pe((M) => M ? { ...M, personalityTags: h } : null) : Ze((M) => ({ ...M, personalityTags: h })), mt("");
}
}, [Qe, Ae.personalityTags, fe, y]), Tt = w((n) => {
fe && y ? Pe((h) => {
var M;
return h ? { ...h, personalityTags: ((M = h.personalityTags) == null ? void 0 : M.filter((pe) => pe !== n)) || [] } : null;
}) : Ze((h) => {
var M;
return { ...h, personalityTags: ((M = h.personalityTags) == null ? void 0 : M.filter((pe) => pe !== n)) || [] };
});
}, [fe, y]), St = w((n) => {
if (fe && y) {
const h = y.personalityTags || [], M = h.includes(n) ? h.filter((pe) => pe !== n) : [...h, n];
Pe((pe) => pe ? { ...pe, personalityTags: M } : null);
} else {
const h = Ae.personalityTags || [], M = h.includes(n) ? h.filter((pe) => pe !== n) : [...h, n];
Ze((pe) => ({ ...pe, personalityTags: M }));
}
}, [fe, y, Ae.personalityTags]), kt = w((n) => {
if (n.target.files && n.target.files[0]) {
const h = n.target.files[0];
Xe(h), n.target.value = "";
}
}, []), Pt = w(async () => {
if (!y && !Ae.name) return;
yt(!0);
const n = He || `A professional avatar for an AI agent named ${(y == null ? void 0 : y.name) || Ae.name}`;
try {
if (fe && y) {
const h = await j(y.id, n);
Pe((M) => M ? { ...M, avatarUrl: h.avatarUrl, avatarType: "generated", avatarPrompt: n } : null), me({
title: "Avatar Generat",
description: "Avatar-ul a fost generat cu succes.",
variant: "default"
});
}
} catch (h) {
me({
title: "Eroare Generare Avatar",
description: `Nu s-a putut genera avatar-ul: ${h.message}`,
variant: "destructive"
});
} finally {
yt(!1);
}
}, [y, Ae.name, He, fe, j, me]), ta = async () => {
if (!(!Re || !y))
try {
const n = await ce(y.id, Re);
Pe((h) => h ? { ...h, avatarUrl: n.avatarUrl, avatarType: "uploaded" } : null), Xe(null), me({
title: "Avatar Încărcat",
description: "Avatar-ul a fost încărcat cu succes.",
variant: "default"
});
} catch (n) {
me({
title: "Eroare Încărcare Avatar",
description: `Nu s-a putut încărca avatar-ul: ${n.message}`,
variant: "destructive"
});
}
};
Ce(() => {
Re && y && fe && ta();
}, [Re, y, fe]);
const $t = ct(() => {
if (!et) return [];
switch (We) {
case "own":
return et.filter((n) => n.isOwner);
case "public":
return et.filter((n) => n.isPublic && !n.isOwner);
default:
return et;
}
}, [et, We]), aa = w((n) => {
nt.mutate({ id: n.id, isPublic: !n.isPublic });
}, [nt]);
if (Bt) {
const n = (ht == null ? void 0 : ht.message) || "Unknown error";
return n.includes("Daily AI usage limit") ? /* @__PURE__ */ e("div", { className: "container mx-auto p-4 md:p-6 flex items-center justify-center h-[calc(100vh-200px)]", children: /* @__PURE__ */ t(qe, { variant: "destructive", className: "max-w-lg", children: [
/* @__PURE__ */ e(Ue, { className: "h-4 w-4" }),
/* @__PURE__ */ e(a, { children: "Tovarășe! Ați Atins Norma Zilnică!" }),
/* @__PURE__ */ t(s, { className: "flex flex-col gap-3 mt-2", children: [
/* @__PURE__ */ e("p", { children: "Entuziasmul în muncă este apreciat, dar resursele trebuie folosite judicios. Limita planului actual a fost atinsă. Te rog sa revii in 24 de ore sau sa optezi pentru un pachet superior." }),
/* @__PURE__ */ e(
"a",
{
href: "/billing",
onClick: (M) => {
M.preventDefault(), Rt("/billing");
},
className: "w-fit text-blue-600 underline hover:text-blue-800 font-medium",
children: "Solicită Aprobare Resurse. Vezi Pachete"
}
)
] })
] }) }) : /* @__PURE__ */ t("div", { className: "text-red-500", children: [
"Eroare la încărcarea agenților: ",
n
] });
}
return qt ? /* @__PURE__ */ t("div", { className: "flex items-center justify-center h-[calc(100vh-200px)]", children: [
/* @__PURE__ */ e(be, { className: "h-8 w-8 animate-spin text-primary" }),
/* @__PURE__ */ e("span", { className: "ml-2", children: "Se încarcă agenții..." })
] }) : /* @__PURE__ */ e(Ge, { children: /* @__PURE__ */ t(
"div",
{
className: "container mx-auto py-8",
id: "agents-page-container",
"data-testid": "agents-page",
"data-component": "AgentsPage",
children: [
/* @__PURE__ */ t(
"div",
{
className: "flex justify-between items-center mb-6",
"data-testid": "page-header",
"data-component": "page-header",
children: [
/* @__PURE__ */ e("div", { children: /* @__PURE__ */ e(
"h1",
{
className: "text-3xl font-bold",
id: "agents-header-title",
"data-testid": "page-title",
"data-component": "page-title",
children: "Management Agenți AI"
}
) }),
/* @__PURE__ */ e("div", { className: "flex items-center gap-4 ml-auto", children: /* @__PURE__ */ e(
"div",
{
className: "hidden md:flex",
id: "agents-profile-menu",
"data-testid": "profile-menu-container",
"data-component": "profile-menu",
children: /* @__PURE__ */ e(d, {})
}
) })
]
}
),
/* @__PURE__ */ e(P, { open: ye, onOpenChange: we, children: /* @__PURE__ */ t(
ie,
{
className: "sm:max-w-[600px]",
id: "agent-create-dialog",
"data-testid": "create-agent-dialog",
"data-component": "create-dialog",
children: [
/* @__PURE__ */ t(ee, { children: [
/* @__PURE__ */ e(te, { children: "Creează Agent Nou" }),
/* @__PURE__ */ e(ue, { children: "Configurați detaliile pentru noul agent AI." })
] }),
/* @__PURE__ */ e(
"div",
{
className: "grid gap-4 py-4 max-h-[70vh] overflow-y-auto px-2",
id: "agent-create-form",
"data-testid": "create-form-container",
"data-component": "form-container",
children: /* @__PURE__ */ e(
It,
{
agentData: Ae,
setData: Kt,
documents: st,
setDocuments: Ve,
handleFileChange: wt,
removeFile: At,
isEditDialogOpen: !1,
isLoadingDocuments: !1,
handleDeleteDocument: () => {
},
deleteDocumentMutation: lt,
personalityOptions: Et,
customTag: Qe,
setCustomTag: mt,
handleAddTag: Ct,
handleRemoveTag: Tt,
handleSelectTag: St,
avatarFile: Re,
setAvatarFile: Xe,
handleAvatarChange: kt,
handleGenerateAvatar: Pt,
isGeneratingAvatar: xt,
avatarPrompt: He,
setAvatarPrompt: pt,
Label: i,
Input: l,
Textarea: Te,
Button: p,
Select: m,
SelectTrigger: le,
SelectValue: Q,
SelectContent: X,
SelectItem: se,
Slider: Ke,
Badge: Ne,
Tabs: he,
TabsList: Se,
TabsTrigger: $e,
TabsContent: ve,
Checkbox: g,
Upload: Ie,
Bot: S,
Loader2: be,
X: De,
Trash2: Ee
}
)
}
),
/* @__PURE__ */ t(B, { children: [
/* @__PURE__ */ e(
p,
{
type: "button",
variant: "secondary",
onClick: () => we(!1),
id: "agent-cancel-button",
"data-testid": "cancel-create-button",
"data-component": "cancel-button",
"data-action": "cancel-create",
children: "Anulează"
}
),
/* @__PURE__ */ e(
p,
{
type: "submit",
onClick: Jt,
disabled: it.isPending || !Ae.name || !Ae.systemInstruction,
id: "agent-submit-button",
"data-testid": "submit-create-button",
"data-component": "submit-button",
"data-action": "submit-create",
"data-state": it.isPending ? "loading" : "idle",
children: it.isPending ? /* @__PURE__ */ t(Oe, { children: [
/* @__PURE__ */ e(be, { className: "mr-2 h-4 w-4 animate-spin" }),
" Se creează..."
] }) : "Creează Agent"
}
)
] })
]
}
) }),
/* @__PURE__ */ e(P, { open: fe, onOpenChange: (n) => {
rt(n), n || Pe(null);
}, children: /* @__PURE__ */ t(
ie,
{
className: "sm:max-w-[600px]",
id: "agent-edit-dialog",
"data-testid": "edit-agent-dialog",
"data-component": "edit-dialog",
children: [
/* @__PURE__ */ t(ee, { children: [
/* @__PURE__ */ t(te, { children: [
"Modifică Agent: ",
y == null ? void 0 : y.name
] }),
/* @__PURE__ */ e(ue, { children: "Actualizați detaliile agentului AI existent." })
] }),
/* @__PURE__ */ e(
"div",
{
className: "grid gap-4 py-4 max-h-[70vh] overflow-y-auto px-2",
id: "agent-edit-form",
"data-testid": "edit-form-container",
"data-component": "form-container",
children: y && /* @__PURE__ */ e(
It,
{
agentData: y,
setData: _t,
documents: st,
setDocuments: Ve,
handleFileChange: wt,
removeFile: At,
isEditDialogOpen: !0,
agentDocuments: Qt,
isLoadingDocuments: Ht,
handleDeleteDocument: Xt,
deleteDocumentMutation: lt,
personalityOptions: Et,
customTag: Qe,
setCustomTag: mt,
handleAddTag: Ct,