@greatapps/greatagents-ui 0.3.10 → 0.3.12
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 +0 -4
- package/dist/index.js +1287 -1301
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/agents/agent-tabs.tsx +94 -46
- package/src/components/capabilities/advanced-tab.tsx +1 -18
- package/src/components/capabilities/capabilities-tab.tsx +11 -47
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useState, useCallback } from "react";
|
|
1
2
|
import type { Agent } from "../../types";
|
|
2
3
|
import type { GagentsHookConfig } from "../../hooks/types";
|
|
3
4
|
import type { IntegrationCardData } from "../../hooks/use-integrations";
|
|
@@ -6,26 +7,24 @@ import type { ConfigOption } from "../capabilities/wizard-steps/config-step";
|
|
|
6
7
|
import { AgentObjectivesList } from "./agent-objectives-list";
|
|
7
8
|
import { AgentPromptEditor } from "./agent-prompt-editor";
|
|
8
9
|
import { AgentConversationsPanel } from "../conversations/agent-conversations-panel";
|
|
9
|
-
import {
|
|
10
|
+
import { CapabilitiesTab } from "../capabilities/capabilities-tab";
|
|
11
|
+
import { IntegrationsTab } from "../capabilities/integrations-tab";
|
|
12
|
+
import { IntegrationWizard } from "../capabilities/integration-wizard";
|
|
10
13
|
import {
|
|
11
14
|
Tabs,
|
|
12
15
|
TabsList,
|
|
13
16
|
TabsTrigger,
|
|
14
17
|
TabsContent,
|
|
15
18
|
} from "@greatapps/greatauth-ui/ui";
|
|
16
|
-
import { Target, FileText, MessageCircle, Blocks } from "lucide-react";
|
|
19
|
+
import { Target, FileText, MessageCircle, Blocks, Plug } from "lucide-react";
|
|
17
20
|
|
|
18
21
|
interface AgentTabsProps {
|
|
19
22
|
agent: Agent;
|
|
20
23
|
config: GagentsHookConfig;
|
|
21
24
|
renderChatLink?: (inboxId: number) => React.ReactNode;
|
|
22
|
-
/** Required for the Capacidades tab — gagents API URL for OAuth flows and advanced features. Falls back to config.baseUrl. */
|
|
23
25
|
gagentsApiUrl?: string;
|
|
24
|
-
/** Resolve wizard metadata for a given integration card. */
|
|
25
26
|
resolveWizardMeta?: (card: IntegrationCardData) => WizardIntegrationMeta;
|
|
26
|
-
/** Callback to load config options after OAuth completes. */
|
|
27
27
|
loadConfigOptions?: (credentialId: number) => Promise<ConfigOption[]>;
|
|
28
|
-
/** Called after wizard completes successfully. */
|
|
29
28
|
onWizardComplete?: () => void;
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -40,53 +39,102 @@ export function AgentTabs({
|
|
|
40
39
|
}: AgentTabsProps) {
|
|
41
40
|
const apiUrl = gagentsApiUrl || config.baseUrl;
|
|
42
41
|
|
|
42
|
+
// Wizard state for Integrações tab
|
|
43
|
+
const [wizardOpen, setWizardOpen] = useState(false);
|
|
44
|
+
const [activeCard, setActiveCard] = useState<IntegrationCardData | null>(null);
|
|
45
|
+
|
|
46
|
+
const handleConnect = useCallback((card: IntegrationCardData) => {
|
|
47
|
+
setActiveCard(card);
|
|
48
|
+
setWizardOpen(true);
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
const handleWizardClose = useCallback((open: boolean) => {
|
|
52
|
+
if (!open) {
|
|
53
|
+
setActiveCard(null);
|
|
54
|
+
}
|
|
55
|
+
setWizardOpen(open);
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
const handleWizardComplete = useCallback(() => {
|
|
59
|
+
setWizardOpen(false);
|
|
60
|
+
setActiveCard(null);
|
|
61
|
+
onWizardComplete?.();
|
|
62
|
+
}, [onWizardComplete]);
|
|
63
|
+
|
|
64
|
+
// Resolve wizard meta with sensible defaults
|
|
65
|
+
const wizardMeta: WizardIntegrationMeta | null = activeCard
|
|
66
|
+
? (resolveWizardMeta?.(activeCard) ?? {
|
|
67
|
+
capabilities: [],
|
|
68
|
+
requirements: [],
|
|
69
|
+
hasConfigStep: false,
|
|
70
|
+
})
|
|
71
|
+
: null;
|
|
72
|
+
|
|
43
73
|
return (
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
<>
|
|
75
|
+
<Tabs defaultValue="prompt">
|
|
76
|
+
<TabsList>
|
|
77
|
+
<TabsTrigger value="prompt" className="flex items-center gap-1.5">
|
|
78
|
+
<FileText aria-hidden="true" className="h-3.5 w-3.5" />
|
|
79
|
+
Prompt
|
|
80
|
+
</TabsTrigger>
|
|
81
|
+
<TabsTrigger value="objetivos" className="flex items-center gap-1.5">
|
|
82
|
+
<Target aria-hidden="true" className="h-3.5 w-3.5" />
|
|
83
|
+
Objetivos
|
|
84
|
+
</TabsTrigger>
|
|
85
|
+
<TabsTrigger value="capacidades" className="flex items-center gap-1.5">
|
|
86
|
+
<Blocks aria-hidden="true" className="h-3.5 w-3.5" />
|
|
87
|
+
Capacidades
|
|
88
|
+
</TabsTrigger>
|
|
89
|
+
<TabsTrigger value="integracoes" className="flex items-center gap-1.5">
|
|
90
|
+
<Plug aria-hidden="true" className="h-3.5 w-3.5" />
|
|
91
|
+
Integrações
|
|
92
|
+
</TabsTrigger>
|
|
93
|
+
<TabsTrigger value="conversas" className="flex items-center gap-1.5">
|
|
94
|
+
<MessageCircle aria-hidden="true" className="h-3.5 w-3.5" />
|
|
95
|
+
Conversas
|
|
96
|
+
</TabsTrigger>
|
|
97
|
+
</TabsList>
|
|
63
98
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
99
|
+
<TabsContent value="prompt" className="mt-4">
|
|
100
|
+
<AgentPromptEditor agent={agent} config={config} />
|
|
101
|
+
</TabsContent>
|
|
67
102
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
103
|
+
<TabsContent value="objetivos" className="mt-4">
|
|
104
|
+
<AgentObjectivesList agent={agent} config={config} />
|
|
105
|
+
</TabsContent>
|
|
71
106
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
107
|
+
<TabsContent value="capacidades" className="mt-4">
|
|
108
|
+
<CapabilitiesTab config={config} agentId={agent.id} />
|
|
109
|
+
</TabsContent>
|
|
110
|
+
|
|
111
|
+
<TabsContent value="integracoes" className="mt-4">
|
|
112
|
+
<IntegrationsTab config={config} agentId={agent.id} onConnect={handleConnect} />
|
|
113
|
+
</TabsContent>
|
|
114
|
+
|
|
115
|
+
<TabsContent value="conversas" className="mt-4">
|
|
116
|
+
<AgentConversationsPanel
|
|
117
|
+
agent={agent}
|
|
118
|
+
config={config}
|
|
119
|
+
renderChatLink={renderChatLink}
|
|
120
|
+
/>
|
|
121
|
+
</TabsContent>
|
|
122
|
+
</Tabs>
|
|
123
|
+
|
|
124
|
+
{activeCard && wizardMeta && (
|
|
125
|
+
<IntegrationWizard
|
|
126
|
+
open={wizardOpen}
|
|
127
|
+
onOpenChange={handleWizardClose}
|
|
128
|
+
integration={activeCard.definition}
|
|
129
|
+
meta={wizardMeta}
|
|
75
130
|
agentId={agent.id}
|
|
131
|
+
config={config}
|
|
76
132
|
gagentsApiUrl={apiUrl}
|
|
77
|
-
|
|
133
|
+
existingCredentialId={activeCard.credentialId}
|
|
134
|
+
onComplete={handleWizardComplete}
|
|
78
135
|
loadConfigOptions={loadConfigOptions}
|
|
79
|
-
onWizardComplete={onWizardComplete}
|
|
80
|
-
/>
|
|
81
|
-
</TabsContent>
|
|
82
|
-
|
|
83
|
-
<TabsContent value="conversas" className="mt-4">
|
|
84
|
-
<AgentConversationsPanel
|
|
85
|
-
agent={agent}
|
|
86
|
-
config={config}
|
|
87
|
-
renderChatLink={renderChatLink}
|
|
88
136
|
/>
|
|
89
|
-
|
|
90
|
-
|
|
137
|
+
)}
|
|
138
|
+
</>
|
|
91
139
|
);
|
|
92
140
|
}
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import type { GagentsHookConfig } from "../../hooks/types";
|
|
5
|
-
import { useToolCredentials } from "../../hooks";
|
|
6
5
|
import { ToolsTable } from "../tools/tools-table";
|
|
7
|
-
import { ToolCredentialsForm } from "../tools/tool-credentials-form";
|
|
8
6
|
import { ToolFormDialog } from "../tools/tool-form-dialog";
|
|
9
7
|
import type { Tool } from "../../types";
|
|
10
8
|
import { Info } from "lucide-react";
|
|
@@ -24,10 +22,6 @@ export interface AdvancedTabProps {
|
|
|
24
22
|
// ---------------------------------------------------------------------------
|
|
25
23
|
|
|
26
24
|
export function AdvancedTab({ config, agentId, gagentsApiUrl }: AdvancedTabProps) {
|
|
27
|
-
const { data: credentialsData, isLoading: isLoadingCredentials } =
|
|
28
|
-
useToolCredentials(config);
|
|
29
|
-
const credentials = credentialsData?.data ?? [];
|
|
30
|
-
|
|
31
25
|
const [editingTool, setEditingTool] = useState<Tool | null>(null);
|
|
32
26
|
const [showToolForm, setShowToolForm] = useState(false);
|
|
33
27
|
|
|
@@ -49,7 +43,7 @@ export function AdvancedTab({ config, agentId, gagentsApiUrl }: AdvancedTabProps
|
|
|
49
43
|
<p className="text-sm text-blue-800 dark:text-blue-300">
|
|
50
44
|
Use as abas <strong>Capacidades</strong> e <strong>Integrações</strong> para
|
|
51
45
|
configuração simplificada. Esta aba oferece controlo manual avançado sobre
|
|
52
|
-
ferramentas
|
|
46
|
+
ferramentas. As credenciais são geridas dentro de cada ferramenta.
|
|
53
47
|
</p>
|
|
54
48
|
</div>
|
|
55
49
|
|
|
@@ -59,17 +53,6 @@ export function AdvancedTab({ config, agentId, gagentsApiUrl }: AdvancedTabProps
|
|
|
59
53
|
<ToolsTable onEdit={handleEditTool} config={config} />
|
|
60
54
|
</section>
|
|
61
55
|
|
|
62
|
-
{/* Credenciais section */}
|
|
63
|
-
<section className="space-y-3">
|
|
64
|
-
<h3 className="text-sm font-medium">Credenciais</h3>
|
|
65
|
-
<ToolCredentialsForm
|
|
66
|
-
credentials={credentials}
|
|
67
|
-
isLoading={isLoadingCredentials}
|
|
68
|
-
config={config}
|
|
69
|
-
gagentsApiUrl={gagentsApiUrl}
|
|
70
|
-
/>
|
|
71
|
-
</section>
|
|
72
|
-
|
|
73
56
|
{/* Tool edit dialog */}
|
|
74
57
|
<ToolFormDialog
|
|
75
58
|
open={showToolForm}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useState, useCallback,
|
|
3
|
+
import { useState, useCallback, useEffect, useMemo } from "react";
|
|
4
4
|
import type { GagentsHookConfig } from "../../hooks/types";
|
|
5
5
|
import {
|
|
6
6
|
useCapabilities,
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
HeartHandshake,
|
|
32
32
|
Package,
|
|
33
33
|
ChevronDown,
|
|
34
|
+
Loader2,
|
|
34
35
|
} from "lucide-react";
|
|
35
36
|
import { toast } from "sonner";
|
|
36
37
|
|
|
@@ -129,7 +130,6 @@ export function CapabilitiesTab({ config, agentId }: CapabilitiesTabProps) {
|
|
|
129
130
|
const [localState, setLocalState] = useState<CapabilityState>(new Map());
|
|
130
131
|
const [serverState, setServerState] = useState<CapabilityState>(new Map());
|
|
131
132
|
const [initialized, setInitialized] = useState(false);
|
|
132
|
-
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
133
133
|
|
|
134
134
|
// Sync server data into local state on first load / refetch
|
|
135
135
|
useEffect(() => {
|
|
@@ -151,41 +151,12 @@ export function CapabilitiesTab({ config, agentId }: CapabilitiesTabProps) {
|
|
|
151
151
|
[localState, serverState, initialized],
|
|
152
152
|
);
|
|
153
153
|
|
|
154
|
-
// ------ Debounced save ------
|
|
155
|
-
const scheduleSave = useCallback(
|
|
156
|
-
(nextState: CapabilityState) => {
|
|
157
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
158
|
-
debounceRef.current = setTimeout(() => {
|
|
159
|
-
const payload = stateToPayload(nextState);
|
|
160
|
-
updateMutation.mutate(
|
|
161
|
-
{ agentId, payload },
|
|
162
|
-
{
|
|
163
|
-
onSuccess: () => {
|
|
164
|
-
setServerState(cloneState(nextState));
|
|
165
|
-
toast.success("Capacidades salvas");
|
|
166
|
-
},
|
|
167
|
-
onError: () => {
|
|
168
|
-
// Rollback to server state
|
|
169
|
-
setLocalState(cloneState(serverState));
|
|
170
|
-
toast.error("Erro ao salvar capacidades");
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
);
|
|
174
|
-
}, 500);
|
|
175
|
-
},
|
|
176
|
-
[agentId, updateMutation, serverState],
|
|
177
|
-
);
|
|
178
|
-
|
|
179
154
|
// ------ State mutation helpers ------
|
|
180
155
|
const updateState = useCallback(
|
|
181
156
|
(updater: (prev: CapabilityState) => CapabilityState) => {
|
|
182
|
-
setLocalState((prev) =>
|
|
183
|
-
const next = updater(prev);
|
|
184
|
-
scheduleSave(next);
|
|
185
|
-
return next;
|
|
186
|
-
});
|
|
157
|
+
setLocalState((prev) => updater(prev));
|
|
187
158
|
},
|
|
188
|
-
[
|
|
159
|
+
[],
|
|
189
160
|
);
|
|
190
161
|
|
|
191
162
|
const toggleModule = useCallback(
|
|
@@ -242,12 +213,10 @@ export function CapabilitiesTab({ config, agentId }: CapabilitiesTabProps) {
|
|
|
242
213
|
}, [updateState]);
|
|
243
214
|
|
|
244
215
|
const discard = useCallback(() => {
|
|
245
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
246
216
|
setLocalState(cloneState(serverState));
|
|
247
217
|
}, [serverState]);
|
|
248
218
|
|
|
249
219
|
const saveNow = useCallback(() => {
|
|
250
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
251
220
|
const payload = stateToPayload(localState);
|
|
252
221
|
updateMutation.mutate(
|
|
253
222
|
{ agentId, payload },
|
|
@@ -368,20 +337,15 @@ export function CapabilitiesTab({ config, agentId }: CapabilitiesTabProps) {
|
|
|
368
337
|
|
|
369
338
|
{/* Save bar */}
|
|
370
339
|
{hasChanges && (
|
|
371
|
-
<div className="sticky bottom-0
|
|
372
|
-
<
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
<div className="flex items-center gap-2">
|
|
376
|
-
<Button variant="outline" size="sm" onClick={discard}>
|
|
340
|
+
<div className="sticky bottom-0 z-10 flex items-center justify-between gap-2 rounded-lg border bg-background p-3 shadow-sm">
|
|
341
|
+
<p className="text-sm text-muted-foreground">Você tem alterações não salvas.</p>
|
|
342
|
+
<div className="flex gap-2">
|
|
343
|
+
<Button variant="ghost" size="sm" onClick={discard} disabled={updateMutation.isPending}>
|
|
377
344
|
Descartar
|
|
378
345
|
</Button>
|
|
379
|
-
<Button
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
disabled={updateMutation.isPending}
|
|
383
|
-
>
|
|
384
|
-
{updateMutation.isPending ? "Salvando..." : "Salvar"}
|
|
346
|
+
<Button size="sm" onClick={saveNow} disabled={updateMutation.isPending}>
|
|
347
|
+
{updateMutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
|
348
|
+
Salvar
|
|
385
349
|
</Button>
|
|
386
350
|
</div>
|
|
387
351
|
</div>
|