@greatapps/greatagents-ui 0.3.2 → 0.3.3
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 +122 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/agents/agent-edit-form.tsx +4 -1
- package/src/components/agents/agent-form-dialog.tsx +5 -1
- package/src/components/agents/agent-objectives-list.tsx +15 -6
- package/src/components/agents/agent-prompt-editor.tsx +9 -5
- package/src/components/agents/agent-tabs.tsx +4 -4
- package/src/components/agents/agent-tools-list.tsx +12 -5
- package/src/components/agents/agents-table.tsx +7 -2
- package/src/components/conversations/agent-conversations-table.tsx +13 -2
- package/src/components/conversations/conversation-view.tsx +2 -2
- package/src/components/tools/tool-credentials-form.tsx +34 -14
- package/src/components/tools/tool-form-dialog.tsx +9 -5
- package/src/components/tools/tools-table.tsx +8 -3
- package/src/pages/agent-detail-page.tsx +1 -0
package/package.json
CHANGED
|
@@ -119,6 +119,7 @@ export function AgentEditForm({ config, agent, idAccount, open, onOpenChange }:
|
|
|
119
119
|
<Label htmlFor="edit-title">Nome do Agente *</Label>
|
|
120
120
|
<Input
|
|
121
121
|
id="edit-title"
|
|
122
|
+
name="title"
|
|
122
123
|
value={form.title}
|
|
123
124
|
onChange={(e) => {
|
|
124
125
|
setForm((prev) => ({
|
|
@@ -152,6 +153,7 @@ export function AgentEditForm({ config, agent, idAccount, open, onOpenChange }:
|
|
|
152
153
|
<Label htmlFor="edit-delay">Delay de Digitação (s)</Label>
|
|
153
154
|
<Input
|
|
154
155
|
id="edit-delay"
|
|
156
|
+
name="delay"
|
|
155
157
|
type="number"
|
|
156
158
|
value={form.delayTyping}
|
|
157
159
|
onChange={(e) => updateField("delayTyping", e.target.value)}
|
|
@@ -168,6 +170,7 @@ export function AgentEditForm({ config, agent, idAccount, open, onOpenChange }:
|
|
|
168
170
|
<Label htmlFor="edit-waiting">Tempo de Espera (s)</Label>
|
|
169
171
|
<Input
|
|
170
172
|
id="edit-waiting"
|
|
173
|
+
name="waiting"
|
|
171
174
|
type="number"
|
|
172
175
|
value={form.waitingTime}
|
|
173
176
|
onChange={(e) => updateField("waitingTime", e.target.value)}
|
|
@@ -193,7 +196,7 @@ export function AgentEditForm({ config, agent, idAccount, open, onOpenChange }:
|
|
|
193
196
|
</Button>
|
|
194
197
|
<Button type="submit" disabled={updateAgent.isPending}>
|
|
195
198
|
{updateAgent.isPending && (
|
|
196
|
-
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
199
|
+
<Loader2 aria-hidden="true" className="mr-2 h-4 w-4 animate-spin" />
|
|
197
200
|
)}
|
|
198
201
|
Salvar
|
|
199
202
|
</Button>
|
|
@@ -96,6 +96,7 @@ export function AgentFormDialog({
|
|
|
96
96
|
<Label htmlFor="agent-photo">Foto (URL)</Label>
|
|
97
97
|
<Input
|
|
98
98
|
id="agent-photo"
|
|
99
|
+
name="photo"
|
|
99
100
|
value={photo}
|
|
100
101
|
onChange={(e) => setPhoto(e.target.value)}
|
|
101
102
|
placeholder="https://exemplo.com/foto.jpg"
|
|
@@ -106,6 +107,7 @@ export function AgentFormDialog({
|
|
|
106
107
|
<Label htmlFor="agent-title">Nome do Agente *</Label>
|
|
107
108
|
<Input
|
|
108
109
|
id="agent-title"
|
|
110
|
+
name="title"
|
|
109
111
|
value={title}
|
|
110
112
|
onChange={(e) => setTitle(e.target.value)}
|
|
111
113
|
placeholder="Ex: Assistente de Agendamento"
|
|
@@ -118,6 +120,7 @@ export function AgentFormDialog({
|
|
|
118
120
|
<Label htmlFor="agent-delay">Delay de Digitação (ms)</Label>
|
|
119
121
|
<Input
|
|
120
122
|
id="agent-delay"
|
|
123
|
+
name="delay"
|
|
121
124
|
type="number"
|
|
122
125
|
value={delayTyping}
|
|
123
126
|
onChange={(e) => setDelayTyping(e.target.value)}
|
|
@@ -130,6 +133,7 @@ export function AgentFormDialog({
|
|
|
130
133
|
<Label htmlFor="agent-waiting">Tempo de Espera (ms)</Label>
|
|
131
134
|
<Input
|
|
132
135
|
id="agent-waiting"
|
|
136
|
+
name="waiting"
|
|
133
137
|
type="number"
|
|
134
138
|
value={waitingTime}
|
|
135
139
|
onChange={(e) => setWaitingTime(e.target.value)}
|
|
@@ -150,7 +154,7 @@ export function AgentFormDialog({
|
|
|
150
154
|
</Button>
|
|
151
155
|
<Button type="submit" disabled={isPending || !title.trim()}>
|
|
152
156
|
{isPending ? (
|
|
153
|
-
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
157
|
+
<Loader2 aria-hidden="true" className="mr-2 h-4 w-4 animate-spin" />
|
|
154
158
|
) : null}
|
|
155
159
|
{isEditing ? "Salvar" : "Criar"}
|
|
156
160
|
</Button>
|
|
@@ -238,7 +238,7 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
238
238
|
className="flex items-center gap-3 rounded-lg border bg-card p-3"
|
|
239
239
|
>
|
|
240
240
|
<SortableItemHandle className="shrink-0 text-muted-foreground hover:text-foreground">
|
|
241
|
-
<GripVertical className="h-5 w-5" />
|
|
241
|
+
<GripVertical aria-hidden="true" className="h-5 w-5" />
|
|
242
242
|
</SortableItemHandle>
|
|
243
243
|
|
|
244
244
|
<div className="flex flex-1 flex-col gap-1 min-w-0">
|
|
@@ -260,6 +260,7 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
260
260
|
</div>
|
|
261
261
|
|
|
262
262
|
<Switch
|
|
263
|
+
aria-label="Ativar/Desativar"
|
|
263
264
|
checked={objective.active}
|
|
264
265
|
onCheckedChange={(checked) =>
|
|
265
266
|
handleToggleActive(objective, checked)
|
|
@@ -270,6 +271,7 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
270
271
|
<Button
|
|
271
272
|
variant="ghost"
|
|
272
273
|
size="icon"
|
|
274
|
+
aria-label="Editar"
|
|
273
275
|
className="shrink-0 text-muted-foreground hover:text-foreground"
|
|
274
276
|
onClick={() => openEdit(objective)}
|
|
275
277
|
>
|
|
@@ -279,6 +281,7 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
279
281
|
<Button
|
|
280
282
|
variant="ghost"
|
|
281
283
|
size="icon"
|
|
284
|
+
aria-label="Excluir"
|
|
282
285
|
className="shrink-0 text-muted-foreground hover:text-destructive"
|
|
283
286
|
onClick={() => setRemoveTarget(objective)}
|
|
284
287
|
>
|
|
@@ -292,7 +295,7 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
292
295
|
const obj = sortedObjectives.find((o) => o.id === value);
|
|
293
296
|
return (
|
|
294
297
|
<div className="flex items-center gap-3 rounded-lg border bg-card p-3 shadow-lg">
|
|
295
|
-
<GripVertical className="h-5 w-5 text-muted-foreground" />
|
|
298
|
+
<GripVertical aria-hidden="true" className="h-5 w-5 text-muted-foreground" />
|
|
296
299
|
<span className="font-medium">{obj?.title}</span>
|
|
297
300
|
</div>
|
|
298
301
|
);
|
|
@@ -311,8 +314,10 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
311
314
|
</DialogHeader>
|
|
312
315
|
<div className="space-y-4">
|
|
313
316
|
<div className="space-y-2">
|
|
314
|
-
<Label>Título *</Label>
|
|
317
|
+
<Label htmlFor="objective-title">Título *</Label>
|
|
315
318
|
<Input
|
|
319
|
+
id="objective-title"
|
|
320
|
+
name="title"
|
|
316
321
|
value={form.title}
|
|
317
322
|
onChange={(e) => {
|
|
318
323
|
const title = e.target.value;
|
|
@@ -327,8 +332,10 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
327
332
|
</div>
|
|
328
333
|
|
|
329
334
|
<div className="space-y-2">
|
|
330
|
-
<Label>Slug (identificador) *</Label>
|
|
335
|
+
<Label htmlFor="objective-slug">Slug (identificador) *</Label>
|
|
331
336
|
<Input
|
|
337
|
+
id="objective-slug"
|
|
338
|
+
name="slug"
|
|
332
339
|
value={form.slug}
|
|
333
340
|
onChange={(e) => {
|
|
334
341
|
setSlugManual(true);
|
|
@@ -343,13 +350,15 @@ export function AgentObjectivesList({ agent, config }: AgentObjectivesListProps)
|
|
|
343
350
|
</div>
|
|
344
351
|
|
|
345
352
|
<div className="space-y-2">
|
|
346
|
-
<Label>Instruções do Objetivo</Label>
|
|
353
|
+
<Label htmlFor="objective-prompt">Instruções do Objetivo</Label>
|
|
347
354
|
<Textarea
|
|
355
|
+
id="objective-prompt"
|
|
356
|
+
name="prompt"
|
|
348
357
|
value={form.prompt}
|
|
349
358
|
onChange={(e) =>
|
|
350
359
|
setForm((f) => ({ ...f, prompt: e.target.value }))
|
|
351
360
|
}
|
|
352
|
-
placeholder="
|
|
361
|
+
placeholder="Instru\u00e7\u00f5es detalhadas que o agente seguir\u00e1 quando este objetivo for ativado\u2026"
|
|
353
362
|
rows={8}
|
|
354
363
|
/>
|
|
355
364
|
<p className="text-xs text-muted-foreground">
|
|
@@ -214,24 +214,28 @@ export function AgentPromptEditor({ config, agent }: AgentPromptEditorProps) {
|
|
|
214
214
|
<div className="space-y-2">
|
|
215
215
|
<textarea
|
|
216
216
|
ref={textareaRef}
|
|
217
|
+
aria-label="Prompt do sistema"
|
|
218
|
+
name="prompt"
|
|
217
219
|
value={promptText}
|
|
218
220
|
onChange={(e) => setPromptText(e.target.value)}
|
|
219
221
|
onKeyDown={handleKeyDown}
|
|
220
|
-
placeholder="Escreva o prompt do sistema aqui
|
|
222
|
+
placeholder="Escreva o prompt do sistema aqui\u2026"
|
|
221
223
|
disabled={updateAgent.isPending}
|
|
222
224
|
className="w-full resize-none rounded-lg border bg-background p-3 font-mono text-sm leading-relaxed focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
|
|
223
225
|
style={{ minHeight: "300px" }}
|
|
224
226
|
/>
|
|
225
227
|
<div className="flex items-center gap-3 text-xs text-muted-foreground">
|
|
226
|
-
<span>{charCount.toLocaleString("pt-BR")} caracteres</span>
|
|
228
|
+
<span className="tabular-nums">{charCount.toLocaleString("pt-BR")} caracteres</span>
|
|
227
229
|
<span>·</span>
|
|
228
|
-
<span>~{tokenEstimate.toLocaleString("pt-BR")} tokens</span>
|
|
230
|
+
<span className="tabular-nums">~{tokenEstimate.toLocaleString("pt-BR")} tokens</span>
|
|
229
231
|
</div>
|
|
230
232
|
</div>
|
|
231
233
|
|
|
232
234
|
{/* Save row */}
|
|
233
235
|
<div className="flex items-center gap-3">
|
|
234
236
|
<Input
|
|
237
|
+
aria-label="Notas da alteração"
|
|
238
|
+
name="changeNotes"
|
|
235
239
|
value={changeNotes}
|
|
236
240
|
onChange={(e) => setChangeNotes(e.target.value)}
|
|
237
241
|
placeholder="O que mudou? (opcional)"
|
|
@@ -390,7 +394,7 @@ export function AgentPromptEditor({ config, agent }: AgentPromptEditorProps) {
|
|
|
390
394
|
onClick={() => setCompareVersionId(isComparing ? null : version.id)}
|
|
391
395
|
className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground"
|
|
392
396
|
>
|
|
393
|
-
<FileText className="h-3 w-3" />
|
|
397
|
+
<FileText aria-hidden="true" className="h-3 w-3" />
|
|
394
398
|
{isComparing ? "Ocultar diff" : "Comparar"}
|
|
395
399
|
</button>
|
|
396
400
|
<button
|
|
@@ -398,7 +402,7 @@ export function AgentPromptEditor({ config, agent }: AgentPromptEditorProps) {
|
|
|
398
402
|
onClick={() => handleRestore(version)}
|
|
399
403
|
className="flex items-center gap-1 text-xs text-primary hover:underline"
|
|
400
404
|
>
|
|
401
|
-
<RotateCcw className="h-3 w-3" />
|
|
405
|
+
<RotateCcw aria-hidden="true" className="h-3 w-3" />
|
|
402
406
|
Restaurar
|
|
403
407
|
</button>
|
|
404
408
|
</div>
|
|
@@ -23,19 +23,19 @@ export function AgentTabs({ agent, config, renderChatLink }: AgentTabsProps) {
|
|
|
23
23
|
<Tabs defaultValue="prompt">
|
|
24
24
|
<TabsList>
|
|
25
25
|
<TabsTrigger value="prompt" className="flex items-center gap-1.5">
|
|
26
|
-
<FileText className="h-3.5 w-3.5" />
|
|
26
|
+
<FileText aria-hidden="true" className="h-3.5 w-3.5" />
|
|
27
27
|
Prompt
|
|
28
28
|
</TabsTrigger>
|
|
29
29
|
<TabsTrigger value="objetivos" className="flex items-center gap-1.5">
|
|
30
|
-
<Target className="h-3.5 w-3.5" />
|
|
30
|
+
<Target aria-hidden="true" className="h-3.5 w-3.5" />
|
|
31
31
|
Objetivos
|
|
32
32
|
</TabsTrigger>
|
|
33
33
|
<TabsTrigger value="ferramentas" className="flex items-center gap-1.5">
|
|
34
|
-
<Wrench className="h-3.5 w-3.5" />
|
|
34
|
+
<Wrench aria-hidden="true" className="h-3.5 w-3.5" />
|
|
35
35
|
Ferramentas
|
|
36
36
|
</TabsTrigger>
|
|
37
37
|
<TabsTrigger value="conversas" className="flex items-center gap-1.5">
|
|
38
|
-
<MessageCircle className="h-3.5 w-3.5" />
|
|
38
|
+
<MessageCircle aria-hidden="true" className="h-3.5 w-3.5" />
|
|
39
39
|
Conversas
|
|
40
40
|
</TabsTrigger>
|
|
41
41
|
</TabsList>
|
|
@@ -182,7 +182,9 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
182
182
|
<PopoverContent className="w-72 p-0" align="end">
|
|
183
183
|
<div className="p-2">
|
|
184
184
|
<Input
|
|
185
|
-
placeholder="Buscar ferramenta
|
|
185
|
+
placeholder="Buscar ferramenta\u2026"
|
|
186
|
+
aria-label="Buscar ferramenta"
|
|
187
|
+
name="search"
|
|
186
188
|
value={search}
|
|
187
189
|
onChange={(e) => setSearch(e.target.value)}
|
|
188
190
|
className="h-8"
|
|
@@ -250,6 +252,7 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
250
252
|
</div>
|
|
251
253
|
|
|
252
254
|
<Switch
|
|
255
|
+
aria-label="Ativar/Desativar"
|
|
253
256
|
checked={agentTool.enabled}
|
|
254
257
|
onCheckedChange={(checked) =>
|
|
255
258
|
handleToggleEnabled(agentTool, checked)
|
|
@@ -260,6 +263,7 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
260
263
|
<Button
|
|
261
264
|
variant="ghost"
|
|
262
265
|
size="icon"
|
|
266
|
+
aria-label="Configurar"
|
|
263
267
|
className="shrink-0 text-muted-foreground hover:text-foreground"
|
|
264
268
|
onClick={() => openConfig(agentTool)}
|
|
265
269
|
title="Configurar instruções"
|
|
@@ -270,6 +274,7 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
270
274
|
<Button
|
|
271
275
|
variant="ghost"
|
|
272
276
|
size="icon"
|
|
277
|
+
aria-label="Remover"
|
|
273
278
|
className="shrink-0 text-muted-foreground hover:text-destructive"
|
|
274
279
|
onClick={() => setRemoveTarget(agentTool)}
|
|
275
280
|
>
|
|
@@ -295,12 +300,12 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
295
300
|
<div className="space-y-4">
|
|
296
301
|
{configTarget && getToolInfo(configTarget.id_tool)?.type !== "none" && (
|
|
297
302
|
<div className="space-y-2">
|
|
298
|
-
<Label>Credencial</Label>
|
|
303
|
+
<Label htmlFor="tool-credential">Credencial</Label>
|
|
299
304
|
<Select
|
|
300
305
|
value={configCredentialId || undefined}
|
|
301
306
|
onValueChange={(val) => setConfigCredentialId(val === "__none__" ? "" : val)}
|
|
302
307
|
>
|
|
303
|
-
<SelectTrigger>
|
|
308
|
+
<SelectTrigger id="tool-credential">
|
|
304
309
|
<SelectValue placeholder="Selecione uma credencial (opcional)" />
|
|
305
310
|
</SelectTrigger>
|
|
306
311
|
<SelectContent>
|
|
@@ -320,11 +325,13 @@ export function AgentToolsList({ agent, config }: AgentToolsListProps) {
|
|
|
320
325
|
</div>
|
|
321
326
|
)}
|
|
322
327
|
<div className="space-y-2">
|
|
323
|
-
<Label>Instruções Personalizadas</Label>
|
|
328
|
+
<Label htmlFor="tool-instructions">Instruções Personalizadas</Label>
|
|
324
329
|
<Textarea
|
|
330
|
+
id="tool-instructions"
|
|
331
|
+
name="instructions"
|
|
325
332
|
value={configInstructions}
|
|
326
333
|
onChange={(e) => setConfigInstructions(e.target.value)}
|
|
327
|
-
placeholder="
|
|
334
|
+
placeholder="Instru\u00e7\u00f5es sobre como e quando o agente deve usar esta ferramenta\u2026"
|
|
328
335
|
rows={6}
|
|
329
336
|
/>
|
|
330
337
|
<p className="text-xs text-muted-foreground">
|
|
@@ -78,6 +78,7 @@ function useColumns(
|
|
|
78
78
|
variant="ghost"
|
|
79
79
|
size="icon"
|
|
80
80
|
className="h-8 w-8"
|
|
81
|
+
aria-label="Editar"
|
|
81
82
|
onClick={() => onEdit(row.original)}
|
|
82
83
|
>
|
|
83
84
|
<Pencil className="h-4 w-4" />
|
|
@@ -91,6 +92,7 @@ function useColumns(
|
|
|
91
92
|
variant="ghost"
|
|
92
93
|
size="icon"
|
|
93
94
|
className="h-8 w-8 text-destructive hover:text-destructive"
|
|
95
|
+
aria-label="Excluir"
|
|
94
96
|
onClick={() => onDelete(row.original.id)}
|
|
95
97
|
>
|
|
96
98
|
<Trash2 className="h-4 w-4" />
|
|
@@ -151,9 +153,12 @@ export function AgentsTable({ config, onNavigateToAgent }: { config: GagentsHook
|
|
|
151
153
|
<>
|
|
152
154
|
<div className="flex items-center gap-3">
|
|
153
155
|
<div className="relative flex-1 max-w-md">
|
|
154
|
-
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
|
156
|
+
<Search aria-hidden="true" className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
|
155
157
|
<Input
|
|
156
|
-
placeholder="Buscar agentes
|
|
158
|
+
placeholder="Buscar agentes\u2026"
|
|
159
|
+
aria-label="Buscar agentes"
|
|
160
|
+
name="search"
|
|
161
|
+
autoComplete="off"
|
|
157
162
|
value={search}
|
|
158
163
|
onChange={(e) => handleSearchChange(e.target.value)}
|
|
159
164
|
className="pl-9"
|
|
@@ -89,11 +89,21 @@ export function AgentConversationsTable({
|
|
|
89
89
|
<TableRow
|
|
90
90
|
key={conversation.id}
|
|
91
91
|
className="cursor-pointer"
|
|
92
|
+
role="button"
|
|
93
|
+
tabIndex={0}
|
|
92
94
|
onClick={() =>
|
|
93
95
|
setSelectedId(
|
|
94
96
|
selectedId === conversation.id ? null : conversation.id,
|
|
95
97
|
)
|
|
96
98
|
}
|
|
99
|
+
onKeyDown={(e) => {
|
|
100
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
setSelectedId(
|
|
103
|
+
selectedId === conversation.id ? null : conversation.id,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}}
|
|
97
107
|
data-state={selectedId === conversation.id ? "selected" : undefined}
|
|
98
108
|
>
|
|
99
109
|
<TableCell className="font-mono text-xs">
|
|
@@ -111,10 +121,10 @@ export function AgentConversationsTable({
|
|
|
111
121
|
<span className="text-xs text-muted-foreground">—</span>
|
|
112
122
|
)}
|
|
113
123
|
</TableCell>
|
|
114
|
-
<TableCell className="text-right">
|
|
124
|
+
<TableCell className="text-right tabular-nums">
|
|
115
125
|
{conversation.message_count ?? "—"}
|
|
116
126
|
</TableCell>
|
|
117
|
-
<TableCell className="text-right">
|
|
127
|
+
<TableCell className="text-right tabular-nums">
|
|
118
128
|
{conversation.usage_tokens ?? "—"}
|
|
119
129
|
</TableCell>
|
|
120
130
|
<TableCell>
|
|
@@ -133,6 +143,7 @@ export function AgentConversationsTable({
|
|
|
133
143
|
<a
|
|
134
144
|
href={`/gchat/inbox/${conversation.id_external}`}
|
|
135
145
|
title="Ver no Chat"
|
|
146
|
+
aria-label="Ver no Chat"
|
|
136
147
|
onClick={(e) => e.stopPropagation()}
|
|
137
148
|
className="inline-flex items-center justify-center rounded-md p-1.5 text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
|
|
138
149
|
>
|
|
@@ -45,7 +45,7 @@ export function ConversationView({
|
|
|
45
45
|
<p className="text-sm text-muted-foreground">
|
|
46
46
|
Conversa não encontrada.
|
|
47
47
|
</p>
|
|
48
|
-
<Button variant="ghost" size="icon" onClick={onClose}>
|
|
48
|
+
<Button variant="ghost" size="icon" aria-label="Fechar" onClick={onClose}>
|
|
49
49
|
<X className="h-4 w-4" />
|
|
50
50
|
</Button>
|
|
51
51
|
</div>
|
|
@@ -58,7 +58,7 @@ export function ConversationView({
|
|
|
58
58
|
<div className="flex items-center justify-between">
|
|
59
59
|
<h3 className="font-semibold">Detalhes da conversa #{conversation.id}</h3>
|
|
60
60
|
<div className="flex items-center gap-1">
|
|
61
|
-
<Button variant="ghost" size="icon" onClick={onClose}>
|
|
61
|
+
<Button variant="ghost" size="icon" aria-label="Fechar" onClick={onClose}>
|
|
62
62
|
<X className="h-4 w-4" />
|
|
63
63
|
</Button>
|
|
64
64
|
</div>
|
|
@@ -130,6 +130,7 @@ function useColumns(
|
|
|
130
130
|
variant="ghost"
|
|
131
131
|
size="icon"
|
|
132
132
|
className="h-8 w-8"
|
|
133
|
+
aria-label="Vincular"
|
|
133
134
|
disabled
|
|
134
135
|
>
|
|
135
136
|
<Link className="h-4 w-4" />
|
|
@@ -144,6 +145,7 @@ function useColumns(
|
|
|
144
145
|
variant="ghost"
|
|
145
146
|
size="icon"
|
|
146
147
|
className="h-8 w-8"
|
|
148
|
+
aria-label="Editar"
|
|
147
149
|
onClick={() => onEdit(row.original)}
|
|
148
150
|
>
|
|
149
151
|
<Pencil className="h-4 w-4" />
|
|
@@ -157,6 +159,7 @@ function useColumns(
|
|
|
157
159
|
variant="ghost"
|
|
158
160
|
size="icon"
|
|
159
161
|
className="h-8 w-8 text-destructive hover:text-destructive"
|
|
162
|
+
aria-label="Excluir"
|
|
160
163
|
onClick={() => onRemove(row.original)}
|
|
161
164
|
>
|
|
162
165
|
<Trash2 className="h-4 w-4" />
|
|
@@ -328,9 +331,12 @@ export function ToolCredentialsForm({
|
|
|
328
331
|
<div className="space-y-4">
|
|
329
332
|
<div className="flex items-center gap-3">
|
|
330
333
|
<div className="relative flex-1 max-w-md">
|
|
331
|
-
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
|
334
|
+
<Search aria-hidden="true" className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
|
332
335
|
<Input
|
|
333
|
-
placeholder="Buscar credenciais
|
|
336
|
+
placeholder="Buscar credenciais\u2026"
|
|
337
|
+
aria-label="Buscar credenciais"
|
|
338
|
+
name="search"
|
|
339
|
+
autoComplete="off"
|
|
334
340
|
value={search}
|
|
335
341
|
onChange={(e) => setSearch(e.target.value)}
|
|
336
342
|
className="pl-9"
|
|
@@ -353,7 +359,7 @@ export function ToolCredentialsForm({
|
|
|
353
359
|
</DialogHeader>
|
|
354
360
|
<div className="space-y-4">
|
|
355
361
|
<div>
|
|
356
|
-
<label className="mb-1 block text-sm font-medium">
|
|
362
|
+
<label htmlFor="cred-tool" className="mb-1 block text-sm font-medium">
|
|
357
363
|
Ferramenta *
|
|
358
364
|
</label>
|
|
359
365
|
<Select
|
|
@@ -362,7 +368,7 @@ export function ToolCredentialsForm({
|
|
|
362
368
|
setCreateForm((f) => ({ ...f, id_tool: val }))
|
|
363
369
|
}
|
|
364
370
|
>
|
|
365
|
-
<SelectTrigger>
|
|
371
|
+
<SelectTrigger id="cred-tool">
|
|
366
372
|
<SelectValue placeholder="Selecione a ferramenta" />
|
|
367
373
|
</SelectTrigger>
|
|
368
374
|
<SelectContent>
|
|
@@ -375,10 +381,12 @@ export function ToolCredentialsForm({
|
|
|
375
381
|
</Select>
|
|
376
382
|
</div>
|
|
377
383
|
<div>
|
|
378
|
-
<label className="mb-1 block text-sm font-medium">
|
|
384
|
+
<label htmlFor="cred-label" className="mb-1 block text-sm font-medium">
|
|
379
385
|
Label *
|
|
380
386
|
</label>
|
|
381
387
|
<Input
|
|
388
|
+
id="cred-label"
|
|
389
|
+
name="label"
|
|
382
390
|
value={createForm.label}
|
|
383
391
|
onChange={(e) =>
|
|
384
392
|
setCreateForm((f) => ({ ...f, label: e.target.value }))
|
|
@@ -387,10 +395,13 @@ export function ToolCredentialsForm({
|
|
|
387
395
|
/>
|
|
388
396
|
</div>
|
|
389
397
|
<div>
|
|
390
|
-
<label className="mb-1 block text-sm font-medium">
|
|
398
|
+
<label htmlFor="cred-credential" className="mb-1 block text-sm font-medium">
|
|
391
399
|
Credencial *
|
|
392
400
|
</label>
|
|
393
401
|
<Input
|
|
402
|
+
id="cred-credential"
|
|
403
|
+
name="credential"
|
|
404
|
+
autoComplete="off"
|
|
394
405
|
type="password"
|
|
395
406
|
value={createForm.credentials_encrypted}
|
|
396
407
|
onChange={(e) =>
|
|
@@ -403,10 +414,12 @@ export function ToolCredentialsForm({
|
|
|
403
414
|
/>
|
|
404
415
|
</div>
|
|
405
416
|
<div>
|
|
406
|
-
<label className="mb-1 block text-sm font-medium">
|
|
417
|
+
<label htmlFor="cred-expires" className="mb-1 block text-sm font-medium">
|
|
407
418
|
Data de Expiração (opcional)
|
|
408
419
|
</label>
|
|
409
420
|
<Input
|
|
421
|
+
id="cred-expires"
|
|
422
|
+
name="expires"
|
|
410
423
|
type="date"
|
|
411
424
|
value={createForm.expires_at}
|
|
412
425
|
onChange={(e) =>
|
|
@@ -448,7 +461,7 @@ export function ToolCredentialsForm({
|
|
|
448
461
|
</DialogHeader>
|
|
449
462
|
<div className="space-y-4">
|
|
450
463
|
<div>
|
|
451
|
-
<label className="mb-1 block text-sm font-medium">
|
|
464
|
+
<label htmlFor="edit-cred-tool" className="mb-1 block text-sm font-medium">
|
|
452
465
|
Ferramenta *
|
|
453
466
|
</label>
|
|
454
467
|
<Select
|
|
@@ -457,7 +470,7 @@ export function ToolCredentialsForm({
|
|
|
457
470
|
setEditForm((f) => ({ ...f, id_tool: val }))
|
|
458
471
|
}
|
|
459
472
|
>
|
|
460
|
-
<SelectTrigger>
|
|
473
|
+
<SelectTrigger id="edit-cred-tool">
|
|
461
474
|
<SelectValue placeholder="Selecione a ferramenta" />
|
|
462
475
|
</SelectTrigger>
|
|
463
476
|
<SelectContent>
|
|
@@ -470,10 +483,12 @@ export function ToolCredentialsForm({
|
|
|
470
483
|
</Select>
|
|
471
484
|
</div>
|
|
472
485
|
<div>
|
|
473
|
-
<label className="mb-1 block text-sm font-medium">
|
|
486
|
+
<label htmlFor="edit-cred-label" className="mb-1 block text-sm font-medium">
|
|
474
487
|
Label
|
|
475
488
|
</label>
|
|
476
489
|
<Input
|
|
490
|
+
id="edit-cred-label"
|
|
491
|
+
name="label"
|
|
477
492
|
value={editForm.label}
|
|
478
493
|
onChange={(e) =>
|
|
479
494
|
setEditForm((f) => ({ ...f, label: e.target.value }))
|
|
@@ -482,10 +497,13 @@ export function ToolCredentialsForm({
|
|
|
482
497
|
/>
|
|
483
498
|
</div>
|
|
484
499
|
<div>
|
|
485
|
-
<label className="mb-1 block text-sm font-medium">
|
|
500
|
+
<label htmlFor="edit-cred-credential" className="mb-1 block text-sm font-medium">
|
|
486
501
|
Nova Credencial (vazio = manter atual)
|
|
487
502
|
</label>
|
|
488
503
|
<Input
|
|
504
|
+
id="edit-cred-credential"
|
|
505
|
+
name="credential"
|
|
506
|
+
autoComplete="off"
|
|
489
507
|
type="password"
|
|
490
508
|
value={editForm.credentials_encrypted}
|
|
491
509
|
onChange={(e) =>
|
|
@@ -498,10 +516,12 @@ export function ToolCredentialsForm({
|
|
|
498
516
|
/>
|
|
499
517
|
</div>
|
|
500
518
|
<div>
|
|
501
|
-
<label className="mb-1 block text-sm font-medium">
|
|
519
|
+
<label htmlFor="edit-cred-expires" className="mb-1 block text-sm font-medium">
|
|
502
520
|
Data de Expiração
|
|
503
521
|
</label>
|
|
504
522
|
<Input
|
|
523
|
+
id="edit-cred-expires"
|
|
524
|
+
name="expires"
|
|
505
525
|
type="date"
|
|
506
526
|
value={editForm.expires_at}
|
|
507
527
|
onChange={(e) =>
|
|
@@ -510,7 +530,7 @@ export function ToolCredentialsForm({
|
|
|
510
530
|
/>
|
|
511
531
|
</div>
|
|
512
532
|
<div>
|
|
513
|
-
<label className="mb-1 block text-sm font-medium">Status</label>
|
|
533
|
+
<label htmlFor="edit-cred-status" className="mb-1 block text-sm font-medium">Status</label>
|
|
514
534
|
<Select
|
|
515
535
|
value={editForm.status || undefined}
|
|
516
536
|
onValueChange={(val) =>
|
|
@@ -520,7 +540,7 @@ export function ToolCredentialsForm({
|
|
|
520
540
|
}))
|
|
521
541
|
}
|
|
522
542
|
>
|
|
523
|
-
<SelectTrigger>
|
|
543
|
+
<SelectTrigger id="edit-cred-status">
|
|
524
544
|
<SelectValue />
|
|
525
545
|
</SelectTrigger>
|
|
526
546
|
<SelectContent>
|
|
@@ -189,6 +189,7 @@ export function ToolFormDialog({
|
|
|
189
189
|
<Label htmlFor="tool-name">Nome *</Label>
|
|
190
190
|
<Input
|
|
191
191
|
id="tool-name"
|
|
192
|
+
name="name"
|
|
192
193
|
value={form.name}
|
|
193
194
|
onChange={(e) => {
|
|
194
195
|
const name = e.target.value;
|
|
@@ -213,6 +214,7 @@ export function ToolFormDialog({
|
|
|
213
214
|
<Label htmlFor="tool-slug">Slug (identificador único) *</Label>
|
|
214
215
|
<Input
|
|
215
216
|
id="tool-slug"
|
|
217
|
+
name="slug"
|
|
216
218
|
value={form.slug}
|
|
217
219
|
onChange={(e) => {
|
|
218
220
|
setSlugManuallyEdited(true);
|
|
@@ -269,11 +271,12 @@ export function ToolFormDialog({
|
|
|
269
271
|
<Label htmlFor="tool-description">Descrição</Label>
|
|
270
272
|
<Textarea
|
|
271
273
|
id="tool-description"
|
|
274
|
+
name="description"
|
|
272
275
|
value={form.description}
|
|
273
276
|
onChange={(e) =>
|
|
274
277
|
setForm((prev) => ({ ...prev, description: e.target.value }))
|
|
275
278
|
}
|
|
276
|
-
placeholder="
|
|
279
|
+
placeholder="Descri\u00e7\u00e3o da ferramenta\u2026"
|
|
277
280
|
rows={3}
|
|
278
281
|
disabled={isPending}
|
|
279
282
|
/>
|
|
@@ -285,6 +288,7 @@ export function ToolFormDialog({
|
|
|
285
288
|
</Label>
|
|
286
289
|
<Textarea
|
|
287
290
|
id="tool-function-defs"
|
|
291
|
+
name="functionDefs"
|
|
288
292
|
value={form.functionDefinitions}
|
|
289
293
|
onChange={(e) => {
|
|
290
294
|
setForm((prev) => ({
|
|
@@ -298,11 +302,11 @@ export function ToolFormDialog({
|
|
|
298
302
|
"type": "function",
|
|
299
303
|
"function": {
|
|
300
304
|
"name": "nome_da_funcao",
|
|
301
|
-
"description": "O que a
|
|
305
|
+
"description": "O que a fun\u00e7\u00e3o faz",
|
|
302
306
|
"parameters": {
|
|
303
307
|
"type": "object",
|
|
304
|
-
"properties": {
|
|
305
|
-
"required": [
|
|
308
|
+
"properties": { \u2026 },
|
|
309
|
+
"required": [\u2026]
|
|
306
310
|
}
|
|
307
311
|
}
|
|
308
312
|
}
|
|
@@ -330,7 +334,7 @@ export function ToolFormDialog({
|
|
|
330
334
|
</Button>
|
|
331
335
|
<Button type="submit" disabled={isPending}>
|
|
332
336
|
{isPending ? (
|
|
333
|
-
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
337
|
+
<Loader2 aria-hidden="true" className="mr-2 h-4 w-4 animate-spin" />
|
|
334
338
|
) : null}
|
|
335
339
|
{isEditing ? "Salvar" : "Criar"}
|
|
336
340
|
</Button>
|