@greatapps/greatagents-ui 0.3.12 → 0.3.14

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
@@ -1139,9 +1139,6 @@ function AgentEditForm({ config, agent, idAccount, open, onOpenChange }) {
1139
1139
  return /* @__PURE__ */ jsx3("div", { className: "max-w-lg pt-4", children: formContent });
1140
1140
  }
1141
1141
 
1142
- // src/components/agents/agent-tabs.tsx
1143
- import { useState as useState10, useCallback as useCallback6 } from "react";
1144
-
1145
1142
  // src/components/agents/agent-objectives-list.tsx
1146
1143
  import { useState as useState5 } from "react";
1147
1144
  import {
@@ -2514,7 +2511,7 @@ import {
2514
2511
  Skeleton as Skeleton5
2515
2512
  } from "@greatapps/greatauth-ui/ui";
2516
2513
  import {
2517
- Calendar,
2514
+ CalendarCheck,
2518
2515
  Users,
2519
2516
  Settings,
2520
2517
  HeartHandshake,
@@ -2534,7 +2531,7 @@ function getOperationLabel(slug) {
2534
2531
  return OPERATION_LABELS[slug] ?? slug;
2535
2532
  }
2536
2533
  var CATEGORY_ICONS = {
2537
- agenda: Calendar,
2534
+ agenda: CalendarCheck,
2538
2535
  cadastros: Users,
2539
2536
  infraestrutura: Settings,
2540
2537
  relacionamentos: HeartHandshake
@@ -2819,1583 +2816,1120 @@ function ModuleRow({
2819
2816
  ] });
2820
2817
  }
2821
2818
 
2822
- // src/components/capabilities/integration-card.tsx
2823
- import { Badge as Badge6, Button as Button8, Tooltip as Tooltip2, TooltipContent as TooltipContent2, TooltipTrigger as TooltipTrigger2 } from "@greatapps/greatauth-ui/ui";
2824
- import {
2825
- CalendarSync,
2826
- Plug,
2827
- Settings as Settings2,
2828
- RefreshCw,
2829
- Users as Users2,
2830
- Clock,
2831
- Plus as Plus2
2832
- } from "lucide-react";
2819
+ // src/components/capabilities/integrations-tab.tsx
2820
+ import { useCallback as useCallback5 } from "react";
2821
+ import { Switch as Switch5, Tooltip as Tooltip2, TooltipContent as TooltipContent2, TooltipTrigger as TooltipTrigger2 } from "@greatapps/greatauth-ui/ui";
2822
+ import { Plug, Loader2 as Loader25 } from "lucide-react";
2823
+ import { CalendarSync } from "lucide-react";
2833
2824
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2834
2825
  var ICON_MAP = {
2835
2826
  CalendarSync,
2836
- Plug,
2837
- Settings: Settings2,
2838
- RefreshCw,
2839
- Users: Users2,
2840
- Clock,
2841
- Plus: Plus2
2827
+ Plug
2842
2828
  };
2843
2829
  function resolveIcon(name) {
2844
2830
  return ICON_MAP[name] ?? Plug;
2845
2831
  }
2846
- var STATE_BADGES = {
2847
- available: {
2848
- label: "Dispon\xEDvel",
2849
- className: "bg-muted text-muted-foreground"
2850
- },
2851
- connected: {
2852
- label: "Conectado",
2853
- className: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"
2854
- },
2855
- expired: {
2856
- label: "Expirado",
2857
- className: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"
2858
- },
2859
- coming_soon: {
2860
- label: "Em breve",
2861
- className: "bg-muted text-muted-foreground"
2862
- }
2863
- };
2864
- function getActionLabel(card) {
2865
- if (card.isAddNew) return "Conectar";
2866
- switch (card.state) {
2867
- case "available":
2868
- return "Conectar";
2869
- case "connected":
2870
- return "Configurar";
2871
- case "expired":
2872
- return "Reconectar";
2873
- default:
2874
- return "";
2875
- }
2876
- }
2877
- function IntegrationCard({ card, onConnect }) {
2878
- const { definition, state, sharedByAgentsCount, isAddNew, accountLabel } = card;
2879
- const Icon = resolveIcon(definition.icon);
2880
- const isComingSoon = state === "coming_soon";
2881
- const actionLabel = getActionLabel(card);
2882
- if (isAddNew) {
2883
- return /* @__PURE__ */ jsxs9(
2884
- "div",
2885
- {
2886
- className: cn(
2887
- "group relative flex flex-col gap-3 rounded-xl border border-dashed bg-card/50 p-5 transition-shadow",
2888
- "hover:shadow-md hover:border-solid hover:bg-card cursor-pointer"
2889
- ),
2890
- role: "button",
2891
- tabIndex: 0,
2892
- "aria-label": `Adicionar conta ${definition.name}`,
2893
- onClick: () => onConnect(card),
2894
- onKeyDown: (e) => {
2895
- if (e.key === "Enter" || e.key === " ") {
2896
- e.preventDefault();
2897
- onConnect(card);
2898
- }
2899
- },
2900
- children: [
2901
- /* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between gap-2", children: [
2902
- /* @__PURE__ */ jsx11("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/5 text-primary/60", children: /* @__PURE__ */ jsx11(Icon, { className: "h-5 w-5" }) }),
2903
- /* @__PURE__ */ jsx11(Badge6, { variant: "outline", className: "text-xs bg-muted text-muted-foreground", children: "Adicionar" })
2904
- ] }),
2905
- /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
2906
- /* @__PURE__ */ jsx11("h3", { className: "text-sm font-semibold leading-tight text-muted-foreground", children: definition.name }),
2907
- /* @__PURE__ */ jsxs9("p", { className: "text-xs text-muted-foreground/70 leading-relaxed flex items-center gap-1", children: [
2908
- /* @__PURE__ */ jsx11(Plus2, { className: "h-3 w-3" }),
2909
- "Adicionar conta"
2910
- ] })
2911
- ] }),
2912
- /* @__PURE__ */ jsx11("div", { className: "mt-auto flex items-center justify-end pt-1", children: /* @__PURE__ */ jsx11(
2913
- Button8,
2914
- {
2915
- variant: "outline",
2916
- size: "sm",
2917
- className: "text-xs",
2918
- onClick: (e) => {
2919
- e.stopPropagation();
2920
- onConnect(card);
2921
- },
2922
- children: actionLabel
2923
- }
2924
- ) })
2925
- ]
2926
- }
2927
- );
2928
- }
2929
- const badge = STATE_BADGES[state];
2930
- return /* @__PURE__ */ jsxs9(
2931
- "div",
2932
- {
2933
- className: cn(
2934
- "group relative flex flex-col gap-3 rounded-xl border bg-card p-5 transition-shadow",
2935
- isComingSoon ? "opacity-60 cursor-default" : "hover:shadow-md cursor-pointer"
2936
- ),
2937
- role: "button",
2938
- tabIndex: isComingSoon ? -1 : 0,
2939
- "aria-label": `${definition.name}${accountLabel ? ` \u2014 ${accountLabel}` : ""} \u2014 ${badge.label}`,
2940
- "aria-disabled": isComingSoon,
2941
- onClick: () => !isComingSoon && onConnect(card),
2942
- onKeyDown: (e) => {
2943
- if (!isComingSoon && (e.key === "Enter" || e.key === " ")) {
2944
- e.preventDefault();
2945
- onConnect(card);
2946
- }
2947
- },
2948
- children: [
2949
- /* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between gap-2", children: [
2950
- /* @__PURE__ */ jsx11("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsx11(Icon, { className: "h-5 w-5" }) }),
2951
- /* @__PURE__ */ jsx11(Badge6, { variant: "outline", className: cn("text-xs", badge.className), children: badge.label })
2952
- ] }),
2953
- /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
2954
- /* @__PURE__ */ jsx11("h3", { className: "text-sm font-semibold leading-tight", children: definition.name }),
2955
- accountLabel ? /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground leading-relaxed truncate", title: accountLabel, children: accountLabel }) : /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground leading-relaxed", children: definition.description })
2956
- ] }),
2957
- /* @__PURE__ */ jsxs9("div", { className: "mt-auto flex items-center justify-between gap-2 pt-1", children: [
2958
- sharedByAgentsCount > 0 ? /* @__PURE__ */ jsxs9(Tooltip2, { children: [
2959
- /* @__PURE__ */ jsx11(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs9("span", { className: "inline-flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400", children: [
2960
- /* @__PURE__ */ jsx11(Users2, { className: "h-3.5 w-3.5" }),
2961
- "Compartilhada"
2962
- ] }) }),
2963
- /* @__PURE__ */ jsx11(TooltipContent2, { children: "Esta credencial est\xE1 dispon\xEDvel para todos os agentes da conta" })
2964
- ] }) : /* @__PURE__ */ jsx11("span", {}),
2965
- !isComingSoon && /* @__PURE__ */ jsx11(
2966
- Button8,
2967
- {
2968
- variant: state === "expired" ? "destructive" : "outline",
2969
- size: "sm",
2970
- className: "text-xs",
2971
- onClick: (e) => {
2972
- e.stopPropagation();
2973
- onConnect(card);
2974
- },
2975
- children: actionLabel
2976
- }
2977
- )
2978
- ] })
2979
- ]
2980
- }
2981
- );
2982
- }
2983
-
2984
- // src/components/capabilities/integrations-tab.tsx
2985
- import { Plug as Plug2, Loader2 as Loader25 } from "lucide-react";
2986
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2987
- function getCardKey(card) {
2988
- if (card.credentialId) {
2989
- return `${card.definition.slug}-cred-${card.credentialId}`;
2990
- }
2991
- if (card.isAddNew) {
2992
- return `${card.definition.slug}-add-new`;
2993
- }
2994
- return card.definition.slug;
2995
- }
2996
2832
  function IntegrationsTab({
2997
2833
  config,
2998
- agentId,
2999
- onConnect
2834
+ agentId
3000
2835
  }) {
3001
2836
  const { cards, isLoading } = useIntegrationState(config, agentId);
3002
- if (isLoading) {
3003
- return /* @__PURE__ */ jsx12("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx12(Loader25, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
3004
- }
3005
- if (cards.length === 0) {
3006
- return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center justify-center gap-3 py-16 text-muted-foreground", children: [
3007
- /* @__PURE__ */ jsx12(Plug2, { className: "h-10 w-10" }),
3008
- /* @__PURE__ */ jsx12("p", { className: "text-sm", children: "Nenhuma integra\xE7\xE3o dispon\xEDvel" })
3009
- ] });
3010
- }
2837
+ const { data: agentToolsData, isLoading: agentToolsLoading } = useAgentTools(config, agentId);
2838
+ const addAgentTool = useAddAgentTool(config);
2839
+ const removeAgentTool = useRemoveAgentTool(config);
2840
+ const agentTools = agentToolsData?.data ?? [];
3011
2841
  const connectedCards = cards.filter(
3012
2842
  (c) => !c.isAddNew && (c.state === "connected" || c.state === "expired")
3013
2843
  );
3014
- const otherCards = cards.filter(
3015
- (c) => c.isAddNew || c.state === "coming_soon"
2844
+ const handleToggle = useCallback5(
2845
+ (toolId, checked) => {
2846
+ if (checked) {
2847
+ addAgentTool.mutate({
2848
+ idAgent: agentId,
2849
+ body: { id_tool: toolId, enabled: true }
2850
+ });
2851
+ } else {
2852
+ const agentTool = agentTools.find((at) => at.id_tool === toolId);
2853
+ if (agentTool) {
2854
+ removeAgentTool.mutate({ idAgent: agentId, id: agentTool.id });
2855
+ }
2856
+ }
2857
+ },
2858
+ [agentTools, agentId, addAgentTool, removeAgentTool]
3016
2859
  );
3017
- return /* @__PURE__ */ jsxs10("div", { className: "space-y-6", children: [
3018
- connectedCards.length > 0 && /* @__PURE__ */ jsxs10("div", { children: [
3019
- /* @__PURE__ */ jsx12("h3", { className: "mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: "Contas conectadas" }),
3020
- /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: connectedCards.map((card) => /* @__PURE__ */ jsx12(
3021
- IntegrationCard,
2860
+ if (isLoading || agentToolsLoading) {
2861
+ return /* @__PURE__ */ jsx11("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx11(Loader25, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
2862
+ }
2863
+ if (connectedCards.length === 0) {
2864
+ return /* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-center justify-center gap-3 py-16 text-muted-foreground", children: [
2865
+ /* @__PURE__ */ jsx11(Plug, { className: "h-10 w-10" }),
2866
+ /* @__PURE__ */ jsx11("p", { className: "text-sm font-medium", children: "Nenhuma integra\xE7\xE3o conectada" }),
2867
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-center max-w-sm", children: "Conecte integra\xE7\xF5es na p\xE1gina de Integra\xE7\xF5es da conta para que possam ser ativadas neste agente." })
2868
+ ] });
2869
+ }
2870
+ return /* @__PURE__ */ jsxs9("div", { className: "space-y-4", children: [
2871
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground", children: "Ative ou desative as integra\xE7\xF5es conectadas na conta para este agente." }),
2872
+ /* @__PURE__ */ jsx11("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3", children: connectedCards.map((card) => {
2873
+ const Icon = resolveIcon(card.definition.icon);
2874
+ const isLinked = card.linkedToAgent;
2875
+ const isMutating = addAgentTool.isPending || removeAgentTool.isPending;
2876
+ return /* @__PURE__ */ jsxs9(
2877
+ "div",
3022
2878
  {
3023
- card,
3024
- onConnect
2879
+ className: cn(
2880
+ "flex items-center gap-3 rounded-xl border bg-card p-4 transition-shadow",
2881
+ isLinked ? "border-primary/30 shadow-sm" : "opacity-75"
2882
+ ),
2883
+ children: [
2884
+ /* @__PURE__ */ jsx11("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsx11(Icon, { className: "h-4.5 w-4.5" }) }),
2885
+ /* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
2886
+ /* @__PURE__ */ jsx11("h4", { className: "text-sm font-medium leading-tight truncate", children: card.definition.name }),
2887
+ card.accountLabel && /* @__PURE__ */ jsxs9(Tooltip2, { children: [
2888
+ /* @__PURE__ */ jsx11(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground truncate", title: card.accountLabel, children: card.accountLabel }) }),
2889
+ /* @__PURE__ */ jsx11(TooltipContent2, { children: card.accountLabel })
2890
+ ] }),
2891
+ card.state === "expired" && /* @__PURE__ */ jsx11("p", { className: "text-xs text-amber-600 dark:text-amber-400", children: "Expirado" })
2892
+ ] }),
2893
+ /* @__PURE__ */ jsx11(
2894
+ Switch5,
2895
+ {
2896
+ checked: isLinked,
2897
+ disabled: isMutating || !card.tool,
2898
+ onCheckedChange: (checked) => card.tool && handleToggle(card.tool.id, checked),
2899
+ "aria-label": `${isLinked ? "Desativar" : "Ativar"} ${card.definition.name} para este agente`
2900
+ }
2901
+ )
2902
+ ]
3025
2903
  },
3026
- getCardKey(card)
3027
- )) })
2904
+ `${card.definition.slug}-cred-${card.credentialId}`
2905
+ );
2906
+ }) })
2907
+ ] });
2908
+ }
2909
+
2910
+ // src/components/agents/agent-tabs.tsx
2911
+ import {
2912
+ Tabs,
2913
+ TabsList,
2914
+ TabsTrigger,
2915
+ TabsContent
2916
+ } from "@greatapps/greatauth-ui/ui";
2917
+ import { Target as Target2, FileText as FileText2, MessageCircle as MessageCircle2, Blocks, Plug as Plug2 } from "lucide-react";
2918
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2919
+ function AgentTabs({
2920
+ agent,
2921
+ config,
2922
+ renderChatLink
2923
+ }) {
2924
+ return /* @__PURE__ */ jsxs10(Tabs, { defaultValue: "prompt", children: [
2925
+ /* @__PURE__ */ jsxs10(TabsList, { children: [
2926
+ /* @__PURE__ */ jsxs10(TabsTrigger, { value: "prompt", className: "flex items-center gap-1.5", children: [
2927
+ /* @__PURE__ */ jsx12(FileText2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
2928
+ "Prompt"
2929
+ ] }),
2930
+ /* @__PURE__ */ jsxs10(TabsTrigger, { value: "objetivos", className: "flex items-center gap-1.5", children: [
2931
+ /* @__PURE__ */ jsx12(Target2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
2932
+ "Objetivos"
2933
+ ] }),
2934
+ /* @__PURE__ */ jsxs10(TabsTrigger, { value: "capacidades", className: "flex items-center gap-1.5", children: [
2935
+ /* @__PURE__ */ jsx12(Blocks, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
2936
+ "Capacidades"
2937
+ ] }),
2938
+ /* @__PURE__ */ jsxs10(TabsTrigger, { value: "integracoes", className: "flex items-center gap-1.5", children: [
2939
+ /* @__PURE__ */ jsx12(Plug2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
2940
+ "Integra\xE7\xF5es"
2941
+ ] }),
2942
+ /* @__PURE__ */ jsxs10(TabsTrigger, { value: "conversas", className: "flex items-center gap-1.5", children: [
2943
+ /* @__PURE__ */ jsx12(MessageCircle2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
2944
+ "Conversas"
2945
+ ] })
3028
2946
  ] }),
3029
- otherCards.length > 0 && /* @__PURE__ */ jsxs10("div", { children: [
3030
- connectedCards.length > 0 && /* @__PURE__ */ jsx12("h3", { className: "mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: "Adicionar integra\xE7\xE3o" }),
3031
- /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: otherCards.map((card) => /* @__PURE__ */ jsx12(
3032
- IntegrationCard,
3033
- {
3034
- card,
3035
- onConnect
3036
- },
3037
- getCardKey(card)
3038
- )) })
3039
- ] })
2947
+ /* @__PURE__ */ jsx12(TabsContent, { value: "prompt", className: "mt-4", children: /* @__PURE__ */ jsx12(AgentPromptEditor, { agent, config }) }),
2948
+ /* @__PURE__ */ jsx12(TabsContent, { value: "objetivos", className: "mt-4", children: /* @__PURE__ */ jsx12(AgentObjectivesList, { agent, config }) }),
2949
+ /* @__PURE__ */ jsx12(TabsContent, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx12(CapabilitiesTab, { config, agentId: agent.id }) }),
2950
+ /* @__PURE__ */ jsx12(TabsContent, { value: "integracoes", className: "mt-4", children: /* @__PURE__ */ jsx12(IntegrationsTab, { config, agentId: agent.id }) }),
2951
+ /* @__PURE__ */ jsx12(TabsContent, { value: "conversas", className: "mt-4", children: /* @__PURE__ */ jsx12(
2952
+ AgentConversationsPanel,
2953
+ {
2954
+ agent,
2955
+ config,
2956
+ renderChatLink
2957
+ }
2958
+ ) })
3040
2959
  ] });
3041
2960
  }
3042
2961
 
3043
- // src/components/capabilities/integration-wizard.tsx
3044
- import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef2, useState as useState9 } from "react";
2962
+ // src/components/agents/agent-tools-list.tsx
2963
+ import { useState as useState9 } from "react";
3045
2964
  import {
2965
+ Switch as Switch6,
2966
+ Badge as Badge6,
2967
+ Button as Button8,
2968
+ Skeleton as Skeleton6,
2969
+ AlertDialog as AlertDialog3,
2970
+ AlertDialogAction as AlertDialogAction3,
2971
+ AlertDialogCancel as AlertDialogCancel3,
2972
+ AlertDialogContent as AlertDialogContent3,
2973
+ AlertDialogDescription as AlertDialogDescription3,
2974
+ AlertDialogFooter as AlertDialogFooter3,
2975
+ AlertDialogHeader as AlertDialogHeader3,
2976
+ AlertDialogTitle as AlertDialogTitle3,
2977
+ Popover,
2978
+ PopoverContent,
2979
+ PopoverTrigger,
2980
+ Input as Input6,
2981
+ Textarea as Textarea2,
3046
2982
  Dialog as Dialog4,
3047
2983
  DialogContent as DialogContent4,
3048
- DialogFooter as DialogFooter4,
3049
2984
  DialogHeader as DialogHeader4,
3050
2985
  DialogTitle as DialogTitle4,
3051
- Button as Button10
2986
+ DialogFooter as DialogFooter4,
2987
+ Label as Label4,
2988
+ Select,
2989
+ SelectContent,
2990
+ SelectItem,
2991
+ SelectTrigger,
2992
+ SelectValue
3052
2993
  } from "@greatapps/greatauth-ui/ui";
3053
- import { Loader2 as Loader28, ChevronLeft, ChevronRight, Check as Check2 } from "lucide-react";
2994
+ import {
2995
+ Trash2 as Trash23,
2996
+ Plus as Plus2,
2997
+ Wrench,
2998
+ Settings2
2999
+ } from "lucide-react";
3054
3000
  import { toast as toast7 } from "sonner";
3055
-
3056
- // src/components/capabilities/wizard-steps/info-step.tsx
3057
- import { Check, Info } from "lucide-react";
3058
3001
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3059
- function InfoStep({ integration, meta }) {
3060
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
3061
- /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-4", children: [
3062
- meta.icon && /* @__PURE__ */ jsx13("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-muted", children: meta.icon }),
3063
- /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
3064
- /* @__PURE__ */ jsx13("h3", { className: "text-lg font-semibold", children: integration.name }),
3065
- /* @__PURE__ */ jsx13("p", { className: "text-sm text-muted-foreground", children: integration.description })
3066
- ] })
3067
- ] }),
3068
- meta.capabilities.length > 0 && /* @__PURE__ */ jsxs11("div", { className: "space-y-3", children: [
3069
- /* @__PURE__ */ jsx13("h4", { className: "text-sm font-medium", children: "O que esta integra\xE7\xE3o permite:" }),
3070
- /* @__PURE__ */ jsx13("ul", { className: "space-y-2", children: meta.capabilities.map((cap, i) => /* @__PURE__ */ jsxs11("li", { className: "flex items-start gap-2 text-sm", children: [
3071
- /* @__PURE__ */ jsx13(
3072
- Check,
3073
- {
3074
- "aria-hidden": "true",
3075
- className: "mt-0.5 h-4 w-4 shrink-0 text-green-600"
3076
- }
3077
- ),
3078
- /* @__PURE__ */ jsxs11("div", { children: [
3079
- /* @__PURE__ */ jsx13("span", { className: "font-medium", children: cap.label }),
3080
- cap.description && /* @__PURE__ */ jsxs11("span", { className: "text-muted-foreground", children: [
3081
- " ",
3082
- "\u2014 ",
3083
- cap.description
3084
- ] })
3085
- ] })
3086
- ] }, i)) })
3087
- ] }),
3088
- meta.requirements.length > 0 && /* @__PURE__ */ jsxs11("div", { className: "space-y-3", children: [
3089
- /* @__PURE__ */ jsx13("h4", { className: "text-sm font-medium", children: "Requisitos:" }),
3090
- /* @__PURE__ */ jsx13("ul", { className: "space-y-2", children: meta.requirements.map((req, i) => /* @__PURE__ */ jsxs11(
3091
- "li",
3092
- {
3093
- className: "flex items-start gap-2 text-sm text-muted-foreground",
3094
- children: [
3095
- /* @__PURE__ */ jsx13(
3096
- Info,
3097
- {
3098
- "aria-hidden": "true",
3099
- className: "mt-0.5 h-4 w-4 shrink-0 text-blue-500"
3100
- }
3101
- ),
3102
- /* @__PURE__ */ jsx13("span", { children: req })
3103
- ]
3104
- },
3105
- i
3106
- )) })
3107
- ] })
3108
- ] });
3109
- }
3110
-
3111
- // src/components/capabilities/wizard-steps/credentials-step.tsx
3112
- import { CheckCircle2, Loader2 as Loader26, AlertCircle, Shield } from "lucide-react";
3113
- import { Button as Button9, Input as Input6, Label as Label4 } from "@greatapps/greatauth-ui/ui";
3114
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3115
- function CredentialsStep({
3116
- integration,
3117
- meta,
3118
- oauthStatus,
3119
- oauthResult,
3120
- apiKey,
3121
- onApiKeyChange,
3122
- onStartOAuth,
3123
- isReconnect = false
3124
- }) {
3125
- if (integration.authType === "oauth2") {
3126
- return /* @__PURE__ */ jsx14(
3127
- OAuthCredentials,
3128
- {
3129
- integration,
3130
- meta,
3131
- oauthStatus,
3132
- oauthResult,
3133
- onStartOAuth,
3134
- isReconnect
3135
- }
3136
- );
3137
- }
3138
- return /* @__PURE__ */ jsx14(ApiKeyCredentials, { apiKey, onApiKeyChange });
3139
- }
3140
- function OAuthCredentials({
3141
- integration,
3142
- meta,
3143
- oauthStatus,
3144
- oauthResult,
3145
- onStartOAuth,
3146
- isReconnect
3147
- }) {
3148
- const providerLabel = meta.providerLabel || integration.name;
3149
- return /* @__PURE__ */ jsxs12("div", { className: "space-y-6", children: [
3150
- /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
3151
- /* @__PURE__ */ jsx14("h3", { className: "text-lg font-semibold", children: "Autentica\xE7\xE3o" }),
3152
- /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: isReconnect ? `Reconecte sua conta ${providerLabel} para renovar a autoriza\xE7\xE3o.` : `Conecte sua conta ${providerLabel} para permitir o acesso.` })
3153
- ] }),
3154
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center gap-4 rounded-lg border p-6", children: [
3155
- oauthStatus === "idle" && /* @__PURE__ */ jsxs12(
3156
- Button9,
3157
- {
3158
- onClick: onStartOAuth,
3159
- size: "lg",
3160
- className: "gap-2",
3161
- children: [
3162
- meta.icon,
3163
- isReconnect ? `Reconectar com ${providerLabel}` : `Conectar com ${providerLabel}`
3164
- ]
3165
- }
3166
- ),
3167
- oauthStatus === "waiting" && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center gap-3 text-center", children: [
3168
- /* @__PURE__ */ jsx14(
3169
- Loader26,
3170
- {
3171
- "aria-hidden": "true",
3172
- className: "h-8 w-8 animate-spin text-muted-foreground"
3173
- }
3174
- ),
3175
- /* @__PURE__ */ jsxs12("div", { children: [
3176
- /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium", children: "Aguardando autoriza\xE7\xE3o..." }),
3177
- /* @__PURE__ */ jsx14("p", { className: "text-xs text-muted-foreground", children: "Complete o login na janela que foi aberta." })
3178
- ] })
3179
- ] }),
3180
- oauthStatus === "success" && oauthResult && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center gap-3 text-center", children: [
3181
- /* @__PURE__ */ jsx14(
3182
- CheckCircle2,
3183
- {
3184
- "aria-hidden": "true",
3185
- className: "h-8 w-8 text-green-600"
3186
- }
3187
- ),
3188
- /* @__PURE__ */ jsxs12("div", { children: [
3189
- /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium text-green-700", children: "Conectado com sucesso!" }),
3190
- oauthResult.email && /* @__PURE__ */ jsx14("p", { className: "text-xs text-muted-foreground", children: oauthResult.email })
3191
- ] })
3192
- ] }),
3193
- oauthStatus === "error" && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center gap-3 text-center", children: [
3194
- /* @__PURE__ */ jsx14(
3195
- AlertCircle,
3196
- {
3197
- "aria-hidden": "true",
3198
- className: "h-8 w-8 text-destructive"
3199
- }
3200
- ),
3201
- /* @__PURE__ */ jsxs12("div", { children: [
3202
- /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium text-destructive", children: "Falha na conex\xE3o" }),
3203
- oauthResult?.error && /* @__PURE__ */ jsx14("p", { className: "text-xs text-muted-foreground", children: oauthResult.error })
3204
- ] }),
3205
- /* @__PURE__ */ jsx14(Button9, { variant: "outline", onClick: onStartOAuth, size: "sm", children: "Tentar novamente" })
3206
- ] })
3207
- ] }),
3208
- /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2 rounded-md bg-muted/50 p-3", children: [
3209
- /* @__PURE__ */ jsx14(
3210
- Shield,
3211
- {
3212
- "aria-hidden": "true",
3213
- className: "mt-0.5 h-4 w-4 shrink-0 text-green-600"
3214
- }
3215
- ),
3216
- /* @__PURE__ */ jsxs12("p", { className: "text-xs text-muted-foreground", children: [
3217
- "Seus dados est\xE3o seguros. Usamos OAuth 2.0 para autentica\xE7\xE3o \u2014 nunca armazenamos sua senha. Voc\xEA pode revogar o acesso a qualquer momento nas configura\xE7\xF5es da sua conta ",
3218
- providerLabel,
3219
- "."
3220
- ] })
3221
- ] })
3222
- ] });
3223
- }
3224
- function ApiKeyCredentials({
3225
- apiKey,
3226
- onApiKeyChange
3227
- }) {
3228
- return /* @__PURE__ */ jsxs12("div", { className: "space-y-6", children: [
3229
- /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
3230
- /* @__PURE__ */ jsx14("h3", { className: "text-lg font-semibold", children: "Autentica\xE7\xE3o" }),
3231
- /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "Insira a chave de API para conectar a integra\xE7\xE3o." })
3232
- ] }),
3233
- /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
3234
- /* @__PURE__ */ jsx14(Label4, { htmlFor: "integration-api-key", children: "Chave de API" }),
3235
- /* @__PURE__ */ jsx14(
3236
- Input6,
3237
- {
3238
- id: "integration-api-key",
3239
- type: "password",
3240
- autoComplete: "off",
3241
- placeholder: "Insira sua chave de API...",
3242
- value: apiKey,
3243
- onChange: (e) => onApiKeyChange(e.target.value)
3244
- }
3245
- )
3246
- ] }),
3247
- /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2 rounded-md bg-muted/50 p-3", children: [
3248
- /* @__PURE__ */ jsx14(
3249
- Shield,
3250
- {
3251
- "aria-hidden": "true",
3252
- className: "mt-0.5 h-4 w-4 shrink-0 text-green-600"
3253
- }
3254
- ),
3255
- /* @__PURE__ */ jsx14("p", { className: "text-xs text-muted-foreground", children: "Sua chave de API \xE9 armazenada de forma segura e encriptada. Nunca \xE9 exposta no frontend." })
3256
- ] })
3257
- ] });
3258
- }
3259
-
3260
- // src/components/capabilities/wizard-steps/config-step.tsx
3261
- import { Loader2 as Loader27 } from "lucide-react";
3262
- import {
3263
- Label as Label5,
3264
- Select,
3265
- SelectContent,
3266
- SelectItem,
3267
- SelectTrigger,
3268
- SelectValue
3269
- } from "@greatapps/greatauth-ui/ui";
3270
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3271
- function ConfigStep({
3272
- integration,
3273
- options,
3274
- isLoading,
3275
- selectedValue,
3276
- onValueChange,
3277
- selectLabel,
3278
- selectPlaceholder
3279
- }) {
3280
- const label = selectLabel || getDefaultLabel(integration.slug);
3281
- const placeholder = selectPlaceholder || getDefaultPlaceholder(integration.slug);
3282
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3283
- /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3284
- /* @__PURE__ */ jsx15("h3", { className: "text-lg font-semibold", children: "Configura\xE7\xE3o" }),
3285
- /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: "Configure as op\xE7\xF5es espec\xEDficas da integra\xE7\xE3o." })
3286
- ] }),
3287
- isLoading ? /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-3 py-8", children: [
3288
- /* @__PURE__ */ jsx15(
3289
- Loader27,
3290
- {
3291
- "aria-hidden": "true",
3292
- className: "h-6 w-6 animate-spin text-muted-foreground"
3293
- }
3294
- ),
3295
- /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: "Carregando op\xE7\xF5es..." })
3296
- ] }) : options.length === 0 ? /* @__PURE__ */ jsx15("div", { className: "rounded-lg border border-dashed p-6 text-center", children: /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: "Nenhuma op\xE7\xE3o dispon\xEDvel. A configura\xE7\xE3o padr\xE3o ser\xE1 usada." }) }) : /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3297
- /* @__PURE__ */ jsx15(Label5, { htmlFor: "integration-config-select", children: label }),
3298
- /* @__PURE__ */ jsxs13(Select, { value: selectedValue, onValueChange, children: [
3299
- /* @__PURE__ */ jsx15(SelectTrigger, { id: "integration-config-select", children: /* @__PURE__ */ jsx15(SelectValue, { placeholder }) }),
3300
- /* @__PURE__ */ jsx15(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsxs13(SelectItem, { value: opt.id, children: [
3301
- /* @__PURE__ */ jsx15("span", { children: opt.label }),
3302
- opt.description && /* @__PURE__ */ jsxs13("span", { className: "ml-2 text-xs text-muted-foreground", children: [
3303
- "(",
3304
- opt.description,
3305
- ")"
3306
- ] })
3307
- ] }, opt.id)) })
3308
- ] })
3309
- ] })
3310
- ] });
3311
- }
3312
- function getDefaultLabel(slug) {
3313
- switch (slug) {
3314
- case "google_calendar":
3315
- return "Calend\xE1rio";
3316
- default:
3317
- return "Op\xE7\xE3o";
3318
- }
3319
- }
3320
- function getDefaultPlaceholder(slug) {
3321
- switch (slug) {
3322
- case "google_calendar":
3323
- return "Selecione o calend\xE1rio...";
3324
- default:
3325
- return "Selecione uma op\xE7\xE3o...";
3326
- }
3327
- }
3328
-
3329
- // src/components/capabilities/wizard-steps/confirm-step.tsx
3330
- import { CheckCircle2 as CheckCircle22 } from "lucide-react";
3331
- import { Label as Label6 } from "@greatapps/greatauth-ui/ui";
3332
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3333
- function ConfirmStep({
3334
- integration,
3335
- oauthResult,
3336
- selectedConfigOption,
3337
- enableOnComplete,
3338
- onEnableChange
3339
- }) {
3340
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-6", children: [
3341
- /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
3342
- /* @__PURE__ */ jsx16("h3", { className: "text-lg font-semibold", children: "Confirma\xE7\xE3o" }),
3343
- /* @__PURE__ */ jsx16("p", { className: "text-sm text-muted-foreground", children: "Revise as configura\xE7\xF5es antes de concluir." })
3344
- ] }),
3345
- /* @__PURE__ */ jsxs14("div", { className: "space-y-3 rounded-lg border p-4", children: [
3346
- /* @__PURE__ */ jsx16(SummaryRow, { label: "Integra\xE7\xE3o", value: integration.name }),
3347
- oauthResult?.email && /* @__PURE__ */ jsx16(SummaryRow, { label: "Conta conectada", value: oauthResult.email }),
3348
- selectedConfigOption && /* @__PURE__ */ jsx16(
3349
- SummaryRow,
3350
- {
3351
- label: getConfigLabel(integration.slug),
3352
- value: selectedConfigOption.label
3353
- }
3354
- ),
3355
- /* @__PURE__ */ jsx16(
3356
- SummaryRow,
3357
- {
3358
- label: "Tipo de autentica\xE7\xE3o",
3359
- value: integration.authType === "oauth2" ? "OAuth 2.0" : "API Key"
3360
- }
3361
- )
3362
- ] }),
3363
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between rounded-lg border p-4", children: [
3364
- /* @__PURE__ */ jsxs14("div", { className: "space-y-0.5", children: [
3365
- /* @__PURE__ */ jsx16(Label6, { htmlFor: "enable-on-complete", className: "text-sm font-medium", children: "Ativar imediatamente" }),
3366
- /* @__PURE__ */ jsx16("p", { className: "text-xs text-muted-foreground", children: "A integra\xE7\xE3o ficar\xE1 ativa assim que concluir o assistente." })
3367
- ] }),
3368
- /* @__PURE__ */ jsx16(
3369
- "button",
3370
- {
3371
- id: "enable-on-complete",
3372
- role: "switch",
3373
- type: "button",
3374
- "aria-checked": enableOnComplete,
3375
- onClick: () => onEnableChange(!enableOnComplete),
3376
- className: `
3377
- relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent
3378
- transition-colors duration-200 ease-in-out focus-visible:outline-none focus-visible:ring-2
3379
- focus-visible:ring-ring focus-visible:ring-offset-2
3380
- ${enableOnComplete ? "bg-primary" : "bg-muted"}
3381
- `,
3382
- children: /* @__PURE__ */ jsx16(
3383
- "span",
3384
- {
3385
- "aria-hidden": "true",
3386
- className: `
3387
- pointer-events-none inline-block h-5 w-5 transform rounded-full bg-background shadow-lg
3388
- ring-0 transition duration-200 ease-in-out
3389
- ${enableOnComplete ? "translate-x-5" : "translate-x-0"}
3390
- `
3391
- }
3392
- )
3393
- }
3394
- )
3395
- ] }),
3396
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 rounded-md bg-green-50 p-3 dark:bg-green-950/20", children: [
3397
- /* @__PURE__ */ jsx16(
3398
- CheckCircle22,
3399
- {
3400
- "aria-hidden": "true",
3401
- className: "h-4 w-4 shrink-0 text-green-600"
3402
- }
3403
- ),
3404
- /* @__PURE__ */ jsx16("p", { className: "text-xs text-green-700 dark:text-green-400", children: 'Tudo pronto! Clique em "Concluir" para finalizar a configura\xE7\xE3o.' })
3405
- ] })
3406
- ] });
3407
- }
3408
- function SummaryRow({ label, value }) {
3409
- return /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between text-sm", children: [
3410
- /* @__PURE__ */ jsx16("span", { className: "text-muted-foreground", children: label }),
3411
- /* @__PURE__ */ jsx16("span", { className: "font-medium", children: value })
3412
- ] });
3413
- }
3414
- function getConfigLabel(slug) {
3415
- switch (slug) {
3416
- case "google_calendar":
3417
- return "Calend\xE1rio";
3418
- default:
3419
- return "Configura\xE7\xE3o";
3420
- }
3421
- }
3422
-
3423
- // src/components/capabilities/integration-wizard.tsx
3424
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
3425
- var STEPS = ["info", "credentials", "config", "confirm"];
3426
- var STEP_LABELS = {
3427
- info: "Informa\xE7\xE3o",
3428
- credentials: "Credenciais",
3429
- config: "Configura\xE7\xE3o",
3430
- confirm: "Confirma\xE7\xE3o"
3431
- };
3432
- function IntegrationWizard({
3433
- open,
3434
- onOpenChange,
3435
- integration,
3436
- meta,
3437
- agentId: _agentId,
3438
- config,
3439
- onComplete,
3440
- gagentsApiUrl,
3441
- existingCredentialId,
3442
- loadConfigOptions,
3443
- existingConfigValue
3444
- }) {
3445
- const isReconnect = !!existingCredentialId;
3446
- const [currentStep, setCurrentStep] = useState9("info");
3447
- const currentIndex = STEPS.indexOf(currentStep);
3448
- const [oauthStatus, setOauthStatus] = useState9("idle");
3449
- const [oauthResult, setOauthResult] = useState9(null);
3450
- const popupRef = useRef2(null);
3451
- const popupPollRef = useRef2(null);
3452
- const [apiKey, setApiKey] = useState9("");
3453
- const [configOptions, setConfigOptions] = useState9([]);
3454
- const [configLoading, setConfigLoading] = useState9(false);
3455
- const [selectedConfigValue, setSelectedConfigValue] = useState9("");
3456
- const [enableOnComplete, setEnableOnComplete] = useState9(true);
3457
- const [isSubmitting, setIsSubmitting] = useState9(false);
3458
- useEffect5(() => {
3459
- return () => {
3460
- if (popupPollRef.current) {
3461
- clearInterval(popupPollRef.current);
3462
- }
3463
- };
3464
- }, []);
3465
- useEffect5(() => {
3466
- if (open) {
3467
- setCurrentStep("info");
3468
- setOauthStatus("idle");
3469
- setOauthResult(null);
3470
- setApiKey("");
3471
- setConfigOptions([]);
3472
- setConfigLoading(false);
3473
- setSelectedConfigValue(existingConfigValue ?? "");
3474
- setEnableOnComplete(true);
3475
- setIsSubmitting(false);
3476
- } else {
3477
- if (popupRef.current && !popupRef.current.closed) {
3478
- popupRef.current.close();
3479
- }
3480
- if (popupPollRef.current) {
3481
- clearInterval(popupPollRef.current);
3482
- popupPollRef.current = null;
3483
- }
3484
- }
3485
- }, [open]);
3486
- const handleOAuthMessage = useCallback5(
3487
- (event) => {
3488
- try {
3489
- if (event.origin !== new URL(gagentsApiUrl).origin) return;
3490
- } catch {
3491
- return;
3492
- }
3493
- if (!event.data || typeof event.data !== "object") return;
3494
- const msg = event.data;
3495
- if (msg.type !== "oauth-callback") return;
3496
- if (msg.success) {
3497
- setOauthStatus("success");
3498
- setOauthResult({
3499
- success: true,
3500
- email: msg.email,
3501
- credentialId: msg.credentialId
3502
- });
3503
- const credId = msg.credentialId || existingCredentialId;
3504
- if (credId && loadConfigOptions && meta.hasConfigStep) {
3505
- setConfigLoading(true);
3506
- loadConfigOptions(credId).then((opts) => {
3507
- setConfigOptions(opts);
3508
- if (opts.length === 1) {
3509
- setSelectedConfigValue(opts[0].id);
3510
- }
3511
- }).catch(() => setConfigOptions([])).finally(() => setConfigLoading(false));
3512
- }
3513
- setTimeout(() => {
3514
- setCurrentStep(meta.hasConfigStep ? "config" : "confirm");
3515
- }, 1200);
3516
- } else {
3517
- setOauthStatus("error");
3518
- setOauthResult({
3519
- success: false,
3520
- error: msg.error || "Falha na autoriza\xE7\xE3o"
3521
- });
3522
- }
3523
- },
3524
- [gagentsApiUrl, existingCredentialId, meta.hasConfigStep, loadConfigOptions]
3002
+ function AgentToolsList({ agent, config }) {
3003
+ const { data: agentToolsData, isLoading } = useAgentTools(config, agent.id);
3004
+ const { data: allToolsData } = useTools(config);
3005
+ const addMutation = useAddAgentTool(config);
3006
+ const removeMutation = useRemoveAgentTool(config);
3007
+ const updateMutation = useUpdateAgentTool(config);
3008
+ const [removeTarget, setRemoveTarget] = useState9(null);
3009
+ const [addOpen, setAddOpen] = useState9(false);
3010
+ const [search, setSearch] = useState9("");
3011
+ const [configTarget, setConfigTarget] = useState9(null);
3012
+ const [configInstructions, setConfigInstructions] = useState9("");
3013
+ const [configCredentialId, setConfigCredentialId] = useState9("");
3014
+ const { data: credentialsData } = useToolCredentials(config);
3015
+ const allCredentials = credentialsData?.data || [];
3016
+ const agentTools = agentToolsData?.data || [];
3017
+ const allTools = (allToolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
3018
+ const assignedToolIds = new Set(agentTools.map((at) => at.id_tool));
3019
+ const visibleAgentTools = agentTools.filter((at) => {
3020
+ const tool = allTools.find((t) => t.id === at.id_tool);
3021
+ return !tool || !tool.slug?.startsWith("gclinic_");
3022
+ });
3023
+ const availableTools = allTools.filter((t) => !assignedToolIds.has(t.id));
3024
+ const filteredAvailable = availableTools.filter(
3025
+ (t) => t.name.toLowerCase().includes(search.toLowerCase())
3525
3026
  );
3526
- useEffect5(() => {
3527
- if (!open) return;
3528
- window.addEventListener("message", handleOAuthMessage);
3529
- return () => window.removeEventListener("message", handleOAuthMessage);
3530
- }, [open, handleOAuthMessage]);
3531
- async function startOAuth() {
3532
- const { language = "pt-br", idWl = 1, accountId, token } = config;
3533
- setOauthStatus("waiting");
3027
+ function getToolInfo(idTool) {
3028
+ return allTools.find((t) => t.id === idTool);
3029
+ }
3030
+ async function handleToggleEnabled(agentTool, checked) {
3534
3031
  try {
3535
- let authorizeUrl = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${accountId}/oauth/authorize/${integration.slug}`;
3536
- if (existingCredentialId) {
3537
- authorizeUrl += `?credential_id=${existingCredentialId}`;
3538
- }
3539
- const response = await fetch(authorizeUrl, {
3540
- headers: { Authorization: `Bearer ${token}` }
3032
+ await updateMutation.mutateAsync({
3033
+ idAgent: agent.id,
3034
+ id: agentTool.id,
3035
+ body: { enabled: checked }
3541
3036
  });
3542
- const result = await response.json();
3543
- if (result.status !== 1 || !result.data?.auth_url) {
3544
- setOauthStatus("error");
3545
- setOauthResult({
3546
- success: false,
3547
- error: result.message || "Erro ao obter URL de autoriza\xE7\xE3o"
3548
- });
3549
- return;
3550
- }
3551
- const popup = window.open(
3552
- result.data.auth_url,
3553
- "oauth-popup",
3554
- "width=500,height=600,scrollbars=yes,resizable=yes"
3555
- );
3556
- popupRef.current = popup;
3557
- if (popup) {
3558
- if (popupPollRef.current) {
3559
- clearInterval(popupPollRef.current);
3560
- }
3561
- popupPollRef.current = setInterval(() => {
3562
- if (popup.closed) {
3563
- if (popupPollRef.current) {
3564
- clearInterval(popupPollRef.current);
3565
- popupPollRef.current = null;
3566
- }
3567
- setOauthStatus(
3568
- (prev) => prev === "waiting" ? "error" : prev
3569
- );
3570
- setOauthResult(
3571
- (prev) => prev === null ? { success: false, error: "Janela fechada antes de concluir" } : prev
3572
- );
3573
- }
3574
- }, 500);
3575
- }
3037
+ toast7.success(checked ? "Ferramenta ativada" : "Ferramenta desativada");
3576
3038
  } catch (err) {
3577
- setOauthStatus("error");
3578
- setOauthResult({
3579
- success: false,
3580
- error: "Erro de rede ao obter URL de autoriza\xE7\xE3o"
3581
- });
3039
+ toast7.error(
3040
+ err instanceof Error ? err.message : "Erro ao alterar estado da ferramenta"
3041
+ );
3582
3042
  }
3583
3043
  }
3584
- function canAdvance() {
3585
- switch (currentStep) {
3586
- case "info":
3587
- return true;
3588
- case "credentials":
3589
- if (integration.authType === "oauth2") {
3590
- return oauthStatus === "success";
3591
- }
3592
- return apiKey.trim().length > 0;
3593
- case "config":
3594
- return true;
3595
- case "confirm":
3596
- return true;
3597
- default:
3598
- return false;
3044
+ async function handleAdd(tool) {
3045
+ try {
3046
+ await addMutation.mutateAsync({
3047
+ idAgent: agent.id,
3048
+ body: { id_tool: tool.id }
3049
+ });
3050
+ toast7.success("Ferramenta adicionada");
3051
+ setAddOpen(false);
3052
+ setSearch("");
3053
+ } catch (err) {
3054
+ toast7.error(
3055
+ err instanceof Error ? err.message : "Erro ao adicionar ferramenta"
3056
+ );
3599
3057
  }
3600
3058
  }
3601
- function goNext() {
3602
- if (!canAdvance()) return;
3603
- if (currentStep === "credentials" && !meta.hasConfigStep) {
3604
- setCurrentStep("confirm");
3605
- return;
3606
- }
3607
- const nextIndex = currentIndex + 1;
3608
- if (nextIndex < STEPS.length) {
3609
- setCurrentStep(STEPS[nextIndex]);
3059
+ async function handleRemove() {
3060
+ if (!removeTarget) return;
3061
+ try {
3062
+ await removeMutation.mutateAsync({
3063
+ idAgent: agent.id,
3064
+ id: removeTarget.id
3065
+ });
3066
+ toast7.success("Ferramenta removida");
3067
+ } catch (err) {
3068
+ toast7.error(
3069
+ err instanceof Error ? err.message : "Erro ao remover ferramenta"
3070
+ );
3071
+ } finally {
3072
+ setRemoveTarget(null);
3610
3073
  }
3611
3074
  }
3612
- function goPrev() {
3613
- if (currentStep === "confirm" && !meta.hasConfigStep) {
3614
- setCurrentStep("credentials");
3615
- return;
3616
- }
3617
- const prevIndex = currentIndex - 1;
3618
- if (prevIndex >= 0) {
3619
- setCurrentStep(STEPS[prevIndex]);
3620
- }
3075
+ function openConfig(agentTool) {
3076
+ setConfigTarget(agentTool);
3077
+ setConfigInstructions(agentTool.custom_instructions || "");
3078
+ setConfigCredentialId(agentTool.id_tool_credential ? String(agentTool.id_tool_credential) : "");
3621
3079
  }
3622
- async function handleComplete() {
3623
- setIsSubmitting(true);
3080
+ async function handleSaveConfig() {
3081
+ if (!configTarget) return;
3624
3082
  try {
3625
- onComplete();
3626
- onOpenChange(false);
3627
- toast7.success(
3628
- `${integration.name} ${isReconnect ? "reconectado" : "configurado"} com sucesso!`
3083
+ const newCredentialId = configCredentialId ? parseInt(configCredentialId, 10) : null;
3084
+ await updateMutation.mutateAsync({
3085
+ idAgent: agent.id,
3086
+ id: configTarget.id,
3087
+ body: {
3088
+ custom_instructions: configInstructions.trim() || null,
3089
+ id_tool_credential: newCredentialId
3090
+ }
3091
+ });
3092
+ toast7.success("Configura\xE7\xE3o atualizada");
3093
+ setConfigTarget(null);
3094
+ } catch (err) {
3095
+ toast7.error(
3096
+ err instanceof Error ? err.message : "Erro ao atualizar configura\xE7\xE3o"
3629
3097
  );
3630
- } catch {
3631
- toast7.error("Erro ao finalizar configura\xE7\xE3o");
3632
- } finally {
3633
- setIsSubmitting(false);
3634
3098
  }
3635
3099
  }
3636
- const selectedConfigOption = configOptions.find((o) => o.id === selectedConfigValue) || null;
3637
- const isLastStep = currentStep === "confirm";
3638
- const effectiveSteps = meta.hasConfigStep ? STEPS : STEPS.filter((s) => s !== "config");
3639
- return /* @__PURE__ */ jsx17(Dialog4, { open, onOpenChange, children: /* @__PURE__ */ jsxs15(DialogContent4, { className: "sm:max-w-lg", children: [
3640
- /* @__PURE__ */ jsx17(DialogHeader4, { children: /* @__PURE__ */ jsx17(DialogTitle4, { children: integration.name }) }),
3641
- /* @__PURE__ */ jsx17(StepIndicator, { steps: effectiveSteps, currentStep }),
3642
- /* @__PURE__ */ jsxs15("div", { className: "min-h-[280px] py-2", children: [
3643
- currentStep === "info" && /* @__PURE__ */ jsx17(
3644
- InfoStep,
3645
- {
3646
- integration,
3647
- meta
3648
- }
3649
- ),
3650
- currentStep === "credentials" && /* @__PURE__ */ jsx17(
3651
- CredentialsStep,
3652
- {
3653
- integration,
3654
- meta,
3655
- oauthStatus,
3656
- oauthResult,
3657
- apiKey,
3658
- onApiKeyChange: setApiKey,
3659
- onStartOAuth: startOAuth,
3660
- isReconnect
3661
- }
3662
- ),
3663
- currentStep === "config" && /* @__PURE__ */ jsx17(
3664
- ConfigStep,
3665
- {
3666
- integration,
3667
- options: configOptions,
3668
- isLoading: configLoading,
3669
- selectedValue: selectedConfigValue,
3670
- onValueChange: setSelectedConfigValue
3671
- }
3672
- ),
3673
- currentStep === "confirm" && /* @__PURE__ */ jsx17(
3674
- ConfirmStep,
3675
- {
3676
- integration,
3677
- oauthResult,
3678
- selectedConfigOption,
3679
- enableOnComplete,
3680
- onEnableChange: setEnableOnComplete
3681
- }
3682
- )
3100
+ if (isLoading) {
3101
+ return /* @__PURE__ */ jsx13("div", { className: "space-y-3 p-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx13(Skeleton6, { className: "h-14 w-full" }, i)) });
3102
+ }
3103
+ return /* @__PURE__ */ jsxs11("div", { className: "space-y-4 p-4", children: [
3104
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
3105
+ /* @__PURE__ */ jsxs11("h3", { className: "text-sm font-medium text-muted-foreground", children: [
3106
+ visibleAgentTools.length,
3107
+ " ferramenta",
3108
+ visibleAgentTools.length !== 1 ? "s" : "",
3109
+ " associada",
3110
+ visibleAgentTools.length !== 1 ? "s" : ""
3111
+ ] }),
3112
+ /* @__PURE__ */ jsxs11(Popover, { open: addOpen, onOpenChange: setAddOpen, children: [
3113
+ /* @__PURE__ */ jsx13(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(Button8, { size: "sm", disabled: availableTools.length === 0, children: [
3114
+ /* @__PURE__ */ jsx13(Plus2, { className: "mr-2 h-4 w-4" }),
3115
+ "Adicionar Ferramenta"
3116
+ ] }) }),
3117
+ /* @__PURE__ */ jsxs11(PopoverContent, { className: "w-72 p-0", align: "end", children: [
3118
+ /* @__PURE__ */ jsx13("div", { className: "p-2", children: /* @__PURE__ */ jsx13(
3119
+ Input6,
3120
+ {
3121
+ placeholder: "Buscar ferramenta\\u2026",
3122
+ "aria-label": "Buscar ferramenta",
3123
+ name: "search",
3124
+ value: search,
3125
+ onChange: (e) => setSearch(e.target.value),
3126
+ className: "h-8"
3127
+ }
3128
+ ) }),
3129
+ /* @__PURE__ */ jsx13("div", { className: "max-h-48 overflow-y-auto", children: filteredAvailable.length === 0 ? /* @__PURE__ */ jsx13("p", { className: "p-3 text-center text-sm text-muted-foreground", children: "Nenhuma ferramenta dispon\xEDvel" }) : filteredAvailable.map((tool) => /* @__PURE__ */ jsxs11(
3130
+ "button",
3131
+ {
3132
+ type: "button",
3133
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-accent",
3134
+ onClick: () => handleAdd(tool),
3135
+ disabled: addMutation.isPending,
3136
+ children: [
3137
+ /* @__PURE__ */ jsx13(Wrench, { className: "h-4 w-4 text-muted-foreground" }),
3138
+ /* @__PURE__ */ jsx13("span", { className: "flex-1 font-medium", children: tool.name }),
3139
+ /* @__PURE__ */ jsx13(Badge6, { variant: "secondary", className: "text-xs", children: tool.type })
3140
+ ]
3141
+ },
3142
+ tool.id
3143
+ )) })
3144
+ ] })
3145
+ ] })
3683
3146
  ] }),
3684
- /* @__PURE__ */ jsxs15(DialogFooter4, { className: "flex-row justify-between sm:justify-between", children: [
3685
- /* @__PURE__ */ jsx17("div", { children: currentStep === "info" ? /* @__PURE__ */ jsx17(
3686
- Button10,
3687
- {
3688
- type: "button",
3689
- variant: "outline",
3690
- onClick: () => onOpenChange(false),
3691
- children: "Cancelar"
3692
- }
3693
- ) : /* @__PURE__ */ jsxs15(
3694
- Button10,
3695
- {
3696
- type: "button",
3697
- variant: "outline",
3698
- onClick: goPrev,
3699
- className: "gap-1",
3700
- children: [
3701
- /* @__PURE__ */ jsx17(ChevronLeft, { "aria-hidden": "true", className: "h-4 w-4" }),
3702
- "Voltar"
3703
- ]
3704
- }
3705
- ) }),
3706
- /* @__PURE__ */ jsx17("div", { children: isLastStep ? /* @__PURE__ */ jsxs15(
3707
- Button10,
3147
+ visibleAgentTools.length === 0 ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
3148
+ /* @__PURE__ */ jsx13(Wrench, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
3149
+ /* @__PURE__ */ jsx13("p", { className: "text-sm text-muted-foreground", children: "Nenhuma ferramenta associada. Clique em 'Adicionar Ferramenta' para come\xE7ar." })
3150
+ ] }) : /* @__PURE__ */ jsx13("div", { className: "space-y-2", children: visibleAgentTools.map((agentTool) => {
3151
+ const tool = getToolInfo(agentTool.id_tool);
3152
+ return /* @__PURE__ */ jsxs11(
3153
+ "div",
3708
3154
  {
3709
- type: "button",
3710
- onClick: handleComplete,
3711
- disabled: isSubmitting,
3712
- className: "gap-1",
3155
+ className: "flex items-center gap-3 rounded-lg border bg-card p-3",
3713
3156
  children: [
3714
- isSubmitting ? /* @__PURE__ */ jsx17(
3715
- Loader28,
3157
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [
3158
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
3159
+ /* @__PURE__ */ jsx13("span", { className: "truncate font-medium", children: tool?.name || `Ferramenta #${agentTool.id_tool}` }),
3160
+ tool?.type && /* @__PURE__ */ jsx13(Badge6, { variant: "secondary", className: "shrink-0 text-xs", children: tool.type })
3161
+ ] }),
3162
+ agentTool.custom_instructions && /* @__PURE__ */ jsx13("p", { className: "truncate text-xs text-muted-foreground", children: agentTool.custom_instructions })
3163
+ ] }),
3164
+ /* @__PURE__ */ jsx13(
3165
+ Switch6,
3716
3166
  {
3717
- "aria-hidden": "true",
3718
- className: "h-4 w-4 animate-spin"
3167
+ "aria-label": "Ativar/Desativar",
3168
+ checked: agentTool.enabled,
3169
+ onCheckedChange: (checked) => handleToggleEnabled(agentTool, checked),
3170
+ disabled: updateMutation.isPending
3719
3171
  }
3720
- ) : /* @__PURE__ */ jsx17(Check2, { "aria-hidden": "true", className: "h-4 w-4" }),
3721
- "Concluir"
3722
- ]
3723
- }
3724
- ) : /* @__PURE__ */ jsxs15(
3725
- Button10,
3726
- {
3727
- type: "button",
3728
- onClick: goNext,
3729
- disabled: !canAdvance(),
3730
- className: "gap-1",
3731
- children: [
3732
- "Continuar",
3733
- /* @__PURE__ */ jsx17(ChevronRight, { "aria-hidden": "true", className: "h-4 w-4" })
3172
+ ),
3173
+ /* @__PURE__ */ jsx13(
3174
+ Button8,
3175
+ {
3176
+ variant: "ghost",
3177
+ size: "icon",
3178
+ "aria-label": "Configurar",
3179
+ className: "shrink-0 text-muted-foreground hover:text-foreground",
3180
+ onClick: () => openConfig(agentTool),
3181
+ title: "Configurar instru\xE7\xF5es",
3182
+ children: /* @__PURE__ */ jsx13(Settings2, { className: "h-4 w-4" })
3183
+ }
3184
+ ),
3185
+ /* @__PURE__ */ jsx13(
3186
+ Button8,
3187
+ {
3188
+ variant: "ghost",
3189
+ size: "icon",
3190
+ "aria-label": "Remover",
3191
+ className: "shrink-0 text-muted-foreground hover:text-destructive",
3192
+ onClick: () => setRemoveTarget(agentTool),
3193
+ children: /* @__PURE__ */ jsx13(Trash23, { className: "h-4 w-4" })
3194
+ }
3195
+ )
3734
3196
  ]
3735
- }
3736
- ) })
3737
- ] })
3738
- ] }) });
3197
+ },
3198
+ agentTool.id
3199
+ );
3200
+ }) }),
3201
+ /* @__PURE__ */ jsx13(
3202
+ Dialog4,
3203
+ {
3204
+ open: !!configTarget,
3205
+ onOpenChange: (open) => !open && setConfigTarget(null),
3206
+ children: /* @__PURE__ */ jsxs11(DialogContent4, { className: "sm:max-w-lg", children: [
3207
+ /* @__PURE__ */ jsx13(DialogHeader4, { children: /* @__PURE__ */ jsx13(DialogTitle4, { children: "Instru\xE7\xF5es da Ferramenta" }) }),
3208
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-4", children: [
3209
+ configTarget && getToolInfo(configTarget.id_tool)?.type !== "none" && /* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
3210
+ /* @__PURE__ */ jsx13(Label4, { htmlFor: "tool-credential", children: "Credencial" }),
3211
+ /* @__PURE__ */ jsxs11(
3212
+ Select,
3213
+ {
3214
+ value: configCredentialId || void 0,
3215
+ onValueChange: (val) => setConfigCredentialId(val === "__none__" ? "" : val),
3216
+ children: [
3217
+ /* @__PURE__ */ jsx13(SelectTrigger, { id: "tool-credential", children: /* @__PURE__ */ jsx13(SelectValue, { placeholder: "Selecione uma credencial (opcional)" }) }),
3218
+ /* @__PURE__ */ jsxs11(SelectContent, { children: [
3219
+ /* @__PURE__ */ jsx13(SelectItem, { value: "__none__", children: "Nenhuma (autom\xE1tico)" }),
3220
+ allCredentials.filter((c) => configTarget && c.id_tool === configTarget.id_tool && c.status === "active").map((c) => /* @__PURE__ */ jsx13(SelectItem, { value: String(c.id), children: c.label || `Credencial #${c.id}` }, c.id))
3221
+ ] })
3222
+ ]
3223
+ }
3224
+ ),
3225
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground", children: "Vincule uma credencial espec\xEDfica a esta ferramenta neste agente." })
3226
+ ] }),
3227
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
3228
+ /* @__PURE__ */ jsx13(Label4, { htmlFor: "tool-instructions", children: "Instru\xE7\xF5es Personalizadas" }),
3229
+ /* @__PURE__ */ jsx13(
3230
+ Textarea2,
3231
+ {
3232
+ id: "tool-instructions",
3233
+ name: "instructions",
3234
+ value: configInstructions,
3235
+ onChange: (e) => setConfigInstructions(e.target.value),
3236
+ placeholder: "Instru\\u00e7\\u00f5es sobre como e quando o agente deve usar esta ferramenta\\u2026",
3237
+ rows: 6
3238
+ }
3239
+ ),
3240
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground", children: "Este texto \xE9 adicionado ao prompt do agente para orientar o uso da ferramenta." })
3241
+ ] })
3242
+ ] }),
3243
+ /* @__PURE__ */ jsxs11(DialogFooter4, { children: [
3244
+ /* @__PURE__ */ jsx13(
3245
+ Button8,
3246
+ {
3247
+ variant: "outline",
3248
+ onClick: () => setConfigTarget(null),
3249
+ children: "Cancelar"
3250
+ }
3251
+ ),
3252
+ /* @__PURE__ */ jsx13(
3253
+ Button8,
3254
+ {
3255
+ onClick: handleSaveConfig,
3256
+ disabled: updateMutation.isPending,
3257
+ children: "Salvar"
3258
+ }
3259
+ )
3260
+ ] })
3261
+ ] })
3262
+ }
3263
+ ),
3264
+ /* @__PURE__ */ jsx13(
3265
+ AlertDialog3,
3266
+ {
3267
+ open: !!removeTarget,
3268
+ onOpenChange: (open) => !open && setRemoveTarget(null),
3269
+ children: /* @__PURE__ */ jsxs11(AlertDialogContent3, { children: [
3270
+ /* @__PURE__ */ jsxs11(AlertDialogHeader3, { children: [
3271
+ /* @__PURE__ */ jsx13(AlertDialogTitle3, { children: "Remover ferramenta?" }),
3272
+ /* @__PURE__ */ jsx13(AlertDialogDescription3, { children: "A ferramenta ser\xE1 desassociada deste agente." })
3273
+ ] }),
3274
+ /* @__PURE__ */ jsxs11(AlertDialogFooter3, { children: [
3275
+ /* @__PURE__ */ jsx13(AlertDialogCancel3, { children: "Cancelar" }),
3276
+ /* @__PURE__ */ jsx13(
3277
+ AlertDialogAction3,
3278
+ {
3279
+ onClick: handleRemove,
3280
+ disabled: removeMutation.isPending,
3281
+ children: "Remover"
3282
+ }
3283
+ )
3284
+ ] })
3285
+ ] })
3286
+ }
3287
+ )
3288
+ ] });
3739
3289
  }
3740
- function StepIndicator({
3741
- steps,
3742
- currentStep
3743
- }) {
3744
- const currentIndex = steps.indexOf(currentStep);
3745
- return /* @__PURE__ */ jsx17(
3746
- "div",
3290
+
3291
+ // src/components/tools/tools-table.tsx
3292
+ import { useMemo as useMemo6, useState as useState10 } from "react";
3293
+ import { DataTable as DataTable2 } from "@greatapps/greatauth-ui";
3294
+ import {
3295
+ Input as Input7,
3296
+ Badge as Badge7,
3297
+ Tooltip as Tooltip3,
3298
+ TooltipTrigger as TooltipTrigger3,
3299
+ TooltipContent as TooltipContent3,
3300
+ AlertDialog as AlertDialog4,
3301
+ AlertDialogAction as AlertDialogAction4,
3302
+ AlertDialogCancel as AlertDialogCancel4,
3303
+ AlertDialogContent as AlertDialogContent4,
3304
+ AlertDialogDescription as AlertDialogDescription4,
3305
+ AlertDialogFooter as AlertDialogFooter4,
3306
+ AlertDialogHeader as AlertDialogHeader4,
3307
+ AlertDialogTitle as AlertDialogTitle4,
3308
+ Button as Button9
3309
+ } from "@greatapps/greatauth-ui/ui";
3310
+ import { Pencil as Pencil3, Trash2 as Trash24, Search as Search2 } from "lucide-react";
3311
+ import { format as format2 } from "date-fns";
3312
+ import { ptBR as ptBR2 } from "date-fns/locale";
3313
+ import { toast as toast8 } from "sonner";
3314
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3315
+ function useColumns2(onEdit, onDelete) {
3316
+ return [
3317
+ {
3318
+ accessorKey: "name",
3319
+ header: "Nome",
3320
+ cell: ({ row }) => /* @__PURE__ */ jsx14("span", { className: "font-medium", children: row.original.name }),
3321
+ sortingFn: (rowA, rowB) => rowA.original.name.toLowerCase().localeCompare(rowB.original.name.toLowerCase())
3322
+ },
3323
+ {
3324
+ accessorKey: "slug",
3325
+ header: "Slug",
3326
+ cell: ({ row }) => /* @__PURE__ */ jsx14("span", { className: "text-muted-foreground text-sm font-mono", children: row.original.slug || "\u2014" })
3327
+ },
3328
+ {
3329
+ accessorKey: "type",
3330
+ header: "Tipo",
3331
+ cell: ({ row }) => /* @__PURE__ */ jsx14(Badge7, { variant: "secondary", children: row.original.type })
3332
+ },
3333
+ {
3334
+ accessorKey: "description",
3335
+ header: "Descri\xE7\xE3o",
3336
+ cell: ({ row }) => {
3337
+ const desc = row.original.description;
3338
+ if (!desc) return /* @__PURE__ */ jsx14("span", { className: "text-muted-foreground text-sm", children: "\u2014" });
3339
+ return /* @__PURE__ */ jsx14("span", { className: "text-muted-foreground text-sm", children: desc.length > 50 ? `${desc.slice(0, 50)}\u2026` : desc });
3340
+ }
3341
+ },
3342
+ {
3343
+ accessorKey: "datetime_add",
3344
+ header: "Criado em",
3345
+ cell: ({ row }) => /* @__PURE__ */ jsx14("span", { className: "text-muted-foreground text-sm", children: format2(new Date(row.original.datetime_add), "dd/MM/yyyy", {
3346
+ locale: ptBR2
3347
+ }) })
3348
+ },
3747
3349
  {
3748
- className: "flex items-center justify-center gap-1 py-2",
3749
- role: "list",
3750
- "aria-label": "Passos do assistente",
3751
- children: steps.map((step, i) => {
3752
- const isCompleted = i < currentIndex;
3753
- const isCurrent = step === currentStep;
3754
- return /* @__PURE__ */ jsxs15("div", { className: "flex items-center", role: "listitem", children: [
3755
- /* @__PURE__ */ jsx17(
3756
- "div",
3757
- {
3758
- className: `
3759
- flex h-7 w-7 items-center justify-center rounded-full text-xs font-medium
3760
- transition-colors duration-200
3761
- ${isCurrent ? "bg-primary text-primary-foreground" : isCompleted ? "bg-green-600 text-white" : "bg-muted text-muted-foreground"}
3762
- `,
3763
- "aria-current": isCurrent ? "step" : void 0,
3764
- "aria-label": `${STEP_LABELS[step]}${isCompleted ? " (conclu\xEDdo)" : isCurrent ? " (atual)" : ""}`,
3765
- children: isCompleted ? /* @__PURE__ */ jsx17(Check2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : i + 1
3766
- }
3767
- ),
3768
- /* @__PURE__ */ jsx17(
3769
- "span",
3350
+ id: "actions",
3351
+ size: 80,
3352
+ enableSorting: false,
3353
+ cell: ({ row }) => /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
3354
+ /* @__PURE__ */ jsxs12(Tooltip3, { children: [
3355
+ /* @__PURE__ */ jsx14(TooltipTrigger3, { asChild: true, children: /* @__PURE__ */ jsx14(
3356
+ Button9,
3770
3357
  {
3771
- className: `
3772
- ml-1.5 hidden text-xs sm:inline
3773
- ${isCurrent ? "font-medium text-foreground" : "text-muted-foreground"}
3774
- `,
3775
- children: STEP_LABELS[step]
3358
+ variant: "ghost",
3359
+ size: "icon",
3360
+ className: "h-8 w-8",
3361
+ "aria-label": "Editar",
3362
+ onClick: () => onEdit(row.original),
3363
+ children: /* @__PURE__ */ jsx14(Pencil3, { className: "h-4 w-4" })
3776
3364
  }
3777
- ),
3778
- i < steps.length - 1 && /* @__PURE__ */ jsx17(
3779
- "div",
3365
+ ) }),
3366
+ /* @__PURE__ */ jsx14(TooltipContent3, { children: "Editar" })
3367
+ ] }),
3368
+ /* @__PURE__ */ jsxs12(Tooltip3, { children: [
3369
+ /* @__PURE__ */ jsx14(TooltipTrigger3, { asChild: true, children: /* @__PURE__ */ jsx14(
3370
+ Button9,
3780
3371
  {
3781
- className: `
3782
- mx-2 h-px w-6
3783
- ${i < currentIndex ? "bg-green-600" : "bg-border"}
3784
- `
3372
+ variant: "ghost",
3373
+ size: "icon",
3374
+ className: "h-8 w-8 text-destructive hover:text-destructive",
3375
+ "aria-label": "Excluir",
3376
+ onClick: () => onDelete(row.original.id),
3377
+ children: /* @__PURE__ */ jsx14(Trash24, { className: "h-4 w-4" })
3785
3378
  }
3786
- )
3787
- ] }, step);
3788
- })
3379
+ ) }),
3380
+ /* @__PURE__ */ jsx14(TooltipContent3, { children: "Excluir" })
3381
+ ] })
3382
+ ] })
3789
3383
  }
3790
- );
3384
+ ];
3791
3385
  }
3792
-
3793
- // src/components/agents/agent-tabs.tsx
3794
- import {
3795
- Tabs,
3796
- TabsList,
3797
- TabsTrigger,
3798
- TabsContent
3799
- } from "@greatapps/greatauth-ui/ui";
3800
- import { Target as Target2, FileText as FileText2, MessageCircle as MessageCircle2, Blocks, Plug as Plug3 } from "lucide-react";
3801
- import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
3802
- function AgentTabs({
3803
- agent,
3804
- config,
3805
- renderChatLink,
3806
- gagentsApiUrl,
3807
- resolveWizardMeta,
3808
- loadConfigOptions,
3809
- onWizardComplete
3810
- }) {
3811
- const apiUrl = gagentsApiUrl || config.baseUrl;
3812
- const [wizardOpen, setWizardOpen] = useState10(false);
3813
- const [activeCard, setActiveCard] = useState10(null);
3814
- const handleConnect = useCallback6((card) => {
3815
- setActiveCard(card);
3816
- setWizardOpen(true);
3817
- }, []);
3818
- const handleWizardClose = useCallback6((open) => {
3819
- if (!open) {
3820
- setActiveCard(null);
3386
+ function ToolsTable({ onEdit, config }) {
3387
+ const [search, setSearch] = useState10("");
3388
+ const [page, setPage] = useState10(1);
3389
+ const queryParams = useMemo6(() => {
3390
+ const params = {
3391
+ limit: "15",
3392
+ page: String(page)
3393
+ };
3394
+ if (search) {
3395
+ params.search = search;
3821
3396
  }
3822
- setWizardOpen(open);
3823
- }, []);
3824
- const handleWizardComplete = useCallback6(() => {
3825
- setWizardOpen(false);
3826
- setActiveCard(null);
3827
- onWizardComplete?.();
3828
- }, [onWizardComplete]);
3829
- const wizardMeta = activeCard ? resolveWizardMeta?.(activeCard) ?? {
3830
- capabilities: [],
3831
- requirements: [],
3832
- hasConfigStep: false
3833
- } : null;
3834
- return /* @__PURE__ */ jsxs16(Fragment2, { children: [
3835
- /* @__PURE__ */ jsxs16(Tabs, { defaultValue: "prompt", children: [
3836
- /* @__PURE__ */ jsxs16(TabsList, { children: [
3837
- /* @__PURE__ */ jsxs16(TabsTrigger, { value: "prompt", className: "flex items-center gap-1.5", children: [
3838
- /* @__PURE__ */ jsx18(FileText2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
3839
- "Prompt"
3840
- ] }),
3841
- /* @__PURE__ */ jsxs16(TabsTrigger, { value: "objetivos", className: "flex items-center gap-1.5", children: [
3842
- /* @__PURE__ */ jsx18(Target2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
3843
- "Objetivos"
3844
- ] }),
3845
- /* @__PURE__ */ jsxs16(TabsTrigger, { value: "capacidades", className: "flex items-center gap-1.5", children: [
3846
- /* @__PURE__ */ jsx18(Blocks, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
3847
- "Capacidades"
3848
- ] }),
3849
- /* @__PURE__ */ jsxs16(TabsTrigger, { value: "integracoes", className: "flex items-center gap-1.5", children: [
3850
- /* @__PURE__ */ jsx18(Plug3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
3851
- "Integra\xE7\xF5es"
3852
- ] }),
3853
- /* @__PURE__ */ jsxs16(TabsTrigger, { value: "conversas", className: "flex items-center gap-1.5", children: [
3854
- /* @__PURE__ */ jsx18(MessageCircle2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
3855
- "Conversas"
3856
- ] })
3857
- ] }),
3858
- /* @__PURE__ */ jsx18(TabsContent, { value: "prompt", className: "mt-4", children: /* @__PURE__ */ jsx18(AgentPromptEditor, { agent, config }) }),
3859
- /* @__PURE__ */ jsx18(TabsContent, { value: "objetivos", className: "mt-4", children: /* @__PURE__ */ jsx18(AgentObjectivesList, { agent, config }) }),
3860
- /* @__PURE__ */ jsx18(TabsContent, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx18(CapabilitiesTab, { config, agentId: agent.id }) }),
3861
- /* @__PURE__ */ jsx18(TabsContent, { value: "integracoes", className: "mt-4", children: /* @__PURE__ */ jsx18(IntegrationsTab, { config, agentId: agent.id, onConnect: handleConnect }) }),
3862
- /* @__PURE__ */ jsx18(TabsContent, { value: "conversas", className: "mt-4", children: /* @__PURE__ */ jsx18(
3863
- AgentConversationsPanel,
3397
+ return params;
3398
+ }, [search, page]);
3399
+ const { data, isLoading } = useTools(config, queryParams);
3400
+ const deleteTool = useDeleteTool(config);
3401
+ const [deleteId, setDeleteId] = useState10(null);
3402
+ const rawTools = data?.data || [];
3403
+ const tools = rawTools.filter((t) => !t.slug?.startsWith("gclinic_"));
3404
+ const total = tools.length;
3405
+ const columns = useColumns2(
3406
+ (tool) => onEdit(tool),
3407
+ (id) => setDeleteId(id)
3408
+ );
3409
+ function handleDelete() {
3410
+ if (!deleteId) return;
3411
+ deleteTool.mutate(deleteId, {
3412
+ onSuccess: () => {
3413
+ toast8.success("Ferramenta exclu\xEDda");
3414
+ setDeleteId(null);
3415
+ },
3416
+ onError: () => toast8.error("Erro ao excluir ferramenta")
3417
+ });
3418
+ }
3419
+ function handleSearchChange(value) {
3420
+ setSearch(value);
3421
+ setPage(1);
3422
+ }
3423
+ return /* @__PURE__ */ jsxs12(Fragment2, { children: [
3424
+ /* @__PURE__ */ jsx14("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs12("div", { className: "relative flex-1 max-w-md", children: [
3425
+ /* @__PURE__ */ jsx14(Search2, { "aria-hidden": "true", className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3426
+ /* @__PURE__ */ jsx14(
3427
+ Input7,
3864
3428
  {
3865
- agent,
3866
- config,
3867
- renderChatLink
3429
+ placeholder: "Buscar ferramentas\\u2026",
3430
+ "aria-label": "Buscar ferramentas",
3431
+ name: "search",
3432
+ autoComplete: "off",
3433
+ value: search,
3434
+ onChange: (e) => handleSearchChange(e.target.value),
3435
+ className: "pl-9"
3868
3436
  }
3869
- ) })
3870
- ] }),
3871
- activeCard && wizardMeta && /* @__PURE__ */ jsx18(
3872
- IntegrationWizard,
3437
+ )
3438
+ ] }) }),
3439
+ /* @__PURE__ */ jsx14(
3440
+ DataTable2,
3873
3441
  {
3874
- open: wizardOpen,
3875
- onOpenChange: handleWizardClose,
3876
- integration: activeCard.definition,
3877
- meta: wizardMeta,
3878
- agentId: agent.id,
3879
- config,
3880
- gagentsApiUrl: apiUrl,
3881
- existingCredentialId: activeCard.credentialId,
3882
- onComplete: handleWizardComplete,
3883
- loadConfigOptions
3442
+ columns,
3443
+ data: tools,
3444
+ isLoading,
3445
+ emptyMessage: "Nenhuma ferramenta encontrada",
3446
+ total,
3447
+ page,
3448
+ onPageChange: setPage,
3449
+ pageSize: 15
3450
+ }
3451
+ ),
3452
+ /* @__PURE__ */ jsx14(
3453
+ AlertDialog4,
3454
+ {
3455
+ open: !!deleteId,
3456
+ onOpenChange: (open) => !open && setDeleteId(null),
3457
+ children: /* @__PURE__ */ jsxs12(AlertDialogContent4, { children: [
3458
+ /* @__PURE__ */ jsxs12(AlertDialogHeader4, { children: [
3459
+ /* @__PURE__ */ jsx14(AlertDialogTitle4, { children: "Excluir ferramenta?" }),
3460
+ /* @__PURE__ */ jsx14(AlertDialogDescription4, { children: "Esta a\xE7\xE3o n\xE3o pode ser desfeita. A ferramenta ser\xE1 removida permanentemente." })
3461
+ ] }),
3462
+ /* @__PURE__ */ jsxs12(AlertDialogFooter4, { children: [
3463
+ /* @__PURE__ */ jsx14(AlertDialogCancel4, { variant: "outline", size: "default", children: "Cancelar" }),
3464
+ /* @__PURE__ */ jsx14(
3465
+ AlertDialogAction4,
3466
+ {
3467
+ variant: "default",
3468
+ size: "default",
3469
+ onClick: handleDelete,
3470
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
3471
+ children: "Excluir"
3472
+ }
3473
+ )
3474
+ ] })
3475
+ ] })
3884
3476
  }
3885
3477
  )
3886
3478
  ] });
3887
3479
  }
3888
3480
 
3889
- // src/components/agents/agent-tools-list.tsx
3481
+ // src/components/tools/tool-form-dialog.tsx
3890
3482
  import { useState as useState11 } from "react";
3891
3483
  import {
3892
- Switch as Switch5,
3893
- Badge as Badge7,
3894
- Button as Button11,
3895
- Skeleton as Skeleton6,
3896
- AlertDialog as AlertDialog3,
3897
- AlertDialogAction as AlertDialogAction3,
3898
- AlertDialogCancel as AlertDialogCancel3,
3899
- AlertDialogContent as AlertDialogContent3,
3900
- AlertDialogDescription as AlertDialogDescription3,
3901
- AlertDialogFooter as AlertDialogFooter3,
3902
- AlertDialogHeader as AlertDialogHeader3,
3903
- AlertDialogTitle as AlertDialogTitle3,
3904
- Popover,
3905
- PopoverContent,
3906
- PopoverTrigger,
3907
- Input as Input7,
3908
- Textarea as Textarea2,
3909
3484
  Dialog as Dialog5,
3910
3485
  DialogContent as DialogContent5,
3911
3486
  DialogHeader as DialogHeader5,
3912
3487
  DialogTitle as DialogTitle5,
3913
3488
  DialogFooter as DialogFooter5,
3914
- Label as Label7,
3489
+ Button as Button10,
3490
+ Input as Input8,
3491
+ Textarea as Textarea3,
3492
+ Label as Label5,
3915
3493
  Select as Select2,
3916
3494
  SelectContent as SelectContent2,
3917
3495
  SelectItem as SelectItem2,
3918
3496
  SelectTrigger as SelectTrigger2,
3919
3497
  SelectValue as SelectValue2
3920
3498
  } from "@greatapps/greatauth-ui/ui";
3921
- import {
3922
- Trash2 as Trash23,
3923
- Plus as Plus3,
3924
- Wrench,
3925
- Settings2 as Settings22
3926
- } from "lucide-react";
3927
- import { toast as toast8 } from "sonner";
3928
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
3929
- function AgentToolsList({ agent, config }) {
3930
- const { data: agentToolsData, isLoading } = useAgentTools(config, agent.id);
3931
- const { data: allToolsData } = useTools(config);
3932
- const addMutation = useAddAgentTool(config);
3933
- const removeMutation = useRemoveAgentTool(config);
3934
- const updateMutation = useUpdateAgentTool(config);
3935
- const [removeTarget, setRemoveTarget] = useState11(null);
3936
- const [addOpen, setAddOpen] = useState11(false);
3937
- const [search, setSearch] = useState11("");
3938
- const [configTarget, setConfigTarget] = useState11(null);
3939
- const [configInstructions, setConfigInstructions] = useState11("");
3940
- const [configCredentialId, setConfigCredentialId] = useState11("");
3941
- const { data: credentialsData } = useToolCredentials(config);
3942
- const allCredentials = credentialsData?.data || [];
3943
- const agentTools = agentToolsData?.data || [];
3944
- const allTools = (allToolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
3945
- const assignedToolIds = new Set(agentTools.map((at) => at.id_tool));
3946
- const visibleAgentTools = agentTools.filter((at) => {
3947
- const tool = allTools.find((t) => t.id === at.id_tool);
3948
- return !tool || !tool.slug?.startsWith("gclinic_");
3949
- });
3950
- const availableTools = allTools.filter((t) => !assignedToolIds.has(t.id));
3951
- const filteredAvailable = availableTools.filter(
3952
- (t) => t.name.toLowerCase().includes(search.toLowerCase())
3499
+ import { Loader2 as Loader26 } from "lucide-react";
3500
+ import { toast as toast9 } from "sonner";
3501
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3502
+ var TOOL_AUTH_TYPES = [
3503
+ { value: "none", label: "Nenhuma" },
3504
+ { value: "api_key", label: "API Key" },
3505
+ { value: "oauth2", label: "OAuth 2.0" }
3506
+ ];
3507
+ function toolToFormState(tool) {
3508
+ return {
3509
+ name: tool?.name || "",
3510
+ slug: tool?.slug || "",
3511
+ type: tool?.type || "none",
3512
+ description: tool?.description || "",
3513
+ functionDefinitions: tool?.function_definitions ? formatJson(tool.function_definitions) : "",
3514
+ nameError: false,
3515
+ slugError: false,
3516
+ typeError: false,
3517
+ jsonError: false
3518
+ };
3519
+ }
3520
+ function formatJson(str) {
3521
+ try {
3522
+ return JSON.stringify(JSON.parse(str), null, 2);
3523
+ } catch {
3524
+ return str;
3525
+ }
3526
+ }
3527
+ function slugify2(name) {
3528
+ return name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
3529
+ }
3530
+ function isValidJson(str) {
3531
+ if (!str.trim()) return true;
3532
+ try {
3533
+ JSON.parse(str);
3534
+ return true;
3535
+ } catch {
3536
+ return false;
3537
+ }
3538
+ }
3539
+ function ToolFormDialog({
3540
+ open,
3541
+ onOpenChange,
3542
+ tool,
3543
+ config
3544
+ }) {
3545
+ const isEditing = !!tool;
3546
+ const createTool = useCreateTool(config);
3547
+ const updateTool = useUpdateTool(config);
3548
+ const [form, setForm] = useState11(() => toolToFormState(tool));
3549
+ const [slugManuallyEdited, setSlugManuallyEdited] = useState11(false);
3550
+ const [lastResetKey, setLastResetKey] = useState11(
3551
+ () => `${tool?.id}-${open}`
3953
3552
  );
3954
- function getToolInfo(idTool) {
3955
- return allTools.find((t) => t.id === idTool);
3553
+ const resetKey = `${tool?.id}-${open}`;
3554
+ if (resetKey !== lastResetKey) {
3555
+ setLastResetKey(resetKey);
3556
+ setForm(toolToFormState(open ? tool : void 0));
3557
+ setSlugManuallyEdited(false);
3956
3558
  }
3957
- async function handleToggleEnabled(agentTool, checked) {
3958
- try {
3959
- await updateMutation.mutateAsync({
3960
- idAgent: agent.id,
3961
- id: agentTool.id,
3962
- body: { enabled: checked }
3963
- });
3964
- toast8.success(checked ? "Ferramenta ativada" : "Ferramenta desativada");
3965
- } catch (err) {
3966
- toast8.error(
3967
- err instanceof Error ? err.message : "Erro ao alterar estado da ferramenta"
3968
- );
3559
+ const isPending = createTool.isPending || updateTool.isPending;
3560
+ async function handleSubmit(e) {
3561
+ e.preventDefault();
3562
+ let hasError = false;
3563
+ if (!form.name.trim()) {
3564
+ setForm((prev) => ({ ...prev, nameError: true }));
3565
+ hasError = true;
3969
3566
  }
3970
- }
3971
- async function handleAdd(tool) {
3972
- try {
3973
- await addMutation.mutateAsync({
3974
- idAgent: agent.id,
3975
- body: { id_tool: tool.id }
3976
- });
3977
- toast8.success("Ferramenta adicionada");
3978
- setAddOpen(false);
3979
- setSearch("");
3980
- } catch (err) {
3981
- toast8.error(
3982
- err instanceof Error ? err.message : "Erro ao adicionar ferramenta"
3983
- );
3567
+ const effectiveSlug = form.slug.trim() || slugify2(form.name);
3568
+ if (!effectiveSlug) {
3569
+ setForm((prev) => ({ ...prev, slugError: true }));
3570
+ hasError = true;
3984
3571
  }
3985
- }
3986
- async function handleRemove() {
3987
- if (!removeTarget) return;
3988
- try {
3989
- await removeMutation.mutateAsync({
3990
- idAgent: agent.id,
3991
- id: removeTarget.id
3992
- });
3993
- toast8.success("Ferramenta removida");
3994
- } catch (err) {
3995
- toast8.error(
3996
- err instanceof Error ? err.message : "Erro ao remover ferramenta"
3997
- );
3998
- } finally {
3999
- setRemoveTarget(null);
3572
+ if (!form.type) {
3573
+ setForm((prev) => ({ ...prev, typeError: true }));
3574
+ hasError = true;
3575
+ }
3576
+ if (!isValidJson(form.functionDefinitions)) {
3577
+ setForm((prev) => ({ ...prev, jsonError: true }));
3578
+ hasError = true;
3579
+ }
3580
+ if (hasError) return;
3581
+ const body = {
3582
+ name: form.name.trim(),
3583
+ slug: effectiveSlug,
3584
+ type: form.type
3585
+ };
3586
+ if (form.description.trim()) body.description = form.description.trim();
3587
+ else body.description = "";
3588
+ if (form.functionDefinitions.trim()) {
3589
+ const parsed = JSON.parse(form.functionDefinitions.trim());
3590
+ body.function_definitions = JSON.stringify(parsed);
3591
+ } else {
3592
+ body.function_definitions = "";
4000
3593
  }
4001
- }
4002
- function openConfig(agentTool) {
4003
- setConfigTarget(agentTool);
4004
- setConfigInstructions(agentTool.custom_instructions || "");
4005
- setConfigCredentialId(agentTool.id_tool_credential ? String(agentTool.id_tool_credential) : "");
4006
- }
4007
- async function handleSaveConfig() {
4008
- if (!configTarget) return;
4009
3594
  try {
4010
- const newCredentialId = configCredentialId ? parseInt(configCredentialId, 10) : null;
4011
- await updateMutation.mutateAsync({
4012
- idAgent: agent.id,
4013
- id: configTarget.id,
4014
- body: {
4015
- custom_instructions: configInstructions.trim() || null,
4016
- id_tool_credential: newCredentialId
4017
- }
4018
- });
4019
- toast8.success("Configura\xE7\xE3o atualizada");
4020
- setConfigTarget(null);
3595
+ if (isEditing) {
3596
+ await updateTool.mutateAsync({ id: tool.id, body });
3597
+ toast9.success("Ferramenta atualizada");
3598
+ } else {
3599
+ await createTool.mutateAsync(
3600
+ body
3601
+ );
3602
+ toast9.success("Ferramenta criada");
3603
+ }
3604
+ onOpenChange(false);
4021
3605
  } catch (err) {
4022
- toast8.error(
4023
- err instanceof Error ? err.message : "Erro ao atualizar configura\xE7\xE3o"
3606
+ toast9.error(
3607
+ err instanceof Error ? err.message : isEditing ? "Erro ao atualizar ferramenta" : "Erro ao criar ferramenta"
4024
3608
  );
4025
3609
  }
4026
3610
  }
4027
- if (isLoading) {
4028
- return /* @__PURE__ */ jsx19("div", { className: "space-y-3 p-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx19(Skeleton6, { className: "h-14 w-full" }, i)) });
4029
- }
4030
- return /* @__PURE__ */ jsxs17("div", { className: "space-y-4 p-4", children: [
4031
- /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between", children: [
4032
- /* @__PURE__ */ jsxs17("h3", { className: "text-sm font-medium text-muted-foreground", children: [
4033
- visibleAgentTools.length,
4034
- " ferramenta",
4035
- visibleAgentTools.length !== 1 ? "s" : "",
4036
- " associada",
4037
- visibleAgentTools.length !== 1 ? "s" : ""
3611
+ return /* @__PURE__ */ jsx15(Dialog5, { open, onOpenChange, children: /* @__PURE__ */ jsxs13(DialogContent5, { className: "sm:max-w-lg", children: [
3612
+ /* @__PURE__ */ jsx15(DialogHeader5, { children: /* @__PURE__ */ jsx15(DialogTitle5, { children: isEditing ? "Editar Ferramenta" : "Nova Ferramenta" }) }),
3613
+ /* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
3614
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3615
+ /* @__PURE__ */ jsx15(Label5, { htmlFor: "tool-name", children: "Nome *" }),
3616
+ /* @__PURE__ */ jsx15(
3617
+ Input8,
3618
+ {
3619
+ id: "tool-name",
3620
+ name: "name",
3621
+ value: form.name,
3622
+ onChange: (e) => {
3623
+ const name = e.target.value;
3624
+ setForm((prev) => ({
3625
+ ...prev,
3626
+ name,
3627
+ nameError: name.trim() ? false : prev.nameError,
3628
+ ...!slugManuallyEdited && !isEditing ? { slug: slugify2(name), slugError: false } : {}
3629
+ }));
3630
+ },
3631
+ placeholder: "Ex: Google Calendar",
3632
+ disabled: isPending
3633
+ }
3634
+ ),
3635
+ form.nameError && /* @__PURE__ */ jsx15("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
4038
3636
  ] }),
4039
- /* @__PURE__ */ jsxs17(Popover, { open: addOpen, onOpenChange: setAddOpen, children: [
4040
- /* @__PURE__ */ jsx19(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs17(Button11, { size: "sm", disabled: availableTools.length === 0, children: [
4041
- /* @__PURE__ */ jsx19(Plus3, { className: "mr-2 h-4 w-4" }),
4042
- "Adicionar Ferramenta"
4043
- ] }) }),
4044
- /* @__PURE__ */ jsxs17(PopoverContent, { className: "w-72 p-0", align: "end", children: [
4045
- /* @__PURE__ */ jsx19("div", { className: "p-2", children: /* @__PURE__ */ jsx19(
4046
- Input7,
4047
- {
4048
- placeholder: "Buscar ferramenta\\u2026",
4049
- "aria-label": "Buscar ferramenta",
4050
- name: "search",
4051
- value: search,
4052
- onChange: (e) => setSearch(e.target.value),
4053
- className: "h-8"
4054
- }
4055
- ) }),
4056
- /* @__PURE__ */ jsx19("div", { className: "max-h-48 overflow-y-auto", children: filteredAvailable.length === 0 ? /* @__PURE__ */ jsx19("p", { className: "p-3 text-center text-sm text-muted-foreground", children: "Nenhuma ferramenta dispon\xEDvel" }) : filteredAvailable.map((tool) => /* @__PURE__ */ jsxs17(
4057
- "button",
4058
- {
4059
- type: "button",
4060
- className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-accent",
4061
- onClick: () => handleAdd(tool),
4062
- disabled: addMutation.isPending,
4063
- children: [
4064
- /* @__PURE__ */ jsx19(Wrench, { className: "h-4 w-4 text-muted-foreground" }),
4065
- /* @__PURE__ */ jsx19("span", { className: "flex-1 font-medium", children: tool.name }),
4066
- /* @__PURE__ */ jsx19(Badge7, { variant: "secondary", className: "text-xs", children: tool.type })
4067
- ]
3637
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3638
+ /* @__PURE__ */ jsx15(Label5, { htmlFor: "tool-slug", children: "Slug (identificador \xFAnico) *" }),
3639
+ /* @__PURE__ */ jsx15(
3640
+ Input8,
3641
+ {
3642
+ id: "tool-slug",
3643
+ name: "slug",
3644
+ value: form.slug,
3645
+ onChange: (e) => {
3646
+ setSlugManuallyEdited(true);
3647
+ setForm((prev) => ({
3648
+ ...prev,
3649
+ slug: e.target.value,
3650
+ slugError: e.target.value.trim() ? false : prev.slugError
3651
+ }));
4068
3652
  },
4069
- tool.id
4070
- )) })
4071
- ] })
4072
- ] })
4073
- ] }),
4074
- visibleAgentTools.length === 0 ? /* @__PURE__ */ jsxs17("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
4075
- /* @__PURE__ */ jsx19(Wrench, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
4076
- /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "Nenhuma ferramenta associada. Clique em 'Adicionar Ferramenta' para come\xE7ar." })
4077
- ] }) : /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: visibleAgentTools.map((agentTool) => {
4078
- const tool = getToolInfo(agentTool.id_tool);
4079
- return /* @__PURE__ */ jsxs17(
4080
- "div",
4081
- {
4082
- className: "flex items-center gap-3 rounded-lg border bg-card p-3",
4083
- children: [
4084
- /* @__PURE__ */ jsxs17("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [
4085
- /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
4086
- /* @__PURE__ */ jsx19("span", { className: "truncate font-medium", children: tool?.name || `Ferramenta #${agentTool.id_tool}` }),
4087
- tool?.type && /* @__PURE__ */ jsx19(Badge7, { variant: "secondary", className: "shrink-0 text-xs", children: tool.type })
4088
- ] }),
4089
- agentTool.custom_instructions && /* @__PURE__ */ jsx19("p", { className: "truncate text-xs text-muted-foreground", children: agentTool.custom_instructions })
4090
- ] }),
4091
- /* @__PURE__ */ jsx19(
4092
- Switch5,
4093
- {
4094
- "aria-label": "Ativar/Desativar",
4095
- checked: agentTool.enabled,
4096
- onCheckedChange: (checked) => handleToggleEnabled(agentTool, checked),
4097
- disabled: updateMutation.isPending
4098
- }
4099
- ),
4100
- /* @__PURE__ */ jsx19(
4101
- Button11,
4102
- {
4103
- variant: "ghost",
4104
- size: "icon",
4105
- "aria-label": "Configurar",
4106
- className: "shrink-0 text-muted-foreground hover:text-foreground",
4107
- onClick: () => openConfig(agentTool),
4108
- title: "Configurar instru\xE7\xF5es",
4109
- children: /* @__PURE__ */ jsx19(Settings22, { className: "h-4 w-4" })
4110
- }
4111
- ),
4112
- /* @__PURE__ */ jsx19(
4113
- Button11,
4114
- {
4115
- variant: "ghost",
4116
- size: "icon",
4117
- "aria-label": "Remover",
4118
- className: "shrink-0 text-muted-foreground hover:text-destructive",
4119
- onClick: () => setRemoveTarget(agentTool),
4120
- children: /* @__PURE__ */ jsx19(Trash23, { className: "h-4 w-4" })
4121
- }
4122
- )
4123
- ]
4124
- },
4125
- agentTool.id
4126
- );
4127
- }) }),
4128
- /* @__PURE__ */ jsx19(
4129
- Dialog5,
4130
- {
4131
- open: !!configTarget,
4132
- onOpenChange: (open) => !open && setConfigTarget(null),
4133
- children: /* @__PURE__ */ jsxs17(DialogContent5, { className: "sm:max-w-lg", children: [
4134
- /* @__PURE__ */ jsx19(DialogHeader5, { children: /* @__PURE__ */ jsx19(DialogTitle5, { children: "Instru\xE7\xF5es da Ferramenta" }) }),
4135
- /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
4136
- configTarget && getToolInfo(configTarget.id_tool)?.type !== "none" && /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4137
- /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-credential", children: "Credencial" }),
4138
- /* @__PURE__ */ jsxs17(
4139
- Select2,
4140
- {
4141
- value: configCredentialId || void 0,
4142
- onValueChange: (val) => setConfigCredentialId(val === "__none__" ? "" : val),
4143
- children: [
4144
- /* @__PURE__ */ jsx19(SelectTrigger2, { id: "tool-credential", children: /* @__PURE__ */ jsx19(SelectValue2, { placeholder: "Selecione uma credencial (opcional)" }) }),
4145
- /* @__PURE__ */ jsxs17(SelectContent2, { children: [
4146
- /* @__PURE__ */ jsx19(SelectItem2, { value: "__none__", children: "Nenhuma (autom\xE1tico)" }),
4147
- allCredentials.filter((c) => configTarget && c.id_tool === configTarget.id_tool && c.status === "active").map((c) => /* @__PURE__ */ jsx19(SelectItem2, { value: String(c.id), children: c.label || `Credencial #${c.id}` }, c.id))
4148
- ] })
4149
- ]
4150
- }
4151
- ),
4152
- /* @__PURE__ */ jsx19("p", { className: "text-xs text-muted-foreground", children: "Vincule uma credencial espec\xEDfica a esta ferramenta neste agente." })
4153
- ] }),
4154
- /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4155
- /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-instructions", children: "Instru\xE7\xF5es Personalizadas" }),
4156
- /* @__PURE__ */ jsx19(
4157
- Textarea2,
4158
- {
4159
- id: "tool-instructions",
4160
- name: "instructions",
4161
- value: configInstructions,
4162
- onChange: (e) => setConfigInstructions(e.target.value),
4163
- placeholder: "Instru\\u00e7\\u00f5es sobre como e quando o agente deve usar esta ferramenta\\u2026",
4164
- rows: 6
4165
- }
4166
- ),
4167
- /* @__PURE__ */ jsx19("p", { className: "text-xs text-muted-foreground", children: "Este texto \xE9 adicionado ao prompt do agente para orientar o uso da ferramenta." })
4168
- ] })
4169
- ] }),
4170
- /* @__PURE__ */ jsxs17(DialogFooter5, { children: [
4171
- /* @__PURE__ */ jsx19(
4172
- Button11,
4173
- {
4174
- variant: "outline",
4175
- onClick: () => setConfigTarget(null),
4176
- children: "Cancelar"
4177
- }
4178
- ),
4179
- /* @__PURE__ */ jsx19(
4180
- Button11,
4181
- {
4182
- onClick: handleSaveConfig,
4183
- disabled: updateMutation.isPending,
4184
- children: "Salvar"
4185
- }
4186
- )
4187
- ] })
4188
- ] })
3653
+ placeholder: "Ex: google-calendar",
3654
+ disabled: isPending
3655
+ }
3656
+ ),
3657
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-muted-foreground", children: "Gerado automaticamente a partir do nome. Usado internamente para identificar a ferramenta." }),
3658
+ form.slugError && /* @__PURE__ */ jsx15("p", { className: "text-sm text-destructive", children: "Slug \xE9 obrigat\xF3rio" })
3659
+ ] }),
3660
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3661
+ /* @__PURE__ */ jsx15(Label5, { htmlFor: "tool-type", children: "Tipo de Autentica\xE7\xE3o *" }),
3662
+ /* @__PURE__ */ jsxs13(
3663
+ Select2,
3664
+ {
3665
+ value: form.type,
3666
+ onValueChange: (value) => {
3667
+ setForm((prev) => ({
3668
+ ...prev,
3669
+ type: value,
3670
+ typeError: false
3671
+ }));
3672
+ },
3673
+ disabled: isPending,
3674
+ children: [
3675
+ /* @__PURE__ */ jsx15(SelectTrigger2, { id: "tool-type", children: /* @__PURE__ */ jsx15(SelectValue2, { placeholder: "Selecione o tipo" }) }),
3676
+ /* @__PURE__ */ jsx15(SelectContent2, { children: TOOL_AUTH_TYPES.map((t) => /* @__PURE__ */ jsx15(SelectItem2, { value: t.value, children: t.label }, t.value)) })
3677
+ ]
3678
+ }
3679
+ ),
3680
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-muted-foreground", children: "Define se a ferramenta requer credenciais para funcionar." }),
3681
+ form.typeError && /* @__PURE__ */ jsx15("p", { className: "text-sm text-destructive", children: "Tipo \xE9 obrigat\xF3rio" })
3682
+ ] }),
3683
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3684
+ /* @__PURE__ */ jsx15(Label5, { htmlFor: "tool-description", children: "Descri\xE7\xE3o" }),
3685
+ /* @__PURE__ */ jsx15(
3686
+ Textarea3,
3687
+ {
3688
+ id: "tool-description",
3689
+ name: "description",
3690
+ value: form.description,
3691
+ onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
3692
+ placeholder: "Descri\\u00e7\\u00e3o da ferramenta\\u2026",
3693
+ rows: 3,
3694
+ disabled: isPending
3695
+ }
3696
+ )
3697
+ ] }),
3698
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
3699
+ /* @__PURE__ */ jsx15(Label5, { htmlFor: "tool-function-defs", children: "Defini\xE7\xF5es de Fun\xE7\xE3o (JSON)" }),
3700
+ /* @__PURE__ */ jsx15(
3701
+ Textarea3,
3702
+ {
3703
+ id: "tool-function-defs",
3704
+ name: "functionDefs",
3705
+ value: form.functionDefinitions,
3706
+ onChange: (e) => {
3707
+ setForm((prev) => ({
3708
+ ...prev,
3709
+ functionDefinitions: e.target.value,
3710
+ jsonError: false
3711
+ }));
3712
+ },
3713
+ placeholder: `[
3714
+ {
3715
+ "type": "function",
3716
+ "function": {
3717
+ "name": "nome_da_funcao",
3718
+ "description": "O que a fun\xE7\xE3o faz",
3719
+ "parameters": {
3720
+ "type": "object",
3721
+ "properties": { \u2026 },
3722
+ "required": [\u2026]
4189
3723
  }
4190
- ),
4191
- /* @__PURE__ */ jsx19(
4192
- AlertDialog3,
4193
- {
4194
- open: !!removeTarget,
4195
- onOpenChange: (open) => !open && setRemoveTarget(null),
4196
- children: /* @__PURE__ */ jsxs17(AlertDialogContent3, { children: [
4197
- /* @__PURE__ */ jsxs17(AlertDialogHeader3, { children: [
4198
- /* @__PURE__ */ jsx19(AlertDialogTitle3, { children: "Remover ferramenta?" }),
4199
- /* @__PURE__ */ jsx19(AlertDialogDescription3, { children: "A ferramenta ser\xE1 desassociada deste agente." })
4200
- ] }),
4201
- /* @__PURE__ */ jsxs17(AlertDialogFooter3, { children: [
4202
- /* @__PURE__ */ jsx19(AlertDialogCancel3, { children: "Cancelar" }),
4203
- /* @__PURE__ */ jsx19(
4204
- AlertDialogAction3,
4205
- {
4206
- onClick: handleRemove,
4207
- disabled: removeMutation.isPending,
4208
- children: "Remover"
4209
- }
4210
- )
4211
- ] })
3724
+ }
3725
+ }
3726
+ ]`,
3727
+ rows: 10,
3728
+ className: "font-mono text-sm",
3729
+ disabled: isPending
3730
+ }
3731
+ ),
3732
+ /* @__PURE__ */ jsx15("p", { className: "text-xs text-muted-foreground", children: "Array de defini\xE7\xF5es no formato OpenAI Function Calling." }),
3733
+ form.jsonError && /* @__PURE__ */ jsx15("p", { className: "text-sm text-destructive", children: "JSON inv\xE1lido" })
3734
+ ] }),
3735
+ /* @__PURE__ */ jsxs13(DialogFooter5, { children: [
3736
+ /* @__PURE__ */ jsx15(
3737
+ Button10,
3738
+ {
3739
+ type: "button",
3740
+ variant: "outline",
3741
+ onClick: () => onOpenChange(false),
3742
+ disabled: isPending,
3743
+ children: "Cancelar"
3744
+ }
3745
+ ),
3746
+ /* @__PURE__ */ jsxs13(Button10, { type: "submit", disabled: isPending, children: [
3747
+ isPending ? /* @__PURE__ */ jsx15(Loader26, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null,
3748
+ isEditing ? "Salvar" : "Criar"
4212
3749
  ] })
4213
- }
4214
- )
4215
- ] });
3750
+ ] })
3751
+ ] })
3752
+ ] }) });
4216
3753
  }
4217
3754
 
4218
- // src/components/tools/tools-table.tsx
4219
- import { useMemo as useMemo6, useState as useState12 } from "react";
4220
- import { DataTable as DataTable2 } from "@greatapps/greatauth-ui";
3755
+ // src/components/tools/tool-credentials-form.tsx
3756
+ import { useMemo as useMemo7, useState as useState12 } from "react";
3757
+ import { DataTable as DataTable3 } from "@greatapps/greatauth-ui";
4221
3758
  import {
4222
- Input as Input8,
3759
+ Input as Input9,
3760
+ Button as Button11,
4223
3761
  Badge as Badge8,
4224
- Tooltip as Tooltip3,
4225
- TooltipTrigger as TooltipTrigger3,
4226
- TooltipContent as TooltipContent3,
4227
- AlertDialog as AlertDialog4,
4228
- AlertDialogAction as AlertDialogAction4,
4229
- AlertDialogCancel as AlertDialogCancel4,
4230
- AlertDialogContent as AlertDialogContent4,
4231
- AlertDialogDescription as AlertDialogDescription4,
4232
- AlertDialogFooter as AlertDialogFooter4,
4233
- AlertDialogHeader as AlertDialogHeader4,
4234
- AlertDialogTitle as AlertDialogTitle4,
4235
- Button as Button12
3762
+ Tooltip as Tooltip4,
3763
+ TooltipTrigger as TooltipTrigger4,
3764
+ TooltipContent as TooltipContent4,
3765
+ AlertDialog as AlertDialog5,
3766
+ AlertDialogAction as AlertDialogAction5,
3767
+ AlertDialogCancel as AlertDialogCancel5,
3768
+ AlertDialogContent as AlertDialogContent5,
3769
+ AlertDialogDescription as AlertDialogDescription5,
3770
+ AlertDialogFooter as AlertDialogFooter5,
3771
+ AlertDialogHeader as AlertDialogHeader5,
3772
+ AlertDialogTitle as AlertDialogTitle5
4236
3773
  } from "@greatapps/greatauth-ui/ui";
4237
- import { Pencil as Pencil3, Trash2 as Trash24, Search as Search2 } from "lucide-react";
4238
- import { format as format2 } from "date-fns";
4239
- import { ptBR as ptBR2 } from "date-fns/locale";
4240
- import { toast as toast9 } from "sonner";
4241
- import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4242
- function useColumns2(onEdit, onDelete) {
3774
+ import { Trash2 as Trash25, Search as Search3 } from "lucide-react";
3775
+ import { format as format3 } from "date-fns";
3776
+ import { ptBR as ptBR3 } from "date-fns/locale";
3777
+ import { toast as toast10 } from "sonner";
3778
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3779
+ function formatDate2(dateStr) {
3780
+ if (!dateStr) return "Sem expira\xE7\xE3o";
3781
+ return format3(new Date(dateStr), "dd/MM/yyyy", { locale: ptBR3 });
3782
+ }
3783
+ function useColumns3(tools, onRemove) {
3784
+ function getToolName(idTool) {
3785
+ if (!idTool) return "\u2014";
3786
+ const tool = tools.find((t) => t.id === idTool);
3787
+ return tool?.name || `Ferramenta #${idTool}`;
3788
+ }
4243
3789
  return [
4244
3790
  {
4245
- accessorKey: "name",
4246
- header: "Nome",
4247
- cell: ({ row }) => /* @__PURE__ */ jsx20("span", { className: "font-medium", children: row.original.name }),
4248
- sortingFn: (rowA, rowB) => rowA.original.name.toLowerCase().localeCompare(rowB.original.name.toLowerCase())
3791
+ accessorKey: "label",
3792
+ header: "Label",
3793
+ cell: ({ row }) => /* @__PURE__ */ jsx16("span", { className: "font-medium", children: row.original.label || "\u2014" })
4249
3794
  },
4250
3795
  {
4251
- accessorKey: "slug",
4252
- header: "Slug",
4253
- cell: ({ row }) => /* @__PURE__ */ jsx20("span", { className: "text-muted-foreground text-sm font-mono", children: row.original.slug || "\u2014" })
3796
+ accessorKey: "id_tool",
3797
+ header: "Ferramenta",
3798
+ cell: ({ row }) => /* @__PURE__ */ jsx16("span", { className: "text-sm", children: getToolName(row.original.id_tool) })
4254
3799
  },
4255
3800
  {
4256
- accessorKey: "type",
4257
- header: "Tipo",
4258
- cell: ({ row }) => /* @__PURE__ */ jsx20(Badge8, { variant: "secondary", children: row.original.type })
3801
+ accessorKey: "status",
3802
+ header: "Status",
3803
+ cell: ({ row }) => /* @__PURE__ */ jsx16(
3804
+ Badge8,
3805
+ {
3806
+ variant: row.original.status === "active" ? "default" : "destructive",
3807
+ children: row.original.status === "active" ? "Ativo" : "Expirado"
3808
+ }
3809
+ )
4259
3810
  },
4260
3811
  {
4261
- accessorKey: "description",
4262
- header: "Descri\xE7\xE3o",
4263
- cell: ({ row }) => {
4264
- const desc = row.original.description;
4265
- if (!desc) return /* @__PURE__ */ jsx20("span", { className: "text-muted-foreground text-sm", children: "\u2014" });
4266
- return /* @__PURE__ */ jsx20("span", { className: "text-muted-foreground text-sm", children: desc.length > 50 ? `${desc.slice(0, 50)}\u2026` : desc });
4267
- }
3812
+ accessorKey: "expires_at",
3813
+ header: "Expira em",
3814
+ cell: ({ row }) => /* @__PURE__ */ jsx16("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.expires_at) })
4268
3815
  },
4269
3816
  {
4270
3817
  accessorKey: "datetime_add",
4271
3818
  header: "Criado em",
4272
- cell: ({ row }) => /* @__PURE__ */ jsx20("span", { className: "text-muted-foreground text-sm", children: format2(new Date(row.original.datetime_add), "dd/MM/yyyy", {
4273
- locale: ptBR2
4274
- }) })
3819
+ cell: ({ row }) => /* @__PURE__ */ jsx16("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.datetime_add) })
4275
3820
  },
4276
3821
  {
4277
3822
  id: "actions",
4278
- size: 80,
3823
+ header: "A\xE7\xF5es",
3824
+ size: 100,
4279
3825
  enableSorting: false,
4280
- cell: ({ row }) => /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1", children: [
4281
- /* @__PURE__ */ jsxs18(Tooltip3, { children: [
4282
- /* @__PURE__ */ jsx20(TooltipTrigger3, { asChild: true, children: /* @__PURE__ */ jsx20(
4283
- Button12,
4284
- {
4285
- variant: "ghost",
4286
- size: "icon",
4287
- className: "h-8 w-8",
4288
- "aria-label": "Editar",
4289
- onClick: () => onEdit(row.original),
4290
- children: /* @__PURE__ */ jsx20(Pencil3, { className: "h-4 w-4" })
4291
- }
4292
- ) }),
4293
- /* @__PURE__ */ jsx20(TooltipContent3, { children: "Editar" })
4294
- ] }),
4295
- /* @__PURE__ */ jsxs18(Tooltip3, { children: [
4296
- /* @__PURE__ */ jsx20(TooltipTrigger3, { asChild: true, children: /* @__PURE__ */ jsx20(
4297
- Button12,
4298
- {
4299
- variant: "ghost",
4300
- size: "icon",
4301
- className: "h-8 w-8 text-destructive hover:text-destructive",
4302
- "aria-label": "Excluir",
4303
- onClick: () => onDelete(row.original.id),
4304
- children: /* @__PURE__ */ jsx20(Trash24, { className: "h-4 w-4" })
4305
- }
4306
- ) }),
4307
- /* @__PURE__ */ jsx20(TooltipContent3, { children: "Excluir" })
4308
- ] })
4309
- ] })
3826
+ cell: ({ row }) => /* @__PURE__ */ jsx16("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxs14(Tooltip4, { children: [
3827
+ /* @__PURE__ */ jsx16(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx16(
3828
+ Button11,
3829
+ {
3830
+ variant: "ghost",
3831
+ size: "icon",
3832
+ className: "h-8 w-8 text-destructive hover:text-destructive",
3833
+ "aria-label": "Excluir",
3834
+ onClick: () => onRemove(row.original),
3835
+ children: /* @__PURE__ */ jsx16(Trash25, { className: "h-4 w-4" })
3836
+ }
3837
+ ) }),
3838
+ /* @__PURE__ */ jsx16(TooltipContent4, { children: "Remover" })
3839
+ ] }) })
4310
3840
  }
4311
3841
  ];
4312
3842
  }
4313
- function ToolsTable({ onEdit, config }) {
3843
+ function ToolCredentialsForm({
3844
+ credentials,
3845
+ isLoading,
3846
+ config,
3847
+ gagentsApiUrl
3848
+ }) {
3849
+ const deleteMutation = useDeleteToolCredential(config);
3850
+ const { data: toolsData } = useTools(config);
3851
+ const tools = (toolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
4314
3852
  const [search, setSearch] = useState12("");
4315
- const [page, setPage] = useState12(1);
4316
- const queryParams = useMemo6(() => {
4317
- const params = {
4318
- limit: "15",
4319
- page: String(page)
4320
- };
4321
- if (search) {
4322
- params.search = search;
4323
- }
4324
- return params;
4325
- }, [search, page]);
4326
- const { data, isLoading } = useTools(config, queryParams);
4327
- const deleteTool = useDeleteTool(config);
4328
- const [deleteId, setDeleteId] = useState12(null);
4329
- const rawTools = data?.data || [];
4330
- const tools = rawTools.filter((t) => !t.slug?.startsWith("gclinic_"));
4331
- const total = tools.length;
4332
- const columns = useColumns2(
4333
- (tool) => onEdit(tool),
4334
- (id) => setDeleteId(id)
4335
- );
4336
- function handleDelete() {
4337
- if (!deleteId) return;
4338
- deleteTool.mutate(deleteId, {
4339
- onSuccess: () => {
4340
- toast9.success("Ferramenta exclu\xEDda");
4341
- setDeleteId(null);
4342
- },
4343
- onError: () => toast9.error("Erro ao excluir ferramenta")
3853
+ const [removeTarget, setRemoveTarget] = useState12(null);
3854
+ const internalToolIds = useMemo7(() => {
3855
+ const allRawTools = toolsData?.data || [];
3856
+ return new Set(
3857
+ allRawTools.filter((t) => t.slug?.startsWith("gclinic_")).map((t) => t.id)
3858
+ );
3859
+ }, [toolsData]);
3860
+ const filteredCredentials = useMemo7(() => {
3861
+ const visible = credentials.filter(
3862
+ (cred) => !cred.id_tool || !internalToolIds.has(cred.id_tool)
3863
+ );
3864
+ if (!search) return visible;
3865
+ const term = search.toLowerCase();
3866
+ return visible.filter((cred) => {
3867
+ const toolName = tools.find((t) => t.id === cred.id_tool)?.name || "";
3868
+ return (cred.label || "").toLowerCase().includes(term) || toolName.toLowerCase().includes(term);
4344
3869
  });
3870
+ }, [credentials, search, tools, internalToolIds]);
3871
+ const columns = useColumns3(
3872
+ tools,
3873
+ (cred) => setRemoveTarget(cred)
3874
+ );
3875
+ async function handleRemove() {
3876
+ if (!removeTarget) return;
3877
+ try {
3878
+ const result = await deleteMutation.mutateAsync(removeTarget.id);
3879
+ if (result.status === 1) {
3880
+ toast10.success("Credencial removida");
3881
+ } else {
3882
+ toast10.error(result.message || "Erro ao remover credencial");
3883
+ }
3884
+ } catch {
3885
+ toast10.error("Erro ao remover credencial");
3886
+ } finally {
3887
+ setRemoveTarget(null);
3888
+ }
4345
3889
  }
4346
- function handleSearchChange(value) {
4347
- setSearch(value);
4348
- setPage(1);
4349
- }
4350
- return /* @__PURE__ */ jsxs18(Fragment3, { children: [
4351
- /* @__PURE__ */ jsx20("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs18("div", { className: "relative flex-1 max-w-md", children: [
4352
- /* @__PURE__ */ jsx20(Search2, { "aria-hidden": "true", className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
4353
- /* @__PURE__ */ jsx20(
4354
- Input8,
3890
+ return /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3891
+ /* @__PURE__ */ jsx16("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs14("div", { className: "relative flex-1 max-w-md", children: [
3892
+ /* @__PURE__ */ jsx16(Search3, { "aria-hidden": "true", className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3893
+ /* @__PURE__ */ jsx16(
3894
+ Input9,
4355
3895
  {
4356
- placeholder: "Buscar ferramentas\\u2026",
4357
- "aria-label": "Buscar ferramentas",
3896
+ placeholder: "Buscar credenciais\\u2026",
3897
+ "aria-label": "Buscar credenciais",
4358
3898
  name: "search",
4359
3899
  autoComplete: "off",
4360
3900
  value: search,
4361
- onChange: (e) => handleSearchChange(e.target.value),
3901
+ onChange: (e) => setSearch(e.target.value),
4362
3902
  className: "pl-9"
4363
3903
  }
4364
3904
  )
4365
3905
  ] }) }),
4366
- /* @__PURE__ */ jsx20(
4367
- DataTable2,
3906
+ /* @__PURE__ */ jsx16(
3907
+ DataTable3,
4368
3908
  {
4369
3909
  columns,
4370
- data: tools,
3910
+ data: filteredCredentials,
4371
3911
  isLoading,
4372
- emptyMessage: "Nenhuma ferramenta encontrada",
4373
- total,
4374
- page,
4375
- onPageChange: setPage,
4376
- pageSize: 15
3912
+ emptyMessage: "Nenhuma credencial encontrada"
4377
3913
  }
4378
3914
  ),
4379
- /* @__PURE__ */ jsx20(
4380
- AlertDialog4,
3915
+ /* @__PURE__ */ jsx16(
3916
+ AlertDialog5,
4381
3917
  {
4382
- open: !!deleteId,
4383
- onOpenChange: (open) => !open && setDeleteId(null),
4384
- children: /* @__PURE__ */ jsxs18(AlertDialogContent4, { children: [
4385
- /* @__PURE__ */ jsxs18(AlertDialogHeader4, { children: [
4386
- /* @__PURE__ */ jsx20(AlertDialogTitle4, { children: "Excluir ferramenta?" }),
4387
- /* @__PURE__ */ jsx20(AlertDialogDescription4, { children: "Esta a\xE7\xE3o n\xE3o pode ser desfeita. A ferramenta ser\xE1 removida permanentemente." })
3918
+ open: !!removeTarget,
3919
+ onOpenChange: (open) => !open && setRemoveTarget(null),
3920
+ children: /* @__PURE__ */ jsxs14(AlertDialogContent5, { children: [
3921
+ /* @__PURE__ */ jsxs14(AlertDialogHeader5, { children: [
3922
+ /* @__PURE__ */ jsx16(AlertDialogTitle5, { children: "Remover credencial?" }),
3923
+ /* @__PURE__ */ jsx16(AlertDialogDescription5, { children: "A credencial ser\xE1 removida permanentemente." })
4388
3924
  ] }),
4389
- /* @__PURE__ */ jsxs18(AlertDialogFooter4, { children: [
4390
- /* @__PURE__ */ jsx20(AlertDialogCancel4, { variant: "outline", size: "default", children: "Cancelar" }),
4391
- /* @__PURE__ */ jsx20(
4392
- AlertDialogAction4,
3925
+ /* @__PURE__ */ jsxs14(AlertDialogFooter5, { children: [
3926
+ /* @__PURE__ */ jsx16(AlertDialogCancel5, { children: "Cancelar" }),
3927
+ /* @__PURE__ */ jsx16(
3928
+ AlertDialogAction5,
4393
3929
  {
4394
- variant: "default",
4395
- size: "default",
4396
- onClick: handleDelete,
4397
- className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
4398
- children: "Excluir"
3930
+ onClick: handleRemove,
3931
+ disabled: deleteMutation.isPending,
3932
+ children: "Remover"
4399
3933
  }
4400
3934
  )
4401
3935
  ] })
@@ -4405,837 +3939,951 @@ function ToolsTable({ onEdit, config }) {
4405
3939
  ] });
4406
3940
  }
4407
3941
 
4408
- // src/components/tools/tool-form-dialog.tsx
4409
- import { useState as useState13 } from "react";
3942
+ // src/components/capabilities/integration-card.tsx
3943
+ import { Badge as Badge9, Button as Button12 } from "@greatapps/greatauth-ui/ui";
4410
3944
  import {
4411
- Dialog as Dialog6,
4412
- DialogContent as DialogContent6,
4413
- DialogHeader as DialogHeader6,
4414
- DialogTitle as DialogTitle6,
4415
- DialogFooter as DialogFooter6,
4416
- Button as Button13,
4417
- Input as Input9,
4418
- Textarea as Textarea3,
4419
- Label as Label8,
4420
- Select as Select3,
4421
- SelectContent as SelectContent3,
4422
- SelectItem as SelectItem3,
4423
- SelectTrigger as SelectTrigger3,
4424
- SelectValue as SelectValue3
4425
- } from "@greatapps/greatauth-ui/ui";
4426
- import { Loader2 as Loader29 } from "lucide-react";
4427
- import { toast as toast10 } from "sonner";
4428
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
4429
- var TOOL_AUTH_TYPES = [
4430
- { value: "none", label: "Nenhuma" },
4431
- { value: "api_key", label: "API Key" },
4432
- { value: "oauth2", label: "OAuth 2.0" }
4433
- ];
4434
- function toolToFormState(tool) {
4435
- return {
4436
- name: tool?.name || "",
4437
- slug: tool?.slug || "",
4438
- type: tool?.type || "none",
4439
- description: tool?.description || "",
4440
- functionDefinitions: tool?.function_definitions ? formatJson(tool.function_definitions) : "",
4441
- nameError: false,
4442
- slugError: false,
4443
- typeError: false,
4444
- jsonError: false
4445
- };
3945
+ CalendarSync as CalendarSync2,
3946
+ Plug as Plug3,
3947
+ Settings as Settings3,
3948
+ RefreshCw,
3949
+ Clock,
3950
+ Plus as Plus3
3951
+ } from "lucide-react";
3952
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
3953
+ var ICON_MAP2 = {
3954
+ CalendarSync: CalendarSync2,
3955
+ Plug: Plug3,
3956
+ Settings: Settings3,
3957
+ RefreshCw,
3958
+ Clock,
3959
+ Plus: Plus3
3960
+ };
3961
+ function resolveIcon2(name) {
3962
+ return ICON_MAP2[name] ?? Plug3;
4446
3963
  }
4447
- function formatJson(str) {
4448
- try {
4449
- return JSON.stringify(JSON.parse(str), null, 2);
4450
- } catch {
4451
- return str;
3964
+ var STATE_BADGES = {
3965
+ available: {
3966
+ label: "Dispon\xEDvel",
3967
+ className: "bg-muted text-muted-foreground"
3968
+ },
3969
+ connected: {
3970
+ label: "Conectado",
3971
+ className: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"
3972
+ },
3973
+ expired: {
3974
+ label: "Expirado",
3975
+ className: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"
3976
+ },
3977
+ coming_soon: {
3978
+ label: "Em breve",
3979
+ className: "bg-muted text-muted-foreground"
4452
3980
  }
4453
- }
4454
- function slugify2(name) {
4455
- return name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4456
- }
4457
- function isValidJson(str) {
4458
- if (!str.trim()) return true;
4459
- try {
4460
- JSON.parse(str);
4461
- return true;
4462
- } catch {
4463
- return false;
3981
+ };
3982
+ function getActionLabel(card) {
3983
+ if (card.isAddNew) return "Conectar";
3984
+ switch (card.state) {
3985
+ case "available":
3986
+ return "Conectar";
3987
+ case "connected":
3988
+ return "Configurar";
3989
+ case "expired":
3990
+ return "Reconectar";
3991
+ default:
3992
+ return "";
4464
3993
  }
4465
3994
  }
4466
- function ToolFormDialog({
4467
- open,
4468
- onOpenChange,
4469
- tool,
4470
- config
4471
- }) {
4472
- const isEditing = !!tool;
4473
- const createTool = useCreateTool(config);
4474
- const updateTool = useUpdateTool(config);
4475
- const [form, setForm] = useState13(() => toolToFormState(tool));
4476
- const [slugManuallyEdited, setSlugManuallyEdited] = useState13(false);
4477
- const [lastResetKey, setLastResetKey] = useState13(
4478
- () => `${tool?.id}-${open}`
4479
- );
4480
- const resetKey = `${tool?.id}-${open}`;
4481
- if (resetKey !== lastResetKey) {
4482
- setLastResetKey(resetKey);
4483
- setForm(toolToFormState(open ? tool : void 0));
4484
- setSlugManuallyEdited(false);
4485
- }
4486
- const isPending = createTool.isPending || updateTool.isPending;
4487
- async function handleSubmit(e) {
4488
- e.preventDefault();
4489
- let hasError = false;
4490
- if (!form.name.trim()) {
4491
- setForm((prev) => ({ ...prev, nameError: true }));
4492
- hasError = true;
4493
- }
4494
- const effectiveSlug = form.slug.trim() || slugify2(form.name);
4495
- if (!effectiveSlug) {
4496
- setForm((prev) => ({ ...prev, slugError: true }));
4497
- hasError = true;
4498
- }
4499
- if (!form.type) {
4500
- setForm((prev) => ({ ...prev, typeError: true }));
4501
- hasError = true;
4502
- }
4503
- if (!isValidJson(form.functionDefinitions)) {
4504
- setForm((prev) => ({ ...prev, jsonError: true }));
4505
- hasError = true;
4506
- }
4507
- if (hasError) return;
4508
- const body = {
4509
- name: form.name.trim(),
4510
- slug: effectiveSlug,
4511
- type: form.type
4512
- };
4513
- if (form.description.trim()) body.description = form.description.trim();
4514
- else body.description = "";
4515
- if (form.functionDefinitions.trim()) {
4516
- const parsed = JSON.parse(form.functionDefinitions.trim());
4517
- body.function_definitions = JSON.stringify(parsed);
4518
- } else {
4519
- body.function_definitions = "";
4520
- }
4521
- try {
4522
- if (isEditing) {
4523
- await updateTool.mutateAsync({ id: tool.id, body });
4524
- toast10.success("Ferramenta atualizada");
4525
- } else {
4526
- await createTool.mutateAsync(
4527
- body
4528
- );
4529
- toast10.success("Ferramenta criada");
3995
+ function IntegrationCard({ card, onConnect }) {
3996
+ const { definition, state, isAddNew, accountLabel } = card;
3997
+ const Icon = resolveIcon2(definition.icon);
3998
+ const isComingSoon = state === "coming_soon";
3999
+ const actionLabel = getActionLabel(card);
4000
+ if (isAddNew) {
4001
+ return /* @__PURE__ */ jsxs15(
4002
+ "div",
4003
+ {
4004
+ className: cn(
4005
+ "group relative flex flex-col gap-3 rounded-xl border border-dashed bg-card/50 p-5 transition-shadow",
4006
+ "hover:shadow-md hover:border-solid hover:bg-card cursor-pointer"
4007
+ ),
4008
+ role: "button",
4009
+ tabIndex: 0,
4010
+ "aria-label": `Adicionar conta ${definition.name}`,
4011
+ onClick: () => onConnect(card),
4012
+ onKeyDown: (e) => {
4013
+ if (e.key === "Enter" || e.key === " ") {
4014
+ e.preventDefault();
4015
+ onConnect(card);
4016
+ }
4017
+ },
4018
+ children: [
4019
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-2", children: [
4020
+ /* @__PURE__ */ jsx17("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/5 text-primary/60", children: /* @__PURE__ */ jsx17(Icon, { className: "h-5 w-5" }) }),
4021
+ /* @__PURE__ */ jsx17(Badge9, { variant: "outline", className: "text-xs bg-muted text-muted-foreground", children: "Adicionar" })
4022
+ ] }),
4023
+ /* @__PURE__ */ jsxs15("div", { className: "space-y-1", children: [
4024
+ /* @__PURE__ */ jsx17("h3", { className: "text-sm font-semibold leading-tight text-muted-foreground", children: definition.name }),
4025
+ /* @__PURE__ */ jsxs15("p", { className: "text-xs text-muted-foreground/70 leading-relaxed flex items-center gap-1", children: [
4026
+ /* @__PURE__ */ jsx17(Plus3, { className: "h-3 w-3" }),
4027
+ "Adicionar conta"
4028
+ ] })
4029
+ ] }),
4030
+ /* @__PURE__ */ jsx17("div", { className: "mt-auto flex items-center justify-end pt-1", children: /* @__PURE__ */ jsx17(
4031
+ Button12,
4032
+ {
4033
+ variant: "outline",
4034
+ size: "sm",
4035
+ className: "text-xs",
4036
+ onClick: (e) => {
4037
+ e.stopPropagation();
4038
+ onConnect(card);
4039
+ },
4040
+ children: actionLabel
4041
+ }
4042
+ ) })
4043
+ ]
4530
4044
  }
4531
- onOpenChange(false);
4532
- } catch (err) {
4533
- toast10.error(
4534
- err instanceof Error ? err.message : isEditing ? "Erro ao atualizar ferramenta" : "Erro ao criar ferramenta"
4535
- );
4536
- }
4045
+ );
4537
4046
  }
4538
- return /* @__PURE__ */ jsx21(Dialog6, { open, onOpenChange, children: /* @__PURE__ */ jsxs19(DialogContent6, { className: "sm:max-w-lg", children: [
4539
- /* @__PURE__ */ jsx21(DialogHeader6, { children: /* @__PURE__ */ jsx21(DialogTitle6, { children: isEditing ? "Editar Ferramenta" : "Nova Ferramenta" }) }),
4540
- /* @__PURE__ */ jsxs19("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
4541
- /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4542
- /* @__PURE__ */ jsx21(Label8, { htmlFor: "tool-name", children: "Nome *" }),
4543
- /* @__PURE__ */ jsx21(
4544
- Input9,
4545
- {
4546
- id: "tool-name",
4547
- name: "name",
4548
- value: form.name,
4549
- onChange: (e) => {
4550
- const name = e.target.value;
4551
- setForm((prev) => ({
4552
- ...prev,
4553
- name,
4554
- nameError: name.trim() ? false : prev.nameError,
4555
- ...!slugManuallyEdited && !isEditing ? { slug: slugify2(name), slugError: false } : {}
4556
- }));
4557
- },
4558
- placeholder: "Ex: Google Calendar",
4559
- disabled: isPending
4560
- }
4561
- ),
4562
- form.nameError && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
4563
- ] }),
4564
- /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4565
- /* @__PURE__ */ jsx21(Label8, { htmlFor: "tool-slug", children: "Slug (identificador \xFAnico) *" }),
4566
- /* @__PURE__ */ jsx21(
4567
- Input9,
4047
+ const badge = STATE_BADGES[state];
4048
+ return /* @__PURE__ */ jsxs15(
4049
+ "div",
4050
+ {
4051
+ className: cn(
4052
+ "group relative flex flex-col gap-3 rounded-xl border bg-card p-5 transition-shadow",
4053
+ isComingSoon ? "opacity-60 cursor-default" : "hover:shadow-md cursor-pointer"
4054
+ ),
4055
+ role: "button",
4056
+ tabIndex: isComingSoon ? -1 : 0,
4057
+ "aria-label": `${definition.name}${accountLabel ? ` \u2014 ${accountLabel}` : ""} \u2014 ${badge.label}`,
4058
+ "aria-disabled": isComingSoon,
4059
+ onClick: () => !isComingSoon && onConnect(card),
4060
+ onKeyDown: (e) => {
4061
+ if (!isComingSoon && (e.key === "Enter" || e.key === " ")) {
4062
+ e.preventDefault();
4063
+ onConnect(card);
4064
+ }
4065
+ },
4066
+ children: [
4067
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-2", children: [
4068
+ /* @__PURE__ */ jsx17("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsx17(Icon, { className: "h-5 w-5" }) }),
4069
+ /* @__PURE__ */ jsx17(Badge9, { variant: "outline", className: cn("text-xs", badge.className), children: badge.label })
4070
+ ] }),
4071
+ /* @__PURE__ */ jsxs15("div", { className: "space-y-1", children: [
4072
+ /* @__PURE__ */ jsx17("h3", { className: "text-sm font-semibold leading-tight", children: definition.name }),
4073
+ accountLabel ? /* @__PURE__ */ jsx17("p", { className: "text-xs text-muted-foreground leading-relaxed truncate", title: accountLabel, children: accountLabel }) : /* @__PURE__ */ jsx17("p", { className: "text-xs text-muted-foreground leading-relaxed", children: definition.description })
4074
+ ] }),
4075
+ /* @__PURE__ */ jsx17("div", { className: "mt-auto flex items-center justify-end gap-2 pt-1", children: !isComingSoon && /* @__PURE__ */ jsx17(
4076
+ Button12,
4568
4077
  {
4569
- id: "tool-slug",
4570
- name: "slug",
4571
- value: form.slug,
4572
- onChange: (e) => {
4573
- setSlugManuallyEdited(true);
4574
- setForm((prev) => ({
4575
- ...prev,
4576
- slug: e.target.value,
4577
- slugError: e.target.value.trim() ? false : prev.slugError
4578
- }));
4078
+ variant: state === "expired" ? "destructive" : "outline",
4079
+ size: "sm",
4080
+ className: "text-xs",
4081
+ onClick: (e) => {
4082
+ e.stopPropagation();
4083
+ onConnect(card);
4579
4084
  },
4580
- placeholder: "Ex: google-calendar",
4581
- disabled: isPending
4085
+ children: actionLabel
4582
4086
  }
4583
- ),
4584
- /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: "Gerado automaticamente a partir do nome. Usado internamente para identificar a ferramenta." }),
4585
- form.slugError && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: "Slug \xE9 obrigat\xF3rio" })
4586
- ] }),
4587
- /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4588
- /* @__PURE__ */ jsx21(Label8, { htmlFor: "tool-type", children: "Tipo de Autentica\xE7\xE3o *" }),
4589
- /* @__PURE__ */ jsxs19(
4590
- Select3,
4087
+ ) })
4088
+ ]
4089
+ }
4090
+ );
4091
+ }
4092
+
4093
+ // src/components/capabilities/advanced-tab.tsx
4094
+ import { useState as useState13 } from "react";
4095
+ import { Info } from "lucide-react";
4096
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4097
+ function AdvancedTab({ config, agentId, gagentsApiUrl }) {
4098
+ const [editingTool, setEditingTool] = useState13(null);
4099
+ const [showToolForm, setShowToolForm] = useState13(false);
4100
+ function handleEditTool(tool) {
4101
+ setEditingTool(tool);
4102
+ setShowToolForm(true);
4103
+ }
4104
+ function handleToolFormOpenChange(open) {
4105
+ setShowToolForm(open);
4106
+ if (!open) setEditingTool(null);
4107
+ }
4108
+ return /* @__PURE__ */ jsxs16("div", { className: "space-y-8", children: [
4109
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-3 rounded-lg border border-blue-200 bg-blue-50 p-4 dark:border-blue-900 dark:bg-blue-950/30", children: [
4110
+ /* @__PURE__ */ jsx18(Info, { className: "mt-0.5 h-4 w-4 shrink-0 text-blue-600 dark:text-blue-400" }),
4111
+ /* @__PURE__ */ jsxs16("p", { className: "text-sm text-blue-800 dark:text-blue-300", children: [
4112
+ "Use as abas ",
4113
+ /* @__PURE__ */ jsx18("strong", { children: "Capacidades" }),
4114
+ " e ",
4115
+ /* @__PURE__ */ jsx18("strong", { children: "Integra\xE7\xF5es" }),
4116
+ " para configura\xE7\xE3o simplificada. Esta aba oferece controlo manual avan\xE7ado sobre ferramentas. As credenciais s\xE3o geridas dentro de cada ferramenta."
4117
+ ] })
4118
+ ] }),
4119
+ /* @__PURE__ */ jsxs16("section", { className: "space-y-3", children: [
4120
+ /* @__PURE__ */ jsx18("h3", { className: "text-sm font-medium", children: "Ferramentas" }),
4121
+ /* @__PURE__ */ jsx18(ToolsTable, { onEdit: handleEditTool, config })
4122
+ ] }),
4123
+ /* @__PURE__ */ jsx18(
4124
+ ToolFormDialog,
4125
+ {
4126
+ open: showToolForm,
4127
+ onOpenChange: handleToolFormOpenChange,
4128
+ tool: editingTool ?? void 0,
4129
+ config
4130
+ }
4131
+ )
4132
+ ] });
4133
+ }
4134
+
4135
+ // src/components/capabilities/integration-wizard.tsx
4136
+ import { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef2, useState as useState14 } from "react";
4137
+ import {
4138
+ Dialog as Dialog6,
4139
+ DialogContent as DialogContent6,
4140
+ DialogFooter as DialogFooter6,
4141
+ DialogHeader as DialogHeader6,
4142
+ DialogTitle as DialogTitle6,
4143
+ Button as Button14
4144
+ } from "@greatapps/greatauth-ui/ui";
4145
+ import { Loader2 as Loader29, ChevronLeft, ChevronRight, Check as Check2 } from "lucide-react";
4146
+ import { toast as toast11 } from "sonner";
4147
+
4148
+ // src/components/capabilities/wizard-steps/info-step.tsx
4149
+ import { Check, Info as Info2 } from "lucide-react";
4150
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
4151
+ function InfoStep({ integration, meta }) {
4152
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-6", children: [
4153
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-4", children: [
4154
+ meta.icon && /* @__PURE__ */ jsx19("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-muted", children: meta.icon }),
4155
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-1", children: [
4156
+ /* @__PURE__ */ jsx19("h3", { className: "text-lg font-semibold", children: integration.name }),
4157
+ /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: integration.description })
4158
+ ] })
4159
+ ] }),
4160
+ meta.capabilities.length > 0 && /* @__PURE__ */ jsxs17("div", { className: "space-y-3", children: [
4161
+ /* @__PURE__ */ jsx19("h4", { className: "text-sm font-medium", children: "O que esta integra\xE7\xE3o permite:" }),
4162
+ /* @__PURE__ */ jsx19("ul", { className: "space-y-2", children: meta.capabilities.map((cap, i) => /* @__PURE__ */ jsxs17("li", { className: "flex items-start gap-2 text-sm", children: [
4163
+ /* @__PURE__ */ jsx19(
4164
+ Check,
4591
4165
  {
4592
- value: form.type,
4593
- onValueChange: (value) => {
4594
- setForm((prev) => ({
4595
- ...prev,
4596
- type: value,
4597
- typeError: false
4598
- }));
4599
- },
4600
- disabled: isPending,
4601
- children: [
4602
- /* @__PURE__ */ jsx21(SelectTrigger3, { id: "tool-type", children: /* @__PURE__ */ jsx21(SelectValue3, { placeholder: "Selecione o tipo" }) }),
4603
- /* @__PURE__ */ jsx21(SelectContent3, { children: TOOL_AUTH_TYPES.map((t) => /* @__PURE__ */ jsx21(SelectItem3, { value: t.value, children: t.label }, t.value)) })
4604
- ]
4166
+ "aria-hidden": "true",
4167
+ className: "mt-0.5 h-4 w-4 shrink-0 text-green-600"
4605
4168
  }
4606
4169
  ),
4607
- /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: "Define se a ferramenta requer credenciais para funcionar." }),
4608
- form.typeError && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: "Tipo \xE9 obrigat\xF3rio" })
4609
- ] }),
4610
- /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4611
- /* @__PURE__ */ jsx21(Label8, { htmlFor: "tool-description", children: "Descri\xE7\xE3o" }),
4612
- /* @__PURE__ */ jsx21(
4613
- Textarea3,
4170
+ /* @__PURE__ */ jsxs17("div", { children: [
4171
+ /* @__PURE__ */ jsx19("span", { className: "font-medium", children: cap.label }),
4172
+ cap.description && /* @__PURE__ */ jsxs17("span", { className: "text-muted-foreground", children: [
4173
+ " ",
4174
+ "\u2014 ",
4175
+ cap.description
4176
+ ] })
4177
+ ] })
4178
+ ] }, i)) })
4179
+ ] }),
4180
+ meta.requirements.length > 0 && /* @__PURE__ */ jsxs17("div", { className: "space-y-3", children: [
4181
+ /* @__PURE__ */ jsx19("h4", { className: "text-sm font-medium", children: "Requisitos:" }),
4182
+ /* @__PURE__ */ jsx19("ul", { className: "space-y-2", children: meta.requirements.map((req, i) => /* @__PURE__ */ jsxs17(
4183
+ "li",
4184
+ {
4185
+ className: "flex items-start gap-2 text-sm text-muted-foreground",
4186
+ children: [
4187
+ /* @__PURE__ */ jsx19(
4188
+ Info2,
4189
+ {
4190
+ "aria-hidden": "true",
4191
+ className: "mt-0.5 h-4 w-4 shrink-0 text-blue-500"
4192
+ }
4193
+ ),
4194
+ /* @__PURE__ */ jsx19("span", { children: req })
4195
+ ]
4196
+ },
4197
+ i
4198
+ )) })
4199
+ ] })
4200
+ ] });
4201
+ }
4202
+
4203
+ // src/components/capabilities/wizard-steps/credentials-step.tsx
4204
+ import { CheckCircle2, Loader2 as Loader27, AlertCircle, Shield } from "lucide-react";
4205
+ import { Button as Button13, Input as Input10, Label as Label6 } from "@greatapps/greatauth-ui/ui";
4206
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4207
+ function CredentialsStep({
4208
+ integration,
4209
+ meta,
4210
+ oauthStatus,
4211
+ oauthResult,
4212
+ apiKey,
4213
+ onApiKeyChange,
4214
+ onStartOAuth,
4215
+ isReconnect = false
4216
+ }) {
4217
+ if (integration.authType === "oauth2") {
4218
+ return /* @__PURE__ */ jsx20(
4219
+ OAuthCredentials,
4220
+ {
4221
+ integration,
4222
+ meta,
4223
+ oauthStatus,
4224
+ oauthResult,
4225
+ onStartOAuth,
4226
+ isReconnect
4227
+ }
4228
+ );
4229
+ }
4230
+ return /* @__PURE__ */ jsx20(ApiKeyCredentials, { apiKey, onApiKeyChange });
4231
+ }
4232
+ function OAuthCredentials({
4233
+ integration,
4234
+ meta,
4235
+ oauthStatus,
4236
+ oauthResult,
4237
+ onStartOAuth,
4238
+ isReconnect
4239
+ }) {
4240
+ const providerLabel = meta.providerLabel || integration.name;
4241
+ return /* @__PURE__ */ jsxs18("div", { className: "space-y-6", children: [
4242
+ /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4243
+ /* @__PURE__ */ jsx20("h3", { className: "text-lg font-semibold", children: "Autentica\xE7\xE3o" }),
4244
+ /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: isReconnect ? `Reconecte sua conta ${providerLabel} para renovar a autoriza\xE7\xE3o.` : `Conecte sua conta ${providerLabel} para permitir o acesso.` })
4245
+ ] }),
4246
+ /* @__PURE__ */ jsxs18("div", { className: "flex flex-col items-center gap-4 rounded-lg border p-6", children: [
4247
+ oauthStatus === "idle" && /* @__PURE__ */ jsxs18(
4248
+ Button13,
4249
+ {
4250
+ onClick: onStartOAuth,
4251
+ size: "lg",
4252
+ className: "gap-2",
4253
+ children: [
4254
+ meta.icon,
4255
+ isReconnect ? `Reconectar com ${providerLabel}` : `Conectar com ${providerLabel}`
4256
+ ]
4257
+ }
4258
+ ),
4259
+ oauthStatus === "waiting" && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col items-center gap-3 text-center", children: [
4260
+ /* @__PURE__ */ jsx20(
4261
+ Loader27,
4614
4262
  {
4615
- id: "tool-description",
4616
- name: "description",
4617
- value: form.description,
4618
- onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
4619
- placeholder: "Descri\\u00e7\\u00e3o da ferramenta\\u2026",
4620
- rows: 3,
4621
- disabled: isPending
4263
+ "aria-hidden": "true",
4264
+ className: "h-8 w-8 animate-spin text-muted-foreground"
4622
4265
  }
4623
- )
4266
+ ),
4267
+ /* @__PURE__ */ jsxs18("div", { children: [
4268
+ /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium", children: "Aguardando autoriza\xE7\xE3o..." }),
4269
+ /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Complete o login na janela que foi aberta." })
4270
+ ] })
4624
4271
  ] }),
4625
- /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4626
- /* @__PURE__ */ jsx21(Label8, { htmlFor: "tool-function-defs", children: "Defini\xE7\xF5es de Fun\xE7\xE3o (JSON)" }),
4627
- /* @__PURE__ */ jsx21(
4628
- Textarea3,
4272
+ oauthStatus === "success" && oauthResult && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col items-center gap-3 text-center", children: [
4273
+ /* @__PURE__ */ jsx20(
4274
+ CheckCircle2,
4629
4275
  {
4630
- id: "tool-function-defs",
4631
- name: "functionDefs",
4632
- value: form.functionDefinitions,
4633
- onChange: (e) => {
4634
- setForm((prev) => ({
4635
- ...prev,
4636
- functionDefinitions: e.target.value,
4637
- jsonError: false
4638
- }));
4639
- },
4640
- placeholder: `[
4641
- {
4642
- "type": "function",
4643
- "function": {
4644
- "name": "nome_da_funcao",
4645
- "description": "O que a fun\xE7\xE3o faz",
4646
- "parameters": {
4647
- "type": "object",
4648
- "properties": { \u2026 },
4649
- "required": [\u2026]
4650
- }
4651
- }
4652
- }
4653
- ]`,
4654
- rows: 10,
4655
- className: "font-mono text-sm",
4656
- disabled: isPending
4276
+ "aria-hidden": "true",
4277
+ className: "h-8 w-8 text-green-600"
4657
4278
  }
4658
4279
  ),
4659
- /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: "Array de defini\xE7\xF5es no formato OpenAI Function Calling." }),
4660
- form.jsonError && /* @__PURE__ */ jsx21("p", { className: "text-sm text-destructive", children: "JSON inv\xE1lido" })
4280
+ /* @__PURE__ */ jsxs18("div", { children: [
4281
+ /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium text-green-700", children: "Conectado com sucesso!" }),
4282
+ oauthResult.email && /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: oauthResult.email })
4283
+ ] })
4661
4284
  ] }),
4662
- /* @__PURE__ */ jsxs19(DialogFooter6, { children: [
4663
- /* @__PURE__ */ jsx21(
4664
- Button13,
4285
+ oauthStatus === "error" && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col items-center gap-3 text-center", children: [
4286
+ /* @__PURE__ */ jsx20(
4287
+ AlertCircle,
4665
4288
  {
4666
- type: "button",
4667
- variant: "outline",
4668
- onClick: () => onOpenChange(false),
4669
- disabled: isPending,
4670
- children: "Cancelar"
4289
+ "aria-hidden": "true",
4290
+ className: "h-8 w-8 text-destructive"
4671
4291
  }
4672
4292
  ),
4673
- /* @__PURE__ */ jsxs19(Button13, { type: "submit", disabled: isPending, children: [
4674
- isPending ? /* @__PURE__ */ jsx21(Loader29, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null,
4675
- isEditing ? "Salvar" : "Criar"
4676
- ] })
4293
+ /* @__PURE__ */ jsxs18("div", { children: [
4294
+ /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium text-destructive", children: "Falha na conex\xE3o" }),
4295
+ oauthResult?.error && /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: oauthResult.error })
4296
+ ] }),
4297
+ /* @__PURE__ */ jsx20(Button13, { variant: "outline", onClick: onStartOAuth, size: "sm", children: "Tentar novamente" })
4298
+ ] })
4299
+ ] }),
4300
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-start gap-2 rounded-md bg-muted/50 p-3", children: [
4301
+ /* @__PURE__ */ jsx20(
4302
+ Shield,
4303
+ {
4304
+ "aria-hidden": "true",
4305
+ className: "mt-0.5 h-4 w-4 shrink-0 text-green-600"
4306
+ }
4307
+ ),
4308
+ /* @__PURE__ */ jsxs18("p", { className: "text-xs text-muted-foreground", children: [
4309
+ "Seus dados est\xE3o seguros. Usamos OAuth 2.0 para autentica\xE7\xE3o \u2014 nunca armazenamos sua senha. Voc\xEA pode revogar o acesso a qualquer momento nas configura\xE7\xF5es da sua conta ",
4310
+ providerLabel,
4311
+ "."
4677
4312
  ] })
4678
4313
  ] })
4679
- ] }) });
4314
+ ] });
4315
+ }
4316
+ function ApiKeyCredentials({
4317
+ apiKey,
4318
+ onApiKeyChange
4319
+ }) {
4320
+ return /* @__PURE__ */ jsxs18("div", { className: "space-y-6", children: [
4321
+ /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4322
+ /* @__PURE__ */ jsx20("h3", { className: "text-lg font-semibold", children: "Autentica\xE7\xE3o" }),
4323
+ /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: "Insira a chave de API para conectar a integra\xE7\xE3o." })
4324
+ ] }),
4325
+ /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4326
+ /* @__PURE__ */ jsx20(Label6, { htmlFor: "integration-api-key", children: "Chave de API" }),
4327
+ /* @__PURE__ */ jsx20(
4328
+ Input10,
4329
+ {
4330
+ id: "integration-api-key",
4331
+ type: "password",
4332
+ autoComplete: "off",
4333
+ placeholder: "Insira sua chave de API...",
4334
+ value: apiKey,
4335
+ onChange: (e) => onApiKeyChange(e.target.value)
4336
+ }
4337
+ )
4338
+ ] }),
4339
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-start gap-2 rounded-md bg-muted/50 p-3", children: [
4340
+ /* @__PURE__ */ jsx20(
4341
+ Shield,
4342
+ {
4343
+ "aria-hidden": "true",
4344
+ className: "mt-0.5 h-4 w-4 shrink-0 text-green-600"
4345
+ }
4346
+ ),
4347
+ /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Sua chave de API \xE9 armazenada de forma segura e encriptada. Nunca \xE9 exposta no frontend." })
4348
+ ] })
4349
+ ] });
4680
4350
  }
4681
4351
 
4682
- // src/components/tools/tool-credentials-form.tsx
4683
- import { useMemo as useMemo7, useState as useState14 } from "react";
4684
- import { DataTable as DataTable3 } from "@greatapps/greatauth-ui";
4352
+ // src/components/capabilities/wizard-steps/config-step.tsx
4353
+ import { Loader2 as Loader28 } from "lucide-react";
4685
4354
  import {
4686
- Input as Input10,
4687
- Button as Button14,
4688
- Badge as Badge9,
4689
- Tooltip as Tooltip4,
4690
- TooltipTrigger as TooltipTrigger4,
4691
- TooltipContent as TooltipContent4,
4692
- Dialog as Dialog7,
4693
- DialogContent as DialogContent7,
4694
- DialogHeader as DialogHeader7,
4695
- DialogTitle as DialogTitle7,
4696
- DialogFooter as DialogFooter7,
4697
- AlertDialog as AlertDialog5,
4698
- AlertDialogAction as AlertDialogAction5,
4699
- AlertDialogCancel as AlertDialogCancel5,
4700
- AlertDialogContent as AlertDialogContent5,
4701
- AlertDialogDescription as AlertDialogDescription5,
4702
- AlertDialogFooter as AlertDialogFooter5,
4703
- AlertDialogHeader as AlertDialogHeader5,
4704
- AlertDialogTitle as AlertDialogTitle5,
4705
- Select as Select4,
4706
- SelectContent as SelectContent4,
4707
- SelectItem as SelectItem4,
4708
- SelectTrigger as SelectTrigger4,
4709
- SelectValue as SelectValue4
4355
+ Label as Label7,
4356
+ Select as Select3,
4357
+ SelectContent as SelectContent3,
4358
+ SelectItem as SelectItem3,
4359
+ SelectTrigger as SelectTrigger3,
4360
+ SelectValue as SelectValue3
4710
4361
  } from "@greatapps/greatauth-ui/ui";
4711
- import { Trash2 as Trash25, Pencil as Pencil4, Link, Search as Search3 } from "lucide-react";
4712
- import { format as format3 } from "date-fns";
4713
- import { ptBR as ptBR3 } from "date-fns/locale";
4714
- import { toast as toast11 } from "sonner";
4715
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4716
- function formatDate2(dateStr) {
4717
- if (!dateStr) return "Sem expira\xE7\xE3o";
4718
- return format3(new Date(dateStr), "dd/MM/yyyy", { locale: ptBR3 });
4362
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
4363
+ function ConfigStep({
4364
+ integration,
4365
+ options,
4366
+ isLoading,
4367
+ selectedValue,
4368
+ onValueChange,
4369
+ selectLabel,
4370
+ selectPlaceholder
4371
+ }) {
4372
+ const label = selectLabel || getDefaultLabel(integration.slug);
4373
+ const placeholder = selectPlaceholder || getDefaultPlaceholder(integration.slug);
4374
+ return /* @__PURE__ */ jsxs19("div", { className: "space-y-6", children: [
4375
+ /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4376
+ /* @__PURE__ */ jsx21("h3", { className: "text-lg font-semibold", children: "Configura\xE7\xE3o" }),
4377
+ /* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "Configure as op\xE7\xF5es espec\xEDficas da integra\xE7\xE3o." })
4378
+ ] }),
4379
+ isLoading ? /* @__PURE__ */ jsxs19("div", { className: "flex flex-col items-center gap-3 py-8", children: [
4380
+ /* @__PURE__ */ jsx21(
4381
+ Loader28,
4382
+ {
4383
+ "aria-hidden": "true",
4384
+ className: "h-6 w-6 animate-spin text-muted-foreground"
4385
+ }
4386
+ ),
4387
+ /* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "Carregando op\xE7\xF5es..." })
4388
+ ] }) : options.length === 0 ? /* @__PURE__ */ jsx21("div", { className: "rounded-lg border border-dashed p-6 text-center", children: /* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "Nenhuma op\xE7\xE3o dispon\xEDvel. A configura\xE7\xE3o padr\xE3o ser\xE1 usada." }) }) : /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4389
+ /* @__PURE__ */ jsx21(Label7, { htmlFor: "integration-config-select", children: label }),
4390
+ /* @__PURE__ */ jsxs19(Select3, { value: selectedValue, onValueChange, children: [
4391
+ /* @__PURE__ */ jsx21(SelectTrigger3, { id: "integration-config-select", children: /* @__PURE__ */ jsx21(SelectValue3, { placeholder }) }),
4392
+ /* @__PURE__ */ jsx21(SelectContent3, { children: options.map((opt) => /* @__PURE__ */ jsxs19(SelectItem3, { value: opt.id, children: [
4393
+ /* @__PURE__ */ jsx21("span", { children: opt.label }),
4394
+ opt.description && /* @__PURE__ */ jsxs19("span", { className: "ml-2 text-xs text-muted-foreground", children: [
4395
+ "(",
4396
+ opt.description,
4397
+ ")"
4398
+ ] })
4399
+ ] }, opt.id)) })
4400
+ ] })
4401
+ ] })
4402
+ ] });
4719
4403
  }
4720
- function useColumns3(tools, onEdit, onConnect, onRemove) {
4721
- function getToolName(idTool) {
4722
- if (!idTool) return "\u2014";
4723
- const tool = tools.find((t) => t.id === idTool);
4724
- return tool?.name || `Ferramenta #${idTool}`;
4404
+ function getDefaultLabel(slug) {
4405
+ switch (slug) {
4406
+ case "google_calendar":
4407
+ return "Calend\xE1rio";
4408
+ default:
4409
+ return "Op\xE7\xE3o";
4725
4410
  }
4726
- function getToolType(idTool) {
4727
- if (!idTool) return null;
4728
- const tool = tools.find((t) => t.id === idTool);
4729
- return tool?.type || null;
4411
+ }
4412
+ function getDefaultPlaceholder(slug) {
4413
+ switch (slug) {
4414
+ case "google_calendar":
4415
+ return "Selecione o calend\xE1rio...";
4416
+ default:
4417
+ return "Selecione uma op\xE7\xE3o...";
4730
4418
  }
4731
- return [
4732
- {
4733
- accessorKey: "label",
4734
- header: "Label",
4735
- cell: ({ row }) => /* @__PURE__ */ jsx22("span", { className: "font-medium", children: row.original.label || "\u2014" })
4736
- },
4737
- {
4738
- accessorKey: "id_tool",
4739
- header: "Ferramenta",
4740
- cell: ({ row }) => /* @__PURE__ */ jsx22("span", { className: "text-sm", children: getToolName(row.original.id_tool) })
4741
- },
4742
- {
4743
- accessorKey: "status",
4744
- header: "Status",
4745
- cell: ({ row }) => /* @__PURE__ */ jsx22(
4746
- Badge9,
4419
+ }
4420
+
4421
+ // src/components/capabilities/wizard-steps/confirm-step.tsx
4422
+ import { CheckCircle2 as CheckCircle22 } from "lucide-react";
4423
+ import { Label as Label8 } from "@greatapps/greatauth-ui/ui";
4424
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4425
+ function ConfirmStep({
4426
+ integration,
4427
+ oauthResult,
4428
+ selectedConfigOption,
4429
+ enableOnComplete,
4430
+ onEnableChange
4431
+ }) {
4432
+ return /* @__PURE__ */ jsxs20("div", { className: "space-y-6", children: [
4433
+ /* @__PURE__ */ jsxs20("div", { className: "space-y-2", children: [
4434
+ /* @__PURE__ */ jsx22("h3", { className: "text-lg font-semibold", children: "Confirma\xE7\xE3o" }),
4435
+ /* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "Revise as configura\xE7\xF5es antes de concluir." })
4436
+ ] }),
4437
+ /* @__PURE__ */ jsxs20("div", { className: "space-y-3 rounded-lg border p-4", children: [
4438
+ /* @__PURE__ */ jsx22(SummaryRow, { label: "Integra\xE7\xE3o", value: integration.name }),
4439
+ oauthResult?.email && /* @__PURE__ */ jsx22(SummaryRow, { label: "Conta conectada", value: oauthResult.email }),
4440
+ selectedConfigOption && /* @__PURE__ */ jsx22(
4441
+ SummaryRow,
4747
4442
  {
4748
- variant: row.original.status === "active" ? "default" : "destructive",
4749
- children: row.original.status === "active" ? "Ativo" : "Expirado"
4443
+ label: getConfigLabel(integration.slug),
4444
+ value: selectedConfigOption.label
4445
+ }
4446
+ ),
4447
+ /* @__PURE__ */ jsx22(
4448
+ SummaryRow,
4449
+ {
4450
+ label: "Tipo de autentica\xE7\xE3o",
4451
+ value: integration.authType === "oauth2" ? "OAuth 2.0" : "API Key"
4750
4452
  }
4751
4453
  )
4752
- },
4753
- {
4754
- accessorKey: "expires_at",
4755
- header: "Expira em",
4756
- cell: ({ row }) => /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.expires_at) })
4757
- },
4758
- {
4759
- accessorKey: "datetime_add",
4760
- header: "Criado em",
4761
- cell: ({ row }) => /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.datetime_add) })
4762
- },
4763
- {
4764
- id: "actions",
4765
- header: "A\xE7\xF5es",
4766
- size: 100,
4767
- enableSorting: false,
4768
- cell: ({ row }) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-1", children: [
4769
- getToolType(row.original.id_tool) === "oauth2" && /* @__PURE__ */ jsxs20(Tooltip4, { children: [
4770
- /* @__PURE__ */ jsx22(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx22(
4771
- Button14,
4772
- {
4773
- variant: "ghost",
4774
- size: "icon",
4775
- className: "h-8 w-8",
4776
- "aria-label": "Vincular",
4777
- disabled: true,
4778
- children: /* @__PURE__ */ jsx22(Link, { className: "h-4 w-4" })
4779
- }
4780
- ) }),
4781
- /* @__PURE__ */ jsx22(TooltipContent4, { children: "Em breve" })
4782
- ] }),
4783
- /* @__PURE__ */ jsxs20(Tooltip4, { children: [
4784
- /* @__PURE__ */ jsx22(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx22(
4785
- Button14,
4454
+ ] }),
4455
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between rounded-lg border p-4", children: [
4456
+ /* @__PURE__ */ jsxs20("div", { className: "space-y-0.5", children: [
4457
+ /* @__PURE__ */ jsx22(Label8, { htmlFor: "enable-on-complete", className: "text-sm font-medium", children: "Ativar imediatamente" }),
4458
+ /* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: "A integra\xE7\xE3o ficar\xE1 ativa assim que concluir o assistente." })
4459
+ ] }),
4460
+ /* @__PURE__ */ jsx22(
4461
+ "button",
4462
+ {
4463
+ id: "enable-on-complete",
4464
+ role: "switch",
4465
+ type: "button",
4466
+ "aria-checked": enableOnComplete,
4467
+ onClick: () => onEnableChange(!enableOnComplete),
4468
+ className: `
4469
+ relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent
4470
+ transition-colors duration-200 ease-in-out focus-visible:outline-none focus-visible:ring-2
4471
+ focus-visible:ring-ring focus-visible:ring-offset-2
4472
+ ${enableOnComplete ? "bg-primary" : "bg-muted"}
4473
+ `,
4474
+ children: /* @__PURE__ */ jsx22(
4475
+ "span",
4786
4476
  {
4787
- variant: "ghost",
4788
- size: "icon",
4789
- className: "h-8 w-8",
4790
- "aria-label": "Editar",
4791
- onClick: () => onEdit(row.original),
4792
- children: /* @__PURE__ */ jsx22(Pencil4, { className: "h-4 w-4" })
4477
+ "aria-hidden": "true",
4478
+ className: `
4479
+ pointer-events-none inline-block h-5 w-5 transform rounded-full bg-background shadow-lg
4480
+ ring-0 transition duration-200 ease-in-out
4481
+ ${enableOnComplete ? "translate-x-5" : "translate-x-0"}
4482
+ `
4793
4483
  }
4794
- ) }),
4795
- /* @__PURE__ */ jsx22(TooltipContent4, { children: "Editar" })
4796
- ] }),
4797
- /* @__PURE__ */ jsxs20(Tooltip4, { children: [
4798
- /* @__PURE__ */ jsx22(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx22(
4799
- Button14,
4800
- {
4801
- variant: "ghost",
4802
- size: "icon",
4803
- className: "h-8 w-8 text-destructive hover:text-destructive",
4804
- "aria-label": "Excluir",
4805
- onClick: () => onRemove(row.original),
4806
- children: /* @__PURE__ */ jsx22(Trash25, { className: "h-4 w-4" })
4484
+ )
4485
+ }
4486
+ )
4487
+ ] }),
4488
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 rounded-md bg-green-50 p-3 dark:bg-green-950/20", children: [
4489
+ /* @__PURE__ */ jsx22(
4490
+ CheckCircle22,
4491
+ {
4492
+ "aria-hidden": "true",
4493
+ className: "h-4 w-4 shrink-0 text-green-600"
4494
+ }
4495
+ ),
4496
+ /* @__PURE__ */ jsx22("p", { className: "text-xs text-green-700 dark:text-green-400", children: 'Tudo pronto! Clique em "Concluir" para finalizar a configura\xE7\xE3o.' })
4497
+ ] })
4498
+ ] });
4499
+ }
4500
+ function SummaryRow({ label, value }) {
4501
+ return /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between text-sm", children: [
4502
+ /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground", children: label }),
4503
+ /* @__PURE__ */ jsx22("span", { className: "font-medium", children: value })
4504
+ ] });
4505
+ }
4506
+ function getConfigLabel(slug) {
4507
+ switch (slug) {
4508
+ case "google_calendar":
4509
+ return "Calend\xE1rio";
4510
+ default:
4511
+ return "Configura\xE7\xE3o";
4512
+ }
4513
+ }
4514
+
4515
+ // src/components/capabilities/integration-wizard.tsx
4516
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
4517
+ var STEPS = ["info", "credentials", "config", "confirm"];
4518
+ var STEP_LABELS = {
4519
+ info: "Informa\xE7\xE3o",
4520
+ credentials: "Credenciais",
4521
+ config: "Configura\xE7\xE3o",
4522
+ confirm: "Confirma\xE7\xE3o"
4523
+ };
4524
+ function IntegrationWizard({
4525
+ open,
4526
+ onOpenChange,
4527
+ integration,
4528
+ meta,
4529
+ agentId: _agentId,
4530
+ config,
4531
+ onComplete,
4532
+ gagentsApiUrl,
4533
+ existingCredentialId,
4534
+ loadConfigOptions,
4535
+ existingConfigValue
4536
+ }) {
4537
+ const isReconnect = !!existingCredentialId;
4538
+ const [currentStep, setCurrentStep] = useState14("info");
4539
+ const currentIndex = STEPS.indexOf(currentStep);
4540
+ const [oauthStatus, setOauthStatus] = useState14("idle");
4541
+ const [oauthResult, setOauthResult] = useState14(null);
4542
+ const popupRef = useRef2(null);
4543
+ const popupPollRef = useRef2(null);
4544
+ const [apiKey, setApiKey] = useState14("");
4545
+ const [configOptions, setConfigOptions] = useState14([]);
4546
+ const [configLoading, setConfigLoading] = useState14(false);
4547
+ const [selectedConfigValue, setSelectedConfigValue] = useState14("");
4548
+ const [enableOnComplete, setEnableOnComplete] = useState14(true);
4549
+ const [isSubmitting, setIsSubmitting] = useState14(false);
4550
+ useEffect5(() => {
4551
+ return () => {
4552
+ if (popupPollRef.current) {
4553
+ clearInterval(popupPollRef.current);
4554
+ }
4555
+ };
4556
+ }, []);
4557
+ useEffect5(() => {
4558
+ if (open) {
4559
+ setCurrentStep("info");
4560
+ setOauthStatus("idle");
4561
+ setOauthResult(null);
4562
+ setApiKey("");
4563
+ setConfigOptions([]);
4564
+ setConfigLoading(false);
4565
+ setSelectedConfigValue(existingConfigValue ?? "");
4566
+ setEnableOnComplete(true);
4567
+ setIsSubmitting(false);
4568
+ } else {
4569
+ if (popupRef.current && !popupRef.current.closed) {
4570
+ popupRef.current.close();
4571
+ }
4572
+ if (popupPollRef.current) {
4573
+ clearInterval(popupPollRef.current);
4574
+ popupPollRef.current = null;
4575
+ }
4576
+ }
4577
+ }, [open]);
4578
+ const handleOAuthMessage = useCallback6(
4579
+ (event) => {
4580
+ try {
4581
+ if (event.origin !== new URL(gagentsApiUrl).origin) return;
4582
+ } catch {
4583
+ return;
4584
+ }
4585
+ if (!event.data || typeof event.data !== "object") return;
4586
+ const msg = event.data;
4587
+ if (msg.type !== "oauth-callback") return;
4588
+ if (msg.success) {
4589
+ setOauthStatus("success");
4590
+ setOauthResult({
4591
+ success: true,
4592
+ email: msg.email,
4593
+ credentialId: msg.credentialId
4594
+ });
4595
+ const credId = msg.credentialId || existingCredentialId;
4596
+ if (credId && loadConfigOptions && meta.hasConfigStep) {
4597
+ setConfigLoading(true);
4598
+ loadConfigOptions(credId).then((opts) => {
4599
+ setConfigOptions(opts);
4600
+ if (opts.length === 1) {
4601
+ setSelectedConfigValue(opts[0].id);
4807
4602
  }
4808
- ) }),
4809
- /* @__PURE__ */ jsx22(TooltipContent4, { children: "Remover" })
4810
- ] })
4811
- ] })
4812
- }
4813
- ];
4814
- }
4815
- function ToolCredentialsForm({
4816
- credentials,
4817
- isLoading,
4818
- config,
4819
- gagentsApiUrl,
4820
- createOpen: externalCreateOpen,
4821
- onCreateOpenChange
4822
- }) {
4823
- const createMutation = useCreateToolCredential(config);
4824
- const updateMutation = useUpdateToolCredential(config);
4825
- const deleteMutation = useDeleteToolCredential(config);
4826
- const { data: toolsData } = useTools(config);
4827
- const tools = (toolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
4828
- const [search, setSearch] = useState14("");
4829
- const [internalCreateOpen, setInternalCreateOpen] = useState14(false);
4830
- const showCreateDialog = externalCreateOpen ?? internalCreateOpen;
4831
- const setShowCreateDialog = onCreateOpenChange ?? setInternalCreateOpen;
4832
- const [createForm, setCreateForm] = useState14({
4833
- id_tool: "",
4834
- label: "",
4835
- credentials_encrypted: "",
4836
- expires_at: ""
4837
- });
4838
- const [editTarget, setEditTarget] = useState14(null);
4839
- const [editForm, setEditForm] = useState14({
4840
- id_tool: "",
4841
- label: "",
4842
- credentials_encrypted: "",
4843
- expires_at: "",
4844
- status: ""
4845
- });
4846
- const [removeTarget, setRemoveTarget] = useState14(null);
4847
- const internalToolIds = useMemo7(() => {
4848
- const allRawTools = toolsData?.data || [];
4849
- return new Set(
4850
- allRawTools.filter((t) => t.slug?.startsWith("gclinic_")).map((t) => t.id)
4851
- );
4852
- }, [toolsData]);
4853
- const filteredCredentials = useMemo7(() => {
4854
- const visible = credentials.filter(
4855
- (cred) => !cred.id_tool || !internalToolIds.has(cred.id_tool)
4856
- );
4857
- if (!search) return visible;
4858
- const term = search.toLowerCase();
4859
- return visible.filter((cred) => {
4860
- const toolName = tools.find((t) => t.id === cred.id_tool)?.name || "";
4861
- return (cred.label || "").toLowerCase().includes(term) || toolName.toLowerCase().includes(term);
4862
- });
4863
- }, [credentials, search, tools, internalToolIds]);
4864
- const columns = useColumns3(
4865
- tools,
4866
- (cred) => startEdit(cred),
4867
- (cred) => handleConnect(cred),
4868
- (cred) => setRemoveTarget(cred)
4603
+ }).catch(() => setConfigOptions([])).finally(() => setConfigLoading(false));
4604
+ }
4605
+ setTimeout(() => {
4606
+ setCurrentStep(meta.hasConfigStep ? "config" : "confirm");
4607
+ }, 1200);
4608
+ } else {
4609
+ setOauthStatus("error");
4610
+ setOauthResult({
4611
+ success: false,
4612
+ error: msg.error || "Falha na autoriza\xE7\xE3o"
4613
+ });
4614
+ }
4615
+ },
4616
+ [gagentsApiUrl, existingCredentialId, meta.hasConfigStep, loadConfigOptions]
4869
4617
  );
4870
- async function handleCreate() {
4871
- const idTool = parseInt(createForm.id_tool, 10);
4872
- if (!idTool || !createForm.label.trim() || !createForm.credentials_encrypted.trim()) return;
4618
+ useEffect5(() => {
4619
+ if (!open) return;
4620
+ window.addEventListener("message", handleOAuthMessage);
4621
+ return () => window.removeEventListener("message", handleOAuthMessage);
4622
+ }, [open, handleOAuthMessage]);
4623
+ async function startOAuth() {
4624
+ const { language = "pt-br", idWl = 1, accountId, token } = config;
4625
+ setOauthStatus("waiting");
4873
4626
  try {
4874
- const result = await createMutation.mutateAsync({
4875
- id_tool: idTool,
4876
- label: createForm.label.trim(),
4877
- credentials_encrypted: createForm.credentials_encrypted.trim(),
4878
- ...createForm.expires_at ? { expires_at: createForm.expires_at } : {}
4627
+ let authorizeUrl = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${accountId}/oauth/authorize/${integration.slug}`;
4628
+ if (existingCredentialId) {
4629
+ authorizeUrl += `?credential_id=${existingCredentialId}`;
4630
+ }
4631
+ const response = await fetch(authorizeUrl, {
4632
+ headers: { Authorization: `Bearer ${token}` }
4879
4633
  });
4880
- if (result.status === 1) {
4881
- toast11.success("Credencial criada");
4882
- setShowCreateDialog(false);
4883
- setCreateForm({ id_tool: "", label: "", credentials_encrypted: "", expires_at: "" });
4884
- } else {
4885
- toast11.error(result.message || "Erro ao criar credencial");
4634
+ const result = await response.json();
4635
+ if (result.status !== 1 || !result.data?.auth_url) {
4636
+ setOauthStatus("error");
4637
+ setOauthResult({
4638
+ success: false,
4639
+ error: result.message || "Erro ao obter URL de autoriza\xE7\xE3o"
4640
+ });
4641
+ return;
4886
4642
  }
4887
- } catch {
4888
- toast11.error("Erro ao criar credencial");
4643
+ const popup = window.open(
4644
+ result.data.auth_url,
4645
+ "oauth-popup",
4646
+ "width=500,height=600,scrollbars=yes,resizable=yes"
4647
+ );
4648
+ popupRef.current = popup;
4649
+ if (popup) {
4650
+ if (popupPollRef.current) {
4651
+ clearInterval(popupPollRef.current);
4652
+ }
4653
+ popupPollRef.current = setInterval(() => {
4654
+ if (popup.closed) {
4655
+ if (popupPollRef.current) {
4656
+ clearInterval(popupPollRef.current);
4657
+ popupPollRef.current = null;
4658
+ }
4659
+ setOauthStatus(
4660
+ (prev) => prev === "waiting" ? "error" : prev
4661
+ );
4662
+ setOauthResult(
4663
+ (prev) => prev === null ? { success: false, error: "Janela fechada antes de concluir" } : prev
4664
+ );
4665
+ }
4666
+ }, 500);
4667
+ }
4668
+ } catch (err) {
4669
+ setOauthStatus("error");
4670
+ setOauthResult({
4671
+ success: false,
4672
+ error: "Erro de rede ao obter URL de autoriza\xE7\xE3o"
4673
+ });
4889
4674
  }
4890
4675
  }
4891
- function startEdit(cred) {
4892
- setEditTarget(cred);
4893
- setEditForm({
4894
- id_tool: cred.id_tool ? String(cred.id_tool) : "",
4895
- label: cred.label || "",
4896
- credentials_encrypted: "",
4897
- expires_at: cred.expires_at || "",
4898
- status: cred.status
4899
- });
4900
- }
4901
- async function handleSaveEdit() {
4902
- if (!editTarget) return;
4903
- const body = {};
4904
- const newIdTool = editForm.id_tool ? parseInt(editForm.id_tool, 10) : null;
4905
- if (newIdTool && newIdTool !== editTarget.id_tool) {
4906
- body.id_tool = newIdTool;
4907
- }
4908
- if (editForm.label.trim() && editForm.label.trim() !== (editTarget.label || "")) {
4909
- body.label = editForm.label.trim();
4910
- }
4911
- if (editForm.credentials_encrypted.trim()) {
4912
- body.credentials_encrypted = editForm.credentials_encrypted.trim();
4676
+ function canAdvance() {
4677
+ switch (currentStep) {
4678
+ case "info":
4679
+ return true;
4680
+ case "credentials":
4681
+ if (integration.authType === "oauth2") {
4682
+ return oauthStatus === "success";
4683
+ }
4684
+ return apiKey.trim().length > 0;
4685
+ case "config":
4686
+ return true;
4687
+ case "confirm":
4688
+ return true;
4689
+ default:
4690
+ return false;
4913
4691
  }
4914
- if (editForm.expires_at !== (editTarget.expires_at || "")) {
4915
- body.expires_at = editForm.expires_at || null;
4692
+ }
4693
+ function goNext() {
4694
+ if (!canAdvance()) return;
4695
+ if (currentStep === "credentials" && !meta.hasConfigStep) {
4696
+ setCurrentStep("confirm");
4697
+ return;
4916
4698
  }
4917
- if (editForm.status && editForm.status !== editTarget.status) {
4918
- body.status = editForm.status;
4699
+ const nextIndex = currentIndex + 1;
4700
+ if (nextIndex < STEPS.length) {
4701
+ setCurrentStep(STEPS[nextIndex]);
4919
4702
  }
4920
- if (Object.keys(body).length === 0) {
4921
- setEditTarget(null);
4703
+ }
4704
+ function goPrev() {
4705
+ if (currentStep === "confirm" && !meta.hasConfigStep) {
4706
+ setCurrentStep("credentials");
4922
4707
  return;
4923
4708
  }
4924
- try {
4925
- const result = await updateMutation.mutateAsync({
4926
- id: editTarget.id,
4927
- body
4928
- });
4929
- if (result.status === 1) {
4930
- toast11.success("Credencial atualizada");
4931
- setEditTarget(null);
4932
- } else {
4933
- toast11.error(result.message || "Erro ao atualizar credencial");
4934
- }
4935
- } catch {
4936
- toast11.error("Erro ao atualizar credencial");
4709
+ const prevIndex = currentIndex - 1;
4710
+ if (prevIndex >= 0) {
4711
+ setCurrentStep(STEPS[prevIndex]);
4937
4712
  }
4938
4713
  }
4939
- async function handleRemove() {
4940
- if (!removeTarget) return;
4714
+ async function handleComplete() {
4715
+ setIsSubmitting(true);
4941
4716
  try {
4942
- const result = await deleteMutation.mutateAsync(removeTarget.id);
4943
- if (result.status === 1) {
4944
- toast11.success("Credencial removida");
4945
- } else {
4946
- toast11.error(result.message || "Erro ao remover credencial");
4947
- }
4717
+ onComplete();
4718
+ onOpenChange(false);
4719
+ toast11.success(
4720
+ `${integration.name} ${isReconnect ? "reconectado" : "configurado"} com sucesso!`
4721
+ );
4948
4722
  } catch {
4949
- toast11.error("Erro ao remover credencial");
4723
+ toast11.error("Erro ao finalizar configura\xE7\xE3o");
4950
4724
  } finally {
4951
- setRemoveTarget(null);
4725
+ setIsSubmitting(false);
4952
4726
  }
4953
4727
  }
4954
- function handleConnect(cred) {
4955
- if (!config.accountId || !config.token) return;
4956
- const language = config.language ?? "pt-br";
4957
- const idWl = config.idWl ?? 1;
4958
- const url = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${config.accountId}/oauth/connect?id_tool=${cred.id_tool}`;
4959
- window.open(url, "_blank");
4960
- }
4961
- return /* @__PURE__ */ jsxs20("div", { className: "space-y-4", children: [
4962
- /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs20("div", { className: "relative flex-1 max-w-md", children: [
4963
- /* @__PURE__ */ jsx22(Search3, { "aria-hidden": "true", className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
4964
- /* @__PURE__ */ jsx22(
4965
- Input10,
4728
+ const selectedConfigOption = configOptions.find((o) => o.id === selectedConfigValue) || null;
4729
+ const isLastStep = currentStep === "confirm";
4730
+ const effectiveSteps = meta.hasConfigStep ? STEPS : STEPS.filter((s) => s !== "config");
4731
+ return /* @__PURE__ */ jsx23(Dialog6, { open, onOpenChange, children: /* @__PURE__ */ jsxs21(DialogContent6, { className: "sm:max-w-lg", children: [
4732
+ /* @__PURE__ */ jsx23(DialogHeader6, { children: /* @__PURE__ */ jsx23(DialogTitle6, { children: integration.name }) }),
4733
+ /* @__PURE__ */ jsx23(StepIndicator, { steps: effectiveSteps, currentStep }),
4734
+ /* @__PURE__ */ jsxs21("div", { className: "min-h-[280px] py-2", children: [
4735
+ currentStep === "info" && /* @__PURE__ */ jsx23(
4736
+ InfoStep,
4966
4737
  {
4967
- placeholder: "Buscar credenciais\\u2026",
4968
- "aria-label": "Buscar credenciais",
4969
- name: "search",
4970
- autoComplete: "off",
4971
- value: search,
4972
- onChange: (e) => setSearch(e.target.value),
4973
- className: "pl-9"
4738
+ integration,
4739
+ meta
4740
+ }
4741
+ ),
4742
+ currentStep === "credentials" && /* @__PURE__ */ jsx23(
4743
+ CredentialsStep,
4744
+ {
4745
+ integration,
4746
+ meta,
4747
+ oauthStatus,
4748
+ oauthResult,
4749
+ apiKey,
4750
+ onApiKeyChange: setApiKey,
4751
+ onStartOAuth: startOAuth,
4752
+ isReconnect
4753
+ }
4754
+ ),
4755
+ currentStep === "config" && /* @__PURE__ */ jsx23(
4756
+ ConfigStep,
4757
+ {
4758
+ integration,
4759
+ options: configOptions,
4760
+ isLoading: configLoading,
4761
+ selectedValue: selectedConfigValue,
4762
+ onValueChange: setSelectedConfigValue
4763
+ }
4764
+ ),
4765
+ currentStep === "confirm" && /* @__PURE__ */ jsx23(
4766
+ ConfirmStep,
4767
+ {
4768
+ integration,
4769
+ oauthResult,
4770
+ selectedConfigOption,
4771
+ enableOnComplete,
4772
+ onEnableChange: setEnableOnComplete
4773
+ }
4774
+ )
4775
+ ] }),
4776
+ /* @__PURE__ */ jsxs21(DialogFooter6, { className: "flex-row justify-between sm:justify-between", children: [
4777
+ /* @__PURE__ */ jsx23("div", { children: currentStep === "info" ? /* @__PURE__ */ jsx23(
4778
+ Button14,
4779
+ {
4780
+ type: "button",
4781
+ variant: "outline",
4782
+ onClick: () => onOpenChange(false),
4783
+ children: "Cancelar"
4784
+ }
4785
+ ) : /* @__PURE__ */ jsxs21(
4786
+ Button14,
4787
+ {
4788
+ type: "button",
4789
+ variant: "outline",
4790
+ onClick: goPrev,
4791
+ className: "gap-1",
4792
+ children: [
4793
+ /* @__PURE__ */ jsx23(ChevronLeft, { "aria-hidden": "true", className: "h-4 w-4" }),
4794
+ "Voltar"
4795
+ ]
4796
+ }
4797
+ ) }),
4798
+ /* @__PURE__ */ jsx23("div", { children: isLastStep ? /* @__PURE__ */ jsxs21(
4799
+ Button14,
4800
+ {
4801
+ type: "button",
4802
+ onClick: handleComplete,
4803
+ disabled: isSubmitting,
4804
+ className: "gap-1",
4805
+ children: [
4806
+ isSubmitting ? /* @__PURE__ */ jsx23(
4807
+ Loader29,
4808
+ {
4809
+ "aria-hidden": "true",
4810
+ className: "h-4 w-4 animate-spin"
4811
+ }
4812
+ ) : /* @__PURE__ */ jsx23(Check2, { "aria-hidden": "true", className: "h-4 w-4" }),
4813
+ "Concluir"
4814
+ ]
4815
+ }
4816
+ ) : /* @__PURE__ */ jsxs21(
4817
+ Button14,
4818
+ {
4819
+ type: "button",
4820
+ onClick: goNext,
4821
+ disabled: !canAdvance(),
4822
+ className: "gap-1",
4823
+ children: [
4824
+ "Continuar",
4825
+ /* @__PURE__ */ jsx23(ChevronRight, { "aria-hidden": "true", className: "h-4 w-4" })
4826
+ ]
4974
4827
  }
4975
- )
4976
- ] }) }),
4977
- /* @__PURE__ */ jsx22(
4978
- DataTable3,
4979
- {
4980
- columns,
4981
- data: filteredCredentials,
4982
- isLoading,
4983
- emptyMessage: "Nenhuma credencial encontrada"
4984
- }
4985
- ),
4986
- /* @__PURE__ */ jsx22(Dialog7, { open: showCreateDialog, onOpenChange: setShowCreateDialog, children: /* @__PURE__ */ jsxs20(DialogContent7, { children: [
4987
- /* @__PURE__ */ jsx22(DialogHeader7, { children: /* @__PURE__ */ jsx22(DialogTitle7, { children: "Nova Credencial" }) }),
4988
- /* @__PURE__ */ jsxs20("div", { className: "space-y-4", children: [
4989
- /* @__PURE__ */ jsxs20("div", { children: [
4990
- /* @__PURE__ */ jsx22("label", { htmlFor: "cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
4991
- /* @__PURE__ */ jsxs20(
4992
- Select4,
4993
- {
4994
- value: createForm.id_tool,
4995
- onValueChange: (val) => setCreateForm((f) => ({ ...f, id_tool: val })),
4996
- children: [
4997
- /* @__PURE__ */ jsx22(SelectTrigger4, { id: "cred-tool", children: /* @__PURE__ */ jsx22(SelectValue4, { placeholder: "Selecione a ferramenta" }) }),
4998
- /* @__PURE__ */ jsx22(SelectContent4, { children: tools.map((tool) => /* @__PURE__ */ jsx22(SelectItem4, { value: String(tool.id), children: tool.name }, tool.id)) })
4999
- ]
5000
- }
5001
- )
5002
- ] }),
5003
- /* @__PURE__ */ jsxs20("div", { children: [
5004
- /* @__PURE__ */ jsx22("label", { htmlFor: "cred-label", className: "mb-1 block text-sm font-medium", children: "Label *" }),
5005
- /* @__PURE__ */ jsx22(
5006
- Input10,
4828
+ ) })
4829
+ ] })
4830
+ ] }) });
4831
+ }
4832
+ function StepIndicator({
4833
+ steps,
4834
+ currentStep
4835
+ }) {
4836
+ const currentIndex = steps.indexOf(currentStep);
4837
+ return /* @__PURE__ */ jsx23(
4838
+ "div",
4839
+ {
4840
+ className: "flex items-center justify-center gap-1 py-2",
4841
+ role: "list",
4842
+ "aria-label": "Passos do assistente",
4843
+ children: steps.map((step, i) => {
4844
+ const isCompleted = i < currentIndex;
4845
+ const isCurrent = step === currentStep;
4846
+ return /* @__PURE__ */ jsxs21("div", { className: "flex items-center", role: "listitem", children: [
4847
+ /* @__PURE__ */ jsx23(
4848
+ "div",
5007
4849
  {
5008
- id: "cred-label",
5009
- name: "label",
5010
- value: createForm.label,
5011
- onChange: (e) => setCreateForm((f) => ({ ...f, label: e.target.value })),
5012
- placeholder: "Ex: Google Calendar - Cl\xEDnica S\xE3o Paulo"
4850
+ className: `
4851
+ flex h-7 w-7 items-center justify-center rounded-full text-xs font-medium
4852
+ transition-colors duration-200
4853
+ ${isCurrent ? "bg-primary text-primary-foreground" : isCompleted ? "bg-green-600 text-white" : "bg-muted text-muted-foreground"}
4854
+ `,
4855
+ "aria-current": isCurrent ? "step" : void 0,
4856
+ "aria-label": `${STEP_LABELS[step]}${isCompleted ? " (conclu\xEDdo)" : isCurrent ? " (atual)" : ""}`,
4857
+ children: isCompleted ? /* @__PURE__ */ jsx23(Check2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : i + 1
5013
4858
  }
5014
- )
5015
- ] }),
5016
- /* @__PURE__ */ jsxs20("div", { children: [
5017
- /* @__PURE__ */ jsx22("label", { htmlFor: "cred-credential", className: "mb-1 block text-sm font-medium", children: "Credencial *" }),
5018
- /* @__PURE__ */ jsx22(
5019
- Input10,
4859
+ ),
4860
+ /* @__PURE__ */ jsx23(
4861
+ "span",
5020
4862
  {
5021
- id: "cred-credential",
5022
- name: "credential",
5023
- autoComplete: "off",
5024
- type: "password",
5025
- value: createForm.credentials_encrypted,
5026
- onChange: (e) => setCreateForm((f) => ({
5027
- ...f,
5028
- credentials_encrypted: e.target.value
5029
- })),
5030
- placeholder: "Credencial encriptada"
4863
+ className: `
4864
+ ml-1.5 hidden text-xs sm:inline
4865
+ ${isCurrent ? "font-medium text-foreground" : "text-muted-foreground"}
4866
+ `,
4867
+ children: STEP_LABELS[step]
5031
4868
  }
5032
- )
5033
- ] }),
5034
- /* @__PURE__ */ jsxs20("div", { children: [
5035
- /* @__PURE__ */ jsx22("label", { htmlFor: "cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o (opcional)" }),
5036
- /* @__PURE__ */ jsx22(
5037
- Input10,
4869
+ ),
4870
+ i < steps.length - 1 && /* @__PURE__ */ jsx23(
4871
+ "div",
5038
4872
  {
5039
- id: "cred-expires",
5040
- name: "expires",
5041
- type: "date",
5042
- value: createForm.expires_at,
5043
- onChange: (e) => setCreateForm((f) => ({ ...f, expires_at: e.target.value }))
4873
+ className: `
4874
+ mx-2 h-px w-6
4875
+ ${i < currentIndex ? "bg-green-600" : "bg-border"}
4876
+ `
5044
4877
  }
5045
4878
  )
5046
- ] })
5047
- ] }),
5048
- /* @__PURE__ */ jsxs20(DialogFooter7, { children: [
5049
- /* @__PURE__ */ jsx22(
5050
- Button14,
5051
- {
5052
- variant: "outline",
5053
- onClick: () => setShowCreateDialog(false),
5054
- children: "Cancelar"
5055
- }
5056
- ),
5057
- /* @__PURE__ */ jsx22(
5058
- Button14,
5059
- {
5060
- onClick: handleCreate,
5061
- disabled: !createForm.id_tool || !createForm.label.trim() || !createForm.credentials_encrypted.trim() || createMutation.isPending,
5062
- children: "Criar"
5063
- }
5064
- )
5065
- ] })
5066
- ] }) }),
5067
- /* @__PURE__ */ jsx22(
5068
- Dialog7,
5069
- {
5070
- open: !!editTarget,
5071
- onOpenChange: (open) => !open && setEditTarget(null),
5072
- children: /* @__PURE__ */ jsxs20(DialogContent7, { children: [
5073
- /* @__PURE__ */ jsx22(DialogHeader7, { children: /* @__PURE__ */ jsx22(DialogTitle7, { children: "Editar Credencial" }) }),
5074
- /* @__PURE__ */ jsxs20("div", { className: "space-y-4", children: [
5075
- /* @__PURE__ */ jsxs20("div", { children: [
5076
- /* @__PURE__ */ jsx22("label", { htmlFor: "edit-cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
5077
- /* @__PURE__ */ jsxs20(
5078
- Select4,
5079
- {
5080
- value: editForm.id_tool,
5081
- onValueChange: (val) => setEditForm((f) => ({ ...f, id_tool: val })),
5082
- children: [
5083
- /* @__PURE__ */ jsx22(SelectTrigger4, { id: "edit-cred-tool", children: /* @__PURE__ */ jsx22(SelectValue4, { placeholder: "Selecione a ferramenta" }) }),
5084
- /* @__PURE__ */ jsx22(SelectContent4, { children: tools.map((tool) => /* @__PURE__ */ jsx22(SelectItem4, { value: String(tool.id), children: tool.name }, tool.id)) })
5085
- ]
5086
- }
5087
- )
5088
- ] }),
5089
- /* @__PURE__ */ jsxs20("div", { children: [
5090
- /* @__PURE__ */ jsx22("label", { htmlFor: "edit-cred-label", className: "mb-1 block text-sm font-medium", children: "Label" }),
5091
- /* @__PURE__ */ jsx22(
5092
- Input10,
5093
- {
5094
- id: "edit-cred-label",
5095
- name: "label",
5096
- value: editForm.label,
5097
- onChange: (e) => setEditForm((f) => ({ ...f, label: e.target.value })),
5098
- placeholder: "Label da credencial"
5099
- }
5100
- )
5101
- ] }),
5102
- /* @__PURE__ */ jsxs20("div", { children: [
5103
- /* @__PURE__ */ jsx22("label", { htmlFor: "edit-cred-credential", className: "mb-1 block text-sm font-medium", children: "Nova Credencial (vazio = manter atual)" }),
5104
- /* @__PURE__ */ jsx22(
5105
- Input10,
5106
- {
5107
- id: "edit-cred-credential",
5108
- name: "credential",
5109
- autoComplete: "off",
5110
- type: "password",
5111
- value: editForm.credentials_encrypted,
5112
- onChange: (e) => setEditForm((f) => ({
5113
- ...f,
5114
- credentials_encrypted: e.target.value
5115
- })),
5116
- placeholder: "Nova credencial"
5117
- }
5118
- )
5119
- ] }),
5120
- /* @__PURE__ */ jsxs20("div", { children: [
5121
- /* @__PURE__ */ jsx22("label", { htmlFor: "edit-cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o" }),
5122
- /* @__PURE__ */ jsx22(
5123
- Input10,
5124
- {
5125
- id: "edit-cred-expires",
5126
- name: "expires",
5127
- type: "date",
5128
- value: editForm.expires_at,
5129
- onChange: (e) => setEditForm((f) => ({ ...f, expires_at: e.target.value }))
5130
- }
5131
- )
5132
- ] }),
5133
- /* @__PURE__ */ jsxs20("div", { children: [
5134
- /* @__PURE__ */ jsx22("label", { htmlFor: "edit-cred-status", className: "mb-1 block text-sm font-medium", children: "Status" }),
5135
- /* @__PURE__ */ jsxs20(
5136
- Select4,
5137
- {
5138
- value: editForm.status || void 0,
5139
- onValueChange: (val) => setEditForm((f) => ({
5140
- ...f,
5141
- status: val
5142
- })),
5143
- children: [
5144
- /* @__PURE__ */ jsx22(SelectTrigger4, { id: "edit-cred-status", children: /* @__PURE__ */ jsx22(SelectValue4, {}) }),
5145
- /* @__PURE__ */ jsxs20(SelectContent4, { children: [
5146
- /* @__PURE__ */ jsx22(SelectItem4, { value: "active", children: "Ativo" }),
5147
- /* @__PURE__ */ jsx22(SelectItem4, { value: "expired", children: "Expirado" })
5148
- ] })
5149
- ]
5150
- }
5151
- )
5152
- ] })
5153
- ] }),
5154
- /* @__PURE__ */ jsxs20(DialogFooter7, { children: [
5155
- /* @__PURE__ */ jsx22(Button14, { variant: "outline", onClick: () => setEditTarget(null), children: "Cancelar" }),
5156
- /* @__PURE__ */ jsx22(
5157
- Button14,
5158
- {
5159
- onClick: handleSaveEdit,
5160
- disabled: updateMutation.isPending,
5161
- children: "Salvar"
5162
- }
5163
- )
5164
- ] })
5165
- ] })
5166
- }
5167
- ),
5168
- /* @__PURE__ */ jsx22(
5169
- AlertDialog5,
5170
- {
5171
- open: !!removeTarget,
5172
- onOpenChange: (open) => !open && setRemoveTarget(null),
5173
- children: /* @__PURE__ */ jsxs20(AlertDialogContent5, { children: [
5174
- /* @__PURE__ */ jsxs20(AlertDialogHeader5, { children: [
5175
- /* @__PURE__ */ jsx22(AlertDialogTitle5, { children: "Remover credencial?" }),
5176
- /* @__PURE__ */ jsx22(AlertDialogDescription5, { children: "A credencial ser\xE1 removida permanentemente." })
5177
- ] }),
5178
- /* @__PURE__ */ jsxs20(AlertDialogFooter5, { children: [
5179
- /* @__PURE__ */ jsx22(AlertDialogCancel5, { children: "Cancelar" }),
5180
- /* @__PURE__ */ jsx22(
5181
- AlertDialogAction5,
5182
- {
5183
- onClick: handleRemove,
5184
- disabled: deleteMutation.isPending,
5185
- children: "Remover"
5186
- }
5187
- )
5188
- ] })
5189
- ] })
5190
- }
5191
- )
5192
- ] });
5193
- }
5194
-
5195
- // src/components/capabilities/advanced-tab.tsx
5196
- import { useState as useState15 } from "react";
5197
- import { Info as Info2 } from "lucide-react";
5198
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
5199
- function AdvancedTab({ config, agentId, gagentsApiUrl }) {
5200
- const [editingTool, setEditingTool] = useState15(null);
5201
- const [showToolForm, setShowToolForm] = useState15(false);
5202
- function handleEditTool(tool) {
5203
- setEditingTool(tool);
5204
- setShowToolForm(true);
5205
- }
5206
- function handleToolFormOpenChange(open) {
5207
- setShowToolForm(open);
5208
- if (!open) setEditingTool(null);
5209
- }
5210
- return /* @__PURE__ */ jsxs21("div", { className: "space-y-8", children: [
5211
- /* @__PURE__ */ jsxs21("div", { className: "flex items-start gap-3 rounded-lg border border-blue-200 bg-blue-50 p-4 dark:border-blue-900 dark:bg-blue-950/30", children: [
5212
- /* @__PURE__ */ jsx23(Info2, { className: "mt-0.5 h-4 w-4 shrink-0 text-blue-600 dark:text-blue-400" }),
5213
- /* @__PURE__ */ jsxs21("p", { className: "text-sm text-blue-800 dark:text-blue-300", children: [
5214
- "Use as abas ",
5215
- /* @__PURE__ */ jsx23("strong", { children: "Capacidades" }),
5216
- " e ",
5217
- /* @__PURE__ */ jsx23("strong", { children: "Integra\xE7\xF5es" }),
5218
- " para configura\xE7\xE3o simplificada. Esta aba oferece controlo manual avan\xE7ado sobre ferramentas. As credenciais s\xE3o geridas dentro de cada ferramenta."
5219
- ] })
5220
- ] }),
5221
- /* @__PURE__ */ jsxs21("section", { className: "space-y-3", children: [
5222
- /* @__PURE__ */ jsx23("h3", { className: "text-sm font-medium", children: "Ferramentas" }),
5223
- /* @__PURE__ */ jsx23(ToolsTable, { onEdit: handleEditTool, config })
5224
- ] }),
5225
- /* @__PURE__ */ jsx23(
5226
- ToolFormDialog,
5227
- {
5228
- open: showToolForm,
5229
- onOpenChange: handleToolFormOpenChange,
5230
- tool: editingTool ?? void 0,
5231
- config
5232
- }
5233
- )
5234
- ] });
4879
+ ] }, step);
4880
+ })
4881
+ }
4882
+ );
5235
4883
  }
5236
4884
 
5237
4885
  // src/pages/agents-page.tsx
5238
- import { useState as useState16 } from "react";
4886
+ import { useState as useState15 } from "react";
5239
4887
  import { Button as Button15 } from "@greatapps/greatauth-ui/ui";
5240
4888
  import { Plus as Plus4 } from "lucide-react";
5241
4889
  import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
@@ -5245,7 +4893,7 @@ function AgentsPage({
5245
4893
  title = "Agentes AI",
5246
4894
  subtitle = "Gerencie seus agentes de atendimento inteligente"
5247
4895
  }) {
5248
- const [createOpen, setCreateOpen] = useState16(false);
4896
+ const [createOpen, setCreateOpen] = useState15(false);
5249
4897
  return /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-4 p-4 md:p-6", children: [
5250
4898
  /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between", children: [
5251
4899
  /* @__PURE__ */ jsxs22("div", { children: [
@@ -5270,10 +4918,10 @@ function AgentsPage({
5270
4918
  }
5271
4919
 
5272
4920
  // src/pages/agent-detail-page.tsx
5273
- import { useState as useState17 } from "react";
4921
+ import { useState as useState16 } from "react";
5274
4922
  import { Badge as Badge10, Button as Button16, Skeleton as Skeleton7 } from "@greatapps/greatauth-ui/ui";
5275
4923
  import { EntityAvatar as EntityAvatar2 } from "@greatapps/greatauth-ui";
5276
- import { ArrowLeft, Pencil as Pencil5 } from "lucide-react";
4924
+ import { ArrowLeft, Pencil as Pencil4 } from "lucide-react";
5277
4925
  import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
5278
4926
  function AgentDetailPage({
5279
4927
  config,
@@ -5282,7 +4930,7 @@ function AgentDetailPage({
5282
4930
  renderChatLink
5283
4931
  }) {
5284
4932
  const { data: agent, isLoading } = useAgent(config, agentId);
5285
- const [editOpen, setEditOpen] = useState17(false);
4933
+ const [editOpen, setEditOpen] = useState16(false);
5286
4934
  if (isLoading) {
5287
4935
  return /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-4 p-4", children: [
5288
4936
  /* @__PURE__ */ jsx25(Skeleton7, { className: "h-4 w-32" }),
@@ -5335,7 +4983,7 @@ function AgentDetailPage({
5335
4983
  className: "shrink-0 self-start",
5336
4984
  onClick: () => setEditOpen(true),
5337
4985
  children: [
5338
- /* @__PURE__ */ jsx25(Pencil5, { className: "mr-2 h-4 w-4" }),
4986
+ /* @__PURE__ */ jsx25(Pencil4, { className: "mr-2 h-4 w-4" }),
5339
4987
  "Editar"
5340
4988
  ]
5341
4989
  }
@@ -5363,55 +5011,23 @@ function AgentDetailPage({
5363
5011
  }
5364
5012
 
5365
5013
  // src/pages/agent-capabilities-page.tsx
5366
- import { useState as useState18, useCallback as useCallback7 } from "react";
5367
5014
  import {
5368
5015
  Tabs as Tabs2,
5369
5016
  TabsList as TabsList2,
5370
5017
  TabsTrigger as TabsTrigger2,
5371
5018
  TabsContent as TabsContent2
5372
5019
  } from "@greatapps/greatauth-ui/ui";
5373
- import { Blocks as Blocks2, Plug as Plug4, Settings as Settings3 } from "lucide-react";
5020
+ import { Blocks as Blocks2, Plug as Plug4, Settings as Settings4 } from "lucide-react";
5374
5021
  import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
5375
- function defaultResolveWizardMeta(card) {
5376
- return {
5377
- capabilities: [
5378
- { label: card.definition.name, description: card.definition.description }
5379
- ],
5380
- requirements: [],
5381
- hasConfigStep: false
5382
- };
5383
- }
5384
5022
  function AgentCapabilitiesPage({
5385
5023
  config,
5386
5024
  agentId,
5387
- gagentsApiUrl,
5388
- resolveWizardMeta = defaultResolveWizardMeta,
5389
- loadConfigOptions,
5390
- onWizardComplete
5025
+ gagentsApiUrl
5391
5026
  }) {
5392
- const [wizardOpen, setWizardOpen] = useState18(false);
5393
- const [activeCard, setActiveCard] = useState18(null);
5394
- const handleConnect = useCallback7(
5395
- (card) => {
5396
- setActiveCard(card);
5397
- setWizardOpen(true);
5398
- },
5399
- []
5400
- );
5401
- const handleWizardComplete = useCallback7(() => {
5402
- setWizardOpen(false);
5403
- setActiveCard(null);
5404
- onWizardComplete?.();
5405
- }, [onWizardComplete]);
5406
- const handleWizardOpenChange = useCallback7((open) => {
5407
- setWizardOpen(open);
5408
- if (!open) setActiveCard(null);
5409
- }, []);
5410
- const wizardMeta = activeCard ? resolveWizardMeta(activeCard) : null;
5411
5027
  return /* @__PURE__ */ jsxs24("div", { className: "space-y-4", children: [
5412
5028
  /* @__PURE__ */ jsxs24("div", { children: [
5413
5029
  /* @__PURE__ */ jsx26("h2", { className: "text-lg font-semibold", children: "Capacidades e Integra\xE7\xF5es" }),
5414
- /* @__PURE__ */ jsx26("p", { className: "text-sm text-muted-foreground", children: "Configure o que este agente pode fazer e quais servi\xE7os externos ele utiliza." })
5030
+ /* @__PURE__ */ jsx26("p", { className: "text-sm text-muted-foreground", children: "Configure o que este agente pode fazer e quais integra\xE7\xF5es ele utiliza." })
5415
5031
  ] }),
5416
5032
  /* @__PURE__ */ jsxs24(Tabs2, { defaultValue: "capacidades", children: [
5417
5033
  /* @__PURE__ */ jsxs24(TabsList2, { children: [
@@ -5424,19 +5040,12 @@ function AgentCapabilitiesPage({
5424
5040
  "Integra\xE7\xF5es"
5425
5041
  ] }),
5426
5042
  /* @__PURE__ */ jsxs24(TabsTrigger2, { value: "avancado", className: "flex items-center gap-1.5", children: [
5427
- /* @__PURE__ */ jsx26(Settings3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
5043
+ /* @__PURE__ */ jsx26(Settings4, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
5428
5044
  "Avan\xE7ado"
5429
5045
  ] })
5430
5046
  ] }),
5431
5047
  /* @__PURE__ */ jsx26(TabsContent2, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx26(CapabilitiesTab, { config, agentId }) }),
5432
- /* @__PURE__ */ jsx26(TabsContent2, { value: "integracoes", className: "mt-4", children: /* @__PURE__ */ jsx26(
5433
- IntegrationsTab,
5434
- {
5435
- config,
5436
- agentId,
5437
- onConnect: handleConnect
5438
- }
5439
- ) }),
5048
+ /* @__PURE__ */ jsx26(TabsContent2, { value: "integracoes", className: "mt-4", children: /* @__PURE__ */ jsx26(IntegrationsTab, { config, agentId }) }),
5440
5049
  /* @__PURE__ */ jsx26(TabsContent2, { value: "avancado", className: "mt-4", children: /* @__PURE__ */ jsx26(
5441
5050
  AdvancedTab,
5442
5051
  {
@@ -5445,27 +5054,12 @@ function AgentCapabilitiesPage({
5445
5054
  gagentsApiUrl
5446
5055
  }
5447
5056
  ) })
5448
- ] }),
5449
- activeCard && wizardMeta && /* @__PURE__ */ jsx26(
5450
- IntegrationWizard,
5451
- {
5452
- open: wizardOpen,
5453
- onOpenChange: handleWizardOpenChange,
5454
- integration: activeCard.definition,
5455
- meta: wizardMeta,
5456
- agentId,
5457
- config,
5458
- onComplete: handleWizardComplete,
5459
- gagentsApiUrl,
5460
- existingCredentialId: activeCard.credential?.id,
5461
- loadConfigOptions
5462
- }
5463
- )
5057
+ ] })
5464
5058
  ] });
5465
5059
  }
5466
5060
 
5467
5061
  // src/pages/tools-page.tsx
5468
- import { useState as useState19 } from "react";
5062
+ import { useState as useState17 } from "react";
5469
5063
  import { Button as Button17 } from "@greatapps/greatauth-ui/ui";
5470
5064
  import { Plus as Plus5 } from "lucide-react";
5471
5065
  import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
@@ -5474,8 +5068,8 @@ function ToolsPage({
5474
5068
  title = "Ferramentas",
5475
5069
  subtitle = "Gerencie as ferramentas dispon\xEDveis para seus agentes"
5476
5070
  }) {
5477
- const [createOpen, setCreateOpen] = useState19(false);
5478
- const [editTool, setEditTool] = useState19(void 0);
5071
+ const [createOpen, setCreateOpen] = useState17(false);
5072
+ const [editTool, setEditTool] = useState17(void 0);
5479
5073
  return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-4 p-4 md:p-6", children: [
5480
5074
  /* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between", children: [
5481
5075
  /* @__PURE__ */ jsxs25("div", { children: [
@@ -5509,9 +5103,6 @@ function ToolsPage({
5509
5103
  }
5510
5104
 
5511
5105
  // src/pages/credentials-page.tsx
5512
- import { useState as useState20 } from "react";
5513
- import { Button as Button18 } from "@greatapps/greatauth-ui/ui";
5514
- import { Plus as Plus6 } from "lucide-react";
5515
5106
  import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
5516
5107
  function CredentialsPage({
5517
5108
  config,
@@ -5520,44 +5111,34 @@ function CredentialsPage({
5520
5111
  subtitle = "Gerencie as credenciais de autentica\xE7\xE3o das ferramentas"
5521
5112
  }) {
5522
5113
  const { data: credentialsData, isLoading: credentialsLoading } = useToolCredentials(config);
5523
- const [createOpen, setCreateOpen] = useState20(false);
5524
5114
  const credentials = credentialsData?.data || [];
5525
5115
  return /* @__PURE__ */ jsxs26("div", { className: "flex flex-col gap-4 p-4 md:p-6", children: [
5526
- /* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between", children: [
5527
- /* @__PURE__ */ jsxs26("div", { children: [
5528
- /* @__PURE__ */ jsx28("h1", { className: "text-xl font-semibold", children: title }),
5529
- /* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: subtitle })
5530
- ] }),
5531
- /* @__PURE__ */ jsxs26(Button18, { onClick: () => setCreateOpen(true), size: "sm", children: [
5532
- /* @__PURE__ */ jsx28(Plus6, { className: "mr-2 h-4 w-4" }),
5533
- "Nova Credencial"
5534
- ] })
5535
- ] }),
5116
+ /* @__PURE__ */ jsx28("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs26("div", { children: [
5117
+ /* @__PURE__ */ jsx28("h1", { className: "text-xl font-semibold", children: title }),
5118
+ /* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: subtitle })
5119
+ ] }) }),
5536
5120
  /* @__PURE__ */ jsx28(
5537
5121
  ToolCredentialsForm,
5538
5122
  {
5539
5123
  config,
5540
5124
  gagentsApiUrl,
5541
5125
  credentials,
5542
- isLoading: credentialsLoading,
5543
- createOpen,
5544
- onCreateOpenChange: setCreateOpen
5126
+ isLoading: credentialsLoading
5545
5127
  }
5546
5128
  )
5547
5129
  ] });
5548
5130
  }
5549
5131
 
5550
5132
  // src/pages/integrations-management-page.tsx
5551
- import { useState as useState21, useMemo as useMemo8 } from "react";
5133
+ import { useMemo as useMemo8, useCallback as useCallback7, useState as useState18 } from "react";
5552
5134
  import {
5553
5135
  Badge as Badge11,
5554
- Button as Button19,
5555
5136
  Tabs as Tabs3,
5556
5137
  TabsContent as TabsContent3,
5557
5138
  TabsList as TabsList3,
5558
5139
  TabsTrigger as TabsTrigger3
5559
5140
  } from "@greatapps/greatauth-ui/ui";
5560
- import { Plus as Plus7, Plug as Plug5, KeyRound, Info as Info3 } from "lucide-react";
5141
+ import { Plug as Plug5, KeyRound, Info as Info3, Loader2 as Loader210 } from "lucide-react";
5561
5142
  import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
5562
5143
  function useCredentialAgentSummary(credentials, tools, agents) {
5563
5144
  return useMemo8(() => {
@@ -5578,18 +5159,48 @@ function useCredentialAgentSummary(credentials, tools, agents) {
5578
5159
  function IntegrationsManagementPage({
5579
5160
  config,
5580
5161
  gagentsApiUrl,
5581
- onConnect,
5162
+ resolveWizardMeta,
5163
+ loadConfigOptions,
5164
+ onWizardComplete,
5582
5165
  title = "Integra\xE7\xF5es e Credenciais",
5583
5166
  subtitle = "Gerencie todas as integra\xE7\xF5es e credenciais da conta."
5584
5167
  }) {
5585
5168
  const { data: credentialsData, isLoading: credentialsLoading } = useToolCredentials(config);
5586
5169
  const { data: agentsData } = useAgents(config);
5587
5170
  const { data: toolsData } = useTools(config);
5588
- const [createOpen, setCreateOpen] = useState21(false);
5171
+ const { cards, isLoading: cardsLoading } = useIntegrationState(config, null);
5172
+ const [wizardOpen, setWizardOpen] = useState18(false);
5173
+ const [activeCard, setActiveCard] = useState18(null);
5589
5174
  const credentials = credentialsData?.data || [];
5590
5175
  const agents = agentsData?.data || [];
5591
5176
  const tools = toolsData?.data || [];
5592
5177
  const summary = useCredentialAgentSummary(credentials, tools, agents);
5178
+ const handleConnect = useCallback7((card) => {
5179
+ setActiveCard(card);
5180
+ setWizardOpen(true);
5181
+ }, []);
5182
+ const handleWizardClose = useCallback7((open) => {
5183
+ if (!open) {
5184
+ setActiveCard(null);
5185
+ }
5186
+ setWizardOpen(open);
5187
+ }, []);
5188
+ const handleWizardComplete = useCallback7(() => {
5189
+ setWizardOpen(false);
5190
+ setActiveCard(null);
5191
+ onWizardComplete?.();
5192
+ }, [onWizardComplete]);
5193
+ const wizardMeta = activeCard ? resolveWizardMeta?.(activeCard) ?? {
5194
+ capabilities: [],
5195
+ requirements: [],
5196
+ hasConfigStep: false
5197
+ } : null;
5198
+ const connectedCards = cards.filter(
5199
+ (c) => !c.isAddNew && (c.state === "connected" || c.state === "expired")
5200
+ );
5201
+ const otherCards = cards.filter(
5202
+ (c) => c.isAddNew || c.state === "coming_soon"
5203
+ );
5593
5204
  return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-4 p-4 md:p-6", children: [
5594
5205
  /* @__PURE__ */ jsx29("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs27("div", { children: [
5595
5206
  /* @__PURE__ */ jsx29("h1", { className: "text-xl font-semibold", children: title }),
@@ -5606,15 +5217,36 @@ function IntegrationsManagementPage({
5606
5217
  "Credenciais"
5607
5218
  ] })
5608
5219
  ] }),
5609
- /* @__PURE__ */ jsx29(TabsContent3, { value: "integrations", className: "mt-4", children: /* @__PURE__ */ jsx29(
5610
- IntegrationsTab,
5611
- {
5612
- config,
5613
- agentId: null,
5614
- onConnect: onConnect ?? (() => {
5615
- })
5616
- }
5617
- ) }),
5220
+ /* @__PURE__ */ jsx29(TabsContent3, { value: "integrations", className: "mt-4", children: cardsLoading ? /* @__PURE__ */ jsx29("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx29(Loader210, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : cards.length === 0 ? /* @__PURE__ */ jsxs27("div", { className: "flex flex-col items-center justify-center gap-3 py-16 text-muted-foreground", children: [
5221
+ /* @__PURE__ */ jsx29(Plug5, { className: "h-10 w-10" }),
5222
+ /* @__PURE__ */ jsx29("p", { className: "text-sm", children: "Nenhuma integra\xE7\xE3o dispon\xEDvel" })
5223
+ ] }) : /* @__PURE__ */ jsxs27("div", { className: "space-y-6", children: [
5224
+ connectedCards.length > 0 && /* @__PURE__ */ jsxs27("div", { children: [
5225
+ /* @__PURE__ */ jsx29("h3", { className: "mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: "Contas conectadas" }),
5226
+ /* @__PURE__ */ jsx29("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: connectedCards.map((card) => /* @__PURE__ */ jsx29(
5227
+ IntegrationCard,
5228
+ {
5229
+ card,
5230
+ onConnect: handleConnect
5231
+ },
5232
+ `${card.definition.slug}-cred-${card.credentialId}`
5233
+ )) })
5234
+ ] }),
5235
+ otherCards.length > 0 && /* @__PURE__ */ jsxs27("div", { children: [
5236
+ connectedCards.length > 0 && /* @__PURE__ */ jsx29("h3", { className: "mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: "Adicionar integra\xE7\xE3o" }),
5237
+ /* @__PURE__ */ jsx29("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: otherCards.map((card) => {
5238
+ const key = card.isAddNew ? `${card.definition.slug}-add-new` : card.definition.slug;
5239
+ return /* @__PURE__ */ jsx29(
5240
+ IntegrationCard,
5241
+ {
5242
+ card,
5243
+ onConnect: handleConnect
5244
+ },
5245
+ key
5246
+ );
5247
+ }) })
5248
+ ] })
5249
+ ] }) }),
5618
5250
  /* @__PURE__ */ jsxs27(TabsContent3, { value: "credentials", className: "mt-4", children: [
5619
5251
  !credentialsLoading && /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-4 rounded-lg border bg-muted/50 px-4 py-3 mb-4", children: [
5620
5252
  /* @__PURE__ */ jsx29(Info3, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
@@ -5635,23 +5267,32 @@ function IntegrationsManagementPage({
5635
5267
  ] })
5636
5268
  ] })
5637
5269
  ] }),
5638
- /* @__PURE__ */ jsx29("div", { className: "flex items-center justify-end mb-4", children: /* @__PURE__ */ jsxs27(Button19, { onClick: () => setCreateOpen(true), size: "sm", children: [
5639
- /* @__PURE__ */ jsx29(Plus7, { className: "mr-2 h-4 w-4" }),
5640
- "Nova Credencial"
5641
- ] }) }),
5642
5270
  /* @__PURE__ */ jsx29(
5643
5271
  ToolCredentialsForm,
5644
5272
  {
5645
5273
  config,
5646
5274
  gagentsApiUrl,
5647
5275
  credentials,
5648
- isLoading: credentialsLoading,
5649
- createOpen,
5650
- onCreateOpenChange: setCreateOpen
5276
+ isLoading: credentialsLoading
5651
5277
  }
5652
5278
  )
5653
5279
  ] })
5654
- ] })
5280
+ ] }),
5281
+ activeCard && wizardMeta && /* @__PURE__ */ jsx29(
5282
+ IntegrationWizard,
5283
+ {
5284
+ open: wizardOpen,
5285
+ onOpenChange: handleWizardClose,
5286
+ integration: activeCard.definition,
5287
+ meta: wizardMeta,
5288
+ agentId: 0,
5289
+ config,
5290
+ gagentsApiUrl,
5291
+ existingCredentialId: activeCard.credentialId,
5292
+ onComplete: handleWizardComplete,
5293
+ loadConfigOptions
5294
+ }
5295
+ )
5655
5296
  ] });
5656
5297
  }
5657
5298
  export {