vault-go 0.6.0 → 0.8.0
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/README.md +65 -3
- package/dist/cloud.d.ts +18 -0
- package/dist/cloud.js +41 -1
- package/dist/server.js +104 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,42 @@ bun --version
|
|
|
14
14
|
|
|
15
15
|
## Instalação MCP
|
|
16
16
|
|
|
17
|
+
### Opção remota somente leitura
|
|
18
|
+
|
|
19
|
+
Para pesquisa e contexto, é possível usar diretamente o endpoint Streamable
|
|
20
|
+
HTTP da plataforma, sem instalar runtime ou banco local. Crie em **Segurança >
|
|
21
|
+
Chaves de API** uma chave apenas com `memory:read` e configure:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
export VAULT_GO_TOKEN='<chave-memory-read>'
|
|
25
|
+
codex mcp add vault-go \
|
|
26
|
+
--url https://vault.resolveup.com.br/api/mcp \
|
|
27
|
+
--bearer-token-env-var VAULT_GO_TOKEN
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Configuração genérica para clientes com transporte HTTP:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"vault-go": {
|
|
36
|
+
"type": "http",
|
|
37
|
+
"url": "https://vault.resolveup.com.br/api/mcp",
|
|
38
|
+
"headers": {
|
|
39
|
+
"Authorization": "Bearer ${VAULT_GO_TOKEN}"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
O endpoint remoto expõe somente projetos, busca, contexto, recentes, feed,
|
|
47
|
+
linha do tempo, contexto de arquivos, estatísticas, estado vetorial e consultas
|
|
48
|
+
às bases de conhecimento. Para captura automática, criação/reconstrução de
|
|
49
|
+
bases, escrita, importação ou exclusão, use o cliente Bun completo abaixo.
|
|
50
|
+
|
|
51
|
+
### Opção Bun completa
|
|
52
|
+
|
|
17
53
|
Execução direta:
|
|
18
54
|
|
|
19
55
|
```sh
|
|
@@ -51,9 +87,13 @@ possível apontar outro diretório:
|
|
|
51
87
|
}
|
|
52
88
|
```
|
|
53
89
|
|
|
54
|
-
Para ambientes efêmeros, `VAULT_GO_TOKEN` aceita um access token
|
|
55
|
-
`
|
|
56
|
-
|
|
90
|
+
Para ambientes efêmeros, `VAULT_GO_TOKEN` aceita um access token de sessão ou
|
|
91
|
+
uma chave `vg_live_...` criada na tela **Segurança > Chaves de API**. Use
|
|
92
|
+
somente os escopos necessários: `memory:read` para pesquisa/contexto,
|
|
93
|
+
`memory:write` para eventos e lembranças e `memory:delete` para exclusão.
|
|
94
|
+
`VAULT_GO_API_URL` troca o endpoint. O login normal permite renovação
|
|
95
|
+
automática; a chave de API é indicada para automações com prazo e escopo
|
|
96
|
+
limitados.
|
|
57
97
|
|
|
58
98
|
## Ferramentas MCP
|
|
59
99
|
|
|
@@ -64,6 +104,8 @@ renovação automática da sessão.
|
|
|
64
104
|
- `vault_go_event`: eventos de prompt, ferramenta e resultado.
|
|
65
105
|
- `vault_go_remember`: observações, decisões, descobertas e resumos.
|
|
66
106
|
- `vault_go_search`: busca textual com ranking e trechos.
|
|
107
|
+
- `vault_go_search_index`: índice compacto com filtros, trechos e custo estimado.
|
|
108
|
+
- `vault_go_observations`: carrega em lote somente os IDs selecionados.
|
|
67
109
|
- `vault_go_timeline`: contexto anterior e posterior a uma memória.
|
|
68
110
|
- `vault_go_context`: contexto progressivo com limite de caracteres.
|
|
69
111
|
- `vault_go_file_context`: histórico ligado aos arquivos lidos ou modificados.
|
|
@@ -72,10 +114,30 @@ renovação automática da sessão.
|
|
|
72
114
|
- `vault_go_job_retry` e `vault_go_job_cancel`: controle idempotente do processamento.
|
|
73
115
|
- `vault_go_export` e `vault_go_import`: transporte JSON tenant-scoped, atômico e idempotente.
|
|
74
116
|
- `vault_go_embedding_status` e `vault_go_embedding_backfill`: busca híbrida e fila vetorial, sem expor chaves.
|
|
117
|
+
- `vault_go_feed`: pagina memórias recentes por projeto, tipo e origem.
|
|
118
|
+
- `vault_go_knowledge_bases` e `vault_go_knowledge_base`: lista e abre bases focadas.
|
|
119
|
+
- `vault_go_knowledge_build` e `vault_go_knowledge_rebuild`: cria ou atualiza uma base a partir de filtros.
|
|
120
|
+
- `vault_go_knowledge_query`: recupera contexto fundamentado e citações dentro da base.
|
|
121
|
+
- `vault_go_knowledge_delete`: remove a base e preserva as memórias originais.
|
|
75
122
|
- `vault_go_forget`: exclusão explícita de uma memória.
|
|
76
123
|
|
|
77
124
|
O recurso `vault-go://status` fornece o resumo sanitizado em JSON.
|
|
78
125
|
|
|
126
|
+
Para reduzir o uso de contexto, prefira a recuperação em três camadas:
|
|
127
|
+
|
|
128
|
+
1. Pesquise com `vault_go_search_index`, usando projeto, origem, conceitos,
|
|
129
|
+
arquivos e intervalo de datas quando conhecidos.
|
|
130
|
+
2. Abra `vault_go_timeline` somente para os resultados que precisam de
|
|
131
|
+
contexto cronológico.
|
|
132
|
+
3. Envie os IDs escolhidos a `vault_go_observations` para carregar o conteúdo
|
|
133
|
+
completo em um único lote tenant-scoped.
|
|
134
|
+
|
|
135
|
+
As bases, filtros, vínculos e feed ficam exclusivamente no PostgreSQL da
|
|
136
|
+
plataforma. A consulta retorna evidências e `synthesisAvailable: false`; o
|
|
137
|
+
cliente MCP faz a síntese, evitando respostas inventadas e chaves ocultas no
|
|
138
|
+
servidor. A síntese do servidor só será habilitada quando um provedor semântico
|
|
139
|
+
for configurado explicitamente.
|
|
140
|
+
|
|
79
141
|
## Fluxo integrado
|
|
80
142
|
|
|
81
143
|
```text
|
package/dist/cloud.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface VaultMemoryApi {
|
|
|
8
8
|
remember(input: Record<string, unknown>): Promise<unknown>;
|
|
9
9
|
forget(id: string): Promise<unknown>;
|
|
10
10
|
search(input: Record<string, unknown>): Promise<unknown>;
|
|
11
|
+
searchIndex(input: Record<string, unknown>): Promise<unknown>;
|
|
12
|
+
observations(ids: string[]): Promise<unknown>;
|
|
11
13
|
timeline(input: Record<string, unknown>): Promise<unknown>;
|
|
12
14
|
context(input: Record<string, unknown>): Promise<unknown>;
|
|
13
15
|
fileContext(input: Record<string, unknown>): Promise<unknown>;
|
|
@@ -19,6 +21,13 @@ export interface VaultMemoryApi {
|
|
|
19
21
|
importMemories(input: Record<string, unknown>): Promise<unknown>;
|
|
20
22
|
embeddingStatus(): Promise<unknown>;
|
|
21
23
|
embeddingBackfill(): Promise<unknown>;
|
|
24
|
+
feed(input: Record<string, unknown>): Promise<unknown>;
|
|
25
|
+
knowledgeBases(): Promise<unknown>;
|
|
26
|
+
knowledgeBase(id: string): Promise<unknown>;
|
|
27
|
+
buildKnowledgeBase(input: Record<string, unknown>): Promise<unknown>;
|
|
28
|
+
rebuildKnowledgeBase(id: string): Promise<unknown>;
|
|
29
|
+
queryKnowledgeBase(id: string, input: Record<string, unknown>): Promise<unknown>;
|
|
30
|
+
deleteKnowledgeBase(id: string): Promise<unknown>;
|
|
22
31
|
}
|
|
23
32
|
export declare class VaultCloudClient implements VaultMemoryApi {
|
|
24
33
|
private readonly home;
|
|
@@ -33,6 +42,8 @@ export declare class VaultCloudClient implements VaultMemoryApi {
|
|
|
33
42
|
remember(input: Record<string, unknown>): Promise<unknown>;
|
|
34
43
|
forget(id: string): Promise<unknown>;
|
|
35
44
|
search(input: Record<string, unknown>): Promise<unknown>;
|
|
45
|
+
searchIndex(input: Record<string, unknown>): Promise<unknown>;
|
|
46
|
+
observations(ids: string[]): Promise<unknown>;
|
|
36
47
|
timeline(input: Record<string, unknown>): Promise<unknown>;
|
|
37
48
|
context(input: Record<string, unknown>): Promise<unknown>;
|
|
38
49
|
fileContext(input: Record<string, unknown>): Promise<unknown>;
|
|
@@ -44,6 +55,13 @@ export declare class VaultCloudClient implements VaultMemoryApi {
|
|
|
44
55
|
importMemories(input: Record<string, unknown>): Promise<unknown>;
|
|
45
56
|
embeddingStatus(): Promise<unknown>;
|
|
46
57
|
embeddingBackfill(): Promise<unknown>;
|
|
58
|
+
feed(input: Record<string, unknown>): Promise<unknown>;
|
|
59
|
+
knowledgeBases(): Promise<unknown>;
|
|
60
|
+
knowledgeBase(id: string): Promise<unknown>;
|
|
61
|
+
buildKnowledgeBase(input: Record<string, unknown>): Promise<unknown>;
|
|
62
|
+
rebuildKnowledgeBase(id: string): Promise<unknown>;
|
|
63
|
+
queryKnowledgeBase(id: string, input: Record<string, unknown>): Promise<unknown>;
|
|
64
|
+
deleteKnowledgeBase(id: string): Promise<unknown>;
|
|
47
65
|
private endpoint;
|
|
48
66
|
private accessToken;
|
|
49
67
|
private request;
|
package/dist/cloud.js
CHANGED
|
@@ -34,6 +34,12 @@ export class VaultCloudClient {
|
|
|
34
34
|
async search(input) {
|
|
35
35
|
return this.request('/memory/search', { method: 'POST', body: input });
|
|
36
36
|
}
|
|
37
|
+
async searchIndex(input) {
|
|
38
|
+
return this.request('/memory/search/index', { method: 'POST', body: input });
|
|
39
|
+
}
|
|
40
|
+
async observations(ids) {
|
|
41
|
+
return this.request('/memory/memories/batch', { method: 'POST', body: { ids } });
|
|
42
|
+
}
|
|
37
43
|
async timeline(input) {
|
|
38
44
|
return this.request('/memory/timeline', { method: 'POST', body: input });
|
|
39
45
|
}
|
|
@@ -78,6 +84,34 @@ export class VaultCloudClient {
|
|
|
78
84
|
async embeddingBackfill() {
|
|
79
85
|
return this.request('/memory/embeddings/backfill', { method: 'POST' });
|
|
80
86
|
}
|
|
87
|
+
async feed(input) {
|
|
88
|
+
return this.request('/memory/feed', { query: input });
|
|
89
|
+
}
|
|
90
|
+
async knowledgeBases() {
|
|
91
|
+
return this.request('/memory/knowledge-bases');
|
|
92
|
+
}
|
|
93
|
+
async knowledgeBase(id) {
|
|
94
|
+
return this.request(`/memory/knowledge-bases/${encodeURIComponent(id)}`);
|
|
95
|
+
}
|
|
96
|
+
async buildKnowledgeBase(input) {
|
|
97
|
+
return this.request('/memory/knowledge-bases', { method: 'POST', body: input });
|
|
98
|
+
}
|
|
99
|
+
async rebuildKnowledgeBase(id) {
|
|
100
|
+
return this.request(`/memory/knowledge-bases/${encodeURIComponent(id)}/rebuild`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async queryKnowledgeBase(id, input) {
|
|
105
|
+
return this.request(`/memory/knowledge-bases/${encodeURIComponent(id)}/query`, {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
body: input,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
async deleteKnowledgeBase(id) {
|
|
111
|
+
return this.request(`/memory/knowledge-bases/${encodeURIComponent(id)}`, {
|
|
112
|
+
method: 'DELETE',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
81
115
|
endpoint(path) {
|
|
82
116
|
const base = validateApiUrl(loadConfig(this.home).apiUrl);
|
|
83
117
|
const prefix = base.pathname.replace(/\/$/u, '');
|
|
@@ -128,7 +162,13 @@ export class VaultCloudClient {
|
|
|
128
162
|
};
|
|
129
163
|
if (options.body)
|
|
130
164
|
request.body = JSON.stringify(options.body);
|
|
131
|
-
const
|
|
165
|
+
const endpoint = this.endpoint(path);
|
|
166
|
+
for (const [key, value] of Object.entries(options.query ?? {})) {
|
|
167
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
168
|
+
endpoint.searchParams.set(key, String(value));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const response = await this.cloudFetch(endpoint, request);
|
|
132
172
|
if (response.status === 401 && options.authenticated !== false && !options.retried) {
|
|
133
173
|
return this.request(path, { ...options, retried: true });
|
|
134
174
|
}
|
package/dist/server.js
CHANGED
|
@@ -26,6 +26,17 @@ async function run(operation) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
const uuid = z.string().uuid();
|
|
29
|
+
const knowledgeFilters = z.object({
|
|
30
|
+
projectId: uuid.optional(),
|
|
31
|
+
kinds: z.array(z.string().trim().min(1).max(100)).max(20).default([]),
|
|
32
|
+
memoryTypes: z.array(z.string().trim().min(1).max(100)).max(20).default([]),
|
|
33
|
+
concepts: z.array(z.string().trim().min(1).max(500)).max(50).default([]),
|
|
34
|
+
files: z.array(z.string().trim().min(1).max(2_000)).max(50).default([]),
|
|
35
|
+
query: z.string().trim().max(1_000).optional(),
|
|
36
|
+
dateStartEpoch: z.number().int().positive().optional(),
|
|
37
|
+
dateEndEpoch: z.number().int().positive().optional(),
|
|
38
|
+
limit: z.number().int().min(1).max(2_000).default(200),
|
|
39
|
+
});
|
|
29
40
|
export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudClient(home)) {
|
|
30
41
|
const server = new McpServer({ name: 'vault-go', version: VERSION });
|
|
31
42
|
server.registerTool('vault_go_status', {
|
|
@@ -50,7 +61,7 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
50
61
|
title: 'Criar projeto',
|
|
51
62
|
description: 'Cria um projeto de memória no Vault.',
|
|
52
63
|
inputSchema: {
|
|
53
|
-
name: z.string().trim().min(
|
|
64
|
+
name: z.string().trim().min(3).max(80),
|
|
54
65
|
rootPath: z.string().trim().max(2_000).optional(),
|
|
55
66
|
},
|
|
56
67
|
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: true },
|
|
@@ -116,10 +127,40 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
116
127
|
projectId: uuid.optional(),
|
|
117
128
|
kind: z.string().trim().max(100).optional(),
|
|
118
129
|
memoryType: z.string().trim().max(100).optional(),
|
|
130
|
+
platformSource: z.string().trim().max(100).optional(),
|
|
131
|
+
concepts: z.array(z.string().trim().min(1).max(500)).max(50).default([]),
|
|
132
|
+
files: z.array(z.string().trim().min(1).max(2_000)).max(50).default([]),
|
|
133
|
+
dateStartEpoch: z.number().int().positive().optional(),
|
|
134
|
+
dateEndEpoch: z.number().int().positive().optional(),
|
|
119
135
|
limit: z.number().int().min(1).max(200).default(20),
|
|
120
136
|
},
|
|
121
137
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
122
138
|
}, async (input) => run(() => cloud.search(input)));
|
|
139
|
+
server.registerTool('vault_go_search_index', {
|
|
140
|
+
title: 'Pesquisar índice compacto',
|
|
141
|
+
description: 'Primeira camada de recuperação: retorna metadados, trechos e custo estimado sem carregar o conteúdo completo.',
|
|
142
|
+
inputSchema: {
|
|
143
|
+
query: z.string().trim().min(1).max(1_000),
|
|
144
|
+
projectId: uuid.optional(),
|
|
145
|
+
kind: z.string().trim().max(100).optional(),
|
|
146
|
+
memoryType: z.string().trim().max(100).optional(),
|
|
147
|
+
platformSource: z.string().trim().max(100).optional(),
|
|
148
|
+
concepts: z.array(z.string().trim().min(1).max(500)).max(50).default([]),
|
|
149
|
+
files: z.array(z.string().trim().min(1).max(2_000)).max(50).default([]),
|
|
150
|
+
dateStartEpoch: z.number().int().positive().optional(),
|
|
151
|
+
dateEndEpoch: z.number().int().positive().optional(),
|
|
152
|
+
limit: z.number().int().min(1).max(200).default(20),
|
|
153
|
+
},
|
|
154
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
155
|
+
}, async (input) => run(() => cloud.searchIndex(input)));
|
|
156
|
+
server.registerTool('vault_go_observations', {
|
|
157
|
+
title: 'Carregar observações por ID',
|
|
158
|
+
description: 'Terceira camada de recuperação: carrega em lote somente as observações escolhidas no índice ou na linha do tempo.',
|
|
159
|
+
inputSchema: {
|
|
160
|
+
ids: z.array(uuid).min(1).max(100),
|
|
161
|
+
},
|
|
162
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
163
|
+
}, async ({ ids }) => run(() => cloud.observations(ids)));
|
|
123
164
|
server.registerTool('vault_go_timeline', {
|
|
124
165
|
title: 'Abrir linha do tempo',
|
|
125
166
|
description: 'Retorna memórias anteriores e posteriores a uma memória âncora.',
|
|
@@ -158,6 +199,68 @@ export function createVaultGoServer(home = vaultHome(), cloud = new VaultCloudCl
|
|
|
158
199
|
inputSchema: {},
|
|
159
200
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
160
201
|
}, async () => run(() => cloud.stats()));
|
|
202
|
+
server.registerTool('vault_go_feed', {
|
|
203
|
+
title: 'Feed de memórias',
|
|
204
|
+
description: 'Lista memórias recentes com paginação estável por cursor.',
|
|
205
|
+
inputSchema: {
|
|
206
|
+
projectId: uuid.optional(),
|
|
207
|
+
kind: z.string().trim().max(100).optional(),
|
|
208
|
+
memoryType: z.string().trim().max(100).optional(),
|
|
209
|
+
platformSource: z.string().trim().max(100).optional(),
|
|
210
|
+
cursor: z.string().trim().max(200).optional(),
|
|
211
|
+
limit: z.number().int().min(1).max(200).default(20),
|
|
212
|
+
},
|
|
213
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
214
|
+
}, async (input) => run(() => cloud.feed(input)));
|
|
215
|
+
server.registerTool('vault_go_knowledge_bases', {
|
|
216
|
+
title: 'Listar bases de conhecimento',
|
|
217
|
+
description: 'Lista bases filtradas e persistidas na plataforma Vault.',
|
|
218
|
+
inputSchema: {},
|
|
219
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
220
|
+
}, async () => run(() => cloud.knowledgeBases()));
|
|
221
|
+
server.registerTool('vault_go_knowledge_base', {
|
|
222
|
+
title: 'Abrir base de conhecimento',
|
|
223
|
+
description: 'Retorna a configuração e as memórias vinculadas a uma base.',
|
|
224
|
+
inputSchema: { id: uuid },
|
|
225
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
226
|
+
}, async ({ id }) => run(() => cloud.knowledgeBase(id)));
|
|
227
|
+
server.registerTool('vault_go_knowledge_build', {
|
|
228
|
+
title: 'Criar base de conhecimento',
|
|
229
|
+
description: 'Cria uma base PostgreSQL a partir de filtros explícitos.',
|
|
230
|
+
inputSchema: {
|
|
231
|
+
name: z.string().trim().min(1).max(200),
|
|
232
|
+
description: z.string().trim().max(2_000).optional(),
|
|
233
|
+
filters: knowledgeFilters,
|
|
234
|
+
},
|
|
235
|
+
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: true },
|
|
236
|
+
}, async (input) => run(() => cloud.buildKnowledgeBase(input)));
|
|
237
|
+
server.registerTool('vault_go_knowledge_rebuild', {
|
|
238
|
+
title: 'Reconstruir base de conhecimento',
|
|
239
|
+
description: 'Reaplica os filtros salvos para incluir as memórias atuais.',
|
|
240
|
+
inputSchema: { id: uuid },
|
|
241
|
+
annotations: { readOnlyHint: false, idempotentHint: true, openWorldHint: true },
|
|
242
|
+
}, async ({ id }) => run(() => cloud.rebuildKnowledgeBase(id)));
|
|
243
|
+
server.registerTool('vault_go_knowledge_query', {
|
|
244
|
+
title: 'Consultar base de conhecimento',
|
|
245
|
+
description: 'Retorna contexto fundamentado e citações para síntese pelo cliente MCP.',
|
|
246
|
+
inputSchema: {
|
|
247
|
+
id: uuid,
|
|
248
|
+
question: z.string().trim().min(1).max(1_000),
|
|
249
|
+
limit: z.number().int().min(1).max(100).default(20),
|
|
250
|
+
},
|
|
251
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
252
|
+
}, async ({ id, ...input }) => run(() => cloud.queryKnowledgeBase(id, input)));
|
|
253
|
+
server.registerTool('vault_go_knowledge_delete', {
|
|
254
|
+
title: 'Excluir base de conhecimento',
|
|
255
|
+
description: 'Exclui a base e seus vínculos, preservando as memórias originais.',
|
|
256
|
+
inputSchema: { id: uuid },
|
|
257
|
+
annotations: {
|
|
258
|
+
readOnlyHint: false,
|
|
259
|
+
destructiveHint: true,
|
|
260
|
+
idempotentHint: true,
|
|
261
|
+
openWorldHint: true,
|
|
262
|
+
},
|
|
263
|
+
}, async ({ id }) => run(() => cloud.deleteKnowledgeBase(id)));
|
|
161
264
|
server.registerTool('vault_go_jobs', {
|
|
162
265
|
title: 'Fila de processamento',
|
|
163
266
|
description: 'Lista jobs da conta sem expor o conteúdo dos eventos.',
|