@greatapps/greatagents-ui 0.3.6 → 0.3.8
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 +1173 -1140
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- 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/integration-wizard.tsx +53 -38
- package/src/components/capabilities/wizard-steps/credentials-step.tsx +5 -1
- package/src/components/tools/tool-credentials-form.tsx +18 -4
- package/src/components/tools/tools-table.tsx +3 -2
package/package.json
CHANGED
|
@@ -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);
|
|
@@ -218,49 +218,64 @@ export function IntegrationWizard({
|
|
|
218
218
|
// OAuth start
|
|
219
219
|
// -----------------------------------------------------------------------
|
|
220
220
|
|
|
221
|
-
function startOAuth() {
|
|
222
|
-
const { language = "pt-br", idWl = 1, accountId } = config;
|
|
223
|
-
|
|
224
|
-
// Build OAuth authorize URL -- the backend already handles the full flow
|
|
225
|
-
const redirectUri = `${window.location.origin}/oauth/callback`;
|
|
226
|
-
const url = new URL(
|
|
227
|
-
`${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${accountId}/oauth/authorize/${integration.slug}`,
|
|
228
|
-
);
|
|
229
|
-
url.searchParams.set("redirect_uri", redirectUri);
|
|
221
|
+
async function startOAuth() {
|
|
222
|
+
const { language = "pt-br", idWl = 1, accountId, token } = config;
|
|
230
223
|
|
|
231
224
|
setOauthStatus("waiting");
|
|
232
225
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
226
|
+
try {
|
|
227
|
+
// 1. Get auth URL from backend
|
|
228
|
+
const response = await fetch(
|
|
229
|
+
`${gagentsApiUrl}/v1/${language}/${idWl}/accounts/${accountId}/oauth/authorize/${integration.slug}`,
|
|
230
|
+
{ headers: { Authorization: `Bearer ${token}` } },
|
|
231
|
+
);
|
|
232
|
+
const result = await response.json();
|
|
233
|
+
|
|
234
|
+
if (result.status !== 1 || !result.data?.auth_url) {
|
|
235
|
+
setOauthStatus("error");
|
|
236
|
+
setOauthResult({
|
|
237
|
+
success: false,
|
|
238
|
+
error: result.message || "Erro ao obter URL de autorização",
|
|
239
|
+
});
|
|
240
|
+
return;
|
|
246
241
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
: prev,
|
|
261
|
-
);
|
|
242
|
+
|
|
243
|
+
// 2. Open auth URL in popup
|
|
244
|
+
const popup = window.open(
|
|
245
|
+
result.data.auth_url,
|
|
246
|
+
"oauth-popup",
|
|
247
|
+
"width=500,height=600,scrollbars=yes,resizable=yes",
|
|
248
|
+
);
|
|
249
|
+
popupRef.current = popup;
|
|
250
|
+
|
|
251
|
+
// Poll for popup closed without completing
|
|
252
|
+
if (popup) {
|
|
253
|
+
if (popupPollRef.current) {
|
|
254
|
+
clearInterval(popupPollRef.current);
|
|
262
255
|
}
|
|
263
|
-
|
|
256
|
+
popupPollRef.current = setInterval(() => {
|
|
257
|
+
if (popup.closed) {
|
|
258
|
+
if (popupPollRef.current) {
|
|
259
|
+
clearInterval(popupPollRef.current);
|
|
260
|
+
popupPollRef.current = null;
|
|
261
|
+
}
|
|
262
|
+
setOauthStatus((prev) =>
|
|
263
|
+
prev === "waiting" ? "error" : prev,
|
|
264
|
+
);
|
|
265
|
+
setOauthResult((prev) =>
|
|
266
|
+
prev === null
|
|
267
|
+
? { success: false, error: "Janela fechada antes de concluir" }
|
|
268
|
+
: prev,
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}, 500);
|
|
272
|
+
}
|
|
273
|
+
} catch (err) {
|
|
274
|
+
setOauthStatus("error");
|
|
275
|
+
setOauthResult({
|
|
276
|
+
success: false,
|
|
277
|
+
error: "Erro de rede ao obter URL de autorização",
|
|
278
|
+
});
|
|
264
279
|
}
|
|
265
280
|
}
|
|
266
281
|
|
|
@@ -77,7 +77,11 @@ function OAuthCredentials({
|
|
|
77
77
|
{/* OAuth status area */}
|
|
78
78
|
<div className="flex flex-col items-center gap-4 rounded-lg border p-6">
|
|
79
79
|
{oauthStatus === "idle" && (
|
|
80
|
-
<Button
|
|
80
|
+
<Button
|
|
81
|
+
onClick={onStartOAuth}
|
|
82
|
+
size="lg"
|
|
83
|
+
className="gap-2"
|
|
84
|
+
>
|
|
81
85
|
{meta.icon}
|
|
82
86
|
{isReconnect
|
|
83
87
|
? `Reconectar com ${providerLabel}`
|
|
@@ -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),
|