@greatapps/greatagents-ui 0.3.13 → 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 +7 -5
- package/dist/index.js +375 -628
- 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/capabilities-tab.tsx +2 -2
- package/src/components/capabilities/integration-card.tsx +160 -112
- package/src/components/capabilities/integration-wizard.tsx +5 -2
- package/src/components/capabilities/integrations-tab.tsx +62 -25
- package/src/components/tools/tool-credentials-form.tsx +1 -374
- package/src/hooks/use-agent-tools.ts +1 -1
- package/src/pages/credentials-page.tsx +0 -10
- package/src/pages/integrations-management-page.tsx +86 -167
- package/src/types/index.ts +1 -1
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
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 { Plus, 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,46 +26,16 @@ 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
|
-
useToolCredentials(config);
|
|
73
|
-
const { data: agentsData } = useAgents(config);
|
|
74
|
-
const { data: toolsData } = useTools(config);
|
|
75
|
-
const [createOpen, setCreateOpen] = useState(false);
|
|
38
|
+
const queryClient = useQueryClient();
|
|
76
39
|
|
|
77
40
|
// Integration cards state (account-level, agentId=null)
|
|
78
41
|
const { cards, isLoading: cardsLoading } = useIntegrationState(config, null);
|
|
@@ -81,17 +44,33 @@ export function IntegrationsManagementPage({
|
|
|
81
44
|
const [wizardOpen, setWizardOpen] = useState(false);
|
|
82
45
|
const [activeCard, setActiveCard] = useState<IntegrationCardData | null>(null);
|
|
83
46
|
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
const summary = useCredentialAgentSummary(credentials, tools, agents);
|
|
47
|
+
// Mutations for card actions
|
|
48
|
+
const deleteCredential = useDeleteToolCredential(config);
|
|
49
|
+
const updateCredential = useUpdateToolCredential(config);
|
|
89
50
|
|
|
90
51
|
const handleConnect = useCallback((card: IntegrationCardData) => {
|
|
91
52
|
setActiveCard(card);
|
|
92
53
|
setWizardOpen(true);
|
|
93
54
|
}, []);
|
|
94
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
|
+
|
|
95
74
|
const handleWizardClose = useCallback((open: boolean) => {
|
|
96
75
|
if (!open) {
|
|
97
76
|
setActiveCard(null);
|
|
@@ -100,10 +79,15 @@ export function IntegrationsManagementPage({
|
|
|
100
79
|
}, []);
|
|
101
80
|
|
|
102
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
|
+
|
|
103
87
|
setWizardOpen(false);
|
|
104
88
|
setActiveCard(null);
|
|
105
89
|
onWizardComplete?.();
|
|
106
|
-
}, [onWizardComplete]);
|
|
90
|
+
}, [onWizardComplete, queryClient]);
|
|
107
91
|
|
|
108
92
|
// Resolve wizard meta with sensible defaults
|
|
109
93
|
const wizardMeta: WizardIntegrationMeta | null = activeCard
|
|
@@ -131,129 +115,64 @@ export function IntegrationsManagementPage({
|
|
|
131
115
|
</div>
|
|
132
116
|
</div>
|
|
133
117
|
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
</h3>
|
|
164
|
-
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
165
|
-
{connectedCards.map((card) => (
|
|
166
|
-
<IntegrationCard
|
|
167
|
-
key={`${card.definition.slug}-cred-${card.credentialId}`}
|
|
168
|
-
card={card}
|
|
169
|
-
onConnect={handleConnect}
|
|
170
|
-
/>
|
|
171
|
-
))}
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
)}
|
|
175
|
-
|
|
176
|
-
{/* Add new / coming soon */}
|
|
177
|
-
{otherCards.length > 0 && (
|
|
178
|
-
<div>
|
|
179
|
-
{connectedCards.length > 0 && (
|
|
180
|
-
<h3 className="mb-3 text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
181
|
-
Adicionar integração
|
|
182
|
-
</h3>
|
|
183
|
-
)}
|
|
184
|
-
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
185
|
-
{otherCards.map((card) => {
|
|
186
|
-
const key = card.isAddNew
|
|
187
|
-
? `${card.definition.slug}-add-new`
|
|
188
|
-
: card.definition.slug;
|
|
189
|
-
return (
|
|
190
|
-
<IntegrationCard
|
|
191
|
-
key={key}
|
|
192
|
-
card={card}
|
|
193
|
-
onConnect={handleConnect}
|
|
194
|
-
/>
|
|
195
|
-
);
|
|
196
|
-
})}
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
)}
|
|
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>
|
|
200
147
|
</div>
|
|
201
148
|
)}
|
|
202
|
-
</TabsContent>
|
|
203
149
|
|
|
204
|
-
|
|
205
|
-
{
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
?
|
|
216
|
-
:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
: "vinculadas a ferramentas"}
|
|
226
|
-
</span>
|
|
227
|
-
<span className="text-muted-foreground">|</span>
|
|
228
|
-
<span>
|
|
229
|
-
<Badge variant="secondary" className="mr-1">
|
|
230
|
-
{summary.totalAgents}
|
|
231
|
-
</Badge>
|
|
232
|
-
{summary.totalAgents === 1
|
|
233
|
-
? "agente na conta"
|
|
234
|
-
: "agentes na conta"}
|
|
235
|
-
</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
|
+
})}
|
|
236
171
|
</div>
|
|
237
172
|
</div>
|
|
238
173
|
)}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
<Button onClick={() => setCreateOpen(true)} size="sm">
|
|
242
|
-
<Plus className="mr-2 h-4 w-4" />
|
|
243
|
-
Nova Credencial
|
|
244
|
-
</Button>
|
|
245
|
-
</div>
|
|
246
|
-
|
|
247
|
-
<ToolCredentialsForm
|
|
248
|
-
config={config}
|
|
249
|
-
gagentsApiUrl={gagentsApiUrl}
|
|
250
|
-
credentials={credentials}
|
|
251
|
-
isLoading={credentialsLoading}
|
|
252
|
-
createOpen={createOpen}
|
|
253
|
-
onCreateOpenChange={setCreateOpen}
|
|
254
|
-
/>
|
|
255
|
-
</TabsContent>
|
|
256
|
-
</Tabs>
|
|
174
|
+
</div>
|
|
175
|
+
)}
|
|
257
176
|
|
|
258
177
|
{/* Integration Wizard */}
|
|
259
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;
|