@greatapps/greatagents-ui 0.3.9 → 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
@@ -518,34 +518,55 @@ function useIntegrationState(config, agentId) {
518
518
  const credentials = credentialsData?.data ?? [];
519
519
  const tools = toolsData?.data ?? [];
520
520
  const agentTools = agentToolsData?.data ?? [];
521
- return INTEGRATIONS_REGISTRY.map((def) => {
521
+ const result = [];
522
+ for (const def of INTEGRATIONS_REGISTRY) {
522
523
  if (def.status === "coming_soon") {
523
- return {
524
+ result.push({
524
525
  definition: def,
525
526
  state: "coming_soon",
526
527
  credential: null,
527
528
  tool: null,
528
529
  sharedByAgentsCount: 0,
529
530
  linkedToAgent: false
530
- };
531
+ });
532
+ continue;
531
533
  }
532
534
  const matchedTool = tools.find((t) => t.slug === def.slug) ?? null;
533
- const matchedCredential = matchedTool ? credentials.find((c) => c.id_tool === matchedTool.id) ?? null : null;
535
+ const matchedCredentials = matchedTool ? credentials.filter((c) => c.id_tool === matchedTool.id) : [];
536
+ const piCredentials = credentials.filter(
537
+ (c) => c.id_platform_integration != null && !c.id_tool && // We can't directly match slug here since we don't have
538
+ // platform_integrations data, but credentials with
539
+ // id_platform_integration are for calendar integrations
540
+ // which match by the registry slug
541
+ matchedTool == null
542
+ );
543
+ const allCredentials = matchedCredentials.length > 0 ? matchedCredentials : piCredentials;
534
544
  const linkedToAgent = matchedTool ? agentTools.some((at) => at.id_tool === matchedTool.id) : false;
535
- const sharedByAgentsCount = matchedCredential ? 1 : 0;
536
- let state = "available";
537
- if (matchedCredential) {
538
- state = matchedCredential.status === "expired" ? "expired" : "connected";
545
+ for (const cred of allCredentials) {
546
+ const state = cred.status === "expired" ? "expired" : "connected";
547
+ const accountLabel = cred.external_reference || cred.label || void 0;
548
+ result.push({
549
+ definition: def,
550
+ state,
551
+ credential: cred,
552
+ tool: matchedTool,
553
+ sharedByAgentsCount: 1,
554
+ linkedToAgent,
555
+ credentialId: cred.id,
556
+ accountLabel
557
+ });
539
558
  }
540
- return {
559
+ result.push({
541
560
  definition: def,
542
- state,
543
- credential: matchedCredential,
561
+ state: "available",
562
+ credential: null,
544
563
  tool: matchedTool,
545
- sharedByAgentsCount,
546
- linkedToAgent
547
- };
548
- });
564
+ sharedByAgentsCount: 0,
565
+ linkedToAgent: false,
566
+ isAddNew: true
567
+ });
568
+ }
569
+ return result;
549
570
  }, [credentialsData, toolsData, agentToolsData]);
550
571
  return { cards, isLoading };
551
572
  }
@@ -2477,7 +2498,7 @@ function AgentConversationsPanel({
2477
2498
  }
2478
2499
 
2479
2500
  // src/pages/agent-capabilities-page.tsx
2480
- import { useState as useState14, useCallback as useCallback6 } from "react";
2501
+ import { useState as useState13, useCallback as useCallback6 } from "react";
2481
2502
  import {
2482
2503
  Tabs,
2483
2504
  TabsList,
@@ -2487,7 +2508,7 @@ import {
2487
2508
  import { Blocks, Plug as Plug3, Settings as Settings3 } from "lucide-react";
2488
2509
 
2489
2510
  // src/components/capabilities/capabilities-tab.tsx
2490
- 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";
2491
2512
  import {
2492
2513
  Accordion,
2493
2514
  AccordionItem,
@@ -2505,7 +2526,8 @@ import {
2505
2526
  Settings,
2506
2527
  HeartHandshake,
2507
2528
  Package,
2508
- ChevronDown as ChevronDown2
2529
+ ChevronDown as ChevronDown2,
2530
+ Loader2 as Loader24
2509
2531
  } from "lucide-react";
2510
2532
  import { toast as toast6 } from "sonner";
2511
2533
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
@@ -2566,7 +2588,6 @@ function CapabilitiesTab({ config, agentId }) {
2566
2588
  const [localState, setLocalState] = useState8(/* @__PURE__ */ new Map());
2567
2589
  const [serverState, setServerState] = useState8(/* @__PURE__ */ new Map());
2568
2590
  const [initialized, setInitialized] = useState8(false);
2569
- const debounceRef = useRef2(null);
2570
2591
  useEffect4(() => {
2571
2592
  if (agentCaps && !initialized) {
2572
2593
  const state = buildStateFromAgent(agentCaps);
@@ -2582,37 +2603,11 @@ function CapabilitiesTab({ config, agentId }) {
2582
2603
  () => initialized && !statesEqual(localState, serverState),
2583
2604
  [localState, serverState, initialized]
2584
2605
  );
2585
- const scheduleSave = useCallback4(
2586
- (nextState) => {
2587
- if (debounceRef.current) clearTimeout(debounceRef.current);
2588
- debounceRef.current = setTimeout(() => {
2589
- const payload = stateToPayload(nextState);
2590
- updateMutation.mutate(
2591
- { agentId, payload },
2592
- {
2593
- onSuccess: () => {
2594
- setServerState(cloneState(nextState));
2595
- toast6.success("Capacidades salvas");
2596
- },
2597
- onError: () => {
2598
- setLocalState(cloneState(serverState));
2599
- toast6.error("Erro ao salvar capacidades");
2600
- }
2601
- }
2602
- );
2603
- }, 500);
2604
- },
2605
- [agentId, updateMutation, serverState]
2606
- );
2607
2606
  const updateState = useCallback4(
2608
2607
  (updater) => {
2609
- setLocalState((prev) => {
2610
- const next = updater(prev);
2611
- scheduleSave(next);
2612
- return next;
2613
- });
2608
+ setLocalState((prev) => updater(prev));
2614
2609
  },
2615
- [scheduleSave]
2610
+ []
2616
2611
  );
2617
2612
  const toggleModule = useCallback4(
2618
2613
  (mod, enabled) => {
@@ -2664,11 +2659,9 @@ function CapabilitiesTab({ config, agentId }) {
2664
2659
  updateState(() => /* @__PURE__ */ new Map());
2665
2660
  }, [updateState]);
2666
2661
  const discard = useCallback4(() => {
2667
- if (debounceRef.current) clearTimeout(debounceRef.current);
2668
2662
  setLocalState(cloneState(serverState));
2669
2663
  }, [serverState]);
2670
2664
  const saveNow = useCallback4(() => {
2671
- if (debounceRef.current) clearTimeout(debounceRef.current);
2672
2665
  const payload = stateToPayload(localState);
2673
2666
  updateMutation.mutate(
2674
2667
  { agentId, payload },
@@ -2750,19 +2743,14 @@ function CapabilitiesTab({ config, agentId }) {
2750
2743
  cat.slug
2751
2744
  );
2752
2745
  }) }),
2753
- hasChanges && /* @__PURE__ */ jsxs8("div", { className: "sticky bottom-0 bg-background border-t py-3 px-4 -mx-4 flex items-center justify-between", children: [
2754
- /* @__PURE__ */ jsx10("span", { className: "text-sm text-muted-foreground", children: "Voc\xEA tem altera\xE7\xF5es n\xE3o salvas." }),
2755
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2756
- /* @__PURE__ */ jsx10(Button7, { variant: "outline", size: "sm", onClick: discard, children: "Descartar" }),
2757
- /* @__PURE__ */ jsx10(
2758
- Button7,
2759
- {
2760
- size: "sm",
2761
- onClick: saveNow,
2762
- disabled: updateMutation.isPending,
2763
- children: updateMutation.isPending ? "Salvando..." : "Salvar"
2764
- }
2765
- )
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
+ ] })
2766
2754
  ] })
2767
2755
  ] })
2768
2756
  ] });
@@ -2846,7 +2834,8 @@ import {
2846
2834
  Settings as Settings2,
2847
2835
  RefreshCw,
2848
2836
  Users as Users2,
2849
- Clock
2837
+ Clock,
2838
+ Plus as Plus2
2850
2839
  } from "lucide-react";
2851
2840
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2852
2841
  var ICON_MAP = {
@@ -2855,7 +2844,8 @@ var ICON_MAP = {
2855
2844
  Settings: Settings2,
2856
2845
  RefreshCw,
2857
2846
  Users: Users2,
2858
- Clock
2847
+ Clock,
2848
+ Plus: Plus2
2859
2849
  };
2860
2850
  function resolveIcon(name) {
2861
2851
  return ICON_MAP[name] ?? Plug;
@@ -2878,8 +2868,9 @@ var STATE_BADGES = {
2878
2868
  className: "bg-muted text-muted-foreground"
2879
2869
  }
2880
2870
  };
2881
- function getActionLabel(state) {
2882
- switch (state) {
2871
+ function getActionLabel(card) {
2872
+ if (card.isAddNew) return "Conectar";
2873
+ switch (card.state) {
2883
2874
  case "available":
2884
2875
  return "Conectar";
2885
2876
  case "connected":
@@ -2891,11 +2882,58 @@ function getActionLabel(state) {
2891
2882
  }
2892
2883
  }
2893
2884
  function IntegrationCard({ card, onConnect }) {
2894
- const { definition, state, sharedByAgentsCount } = card;
2885
+ const { definition, state, sharedByAgentsCount, isAddNew, accountLabel } = card;
2895
2886
  const Icon = resolveIcon(definition.icon);
2896
- const badge = STATE_BADGES[state];
2897
- const actionLabel = getActionLabel(state);
2898
2887
  const isComingSoon = state === "coming_soon";
2888
+ const actionLabel = getActionLabel(card);
2889
+ if (isAddNew) {
2890
+ return /* @__PURE__ */ jsxs9(
2891
+ "div",
2892
+ {
2893
+ className: cn(
2894
+ "group relative flex flex-col gap-3 rounded-xl border border-dashed bg-card/50 p-5 transition-shadow",
2895
+ "hover:shadow-md hover:border-solid hover:bg-card cursor-pointer"
2896
+ ),
2897
+ role: "button",
2898
+ tabIndex: 0,
2899
+ "aria-label": `Adicionar conta ${definition.name}`,
2900
+ onClick: () => onConnect(card),
2901
+ onKeyDown: (e) => {
2902
+ if (e.key === "Enter" || e.key === " ") {
2903
+ e.preventDefault();
2904
+ onConnect(card);
2905
+ }
2906
+ },
2907
+ children: [
2908
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between gap-2", children: [
2909
+ /* @__PURE__ */ jsx11("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/5 text-primary/60", children: /* @__PURE__ */ jsx11(Icon, { className: "h-5 w-5" }) }),
2910
+ /* @__PURE__ */ jsx11(Badge6, { variant: "outline", className: "text-xs bg-muted text-muted-foreground", children: "Adicionar" })
2911
+ ] }),
2912
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
2913
+ /* @__PURE__ */ jsx11("h3", { className: "text-sm font-semibold leading-tight text-muted-foreground", children: definition.name }),
2914
+ /* @__PURE__ */ jsxs9("p", { className: "text-xs text-muted-foreground/70 leading-relaxed flex items-center gap-1", children: [
2915
+ /* @__PURE__ */ jsx11(Plus2, { className: "h-3 w-3" }),
2916
+ "Adicionar conta"
2917
+ ] })
2918
+ ] }),
2919
+ /* @__PURE__ */ jsx11("div", { className: "mt-auto flex items-center justify-end pt-1", children: /* @__PURE__ */ jsx11(
2920
+ Button8,
2921
+ {
2922
+ variant: "outline",
2923
+ size: "sm",
2924
+ className: "text-xs",
2925
+ onClick: (e) => {
2926
+ e.stopPropagation();
2927
+ onConnect(card);
2928
+ },
2929
+ children: actionLabel
2930
+ }
2931
+ ) })
2932
+ ]
2933
+ }
2934
+ );
2935
+ }
2936
+ const badge = STATE_BADGES[state];
2899
2937
  return /* @__PURE__ */ jsxs9(
2900
2938
  "div",
2901
2939
  {
@@ -2905,7 +2943,7 @@ function IntegrationCard({ card, onConnect }) {
2905
2943
  ),
2906
2944
  role: "button",
2907
2945
  tabIndex: isComingSoon ? -1 : 0,
2908
- "aria-label": `${definition.name} \u2014 ${badge.label}`,
2946
+ "aria-label": `${definition.name}${accountLabel ? ` \u2014 ${accountLabel}` : ""} \u2014 ${badge.label}`,
2909
2947
  "aria-disabled": isComingSoon,
2910
2948
  onClick: () => !isComingSoon && onConnect(card),
2911
2949
  onKeyDown: (e) => {
@@ -2921,7 +2959,7 @@ function IntegrationCard({ card, onConnect }) {
2921
2959
  ] }),
2922
2960
  /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
2923
2961
  /* @__PURE__ */ jsx11("h3", { className: "text-sm font-semibold leading-tight", children: definition.name }),
2924
- /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground leading-relaxed", children: definition.description })
2962
+ accountLabel ? /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground leading-relaxed truncate", title: accountLabel, children: accountLabel }) : /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground leading-relaxed", children: definition.description })
2925
2963
  ] }),
2926
2964
  /* @__PURE__ */ jsxs9("div", { className: "mt-auto flex items-center justify-between gap-2 pt-1", children: [
2927
2965
  sharedByAgentsCount > 0 ? /* @__PURE__ */ jsxs9(Tooltip2, { children: [
@@ -2951,8 +2989,17 @@ function IntegrationCard({ card, onConnect }) {
2951
2989
  }
2952
2990
 
2953
2991
  // src/components/capabilities/integrations-tab.tsx
2954
- import { Plug as Plug2, Loader2 as Loader24 } from "lucide-react";
2992
+ import { Plug as Plug2, Loader2 as Loader25 } from "lucide-react";
2955
2993
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2994
+ function getCardKey(card) {
2995
+ if (card.credentialId) {
2996
+ return `${card.definition.slug}-cred-${card.credentialId}`;
2997
+ }
2998
+ if (card.isAddNew) {
2999
+ return `${card.definition.slug}-add-new`;
3000
+ }
3001
+ return card.definition.slug;
3002
+ }
2956
3003
  function IntegrationsTab({
2957
3004
  config,
2958
3005
  agentId,
@@ -2960,7 +3007,7 @@ function IntegrationsTab({
2960
3007
  }) {
2961
3008
  const { cards, isLoading } = useIntegrationState(config, agentId);
2962
3009
  if (isLoading) {
2963
- 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" }) });
2964
3011
  }
2965
3012
  if (cards.length === 0) {
2966
3013
  return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center justify-center gap-3 py-16 text-muted-foreground", children: [
@@ -2968,18 +3015,40 @@ function IntegrationsTab({
2968
3015
  /* @__PURE__ */ jsx12("p", { className: "text-sm", children: "Nenhuma integra\xE7\xE3o dispon\xEDvel" })
2969
3016
  ] });
2970
3017
  }
2971
- return /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: cards.map((card) => /* @__PURE__ */ jsx12(
2972
- IntegrationCard,
2973
- {
2974
- card,
2975
- onConnect
2976
- },
2977
- card.definition.slug
2978
- )) });
3018
+ const connectedCards = cards.filter(
3019
+ (c) => !c.isAddNew && (c.state === "connected" || c.state === "expired")
3020
+ );
3021
+ const otherCards = cards.filter(
3022
+ (c) => c.isAddNew || c.state === "coming_soon"
3023
+ );
3024
+ return /* @__PURE__ */ jsxs10("div", { className: "space-y-6", children: [
3025
+ connectedCards.length > 0 && /* @__PURE__ */ jsxs10("div", { children: [
3026
+ /* @__PURE__ */ jsx12("h3", { className: "mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: "Contas conectadas" }),
3027
+ /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: connectedCards.map((card) => /* @__PURE__ */ jsx12(
3028
+ IntegrationCard,
3029
+ {
3030
+ card,
3031
+ onConnect
3032
+ },
3033
+ getCardKey(card)
3034
+ )) })
3035
+ ] }),
3036
+ otherCards.length > 0 && /* @__PURE__ */ jsxs10("div", { children: [
3037
+ connectedCards.length > 0 && /* @__PURE__ */ jsx12("h3", { className: "mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: "Adicionar integra\xE7\xE3o" }),
3038
+ /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: otherCards.map((card) => /* @__PURE__ */ jsx12(
3039
+ IntegrationCard,
3040
+ {
3041
+ card,
3042
+ onConnect
3043
+ },
3044
+ getCardKey(card)
3045
+ )) })
3046
+ ] })
3047
+ ] });
2979
3048
  }
2980
3049
 
2981
3050
  // src/components/capabilities/integration-wizard.tsx
2982
- 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";
2983
3052
  import {
2984
3053
  Dialog as Dialog4,
2985
3054
  DialogContent as DialogContent4,
@@ -2988,7 +3057,7 @@ import {
2988
3057
  DialogTitle as DialogTitle4,
2989
3058
  Button as Button10
2990
3059
  } from "@greatapps/greatauth-ui/ui";
2991
- 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";
2992
3061
  import { toast as toast7 } from "sonner";
2993
3062
 
2994
3063
  // src/components/capabilities/wizard-steps/info-step.tsx
@@ -3047,7 +3116,7 @@ function InfoStep({ integration, meta }) {
3047
3116
  }
3048
3117
 
3049
3118
  // src/components/capabilities/wizard-steps/credentials-step.tsx
3050
- import { CheckCircle2, Loader2 as Loader25, AlertCircle, Shield } from "lucide-react";
3119
+ import { CheckCircle2, Loader2 as Loader26, AlertCircle, Shield } from "lucide-react";
3051
3120
  import { Button as Button9, Input as Input6, Label as Label4 } from "@greatapps/greatauth-ui/ui";
3052
3121
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3053
3122
  function CredentialsStep({
@@ -3104,7 +3173,7 @@ function OAuthCredentials({
3104
3173
  ),
3105
3174
  oauthStatus === "waiting" && /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center gap-3 text-center", children: [
3106
3175
  /* @__PURE__ */ jsx14(
3107
- Loader25,
3176
+ Loader26,
3108
3177
  {
3109
3178
  "aria-hidden": "true",
3110
3179
  className: "h-8 w-8 animate-spin text-muted-foreground"
@@ -3196,7 +3265,7 @@ function ApiKeyCredentials({
3196
3265
  }
3197
3266
 
3198
3267
  // src/components/capabilities/wizard-steps/config-step.tsx
3199
- import { Loader2 as Loader26 } from "lucide-react";
3268
+ import { Loader2 as Loader27 } from "lucide-react";
3200
3269
  import {
3201
3270
  Label as Label5,
3202
3271
  Select,
@@ -3224,7 +3293,7 @@ function ConfigStep({
3224
3293
  ] }),
3225
3294
  isLoading ? /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-3 py-8", children: [
3226
3295
  /* @__PURE__ */ jsx15(
3227
- Loader26,
3296
+ Loader27,
3228
3297
  {
3229
3298
  "aria-hidden": "true",
3230
3299
  className: "h-6 w-6 animate-spin text-muted-foreground"
@@ -3385,8 +3454,8 @@ function IntegrationWizard({
3385
3454
  const currentIndex = STEPS.indexOf(currentStep);
3386
3455
  const [oauthStatus, setOauthStatus] = useState9("idle");
3387
3456
  const [oauthResult, setOauthResult] = useState9(null);
3388
- const popupRef = useRef3(null);
3389
- const popupPollRef = useRef3(null);
3457
+ const popupRef = useRef2(null);
3458
+ const popupPollRef = useRef2(null);
3390
3459
  const [apiKey, setApiKey] = useState9("");
3391
3460
  const [configOptions, setConfigOptions] = useState9([]);
3392
3461
  const [configLoading, setConfigLoading] = useState9(false);
@@ -3470,10 +3539,13 @@ function IntegrationWizard({
3470
3539
  const { language = "pt-br", idWl = 1, accountId, token } = config;
3471
3540
  setOauthStatus("waiting");
3472
3541
  try {
3473
- const response = await fetch(
3474
- `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${accountId}/oauth/authorize/${integration.slug}`,
3475
- { headers: { Authorization: `Bearer ${token}` } }
3476
- );
3542
+ let authorizeUrl = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${accountId}/oauth/authorize/${integration.slug}`;
3543
+ if (existingCredentialId) {
3544
+ authorizeUrl += `?credential_id=${existingCredentialId}`;
3545
+ }
3546
+ const response = await fetch(authorizeUrl, {
3547
+ headers: { Authorization: `Bearer ${token}` }
3548
+ });
3477
3549
  const result = await response.json();
3478
3550
  if (result.status !== 1 || !result.data?.auth_url) {
3479
3551
  setOauthStatus("error");
@@ -3647,7 +3719,7 @@ function IntegrationWizard({
3647
3719
  className: "gap-1",
3648
3720
  children: [
3649
3721
  isSubmitting ? /* @__PURE__ */ jsx17(
3650
- Loader27,
3722
+ Loader28,
3651
3723
  {
3652
3724
  "aria-hidden": "true",
3653
3725
  className: "h-4 w-4 animate-spin"
@@ -3726,7 +3798,7 @@ function StepIndicator({
3726
3798
  }
3727
3799
 
3728
3800
  // src/components/capabilities/advanced-tab.tsx
3729
- import { useState as useState13 } from "react";
3801
+ import { useState as useState12 } from "react";
3730
3802
 
3731
3803
  // src/components/tools/tools-table.tsx
3732
3804
  import { useMemo as useMemo6, useState as useState10 } from "react";
@@ -3918,590 +3990,77 @@ function ToolsTable({ onEdit, config }) {
3918
3990
  ] });
3919
3991
  }
3920
3992
 
3921
- // src/components/tools/tool-credentials-form.tsx
3922
- import { useMemo as useMemo7, useState as useState11 } from "react";
3923
- import { DataTable as DataTable3 } from "@greatapps/greatauth-ui";
3993
+ // src/components/tools/tool-form-dialog.tsx
3994
+ import { useState as useState11 } from "react";
3924
3995
  import {
3925
- Input as Input8,
3926
- Button as Button12,
3927
- Badge as Badge8,
3928
- Tooltip as Tooltip4,
3929
- TooltipTrigger as TooltipTrigger4,
3930
- TooltipContent as TooltipContent4,
3931
3996
  Dialog as Dialog5,
3932
3997
  DialogContent as DialogContent5,
3933
3998
  DialogHeader as DialogHeader5,
3934
3999
  DialogTitle as DialogTitle5,
3935
4000
  DialogFooter as DialogFooter5,
3936
- AlertDialog as AlertDialog4,
3937
- AlertDialogAction as AlertDialogAction4,
3938
- AlertDialogCancel as AlertDialogCancel4,
3939
- AlertDialogContent as AlertDialogContent4,
3940
- AlertDialogDescription as AlertDialogDescription4,
3941
- AlertDialogFooter as AlertDialogFooter4,
3942
- AlertDialogHeader as AlertDialogHeader4,
3943
- AlertDialogTitle as AlertDialogTitle4,
4001
+ Button as Button12,
4002
+ Input as Input8,
4003
+ Textarea as Textarea2,
4004
+ Label as Label7,
3944
4005
  Select as Select2,
3945
4006
  SelectContent as SelectContent2,
3946
4007
  SelectItem as SelectItem2,
3947
4008
  SelectTrigger as SelectTrigger2,
3948
4009
  SelectValue as SelectValue2
3949
4010
  } from "@greatapps/greatauth-ui/ui";
3950
- import { Trash2 as Trash24, Pencil as Pencil4, Link, Search as Search3 } from "lucide-react";
3951
- import { format as format3 } from "date-fns";
3952
- import { ptBR as ptBR3 } from "date-fns/locale";
4011
+ import { Loader2 as Loader29 } from "lucide-react";
3953
4012
  import { toast as toast9 } from "sonner";
3954
4013
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
3955
- function formatDate2(dateStr) {
3956
- if (!dateStr) return "Sem expira\xE7\xE3o";
3957
- 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
+ };
3958
4031
  }
3959
- function useColumns3(tools, onEdit, onConnect, onRemove) {
3960
- function getToolName(idTool) {
3961
- if (!idTool) return "\u2014";
3962
- const tool = tools.find((t) => t.id === idTool);
3963
- 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;
3964
4037
  }
3965
- function getToolType(idTool) {
3966
- if (!idTool) return null;
3967
- const tool = tools.find((t) => t.id === idTool);
3968
- 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;
3969
4049
  }
3970
- return [
3971
- {
3972
- accessorKey: "label",
3973
- header: "Label",
3974
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "font-medium", children: row.original.label || "\u2014" })
3975
- },
3976
- {
3977
- accessorKey: "id_tool",
3978
- header: "Ferramenta",
3979
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "text-sm", children: getToolName(row.original.id_tool) })
3980
- },
3981
- {
3982
- accessorKey: "status",
3983
- header: "Status",
3984
- cell: ({ row }) => /* @__PURE__ */ jsx19(
3985
- Badge8,
3986
- {
3987
- variant: row.original.status === "active" ? "default" : "destructive",
3988
- children: row.original.status === "active" ? "Ativo" : "Expirado"
3989
- }
3990
- )
3991
- },
3992
- {
3993
- accessorKey: "expires_at",
3994
- header: "Expira em",
3995
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.expires_at) })
3996
- },
3997
- {
3998
- accessorKey: "datetime_add",
3999
- header: "Criado em",
4000
- cell: ({ row }) => /* @__PURE__ */ jsx19("span", { className: "text-muted-foreground text-sm", children: formatDate2(row.original.datetime_add) })
4001
- },
4002
- {
4003
- id: "actions",
4004
- header: "A\xE7\xF5es",
4005
- size: 100,
4006
- enableSorting: false,
4007
- cell: ({ row }) => /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1", children: [
4008
- getToolType(row.original.id_tool) === "oauth2" && /* @__PURE__ */ jsxs17(Tooltip4, { children: [
4009
- /* @__PURE__ */ jsx19(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx19(
4010
- Button12,
4011
- {
4012
- variant: "ghost",
4013
- size: "icon",
4014
- className: "h-8 w-8",
4015
- "aria-label": "Vincular",
4016
- disabled: true,
4017
- children: /* @__PURE__ */ jsx19(Link, { className: "h-4 w-4" })
4018
- }
4019
- ) }),
4020
- /* @__PURE__ */ jsx19(TooltipContent4, { children: "Em breve" })
4021
- ] }),
4022
- /* @__PURE__ */ jsxs17(Tooltip4, { children: [
4023
- /* @__PURE__ */ jsx19(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx19(
4024
- Button12,
4025
- {
4026
- variant: "ghost",
4027
- size: "icon",
4028
- className: "h-8 w-8",
4029
- "aria-label": "Editar",
4030
- onClick: () => onEdit(row.original),
4031
- children: /* @__PURE__ */ jsx19(Pencil4, { className: "h-4 w-4" })
4032
- }
4033
- ) }),
4034
- /* @__PURE__ */ jsx19(TooltipContent4, { children: "Editar" })
4035
- ] }),
4036
- /* @__PURE__ */ jsxs17(Tooltip4, { children: [
4037
- /* @__PURE__ */ jsx19(TooltipTrigger4, { asChild: true, children: /* @__PURE__ */ jsx19(
4038
- Button12,
4039
- {
4040
- variant: "ghost",
4041
- size: "icon",
4042
- className: "h-8 w-8 text-destructive hover:text-destructive",
4043
- "aria-label": "Excluir",
4044
- onClick: () => onRemove(row.original),
4045
- children: /* @__PURE__ */ jsx19(Trash24, { className: "h-4 w-4" })
4046
- }
4047
- ) }),
4048
- /* @__PURE__ */ jsx19(TooltipContent4, { children: "Remover" })
4049
- ] })
4050
- ] })
4051
- }
4052
- ];
4053
4050
  }
4054
- function ToolCredentialsForm({
4055
- credentials,
4056
- isLoading,
4057
- config,
4058
- gagentsApiUrl,
4059
- createOpen: externalCreateOpen,
4060
- onCreateOpenChange
4051
+ function ToolFormDialog({
4052
+ open,
4053
+ onOpenChange,
4054
+ tool,
4055
+ config
4061
4056
  }) {
4062
- const createMutation = useCreateToolCredential(config);
4063
- const updateMutation = useUpdateToolCredential(config);
4064
- const deleteMutation = useDeleteToolCredential(config);
4065
- const { data: toolsData } = useTools(config);
4066
- const tools = (toolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
4067
- const [search, setSearch] = useState11("");
4068
- const [internalCreateOpen, setInternalCreateOpen] = useState11(false);
4069
- const showCreateDialog = externalCreateOpen ?? internalCreateOpen;
4070
- const setShowCreateDialog = onCreateOpenChange ?? setInternalCreateOpen;
4071
- const [createForm, setCreateForm] = useState11({
4072
- id_tool: "",
4073
- label: "",
4074
- credentials_encrypted: "",
4075
- expires_at: ""
4076
- });
4077
- const [editTarget, setEditTarget] = useState11(null);
4078
- const [editForm, setEditForm] = useState11({
4079
- id_tool: "",
4080
- label: "",
4081
- credentials_encrypted: "",
4082
- expires_at: "",
4083
- status: ""
4084
- });
4085
- const [removeTarget, setRemoveTarget] = useState11(null);
4086
- const internalToolIds = useMemo7(() => {
4087
- const allRawTools = toolsData?.data || [];
4088
- return new Set(
4089
- allRawTools.filter((t) => t.slug?.startsWith("gclinic_")).map((t) => t.id)
4090
- );
4091
- }, [toolsData]);
4092
- const filteredCredentials = useMemo7(() => {
4093
- const visible = credentials.filter(
4094
- (cred) => !cred.id_tool || !internalToolIds.has(cred.id_tool)
4095
- );
4096
- if (!search) return visible;
4097
- const term = search.toLowerCase();
4098
- return visible.filter((cred) => {
4099
- const toolName = tools.find((t) => t.id === cred.id_tool)?.name || "";
4100
- return (cred.label || "").toLowerCase().includes(term) || toolName.toLowerCase().includes(term);
4101
- });
4102
- }, [credentials, search, tools, internalToolIds]);
4103
- const columns = useColumns3(
4104
- tools,
4105
- (cred) => startEdit(cred),
4106
- (cred) => handleConnect(cred),
4107
- (cred) => setRemoveTarget(cred)
4108
- );
4109
- async function handleCreate() {
4110
- const idTool = parseInt(createForm.id_tool, 10);
4111
- if (!idTool || !createForm.label.trim() || !createForm.credentials_encrypted.trim()) return;
4112
- try {
4113
- const result = await createMutation.mutateAsync({
4114
- id_tool: idTool,
4115
- label: createForm.label.trim(),
4116
- credentials_encrypted: createForm.credentials_encrypted.trim(),
4117
- ...createForm.expires_at ? { expires_at: createForm.expires_at } : {}
4118
- });
4119
- if (result.status === 1) {
4120
- toast9.success("Credencial criada");
4121
- setShowCreateDialog(false);
4122
- setCreateForm({ id_tool: "", label: "", credentials_encrypted: "", expires_at: "" });
4123
- } else {
4124
- toast9.error(result.message || "Erro ao criar credencial");
4125
- }
4126
- } catch {
4127
- toast9.error("Erro ao criar credencial");
4128
- }
4129
- }
4130
- function startEdit(cred) {
4131
- setEditTarget(cred);
4132
- setEditForm({
4133
- id_tool: cred.id_tool ? String(cred.id_tool) : "",
4134
- label: cred.label || "",
4135
- credentials_encrypted: "",
4136
- expires_at: cred.expires_at || "",
4137
- status: cred.status
4138
- });
4139
- }
4140
- async function handleSaveEdit() {
4141
- if (!editTarget) return;
4142
- const body = {};
4143
- const newIdTool = editForm.id_tool ? parseInt(editForm.id_tool, 10) : null;
4144
- if (newIdTool && newIdTool !== editTarget.id_tool) {
4145
- body.id_tool = newIdTool;
4146
- }
4147
- if (editForm.label.trim() && editForm.label.trim() !== (editTarget.label || "")) {
4148
- body.label = editForm.label.trim();
4149
- }
4150
- if (editForm.credentials_encrypted.trim()) {
4151
- body.credentials_encrypted = editForm.credentials_encrypted.trim();
4152
- }
4153
- if (editForm.expires_at !== (editTarget.expires_at || "")) {
4154
- body.expires_at = editForm.expires_at || null;
4155
- }
4156
- if (editForm.status && editForm.status !== editTarget.status) {
4157
- body.status = editForm.status;
4158
- }
4159
- if (Object.keys(body).length === 0) {
4160
- setEditTarget(null);
4161
- return;
4162
- }
4163
- try {
4164
- const result = await updateMutation.mutateAsync({
4165
- id: editTarget.id,
4166
- body
4167
- });
4168
- if (result.status === 1) {
4169
- toast9.success("Credencial atualizada");
4170
- setEditTarget(null);
4171
- } else {
4172
- toast9.error(result.message || "Erro ao atualizar credencial");
4173
- }
4174
- } catch {
4175
- toast9.error("Erro ao atualizar credencial");
4176
- }
4177
- }
4178
- async function handleRemove() {
4179
- if (!removeTarget) return;
4180
- try {
4181
- const result = await deleteMutation.mutateAsync(removeTarget.id);
4182
- if (result.status === 1) {
4183
- toast9.success("Credencial removida");
4184
- } else {
4185
- toast9.error(result.message || "Erro ao remover credencial");
4186
- }
4187
- } catch {
4188
- toast9.error("Erro ao remover credencial");
4189
- } finally {
4190
- setRemoveTarget(null);
4191
- }
4192
- }
4193
- function handleConnect(cred) {
4194
- if (!config.accountId || !config.token) return;
4195
- const language = config.language ?? "pt-br";
4196
- const idWl = config.idWl ?? 1;
4197
- const url = `${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${config.accountId}/oauth/connect?id_tool=${cred.id_tool}`;
4198
- window.open(url, "_blank");
4199
- }
4200
- return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
4201
- /* @__PURE__ */ jsx19("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs17("div", { className: "relative flex-1 max-w-md", children: [
4202
- /* @__PURE__ */ jsx19(Search3, { "aria-hidden": "true", className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
4203
- /* @__PURE__ */ jsx19(
4204
- Input8,
4205
- {
4206
- placeholder: "Buscar credenciais\\u2026",
4207
- "aria-label": "Buscar credenciais",
4208
- name: "search",
4209
- autoComplete: "off",
4210
- value: search,
4211
- onChange: (e) => setSearch(e.target.value),
4212
- className: "pl-9"
4213
- }
4214
- )
4215
- ] }) }),
4216
- /* @__PURE__ */ jsx19(
4217
- DataTable3,
4218
- {
4219
- columns,
4220
- data: filteredCredentials,
4221
- isLoading,
4222
- emptyMessage: "Nenhuma credencial encontrada"
4223
- }
4224
- ),
4225
- /* @__PURE__ */ jsx19(Dialog5, { open: showCreateDialog, onOpenChange: setShowCreateDialog, children: /* @__PURE__ */ jsxs17(DialogContent5, { children: [
4226
- /* @__PURE__ */ jsx19(DialogHeader5, { children: /* @__PURE__ */ jsx19(DialogTitle5, { children: "Nova Credencial" }) }),
4227
- /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
4228
- /* @__PURE__ */ jsxs17("div", { children: [
4229
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
4230
- /* @__PURE__ */ jsxs17(
4231
- Select2,
4232
- {
4233
- value: createForm.id_tool,
4234
- onValueChange: (val) => setCreateForm((f) => ({ ...f, id_tool: val })),
4235
- children: [
4236
- /* @__PURE__ */ jsx19(SelectTrigger2, { id: "cred-tool", children: /* @__PURE__ */ jsx19(SelectValue2, { placeholder: "Selecione a ferramenta" }) }),
4237
- /* @__PURE__ */ jsx19(SelectContent2, { children: tools.map((tool) => /* @__PURE__ */ jsx19(SelectItem2, { value: String(tool.id), children: tool.name }, tool.id)) })
4238
- ]
4239
- }
4240
- )
4241
- ] }),
4242
- /* @__PURE__ */ jsxs17("div", { children: [
4243
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-label", className: "mb-1 block text-sm font-medium", children: "Label *" }),
4244
- /* @__PURE__ */ jsx19(
4245
- Input8,
4246
- {
4247
- id: "cred-label",
4248
- name: "label",
4249
- value: createForm.label,
4250
- onChange: (e) => setCreateForm((f) => ({ ...f, label: e.target.value })),
4251
- placeholder: "Ex: Google Calendar - Cl\xEDnica S\xE3o Paulo"
4252
- }
4253
- )
4254
- ] }),
4255
- /* @__PURE__ */ jsxs17("div", { children: [
4256
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-credential", className: "mb-1 block text-sm font-medium", children: "Credencial *" }),
4257
- /* @__PURE__ */ jsx19(
4258
- Input8,
4259
- {
4260
- id: "cred-credential",
4261
- name: "credential",
4262
- autoComplete: "off",
4263
- type: "password",
4264
- value: createForm.credentials_encrypted,
4265
- onChange: (e) => setCreateForm((f) => ({
4266
- ...f,
4267
- credentials_encrypted: e.target.value
4268
- })),
4269
- placeholder: "Credencial encriptada"
4270
- }
4271
- )
4272
- ] }),
4273
- /* @__PURE__ */ jsxs17("div", { children: [
4274
- /* @__PURE__ */ jsx19("label", { htmlFor: "cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o (opcional)" }),
4275
- /* @__PURE__ */ jsx19(
4276
- Input8,
4277
- {
4278
- id: "cred-expires",
4279
- name: "expires",
4280
- type: "date",
4281
- value: createForm.expires_at,
4282
- onChange: (e) => setCreateForm((f) => ({ ...f, expires_at: e.target.value }))
4283
- }
4284
- )
4285
- ] })
4286
- ] }),
4287
- /* @__PURE__ */ jsxs17(DialogFooter5, { children: [
4288
- /* @__PURE__ */ jsx19(
4289
- Button12,
4290
- {
4291
- variant: "outline",
4292
- onClick: () => setShowCreateDialog(false),
4293
- children: "Cancelar"
4294
- }
4295
- ),
4296
- /* @__PURE__ */ jsx19(
4297
- Button12,
4298
- {
4299
- onClick: handleCreate,
4300
- disabled: !createForm.id_tool || !createForm.label.trim() || !createForm.credentials_encrypted.trim() || createMutation.isPending,
4301
- children: "Criar"
4302
- }
4303
- )
4304
- ] })
4305
- ] }) }),
4306
- /* @__PURE__ */ jsx19(
4307
- Dialog5,
4308
- {
4309
- open: !!editTarget,
4310
- onOpenChange: (open) => !open && setEditTarget(null),
4311
- children: /* @__PURE__ */ jsxs17(DialogContent5, { children: [
4312
- /* @__PURE__ */ jsx19(DialogHeader5, { children: /* @__PURE__ */ jsx19(DialogTitle5, { children: "Editar Credencial" }) }),
4313
- /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
4314
- /* @__PURE__ */ jsxs17("div", { children: [
4315
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-tool", className: "mb-1 block text-sm font-medium", children: "Ferramenta *" }),
4316
- /* @__PURE__ */ jsxs17(
4317
- Select2,
4318
- {
4319
- value: editForm.id_tool,
4320
- onValueChange: (val) => setEditForm((f) => ({ ...f, id_tool: val })),
4321
- children: [
4322
- /* @__PURE__ */ jsx19(SelectTrigger2, { id: "edit-cred-tool", children: /* @__PURE__ */ jsx19(SelectValue2, { placeholder: "Selecione a ferramenta" }) }),
4323
- /* @__PURE__ */ jsx19(SelectContent2, { children: tools.map((tool) => /* @__PURE__ */ jsx19(SelectItem2, { value: String(tool.id), children: tool.name }, tool.id)) })
4324
- ]
4325
- }
4326
- )
4327
- ] }),
4328
- /* @__PURE__ */ jsxs17("div", { children: [
4329
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-label", className: "mb-1 block text-sm font-medium", children: "Label" }),
4330
- /* @__PURE__ */ jsx19(
4331
- Input8,
4332
- {
4333
- id: "edit-cred-label",
4334
- name: "label",
4335
- value: editForm.label,
4336
- onChange: (e) => setEditForm((f) => ({ ...f, label: e.target.value })),
4337
- placeholder: "Label da credencial"
4338
- }
4339
- )
4340
- ] }),
4341
- /* @__PURE__ */ jsxs17("div", { children: [
4342
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-credential", className: "mb-1 block text-sm font-medium", children: "Nova Credencial (vazio = manter atual)" }),
4343
- /* @__PURE__ */ jsx19(
4344
- Input8,
4345
- {
4346
- id: "edit-cred-credential",
4347
- name: "credential",
4348
- autoComplete: "off",
4349
- type: "password",
4350
- value: editForm.credentials_encrypted,
4351
- onChange: (e) => setEditForm((f) => ({
4352
- ...f,
4353
- credentials_encrypted: e.target.value
4354
- })),
4355
- placeholder: "Nova credencial"
4356
- }
4357
- )
4358
- ] }),
4359
- /* @__PURE__ */ jsxs17("div", { children: [
4360
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-expires", className: "mb-1 block text-sm font-medium", children: "Data de Expira\xE7\xE3o" }),
4361
- /* @__PURE__ */ jsx19(
4362
- Input8,
4363
- {
4364
- id: "edit-cred-expires",
4365
- name: "expires",
4366
- type: "date",
4367
- value: editForm.expires_at,
4368
- onChange: (e) => setEditForm((f) => ({ ...f, expires_at: e.target.value }))
4369
- }
4370
- )
4371
- ] }),
4372
- /* @__PURE__ */ jsxs17("div", { children: [
4373
- /* @__PURE__ */ jsx19("label", { htmlFor: "edit-cred-status", className: "mb-1 block text-sm font-medium", children: "Status" }),
4374
- /* @__PURE__ */ jsxs17(
4375
- Select2,
4376
- {
4377
- value: editForm.status || void 0,
4378
- onValueChange: (val) => setEditForm((f) => ({
4379
- ...f,
4380
- status: val
4381
- })),
4382
- children: [
4383
- /* @__PURE__ */ jsx19(SelectTrigger2, { id: "edit-cred-status", children: /* @__PURE__ */ jsx19(SelectValue2, {}) }),
4384
- /* @__PURE__ */ jsxs17(SelectContent2, { children: [
4385
- /* @__PURE__ */ jsx19(SelectItem2, { value: "active", children: "Ativo" }),
4386
- /* @__PURE__ */ jsx19(SelectItem2, { value: "expired", children: "Expirado" })
4387
- ] })
4388
- ]
4389
- }
4390
- )
4391
- ] })
4392
- ] }),
4393
- /* @__PURE__ */ jsxs17(DialogFooter5, { children: [
4394
- /* @__PURE__ */ jsx19(Button12, { variant: "outline", onClick: () => setEditTarget(null), children: "Cancelar" }),
4395
- /* @__PURE__ */ jsx19(
4396
- Button12,
4397
- {
4398
- onClick: handleSaveEdit,
4399
- disabled: updateMutation.isPending,
4400
- children: "Salvar"
4401
- }
4402
- )
4403
- ] })
4404
- ] })
4405
- }
4406
- ),
4407
- /* @__PURE__ */ jsx19(
4408
- AlertDialog4,
4409
- {
4410
- open: !!removeTarget,
4411
- onOpenChange: (open) => !open && setRemoveTarget(null),
4412
- children: /* @__PURE__ */ jsxs17(AlertDialogContent4, { children: [
4413
- /* @__PURE__ */ jsxs17(AlertDialogHeader4, { children: [
4414
- /* @__PURE__ */ jsx19(AlertDialogTitle4, { children: "Remover credencial?" }),
4415
- /* @__PURE__ */ jsx19(AlertDialogDescription4, { children: "A credencial ser\xE1 removida permanentemente." })
4416
- ] }),
4417
- /* @__PURE__ */ jsxs17(AlertDialogFooter4, { children: [
4418
- /* @__PURE__ */ jsx19(AlertDialogCancel4, { children: "Cancelar" }),
4419
- /* @__PURE__ */ jsx19(
4420
- AlertDialogAction4,
4421
- {
4422
- onClick: handleRemove,
4423
- disabled: deleteMutation.isPending,
4424
- children: "Remover"
4425
- }
4426
- )
4427
- ] })
4428
- ] })
4429
- }
4430
- )
4431
- ] });
4432
- }
4433
-
4434
- // src/components/tools/tool-form-dialog.tsx
4435
- import { useState as useState12 } from "react";
4436
- import {
4437
- Dialog as Dialog6,
4438
- DialogContent as DialogContent6,
4439
- DialogHeader as DialogHeader6,
4440
- DialogTitle as DialogTitle6,
4441
- DialogFooter as DialogFooter6,
4442
- Button as Button13,
4443
- Input as Input9,
4444
- Textarea as Textarea2,
4445
- Label as Label7,
4446
- Select as Select3,
4447
- SelectContent as SelectContent3,
4448
- SelectItem as SelectItem3,
4449
- SelectTrigger as SelectTrigger3,
4450
- SelectValue as SelectValue3
4451
- } from "@greatapps/greatauth-ui/ui";
4452
- import { Loader2 as Loader28 } from "lucide-react";
4453
- import { toast as toast10 } from "sonner";
4454
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4455
- var TOOL_AUTH_TYPES = [
4456
- { value: "none", label: "Nenhuma" },
4457
- { value: "api_key", label: "API Key" },
4458
- { value: "oauth2", label: "OAuth 2.0" }
4459
- ];
4460
- function toolToFormState(tool) {
4461
- return {
4462
- name: tool?.name || "",
4463
- slug: tool?.slug || "",
4464
- type: tool?.type || "none",
4465
- description: tool?.description || "",
4466
- functionDefinitions: tool?.function_definitions ? formatJson(tool.function_definitions) : "",
4467
- nameError: false,
4468
- slugError: false,
4469
- typeError: false,
4470
- jsonError: false
4471
- };
4472
- }
4473
- function formatJson(str) {
4474
- try {
4475
- return JSON.stringify(JSON.parse(str), null, 2);
4476
- } catch {
4477
- return str;
4478
- }
4479
- }
4480
- function slugify2(name) {
4481
- return name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4482
- }
4483
- function isValidJson(str) {
4484
- if (!str.trim()) return true;
4485
- try {
4486
- JSON.parse(str);
4487
- return true;
4488
- } catch {
4489
- return false;
4490
- }
4491
- }
4492
- function ToolFormDialog({
4493
- open,
4494
- onOpenChange,
4495
- tool,
4496
- config
4497
- }) {
4498
- const isEditing = !!tool;
4499
- const createTool = useCreateTool(config);
4500
- const updateTool = useUpdateTool(config);
4501
- const [form, setForm] = useState12(() => toolToFormState(tool));
4502
- const [slugManuallyEdited, setSlugManuallyEdited] = useState12(false);
4503
- const [lastResetKey, setLastResetKey] = useState12(
4504
- () => `${tool?.id}-${open}`
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}`
4505
4064
  );
4506
4065
  const resetKey = `${tool?.id}-${open}`;
4507
4066
  if (resetKey !== lastResetKey) {
@@ -4547,27 +4106,27 @@ function ToolFormDialog({
4547
4106
  try {
4548
4107
  if (isEditing) {
4549
4108
  await updateTool.mutateAsync({ id: tool.id, body });
4550
- toast10.success("Ferramenta atualizada");
4109
+ toast9.success("Ferramenta atualizada");
4551
4110
  } else {
4552
4111
  await createTool.mutateAsync(
4553
4112
  body
4554
4113
  );
4555
- toast10.success("Ferramenta criada");
4114
+ toast9.success("Ferramenta criada");
4556
4115
  }
4557
4116
  onOpenChange(false);
4558
4117
  } catch (err) {
4559
- toast10.error(
4118
+ toast9.error(
4560
4119
  err instanceof Error ? err.message : isEditing ? "Erro ao atualizar ferramenta" : "Erro ao criar ferramenta"
4561
4120
  );
4562
4121
  }
4563
4122
  }
4564
- return /* @__PURE__ */ jsx20(Dialog6, { open, onOpenChange, children: /* @__PURE__ */ jsxs18(DialogContent6, { className: "sm:max-w-lg", children: [
4565
- /* @__PURE__ */ jsx20(DialogHeader6, { children: /* @__PURE__ */ jsx20(DialogTitle6, { children: isEditing ? "Editar Ferramenta" : "Nova Ferramenta" }) }),
4566
- /* @__PURE__ */ jsxs18("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
4567
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4568
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-name", children: "Nome *" }),
4569
- /* @__PURE__ */ jsx20(
4570
- Input9,
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,
4571
4130
  {
4572
4131
  id: "tool-name",
4573
4132
  name: "name",
@@ -4585,12 +4144,12 @@ function ToolFormDialog({
4585
4144
  disabled: isPending
4586
4145
  }
4587
4146
  ),
4588
- form.nameError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
4147
+ form.nameError && /* @__PURE__ */ jsx19("p", { className: "text-sm text-destructive", children: "Nome \xE9 obrigat\xF3rio" })
4589
4148
  ] }),
4590
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4591
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-slug", children: "Slug (identificador \xFAnico) *" }),
4592
- /* @__PURE__ */ jsx20(
4593
- Input9,
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,
4594
4153
  {
4595
4154
  id: "tool-slug",
4596
4155
  name: "slug",
@@ -4607,13 +4166,13 @@ function ToolFormDialog({
4607
4166
  disabled: isPending
4608
4167
  }
4609
4168
  ),
4610
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Gerado automaticamente a partir do nome. Usado internamente para identificar a ferramenta." }),
4611
- form.slugError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "Slug \xE9 obrigat\xF3rio" })
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" })
4612
4171
  ] }),
4613
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4614
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-type", children: "Tipo de Autentica\xE7\xE3o *" }),
4615
- /* @__PURE__ */ jsxs18(
4616
- Select3,
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,
4617
4176
  {
4618
4177
  value: form.type,
4619
4178
  onValueChange: (value) => {
@@ -4625,17 +4184,17 @@ function ToolFormDialog({
4625
4184
  },
4626
4185
  disabled: isPending,
4627
4186
  children: [
4628
- /* @__PURE__ */ jsx20(SelectTrigger3, { id: "tool-type", children: /* @__PURE__ */ jsx20(SelectValue3, { placeholder: "Selecione o tipo" }) }),
4629
- /* @__PURE__ */ jsx20(SelectContent3, { children: TOOL_AUTH_TYPES.map((t) => /* @__PURE__ */ jsx20(SelectItem3, { value: t.value, children: t.label }, t.value)) })
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)) })
4630
4189
  ]
4631
4190
  }
4632
4191
  ),
4633
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Define se a ferramenta requer credenciais para funcionar." }),
4634
- form.typeError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "Tipo \xE9 obrigat\xF3rio" })
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" })
4635
4194
  ] }),
4636
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4637
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-description", children: "Descri\xE7\xE3o" }),
4638
- /* @__PURE__ */ jsx20(
4195
+ /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
4196
+ /* @__PURE__ */ jsx19(Label7, { htmlFor: "tool-description", children: "Descri\xE7\xE3o" }),
4197
+ /* @__PURE__ */ jsx19(
4639
4198
  Textarea2,
4640
4199
  {
4641
4200
  id: "tool-description",
@@ -4648,9 +4207,9 @@ function ToolFormDialog({
4648
4207
  }
4649
4208
  )
4650
4209
  ] }),
4651
- /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4652
- /* @__PURE__ */ jsx20(Label7, { htmlFor: "tool-function-defs", children: "Defini\xE7\xF5es de Fun\xE7\xE3o (JSON)" }),
4653
- /* @__PURE__ */ jsx20(
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(
4654
4213
  Textarea2,
4655
4214
  {
4656
4215
  id: "tool-function-defs",
@@ -4682,12 +4241,12 @@ function ToolFormDialog({
4682
4241
  disabled: isPending
4683
4242
  }
4684
4243
  ),
4685
- /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Array de defini\xE7\xF5es no formato OpenAI Function Calling." }),
4686
- form.jsonError && /* @__PURE__ */ jsx20("p", { className: "text-sm text-destructive", children: "JSON inv\xE1lido" })
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" })
4687
4246
  ] }),
4688
- /* @__PURE__ */ jsxs18(DialogFooter6, { children: [
4689
- /* @__PURE__ */ jsx20(
4690
- Button13,
4247
+ /* @__PURE__ */ jsxs17(DialogFooter5, { children: [
4248
+ /* @__PURE__ */ jsx19(
4249
+ Button12,
4691
4250
  {
4692
4251
  type: "button",
4693
4252
  variant: "outline",
@@ -4696,8 +4255,8 @@ function ToolFormDialog({
4696
4255
  children: "Cancelar"
4697
4256
  }
4698
4257
  ),
4699
- /* @__PURE__ */ jsxs18(Button13, { type: "submit", disabled: isPending, children: [
4700
- isPending ? /* @__PURE__ */ jsx20(Loader28, { "aria-hidden": "true", className: "mr-2 h-4 w-4 animate-spin" }) : null,
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,
4701
4260
  isEditing ? "Salvar" : "Criar"
4702
4261
  ] })
4703
4262
  ] })
@@ -4707,12 +4266,10 @@ function ToolFormDialog({
4707
4266
 
4708
4267
  // src/components/capabilities/advanced-tab.tsx
4709
4268
  import { Info as Info2 } from "lucide-react";
4710
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
4269
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
4711
4270
  function AdvancedTab({ config, agentId, gagentsApiUrl }) {
4712
- const { data: credentialsData, isLoading: isLoadingCredentials } = useToolCredentials(config);
4713
- const credentials = credentialsData?.data ?? [];
4714
- const [editingTool, setEditingTool] = useState13(null);
4715
- const [showToolForm, setShowToolForm] = useState13(false);
4271
+ const [editingTool, setEditingTool] = useState12(null);
4272
+ const [showToolForm, setShowToolForm] = useState12(false);
4716
4273
  function handleEditTool(tool) {
4717
4274
  setEditingTool(tool);
4718
4275
  setShowToolForm(true);
@@ -4721,34 +4278,22 @@ function AdvancedTab({ config, agentId, gagentsApiUrl }) {
4721
4278
  setShowToolForm(open);
4722
4279
  if (!open) setEditingTool(null);
4723
4280
  }
4724
- return /* @__PURE__ */ jsxs19("div", { className: "space-y-8", children: [
4725
- /* @__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: [
4726
- /* @__PURE__ */ jsx21(Info2, { className: "mt-0.5 h-4 w-4 shrink-0 text-blue-600 dark:text-blue-400" }),
4727
- /* @__PURE__ */ jsxs19("p", { className: "text-sm text-blue-800 dark:text-blue-300", children: [
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: [
4728
4285
  "Use as abas ",
4729
- /* @__PURE__ */ jsx21("strong", { children: "Capacidades" }),
4286
+ /* @__PURE__ */ jsx20("strong", { children: "Capacidades" }),
4730
4287
  " e ",
4731
- /* @__PURE__ */ jsx21("strong", { children: "Integra\xE7\xF5es" }),
4732
- " para configura\xE7\xE3o simplificada. Esta aba oferece controlo manual avan\xE7ado sobre ferramentas e credenciais."
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."
4733
4290
  ] })
4734
4291
  ] }),
4735
- /* @__PURE__ */ jsxs19("section", { className: "space-y-3", children: [
4736
- /* @__PURE__ */ jsx21("h3", { className: "text-sm font-medium", children: "Ferramentas" }),
4737
- /* @__PURE__ */ jsx21(ToolsTable, { onEdit: handleEditTool, config })
4738
- ] }),
4739
- /* @__PURE__ */ jsxs19("section", { className: "space-y-3", children: [
4740
- /* @__PURE__ */ jsx21("h3", { className: "text-sm font-medium", children: "Credenciais" }),
4741
- /* @__PURE__ */ jsx21(
4742
- ToolCredentialsForm,
4743
- {
4744
- credentials,
4745
- isLoading: isLoadingCredentials,
4746
- config,
4747
- gagentsApiUrl
4748
- }
4749
- )
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 })
4750
4295
  ] }),
4751
- /* @__PURE__ */ jsx21(
4296
+ /* @__PURE__ */ jsx20(
4752
4297
  ToolFormDialog,
4753
4298
  {
4754
4299
  open: showToolForm,
@@ -4761,7 +4306,7 @@ function AdvancedTab({ config, agentId, gagentsApiUrl }) {
4761
4306
  }
4762
4307
 
4763
4308
  // src/pages/agent-capabilities-page.tsx
4764
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4309
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
4765
4310
  function defaultResolveWizardMeta(card) {
4766
4311
  return {
4767
4312
  capabilities: [
@@ -4779,8 +4324,8 @@ function AgentCapabilitiesPage({
4779
4324
  loadConfigOptions,
4780
4325
  onWizardComplete
4781
4326
  }) {
4782
- const [wizardOpen, setWizardOpen] = useState14(false);
4783
- const [activeCard, setActiveCard] = useState14(null);
4327
+ const [wizardOpen, setWizardOpen] = useState13(false);
4328
+ const [activeCard, setActiveCard] = useState13(null);
4784
4329
  const handleConnect = useCallback6(
4785
4330
  (card) => {
4786
4331
  setActiveCard(card);
@@ -4798,28 +4343,28 @@ function AgentCapabilitiesPage({
4798
4343
  if (!open) setActiveCard(null);
4799
4344
  }, []);
4800
4345
  const wizardMeta = activeCard ? resolveWizardMeta(activeCard) : null;
4801
- return /* @__PURE__ */ jsxs20("div", { className: "space-y-4", children: [
4802
- /* @__PURE__ */ jsxs20("div", { children: [
4803
- /* @__PURE__ */ jsx22("h2", { className: "text-lg font-semibold", children: "Capacidades e Integra\xE7\xF5es" }),
4804
- /* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "Configure o que este agente pode fazer e quais servi\xE7os externos ele utiliza." })
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." })
4805
4350
  ] }),
4806
- /* @__PURE__ */ jsxs20(Tabs, { defaultValue: "capacidades", children: [
4807
- /* @__PURE__ */ jsxs20(TabsList, { children: [
4808
- /* @__PURE__ */ jsxs20(TabsTrigger, { value: "capacidades", className: "flex items-center gap-1.5", children: [
4809
- /* @__PURE__ */ jsx22(Blocks, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
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" }),
4810
4355
  "Capacidades"
4811
4356
  ] }),
4812
- /* @__PURE__ */ jsxs20(TabsTrigger, { value: "integracoes", className: "flex items-center gap-1.5", children: [
4813
- /* @__PURE__ */ jsx22(Plug3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
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" }),
4814
4359
  "Integra\xE7\xF5es"
4815
4360
  ] }),
4816
- /* @__PURE__ */ jsxs20(TabsTrigger, { value: "avancado", className: "flex items-center gap-1.5", children: [
4817
- /* @__PURE__ */ jsx22(Settings3, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
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" }),
4818
4363
  "Avan\xE7ado"
4819
4364
  ] })
4820
4365
  ] }),
4821
- /* @__PURE__ */ jsx22(TabsContent, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx22(CapabilitiesTab, { config, agentId }) }),
4822
- /* @__PURE__ */ jsx22(TabsContent, { value: "integracoes", className: "mt-4", children: /* @__PURE__ */ jsx22(
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(
4823
4368
  IntegrationsTab,
4824
4369
  {
4825
4370
  config,
@@ -4827,7 +4372,7 @@ function AgentCapabilitiesPage({
4827
4372
  onConnect: handleConnect
4828
4373
  }
4829
4374
  ) }),
4830
- /* @__PURE__ */ jsx22(TabsContent, { value: "avancado", className: "mt-4", children: /* @__PURE__ */ jsx22(
4375
+ /* @__PURE__ */ jsx21(TabsContent, { value: "avancado", className: "mt-4", children: /* @__PURE__ */ jsx21(
4831
4376
  AdvancedTab,
4832
4377
  {
4833
4378
  config,
@@ -4836,7 +4381,7 @@ function AgentCapabilitiesPage({
4836
4381
  }
4837
4382
  ) })
4838
4383
  ] }),
4839
- activeCard && wizardMeta && /* @__PURE__ */ jsx22(
4384
+ activeCard && wizardMeta && /* @__PURE__ */ jsx21(
4840
4385
  IntegrationWizard,
4841
4386
  {
4842
4387
  open: wizardOpen,
@@ -4862,7 +4407,7 @@ import {
4862
4407
  TabsContent as TabsContent2
4863
4408
  } from "@greatapps/greatauth-ui/ui";
4864
4409
  import { Target as Target2, FileText as FileText2, MessageCircle as MessageCircle2, Blocks as Blocks2 } from "lucide-react";
4865
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
4410
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4866
4411
  function AgentTabs({
4867
4412
  agent,
4868
4413
  config,
@@ -4873,28 +4418,28 @@ function AgentTabs({
4873
4418
  onWizardComplete
4874
4419
  }) {
4875
4420
  const apiUrl = gagentsApiUrl || config.baseUrl;
4876
- return /* @__PURE__ */ jsxs21(Tabs2, { defaultValue: "prompt", children: [
4877
- /* @__PURE__ */ jsxs21(TabsList2, { children: [
4878
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "prompt", className: "flex items-center gap-1.5", children: [
4879
- /* @__PURE__ */ jsx23(FileText2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
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" }),
4880
4425
  "Prompt"
4881
4426
  ] }),
4882
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "objetivos", className: "flex items-center gap-1.5", children: [
4883
- /* @__PURE__ */ jsx23(Target2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
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" }),
4884
4429
  "Objetivos"
4885
4430
  ] }),
4886
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "capacidades", className: "flex items-center gap-1.5", children: [
4887
- /* @__PURE__ */ jsx23(Blocks2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
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" }),
4888
4433
  "Capacidades"
4889
4434
  ] }),
4890
- /* @__PURE__ */ jsxs21(TabsTrigger2, { value: "conversas", className: "flex items-center gap-1.5", children: [
4891
- /* @__PURE__ */ jsx23(MessageCircle2, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
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" }),
4892
4437
  "Conversas"
4893
4438
  ] })
4894
4439
  ] }),
4895
- /* @__PURE__ */ jsx23(TabsContent2, { value: "prompt", className: "mt-4", children: /* @__PURE__ */ jsx23(AgentPromptEditor, { agent, config }) }),
4896
- /* @__PURE__ */ jsx23(TabsContent2, { value: "objetivos", className: "mt-4", children: /* @__PURE__ */ jsx23(AgentObjectivesList, { agent, config }) }),
4897
- /* @__PURE__ */ jsx23(TabsContent2, { value: "capacidades", className: "mt-4", children: /* @__PURE__ */ jsx23(
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(
4898
4443
  AgentCapabilitiesPage,
4899
4444
  {
4900
4445
  config,
@@ -4905,7 +4450,7 @@ function AgentTabs({
4905
4450
  onWizardComplete
4906
4451
  }
4907
4452
  ) }),
4908
- /* @__PURE__ */ jsx23(TabsContent2, { value: "conversas", className: "mt-4", children: /* @__PURE__ */ jsx23(
4453
+ /* @__PURE__ */ jsx22(TabsContent2, { value: "conversas", className: "mt-4", children: /* @__PURE__ */ jsx22(
4909
4454
  AgentConversationsPanel,
4910
4455
  {
4911
4456
  agent,
@@ -4917,12 +4462,349 @@ function AgentTabs({
4917
4462
  }
4918
4463
 
4919
4464
  // src/components/agents/agent-tools-list.tsx
4920
- import { useState as useState15 } from "react";
4465
+ import { useState as useState14 } from "react";
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,
4484
+ Dialog as Dialog6,
4485
+ DialogContent as DialogContent6,
4486
+ DialogHeader as DialogHeader6,
4487
+ DialogTitle as DialogTitle6,
4488
+ DialogFooter as DialogFooter6,
4489
+ Label as Label8,
4490
+ Select as Select3,
4491
+ SelectContent as SelectContent3,
4492
+ SelectItem as SelectItem3,
4493
+ SelectTrigger as SelectTrigger3,
4494
+ SelectValue as SelectValue3
4495
+ } from "@greatapps/greatauth-ui/ui";
4496
+ import {
4497
+ Trash2 as Trash24,
4498
+ Plus as Plus3,
4499
+ Wrench,
4500
+ Settings2 as Settings22
4501
+ } from "lucide-react";
4502
+ import { toast as toast10 } from "sonner";
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())
4528
+ );
4529
+ function getToolInfo(idTool) {
4530
+ return allTools.find((t) => t.id === idTool);
4531
+ }
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
+ );
4544
+ }
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
+ );
4559
+ }
4560
+ }
4561
+ async function handleRemove() {
4562
+ if (!removeTarget) return;
4563
+ try {
4564
+ await removeMutation.mutateAsync({
4565
+ idAgent: agent.id,
4566
+ id: removeTarget.id
4567
+ });
4568
+ toast10.success("Ferramenta removida");
4569
+ } catch (err) {
4570
+ toast10.error(
4571
+ err instanceof Error ? err.message : "Erro ao remover ferramenta"
4572
+ );
4573
+ } finally {
4574
+ setRemoveTarget(null);
4575
+ }
4576
+ }
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
+ );
4600
+ }
4601
+ }
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" : ""
4613
+ ] }),
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
+ )) })
4646
+ ] })
4647
+ ] })
4648
+ ] }),
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",
4656
+ {
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,
4705
+ {
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
+ ] })
4763
+ ] })
4764
+ }
4765
+ ),
4766
+ /* @__PURE__ */ jsx23(
4767
+ AlertDialog4,
4768
+ {
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
+ ] })
4788
+ }
4789
+ )
4790
+ ] });
4791
+ }
4792
+
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";
4921
4796
  import {
4922
- Switch as Switch5,
4923
- Badge as Badge9,
4797
+ Input as Input10,
4924
4798
  Button as Button14,
4925
- 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,
4926
4808
  AlertDialog as AlertDialog5,
4927
4809
  AlertDialogAction as AlertDialogAction5,
4928
4810
  AlertDialogCancel as AlertDialogCancel5,
@@ -4931,285 +4813,461 @@ import {
4931
4813
  AlertDialogFooter as AlertDialogFooter5,
4932
4814
  AlertDialogHeader as AlertDialogHeader5,
4933
4815
  AlertDialogTitle as AlertDialogTitle5,
4934
- Popover,
4935
- PopoverContent,
4936
- PopoverTrigger,
4937
- Input as Input10,
4938
- Textarea as Textarea3,
4939
- Dialog as Dialog7,
4940
- DialogContent as DialogContent7,
4941
- DialogHeader as DialogHeader7,
4942
- DialogTitle as DialogTitle7,
4943
- DialogFooter as DialogFooter7,
4944
- Label as Label8,
4945
4816
  Select as Select4,
4946
4817
  SelectContent as SelectContent4,
4947
4818
  SelectItem as SelectItem4,
4948
4819
  SelectTrigger as SelectTrigger4,
4949
4820
  SelectValue as SelectValue4
4950
4821
  } from "@greatapps/greatauth-ui/ui";
4951
- import {
4952
- Trash2 as Trash25,
4953
- Plus as Plus2,
4954
- Wrench,
4955
- Settings2 as Settings22
4956
- } 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";
4957
4825
  import { toast as toast11 } from "sonner";
4958
4826
  import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
4959
- function AgentToolsList({ agent, config }) {
4960
- const { data: agentToolsData, isLoading } = useAgentTools(config, agent.id);
4961
- const { data: allToolsData } = useTools(config);
4962
- const addMutation = useAddAgentTool(config);
4963
- const removeMutation = useRemoveAgentTool(config);
4964
- const updateMutation = useUpdateAgentTool(config);
4965
- const [removeTarget, setRemoveTarget] = useState15(null);
4966
- 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_"));
4967
4939
  const [search, setSearch] = useState15("");
4968
- const [configTarget, setConfigTarget] = useState15(null);
4969
- const [configInstructions, setConfigInstructions] = useState15("");
4970
- const [configCredentialId, setConfigCredentialId] = useState15("");
4971
- const { data: credentialsData } = useToolCredentials(config);
4972
- const allCredentials = credentialsData?.data || [];
4973
- const agentTools = agentToolsData?.data || [];
4974
- const allTools = (allToolsData?.data || []).filter((t) => !t.slug?.startsWith("gclinic_"));
4975
- const assignedToolIds = new Set(agentTools.map((at) => at.id_tool));
4976
- const visibleAgentTools = agentTools.filter((at) => {
4977
- const tool = allTools.find((t) => t.id === at.id_tool);
4978
- 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: ""
4979
4948
  });
4980
- const availableTools = allTools.filter((t) => !assignedToolIds.has(t.id));
4981
- const filteredAvailable = availableTools.filter(
4982
- (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)
4983
4980
  );
4984
- function getToolInfo(idTool) {
4985
- return allTools.find((t) => t.id === idTool);
4986
- }
4987
- 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;
4988
4984
  try {
4989
- await updateMutation.mutateAsync({
4990
- idAgent: agent.id,
4991
- id: agentTool.id,
4992
- 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 } : {}
4993
4990
  });
4994
- toast11.success(checked ? "Ferramenta ativada" : "Ferramenta desativada");
4995
- } catch (err) {
4996
- toast11.error(
4997
- err instanceof Error ? err.message : "Erro ao alterar estado da ferramenta"
4998
- );
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");
4999
5000
  }
5000
5001
  }
5001
- async function handleAdd(tool) {
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
+ });
5011
+ }
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
+ }
5002
5035
  try {
5003
- await addMutation.mutateAsync({
5004
- idAgent: agent.id,
5005
- body: { id_tool: tool.id }
5036
+ const result = await updateMutation.mutateAsync({
5037
+ id: editTarget.id,
5038
+ body
5006
5039
  });
5007
- toast11.success("Ferramenta adicionada");
5008
- setAddOpen(false);
5009
- setSearch("");
5010
- } catch (err) {
5011
- toast11.error(
5012
- err instanceof Error ? err.message : "Erro ao adicionar ferramenta"
5013
- );
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");
5014
5048
  }
5015
5049
  }
5016
5050
  async function handleRemove() {
5017
5051
  if (!removeTarget) return;
5018
- try {
5019
- await removeMutation.mutateAsync({
5020
- idAgent: agent.id,
5021
- id: removeTarget.id
5022
- });
5023
- toast11.success("Ferramenta removida");
5024
- } catch (err) {
5025
- toast11.error(
5026
- err instanceof Error ? err.message : "Erro ao remover ferramenta"
5027
- );
5052
+ try {
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");
5028
5061
  } finally {
5029
5062
  setRemoveTarget(null);
5030
5063
  }
5031
5064
  }
5032
- function openConfig(agentTool) {
5033
- setConfigTarget(agentTool);
5034
- setConfigInstructions(agentTool.custom_instructions || "");
5035
- setConfigCredentialId(agentTool.id_tool_credential ? String(agentTool.id_tool_credential) : "");
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");
5036
5071
  }
5037
- async function handleSaveConfig() {
5038
- if (!configTarget) return;
5039
- try {
5040
- const newCredentialId = configCredentialId ? parseInt(configCredentialId, 10) : null;
5041
- await updateMutation.mutateAsync({
5042
- idAgent: agent.id,
5043
- id: configTarget.id,
5044
- body: {
5045
- custom_instructions: configInstructions.trim() || null,
5046
- id_tool_credential: newCredentialId
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"
5047
5085
  }
5048
- });
5049
- toast11.success("Configura\xE7\xE3o atualizada");
5050
- setConfigTarget(null);
5051
- } catch (err) {
5052
- toast11.error(
5053
- err instanceof Error ? err.message : "Erro ao atualizar configura\xE7\xE3o"
5054
- );
5055
- }
5056
- }
5057
- if (isLoading) {
5058
- 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)) });
5059
- }
5060
- return /* @__PURE__ */ jsxs22("div", { className: "space-y-4 p-4", children: [
5061
- /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between", children: [
5062
- /* @__PURE__ */ jsxs22("h3", { className: "text-sm font-medium text-muted-foreground", children: [
5063
- visibleAgentTools.length,
5064
- " ferramenta",
5065
- visibleAgentTools.length !== 1 ? "s" : "",
5066
- " associada",
5067
- visibleAgentTools.length !== 1 ? "s" : ""
5068
- ] }),
5069
- /* @__PURE__ */ jsxs22(Popover, { open: addOpen, onOpenChange: setAddOpen, children: [
5070
- /* @__PURE__ */ jsx24(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs22(Button14, { size: "sm", disabled: availableTools.length === 0, children: [
5071
- /* @__PURE__ */ jsx24(Plus2, { className: "mr-2 h-4 w-4" }),
5072
- "Adicionar Ferramenta"
5073
- ] }) }),
5074
- /* @__PURE__ */ jsxs22(PopoverContent, { className: "w-72 p-0", align: "end", children: [
5075
- /* @__PURE__ */ jsx24("div", { className: "p-2", children: /* @__PURE__ */ jsx24(
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(
5076
5117
  Input10,
5077
5118
  {
5078
- placeholder: "Buscar ferramenta\\u2026",
5079
- "aria-label": "Buscar ferramenta",
5080
- name: "search",
5081
- value: search,
5082
- onChange: (e) => setSearch(e.target.value),
5083
- 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"
5084
5124
  }
5085
- ) }),
5086
- /* @__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(
5087
- "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,
5088
5131
  {
5089
- type: "button",
5090
- className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-accent",
5091
- onClick: () => handleAdd(tool),
5092
- disabled: addMutation.isPending,
5093
- children: [
5094
- /* @__PURE__ */ jsx24(Wrench, { className: "h-4 w-4 text-muted-foreground" }),
5095
- /* @__PURE__ */ jsx24("span", { className: "flex-1 font-medium", children: tool.name }),
5096
- /* @__PURE__ */ jsx24(Badge9, { variant: "secondary", className: "text-xs", children: tool.type })
5097
- ]
5098
- },
5099
- tool.id
5100
- )) })
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
+ )
5101
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
+ )
5102
5176
  ] })
5103
- ] }),
5104
- visibleAgentTools.length === 0 ? /* @__PURE__ */ jsxs22("div", { className: "flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center", children: [
5105
- /* @__PURE__ */ jsx24(Wrench, { className: "mb-2 h-8 w-8 text-muted-foreground" }),
5106
- /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Nenhuma ferramenta associada. Clique em 'Adicionar Ferramenta' para come\xE7ar." })
5107
- ] }) : /* @__PURE__ */ jsx24("div", { className: "space-y-2", children: visibleAgentTools.map((agentTool) => {
5108
- const tool = getToolInfo(agentTool.id_tool);
5109
- return /* @__PURE__ */ jsxs22(
5110
- "div",
5111
- {
5112
- className: "flex items-center gap-3 rounded-lg border bg-card p-3",
5113
- children: [
5114
- /* @__PURE__ */ jsxs22("div", { className: "flex flex-1 flex-col gap-1 min-w-0", children: [
5115
- /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
5116
- /* @__PURE__ */ jsx24("span", { className: "truncate font-medium", children: tool?.name || `Ferramenta #${agentTool.id_tool}` }),
5117
- tool?.type && /* @__PURE__ */ jsx24(Badge9, { variant: "secondary", className: "shrink-0 text-xs", children: tool.type })
5118
- ] }),
5119
- agentTool.custom_instructions && /* @__PURE__ */ jsx24("p", { className: "truncate text-xs text-muted-foreground", children: agentTool.custom_instructions })
5120
- ] }),
5121
- /* @__PURE__ */ jsx24(
5122
- Switch5,
5123
- {
5124
- "aria-label": "Ativar/Desativar",
5125
- checked: agentTool.enabled,
5126
- onCheckedChange: (checked) => handleToggleEnabled(agentTool, checked),
5127
- disabled: updateMutation.isPending
5128
- }
5129
- ),
5130
- /* @__PURE__ */ jsx24(
5131
- Button14,
5132
- {
5133
- variant: "ghost",
5134
- size: "icon",
5135
- "aria-label": "Configurar",
5136
- className: "shrink-0 text-muted-foreground hover:text-foreground",
5137
- onClick: () => openConfig(agentTool),
5138
- title: "Configurar instru\xE7\xF5es",
5139
- children: /* @__PURE__ */ jsx24(Settings22, { className: "h-4 w-4" })
5140
- }
5141
- ),
5142
- /* @__PURE__ */ jsx24(
5143
- Button14,
5144
- {
5145
- variant: "ghost",
5146
- size: "icon",
5147
- "aria-label": "Remover",
5148
- className: "shrink-0 text-muted-foreground hover:text-destructive",
5149
- onClick: () => setRemoveTarget(agentTool),
5150
- children: /* @__PURE__ */ jsx24(Trash25, { className: "h-4 w-4" })
5151
- }
5152
- )
5153
- ]
5154
- },
5155
- agentTool.id
5156
- );
5157
- }) }),
5177
+ ] }) }),
5158
5178
  /* @__PURE__ */ jsx24(
5159
5179
  Dialog7,
5160
5180
  {
5161
- open: !!configTarget,
5162
- onOpenChange: (open) => !open && setConfigTarget(null),
5163
- children: /* @__PURE__ */ jsxs22(DialogContent7, { className: "sm:max-w-lg", children: [
5164
- /* @__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" }) }),
5165
5185
  /* @__PURE__ */ jsxs22("div", { className: "space-y-4", children: [
5166
- configTarget && getToolInfo(configTarget.id_tool)?.type !== "none" && /* @__PURE__ */ jsxs22("div", { className: "space-y-2", children: [
5167
- /* @__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 *" }),
5168
5188
  /* @__PURE__ */ jsxs22(
5169
5189
  Select4,
5170
5190
  {
5171
- value: configCredentialId || void 0,
5172
- onValueChange: (val) => setConfigCredentialId(val === "__none__" ? "" : val),
5191
+ value: editForm.id_tool,
5192
+ onValueChange: (val) => setEditForm((f) => ({ ...f, id_tool: val })),
5173
5193
  children: [
5174
- /* @__PURE__ */ jsx24(SelectTrigger4, { id: "tool-credential", children: /* @__PURE__ */ jsx24(SelectValue4, { placeholder: "Selecione uma credencial (opcional)" }) }),
5175
- /* @__PURE__ */ jsxs22(SelectContent4, { children: [
5176
- /* @__PURE__ */ jsx24(SelectItem4, { value: "__none__", children: "Nenhuma (autom\xE1tico)" }),
5177
- 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))
5178
- ] })
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)) })
5179
5196
  ]
5180
5197
  }
5181
- ),
5182
- /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: "Vincule uma credencial espec\xEDfica a esta ferramenta neste agente." })
5198
+ )
5183
5199
  ] }),
5184
- /* @__PURE__ */ jsxs22("div", { className: "space-y-2", children: [
5185
- /* @__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" }),
5186
5202
  /* @__PURE__ */ jsx24(
5187
- Textarea3,
5203
+ Input10,
5188
5204
  {
5189
- id: "tool-instructions",
5190
- name: "instructions",
5191
- value: configInstructions,
5192
- onChange: (e) => setConfigInstructions(e.target.value),
5193
- placeholder: "Instru\\u00e7\\u00f5es sobre como e quando o agente deve usar esta ferramenta\\u2026",
5194
- 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"
5195
5210
  }
5196
- ),
5197
- /* @__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
+ )
5198
5263
  ] })
5199
5264
  ] }),
5200
5265
  /* @__PURE__ */ jsxs22(DialogFooter7, { children: [
5266
+ /* @__PURE__ */ jsx24(Button14, { variant: "outline", onClick: () => setEditTarget(null), children: "Cancelar" }),
5201
5267
  /* @__PURE__ */ jsx24(
5202
5268
  Button14,
5203
5269
  {
5204
- variant: "outline",
5205
- onClick: () => setConfigTarget(null),
5206
- children: "Cancelar"
5207
- }
5208
- ),
5209
- /* @__PURE__ */ jsx24(
5210
- Button14,
5211
- {
5212
- onClick: handleSaveConfig,
5270
+ onClick: handleSaveEdit,
5213
5271
  disabled: updateMutation.isPending,
5214
5272
  children: "Salvar"
5215
5273
  }
@@ -5225,8 +5283,8 @@ function AgentToolsList({ agent, config }) {
5225
5283
  onOpenChange: (open) => !open && setRemoveTarget(null),
5226
5284
  children: /* @__PURE__ */ jsxs22(AlertDialogContent5, { children: [
5227
5285
  /* @__PURE__ */ jsxs22(AlertDialogHeader5, { children: [
5228
- /* @__PURE__ */ jsx24(AlertDialogTitle5, { children: "Remover ferramenta?" }),
5229
- /* @__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." })
5230
5288
  ] }),
5231
5289
  /* @__PURE__ */ jsxs22(AlertDialogFooter5, { children: [
5232
5290
  /* @__PURE__ */ jsx24(AlertDialogCancel5, { children: "Cancelar" }),
@@ -5234,7 +5292,7 @@ function AgentToolsList({ agent, config }) {
5234
5292
  AlertDialogAction5,
5235
5293
  {
5236
5294
  onClick: handleRemove,
5237
- disabled: removeMutation.isPending,
5295
+ disabled: deleteMutation.isPending,
5238
5296
  children: "Remover"
5239
5297
  }
5240
5298
  )
@@ -5248,7 +5306,7 @@ function AgentToolsList({ agent, config }) {
5248
5306
  // src/pages/agents-page.tsx
5249
5307
  import { useState as useState16 } from "react";
5250
5308
  import { Button as Button15 } from "@greatapps/greatauth-ui/ui";
5251
- import { Plus as Plus3 } from "lucide-react";
5309
+ import { Plus as Plus4 } from "lucide-react";
5252
5310
  import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
5253
5311
  function AgentsPage({
5254
5312
  config,
@@ -5264,7 +5322,7 @@ function AgentsPage({
5264
5322
  /* @__PURE__ */ jsx25("p", { className: "text-sm text-muted-foreground", children: subtitle })
5265
5323
  ] }),
5266
5324
  /* @__PURE__ */ jsxs23(Button15, { onClick: () => setCreateOpen(true), size: "sm", children: [
5267
- /* @__PURE__ */ jsx25(Plus3, { className: "mr-2 h-4 w-4" }),
5325
+ /* @__PURE__ */ jsx25(Plus4, { className: "mr-2 h-4 w-4" }),
5268
5326
  "Novo Agente"
5269
5327
  ] })
5270
5328
  ] }),
@@ -5376,7 +5434,7 @@ function AgentDetailPage({
5376
5434
  // src/pages/tools-page.tsx
5377
5435
  import { useState as useState18 } from "react";
5378
5436
  import { Button as Button17 } from "@greatapps/greatauth-ui/ui";
5379
- import { Plus as Plus4 } from "lucide-react";
5437
+ import { Plus as Plus5 } from "lucide-react";
5380
5438
  import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
5381
5439
  function ToolsPage({
5382
5440
  config,
@@ -5392,7 +5450,7 @@ function ToolsPage({
5392
5450
  /* @__PURE__ */ jsx27("p", { className: "text-sm text-muted-foreground", children: subtitle })
5393
5451
  ] }),
5394
5452
  /* @__PURE__ */ jsxs25(Button17, { onClick: () => setCreateOpen(true), size: "sm", children: [
5395
- /* @__PURE__ */ jsx27(Plus4, { className: "mr-2 h-4 w-4" }),
5453
+ /* @__PURE__ */ jsx27(Plus5, { className: "mr-2 h-4 w-4" }),
5396
5454
  "Nova Ferramenta"
5397
5455
  ] })
5398
5456
  ] }),
@@ -5420,7 +5478,7 @@ function ToolsPage({
5420
5478
  // src/pages/credentials-page.tsx
5421
5479
  import { useState as useState19 } from "react";
5422
5480
  import { Button as Button18 } from "@greatapps/greatauth-ui/ui";
5423
- import { Plus as Plus5 } from "lucide-react";
5481
+ import { Plus as Plus6 } from "lucide-react";
5424
5482
  import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
5425
5483
  function CredentialsPage({
5426
5484
  config,
@@ -5438,7 +5496,7 @@ function CredentialsPage({
5438
5496
  /* @__PURE__ */ jsx28("p", { className: "text-sm text-muted-foreground", children: subtitle })
5439
5497
  ] }),
5440
5498
  /* @__PURE__ */ jsxs26(Button18, { onClick: () => setCreateOpen(true), size: "sm", children: [
5441
- /* @__PURE__ */ jsx28(Plus5, { className: "mr-2 h-4 w-4" }),
5499
+ /* @__PURE__ */ jsx28(Plus6, { className: "mr-2 h-4 w-4" }),
5442
5500
  "Nova Credencial"
5443
5501
  ] })
5444
5502
  ] }),
@@ -5466,7 +5524,7 @@ import {
5466
5524
  TabsList as TabsList3,
5467
5525
  TabsTrigger as TabsTrigger3
5468
5526
  } from "@greatapps/greatauth-ui/ui";
5469
- import { Plus as Plus6, Plug as Plug4, KeyRound, Info as Info3 } from "lucide-react";
5527
+ import { Plus as Plus7, Plug as Plug4, KeyRound, Info as Info3 } from "lucide-react";
5470
5528
  import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
5471
5529
  function useCredentialAgentSummary(credentials, tools, agents) {
5472
5530
  return useMemo8(() => {
@@ -5545,7 +5603,7 @@ function IntegrationsManagementPage({
5545
5603
  ] })
5546
5604
  ] }),
5547
5605
  /* @__PURE__ */ jsx29("div", { className: "flex items-center justify-end mb-4", children: /* @__PURE__ */ jsxs27(Button19, { onClick: () => setCreateOpen(true), size: "sm", children: [
5548
- /* @__PURE__ */ jsx29(Plus6, { className: "mr-2 h-4 w-4" }),
5606
+ /* @__PURE__ */ jsx29(Plus7, { className: "mr-2 h-4 w-4" }),
5549
5607
  "Nova Credencial"
5550
5608
  ] }) }),
5551
5609
  /* @__PURE__ */ jsx29(