@greatapps/greatagents-ui 0.1.0 → 0.2.0

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/index.js CHANGED
@@ -443,7 +443,3161 @@ function useGagentsContacts(config, params) {
443
443
  select: (res) => ({ data: res.data || [], total: res.total || 0 })
444
444
  });
445
445
  }
446
+
447
+ // src/components/agents/agents-table.tsx
448
+ import { useMemo as useMemo2, useState } from "react";
449
+ import { DataTable } from "@greatapps/greatauth-ui";
450
+ import {
451
+ Input,
452
+ Badge,
453
+ Tooltip,
454
+ TooltipTrigger,
455
+ TooltipContent,
456
+ AlertDialog,
457
+ AlertDialogAction,
458
+ AlertDialogCancel,
459
+ AlertDialogContent,
460
+ AlertDialogDescription,
461
+ AlertDialogFooter,
462
+ AlertDialogHeader,
463
+ AlertDialogTitle,
464
+ Button
465
+ } from "@greatapps/greatauth-ui/ui";
466
+ import { Pencil, Trash2, Search } from "lucide-react";
467
+ import { EntityAvatar } from "@greatapps/greatauth-ui";
468
+ import { format } from "date-fns";
469
+ import { ptBR } from "date-fns/locale";
470
+ import { toast } from "sonner";
471
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
472
+ function useColumns(onEdit, onDelete) {
473
+ return [
474
+ {
475
+ accessorKey: "title",
476
+ header: "Nome",
477
+ cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
478
+ /* @__PURE__ */ jsx(EntityAvatar, { photo: row.original.photo, name: row.original.title, size: "sm" }),
479
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: row.original.title })
480
+ ] }),
481
+ sortingFn: (rowA, rowB) => rowA.original.title.toLowerCase().localeCompare(rowB.original.title.toLowerCase())
482
+ },
483
+ {
484
+ accessorKey: "active",
485
+ header: "Status",
486
+ cell: ({ row }) => row.original.active ? /* @__PURE__ */ jsx(Badge, { variant: "default", children: "Ativo" }) : /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: "Inativo" })
487
+ },
488
+ {
489
+ accessorKey: "datetime_add",
490
+ header: "Criado em",
491
+ cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: format(new Date(row.original.datetime_add), "dd/MM/yyyy", {
492
+ locale: ptBR
493
+ }) })
494
+ },
495
+ {
496
+ id: "actions",
497
+ size: 80,
498
+ enableSorting: false,
499
+ cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
500
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
501
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
502
+ Button,
503
+ {
504
+ variant: "ghost",
505
+ size: "icon",
506
+ className: "h-8 w-8",
507
+ onClick: () => onEdit(row.original),
508
+ children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
509
+ }
510
+ ) }),
511
+ /* @__PURE__ */ jsx(TooltipContent, { children: "Editar" })
512
+ ] }),
513
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
514
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
515
+ Button,
516
+ {
517
+ variant: "ghost",
518
+ size: "icon",
519
+ className: "h-8 w-8 text-destructive hover:text-destructive",
520
+ onClick: () => onDelete(row.original.id),
521
+ children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
522
+ }
523
+ ) }),
524
+ /* @__PURE__ */ jsx(TooltipContent, { children: "Excluir" })
525
+ ] })
526
+ ] })
527
+ }
528
+ ];
529
+ }
530
+ function AgentsTable({ config, onNavigateToAgent }) {
531
+ const [search, setSearch] = useState("");
532
+ const [page, setPage] = useState(1);
533
+ const queryParams = useMemo2(() => {
534
+ const params = {
535
+ limit: "15",
536
+ page: String(page)
537
+ };
538
+ if (search) {
539
+ params.search = search;
540
+ }
541
+ return params;
542
+ }, [search, page]);
543
+ const { data, isLoading } = useAgents(config, queryParams);
544
+ const deleteAgent = useDeleteAgent(config);
545
+ const [deleteId, setDeleteId] = useState(null);
546
+ const agents = data?.data || [];
547
+ const total = data?.total || 0;
548
+ const columns = useColumns(
549
+ (agent) => onNavigateToAgent?.(agent.id),
550
+ (id) => setDeleteId(id)
551
+ );
552
+ function handleDelete() {
553
+ if (!deleteId) return;
554
+ deleteAgent.mutate(deleteId, {
555
+ onSuccess: () => {
556
+ toast.success("Agente exclu\xEDdo");
557
+ setDeleteId(null);
558
+ },
559
+ onError: () => toast.error("Erro ao excluir agente")
560
+ });
561
+ }
562
+ function handleSearchChange(value) {
563
+ setSearch(value);
564
+ setPage(1);
565
+ }
566
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
567
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs("div", { className: "relative flex-1 max-w-md", children: [
568
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
569
+ /* @__PURE__ */ jsx(
570
+ Input,
571
+ {
572
+ placeholder: "Buscar agentes...",
573
+ value: search,
574
+ onChange: (e) => handleSearchChange(e.target.value),
575
+ className: "pl-9"
576
+ }
577
+ )
578
+ ] }) }),
579
+ /* @__PURE__ */ jsx(
580
+ DataTable,
581
+ {
582
+ columns,
583
+ data: agents,
584
+ isLoading,
585
+ emptyMessage: "Nenhum agente encontrado",
586
+ total,
587
+ page,
588
+ onPageChange: setPage,
589
+ pageSize: 15
590
+ }
591
+ ),
592
+ /* @__PURE__ */ jsx(
593
+ AlertDialog,
594
+ {
595
+ open: !!deleteId,
596
+ onOpenChange: (open) => !open && setDeleteId(null),
597
+ children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [
598
+ /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
599
+ /* @__PURE__ */ jsx(AlertDialogTitle, { children: "Excluir agente?" }),
600
+ /* @__PURE__ */ jsx(AlertDialogDescription, { children: "Esta a\xE7\xE3o n\xE3o pode ser desfeita. O agente ser\xE1 removido permanentemente." })
601
+ ] }),
602
+ /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
603
+ /* @__PURE__ */ jsx(AlertDialogCancel, { variant: "outline", size: "default", children: "Cancelar" }),
604
+ /* @__PURE__ */ jsx(
605
+ AlertDialogAction,
606
+ {
607
+ variant: "default",
608
+ size: "default",
609
+ onClick: handleDelete,
610
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
611
+ children: "Excluir"
612
+ }
613
+ )
614
+ ] })
615
+ ] })
616
+ }
617
+ )
618
+ ] });
619
+ }
620
+
621
+ // src/components/agents/agent-form-dialog.tsx
622
+ import { useEffect, useState as useState2 } from "react";
623
+ import {
624
+ Dialog,
625
+ DialogContent,
626
+ DialogHeader,
627
+ DialogTitle,
628
+ DialogFooter,
629
+ Button as Button2,
630
+ Input as Input2,
631
+ Textarea,
632
+ Label
633
+ } from "@greatapps/greatauth-ui/ui";
634
+ import { Loader2 } from "lucide-react";
635
+ import { toast as toast2 } from "sonner";
636
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
637
+ function AgentFormDialog({
638
+ config,
639
+ open,
640
+ onOpenChange,
641
+ agent
642
+ }) {
643
+ const isEditing = !!agent;
644
+ const createAgent = useCreateAgent(config);
645
+ const updateAgent = useUpdateAgent(config);
646
+ const [title, setTitle] = useState2("");
647
+ const [prompt, setPrompt] = useState2("");
648
+ const [photo, setPhoto] = useState2("");
649
+ const [delayTyping, setDelayTyping] = useState2("");
650
+ const [waitingTime, setWaitingTime] = useState2("");
651
+ useEffect(() => {
652
+ if (agent) {
653
+ setTitle(agent.title);
654
+ setPrompt(agent.prompt || "");
655
+ setPhoto(agent.photo || "");
656
+ setDelayTyping(agent.delay_typing != null ? String(agent.delay_typing) : "");
657
+ setWaitingTime(agent.waiting_time != null ? String(agent.waiting_time) : "");
658
+ } else {
659
+ setTitle("");
660
+ setPrompt("");
661
+ setPhoto("");
662
+ setDelayTyping("");
663
+ setWaitingTime("");
664
+ }
665
+ }, [agent, open]);
666
+ const isPending = createAgent.isPending || updateAgent.isPending;
667
+ async function handleSubmit(e) {
668
+ e.preventDefault();
669
+ if (!title.trim()) return;
670
+ const body = {
671
+ title: title.trim()
672
+ };
673
+ if (prompt.trim()) body.prompt = prompt.trim();
674
+ if (photo.trim()) body.photo = photo.trim();
675
+ if (delayTyping.trim()) body.delay_typing = Number(delayTyping);
676
+ if (waitingTime.trim()) body.waiting_time = Number(waitingTime);
677
+ try {
678
+ if (isEditing) {
679
+ await updateAgent.mutateAsync({ id: agent.id, body });
680
+ toast2.success("Agente atualizado");
681
+ } else {
682
+ await createAgent.mutateAsync(
683
+ body
684
+ );
685
+ toast2.success("Agente criado");
686
+ }
687
+ onOpenChange(false);
688
+ } catch {
689
+ toast2.error(isEditing ? "Erro ao atualizar agente" : "Erro ao criar agente");
690
+ }
691
+ }
692
+ return /* @__PURE__ */ jsx2(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs2(DialogContent, { className: "sm:max-w-lg", children: [
693
+ /* @__PURE__ */ jsx2(DialogHeader, { children: /* @__PURE__ */ jsx2(DialogTitle, { children: isEditing ? "Editar Agente" : "Novo Agente" }) }),
694
+ /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
695
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
696
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "agent-photo", children: "Foto (URL)" }),
697
+ /* @__PURE__ */ jsx2(
698
+ Input2,
699
+ {
700
+ id: "agent-photo",
701
+ value: photo,
702
+ onChange: (e) => setPhoto(e.target.value),
703
+ placeholder: "https://exemplo.com/foto.jpg",
704
+ disabled: isPending
705
+ }
706
+ )
707
+ ] }),
708
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
709
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "agent-title", children: "Nome do Agente *" }),
710
+ /* @__PURE__ */ jsx2(
711
+ Input2,
712
+ {
713
+ id: "agent-title",
714
+ value: title,
715
+ onChange: (e) => setTitle(e.target.value),
716
+ placeholder: "Ex: Assistente de Agendamento",
717
+ required: true,
718
+ disabled: isPending
719
+ }
720
+ )
721
+ ] }),
722
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
723
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "agent-prompt", children: "Prompt do Sistema" }),
724
+ /* @__PURE__ */ jsx2(
725
+ Textarea,
726
+ {
727
+ id: "agent-prompt",
728
+ value: prompt,
729
+ onChange: (e) => setPrompt(e.target.value),
730
+ placeholder: "Instru\xE7\xF5es para o agente AI...",
731
+ rows: 6,
732
+ disabled: isPending
733
+ }
734
+ )
735
+ ] }),
736
+ /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-2 gap-4", children: [
737
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
738
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "agent-delay", children: "Delay de Digita\xE7\xE3o (ms)" }),
739
+ /* @__PURE__ */ jsx2(
740
+ Input2,
741
+ {
742
+ id: "agent-delay",
743
+ type: "number",
744
+ value: delayTyping,
745
+ onChange: (e) => setDelayTyping(e.target.value),
746
+ placeholder: "0",
747
+ min: "0",
748
+ disabled: isPending
749
+ }
750
+ )
751
+ ] }),
752
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
753
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "agent-waiting", children: "Tempo de Espera (ms)" }),
754
+ /* @__PURE__ */ jsx2(
755
+ Input2,
756
+ {
757
+ id: "agent-waiting",
758
+ type: "number",
759
+ value: waitingTime,
760
+ onChange: (e) => setWaitingTime(e.target.value),
761
+ placeholder: "0",
762
+ min: "0",
763
+ disabled: isPending
764
+ }
765
+ )
766
+ ] })
767
+ ] }),
768
+ /* @__PURE__ */ jsxs2(DialogFooter, { children: [
769
+ /* @__PURE__ */ jsx2(
770
+ Button2,
771
+ {
772
+ type: "button",
773
+ variant: "outline",
774
+ onClick: () => onOpenChange(false),
775
+ disabled: isPending,
776
+ children: "Cancelar"
777
+ }
778
+ ),
779
+ /* @__PURE__ */ jsxs2(Button2, { type: "submit", disabled: isPending || !title.trim(), children: [
780
+ isPending ? /* @__PURE__ */ jsx2(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
781
+ isEditing ? "Salvar" : "Criar"
782
+ ] })
783
+ ] })
784
+ ] })
785
+ ] }) });
786
+ }
787
+
788
+ // src/components/agents/agent-edit-form.tsx
789
+ import { useEffect as useEffect2, useState as useState3 } from "react";
790
+ import {
791
+ Button as Button3,
792
+ Input as Input3,
793
+ Label as Label2,
794
+ Switch,
795
+ Dialog as Dialog2,
796
+ DialogContent as DialogContent2,
797
+ DialogHeader as DialogHeader2,
798
+ DialogTitle as DialogTitle2,
799
+ DialogFooter as DialogFooter2
800
+ } from "@greatapps/greatauth-ui/ui";
801
+ import { Loader2 as Loader22 } from "lucide-react";
802
+ import { toast as toast3 } from "sonner";
803
+ import { ImageCropUpload } from "@greatapps/greatauth-ui";
804
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
805
+ function msToSeconds(ms) {
806
+ if (ms == null || ms === 0) return "";
807
+ return String(Math.round(ms / 1e3));
808
+ }
809
+ function secondsToMs(seconds) {
810
+ const val = parseFloat(seconds);
811
+ if (isNaN(val) || val <= 0) return void 0;
812
+ return Math.round(val * 1e3);
813
+ }
814
+ function agentToFormState(agent) {
815
+ return {
816
+ title: agent.title,
817
+ photo: agent.photo || "",
818
+ active: agent.active,
819
+ delayTyping: msToSeconds(agent.delay_typing),
820
+ waitingTime: msToSeconds(agent.waiting_time),
821
+ titleError: false
822
+ };
823
+ }
824
+ function AgentEditForm({ config, agent, idAccount, open, onOpenChange }) {
825
+ const updateAgent = useUpdateAgent(config);
826
+ const [form, setForm] = useState3(() => agentToFormState(agent));
827
+ useEffect2(() => {
828
+ setForm(agentToFormState(agent));
829
+ }, [agent]);
830
+ function updateField(key, value) {
831
+ setForm((prev) => ({ ...prev, [key]: value }));
832
+ }
833
+ async function handleSubmit(e) {
834
+ e.preventDefault();
835
+ if (!form.title.trim()) {
836
+ updateField("titleError", true);
837
+ return;
838
+ }
839
+ const body = {
840
+ title: form.title.trim(),
841
+ active: form.active
842
+ };
843
+ if (form.photo.trim()) body.photo = form.photo.trim();
844
+ else body.photo = "";
845
+ const delayMs = secondsToMs(form.delayTyping);
846
+ if (delayMs !== void 0) body.delay_typing = delayMs;
847
+ else body.delay_typing = 0;
848
+ const waitingMs = secondsToMs(form.waitingTime);
849
+ if (waitingMs !== void 0) body.waiting_time = waitingMs;
850
+ else body.waiting_time = 0;
851
+ try {
852
+ await updateAgent.mutateAsync({ id: agent.id, body });
853
+ toast3.success("Agente atualizado");
854
+ onOpenChange?.(false);
855
+ } catch {
856
+ toast3.error("Erro ao atualizar agente");
857
+ }
858
+ }
859
+ const formContent = /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
860
+ /* @__PURE__ */ jsx3("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx3(
861
+ ImageCropUpload,
862
+ {
863
+ value: form.photo || null,
864
+ onChange: (url) => updateField("photo", url),
865
+ onRemove: () => updateField("photo", ""),
866
+ entityType: "agents",
867
+ entityId: agent.id,
868
+ idAccount: typeof idAccount === "string" ? Number(idAccount) : idAccount ?? 0,
869
+ name: form.title || null,
870
+ disabled: updateAgent.isPending
871
+ }
872
+ ) }),
873
+ /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
874
+ /* @__PURE__ */ jsx3(Label2, { htmlFor: "edit-title", children: "Nome do Agente *" }),
875
+ /* @__PURE__ */ jsx3(
876
+ Input3,
877
+ {
878
+ id: "edit-title",
879
+ value: form.title,
880
+ onChange: (e) => {
881
+ setForm((prev) => ({
882
+ ...prev,
883
+ title: e.target.value,
884
+ titleError: e.target.value.trim() ? false : prev.titleError
885
+ }));
886
+ },
887
+ placeholder: "Ex: Assistente de Agendamento",
888
+ disabled: updateAgent.isPending
889
+ }
890
+ ),
891
+ form.titleError && /* @__PURE__ */ jsx3("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
892
+ ] }),
893
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
894
+ /* @__PURE__ */ jsx3(
895
+ Switch,
896
+ {
897
+ id: "edit-active",
898
+ checked: form.active,
899
+ onCheckedChange: (checked) => updateField("active", checked),
900
+ disabled: updateAgent.isPending
901
+ }
902
+ ),
903
+ /* @__PURE__ */ jsx3(Label2, { htmlFor: "edit-active", className: "cursor-pointer", children: form.active ? "Ativo" : "Inativo" })
904
+ ] }),
905
+ /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-2 gap-4", children: [
906
+ /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
907
+ /* @__PURE__ */ jsx3(Label2, { htmlFor: "edit-delay", children: "Delay de Digita\xE7\xE3o (s)" }),
908
+ /* @__PURE__ */ jsx3(
909
+ Input3,
910
+ {
911
+ id: "edit-delay",
912
+ type: "number",
913
+ value: form.delayTyping,
914
+ onChange: (e) => updateField("delayTyping", e.target.value),
915
+ placeholder: "0",
916
+ min: "0",
917
+ step: "0.5",
918
+ disabled: updateAgent.isPending
919
+ }
920
+ ),
921
+ /* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground", children: "Tempo de simula\xE7\xE3o de digita\xE7\xE3o" })
922
+ ] }),
923
+ /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
924
+ /* @__PURE__ */ jsx3(Label2, { htmlFor: "edit-waiting", children: "Tempo de Espera (s)" }),
925
+ /* @__PURE__ */ jsx3(
926
+ Input3,
927
+ {
928
+ id: "edit-waiting",
929
+ type: "number",
930
+ value: form.waitingTime,
931
+ onChange: (e) => updateField("waitingTime", e.target.value),
932
+ placeholder: "0",
933
+ min: "0",
934
+ step: "0.5",
935
+ disabled: updateAgent.isPending
936
+ }
937
+ ),
938
+ /* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground", children: "Espera por mensagens agrupadas" })
939
+ ] })
940
+ ] }),
941
+ /* @__PURE__ */ jsxs3(DialogFooter2, { children: [
942
+ /* @__PURE__ */ jsx3(
943
+ Button3,
944
+ {
945
+ type: "button",
946
+ variant: "outline",
947
+ onClick: () => onOpenChange?.(false),
948
+ disabled: updateAgent.isPending,
949
+ children: "Cancelar"
950
+ }
951
+ ),
952
+ /* @__PURE__ */ jsxs3(Button3, { type: "submit", disabled: updateAgent.isPending, children: [
953
+ updateAgent.isPending && /* @__PURE__ */ jsx3(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
954
+ "Salvar"
955
+ ] })
956
+ ] })
957
+ ] });
958
+ if (open !== void 0 && onOpenChange) {
959
+ return /* @__PURE__ */ jsx3(Dialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs3(DialogContent2, { className: "sm:max-w-md", children: [
960
+ /* @__PURE__ */ jsx3(DialogHeader2, { children: /* @__PURE__ */ jsx3(DialogTitle2, { children: "Editar Agente" }) }),
961
+ formContent
962
+ ] }) });
963
+ }
964
+ return /* @__PURE__ */ jsx3("div", { className: "max-w-lg pt-4", children: formContent });
965
+ }
966
+
967
+ // src/components/agents/agent-tools-list.tsx
968
+ import { useState as useState4 } from "react";
969
+ import {
970
+ Switch as Switch2,
971
+ Badge as Badge2,
972
+ Button as Button4,
973
+ Skeleton,
974
+ AlertDialog as AlertDialog2,
975
+ AlertDialogAction as AlertDialogAction2,
976
+ AlertDialogCancel as AlertDialogCancel2,
977
+ AlertDialogContent as AlertDialogContent2,
978
+ AlertDialogDescription as AlertDialogDescription2,
979
+ AlertDialogFooter as AlertDialogFooter2,
980
+ AlertDialogHeader as AlertDialogHeader2,
981
+ AlertDialogTitle as AlertDialogTitle2,
982
+ Popover,
983
+ PopoverContent,
984
+ PopoverTrigger,
985
+ Input as Input4,
986
+ Textarea as Textarea2,
987
+ Dialog as Dialog3,
988
+ DialogContent as DialogContent3,
989
+ DialogHeader as DialogHeader3,
990
+ DialogTitle as DialogTitle3,
991
+ DialogFooter as DialogFooter3,
992
+ Label as Label3,
993
+ Select,
994
+ SelectContent,
995
+ SelectItem,
996
+ SelectTrigger,
997
+ SelectValue
998
+ } from "@greatapps/greatauth-ui/ui";
999
+ import {
1000
+ Trash2 as Trash22,
1001
+ Plus,
1002
+ Wrench,
1003
+ Settings2
1004
+ } from "lucide-react";
1005
+ import { toast as toast4 } from "sonner";
1006
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1007
+ function AgentToolsList({ agent, config }) {
1008
+ const { data: agentToolsData, isLoading } = useAgentTools(config, agent.id);
1009
+ const { data: allToolsData } = useTools(config);
1010
+ const addMutation = useAddAgentTool(config);
1011
+ const removeMutation = useRemoveAgentTool(config);
1012
+ const updateMutation = useUpdateAgentTool(config);
1013
+ const [removeTarget, setRemoveTarget] = useState4(null);
1014
+ const [addOpen, setAddOpen] = useState4(false);
1015
+ const [search, setSearch] = useState4("");
1016
+ const [configTarget, setConfigTarget] = useState4(null);
1017
+ const [configInstructions, setConfigInstructions] = useState4("");
1018
+ const [configCredentialId, setConfigCredentialId] = useState4("");
1019
+ const { data: credentialsData } = useToolCredentials(config);
1020
+ const allCredentials = credentialsData?.data || [];
1021
+ const agentTools = agentToolsData?.data || [];
1022
+ const allTools = allToolsData?.data || [];
1023
+ const assignedToolIds = new Set(agentTools.map((at) => at.id_tool));
1024
+ const availableTools = allTools.filter((t) => !assignedToolIds.has(t.id));
1025
+ const filteredAvailable = availableTools.filter(
1026
+ (t) => t.name.toLowerCase().includes(search.toLowerCase())
1027
+ );
1028
+ function getToolInfo(idTool) {
1029
+ return allTools.find((t) => t.id === idTool);
1030
+ }
1031
+ async function handleToggleEnabled(agentTool, checked) {
1032
+ try {
1033
+ await updateMutation.mutateAsync({
1034
+ idAgent: agent.id,
1035
+ id: agentTool.id,
1036
+ body: { enabled: checked }
1037
+ });
1038
+ toast4.success(checked ? "Ferramenta ativada" : "Ferramenta desativada");
1039
+ } catch (err) {
1040
+ toast4.error(
1041
+ err instanceof Error ? err.message : "Erro ao alterar estado da ferramenta"
1042
+ );
1043
+ }
1044
+ }
1045
+ async function handleAdd(tool) {
1046
+ try {
1047
+ await addMutation.mutateAsync({
1048
+ idAgent: agent.id,
1049
+ body: { id_tool: tool.id }
1050
+ });
1051
+ toast4.success("Ferramenta adicionada");
1052
+ setAddOpen(false);
1053
+ setSearch("");
1054
+ } catch (err) {
1055
+ toast4.error(
1056
+ err instanceof Error ? err.message : "Erro ao adicionar ferramenta"
1057
+ );
1058
+ }
1059
+ }
1060
+ async function handleRemove() {
1061
+ if (!removeTarget) return;
1062
+ try {
1063
+ await removeMutation.mutateAsync({
1064
+ idAgent: agent.id,
1065
+ id: removeTarget.id
1066
+ });
1067
+ toast4.success("Ferramenta removida");
1068
+ } catch (err) {
1069
+ toast4.error(
1070
+ err instanceof Error ? err.message : "Erro ao remover ferramenta"
1071
+ );
1072
+ } finally {
1073
+ setRemoveTarget(null);
1074
+ }
1075
+ }
1076
+ function openConfig(agentTool) {
1077
+ setConfigTarget(agentTool);
1078
+ setConfigInstructions(agentTool.custom_instructions || "");
1079
+ setConfigCredentialId(agentTool.id_tool_credential ? String(agentTool.id_tool_credential) : "");
1080
+ }
1081
+ async function handleSaveConfig() {
1082
+ if (!configTarget) return;
1083
+ try {
1084
+ const newCredentialId = configCredentialId ? parseInt(configCredentialId, 10) : null;
1085
+ await updateMutation.mutateAsync({
1086
+ idAgent: agent.id,
1087
+ id: configTarget.id,
1088
+ body: {
1089
+ custom_instructions: configInstructions.trim() || null,
1090
+ id_tool_credential: newCredentialId
1091
+ }
1092
+ });
1093
+ toast4.success("Configura\xE7\xE3o atualizada");
1094
+ setConfigTarget(null);
1095
+ } catch (err) {
1096
+ toast4.error(
1097
+ err instanceof Error ? err.message : "Erro ao atualizar configura\xE7\xE3o"
1098
+ );
1099
+ }
1100
+ }
1101
+ if (isLoading) {
1102
+ return /* @__PURE__ */ jsx4("div", { className: "space-y-3 p-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx4(Skeleton, { className: "h-14 w-full" }, i)) });
1103
+ }
1104
+ return /* @__PURE__ */ jsxs4("div", { className: "space-y-4 p-4", children: [
1105
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between", children: [
1106
+ /* @__PURE__ */ jsxs4("h3", { className: "text-sm font-medium text-muted-foreground", children: [
1107
+ agentTools.length,
1108
+ " ferramenta",
1109
+ agentTools.length !== 1 ? "s" : "",
1110
+ " associada",
1111
+ agentTools.length !== 1 ? "s" : ""
1112
+ ] }),
1113
+ /* @__PURE__ */ jsxs4(Popover, { open: addOpen, onOpenChange: setAddOpen, children: [
1114
+ /* @__PURE__ */ jsx4(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(Button4, { size: "sm", disabled: availableTools.length === 0, children: [
1115
+ /* @__PURE__ */ jsx4(Plus, { className: "mr-2 h-4 w-4" }),
1116
+ "Adicionar Ferramenta"
1117
+ ] }) }),
1118
+ /* @__PURE__ */ jsxs4(PopoverContent, { className: "w-72 p-0", align: "end", children: [
1119
+ /* @__PURE__ */ jsx4("div", { className: "p-2", children: /* @__PURE__ */ jsx4(
1120
+ Input4,
1121
+ {
1122
+ placeholder: "Buscar ferramenta...",
1123
+ value: search,
1124
+ onChange: (e) => setSearch(e.target.value),
1125
+ className: "h-8"
1126
+ }
1127
+ ) }),
1128
+ /* @__PURE__ */ jsx4("div", { className: "max-h-48 overflow-y-auto", children: filteredAvailable.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "p-3 text-center text-sm text-muted-foreground", children: "Nenhuma ferramenta dispon\xEDvel" }) : filteredAvailable.map((tool) => /* @__PURE__ */ jsxs4(
1129
+ "button",
1130
+ {
1131
+ type: "button",
1132
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-accent",
1133
+ onClick: () => handleAdd(tool),
1134
+ disabled: addMutation.isPending,
1135
+ children: [
1136
+ /* @__PURE__ */ jsx4(Wrench, { className: "h-4 w-4 text-muted-foreground" }),
1137
+ /* @__PURE__ */ jsx4("span", { className: "flex-1 font-medium", children: tool.name }),
1138
+ /* @__PURE__ */ jsx4(Badge2, { variant: "secondary", className: "text-xs", children: tool.type })
1139
+ ]
1140
+ },
1141
+ tool.id
1142
+ )) })
1143
+ ] })
1144
+ ] })
1145
+ ] }),
1146
+ agentTools.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
1147
+ /* @__PURE__ */ jsx4(Wrench, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
1148
+ /* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground", children: "Nenhuma ferramenta associada. Clique em 'Adicionar Ferramenta' para come\xE7ar." })
1149
+ ] }) : /* @__PURE__ */ jsx4("div", { className: "space-y-2", children: agentTools.map((agentTool) => {
1150
+ const tool = getToolInfo(agentTool.id_tool);
1151
+ return /* @__PURE__ */ jsxs4(
1152
+ "div",
1153
+ {
1154
+ className: "flex items-center gap-3 rounded-lg border bg-card p-3",
1155
+ children: [
1156
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [
1157
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1158
+ /* @__PURE__ */ jsx4("span", { className: "truncate font-medium", children: tool?.name || `Ferramenta #${agentTool.id_tool}` }),
1159
+ tool?.type && /* @__PURE__ */ jsx4(Badge2, { variant: "secondary", className: "shrink-0 text-xs", children: tool.type })
1160
+ ] }),
1161
+ agentTool.custom_instructions && /* @__PURE__ */ jsx4("p", { className: "truncate text-xs text-muted-foreground", children: agentTool.custom_instructions })
1162
+ ] }),
1163
+ /* @__PURE__ */ jsx4(
1164
+ Switch2,
1165
+ {
1166
+ checked: agentTool.enabled,
1167
+ onCheckedChange: (checked) => handleToggleEnabled(agentTool, checked),
1168
+ disabled: updateMutation.isPending
1169
+ }
1170
+ ),
1171
+ /* @__PURE__ */ jsx4(
1172
+ Button4,
1173
+ {
1174
+ variant: "ghost",
1175
+ size: "icon",
1176
+ className: "shrink-0 text-muted-foreground hover:text-foreground",
1177
+ onClick: () => openConfig(agentTool),
1178
+ title: "Configurar instru\xE7\xF5es",
1179
+ children: /* @__PURE__ */ jsx4(Settings2, { className: "h-4 w-4" })
1180
+ }
1181
+ ),
1182
+ /* @__PURE__ */ jsx4(
1183
+ Button4,
1184
+ {
1185
+ variant: "ghost",
1186
+ size: "icon",
1187
+ className: "shrink-0 text-muted-foreground hover:text-destructive",
1188
+ onClick: () => setRemoveTarget(agentTool),
1189
+ children: /* @__PURE__ */ jsx4(Trash22, { className: "h-4 w-4" })
1190
+ }
1191
+ )
1192
+ ]
1193
+ },
1194
+ agentTool.id
1195
+ );
1196
+ }) }),
1197
+ /* @__PURE__ */ jsx4(
1198
+ Dialog3,
1199
+ {
1200
+ open: !!configTarget,
1201
+ onOpenChange: (open) => !open && setConfigTarget(null),
1202
+ children: /* @__PURE__ */ jsxs4(DialogContent3, { className: "sm:max-w-lg", children: [
1203
+ /* @__PURE__ */ jsx4(DialogHeader3, { children: /* @__PURE__ */ jsx4(DialogTitle3, { children: "Instru\xE7\xF5es da Ferramenta" }) }),
1204
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-4", children: [
1205
+ configTarget && getToolInfo(configTarget.id_tool)?.type !== "none" && /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
1206
+ /* @__PURE__ */ jsx4(Label3, { children: "Credencial" }),
1207
+ /* @__PURE__ */ jsxs4(
1208
+ Select,
1209
+ {
1210
+ value: configCredentialId || void 0,
1211
+ onValueChange: (val) => setConfigCredentialId(val === "__none__" ? "" : val),
1212
+ children: [
1213
+ /* @__PURE__ */ jsx4(SelectTrigger, { children: /* @__PURE__ */ jsx4(SelectValue, { placeholder: "Selecione uma credencial (opcional)" }) }),
1214
+ /* @__PURE__ */ jsxs4(SelectContent, { children: [
1215
+ /* @__PURE__ */ jsx4(SelectItem, { value: "__none__", children: "Nenhuma (autom\xE1tico)" }),
1216
+ allCredentials.filter((c) => configTarget && c.id_tool === configTarget.id_tool && c.status === "active").map((c) => /* @__PURE__ */ jsx4(SelectItem, { value: String(c.id), children: c.label || `Credencial #${c.id}` }, c.id))
1217
+ ] })
1218
+ ]
1219
+ }
1220
+ ),
1221
+ /* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground", children: "Vincule uma credencial espec\xEDfica a esta ferramenta neste agente." })
1222
+ ] }),
1223
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
1224
+ /* @__PURE__ */ jsx4(Label3, { children: "Instru\xE7\xF5es Personalizadas" }),
1225
+ /* @__PURE__ */ jsx4(
1226
+ Textarea2,
1227
+ {
1228
+ value: configInstructions,
1229
+ onChange: (e) => setConfigInstructions(e.target.value),
1230
+ placeholder: "Instru\xE7\xF5es sobre como e quando o agente deve usar esta ferramenta...",
1231
+ rows: 6
1232
+ }
1233
+ ),
1234
+ /* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground", children: "Este texto \xE9 adicionado ao prompt do agente para orientar o uso da ferramenta." })
1235
+ ] })
1236
+ ] }),
1237
+ /* @__PURE__ */ jsxs4(DialogFooter3, { children: [
1238
+ /* @__PURE__ */ jsx4(
1239
+ Button4,
1240
+ {
1241
+ variant: "outline",
1242
+ onClick: () => setConfigTarget(null),
1243
+ children: "Cancelar"
1244
+ }
1245
+ ),
1246
+ /* @__PURE__ */ jsx4(
1247
+ Button4,
1248
+ {
1249
+ onClick: handleSaveConfig,
1250
+ disabled: updateMutation.isPending,
1251
+ children: "Salvar"
1252
+ }
1253
+ )
1254
+ ] })
1255
+ ] })
1256
+ }
1257
+ ),
1258
+ /* @__PURE__ */ jsx4(
1259
+ AlertDialog2,
1260
+ {
1261
+ open: !!removeTarget,
1262
+ onOpenChange: (open) => !open && setRemoveTarget(null),
1263
+ children: /* @__PURE__ */ jsxs4(AlertDialogContent2, { children: [
1264
+ /* @__PURE__ */ jsxs4(AlertDialogHeader2, { children: [
1265
+ /* @__PURE__ */ jsx4(AlertDialogTitle2, { children: "Remover ferramenta?" }),
1266
+ /* @__PURE__ */ jsx4(AlertDialogDescription2, { children: "A ferramenta ser\xE1 desassociada deste agente." })
1267
+ ] }),
1268
+ /* @__PURE__ */ jsxs4(AlertDialogFooter2, { children: [
1269
+ /* @__PURE__ */ jsx4(AlertDialogCancel2, { children: "Cancelar" }),
1270
+ /* @__PURE__ */ jsx4(
1271
+ AlertDialogAction2,
1272
+ {
1273
+ onClick: handleRemove,
1274
+ disabled: removeMutation.isPending,
1275
+ children: "Remover"
1276
+ }
1277
+ )
1278
+ ] })
1279
+ ] })
1280
+ }
1281
+ )
1282
+ ] });
1283
+ }
1284
+
1285
+ // src/components/agents/agent-objectives-list.tsx
1286
+ import { useState as useState6 } from "react";
1287
+ import {
1288
+ Input as Input5,
1289
+ Button as Button5,
1290
+ Switch as Switch3,
1291
+ Skeleton as Skeleton2,
1292
+ Textarea as Textarea3,
1293
+ Label as Label4,
1294
+ Badge as Badge3,
1295
+ Dialog as Dialog4,
1296
+ DialogContent as DialogContent4,
1297
+ DialogHeader as DialogHeader4,
1298
+ DialogTitle as DialogTitle4,
1299
+ DialogFooter as DialogFooter4,
1300
+ AlertDialog as AlertDialog3,
1301
+ AlertDialogAction as AlertDialogAction3,
1302
+ AlertDialogCancel as AlertDialogCancel3,
1303
+ AlertDialogContent as AlertDialogContent3,
1304
+ AlertDialogDescription as AlertDialogDescription3,
1305
+ AlertDialogFooter as AlertDialogFooter3,
1306
+ AlertDialogHeader as AlertDialogHeader3,
1307
+ AlertDialogTitle as AlertDialogTitle3
1308
+ } from "@greatapps/greatauth-ui/ui";
1309
+
1310
+ // src/components/ui/sortable.tsx
1311
+ import {
1312
+ closestCenter,
1313
+ closestCorners,
1314
+ DndContext,
1315
+ DragOverlay,
1316
+ defaultDropAnimationSideEffects,
1317
+ KeyboardSensor,
1318
+ MouseSensor,
1319
+ TouchSensor,
1320
+ useSensor,
1321
+ useSensors
1322
+ } from "@dnd-kit/core";
1323
+ import {
1324
+ restrictToHorizontalAxis,
1325
+ restrictToParentElement,
1326
+ restrictToVerticalAxis
1327
+ } from "@dnd-kit/modifiers";
1328
+ import {
1329
+ arrayMove,
1330
+ horizontalListSortingStrategy,
1331
+ SortableContext,
1332
+ sortableKeyboardCoordinates,
1333
+ useSortable,
1334
+ verticalListSortingStrategy
1335
+ } from "@dnd-kit/sortable";
1336
+ import { CSS } from "@dnd-kit/utilities";
1337
+ import { Slot as SlotPrimitive } from "radix-ui";
1338
+ import * as React2 from "react";
1339
+ import * as ReactDOM from "react-dom";
1340
+
1341
+ // src/lib/compose-refs.ts
1342
+ import * as React from "react";
1343
+ function setRef(ref, value) {
1344
+ if (typeof ref === "function") {
1345
+ return ref(value);
1346
+ }
1347
+ if (ref !== null && ref !== void 0) {
1348
+ ref.current = value;
1349
+ }
1350
+ }
1351
+ function composeRefs(...refs) {
1352
+ return (node) => {
1353
+ let hasCleanup = false;
1354
+ const cleanups = refs.map((ref) => {
1355
+ const cleanup = setRef(ref, node);
1356
+ if (!hasCleanup && typeof cleanup === "function") {
1357
+ hasCleanup = true;
1358
+ }
1359
+ return cleanup;
1360
+ });
1361
+ if (hasCleanup) {
1362
+ return () => {
1363
+ for (let i = 0; i < cleanups.length; i++) {
1364
+ const cleanup = cleanups[i];
1365
+ if (typeof cleanup === "function") {
1366
+ cleanup();
1367
+ } else {
1368
+ setRef(refs[i], null);
1369
+ }
1370
+ }
1371
+ };
1372
+ }
1373
+ };
1374
+ }
1375
+ function useComposedRefs(...refs) {
1376
+ return React.useCallback(composeRefs(...refs), refs);
1377
+ }
1378
+
1379
+ // src/components/ui/sortable.tsx
1380
+ import { jsx as jsx5 } from "react/jsx-runtime";
1381
+ var orientationConfig = {
1382
+ vertical: {
1383
+ modifiers: [restrictToVerticalAxis, restrictToParentElement],
1384
+ strategy: verticalListSortingStrategy,
1385
+ collisionDetection: closestCenter
1386
+ },
1387
+ horizontal: {
1388
+ modifiers: [restrictToHorizontalAxis, restrictToParentElement],
1389
+ strategy: horizontalListSortingStrategy,
1390
+ collisionDetection: closestCenter
1391
+ },
1392
+ mixed: {
1393
+ modifiers: [restrictToParentElement],
1394
+ strategy: void 0,
1395
+ collisionDetection: closestCorners
1396
+ }
1397
+ };
1398
+ var ROOT_NAME = "Sortable";
1399
+ var CONTENT_NAME = "SortableContent";
1400
+ var ITEM_NAME = "SortableItem";
1401
+ var ITEM_HANDLE_NAME = "SortableItemHandle";
1402
+ var OVERLAY_NAME = "SortableOverlay";
1403
+ var SortableRootContext = React2.createContext(null);
1404
+ function useSortableContext(consumerName) {
1405
+ const context = React2.useContext(SortableRootContext);
1406
+ if (!context) {
1407
+ throw new Error(`\`${consumerName}\` must be used within \`${ROOT_NAME}\``);
1408
+ }
1409
+ return context;
1410
+ }
1411
+ function Sortable(props) {
1412
+ const {
1413
+ value,
1414
+ onValueChange,
1415
+ collisionDetection,
1416
+ modifiers,
1417
+ strategy,
1418
+ onMove,
1419
+ orientation = "vertical",
1420
+ flatCursor = false,
1421
+ getItemValue: getItemValueProp,
1422
+ accessibility,
1423
+ ...sortableProps
1424
+ } = props;
1425
+ const id = React2.useId();
1426
+ const [activeId, setActiveId] = React2.useState(null);
1427
+ const sensors = useSensors(
1428
+ useSensor(MouseSensor),
1429
+ useSensor(TouchSensor),
1430
+ useSensor(KeyboardSensor, {
1431
+ coordinateGetter: sortableKeyboardCoordinates
1432
+ })
1433
+ );
1434
+ const config = React2.useMemo(
1435
+ () => orientationConfig[orientation],
1436
+ [orientation]
1437
+ );
1438
+ const getItemValue = React2.useCallback(
1439
+ (item) => {
1440
+ if (typeof item === "object" && !getItemValueProp) {
1441
+ throw new Error(
1442
+ "`getItemValue` is required when using array of objects"
1443
+ );
1444
+ }
1445
+ return getItemValueProp ? getItemValueProp(item) : item;
1446
+ },
1447
+ [getItemValueProp]
1448
+ );
1449
+ const items = React2.useMemo(() => {
1450
+ return value.map((item) => getItemValue(item));
1451
+ }, [value, getItemValue]);
1452
+ const onDragStart = React2.useCallback(
1453
+ (event) => {
1454
+ sortableProps.onDragStart?.(event);
1455
+ if (event.activatorEvent.defaultPrevented) return;
1456
+ setActiveId(event.active.id);
1457
+ },
1458
+ [sortableProps.onDragStart]
1459
+ );
1460
+ const onDragEnd = React2.useCallback(
1461
+ (event) => {
1462
+ sortableProps.onDragEnd?.(event);
1463
+ if (event.activatorEvent.defaultPrevented) return;
1464
+ const { active, over } = event;
1465
+ if (over && active.id !== over?.id) {
1466
+ const activeIndex = value.findIndex(
1467
+ (item) => getItemValue(item) === active.id
1468
+ );
1469
+ const overIndex = value.findIndex(
1470
+ (item) => getItemValue(item) === over.id
1471
+ );
1472
+ if (onMove) {
1473
+ onMove({ ...event, activeIndex, overIndex });
1474
+ } else {
1475
+ onValueChange?.(arrayMove(value, activeIndex, overIndex));
1476
+ }
1477
+ }
1478
+ setActiveId(null);
1479
+ },
1480
+ [value, onValueChange, onMove, getItemValue, sortableProps.onDragEnd]
1481
+ );
1482
+ const onDragCancel = React2.useCallback(
1483
+ (event) => {
1484
+ sortableProps.onDragCancel?.(event);
1485
+ if (event.activatorEvent.defaultPrevented) return;
1486
+ setActiveId(null);
1487
+ },
1488
+ [sortableProps.onDragCancel]
1489
+ );
1490
+ const announcements = React2.useMemo(
1491
+ () => ({
1492
+ onDragStart({ active }) {
1493
+ const activeValue = active.id.toString();
1494
+ return `Grabbed sortable item "${activeValue}". Current position is ${active.data.current?.sortable.index + 1} of ${value.length}. Use arrow keys to move, space to drop.`;
1495
+ },
1496
+ onDragOver({ active, over }) {
1497
+ if (over) {
1498
+ const overIndex = over.data.current?.sortable.index ?? 0;
1499
+ const activeIndex = active.data.current?.sortable.index ?? 0;
1500
+ const moveDirection = overIndex > activeIndex ? "down" : "up";
1501
+ const activeValue = active.id.toString();
1502
+ return `Sortable item "${activeValue}" moved ${moveDirection} to position ${overIndex + 1} of ${value.length}.`;
1503
+ }
1504
+ return "Sortable item is no longer over a droppable area. Press escape to cancel.";
1505
+ },
1506
+ onDragEnd({ active, over }) {
1507
+ const activeValue = active.id.toString();
1508
+ if (over) {
1509
+ const overIndex = over.data.current?.sortable.index ?? 0;
1510
+ return `Sortable item "${activeValue}" dropped at position ${overIndex + 1} of ${value.length}.`;
1511
+ }
1512
+ return `Sortable item "${activeValue}" dropped. No changes were made.`;
1513
+ },
1514
+ onDragCancel({ active }) {
1515
+ const activeIndex = active.data.current?.sortable.index ?? 0;
1516
+ const activeValue = active.id.toString();
1517
+ return `Sorting cancelled. Sortable item "${activeValue}" returned to position ${activeIndex + 1} of ${value.length}.`;
1518
+ },
1519
+ onDragMove({ active, over }) {
1520
+ if (over) {
1521
+ const overIndex = over.data.current?.sortable.index ?? 0;
1522
+ const activeIndex = active.data.current?.sortable.index ?? 0;
1523
+ const moveDirection = overIndex > activeIndex ? "down" : "up";
1524
+ const activeValue = active.id.toString();
1525
+ return `Sortable item "${activeValue}" is moving ${moveDirection} to position ${overIndex + 1} of ${value.length}.`;
1526
+ }
1527
+ return "Sortable item is no longer over a droppable area. Press escape to cancel.";
1528
+ }
1529
+ }),
1530
+ [value]
1531
+ );
1532
+ const screenReaderInstructions = React2.useMemo(
1533
+ () => ({
1534
+ draggable: `
1535
+ To pick up a sortable item, press space or enter.
1536
+ While dragging, use the ${orientation === "vertical" ? "up and down" : orientation === "horizontal" ? "left and right" : "arrow"} keys to move the item.
1537
+ Press space or enter again to drop the item in its new position, or press escape to cancel.
1538
+ `
1539
+ }),
1540
+ [orientation]
1541
+ );
1542
+ const contextValue = React2.useMemo(
1543
+ () => ({
1544
+ id,
1545
+ items,
1546
+ modifiers: modifiers ?? config.modifiers,
1547
+ strategy: strategy ?? config.strategy,
1548
+ activeId,
1549
+ setActiveId,
1550
+ getItemValue,
1551
+ flatCursor
1552
+ }),
1553
+ [
1554
+ id,
1555
+ items,
1556
+ modifiers,
1557
+ strategy,
1558
+ config.modifiers,
1559
+ config.strategy,
1560
+ activeId,
1561
+ getItemValue,
1562
+ flatCursor
1563
+ ]
1564
+ );
1565
+ return /* @__PURE__ */ jsx5(
1566
+ SortableRootContext.Provider,
1567
+ {
1568
+ value: contextValue,
1569
+ children: /* @__PURE__ */ jsx5(
1570
+ DndContext,
1571
+ {
1572
+ collisionDetection: collisionDetection ?? config.collisionDetection,
1573
+ modifiers: modifiers ?? config.modifiers,
1574
+ sensors,
1575
+ ...sortableProps,
1576
+ id,
1577
+ onDragStart,
1578
+ onDragEnd,
1579
+ onDragCancel,
1580
+ accessibility: {
1581
+ announcements,
1582
+ screenReaderInstructions,
1583
+ ...accessibility
1584
+ }
1585
+ }
1586
+ )
1587
+ }
1588
+ );
1589
+ }
1590
+ var SortableContentContext = React2.createContext(false);
1591
+ function SortableContent(props) {
1592
+ const {
1593
+ strategy: strategyProp,
1594
+ asChild,
1595
+ withoutSlot,
1596
+ children,
1597
+ ref,
1598
+ ...contentProps
1599
+ } = props;
1600
+ const context = useSortableContext(CONTENT_NAME);
1601
+ const ContentPrimitive = asChild ? SlotPrimitive.Slot : "div";
1602
+ return /* @__PURE__ */ jsx5(SortableContentContext.Provider, { value: true, children: /* @__PURE__ */ jsx5(
1603
+ SortableContext,
1604
+ {
1605
+ items: context.items,
1606
+ strategy: strategyProp ?? context.strategy,
1607
+ children: withoutSlot ? children : /* @__PURE__ */ jsx5(
1608
+ ContentPrimitive,
1609
+ {
1610
+ "data-slot": "sortable-content",
1611
+ ...contentProps,
1612
+ ref,
1613
+ children
1614
+ }
1615
+ )
1616
+ }
1617
+ ) });
1618
+ }
1619
+ var SortableItemContext = React2.createContext(null);
1620
+ function useSortableItemContext(consumerName) {
1621
+ const context = React2.useContext(SortableItemContext);
1622
+ if (!context) {
1623
+ throw new Error(`\`${consumerName}\` must be used within \`${ITEM_NAME}\``);
1624
+ }
1625
+ return context;
1626
+ }
1627
+ function SortableItem(props) {
1628
+ const {
1629
+ value,
1630
+ style,
1631
+ asHandle,
1632
+ asChild,
1633
+ disabled,
1634
+ className,
1635
+ ref,
1636
+ ...itemProps
1637
+ } = props;
1638
+ const inSortableContent = React2.useContext(SortableContentContext);
1639
+ const inSortableOverlay = React2.useContext(SortableOverlayContext);
1640
+ if (!inSortableContent && !inSortableOverlay) {
1641
+ throw new Error(
1642
+ `\`${ITEM_NAME}\` must be used within \`${CONTENT_NAME}\` or \`${OVERLAY_NAME}\``
1643
+ );
1644
+ }
1645
+ if (value === "") {
1646
+ throw new Error(`\`${ITEM_NAME}\` value cannot be an empty string`);
1647
+ }
1648
+ const context = useSortableContext(ITEM_NAME);
1649
+ const id = React2.useId();
1650
+ const {
1651
+ attributes,
1652
+ listeners,
1653
+ setNodeRef,
1654
+ setActivatorNodeRef,
1655
+ transform,
1656
+ transition,
1657
+ isDragging
1658
+ } = useSortable({ id: value, disabled });
1659
+ const composedRef = useComposedRefs(ref, (node) => {
1660
+ if (disabled) return;
1661
+ setNodeRef(node);
1662
+ if (asHandle) setActivatorNodeRef(node);
1663
+ });
1664
+ const composedStyle = React2.useMemo(() => {
1665
+ return {
1666
+ transform: CSS.Translate.toString(transform),
1667
+ transition,
1668
+ ...style
1669
+ };
1670
+ }, [transform, transition, style]);
1671
+ const itemContext = React2.useMemo(
1672
+ () => ({
1673
+ id,
1674
+ attributes,
1675
+ listeners,
1676
+ setActivatorNodeRef,
1677
+ isDragging,
1678
+ disabled
1679
+ }),
1680
+ [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled]
1681
+ );
1682
+ const ItemPrimitive = asChild ? SlotPrimitive.Slot : "div";
1683
+ return /* @__PURE__ */ jsx5(SortableItemContext.Provider, { value: itemContext, children: /* @__PURE__ */ jsx5(
1684
+ ItemPrimitive,
1685
+ {
1686
+ id,
1687
+ "data-disabled": disabled,
1688
+ "data-dragging": isDragging ? "" : void 0,
1689
+ "data-slot": "sortable-item",
1690
+ ...itemProps,
1691
+ ...asHandle && !disabled ? attributes : {},
1692
+ ...asHandle && !disabled ? listeners : {},
1693
+ ref: composedRef,
1694
+ style: composedStyle,
1695
+ className: cn(
1696
+ "focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1",
1697
+ {
1698
+ "touch-none select-none": asHandle,
1699
+ "cursor-default": context.flatCursor,
1700
+ "data-dragging:cursor-grabbing": !context.flatCursor,
1701
+ "cursor-grab": !isDragging && asHandle && !context.flatCursor,
1702
+ "opacity-50": isDragging,
1703
+ "pointer-events-none opacity-50": disabled
1704
+ },
1705
+ className
1706
+ )
1707
+ }
1708
+ ) });
1709
+ }
1710
+ function SortableItemHandle(props) {
1711
+ const { asChild, disabled, className, ref, ...itemHandleProps } = props;
1712
+ const context = useSortableContext(ITEM_HANDLE_NAME);
1713
+ const itemContext = useSortableItemContext(ITEM_HANDLE_NAME);
1714
+ const isDisabled = disabled ?? itemContext.disabled;
1715
+ const composedRef = useComposedRefs(ref, (node) => {
1716
+ if (!isDisabled) return;
1717
+ itemContext.setActivatorNodeRef(node);
1718
+ });
1719
+ const HandlePrimitive = asChild ? SlotPrimitive.Slot : "button";
1720
+ return /* @__PURE__ */ jsx5(
1721
+ HandlePrimitive,
1722
+ {
1723
+ type: "button",
1724
+ "aria-controls": itemContext.id,
1725
+ "data-disabled": isDisabled,
1726
+ "data-dragging": itemContext.isDragging ? "" : void 0,
1727
+ "data-slot": "sortable-item-handle",
1728
+ ...itemHandleProps,
1729
+ ...isDisabled ? {} : itemContext.attributes,
1730
+ ...isDisabled ? {} : itemContext.listeners,
1731
+ ref: composedRef,
1732
+ className: cn(
1733
+ "select-none disabled:pointer-events-none disabled:opacity-50",
1734
+ context.flatCursor ? "cursor-default" : "cursor-grab data-dragging:cursor-grabbing",
1735
+ className
1736
+ ),
1737
+ disabled: isDisabled
1738
+ }
1739
+ );
1740
+ }
1741
+ var SortableOverlayContext = React2.createContext(false);
1742
+ var dropAnimation = {
1743
+ sideEffects: defaultDropAnimationSideEffects({
1744
+ styles: {
1745
+ active: {
1746
+ opacity: "0.4"
1747
+ }
1748
+ }
1749
+ })
1750
+ };
1751
+ function SortableOverlay(props) {
1752
+ const { container: containerProp, children, ...overlayProps } = props;
1753
+ const context = useSortableContext(OVERLAY_NAME);
1754
+ const [mounted, setMounted] = React2.useState(false);
1755
+ React2.useLayoutEffect(() => setMounted(true), []);
1756
+ const container = containerProp ?? (mounted ? globalThis.document?.body : null);
1757
+ if (!container) return null;
1758
+ return ReactDOM.createPortal(
1759
+ /* @__PURE__ */ jsx5(
1760
+ DragOverlay,
1761
+ {
1762
+ dropAnimation,
1763
+ modifiers: context.modifiers,
1764
+ className: cn(!context.flatCursor && "cursor-grabbing"),
1765
+ ...overlayProps,
1766
+ children: /* @__PURE__ */ jsx5(SortableOverlayContext.Provider, { value: true, children: context.activeId ? typeof children === "function" ? children({ value: context.activeId }) : children : null })
1767
+ }
1768
+ ),
1769
+ container
1770
+ );
1771
+ }
1772
+
1773
+ // src/components/agents/agent-objectives-list.tsx
1774
+ import { Trash2 as Trash23, Target, Pencil as Pencil2, Plus as Plus2, GripVertical } from "lucide-react";
1775
+ import { toast as toast5 } from "sonner";
1776
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1777
+ function slugify(text) {
1778
+ return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1779
+ }
1780
+ var EMPTY_FORM = { title: "", slug: "", prompt: "" };
1781
+ function AgentObjectivesList({ agent, config }) {
1782
+ const { data: objectivesData, isLoading } = useObjectives(config, agent.id);
1783
+ const createMutation = useCreateObjective(config);
1784
+ const updateMutation = useUpdateObjective(config);
1785
+ const deleteMutation = useDeleteObjective(config);
1786
+ const [formOpen, setFormOpen] = useState6(false);
1787
+ const [editTarget, setEditTarget] = useState6(null);
1788
+ const [form, setForm] = useState6(EMPTY_FORM);
1789
+ const [slugManual, setSlugManual] = useState6(false);
1790
+ const [removeTarget, setRemoveTarget] = useState6(null);
1791
+ const objectives = objectivesData?.data || [];
1792
+ const sortedObjectives = [...objectives].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
1793
+ async function handleReorder(newItems) {
1794
+ const updates = newItems.map((item, index) => ({ ...item, order: index + 1 })).filter((item, index) => sortedObjectives[index]?.id !== item.id);
1795
+ try {
1796
+ for (const item of updates) {
1797
+ await updateMutation.mutateAsync({
1798
+ idAgent: agent.id,
1799
+ id: item.id,
1800
+ body: { order: item.order }
1801
+ });
1802
+ }
1803
+ toast5.success("Ordem atualizada");
1804
+ } catch {
1805
+ toast5.error("Erro ao reordenar objetivos");
1806
+ }
1807
+ }
1808
+ function openCreate() {
1809
+ setEditTarget(null);
1810
+ setForm(EMPTY_FORM);
1811
+ setSlugManual(false);
1812
+ setFormOpen(true);
1813
+ }
1814
+ function openEdit(objective) {
1815
+ setEditTarget(objective);
1816
+ setForm({
1817
+ title: objective.title,
1818
+ slug: objective.slug || "",
1819
+ prompt: objective.prompt || ""
1820
+ });
1821
+ setSlugManual(true);
1822
+ setFormOpen(true);
1823
+ }
1824
+ async function handleSubmit() {
1825
+ if (!form.title.trim()) return;
1826
+ const effectiveSlug = form.slug.trim() || slugify(form.title);
1827
+ const nextOrder = sortedObjectives.length > 0 ? Math.max(...sortedObjectives.map((o) => o.order)) + 1 : 1;
1828
+ try {
1829
+ if (editTarget) {
1830
+ await updateMutation.mutateAsync({
1831
+ idAgent: agent.id,
1832
+ id: editTarget.id,
1833
+ body: {
1834
+ title: form.title.trim(),
1835
+ slug: effectiveSlug,
1836
+ prompt: form.prompt.trim() || null
1837
+ }
1838
+ });
1839
+ toast5.success("Objetivo atualizado");
1840
+ } else {
1841
+ await createMutation.mutateAsync({
1842
+ idAgent: agent.id,
1843
+ body: {
1844
+ title: form.title.trim(),
1845
+ slug: effectiveSlug,
1846
+ prompt: form.prompt.trim() || null,
1847
+ order: nextOrder
1848
+ }
1849
+ });
1850
+ toast5.success("Objetivo criado");
1851
+ }
1852
+ setFormOpen(false);
1853
+ } catch (err) {
1854
+ toast5.error(
1855
+ err instanceof Error ? err.message : editTarget ? "Erro ao atualizar objetivo" : "Erro ao criar objetivo"
1856
+ );
1857
+ }
1858
+ }
1859
+ async function handleToggleActive(objective, checked) {
1860
+ try {
1861
+ await updateMutation.mutateAsync({
1862
+ idAgent: agent.id,
1863
+ id: objective.id,
1864
+ body: { active: checked }
1865
+ });
1866
+ toast5.success(checked ? "Objetivo ativado" : "Objetivo desativado");
1867
+ } catch (err) {
1868
+ toast5.error(
1869
+ err instanceof Error ? err.message : "Erro ao alterar estado do objetivo"
1870
+ );
1871
+ }
1872
+ }
1873
+ async function handleRemove() {
1874
+ if (!removeTarget) return;
1875
+ try {
1876
+ await deleteMutation.mutateAsync({
1877
+ idAgent: agent.id,
1878
+ id: removeTarget.id
1879
+ });
1880
+ toast5.success("Objetivo removido");
1881
+ } catch (err) {
1882
+ toast5.error(
1883
+ err instanceof Error ? err.message : "Erro ao remover o objetivo"
1884
+ );
1885
+ } finally {
1886
+ setRemoveTarget(null);
1887
+ }
1888
+ }
1889
+ if (isLoading) {
1890
+ return /* @__PURE__ */ jsx6("div", { className: "space-y-3 p-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx6(Skeleton2, { className: "h-14 w-full" }, i)) });
1891
+ }
1892
+ return /* @__PURE__ */ jsxs5("div", { className: "space-y-4 p-4", children: [
1893
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
1894
+ /* @__PURE__ */ jsxs5("div", { children: [
1895
+ /* @__PURE__ */ jsxs5("h3", { className: "text-sm font-medium text-muted-foreground", children: [
1896
+ sortedObjectives.length,
1897
+ " objetivo",
1898
+ sortedObjectives.length !== 1 ? "s" : "",
1899
+ " definido",
1900
+ sortedObjectives.length !== 1 ? "s" : ""
1901
+ ] }),
1902
+ /* @__PURE__ */ jsx6("p", { className: "text-xs text-muted-foreground", children: "Objetivos s\xE3o modos de conversa que o agente ativa automaticamente conforme a inten\xE7\xE3o do utilizador." })
1903
+ ] }),
1904
+ /* @__PURE__ */ jsxs5(Button5, { onClick: openCreate, size: "sm", children: [
1905
+ /* @__PURE__ */ jsx6(Plus2, { className: "mr-2 h-4 w-4" }),
1906
+ "Novo Objetivo"
1907
+ ] })
1908
+ ] }),
1909
+ sortedObjectives.length === 0 ? /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
1910
+ /* @__PURE__ */ jsx6(Target, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
1911
+ /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: "Nenhum objetivo definido. Adicione objetivos para orientar o agente em diferentes contextos." })
1912
+ ] }) : /* @__PURE__ */ jsxs5(
1913
+ Sortable,
1914
+ {
1915
+ value: sortedObjectives,
1916
+ onValueChange: handleReorder,
1917
+ getItemValue: (item) => item.id,
1918
+ children: [
1919
+ /* @__PURE__ */ jsx6(SortableContent, { className: "space-y-2", children: sortedObjectives.map((objective) => /* @__PURE__ */ jsxs5(
1920
+ SortableItem,
1921
+ {
1922
+ value: objective.id,
1923
+ className: "flex items-center gap-3 rounded-lg border bg-card p-3",
1924
+ children: [
1925
+ /* @__PURE__ */ jsx6(SortableItemHandle, { className: "shrink-0 text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx6(GripVertical, { className: "h-5 w-5" }) }),
1926
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [
1927
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
1928
+ /* @__PURE__ */ jsx6("span", { className: "truncate font-medium", children: objective.title }),
1929
+ objective.slug && /* @__PURE__ */ jsx6(Badge3, { variant: "secondary", className: "shrink-0 text-xs font-mono", children: objective.slug })
1930
+ ] }),
1931
+ objective.prompt && /* @__PURE__ */ jsx6("p", { className: "line-clamp-2 text-xs text-muted-foreground", children: objective.prompt })
1932
+ ] }),
1933
+ /* @__PURE__ */ jsx6(
1934
+ Switch3,
1935
+ {
1936
+ checked: objective.active,
1937
+ onCheckedChange: (checked) => handleToggleActive(objective, checked),
1938
+ disabled: updateMutation.isPending
1939
+ }
1940
+ ),
1941
+ /* @__PURE__ */ jsx6(
1942
+ Button5,
1943
+ {
1944
+ variant: "ghost",
1945
+ size: "icon",
1946
+ className: "shrink-0 text-muted-foreground hover:text-foreground",
1947
+ onClick: () => openEdit(objective),
1948
+ children: /* @__PURE__ */ jsx6(Pencil2, { className: "h-4 w-4" })
1949
+ }
1950
+ ),
1951
+ /* @__PURE__ */ jsx6(
1952
+ Button5,
1953
+ {
1954
+ variant: "ghost",
1955
+ size: "icon",
1956
+ className: "shrink-0 text-muted-foreground hover:text-destructive",
1957
+ onClick: () => setRemoveTarget(objective),
1958
+ children: /* @__PURE__ */ jsx6(Trash23, { className: "h-4 w-4" })
1959
+ }
1960
+ )
1961
+ ]
1962
+ },
1963
+ objective.id
1964
+ )) }),
1965
+ /* @__PURE__ */ jsx6(SortableOverlay, { children: ({ value }) => {
1966
+ const obj = sortedObjectives.find((o) => o.id === value);
1967
+ return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3 rounded-lg border bg-card p-3 shadow-lg", children: [
1968
+ /* @__PURE__ */ jsx6(GripVertical, { className: "h-5 w-5 text-muted-foreground" }),
1969
+ /* @__PURE__ */ jsx6("span", { className: "font-medium", children: obj?.title })
1970
+ ] });
1971
+ } })
1972
+ ]
1973
+ }
1974
+ ),
1975
+ /* @__PURE__ */ jsx6(Dialog4, { open: formOpen, onOpenChange: setFormOpen, children: /* @__PURE__ */ jsxs5(DialogContent4, { className: "sm:max-w-lg", children: [
1976
+ /* @__PURE__ */ jsx6(DialogHeader4, { children: /* @__PURE__ */ jsx6(DialogTitle4, { children: editTarget ? "Editar Objetivo" : "Novo Objetivo" }) }),
1977
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
1978
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
1979
+ /* @__PURE__ */ jsx6(Label4, { children: "T\xEDtulo *" }),
1980
+ /* @__PURE__ */ jsx6(
1981
+ Input5,
1982
+ {
1983
+ value: form.title,
1984
+ onChange: (e) => {
1985
+ const title = e.target.value;
1986
+ setForm((f) => ({
1987
+ ...f,
1988
+ title,
1989
+ ...!slugManual ? { slug: slugify(title) } : {}
1990
+ }));
1991
+ },
1992
+ placeholder: "Ex: Agendar Consulta"
1993
+ }
1994
+ )
1995
+ ] }),
1996
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
1997
+ /* @__PURE__ */ jsx6(Label4, { children: "Slug (identificador) *" }),
1998
+ /* @__PURE__ */ jsx6(
1999
+ Input5,
2000
+ {
2001
+ value: form.slug,
2002
+ onChange: (e) => {
2003
+ setSlugManual(true);
2004
+ setForm((f) => ({ ...f, slug: e.target.value }));
2005
+ },
2006
+ placeholder: "Ex: agendar-consulta",
2007
+ className: "font-mono"
2008
+ }
2009
+ ),
2010
+ /* @__PURE__ */ jsx6("p", { className: "text-xs text-muted-foreground", children: "Gerado automaticamente. Usado pelo agente para identificar o objetivo." })
2011
+ ] }),
2012
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
2013
+ /* @__PURE__ */ jsx6(Label4, { children: "Instru\xE7\xF5es do Objetivo" }),
2014
+ /* @__PURE__ */ jsx6(
2015
+ Textarea3,
2016
+ {
2017
+ value: form.prompt,
2018
+ onChange: (e) => setForm((f) => ({ ...f, prompt: e.target.value })),
2019
+ placeholder: "Instru\xE7\xF5es detalhadas que o agente seguir\xE1 quando este objetivo for ativado. Ex: passos para agendar consulta, perguntas a fazer, valida\xE7\xF5es necess\xE1rias...",
2020
+ rows: 8
2021
+ }
2022
+ ),
2023
+ /* @__PURE__ */ jsx6("p", { className: "text-xs text-muted-foreground", children: "Estas instru\xE7\xF5es s\xE3o carregadas automaticamente quando o agente detecta que o utilizador precisa deste objetivo." })
2024
+ ] })
2025
+ ] }),
2026
+ /* @__PURE__ */ jsxs5(DialogFooter4, { children: [
2027
+ /* @__PURE__ */ jsx6(
2028
+ Button5,
2029
+ {
2030
+ variant: "outline",
2031
+ onClick: () => setFormOpen(false),
2032
+ children: "Cancelar"
2033
+ }
2034
+ ),
2035
+ /* @__PURE__ */ jsx6(
2036
+ Button5,
2037
+ {
2038
+ onClick: handleSubmit,
2039
+ disabled: !form.title.trim() || createMutation.isPending || updateMutation.isPending,
2040
+ children: editTarget ? "Salvar" : "Criar"
2041
+ }
2042
+ )
2043
+ ] })
2044
+ ] }) }),
2045
+ /* @__PURE__ */ jsx6(
2046
+ AlertDialog3,
2047
+ {
2048
+ open: !!removeTarget,
2049
+ onOpenChange: (open) => !open && setRemoveTarget(null),
2050
+ children: /* @__PURE__ */ jsxs5(AlertDialogContent3, { children: [
2051
+ /* @__PURE__ */ jsxs5(AlertDialogHeader3, { children: [
2052
+ /* @__PURE__ */ jsx6(AlertDialogTitle3, { children: "Remover objetivo?" }),
2053
+ /* @__PURE__ */ jsx6(AlertDialogDescription3, { children: "O objetivo ser\xE1 removido permanentemente." })
2054
+ ] }),
2055
+ /* @__PURE__ */ jsxs5(AlertDialogFooter3, { children: [
2056
+ /* @__PURE__ */ jsx6(AlertDialogCancel3, { children: "Cancelar" }),
2057
+ /* @__PURE__ */ jsx6(
2058
+ AlertDialogAction3,
2059
+ {
2060
+ onClick: handleRemove,
2061
+ disabled: deleteMutation.isPending,
2062
+ children: "Remover"
2063
+ }
2064
+ )
2065
+ ] })
2066
+ ] })
2067
+ }
2068
+ )
2069
+ ] });
2070
+ }
2071
+
2072
+ // src/components/agents/agent-prompt-editor.tsx
2073
+ import { useState as useState7, useRef, useCallback as useCallback3, useEffect as useEffect3 } from "react";
2074
+ import { Button as Button6, Input as Input6, Skeleton as Skeleton3, Badge as Badge4 } from "@greatapps/greatauth-ui/ui";
2075
+ import { FileText, Loader2 as Loader23, ChevronDown, ChevronUp, RotateCcw } from "lucide-react";
2076
+ import { toast as toast6 } from "sonner";
2077
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2078
+ function formatDate(dateStr) {
2079
+ const date = new Date(dateStr);
2080
+ return date.toLocaleDateString("pt-BR", {
2081
+ day: "2-digit",
2082
+ month: "2-digit",
2083
+ year: "numeric",
2084
+ hour: "2-digit",
2085
+ minute: "2-digit"
2086
+ });
2087
+ }
2088
+ function computeDiff(oldText, newText) {
2089
+ const oldLines = oldText.split("\n");
2090
+ const newLines = newText.split("\n");
2091
+ const result = [];
2092
+ const maxLen = Math.max(oldLines.length, newLines.length);
2093
+ for (let i = 0; i < maxLen; i++) {
2094
+ const oldLine = i < oldLines.length ? oldLines[i] : void 0;
2095
+ const newLine = i < newLines.length ? newLines[i] : void 0;
2096
+ if (oldLine === newLine) {
2097
+ result.push({ type: "equal", line: newLine });
2098
+ } else {
2099
+ if (oldLine !== void 0) {
2100
+ result.push({ type: "removed", line: oldLine });
2101
+ }
2102
+ if (newLine !== void 0) {
2103
+ result.push({ type: "added", line: newLine });
2104
+ }
2105
+ }
2106
+ }
2107
+ return result;
2108
+ }
2109
+ function buildPreview(promptText, objectives, agentTools, allTools) {
2110
+ let preview = promptText;
2111
+ const activeObjectives = objectives.filter((o) => o.active);
2112
+ if (activeObjectives.length > 0) {
2113
+ preview += "\n\n[SKILLS DISPON\xCDVEIS]\n";
2114
+ for (const obj of activeObjectives) {
2115
+ preview += `- ${obj.title}`;
2116
+ if (obj.prompt) preview += `: ${obj.prompt}`;
2117
+ preview += "\n";
2118
+ }
2119
+ }
2120
+ const enabledAgentTools = agentTools.filter((at) => at.enabled);
2121
+ if (enabledAgentTools.length > 0) {
2122
+ const toolMap = new Map(allTools.map((t) => [t.id, t]));
2123
+ preview += "\n[TOOLS DISPON\xCDVEIS]\n";
2124
+ for (const at of enabledAgentTools) {
2125
+ const tool = toolMap.get(at.id_tool);
2126
+ const name = tool?.name || `Tool #${at.id_tool}`;
2127
+ const desc = tool?.description ? `: ${tool.description}` : "";
2128
+ preview += `- ${name}${desc}`;
2129
+ if (at.custom_instructions) {
2130
+ preview += `
2131
+ Instru\xE7\xF5es: ${at.custom_instructions}`;
2132
+ }
2133
+ preview += "\n";
2134
+ }
2135
+ }
2136
+ return preview;
2137
+ }
2138
+ function AgentPromptEditor({ config, agent }) {
2139
+ const { data: versionsData, isLoading } = usePromptVersions(config, agent.id);
2140
+ const updateAgent = useUpdateAgent(config);
2141
+ const { data: objectivesData } = useObjectives(config, agent.id);
2142
+ const { data: agentToolsData } = useAgentTools(config, agent.id);
2143
+ const { data: toolsData } = useTools(config);
2144
+ const [trackedAgentId, setTrackedAgentId] = useState7(agent.id);
2145
+ const [promptText, setPromptText] = useState7(agent.prompt || "");
2146
+ const [changeNotes, setChangeNotes] = useState7("");
2147
+ const [showPreview, setShowPreview] = useState7(false);
2148
+ const [compareVersionId, setCompareVersionId] = useState7(null);
2149
+ const textareaRef = useRef(null);
2150
+ if (trackedAgentId !== agent.id) {
2151
+ setTrackedAgentId(agent.id);
2152
+ setPromptText(agent.prompt || "");
2153
+ setCompareVersionId(null);
2154
+ }
2155
+ const autoResize = useCallback3(() => {
2156
+ const el = textareaRef.current;
2157
+ if (!el) return;
2158
+ el.style.height = "auto";
2159
+ el.style.height = `${Math.max(300, el.scrollHeight)}px`;
2160
+ }, []);
2161
+ useEffect3(() => {
2162
+ autoResize();
2163
+ }, [promptText, autoResize]);
2164
+ function handleKeyDown(e) {
2165
+ if (e.key === "Tab") {
2166
+ e.preventDefault();
2167
+ const el = e.currentTarget;
2168
+ const start = el.selectionStart;
2169
+ const end = el.selectionEnd;
2170
+ const value = el.value;
2171
+ const newValue = value.substring(0, start) + " " + value.substring(end);
2172
+ setPromptText(newValue);
2173
+ requestAnimationFrame(() => {
2174
+ el.selectionStart = el.selectionEnd = start + 2;
2175
+ });
2176
+ }
2177
+ }
2178
+ const versions = versionsData?.data || [];
2179
+ const sortedVersions = [...versions].sort(
2180
+ (a, b) => new Date(b.datetime_add).getTime() - new Date(a.datetime_add).getTime()
2181
+ );
2182
+ const currentVersion = sortedVersions.length > 0 ? sortedVersions[0] : null;
2183
+ const compareVersion = sortedVersions.find((v) => v.id === compareVersionId);
2184
+ const diffLines = currentVersion && compareVersion && compareVersion.id !== currentVersion.id ? computeDiff(compareVersion.prompt_content ?? "", currentVersion.prompt_content ?? "") : null;
2185
+ async function handleSave() {
2186
+ const body = {
2187
+ prompt: promptText.trim()
2188
+ };
2189
+ if (changeNotes.trim()) {
2190
+ body.change_notes = changeNotes.trim();
2191
+ }
2192
+ try {
2193
+ await updateAgent.mutateAsync({ id: agent.id, body });
2194
+ setChangeNotes("");
2195
+ toast6.success("Prompt salvo com sucesso");
2196
+ } catch {
2197
+ toast6.error("Erro ao salvar prompt");
2198
+ }
2199
+ }
2200
+ function handleRestore(version) {
2201
+ setPromptText(version.prompt_content ?? "");
2202
+ setChangeNotes(`Restaurado da v${version.version_number}`);
2203
+ toast6.info("Prompt restaurado no editor. Clique em Salvar para confirmar.");
2204
+ }
2205
+ const charCount = promptText.length;
2206
+ const tokenEstimate = Math.ceil(charCount / 4);
2207
+ const objectives = objectivesData?.data || [];
2208
+ const agentTools = agentToolsData?.data || [];
2209
+ const allTools = toolsData?.data || [];
2210
+ const previewText = buildPreview(promptText, objectives, agentTools, allTools);
2211
+ if (isLoading) {
2212
+ return /* @__PURE__ */ jsx7("div", { className: "space-y-3 p-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx7(Skeleton3, { className: "h-14 w-full" }, i)) });
2213
+ }
2214
+ return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-4 p-4 lg:flex-row", children: [
2215
+ /* @__PURE__ */ jsxs6("div", { className: "min-w-0 flex-1 space-y-4", children: [
2216
+ /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
2217
+ /* @__PURE__ */ jsx7(
2218
+ "textarea",
2219
+ {
2220
+ ref: textareaRef,
2221
+ value: promptText,
2222
+ onChange: (e) => setPromptText(e.target.value),
2223
+ onKeyDown: handleKeyDown,
2224
+ placeholder: "Escreva o prompt do sistema aqui...",
2225
+ disabled: updateAgent.isPending,
2226
+ className: "w-full resize-none rounded-lg border bg-background p-3 font-mono text-sm leading-relaxed focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50",
2227
+ style: { minHeight: "300px" }
2228
+ }
2229
+ ),
2230
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
2231
+ /* @__PURE__ */ jsxs6("span", { children: [
2232
+ charCount.toLocaleString("pt-BR"),
2233
+ " caracteres"
2234
+ ] }),
2235
+ /* @__PURE__ */ jsx7("span", { children: "\xB7" }),
2236
+ /* @__PURE__ */ jsxs6("span", { children: [
2237
+ "~",
2238
+ tokenEstimate.toLocaleString("pt-BR"),
2239
+ " tokens"
2240
+ ] })
2241
+ ] })
2242
+ ] }),
2243
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
2244
+ /* @__PURE__ */ jsx7(
2245
+ Input6,
2246
+ {
2247
+ value: changeNotes,
2248
+ onChange: (e) => setChangeNotes(e.target.value),
2249
+ placeholder: "O que mudou? (opcional)",
2250
+ disabled: updateAgent.isPending,
2251
+ className: "flex-1",
2252
+ onKeyDown: (e) => {
2253
+ if (e.key === "Enter") {
2254
+ e.preventDefault();
2255
+ handleSave();
2256
+ }
2257
+ }
2258
+ }
2259
+ ),
2260
+ /* @__PURE__ */ jsxs6(
2261
+ Button6,
2262
+ {
2263
+ onClick: handleSave,
2264
+ disabled: updateAgent.isPending || !promptText.trim(),
2265
+ children: [
2266
+ updateAgent.isPending && /* @__PURE__ */ jsx7(Loader23, { className: "mr-2 h-4 w-4 animate-spin" }),
2267
+ "Salvar"
2268
+ ]
2269
+ }
2270
+ )
2271
+ ] }),
2272
+ /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border", children: [
2273
+ /* @__PURE__ */ jsxs6(
2274
+ "button",
2275
+ {
2276
+ type: "button",
2277
+ onClick: () => setShowPreview((prev) => !prev),
2278
+ className: "flex w-full items-center justify-between px-4 py-3 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors",
2279
+ children: [
2280
+ /* @__PURE__ */ jsx7("span", { children: "Preview do prompt final" }),
2281
+ showPreview ? /* @__PURE__ */ jsx7(ChevronUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(ChevronDown, { className: "h-4 w-4" })
2282
+ ]
2283
+ }
2284
+ ),
2285
+ showPreview && /* @__PURE__ */ jsx7("div", { className: "border-t px-4 py-3", children: /* @__PURE__ */ jsx7("pre", { className: "max-h-96 overflow-auto whitespace-pre-wrap font-mono text-sm leading-relaxed", children: previewText.split("\n").map((line, i) => {
2286
+ const isSection = line.startsWith("[SKILLS DISPON\xCDVEIS]") || line.startsWith("[TOOLS DISPON\xCDVEIS]");
2287
+ return /* @__PURE__ */ jsxs6(
2288
+ "span",
2289
+ {
2290
+ className: isSection ? "font-semibold text-muted-foreground" : "",
2291
+ children: [
2292
+ line,
2293
+ "\n"
2294
+ ]
2295
+ },
2296
+ i
2297
+ );
2298
+ }) }) })
2299
+ ] }),
2300
+ diffLines && compareVersion && currentVersion && /* @__PURE__ */ jsxs6("div", { children: [
2301
+ /* @__PURE__ */ jsxs6("div", { className: "mb-2 flex items-center justify-between", children: [
2302
+ /* @__PURE__ */ jsxs6("h3", { className: "text-sm font-medium text-muted-foreground", children: [
2303
+ "Diferen\xE7as: v",
2304
+ compareVersion.version_number,
2305
+ " \u2192 v",
2306
+ currentVersion.version_number,
2307
+ " (actual)"
2308
+ ] }),
2309
+ /* @__PURE__ */ jsx7(
2310
+ Button6,
2311
+ {
2312
+ variant: "ghost",
2313
+ size: "sm",
2314
+ onClick: () => setCompareVersionId(null),
2315
+ className: "text-xs",
2316
+ children: "Fechar"
2317
+ }
2318
+ )
2319
+ ] }),
2320
+ /* @__PURE__ */ jsx7("div", { className: "max-h-64 overflow-auto rounded-lg border font-mono text-sm", children: diffLines.map((line, i) => /* @__PURE__ */ jsxs6(
2321
+ "div",
2322
+ {
2323
+ className: `whitespace-pre-wrap px-3 py-0.5 ${line.type === "added" ? "bg-green-500/10 text-green-700 dark:text-green-400" : line.type === "removed" ? "bg-red-500/10 text-red-700 dark:text-red-400" : ""}`,
2324
+ children: [
2325
+ /* @__PURE__ */ jsx7("span", { className: "mr-2 inline-block w-4 select-none text-muted-foreground", children: line.type === "added" ? "+" : line.type === "removed" ? "-" : " " }),
2326
+ line.line || " "
2327
+ ]
2328
+ },
2329
+ i
2330
+ )) })
2331
+ ] })
2332
+ ] }),
2333
+ /* @__PURE__ */ jsxs6("div", { className: "w-full space-y-2 lg:w-80 lg:shrink-0", children: [
2334
+ /* @__PURE__ */ jsx7("h3", { className: "text-sm font-medium text-muted-foreground", children: "Hist\xF3rico de Vers\xF5es" }),
2335
+ sortedVersions.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
2336
+ /* @__PURE__ */ jsx7(FileText, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
2337
+ /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground", children: "Nenhuma vers\xE3o encontrada. Salve o prompt para criar a primeira vers\xE3o." })
2338
+ ] }) : /* @__PURE__ */ jsx7("div", { className: "space-y-1", children: sortedVersions.map((version, idx) => {
2339
+ const isCurrent = idx === 0;
2340
+ const isComparing = version.id === compareVersionId;
2341
+ return /* @__PURE__ */ jsxs6(
2342
+ "div",
2343
+ {
2344
+ className: `rounded-lg border p-3 transition-colors ${isCurrent ? "border-primary bg-primary/5" : isComparing ? "border-muted-foreground/30 bg-muted/50" : ""}`,
2345
+ children: [
2346
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
2347
+ /* @__PURE__ */ jsxs6("span", { className: "text-sm font-medium", children: [
2348
+ "v",
2349
+ version.version_number
2350
+ ] }),
2351
+ isCurrent && /* @__PURE__ */ jsx7(Badge4, { variant: "default", className: "text-[10px] px-1.5 py-0", children: "Actual" })
2352
+ ] }),
2353
+ /* @__PURE__ */ jsx7("div", { className: "mt-1 text-xs text-muted-foreground", children: formatDate(version.datetime_add) }),
2354
+ /* @__PURE__ */ jsxs6("div", { className: "mt-1 flex items-center gap-2 text-xs text-muted-foreground", children: [
2355
+ /* @__PURE__ */ jsxs6("span", { children: [
2356
+ (version.prompt_content ?? "").length,
2357
+ " chars"
2358
+ ] }),
2359
+ /* @__PURE__ */ jsx7("span", { children: "\xB7" }),
2360
+ /* @__PURE__ */ jsx7("span", { className: "truncate font-mono", children: (version.prompt_hash ?? "").slice(0, 8) })
2361
+ ] }),
2362
+ version.change_notes && /* @__PURE__ */ jsx7("div", { className: "mt-1.5 text-xs italic text-muted-foreground", children: version.change_notes }),
2363
+ !isCurrent && /* @__PURE__ */ jsxs6("div", { className: "mt-2 flex items-center gap-3", children: [
2364
+ /* @__PURE__ */ jsxs6(
2365
+ "button",
2366
+ {
2367
+ type: "button",
2368
+ onClick: () => setCompareVersionId(isComparing ? null : version.id),
2369
+ className: "flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
2370
+ children: [
2371
+ /* @__PURE__ */ jsx7(FileText, { className: "h-3 w-3" }),
2372
+ isComparing ? "Ocultar diff" : "Comparar"
2373
+ ]
2374
+ }
2375
+ ),
2376
+ /* @__PURE__ */ jsxs6(
2377
+ "button",
2378
+ {
2379
+ type: "button",
2380
+ onClick: () => handleRestore(version),
2381
+ className: "flex items-center gap-1 text-xs text-primary hover:underline",
2382
+ children: [
2383
+ /* @__PURE__ */ jsx7(RotateCcw, { className: "h-3 w-3" }),
2384
+ "Restaurar"
2385
+ ]
2386
+ }
2387
+ )
2388
+ ] })
2389
+ ]
2390
+ },
2391
+ version.id
2392
+ );
2393
+ }) })
2394
+ ] })
2395
+ ] });
2396
+ }
2397
+
2398
+ // src/components/agents/agent-tabs.tsx
2399
+ import {
2400
+ Tabs,
2401
+ TabsList,
2402
+ TabsTrigger,
2403
+ TabsContent
2404
+ } from "@greatapps/greatauth-ui/ui";
2405
+ import { Wrench as Wrench2, Target as Target2, FileText as FileText2, MessageCircle } from "lucide-react";
2406
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2407
+ function AgentTabs({ agent, config, renderConversationsTab }) {
2408
+ return /* @__PURE__ */ jsxs7(Tabs, { defaultValue: "prompt", children: [
2409
+ /* @__PURE__ */ jsxs7(TabsList, { children: [
2410
+ /* @__PURE__ */ jsxs7(TabsTrigger, { value: "prompt", className: "flex items-center gap-1.5", children: [
2411
+ /* @__PURE__ */ jsx8(FileText2, { className: "h-3.5 w-3.5" }),
2412
+ "Prompt"
2413
+ ] }),
2414
+ /* @__PURE__ */ jsxs7(TabsTrigger, { value: "objetivos", className: "flex items-center gap-1.5", children: [
2415
+ /* @__PURE__ */ jsx8(Target2, { className: "h-3.5 w-3.5" }),
2416
+ "Objetivos"
2417
+ ] }),
2418
+ /* @__PURE__ */ jsxs7(TabsTrigger, { value: "ferramentas", className: "flex items-center gap-1.5", children: [
2419
+ /* @__PURE__ */ jsx8(Wrench2, { className: "h-3.5 w-3.5" }),
2420
+ "Ferramentas"
2421
+ ] }),
2422
+ renderConversationsTab && /* @__PURE__ */ jsxs7(TabsTrigger, { value: "conversas", className: "flex items-center gap-1.5", children: [
2423
+ /* @__PURE__ */ jsx8(MessageCircle, { className: "h-3.5 w-3.5" }),
2424
+ "Conversas"
2425
+ ] })
2426
+ ] }),
2427
+ /* @__PURE__ */ jsx8(TabsContent, { value: "prompt", className: "mt-4", children: /* @__PURE__ */ jsx8(AgentPromptEditor, { agent, config }) }),
2428
+ /* @__PURE__ */ jsx8(TabsContent, { value: "objetivos", className: "mt-4", children: /* @__PURE__ */ jsx8(AgentObjectivesList, { agent, config }) }),
2429
+ /* @__PURE__ */ jsx8(TabsContent, { value: "ferramentas", className: "mt-4", children: /* @__PURE__ */ jsx8(AgentToolsList, { agent, config }) }),
2430
+ renderConversationsTab && /* @__PURE__ */ jsx8(TabsContent, { value: "conversas", className: "mt-4", children: renderConversationsTab(agent) })
2431
+ ] });
2432
+ }
2433
+
2434
+ // src/components/tools/tools-table.tsx
2435
+ import { useMemo as useMemo4, useState as useState8 } from "react";
2436
+ import { DataTable as DataTable2 } from "@greatapps/greatauth-ui";
2437
+ import {
2438
+ Input as Input7,
2439
+ Badge as Badge5,
2440
+ Tooltip as Tooltip2,
2441
+ TooltipTrigger as TooltipTrigger2,
2442
+ TooltipContent as TooltipContent2,
2443
+ AlertDialog as AlertDialog4,
2444
+ AlertDialogAction as AlertDialogAction4,
2445
+ AlertDialogCancel as AlertDialogCancel4,
2446
+ AlertDialogContent as AlertDialogContent4,
2447
+ AlertDialogDescription as AlertDialogDescription4,
2448
+ AlertDialogFooter as AlertDialogFooter4,
2449
+ AlertDialogHeader as AlertDialogHeader4,
2450
+ AlertDialogTitle as AlertDialogTitle4,
2451
+ Button as Button7
2452
+ } from "@greatapps/greatauth-ui/ui";
2453
+ import { Pencil as Pencil3, Trash2 as Trash24, Search as Search2 } from "lucide-react";
2454
+ import { format as format2 } from "date-fns";
2455
+ import { ptBR as ptBR2 } from "date-fns/locale";
2456
+ import { toast as toast7 } from "sonner";
2457
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2458
+ function useColumns2(onEdit, onDelete) {
2459
+ return [
2460
+ {
2461
+ accessorKey: "name",
2462
+ header: "Nome",
2463
+ cell: ({ row }) => /* @__PURE__ */ jsx9("span", { className: "font-medium", children: row.original.name }),
2464
+ sortingFn: (rowA, rowB) => rowA.original.name.toLowerCase().localeCompare(rowB.original.name.toLowerCase())
2465
+ },
2466
+ {
2467
+ accessorKey: "slug",
2468
+ header: "Slug",
2469
+ cell: ({ row }) => /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground text-sm font-mono", children: row.original.slug || "\u2014" })
2470
+ },
2471
+ {
2472
+ accessorKey: "type",
2473
+ header: "Tipo",
2474
+ cell: ({ row }) => /* @__PURE__ */ jsx9(Badge5, { variant: "secondary", children: row.original.type })
2475
+ },
2476
+ {
2477
+ accessorKey: "description",
2478
+ header: "Descri\xE7\xE3o",
2479
+ cell: ({ row }) => {
2480
+ const desc = row.original.description;
2481
+ if (!desc) return /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground text-sm", children: "\u2014" });
2482
+ return /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground text-sm", children: desc.length > 50 ? `${desc.slice(0, 50)}...` : desc });
2483
+ }
2484
+ },
2485
+ {
2486
+ accessorKey: "datetime_add",
2487
+ header: "Criado em",
2488
+ cell: ({ row }) => /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground text-sm", children: format2(new Date(row.original.datetime_add), "dd/MM/yyyy", {
2489
+ locale: ptBR2
2490
+ }) })
2491
+ },
2492
+ {
2493
+ id: "actions",
2494
+ size: 80,
2495
+ enableSorting: false,
2496
+ cell: ({ row }) => /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1", children: [
2497
+ /* @__PURE__ */ jsxs8(Tooltip2, { children: [
2498
+ /* @__PURE__ */ jsx9(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx9(
2499
+ Button7,
2500
+ {
2501
+ variant: "ghost",
2502
+ size: "icon",
2503
+ className: "h-8 w-8",
2504
+ onClick: () => onEdit(row.original),
2505
+ children: /* @__PURE__ */ jsx9(Pencil3, { className: "h-4 w-4" })
2506
+ }
2507
+ ) }),
2508
+ /* @__PURE__ */ jsx9(TooltipContent2, { children: "Editar" })
2509
+ ] }),
2510
+ /* @__PURE__ */ jsxs8(Tooltip2, { children: [
2511
+ /* @__PURE__ */ jsx9(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx9(
2512
+ Button7,
2513
+ {
2514
+ variant: "ghost",
2515
+ size: "icon",
2516
+ className: "h-8 w-8 text-destructive hover:text-destructive",
2517
+ onClick: () => onDelete(row.original.id),
2518
+ children: /* @__PURE__ */ jsx9(Trash24, { className: "h-4 w-4" })
2519
+ }
2520
+ ) }),
2521
+ /* @__PURE__ */ jsx9(TooltipContent2, { children: "Excluir" })
2522
+ ] })
2523
+ ] })
2524
+ }
2525
+ ];
2526
+ }
2527
+ function ToolsTable({ onEdit, config }) {
2528
+ const [search, setSearch] = useState8("");
2529
+ const [page, setPage] = useState8(1);
2530
+ const queryParams = useMemo4(() => {
2531
+ const params = {
2532
+ limit: "15",
2533
+ page: String(page)
2534
+ };
2535
+ if (search) {
2536
+ params.search = search;
2537
+ }
2538
+ return params;
2539
+ }, [search, page]);
2540
+ const { data, isLoading } = useTools(config, queryParams);
2541
+ const deleteTool = useDeleteTool(config);
2542
+ const [deleteId, setDeleteId] = useState8(null);
2543
+ const tools = data?.data || [];
2544
+ const total = data?.total || 0;
2545
+ const columns = useColumns2(
2546
+ (tool) => onEdit(tool),
2547
+ (id) => setDeleteId(id)
2548
+ );
2549
+ function handleDelete() {
2550
+ if (!deleteId) return;
2551
+ deleteTool.mutate(deleteId, {
2552
+ onSuccess: () => {
2553
+ toast7.success("Ferramenta exclu\xEDda");
2554
+ setDeleteId(null);
2555
+ },
2556
+ onError: () => toast7.error("Erro ao excluir ferramenta")
2557
+ });
2558
+ }
2559
+ function handleSearchChange(value) {
2560
+ setSearch(value);
2561
+ setPage(1);
2562
+ }
2563
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
2564
+ /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs8("div", { className: "relative flex-1 max-w-md", children: [
2565
+ /* @__PURE__ */ jsx9(Search2, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2566
+ /* @__PURE__ */ jsx9(
2567
+ Input7,
2568
+ {
2569
+ placeholder: "Buscar ferramentas...",
2570
+ value: search,
2571
+ onChange: (e) => handleSearchChange(e.target.value),
2572
+ className: "pl-9"
2573
+ }
2574
+ )
2575
+ ] }) }),
2576
+ /* @__PURE__ */ jsx9(
2577
+ DataTable2,
2578
+ {
2579
+ columns,
2580
+ data: tools,
2581
+ isLoading,
2582
+ emptyMessage: "Nenhuma ferramenta encontrada",
2583
+ total,
2584
+ page,
2585
+ onPageChange: setPage,
2586
+ pageSize: 15
2587
+ }
2588
+ ),
2589
+ /* @__PURE__ */ jsx9(
2590
+ AlertDialog4,
2591
+ {
2592
+ open: !!deleteId,
2593
+ onOpenChange: (open) => !open && setDeleteId(null),
2594
+ children: /* @__PURE__ */ jsxs8(AlertDialogContent4, { children: [
2595
+ /* @__PURE__ */ jsxs8(AlertDialogHeader4, { children: [
2596
+ /* @__PURE__ */ jsx9(AlertDialogTitle4, { children: "Excluir ferramenta?" }),
2597
+ /* @__PURE__ */ jsx9(AlertDialogDescription4, { children: "Esta a\xE7\xE3o n\xE3o pode ser desfeita. A ferramenta ser\xE1 removida permanentemente." })
2598
+ ] }),
2599
+ /* @__PURE__ */ jsxs8(AlertDialogFooter4, { children: [
2600
+ /* @__PURE__ */ jsx9(AlertDialogCancel4, { variant: "outline", size: "default", children: "Cancelar" }),
2601
+ /* @__PURE__ */ jsx9(
2602
+ AlertDialogAction4,
2603
+ {
2604
+ variant: "default",
2605
+ size: "default",
2606
+ onClick: handleDelete,
2607
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
2608
+ children: "Excluir"
2609
+ }
2610
+ )
2611
+ ] })
2612
+ ] })
2613
+ }
2614
+ )
2615
+ ] });
2616
+ }
2617
+
2618
+ // src/components/tools/tool-form-dialog.tsx
2619
+ import { useState as useState9 } from "react";
2620
+ import {
2621
+ Dialog as Dialog5,
2622
+ DialogContent as DialogContent5,
2623
+ DialogHeader as DialogHeader5,
2624
+ DialogTitle as DialogTitle5,
2625
+ DialogFooter as DialogFooter5,
2626
+ Button as Button8,
2627
+ Input as Input8,
2628
+ Textarea as Textarea4,
2629
+ Label as Label5,
2630
+ Select as Select2,
2631
+ SelectContent as SelectContent2,
2632
+ SelectItem as SelectItem2,
2633
+ SelectTrigger as SelectTrigger2,
2634
+ SelectValue as SelectValue2
2635
+ } from "@greatapps/greatauth-ui/ui";
2636
+ import { Loader2 as Loader24 } from "lucide-react";
2637
+ import { toast as toast8 } from "sonner";
2638
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2639
+ var TOOL_AUTH_TYPES = [
2640
+ { value: "none", label: "Nenhuma" },
2641
+ { value: "api_key", label: "API Key" },
2642
+ { value: "oauth2", label: "OAuth 2.0" }
2643
+ ];
2644
+ function toolToFormState(tool) {
2645
+ return {
2646
+ name: tool?.name || "",
2647
+ slug: tool?.slug || "",
2648
+ type: tool?.type || "none",
2649
+ description: tool?.description || "",
2650
+ functionDefinitions: tool?.function_definitions ? formatJson(tool.function_definitions) : "",
2651
+ nameError: false,
2652
+ slugError: false,
2653
+ typeError: false,
2654
+ jsonError: false
2655
+ };
2656
+ }
2657
+ function formatJson(str) {
2658
+ try {
2659
+ return JSON.stringify(JSON.parse(str), null, 2);
2660
+ } catch {
2661
+ return str;
2662
+ }
2663
+ }
2664
+ function slugify2(name) {
2665
+ return name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
2666
+ }
2667
+ function isValidJson(str) {
2668
+ if (!str.trim()) return true;
2669
+ try {
2670
+ JSON.parse(str);
2671
+ return true;
2672
+ } catch {
2673
+ return false;
2674
+ }
2675
+ }
2676
+ function ToolFormDialog({
2677
+ open,
2678
+ onOpenChange,
2679
+ tool,
2680
+ config
2681
+ }) {
2682
+ const isEditing = !!tool;
2683
+ const createTool = useCreateTool(config);
2684
+ const updateTool = useUpdateTool(config);
2685
+ const [form, setForm] = useState9(() => toolToFormState(tool));
2686
+ const [slugManuallyEdited, setSlugManuallyEdited] = useState9(false);
2687
+ const [lastResetKey, setLastResetKey] = useState9(
2688
+ () => `${tool?.id}-${open}`
2689
+ );
2690
+ const resetKey = `${tool?.id}-${open}`;
2691
+ if (resetKey !== lastResetKey) {
2692
+ setLastResetKey(resetKey);
2693
+ setForm(toolToFormState(open ? tool : void 0));
2694
+ setSlugManuallyEdited(false);
2695
+ }
2696
+ const isPending = createTool.isPending || updateTool.isPending;
2697
+ async function handleSubmit(e) {
2698
+ e.preventDefault();
2699
+ let hasError = false;
2700
+ if (!form.name.trim()) {
2701
+ setForm((prev) => ({ ...prev, nameError: true }));
2702
+ hasError = true;
2703
+ }
2704
+ const effectiveSlug = form.slug.trim() || slugify2(form.name);
2705
+ if (!effectiveSlug) {
2706
+ setForm((prev) => ({ ...prev, slugError: true }));
2707
+ hasError = true;
2708
+ }
2709
+ if (!form.type) {
2710
+ setForm((prev) => ({ ...prev, typeError: true }));
2711
+ hasError = true;
2712
+ }
2713
+ if (!isValidJson(form.functionDefinitions)) {
2714
+ setForm((prev) => ({ ...prev, jsonError: true }));
2715
+ hasError = true;
2716
+ }
2717
+ if (hasError) return;
2718
+ const body = {
2719
+ name: form.name.trim(),
2720
+ slug: effectiveSlug,
2721
+ type: form.type
2722
+ };
2723
+ if (form.description.trim()) body.description = form.description.trim();
2724
+ else body.description = "";
2725
+ if (form.functionDefinitions.trim()) {
2726
+ const parsed = JSON.parse(form.functionDefinitions.trim());
2727
+ body.function_definitions = JSON.stringify(parsed);
2728
+ } else {
2729
+ body.function_definitions = "";
2730
+ }
2731
+ try {
2732
+ if (isEditing) {
2733
+ await updateTool.mutateAsync({ id: tool.id, body });
2734
+ toast8.success("Ferramenta atualizada");
2735
+ } else {
2736
+ await createTool.mutateAsync(
2737
+ body
2738
+ );
2739
+ toast8.success("Ferramenta criada");
2740
+ }
2741
+ onOpenChange(false);
2742
+ } catch (err) {
2743
+ toast8.error(
2744
+ err instanceof Error ? err.message : isEditing ? "Erro ao atualizar ferramenta" : "Erro ao criar ferramenta"
2745
+ );
2746
+ }
2747
+ }
2748
+ return /* @__PURE__ */ jsx10(Dialog5, { open, onOpenChange, children: /* @__PURE__ */ jsxs9(DialogContent5, { className: "sm:max-w-lg", children: [
2749
+ /* @__PURE__ */ jsx10(DialogHeader5, { children: /* @__PURE__ */ jsx10(DialogTitle5, { children: isEditing ? "Editar Ferramenta" : "Nova Ferramenta" }) }),
2750
+ /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
2751
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2752
+ /* @__PURE__ */ jsx10(Label5, { htmlFor: "tool-name", children: "Nome *" }),
2753
+ /* @__PURE__ */ jsx10(
2754
+ Input8,
2755
+ {
2756
+ id: "tool-name",
2757
+ value: form.name,
2758
+ onChange: (e) => {
2759
+ const name = e.target.value;
2760
+ setForm((prev) => ({
2761
+ ...prev,
2762
+ name,
2763
+ nameError: name.trim() ? false : prev.nameError,
2764
+ ...!slugManuallyEdited && !isEditing ? { slug: slugify2(name), slugError: false } : {}
2765
+ }));
2766
+ },
2767
+ placeholder: "Ex: Google Calendar",
2768
+ disabled: isPending
2769
+ }
2770
+ ),
2771
+ form.nameError && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
2772
+ ] }),
2773
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2774
+ /* @__PURE__ */ jsx10(Label5, { htmlFor: "tool-slug", children: "Slug (identificador \xFAnico) *" }),
2775
+ /* @__PURE__ */ jsx10(
2776
+ Input8,
2777
+ {
2778
+ id: "tool-slug",
2779
+ value: form.slug,
2780
+ onChange: (e) => {
2781
+ setSlugManuallyEdited(true);
2782
+ setForm((prev) => ({
2783
+ ...prev,
2784
+ slug: e.target.value,
2785
+ slugError: e.target.value.trim() ? false : prev.slugError
2786
+ }));
2787
+ },
2788
+ placeholder: "Ex: google-calendar",
2789
+ disabled: isPending
2790
+ }
2791
+ ),
2792
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground", children: "Gerado automaticamente a partir do nome. Usado internamente para identificar a ferramenta." }),
2793
+ form.slugError && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: "Slug \xE9 obrigat\xF3rio" })
2794
+ ] }),
2795
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2796
+ /* @__PURE__ */ jsx10(Label5, { htmlFor: "tool-type", children: "Tipo de Autentica\xE7\xE3o *" }),
2797
+ /* @__PURE__ */ jsxs9(
2798
+ Select2,
2799
+ {
2800
+ value: form.type,
2801
+ onValueChange: (value) => {
2802
+ setForm((prev) => ({
2803
+ ...prev,
2804
+ type: value,
2805
+ typeError: false
2806
+ }));
2807
+ },
2808
+ disabled: isPending,
2809
+ children: [
2810
+ /* @__PURE__ */ jsx10(SelectTrigger2, { id: "tool-type", children: /* @__PURE__ */ jsx10(SelectValue2, { placeholder: "Selecione o tipo" }) }),
2811
+ /* @__PURE__ */ jsx10(SelectContent2, { children: TOOL_AUTH_TYPES.map((t) => /* @__PURE__ */ jsx10(SelectItem2, { value: t.value, children: t.label }, t.value)) })
2812
+ ]
2813
+ }
2814
+ ),
2815
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground", children: "Define se a ferramenta requer credenciais para funcionar." }),
2816
+ form.typeError && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: "Tipo \xE9 obrigat\xF3rio" })
2817
+ ] }),
2818
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2819
+ /* @__PURE__ */ jsx10(Label5, { htmlFor: "tool-description", children: "Descri\xE7\xE3o" }),
2820
+ /* @__PURE__ */ jsx10(
2821
+ Textarea4,
2822
+ {
2823
+ id: "tool-description",
2824
+ value: form.description,
2825
+ onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
2826
+ placeholder: "Descri\xE7\xE3o da ferramenta...",
2827
+ rows: 3,
2828
+ disabled: isPending
2829
+ }
2830
+ )
2831
+ ] }),
2832
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2833
+ /* @__PURE__ */ jsx10(Label5, { htmlFor: "tool-function-defs", children: "Defini\xE7\xF5es de Fun\xE7\xE3o (JSON)" }),
2834
+ /* @__PURE__ */ jsx10(
2835
+ Textarea4,
2836
+ {
2837
+ id: "tool-function-defs",
2838
+ value: form.functionDefinitions,
2839
+ onChange: (e) => {
2840
+ setForm((prev) => ({
2841
+ ...prev,
2842
+ functionDefinitions: e.target.value,
2843
+ jsonError: false
2844
+ }));
2845
+ },
2846
+ placeholder: `[
2847
+ {
2848
+ "type": "function",
2849
+ "function": {
2850
+ "name": "nome_da_funcao",
2851
+ "description": "O que a fun\xE7\xE3o faz",
2852
+ "parameters": {
2853
+ "type": "object",
2854
+ "properties": { ... },
2855
+ "required": [...]
2856
+ }
2857
+ }
2858
+ }
2859
+ ]`,
2860
+ rows: 10,
2861
+ className: "font-mono text-sm",
2862
+ disabled: isPending
2863
+ }
2864
+ ),
2865
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground", children: "Array de defini\xE7\xF5es no formato OpenAI Function Calling." }),
2866
+ form.jsonError && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: "JSON inv\xE1lido" })
2867
+ ] }),
2868
+ /* @__PURE__ */ jsxs9(DialogFooter5, { children: [
2869
+ /* @__PURE__ */ jsx10(
2870
+ Button8,
2871
+ {
2872
+ type: "button",
2873
+ variant: "outline",
2874
+ onClick: () => onOpenChange(false),
2875
+ disabled: isPending,
2876
+ children: "Cancelar"
2877
+ }
2878
+ ),
2879
+ /* @__PURE__ */ jsxs9(Button8, { type: "submit", disabled: isPending, children: [
2880
+ isPending ? /* @__PURE__ */ jsx10(Loader24, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
2881
+ isEditing ? "Salvar" : "Criar"
2882
+ ] })
2883
+ ] })
2884
+ ] })
2885
+ ] }) });
2886
+ }
2887
+
2888
+ // src/components/tools/tool-credentials-form.tsx
2889
+ import { useMemo as useMemo5, useState as useState10 } from "react";
2890
+ import { DataTable as DataTable3 } from "@greatapps/greatauth-ui";
2891
+ import {
2892
+ Input as Input9,
2893
+ Button as Button9,
2894
+ Badge as Badge6,
2895
+ Tooltip as Tooltip3,
2896
+ TooltipTrigger as TooltipTrigger3,
2897
+ TooltipContent as TooltipContent3,
2898
+ Dialog as Dialog6,
2899
+ DialogContent as DialogContent6,
2900
+ DialogHeader as DialogHeader6,
2901
+ DialogTitle as DialogTitle6,
2902
+ DialogFooter as DialogFooter6,
2903
+ AlertDialog as AlertDialog5,
2904
+ AlertDialogAction as AlertDialogAction5,
2905
+ AlertDialogCancel as AlertDialogCancel5,
2906
+ AlertDialogContent as AlertDialogContent5,
2907
+ AlertDialogDescription as AlertDialogDescription5,
2908
+ AlertDialogFooter as AlertDialogFooter5,
2909
+ AlertDialogHeader as AlertDialogHeader5,
2910
+ AlertDialogTitle as AlertDialogTitle5,
2911
+ Select as Select3,
2912
+ SelectContent as SelectContent3,
2913
+ SelectItem as SelectItem3,
2914
+ SelectTrigger as SelectTrigger3,
2915
+ SelectValue as SelectValue3
2916
+ } from "@greatapps/greatauth-ui/ui";
2917
+ import { Trash2 as Trash25, Pencil as Pencil4, Link, Search as Search3 } from "lucide-react";
2918
+ import { format as format3 } from "date-fns";
2919
+ import { ptBR as ptBR3 } from "date-fns/locale";
2920
+ import { toast as toast9 } from "sonner";
2921
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2922
+ function formatDate2(dateStr) {
2923
+ if (!dateStr) return "Sem expira\xE7\xE3o";
2924
+ return format3(new Date(dateStr), "dd/MM/yyyy", { locale: ptBR3 });
2925
+ }
2926
+ function useColumns3(tools, onEdit, onConnect, onRemove) {
2927
+ function getToolName(idTool) {
2928
+ if (!idTool) return "\u2014";
2929
+ const tool = tools.find((t) => t.id === idTool);
2930
+ return tool?.name || `Ferramenta #${idTool}`;
2931
+ }
2932
+ function getToolType(idTool) {
2933
+ if (!idTool) return null;
2934
+ const tool = tools.find((t) => t.id === idTool);
2935
+ return tool?.type || null;
2936
+ }
2937
+ return [
2938
+ {
2939
+ accessorKey: "label",
2940
+ header: "Label",
2941
+ cell: ({ row }) => /* @__PURE__ */ jsx11("span", { className: "font-medium", children: row.original.label || "\u2014" })
2942
+ },
2943
+ {
2944
+ accessorKey: "id_tool",
2945
+ header: "Ferramenta",
2946
+ cell: ({ row }) => /* @__PURE__ */ jsx11("span", { className: "text-sm", children: getToolName(row.original.id_tool) })
2947
+ },
2948
+ {
2949
+ accessorKey: "status",
2950
+ header: "Status",
2951
+ cell: ({ row }) => /* @__PURE__ */ jsx11(
2952
+ Badge6,
2953
+ {
2954
+ variant: row.original.status === "active" ? "default" : "destructive",
2955
+ children: row.original.status === "active" ? "Ativo" : "Expirado"
2956
+ }
2957
+ )
2958
+ },
2959
+ {
2960
+ accessorKey: "expires_at",
2961
+ header: "Expira em",
2962
+ cell: ({ row }) => /* @__PURE__ */ jsx11("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.expires_at) })
2963
+ },
2964
+ {
2965
+ accessorKey: "datetime_add",
2966
+ header: "Criado em",
2967
+ cell: ({ row }) => /* @__PURE__ */ jsx11("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.datetime_add) })
2968
+ },
2969
+ {
2970
+ id: "actions",
2971
+ header: "A\xE7\xF5es",
2972
+ size: 100,
2973
+ enableSorting: false,
2974
+ cell: ({ row }) => /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
2975
+ getToolType(row.original.id_tool) === "oauth2" && /* @__PURE__ */ jsxs10(Tooltip3, { children: [
2976
+ /* @__PURE__ */ jsx11(TooltipTrigger3, { asChild: true, children: /* @__PURE__ */ jsx11(
2977
+ Button9,
2978
+ {
2979
+ variant: "ghost",
2980
+ size: "icon",
2981
+ className: "h-8 w-8",
2982
+ disabled: true,
2983
+ children: /* @__PURE__ */ jsx11(Link, { className: "h-4 w-4" })
2984
+ }
2985
+ ) }),
2986
+ /* @__PURE__ */ jsx11(TooltipContent3, { children: "Em breve" })
2987
+ ] }),
2988
+ /* @__PURE__ */ jsxs10(Tooltip3, { children: [
2989
+ /* @__PURE__ */ jsx11(TooltipTrigger3, { asChild: true, children: /* @__PURE__ */ jsx11(
2990
+ Button9,
2991
+ {
2992
+ variant: "ghost",
2993
+ size: "icon",
2994
+ className: "h-8 w-8",
2995
+ onClick: () => onEdit(row.original),
2996
+ children: /* @__PURE__ */ jsx11(Pencil4, { className: "h-4 w-4" })
2997
+ }
2998
+ ) }),
2999
+ /* @__PURE__ */ jsx11(TooltipContent3, { children: "Editar" })
3000
+ ] }),
3001
+ /* @__PURE__ */ jsxs10(Tooltip3, { children: [
3002
+ /* @__PURE__ */ jsx11(TooltipTrigger3, { asChild: true, children: /* @__PURE__ */ jsx11(
3003
+ Button9,
3004
+ {
3005
+ variant: "ghost",
3006
+ size: "icon",
3007
+ className: "h-8 w-8 text-destructive hover:text-destructive",
3008
+ onClick: () => onRemove(row.original),
3009
+ children: /* @__PURE__ */ jsx11(Trash25, { className: "h-4 w-4" })
3010
+ }
3011
+ ) }),
3012
+ /* @__PURE__ */ jsx11(TooltipContent3, { children: "Remover" })
3013
+ ] })
3014
+ ] })
3015
+ }
3016
+ ];
3017
+ }
3018
+ function ToolCredentialsForm({
3019
+ credentials,
3020
+ isLoading,
3021
+ config,
3022
+ gagentsApiUrl,
3023
+ createOpen: externalCreateOpen,
3024
+ onCreateOpenChange
3025
+ }) {
3026
+ const createMutation = useCreateToolCredential(config);
3027
+ const updateMutation = useUpdateToolCredential(config);
3028
+ const deleteMutation = useDeleteToolCredential(config);
3029
+ const { data: toolsData } = useTools(config);
3030
+ const tools = toolsData?.data || [];
3031
+ const [search, setSearch] = useState10("");
3032
+ const [internalCreateOpen, setInternalCreateOpen] = useState10(false);
3033
+ const showCreateDialog = externalCreateOpen ?? internalCreateOpen;
3034
+ const setShowCreateDialog = onCreateOpenChange ?? setInternalCreateOpen;
3035
+ const [createForm, setCreateForm] = useState10({
3036
+ id_tool: "",
3037
+ label: "",
3038
+ credentials_encrypted: "",
3039
+ expires_at: ""
3040
+ });
3041
+ const [editTarget, setEditTarget] = useState10(null);
3042
+ const [editForm, setEditForm] = useState10({
3043
+ id_tool: "",
3044
+ label: "",
3045
+ credentials_encrypted: "",
3046
+ expires_at: "",
3047
+ status: ""
3048
+ });
3049
+ const [removeTarget, setRemoveTarget] = useState10(null);
3050
+ const filteredCredentials = useMemo5(() => {
3051
+ if (!search) return credentials;
3052
+ const term = search.toLowerCase();
3053
+ return credentials.filter((cred) => {
3054
+ const toolName = tools.find((t) => t.id === cred.id_tool)?.name || "";
3055
+ return (cred.label || "").toLowerCase().includes(term) || toolName.toLowerCase().includes(term);
3056
+ });
3057
+ }, [credentials, search, tools]);
3058
+ const columns = useColumns3(
3059
+ tools,
3060
+ (cred) => startEdit(cred),
3061
+ (cred) => handleConnect(cred),
3062
+ (cred) => setRemoveTarget(cred)
3063
+ );
3064
+ async function handleCreate() {
3065
+ const idTool = parseInt(createForm.id_tool, 10);
3066
+ if (!idTool || !createForm.label.trim() || !createForm.credentials_encrypted.trim()) return;
3067
+ try {
3068
+ const result = await createMutation.mutateAsync({
3069
+ id_tool: idTool,
3070
+ label: createForm.label.trim(),
3071
+ credentials_encrypted: createForm.credentials_encrypted.trim(),
3072
+ ...createForm.expires_at ? { expires_at: createForm.expires_at } : {}
3073
+ });
3074
+ if (result.status === 1) {
3075
+ toast9.success("Credencial criada");
3076
+ setShowCreateDialog(false);
3077
+ setCreateForm({ id_tool: "", label: "", credentials_encrypted: "", expires_at: "" });
3078
+ } else {
3079
+ toast9.error(result.message || "Erro ao criar credencial");
3080
+ }
3081
+ } catch {
3082
+ toast9.error("Erro ao criar credencial");
3083
+ }
3084
+ }
3085
+ function startEdit(cred) {
3086
+ setEditTarget(cred);
3087
+ setEditForm({
3088
+ id_tool: cred.id_tool ? String(cred.id_tool) : "",
3089
+ label: cred.label || "",
3090
+ credentials_encrypted: "",
3091
+ expires_at: cred.expires_at || "",
3092
+ status: cred.status
3093
+ });
3094
+ }
3095
+ async function handleSaveEdit() {
3096
+ if (!editTarget) return;
3097
+ const body = {};
3098
+ const newIdTool = editForm.id_tool ? parseInt(editForm.id_tool, 10) : null;
3099
+ if (newIdTool && newIdTool !== editTarget.id_tool) {
3100
+ body.id_tool = newIdTool;
3101
+ }
3102
+ if (editForm.label.trim() && editForm.label.trim() !== (editTarget.label || "")) {
3103
+ body.label = editForm.label.trim();
3104
+ }
3105
+ if (editForm.credentials_encrypted.trim()) {
3106
+ body.credentials_encrypted = editForm.credentials_encrypted.trim();
3107
+ }
3108
+ if (editForm.expires_at !== (editTarget.expires_at || "")) {
3109
+ body.expires_at = editForm.expires_at || null;
3110
+ }
3111
+ if (editForm.status && editForm.status !== editTarget.status) {
3112
+ body.status = editForm.status;
3113
+ }
3114
+ if (Object.keys(body).length === 0) {
3115
+ setEditTarget(null);
3116
+ return;
3117
+ }
3118
+ try {
3119
+ const result = await updateMutation.mutateAsync({
3120
+ id: editTarget.id,
3121
+ body
3122
+ });
3123
+ if (result.status === 1) {
3124
+ toast9.success("Credencial atualizada");
3125
+ setEditTarget(null);
3126
+ } else {
3127
+ toast9.error(result.message || "Erro ao atualizar credencial");
3128
+ }
3129
+ } catch {
3130
+ toast9.error("Erro ao atualizar credencial");
3131
+ }
3132
+ }
3133
+ async function handleRemove() {
3134
+ if (!removeTarget) return;
3135
+ try {
3136
+ const result = await deleteMutation.mutateAsync(removeTarget.id);
3137
+ if (result.status === 1) {
3138
+ toast9.success("Credencial removida");
3139
+ } else {
3140
+ toast9.error(result.message || "Erro ao remover credencial");
3141
+ }
3142
+ } catch {
3143
+ toast9.error("Erro ao remover credencial");
3144
+ } finally {
3145
+ setRemoveTarget(null);
3146
+ }
3147
+ }
3148
+ function handleConnect(cred) {
3149
+ if (!config.accountId || !config.token) return;
3150
+ const language = config.language ?? "pt-br";
3151
+ const idWl = config.idWl ?? 1;
3152
+ const url = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${config.accountId}/oauth/connect?id_tool=${cred.id_tool}`;
3153
+ window.open(url, "_blank");
3154
+ }
3155
+ return /* @__PURE__ */ jsxs10("div", { className: "space-y-4", children: [
3156
+ /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs10("div", { className: "relative flex-1 max-w-md", children: [
3157
+ /* @__PURE__ */ jsx11(Search3, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3158
+ /* @__PURE__ */ jsx11(
3159
+ Input9,
3160
+ {
3161
+ placeholder: "Buscar credenciais...",
3162
+ value: search,
3163
+ onChange: (e) => setSearch(e.target.value),
3164
+ className: "pl-9"
3165
+ }
3166
+ )
3167
+ ] }) }),
3168
+ /* @__PURE__ */ jsx11(
3169
+ DataTable3,
3170
+ {
3171
+ columns,
3172
+ data: filteredCredentials,
3173
+ isLoading,
3174
+ emptyMessage: "Nenhuma credencial encontrada"
3175
+ }
3176
+ ),
3177
+ /* @__PURE__ */ jsx11(Dialog6, { open: showCreateDialog, onOpenChange: setShowCreateDialog, children: /* @__PURE__ */ jsxs10(DialogContent6, { children: [
3178
+ /* @__PURE__ */ jsx11(DialogHeader6, { children: /* @__PURE__ */ jsx11(DialogTitle6, { children: "Nova Credencial" }) }),
3179
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-4", children: [
3180
+ /* @__PURE__ */ jsxs10("div", { children: [
3181
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
3182
+ /* @__PURE__ */ jsxs10(
3183
+ Select3,
3184
+ {
3185
+ value: createForm.id_tool,
3186
+ onValueChange: (val) => setCreateForm((f) => ({ ...f, id_tool: val })),
3187
+ children: [
3188
+ /* @__PURE__ */ jsx11(SelectTrigger3, { children: /* @__PURE__ */ jsx11(SelectValue3, { placeholder: "Selecione a ferramenta" }) }),
3189
+ /* @__PURE__ */ jsx11(SelectContent3, { children: tools.map((tool) => /* @__PURE__ */ jsx11(SelectItem3, { value: String(tool.id), children: tool.name }, tool.id)) })
3190
+ ]
3191
+ }
3192
+ )
3193
+ ] }),
3194
+ /* @__PURE__ */ jsxs10("div", { children: [
3195
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Label *" }),
3196
+ /* @__PURE__ */ jsx11(
3197
+ Input9,
3198
+ {
3199
+ value: createForm.label,
3200
+ onChange: (e) => setCreateForm((f) => ({ ...f, label: e.target.value })),
3201
+ placeholder: "Ex: Google Calendar - Cl\xEDnica S\xE3o Paulo"
3202
+ }
3203
+ )
3204
+ ] }),
3205
+ /* @__PURE__ */ jsxs10("div", { children: [
3206
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Credencial *" }),
3207
+ /* @__PURE__ */ jsx11(
3208
+ Input9,
3209
+ {
3210
+ type: "password",
3211
+ value: createForm.credentials_encrypted,
3212
+ onChange: (e) => setCreateForm((f) => ({
3213
+ ...f,
3214
+ credentials_encrypted: e.target.value
3215
+ })),
3216
+ placeholder: "Credencial encriptada"
3217
+ }
3218
+ )
3219
+ ] }),
3220
+ /* @__PURE__ */ jsxs10("div", { children: [
3221
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o (opcional)" }),
3222
+ /* @__PURE__ */ jsx11(
3223
+ Input9,
3224
+ {
3225
+ type: "date",
3226
+ value: createForm.expires_at,
3227
+ onChange: (e) => setCreateForm((f) => ({ ...f, expires_at: e.target.value }))
3228
+ }
3229
+ )
3230
+ ] })
3231
+ ] }),
3232
+ /* @__PURE__ */ jsxs10(DialogFooter6, { children: [
3233
+ /* @__PURE__ */ jsx11(
3234
+ Button9,
3235
+ {
3236
+ variant: "outline",
3237
+ onClick: () => setShowCreateDialog(false),
3238
+ children: "Cancelar"
3239
+ }
3240
+ ),
3241
+ /* @__PURE__ */ jsx11(
3242
+ Button9,
3243
+ {
3244
+ onClick: handleCreate,
3245
+ disabled: !createForm.id_tool || !createForm.label.trim() || !createForm.credentials_encrypted.trim() || createMutation.isPending,
3246
+ children: "Criar"
3247
+ }
3248
+ )
3249
+ ] })
3250
+ ] }) }),
3251
+ /* @__PURE__ */ jsx11(
3252
+ Dialog6,
3253
+ {
3254
+ open: !!editTarget,
3255
+ onOpenChange: (open) => !open && setEditTarget(null),
3256
+ children: /* @__PURE__ */ jsxs10(DialogContent6, { children: [
3257
+ /* @__PURE__ */ jsx11(DialogHeader6, { children: /* @__PURE__ */ jsx11(DialogTitle6, { children: "Editar Credencial" }) }),
3258
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-4", children: [
3259
+ /* @__PURE__ */ jsxs10("div", { children: [
3260
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
3261
+ /* @__PURE__ */ jsxs10(
3262
+ Select3,
3263
+ {
3264
+ value: editForm.id_tool,
3265
+ onValueChange: (val) => setEditForm((f) => ({ ...f, id_tool: val })),
3266
+ children: [
3267
+ /* @__PURE__ */ jsx11(SelectTrigger3, { children: /* @__PURE__ */ jsx11(SelectValue3, { placeholder: "Selecione a ferramenta" }) }),
3268
+ /* @__PURE__ */ jsx11(SelectContent3, { children: tools.map((tool) => /* @__PURE__ */ jsx11(SelectItem3, { value: String(tool.id), children: tool.name }, tool.id)) })
3269
+ ]
3270
+ }
3271
+ )
3272
+ ] }),
3273
+ /* @__PURE__ */ jsxs10("div", { children: [
3274
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Label" }),
3275
+ /* @__PURE__ */ jsx11(
3276
+ Input9,
3277
+ {
3278
+ value: editForm.label,
3279
+ onChange: (e) => setEditForm((f) => ({ ...f, label: e.target.value })),
3280
+ placeholder: "Label da credencial"
3281
+ }
3282
+ )
3283
+ ] }),
3284
+ /* @__PURE__ */ jsxs10("div", { children: [
3285
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Nova Credencial (vazio = manter atual)" }),
3286
+ /* @__PURE__ */ jsx11(
3287
+ Input9,
3288
+ {
3289
+ type: "password",
3290
+ value: editForm.credentials_encrypted,
3291
+ onChange: (e) => setEditForm((f) => ({
3292
+ ...f,
3293
+ credentials_encrypted: e.target.value
3294
+ })),
3295
+ placeholder: "Nova credencial"
3296
+ }
3297
+ )
3298
+ ] }),
3299
+ /* @__PURE__ */ jsxs10("div", { children: [
3300
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o" }),
3301
+ /* @__PURE__ */ jsx11(
3302
+ Input9,
3303
+ {
3304
+ type: "date",
3305
+ value: editForm.expires_at,
3306
+ onChange: (e) => setEditForm((f) => ({ ...f, expires_at: e.target.value }))
3307
+ }
3308
+ )
3309
+ ] }),
3310
+ /* @__PURE__ */ jsxs10("div", { children: [
3311
+ /* @__PURE__ */ jsx11("label", { className: "mb-1 block text-sm font-medium", children: "Status" }),
3312
+ /* @__PURE__ */ jsxs10(
3313
+ Select3,
3314
+ {
3315
+ value: editForm.status || void 0,
3316
+ onValueChange: (val) => setEditForm((f) => ({
3317
+ ...f,
3318
+ status: val
3319
+ })),
3320
+ children: [
3321
+ /* @__PURE__ */ jsx11(SelectTrigger3, { children: /* @__PURE__ */ jsx11(SelectValue3, {}) }),
3322
+ /* @__PURE__ */ jsxs10(SelectContent3, { children: [
3323
+ /* @__PURE__ */ jsx11(SelectItem3, { value: "active", children: "Ativo" }),
3324
+ /* @__PURE__ */ jsx11(SelectItem3, { value: "expired", children: "Expirado" })
3325
+ ] })
3326
+ ]
3327
+ }
3328
+ )
3329
+ ] })
3330
+ ] }),
3331
+ /* @__PURE__ */ jsxs10(DialogFooter6, { children: [
3332
+ /* @__PURE__ */ jsx11(Button9, { variant: "outline", onClick: () => setEditTarget(null), children: "Cancelar" }),
3333
+ /* @__PURE__ */ jsx11(
3334
+ Button9,
3335
+ {
3336
+ onClick: handleSaveEdit,
3337
+ disabled: updateMutation.isPending,
3338
+ children: "Salvar"
3339
+ }
3340
+ )
3341
+ ] })
3342
+ ] })
3343
+ }
3344
+ ),
3345
+ /* @__PURE__ */ jsx11(
3346
+ AlertDialog5,
3347
+ {
3348
+ open: !!removeTarget,
3349
+ onOpenChange: (open) => !open && setRemoveTarget(null),
3350
+ children: /* @__PURE__ */ jsxs10(AlertDialogContent5, { children: [
3351
+ /* @__PURE__ */ jsxs10(AlertDialogHeader5, { children: [
3352
+ /* @__PURE__ */ jsx11(AlertDialogTitle5, { children: "Remover credencial?" }),
3353
+ /* @__PURE__ */ jsx11(AlertDialogDescription5, { children: "A credencial ser\xE1 removida permanentemente." })
3354
+ ] }),
3355
+ /* @__PURE__ */ jsxs10(AlertDialogFooter5, { children: [
3356
+ /* @__PURE__ */ jsx11(AlertDialogCancel5, { children: "Cancelar" }),
3357
+ /* @__PURE__ */ jsx11(
3358
+ AlertDialogAction5,
3359
+ {
3360
+ onClick: handleRemove,
3361
+ disabled: deleteMutation.isPending,
3362
+ children: "Remover"
3363
+ }
3364
+ )
3365
+ ] })
3366
+ ] })
3367
+ }
3368
+ )
3369
+ ] });
3370
+ }
3371
+
3372
+ // src/pages/agents-page.tsx
3373
+ import { useState as useState11 } from "react";
3374
+ import { Button as Button10 } from "@greatapps/greatauth-ui/ui";
3375
+ import { Plus as Plus3 } from "lucide-react";
3376
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
3377
+ function AgentsPage({
3378
+ config,
3379
+ onNavigateToAgent,
3380
+ title = "Agentes AI",
3381
+ subtitle = "Gerencie seus agentes de atendimento inteligente"
3382
+ }) {
3383
+ const [createOpen, setCreateOpen] = useState11(false);
3384
+ return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 p-4", children: [
3385
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
3386
+ /* @__PURE__ */ jsxs11("div", { children: [
3387
+ /* @__PURE__ */ jsx12("h1", { className: "text-xl font-semibold", children: title }),
3388
+ /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground", children: subtitle })
3389
+ ] }),
3390
+ /* @__PURE__ */ jsxs11(Button10, { onClick: () => setCreateOpen(true), size: "sm", children: [
3391
+ /* @__PURE__ */ jsx12(Plus3, { className: "mr-2 h-4 w-4" }),
3392
+ "Novo Agente"
3393
+ ] })
3394
+ ] }),
3395
+ /* @__PURE__ */ jsx12(AgentsTable, { config, onNavigateToAgent }),
3396
+ /* @__PURE__ */ jsx12(
3397
+ AgentFormDialog,
3398
+ {
3399
+ config,
3400
+ open: createOpen,
3401
+ onOpenChange: setCreateOpen
3402
+ }
3403
+ )
3404
+ ] });
3405
+ }
3406
+
3407
+ // src/pages/agent-detail-page.tsx
3408
+ import { useState as useState12 } from "react";
3409
+ import { Badge as Badge7, Button as Button11, Skeleton as Skeleton4 } from "@greatapps/greatauth-ui/ui";
3410
+ import { EntityAvatar as EntityAvatar2 } from "@greatapps/greatauth-ui";
3411
+ import { ArrowLeft, Pencil as Pencil5 } from "lucide-react";
3412
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
3413
+ function AgentDetailPage({
3414
+ config,
3415
+ agentId,
3416
+ onBack,
3417
+ renderConversationsTab
3418
+ }) {
3419
+ const { data: agent, isLoading } = useAgent(config, agentId);
3420
+ const [editOpen, setEditOpen] = useState12(false);
3421
+ if (isLoading) {
3422
+ return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-4 p-4", children: [
3423
+ /* @__PURE__ */ jsx13(Skeleton4, { className: "h-4 w-32" }),
3424
+ /* @__PURE__ */ jsx13(Skeleton4, { className: "h-8 w-48" }),
3425
+ /* @__PURE__ */ jsx13(Skeleton4, { className: "h-10 w-full" }),
3426
+ /* @__PURE__ */ jsx13(Skeleton4, { className: "h-64 w-full" })
3427
+ ] });
3428
+ }
3429
+ if (!agent) {
3430
+ return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center gap-2 p-8", children: [
3431
+ /* @__PURE__ */ jsx13("p", { className: "text-muted-foreground", children: "Agente n\xE3o encontrado" }),
3432
+ onBack && /* @__PURE__ */ jsxs12(Button11, { variant: "ghost", size: "sm", onClick: onBack, children: [
3433
+ /* @__PURE__ */ jsx13(ArrowLeft, { className: "mr-2 h-4 w-4" }),
3434
+ "Voltar para agentes"
3435
+ ] })
3436
+ ] });
3437
+ }
3438
+ return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-6 p-4", children: [
3439
+ /* @__PURE__ */ jsx13("div", { className: "rounded-lg border p-4 md:p-6", children: /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-4 md:flex-row md:items-start md:gap-6", children: [
3440
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3 flex-1", children: [
3441
+ onBack && /* @__PURE__ */ jsx13(
3442
+ Button11,
3443
+ {
3444
+ variant: "ghost",
3445
+ size: "icon",
3446
+ className: "shrink-0 mt-1",
3447
+ onClick: onBack,
3448
+ children: /* @__PURE__ */ jsx13(ArrowLeft, { className: "h-4 w-4" })
3449
+ }
3450
+ ),
3451
+ /* @__PURE__ */ jsx13(EntityAvatar2, { photo: agent.photo, name: agent.title, size: "xl" }),
3452
+ /* @__PURE__ */ jsx13("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 flex-wrap", children: [
3453
+ /* @__PURE__ */ jsx13("h1", { className: "text-xl font-semibold", children: agent.title }),
3454
+ /* @__PURE__ */ jsx13(
3455
+ Badge7,
3456
+ {
3457
+ variant: agent.active ? "default" : "destructive",
3458
+ className: "text-xs",
3459
+ children: agent.active ? "Ativo" : "Inativo"
3460
+ }
3461
+ )
3462
+ ] }) })
3463
+ ] }),
3464
+ /* @__PURE__ */ jsxs12(
3465
+ Button11,
3466
+ {
3467
+ variant: "outline",
3468
+ size: "sm",
3469
+ className: "shrink-0 self-start",
3470
+ onClick: () => setEditOpen(true),
3471
+ children: [
3472
+ /* @__PURE__ */ jsx13(Pencil5, { className: "mr-2 h-4 w-4" }),
3473
+ "Editar"
3474
+ ]
3475
+ }
3476
+ )
3477
+ ] }) }),
3478
+ /* @__PURE__ */ jsx13(
3479
+ AgentTabs,
3480
+ {
3481
+ agent,
3482
+ config,
3483
+ renderConversationsTab
3484
+ }
3485
+ ),
3486
+ editOpen && /* @__PURE__ */ jsx13(
3487
+ AgentEditForm,
3488
+ {
3489
+ agent,
3490
+ config,
3491
+ idAccount: config.accountId,
3492
+ open: editOpen,
3493
+ onOpenChange: setEditOpen
3494
+ }
3495
+ )
3496
+ ] });
3497
+ }
3498
+
3499
+ // src/pages/tools-page.tsx
3500
+ import { useState as useState13 } from "react";
3501
+ import { Button as Button12 } from "@greatapps/greatauth-ui/ui";
3502
+ import { Plus as Plus4 } from "lucide-react";
3503
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
3504
+ function ToolsPage({
3505
+ config,
3506
+ title = "Ferramentas",
3507
+ subtitle = "Gerencie as ferramentas dispon\xEDveis para seus agentes"
3508
+ }) {
3509
+ const [createOpen, setCreateOpen] = useState13(false);
3510
+ const [editTool, setEditTool] = useState13(void 0);
3511
+ return /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-4 p-4", children: [
3512
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between", children: [
3513
+ /* @__PURE__ */ jsxs13("div", { children: [
3514
+ /* @__PURE__ */ jsx14("h1", { className: "text-xl font-semibold", children: title }),
3515
+ /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: subtitle })
3516
+ ] }),
3517
+ /* @__PURE__ */ jsxs13(Button12, { onClick: () => setCreateOpen(true), size: "sm", children: [
3518
+ /* @__PURE__ */ jsx14(Plus4, { className: "mr-2 h-4 w-4" }),
3519
+ "Nova Ferramenta"
3520
+ ] })
3521
+ ] }),
3522
+ /* @__PURE__ */ jsx14(ToolsTable, { config, onEdit: (tool) => setEditTool(tool) }),
3523
+ /* @__PURE__ */ jsx14(
3524
+ ToolFormDialog,
3525
+ {
3526
+ config,
3527
+ open: createOpen,
3528
+ onOpenChange: setCreateOpen
3529
+ }
3530
+ ),
3531
+ /* @__PURE__ */ jsx14(
3532
+ ToolFormDialog,
3533
+ {
3534
+ config,
3535
+ open: !!editTool,
3536
+ onOpenChange: (open) => !open && setEditTool(void 0),
3537
+ tool: editTool
3538
+ }
3539
+ )
3540
+ ] });
3541
+ }
3542
+
3543
+ // src/pages/credentials-page.tsx
3544
+ import { useState as useState14 } from "react";
3545
+ import { Button as Button13 } from "@greatapps/greatauth-ui/ui";
3546
+ import { Plus as Plus5 } from "lucide-react";
3547
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
3548
+ function CredentialsPage({
3549
+ config,
3550
+ gagentsApiUrl,
3551
+ title = "Credenciais",
3552
+ subtitle = "Gerencie as credenciais de autentica\xE7\xE3o das ferramentas"
3553
+ }) {
3554
+ const { data: credentialsData, isLoading: credentialsLoading } = useToolCredentials(config);
3555
+ const [createOpen, setCreateOpen] = useState14(false);
3556
+ const credentials = credentialsData?.data || [];
3557
+ return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-4 p-4", children: [
3558
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between", children: [
3559
+ /* @__PURE__ */ jsxs14("div", { children: [
3560
+ /* @__PURE__ */ jsx15("h1", { className: "text-xl font-semibold", children: title }),
3561
+ /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: subtitle })
3562
+ ] }),
3563
+ /* @__PURE__ */ jsxs14(Button13, { onClick: () => setCreateOpen(true), size: "sm", children: [
3564
+ /* @__PURE__ */ jsx15(Plus5, { className: "mr-2 h-4 w-4" }),
3565
+ "Nova Credencial"
3566
+ ] })
3567
+ ] }),
3568
+ /* @__PURE__ */ jsx15(
3569
+ ToolCredentialsForm,
3570
+ {
3571
+ config,
3572
+ gagentsApiUrl,
3573
+ credentials,
3574
+ isLoading: credentialsLoading,
3575
+ createOpen,
3576
+ onCreateOpenChange: setCreateOpen
3577
+ }
3578
+ )
3579
+ ] });
3580
+ }
446
3581
  export {
3582
+ AgentDetailPage,
3583
+ AgentEditForm,
3584
+ AgentFormDialog,
3585
+ AgentObjectivesList,
3586
+ AgentPromptEditor,
3587
+ AgentTabs,
3588
+ AgentToolsList,
3589
+ AgentsPage,
3590
+ AgentsTable,
3591
+ CredentialsPage,
3592
+ Sortable,
3593
+ SortableContent,
3594
+ SortableItem,
3595
+ SortableItemHandle,
3596
+ SortableOverlay,
3597
+ ToolCredentialsForm,
3598
+ ToolFormDialog,
3599
+ ToolsPage,
3600
+ ToolsTable,
447
3601
  cn,
448
3602
  createGagentsClient,
449
3603
  useAddAgentTool,