@greatapps/greatagents-ui 0.3.10 → 0.3.11

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
@@ -2498,7 +2498,7 @@ function AgentConversationsPanel({
2498
2498
  }
2499
2499
 
2500
2500
  // src/pages/agent-capabilities-page.tsx
2501
- import { useState as useState14, useCallback as useCallback6 } from "react";
2501
+ import { useState as useState13, useCallback as useCallback6 } from "react";
2502
2502
  import {
2503
2503
  Tabs,
2504
2504
  TabsList,
@@ -2508,7 +2508,7 @@ import {
2508
2508
  import { Blocks, Plug as Plug3, Settings as Settings3 } from "lucide-react";
2509
2509
 
2510
2510
  // src/components/capabilities/capabilities-tab.tsx
2511
- import { useState as useState8, useCallback as useCallback4, useRef as useRef2, useEffect as useEffect4, useMemo as useMemo5 } from "react";
2511
+ import { useState as useState8, useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo5 } from "react";
2512
2512
  import {
2513
2513
  Accordion,
2514
2514
  AccordionItem,
@@ -2526,7 +2526,8 @@ import {
2526
2526
  Settings,
2527
2527
  HeartHandshake,
2528
2528
  Package,
2529
- ChevronDown as ChevronDown2
2529
+ ChevronDown as ChevronDown2,
2530
+ Loader2 as Loader24
2530
2531
  } from "lucide-react";
2531
2532
  import { toast as toast6 } from "sonner";
2532
2533
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
@@ -2587,7 +2588,6 @@ function CapabilitiesTab({ config, agentId }) {
2587
2588
  const [localState, setLocalState] = useState8(/* @__PURE__ */ new Map());
2588
2589
  const [serverState, setServerState] = useState8(/* @__PURE__ */ new Map());
2589
2590
  const [initialized, setInitialized] = useState8(false);
2590
- const debounceRef = useRef2(null);
2591
2591
  useEffect4(() => {
2592
2592
  if (agentCaps && !initialized) {
2593
2593
  const state = buildStateFromAgent(agentCaps);
@@ -2603,37 +2603,11 @@ function CapabilitiesTab({ config, agentId }) {
2603
2603
  () => initialized && !statesEqual(localState, serverState),
2604
2604
  [localState, serverState, initialized]
2605
2605
  );
2606
- const scheduleSave = useCallback4(
2607
- (nextState) => {
2608
- if (debounceRef.current) clearTimeout(debounceRef.current);
2609
- debounceRef.current = setTimeout(() => {
2610
- const payload = stateToPayload(nextState);
2611
- updateMutation.mutate(
2612
- { agentId, payload },
2613
- {
2614
- onSuccess: () => {
2615
- setServerState(cloneState(nextState));
2616
- toast6.success("Capacidades salvas");
2617
- },
2618
- onError: () => {
2619
- setLocalState(cloneState(serverState));
2620
- toast6.error("Erro ao salvar capacidades");
2621
- }
2622
- }
2623
- );
2624
- }, 500);
2625
- },
2626
- [agentId, updateMutation, serverState]
2627
- );
2628
2606
  const updateState = useCallback4(
2629
2607
  (updater) => {
2630
- setLocalState((prev) => {
2631
- const next = updater(prev);
2632
- scheduleSave(next);
2633
- return next;
2634
- });
2608
+ setLocalState((prev) => updater(prev));
2635
2609
  },
2636
- [scheduleSave]
2610
+ []
2637
2611
  );
2638
2612
  const toggleModule = useCallback4(
2639
2613
  (mod, enabled) => {
@@ -2685,11 +2659,9 @@ function CapabilitiesTab({ config, agentId }) {
2685
2659
  updateState(() => /* @__PURE__ */ new Map());
2686
2660
  }, [updateState]);
2687
2661
  const discard = useCallback4(() => {
2688
- if (debounceRef.current) clearTimeout(debounceRef.current);
2689
2662
  setLocalState(cloneState(serverState));
2690
2663
  }, [serverState]);
2691
2664
  const saveNow = useCallback4(() => {
2692
- if (debounceRef.current) clearTimeout(debounceRef.current);
2693
2665
  const payload = stateToPayload(localState);
2694
2666
  updateMutation.mutate(
2695
2667
  { agentId, payload },
@@ -2771,19 +2743,14 @@ function CapabilitiesTab({ config, agentId }) {
2771
2743
  cat.slug
2772
2744
  );
2773
2745
  }) }),
2774
- hasChanges && /* @__PURE__ */ jsxs8("div", { className: "sticky bottom-0 bg-background border-t py-3 px-4 -mx-4 flex items-center justify-between", children: [
2775
- /* @__PURE__ */ jsx10("span", { className: "text-sm text-muted-foreground", children: "Voc\xEA tem altera\xE7\xF5es n\xE3o salvas." }),
2776
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2777
- /* @__PURE__ */ jsx10(Button7, { variant: "outline", size: "sm", onClick: discard, children: "Descartar" }),
2778
- /* @__PURE__ */ jsx10(
2779
- Button7,
2780
- {
2781
- size: "sm",
2782
- onClick: saveNow,
2783
- disabled: updateMutation.isPending,
2784
- children: updateMutation.isPending ? "Salvando..." : "Salvar"
2785
- }
2786
- )
2746
+ hasChanges && /* @__PURE__ */ jsxs8("div", { className: "sticky bottom-0 z-10 flex items-center justify-between gap-2 rounded-lg border bg-background p-3 shadow-sm", children: [
2747
+ /* @__PURE__ */ jsx10("p", { className: "text-sm text-muted-foreground", children: "Voc\xEA tem altera\xE7\xF5es n\xE3o salvas." }),
2748
+ /* @__PURE__ */ jsxs8("div", { className: "flex gap-2", children: [
2749
+ /* @__PURE__ */ jsx10(Button7, { variant: "ghost", size: "sm", onClick: discard, disabled: updateMutation.isPending, children: "Descartar" }),
2750
+ /* @__PURE__ */ jsxs8(Button7, { size: "sm", onClick: saveNow, disabled: updateMutation.isPending, children: [
2751
+ updateMutation.isPending && /* @__PURE__ */ jsx10(Loader24, { className: "mr-2 h-4 w-4 animate-spin" }),
2752
+ "Salvar"
2753
+ ] })
2787
2754
  ] })
2788
2755
  ] })
2789
2756
  ] });
@@ -3022,7 +2989,7 @@ function IntegrationCard({ card, onConnect }) {
3022
2989
  }
3023
2990
 
3024
2991
  // src/components/capabilities/integrations-tab.tsx
3025
- import { Plug as Plug2, Loader2 as Loader24 } from "lucide-react";
2992
+ import { Plug as Plug2, Loader2 as Loader25 } from "lucide-react";
3026
2993
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
3027
2994
  function getCardKey(card) {
3028
2995
  if (card.credentialId) {
@@ -3040,7 +3007,7 @@ function IntegrationsTab({
3040
3007
  }) {
3041
3008
  const { cards, isLoading } = useIntegrationState(config, agentId);
3042
3009
  if (isLoading) {
3043
- return /* @__PURE__ */ jsx12("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx12(Loader24, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
3010
+ 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" }) });
3044
3011
  }
3045
3012
  if (cards.length === 0) {
3046
3013
  return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center justify-center gap-3 py-16 text-muted-foreground", children: [
@@ -3081,7 +3048,7 @@ function IntegrationsTab({
3081
3048
  }
3082
3049
 
3083
3050
  // src/components/capabilities/integration-wizard.tsx
3084
- import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef3, useState as useState9 } from "react";
3051
+ import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef2, useState as useState9 } from "react";
3085
3052
  import {
3086
3053
  Dialog as Dialog4,
3087
3054
  DialogContent as DialogContent4,
@@ -3090,7 +3057,7 @@ import {
3090
3057
  DialogTitle as DialogTitle4,
3091
3058
  Button as Button10
3092
3059
  } from "@greatapps/greatauth-ui/ui";
3093
- import { Loader2 as Loader27, ChevronLeft, ChevronRight, Check as Check2 } from "lucide-react";
3060
+ import { Loader2 as Loader28, ChevronLeft, ChevronRight, Check as Check2 } from "lucide-react";
3094
3061
  import { toast as toast7 } from "sonner";
3095
3062
 
3096
3063
  // src/components/capabilities/wizard-steps/info-step.tsx
@@ -3149,7 +3116,7 @@ function InfoStep({ integration, meta }) {
3149
3116
  }
3150
3117
 
3151
3118
  // src/components/capabilities/wizard-steps/credentials-step.tsx
3152
- import { CheckCircle2, Loader2 as Loader25, AlertCircle, Shield } from "lucide-react";
3119
+ import { CheckCircle2, Loader2 as Loader26, AlertCircle, Shield } from "lucide-react";
3153
3120
  import { Button as Button9, Input as Input6, Label as Label4 } from "@greatapps/greatauth-ui/ui";
3154
3121
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3155
3122
  function CredentialsStep({
@@ -3206,7 +3173,7 @@ function OAuthCredentials({
3206
3173
  ),
3207
3174
  oauthStatus === "waiting" && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center gap-3 text-center", children: [
3208
3175
  /* @__PURE__ */ jsx14(
3209
- Loader25,
3176
+ Loader26,
3210
3177
  {
3211
3178
  "aria-hidden": "true",
3212
3179
  className: "h-8 w-8 animate-spin text-muted-foreground"
@@ -3298,7 +3265,7 @@ function ApiKeyCredentials({
3298
3265
  }
3299
3266
 
3300
3267
  // src/components/capabilities/wizard-steps/config-step.tsx
3301
- import { Loader2 as Loader26 } from "lucide-react";
3268
+ import { Loader2 as Loader27 } from "lucide-react";
3302
3269
  import {
3303
3270
  Label as Label5,
3304
3271
  Select,
@@ -3326,7 +3293,7 @@ function ConfigStep({
3326
3293
  ] }),
3327
3294
  isLoading ? /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-3 py-8", children: [
3328
3295
  /* @__PURE__ */ jsx15(
3329
- Loader26,
3296
+ Loader27,
3330
3297
  {
3331
3298
  "aria-hidden": "true",
3332
3299
  className: "h-6 w-6 animate-spin text-muted-foreground"
@@ -3487,8 +3454,8 @@ function IntegrationWizard({
3487
3454
  const currentIndex = STEPS.indexOf(currentStep);
3488
3455
  const [oauthStatus, setOauthStatus] = useState9("idle");
3489
3456
  const [oauthResult, setOauthResult] = useState9(null);
3490
- const popupRef = useRef3(null);
3491
- const popupPollRef = useRef3(null);
3457
+ const popupRef = useRef2(null);
3458
+ const popupPollRef = useRef2(null);
3492
3459
  const [apiKey, setApiKey] = useState9("");
3493
3460
  const [configOptions, setConfigOptions] = useState9([]);
3494
3461
  const [configLoading, setConfigLoading] = useState9(false);
@@ -3752,7 +3719,7 @@ function IntegrationWizard({
3752
3719
  className: "gap-1",
3753
3720
  children: [
3754
3721
  isSubmitting ? /* @__PURE__ */ jsx17(
3755
- Loader27,
3722
+ Loader28,
3756
3723
  {
3757
3724
  "aria-hidden": "true",
3758
3725
  className: "h-4 w-4 animate-spin"
@@ -3831,7 +3798,7 @@ function StepIndicator({
3831
3798
  }
3832
3799
 
3833
3800
  // src/components/capabilities/advanced-tab.tsx
3834
- import { useState as useState13 } from "react";
3801
+ import { useState as useState12 } from "react";
3835
3802
 
3836
3803
  // src/components/tools/tools-table.tsx
3837
3804
  import { useMemo as useMemo6, useState as useState10 } from "react";
@@ -4023,1011 +3990,821 @@ function ToolsTable({ onEdit, config }) {
4023
3990
  ] });
4024
3991
  }
4025
3992
 
4026
- // src/components/tools/tool-credentials-form.tsx
4027
- import { useMemo as useMemo7, useState as useState11 } from "react";
4028
- import { DataTable as DataTable3 } from "@greatapps/greatauth-ui";
3993
+ // src/components/tools/tool-form-dialog.tsx
3994
+ import { useState as useState11 } from "react";
4029
3995
  import {
4030
- Input as Input8,
4031
- Button as Button12,
4032
- Badge as Badge8,
4033
- Tooltip as Tooltip4,
4034
- TooltipTrigger as TooltipTrigger4,
4035
- TooltipContent as TooltipContent4,
4036
3996
  Dialog as Dialog5,
4037
3997
  DialogContent as DialogContent5,
4038
3998
  DialogHeader as DialogHeader5,
4039
3999
  DialogTitle as DialogTitle5,
4040
4000
  DialogFooter as DialogFooter5,
4041
- AlertDialog as AlertDialog4,
4042
- AlertDialogAction as AlertDialogAction4,
4043
- AlertDialogCancel as AlertDialogCancel4,
4044
- AlertDialogContent as AlertDialogContent4,
4045
- AlertDialogDescription as AlertDialogDescription4,
4046
- AlertDialogFooter as AlertDialogFooter4,
4047
- AlertDialogHeader as AlertDialogHeader4,
4048
- AlertDialogTitle as AlertDialogTitle4,
4001
+ Button as Button12,
4002
+ Input as Input8,
4003
+ Textarea as Textarea2,
4004
+ Label as Label7,
4049
4005
  Select as Select2,
4050
4006
  SelectContent as SelectContent2,
4051
4007
  SelectItem as SelectItem2,
4052
4008
  SelectTrigger as SelectTrigger2,
4053
4009
  SelectValue as SelectValue2
4054
4010
  } from "@greatapps/greatauth-ui/ui";
4055
- import { Trash2 as Trash24, Pencil as Pencil4, Link, Search as Search3 } from "lucide-react";
4056
- import { format as format3 } from "date-fns";
4057
- import { ptBR as ptBR3 } from "date-fns/locale";
4011
+ import { Loader2 as Loader29 } from "lucide-react";
4058
4012
  import { toast as toast9 } from "sonner";
4059
4013
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
4060
- function formatDate2(dateStr) {
4061
- if (!dateStr) return "Sem expira\xE7\xE3o";
4062
- return format3(new Date(dateStr), "dd/MM/yyyy", { locale: ptBR3 });
4014
+ var TOOL_AUTH_TYPES = [
4015
+ { value: "none", label: "Nenhuma" },
4016
+ { value: "api_key", label: "API Key" },
4017
+ { value: "oauth2", label: "OAuth 2.0" }
4018
+ ];
4019
+ function toolToFormState(tool) {
4020
+ return {
4021
+ name: tool?.name || "",
4022
+ slug: tool?.slug || "",
4023
+ type: tool?.type || "none",
4024
+ description: tool?.description || "",
4025
+ functionDefinitions: tool?.function_definitions ? formatJson(tool.function_definitions) : "",
4026
+ nameError: false,
4027
+ slugError: false,
4028
+ typeError: false,
4029
+ jsonError: false
4030
+ };
4063
4031
  }
4064
- function useColumns3(tools, onEdit, onConnect, onRemove) {
4065
- function getToolName(idTool) {
4066
- if (!idTool) return "\u2014";
4067
- const tool = tools.find((t) => t.id === idTool);
4068
- return tool?.name || `Ferramenta #${idTool}`;
4032
+ function formatJson(str) {
4033
+ try {
4034
+ return JSON.stringify(JSON.parse(str), null, 2);
4035
+ } catch {
4036
+ return str;
4069
4037
  }
4070
- function getToolType(idTool) {
4071
- if (!idTool) return null;
4072
- const tool = tools.find((t) => t.id === idTool);
4073
- return tool?.type || null;
4038
+ }
4039
+ function slugify2(name) {
4040
+ return name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4041
+ }
4042
+ function isValidJson(str) {
4043
+ if (!str.trim()) return true;
4044
+ try {
4045
+ JSON.parse(str);
4046
+ return true;
4047
+ } catch {
4048
+ return false;
4074
4049
  }
4075
- return [
4076
- {
4077
- accessorKey: "label",
4078
- header: "Label",
4079
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "font-medium", children: row.original.label || "\u2014" })
4080
- },
4081
- {
4082
- accessorKey: "id_tool",
4083
- header: "Ferramenta",
4084
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "text-sm", children: getToolName(row.original.id_tool) })
4085
- },
4086
- {
4087
- accessorKey: "status",
4088
- header: "Status",
4089
- cell: ({ row }) => /* @__PURE__ */ jsx19(
4090
- Badge8,
4091
- {
4092
- variant: row.original.status === "active" ? "default" : "destructive",
4093
- children: row.original.status === "active" ? "Ativo" : "Expirado"
4094
- }
4095
- )
4096
- },
4097
- {
4098
- accessorKey: "expires_at",
4099
- header: "Expira em",
4100
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.expires_at) })
4101
- },
4102
- {
4103
- accessorKey: "datetime_add",
4104
- header: "Criado em",
4105
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.datetime_add) })
4106
- },
4107
- {
4108
- id: "actions",
4109
- header: "A\xE7\xF5es",
4110
- size: 100,
4111
- enableSorting: false,
4112
- cell: ({ row }) => /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1", children: [
4113
- getToolType(row.original.id_tool) === "oauth2" && /* @__PURE__ */ jsxs17(Tooltip4, { children: [
4114
- /* @__PURE__ */ jsx19(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx19(
4115
- Button12,
4116
- {
4117
- variant: "ghost",
4118
- size: "icon",
4119
- className: "h-8 w-8",
4120
- "aria-label": "Vincular",
4121
- disabled: true,
4122
- children: /* @__PURE__ */ jsx19(Link, { className: "h-4 w-4" })
4123
- }
4124
- ) }),
4125
- /* @__PURE__ */ jsx19(TooltipContent4, { children: "Em breve" })
4126
- ] }),
4127
- /* @__PURE__ */ jsxs17(Tooltip4, { children: [
4128
- /* @__PURE__ */ jsx19(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx19(
4129
- Button12,
4130
- {
4131
- variant: "ghost",
4132
- size: "icon",
4133
- className: "h-8 w-8",
4134
- "aria-label": "Editar",
4135
- onClick: () => onEdit(row.original),
4136
- children: /* @__PURE__ */ jsx19(Pencil4, { className: "h-4 w-4" })
4137
- }
4138
- ) }),
4139
- /* @__PURE__ */ jsx19(TooltipContent4, { children: "Editar" })
4140
- ] }),
4141
- /* @__PURE__ */ jsxs17(Tooltip4, { children: [
4142
- /* @__PURE__ */ jsx19(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx19(
4143
- Button12,
4144
- {
4145
- variant: "ghost",
4146
- size: "icon",
4147
- className: "h-8 w-8 text-destructive hover:text-destructive",
4148
- "aria-label": "Excluir",
4149
- onClick: () => onRemove(row.original),
4150
- children: /* @__PURE__ */ jsx19(Trash24, { className: "h-4 w-4" })
4151
- }
4152
- ) }),
4153
- /* @__PURE__ */ jsx19(TooltipContent4, { children: "Remover" })
4154
- ] })
4155
- ] })
4156
- }
4157
- ];
4158
4050
  }
4159
- function ToolCredentialsForm({
4160
- credentials,
4161
- isLoading,
4162
- config,
4163
- gagentsApiUrl,
4164
- createOpen: externalCreateOpen,
4165
- onCreateOpenChange
4051
+ function ToolFormDialog({
4052
+ open,
4053
+ onOpenChange,
4054
+ tool,
4055
+ config
4166
4056
  }) {
4167
- const createMutation = useCreateToolCredential(config);
4168
- const updateMutation = useUpdateToolCredential(config);
4169
- const deleteMutation = useDeleteToolCredential(config);
4170
- const { data: toolsData } = useTools(config);
4171
- const tools = (toolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
4172
- const [search, setSearch] = useState11("");
4173
- const [internalCreateOpen, setInternalCreateOpen] = useState11(false);
4174
- const showCreateDialog = externalCreateOpen ?? internalCreateOpen;
4175
- const setShowCreateDialog = onCreateOpenChange ?? setInternalCreateOpen;
4176
- const [createForm, setCreateForm] = useState11({
4177
- id_tool: "",
4178
- label: "",
4179
- credentials_encrypted: "",
4180
- expires_at: ""
4181
- });
4182
- const [editTarget, setEditTarget] = useState11(null);
4183
- const [editForm, setEditForm] = useState11({
4184
- id_tool: "",
4185
- label: "",
4186
- credentials_encrypted: "",
4187
- expires_at: "",
4188
- status: ""
4189
- });
4190
- const [removeTarget, setRemoveTarget] = useState11(null);
4191
- const internalToolIds = useMemo7(() => {
4192
- const allRawTools = toolsData?.data || [];
4193
- return new Set(
4194
- allRawTools.filter((t) => t.slug?.startsWith("gclinic_")).map((t) => t.id)
4195
- );
4196
- }, [toolsData]);
4197
- const filteredCredentials = useMemo7(() => {
4198
- const visible = credentials.filter(
4199
- (cred) => !cred.id_tool || !internalToolIds.has(cred.id_tool)
4200
- );
4201
- if (!search) return visible;
4202
- const term = search.toLowerCase();
4203
- return visible.filter((cred) => {
4204
- const toolName = tools.find((t) => t.id === cred.id_tool)?.name || "";
4205
- return (cred.label || "").toLowerCase().includes(term) || toolName.toLowerCase().includes(term);
4206
- });
4207
- }, [credentials, search, tools, internalToolIds]);
4208
- const columns = useColumns3(
4209
- tools,
4210
- (cred) => startEdit(cred),
4211
- (cred) => handleConnect(cred),
4212
- (cred) => setRemoveTarget(cred)
4057
+ const isEditing = !!tool;
4058
+ const createTool = useCreateTool(config);
4059
+ const updateTool = useUpdateTool(config);
4060
+ const [form, setForm] = useState11(() => toolToFormState(tool));
4061
+ const [slugManuallyEdited, setSlugManuallyEdited] = useState11(false);
4062
+ const [lastResetKey, setLastResetKey] = useState11(
4063
+ () => `${tool?.id}-${open}`
4213
4064
  );
4214
- async function handleCreate() {
4215
- const idTool = parseInt(createForm.id_tool, 10);
4216
- if (!idTool || !createForm.label.trim() || !createForm.credentials_encrypted.trim()) return;
4217
- try {
4218
- const result = await createMutation.mutateAsync({
4219
- id_tool: idTool,
4220
- label: createForm.label.trim(),
4221
- credentials_encrypted: createForm.credentials_encrypted.trim(),
4222
- ...createForm.expires_at ? { expires_at: createForm.expires_at } : {}
4223
- });
4224
- if (result.status === 1) {
4225
- toast9.success("Credencial criada");
4226
- setShowCreateDialog(false);
4227
- setCreateForm({ id_tool: "", label: "", credentials_encrypted: "", expires_at: "" });
4228
- } else {
4229
- toast9.error(result.message || "Erro ao criar credencial");
4230
- }
4231
- } catch {
4232
- toast9.error("Erro ao criar credencial");
4233
- }
4234
- }
4235
- function startEdit(cred) {
4236
- setEditTarget(cred);
4237
- setEditForm({
4238
- id_tool: cred.id_tool ? String(cred.id_tool) : "",
4239
- label: cred.label || "",
4240
- credentials_encrypted: "",
4241
- expires_at: cred.expires_at || "",
4242
- status: cred.status
4243
- });
4065
+ const resetKey = `${tool?.id}-${open}`;
4066
+ if (resetKey !== lastResetKey) {
4067
+ setLastResetKey(resetKey);
4068
+ setForm(toolToFormState(open ? tool : void 0));
4069
+ setSlugManuallyEdited(false);
4244
4070
  }
4245
- async function handleSaveEdit() {
4246
- if (!editTarget) return;
4247
- const body = {};
4248
- const newIdTool = editForm.id_tool ? parseInt(editForm.id_tool, 10) : null;
4249
- if (newIdTool && newIdTool !== editTarget.id_tool) {
4250
- body.id_tool = newIdTool;
4251
- }
4252
- if (editForm.label.trim() && editForm.label.trim() !== (editTarget.label || "")) {
4253
- body.label = editForm.label.trim();
4071
+ const isPending = createTool.isPending || updateTool.isPending;
4072
+ async function handleSubmit(e) {
4073
+ e.preventDefault();
4074
+ let hasError = false;
4075
+ if (!form.name.trim()) {
4076
+ setForm((prev) => ({ ...prev, nameError: true }));
4077
+ hasError = true;
4254
4078
  }
4255
- if (editForm.credentials_encrypted.trim()) {
4256
- body.credentials_encrypted = editForm.credentials_encrypted.trim();
4079
+ const effectiveSlug = form.slug.trim() || slugify2(form.name);
4080
+ if (!effectiveSlug) {
4081
+ setForm((prev) => ({ ...prev, slugError: true }));
4082
+ hasError = true;
4257
4083
  }
4258
- if (editForm.expires_at !== (editTarget.expires_at || "")) {
4259
- body.expires_at = editForm.expires_at || null;
4084
+ if (!form.type) {
4085
+ setForm((prev) => ({ ...prev, typeError: true }));
4086
+ hasError = true;
4260
4087
  }
4261
- if (editForm.status && editForm.status !== editTarget.status) {
4262
- body.status = editForm.status;
4088
+ if (!isValidJson(form.functionDefinitions)) {
4089
+ setForm((prev) => ({ ...prev, jsonError: true }));
4090
+ hasError = true;
4263
4091
  }
4264
- if (Object.keys(body).length === 0) {
4265
- setEditTarget(null);
4266
- return;
4092
+ if (hasError) return;
4093
+ const body = {
4094
+ name: form.name.trim(),
4095
+ slug: effectiveSlug,
4096
+ type: form.type
4097
+ };
4098
+ if (form.description.trim()) body.description = form.description.trim();
4099
+ else body.description = "";
4100
+ if (form.functionDefinitions.trim()) {
4101
+ const parsed = JSON.parse(form.functionDefinitions.trim());
4102
+ body.function_definitions = JSON.stringify(parsed);
4103
+ } else {
4104
+ body.function_definitions = "";
4267
4105
  }
4268
4106
  try {
4269
- const result = await updateMutation.mutateAsync({
4270
- id: editTarget.id,
4271
- body
4272
- });
4273
- if (result.status === 1) {
4274
- toast9.success("Credencial atualizada");
4275
- setEditTarget(null);
4107
+ if (isEditing) {
4108
+ await updateTool.mutateAsync({ id: tool.id, body });
4109
+ toast9.success("Ferramenta atualizada");
4276
4110
  } else {
4277
- toast9.error(result.message || "Erro ao atualizar credencial");
4111
+ await createTool.mutateAsync(
4112
+ body
4113
+ );
4114
+ toast9.success("Ferramenta criada");
4278
4115
  }
4279
- } catch {
4280
- toast9.error("Erro ao atualizar credencial");
4116
+ onOpenChange(false);
4117
+ } catch (err) {
4118
+ toast9.error(
4119
+ err instanceof Error ? err.message : isEditing ? "Erro ao atualizar ferramenta" : "Erro ao criar ferramenta"
4120
+ );
4281
4121
  }
4282
4122
  }
4283
- async function handleRemove() {
4284
- if (!removeTarget) return;
4285
- try {
4286
- const result = await deleteMutation.mutateAsync(removeTarget.id);
4287
- if (result.status === 1) {
4288
- toast9.success("Credencial removida");
4289
- } else {
4290
- toast9.error(result.message || "Erro ao remover credencial");
4123
+ return /* @__PURE__ */ jsx19(Dialog5, { open, onOpenChange, children: /* @__PURE__ */ jsxs17(DialogContent5, { className: "sm:max-w-lg", children: [
4124
+ /* @__PURE__ */ jsx19(DialogHeader5, { children: /* @__PURE__ */ jsx19(DialogTitle5, { children: isEditing ? "Editar Ferramenta" : "Nova Ferramenta" }) }),
4125
+ /* @__PURE__ */ jsxs17("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
4126
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4127
+ /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-name", children: "Nome *" }),
4128
+ /* @__PURE__ */ jsx19(
4129
+ Input8,
4130
+ {
4131
+ id: "tool-name",
4132
+ name: "name",
4133
+ value: form.name,
4134
+ onChange: (e) => {
4135
+ const name = e.target.value;
4136
+ setForm((prev) => ({
4137
+ ...prev,
4138
+ name,
4139
+ nameError: name.trim() ? false : prev.nameError,
4140
+ ...!slugManuallyEdited && !isEditing ? { slug: slugify2(name), slugError: false } : {}
4141
+ }));
4142
+ },
4143
+ placeholder: "Ex: Google Calendar",
4144
+ disabled: isPending
4145
+ }
4146
+ ),
4147
+ form.nameError && /* @__PURE__ */ jsx19("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
4148
+ ] }),
4149
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4150
+ /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-slug", children: "Slug (identificador \xFAnico) *" }),
4151
+ /* @__PURE__ */ jsx19(
4152
+ Input8,
4153
+ {
4154
+ id: "tool-slug",
4155
+ name: "slug",
4156
+ value: form.slug,
4157
+ onChange: (e) => {
4158
+ setSlugManuallyEdited(true);
4159
+ setForm((prev) => ({
4160
+ ...prev,
4161
+ slug: e.target.value,
4162
+ slugError: e.target.value.trim() ? false : prev.slugError
4163
+ }));
4164
+ },
4165
+ placeholder: "Ex: google-calendar",
4166
+ disabled: isPending
4167
+ }
4168
+ ),
4169
+ /* @__PURE__ */ jsx19("p", { className: "text-xs text-muted-foreground", children: "Gerado automaticamente a partir do nome. Usado internamente para identificar a ferramenta." }),
4170
+ form.slugError && /* @__PURE__ */ jsx19("p", { className: "text-sm text-destructive", children: "Slug \xE9 obrigat\xF3rio" })
4171
+ ] }),
4172
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4173
+ /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-type", children: "Tipo de Autentica\xE7\xE3o *" }),
4174
+ /* @__PURE__ */ jsxs17(
4175
+ Select2,
4176
+ {
4177
+ value: form.type,
4178
+ onValueChange: (value) => {
4179
+ setForm((prev) => ({
4180
+ ...prev,
4181
+ type: value,
4182
+ typeError: false
4183
+ }));
4184
+ },
4185
+ disabled: isPending,
4186
+ children: [
4187
+ /* @__PURE__ */ jsx19(SelectTrigger2, { id: "tool-type", children: /* @__PURE__ */ jsx19(SelectValue2, { placeholder: "Selecione o tipo" }) }),
4188
+ /* @__PURE__ */ jsx19(SelectContent2, { children: TOOL_AUTH_TYPES.map((t) => /* @__PURE__ */ jsx19(SelectItem2, { value: t.value, children: t.label }, t.value)) })
4189
+ ]
4190
+ }
4191
+ ),
4192
+ /* @__PURE__ */ jsx19("p", { className: "text-xs text-muted-foreground", children: "Define se a ferramenta requer credenciais para funcionar." }),
4193
+ form.typeError && /* @__PURE__ */ jsx19("p", { className: "text-sm text-destructive", children: "Tipo \xE9 obrigat\xF3rio" })
4194
+ ] }),
4195
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4196
+ /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-description", children: "Descri\xE7\xE3o" }),
4197
+ /* @__PURE__ */ jsx19(
4198
+ Textarea2,
4199
+ {
4200
+ id: "tool-description",
4201
+ name: "description",
4202
+ value: form.description,
4203
+ onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
4204
+ placeholder: "Descri\\u00e7\\u00e3o da ferramenta\\u2026",
4205
+ rows: 3,
4206
+ disabled: isPending
4207
+ }
4208
+ )
4209
+ ] }),
4210
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4211
+ /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-function-defs", children: "Defini\xE7\xF5es de Fun\xE7\xE3o (JSON)" }),
4212
+ /* @__PURE__ */ jsx19(
4213
+ Textarea2,
4214
+ {
4215
+ id: "tool-function-defs",
4216
+ name: "functionDefs",
4217
+ value: form.functionDefinitions,
4218
+ onChange: (e) => {
4219
+ setForm((prev) => ({
4220
+ ...prev,
4221
+ functionDefinitions: e.target.value,
4222
+ jsonError: false
4223
+ }));
4224
+ },
4225
+ placeholder: `[
4226
+ {
4227
+ "type": "function",
4228
+ "function": {
4229
+ "name": "nome_da_funcao",
4230
+ "description": "O que a fun\xE7\xE3o faz",
4231
+ "parameters": {
4232
+ "type": "object",
4233
+ "properties": { \u2026 },
4234
+ "required": [\u2026]
4291
4235
  }
4292
- } catch {
4293
- toast9.error("Erro ao remover credencial");
4294
- } finally {
4295
- setRemoveTarget(null);
4296
4236
  }
4297
4237
  }
4298
- function handleConnect(cred) {
4299
- if (!config.accountId || !config.token) return;
4300
- const language = config.language ?? "pt-br";
4301
- const idWl = config.idWl ?? 1;
4302
- const url = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${config.accountId}/oauth/connect?id_tool=${cred.id_tool}`;
4303
- window.open(url, "_blank");
4304
- }
4305
- return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
4306
- /* @__PURE__ */ jsx19("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs17("div", { className: "relative flex-1 max-w-md", children: [
4307
- /* @__PURE__ */ jsx19(Search3, { "aria-hidden": "true", className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
4308
- /* @__PURE__ */ jsx19(
4309
- Input8,
4310
- {
4311
- placeholder: "Buscar credenciais\\u2026",
4312
- "aria-label": "Buscar credenciais",
4313
- name: "search",
4314
- autoComplete: "off",
4315
- value: search,
4316
- onChange: (e) => setSearch(e.target.value),
4317
- className: "pl-9"
4318
- }
4319
- )
4320
- ] }) }),
4321
- /* @__PURE__ */ jsx19(
4322
- DataTable3,
4323
- {
4324
- columns,
4325
- data: filteredCredentials,
4326
- isLoading,
4327
- emptyMessage: "Nenhuma credencial encontrada"
4328
- }
4329
- ),
4330
- /* @__PURE__ */ jsx19(Dialog5, { open: showCreateDialog, onOpenChange: setShowCreateDialog, children: /* @__PURE__ */ jsxs17(DialogContent5, { children: [
4331
- /* @__PURE__ */ jsx19(DialogHeader5, { children: /* @__PURE__ */ jsx19(DialogTitle5, { children: "Nova Credencial" }) }),
4332
- /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
4333
- /* @__PURE__ */ jsxs17("div", { children: [
4334
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
4335
- /* @__PURE__ */ jsxs17(
4336
- Select2,
4337
- {
4338
- value: createForm.id_tool,
4339
- onValueChange: (val) => setCreateForm((f) => ({ ...f, id_tool: val })),
4340
- children: [
4341
- /* @__PURE__ */ jsx19(SelectTrigger2, { id: "cred-tool", children: /* @__PURE__ */ jsx19(SelectValue2, { placeholder: "Selecione a ferramenta" }) }),
4342
- /* @__PURE__ */ jsx19(SelectContent2, { children: tools.map((tool) => /* @__PURE__ */ jsx19(SelectItem2, { value: String(tool.id), children: tool.name }, tool.id)) })
4343
- ]
4344
- }
4345
- )
4346
- ] }),
4347
- /* @__PURE__ */ jsxs17("div", { children: [
4348
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-label", className: "mb-1 block text-sm font-medium", children: "Label *" }),
4349
- /* @__PURE__ */ jsx19(
4350
- Input8,
4351
- {
4352
- id: "cred-label",
4353
- name: "label",
4354
- value: createForm.label,
4355
- onChange: (e) => setCreateForm((f) => ({ ...f, label: e.target.value })),
4356
- placeholder: "Ex: Google Calendar - Cl\xEDnica S\xE3o Paulo"
4357
- }
4358
- )
4359
- ] }),
4360
- /* @__PURE__ */ jsxs17("div", { children: [
4361
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-credential", className: "mb-1 block text-sm font-medium", children: "Credencial *" }),
4362
- /* @__PURE__ */ jsx19(
4363
- Input8,
4364
- {
4365
- id: "cred-credential",
4366
- name: "credential",
4367
- autoComplete: "off",
4368
- type: "password",
4369
- value: createForm.credentials_encrypted,
4370
- onChange: (e) => setCreateForm((f) => ({
4371
- ...f,
4372
- credentials_encrypted: e.target.value
4373
- })),
4374
- placeholder: "Credencial encriptada"
4375
- }
4376
- )
4377
- ] }),
4378
- /* @__PURE__ */ jsxs17("div", { children: [
4379
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o (opcional)" }),
4380
- /* @__PURE__ */ jsx19(
4381
- Input8,
4382
- {
4383
- id: "cred-expires",
4384
- name: "expires",
4385
- type: "date",
4386
- value: createForm.expires_at,
4387
- onChange: (e) => setCreateForm((f) => ({ ...f, expires_at: e.target.value }))
4388
- }
4389
- )
4390
- ] })
4238
+ ]`,
4239
+ rows: 10,
4240
+ className: "font-mono text-sm",
4241
+ disabled: isPending
4242
+ }
4243
+ ),
4244
+ /* @__PURE__ */ jsx19("p", { className: "text-xs text-muted-foreground", children: "Array de defini\xE7\xF5es no formato OpenAI Function Calling." }),
4245
+ form.jsonError && /* @__PURE__ */ jsx19("p", { className: "text-sm text-destructive", children: "JSON inv\xE1lido" })
4391
4246
  ] }),
4392
4247
  /* @__PURE__ */ jsxs17(DialogFooter5, { children: [
4393
4248
  /* @__PURE__ */ jsx19(
4394
4249
  Button12,
4395
4250
  {
4251
+ type: "button",
4396
4252
  variant: "outline",
4397
- onClick: () => setShowCreateDialog(false),
4253
+ onClick: () => onOpenChange(false),
4254
+ disabled: isPending,
4398
4255
  children: "Cancelar"
4399
4256
  }
4400
4257
  ),
4401
- /* @__PURE__ */ jsx19(
4402
- Button12,
4403
- {
4404
- onClick: handleCreate,
4405
- disabled: !createForm.id_tool || !createForm.label.trim() || !createForm.credentials_encrypted.trim() || createMutation.isPending,
4406
- children: "Criar"
4407
- }
4408
- )
4258
+ /* @__PURE__ */ jsxs17(Button12, { type: "submit", disabled: isPending, children: [
4259
+ isPending ? /* @__PURE__ */ jsx19(Loader29, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null,
4260
+ isEditing ? "Salvar" : "Criar"
4261
+ ] })
4409
4262
  ] })
4410
- ] }) }),
4411
- /* @__PURE__ */ jsx19(
4412
- Dialog5,
4263
+ ] })
4264
+ ] }) });
4265
+ }
4266
+
4267
+ // src/components/capabilities/advanced-tab.tsx
4268
+ import { Info as Info2 } from "lucide-react";
4269
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4270
+ function AdvancedTab({ config, agentId, gagentsApiUrl }) {
4271
+ const [editingTool, setEditingTool] = useState12(null);
4272
+ const [showToolForm, setShowToolForm] = useState12(false);
4273
+ function handleEditTool(tool) {
4274
+ setEditingTool(tool);
4275
+ setShowToolForm(true);
4276
+ }
4277
+ function handleToolFormOpenChange(open) {
4278
+ setShowToolForm(open);
4279
+ if (!open) setEditingTool(null);
4280
+ }
4281
+ return /* @__PURE__ */ jsxs18("div", { className: "space-y-8", children: [
4282
+ /* @__PURE__ */ jsxs18("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: [
4283
+ /* @__PURE__ */ jsx20(Info2, { className: "mt-0.5 h-4 w-4 shrink-0 text-blue-600 dark:text-blue-400" }),
4284
+ /* @__PURE__ */ jsxs18("p", { className: "text-sm text-blue-800 dark:text-blue-300", children: [
4285
+ "Use as abas ",
4286
+ /* @__PURE__ */ jsx20("strong", { children: "Capacidades" }),
4287
+ " e ",
4288
+ /* @__PURE__ */ jsx20("strong", { children: "Integra\xE7\xF5es" }),
4289
+ " para configura\xE7\xE3o simplificada. Esta aba oferece controlo manual avan\xE7ado sobre ferramentas. As credenciais s\xE3o geridas dentro de cada ferramenta."
4290
+ ] })
4291
+ ] }),
4292
+ /* @__PURE__ */ jsxs18("section", { className: "space-y-3", children: [
4293
+ /* @__PURE__ */ jsx20("h3", { className: "text-sm font-medium", children: "Ferramentas" }),
4294
+ /* @__PURE__ */ jsx20(ToolsTable, { onEdit: handleEditTool, config })
4295
+ ] }),
4296
+ /* @__PURE__ */ jsx20(
4297
+ ToolFormDialog,
4413
4298
  {
4414
- open: !!editTarget,
4415
- onOpenChange: (open) => !open && setEditTarget(null),
4416
- children: /* @__PURE__ */ jsxs17(DialogContent5, { children: [
4417
- /* @__PURE__ */ jsx19(DialogHeader5, { children: /* @__PURE__ */ jsx19(DialogTitle5, { children: "Editar Credencial" }) }),
4418
- /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
4419
- /* @__PURE__ */ jsxs17("div", { children: [
4420
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
4421
- /* @__PURE__ */ jsxs17(
4422
- Select2,
4423
- {
4424
- value: editForm.id_tool,
4425
- onValueChange: (val) => setEditForm((f) => ({ ...f, id_tool: val })),
4426
- children: [
4427
- /* @__PURE__ */ jsx19(SelectTrigger2, { id: "edit-cred-tool", children: /* @__PURE__ */ jsx19(SelectValue2, { placeholder: "Selecione a ferramenta" }) }),
4428
- /* @__PURE__ */ jsx19(SelectContent2, { children: tools.map((tool) => /* @__PURE__ */ jsx19(SelectItem2, { value: String(tool.id), children: tool.name }, tool.id)) })
4429
- ]
4430
- }
4431
- )
4432
- ] }),
4433
- /* @__PURE__ */ jsxs17("div", { children: [
4434
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-label", className: "mb-1 block text-sm font-medium", children: "Label" }),
4435
- /* @__PURE__ */ jsx19(
4436
- Input8,
4437
- {
4438
- id: "edit-cred-label",
4439
- name: "label",
4440
- value: editForm.label,
4441
- onChange: (e) => setEditForm((f) => ({ ...f, label: e.target.value })),
4442
- placeholder: "Label da credencial"
4443
- }
4444
- )
4445
- ] }),
4446
- /* @__PURE__ */ jsxs17("div", { children: [
4447
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-credential", className: "mb-1 block text-sm font-medium", children: "Nova Credencial (vazio = manter atual)" }),
4448
- /* @__PURE__ */ jsx19(
4449
- Input8,
4450
- {
4451
- id: "edit-cred-credential",
4452
- name: "credential",
4453
- autoComplete: "off",
4454
- type: "password",
4455
- value: editForm.credentials_encrypted,
4456
- onChange: (e) => setEditForm((f) => ({
4457
- ...f,
4458
- credentials_encrypted: e.target.value
4459
- })),
4460
- placeholder: "Nova credencial"
4461
- }
4462
- )
4463
- ] }),
4464
- /* @__PURE__ */ jsxs17("div", { children: [
4465
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o" }),
4466
- /* @__PURE__ */ jsx19(
4467
- Input8,
4468
- {
4469
- id: "edit-cred-expires",
4470
- name: "expires",
4471
- type: "date",
4472
- value: editForm.expires_at,
4473
- onChange: (e) => setEditForm((f) => ({ ...f, expires_at: e.target.value }))
4474
- }
4475
- )
4476
- ] }),
4477
- /* @__PURE__ */ jsxs17("div", { children: [
4478
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-status", className: "mb-1 block text-sm font-medium", children: "Status" }),
4479
- /* @__PURE__ */ jsxs17(
4480
- Select2,
4481
- {
4482
- value: editForm.status || void 0,
4483
- onValueChange: (val) => setEditForm((f) => ({
4484
- ...f,
4485
- status: val
4486
- })),
4487
- children: [
4488
- /* @__PURE__ */ jsx19(SelectTrigger2, { id: "edit-cred-status", children: /* @__PURE__ */ jsx19(SelectValue2, {}) }),
4489
- /* @__PURE__ */ jsxs17(SelectContent2, { children: [
4490
- /* @__PURE__ */ jsx19(SelectItem2, { value: "active", children: "Ativo" }),
4491
- /* @__PURE__ */ jsx19(SelectItem2, { value: "expired", children: "Expirado" })
4492
- ] })
4493
- ]
4494
- }
4495
- )
4496
- ] })
4497
- ] }),
4498
- /* @__PURE__ */ jsxs17(DialogFooter5, { children: [
4499
- /* @__PURE__ */ jsx19(Button12, { variant: "outline", onClick: () => setEditTarget(null), children: "Cancelar" }),
4500
- /* @__PURE__ */ jsx19(
4501
- Button12,
4502
- {
4503
- onClick: handleSaveEdit,
4504
- disabled: updateMutation.isPending,
4505
- children: "Salvar"
4506
- }
4507
- )
4508
- ] })
4509
- ] })
4299
+ open: showToolForm,
4300
+ onOpenChange: handleToolFormOpenChange,
4301
+ tool: editingTool ?? void 0,
4302
+ config
4510
4303
  }
4511
- ),
4512
- /* @__PURE__ */ jsx19(
4513
- AlertDialog4,
4514
- {
4515
- open: !!removeTarget,
4516
- onOpenChange: (open) => !open && setRemoveTarget(null),
4517
- children: /* @__PURE__ */ jsxs17(AlertDialogContent4, { children: [
4518
- /* @__PURE__ */ jsxs17(AlertDialogHeader4, { children: [
4519
- /* @__PURE__ */ jsx19(AlertDialogTitle4, { children: "Remover credencial?" }),
4520
- /* @__PURE__ */ jsx19(AlertDialogDescription4, { children: "A credencial ser\xE1 removida permanentemente." })
4521
- ] }),
4522
- /* @__PURE__ */ jsxs17(AlertDialogFooter4, { children: [
4523
- /* @__PURE__ */ jsx19(AlertDialogCancel4, { children: "Cancelar" }),
4524
- /* @__PURE__ */ jsx19(
4525
- AlertDialogAction4,
4526
- {
4527
- onClick: handleRemove,
4528
- disabled: deleteMutation.isPending,
4529
- children: "Remover"
4530
- }
4531
- )
4532
- ] })
4304
+ )
4305
+ ] });
4306
+ }
4307
+
4308
+ // src/pages/agent-capabilities-page.tsx
4309
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
4310
+ function defaultResolveWizardMeta(card) {
4311
+ return {
4312
+ capabilities: [
4313
+ { label: card.definition.name, description: card.definition.description }
4314
+ ],
4315
+ requirements: [],
4316
+ hasConfigStep: false
4317
+ };
4318
+ }
4319
+ function AgentCapabilitiesPage({
4320
+ config,
4321
+ agentId,
4322
+ gagentsApiUrl,
4323
+ resolveWizardMeta = defaultResolveWizardMeta,
4324
+ loadConfigOptions,
4325
+ onWizardComplete
4326
+ }) {
4327
+ const [wizardOpen, setWizardOpen] = useState13(false);
4328
+ const [activeCard, setActiveCard] = useState13(null);
4329
+ const handleConnect = useCallback6(
4330
+ (card) => {
4331
+ setActiveCard(card);
4332
+ setWizardOpen(true);
4333
+ },
4334
+ []
4335
+ );
4336
+ const handleWizardComplete = useCallback6(() => {
4337
+ setWizardOpen(false);
4338
+ setActiveCard(null);
4339
+ onWizardComplete?.();
4340
+ }, [onWizardComplete]);
4341
+ const handleWizardOpenChange = useCallback6((open) => {
4342
+ setWizardOpen(open);
4343
+ if (!open) setActiveCard(null);
4344
+ }, []);
4345
+ const wizardMeta = activeCard ? resolveWizardMeta(activeCard) : null;
4346
+ return /* @__PURE__ */ jsxs19("div", { className: "space-y-4", children: [
4347
+ /* @__PURE__ */ jsxs19("div", { children: [
4348
+ /* @__PURE__ */ jsx21("h2", { className: "text-lg font-semibold", children: "Capacidades e Integra\xE7\xF5es" }),
4349
+ /* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "Configure o que este agente pode fazer e quais servi\xE7os externos ele utiliza." })
4350
+ ] }),
4351
+ /* @__PURE__ */ jsxs19(Tabs, { defaultValue: "capacidades", children: [
4352
+ /* @__PURE__ */ jsxs19(TabsList, { children: [
4353
+ /* @__PURE__ */ jsxs19(TabsTrigger, { value: "capacidades", className: "flex items-center gap-1.5", children: [
4354
+ /* @__PURE__ */ jsx21(Blocks, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4355
+ "Capacidades"
4356
+ ] }),
4357
+ /* @__PURE__ */ jsxs19(TabsTrigger, { value: "integracoes", className: "flex items-center gap-1.5", children: [
4358
+ /* @__PURE__ */ jsx21(Plug3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4359
+ "Integra\xE7\xF5es"
4360
+ ] }),
4361
+ /* @__PURE__ */ jsxs19(TabsTrigger, { value: "avancado", className: "flex items-center gap-1.5", children: [
4362
+ /* @__PURE__ */ jsx21(Settings3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4363
+ "Avan\xE7ado"
4533
4364
  ] })
4365
+ ] }),
4366
+ /* @__PURE__ */ jsx21(TabsContent, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx21(CapabilitiesTab, { config, agentId }) }),
4367
+ /* @__PURE__ */ jsx21(TabsContent, { value: "integracoes", className: "mt-4", children: /* @__PURE__ */ jsx21(
4368
+ IntegrationsTab,
4369
+ {
4370
+ config,
4371
+ agentId,
4372
+ onConnect: handleConnect
4373
+ }
4374
+ ) }),
4375
+ /* @__PURE__ */ jsx21(TabsContent, { value: "avancado", className: "mt-4", children: /* @__PURE__ */ jsx21(
4376
+ AdvancedTab,
4377
+ {
4378
+ config,
4379
+ agentId,
4380
+ gagentsApiUrl
4381
+ }
4382
+ ) })
4383
+ ] }),
4384
+ activeCard && wizardMeta && /* @__PURE__ */ jsx21(
4385
+ IntegrationWizard,
4386
+ {
4387
+ open: wizardOpen,
4388
+ onOpenChange: handleWizardOpenChange,
4389
+ integration: activeCard.definition,
4390
+ meta: wizardMeta,
4391
+ agentId,
4392
+ config,
4393
+ onComplete: handleWizardComplete,
4394
+ gagentsApiUrl,
4395
+ existingCredentialId: activeCard.credential?.id,
4396
+ loadConfigOptions
4534
4397
  }
4535
4398
  )
4536
4399
  ] });
4537
4400
  }
4538
4401
 
4539
- // src/components/tools/tool-form-dialog.tsx
4540
- import { useState as useState12 } from "react";
4402
+ // src/components/agents/agent-tabs.tsx
4403
+ import {
4404
+ Tabs as Tabs2,
4405
+ TabsList as TabsList2,
4406
+ TabsTrigger as TabsTrigger2,
4407
+ TabsContent as TabsContent2
4408
+ } from "@greatapps/greatauth-ui/ui";
4409
+ import { Target as Target2, FileText as FileText2, MessageCircle as MessageCircle2, Blocks as Blocks2 } from "lucide-react";
4410
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4411
+ function AgentTabs({
4412
+ agent,
4413
+ config,
4414
+ renderChatLink,
4415
+ gagentsApiUrl,
4416
+ resolveWizardMeta,
4417
+ loadConfigOptions,
4418
+ onWizardComplete
4419
+ }) {
4420
+ const apiUrl = gagentsApiUrl || config.baseUrl;
4421
+ return /* @__PURE__ */ jsxs20(Tabs2, { defaultValue: "prompt", children: [
4422
+ /* @__PURE__ */ jsxs20(TabsList2, { children: [
4423
+ /* @__PURE__ */ jsxs20(TabsTrigger2, { value: "prompt", className: "flex items-center gap-1.5", children: [
4424
+ /* @__PURE__ */ jsx22(FileText2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4425
+ "Prompt"
4426
+ ] }),
4427
+ /* @__PURE__ */ jsxs20(TabsTrigger2, { value: "objetivos", className: "flex items-center gap-1.5", children: [
4428
+ /* @__PURE__ */ jsx22(Target2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4429
+ "Objetivos"
4430
+ ] }),
4431
+ /* @__PURE__ */ jsxs20(TabsTrigger2, { value: "capacidades", className: "flex items-center gap-1.5", children: [
4432
+ /* @__PURE__ */ jsx22(Blocks2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4433
+ "Capacidades"
4434
+ ] }),
4435
+ /* @__PURE__ */ jsxs20(TabsTrigger2, { value: "conversas", className: "flex items-center gap-1.5", children: [
4436
+ /* @__PURE__ */ jsx22(MessageCircle2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4437
+ "Conversas"
4438
+ ] })
4439
+ ] }),
4440
+ /* @__PURE__ */ jsx22(TabsContent2, { value: "prompt", className: "mt-4", children: /* @__PURE__ */ jsx22(AgentPromptEditor, { agent, config }) }),
4441
+ /* @__PURE__ */ jsx22(TabsContent2, { value: "objetivos", className: "mt-4", children: /* @__PURE__ */ jsx22(AgentObjectivesList, { agent, config }) }),
4442
+ /* @__PURE__ */ jsx22(TabsContent2, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx22(
4443
+ AgentCapabilitiesPage,
4444
+ {
4445
+ config,
4446
+ agentId: agent.id,
4447
+ gagentsApiUrl: apiUrl,
4448
+ resolveWizardMeta,
4449
+ loadConfigOptions,
4450
+ onWizardComplete
4451
+ }
4452
+ ) }),
4453
+ /* @__PURE__ */ jsx22(TabsContent2, { value: "conversas", className: "mt-4", children: /* @__PURE__ */ jsx22(
4454
+ AgentConversationsPanel,
4455
+ {
4456
+ agent,
4457
+ config,
4458
+ renderChatLink
4459
+ }
4460
+ ) })
4461
+ ] });
4462
+ }
4463
+
4464
+ // src/components/agents/agent-tools-list.tsx
4465
+ import { useState as useState14 } from "react";
4541
4466
  import {
4467
+ Switch as Switch5,
4468
+ Badge as Badge8,
4469
+ Button as Button13,
4470
+ Skeleton as Skeleton6,
4471
+ AlertDialog as AlertDialog4,
4472
+ AlertDialogAction as AlertDialogAction4,
4473
+ AlertDialogCancel as AlertDialogCancel4,
4474
+ AlertDialogContent as AlertDialogContent4,
4475
+ AlertDialogDescription as AlertDialogDescription4,
4476
+ AlertDialogFooter as AlertDialogFooter4,
4477
+ AlertDialogHeader as AlertDialogHeader4,
4478
+ AlertDialogTitle as AlertDialogTitle4,
4479
+ Popover,
4480
+ PopoverContent,
4481
+ PopoverTrigger,
4482
+ Input as Input9,
4483
+ Textarea as Textarea3,
4542
4484
  Dialog as Dialog6,
4543
4485
  DialogContent as DialogContent6,
4544
4486
  DialogHeader as DialogHeader6,
4545
4487
  DialogTitle as DialogTitle6,
4546
4488
  DialogFooter as DialogFooter6,
4547
- Button as Button13,
4548
- Input as Input9,
4549
- Textarea as Textarea2,
4550
- Label as Label7,
4489
+ Label as Label8,
4551
4490
  Select as Select3,
4552
4491
  SelectContent as SelectContent3,
4553
4492
  SelectItem as SelectItem3,
4554
4493
  SelectTrigger as SelectTrigger3,
4555
4494
  SelectValue as SelectValue3
4556
4495
  } from "@greatapps/greatauth-ui/ui";
4557
- import { Loader2 as Loader28 } from "lucide-react";
4496
+ import {
4497
+ Trash2 as Trash24,
4498
+ Plus as Plus3,
4499
+ Wrench,
4500
+ Settings2 as Settings22
4501
+ } from "lucide-react";
4558
4502
  import { toast as toast10 } from "sonner";
4559
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4560
- var TOOL_AUTH_TYPES = [
4561
- { value: "none", label: "Nenhuma" },
4562
- { value: "api_key", label: "API Key" },
4563
- { value: "oauth2", label: "OAuth 2.0" }
4564
- ];
4565
- function toolToFormState(tool) {
4566
- return {
4567
- name: tool?.name || "",
4568
- slug: tool?.slug || "",
4569
- type: tool?.type || "none",
4570
- description: tool?.description || "",
4571
- functionDefinitions: tool?.function_definitions ? formatJson(tool.function_definitions) : "",
4572
- nameError: false,
4573
- slugError: false,
4574
- typeError: false,
4575
- jsonError: false
4576
- };
4577
- }
4578
- function formatJson(str) {
4579
- try {
4580
- return JSON.stringify(JSON.parse(str), null, 2);
4581
- } catch {
4582
- return str;
4583
- }
4584
- }
4585
- function slugify2(name) {
4586
- return name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4587
- }
4588
- function isValidJson(str) {
4589
- if (!str.trim()) return true;
4590
- try {
4591
- JSON.parse(str);
4592
- return true;
4593
- } catch {
4594
- return false;
4595
- }
4596
- }
4597
- function ToolFormDialog({
4598
- open,
4599
- onOpenChange,
4600
- tool,
4601
- config
4602
- }) {
4603
- const isEditing = !!tool;
4604
- const createTool = useCreateTool(config);
4605
- const updateTool = useUpdateTool(config);
4606
- const [form, setForm] = useState12(() => toolToFormState(tool));
4607
- const [slugManuallyEdited, setSlugManuallyEdited] = useState12(false);
4608
- const [lastResetKey, setLastResetKey] = useState12(
4609
- () => `${tool?.id}-${open}`
4503
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
4504
+ function AgentToolsList({ agent, config }) {
4505
+ const { data: agentToolsData, isLoading } = useAgentTools(config, agent.id);
4506
+ const { data: allToolsData } = useTools(config);
4507
+ const addMutation = useAddAgentTool(config);
4508
+ const removeMutation = useRemoveAgentTool(config);
4509
+ const updateMutation = useUpdateAgentTool(config);
4510
+ const [removeTarget, setRemoveTarget] = useState14(null);
4511
+ const [addOpen, setAddOpen] = useState14(false);
4512
+ const [search, setSearch] = useState14("");
4513
+ const [configTarget, setConfigTarget] = useState14(null);
4514
+ const [configInstructions, setConfigInstructions] = useState14("");
4515
+ const [configCredentialId, setConfigCredentialId] = useState14("");
4516
+ const { data: credentialsData } = useToolCredentials(config);
4517
+ const allCredentials = credentialsData?.data || [];
4518
+ const agentTools = agentToolsData?.data || [];
4519
+ const allTools = (allToolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
4520
+ const assignedToolIds = new Set(agentTools.map((at) => at.id_tool));
4521
+ const visibleAgentTools = agentTools.filter((at) => {
4522
+ const tool = allTools.find((t) => t.id === at.id_tool);
4523
+ return !tool || !tool.slug?.startsWith("gclinic_");
4524
+ });
4525
+ const availableTools = allTools.filter((t) => !assignedToolIds.has(t.id));
4526
+ const filteredAvailable = availableTools.filter(
4527
+ (t) => t.name.toLowerCase().includes(search.toLowerCase())
4610
4528
  );
4611
- const resetKey = `${tool?.id}-${open}`;
4612
- if (resetKey !== lastResetKey) {
4613
- setLastResetKey(resetKey);
4614
- setForm(toolToFormState(open ? tool : void 0));
4615
- setSlugManuallyEdited(false);
4529
+ function getToolInfo(idTool) {
4530
+ return allTools.find((t) => t.id === idTool);
4616
4531
  }
4617
- const isPending = createTool.isPending || updateTool.isPending;
4618
- async function handleSubmit(e) {
4619
- e.preventDefault();
4620
- let hasError = false;
4621
- if (!form.name.trim()) {
4622
- setForm((prev) => ({ ...prev, nameError: true }));
4623
- hasError = true;
4624
- }
4625
- const effectiveSlug = form.slug.trim() || slugify2(form.name);
4626
- if (!effectiveSlug) {
4627
- setForm((prev) => ({ ...prev, slugError: true }));
4628
- hasError = true;
4629
- }
4630
- if (!form.type) {
4631
- setForm((prev) => ({ ...prev, typeError: true }));
4632
- hasError = true;
4633
- }
4634
- if (!isValidJson(form.functionDefinitions)) {
4635
- setForm((prev) => ({ ...prev, jsonError: true }));
4636
- hasError = true;
4532
+ async function handleToggleEnabled(agentTool, checked) {
4533
+ try {
4534
+ await updateMutation.mutateAsync({
4535
+ idAgent: agent.id,
4536
+ id: agentTool.id,
4537
+ body: { enabled: checked }
4538
+ });
4539
+ toast10.success(checked ? "Ferramenta ativada" : "Ferramenta desativada");
4540
+ } catch (err) {
4541
+ toast10.error(
4542
+ err instanceof Error ? err.message : "Erro ao alterar estado da ferramenta"
4543
+ );
4637
4544
  }
4638
- if (hasError) return;
4639
- const body = {
4640
- name: form.name.trim(),
4641
- slug: effectiveSlug,
4642
- type: form.type
4643
- };
4644
- if (form.description.trim()) body.description = form.description.trim();
4645
- else body.description = "";
4646
- if (form.functionDefinitions.trim()) {
4647
- const parsed = JSON.parse(form.functionDefinitions.trim());
4648
- body.function_definitions = JSON.stringify(parsed);
4649
- } else {
4650
- body.function_definitions = "";
4545
+ }
4546
+ async function handleAdd(tool) {
4547
+ try {
4548
+ await addMutation.mutateAsync({
4549
+ idAgent: agent.id,
4550
+ body: { id_tool: tool.id }
4551
+ });
4552
+ toast10.success("Ferramenta adicionada");
4553
+ setAddOpen(false);
4554
+ setSearch("");
4555
+ } catch (err) {
4556
+ toast10.error(
4557
+ err instanceof Error ? err.message : "Erro ao adicionar ferramenta"
4558
+ );
4651
4559
  }
4560
+ }
4561
+ async function handleRemove() {
4562
+ if (!removeTarget) return;
4652
4563
  try {
4653
- if (isEditing) {
4654
- await updateTool.mutateAsync({ id: tool.id, body });
4655
- toast10.success("Ferramenta atualizada");
4656
- } else {
4657
- await createTool.mutateAsync(
4658
- body
4659
- );
4660
- toast10.success("Ferramenta criada");
4661
- }
4662
- onOpenChange(false);
4564
+ await removeMutation.mutateAsync({
4565
+ idAgent: agent.id,
4566
+ id: removeTarget.id
4567
+ });
4568
+ toast10.success("Ferramenta removida");
4663
4569
  } catch (err) {
4664
4570
  toast10.error(
4665
- err instanceof Error ? err.message : isEditing ? "Erro ao atualizar ferramenta" : "Erro ao criar ferramenta"
4571
+ err instanceof Error ? err.message : "Erro ao remover ferramenta"
4666
4572
  );
4573
+ } finally {
4574
+ setRemoveTarget(null);
4667
4575
  }
4668
4576
  }
4669
- return /* @__PURE__ */ jsx20(Dialog6, { open, onOpenChange, children: /* @__PURE__ */ jsxs18(DialogContent6, { className: "sm:max-w-lg", children: [
4670
- /* @__PURE__ */ jsx20(DialogHeader6, { children: /* @__PURE__ */ jsx20(DialogTitle6, { children: isEditing ? "Editar Ferramenta" : "Nova Ferramenta" }) }),
4671
- /* @__PURE__ */ jsxs18("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
4672
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4673
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-name", children: "Nome *" }),
4674
- /* @__PURE__ */ jsx20(
4675
- Input9,
4676
- {
4677
- id: "tool-name",
4678
- name: "name",
4679
- value: form.name,
4680
- onChange: (e) => {
4681
- const name = e.target.value;
4682
- setForm((prev) => ({
4683
- ...prev,
4684
- name,
4685
- nameError: name.trim() ? false : prev.nameError,
4686
- ...!slugManuallyEdited && !isEditing ? { slug: slugify2(name), slugError: false } : {}
4687
- }));
4688
- },
4689
- placeholder: "Ex: Google Calendar",
4690
- disabled: isPending
4691
- }
4692
- ),
4693
- form.nameError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
4694
- ] }),
4695
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4696
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-slug", children: "Slug (identificador \xFAnico) *" }),
4697
- /* @__PURE__ */ jsx20(
4698
- Input9,
4699
- {
4700
- id: "tool-slug",
4701
- name: "slug",
4702
- value: form.slug,
4703
- onChange: (e) => {
4704
- setSlugManuallyEdited(true);
4705
- setForm((prev) => ({
4706
- ...prev,
4707
- slug: e.target.value,
4708
- slugError: e.target.value.trim() ? false : prev.slugError
4709
- }));
4710
- },
4711
- placeholder: "Ex: google-calendar",
4712
- disabled: isPending
4713
- }
4714
- ),
4715
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Gerado automaticamente a partir do nome. Usado internamente para identificar a ferramenta." }),
4716
- form.slugError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "Slug \xE9 obrigat\xF3rio" })
4717
- ] }),
4718
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4719
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-type", children: "Tipo de Autentica\xE7\xE3o *" }),
4720
- /* @__PURE__ */ jsxs18(
4721
- Select3,
4722
- {
4723
- value: form.type,
4724
- onValueChange: (value) => {
4725
- setForm((prev) => ({
4726
- ...prev,
4727
- type: value,
4728
- typeError: false
4729
- }));
4730
- },
4731
- disabled: isPending,
4732
- children: [
4733
- /* @__PURE__ */ jsx20(SelectTrigger3, { id: "tool-type", children: /* @__PURE__ */ jsx20(SelectValue3, { placeholder: "Selecione o tipo" }) }),
4734
- /* @__PURE__ */ jsx20(SelectContent3, { children: TOOL_AUTH_TYPES.map((t) => /* @__PURE__ */ jsx20(SelectItem3, { value: t.value, children: t.label }, t.value)) })
4735
- ]
4736
- }
4737
- ),
4738
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Define se a ferramenta requer credenciais para funcionar." }),
4739
- form.typeError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "Tipo \xE9 obrigat\xF3rio" })
4740
- ] }),
4741
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4742
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-description", children: "Descri\xE7\xE3o" }),
4743
- /* @__PURE__ */ jsx20(
4744
- Textarea2,
4745
- {
4746
- id: "tool-description",
4747
- name: "description",
4748
- value: form.description,
4749
- onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
4750
- placeholder: "Descri\\u00e7\\u00e3o da ferramenta\\u2026",
4751
- rows: 3,
4752
- disabled: isPending
4753
- }
4754
- )
4755
- ] }),
4756
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4757
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-function-defs", children: "Defini\xE7\xF5es de Fun\xE7\xE3o (JSON)" }),
4758
- /* @__PURE__ */ jsx20(
4759
- Textarea2,
4760
- {
4761
- id: "tool-function-defs",
4762
- name: "functionDefs",
4763
- value: form.functionDefinitions,
4764
- onChange: (e) => {
4765
- setForm((prev) => ({
4766
- ...prev,
4767
- functionDefinitions: e.target.value,
4768
- jsonError: false
4769
- }));
4770
- },
4771
- placeholder: `[
4772
- {
4773
- "type": "function",
4774
- "function": {
4775
- "name": "nome_da_funcao",
4776
- "description": "O que a fun\xE7\xE3o faz",
4777
- "parameters": {
4778
- "type": "object",
4779
- "properties": { \u2026 },
4780
- "required": [\u2026]
4781
- }
4577
+ function openConfig(agentTool) {
4578
+ setConfigTarget(agentTool);
4579
+ setConfigInstructions(agentTool.custom_instructions || "");
4580
+ setConfigCredentialId(agentTool.id_tool_credential ? String(agentTool.id_tool_credential) : "");
4581
+ }
4582
+ async function handleSaveConfig() {
4583
+ if (!configTarget) return;
4584
+ try {
4585
+ const newCredentialId = configCredentialId ? parseInt(configCredentialId, 10) : null;
4586
+ await updateMutation.mutateAsync({
4587
+ idAgent: agent.id,
4588
+ id: configTarget.id,
4589
+ body: {
4590
+ custom_instructions: configInstructions.trim() || null,
4591
+ id_tool_credential: newCredentialId
4592
+ }
4593
+ });
4594
+ toast10.success("Configura\xE7\xE3o atualizada");
4595
+ setConfigTarget(null);
4596
+ } catch (err) {
4597
+ toast10.error(
4598
+ err instanceof Error ? err.message : "Erro ao atualizar configura\xE7\xE3o"
4599
+ );
4782
4600
  }
4783
4601
  }
4784
- ]`,
4785
- rows: 10,
4786
- className: "font-mono text-sm",
4787
- disabled: isPending
4788
- }
4789
- ),
4790
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Array de defini\xE7\xF5es no formato OpenAI Function Calling." }),
4791
- form.jsonError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "JSON inv\xE1lido" })
4602
+ if (isLoading) {
4603
+ return /* @__PURE__ */ jsx23("div", { className: "space-y-3 p-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx23(Skeleton6, { className: "h-14 w-full" }, i)) });
4604
+ }
4605
+ return /* @__PURE__ */ jsxs21("div", { className: "space-y-4 p-4", children: [
4606
+ /* @__PURE__ */ jsxs21("div", { className: "flex items-center justify-between", children: [
4607
+ /* @__PURE__ */ jsxs21("h3", { className: "text-sm font-medium text-muted-foreground", children: [
4608
+ visibleAgentTools.length,
4609
+ " ferramenta",
4610
+ visibleAgentTools.length !== 1 ? "s" : "",
4611
+ " associada",
4612
+ visibleAgentTools.length !== 1 ? "s" : ""
4792
4613
  ] }),
4793
- /* @__PURE__ */ jsxs18(DialogFooter6, { children: [
4794
- /* @__PURE__ */ jsx20(
4795
- Button13,
4796
- {
4797
- type: "button",
4798
- variant: "outline",
4799
- onClick: () => onOpenChange(false),
4800
- disabled: isPending,
4801
- children: "Cancelar"
4802
- }
4803
- ),
4804
- /* @__PURE__ */ jsxs18(Button13, { type: "submit", disabled: isPending, children: [
4805
- isPending ? /* @__PURE__ */ jsx20(Loader28, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null,
4806
- isEditing ? "Salvar" : "Criar"
4614
+ /* @__PURE__ */ jsxs21(Popover, { open: addOpen, onOpenChange: setAddOpen, children: [
4615
+ /* @__PURE__ */ jsx23(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs21(Button13, { size: "sm", disabled: availableTools.length === 0, children: [
4616
+ /* @__PURE__ */ jsx23(Plus3, { className: "mr-2 h-4 w-4" }),
4617
+ "Adicionar Ferramenta"
4618
+ ] }) }),
4619
+ /* @__PURE__ */ jsxs21(PopoverContent, { className: "w-72 p-0", align: "end", children: [
4620
+ /* @__PURE__ */ jsx23("div", { className: "p-2", children: /* @__PURE__ */ jsx23(
4621
+ Input9,
4622
+ {
4623
+ placeholder: "Buscar ferramenta\\u2026",
4624
+ "aria-label": "Buscar ferramenta",
4625
+ name: "search",
4626
+ value: search,
4627
+ onChange: (e) => setSearch(e.target.value),
4628
+ className: "h-8"
4629
+ }
4630
+ ) }),
4631
+ /* @__PURE__ */ jsx23("div", { className: "max-h-48 overflow-y-auto", children: filteredAvailable.length === 0 ? /* @__PURE__ */ jsx23("p", { className: "p-3 text-center text-sm text-muted-foreground", children: "Nenhuma ferramenta dispon\xEDvel" }) : filteredAvailable.map((tool) => /* @__PURE__ */ jsxs21(
4632
+ "button",
4633
+ {
4634
+ type: "button",
4635
+ className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-accent",
4636
+ onClick: () => handleAdd(tool),
4637
+ disabled: addMutation.isPending,
4638
+ children: [
4639
+ /* @__PURE__ */ jsx23(Wrench, { className: "h-4 w-4 text-muted-foreground" }),
4640
+ /* @__PURE__ */ jsx23("span", { className: "flex-1 font-medium", children: tool.name }),
4641
+ /* @__PURE__ */ jsx23(Badge8, { variant: "secondary", className: "text-xs", children: tool.type })
4642
+ ]
4643
+ },
4644
+ tool.id
4645
+ )) })
4807
4646
  ] })
4808
4647
  ] })
4809
- ] })
4810
- ] }) });
4811
- }
4812
-
4813
- // src/components/capabilities/advanced-tab.tsx
4814
- import { Info as Info2 } from "lucide-react";
4815
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
4816
- function AdvancedTab({ config, agentId, gagentsApiUrl }) {
4817
- const { data: credentialsData, isLoading: isLoadingCredentials } = useToolCredentials(config);
4818
- const credentials = credentialsData?.data ?? [];
4819
- const [editingTool, setEditingTool] = useState13(null);
4820
- const [showToolForm, setShowToolForm] = useState13(false);
4821
- function handleEditTool(tool) {
4822
- setEditingTool(tool);
4823
- setShowToolForm(true);
4824
- }
4825
- function handleToolFormOpenChange(open) {
4826
- setShowToolForm(open);
4827
- if (!open) setEditingTool(null);
4828
- }
4829
- return /* @__PURE__ */ jsxs19("div", { className: "space-y-8", children: [
4830
- /* @__PURE__ */ jsxs19("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: [
4831
- /* @__PURE__ */ jsx21(Info2, { className: "mt-0.5 h-4 w-4 shrink-0 text-blue-600 dark:text-blue-400" }),
4832
- /* @__PURE__ */ jsxs19("p", { className: "text-sm text-blue-800 dark:text-blue-300", children: [
4833
- "Use as abas ",
4834
- /* @__PURE__ */ jsx21("strong", { children: "Capacidades" }),
4835
- " e ",
4836
- /* @__PURE__ */ jsx21("strong", { children: "Integra\xE7\xF5es" }),
4837
- " para configura\xE7\xE3o simplificada. Esta aba oferece controlo manual avan\xE7ado sobre ferramentas e credenciais."
4838
- ] })
4839
4648
  ] }),
4840
- /* @__PURE__ */ jsxs19("section", { className: "space-y-3", children: [
4841
- /* @__PURE__ */ jsx21("h3", { className: "text-sm font-medium", children: "Ferramentas" }),
4842
- /* @__PURE__ */ jsx21(ToolsTable, { onEdit: handleEditTool, config })
4843
- ] }),
4844
- /* @__PURE__ */ jsxs19("section", { className: "space-y-3", children: [
4845
- /* @__PURE__ */ jsx21("h3", { className: "text-sm font-medium", children: "Credenciais" }),
4846
- /* @__PURE__ */ jsx21(
4847
- ToolCredentialsForm,
4649
+ visibleAgentTools.length === 0 ? /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
4650
+ /* @__PURE__ */ jsx23(Wrench, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
4651
+ /* @__PURE__ */ jsx23("p", { className: "text-sm text-muted-foreground", children: "Nenhuma ferramenta associada. Clique em 'Adicionar Ferramenta' para come\xE7ar." })
4652
+ ] }) : /* @__PURE__ */ jsx23("div", { className: "space-y-2", children: visibleAgentTools.map((agentTool) => {
4653
+ const tool = getToolInfo(agentTool.id_tool);
4654
+ return /* @__PURE__ */ jsxs21(
4655
+ "div",
4848
4656
  {
4849
- credentials,
4850
- isLoading: isLoadingCredentials,
4851
- config,
4852
- gagentsApiUrl
4853
- }
4854
- )
4855
- ] }),
4856
- /* @__PURE__ */ jsx21(
4857
- ToolFormDialog,
4657
+ className: "flex items-center gap-3 rounded-lg border bg-card p-3",
4658
+ children: [
4659
+ /* @__PURE__ */ jsxs21("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [
4660
+ /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
4661
+ /* @__PURE__ */ jsx23("span", { className: "truncate font-medium", children: tool?.name || `Ferramenta #${agentTool.id_tool}` }),
4662
+ tool?.type && /* @__PURE__ */ jsx23(Badge8, { variant: "secondary", className: "shrink-0 text-xs", children: tool.type })
4663
+ ] }),
4664
+ agentTool.custom_instructions && /* @__PURE__ */ jsx23("p", { className: "truncate text-xs text-muted-foreground", children: agentTool.custom_instructions })
4665
+ ] }),
4666
+ /* @__PURE__ */ jsx23(
4667
+ Switch5,
4668
+ {
4669
+ "aria-label": "Ativar/Desativar",
4670
+ checked: agentTool.enabled,
4671
+ onCheckedChange: (checked) => handleToggleEnabled(agentTool, checked),
4672
+ disabled: updateMutation.isPending
4673
+ }
4674
+ ),
4675
+ /* @__PURE__ */ jsx23(
4676
+ Button13,
4677
+ {
4678
+ variant: "ghost",
4679
+ size: "icon",
4680
+ "aria-label": "Configurar",
4681
+ className: "shrink-0 text-muted-foreground hover:text-foreground",
4682
+ onClick: () => openConfig(agentTool),
4683
+ title: "Configurar instru\xE7\xF5es",
4684
+ children: /* @__PURE__ */ jsx23(Settings22, { className: "h-4 w-4" })
4685
+ }
4686
+ ),
4687
+ /* @__PURE__ */ jsx23(
4688
+ Button13,
4689
+ {
4690
+ variant: "ghost",
4691
+ size: "icon",
4692
+ "aria-label": "Remover",
4693
+ className: "shrink-0 text-muted-foreground hover:text-destructive",
4694
+ onClick: () => setRemoveTarget(agentTool),
4695
+ children: /* @__PURE__ */ jsx23(Trash24, { className: "h-4 w-4" })
4696
+ }
4697
+ )
4698
+ ]
4699
+ },
4700
+ agentTool.id
4701
+ );
4702
+ }) }),
4703
+ /* @__PURE__ */ jsx23(
4704
+ Dialog6,
4858
4705
  {
4859
- open: showToolForm,
4860
- onOpenChange: handleToolFormOpenChange,
4861
- tool: editingTool ?? void 0,
4862
- config
4863
- }
4864
- )
4865
- ] });
4866
- }
4867
-
4868
- // src/pages/agent-capabilities-page.tsx
4869
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4870
- function defaultResolveWizardMeta(card) {
4871
- return {
4872
- capabilities: [
4873
- { label: card.definition.name, description: card.definition.description }
4874
- ],
4875
- requirements: [],
4876
- hasConfigStep: false
4877
- };
4878
- }
4879
- function AgentCapabilitiesPage({
4880
- config,
4881
- agentId,
4882
- gagentsApiUrl,
4883
- resolveWizardMeta = defaultResolveWizardMeta,
4884
- loadConfigOptions,
4885
- onWizardComplete
4886
- }) {
4887
- const [wizardOpen, setWizardOpen] = useState14(false);
4888
- const [activeCard, setActiveCard] = useState14(null);
4889
- const handleConnect = useCallback6(
4890
- (card) => {
4891
- setActiveCard(card);
4892
- setWizardOpen(true);
4893
- },
4894
- []
4895
- );
4896
- const handleWizardComplete = useCallback6(() => {
4897
- setWizardOpen(false);
4898
- setActiveCard(null);
4899
- onWizardComplete?.();
4900
- }, [onWizardComplete]);
4901
- const handleWizardOpenChange = useCallback6((open) => {
4902
- setWizardOpen(open);
4903
- if (!open) setActiveCard(null);
4904
- }, []);
4905
- const wizardMeta = activeCard ? resolveWizardMeta(activeCard) : null;
4906
- return /* @__PURE__ */ jsxs20("div", { className: "space-y-4", children: [
4907
- /* @__PURE__ */ jsxs20("div", { children: [
4908
- /* @__PURE__ */ jsx22("h2", { className: "text-lg font-semibold", children: "Capacidades e Integra\xE7\xF5es" }),
4909
- /* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "Configure o que este agente pode fazer e quais servi\xE7os externos ele utiliza." })
4910
- ] }),
4911
- /* @__PURE__ */ jsxs20(Tabs, { defaultValue: "capacidades", children: [
4912
- /* @__PURE__ */ jsxs20(TabsList, { children: [
4913
- /* @__PURE__ */ jsxs20(TabsTrigger, { value: "capacidades", className: "flex items-center gap-1.5", children: [
4914
- /* @__PURE__ */ jsx22(Blocks, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4915
- "Capacidades"
4916
- ] }),
4917
- /* @__PURE__ */ jsxs20(TabsTrigger, { value: "integracoes", className: "flex items-center gap-1.5", children: [
4918
- /* @__PURE__ */ jsx22(Plug3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4919
- "Integra\xE7\xF5es"
4920
- ] }),
4921
- /* @__PURE__ */ jsxs20(TabsTrigger, { value: "avancado", className: "flex items-center gap-1.5", children: [
4922
- /* @__PURE__ */ jsx22(Settings3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4923
- "Avan\xE7ado"
4706
+ open: !!configTarget,
4707
+ onOpenChange: (open) => !open && setConfigTarget(null),
4708
+ children: /* @__PURE__ */ jsxs21(DialogContent6, { className: "sm:max-w-lg", children: [
4709
+ /* @__PURE__ */ jsx23(DialogHeader6, { children: /* @__PURE__ */ jsx23(DialogTitle6, { children: "Instru\xE7\xF5es da Ferramenta" }) }),
4710
+ /* @__PURE__ */ jsxs21("div", { className: "space-y-4", children: [
4711
+ configTarget && getToolInfo(configTarget.id_tool)?.type !== "none" && /* @__PURE__ */ jsxs21("div", { className: "space-y-2", children: [
4712
+ /* @__PURE__ */ jsx23(Label8, { htmlFor: "tool-credential", children: "Credencial" }),
4713
+ /* @__PURE__ */ jsxs21(
4714
+ Select3,
4715
+ {
4716
+ value: configCredentialId || void 0,
4717
+ onValueChange: (val) => setConfigCredentialId(val === "__none__" ? "" : val),
4718
+ children: [
4719
+ /* @__PURE__ */ jsx23(SelectTrigger3, { id: "tool-credential", children: /* @__PURE__ */ jsx23(SelectValue3, { placeholder: "Selecione uma credencial (opcional)" }) }),
4720
+ /* @__PURE__ */ jsxs21(SelectContent3, { children: [
4721
+ /* @__PURE__ */ jsx23(SelectItem3, { value: "__none__", children: "Nenhuma (autom\xE1tico)" }),
4722
+ allCredentials.filter((c) => configTarget && c.id_tool === configTarget.id_tool && c.status === "active").map((c) => /* @__PURE__ */ jsx23(SelectItem3, { value: String(c.id), children: c.label || `Credencial #${c.id}` }, c.id))
4723
+ ] })
4724
+ ]
4725
+ }
4726
+ ),
4727
+ /* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: "Vincule uma credencial espec\xEDfica a esta ferramenta neste agente." })
4728
+ ] }),
4729
+ /* @__PURE__ */ jsxs21("div", { className: "space-y-2", children: [
4730
+ /* @__PURE__ */ jsx23(Label8, { htmlFor: "tool-instructions", children: "Instru\xE7\xF5es Personalizadas" }),
4731
+ /* @__PURE__ */ jsx23(
4732
+ Textarea3,
4733
+ {
4734
+ id: "tool-instructions",
4735
+ name: "instructions",
4736
+ value: configInstructions,
4737
+ onChange: (e) => setConfigInstructions(e.target.value),
4738
+ placeholder: "Instru\\u00e7\\u00f5es sobre como e quando o agente deve usar esta ferramenta\\u2026",
4739
+ rows: 6
4740
+ }
4741
+ ),
4742
+ /* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: "Este texto \xE9 adicionado ao prompt do agente para orientar o uso da ferramenta." })
4743
+ ] })
4744
+ ] }),
4745
+ /* @__PURE__ */ jsxs21(DialogFooter6, { children: [
4746
+ /* @__PURE__ */ jsx23(
4747
+ Button13,
4748
+ {
4749
+ variant: "outline",
4750
+ onClick: () => setConfigTarget(null),
4751
+ children: "Cancelar"
4752
+ }
4753
+ ),
4754
+ /* @__PURE__ */ jsx23(
4755
+ Button13,
4756
+ {
4757
+ onClick: handleSaveConfig,
4758
+ disabled: updateMutation.isPending,
4759
+ children: "Salvar"
4760
+ }
4761
+ )
4762
+ ] })
4924
4763
  ] })
4925
- ] }),
4926
- /* @__PURE__ */ jsx22(TabsContent, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx22(CapabilitiesTab, { config, agentId }) }),
4927
- /* @__PURE__ */ jsx22(TabsContent, { value: "integracoes", className: "mt-4", children: /* @__PURE__ */ jsx22(
4928
- IntegrationsTab,
4929
- {
4930
- config,
4931
- agentId,
4932
- onConnect: handleConnect
4933
- }
4934
- ) }),
4935
- /* @__PURE__ */ jsx22(TabsContent, { value: "avancado", className: "mt-4", children: /* @__PURE__ */ jsx22(
4936
- AdvancedTab,
4937
- {
4938
- config,
4939
- agentId,
4940
- gagentsApiUrl
4941
- }
4942
- ) })
4943
- ] }),
4944
- activeCard && wizardMeta && /* @__PURE__ */ jsx22(
4945
- IntegrationWizard,
4946
- {
4947
- open: wizardOpen,
4948
- onOpenChange: handleWizardOpenChange,
4949
- integration: activeCard.definition,
4950
- meta: wizardMeta,
4951
- agentId,
4952
- config,
4953
- onComplete: handleWizardComplete,
4954
- gagentsApiUrl,
4955
- existingCredentialId: activeCard.credential?.id,
4956
- loadConfigOptions
4957
- }
4958
- )
4959
- ] });
4960
- }
4961
-
4962
- // src/components/agents/agent-tabs.tsx
4963
- import {
4964
- Tabs as Tabs2,
4965
- TabsList as TabsList2,
4966
- TabsTrigger as TabsTrigger2,
4967
- TabsContent as TabsContent2
4968
- } from "@greatapps/greatauth-ui/ui";
4969
- import { Target as Target2, FileText as FileText2, MessageCircle as MessageCircle2, Blocks as Blocks2 } from "lucide-react";
4970
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
4971
- function AgentTabs({
4972
- agent,
4973
- config,
4974
- renderChatLink,
4975
- gagentsApiUrl,
4976
- resolveWizardMeta,
4977
- loadConfigOptions,
4978
- onWizardComplete
4979
- }) {
4980
- const apiUrl = gagentsApiUrl || config.baseUrl;
4981
- return /* @__PURE__ */ jsxs21(Tabs2, { defaultValue: "prompt", children: [
4982
- /* @__PURE__ */ jsxs21(TabsList2, { children: [
4983
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "prompt", className: "flex items-center gap-1.5", children: [
4984
- /* @__PURE__ */ jsx23(FileText2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4985
- "Prompt"
4986
- ] }),
4987
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "objetivos", className: "flex items-center gap-1.5", children: [
4988
- /* @__PURE__ */ jsx23(Target2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4989
- "Objetivos"
4990
- ] }),
4991
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "capacidades", className: "flex items-center gap-1.5", children: [
4992
- /* @__PURE__ */ jsx23(Blocks2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4993
- "Capacidades"
4994
- ] }),
4995
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "conversas", className: "flex items-center gap-1.5", children: [
4996
- /* @__PURE__ */ jsx23(MessageCircle2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
4997
- "Conversas"
4998
- ] })
4999
- ] }),
5000
- /* @__PURE__ */ jsx23(TabsContent2, { value: "prompt", className: "mt-4", children: /* @__PURE__ */ jsx23(AgentPromptEditor, { agent, config }) }),
5001
- /* @__PURE__ */ jsx23(TabsContent2, { value: "objetivos", className: "mt-4", children: /* @__PURE__ */ jsx23(AgentObjectivesList, { agent, config }) }),
5002
- /* @__PURE__ */ jsx23(TabsContent2, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx23(
5003
- AgentCapabilitiesPage,
5004
- {
5005
- config,
5006
- agentId: agent.id,
5007
- gagentsApiUrl: apiUrl,
5008
- resolveWizardMeta,
5009
- loadConfigOptions,
5010
- onWizardComplete
5011
4764
  }
5012
- ) }),
5013
- /* @__PURE__ */ jsx23(TabsContent2, { value: "conversas", className: "mt-4", children: /* @__PURE__ */ jsx23(
5014
- AgentConversationsPanel,
4765
+ ),
4766
+ /* @__PURE__ */ jsx23(
4767
+ AlertDialog4,
5015
4768
  {
5016
- agent,
5017
- config,
5018
- renderChatLink
4769
+ open: !!removeTarget,
4770
+ onOpenChange: (open) => !open && setRemoveTarget(null),
4771
+ children: /* @__PURE__ */ jsxs21(AlertDialogContent4, { children: [
4772
+ /* @__PURE__ */ jsxs21(AlertDialogHeader4, { children: [
4773
+ /* @__PURE__ */ jsx23(AlertDialogTitle4, { children: "Remover ferramenta?" }),
4774
+ /* @__PURE__ */ jsx23(AlertDialogDescription4, { children: "A ferramenta ser\xE1 desassociada deste agente." })
4775
+ ] }),
4776
+ /* @__PURE__ */ jsxs21(AlertDialogFooter4, { children: [
4777
+ /* @__PURE__ */ jsx23(AlertDialogCancel4, { children: "Cancelar" }),
4778
+ /* @__PURE__ */ jsx23(
4779
+ AlertDialogAction4,
4780
+ {
4781
+ onClick: handleRemove,
4782
+ disabled: removeMutation.isPending,
4783
+ children: "Remover"
4784
+ }
4785
+ )
4786
+ ] })
4787
+ ] })
5019
4788
  }
5020
- ) })
4789
+ )
5021
4790
  ] });
5022
4791
  }
5023
4792
 
5024
- // src/components/agents/agent-tools-list.tsx
5025
- import { useState as useState15 } from "react";
4793
+ // src/components/tools/tool-credentials-form.tsx
4794
+ import { useMemo as useMemo7, useState as useState15 } from "react";
4795
+ import { DataTable as DataTable3 } from "@greatapps/greatauth-ui";
5026
4796
  import {
5027
- Switch as Switch5,
5028
- Badge as Badge9,
4797
+ Input as Input10,
5029
4798
  Button as Button14,
5030
- Skeleton as Skeleton6,
4799
+ Badge as Badge9,
4800
+ Tooltip as Tooltip4,
4801
+ TooltipTrigger as TooltipTrigger4,
4802
+ TooltipContent as TooltipContent4,
4803
+ Dialog as Dialog7,
4804
+ DialogContent as DialogContent7,
4805
+ DialogHeader as DialogHeader7,
4806
+ DialogTitle as DialogTitle7,
4807
+ DialogFooter as DialogFooter7,
5031
4808
  AlertDialog as AlertDialog5,
5032
4809
  AlertDialogAction as AlertDialogAction5,
5033
4810
  AlertDialogCancel as AlertDialogCancel5,
@@ -5036,285 +4813,461 @@ import {
5036
4813
  AlertDialogFooter as AlertDialogFooter5,
5037
4814
  AlertDialogHeader as AlertDialogHeader5,
5038
4815
  AlertDialogTitle as AlertDialogTitle5,
5039
- Popover,
5040
- PopoverContent,
5041
- PopoverTrigger,
5042
- Input as Input10,
5043
- Textarea as Textarea3,
5044
- Dialog as Dialog7,
5045
- DialogContent as DialogContent7,
5046
- DialogHeader as DialogHeader7,
5047
- DialogTitle as DialogTitle7,
5048
- DialogFooter as DialogFooter7,
5049
- Label as Label8,
5050
4816
  Select as Select4,
5051
4817
  SelectContent as SelectContent4,
5052
4818
  SelectItem as SelectItem4,
5053
4819
  SelectTrigger as SelectTrigger4,
5054
4820
  SelectValue as SelectValue4
5055
4821
  } from "@greatapps/greatauth-ui/ui";
5056
- import {
5057
- Trash2 as Trash25,
5058
- Plus as Plus3,
5059
- Wrench,
5060
- Settings2 as Settings22
5061
- } from "lucide-react";
4822
+ import { Trash2 as Trash25, Pencil as Pencil4, Link, Search as Search3 } from "lucide-react";
4823
+ import { format as format3 } from "date-fns";
4824
+ import { ptBR as ptBR3 } from "date-fns/locale";
5062
4825
  import { toast as toast11 } from "sonner";
5063
4826
  import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
5064
- function AgentToolsList({ agent, config }) {
5065
- const { data: agentToolsData, isLoading } = useAgentTools(config, agent.id);
5066
- const { data: allToolsData } = useTools(config);
5067
- const addMutation = useAddAgentTool(config);
5068
- const removeMutation = useRemoveAgentTool(config);
5069
- const updateMutation = useUpdateAgentTool(config);
5070
- const [removeTarget, setRemoveTarget] = useState15(null);
5071
- const [addOpen, setAddOpen] = useState15(false);
4827
+ function formatDate2(dateStr) {
4828
+ if (!dateStr) return "Sem expira\xE7\xE3o";
4829
+ return format3(new Date(dateStr), "dd/MM/yyyy", { locale: ptBR3 });
4830
+ }
4831
+ function useColumns3(tools, onEdit, onConnect, onRemove) {
4832
+ function getToolName(idTool) {
4833
+ if (!idTool) return "\u2014";
4834
+ const tool = tools.find((t) => t.id === idTool);
4835
+ return tool?.name || `Ferramenta #${idTool}`;
4836
+ }
4837
+ function getToolType(idTool) {
4838
+ if (!idTool) return null;
4839
+ const tool = tools.find((t) => t.id === idTool);
4840
+ return tool?.type || null;
4841
+ }
4842
+ return [
4843
+ {
4844
+ accessorKey: "label",
4845
+ header: "Label",
4846
+ cell: ({ row }) => /* @__PURE__ */ jsx24("span", { className: "font-medium", children: row.original.label || "\u2014" })
4847
+ },
4848
+ {
4849
+ accessorKey: "id_tool",
4850
+ header: "Ferramenta",
4851
+ cell: ({ row }) => /* @__PURE__ */ jsx24("span", { className: "text-sm", children: getToolName(row.original.id_tool) })
4852
+ },
4853
+ {
4854
+ accessorKey: "status",
4855
+ header: "Status",
4856
+ cell: ({ row }) => /* @__PURE__ */ jsx24(
4857
+ Badge9,
4858
+ {
4859
+ variant: row.original.status === "active" ? "default" : "destructive",
4860
+ children: row.original.status === "active" ? "Ativo" : "Expirado"
4861
+ }
4862
+ )
4863
+ },
4864
+ {
4865
+ accessorKey: "expires_at",
4866
+ header: "Expira em",
4867
+ cell: ({ row }) => /* @__PURE__ */ jsx24("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.expires_at) })
4868
+ },
4869
+ {
4870
+ accessorKey: "datetime_add",
4871
+ header: "Criado em",
4872
+ cell: ({ row }) => /* @__PURE__ */ jsx24("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.datetime_add) })
4873
+ },
4874
+ {
4875
+ id: "actions",
4876
+ header: "A\xE7\xF5es",
4877
+ size: 100,
4878
+ enableSorting: false,
4879
+ cell: ({ row }) => /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-1", children: [
4880
+ getToolType(row.original.id_tool) === "oauth2" && /* @__PURE__ */ jsxs22(Tooltip4, { children: [
4881
+ /* @__PURE__ */ jsx24(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx24(
4882
+ Button14,
4883
+ {
4884
+ variant: "ghost",
4885
+ size: "icon",
4886
+ className: "h-8 w-8",
4887
+ "aria-label": "Vincular",
4888
+ disabled: true,
4889
+ children: /* @__PURE__ */ jsx24(Link, { className: "h-4 w-4" })
4890
+ }
4891
+ ) }),
4892
+ /* @__PURE__ */ jsx24(TooltipContent4, { children: "Em breve" })
4893
+ ] }),
4894
+ /* @__PURE__ */ jsxs22(Tooltip4, { children: [
4895
+ /* @__PURE__ */ jsx24(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx24(
4896
+ Button14,
4897
+ {
4898
+ variant: "ghost",
4899
+ size: "icon",
4900
+ className: "h-8 w-8",
4901
+ "aria-label": "Editar",
4902
+ onClick: () => onEdit(row.original),
4903
+ children: /* @__PURE__ */ jsx24(Pencil4, { className: "h-4 w-4" })
4904
+ }
4905
+ ) }),
4906
+ /* @__PURE__ */ jsx24(TooltipContent4, { children: "Editar" })
4907
+ ] }),
4908
+ /* @__PURE__ */ jsxs22(Tooltip4, { children: [
4909
+ /* @__PURE__ */ jsx24(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx24(
4910
+ Button14,
4911
+ {
4912
+ variant: "ghost",
4913
+ size: "icon",
4914
+ className: "h-8 w-8 text-destructive hover:text-destructive",
4915
+ "aria-label": "Excluir",
4916
+ onClick: () => onRemove(row.original),
4917
+ children: /* @__PURE__ */ jsx24(Trash25, { className: "h-4 w-4" })
4918
+ }
4919
+ ) }),
4920
+ /* @__PURE__ */ jsx24(TooltipContent4, { children: "Remover" })
4921
+ ] })
4922
+ ] })
4923
+ }
4924
+ ];
4925
+ }
4926
+ function ToolCredentialsForm({
4927
+ credentials,
4928
+ isLoading,
4929
+ config,
4930
+ gagentsApiUrl,
4931
+ createOpen: externalCreateOpen,
4932
+ onCreateOpenChange
4933
+ }) {
4934
+ const createMutation = useCreateToolCredential(config);
4935
+ const updateMutation = useUpdateToolCredential(config);
4936
+ const deleteMutation = useDeleteToolCredential(config);
4937
+ const { data: toolsData } = useTools(config);
4938
+ const tools = (toolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
5072
4939
  const [search, setSearch] = useState15("");
5073
- const [configTarget, setConfigTarget] = useState15(null);
5074
- const [configInstructions, setConfigInstructions] = useState15("");
5075
- const [configCredentialId, setConfigCredentialId] = useState15("");
5076
- const { data: credentialsData } = useToolCredentials(config);
5077
- const allCredentials = credentialsData?.data || [];
5078
- const agentTools = agentToolsData?.data || [];
5079
- const allTools = (allToolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
5080
- const assignedToolIds = new Set(agentTools.map((at) => at.id_tool));
5081
- const visibleAgentTools = agentTools.filter((at) => {
5082
- const tool = allTools.find((t) => t.id === at.id_tool);
5083
- return !tool || !tool.slug?.startsWith("gclinic_");
4940
+ const [internalCreateOpen, setInternalCreateOpen] = useState15(false);
4941
+ const showCreateDialog = externalCreateOpen ?? internalCreateOpen;
4942
+ const setShowCreateDialog = onCreateOpenChange ?? setInternalCreateOpen;
4943
+ const [createForm, setCreateForm] = useState15({
4944
+ id_tool: "",
4945
+ label: "",
4946
+ credentials_encrypted: "",
4947
+ expires_at: ""
5084
4948
  });
5085
- const availableTools = allTools.filter((t) => !assignedToolIds.has(t.id));
5086
- const filteredAvailable = availableTools.filter(
5087
- (t) => t.name.toLowerCase().includes(search.toLowerCase())
4949
+ const [editTarget, setEditTarget] = useState15(null);
4950
+ const [editForm, setEditForm] = useState15({
4951
+ id_tool: "",
4952
+ label: "",
4953
+ credentials_encrypted: "",
4954
+ expires_at: "",
4955
+ status: ""
4956
+ });
4957
+ const [removeTarget, setRemoveTarget] = useState15(null);
4958
+ const internalToolIds = useMemo7(() => {
4959
+ const allRawTools = toolsData?.data || [];
4960
+ return new Set(
4961
+ allRawTools.filter((t) => t.slug?.startsWith("gclinic_")).map((t) => t.id)
4962
+ );
4963
+ }, [toolsData]);
4964
+ const filteredCredentials = useMemo7(() => {
4965
+ const visible = credentials.filter(
4966
+ (cred) => !cred.id_tool || !internalToolIds.has(cred.id_tool)
4967
+ );
4968
+ if (!search) return visible;
4969
+ const term = search.toLowerCase();
4970
+ return visible.filter((cred) => {
4971
+ const toolName = tools.find((t) => t.id === cred.id_tool)?.name || "";
4972
+ return (cred.label || "").toLowerCase().includes(term) || toolName.toLowerCase().includes(term);
4973
+ });
4974
+ }, [credentials, search, tools, internalToolIds]);
4975
+ const columns = useColumns3(
4976
+ tools,
4977
+ (cred) => startEdit(cred),
4978
+ (cred) => handleConnect(cred),
4979
+ (cred) => setRemoveTarget(cred)
5088
4980
  );
5089
- function getToolInfo(idTool) {
5090
- return allTools.find((t) => t.id === idTool);
5091
- }
5092
- async function handleToggleEnabled(agentTool, checked) {
4981
+ async function handleCreate() {
4982
+ const idTool = parseInt(createForm.id_tool, 10);
4983
+ if (!idTool || !createForm.label.trim() || !createForm.credentials_encrypted.trim()) return;
5093
4984
  try {
5094
- await updateMutation.mutateAsync({
5095
- idAgent: agent.id,
5096
- id: agentTool.id,
5097
- body: { enabled: checked }
4985
+ const result = await createMutation.mutateAsync({
4986
+ id_tool: idTool,
4987
+ label: createForm.label.trim(),
4988
+ credentials_encrypted: createForm.credentials_encrypted.trim(),
4989
+ ...createForm.expires_at ? { expires_at: createForm.expires_at } : {}
5098
4990
  });
5099
- toast11.success(checked ? "Ferramenta ativada" : "Ferramenta desativada");
5100
- } catch (err) {
5101
- toast11.error(
5102
- err instanceof Error ? err.message : "Erro ao alterar estado da ferramenta"
5103
- );
4991
+ if (result.status === 1) {
4992
+ toast11.success("Credencial criada");
4993
+ setShowCreateDialog(false);
4994
+ setCreateForm({ id_tool: "", label: "", credentials_encrypted: "", expires_at: "" });
4995
+ } else {
4996
+ toast11.error(result.message || "Erro ao criar credencial");
4997
+ }
4998
+ } catch {
4999
+ toast11.error("Erro ao criar credencial");
5104
5000
  }
5105
5001
  }
5106
- async function handleAdd(tool) {
5107
- try {
5108
- await addMutation.mutateAsync({
5109
- idAgent: agent.id,
5110
- body: { id_tool: tool.id }
5111
- });
5112
- toast11.success("Ferramenta adicionada");
5113
- setAddOpen(false);
5114
- setSearch("");
5115
- } catch (err) {
5116
- toast11.error(
5117
- err instanceof Error ? err.message : "Erro ao adicionar ferramenta"
5118
- );
5119
- }
5002
+ function startEdit(cred) {
5003
+ setEditTarget(cred);
5004
+ setEditForm({
5005
+ id_tool: cred.id_tool ? String(cred.id_tool) : "",
5006
+ label: cred.label || "",
5007
+ credentials_encrypted: "",
5008
+ expires_at: cred.expires_at || "",
5009
+ status: cred.status
5010
+ });
5120
5011
  }
5121
- async function handleRemove() {
5122
- if (!removeTarget) return;
5012
+ async function handleSaveEdit() {
5013
+ if (!editTarget) return;
5014
+ const body = {};
5015
+ const newIdTool = editForm.id_tool ? parseInt(editForm.id_tool, 10) : null;
5016
+ if (newIdTool && newIdTool !== editTarget.id_tool) {
5017
+ body.id_tool = newIdTool;
5018
+ }
5019
+ if (editForm.label.trim() && editForm.label.trim() !== (editTarget.label || "")) {
5020
+ body.label = editForm.label.trim();
5021
+ }
5022
+ if (editForm.credentials_encrypted.trim()) {
5023
+ body.credentials_encrypted = editForm.credentials_encrypted.trim();
5024
+ }
5025
+ if (editForm.expires_at !== (editTarget.expires_at || "")) {
5026
+ body.expires_at = editForm.expires_at || null;
5027
+ }
5028
+ if (editForm.status && editForm.status !== editTarget.status) {
5029
+ body.status = editForm.status;
5030
+ }
5031
+ if (Object.keys(body).length === 0) {
5032
+ setEditTarget(null);
5033
+ return;
5034
+ }
5123
5035
  try {
5124
- await removeMutation.mutateAsync({
5125
- idAgent: agent.id,
5126
- id: removeTarget.id
5036
+ const result = await updateMutation.mutateAsync({
5037
+ id: editTarget.id,
5038
+ body
5127
5039
  });
5128
- toast11.success("Ferramenta removida");
5129
- } catch (err) {
5130
- toast11.error(
5131
- err instanceof Error ? err.message : "Erro ao remover ferramenta"
5132
- );
5133
- } finally {
5134
- setRemoveTarget(null);
5040
+ if (result.status === 1) {
5041
+ toast11.success("Credencial atualizada");
5042
+ setEditTarget(null);
5043
+ } else {
5044
+ toast11.error(result.message || "Erro ao atualizar credencial");
5045
+ }
5046
+ } catch {
5047
+ toast11.error("Erro ao atualizar credencial");
5135
5048
  }
5136
5049
  }
5137
- function openConfig(agentTool) {
5138
- setConfigTarget(agentTool);
5139
- setConfigInstructions(agentTool.custom_instructions || "");
5140
- setConfigCredentialId(agentTool.id_tool_credential ? String(agentTool.id_tool_credential) : "");
5141
- }
5142
- async function handleSaveConfig() {
5143
- if (!configTarget) return;
5050
+ async function handleRemove() {
5051
+ if (!removeTarget) return;
5144
5052
  try {
5145
- const newCredentialId = configCredentialId ? parseInt(configCredentialId, 10) : null;
5146
- await updateMutation.mutateAsync({
5147
- idAgent: agent.id,
5148
- id: configTarget.id,
5149
- body: {
5150
- custom_instructions: configInstructions.trim() || null,
5151
- id_tool_credential: newCredentialId
5152
- }
5153
- });
5154
- toast11.success("Configura\xE7\xE3o atualizada");
5155
- setConfigTarget(null);
5156
- } catch (err) {
5157
- toast11.error(
5158
- err instanceof Error ? err.message : "Erro ao atualizar configura\xE7\xE3o"
5159
- );
5053
+ const result = await deleteMutation.mutateAsync(removeTarget.id);
5054
+ if (result.status === 1) {
5055
+ toast11.success("Credencial removida");
5056
+ } else {
5057
+ toast11.error(result.message || "Erro ao remover credencial");
5058
+ }
5059
+ } catch {
5060
+ toast11.error("Erro ao remover credencial");
5061
+ } finally {
5062
+ setRemoveTarget(null);
5160
5063
  }
5161
5064
  }
5162
- if (isLoading) {
5163
- return /* @__PURE__ */ jsx24("div", { className: "space-y-3 p-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx24(Skeleton6, { className: "h-14 w-full" }, i)) });
5065
+ function handleConnect(cred) {
5066
+ if (!config.accountId || !config.token) return;
5067
+ const language = config.language ?? "pt-br";
5068
+ const idWl = config.idWl ?? 1;
5069
+ const url = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${config.accountId}/oauth/connect?id_tool=${cred.id_tool}`;
5070
+ window.open(url, "_blank");
5164
5071
  }
5165
- return /* @__PURE__ */ jsxs22("div", { className: "space-y-4 p-4", children: [
5166
- /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between", children: [
5167
- /* @__PURE__ */ jsxs22("h3", { className: "text-sm font-medium text-muted-foreground", children: [
5168
- visibleAgentTools.length,
5169
- " ferramenta",
5170
- visibleAgentTools.length !== 1 ? "s" : "",
5171
- " associada",
5172
- visibleAgentTools.length !== 1 ? "s" : ""
5173
- ] }),
5174
- /* @__PURE__ */ jsxs22(Popover, { open: addOpen, onOpenChange: setAddOpen, children: [
5175
- /* @__PURE__ */ jsx24(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs22(Button14, { size: "sm", disabled: availableTools.length === 0, children: [
5176
- /* @__PURE__ */ jsx24(Plus3, { className: "mr-2 h-4 w-4" }),
5177
- "Adicionar Ferramenta"
5178
- ] }) }),
5179
- /* @__PURE__ */ jsxs22(PopoverContent, { className: "w-72 p-0", align: "end", children: [
5180
- /* @__PURE__ */ jsx24("div", { className: "p-2", children: /* @__PURE__ */ jsx24(
5072
+ return /* @__PURE__ */ jsxs22("div", { className: "space-y-4", children: [
5073
+ /* @__PURE__ */ jsx24("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs22("div", { className: "relative flex-1 max-w-md", children: [
5074
+ /* @__PURE__ */ jsx24(Search3, { "aria-hidden": "true", className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
5075
+ /* @__PURE__ */ jsx24(
5076
+ Input10,
5077
+ {
5078
+ placeholder: "Buscar credenciais\\u2026",
5079
+ "aria-label": "Buscar credenciais",
5080
+ name: "search",
5081
+ autoComplete: "off",
5082
+ value: search,
5083
+ onChange: (e) => setSearch(e.target.value),
5084
+ className: "pl-9"
5085
+ }
5086
+ )
5087
+ ] }) }),
5088
+ /* @__PURE__ */ jsx24(
5089
+ DataTable3,
5090
+ {
5091
+ columns,
5092
+ data: filteredCredentials,
5093
+ isLoading,
5094
+ emptyMessage: "Nenhuma credencial encontrada"
5095
+ }
5096
+ ),
5097
+ /* @__PURE__ */ jsx24(Dialog7, { open: showCreateDialog, onOpenChange: setShowCreateDialog, children: /* @__PURE__ */ jsxs22(DialogContent7, { children: [
5098
+ /* @__PURE__ */ jsx24(DialogHeader7, { children: /* @__PURE__ */ jsx24(DialogTitle7, { children: "Nova Credencial" }) }),
5099
+ /* @__PURE__ */ jsxs22("div", { className: "space-y-4", children: [
5100
+ /* @__PURE__ */ jsxs22("div", { children: [
5101
+ /* @__PURE__ */ jsx24("label", { htmlFor: "cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
5102
+ /* @__PURE__ */ jsxs22(
5103
+ Select4,
5104
+ {
5105
+ value: createForm.id_tool,
5106
+ onValueChange: (val) => setCreateForm((f) => ({ ...f, id_tool: val })),
5107
+ children: [
5108
+ /* @__PURE__ */ jsx24(SelectTrigger4, { id: "cred-tool", children: /* @__PURE__ */ jsx24(SelectValue4, { placeholder: "Selecione a ferramenta" }) }),
5109
+ /* @__PURE__ */ jsx24(SelectContent4, { children: tools.map((tool) => /* @__PURE__ */ jsx24(SelectItem4, { value: String(tool.id), children: tool.name }, tool.id)) })
5110
+ ]
5111
+ }
5112
+ )
5113
+ ] }),
5114
+ /* @__PURE__ */ jsxs22("div", { children: [
5115
+ /* @__PURE__ */ jsx24("label", { htmlFor: "cred-label", className: "mb-1 block text-sm font-medium", children: "Label *" }),
5116
+ /* @__PURE__ */ jsx24(
5181
5117
  Input10,
5182
5118
  {
5183
- placeholder: "Buscar ferramenta\\u2026",
5184
- "aria-label": "Buscar ferramenta",
5185
- name: "search",
5186
- value: search,
5187
- onChange: (e) => setSearch(e.target.value),
5188
- className: "h-8"
5119
+ id: "cred-label",
5120
+ name: "label",
5121
+ value: createForm.label,
5122
+ onChange: (e) => setCreateForm((f) => ({ ...f, label: e.target.value })),
5123
+ placeholder: "Ex: Google Calendar - Cl\xEDnica S\xE3o Paulo"
5189
5124
  }
5190
- ) }),
5191
- /* @__PURE__ */ jsx24("div", { className: "max-h-48 overflow-y-auto", children: filteredAvailable.length === 0 ? /* @__PURE__ */ jsx24("p", { className: "p-3 text-center text-sm text-muted-foreground", children: "Nenhuma ferramenta dispon\xEDvel" }) : filteredAvailable.map((tool) => /* @__PURE__ */ jsxs22(
5192
- "button",
5125
+ )
5126
+ ] }),
5127
+ /* @__PURE__ */ jsxs22("div", { children: [
5128
+ /* @__PURE__ */ jsx24("label", { htmlFor: "cred-credential", className: "mb-1 block text-sm font-medium", children: "Credencial *" }),
5129
+ /* @__PURE__ */ jsx24(
5130
+ Input10,
5193
5131
  {
5194
- type: "button",
5195
- className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-accent",
5196
- onClick: () => handleAdd(tool),
5197
- disabled: addMutation.isPending,
5198
- children: [
5199
- /* @__PURE__ */ jsx24(Wrench, { className: "h-4 w-4 text-muted-foreground" }),
5200
- /* @__PURE__ */ jsx24("span", { className: "flex-1 font-medium", children: tool.name }),
5201
- /* @__PURE__ */ jsx24(Badge9, { variant: "secondary", className: "text-xs", children: tool.type })
5202
- ]
5203
- },
5204
- tool.id
5205
- )) })
5132
+ id: "cred-credential",
5133
+ name: "credential",
5134
+ autoComplete: "off",
5135
+ type: "password",
5136
+ value: createForm.credentials_encrypted,
5137
+ onChange: (e) => setCreateForm((f) => ({
5138
+ ...f,
5139
+ credentials_encrypted: e.target.value
5140
+ })),
5141
+ placeholder: "Credencial encriptada"
5142
+ }
5143
+ )
5144
+ ] }),
5145
+ /* @__PURE__ */ jsxs22("div", { children: [
5146
+ /* @__PURE__ */ jsx24("label", { htmlFor: "cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o (opcional)" }),
5147
+ /* @__PURE__ */ jsx24(
5148
+ Input10,
5149
+ {
5150
+ id: "cred-expires",
5151
+ name: "expires",
5152
+ type: "date",
5153
+ value: createForm.expires_at,
5154
+ onChange: (e) => setCreateForm((f) => ({ ...f, expires_at: e.target.value }))
5155
+ }
5156
+ )
5206
5157
  ] })
5158
+ ] }),
5159
+ /* @__PURE__ */ jsxs22(DialogFooter7, { children: [
5160
+ /* @__PURE__ */ jsx24(
5161
+ Button14,
5162
+ {
5163
+ variant: "outline",
5164
+ onClick: () => setShowCreateDialog(false),
5165
+ children: "Cancelar"
5166
+ }
5167
+ ),
5168
+ /* @__PURE__ */ jsx24(
5169
+ Button14,
5170
+ {
5171
+ onClick: handleCreate,
5172
+ disabled: !createForm.id_tool || !createForm.label.trim() || !createForm.credentials_encrypted.trim() || createMutation.isPending,
5173
+ children: "Criar"
5174
+ }
5175
+ )
5207
5176
  ] })
5208
- ] }),
5209
- visibleAgentTools.length === 0 ? /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
5210
- /* @__PURE__ */ jsx24(Wrench, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
5211
- /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Nenhuma ferramenta associada. Clique em 'Adicionar Ferramenta' para come\xE7ar." })
5212
- ] }) : /* @__PURE__ */ jsx24("div", { className: "space-y-2", children: visibleAgentTools.map((agentTool) => {
5213
- const tool = getToolInfo(agentTool.id_tool);
5214
- return /* @__PURE__ */ jsxs22(
5215
- "div",
5216
- {
5217
- className: "flex items-center gap-3 rounded-lg border bg-card p-3",
5218
- children: [
5219
- /* @__PURE__ */ jsxs22("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [
5220
- /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
5221
- /* @__PURE__ */ jsx24("span", { className: "truncate font-medium", children: tool?.name || `Ferramenta #${agentTool.id_tool}` }),
5222
- tool?.type && /* @__PURE__ */ jsx24(Badge9, { variant: "secondary", className: "shrink-0 text-xs", children: tool.type })
5223
- ] }),
5224
- agentTool.custom_instructions && /* @__PURE__ */ jsx24("p", { className: "truncate text-xs text-muted-foreground", children: agentTool.custom_instructions })
5225
- ] }),
5226
- /* @__PURE__ */ jsx24(
5227
- Switch5,
5228
- {
5229
- "aria-label": "Ativar/Desativar",
5230
- checked: agentTool.enabled,
5231
- onCheckedChange: (checked) => handleToggleEnabled(agentTool, checked),
5232
- disabled: updateMutation.isPending
5233
- }
5234
- ),
5235
- /* @__PURE__ */ jsx24(
5236
- Button14,
5237
- {
5238
- variant: "ghost",
5239
- size: "icon",
5240
- "aria-label": "Configurar",
5241
- className: "shrink-0 text-muted-foreground hover:text-foreground",
5242
- onClick: () => openConfig(agentTool),
5243
- title: "Configurar instru\xE7\xF5es",
5244
- children: /* @__PURE__ */ jsx24(Settings22, { className: "h-4 w-4" })
5245
- }
5246
- ),
5247
- /* @__PURE__ */ jsx24(
5248
- Button14,
5249
- {
5250
- variant: "ghost",
5251
- size: "icon",
5252
- "aria-label": "Remover",
5253
- className: "shrink-0 text-muted-foreground hover:text-destructive",
5254
- onClick: () => setRemoveTarget(agentTool),
5255
- children: /* @__PURE__ */ jsx24(Trash25, { className: "h-4 w-4" })
5256
- }
5257
- )
5258
- ]
5259
- },
5260
- agentTool.id
5261
- );
5262
- }) }),
5177
+ ] }) }),
5263
5178
  /* @__PURE__ */ jsx24(
5264
5179
  Dialog7,
5265
5180
  {
5266
- open: !!configTarget,
5267
- onOpenChange: (open) => !open && setConfigTarget(null),
5268
- children: /* @__PURE__ */ jsxs22(DialogContent7, { className: "sm:max-w-lg", children: [
5269
- /* @__PURE__ */ jsx24(DialogHeader7, { children: /* @__PURE__ */ jsx24(DialogTitle7, { children: "Instru\xE7\xF5es da Ferramenta" }) }),
5181
+ open: !!editTarget,
5182
+ onOpenChange: (open) => !open && setEditTarget(null),
5183
+ children: /* @__PURE__ */ jsxs22(DialogContent7, { children: [
5184
+ /* @__PURE__ */ jsx24(DialogHeader7, { children: /* @__PURE__ */ jsx24(DialogTitle7, { children: "Editar Credencial" }) }),
5270
5185
  /* @__PURE__ */ jsxs22("div", { className: "space-y-4", children: [
5271
- configTarget && getToolInfo(configTarget.id_tool)?.type !== "none" && /* @__PURE__ */ jsxs22("div", { className: "space-y-2", children: [
5272
- /* @__PURE__ */ jsx24(Label8, { htmlFor: "tool-credential", children: "Credencial" }),
5186
+ /* @__PURE__ */ jsxs22("div", { children: [
5187
+ /* @__PURE__ */ jsx24("label", { htmlFor: "edit-cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
5273
5188
  /* @__PURE__ */ jsxs22(
5274
5189
  Select4,
5275
5190
  {
5276
- value: configCredentialId || void 0,
5277
- onValueChange: (val) => setConfigCredentialId(val === "__none__" ? "" : val),
5191
+ value: editForm.id_tool,
5192
+ onValueChange: (val) => setEditForm((f) => ({ ...f, id_tool: val })),
5278
5193
  children: [
5279
- /* @__PURE__ */ jsx24(SelectTrigger4, { id: "tool-credential", children: /* @__PURE__ */ jsx24(SelectValue4, { placeholder: "Selecione uma credencial (opcional)" }) }),
5280
- /* @__PURE__ */ jsxs22(SelectContent4, { children: [
5281
- /* @__PURE__ */ jsx24(SelectItem4, { value: "__none__", children: "Nenhuma (autom\xE1tico)" }),
5282
- allCredentials.filter((c) => configTarget && c.id_tool === configTarget.id_tool && c.status === "active").map((c) => /* @__PURE__ */ jsx24(SelectItem4, { value: String(c.id), children: c.label || `Credencial #${c.id}` }, c.id))
5283
- ] })
5194
+ /* @__PURE__ */ jsx24(SelectTrigger4, { id: "edit-cred-tool", children: /* @__PURE__ */ jsx24(SelectValue4, { placeholder: "Selecione a ferramenta" }) }),
5195
+ /* @__PURE__ */ jsx24(SelectContent4, { children: tools.map((tool) => /* @__PURE__ */ jsx24(SelectItem4, { value: String(tool.id), children: tool.name }, tool.id)) })
5284
5196
  ]
5285
5197
  }
5286
- ),
5287
- /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Vincule uma credencial espec\xEDfica a esta ferramenta neste agente." })
5198
+ )
5288
5199
  ] }),
5289
- /* @__PURE__ */ jsxs22("div", { className: "space-y-2", children: [
5290
- /* @__PURE__ */ jsx24(Label8, { htmlFor: "tool-instructions", children: "Instru\xE7\xF5es Personalizadas" }),
5200
+ /* @__PURE__ */ jsxs22("div", { children: [
5201
+ /* @__PURE__ */ jsx24("label", { htmlFor: "edit-cred-label", className: "mb-1 block text-sm font-medium", children: "Label" }),
5291
5202
  /* @__PURE__ */ jsx24(
5292
- Textarea3,
5203
+ Input10,
5293
5204
  {
5294
- id: "tool-instructions",
5295
- name: "instructions",
5296
- value: configInstructions,
5297
- onChange: (e) => setConfigInstructions(e.target.value),
5298
- placeholder: "Instru\\u00e7\\u00f5es sobre como e quando o agente deve usar esta ferramenta\\u2026",
5299
- rows: 6
5205
+ id: "edit-cred-label",
5206
+ name: "label",
5207
+ value: editForm.label,
5208
+ onChange: (e) => setEditForm((f) => ({ ...f, label: e.target.value })),
5209
+ placeholder: "Label da credencial"
5300
5210
  }
5301
- ),
5302
- /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Este texto \xE9 adicionado ao prompt do agente para orientar o uso da ferramenta." })
5211
+ )
5212
+ ] }),
5213
+ /* @__PURE__ */ jsxs22("div", { children: [
5214
+ /* @__PURE__ */ jsx24("label", { htmlFor: "edit-cred-credential", className: "mb-1 block text-sm font-medium", children: "Nova Credencial (vazio = manter atual)" }),
5215
+ /* @__PURE__ */ jsx24(
5216
+ Input10,
5217
+ {
5218
+ id: "edit-cred-credential",
5219
+ name: "credential",
5220
+ autoComplete: "off",
5221
+ type: "password",
5222
+ value: editForm.credentials_encrypted,
5223
+ onChange: (e) => setEditForm((f) => ({
5224
+ ...f,
5225
+ credentials_encrypted: e.target.value
5226
+ })),
5227
+ placeholder: "Nova credencial"
5228
+ }
5229
+ )
5230
+ ] }),
5231
+ /* @__PURE__ */ jsxs22("div", { children: [
5232
+ /* @__PURE__ */ jsx24("label", { htmlFor: "edit-cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o" }),
5233
+ /* @__PURE__ */ jsx24(
5234
+ Input10,
5235
+ {
5236
+ id: "edit-cred-expires",
5237
+ name: "expires",
5238
+ type: "date",
5239
+ value: editForm.expires_at,
5240
+ onChange: (e) => setEditForm((f) => ({ ...f, expires_at: e.target.value }))
5241
+ }
5242
+ )
5243
+ ] }),
5244
+ /* @__PURE__ */ jsxs22("div", { children: [
5245
+ /* @__PURE__ */ jsx24("label", { htmlFor: "edit-cred-status", className: "mb-1 block text-sm font-medium", children: "Status" }),
5246
+ /* @__PURE__ */ jsxs22(
5247
+ Select4,
5248
+ {
5249
+ value: editForm.status || void 0,
5250
+ onValueChange: (val) => setEditForm((f) => ({
5251
+ ...f,
5252
+ status: val
5253
+ })),
5254
+ children: [
5255
+ /* @__PURE__ */ jsx24(SelectTrigger4, { id: "edit-cred-status", children: /* @__PURE__ */ jsx24(SelectValue4, {}) }),
5256
+ /* @__PURE__ */ jsxs22(SelectContent4, { children: [
5257
+ /* @__PURE__ */ jsx24(SelectItem4, { value: "active", children: "Ativo" }),
5258
+ /* @__PURE__ */ jsx24(SelectItem4, { value: "expired", children: "Expirado" })
5259
+ ] })
5260
+ ]
5261
+ }
5262
+ )
5303
5263
  ] })
5304
5264
  ] }),
5305
5265
  /* @__PURE__ */ jsxs22(DialogFooter7, { children: [
5266
+ /* @__PURE__ */ jsx24(Button14, { variant: "outline", onClick: () => setEditTarget(null), children: "Cancelar" }),
5306
5267
  /* @__PURE__ */ jsx24(
5307
5268
  Button14,
5308
5269
  {
5309
- variant: "outline",
5310
- onClick: () => setConfigTarget(null),
5311
- children: "Cancelar"
5312
- }
5313
- ),
5314
- /* @__PURE__ */ jsx24(
5315
- Button14,
5316
- {
5317
- onClick: handleSaveConfig,
5270
+ onClick: handleSaveEdit,
5318
5271
  disabled: updateMutation.isPending,
5319
5272
  children: "Salvar"
5320
5273
  }
@@ -5330,8 +5283,8 @@ function AgentToolsList({ agent, config }) {
5330
5283
  onOpenChange: (open) => !open && setRemoveTarget(null),
5331
5284
  children: /* @__PURE__ */ jsxs22(AlertDialogContent5, { children: [
5332
5285
  /* @__PURE__ */ jsxs22(AlertDialogHeader5, { children: [
5333
- /* @__PURE__ */ jsx24(AlertDialogTitle5, { children: "Remover ferramenta?" }),
5334
- /* @__PURE__ */ jsx24(AlertDialogDescription5, { children: "A ferramenta ser\xE1 desassociada deste agente." })
5286
+ /* @__PURE__ */ jsx24(AlertDialogTitle5, { children: "Remover credencial?" }),
5287
+ /* @__PURE__ */ jsx24(AlertDialogDescription5, { children: "A credencial ser\xE1 removida permanentemente." })
5335
5288
  ] }),
5336
5289
  /* @__PURE__ */ jsxs22(AlertDialogFooter5, { children: [
5337
5290
  /* @__PURE__ */ jsx24(AlertDialogCancel5, { children: "Cancelar" }),
@@ -5339,7 +5292,7 @@ function AgentToolsList({ agent, config }) {
5339
5292
  AlertDialogAction5,
5340
5293
  {
5341
5294
  onClick: handleRemove,
5342
- disabled: removeMutation.isPending,
5295
+ disabled: deleteMutation.isPending,
5343
5296
  children: "Remover"
5344
5297
  }
5345
5298
  )