@greatapps/greatagents-ui 0.3.14 → 0.3.15
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 +6 -2
- package/dist/index.js +330 -221
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/agents/agent-prompt-editor.tsx +59 -22
- package/src/components/capabilities/integration-card.tsx +160 -94
- package/src/components/capabilities/integration-wizard.tsx +5 -2
- package/src/components/capabilities/integrations-tab.tsx +61 -13
- package/src/hooks/use-agent-tools.ts +1 -1
- package/src/pages/integrations-management-page.tsx +86 -156
- package/src/types/index.ts +1 -1
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useMemo, useCallback, useState } from "react";
|
|
4
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
4
5
|
import { useToolCredentials, useAgents, useTools } from "../hooks";
|
|
5
|
-
import { ToolCredentialsForm } from "../components/tools/tool-credentials-form";
|
|
6
6
|
import { IntegrationCard } from "../components/capabilities/integration-card";
|
|
7
7
|
import { IntegrationWizard } from "../components/capabilities/integration-wizard";
|
|
8
8
|
import { useIntegrationState, type IntegrationCardData } from "../hooks/use-integrations";
|
|
9
|
+
import { useDeleteToolCredential, useUpdateToolCredential } from "../hooks/use-settings";
|
|
9
10
|
import type { WizardIntegrationMeta } from "../components/capabilities/types";
|
|
10
11
|
import type { ConfigOption } from "../components/capabilities/wizard-steps/config-step";
|
|
11
|
-
import {
|
|
12
|
-
Badge,
|
|
13
|
-
Button,
|
|
14
|
-
Tabs,
|
|
15
|
-
TabsContent,
|
|
16
|
-
TabsList,
|
|
17
|
-
TabsTrigger,
|
|
18
|
-
} from "@greatapps/greatauth-ui/ui";
|
|
19
|
-
import { Plug, KeyRound, Info, Loader2 } from "lucide-react";
|
|
12
|
+
import { Plug, Loader2 } from "lucide-react";
|
|
20
13
|
import type { GagentsHookConfig } from "../hooks/types";
|
|
21
14
|
import type { Agent, Tool, ToolCredential } from "../types";
|
|
22
15
|
|
|
@@ -33,45 +26,17 @@ export interface IntegrationsManagementPageProps {
|
|
|
33
26
|
subtitle?: string;
|
|
34
27
|
}
|
|
35
28
|
|
|
36
|
-
/**
|
|
37
|
-
* Build a map of credential id -> list of agent names that use it.
|
|
38
|
-
*/
|
|
39
|
-
function useCredentialAgentSummary(
|
|
40
|
-
credentials: ToolCredential[],
|
|
41
|
-
tools: Tool[],
|
|
42
|
-
agents: Agent[],
|
|
43
|
-
) {
|
|
44
|
-
return useMemo(() => {
|
|
45
|
-
const toolIdsWithCredentials = new Set(
|
|
46
|
-
credentials.map((c) => c.id_tool).filter(Boolean),
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const linkedCount = credentials.filter(
|
|
50
|
-
(c) => c.id_tool && toolIdsWithCredentials.has(c.id_tool),
|
|
51
|
-
).length;
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
totalCredentials: credentials.length,
|
|
55
|
-
linkedToTools: linkedCount,
|
|
56
|
-
totalAgents: agents.length,
|
|
57
|
-
totalTools: tools.length,
|
|
58
|
-
};
|
|
59
|
-
}, [credentials, tools, agents]);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
29
|
export function IntegrationsManagementPage({
|
|
63
30
|
config,
|
|
64
31
|
gagentsApiUrl,
|
|
65
32
|
resolveWizardMeta,
|
|
66
33
|
loadConfigOptions,
|
|
67
34
|
onWizardComplete,
|
|
68
|
-
title = "Integrações
|
|
69
|
-
subtitle = "Gerencie
|
|
35
|
+
title = "Integrações",
|
|
36
|
+
subtitle = "Gerencie as integrações da conta.",
|
|
70
37
|
}: IntegrationsManagementPageProps) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
const { data: agentsData } = useAgents(config);
|
|
74
|
-
const { data: toolsData } = useTools(config);
|
|
38
|
+
const queryClient = useQueryClient();
|
|
39
|
+
|
|
75
40
|
// Integration cards state (account-level, agentId=null)
|
|
76
41
|
const { cards, isLoading: cardsLoading } = useIntegrationState(config, null);
|
|
77
42
|
|
|
@@ -79,17 +44,33 @@ export function IntegrationsManagementPage({
|
|
|
79
44
|
const [wizardOpen, setWizardOpen] = useState(false);
|
|
80
45
|
const [activeCard, setActiveCard] = useState<IntegrationCardData | null>(null);
|
|
81
46
|
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
const summary = useCredentialAgentSummary(credentials, tools, agents);
|
|
47
|
+
// Mutations for card actions
|
|
48
|
+
const deleteCredential = useDeleteToolCredential(config);
|
|
49
|
+
const updateCredential = useUpdateToolCredential(config);
|
|
87
50
|
|
|
88
51
|
const handleConnect = useCallback((card: IntegrationCardData) => {
|
|
89
52
|
setActiveCard(card);
|
|
90
53
|
setWizardOpen(true);
|
|
91
54
|
}, []);
|
|
92
55
|
|
|
56
|
+
const handleReconnect = useCallback((card: IntegrationCardData) => {
|
|
57
|
+
setActiveCard(card);
|
|
58
|
+
setWizardOpen(true);
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
const handleDisconnect = useCallback((card: IntegrationCardData) => {
|
|
62
|
+
if (!card.credentialId) return;
|
|
63
|
+
updateCredential.mutate({
|
|
64
|
+
id: card.credentialId,
|
|
65
|
+
body: { status: "inactive" },
|
|
66
|
+
});
|
|
67
|
+
}, [updateCredential]);
|
|
68
|
+
|
|
69
|
+
const handleDelete = useCallback((card: IntegrationCardData) => {
|
|
70
|
+
if (!card.credentialId) return;
|
|
71
|
+
deleteCredential.mutate(card.credentialId);
|
|
72
|
+
}, [deleteCredential]);
|
|
73
|
+
|
|
93
74
|
const handleWizardClose = useCallback((open: boolean) => {
|
|
94
75
|
if (!open) {
|
|
95
76
|
setActiveCard(null);
|
|
@@ -98,10 +79,15 @@ export function IntegrationsManagementPage({
|
|
|
98
79
|
}, []);
|
|
99
80
|
|
|
100
81
|
const handleWizardComplete = useCallback(() => {
|
|
82
|
+
// Invalidate queries BEFORE closing so data refreshes
|
|
83
|
+
queryClient.invalidateQueries({ queryKey: ["greatagents", "tool-credentials"] });
|
|
84
|
+
queryClient.invalidateQueries({ queryKey: ["greatagents", "tools"] });
|
|
85
|
+
queryClient.invalidateQueries({ queryKey: ["greatagents", "agent-tools"] });
|
|
86
|
+
|
|
101
87
|
setWizardOpen(false);
|
|
102
88
|
setActiveCard(null);
|
|
103
89
|
onWizardComplete?.();
|
|
104
|
-
}, [onWizardComplete]);
|
|
90
|
+
}, [onWizardComplete, queryClient]);
|
|
105
91
|
|
|
106
92
|
// Resolve wizard meta with sensible defaults
|
|
107
93
|
const wizardMeta: WizardIntegrationMeta | null = activeCard
|
|
@@ -129,120 +115,64 @@ export function IntegrationsManagementPage({
|
|
|
129
115
|
</div>
|
|
130
116
|
</div>
|
|
131
117
|
|
|
132
|
-
|
|
133
|
-
<
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
</h3>
|
|
162
|
-
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
163
|
-
{connectedCards.map((card) => (
|
|
164
|
-
<IntegrationCard
|
|
165
|
-
key={`${card.definition.slug}-cred-${card.credentialId}`}
|
|
166
|
-
card={card}
|
|
167
|
-
onConnect={handleConnect}
|
|
168
|
-
/>
|
|
169
|
-
))}
|
|
170
|
-
</div>
|
|
171
|
-
</div>
|
|
172
|
-
)}
|
|
173
|
-
|
|
174
|
-
{/* Add new / coming soon */}
|
|
175
|
-
{otherCards.length > 0 && (
|
|
176
|
-
<div>
|
|
177
|
-
{connectedCards.length > 0 && (
|
|
178
|
-
<h3 className="mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
179
|
-
Adicionar integração
|
|
180
|
-
</h3>
|
|
181
|
-
)}
|
|
182
|
-
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
183
|
-
{otherCards.map((card) => {
|
|
184
|
-
const key = card.isAddNew
|
|
185
|
-
? `${card.definition.slug}-add-new`
|
|
186
|
-
: card.definition.slug;
|
|
187
|
-
return (
|
|
188
|
-
<IntegrationCard
|
|
189
|
-
key={key}
|
|
190
|
-
card={card}
|
|
191
|
-
onConnect={handleConnect}
|
|
192
|
-
/>
|
|
193
|
-
);
|
|
194
|
-
})}
|
|
195
|
-
</div>
|
|
196
|
-
</div>
|
|
197
|
-
)}
|
|
118
|
+
{cardsLoading ? (
|
|
119
|
+
<div className="flex items-center justify-center py-16">
|
|
120
|
+
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
|
|
121
|
+
</div>
|
|
122
|
+
) : cards.length === 0 ? (
|
|
123
|
+
<div className="flex flex-col items-center justify-center gap-3 py-16 text-muted-foreground">
|
|
124
|
+
<Plug className="h-10 w-10" />
|
|
125
|
+
<p className="text-sm">Nenhuma integração disponível</p>
|
|
126
|
+
</div>
|
|
127
|
+
) : (
|
|
128
|
+
<div className="space-y-6">
|
|
129
|
+
{/* Connected accounts */}
|
|
130
|
+
{connectedCards.length > 0 && (
|
|
131
|
+
<div>
|
|
132
|
+
<h3 className="mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
133
|
+
Contas conectadas
|
|
134
|
+
</h3>
|
|
135
|
+
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
136
|
+
{connectedCards.map((card) => (
|
|
137
|
+
<IntegrationCard
|
|
138
|
+
key={`${card.definition.slug}-cred-${card.credentialId}`}
|
|
139
|
+
card={card}
|
|
140
|
+
onConnect={handleConnect}
|
|
141
|
+
onReconnect={handleReconnect}
|
|
142
|
+
onDisconnect={handleDisconnect}
|
|
143
|
+
onDelete={handleDelete}
|
|
144
|
+
/>
|
|
145
|
+
))}
|
|
146
|
+
</div>
|
|
198
147
|
</div>
|
|
199
148
|
)}
|
|
200
|
-
</TabsContent>
|
|
201
149
|
|
|
202
|
-
|
|
203
|
-
{
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
?
|
|
214
|
-
:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
: "vinculadas a ferramentas"}
|
|
224
|
-
</span>
|
|
225
|
-
<span className="text-muted-foreground">|</span>
|
|
226
|
-
<span>
|
|
227
|
-
<Badge variant="secondary" className="mr-1">
|
|
228
|
-
{summary.totalAgents}
|
|
229
|
-
</Badge>
|
|
230
|
-
{summary.totalAgents === 1
|
|
231
|
-
? "agente na conta"
|
|
232
|
-
: "agentes na conta"}
|
|
233
|
-
</span>
|
|
150
|
+
{/* Add new / coming soon */}
|
|
151
|
+
{otherCards.length > 0 && (
|
|
152
|
+
<div>
|
|
153
|
+
{connectedCards.length > 0 && (
|
|
154
|
+
<h3 className="mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
155
|
+
Adicionar integração
|
|
156
|
+
</h3>
|
|
157
|
+
)}
|
|
158
|
+
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
159
|
+
{otherCards.map((card) => {
|
|
160
|
+
const key = card.isAddNew
|
|
161
|
+
? `${card.definition.slug}-add-new`
|
|
162
|
+
: card.definition.slug;
|
|
163
|
+
return (
|
|
164
|
+
<IntegrationCard
|
|
165
|
+
key={key}
|
|
166
|
+
card={card}
|
|
167
|
+
onConnect={handleConnect}
|
|
168
|
+
/>
|
|
169
|
+
);
|
|
170
|
+
})}
|
|
234
171
|
</div>
|
|
235
172
|
</div>
|
|
236
173
|
)}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
config={config}
|
|
240
|
-
gagentsApiUrl={gagentsApiUrl}
|
|
241
|
-
credentials={credentials}
|
|
242
|
-
isLoading={credentialsLoading}
|
|
243
|
-
/>
|
|
244
|
-
</TabsContent>
|
|
245
|
-
</Tabs>
|
|
174
|
+
</div>
|
|
175
|
+
)}
|
|
246
176
|
|
|
247
177
|
{/* Integration Wizard */}
|
|
248
178
|
{activeCard && wizardMeta && (
|
package/src/types/index.ts
CHANGED
|
@@ -105,7 +105,7 @@ export interface ToolCredential {
|
|
|
105
105
|
label: string;
|
|
106
106
|
credentials_encrypted: string;
|
|
107
107
|
expires_at: string | null;
|
|
108
|
-
status: "active" | "expired";
|
|
108
|
+
status: "active" | "expired" | "inactive";
|
|
109
109
|
authorized_by_contact: number | null;
|
|
110
110
|
deleted: number;
|
|
111
111
|
datetime_add: string;
|