@greatapps/greatagents-ui 0.3.5 → 0.3.7
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.d.ts +2 -1
- package/dist/index.js +1274 -1233
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/agents/agent-form-dialog.tsx +12 -11
- package/src/components/agents/agent-tabs.tsx +1 -10
- package/src/components/agents/agent-tools-list.tsx +11 -6
- package/src/components/capabilities/capabilities-tab.tsx +1 -1
- package/src/components/capabilities/wizard-steps/credentials-step.tsx +50 -8
- package/src/components/tools/tool-credentials-form.tsx +18 -4
- package/src/components/tools/tools-table.tsx +3 -2
package/package.json
CHANGED
|
@@ -15,12 +15,14 @@ import {
|
|
|
15
15
|
} from "@greatapps/greatauth-ui/ui";
|
|
16
16
|
import { Loader2 } from "lucide-react";
|
|
17
17
|
import { toast } from "sonner";
|
|
18
|
+
import { ImageCropUpload } from "@greatapps/greatauth-ui";
|
|
18
19
|
|
|
19
20
|
interface AgentFormDialogProps {
|
|
20
21
|
config: GagentsHookConfig;
|
|
21
22
|
open: boolean;
|
|
22
23
|
onOpenChange: (open: boolean) => void;
|
|
23
24
|
agent?: Agent;
|
|
25
|
+
idAccount?: string | number | null;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
interface FormState {
|
|
@@ -68,6 +70,7 @@ export function AgentFormDialog({
|
|
|
68
70
|
open,
|
|
69
71
|
onOpenChange,
|
|
70
72
|
agent,
|
|
73
|
+
idAccount,
|
|
71
74
|
}: AgentFormDialogProps) {
|
|
72
75
|
const isEditing = !!agent;
|
|
73
76
|
const createAgent = useCreateAgent(config);
|
|
@@ -139,19 +142,17 @@ export function AgentFormDialog({
|
|
|
139
142
|
</DialogTitle>
|
|
140
143
|
</DialogHeader>
|
|
141
144
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
142
|
-
<div className="
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
<div className="flex justify-center">
|
|
146
|
+
<ImageCropUpload
|
|
147
|
+
value={form.photo || null}
|
|
148
|
+
onChange={(url) => updateField("photo", url)}
|
|
149
|
+
onRemove={() => updateField("photo", "")}
|
|
150
|
+
entityType="agents"
|
|
151
|
+
entityId={agent?.id}
|
|
152
|
+
idAccount={typeof idAccount === "string" ? Number(idAccount) : (idAccount ?? Number(config.accountId) ?? 0)}
|
|
153
|
+
name={form.title || null}
|
|
150
154
|
disabled={isPending}
|
|
151
155
|
/>
|
|
152
|
-
<p className="text-xs text-muted-foreground">
|
|
153
|
-
URL da imagem de avatar do agente
|
|
154
|
-
</p>
|
|
155
156
|
</div>
|
|
156
157
|
<div className="space-y-2">
|
|
157
158
|
<Label htmlFor="agent-title">Nome do Agente *</Label>
|
|
@@ -3,7 +3,6 @@ import type { GagentsHookConfig } from "../../hooks/types";
|
|
|
3
3
|
import type { IntegrationCardData } from "../../hooks/use-integrations";
|
|
4
4
|
import type { WizardIntegrationMeta } from "../capabilities/types";
|
|
5
5
|
import type { ConfigOption } from "../capabilities/wizard-steps/config-step";
|
|
6
|
-
import { AgentToolsList } from "./agent-tools-list";
|
|
7
6
|
import { AgentObjectivesList } from "./agent-objectives-list";
|
|
8
7
|
import { AgentPromptEditor } from "./agent-prompt-editor";
|
|
9
8
|
import { AgentConversationsPanel } from "../conversations/agent-conversations-panel";
|
|
@@ -14,7 +13,7 @@ import {
|
|
|
14
13
|
TabsTrigger,
|
|
15
14
|
TabsContent,
|
|
16
15
|
} from "@greatapps/greatauth-ui/ui";
|
|
17
|
-
import {
|
|
16
|
+
import { Target, FileText, MessageCircle, Blocks } from "lucide-react";
|
|
18
17
|
|
|
19
18
|
interface AgentTabsProps {
|
|
20
19
|
agent: Agent;
|
|
@@ -52,10 +51,6 @@ export function AgentTabs({
|
|
|
52
51
|
<Target aria-hidden="true" className="h-3.5 w-3.5" />
|
|
53
52
|
Objetivos
|
|
54
53
|
</TabsTrigger>
|
|
55
|
-
<TabsTrigger value="ferramentas" className="flex items-center gap-1.5">
|
|
56
|
-
<Wrench aria-hidden="true" className="h-3.5 w-3.5" />
|
|
57
|
-
Ferramentas
|
|
58
|
-
</TabsTrigger>
|
|
59
54
|
<TabsTrigger value="capacidades" className="flex items-center gap-1.5">
|
|
60
55
|
<Blocks aria-hidden="true" className="h-3.5 w-3.5" />
|
|
61
56
|
Capacidades
|
|
@@ -74,10 +69,6 @@ export function AgentTabs({
|
|
|
74
69
|
<AgentObjectivesList agent={agent} config={config} />
|
|
75
70
|
</TabsContent>
|
|
76
71
|
|
|
77
|
-
<TabsContent value="ferramentas" className="mt-4">
|
|
78
|
-
<AgentToolsList agent={agent} config={config} />
|
|
79
|
-
</TabsContent>
|
|
80
|
-
|
|
81
72
|
<TabsContent value="capacidades" className="mt-4">
|
|
82
73
|
<AgentCapabilitiesPage
|
|
83
74
|
config={config}
|
|
@@ -70,10 +70,15 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
70
70
|
const allCredentials: ToolCredential[] = credentialsData?.data || [];
|
|
71
71
|
|
|
72
72
|
const agentTools = agentToolsData?.data || [];
|
|
73
|
-
const allTools = allToolsData?.data || [];
|
|
73
|
+
const allTools = (allToolsData?.data || []).filter((t: Tool) => !t.slug?.startsWith("gclinic_"));
|
|
74
74
|
const assignedToolIds = new Set(agentTools.map((at) => at.id_tool));
|
|
75
|
-
|
|
76
|
-
const
|
|
75
|
+
// Filter out internal gclinic_* tools from assigned tools display
|
|
76
|
+
const visibleAgentTools = agentTools.filter((at) => {
|
|
77
|
+
const tool = allTools.find((t: Tool) => t.id === at.id_tool);
|
|
78
|
+
return !tool || !tool.slug?.startsWith("gclinic_");
|
|
79
|
+
});
|
|
80
|
+
const availableTools = allTools.filter((t: Tool) => !assignedToolIds.has(t.id));
|
|
81
|
+
const filteredAvailable = availableTools.filter((t: Tool) =>
|
|
77
82
|
t.name.toLowerCase().includes(search.toLowerCase()),
|
|
78
83
|
);
|
|
79
84
|
|
|
@@ -170,7 +175,7 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
170
175
|
<div className="space-y-4 p-4">
|
|
171
176
|
<div className="flex items-center justify-between">
|
|
172
177
|
<h3 className="text-sm font-medium text-muted-foreground">
|
|
173
|
-
{
|
|
178
|
+
{visibleAgentTools.length} ferramenta{visibleAgentTools.length !== 1 ? "s" : ""} associada{visibleAgentTools.length !== 1 ? "s" : ""}
|
|
174
179
|
</h3>
|
|
175
180
|
<Popover open={addOpen} onOpenChange={setAddOpen}>
|
|
176
181
|
<PopoverTrigger asChild>
|
|
@@ -217,7 +222,7 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
217
222
|
</Popover>
|
|
218
223
|
</div>
|
|
219
224
|
|
|
220
|
-
{
|
|
225
|
+
{visibleAgentTools.length === 0 ? (
|
|
221
226
|
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed p-8 text-center">
|
|
222
227
|
<Wrench className="mb-2 h-8 w-8 text-muted-foreground" />
|
|
223
228
|
<p className="text-sm text-muted-foreground">
|
|
@@ -226,7 +231,7 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
226
231
|
</div>
|
|
227
232
|
) : (
|
|
228
233
|
<div className="space-y-2">
|
|
229
|
-
{
|
|
234
|
+
{visibleAgentTools.map((agentTool) => {
|
|
230
235
|
const tool = getToolInfo(agentTool.id_tool);
|
|
231
236
|
return (
|
|
232
237
|
<div
|
|
@@ -337,7 +337,7 @@ export function CapabilitiesTab({ config, agentId }: CapabilitiesTabProps) {
|
|
|
337
337
|
</Badge>
|
|
338
338
|
</div>
|
|
339
339
|
</AccordionTrigger>
|
|
340
|
-
<AccordionContent className="pb-3">
|
|
340
|
+
<AccordionContent className="pb-3 !h-auto">
|
|
341
341
|
<div className="space-y-1">
|
|
342
342
|
{cat.modules.map((mod) => {
|
|
343
343
|
const enabledOps = localState.get(mod.slug);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { CheckCircle2, Loader2, AlertCircle, Shield } from "lucide-react";
|
|
4
|
-
import { Button, Input, Label } from "@greatapps/greatauth-ui/ui";
|
|
3
|
+
import { CheckCircle2, Loader2, AlertCircle, Shield, Info } from "lucide-react";
|
|
4
|
+
import { Button, Input, Label, Tooltip, TooltipTrigger, TooltipContent } from "@greatapps/greatauth-ui/ui";
|
|
5
5
|
import type { IntegrationDefinition } from "../../../data/integrations-registry";
|
|
6
6
|
import type { WizardIntegrationMeta, OAuthStatus, OAuthResult } from "../types";
|
|
7
7
|
|
|
@@ -14,6 +14,8 @@ interface CredentialsStepProps {
|
|
|
14
14
|
onApiKeyChange: (value: string) => void;
|
|
15
15
|
onStartOAuth: () => void;
|
|
16
16
|
isReconnect?: boolean;
|
|
17
|
+
/** When true, the OAuth authorize endpoint is available on the backend. */
|
|
18
|
+
oauthConfigured?: boolean;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export function CredentialsStep({
|
|
@@ -25,6 +27,7 @@ export function CredentialsStep({
|
|
|
25
27
|
onApiKeyChange,
|
|
26
28
|
onStartOAuth,
|
|
27
29
|
isReconnect = false,
|
|
30
|
+
oauthConfigured = false,
|
|
28
31
|
}: CredentialsStepProps) {
|
|
29
32
|
if (integration.authType === "oauth2") {
|
|
30
33
|
return (
|
|
@@ -35,6 +38,7 @@ export function CredentialsStep({
|
|
|
35
38
|
oauthResult={oauthResult}
|
|
36
39
|
onStartOAuth={onStartOAuth}
|
|
37
40
|
isReconnect={isReconnect}
|
|
41
|
+
oauthConfigured={oauthConfigured}
|
|
38
42
|
/>
|
|
39
43
|
);
|
|
40
44
|
}
|
|
@@ -53,6 +57,7 @@ function OAuthCredentials({
|
|
|
53
57
|
oauthResult,
|
|
54
58
|
onStartOAuth,
|
|
55
59
|
isReconnect,
|
|
60
|
+
oauthConfigured,
|
|
56
61
|
}: {
|
|
57
62
|
integration: IntegrationDefinition;
|
|
58
63
|
meta: WizardIntegrationMeta;
|
|
@@ -60,6 +65,7 @@ function OAuthCredentials({
|
|
|
60
65
|
oauthResult: OAuthResult | null;
|
|
61
66
|
onStartOAuth: () => void;
|
|
62
67
|
isReconnect: boolean;
|
|
68
|
+
oauthConfigured: boolean;
|
|
63
69
|
}) {
|
|
64
70
|
const providerLabel = meta.providerLabel || integration.name;
|
|
65
71
|
|
|
@@ -74,15 +80,51 @@ function OAuthCredentials({
|
|
|
74
80
|
</p>
|
|
75
81
|
</div>
|
|
76
82
|
|
|
83
|
+
{/* OAuth not configured notice */}
|
|
84
|
+
{!oauthConfigured && oauthStatus === "idle" && (
|
|
85
|
+
<div className="flex items-start gap-3 rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-900 dark:bg-amber-950/30">
|
|
86
|
+
<Info
|
|
87
|
+
aria-hidden="true"
|
|
88
|
+
className="mt-0.5 h-5 w-5 shrink-0 text-amber-600 dark:text-amber-400"
|
|
89
|
+
/>
|
|
90
|
+
<div className="space-y-1">
|
|
91
|
+
<p className="text-sm font-medium text-amber-800 dark:text-amber-200">
|
|
92
|
+
Configuração necessária
|
|
93
|
+
</p>
|
|
94
|
+
<p className="text-xs text-amber-700 dark:text-amber-300">
|
|
95
|
+
A integração com {providerLabel} requer configuração pelo
|
|
96
|
+
administrador do sistema. Entre em contato com o suporte para
|
|
97
|
+
ativar esta funcionalidade.
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
|
|
77
103
|
{/* OAuth status area */}
|
|
78
104
|
<div className="flex flex-col items-center gap-4 rounded-lg border p-6">
|
|
79
105
|
{oauthStatus === "idle" && (
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
106
|
+
<Tooltip>
|
|
107
|
+
<TooltipTrigger asChild>
|
|
108
|
+
<span tabIndex={!oauthConfigured ? 0 : undefined}>
|
|
109
|
+
<Button
|
|
110
|
+
onClick={onStartOAuth}
|
|
111
|
+
size="lg"
|
|
112
|
+
className="gap-2"
|
|
113
|
+
disabled={!oauthConfigured}
|
|
114
|
+
>
|
|
115
|
+
{meta.icon}
|
|
116
|
+
{isReconnect
|
|
117
|
+
? `Reconectar com ${providerLabel}`
|
|
118
|
+
: `Conectar com ${providerLabel}`}
|
|
119
|
+
</Button>
|
|
120
|
+
</span>
|
|
121
|
+
</TooltipTrigger>
|
|
122
|
+
{!oauthConfigured && (
|
|
123
|
+
<TooltipContent>
|
|
124
|
+
Integração OAuth ainda não configurada no servidor
|
|
125
|
+
</TooltipContent>
|
|
126
|
+
)}
|
|
127
|
+
</Tooltip>
|
|
86
128
|
)}
|
|
87
129
|
|
|
88
130
|
{oauthStatus === "waiting" && (
|
|
@@ -185,7 +185,7 @@ export function ToolCredentialsForm({
|
|
|
185
185
|
const updateMutation = useUpdateToolCredential(config);
|
|
186
186
|
const deleteMutation = useDeleteToolCredential(config);
|
|
187
187
|
const { data: toolsData } = useTools(config);
|
|
188
|
-
const tools: Tool[] = toolsData?.data || [];
|
|
188
|
+
const tools: Tool[] = (toolsData?.data || []).filter((t: Tool) => !t.slug?.startsWith("gclinic_"));
|
|
189
189
|
|
|
190
190
|
const [search, setSearch] = useState("");
|
|
191
191
|
const [internalCreateOpen, setInternalCreateOpen] = useState(false);
|
|
@@ -209,17 +209,31 @@ export function ToolCredentialsForm({
|
|
|
209
209
|
|
|
210
210
|
const [removeTarget, setRemoveTarget] = useState<ToolCredential | null>(null);
|
|
211
211
|
|
|
212
|
+
// Build a set of internal tool IDs to exclude from credentials display
|
|
213
|
+
const internalToolIds = useMemo(() => {
|
|
214
|
+
const allRawTools: Tool[] = toolsData?.data || [];
|
|
215
|
+
return new Set(
|
|
216
|
+
allRawTools
|
|
217
|
+
.filter((t: Tool) => t.slug?.startsWith("gclinic_"))
|
|
218
|
+
.map((t: Tool) => t.id),
|
|
219
|
+
);
|
|
220
|
+
}, [toolsData]);
|
|
221
|
+
|
|
212
222
|
const filteredCredentials = useMemo(() => {
|
|
213
|
-
|
|
223
|
+
// Exclude credentials linked to internal gclinic_* tools
|
|
224
|
+
const visible = credentials.filter(
|
|
225
|
+
(cred) => !cred.id_tool || !internalToolIds.has(cred.id_tool),
|
|
226
|
+
);
|
|
227
|
+
if (!search) return visible;
|
|
214
228
|
const term = search.toLowerCase();
|
|
215
|
-
return
|
|
229
|
+
return visible.filter((cred) => {
|
|
216
230
|
const toolName = tools.find((t) => t.id === cred.id_tool)?.name || "";
|
|
217
231
|
return (
|
|
218
232
|
(cred.label || "").toLowerCase().includes(term) ||
|
|
219
233
|
toolName.toLowerCase().includes(term)
|
|
220
234
|
);
|
|
221
235
|
});
|
|
222
|
-
}, [credentials, search, tools]);
|
|
236
|
+
}, [credentials, search, tools, internalToolIds]);
|
|
223
237
|
|
|
224
238
|
const columns = useColumns(
|
|
225
239
|
tools,
|
|
@@ -145,8 +145,9 @@ export function ToolsTable({ onEdit, config }: ToolsTableProps) {
|
|
|
145
145
|
const deleteTool = useDeleteTool(config);
|
|
146
146
|
const [deleteId, setDeleteId] = useState<number | null>(null);
|
|
147
147
|
|
|
148
|
-
const
|
|
149
|
-
const
|
|
148
|
+
const rawTools = data?.data || [];
|
|
149
|
+
const tools = rawTools.filter((t: Tool) => !t.slug?.startsWith("gclinic_"));
|
|
150
|
+
const total = tools.length;
|
|
150
151
|
|
|
151
152
|
const columns = useColumns(
|
|
152
153
|
(tool) => onEdit(tool),
|