@engramind/client 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,1687 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, CSSProperties } from 'react';
3
+ import { LucideIcon } from 'lucide-react';
4
+ import { z } from 'zod';
5
+ import * as _tanstack_react_query from '@tanstack/react-query';
6
+ import { QueryKey } from '@tanstack/react-query';
7
+ import { BackgroundVariant } from '@xyflow/react';
8
+
9
+ declare class EngramindError extends Error {
10
+ readonly status: number;
11
+ readonly code: string;
12
+ readonly details?: unknown;
13
+ /** Segundos de `Retry-After` (429). */
14
+ readonly retryAfter: number | null;
15
+ constructor(status: number, message: string, code: string, details?: unknown, retryAfter?: number | null);
16
+ }
17
+
18
+ type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
19
+ type Params$1 = Record<string, string | number | boolean | undefined | null>;
20
+ /**
21
+ * Fonte de dados dos componentes: o caminho é o mesmo do REST do Engramind sem o `/v1`
22
+ * (`channels`, `memories/m_1/pin`). O navegador nunca chama o Engramind direto: a fonte padrão
23
+ * (`createHttpDataSource`) chama o proxy montado pelo app.
24
+ */
25
+ interface EngramindDataSource {
26
+ request<T>(method: HttpMethod, path: string, options?: {
27
+ params?: Params$1;
28
+ body?: unknown;
29
+ signal?: AbortSignal;
30
+ }): Promise<T>;
31
+ }
32
+ interface HttpDataSourceOptions {
33
+ /** Prefixo das rotas do proxy no app (ex.: `/api/engramind`). */
34
+ basePath: string;
35
+ /** Desembrulha a resposta (padrão: `{ success, data }` → `data`; outro JSON passa como está). */
36
+ unwrap?: (json: unknown) => unknown;
37
+ headers?: Record<string, string> | (() => Record<string, string>);
38
+ fetch?: typeof fetch;
39
+ credentials?: RequestCredentials;
40
+ }
41
+ /** Erro de uma resposta do proxy: `{ success: false, error, code, details }` ou `{ error: { code, message } }`. */
42
+ declare function errorFromResponse(status: number, json: unknown, retryAfter?: string | null): EngramindError;
43
+ declare function createHttpDataSource(options: HttpDataSourceOptions): EngramindDataSource;
44
+ /** Código estável de um erro (`ENGRAMIND_CHANNEL_SHARED`...). */
45
+ declare function apiErrorCode(error: unknown): string | undefined;
46
+ /** Mensagem pt-BR de um erro, com um texto padrão. */
47
+ declare function apiErrorMessage(error: unknown, fallback?: string): string;
48
+ /** Status HTTP de um erro. */
49
+ declare const apiErrorStatus: (error: unknown) => number | undefined;
50
+
51
+ /** Título e dica de um canal quando a ponta do slug não é legível (ex.: id da central). */
52
+ interface ChannelLabel {
53
+ /** Texto destacado no lugar da ponta final do slug (ex.: a sigla `OPE`). */
54
+ title: string;
55
+ /** Dica ao passar o mouse no título (ex.: o nome do repositório). */
56
+ hint: string;
57
+ }
58
+ /** Partes exibidas do nome de um canal: prefixo discreto, título e a dica (quando houver rótulo). */
59
+ declare function channelNameParts(slug: string, labels?: ReadonlyMap<string, ChannelLabel>): {
60
+ prefix: string;
61
+ title: string;
62
+ hint: string | null;
63
+ };
64
+ /**
65
+ * Slug do canal para exibir numa linha (chips, legendas, trilha, opções de filtro): canal de central com
66
+ * a ponta trocada pela sigla (`agentes/desenvolvedor/central/OPE`); sem rótulo, o slug como está.
67
+ * Helper único (OPE-113): todo lugar que mostra um canal usa este.
68
+ */
69
+ declare function channelDisplayName(slug: string, labels?: ReadonlyMap<string, ChannelLabel>): string;
70
+ /** Dica do canal exibido: nome do repositório e o slug inteiro (quando há rótulo); senão o slug. */
71
+ declare function channelDisplayHint(slug: string, labels?: ReadonlyMap<string, ChannelLabel>): string;
72
+
73
+ /** Evento ao vivo entregue pelo SSE da lib (`event: engramind`). */
74
+ interface LiveEvent {
75
+ /** `id` do webhook (ausente nos eventos gerados pelo próprio app). */
76
+ id?: string;
77
+ type: string;
78
+ channel?: string | null;
79
+ memoryIds?: string[];
80
+ keys?: string[];
81
+ agent?: string | null;
82
+ app?: string | null;
83
+ consumption?: string;
84
+ operation?: string;
85
+ titleIds?: string[];
86
+ contextVersion?: string;
87
+ at?: string;
88
+ }
89
+ /**
90
+ * Consumo agrupado (um por `consumption`): o formato que a rede anima. `channels` são os canais que
91
+ * entregaram memórias (um evento por canal), `delivered` idem.
92
+ */
93
+ interface ConsumptionEvent {
94
+ /** Agente que leu (`app/agente`). */
95
+ agent: string;
96
+ kind: "context" | "search";
97
+ channels: string[];
98
+ delivered: string[];
99
+ memoryIds: string[];
100
+ titleIds?: string[];
101
+ version?: string;
102
+ /** Id do consumo no Engramind (`cns_…`). */
103
+ consumption?: string;
104
+ operation?: string;
105
+ }
106
+
107
+ /** Tipos da rede "universo de partículas" do Engramind (OPE-109), independentes da origem dos dados. */
108
+ type MemoryStatus = "active" | "permanent" | "archived";
109
+ interface NetworkMemory {
110
+ id: string;
111
+ channel: string;
112
+ title: string;
113
+ text: string;
114
+ category: string;
115
+ status: MemoryStatus;
116
+ version: number;
117
+ createdAt: string;
118
+ updatedAt: string;
119
+ /** `retrieval_count` do Engramind (buscas). */
120
+ retrievals: number;
121
+ /** `injected_count` do Engramind (entradas no contexto). */
122
+ injections: number;
123
+ lastRetrievedAt: string | null;
124
+ verifiedAt: string | null;
125
+ /** `stale_candidate`: candidata a esquecimento pelo consolidador. */
126
+ stale: boolean;
127
+ author: string | null;
128
+ /** Agente autor (`app/agente`, `author.agent` do Engramind); `null` = gravada sem agente (dono, Mentor, app). */
129
+ authorAgent?: string | null;
130
+ /** Memória escrita pelo dono (listas dos agentes em `/integracoes/ia`). */
131
+ fromOwner?: boolean;
132
+ /** Quem gravou, quando não foi o dono (Mentor, agente): o selo de origem da antiga lista. */
133
+ originLabel?: string;
134
+ }
135
+ interface NetworkAgent {
136
+ /** `app/agente`. */
137
+ id: string;
138
+ app: string;
139
+ /** Nome sem o prefixo "Agente". */
140
+ name: string;
141
+ }
142
+ interface NetworkChannel {
143
+ slug: string;
144
+ name: string;
145
+ archived: boolean;
146
+ }
147
+ type SubscriptionMode = "inject" | "search" | "manage";
148
+ interface NetworkLink {
149
+ id: string;
150
+ agent: string;
151
+ channel: string;
152
+ mode: SubscriptionMode;
153
+ }
154
+
155
+ type UniverseRef = {
156
+ kind: "channel";
157
+ slug: string;
158
+ } | {
159
+ kind: "agent";
160
+ id: string;
161
+ };
162
+
163
+ declare const PARTICLE_MIN_PX = 10;
164
+ declare const PARTICLE_MAX_PX = 34;
165
+ /** Fixada nunca some: brilho mínimo visível. */
166
+ declare const PINNED_MIN_BRIGHTNESS = 0.25;
167
+ /** Padrão do Engramind para `consolidation.stale_after_days` (quando a configuração não vem). */
168
+ declare const DEFAULT_STALE_AFTER_DAYS = 90;
169
+ /** "Agente Opex" → "Opex" (os nodes mostram o nome sem o prefixo). */
170
+ declare function agentDisplayName(name: string): string;
171
+ /** Relevância: consultas + injeções somadas. */
172
+ declare const memoryUses: (memory: Pick<NetworkMemory, "retrievals" | "injections">) => number;
173
+ /**
174
+ * Último uso: o maior entre a última recuperação no Engramind (`last_retrieved_at`) e a criação. A verificação
175
+ * do consolidador (`verified_at`) não é consumo e não conta.
176
+ */
177
+ declare function lastUseOf(memory: Pick<NetworkMemory, "id" | "lastRetrievedAt" | "createdAt">): string;
178
+ /** Data de uso real (sem cair na criação): `null` = "nunca usada". */
179
+ declare function lastRealUseOf(memory: Pick<NetworkMemory, "id" | "lastRetrievedAt">): string | null;
180
+ /** Tamanho pela soma de consultas e injeções, em escala logarítmica suave relativa ao universo. */
181
+ declare function particleSize(uses: number, maxUses: number): number;
182
+ /**
183
+ * Brilho de 1 (usada agora) a 0 (cinza), linear até o prazo `stale_after_days` do consolidador.
184
+ * Candidata a esquecimento → 0; inativa → 0; fixada nunca fica abaixo do mínimo visível.
185
+ */
186
+ declare function particleBrightness(input: {
187
+ status: MemoryStatus;
188
+ stale: boolean;
189
+ lastUse: string;
190
+ }, staleAfterDays: number, now?: number): number;
191
+ /** Cor final da partícula: a cor do canal apagada em direção ao cinza conforme perde brilho. */
192
+ declare function particleColor(base: string, brightness: number): string;
193
+ /** Cor do canal com mais memórias do universo (e de todo universo de um canal só). */
194
+ declare const PRIMARY_CHANNEL_COLOR = "var(--color-primary)";
195
+ declare function stableHash(text: string): number;
196
+ /**
197
+ * Token `--chart-N` do tema. O shadcn/ui traz `--chart-1..5`: o `--chart-6` cai numa variação do
198
+ * `--chart-3` quando o app não o define (sem cor fixa).
199
+ */
200
+ declare const chartToken: (index: number) => string;
201
+ /**
202
+ * Cor de cada canal: a cor base (`--chart-2..6`) vem só do slug (o mesmo canal tem sempre a mesma
203
+ * cor). Quando mais de um canal cai na mesma base, os seguintes (em ordem de slug) ganham variações de
204
+ * tom da mesma cor.
205
+ */
206
+ declare function channelColors(slugs: readonly string[]): Map<string, string>;
207
+ /** Só as cores dos canais de um universo, a partir do mapa de TODOS os canais (a cor não muda entre universos). */
208
+ declare function pickChannelColors(all: ReadonlyMap<string, string>, slugs: readonly string[]): Map<string, string>;
209
+ /**
210
+ * Cores de um universo: cada canal com a sua cor estável (do mapa `base` ou do slug) e o canal com mais
211
+ * memórias (todas, inclusive inativas; empate pelo slug, a ordem da legenda "Por canal") com o roxo
212
+ * primário. Canais do mapa sem memórias entram com a cor estável. Sem memórias, nenhum fica roxo.
213
+ */
214
+ declare function universeChannelColors(base: ReadonlyMap<string, string> | undefined, memories: readonly Pick<NetworkMemory, "channel">[]): Map<string, string>;
215
+ /**
216
+ * Nome do canal em duas partes: o prefixo até a última `/` (linha discreta) e a ponta final (o
217
+ * título destacado). Canais com o mesmo começo (`agentes/desenvolvedor/…`) passam a se distinguir.
218
+ */
219
+ declare function splitChannelSlug(slug: string): {
220
+ prefix: string;
221
+ leaf: string;
222
+ };
223
+ /** O alvo da assinatura (exato ou prefixo `eng/projeto-*`) alcança o canal? */
224
+ declare function subscriptionReaches(target: string, isPrefix: boolean, slug: string): boolean;
225
+ interface SubscriptionInput {
226
+ id: string;
227
+ agent: string;
228
+ target: string;
229
+ isPrefix: boolean;
230
+ mode: SubscriptionMode;
231
+ /** Canais ativos que o alvo alcança (`reaches` do Engramind). */
232
+ reaches: readonly string[];
233
+ }
234
+ /**
235
+ * Um link por canal casado em cada assinatura: os ativos pelo `reaches` do Engramind e, com
236
+ * "Mostrar arquivados", os arquivados casados localmente. Só canais visíveis; prefixo sem canal não gera link.
237
+ */
238
+ declare function subscriptionLinks(subscriptions: readonly SubscriptionInput[], channels: readonly NetworkChannel[], includeArchived: boolean): NetworkLink[];
239
+ interface Point {
240
+ x: number;
241
+ y: number;
242
+ }
243
+ interface Rect {
244
+ x: number;
245
+ y: number;
246
+ width: number;
247
+ height: number;
248
+ }
249
+ /** Zoom mínimo do enquadramento inicial no celular: os nomes continuam legíveis. */
250
+ declare const MOBILE_FIT_MIN_ZOOM = 0.5;
251
+ /**
252
+ * Enquadramento com zoom mínimo (celular): se caber o retângulo inteiro com zoom ≥ `minZoom`, devolve
253
+ * `null` (enquadra normalmente); senão, centraliza no meio do retângulo com `minZoom` (o resto fica a
254
+ * um arrastar). Sem tamanho medido do quadro, `null`.
255
+ */
256
+ declare function minZoomCenter(bounds: Rect, size: {
257
+ width: number;
258
+ height: number;
259
+ }, minZoom: number): {
260
+ x: number;
261
+ y: number;
262
+ zoom: number;
263
+ } | null;
264
+ /**
265
+ * Tamanho visível do card da memória: o natural (largura fixa, altura do conteúdo) limitado ao quadro
266
+ * menos `margin` de cada lado. Sem quadro medido, o natural.
267
+ */
268
+ declare function memoryCardSize(natural: {
269
+ width: number;
270
+ height: number;
271
+ }, canvas: {
272
+ width: number;
273
+ height: number;
274
+ }, margin?: number): {
275
+ width: number;
276
+ height: number;
277
+ };
278
+ /**
279
+ * Posição (canto superior esquerdo, em px da tela) do card que substitui a partícula: centralizado
280
+ * sobre ela e empurrado para dentro do canvas, com `margin` de folga em todas as bordas.
281
+ */
282
+ declare function clampCardRect(anchor: Point, card: {
283
+ width: number;
284
+ height: number;
285
+ }, canvas: {
286
+ width: number;
287
+ height: number;
288
+ }, margin?: number): Point;
289
+ declare const UNIVERSE_FIRST_RADIUS = 150;
290
+ declare const UNIVERSE_RING_GAP = 58;
291
+ declare const UNIVERSE_SLOT = 46;
292
+ /**
293
+ * Universo: órbitas concêntricas em volta do centro (0,0) pela idade (criação): as mais novas nas
294
+ * órbitas internas, as mais antigas (e as de data inválida) nas externas.
295
+ */
296
+ declare function layoutUniverse(memories: readonly Pick<NetworkMemory, "id" | "createdAt">[]): Map<string, Point>;
297
+ /** Vagas de um anel (≈ `UNIVERSE_SLOT` px entre vizinhas). */
298
+ declare const universeRingCapacity: (ring: number) => number;
299
+ /**
300
+ * Quantas memórias em cada anel: o número de anéis é o mínimo que comporta todas, e elas são
301
+ * distribuídas proporcionalmente às vagas de cada anel (maior resto), para o último anel não ficar
302
+ * quase vazio (50 memórias: ~12/17/21 em vez de 20/28/2).
303
+ */
304
+ declare function universeRingCounts(total: number): number[];
305
+ /** Deslocamento do hover: as demais partículas se afastam levemente da focada. */
306
+ declare function repelOffset(from: Point, focus: Point, strength?: number, radius?: number): Point;
307
+ /** Link partícula ↔ centro destacado: só no universo do agente, quando ele escreveu a memória. */
308
+ declare function isAuthoredByCenter(memory: Pick<NetworkMemory, "authorAgent">, center: {
309
+ kind: "channel" | "agent";
310
+ id: string;
311
+ }): boolean;
312
+ /** Janela em que uma memória nova conta como "acabou de ser criada" (partícula de criação). */
313
+ declare const AGENT_WRITE_WINDOW_MS: number;
314
+ interface AgentWrite {
315
+ id: string;
316
+ agent: string;
317
+ channel: string;
318
+ }
319
+ /**
320
+ * Criações por agente entre os ids que acabaram de aparecer: só memórias com agente autor
321
+ * (`authorAgent`) criadas há pouco. Ids que só apareceram agora por outro motivo (Mostrar arquivados,
322
+ * filtro de app, memória movida) não contam.
323
+ */
324
+ declare function agentWritesOf(fresh: readonly string[], memories: readonly Pick<NetworkMemory, "id" | "authorAgent" | "channel" | "createdAt">[], now?: number): AgentWrite[];
325
+ /** Pesos da fusão da busca do Engramind (`search.vector_weight`, `search.text_weight`, `search.rrf_k`). */
326
+ interface SearchFusion {
327
+ vectorWeight: number;
328
+ textWeight: number;
329
+ k: number;
330
+ }
331
+ declare const DEFAULT_SEARCH_FUSION: SearchFusion;
332
+ /** Acertos de um ramo sozinho que ainda destacam: as primeiras posições (as mais próximas pelo sentido). */
333
+ declare const SEARCH_SINGLE_BRANCH_TOP = 3;
334
+ /**
335
+ * Ids que a busca destaca. O ramo vetorial do Engramind não tem limiar: devolve as memórias mais
336
+ * próximas até o `limit`, mesmo sem relação com o termo, e com poucas memórias elas são todas. No modo
337
+ * `hybrid`, destacam as que os dois ramos encontraram (sentido e texto) e as que um ramo sozinho pôs
338
+ * nas `SEARCH_SINGLE_BRANCH_TOP` primeiras posições: score ≥ `max(peso) / (k + top)`. Como o acerto dos
339
+ * dois ramos vale no mínimo `(pesoV + pesoT) / (k + limit)`, ele sempre passa. No modo `text`, todas.
340
+ */
341
+ declare function relevantSearchIds(results: readonly {
342
+ score: number;
343
+ memory: {
344
+ id: string;
345
+ };
346
+ }[], mode: "hybrid" | "text", fusion?: SearchFusion): string[];
347
+ interface UniverseStats {
348
+ active: number;
349
+ inactive: number;
350
+ pinned: number;
351
+ uses: number;
352
+ lastUse: string | null;
353
+ forgotten: number;
354
+ byChannel: {
355
+ slug: string;
356
+ count: number;
357
+ }[];
358
+ }
359
+ /** Números do card de estatísticas de um universo (canal ou agente). */
360
+ declare function universeStats(memories: readonly NetworkMemory[], brightness: ReadonlyMap<string, number>): UniverseStats;
361
+ /** Alcance de cada agente: memórias somadas dos canais ligados a ele. */
362
+ declare function agentReach(links: readonly NetworkLink[], countByChannel: ReadonlyMap<string, number>): Map<string, number>;
363
+
364
+ /**
365
+ * Layout da visão inicial da rede do Engramind (OPE-113, puro). Duas distribuições, escolhidas na
366
+ * legenda do diagrama:
367
+ * - `by-agent` ("Canais junto dos agentes", padrão): o canal de um agente só orbita esse agente; o
368
+ * canal compartilhado fica entre os agentes que o usam (no centroide deles);
369
+ * - `agents-center` ("Agentes no centro"): agentes num círculo no meio e canais em anéis em volta, cada
370
+ * canal no ângulo médio dos agentes que o usam.
371
+ * Os cards (os mesmos de sempre) crescem com as memórias (`overviewScale`) e nunca se sobrepõem: um
372
+ * afastamento determinístico separa o que encostar, e o círculo cresce enquanto sobrar sobreposição.
373
+ * Os links são curvas suaves de centro a centro: minimizam cruzamentos, sem garantia absoluta.
374
+ */
375
+ type OverviewLayoutMode = "by-agent" | "agents-center";
376
+ declare const OVERVIEW_LAYOUT_MODES: readonly ["by-agent", "agents-center"];
377
+ declare const DEFAULT_OVERVIEW_LAYOUT: OverviewLayoutMode;
378
+ declare const OVERVIEW_LAYOUT_LABEL: Record<OverviewLayoutMode, string>;
379
+ /** Caixa dos cards em escala 1 (pílula do agente até 180 px; card do canal até 288 px, `max-w-72`). */
380
+ declare const OVERVIEW_AGENT_BOX: {
381
+ width: number;
382
+ height: number;
383
+ };
384
+ declare const OVERVIEW_CHANNEL_BOX: {
385
+ width: number;
386
+ height: number;
387
+ };
388
+ /** Faixa de escala dos cards pela quantidade de memórias (log). */
389
+ declare const OVERVIEW_SCALE_MIN = 0.85;
390
+ declare const OVERVIEW_SCALE_MAX = 1.6;
391
+ /** Folga mínima entre dois cards. */
392
+ declare const OVERVIEW_PADDING = 16;
393
+ /** Folga do enquadramento inicial em cada lado (fração do tamanho). */
394
+ declare const OVERVIEW_FIT_MARGIN = 0.1;
395
+ /** Curvatura dos links (fração do comprimento, para o lado). */
396
+ declare const OVERVIEW_LINK_BEND = 0.12;
397
+ interface OverviewLayoutInput {
398
+ agents: readonly {
399
+ id: string;
400
+ app: string;
401
+ }[];
402
+ channels: readonly {
403
+ slug: string;
404
+ }[];
405
+ /** Assinaturas visíveis (agente → canal). */
406
+ links: readonly {
407
+ agent: string;
408
+ channel: string;
409
+ }[];
410
+ /** Memórias por agente (alcance) e por canal: o tamanho dos cards. */
411
+ agentCounts?: ReadonlyMap<string, number>;
412
+ channelCounts?: ReadonlyMap<string, number>;
413
+ mode?: OverviewLayoutMode;
414
+ }
415
+ interface OverviewLayout {
416
+ agents: Map<string, Point>;
417
+ channels: Map<string, Point>;
418
+ /** Escala de cada card (`agent:<id>` / `channel:<slug>`). */
419
+ scales: Map<string, number>;
420
+ /** Caixa de cada card já escalada. */
421
+ boxes: Map<string, {
422
+ width: number;
423
+ height: number;
424
+ }>;
425
+ mode: OverviewLayoutMode;
426
+ }
427
+ /** Escala do card pela quantidade de memórias, em log entre `OVERVIEW_SCALE_MIN` e `OVERVIEW_SCALE_MAX`. */
428
+ declare function overviewScale(count: number, max: number): number;
429
+ /** Distribui agentes e canais (ver o topo do arquivo). Mesmo resultado para a mesma entrada. */
430
+ declare function layoutOverview(input: OverviewLayoutInput): OverviewLayout;
431
+ /** Menor distância entre os centros de duas caixas, na direção `angle`, para não se tocarem (com a folga). */
432
+ declare function clearDistance(a: {
433
+ width: number;
434
+ height: number;
435
+ }, b: {
436
+ width: number;
437
+ height: number;
438
+ }, angle: number): number;
439
+ /** Link agente → canal: curva quadrática suave de centro a centro. */
440
+ declare function overviewLinkPath(source: Point, target: Point, bend?: number): string;
441
+ /** Meio da curva do link (rótulo do modo). */
442
+ declare function overviewLinkMidpoint(source: Point, target: Point, bend?: number): Point;
443
+ /** Enquadramento inicial: a caixa de todos os cards escalados, com `OVERVIEW_FIT_MARGIN` de folga. */
444
+ declare function overviewInitialBounds(layout: Pick<OverviewLayout, "agents" | "channels" | "boxes">): Rect | null;
445
+
446
+ /**
447
+ * Textos da lib (pt-BR). O app sobrescreve qualquer chave pelo `messages` do `EngramindProvider`; chave
448
+ * ausente usa o texto padrão. `{nome}` é trocado pelo valor correspondente.
449
+ */
450
+ declare const DEFAULT_MESSAGES: {
451
+ readonly "network.channelNotFound": "Canal não encontrado: voltando à rede.";
452
+ readonly "network.agentNotFound": "Agente não encontrado: voltando à rede.";
453
+ readonly "network.appNotFound": "App não encontrado: voltando à rede.";
454
+ readonly "network.searchFailed": "Não foi possível buscar as memórias.";
455
+ readonly "network.backToNetwork": "Voltar à rede";
456
+ readonly "network.noApps.title": "Nenhum app no Engramind";
457
+ readonly "network.noApps.description": "Crie um app e os agentes dele para ver a rede.";
458
+ readonly "network.noAgents.title": "Este app não tem agentes ativos";
459
+ readonly "network.noAgents.description": "Crie ou ative um agente deste app na configuração do Engramind.";
460
+ readonly "network.noLinkedChannels.title": "Os agentes deste app não assinam nenhum canal com memórias";
461
+ readonly "network.noLinkedChannels.description": "Canais sem memórias ficam fora da rede. Assine um canal ou grave uma memória num canal assinado.";
462
+ readonly "network.configure": "Configurar";
463
+ readonly "network.layout": "Distribuição da rede";
464
+ readonly "network.newMemory": "Nova memória";
465
+ readonly "network.agentEmpty": "Nenhuma memória nos canais deste agente";
466
+ readonly "network.agentNoChannels": "Este agente não assina nenhum canal";
467
+ readonly "state.configure.title": "Reconfigure o Engramind";
468
+ readonly "state.configure.description": "O Engramind recusou o token do app. Peça um novo token ao gestor e reconfigure o servidor do app.";
469
+ readonly "state.noAccess.title": "Sem acesso";
470
+ readonly "state.noAccess.description": "O token do app não alcança este registro.";
471
+ readonly "state.retry": "Tentar novamente";
472
+ readonly "config.agents.title": "Agentes";
473
+ readonly "config.channels.title": "Canais";
474
+ readonly "config.tokens.title": "Tokens de agente";
475
+ readonly "config.webhook.title": "Webhook do app";
476
+ readonly "config.empty.agents": "Nenhum agente neste app.";
477
+ readonly "config.newAgent": "Novo agente";
478
+ readonly "config.newChannel": "Novo canal";
479
+ readonly "config.webhook.url": "URL do webhook";
480
+ readonly "config.webhook.save": "Salvar webhook";
481
+ readonly "config.webhook.remove": "Remover webhook";
482
+ readonly "config.webhook.rotate": "Gerar novo segredo";
483
+ readonly "config.webhook.saved": "Webhook do app atualizado.";
484
+ readonly "config.webhook.secretOnce": "Copie o segredo agora: ele não aparece de novo. Configure-o no servidor do app para validar a assinatura.";
485
+ readonly "config.webhook.configured": "Segredo configurado";
486
+ readonly "config.webhook.notConfigured": "Sem webhook: a rede atualiza só pelas próprias ações e ao reconsultar.";
487
+ };
488
+ type MessageKey = keyof typeof DEFAULT_MESSAGES;
489
+ type Messages = Record<MessageKey, string>;
490
+ type PartialMessages = Partial<Messages>;
491
+ declare function mergeMessages(overrides?: PartialMessages): Messages;
492
+
493
+ /**
494
+ * Navegação dos componentes (`?universo=`, `?app=`, links internos). O app pode passar as funções do
495
+ * próprio roteador (`navigation` no provider, ex.: Next.js); o padrão usa o History API do navegador.
496
+ */
497
+ interface EngramindRouter {
498
+ push(url: string, options?: {
499
+ scroll?: boolean;
500
+ }): void;
501
+ replace(url: string, options?: {
502
+ scroll?: boolean;
503
+ }): void;
504
+ }
505
+ interface NavigationAdapter {
506
+ useRouter: () => EngramindRouter;
507
+ usePathname: () => string;
508
+ useSearchParams: () => {
509
+ get(name: string): string | null;
510
+ toString(): string;
511
+ };
512
+ }
513
+ /** Navegação padrão pelo History API (sem roteador). */
514
+ declare const historyNavigation: NavigationAdapter;
515
+
516
+ /**
517
+ * `app`: o token do próprio app (o app, os agentes dele e os canais que eles alcançam), sem funções de
518
+ * gestor. `manager`: só para o gestor da rede (token admin), libera a visão Apps x canais.
519
+ */
520
+ type EngramindMode = "app" | "manager";
521
+ interface EngramindHrefs {
522
+ /** Página da rede (os parâmetros `?app=` e `?universo=` são acrescentados). */
523
+ network: string;
524
+ /** Página de detalhe de um canal; `null` esconde o link "Abrir página do canal". */
525
+ channel: ((slug: string) => string) | null;
526
+ }
527
+ interface RenderLinkProps {
528
+ href: string;
529
+ children?: ReactNode;
530
+ className?: string;
531
+ [key: string]: unknown;
532
+ }
533
+ interface FooterContext {
534
+ /** Distribuição da visão inicial (só fora dos universos). */
535
+ layout?: {
536
+ value: OverviewLayoutMode;
537
+ onChange: (value: OverviewLayoutMode) => void;
538
+ };
539
+ }
540
+ /** Para onde levar o "Configurar". */
541
+ type ConfigureTarget = "connection" | "identities";
542
+ interface EngramindConfig {
543
+ mode: EngramindMode;
544
+ /** Slug do app do token (modo app); a visão inicial é a rede Agentes x canais dele. */
545
+ app: string | null;
546
+ /** Nome exibido do app no modo app (padrão: o slug). */
547
+ appName?: string;
548
+ /** URL do SSE da lib montado pelo app (`createSseHandler`); `null` desliga o tempo real. */
549
+ events: string | null;
550
+ navigation: NavigationAdapter;
551
+ renderLink?: (props: RenderLinkProps) => ReactNode;
552
+ hrefs: EngramindHrefs;
553
+ /** Ícone de cada agente (`app/agente`); padrão: robô. */
554
+ agentIcon: (agent: string) => LucideIcon;
555
+ /** Gravações por agente que o app conhece (selo "gravadas" do node do agente). */
556
+ agentWrites?: (agent: string) => {
557
+ total: number;
558
+ last7d: number;
559
+ } | null;
560
+ /** Rótulos legíveis de canais (título e dica no lugar da ponta do slug). */
561
+ channelLabels: ReadonlyMap<string, ChannelLabel>;
562
+ messages: Messages;
563
+ /** Prazo de desuso fixo (sobrepõe o do Engramind). */
564
+ staleAfterDays?: number;
565
+ /**
566
+ * Ação "Configurar": `connection` (token recusado ou sem conexão, card do fim da página) ou `identities`
567
+ * (nenhum app, app sem agentes ativos).
568
+ */
569
+ onConfigure?: (target?: ConfigureTarget) => void;
570
+ /** Conteúdo extra: o fim da página da rede e o detalhe do canal. */
571
+ slots: {
572
+ footer?: (context: FooterContext) => ReactNode;
573
+ channelDetail?: (slug: string) => ReactNode;
574
+ };
575
+ /** Prefixo das chaves do `localStorage` (filtros da rede); vazio usa a chave sem prefixo. */
576
+ storagePrefix: string;
577
+ }
578
+ declare function useEngramindConfig(): EngramindConfig;
579
+ /** `true` no modo gestor (Apps x canais, apps e configurações globais). */
580
+ declare const useIsManager: () => boolean;
581
+ /** Texto pt-BR (ou o sobrescrito pelo app) de uma chave do dicionário. */
582
+ declare function useT(): (key: keyof Messages, vars?: Record<string, string | number>) => string;
583
+
584
+ /**
585
+ * Toasts da lib: delegam ao `notify` do `EngramindProvider` (o app liga ao seu sistema de toasts, como o
586
+ * `sonner`). Sem `notify`, nada aparece. Mesma forma do `sonner` (`toast.success(...)`).
587
+ */
588
+ type NotifyKind = "success" | "error" | "info" | "warning";
589
+ type Notify = (kind: NotifyKind, message: string, options?: {
590
+ description?: string;
591
+ id?: string | number;
592
+ }) => void;
593
+
594
+ interface EngramindProviderProps {
595
+ /** Fonte de dados: o proxy da lib montado pelo app (`createHttpDataSource({ basePath })`). */
596
+ dataSource: EngramindDataSource;
597
+ /** `app` (padrão): token do próprio app. `manager`: só para o gestor da rede (token admin). */
598
+ mode?: EngramindMode;
599
+ /** URL do SSE da lib (`createSseHandler`); sem ela, a tela atualiza só pelas próprias ações e ao reconsultar. */
600
+ events?: string | null;
601
+ /** Slug do app do token (modo app); sem ele, a lib lê de `whoami`. */
602
+ app?: string | null;
603
+ /** Nome exibido do app (modo app). */
604
+ appName?: string;
605
+ /** Toasts do app (ex.: `sonner`). */
606
+ notify?: Notify;
607
+ /** Navegação do roteador do app (ex.: `next/navigation`); padrão: History API. */
608
+ navigation?: NavigationAdapter;
609
+ /** Link interno do app (ex.: `next/link`); padrão: `<a>`. */
610
+ renderLink?: (props: RenderLinkProps) => ReactNode;
611
+ hrefs?: Partial<EngramindHrefs>;
612
+ agentIcon?: (agent: string) => LucideIcon;
613
+ agentWrites?: (agent: string) => {
614
+ total: number;
615
+ last7d: number;
616
+ } | null;
617
+ channelLabels?: ReadonlyMap<string, ChannelLabel>;
618
+ /** Textos sobrescritos (chave ausente usa o padrão pt-BR). */
619
+ messages?: PartialMessages;
620
+ staleAfterDays?: number;
621
+ onConfigure?: (target?: ConfigureTarget) => void;
622
+ slots?: {
623
+ footer?: (context: FooterContext) => ReactNode;
624
+ channelDetail?: (slug: string) => ReactNode;
625
+ };
626
+ storagePrefix?: string;
627
+ children: ReactNode;
628
+ }
629
+ /**
630
+ * Raiz dos componentes do Engramind. O app monta dentro do próprio `QueryClientProvider` (TanStack Query)
631
+ * e do próprio login: o provider só leva a fonte de dados (o proxy), o SSE e os adaptadores do app.
632
+ * Uma fonte de dados por página: dois providers com fontes diferentes na mesma tela usam a última montada.
633
+ */
634
+ declare function EngramindProvider(props: EngramindProviderProps): react.JSX.Element;
635
+
636
+ /**
637
+ * Conexão SSE compartilhada por URL (`EventSource`), com contagem de referências. Quando cai, reconecta
638
+ * com espera crescente (1 s → 30 s) e avisa os ouvintes `onReconnect` (a tela relê o que pode ter perdido).
639
+ */
640
+ type Listener = (event: LiveEvent) => void;
641
+ type StatusListener = (connected: boolean) => void;
642
+ interface LiveSubscription {
643
+ onEvent?: Listener;
644
+ onReconnect?: () => void;
645
+ onStatus?: StatusListener;
646
+ }
647
+ /** Assina o SSE em `url`; devolve a função que cancela a assinatura. */
648
+ declare function subscribeLive(url: string, subscription: LiveSubscription): () => void;
649
+
650
+ /**
651
+ * Rede do Engramind: no modo gestor, a visão inicial Apps x canais e a visão Agentes x canais de um app
652
+ * (`?app=`); no modo app, a visão inicial é a rede Agentes x canais do próprio app. Universo do canal e
653
+ * universo do agente (`?universo=`), com a gestão de canais e memórias. As redes escondem os canais sem
654
+ * nenhuma memória (lista "Sem memórias (N)").
655
+ */
656
+ declare function EngramindNetwork({ onConfigure }: {
657
+ onConfigure?: () => void;
658
+ }): react.JSX.Element;
659
+
660
+ /** Aparência calculada de uma partícula de memória (módulo puro, OPE-109). */
661
+ interface ParticleVisual {
662
+ id: string;
663
+ size: number;
664
+ /** Cor final (a do canal apagada pelo brilho). */
665
+ color: string;
666
+ /** Cor do canal, sem o brilho. */
667
+ baseColor: string;
668
+ brightness: number;
669
+ uses: number;
670
+ /** Data usada no brilho (cai na criação). */
671
+ lastUse: string;
672
+ /** Último uso real (`null` = nunca usada). */
673
+ lastRealUse: string | null;
674
+ pinned: boolean;
675
+ archived: boolean;
676
+ }
677
+ /** Crescimento local por consumo ao vivo, até a releitura dos contadores. */
678
+ declare const LIVE_BUMP_PX = 2;
679
+ /**
680
+ * Escala relativa ao universo visível: cor pelo canal (`channelColors`, de `universeChannelColors`;
681
+ * sem mapa, o roxo primário), tamanho logarítmico pelo uso e brilho pelo prazo do consolidador. A escala considera todas as memórias do
682
+ * universo, inclusive as que a busca apaga (o destaque não recalcula nada).
683
+ */
684
+ declare function buildParticles(memories: readonly NetworkMemory[], options: {
685
+ channelColors?: ReadonlyMap<string, string>;
686
+ staleAfterDays: number;
687
+ bumps?: Record<string, number>;
688
+ now?: number;
689
+ }): Map<string, ParticleVisual>;
690
+
691
+ /** Ações do card da memória; a origem dos dados (Engramind bruto ou listas dos agentes) decide como gravar. */
692
+ interface MemoryCardActions {
693
+ onActive: (memory: NetworkMemory, active: boolean) => void;
694
+ onPin: (memory: NetworkMemory, pinned: boolean) => void;
695
+ onEdit: (memory: NetworkMemory) => void;
696
+ onDelete: (memory: NetworkMemory) => void;
697
+ onMove?: (memory: NetworkMemory) => void;
698
+ onHistory?: (memory: NetworkMemory) => void;
699
+ /** Somente leitura (ex.: canal arquivado). */
700
+ readOnly?: boolean;
701
+ }
702
+
703
+ /**
704
+ * Remoções confirmadas nesta tela (excluir ou mover): o universo não avisa "excluída por outra origem"
705
+ * quando a memória aberta sai por uma ação daqui. A marca entra só na **confirmação** (cancelar o
706
+ * diálogo não marca), sai se a ação falhar e é esquecida quando o item deixa o universo.
707
+ */
708
+ interface LocalRemovals {
709
+ mark: (id: string) => void;
710
+ forget: (id: string) => void;
711
+ has: (id: string) => boolean;
712
+ }
713
+ declare function useLocalRemovals(): LocalRemovals;
714
+
715
+ interface UniverseCenter {
716
+ kind: "channel" | "agent";
717
+ /** Slug do canal ou `app/agente`. */
718
+ id: string;
719
+ label: string;
720
+ archived?: boolean;
721
+ }
722
+ interface MemoryUniverseProps {
723
+ center: UniverseCenter;
724
+ memories: NetworkMemory[];
725
+ staleAfterDays: number;
726
+ /** Cor estável de cada canal (universo do agente); o universo marca o maior canal com o roxo primário. */
727
+ channelColors?: Map<string, string>;
728
+ /** Destaque da busca/filtros (`null` = sem filtro). */
729
+ isMatch?: ((memory: NetworkMemory) => boolean) | null;
730
+ actions: MemoryCardActions;
731
+ /** Assinantes do canal (universo do canal). */
732
+ subscribers?: number;
733
+ /** Releitura dos dados: zera o crescimento local do consumo ao vivo. */
734
+ dataVersion?: number;
735
+ onCreate?: (() => void) | null;
736
+ /** Botão de criar no canto (universo com memórias); vazio mostra a ação no estado vazio. */
737
+ createLabel?: string;
738
+ emptyTitle?: string;
739
+ className?: string;
740
+ /** Memória provisória da lista otimista (`pendente-…`): a definitiva que a substitui não nasce de novo. */
741
+ isProvisional?: (id: string) => boolean;
742
+ /** Remoções confirmadas nesta tela (sem o aviso de "outra origem" quando a memória aberta sai). */
743
+ localRemovals?: LocalRemovals;
744
+ }
745
+ /**
746
+ * Universo de um canal ou de um agente (OPE-109): o node central e uma partícula por memória, em
747
+ * órbitas (mais novas mais perto), com a cor do canal (o com mais memórias no roxo primário), tamanho pelo
748
+ * uso e brilho pelo último uso. Clique ou toque abre o card (passar o mouse só afasta as vizinhas); o
749
+ * consumo ao vivo pulsa a memória e manda uma partícula ao centro. No universo do agente, o link tem a
750
+ * cor do canal e é destacado nas memórias que ele escreveu (OPE-113).
751
+ */
752
+ declare function MemoryUniverse({ center, memories, staleAfterDays, channelColors, isMatch, actions, subscribers, dataVersion, onCreate, createLabel, emptyTitle, className, isProvisional, localRemovals, }: MemoryUniverseProps): react.JSX.Element;
753
+
754
+ /**
755
+ * Formatos devolvidos pela API do Engramind (contrato 0.12.0, `docs/openapi.json` do repositório
756
+ * `nandobfer/engramind`). Só os campos que a lib usa; o resto passa adiante sem tipagem.
757
+ */
758
+ interface Ref {
759
+ id: string;
760
+ slug: string;
761
+ }
762
+ interface EngramindAgent {
763
+ id: string;
764
+ slug: string;
765
+ qualified_slug: string;
766
+ name: string;
767
+ description: string | null;
768
+ app: Ref;
769
+ created_at: string;
770
+ disabled_at: string | null;
771
+ }
772
+ interface Category {
773
+ key: string;
774
+ label: string;
775
+ priority: number;
776
+ }
777
+ interface EngramindChannel {
778
+ id: string;
779
+ slug: string;
780
+ name: string;
781
+ description: string | null;
782
+ priority: number;
783
+ version: number;
784
+ created_at: string;
785
+ archived_at: string | null;
786
+ }
787
+ interface EngramindSubscription {
788
+ id: string;
789
+ agent: Ref & {
790
+ qualified_slug?: string;
791
+ };
792
+ target: string;
793
+ is_prefix: boolean;
794
+ mode: "inject" | "search" | "manage";
795
+ access: string[] | null;
796
+ priority: number | null;
797
+ reaches: string[];
798
+ created_at: string;
799
+ }
800
+ interface Author {
801
+ app: string | null;
802
+ app_id: string | null;
803
+ agent: string | null;
804
+ agent_id: string | null;
805
+ }
806
+ interface EngramindMemory {
807
+ id: string;
808
+ channel: string;
809
+ channel_id: string;
810
+ title: string | null;
811
+ title_state: "pending" | "ready" | "fallback";
812
+ text: string;
813
+ category: string;
814
+ status: "active" | "permanent" | "archived";
815
+ version: number;
816
+ author: Author;
817
+ origin?: {
818
+ source: string;
819
+ label?: string | null;
820
+ } | null;
821
+ embedding_state: "pending" | "ready" | "failed" | "off";
822
+ retrieval_count: number;
823
+ /** Entradas no contexto (gravado em lote; pode atrasar alguns segundos). */
824
+ injected_count?: number;
825
+ last_retrieved_at?: string | null;
826
+ verified_at?: string | null;
827
+ /** Sem uso há mais de `consolidation.stale_after_days` (candidata a esquecimento). */
828
+ stale_candidate?: boolean;
829
+ importance?: number | null;
830
+ created_at: string;
831
+ updated_at: string;
832
+ archived_at: string | null;
833
+ }
834
+ /** `get_consumer_settings`: o que a interface do consumidor precisa sem token admin. */
835
+ interface ConsumerSettings {
836
+ memory: {
837
+ text_min: number;
838
+ text_max: number;
839
+ };
840
+ limits: {
841
+ max_batch: number;
842
+ };
843
+ context: {
844
+ budget_tokens: number;
845
+ titles_budget_tokens: number;
846
+ default_format: string;
847
+ text_max_chars: number;
848
+ };
849
+ channels: {
850
+ channel: string;
851
+ memory_text_max: number;
852
+ budget_tokens: number;
853
+ category_priorities: Record<string, number>;
854
+ text_max_chars: number;
855
+ }[];
856
+ /**
857
+ * Prazo de desuso e pesos da busca: pedidos ao Engramind para o modo app (ver
858
+ * `docs/engramind-consumer-settings.md`). Até lá a lib usa os padrões (90 dias, 1/1/60).
859
+ */
860
+ consolidation?: {
861
+ stale_after_days?: number;
862
+ };
863
+ search?: {
864
+ vector_weight?: number;
865
+ text_weight?: number;
866
+ rrf_k?: number;
867
+ };
868
+ }
869
+
870
+ /**
871
+ * Painel lateral do canal (menu "⋯" ou botão direito no node): Editar (slug imutável), Assinantes,
872
+ * o conteúdo extra do app (`slots.channelDetail`, ex.: as configurações do canal no gestor) e
873
+ * Arquivar / Restaurar / Excluir de vez (só arquivado), com confirmação. No modo app, o Engramind só
874
+ * deixa o token de app arquivar e restaurar os canais que ele criou (`409 CHANNEL_SHARED` nos outros):
875
+ * editar e excluir de vez são do gestor e não aparecem.
876
+ */
877
+ declare function ChannelPanel({ channel, onOpenChange, onDeleted }: {
878
+ channel: EngramindChannel | null;
879
+ onOpenChange: (open: boolean) => void;
880
+ onDeleted?: (slug: string) => void;
881
+ }): react.JSX.Element;
882
+
883
+ /**
884
+ * Rótulos legíveis dos canais (título no lugar da ponta do slug e a dica): os de `value` ou os do
885
+ * `channelLabels` do provider (o app calcula os dele, ex.: a sigla de um repositório).
886
+ */
887
+ declare function ChannelLabelsProvider({ value, children }: {
888
+ value?: ReadonlyMap<string, ChannelLabel>;
889
+ children: React.ReactNode;
890
+ }): react.JSX.Element;
891
+ /** Rótulos dos canais de central (fora do `ChannelLabelsProvider`, um mapa vazio: o slug como está). */
892
+ declare function useChannelLabels(): ReadonlyMap<string, ChannelLabel>;
893
+ /** Nome legível de um canal numa linha (`channelDisplayName`), com o slug e o repositório na dica. */
894
+ declare function ChannelDisplayName({ slug, className }: {
895
+ slug: string;
896
+ className?: string;
897
+ }): react.JSX.Element;
898
+ declare const SIZES: {
899
+ readonly node: {
900
+ readonly prefix: "text-[10px]";
901
+ readonly title: "text-sm";
902
+ };
903
+ readonly center: {
904
+ readonly prefix: "text-[10px]";
905
+ readonly title: "text-sm";
906
+ };
907
+ readonly legend: {
908
+ readonly prefix: "text-[9px]";
909
+ readonly title: "text-xs";
910
+ };
911
+ };
912
+ /**
913
+ * Nome do canal em duas linhas: o prefixo até a última `/` discreto em cima e a ponta final como
914
+ * título destacado (canal de central: a sigla do repositório, com o nome na dica). O slug inteiro
915
+ * aparece ao passar o mouse.
916
+ */
917
+ declare function ChannelName({ slug, size, className, titleClassName }: {
918
+ slug: string;
919
+ size?: keyof typeof SIZES;
920
+ className?: string;
921
+ titleClassName?: string;
922
+ }): react.JSX.Element;
923
+
924
+ /**
925
+ * Skeleton com as dimensões da rede: área do canvas (mesmo fundo), a visão inicial na distribuição
926
+ * padrão (agentes em volta do centro, cada um com os seus canais em órbita, OPE-113) e o card de
927
+ * estatísticas (a barra fica fora da carga). No celular, o card aparece recolhido (o botão do canto),
928
+ * como na rede.
929
+ */
930
+ declare function NetworkSkeleton({ className }: {
931
+ className?: string;
932
+ }): react.JSX.Element;
933
+
934
+ /**
935
+ * Fim da página da rede: o `slots.footer` do app (ex.: o card "O que é o Engramind" do Opex) ou, sem ele,
936
+ * um card com a distribuição da visão inicial (Órbita ou Radial; só fora dos universos) e Configurar.
937
+ */
938
+ declare function NetworkFooter(context: FooterContext): react.JSX.Element | null;
939
+
940
+ /**
941
+ * Texto das memórias dos agentes (módulo PURO: tela, rotas, ferramentas e migração). Os limites vêm do
942
+ * Engramind (`memory.text_min` / `memory.text_max`, este com sobreposição por canal); os schemas
943
+ * estáticos só seguram o teto absoluto do Engramind (20.000) e a regra fina fica em `memoryInputSchemaFor`.
944
+ */
945
+ interface MemoryTextLimits {
946
+ textMin: number;
947
+ textMax: number;
948
+ }
949
+ /** Padrões do Engramind (usados até a primeira leitura das configurações). */
950
+ declare const DEFAULT_MEMORY_TEXT_LIMITS: MemoryTextLimits;
951
+ declare function memoryTextSchema(limits?: MemoryTextLimits): z.ZodString;
952
+
953
+ interface MemoryEditorTarget {
954
+ mode: "create" | "edit";
955
+ channel: string;
956
+ initial?: {
957
+ texto: string;
958
+ categoria: string | null;
959
+ };
960
+ }
961
+ /**
962
+ * O mesmo editor de memória das listas (texto + categoria, limites do Engramind) num diálogo da rede.
963
+ * `onSave` resolve `true` no sucesso; num conflito de versão o diálogo continua aberto com o texto.
964
+ */
965
+ declare function MemoryEditorDialog({ target, limits, categories, onSave, onClose }: {
966
+ target: MemoryEditorTarget | null;
967
+ limits?: MemoryTextLimits;
968
+ categories: {
969
+ key: string;
970
+ label: string;
971
+ }[];
972
+ onSave: (values: {
973
+ texto: string;
974
+ categoria: string;
975
+ }) => Promise<boolean>;
976
+ onClose: () => void;
977
+ }): react.JSX.Element;
978
+
979
+ /** Card quadrado e fixo (OPE-113): não depende do zoom da rede; o texto rola dentro. */
980
+ declare const MEMORY_CARD_WIDTH = 360;
981
+ declare const MEMORY_CARD_HEIGHT = 360;
982
+ declare const MEMORY_CARD_MORPH_S = 0.22;
983
+
984
+ /** Traço do link ao centro: normal e destacado (memória escrita pelo agente do centro). */
985
+ declare const ORBIT_STROKE_WIDTH: {
986
+ readonly normal: 1;
987
+ readonly authored: 2.25;
988
+ };
989
+
990
+ declare const UNIVERSE_PARAM = "universo";
991
+ /** App aberto (`?app=<slug>`): a visão Agentes x canais restrita a ele (OPE-129). */
992
+ declare const APP_PARAM = "app";
993
+ /** `canal:<slug>` / `agente:<app/agente>` ↔ referência do universo (inválido → `null`). */
994
+ declare function parseUniverse(value: string | null | undefined): UniverseRef | null;
995
+ declare const formatUniverse: (ref: UniverseRef) => string;
996
+
997
+ /** Dimensões compartilhadas pela rede e pelo skeleton (o skeleton acompanha a interface). */
998
+ /** Fundo das redes no padrão do app (tema compartilhado dos canvas React Flow, `@/components/flow/flow-theme`). */
999
+ declare const NETWORK_CANVAS_CLASS = "relative overflow-hidden rounded-xl border bg-background bg-[radial-gradient(ellipse_at_center,color-mix(in_oklab,var(--color-primary)_8%,transparent),transparent_70%)] h-[min(72dvh,44rem)] w-full max-md:h-[70dvh]";
1000
+ /** Tema do React Flow pelos tokens do app (variáveis no próprio elemento vencem a folha do `colorMode="dark"`). */
1001
+ declare const NETWORK_FLOW_THEME: react.CSSProperties;
1002
+ /** Altura menor dos universos dentro dos cards de `/integracoes/ia` (no celular, quase a tela). */
1003
+ declare const NETWORK_CANVAS_COMPACT_CLASS = "h-[28rem] max-md:h-[60dvh]";
1004
+ declare const NETWORK_STATS_CLASS = "pointer-events-auto absolute right-3 top-3 z-10 max-h-[calc(100%-1.5rem)] w-64 overflow-y-auto rounded-xl border bg-card/90 p-3 text-xs shadow-lg backdrop-blur max-md:left-3 max-md:w-auto";
1005
+ /** Card de estatísticas recolhido (celular): um botão no canto com o resumo. */
1006
+ declare const NETWORK_STATS_TOGGLE_CLASS = "pointer-events-auto absolute right-3 top-3 z-10 flex h-10 items-center gap-1.5 rounded-xl border bg-card/90 px-3 text-xs font-medium text-foreground shadow-lg backdrop-blur";
1007
+ /** Área de toque mínima (40 px) dos botões sobre a rede no celular. */
1008
+ declare const NETWORK_TOUCH_BUTTON_CLASS = "max-md:h-10 max-md:px-3";
1009
+ /** Skeleton da visão inicial: área livre à esquerda do card de estatísticas, com o grupo de agentes e canais ao centro. */
1010
+ declare const NETWORK_SKELETON_AREA_CLASS = "absolute inset-y-0 left-0 right-72 flex items-center justify-center max-md:right-0 max-md:overflow-hidden";
1011
+ /** Card do agente na visão inicial: largura e altura fixas (as linhas de contagem não deslocam o layout, OPE-117). */
1012
+ declare const AGENT_NODE_SIZE_CLASS = "w-[11.25rem] h-16";
1013
+
1014
+ /** Link de volta à rede, com o universo do canal aberto. */
1015
+ declare function networkHref(network: string, params: Record<string, string>): string;
1016
+ /** Detalhe do canal: assinantes e o conteúdo extra do app (`slots.channelDetail`, ex.: configurações do canal). */
1017
+ declare function ChannelDetail({ slug }: {
1018
+ slug: string;
1019
+ }): react.JSX.Element;
1020
+
1021
+ /** Assinantes do canal: listar, assinar um agente, editar e remover. */
1022
+ declare function SubscribersCard({ channel }: {
1023
+ channel: string;
1024
+ }): react.JSX.Element;
1025
+
1026
+ type AppSettingsTab = "agents" | "channels" | "tokens" | "webhook";
1027
+ /**
1028
+ * Configuração do app no Engramind (modo app, só o token do próprio app): Agentes e assinaturas, Canais,
1029
+ * Tokens de agente (o segredo aparece uma única vez) e Webhook. Sem funções de gestor (outros apps,
1030
+ * tokens admin ou de app, configurações globais).
1031
+ */
1032
+ declare function EngramindAppSettings({ defaultTab }: {
1033
+ defaultTab?: AppSettingsTab;
1034
+ }): react.JSX.Element;
1035
+ declare function AppSettingsSkeleton(): react.JSX.Element;
1036
+
1037
+ /** Segredo novo do webhook: 32 bytes aleatórios em hexadecimal (64 caracteres, dentro de 32 a 256). */
1038
+ declare function generateWebhookSecret(): string;
1039
+ /**
1040
+ * Webhook do app (`update_app_webhook`): registrar a URL, gerar ou rotacionar o segredo (mostrado uma
1041
+ * única vez, para o app gravar no servidor dele) e remover. A leitura do estado atual usa `get_app`; se o
1042
+ * Engramind não a liberar para o token de app, a tela mostra só o que foi gravado nesta visita.
1043
+ */
1044
+ declare function WebhookCard({ app }: {
1045
+ app: string;
1046
+ }): react.JSX.Element;
1047
+
1048
+ /**
1049
+ * Canais que os agentes do app alcançam: criar pela assinatura exata (o token de app não cria canal
1050
+ * direto), abrir o painel do canal (assinantes, arquivar e restaurar os que o app criou; o Engramind
1051
+ * recusa os compartilhados com `409 CHANNEL_SHARED`).
1052
+ */
1053
+ declare function ChannelsCard({ channels, agents, subscriptions }: {
1054
+ channels: readonly EngramindChannel[];
1055
+ agents: readonly EngramindAgent[];
1056
+ subscriptions: readonly EngramindSubscription[];
1057
+ }): react.JSX.Element;
1058
+
1059
+ interface QueryBoundaryProps {
1060
+ isLoading: boolean;
1061
+ error: unknown;
1062
+ onRetry: () => void;
1063
+ skeleton: ReactNode;
1064
+ /** Para onde levar quando a conexão precisa ser (re)configurada. */
1065
+ onConfigure?: () => void;
1066
+ children: ReactNode;
1067
+ }
1068
+ /** Erro de acesso do token de app (registro de outro app ou canal fora das assinaturas). */
1069
+ declare const isNoAccessError: (error: unknown) => boolean;
1070
+ /**
1071
+ * Carregando (skeleton), erro com "Tentar novamente", "Reconfigure o token" (401 do Engramind), "Sem
1072
+ * acesso" (`403 FOREIGN_APP`/`CHANNEL_NOT_SUBSCRIBED`) e o conteúdo. Fora do ar, proxy mascarado e `429`
1073
+ * (com o `Retry-After` na mensagem) mostram a mensagem pt-BR com "Tentar novamente".
1074
+ */
1075
+ declare function QueryBoundary({ isLoading, error, onRetry, skeleton, onConfigure, children }: QueryBoundaryProps): react.JSX.Element;
1076
+
1077
+ interface SectionProps {
1078
+ title: string;
1079
+ info?: ReactNode;
1080
+ description?: ReactNode;
1081
+ actions?: ReactNode;
1082
+ children: ReactNode;
1083
+ className?: string;
1084
+ contentClassName?: string;
1085
+ }
1086
+ /** Card de uma seção das telas do Engramind: título com tooltip, descrição e ações à direita. */
1087
+ declare function Section({ title, info, description, actions, children, className, contentClassName }: SectionProps): react.JSX.Element;
1088
+
1089
+ /** Selo com tooltip (status, modo, tipo, escopo...). */
1090
+ declare function HelpBadge({ value, help, tone, className }: {
1091
+ value: string;
1092
+ help?: string;
1093
+ tone?: "outline" | "success" | "warning" | "destructive" | "secondary";
1094
+ className?: string;
1095
+ }): react.JSX.Element;
1096
+
1097
+ interface MemoryEditorProps {
1098
+ label: string;
1099
+ initial?: {
1100
+ texto: string;
1101
+ categoria: string | null;
1102
+ };
1103
+ limits?: MemoryTextLimits;
1104
+ categories: {
1105
+ key: string;
1106
+ label: string;
1107
+ }[];
1108
+ onSave: (values: {
1109
+ texto: string;
1110
+ categoria: string;
1111
+ }) => void;
1112
+ onCancel: () => void;
1113
+ }
1114
+ /** Texto livre da memória + categoria (mesmos limites da API, vindos do Engramind). Ctrl+Enter salva, Esc cancela. */
1115
+ declare function MemoryEditor({ label, initial, limits, categories, onSave, onCancel }: MemoryEditorProps): react.JSX.Element;
1116
+
1117
+ /**
1118
+ * Base dos hooks do Engramind: tudo passa pela fonte de dados do `EngramindProvider` (o proxy montado
1119
+ * pelo app; o navegador nunca chama o Engramind). Chave: `["engramind", <1º segmento da rota>, rota, parâmetros]`, invalidada
1120
+ * pelo prefixo no tempo real (`useEngramindRealtime`).
1121
+ */
1122
+ type Params = Record<string, string | number | boolean | undefined | null>;
1123
+ declare const engramindKey: (route: string, params?: Params) => QueryKey;
1124
+ declare const areaKey: (area: string) => QueryKey;
1125
+ /** Caminho do Opex com os segmentos codificados (`channels/eng%2Fglobal/stats`). */
1126
+ declare const route: (...segments: (string | number)[]) => string;
1127
+ declare function engramindGet<T>(path: string, params?: Params): Promise<T>;
1128
+ declare function engramindSend<T>(method: "post" | "put" | "patch" | "delete", path: string, body?: unknown): Promise<T>;
1129
+ /** Consulta simples de uma rota do Engramind. */
1130
+ declare function useEngramindQuery<T>(path: string | null, params?: Params, options?: {
1131
+ enabled?: boolean; /** Número, `false` ou função dos dados atuais (ex.: polling só enquanto algo carrega). */
1132
+ refetchInterval?: number | false | ((data: T | undefined) => number | false);
1133
+ }): _tanstack_react_query.UseQueryResult<T, Error>;
1134
+ declare function useEngramindList<T>(path: string | null, field: string, params?: Params, options?: {
1135
+ enabled?: boolean; /** Lê todas as páginas (listas pequenas, como apps e tokens). */
1136
+ all?: boolean;
1137
+ }): {
1138
+ items: T[];
1139
+ data: _tanstack_react_query.InfiniteData<{
1140
+ items: T[];
1141
+ nextCursor: string | null;
1142
+ truncated: boolean;
1143
+ }, unknown>;
1144
+ error: Error;
1145
+ isError: true;
1146
+ isPending: false;
1147
+ isLoading: false;
1148
+ isLoadingError: false;
1149
+ isRefetchError: true;
1150
+ isSuccess: false;
1151
+ isPlaceholderData: false;
1152
+ status: "error";
1153
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1154
+ items: T[];
1155
+ nextCursor: string | null;
1156
+ truncated: boolean;
1157
+ }, unknown>, Error>>;
1158
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1159
+ items: T[];
1160
+ nextCursor: string | null;
1161
+ truncated: boolean;
1162
+ }, unknown>, Error>>;
1163
+ hasNextPage: boolean;
1164
+ hasPreviousPage: boolean;
1165
+ isFetchNextPageError: boolean;
1166
+ isFetchingNextPage: boolean;
1167
+ isFetchPreviousPageError: boolean;
1168
+ isFetchingPreviousPage: boolean;
1169
+ dataUpdatedAt: number;
1170
+ errorUpdatedAt: number;
1171
+ failureCount: number;
1172
+ failureReason: Error | null;
1173
+ errorUpdateCount: number;
1174
+ isFetched: boolean;
1175
+ isFetchedAfterMount: boolean;
1176
+ isFetching: boolean;
1177
+ isInitialLoading: boolean;
1178
+ isPaused: boolean;
1179
+ isRefetching: boolean;
1180
+ isStale: boolean;
1181
+ isEnabled: boolean;
1182
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<{
1183
+ items: T[];
1184
+ nextCursor: string | null;
1185
+ truncated: boolean;
1186
+ }, unknown>, Error>>;
1187
+ fetchStatus: _tanstack_react_query.FetchStatus;
1188
+ } | {
1189
+ items: T[];
1190
+ data: _tanstack_react_query.InfiniteData<{
1191
+ items: T[];
1192
+ nextCursor: string | null;
1193
+ truncated: boolean;
1194
+ }, unknown>;
1195
+ error: null;
1196
+ isError: false;
1197
+ isPending: false;
1198
+ isLoading: false;
1199
+ isLoadingError: false;
1200
+ isRefetchError: false;
1201
+ isFetchNextPageError: false;
1202
+ isFetchPreviousPageError: false;
1203
+ isSuccess: true;
1204
+ isPlaceholderData: false;
1205
+ status: "success";
1206
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1207
+ items: T[];
1208
+ nextCursor: string | null;
1209
+ truncated: boolean;
1210
+ }, unknown>, Error>>;
1211
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1212
+ items: T[];
1213
+ nextCursor: string | null;
1214
+ truncated: boolean;
1215
+ }, unknown>, Error>>;
1216
+ hasNextPage: boolean;
1217
+ hasPreviousPage: boolean;
1218
+ isFetchingNextPage: boolean;
1219
+ isFetchingPreviousPage: boolean;
1220
+ dataUpdatedAt: number;
1221
+ errorUpdatedAt: number;
1222
+ failureCount: number;
1223
+ failureReason: Error | null;
1224
+ errorUpdateCount: number;
1225
+ isFetched: boolean;
1226
+ isFetchedAfterMount: boolean;
1227
+ isFetching: boolean;
1228
+ isInitialLoading: boolean;
1229
+ isPaused: boolean;
1230
+ isRefetching: boolean;
1231
+ isStale: boolean;
1232
+ isEnabled: boolean;
1233
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<{
1234
+ items: T[];
1235
+ nextCursor: string | null;
1236
+ truncated: boolean;
1237
+ }, unknown>, Error>>;
1238
+ fetchStatus: _tanstack_react_query.FetchStatus;
1239
+ } | {
1240
+ items: T[];
1241
+ data: undefined;
1242
+ error: Error;
1243
+ isError: true;
1244
+ isPending: false;
1245
+ isLoading: false;
1246
+ isLoadingError: true;
1247
+ isRefetchError: false;
1248
+ isFetchNextPageError: false;
1249
+ isFetchPreviousPageError: false;
1250
+ isSuccess: false;
1251
+ isPlaceholderData: false;
1252
+ status: "error";
1253
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1254
+ items: T[];
1255
+ nextCursor: string | null;
1256
+ truncated: boolean;
1257
+ }, unknown>, Error>>;
1258
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1259
+ items: T[];
1260
+ nextCursor: string | null;
1261
+ truncated: boolean;
1262
+ }, unknown>, Error>>;
1263
+ hasNextPage: boolean;
1264
+ hasPreviousPage: boolean;
1265
+ isFetchingNextPage: boolean;
1266
+ isFetchingPreviousPage: boolean;
1267
+ dataUpdatedAt: number;
1268
+ errorUpdatedAt: number;
1269
+ failureCount: number;
1270
+ failureReason: Error | null;
1271
+ errorUpdateCount: number;
1272
+ isFetched: boolean;
1273
+ isFetchedAfterMount: boolean;
1274
+ isFetching: boolean;
1275
+ isInitialLoading: boolean;
1276
+ isPaused: boolean;
1277
+ isRefetching: boolean;
1278
+ isStale: boolean;
1279
+ isEnabled: boolean;
1280
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<{
1281
+ items: T[];
1282
+ nextCursor: string | null;
1283
+ truncated: boolean;
1284
+ }, unknown>, Error>>;
1285
+ fetchStatus: _tanstack_react_query.FetchStatus;
1286
+ } | {
1287
+ items: T[];
1288
+ data: undefined;
1289
+ error: null;
1290
+ isError: false;
1291
+ isPending: true;
1292
+ isLoading: true;
1293
+ isLoadingError: false;
1294
+ isRefetchError: false;
1295
+ isFetchNextPageError: false;
1296
+ isFetchPreviousPageError: false;
1297
+ isSuccess: false;
1298
+ isPlaceholderData: false;
1299
+ status: "pending";
1300
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1301
+ items: T[];
1302
+ nextCursor: string | null;
1303
+ truncated: boolean;
1304
+ }, unknown>, Error>>;
1305
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1306
+ items: T[];
1307
+ nextCursor: string | null;
1308
+ truncated: boolean;
1309
+ }, unknown>, Error>>;
1310
+ hasNextPage: boolean;
1311
+ hasPreviousPage: boolean;
1312
+ isFetchingNextPage: boolean;
1313
+ isFetchingPreviousPage: boolean;
1314
+ dataUpdatedAt: number;
1315
+ errorUpdatedAt: number;
1316
+ failureCount: number;
1317
+ failureReason: Error | null;
1318
+ errorUpdateCount: number;
1319
+ isFetched: boolean;
1320
+ isFetchedAfterMount: boolean;
1321
+ isFetching: boolean;
1322
+ isInitialLoading: boolean;
1323
+ isPaused: boolean;
1324
+ isRefetching: boolean;
1325
+ isStale: boolean;
1326
+ isEnabled: boolean;
1327
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<{
1328
+ items: T[];
1329
+ nextCursor: string | null;
1330
+ truncated: boolean;
1331
+ }, unknown>, Error>>;
1332
+ fetchStatus: _tanstack_react_query.FetchStatus;
1333
+ } | {
1334
+ items: T[];
1335
+ data: undefined;
1336
+ error: null;
1337
+ isError: false;
1338
+ isPending: true;
1339
+ isLoadingError: false;
1340
+ isRefetchError: false;
1341
+ isFetchNextPageError: false;
1342
+ isFetchPreviousPageError: false;
1343
+ isSuccess: false;
1344
+ isPlaceholderData: false;
1345
+ status: "pending";
1346
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1347
+ items: T[];
1348
+ nextCursor: string | null;
1349
+ truncated: boolean;
1350
+ }, unknown>, Error>>;
1351
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1352
+ items: T[];
1353
+ nextCursor: string | null;
1354
+ truncated: boolean;
1355
+ }, unknown>, Error>>;
1356
+ hasNextPage: boolean;
1357
+ hasPreviousPage: boolean;
1358
+ isFetchingNextPage: boolean;
1359
+ isFetchingPreviousPage: boolean;
1360
+ dataUpdatedAt: number;
1361
+ errorUpdatedAt: number;
1362
+ failureCount: number;
1363
+ failureReason: Error | null;
1364
+ errorUpdateCount: number;
1365
+ isFetched: boolean;
1366
+ isFetchedAfterMount: boolean;
1367
+ isFetching: boolean;
1368
+ isLoading: boolean;
1369
+ isInitialLoading: boolean;
1370
+ isPaused: boolean;
1371
+ isRefetching: boolean;
1372
+ isStale: boolean;
1373
+ isEnabled: boolean;
1374
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<{
1375
+ items: T[];
1376
+ nextCursor: string | null;
1377
+ truncated: boolean;
1378
+ }, unknown>, Error>>;
1379
+ fetchStatus: _tanstack_react_query.FetchStatus;
1380
+ } | {
1381
+ items: T[];
1382
+ data: _tanstack_react_query.InfiniteData<{
1383
+ items: T[];
1384
+ nextCursor: string | null;
1385
+ truncated: boolean;
1386
+ }, unknown>;
1387
+ isError: false;
1388
+ error: null;
1389
+ isPending: false;
1390
+ isLoading: false;
1391
+ isLoadingError: false;
1392
+ isRefetchError: false;
1393
+ isSuccess: true;
1394
+ isPlaceholderData: true;
1395
+ isFetchNextPageError: false;
1396
+ isFetchPreviousPageError: false;
1397
+ status: "success";
1398
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1399
+ items: T[];
1400
+ nextCursor: string | null;
1401
+ truncated: boolean;
1402
+ }, unknown>, Error>>;
1403
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
1404
+ items: T[];
1405
+ nextCursor: string | null;
1406
+ truncated: boolean;
1407
+ }, unknown>, Error>>;
1408
+ hasNextPage: boolean;
1409
+ hasPreviousPage: boolean;
1410
+ isFetchingNextPage: boolean;
1411
+ isFetchingPreviousPage: boolean;
1412
+ dataUpdatedAt: number;
1413
+ errorUpdatedAt: number;
1414
+ failureCount: number;
1415
+ failureReason: Error | null;
1416
+ errorUpdateCount: number;
1417
+ isFetched: boolean;
1418
+ isFetchedAfterMount: boolean;
1419
+ isFetching: boolean;
1420
+ isInitialLoading: boolean;
1421
+ isPaused: boolean;
1422
+ isRefetching: boolean;
1423
+ isStale: boolean;
1424
+ isEnabled: boolean;
1425
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<{
1426
+ items: T[];
1427
+ nextCursor: string | null;
1428
+ truncated: boolean;
1429
+ }, unknown>, Error>>;
1430
+ fetchStatus: _tanstack_react_query.FetchStatus;
1431
+ };
1432
+ interface MutationOptions<V> {
1433
+ /** Áreas (1º segmento) a invalidar no sucesso. */
1434
+ invalidate: string[];
1435
+ success?: string | ((variables: V) => string);
1436
+ /** Não mostra o toast de erro (o chamador mostra no formulário). */
1437
+ silentError?: boolean;
1438
+ /** Outras chaves a invalidar (ex.: o detalhe da integração). */
1439
+ alsoInvalidate?: readonly QueryKey[];
1440
+ }
1441
+ /** Mutação numa rota do Engramind, com toast pt-BR e invalidação das áreas afetadas. */
1442
+ declare function useEngramindMutation<V, T = unknown>(request: (variables: V) => Promise<T>, options: MutationOptions<V>): _tanstack_react_query.UseMutationResult<T, Error, V, unknown>;
1443
+ /** Áreas a invalidar por tipo de evento. `memory.consumed` não invalida nada (só anima a rede). */
1444
+ declare function areasForEvent(type: string): string[];
1445
+ /**
1446
+ * Tempo real pelo SSE da lib (`events` do provider): cada evento invalida as áreas afetadas e, quando a
1447
+ * conexão volta depois de cair, todas as consultas do Engramind são relidas. Sem `events`, nada.
1448
+ */
1449
+ declare function useEngramindRealtime(): void;
1450
+ /** Erro que pede reconfigurar a conexão (token inválido/insuficiente ou sem configuração). */
1451
+ declare function needsReconnect(error: unknown): "configure" | "token" | null;
1452
+
1453
+ /**
1454
+ * Dados da rede do Engramind: canais (com os arquivados), agentes, assinaturas e memórias de todos os
1455
+ * status (todas as páginas). No modo gestor, também os apps e as configurações globais (o prazo
1456
+ * `consolidation.stale_after_days` e os pesos da busca); no modo app, o próprio app (`whoami`), as
1457
+ * categorias e os limites de `get_consumer_settings`. Tudo pela fonte de dados do provider.
1458
+ */
1459
+ declare const STALE_AFTER_DAYS_KEY = "consolidation.stale_after_days";
1460
+ declare function toNetworkMemory(memory: EngramindMemory): NetworkMemory;
1461
+ /** Pesos da fusão da busca nas configurações do Engramind (padrão 1/1/60). */
1462
+ declare function searchFusionOf(setting: (key: string) => unknown): SearchFusion;
1463
+ declare function firstSentence(text: string): string;
1464
+ /** Pesos da fusão da busca em `get_consumer_settings` (modo app). */
1465
+ declare function consumerSearchFusion(consumer: ConsumerSettings | undefined): SearchFusion;
1466
+ /** Prazo de desuso: o fixado pelo app, o do Engramind (gestor: `settings`; app: `consumer-settings`) ou 90. */
1467
+ declare function resolveStaleAfterDays(fixed: number | undefined, fromEngramind: unknown): number;
1468
+ /** Slug do app do token (modo app): o fixado no provider ou o de `whoami`. */
1469
+ declare function useOwnApp(): {
1470
+ slug: string | null;
1471
+ isLoading: boolean;
1472
+ error: unknown;
1473
+ };
1474
+ declare function useEngramindNetwork(): {
1475
+ apps: {
1476
+ slug: string;
1477
+ name: string;
1478
+ }[];
1479
+ /** App do token (modo app); `null` no gestor. */
1480
+ ownApp: string | null;
1481
+ rawChannels: EngramindChannel[];
1482
+ rawAgents: EngramindAgent[];
1483
+ rawMemories: EngramindMemory[];
1484
+ categories: Category[];
1485
+ limits: {
1486
+ textMin: number;
1487
+ textMax: number;
1488
+ } | undefined;
1489
+ maxBatch: number | null;
1490
+ searchFusion: SearchFusion;
1491
+ staleAfterDays: number;
1492
+ memoriesUpdatedAt: number;
1493
+ /** Lista de canais sendo relida (canal recém-criado ainda não chegou). */
1494
+ channelsFetching: boolean;
1495
+ isLoading: boolean;
1496
+ error: unknown;
1497
+ refetch: () => void;
1498
+ agents: NetworkAgent[];
1499
+ agentNames: Map<string, string>;
1500
+ channels: NetworkChannel[];
1501
+ subscriptions: SubscriptionInput[];
1502
+ memories: NetworkMemory[];
1503
+ };
1504
+
1505
+ /** O Engramind grava os contadores em lote a cada 5 s: a releitura espera um pouco mais. */
1506
+ declare const CONSUMPTION_REFRESH_DELAY_MS = 6000;
1507
+ /** Espera para juntar os eventos por canal de uma mesma leitura (`consumption`). */
1508
+ declare const CONSUMPTION_GROUP_WINDOW_MS = 400;
1509
+ declare function isConsumptionEvent(value: unknown): value is ConsumptionEvent;
1510
+ /**
1511
+ * Tempo real do consumo de memórias: o webhook `memory.consumed` (Engramind ≥ 0.12.0) chega pelo SSE da
1512
+ * lib, um evento por canal; os eventos da mesma leitura são agrupados pelo `consumption` e a tela anima
1513
+ * **uma** vez com o `handler` (estado local: brilho cheio e tamanho um pouco maior). Leitura sem agente
1514
+ * (token de app ou admin) não anima. Os contadores reais são relidos depois do lote do Engramind; o
1515
+ * consumo não invalida o contexto.
1516
+ */
1517
+ declare function useEngramindConsumption(handler: (event: ConsumptionEvent) => void): void;
1518
+ interface Travel {
1519
+ id: string;
1520
+ /** Aresta por onde a partícula viaja. */
1521
+ edge: string;
1522
+ /** `true`: do alvo para a origem da aresta. */
1523
+ reverse: boolean;
1524
+ /** `success`: criação de memória por um agente (verde). */
1525
+ tone: "primary" | "white" | "success";
1526
+ delayMs: number;
1527
+ }
1528
+ /**
1529
+ * Efeitos locais da rede: pulsos por node (contador que remonta o anel), partículas viajando pelas
1530
+ * arestas e o leve aumento de tamanho das memórias consumidas (zerado quando o Engramind relê os
1531
+ * números). Movimento reduzido: sem pulsos nem viagens; o aumento e o brilho continuam.
1532
+ */
1533
+ declare function useLiveEffects(resetKey: unknown): {
1534
+ pulses: Record<string, number>;
1535
+ travels: Travel[];
1536
+ bumps: Record<string, number>;
1537
+ liveCount: number;
1538
+ pulse: (keys: readonly string[], delayMs?: number) => void;
1539
+ travel: (items: readonly Omit<Travel, "id">[]) => void;
1540
+ finish: (id: string) => void;
1541
+ bump: (ids: readonly string[]) => void;
1542
+ countEvent: () => void;
1543
+ reducedMotion: boolean;
1544
+ };
1545
+ type LiveEffects = ReturnType<typeof useLiveEffects>;
1546
+
1547
+ interface NetworkSearchResult {
1548
+ ids: Set<string>;
1549
+ textOnly: boolean;
1550
+ }
1551
+ /** Divide os canais citados em lotes de `size`. Sem canais: um lote vazio (busca sem citar canais). */
1552
+ declare function channelBatches(channels: readonly string[], size?: number): string[][];
1553
+ /**
1554
+ * Busca da rede (OPE-113): roda sozinha com o termo (a espera de digitação fica no campo), cita os
1555
+ * canais da visão atual (o Engramind só busca nos canais `manage` e arquivados quando citados), em lotes
1556
+ * de 50, e destaca só os resultados relevantes (`relevantSearchIds`).
1557
+ */
1558
+ declare function useNetworkSearch({ query, channels, categories, fusion, enabled }: {
1559
+ query: string;
1560
+ channels: readonly string[];
1561
+ categories: readonly string[];
1562
+ fusion: SearchFusion;
1563
+ enabled?: boolean;
1564
+ }): _tanstack_react_query.UseQueryResult<NetworkSearchResult, Error>;
1565
+
1566
+ /**
1567
+ * Busca e filtros da rede do Engramind (OPE-113, puro): no padrão de `/tarefas`, ficam no navegador
1568
+ * (`usePersistentState`, chave versionada) e **destacam sem remover** (as que não casam ficam apagadas).
1569
+ */
1570
+ declare const NETWORK_FILTERS_STORAGE_KEY = "opex.engramind.network-filters.v1";
1571
+ declare const networkFiltersSchema: z.ZodObject<{
1572
+ search: z.ZodCatch<z.ZodString>;
1573
+ channels: z.ZodCatch<z.ZodArray<z.ZodString>>;
1574
+ statuses: z.ZodCatch<z.ZodArray<z.ZodString>>;
1575
+ categories: z.ZodCatch<z.ZodArray<z.ZodString>>;
1576
+ authors: z.ZodCatch<z.ZodArray<z.ZodString>>;
1577
+ from: z.ZodCatch<z.ZodUnion<[z.ZodString, z.ZodLiteral<"">]>>;
1578
+ to: z.ZodCatch<z.ZodUnion<[z.ZodString, z.ZodLiteral<"">]>>;
1579
+ includeArchived: z.ZodCatch<z.ZodBoolean>;
1580
+ overviewLayout: z.ZodCatch<z.ZodEnum<{
1581
+ "by-agent": "by-agent";
1582
+ "agents-center": "agents-center";
1583
+ }>>;
1584
+ }, z.core.$strip>;
1585
+ type NetworkFilters = z.infer<typeof networkFiltersSchema>;
1586
+ declare const DEFAULT_NETWORK_FILTERS: NetworkFilters;
1587
+ /** Campos que o "Limpar" zera (a distribuição escolhida no card "O que é o Engramind" fica). */
1588
+ declare const NETWORK_FILTER_KEYS: readonly ["search", "channels", "statuses", "categories", "authors", "from", "to", "includeArchived"];
1589
+ declare const clearNetworkFilters: (filters: NetworkFilters) => NetworkFilters;
1590
+ /** Filtros que destacam memórias (sem a busca, que vem do servidor, e sem os arquivados). */
1591
+ declare const hasMemoryFilters: (filters: NetworkFilters) => boolean;
1592
+ declare const hasActiveFilters: (filters: NetworkFilters, searchIds: ReadonlySet<string> | null) => boolean;
1593
+ /** A memória casa com a busca e os filtros? (Destaque: as demais ficam apagadas, nada sai da rede.) */
1594
+ declare function matchesFilters(memory: NetworkMemory, filters: NetworkFilters, searchIds: ReadonlySet<string> | null): boolean;
1595
+ declare const memoryStatusLabel: (status: string) => string;
1596
+ declare const MEMORY_STATUS_OPTIONS: {
1597
+ value: "active" | "permanent" | "archived";
1598
+ label: string;
1599
+ }[];
1600
+ interface NetworkFilterChip {
1601
+ key: string;
1602
+ label: string;
1603
+ remove: Partial<NetworkFilters>;
1604
+ }
1605
+ /**
1606
+ * Chips dos filtros ativos (resumo do cartão recolhido e contagem da gaveta no celular). `channelLabel`
1607
+ * mostra o canal legível (`channelDisplayName`: sigla da central no lugar do id).
1608
+ */
1609
+ declare function activeNetworkFilterChips(filters: NetworkFilters, channelLabel?: (slug: string) => string): NetworkFilterChip[];
1610
+
1611
+ /**
1612
+ * Visão inicial Apps x canais (OPE-129, puro): os links por agente agregados por app e o corte dos
1613
+ * canais vazios. Decisão do dono no plano aprovado: as duas redes (Apps x canais e Agentes x canais)
1614
+ * escondem o canal **sem nenhuma memória**; inativas contam (só some com zero de qualquer status).
1615
+ * Os universos, o filtro Canal, o painel do canal e o Importar continuam com todos os canais.
1616
+ */
1617
+ /** Só os canais com ao menos uma memória (de qualquer status), na ordem recebida. */
1618
+ declare function channelsWithMemories<T extends {
1619
+ slug: string;
1620
+ }>(channels: readonly T[], memories: readonly {
1621
+ channel: string;
1622
+ }[]): T[];
1623
+ /** App de um agente (`app/agente` → `app`). */
1624
+ declare const appOfAgent: (agent: string) => string;
1625
+ /** Id da aresta app → canal na visão de apps. */
1626
+ declare const appLinkEdgeId: (app: string, channel: string) => string;
1627
+ /** Link app → canal: as assinaturas de todos os agentes do app naquele canal. */
1628
+ interface AppLink {
1629
+ id: string;
1630
+ app: string;
1631
+ channel: string;
1632
+ /** Modos das assinaturas, sem repetição (ordem de chegada). */
1633
+ modes: SubscriptionMode[];
1634
+ /** Agentes (`app/agente`) que assinam o canal, sem repetição. */
1635
+ agents: string[];
1636
+ }
1637
+ /** Um link por par (app, canal), na ordem em que o par aparece pela primeira vez. */
1638
+ declare function appLinks(links: readonly NetworkLink[]): AppLink[];
1639
+ /** Canais assinados por algum agente do app (sem repetição, na ordem dos links). */
1640
+ declare function appChannels(app: string, links: readonly NetworkLink[]): string[];
1641
+ /** Alcance do app: soma das memórias (ativas) dos canais que os agentes dele assinam, cada canal uma vez. */
1642
+ declare function appReach(links: readonly AppLink[], countByChannel: ReadonlyMap<string, number>): Map<string, number>;
1643
+
1644
+ /**
1645
+ * Tema dos canvas React Flow (rede do Engramind e outros canvas do app). Só tokens do tema do app
1646
+ * (`var(--color-*)` do Tailwind 4 e `color-mix`), sem cor fixa: a cor primária do app manda.
1647
+ *
1648
+ * O fundo segue o padrão das páginas (`bg-background`) com um brilho da cor primária bem suave no centro; o
1649
+ * React Flow fica transparente. O `colorMode="dark"` da biblioteca pinta o canvas, o minimapa e os
1650
+ * controles de cinza neutro fixo por uma folha de estilo fora das camadas do Tailwind: as variáveis no
1651
+ * `style` do próprio elemento (`FLOW_THEME_STYLE`) vencem essa folha. Os tipos de nó reservados da
1652
+ * biblioteca (`group`, `default`, `input`, `output`) ganham classe com fundo, padding e borda próprios:
1653
+ * os canvas usam tipos com prefixo do domínio, e as variáveis abaixo neutralizam o que sobrar.
1654
+ *
1655
+ * Cor e espessura das arestas vão no `style` inline do `path`: a folha do React Flow é importada fora
1656
+ * das camadas do Tailwind, então a regra `.react-flow__edge-path { stroke; stroke-width }` vence
1657
+ * qualquer classe utilitária (`stroke-primary`) e o atributo `strokeWidth` do SVG.
1658
+ */
1659
+ declare const FLOW_SURFACE_CLASS = "relative overflow-hidden rounded-xl border bg-background bg-[radial-gradient(ellipse_at_center,color-mix(in_oklab,var(--color-primary)_8%,transparent),transparent_70%)]";
1660
+ /** Cor das linhas das arestas: a primária do tema (aplicar no `style` inline, ver acima). */
1661
+ declare const FLOW_EDGE_PRIMARY_STROKE = "var(--color-primary)";
1662
+ declare const FLOW_THEME_STYLE: CSSProperties;
1663
+ /** Pontos discretos do fundo (`<Background {...FLOW_BACKGROUND_PROPS} />`). */
1664
+ declare const FLOW_BACKGROUND_PROPS: {
1665
+ variant: BackgroundVariant;
1666
+ gap: number;
1667
+ size: number;
1668
+ };
1669
+
1670
+ /**
1671
+ * Partícula que percorre um caminho SVG uma vez (Framer Motion) e avisa ao chegar. Usada nas redes do
1672
+ * Engramind (memórias viajando) e nos diagramas do Agente Arquiteto (pulso da aresta que nasce).
1673
+ */
1674
+ declare function PathTraveler({ path, reverse, delayMs, durationMs, radius, className, testId, edge, tone, onDone }: {
1675
+ path: string;
1676
+ reverse?: boolean;
1677
+ delayMs?: number;
1678
+ durationMs?: number;
1679
+ radius?: number;
1680
+ className?: string;
1681
+ testId?: string; /** `data-edge` do grupo e `data-tone` do círculo (testes e estilo). */
1682
+ edge?: string;
1683
+ tone?: string;
1684
+ onDone?: () => void;
1685
+ }): react.JSX.Element;
1686
+
1687
+ export { AGENT_NODE_SIZE_CLASS, AGENT_WRITE_WINDOW_MS, APP_PARAM, type AgentWrite, type AppLink, AppSettingsSkeleton, type AppSettingsTab, CONSUMPTION_GROUP_WINDOW_MS, CONSUMPTION_REFRESH_DELAY_MS, ChannelDetail, ChannelDisplayName, type ChannelLabel, ChannelLabelsProvider, ChannelName, ChannelPanel, ChannelsCard, type ConfigureTarget, type ConsumptionEvent, DEFAULT_MEMORY_TEXT_LIMITS, DEFAULT_MESSAGES, DEFAULT_NETWORK_FILTERS, DEFAULT_OVERVIEW_LAYOUT, DEFAULT_SEARCH_FUSION, DEFAULT_STALE_AFTER_DAYS, EngramindAppSettings, type EngramindConfig, type EngramindDataSource, type EngramindHrefs, type EngramindMode, EngramindNetwork, EngramindProvider, type EngramindProviderProps, type EngramindRouter, FLOW_BACKGROUND_PROPS, FLOW_EDGE_PRIMARY_STROKE, FLOW_SURFACE_CLASS, FLOW_THEME_STYLE, type FooterContext, HelpBadge, type HttpDataSourceOptions, type HttpMethod, LIVE_BUMP_PX, type LiveEffects, type LiveSubscription, type LocalRemovals, MEMORY_CARD_HEIGHT, MEMORY_CARD_MORPH_S, MEMORY_CARD_WIDTH, MEMORY_STATUS_OPTIONS, MOBILE_FIT_MIN_ZOOM, type MemoryCardActions, MemoryEditor, MemoryEditorDialog, type MemoryEditorTarget, type MemoryStatus, type MemoryTextLimits, MemoryUniverse, type MemoryUniverseProps, type MessageKey, type Messages, NETWORK_CANVAS_CLASS, NETWORK_CANVAS_COMPACT_CLASS, NETWORK_FILTERS_STORAGE_KEY, NETWORK_FILTER_KEYS, NETWORK_FLOW_THEME, NETWORK_SKELETON_AREA_CLASS, NETWORK_STATS_CLASS, NETWORK_STATS_TOGGLE_CLASS, NETWORK_TOUCH_BUTTON_CLASS, type NavigationAdapter, type NetworkAgent, type NetworkChannel, type NetworkFilterChip, type NetworkFilters, NetworkFooter, type NetworkLink, type NetworkMemory, NetworkSkeleton, type Notify, type NotifyKind, ORBIT_STROKE_WIDTH, OVERVIEW_AGENT_BOX, OVERVIEW_CHANNEL_BOX, OVERVIEW_FIT_MARGIN, OVERVIEW_LAYOUT_LABEL, OVERVIEW_LAYOUT_MODES, OVERVIEW_LINK_BEND, OVERVIEW_PADDING, OVERVIEW_SCALE_MAX, OVERVIEW_SCALE_MIN, type OverviewLayout, type OverviewLayoutInput, type OverviewLayoutMode, PARTICLE_MAX_PX, PARTICLE_MIN_PX, PINNED_MIN_BRIGHTNESS, PRIMARY_CHANNEL_COLOR, type Params$1 as Params, type PartialMessages, type ParticleVisual, PathTraveler, type Point, QueryBoundary, type Rect, type RenderLinkProps, SEARCH_SINGLE_BRANCH_TOP, STALE_AFTER_DAYS_KEY, type SearchFusion, Section, SubscribersCard, type SubscriptionInput, type SubscriptionMode, type Travel, UNIVERSE_FIRST_RADIUS, UNIVERSE_PARAM, UNIVERSE_RING_GAP, UNIVERSE_SLOT, type UniverseCenter, type UniverseRef, type UniverseStats, WebhookCard, activeNetworkFilterChips, agentDisplayName, agentReach, agentWritesOf, apiErrorCode, apiErrorMessage, apiErrorStatus, appChannels, appLinkEdgeId, appLinks, appOfAgent, appReach, areaKey, areasForEvent, buildParticles, channelBatches, channelColors, channelDisplayHint, channelDisplayName, channelNameParts, channelsWithMemories, chartToken, clampCardRect, clearDistance, clearNetworkFilters, consumerSearchFusion, createHttpDataSource, engramindGet, engramindKey, engramindSend, errorFromResponse, firstSentence, formatUniverse, generateWebhookSecret, hasActiveFilters, hasMemoryFilters, historyNavigation, isAuthoredByCenter, isConsumptionEvent, isNoAccessError, lastRealUseOf, lastUseOf, layoutOverview, layoutUniverse, matchesFilters, memoryCardSize, memoryStatusLabel, memoryTextSchema, memoryUses, mergeMessages, minZoomCenter, needsReconnect, networkFiltersSchema, networkHref, overviewInitialBounds, overviewLinkMidpoint, overviewLinkPath, overviewScale, parseUniverse, particleBrightness, particleColor, particleSize, pickChannelColors, relevantSearchIds, repelOffset, resolveStaleAfterDays, route, searchFusionOf, splitChannelSlug, stableHash, subscribeLive, subscriptionLinks, subscriptionReaches, toNetworkMemory, universeChannelColors, universeRingCapacity, universeRingCounts, universeStats, useChannelLabels, useEngramindConfig, useEngramindConsumption, useEngramindList, useEngramindMutation, useEngramindNetwork, useEngramindQuery, useEngramindRealtime, useIsManager, useLiveEffects, useLocalRemovals, useNetworkSearch, useOwnApp, useT };