@decido/discovery-studio 0.1.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +278 -84
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +213 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -6
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 🚀 @decido/discovery-studio
|
|
2
|
+
|
|
3
|
+
> WhatsApp Discovery Studio — Enterprise-grade conversational analytics, flow design, and live chat
|
|
4
|
+
|
|
5
|
+
Bienvenido a la documentación oficial de **@decido/discovery-studio**, un componente integral del ecosistema **Decido OS**.
|
|
6
|
+
|
|
7
|
+
## 📦 Instalación
|
|
8
|
+
|
|
9
|
+
Para aprovisionar este módulo dentro de otra área del monorepo o consumirlo remotamente:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @decido/discovery-studio
|
|
13
|
+
# o mediante el gestor oficial del monorepo
|
|
14
|
+
pnpm add @decido/discovery-studio
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 🔧 Estructura y Dependencias
|
|
18
|
+
|
|
19
|
+
Este paquete está diseñado para interoperar de forma nativa con la infraestructura central.
|
|
20
|
+
Para su correcto funcionamiento en un entorno aislado (Sandboxed), se apoya en los siguientes cimientos tecnológicos:
|
|
21
|
+
|
|
22
|
+
- `react`
|
|
23
|
+
- `react-dom`
|
|
24
|
+
- `@decido/canvas-ai`
|
|
25
|
+
- `@decido/kernel-bridge`
|
|
26
|
+
- `@decido/macia-core`
|
|
27
|
+
|
|
28
|
+
## 🔐 Licencia y Privacidad
|
|
29
|
+
El código de este componente se encuentra auditado y restringido (Sin Sourcemaps).
|
|
30
|
+
Propiedad Intelectual Protegida - Framework Decido OS.
|
|
31
|
+
Distribuido bajo licencia **UNLICENSED**.
|
package/dist/index.d.mts
CHANGED
|
@@ -67,7 +67,7 @@ interface FlowState {
|
|
|
67
67
|
edges: any[];
|
|
68
68
|
}
|
|
69
69
|
interface StudioState {
|
|
70
|
-
activeTab: 'chat' | 'flow' | 'analytics';
|
|
70
|
+
activeTab: 'chat' | 'flow' | 'analytics' | 'architect';
|
|
71
71
|
selectedContact: string | null;
|
|
72
72
|
explorerOpen: boolean;
|
|
73
73
|
inspectorOpen: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -67,7 +67,7 @@ interface FlowState {
|
|
|
67
67
|
edges: any[];
|
|
68
68
|
}
|
|
69
69
|
interface StudioState {
|
|
70
|
-
activeTab: 'chat' | 'flow' | 'analytics';
|
|
70
|
+
activeTab: 'chat' | 'flow' | 'analytics' | 'architect';
|
|
71
71
|
selectedContact: string | null;
|
|
72
72
|
explorerOpen: boolean;
|
|
73
73
|
inspectorOpen: boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React9 = require('react');
|
|
4
4
|
var socket_ioClient = require('socket.io-client');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var kernelBridge = require('@decido/kernel-bridge');
|
|
@@ -11,7 +11,7 @@ var lucideReact = require('lucide-react');
|
|
|
11
11
|
|
|
12
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var React9__default = /*#__PURE__*/_interopDefault(React9);
|
|
15
15
|
|
|
16
16
|
// src/DiscoveryStudio.tsx
|
|
17
17
|
var API_URL = undefined?.VITE_API_BASE_URL || "http://localhost:3001";
|
|
@@ -34,7 +34,7 @@ var Section = ({
|
|
|
34
34
|
defaultOpen = true,
|
|
35
35
|
children
|
|
36
36
|
}) => {
|
|
37
|
-
const [open, setOpen] =
|
|
37
|
+
const [open, setOpen] = React9.useState(defaultOpen);
|
|
38
38
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b", style: { borderColor: "var(--border-color)" }, children: [
|
|
39
39
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
40
40
|
"button",
|
|
@@ -54,9 +54,9 @@ var Section = ({
|
|
|
54
54
|
] });
|
|
55
55
|
};
|
|
56
56
|
var SideExplorer = ({ selectedContact, onSelectContact }) => {
|
|
57
|
-
const [filter, setFilter] =
|
|
58
|
-
const [conversations, setConversations] =
|
|
59
|
-
|
|
57
|
+
const [filter, setFilter] = React9.useState("");
|
|
58
|
+
const [conversations, setConversations] = React9.useState([]);
|
|
59
|
+
React9.useEffect(() => {
|
|
60
60
|
const fetchConversations = async () => {
|
|
61
61
|
try {
|
|
62
62
|
const res = await fetch(`${API_URL}/api/whatsapp/conversations`);
|
|
@@ -129,10 +129,7 @@ var SideExplorer = ({ selectedContact, onSelectContact }) => {
|
|
|
129
129
|
),
|
|
130
130
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
131
131
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
132
|
-
/* @__PURE__ */ jsxRuntime.
|
|
133
|
-
"+",
|
|
134
|
-
conv.phone
|
|
135
|
-
] }),
|
|
132
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-bold truncate", style: { color: "var(--text-primary)" }, children: conv.profile_name || "+" + conv.phone }),
|
|
136
133
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] shrink-0 ml-1", style: { color: "var(--text-secondary)" }, children: conv.last_activity.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) })
|
|
137
134
|
] }),
|
|
138
135
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] truncate mt-0.5", style: { color: "var(--text-secondary)" }, children: conv.last_message || "Media" })
|
|
@@ -189,9 +186,9 @@ var CONTACT_DETAILS = {
|
|
|
189
186
|
tags: ["VIP", "Frecuente", "Muebler\xEDa"],
|
|
190
187
|
timeline: [
|
|
191
188
|
{ time: "2m", event: "Pregunt\xF3 por estado de pedido", icon: "fas fa-comment" },
|
|
192
|
-
{ time: "1d", event: "Pedido PED-1847 en
|
|
193
|
-
{ time: "3d", event: "
|
|
194
|
-
{ time: "1w", event: "
|
|
189
|
+
{ time: "1d", event: "Pedido PED-1847 en PRODUCTION", icon: "fas fa-industry" },
|
|
190
|
+
{ time: "3d", event: "Transici\xF3n a IN_CUTTING (Control)", icon: "fas fa-check-circle" },
|
|
191
|
+
{ time: "1w", event: "Tracking Link Generado", icon: "fas fa-link" }
|
|
195
192
|
]
|
|
196
193
|
},
|
|
197
194
|
c2: {
|
|
@@ -206,7 +203,7 @@ var CONTACT_DETAILS = {
|
|
|
206
203
|
tags: ["Empresa", "Nuevo"],
|
|
207
204
|
timeline: [
|
|
208
205
|
{ time: "15m", event: "Solicit\xF3 cotizaci\xF3n de mesa", icon: "fas fa-comment" },
|
|
209
|
-
{ time: "2d", event: "
|
|
206
|
+
{ time: "2d", event: "RuleEngine Trigger: NEW Order", icon: "fas fa-bolt" }
|
|
210
207
|
]
|
|
211
208
|
}
|
|
212
209
|
};
|
|
@@ -306,25 +303,64 @@ var InspectorPanel = ({ selectedContact }) => {
|
|
|
306
303
|
] });
|
|
307
304
|
};
|
|
308
305
|
var AgentPanel = () => {
|
|
309
|
-
const [messages, setMessages] =
|
|
306
|
+
const [messages, setMessages] = React9.useState([
|
|
310
307
|
{ id: "1", text: "Soy tu Agente Vocal asignado. \xBFEn qu\xE9 te ayudo con tus flujos?", type: "system" }
|
|
311
308
|
]);
|
|
312
|
-
const [input, setInput] =
|
|
313
|
-
const [isTyping, setIsTyping] =
|
|
314
|
-
const scrollRef =
|
|
315
|
-
|
|
309
|
+
const [input, setInput] = React9.useState("");
|
|
310
|
+
const [isTyping, setIsTyping] = React9.useState(false);
|
|
311
|
+
const scrollRef = React9.useRef(null);
|
|
312
|
+
React9.useEffect(() => {
|
|
316
313
|
if (scrollRef.current) {
|
|
317
314
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
318
315
|
}
|
|
319
316
|
}, [messages]);
|
|
320
|
-
|
|
317
|
+
React9.useEffect(() => {
|
|
321
318
|
const unsubscribe = kernelBridge.kernel.onEvent((payload) => {
|
|
322
319
|
if (payload.event_type === "message_sent" && payload.data?.target === "vocal_domain_agent") ; else if (payload.event_type === "message_sent" && payload.data?.intent === "vocal_response") {
|
|
323
320
|
setMessages((prev) => [...prev, { id: Date.now().toString(), text: payload.data.payload, type: "agent" }]);
|
|
324
321
|
setIsTyping(false);
|
|
325
322
|
}
|
|
326
323
|
});
|
|
327
|
-
|
|
324
|
+
let es = null;
|
|
325
|
+
try {
|
|
326
|
+
es = new EventSource("http://localhost:3001/api/events");
|
|
327
|
+
es.addEventListener("whatsapp:message_received", (e) => {
|
|
328
|
+
try {
|
|
329
|
+
const data = JSON.parse(e.data);
|
|
330
|
+
setMessages((prev) => [...prev, {
|
|
331
|
+
id: Date.now().toString(),
|
|
332
|
+
text: `\u{1F4F1} [WA] ${data.profileName || data.from}: ${data.text || "Archivo Adjunto"}`,
|
|
333
|
+
type: "user"
|
|
334
|
+
}]);
|
|
335
|
+
setIsTyping(true);
|
|
336
|
+
setTimeout(() => {
|
|
337
|
+
setMessages((p) => [...p, { id: Date.now().toString(), text: "Regla disparada: Mensaje recibido. Evaluando intenci\xF3n...", type: "system" }]);
|
|
338
|
+
setIsTyping(false);
|
|
339
|
+
}, 1e3);
|
|
340
|
+
} catch (e2) {
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
es.addEventListener("whatsapp:status_update", (e) => {
|
|
344
|
+
try {
|
|
345
|
+
const data = JSON.parse(e.data);
|
|
346
|
+
setMessages((prev) => [...prev, {
|
|
347
|
+
id: Date.now().toString(),
|
|
348
|
+
text: `\u2714\uFE0F [Estado WA] ${data.status} a ${data.recipient_id}`,
|
|
349
|
+
type: "system"
|
|
350
|
+
}]);
|
|
351
|
+
} catch (e2) {
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
es.onerror = () => {
|
|
355
|
+
es?.close();
|
|
356
|
+
};
|
|
357
|
+
} catch (e) {
|
|
358
|
+
console.log("SSE Error, falling back to local kernel");
|
|
359
|
+
}
|
|
360
|
+
return () => {
|
|
361
|
+
unsubscribe();
|
|
362
|
+
if (es) es.close();
|
|
363
|
+
};
|
|
328
364
|
}, []);
|
|
329
365
|
const handleSend = async () => {
|
|
330
366
|
if (!input.trim()) return;
|
|
@@ -412,12 +448,12 @@ var AgentPanel = () => {
|
|
|
412
448
|
};
|
|
413
449
|
var API_URL2 = undefined?.VITE_API_BASE_URL || "http://localhost:3001";
|
|
414
450
|
var ChatTab = ({ selectedContact }) => {
|
|
415
|
-
const [messages, setMessages] =
|
|
416
|
-
const [input, setInput] =
|
|
417
|
-
const [opMode, setOpMode] =
|
|
418
|
-
const [socket, setSocket] =
|
|
419
|
-
const chatEndRef =
|
|
420
|
-
const fetchMessages =
|
|
451
|
+
const [messages, setMessages] = React9.useState([]);
|
|
452
|
+
const [input, setInput] = React9.useState("");
|
|
453
|
+
const [opMode, setOpMode] = React9.useState("COPILOT");
|
|
454
|
+
const [socket, setSocket] = React9.useState(null);
|
|
455
|
+
const chatEndRef = React9.useRef(null);
|
|
456
|
+
const fetchMessages = React9.useCallback(async () => {
|
|
421
457
|
if (!selectedContact) {
|
|
422
458
|
setMessages([]);
|
|
423
459
|
return;
|
|
@@ -438,7 +474,7 @@ var ChatTab = ({ selectedContact }) => {
|
|
|
438
474
|
console.error("Failed to fetch messages:", error);
|
|
439
475
|
}
|
|
440
476
|
}, [selectedContact]);
|
|
441
|
-
|
|
477
|
+
React9.useEffect(() => {
|
|
442
478
|
fetchMessages();
|
|
443
479
|
const s = socket_ioClient.io(API_URL2, { transports: ["websocket", "polling"] });
|
|
444
480
|
s.on("connect", () => console.log("[ChatTab] Connected to WebSocket"));
|
|
@@ -460,7 +496,7 @@ var ChatTab = ({ selectedContact }) => {
|
|
|
460
496
|
s.disconnect();
|
|
461
497
|
};
|
|
462
498
|
}, [selectedContact, fetchMessages]);
|
|
463
|
-
|
|
499
|
+
React9.useEffect(() => {
|
|
464
500
|
chatEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
465
501
|
}, [messages]);
|
|
466
502
|
const handleSend = async () => {
|
|
@@ -666,7 +702,7 @@ var MESSAGE_CONFIG = {
|
|
|
666
702
|
outgoing: { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Reply, { size: 14 }), colorClass: "text-blue-400", bgClass: "from-blue-500/10 to-transparent" },
|
|
667
703
|
system: { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { size: 14 }), colorClass: "text-purple-400", bgClass: "from-purple-500/10 to-transparent" }
|
|
668
704
|
};
|
|
669
|
-
var MessageNode =
|
|
705
|
+
var MessageNode = React9.memo(({ id, data, selected }) => {
|
|
670
706
|
const nodeData = data || {};
|
|
671
707
|
const config = MESSAGE_CONFIG[nodeData.type] || MESSAGE_CONFIG.incoming;
|
|
672
708
|
const titleElement = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center w-full min-w-[140px]", children: [
|
|
@@ -699,7 +735,7 @@ var ACTION_CONFIG = {
|
|
|
699
735
|
analyze: { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Brain, { size: 14 }), colorClass: "text-violet-400", bgClass: "from-violet-500/10 to-transparent" },
|
|
700
736
|
decision: { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranch, { size: 14 }), colorClass: "text-cyan-400", bgClass: "from-cyan-500/10 to-transparent" }
|
|
701
737
|
};
|
|
702
|
-
var BotActionNode =
|
|
738
|
+
var BotActionNode = React9.memo(({ id, data, selected }) => {
|
|
703
739
|
const nodeData = data || {};
|
|
704
740
|
const config = ACTION_CONFIG[nodeData?.actionType] || ACTION_CONFIG.reply;
|
|
705
741
|
const titleElement = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -725,6 +761,56 @@ var BotActionNode = React8.memo(({ id, data, selected }) => {
|
|
|
725
761
|
);
|
|
726
762
|
});
|
|
727
763
|
BotActionNode.displayName = "BotActionNode";
|
|
764
|
+
var TrackingPreview = ({ token = "demo-token-123", onClose }) => {
|
|
765
|
+
const trackingUrl = `http://localhost:3001/track/${token}`;
|
|
766
|
+
const [isLoading, setIsLoading] = React9.useState(true);
|
|
767
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm p-4 animate-in fade-in", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-[400px] bg-[#0E1525] rounded-[24px] overflow-hidden border border-white/10 shadow-2xl flex flex-col h-[700px] max-h-[90vh] relative animate-in zoom-in-95", children: [
|
|
768
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-4 right-4 z-10 flex gap-2", children: [
|
|
769
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
770
|
+
"button",
|
|
771
|
+
{
|
|
772
|
+
onClick: () => window.open(trackingUrl, "_blank"),
|
|
773
|
+
className: "w-8 h-8 rounded-full bg-white/10 backdrop-blur-md flex items-center justify-center text-white/70 hover:text-white hover:bg-white/20 transition-colors",
|
|
774
|
+
title: "Abrir en nueva pesta\xF1a",
|
|
775
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-external-link-alt text-xs" })
|
|
776
|
+
}
|
|
777
|
+
),
|
|
778
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
779
|
+
"button",
|
|
780
|
+
{
|
|
781
|
+
onClick: onClose,
|
|
782
|
+
className: "w-8 h-8 rounded-full bg-white/10 backdrop-blur-md flex items-center justify-center text-white/70 hover:text-white hover:bg-white/20 transition-colors",
|
|
783
|
+
title: "Cerrar vista previa",
|
|
784
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-times text-xs" })
|
|
785
|
+
}
|
|
786
|
+
)
|
|
787
|
+
] }),
|
|
788
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-7 w-full bg-black flex justify-center items-start shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[120px] h-5 bg-black rounded-b-xl" }) }),
|
|
789
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-2 bg-black/50 border-b border-white/5 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white/5 rounded-lg px-3 py-1 flex items-center gap-2 text-[10px] text-white/40 w-fit", children: [
|
|
790
|
+
/* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-lock text-[8px]" }),
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
792
|
+
"decido.com/track/",
|
|
793
|
+
token
|
|
794
|
+
] })
|
|
795
|
+
] }) }),
|
|
796
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 relative bg-black", children: [
|
|
797
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center bg-[#0E1525] text-white/50", children: [
|
|
798
|
+
/* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-circle-notch fa-spin text-2xl text-emerald-500 mb-3" }),
|
|
799
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: "Cargando vista m\xF3vil..." })
|
|
800
|
+
] }),
|
|
801
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
802
|
+
"iframe",
|
|
803
|
+
{
|
|
804
|
+
src: trackingUrl,
|
|
805
|
+
className: `w-full h-full border-none transition-opacity duration-300 ${isLoading ? "opacity-0" : "opacity-100"}`,
|
|
806
|
+
onLoad: () => setIsLoading(false),
|
|
807
|
+
title: "Tracking Portal Preview"
|
|
808
|
+
}
|
|
809
|
+
)
|
|
810
|
+
] }),
|
|
811
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-full bg-black flex justify-center items-center shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[120px] h-1 bg-white/20 rounded-full" }) })
|
|
812
|
+
] }) });
|
|
813
|
+
};
|
|
728
814
|
var nodeTypes = {
|
|
729
815
|
messageNode: MessageNode,
|
|
730
816
|
botAction: BotActionNode
|
|
@@ -742,14 +828,14 @@ var initialNodes = [
|
|
|
742
828
|
id: "ai-intent",
|
|
743
829
|
type: "botAction",
|
|
744
830
|
position: { x: 400, y: 280 },
|
|
745
|
-
data: { label: "
|
|
831
|
+
data: { label: "Reconocimiento Intenci\xF3n IA", actionType: "analyze", description: 'Detectar Intenci\xF3n: "Estado de Pedido"' }
|
|
746
832
|
},
|
|
747
833
|
// Database Check
|
|
748
834
|
{
|
|
749
835
|
id: "db-check",
|
|
750
836
|
type: "botAction",
|
|
751
837
|
position: { x: 750, y: 150 },
|
|
752
|
-
data: { label: "
|
|
838
|
+
data: { label: "Acci\xF3n Ejecutada", actionType: "decision", description: "Action: GENERATE_TRACKING_LINK" }
|
|
753
839
|
},
|
|
754
840
|
{
|
|
755
841
|
id: "escalate-human",
|
|
@@ -762,13 +848,13 @@ var initialNodes = [
|
|
|
762
848
|
id: "reply-status",
|
|
763
849
|
type: "messageNode",
|
|
764
850
|
position: { x: 1050, y: 150 },
|
|
765
|
-
data: { label: "
|
|
851
|
+
data: { label: "Regla: SEND_WA_TEMPLATE", type: "outgoing", text: "Template: pedido_produccion\nPar\xE1metros: [legacyId, trackUrl]", time: "10:06 AM" }
|
|
766
852
|
},
|
|
767
853
|
{
|
|
768
854
|
id: "assign-agent",
|
|
769
855
|
type: "messageNode",
|
|
770
856
|
position: { x: 1050, y: 400 },
|
|
771
|
-
data: { label: "Soporte Asignado", type: "system", text: "Asignando Chat #3421
|
|
857
|
+
data: { label: "Soporte Asignado", type: "system", text: "Asignando Chat #3421 (Humano en la ruta)" }
|
|
772
858
|
}
|
|
773
859
|
];
|
|
774
860
|
var initialEdges = [
|
|
@@ -780,15 +866,21 @@ var initialEdges = [
|
|
|
780
866
|
{ id: "e6", source: "escalate-human", target: "assign-agent", style: { stroke: "#f59e0b" }, markerEnd: { type: react.MarkerType.ArrowClosed, color: "#f59e0b" } }
|
|
781
867
|
];
|
|
782
868
|
var FlowCanvasTab = () => {
|
|
783
|
-
const [nodes, setNodes] =
|
|
784
|
-
const [edges, setEdges] =
|
|
785
|
-
const
|
|
869
|
+
const [nodes, setNodes] = React9.useState(initialNodes);
|
|
870
|
+
const [edges, setEdges] = React9.useState(initialEdges);
|
|
871
|
+
const [previewOpen, setPreviewOpen] = React9.useState(false);
|
|
872
|
+
const onNodesChange = React9.useCallback((changes) => {
|
|
786
873
|
}, []);
|
|
787
|
-
const onEdgesChange =
|
|
874
|
+
const onEdgesChange = React9.useCallback((changes) => {
|
|
788
875
|
}, []);
|
|
789
|
-
const onConnect =
|
|
876
|
+
const onConnect = React9.useCallback((params) => {
|
|
790
877
|
setEdges((eds) => [...eds, { ...params, id: `e-${Date.now()}`, animated: true }]);
|
|
791
878
|
}, [setEdges]);
|
|
879
|
+
const onNodeClick = React9.useCallback((event, node) => {
|
|
880
|
+
if (node.data?.description?.includes("GENERATE_TRACKING_LINK") || node.data?.text?.includes("trackUrl")) {
|
|
881
|
+
setPreviewOpen(true);
|
|
882
|
+
}
|
|
883
|
+
}, []);
|
|
792
884
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-h-0 flex flex-col overflow-hidden", children: [
|
|
793
885
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
794
886
|
"div",
|
|
@@ -840,9 +932,11 @@ var FlowCanvasTab = () => {
|
|
|
840
932
|
onNodesChange,
|
|
841
933
|
onEdgesChange,
|
|
842
934
|
onConnect,
|
|
935
|
+
onNodeClick,
|
|
843
936
|
nodeTypes
|
|
844
937
|
}
|
|
845
|
-
) })
|
|
938
|
+
) }),
|
|
939
|
+
previewOpen && /* @__PURE__ */ jsxRuntime.jsx(TrackingPreview, { onClose: () => setPreviewOpen(false) })
|
|
846
940
|
] });
|
|
847
941
|
};
|
|
848
942
|
var HOURLY_DATA = [
|
|
@@ -901,8 +995,8 @@ var BarChart = ({ data }) => {
|
|
|
901
995
|
] }, i)) });
|
|
902
996
|
};
|
|
903
997
|
var AnalyticsTab = () => {
|
|
904
|
-
const [animatedValues, setAnimatedValues] =
|
|
905
|
-
|
|
998
|
+
const [animatedValues, setAnimatedValues] = React9.useState({});
|
|
999
|
+
React9.useEffect(() => {
|
|
906
1000
|
const timer = setTimeout(() => {
|
|
907
1001
|
const vals = {};
|
|
908
1002
|
TOP_INTENTS.forEach((intent) => {
|
|
@@ -999,7 +1093,7 @@ var AnalyticsTab = () => {
|
|
|
999
1093
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-1", style: { gridTemplateColumns: "auto repeat(24, 1fr)" }, children: [
|
|
1000
1094
|
/* @__PURE__ */ jsxRuntime.jsx("div", {}),
|
|
1001
1095
|
Array.from({ length: 24 }, (_, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[7px] text-center font-bold", style: { color: "var(--text-secondary)" }, children: i }, i)),
|
|
1002
|
-
["Lun", "Mar", "Mi\xE9", "Jue", "Vie", "S\xE1b", "Dom"].map((day, di) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1096
|
+
["Lun", "Mar", "Mi\xE9", "Jue", "Vie", "S\xE1b", "Dom"].map((day, di) => /* @__PURE__ */ jsxRuntime.jsxs(React9__default.default.Fragment, { children: [
|
|
1003
1097
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[9px] font-bold pr-2 flex items-center", style: { color: "var(--text-secondary)" }, children: day }),
|
|
1004
1098
|
Array.from({ length: 24 }, (_, hi) => {
|
|
1005
1099
|
const intensity = Math.random();
|
|
@@ -1024,20 +1118,20 @@ var AnalyticsTab = () => {
|
|
|
1024
1118
|
] });
|
|
1025
1119
|
};
|
|
1026
1120
|
var ApiTesterTab = () => {
|
|
1027
|
-
const [phone, setPhone] =
|
|
1028
|
-
const [msgType, setMsgType] =
|
|
1029
|
-
const [payloadText, setPayloadText] =
|
|
1030
|
-
const [templateName, setTemplateName] =
|
|
1031
|
-
const [templateLanguage, setTemplateLanguage] =
|
|
1032
|
-
const [loading, setLoading] =
|
|
1033
|
-
const [result, setResult] =
|
|
1034
|
-
const [savedPhones, setSavedPhones] =
|
|
1035
|
-
const [newPhoneName, setNewPhoneName] =
|
|
1036
|
-
const [showPhoneSave, setShowPhoneSave] =
|
|
1037
|
-
const [templateVariables, setTemplateVariables] =
|
|
1038
|
-
const [templates, setTemplates] =
|
|
1039
|
-
const [fetchingTemplates, setFetchingTemplates] =
|
|
1040
|
-
|
|
1121
|
+
const [phone, setPhone] = React9.useState("");
|
|
1122
|
+
const [msgType, setMsgType] = React9.useState("text");
|
|
1123
|
+
const [payloadText, setPayloadText] = React9.useState("Hola desde Decido OS \u{1F680}");
|
|
1124
|
+
const [templateName, setTemplateName] = React9.useState("hello_world");
|
|
1125
|
+
const [templateLanguage, setTemplateLanguage] = React9.useState("en_US");
|
|
1126
|
+
const [loading, setLoading] = React9.useState(false);
|
|
1127
|
+
const [result, setResult] = React9.useState(null);
|
|
1128
|
+
const [savedPhones, setSavedPhones] = React9.useState([]);
|
|
1129
|
+
const [newPhoneName, setNewPhoneName] = React9.useState("");
|
|
1130
|
+
const [showPhoneSave, setShowPhoneSave] = React9.useState(false);
|
|
1131
|
+
const [templateVariables, setTemplateVariables] = React9.useState([]);
|
|
1132
|
+
const [templates, setTemplates] = React9.useState([]);
|
|
1133
|
+
const [fetchingTemplates, setFetchingTemplates] = React9.useState(false);
|
|
1134
|
+
React9__default.default.useEffect(() => {
|
|
1041
1135
|
const saved = localStorage.getItem("wa_api_tester_phones");
|
|
1042
1136
|
if (saved) {
|
|
1043
1137
|
try {
|
|
@@ -1047,7 +1141,7 @@ var ApiTesterTab = () => {
|
|
|
1047
1141
|
}
|
|
1048
1142
|
fetchTemplates();
|
|
1049
1143
|
}, []);
|
|
1050
|
-
|
|
1144
|
+
React9__default.default.useEffect(() => {
|
|
1051
1145
|
const selected = templates.find((t) => t.name === templateName && t.language === templateLanguage);
|
|
1052
1146
|
if (selected) {
|
|
1053
1147
|
const bodyComponent = selected.components?.find((c) => c.type === "BODY" || c.type === "body");
|
|
@@ -1340,18 +1434,18 @@ var ApiTesterTab = () => {
|
|
|
1340
1434
|
] }) });
|
|
1341
1435
|
};
|
|
1342
1436
|
var TemplateManagerTab = () => {
|
|
1343
|
-
const [templates, setTemplates] =
|
|
1344
|
-
const [loading, setLoading] =
|
|
1345
|
-
const [error, setError] =
|
|
1346
|
-
const [creating, setCreating] =
|
|
1347
|
-
const [name, setName] =
|
|
1348
|
-
const [category, setCategory] =
|
|
1349
|
-
const [language, setLanguage] =
|
|
1350
|
-
const [headerText, setHeaderText] =
|
|
1351
|
-
const [bodyText, setBodyText] =
|
|
1352
|
-
const [footerText, setFooterText] =
|
|
1353
|
-
const [buttons, setButtons] =
|
|
1354
|
-
|
|
1437
|
+
const [templates, setTemplates] = React9.useState([]);
|
|
1438
|
+
const [loading, setLoading] = React9.useState(true);
|
|
1439
|
+
const [error, setError] = React9.useState(null);
|
|
1440
|
+
const [creating, setCreating] = React9.useState(false);
|
|
1441
|
+
const [name, setName] = React9.useState("");
|
|
1442
|
+
const [category, setCategory] = React9.useState("UTILITY");
|
|
1443
|
+
const [language, setLanguage] = React9.useState("es");
|
|
1444
|
+
const [headerText, setHeaderText] = React9.useState("");
|
|
1445
|
+
const [bodyText, setBodyText] = React9.useState("Hola {{1}}, tu pedido est\xE1 listo.");
|
|
1446
|
+
const [footerText, setFooterText] = React9.useState("");
|
|
1447
|
+
const [buttons, setButtons] = React9.useState([]);
|
|
1448
|
+
React9.useEffect(() => {
|
|
1355
1449
|
fetchTemplates();
|
|
1356
1450
|
}, []);
|
|
1357
1451
|
const fetchTemplates = async () => {
|
|
@@ -1693,15 +1787,112 @@ var TemplateManagerTab = () => {
|
|
|
1693
1787
|
] })
|
|
1694
1788
|
] }) });
|
|
1695
1789
|
};
|
|
1790
|
+
var SUGGESTIONS = [
|
|
1791
|
+
{ icon: "fas fa-comment-dots", color: "text-indigo-400", bg: "bg-indigo-500/10", text: "Saluda al cliente cuando se cree un pedido" },
|
|
1792
|
+
{ icon: "fas fa-camera", color: "text-amber-400", bg: "bg-amber-500/10", text: "Detecta pagos en fotos de comprobante" },
|
|
1793
|
+
{ icon: "fas fa-industry", color: "text-emerald-400", bg: "bg-emerald-500/10", text: "Avisa por WhatsApp al pasar a Producci\xF3n" },
|
|
1794
|
+
{ icon: "fas fa-truck", color: "text-cyan-400", bg: "bg-cyan-500/10", text: "Pedido listo: avisa si >$1M" }
|
|
1795
|
+
];
|
|
1796
|
+
var RulesArchitectTab = () => {
|
|
1797
|
+
const [prompt, setPrompt] = React9.useState("");
|
|
1798
|
+
const [loading, setLoading] = React9.useState(false);
|
|
1799
|
+
const [result, setResult] = React9.useState(null);
|
|
1800
|
+
const [error, setError] = React9.useState(null);
|
|
1801
|
+
const generateRule = async (textToUse) => {
|
|
1802
|
+
const text = textToUse || prompt;
|
|
1803
|
+
if (!text.trim()) return;
|
|
1804
|
+
setLoading(true);
|
|
1805
|
+
setError(null);
|
|
1806
|
+
setResult(null);
|
|
1807
|
+
try {
|
|
1808
|
+
const res = await fetch("http://localhost:3001/api/whatsapp/rules/generate", {
|
|
1809
|
+
method: "POST",
|
|
1810
|
+
headers: {
|
|
1811
|
+
"Content-Type": "application/json",
|
|
1812
|
+
// Note: Mocking tenant matching local dev
|
|
1813
|
+
"x-tenant-id": "dev-tenant"
|
|
1814
|
+
},
|
|
1815
|
+
body: JSON.stringify({ prompt: text })
|
|
1816
|
+
});
|
|
1817
|
+
if (!res.ok) throw new Error("Error al generar regla IA");
|
|
1818
|
+
const data = await res.json();
|
|
1819
|
+
setResult(JSON.stringify(data.rule || data, null, 2));
|
|
1820
|
+
} catch (err) {
|
|
1821
|
+
setError(err.message || "Error de conexi\xF3n con el AI Service");
|
|
1822
|
+
} finally {
|
|
1823
|
+
setLoading(false);
|
|
1824
|
+
}
|
|
1825
|
+
};
|
|
1826
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-full flex flex-col items-center justify-center p-8 bg-black/20 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-3xl", children: [
|
|
1827
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-10 text-white", children: [
|
|
1828
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-indigo-500/20 text-indigo-400 mb-6 border border-indigo-500/30 shadow-[0_0_30px_rgba(99,102,241,0.2)]", children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-wand-magic-sparkles text-2xl" }) }),
|
|
1829
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-black tracking-tight mb-3", children: "Workflow Architect" }),
|
|
1830
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-zinc-400 max-w-lg mx-auto leading-relaxed", children: "Escribe una instrucci\xF3n en lenguaje natural y Sentinal AI generar\xE1 la regla JSON requerida para la automatizaci\xF3n de WhatsApp." })
|
|
1831
|
+
] }),
|
|
1832
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3 mb-8", children: SUGGESTIONS.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1833
|
+
"button",
|
|
1834
|
+
{
|
|
1835
|
+
onClick: () => {
|
|
1836
|
+
setPrompt(s.text);
|
|
1837
|
+
generateRule(s.text);
|
|
1838
|
+
},
|
|
1839
|
+
className: `flex items-center gap-3 p-4 text-left rounded-xl transition-all border border-white/5 bg-zinc-900/50 hover:bg-zinc-800/80 hover:border-white/10 group`,
|
|
1840
|
+
children: [
|
|
1841
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-8 h-8 shrink-0 flex items-center justify-center rounded-lg ${s.bg} ${s.color}`, children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: s.icon }) }),
|
|
1842
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-zinc-300 group-hover:text-white leading-tight", children: s.text })
|
|
1843
|
+
]
|
|
1844
|
+
},
|
|
1845
|
+
i
|
|
1846
|
+
)) }),
|
|
1847
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
1848
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
|
|
1849
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-terminal text-zinc-500" }) }),
|
|
1850
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1851
|
+
"input",
|
|
1852
|
+
{
|
|
1853
|
+
type: "text",
|
|
1854
|
+
value: prompt,
|
|
1855
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
1856
|
+
onKeyDown: (e) => e.key === "Enter" && generateRule(),
|
|
1857
|
+
placeholder: "Ej: Cuando un pedido pase de Producci\xF3n a Dispatch, env\xEDa una plantilla...",
|
|
1858
|
+
className: "block w-full pl-11 pr-32 py-4 bg-zinc-950/80 border-2 border-zinc-800 rounded-xl text-sm outline-none text-zinc-200 placeholder-zinc-600 focus:border-indigo-500/50 focus:bg-zinc-950 transition-all shadow-inner"
|
|
1859
|
+
}
|
|
1860
|
+
),
|
|
1861
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1862
|
+
"button",
|
|
1863
|
+
{
|
|
1864
|
+
onClick: () => generateRule(),
|
|
1865
|
+
disabled: loading || !prompt.trim(),
|
|
1866
|
+
className: "absolute right-2 top-2 bottom-2 px-6 bg-indigo-600 hover:bg-indigo-500 disabled:bg-zinc-800 disabled:text-zinc-600 text-white font-bold rounded-lg text-sm transition-all shadow-lg active:scale-95 flex items-center gap-2",
|
|
1867
|
+
children: loading ? /* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-circle-notch fa-spin" }) : "Generar"
|
|
1868
|
+
}
|
|
1869
|
+
)
|
|
1870
|
+
] }),
|
|
1871
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 rounded-xl bg-rose-500/10 border border-rose-500/20 text-rose-400 text-sm flex items-start gap-3 animate-in fade-in slide-in-from-top-2", children: [
|
|
1872
|
+
/* @__PURE__ */ jsxRuntime.jsx("i", { className: "fas fa-exclamation-circle mt-0.5" }),
|
|
1873
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: error })
|
|
1874
|
+
] }),
|
|
1875
|
+
result && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl overflow-hidden border border-zinc-800 bg-[#0d1117] relative animate-in zoom-in-95 fade-in duration-300 shadow-2xl", children: [
|
|
1876
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2 border-b border-zinc-800 bg-[#161b22] flex items-center gap-2", children: [
|
|
1877
|
+
/* @__PURE__ */ jsxRuntime.jsx("i", { className: "fab fa-js text-yellow-400/80 text-xs" }),
|
|
1878
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-mono text-zinc-400", children: "generated_rule.json" }),
|
|
1879
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
|
|
1880
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase font-bold text-emerald-400 bg-emerald-500/10 px-2 py-0.5 rounded", children: "V\xE1lido" })
|
|
1881
|
+
] }),
|
|
1882
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-5 text-xs font-mono leading-relaxed text-[#c9d1d9] overflow-x-auto whitespace-pre-wrap max-h-[300px] overflow-y-auto custom-scrollbar", children: result })
|
|
1883
|
+
] })
|
|
1884
|
+
] })
|
|
1885
|
+
] }) });
|
|
1886
|
+
};
|
|
1696
1887
|
var useStatusMetrics = () => {
|
|
1697
|
-
const [metrics, setMetrics] =
|
|
1888
|
+
const [metrics, setMetrics] = React9.useState({
|
|
1698
1889
|
activeChats: 12,
|
|
1699
1890
|
avgResponse: "2.4s",
|
|
1700
1891
|
todayMessages: 347,
|
|
1701
1892
|
botUptime: "99.8%",
|
|
1702
1893
|
queuedMessages: 3
|
|
1703
1894
|
});
|
|
1704
|
-
|
|
1895
|
+
React9.useEffect(() => {
|
|
1705
1896
|
const interval = setInterval(() => {
|
|
1706
1897
|
setMetrics((prev) => ({
|
|
1707
1898
|
...prev,
|
|
@@ -1714,7 +1905,7 @@ var useStatusMetrics = () => {
|
|
|
1714
1905
|
}, []);
|
|
1715
1906
|
return metrics;
|
|
1716
1907
|
};
|
|
1717
|
-
var StatusBarMetrics =
|
|
1908
|
+
var StatusBarMetrics = React9__default.default.memo(() => {
|
|
1718
1909
|
const metrics = useStatusMetrics();
|
|
1719
1910
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1720
1911
|
"div",
|
|
@@ -1762,20 +1953,21 @@ var StatusBarMetrics = React8__default.default.memo(() => {
|
|
|
1762
1953
|
var TABS = [
|
|
1763
1954
|
{ id: "chat", label: "Live Chat", icon: "fas fa-comments" },
|
|
1764
1955
|
{ id: "flow", label: "Flow Canvas", icon: "fas fa-project-diagram" },
|
|
1956
|
+
{ id: "architect", label: "Workflow Architect", icon: "fas fa-wand-magic-sparkles" },
|
|
1765
1957
|
{ id: "analytics", label: "Analytics", icon: "fas fa-chart-bar" },
|
|
1766
1958
|
{ id: "api_tester", label: "API Tester", icon: "fas fa-vial" },
|
|
1767
1959
|
{ id: "templates", label: "Templates", icon: "fas fa-layer-group" }
|
|
1768
1960
|
];
|
|
1769
1961
|
var DiscoveryStudio = ({ gatewayStatus = "connected", activeProvider = "Meta Cloud API" }) => {
|
|
1770
|
-
const [activeTab, setActiveTab] =
|
|
1771
|
-
const [explorerOpen, setExplorerOpen] =
|
|
1772
|
-
const [inspectorOpen, setInspectorOpen] =
|
|
1773
|
-
const [agentOpen, setAgentOpen] =
|
|
1774
|
-
const [selectedContact, setSelectedContact] =
|
|
1775
|
-
const [cmdOpen, setCmdOpen] =
|
|
1776
|
-
const [cmdQuery, setCmdQuery] =
|
|
1777
|
-
const cmdInputRef =
|
|
1778
|
-
|
|
1962
|
+
const [activeTab, setActiveTab] = React9.useState("chat");
|
|
1963
|
+
const [explorerOpen, setExplorerOpen] = React9.useState(true);
|
|
1964
|
+
const [inspectorOpen, setInspectorOpen] = React9.useState(false);
|
|
1965
|
+
const [agentOpen, setAgentOpen] = React9.useState(true);
|
|
1966
|
+
const [selectedContact, setSelectedContact] = React9.useState(null);
|
|
1967
|
+
const [cmdOpen, setCmdOpen] = React9.useState(false);
|
|
1968
|
+
const [cmdQuery, setCmdQuery] = React9.useState("");
|
|
1969
|
+
const cmdInputRef = React9.useRef(null);
|
|
1970
|
+
React9.useEffect(() => {
|
|
1779
1971
|
const handleKeyDown = (e) => {
|
|
1780
1972
|
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
|
1781
1973
|
e.preventDefault();
|
|
@@ -1787,7 +1979,7 @@ var DiscoveryStudio = ({ gatewayStatus = "connected", activeProvider = "Meta Clo
|
|
|
1787
1979
|
window.addEventListener("keydown", handleKeyDown);
|
|
1788
1980
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1789
1981
|
}, []);
|
|
1790
|
-
|
|
1982
|
+
React9.useEffect(() => {
|
|
1791
1983
|
if (cmdOpen && cmdInputRef.current) {
|
|
1792
1984
|
cmdInputRef.current.focus();
|
|
1793
1985
|
}
|
|
@@ -1795,6 +1987,7 @@ var DiscoveryStudio = ({ gatewayStatus = "connected", activeProvider = "Meta Clo
|
|
|
1795
1987
|
const commands = [
|
|
1796
1988
|
{ id: "chat", label: "Abrir Chat en Vivo", icon: "fas fa-comments", action: () => setActiveTab("chat") },
|
|
1797
1989
|
{ id: "flow", label: "Abrir Flow Canvas", icon: "fas fa-project-diagram", action: () => setActiveTab("flow") },
|
|
1990
|
+
{ id: "architect", label: "Abrir Workflow Architect (IA)", icon: "fas fa-wand-magic-sparkles", action: () => setActiveTab("architect") },
|
|
1798
1991
|
{ id: "analytics", label: "Abrir Analytics", icon: "fas fa-chart-bar", action: () => setActiveTab("analytics") },
|
|
1799
1992
|
{ id: "explorer", label: explorerOpen ? "Cerrar Explorer" : "Abrir Explorer", icon: "fas fa-folder-tree", action: () => setExplorerOpen((p) => !p) },
|
|
1800
1993
|
{ id: "inspector", label: inspectorOpen ? "Cerrar Inspector" : "Abrir Inspector", icon: "fas fa-info-circle", action: () => setInspectorOpen((p) => !p) },
|
|
@@ -1952,6 +2145,7 @@ var DiscoveryStudio = ({ gatewayStatus = "connected", activeProvider = "Meta Clo
|
|
|
1952
2145
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex flex-col overflow-hidden", children: [
|
|
1953
2146
|
activeTab === "chat" && /* @__PURE__ */ jsxRuntime.jsx(ChatTab, { selectedContact }),
|
|
1954
2147
|
activeTab === "flow" && /* @__PURE__ */ jsxRuntime.jsx(FlowCanvasTab, {}),
|
|
2148
|
+
activeTab === "architect" && /* @__PURE__ */ jsxRuntime.jsx(RulesArchitectTab, {}),
|
|
1955
2149
|
activeTab === "analytics" && /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTab, {}),
|
|
1956
2150
|
activeTab === "api_tester" && /* @__PURE__ */ jsxRuntime.jsx(ApiTesterTab, {}),
|
|
1957
2151
|
activeTab === "templates" && /* @__PURE__ */ jsxRuntime.jsx(TemplateManagerTab, {})
|