@infuro/cms-core 1.0.19 → 1.0.20
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/admin.cjs +534 -11
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.js +564 -23
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +727 -36
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +705 -18
- package/dist/api.js.map +1 -1
- package/dist/{index-GMn7-9PX.d.ts → index--GBYw5JE.d.ts} +84 -2
- package/dist/{index-D2C1O9b4.d.cts → index-DGtM2Gsk.d.cts} +84 -2
- package/dist/index.cjs +1701 -713
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -13
- package/dist/index.d.ts +99 -13
- package/dist/index.js +1554 -574
- package/dist/index.js.map +1 -1
- package/dist/migrations/1775300000000-LlmAgents.ts +57 -0
- package/dist/migrations/1775300000001-LlmAgentsValidationRulesText.ts +43 -0
- package/dist/migrations/1775300000002-SeedLlmAgentsPermissions.ts +33 -0
- package/dist/migrations/1775300000003-LlmAgentKnowledgeDocuments.ts +50 -0
- package/dist/migrations/1775400000000-KnowledgeBaseVectorDimension384.ts +32 -0
- package/package.json +8 -6
package/dist/admin.js
CHANGED
|
@@ -338,7 +338,8 @@ import {
|
|
|
338
338
|
ShoppingCart,
|
|
339
339
|
CreditCard,
|
|
340
340
|
Receipt,
|
|
341
|
-
FolderTree
|
|
341
|
+
FolderTree,
|
|
342
|
+
Bot
|
|
342
343
|
} from "lucide-react";
|
|
343
344
|
|
|
344
345
|
// src/admin/admin-config-context.tsx
|
|
@@ -351,7 +352,7 @@ var defaultValue = {
|
|
|
351
352
|
var AdminConfigContext = createContext(defaultValue);
|
|
352
353
|
|
|
353
354
|
// src/lib/cms-version.ts
|
|
354
|
-
var CMS_VERSION = true ? "1.0.
|
|
355
|
+
var CMS_VERSION = true ? "1.0.20" : "0.0.0";
|
|
355
356
|
|
|
356
357
|
// src/components/Admin/Sidebar.tsx
|
|
357
358
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -496,6 +497,10 @@ function AdminSidebar({ variant = "sidebar" }) {
|
|
|
496
497
|
/* @__PURE__ */ jsx4(Shield, { className: `h-4 w-4 mr-2 ${isActive("/admin/roles") ? iconActive : iconInactive}` }),
|
|
497
498
|
"Roles"
|
|
498
499
|
] }) }),
|
|
500
|
+
/* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsxs3(Link2, { href: "/admin/llm_agents", className: `${linkCls} ${isActive("/admin/llm_agents") ? linkActive : linkInactive}`, children: [
|
|
501
|
+
/* @__PURE__ */ jsx4(Bot, { className: `h-4 w-4 mr-2 ${isActive("/admin/llm_agents") ? iconActive : iconInactive}` }),
|
|
502
|
+
"LLM agents"
|
|
503
|
+
] }) }),
|
|
499
504
|
/* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsxs3(Link2, { href: "/admin/plugins", className: `${linkCls} ${isActive("/admin/plugins") ? linkActive : linkInactive}`, children: [
|
|
500
505
|
/* @__PURE__ */ jsx4(Puzzle, { className: `h-4 w-4 mr-2 ${isActive("/admin/plugins") ? iconActive : iconInactive}` }),
|
|
501
506
|
"Plugins"
|
|
@@ -880,7 +885,7 @@ function AdminShell({ children }) {
|
|
|
880
885
|
}
|
|
881
886
|
|
|
882
887
|
// src/components/Admin/CRUD.tsx
|
|
883
|
-
import { useEffect as useEffect6, useRef as useRef3, useState as useState8 } from "react";
|
|
888
|
+
import { useEffect as useEffect6, useMemo as useMemo2, useRef as useRef3, useState as useState8 } from "react";
|
|
884
889
|
|
|
885
890
|
// src/components/Admin/CreateEditForm.tsx
|
|
886
891
|
import { useState as useState6, useEffect as useEffect4 } from "react";
|
|
@@ -1363,7 +1368,9 @@ function CreateEditForm({ isOpen, onClose, apiEndpoint, columns, existingData })
|
|
|
1363
1368
|
if (existingData) {
|
|
1364
1369
|
setFormData(existingData);
|
|
1365
1370
|
} else {
|
|
1366
|
-
setFormData(
|
|
1371
|
+
setFormData(
|
|
1372
|
+
columns.filter((col) => !col.hideInForm).reduce((acc, col) => ({ ...acc, [col.field]: col.defaultValue || "" }), {})
|
|
1373
|
+
);
|
|
1367
1374
|
}
|
|
1368
1375
|
}, [existingData, columns]);
|
|
1369
1376
|
const handleChange = (e, field) => {
|
|
@@ -1377,7 +1384,7 @@ function CreateEditForm({ isOpen, onClose, apiEndpoint, columns, existingData })
|
|
|
1377
1384
|
};
|
|
1378
1385
|
const validateForm = () => {
|
|
1379
1386
|
let newErrors = {};
|
|
1380
|
-
columns.forEach((col) => {
|
|
1387
|
+
columns.filter((col) => !col.hideInForm).forEach((col) => {
|
|
1381
1388
|
if (col.validation?.required && !formData[col.field]) {
|
|
1382
1389
|
newErrors[col.field] = `${col.displayName} is required`;
|
|
1383
1390
|
}
|
|
@@ -1417,7 +1424,7 @@ Note: ${result.note}`);
|
|
|
1417
1424
|
/* @__PURE__ */ jsx17(Button, { type: "button", variant: "ghost", size: "icon", onClick: onClose, className: "h-8 w-8", "aria-label": "Close", children: /* @__PURE__ */ jsx17(X2, { className: "h-5 w-5" }) })
|
|
1418
1425
|
] }),
|
|
1419
1426
|
/* @__PURE__ */ jsxs11("form", { onSubmit: handleSubmit, className: "flex flex-col flex-1 min-h-0", children: [
|
|
1420
|
-
/* @__PURE__ */ jsx17("div", { className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-4", children: columns.map((col) => /* @__PURE__ */ jsxs11("div", { children: [
|
|
1427
|
+
/* @__PURE__ */ jsx17("div", { className: "flex-1 min-h-0 overflow-y-auto p-6 space-y-4", children: columns.filter((col) => !col.hideInForm).map((col) => /* @__PURE__ */ jsxs11("div", { children: [
|
|
1421
1428
|
/* @__PURE__ */ jsx17(Label3, { className: "block text-sm font-medium mb-1", children: col.displayName }),
|
|
1422
1429
|
col.relationApi ? /* @__PURE__ */ jsx17(
|
|
1423
1430
|
RelationAutocomplete,
|
|
@@ -1429,10 +1436,35 @@ Note: ${result.note}`);
|
|
|
1429
1436
|
valueField: col.relationValueField ?? "id",
|
|
1430
1437
|
placeholder: `Select ${col.displayName}`
|
|
1431
1438
|
}
|
|
1432
|
-
) : col.type === "textarea" ? /* @__PURE__ */ jsx17(
|
|
1439
|
+
) : col.type === "textarea" ? /* @__PURE__ */ jsx17(
|
|
1440
|
+
Textarea,
|
|
1441
|
+
{
|
|
1442
|
+
rows: typeof col.textareaRows === "number" ? col.textareaRows : 4,
|
|
1443
|
+
className: "min-h-[80px] font-mono text-sm",
|
|
1444
|
+
value: formData[col.field] ?? "",
|
|
1445
|
+
onChange: (e) => handleChange(e, col.field),
|
|
1446
|
+
placeholder: col.placeholder
|
|
1447
|
+
}
|
|
1448
|
+
) : col.type === "select" ? /* @__PURE__ */ jsxs11(Select, { onValueChange: (value) => setFormData({ ...formData, [col.field]: value }), children: [
|
|
1433
1449
|
/* @__PURE__ */ jsx17(SelectTrigger, { children: /* @__PURE__ */ jsx17(SelectValue, { placeholder: formData[col.field] || "Select an option" }) }),
|
|
1434
1450
|
/* @__PURE__ */ jsx17(SelectContent, { children: col.options?.map((option) => /* @__PURE__ */ jsx17(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1435
|
-
] }) : col.type === "boolean" ? /* @__PURE__ */ jsx17(Switch, { checked: formData[col.field] || false, onCheckedChange: () => handleToggleChange(col.field) }) : col.type === "date" ? /* @__PURE__ */ jsx17(Input, { type: "date", value: formData[col.field] || "", onChange: (e) => handleChange(e, col.field) }) : col.type === "password" ? /* @__PURE__ */ jsx17(Input, { type: "password", value: formData[col.field] || "", onChange: (e) => handleChange(e, col.field) }) : col.type === "number" ? /* @__PURE__ */ jsx17(
|
|
1451
|
+
] }) : col.type === "boolean" ? /* @__PURE__ */ jsx17(Switch, { checked: formData[col.field] || false, onCheckedChange: () => handleToggleChange(col.field) }) : col.type === "date" ? /* @__PURE__ */ jsx17(Input, { type: "date", value: formData[col.field] || "", onChange: (e) => handleChange(e, col.field) }) : col.type === "password" ? /* @__PURE__ */ jsx17(Input, { type: "password", value: formData[col.field] || "", onChange: (e) => handleChange(e, col.field) }) : col.type === "number" ? /* @__PURE__ */ jsx17(
|
|
1452
|
+
Input,
|
|
1453
|
+
{
|
|
1454
|
+
type: "number",
|
|
1455
|
+
placeholder: col.placeholder,
|
|
1456
|
+
value: formData[col.field] ?? "",
|
|
1457
|
+
onChange: (e) => handleChange(e, col.field)
|
|
1458
|
+
}
|
|
1459
|
+
) : col.type === "file" ? /* @__PURE__ */ jsx17(FileUpload, { onUploadSuccess: (url) => handleFileUpload(col.field, url) }) : /* @__PURE__ */ jsx17(
|
|
1460
|
+
Input,
|
|
1461
|
+
{
|
|
1462
|
+
type: col.type || "text",
|
|
1463
|
+
placeholder: col.placeholder,
|
|
1464
|
+
value: formData[col.field] ?? "",
|
|
1465
|
+
onChange: (e) => handleChange(e, col.field)
|
|
1466
|
+
}
|
|
1467
|
+
),
|
|
1436
1468
|
errors[col.field] && /* @__PURE__ */ jsx17("p", { className: "text-red-500 text-sm mt-1", children: errors[col.field] })
|
|
1437
1469
|
] }, col.field)) }),
|
|
1438
1470
|
/* @__PURE__ */ jsxs11("div", { className: "flex gap-2 p-4 border-t border-gray-200 shrink-0 bg-white", children: [
|
|
@@ -2035,6 +2067,10 @@ function AdminCRUD({
|
|
|
2035
2067
|
const hasLoadedRef = useRef3(false);
|
|
2036
2068
|
const isMobile = useIsMobile();
|
|
2037
2069
|
const showGroupColumn = !!manageUserGroups && roleOptions.length > 0;
|
|
2070
|
+
const listColumns = useMemo2(
|
|
2071
|
+
() => Array.isArray(columns) ? columns.filter((c) => !c.hideInTable) : [],
|
|
2072
|
+
[columns]
|
|
2073
|
+
);
|
|
2038
2074
|
useEffect6(() => {
|
|
2039
2075
|
const timeoutId = setTimeout(() => {
|
|
2040
2076
|
if (searchInput !== searchQuery) {
|
|
@@ -2485,7 +2521,7 @@ function AdminCRUD({
|
|
|
2485
2521
|
/* @__PURE__ */ jsx22("span", { className: "ml-2", children: "Refreshing list..." })
|
|
2486
2522
|
] }),
|
|
2487
2523
|
isMobile ? /* @__PURE__ */ jsx22("div", { className: "flex flex-col gap-2 min-w-0", children: data && data.length > 0 ? data.map((item, index) => {
|
|
2488
|
-
const displayCols =
|
|
2524
|
+
const displayCols = listColumns?.slice(0, 4) ?? [];
|
|
2489
2525
|
const primary = displayCols[0];
|
|
2490
2526
|
const primaryVal = primary ? getNestedValue(item, primary.field || primary.key) : null;
|
|
2491
2527
|
return /* @__PURE__ */ jsxs15(
|
|
@@ -2559,7 +2595,7 @@ function AdminCRUD({
|
|
|
2559
2595
|
);
|
|
2560
2596
|
}) : /* @__PURE__ */ jsx22("div", { className: "rounded-md border border-gray-200 p-6 text-center text-gray-500", children: "No data found" }) }) : /* @__PURE__ */ jsx22("div", { className: "overflow-x-auto min-w-0 rounded-md border border-gray-200", children: /* @__PURE__ */ jsxs15(Table, { children: [
|
|
2561
2597
|
/* @__PURE__ */ jsx22(TableHeader, { children: /* @__PURE__ */ jsxs15(TableRow, { children: [
|
|
2562
|
-
|
|
2598
|
+
listColumns && listColumns.map((col) => /* @__PURE__ */ jsxs15(
|
|
2563
2599
|
TableHead,
|
|
2564
2600
|
{
|
|
2565
2601
|
className: "cursor-pointer",
|
|
@@ -2581,7 +2617,7 @@ function AdminCRUD({
|
|
|
2581
2617
|
className: "cursor-pointer",
|
|
2582
2618
|
onClick: () => handleRowClick(item),
|
|
2583
2619
|
children: [
|
|
2584
|
-
|
|
2620
|
+
listColumns && listColumns.map((col, colIndex) => {
|
|
2585
2621
|
const fieldKey = col.field || col.key;
|
|
2586
2622
|
const value = getNestedValue(item, fieldKey);
|
|
2587
2623
|
return /* @__PURE__ */ jsx22(TableCell, { children: formatCellValue(value, col) }, `${item.id}-${colIndex}-${fieldKey}`);
|
|
@@ -2665,7 +2701,7 @@ function AdminCRUD({
|
|
|
2665
2701
|
)) : /* @__PURE__ */ jsx22(TableRow, { children: /* @__PURE__ */ jsx22(
|
|
2666
2702
|
TableCell,
|
|
2667
2703
|
{
|
|
2668
|
-
colSpan:
|
|
2704
|
+
colSpan: listColumns.length ? listColumns.length + 1 + (showGroupColumn ? 1 : 0) : 1,
|
|
2669
2705
|
className: "text-center py-8",
|
|
2670
2706
|
children: "No data found"
|
|
2671
2707
|
}
|
|
@@ -3939,7 +3975,7 @@ function TagAutocomplete({
|
|
|
3939
3975
|
|
|
3940
3976
|
// src/components/Admin/JoditRichText.tsx
|
|
3941
3977
|
import dynamic from "next/dynamic";
|
|
3942
|
-
import { useMemo as
|
|
3978
|
+
import { useMemo as useMemo3 } from "react";
|
|
3943
3979
|
import "jodit/es2021/jodit.min.css";
|
|
3944
3980
|
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
3945
3981
|
var JoditEditor = dynamic(() => import("jodit-react").then((m) => m.default), {
|
|
@@ -3947,7 +3983,7 @@ var JoditEditor = dynamic(() => import("jodit-react").then((m) => m.default), {
|
|
|
3947
3983
|
loading: () => /* @__PURE__ */ jsx28("div", { className: "min-h-[300px] rounded-md border border-gray-200 bg-gray-50 animate-pulse" })
|
|
3948
3984
|
});
|
|
3949
3985
|
function JoditRichText({ value, onChange, placeholder, minHeight = 400 }) {
|
|
3950
|
-
const config =
|
|
3986
|
+
const config = useMemo3(
|
|
3951
3987
|
() => ({
|
|
3952
3988
|
readonly: false,
|
|
3953
3989
|
placeholder: placeholder ?? "",
|
|
@@ -5763,7 +5799,7 @@ function InvitePage() {
|
|
|
5763
5799
|
|
|
5764
5800
|
// src/admin/pages/DashboardPage.tsx
|
|
5765
5801
|
import { useSession as useSession4 } from "next-auth/react";
|
|
5766
|
-
import { useContext as useContext3, useEffect as useEffect19, useMemo as
|
|
5802
|
+
import { useContext as useContext3, useEffect as useEffect19, useMemo as useMemo4, useState as useState22 } from "react";
|
|
5767
5803
|
import { useRouter as useRouter6 } from "next/navigation";
|
|
5768
5804
|
import { Chart as ChartJS2, ArcElement, Tooltip as Tooltip2, Legend as Legend2 } from "chart.js";
|
|
5769
5805
|
import { Doughnut } from "react-chartjs-2";
|
|
@@ -5781,7 +5817,7 @@ function DashboardPage() {
|
|
|
5781
5817
|
const [analyticsEnabled, setAnalyticsEnabled] = useState22(false);
|
|
5782
5818
|
const [days, setDays] = useState22(30);
|
|
5783
5819
|
const [activeTab, setActiveTab] = useState22("overview");
|
|
5784
|
-
const formatMoney4 =
|
|
5820
|
+
const formatMoney4 = useMemo4(
|
|
5785
5821
|
() => (value) => new Intl.NumberFormat(void 0, {
|
|
5786
5822
|
style: "currency",
|
|
5787
5823
|
currency: "INR",
|
|
@@ -6460,7 +6496,7 @@ function DashboardPage() {
|
|
|
6460
6496
|
}
|
|
6461
6497
|
|
|
6462
6498
|
// src/admin/pages/AdminPageResolver.tsx
|
|
6463
|
-
import { useState as useState36, useEffect as useEffect33, useContext as useContext7, useMemo as
|
|
6499
|
+
import { useState as useState36, useEffect as useEffect33, useContext as useContext7, useMemo as useMemo5 } from "react";
|
|
6464
6500
|
import { useRouter as useRouter15 } from "next/navigation";
|
|
6465
6501
|
|
|
6466
6502
|
// src/admin/pages/SubmissionDetailPage.tsx
|
|
@@ -9204,8 +9240,25 @@ function PageBuilderPage({ pageId }) {
|
|
|
9204
9240
|
}
|
|
9205
9241
|
|
|
9206
9242
|
// src/admin/pages/PluginsPage.tsx
|
|
9207
|
-
import { useContext as useContext6, useState as useState30, useEffect as useEffect27 } from "react";
|
|
9208
|
-
import {
|
|
9243
|
+
import { useContext as useContext6, useState as useState30, useEffect as useEffect27, useCallback as useCallback7 } from "react";
|
|
9244
|
+
import {
|
|
9245
|
+
HardDrive,
|
|
9246
|
+
Mail,
|
|
9247
|
+
CreditCard as CreditCard2,
|
|
9248
|
+
MessageCircle,
|
|
9249
|
+
BarChart3 as BarChart32,
|
|
9250
|
+
Building2 as Building22,
|
|
9251
|
+
Puzzle as Puzzle2,
|
|
9252
|
+
CheckCircle2 as CheckCircle22,
|
|
9253
|
+
XCircle,
|
|
9254
|
+
Save as Save5,
|
|
9255
|
+
X as X18,
|
|
9256
|
+
Plus as Plus8,
|
|
9257
|
+
Smartphone,
|
|
9258
|
+
Bot as Bot2,
|
|
9259
|
+
FileUp,
|
|
9260
|
+
Loader2
|
|
9261
|
+
} from "lucide-react";
|
|
9209
9262
|
|
|
9210
9263
|
// src/lib/email-recipients.ts
|
|
9211
9264
|
function parseEmailRecipientsFromConfig(raw) {
|
|
@@ -9254,6 +9307,10 @@ Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
|
9254
9307
|
// src/admin/pages/PluginsPage.tsx
|
|
9255
9308
|
import { toast as toast5 } from "sonner";
|
|
9256
9309
|
import { Fragment as Fragment14, jsx as jsx56, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
9310
|
+
function slugifyAgentKey(name) {
|
|
9311
|
+
const s = name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
9312
|
+
return s || "agent";
|
|
9313
|
+
}
|
|
9257
9314
|
function normalizeChatMode(raw) {
|
|
9258
9315
|
if (raw === "external" || raw === "llm") return raw;
|
|
9259
9316
|
return "whatsapp";
|
|
@@ -9413,6 +9470,25 @@ function PluginSettingsPanel({
|
|
|
9413
9470
|
const [chatMode, setChatMode] = useState30("whatsapp");
|
|
9414
9471
|
const [whatsappPhone, setWhatsappPhone] = useState30("");
|
|
9415
9472
|
const [externalChatSnippet, setExternalChatSnippet] = useState30("");
|
|
9473
|
+
const [attachedAgentSlug, setAttachedAgentSlug] = useState30("");
|
|
9474
|
+
const [llmAgents, setLlmAgents] = useState30([]);
|
|
9475
|
+
const [agentId, setAgentId] = useState30(null);
|
|
9476
|
+
const [agentName, setAgentName] = useState30("");
|
|
9477
|
+
const [agentSlug, setAgentSlug] = useState30("");
|
|
9478
|
+
const [agentSystem, setAgentSystem] = useState30("");
|
|
9479
|
+
const [agentModel, setAgentModel] = useState30("");
|
|
9480
|
+
const [agentTemp, setAgentTemp] = useState30("");
|
|
9481
|
+
const [agentMaxTokens, setAgentMaxTokens] = useState30("");
|
|
9482
|
+
const [agentValidationJson, setAgentValidationJson] = useState30("");
|
|
9483
|
+
const [agentLoading, setAgentLoading] = useState30(false);
|
|
9484
|
+
const [agentSaving, setAgentSaving] = useState30(false);
|
|
9485
|
+
const [kbCatalog, setKbCatalog] = useState30([]);
|
|
9486
|
+
const [attachedAgentKnowledge, setAttachedAgentKnowledge] = useState30([]);
|
|
9487
|
+
const [attachedKbLoading, setAttachedKbLoading] = useState30(false);
|
|
9488
|
+
const [attachExistingDocId, setAttachExistingDocId] = useState30("__none__");
|
|
9489
|
+
const [uploadingAttachedKbFile, setUploadingAttachedKbFile] = useState30(false);
|
|
9490
|
+
const [uploadingAttachedKbLink, setUploadingAttachedKbLink] = useState30(false);
|
|
9491
|
+
const [attachedKbInputKey, setAttachedKbInputKey] = useState30(0);
|
|
9416
9492
|
const [erpPipelineName, setErpPipelineName] = useState30("");
|
|
9417
9493
|
const [erpPipelineStageName, setErpPipelineStageName] = useState30("");
|
|
9418
9494
|
const [erpFormsCatalog, setErpFormsCatalog] = useState30([]);
|
|
@@ -9436,6 +9512,7 @@ function PluginSettingsPanel({
|
|
|
9436
9512
|
setIconImageUrl(data.iconImageUrl ?? "");
|
|
9437
9513
|
setIconBackgroundColor(data.iconBackgroundColor ?? "#6366f1");
|
|
9438
9514
|
setHeaderColor(data.headerColor ?? "#6366f1");
|
|
9515
|
+
setAttachedAgentSlug(data.attachedAgentSlug ?? "");
|
|
9439
9516
|
}
|
|
9440
9517
|
if (isErp) {
|
|
9441
9518
|
setErpPipelineName(data.pipelineName ?? data.pipelineId ?? "");
|
|
@@ -9490,6 +9567,116 @@ function PluginSettingsPanel({
|
|
|
9490
9567
|
setErpFormsCatalog(rows);
|
|
9491
9568
|
}).catch(() => setErpFormsCatalog([]));
|
|
9492
9569
|
}, [isErp, loading]);
|
|
9570
|
+
const fetchLlmAgents = useCallback7(async () => {
|
|
9571
|
+
const res = await fetch("/api/llm_agents?limit=100&sortField=name&sortOrder=asc");
|
|
9572
|
+
if (!res.ok) {
|
|
9573
|
+
setLlmAgents([]);
|
|
9574
|
+
return;
|
|
9575
|
+
}
|
|
9576
|
+
const j = await res.json();
|
|
9577
|
+
const list = (j.data ?? []).map((r) => ({
|
|
9578
|
+
id: r.id,
|
|
9579
|
+
name: String(r.name ?? ""),
|
|
9580
|
+
slug: String(r.slug ?? ""),
|
|
9581
|
+
enabled: r.enabled !== false
|
|
9582
|
+
}));
|
|
9583
|
+
setLlmAgents(list);
|
|
9584
|
+
const pick = list.find((a) => a.enabled) ?? list[0];
|
|
9585
|
+
const fullRow = (j.data ?? []).find((r) => r.id === pick?.id);
|
|
9586
|
+
if (pick && fullRow) {
|
|
9587
|
+
setAgentId(pick.id);
|
|
9588
|
+
setAgentName(pick.name);
|
|
9589
|
+
setAgentSlug(pick.slug);
|
|
9590
|
+
setAgentSystem(String(fullRow.systemInstruction ?? ""));
|
|
9591
|
+
setAgentModel(String(fullRow.model ?? ""));
|
|
9592
|
+
setAgentTemp(fullRow.temperature != null ? String(fullRow.temperature) : "");
|
|
9593
|
+
setAgentMaxTokens(fullRow.maxTokens != null ? String(fullRow.maxTokens) : "");
|
|
9594
|
+
setAgentValidationJson(String(fullRow.validationRules ?? ""));
|
|
9595
|
+
setAttachedAgentSlug(pick.slug);
|
|
9596
|
+
}
|
|
9597
|
+
}, []);
|
|
9598
|
+
const fetchKbCatalog = useCallback7(async () => {
|
|
9599
|
+
try {
|
|
9600
|
+
const res = await fetch("/api/knowledge_base_documents?limit=300&sortField=name&sortOrder=asc");
|
|
9601
|
+
if (!res.ok) {
|
|
9602
|
+
setKbCatalog([]);
|
|
9603
|
+
return;
|
|
9604
|
+
}
|
|
9605
|
+
const j = await res.json();
|
|
9606
|
+
setKbCatalog(
|
|
9607
|
+
(j.data ?? []).map((r) => ({
|
|
9608
|
+
id: typeof r.id === "number" ? r.id : Number(r.id),
|
|
9609
|
+
name: String(r.name ?? "")
|
|
9610
|
+
})).filter((r) => Number.isInteger(r.id) && r.id > 0)
|
|
9611
|
+
);
|
|
9612
|
+
} catch {
|
|
9613
|
+
setKbCatalog([]);
|
|
9614
|
+
}
|
|
9615
|
+
}, []);
|
|
9616
|
+
const fetchAttachedKnowledge = useCallback7(async (slug) => {
|
|
9617
|
+
if (!slug.trim()) {
|
|
9618
|
+
setAttachedAgentKnowledge([]);
|
|
9619
|
+
return;
|
|
9620
|
+
}
|
|
9621
|
+
setAttachedKbLoading(true);
|
|
9622
|
+
try {
|
|
9623
|
+
const res = await fetch(`/api/llm_agents/${encodeURIComponent(slug.trim())}/knowledge`);
|
|
9624
|
+
if (!res.ok) {
|
|
9625
|
+
setAttachedAgentKnowledge([]);
|
|
9626
|
+
return;
|
|
9627
|
+
}
|
|
9628
|
+
const j = await res.json();
|
|
9629
|
+
setAttachedAgentKnowledge(
|
|
9630
|
+
(j.documents ?? []).map((d) => ({
|
|
9631
|
+
id: typeof d.id === "number" ? d.id : Number(d.id),
|
|
9632
|
+
name: String(d.name ?? "")
|
|
9633
|
+
}))
|
|
9634
|
+
);
|
|
9635
|
+
} catch {
|
|
9636
|
+
setAttachedAgentKnowledge([]);
|
|
9637
|
+
} finally {
|
|
9638
|
+
setAttachedKbLoading(false);
|
|
9639
|
+
}
|
|
9640
|
+
}, []);
|
|
9641
|
+
useEffect27(() => {
|
|
9642
|
+
if (!isLlm || loading || chatMode !== "llm") return;
|
|
9643
|
+
setAgentLoading(true);
|
|
9644
|
+
void (async () => {
|
|
9645
|
+
try {
|
|
9646
|
+
await fetchLlmAgents();
|
|
9647
|
+
const listRes = await fetch("/api/llm_agents?limit=1");
|
|
9648
|
+
const listJ = listRes.ok ? await listRes.json() : { data: [] };
|
|
9649
|
+
if (!listJ.data?.length) {
|
|
9650
|
+
const defaultName = botName.trim() || "Assistant";
|
|
9651
|
+
const defaultSlug = slugifyAgentKey(defaultName);
|
|
9652
|
+
const createRes = await fetch("/api/llm_agents", {
|
|
9653
|
+
method: "POST",
|
|
9654
|
+
headers: { "Content-Type": "application/json" },
|
|
9655
|
+
body: JSON.stringify({ name: defaultName, slug: defaultSlug, systemInstruction: "", enabled: true })
|
|
9656
|
+
});
|
|
9657
|
+
if (createRes.ok) {
|
|
9658
|
+
await fetchLlmAgents();
|
|
9659
|
+
}
|
|
9660
|
+
}
|
|
9661
|
+
} finally {
|
|
9662
|
+
setAgentLoading(false);
|
|
9663
|
+
}
|
|
9664
|
+
})();
|
|
9665
|
+
}, [isLlm, loading, chatMode]);
|
|
9666
|
+
useEffect27(() => {
|
|
9667
|
+
if (!isLlm || loading || chatMode !== "llm") return;
|
|
9668
|
+
void fetchKbCatalog();
|
|
9669
|
+
}, [isLlm, loading, chatMode, fetchKbCatalog]);
|
|
9670
|
+
useEffect27(() => {
|
|
9671
|
+
if (!isLlm || loading || chatMode !== "llm" || !attachedAgentSlug.trim()) {
|
|
9672
|
+
setAttachedAgentKnowledge([]);
|
|
9673
|
+
return;
|
|
9674
|
+
}
|
|
9675
|
+
void fetchAttachedKnowledge(attachedAgentSlug);
|
|
9676
|
+
}, [isLlm, loading, chatMode, attachedAgentSlug, fetchAttachedKnowledge]);
|
|
9677
|
+
useEffect27(() => {
|
|
9678
|
+
setAttachExistingDocId("__none__");
|
|
9679
|
+
}, [attachedAgentSlug]);
|
|
9493
9680
|
const buildPayload = () => {
|
|
9494
9681
|
if (isErp) {
|
|
9495
9682
|
const sortedIds = [...new Set(erpOpportunityFormIds.filter((n) => Number.isInteger(n) && n > 0))].sort(
|
|
@@ -9524,6 +9711,7 @@ function PluginSettingsPanel({
|
|
|
9524
9711
|
payload.iconImageUrl = { value: iconImageUrl, type: "public" };
|
|
9525
9712
|
payload.iconBackgroundColor = { value: iconBackgroundColor, type: "public" };
|
|
9526
9713
|
payload.headerColor = { value: headerColor, type: "public" };
|
|
9714
|
+
payload.attachedAgentSlug = { value: attachedAgentSlug.trim(), type: "public" };
|
|
9527
9715
|
}
|
|
9528
9716
|
if (isEmail) {
|
|
9529
9717
|
payload.salesTeamEmails = { value: serializeEmailRecipients(salesTeamEmails), type: "public" };
|
|
@@ -9539,6 +9727,56 @@ function PluginSettingsPanel({
|
|
|
9539
9727
|
}
|
|
9540
9728
|
return payload;
|
|
9541
9729
|
};
|
|
9730
|
+
const handleSaveAgent = async () => {
|
|
9731
|
+
if (!agentId) {
|
|
9732
|
+
toast5.error("No agent to save");
|
|
9733
|
+
return;
|
|
9734
|
+
}
|
|
9735
|
+
const name = agentName.trim();
|
|
9736
|
+
if (!name) {
|
|
9737
|
+
toast5.error("Agent name is required");
|
|
9738
|
+
return;
|
|
9739
|
+
}
|
|
9740
|
+
const tempRaw = agentTemp.trim();
|
|
9741
|
+
const maxRaw = agentMaxTokens.trim();
|
|
9742
|
+
const temperature = tempRaw === "" ? null : Number(tempRaw);
|
|
9743
|
+
const maxTokens = maxRaw === "" ? null : parseInt(maxRaw, 10);
|
|
9744
|
+
if (tempRaw !== "" && !Number.isFinite(temperature)) {
|
|
9745
|
+
toast5.error("Temperature must be a number");
|
|
9746
|
+
return;
|
|
9747
|
+
}
|
|
9748
|
+
if (maxRaw !== "" && (!Number.isFinite(maxTokens) || maxTokens < 1)) {
|
|
9749
|
+
toast5.error("Max tokens must be a positive integer");
|
|
9750
|
+
return;
|
|
9751
|
+
}
|
|
9752
|
+
setAgentSaving(true);
|
|
9753
|
+
try {
|
|
9754
|
+
const res = await fetch(`/api/llm_agents/${agentId}`, {
|
|
9755
|
+
method: "PUT",
|
|
9756
|
+
headers: { "Content-Type": "application/json" },
|
|
9757
|
+
body: JSON.stringify({
|
|
9758
|
+
name,
|
|
9759
|
+
systemInstruction: agentSystem.trim(),
|
|
9760
|
+
model: agentModel.trim() || null,
|
|
9761
|
+
temperature,
|
|
9762
|
+
maxTokens,
|
|
9763
|
+
validationRules: agentValidationJson.trim() || null,
|
|
9764
|
+
enabled: true
|
|
9765
|
+
})
|
|
9766
|
+
});
|
|
9767
|
+
if (!res.ok) {
|
|
9768
|
+
const err = await res.json().catch(() => ({}));
|
|
9769
|
+
toast5.error(err.error || "Failed to update agent");
|
|
9770
|
+
return;
|
|
9771
|
+
}
|
|
9772
|
+
setAttachedAgentSlug(agentSlug);
|
|
9773
|
+
toast5.success("Agent saved");
|
|
9774
|
+
} catch {
|
|
9775
|
+
toast5.error("Failed to update agent");
|
|
9776
|
+
} finally {
|
|
9777
|
+
setAgentSaving(false);
|
|
9778
|
+
}
|
|
9779
|
+
};
|
|
9542
9780
|
const handleSave = async () => {
|
|
9543
9781
|
setSaving(true);
|
|
9544
9782
|
try {
|
|
@@ -9572,6 +9810,78 @@ function PluginSettingsPanel({
|
|
|
9572
9810
|
setSaving(false);
|
|
9573
9811
|
}
|
|
9574
9812
|
};
|
|
9813
|
+
const uploadKbFileToAttached = async (file) => {
|
|
9814
|
+
const slug = agentSlug.trim() || attachedAgentSlug.trim();
|
|
9815
|
+
if (!slug) {
|
|
9816
|
+
toast5.error("No agent configured");
|
|
9817
|
+
return;
|
|
9818
|
+
}
|
|
9819
|
+
setUploadingAttachedKbFile(true);
|
|
9820
|
+
try {
|
|
9821
|
+
const fd = new FormData();
|
|
9822
|
+
const stem = file.name.replace(/\.[^/.]+$/, "").trim() || "Upload";
|
|
9823
|
+
fd.append("name", stem);
|
|
9824
|
+
fd.append("file", file);
|
|
9825
|
+
const r = await fetch(`/api/llm_agents/${encodeURIComponent(slug)}/knowledge`, { method: "POST", body: fd });
|
|
9826
|
+
if (!r.ok) {
|
|
9827
|
+
const err = await r.json().catch(() => ({}));
|
|
9828
|
+
toast5.error(err.error || "Upload failed");
|
|
9829
|
+
return;
|
|
9830
|
+
}
|
|
9831
|
+
toast5.success("Knowledge added and linked");
|
|
9832
|
+
setAttachedKbInputKey((k) => k + 1);
|
|
9833
|
+
await fetchAttachedKnowledge(slug);
|
|
9834
|
+
await fetchKbCatalog();
|
|
9835
|
+
} finally {
|
|
9836
|
+
setUploadingAttachedKbFile(false);
|
|
9837
|
+
}
|
|
9838
|
+
};
|
|
9839
|
+
const onAttachedKbFileChange = (e) => {
|
|
9840
|
+
const file = e.target.files?.[0];
|
|
9841
|
+
if (!file) return;
|
|
9842
|
+
const slug = agentSlug.trim() || attachedAgentSlug.trim();
|
|
9843
|
+
if (!slug) {
|
|
9844
|
+
toast5.error("No agent configured");
|
|
9845
|
+
e.target.value = "";
|
|
9846
|
+
return;
|
|
9847
|
+
}
|
|
9848
|
+
void uploadKbFileToAttached(file);
|
|
9849
|
+
};
|
|
9850
|
+
const handleAttachExistingToAttached = async () => {
|
|
9851
|
+
const slug = agentSlug.trim() || attachedAgentSlug.trim();
|
|
9852
|
+
if (!slug || attachExistingDocId === "__none__") return;
|
|
9853
|
+
const docId = parseInt(attachExistingDocId, 10);
|
|
9854
|
+
if (!Number.isFinite(docId)) return;
|
|
9855
|
+
setUploadingAttachedKbLink(true);
|
|
9856
|
+
try {
|
|
9857
|
+
const r = await fetch(`/api/llm_agents/${encodeURIComponent(slug)}/knowledge`, {
|
|
9858
|
+
method: "POST",
|
|
9859
|
+
headers: { "Content-Type": "application/json" },
|
|
9860
|
+
body: JSON.stringify({ documentId: docId })
|
|
9861
|
+
});
|
|
9862
|
+
if (!r.ok) {
|
|
9863
|
+
const err = await r.json().catch(() => ({}));
|
|
9864
|
+
toast5.error(err.error || "Attach failed");
|
|
9865
|
+
return;
|
|
9866
|
+
}
|
|
9867
|
+
toast5.success("Document attached");
|
|
9868
|
+
setAttachExistingDocId("__none__");
|
|
9869
|
+
await fetchAttachedKnowledge(slug);
|
|
9870
|
+
} finally {
|
|
9871
|
+
setUploadingAttachedKbLink(false);
|
|
9872
|
+
}
|
|
9873
|
+
};
|
|
9874
|
+
const handleUnlinkKbDoc = async (docId) => {
|
|
9875
|
+
const slug = agentSlug.trim() || attachedAgentSlug.trim();
|
|
9876
|
+
if (!slug) return;
|
|
9877
|
+
const r = await fetch(`/api/llm_agents/${encodeURIComponent(slug)}/knowledge/${docId}`, { method: "DELETE" });
|
|
9878
|
+
if (!r.ok) {
|
|
9879
|
+
toast5.error("Could not remove link");
|
|
9880
|
+
return;
|
|
9881
|
+
}
|
|
9882
|
+
toast5.success("Removed from agent");
|
|
9883
|
+
await fetchAttachedKnowledge(slug);
|
|
9884
|
+
};
|
|
9575
9885
|
if (loading) return /* @__PURE__ */ jsx56("div", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Loading..." });
|
|
9576
9886
|
if (isErp) {
|
|
9577
9887
|
return /* @__PURE__ */ jsxs46("div", { className: "space-y-4", children: [
|
|
@@ -10013,8 +10323,206 @@ function PluginSettingsPanel({
|
|
|
10013
10323
|
/* @__PURE__ */ jsx56("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Only paste code from sources you trust." })
|
|
10014
10324
|
] }),
|
|
10015
10325
|
chatMode === "llm" && /* @__PURE__ */ jsxs46(Fragment14, { children: [
|
|
10326
|
+
/* @__PURE__ */ jsxs46("div", { className: "rounded-lg border border-gray-200 dark:border-gray-600 bg-gray-50/80 dark:bg-gray-800/40 p-3 space-y-3", children: [
|
|
10327
|
+
/* @__PURE__ */ jsxs46("div", { className: "flex items-center gap-2 text-sm font-medium text-gray-900 dark:text-white", children: [
|
|
10328
|
+
/* @__PURE__ */ jsx56(Bot2, { className: "h-4 w-4" }),
|
|
10329
|
+
"Chat assistant agent"
|
|
10330
|
+
] }),
|
|
10331
|
+
agentLoading ? /* @__PURE__ */ jsxs46("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [
|
|
10332
|
+
/* @__PURE__ */ jsx56(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
10333
|
+
"Loading agent\u2026"
|
|
10334
|
+
] }) : !agentId ? /* @__PURE__ */ jsx56("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "No agent found. Save settings to auto-create one." }) : /* @__PURE__ */ jsxs46(Fragment14, { children: [
|
|
10335
|
+
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10336
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: "agent-name", className: "text-sm", children: "Name" }),
|
|
10337
|
+
/* @__PURE__ */ jsx56(
|
|
10338
|
+
Input,
|
|
10339
|
+
{
|
|
10340
|
+
id: "agent-name",
|
|
10341
|
+
value: agentName,
|
|
10342
|
+
onChange: (e) => setAgentName(e.target.value),
|
|
10343
|
+
placeholder: "e.g. Sales assistant",
|
|
10344
|
+
className: "h-8 text-sm"
|
|
10345
|
+
}
|
|
10346
|
+
)
|
|
10347
|
+
] }),
|
|
10348
|
+
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10349
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: "agent-slug", className: "text-sm", children: "Slug" }),
|
|
10350
|
+
/* @__PURE__ */ jsx56(
|
|
10351
|
+
Input,
|
|
10352
|
+
{
|
|
10353
|
+
id: "agent-slug",
|
|
10354
|
+
value: agentSlug,
|
|
10355
|
+
disabled: true,
|
|
10356
|
+
className: "h-8 text-sm font-mono bg-gray-100 dark:bg-gray-700"
|
|
10357
|
+
}
|
|
10358
|
+
),
|
|
10359
|
+
/* @__PURE__ */ jsx56("p", { className: "text-[11px] text-gray-500", children: "Auto-generated. Used in API routes." })
|
|
10360
|
+
] }),
|
|
10361
|
+
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10362
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: "agent-system", className: "text-sm", children: "System instruction" }),
|
|
10363
|
+
/* @__PURE__ */ jsx56(
|
|
10364
|
+
Textarea,
|
|
10365
|
+
{
|
|
10366
|
+
id: "agent-system",
|
|
10367
|
+
value: agentSystem,
|
|
10368
|
+
onChange: (e) => setAgentSystem(e.target.value),
|
|
10369
|
+
rows: 5,
|
|
10370
|
+
placeholder: "How the model should behave\u2026",
|
|
10371
|
+
className: "text-sm"
|
|
10372
|
+
}
|
|
10373
|
+
)
|
|
10374
|
+
] }),
|
|
10375
|
+
/* @__PURE__ */ jsxs46("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
10376
|
+
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10377
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: "agent-model", className: "text-sm", children: "Model (optional)" }),
|
|
10378
|
+
/* @__PURE__ */ jsx56(
|
|
10379
|
+
Input,
|
|
10380
|
+
{
|
|
10381
|
+
id: "agent-model",
|
|
10382
|
+
value: agentModel,
|
|
10383
|
+
onChange: (e) => setAgentModel(e.target.value),
|
|
10384
|
+
placeholder: "Gateway model id",
|
|
10385
|
+
className: "h-8 text-sm font-mono"
|
|
10386
|
+
}
|
|
10387
|
+
)
|
|
10388
|
+
] }),
|
|
10389
|
+
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10390
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: "agent-temp", className: "text-sm", children: "Temperature" }),
|
|
10391
|
+
/* @__PURE__ */ jsx56(
|
|
10392
|
+
Input,
|
|
10393
|
+
{
|
|
10394
|
+
id: "agent-temp",
|
|
10395
|
+
value: agentTemp,
|
|
10396
|
+
onChange: (e) => setAgentTemp(e.target.value),
|
|
10397
|
+
placeholder: "e.g. 0.7",
|
|
10398
|
+
className: "h-8 text-sm"
|
|
10399
|
+
}
|
|
10400
|
+
)
|
|
10401
|
+
] })
|
|
10402
|
+
] }),
|
|
10403
|
+
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10404
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: "agent-max", className: "text-sm", children: "Max tokens" }),
|
|
10405
|
+
/* @__PURE__ */ jsx56(
|
|
10406
|
+
Input,
|
|
10407
|
+
{
|
|
10408
|
+
id: "agent-max",
|
|
10409
|
+
value: agentMaxTokens,
|
|
10410
|
+
onChange: (e) => setAgentMaxTokens(e.target.value.replace(/\D/g, "")),
|
|
10411
|
+
placeholder: "e.g. 1024",
|
|
10412
|
+
className: "h-8 text-sm"
|
|
10413
|
+
}
|
|
10414
|
+
)
|
|
10415
|
+
] }),
|
|
10416
|
+
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10417
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: "agent-validation", className: "text-sm", children: "Validation & output guardrails" }),
|
|
10418
|
+
/* @__PURE__ */ jsx56(
|
|
10419
|
+
Textarea,
|
|
10420
|
+
{
|
|
10421
|
+
id: "agent-validation",
|
|
10422
|
+
value: agentValidationJson,
|
|
10423
|
+
onChange: (e) => setAgentValidationJson(e.target.value),
|
|
10424
|
+
rows: 4,
|
|
10425
|
+
placeholder: 'Plain text or JSON: {"guardrails":"Never promise refunds.","maxUserChars":2000}',
|
|
10426
|
+
className: "text-xs font-mono"
|
|
10427
|
+
}
|
|
10428
|
+
)
|
|
10429
|
+
] }),
|
|
10430
|
+
/* @__PURE__ */ jsx56(
|
|
10431
|
+
Button,
|
|
10432
|
+
{
|
|
10433
|
+
type: "button",
|
|
10434
|
+
size: "sm",
|
|
10435
|
+
className: "gap-1",
|
|
10436
|
+
disabled: agentSaving,
|
|
10437
|
+
onClick: () => void handleSaveAgent(),
|
|
10438
|
+
children: agentSaving ? /* @__PURE__ */ jsxs46("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
10439
|
+
/* @__PURE__ */ jsx56(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
10440
|
+
"Saving\u2026"
|
|
10441
|
+
] }) : /* @__PURE__ */ jsxs46(Fragment14, { children: [
|
|
10442
|
+
/* @__PURE__ */ jsx56(Save5, { className: "h-3.5 w-3.5" }),
|
|
10443
|
+
"Save agent"
|
|
10444
|
+
] })
|
|
10445
|
+
}
|
|
10446
|
+
)
|
|
10447
|
+
] }),
|
|
10448
|
+
agentId && agentSlug.trim() ? /* @__PURE__ */ jsxs46("div", { className: "rounded-md border border-dashed border-gray-300 dark:border-gray-600 bg-white/60 dark:bg-gray-900/30 p-3 space-y-3", children: [
|
|
10449
|
+
/* @__PURE__ */ jsxs46("div", { className: "flex items-center gap-2 text-xs font-medium text-gray-800 dark:text-gray-200", children: [
|
|
10450
|
+
/* @__PURE__ */ jsx56(FileUp, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
10451
|
+
"Knowledge for this agent"
|
|
10452
|
+
] }),
|
|
10453
|
+
/* @__PURE__ */ jsx56("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Upload text (.txt, .md, .json) or PDF (.pdf), or link documents already in the knowledge base." }),
|
|
10454
|
+
attachedKbLoading ? /* @__PURE__ */ jsx56("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Loading linked documents\u2026" }) : attachedAgentKnowledge.length === 0 ? /* @__PURE__ */ jsx56("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "No documents linked yet." }) : /* @__PURE__ */ jsx56("ul", { className: "max-h-32 space-y-1.5 overflow-y-auto", children: attachedAgentKnowledge.map((d) => /* @__PURE__ */ jsxs46("li", { className: "flex items-center justify-between gap-2 text-sm", children: [
|
|
10455
|
+
/* @__PURE__ */ jsx56("span", { className: "min-w-0 truncate", title: d.name, children: d.name }),
|
|
10456
|
+
/* @__PURE__ */ jsx56(
|
|
10457
|
+
Button,
|
|
10458
|
+
{
|
|
10459
|
+
type: "button",
|
|
10460
|
+
variant: "ghost",
|
|
10461
|
+
size: "sm",
|
|
10462
|
+
className: "h-7 shrink-0 text-xs text-red-600 hover:text-red-700 dark:text-red-400",
|
|
10463
|
+
onClick: () => void handleUnlinkKbDoc(d.id),
|
|
10464
|
+
children: "Remove"
|
|
10465
|
+
}
|
|
10466
|
+
)
|
|
10467
|
+
] }, d.id)) }),
|
|
10468
|
+
/* @__PURE__ */ jsxs46("div", { className: "min-w-[180px] space-y-1", children: [
|
|
10469
|
+
/* @__PURE__ */ jsx56(Label3, { className: "text-xs", children: "Upload file" }),
|
|
10470
|
+
/* @__PURE__ */ jsxs46("div", { className: "relative", children: [
|
|
10471
|
+
/* @__PURE__ */ jsx56(
|
|
10472
|
+
Input,
|
|
10473
|
+
{
|
|
10474
|
+
type: "file",
|
|
10475
|
+
accept: ".txt,.md,.json,.pdf,text/plain,text/markdown,application/json,application/pdf",
|
|
10476
|
+
disabled: uploadingAttachedKbFile || uploadingAttachedKbLink,
|
|
10477
|
+
className: "h-8 cursor-pointer text-xs disabled:opacity-60",
|
|
10478
|
+
onChange: onAttachedKbFileChange
|
|
10479
|
+
},
|
|
10480
|
+
attachedKbInputKey
|
|
10481
|
+
),
|
|
10482
|
+
uploadingAttachedKbFile ? /* @__PURE__ */ jsxs46(
|
|
10483
|
+
"div",
|
|
10484
|
+
{
|
|
10485
|
+
className: "pointer-events-none absolute inset-0 flex items-center justify-center gap-2 rounded-md bg-background/85 text-xs font-medium text-gray-700 dark:text-gray-200",
|
|
10486
|
+
"aria-live": "polite",
|
|
10487
|
+
children: [
|
|
10488
|
+
/* @__PURE__ */ jsx56(Loader2, { className: "h-4 w-4 shrink-0 animate-spin" }),
|
|
10489
|
+
"Saving & linking\u2026"
|
|
10490
|
+
]
|
|
10491
|
+
}
|
|
10492
|
+
) : null
|
|
10493
|
+
] }),
|
|
10494
|
+
/* @__PURE__ */ jsx56("p", { className: "text-[11px] text-gray-500 dark:text-gray-400", children: "Pick a file to upload immediately (chunking, embeddings if configured, then link to this agent)." })
|
|
10495
|
+
] }),
|
|
10496
|
+
/* @__PURE__ */ jsxs46("div", { className: "flex flex-wrap items-end gap-2", children: [
|
|
10497
|
+
/* @__PURE__ */ jsxs46("div", { className: "min-w-[200px] flex-1 space-y-1", children: [
|
|
10498
|
+
/* @__PURE__ */ jsx56(Label3, { className: "text-xs", children: "Attach existing document" }),
|
|
10499
|
+
/* @__PURE__ */ jsxs46(Select, { value: attachExistingDocId, onValueChange: setAttachExistingDocId, children: [
|
|
10500
|
+
/* @__PURE__ */ jsx56(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx56(SelectValue, { placeholder: "Choose a document" }) }),
|
|
10501
|
+
/* @__PURE__ */ jsxs46(SelectContent, { children: [
|
|
10502
|
+
/* @__PURE__ */ jsx56(SelectItem, { value: "__none__", children: "\u2014 Select \u2014" }),
|
|
10503
|
+
kbCatalog.filter((d) => !attachedAgentKnowledge.some((a) => a.id === d.id)).map((d) => /* @__PURE__ */ jsx56(SelectItem, { value: String(d.id), children: d.name }, d.id))
|
|
10504
|
+
] })
|
|
10505
|
+
] })
|
|
10506
|
+
] }),
|
|
10507
|
+
/* @__PURE__ */ jsx56(
|
|
10508
|
+
Button,
|
|
10509
|
+
{
|
|
10510
|
+
type: "button",
|
|
10511
|
+
size: "sm",
|
|
10512
|
+
className: "h-8",
|
|
10513
|
+
disabled: uploadingAttachedKbFile || uploadingAttachedKbLink || attachExistingDocId === "__none__",
|
|
10514
|
+
onClick: () => void handleAttachExistingToAttached(),
|
|
10515
|
+
children: uploadingAttachedKbLink ? /* @__PURE__ */ jsxs46("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
10516
|
+
/* @__PURE__ */ jsx56(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
10517
|
+
"Linking\u2026"
|
|
10518
|
+
] }) : "Attach"
|
|
10519
|
+
}
|
|
10520
|
+
)
|
|
10521
|
+
] })
|
|
10522
|
+
] }) : null
|
|
10523
|
+
] }),
|
|
10016
10524
|
/* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
|
|
10017
|
-
/* @__PURE__ */ jsx56(Label3, { htmlFor: `${settingsGroup}-botName`, className: "text-sm", children: "
|
|
10525
|
+
/* @__PURE__ */ jsx56(Label3, { htmlFor: `${settingsGroup}-botName`, className: "text-sm", children: "Widget title" }),
|
|
10018
10526
|
/* @__PURE__ */ jsx56(
|
|
10019
10527
|
Input,
|
|
10020
10528
|
{
|
|
@@ -11770,7 +12278,7 @@ function CollectionEditPage({ collectionId }) {
|
|
|
11770
12278
|
}
|
|
11771
12279
|
|
|
11772
12280
|
// src/admin/pages/RolesPage.tsx
|
|
11773
|
-
import { useCallback as
|
|
12281
|
+
import { useCallback as useCallback8, useEffect as useEffect32, useState as useState35 } from "react";
|
|
11774
12282
|
import { useSession as useSession5 } from "next-auth/react";
|
|
11775
12283
|
import { Shield as Shield2, Save as Save9, Trash2 as Trash27 } from "lucide-react";
|
|
11776
12284
|
|
|
@@ -11814,7 +12322,7 @@ function RolesPage() {
|
|
|
11814
12322
|
const [newName, setNewName] = useState35("");
|
|
11815
12323
|
const [deleteRoleOpen, setDeleteRoleOpen] = useState35(false);
|
|
11816
12324
|
const [error, setError] = useState35(null);
|
|
11817
|
-
const load =
|
|
12325
|
+
const load = useCallback8(async () => {
|
|
11818
12326
|
setLoading(true);
|
|
11819
12327
|
setError(null);
|
|
11820
12328
|
try {
|
|
@@ -12350,6 +12858,39 @@ var CRUD_CONFIGS = {
|
|
|
12350
12858
|
{ field: "createdAt", displayName: "Created", type: "date" }
|
|
12351
12859
|
],
|
|
12352
12860
|
addEditPageUrl: ""
|
|
12861
|
+
},
|
|
12862
|
+
llm_agents: {
|
|
12863
|
+
title: "LLM agents",
|
|
12864
|
+
apiEndpoint: "/api/llm_agents",
|
|
12865
|
+
defaultSortField: "name",
|
|
12866
|
+
defaultSortOrder: "asc",
|
|
12867
|
+
columns: [
|
|
12868
|
+
{ field: "name", displayName: "Name" },
|
|
12869
|
+
{ field: "slug", displayName: "Slug" },
|
|
12870
|
+
{
|
|
12871
|
+
field: "systemInstruction",
|
|
12872
|
+
displayName: "System instruction",
|
|
12873
|
+
type: "textarea",
|
|
12874
|
+
hideInTable: true,
|
|
12875
|
+
textareaRows: 10,
|
|
12876
|
+
placeholder: "How the model should behave for this agent (sent as system prompt to the LLM)."
|
|
12877
|
+
},
|
|
12878
|
+
{ field: "model", displayName: "Model", placeholder: "Optional gateway model id" },
|
|
12879
|
+
{ field: "temperature", displayName: "Temperature", type: "number" },
|
|
12880
|
+
{ field: "maxTokens", displayName: "Max tokens", type: "number" },
|
|
12881
|
+
{
|
|
12882
|
+
field: "validationRules",
|
|
12883
|
+
displayName: "Validation & output guardrails",
|
|
12884
|
+
type: "textarea",
|
|
12885
|
+
hideInTable: true,
|
|
12886
|
+
textareaRows: 8,
|
|
12887
|
+
placeholder: "Plain text: rules appended to the system prompt. Or JSON: guardrails, maxUserChars, blockedSubstrings, etc."
|
|
12888
|
+
},
|
|
12889
|
+
{ field: "enabled", displayName: "Enabled", type: "boolean" },
|
|
12890
|
+
{ field: "createdAt", displayName: "Created", type: "date", hideInForm: true },
|
|
12891
|
+
{ field: "updatedAt", displayName: "Updated", type: "datetime", hideInForm: true }
|
|
12892
|
+
],
|
|
12893
|
+
addEditPageUrl: ""
|
|
12353
12894
|
}
|
|
12354
12895
|
};
|
|
12355
12896
|
function BlogEditorWrapper({ blogId }) {
|
|
@@ -12431,7 +12972,7 @@ function AdminPageResolver({ slug }) {
|
|
|
12431
12972
|
{ field: "orderCount", displayName: "Orders" },
|
|
12432
12973
|
{ field: "totalPaid", displayName: "Total paid" }
|
|
12433
12974
|
] : crud.columns;
|
|
12434
|
-
const extraListParams =
|
|
12975
|
+
const extraListParams = useMemo5(
|
|
12435
12976
|
() => isContactsWithStore ? { includeSummary: "1" } : void 0,
|
|
12436
12977
|
[isContactsWithStore]
|
|
12437
12978
|
);
|