@ftarganski/omni-ai 1.1.5 → 1.1.6

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.
Files changed (2) hide show
  1. package/README.md +1485 -0
  2. package/package.json +4 -2
package/README.md ADDED
@@ -0,0 +1,1485 @@
1
+ # omni-ai
2
+
3
+ **Framework provider-agnostic de AI agents e skills para monorepos TypeScript.**
4
+
5
+ Configure qualquer provider LLM (Anthropic, OpenAI, GitHub Copilot, ou self-hosted) e compose agentes reutilizáveis para seus projetos — geração de backend, componentes frontend, revisão UX, validação QA, e mais — tudo via CLI ou API programática.
6
+
7
+ ---
8
+
9
+ ## Como funciona
10
+
11
+ ```
12
+ cd meu-projeto
13
+ omni run backend-dev "crie o módulo de pedidos com CRUD e GraphQL"
14
+
15
+
16
+ CLI (omni)
17
+ │ lê config/omni-ai.yaml ← provider, modelo e agentsDir
18
+ │ resolve "backend-dev" ← busca agents/**/*.yaml por name:
19
+ │ instancia o provider ← AnthropicProvider / OpenAIProvider
20
+ │ monta o SkillRegistry ← read-file, write-file, search-code...
21
+ │ cria o Agent → agent.run()
22
+
23
+ └─ Loop agentico:
24
+ 1. Envia systemPrompt + input para o LLM
25
+ 2. LLM retorna texto ou tool calls
26
+ 3. Skills são executadas (lê/escreve arquivos no meu-projeto/)
27
+ 4. Resultados voltam para o LLM
28
+ 5. Repete até concluir ou atingir maxIterations
29
+ ```
30
+
31
+ As skills (`read-file`, `write-file`, `search-code`, etc.) operam sempre no **diretório onde você executou o comando** (`process.cwd()`). O config e os agents ficam no repositório `omni-ai`.
32
+
33
+ ---
34
+
35
+ ## Instalação
36
+
37
+ ### Pré-requisitos
38
+
39
+ | Ferramenta | Versão mínima |
40
+ |------------|---------------|
41
+ | Node.js | 22.x |
42
+ | pnpm | 9.x |
43
+
44
+ ### 1. Clonar e instalar
45
+
46
+ ```bash
47
+ git clone https://github.com/Ftarganski/omni-ai.git
48
+ cd omni-ai
49
+ pnpm install
50
+ pnpm build
51
+ ```
52
+
53
+ ### 2. Configurar o provider
54
+
55
+ **Opção A — wizard interativo (recomendado):**
56
+
57
+ ```bash
58
+ omni init
59
+ ```
60
+
61
+ **Opção B — manual:**
62
+
63
+ ```bash
64
+ cp config/omni-ai.example.yaml config/omni-ai.yaml
65
+ cp .env.example .env
66
+ ```
67
+
68
+ Edite `config/omni-ai.yaml` e `.env` de acordo com o provider escolhido. Veja a seção [Providers](#providers) abaixo.
69
+
70
+ ### 3. Disponibilizar o CLI globalmente
71
+
72
+ **Opção A — via npm (pacote publicado):**
73
+
74
+ ```bash
75
+ npm install -g @ftarganski/omni-ai
76
+ ```
77
+
78
+ **Opção B — via link local (desenvolvimento):**
79
+
80
+ ```bash
81
+ # Na raiz do omni-ai, uma vez só
82
+ pnpm build
83
+ npm link bundle/omni-ai
84
+ ```
85
+
86
+ Depois disso, `omni` funciona de qualquer diretório.
87
+
88
+ ### 4. Testar a instalação
89
+
90
+ ```bash
91
+ # A partir do próprio omni-ai (ou de qualquer projeto)
92
+ omni list agents
93
+ omni list providers
94
+ omni list skills
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Uso rápido
100
+
101
+ ```bash
102
+ # Entrar no projeto alvo
103
+ cd /path/para/meu-projeto
104
+
105
+ # Rodar um agente
106
+ omni run backend-dev "crie o módulo de pedidos"
107
+
108
+ # Com sessão de memória (persiste entre runs)
109
+ omni run backend-dev "continue o módulo de pedidos" --session user1:feature1
110
+
111
+ # Modo verbose — mostra iterações e tokens por step
112
+ omni run qa-backend "valide src/orders/orders.service.ts" --verbose
113
+
114
+ # Salvar output em arquivo
115
+ omni run backend-dev "crie módulo de notificações" --output implementacao.md
116
+ ```
117
+
118
+ ---
119
+
120
+ ## CLI — Referência completa
121
+
122
+ ### `omni run`
123
+
124
+ ```
125
+ omni run <agent> "<prompt>" [opções]
126
+ ```
127
+
128
+ | Opção | Tipo | Descrição |
129
+ |-------|------|-----------|
130
+ | `--config <path>` | string | Caminho para o `omni-ai.yaml` (padrão: detectado automaticamente) |
131
+ | `--session <id>` | string | ID de sessão no formato `"resourceId:threadId"` — habilita memória SQLite entre runs |
132
+ | `--output <file>` | string | Salva o output completo em um arquivo |
133
+ | `--verbose` | flag | Exibe cada iteração, tool calls e contagem de tokens por step |
134
+ | `--stream` | flag | Transmite tokens em tempo real enquanto o agente responde |
135
+
136
+ **Exemplos:**
137
+
138
+ ```bash
139
+ # Backend — gera módulo completo
140
+ omni run backend-dev "crie o módulo de customers com CRUD, GraphQL e listeners"
141
+
142
+ # Frontend — gera componente
143
+ omni run frontend-dev "crie a página de listagem de pedidos com filtros e paginação"
144
+
145
+ # UX — audita e corrige problemas
146
+ omni run ux-lead "audite o componente OrderForm"
147
+
148
+ # QA — valida código gerado
149
+ omni run qa-lead "valide todos os arquivos em src/orders/"
150
+
151
+ # Com memória entre sessões
152
+ omni run backend-dev "o que você implementou no módulo de customers?" --session dev1:customers
153
+
154
+ # Agente específico + output em arquivo
155
+ omni run backend-schema "crie o schema para a entidade Invoice" --output invoice-schema.md
156
+ ```
157
+
158
+ ---
159
+
160
+ ### `omni list`
161
+
162
+ ```bash
163
+ omni list agents # Lista todos os agentes disponíveis (nome + descrição)
164
+ omni list skills # Lista todas as skills registradas
165
+ omni list providers # Lista os providers registrados e seus tipos
166
+ ```
167
+
168
+ ---
169
+
170
+ ### `omni chain`
171
+
172
+ Executa uma sequência de agentes em pipeline: a saída de cada agente se torna a entrada do próximo.
173
+
174
+ ```
175
+ omni chain "<prompt>" <agent1> <agent2> [agent3...]
176
+ ```
177
+
178
+ | Opção | Tipo | Descrição |
179
+ |-------|------|-----------|
180
+ | `--config <path>` | string | Caminho para o `omni-ai.yaml` |
181
+ | `--output <file>` | string | Salva o output final em arquivo |
182
+ | `--verbose` | flag | Imprime o output de cada agente intermediário |
183
+ | `--stream` | flag | Transmite tokens em tempo real para cada agente da cadeia |
184
+
185
+ **Exemplos:**
186
+
187
+ ```bash
188
+ # Schema → implementação → validação
189
+ omni chain "crie módulo de orders" backend-schema backend-dev qa-backend
190
+
191
+ # Geração de componente + auditoria UX
192
+ omni chain "crie a página de listagem de pedidos" frontend-dev ux-reviewer
193
+
194
+ # Com output salvo
195
+ omni chain "crie o módulo de customers" backend-schema backend-dev qa-backend --output customers.md
196
+
197
+ # Verbose — mostra output intermediário de cada agente
198
+ omni chain "crie módulo de invoices" backend-schema backend-dev --verbose
199
+
200
+ # Streaming em tempo real ao longo da cadeia
201
+ omni chain "crie e revise o módulo de orders" backend-dev qa-backend --stream
202
+ ```
203
+
204
+ **Output visual:**
205
+
206
+ ```
207
+ ◆ backend-schema [anthropic / claude-sonnet-4-6]
208
+ ... (3 iterações)
209
+
210
+ ↓ saída passada para: backend-dev
211
+
212
+ ◆ backend-dev [anthropic / claude-sonnet-4-6]
213
+ ... (8 iterações)
214
+
215
+ ↓ saída passada para: qa-backend
216
+
217
+ ◆ qa-backend [anthropic / claude-sonnet-4-6]
218
+ ... (4 iterações)
219
+
220
+ <output final do qa-backend>
221
+
222
+ Tokens: 18.400 entrada · 5.200 saída · ~$0.084
223
+ ```
224
+
225
+ ---
226
+
227
+ ### `omni init`
228
+
229
+ Wizard interativo que gera `config/omni-ai.yaml` e atualiza o `.env` sem editar arquivos manualmente.
230
+
231
+ ```bash
232
+ omni init
233
+ ```
234
+
235
+ O wizard irá:
236
+
237
+ 1. Perguntar qual provider usar (Copilot, Anthropic, OpenAI ou Custom/self-hosted)
238
+ 2. Solicitar a API key ou token via campo oculto (não aparece no terminal)
239
+ 3. Permitir selecionar o modelo padrão
240
+ 4. Opcionalmente configurar um segundo provider para agentes específicos
241
+ 5. Gerar `config/omni-ai.yaml` e atualizar `.env` preservando entradas existentes
242
+ 6. Exibir os próximos passos com exemplos de comandos
243
+
244
+ **Quando usar:** na primeira vez que configurar o omni-ai, ou quando quiser trocar ou adicionar um provider.
245
+
246
+ > Se `config/omni-ai.yaml` já existir, o wizard pergunta antes de sobrescrever.
247
+
248
+ ---
249
+
250
+ ### `omni serve`
251
+
252
+ Inicia um servidor HTTP local para executar agentes via REST ou SSE.
253
+
254
+ ```
255
+ omni serve [opções]
256
+ ```
257
+
258
+ | Opção | Tipo | Descrição |
259
+ |-------|------|-----------|
260
+ | `--port <number>` | number | Porta (padrão: 3000) |
261
+ | `--config <path>` | string | Caminho para `omni-ai.yaml` |
262
+
263
+ **Endpoints:**
264
+
265
+ | Método | Rota | Descrição |
266
+ |--------|------|-----------|
267
+ | `GET` | `/health` | Status do servidor e versão |
268
+ | `GET` | `/agents` | Lista todos os agentes disponíveis |
269
+ | `POST` | `/run` | Executa um agente (JSON response) |
270
+ | `POST` | `/run/stream` | Executa um agente com streaming SSE |
271
+
272
+ ```bash
273
+ # Iniciar o servidor
274
+ omni serve --port 4000
275
+
276
+ # Executar um agente via API
277
+ curl -X POST http://localhost:3000/run \
278
+ -H "Content-Type: application/json" \
279
+ -d '{"agent": "backend-dev", "prompt": "liste os endpoints do módulo de orders"}'
280
+
281
+ # Com sessão
282
+ curl -X POST http://localhost:3000/run \
283
+ -d '{"agent": "backend-dev", "prompt": "continue o módulo de customers", "session": "dev1:customers"}'
284
+ ```
285
+
286
+ ---
287
+
288
+ ### `omni watch`
289
+
290
+ Reexecuta um agente automaticamente quando arquivos do projeto mudam.
291
+
292
+ ```
293
+ omni watch <agent> "<prompt>" [opções]
294
+ ```
295
+
296
+ | Opção | Tipo | Descrição |
297
+ |-------|------|-----------|
298
+ | `--config <path>` | string | Caminho para `omni-ai.yaml` |
299
+ | `--glob <pattern>` | string | Glob dos arquivos a observar (padrão: `src/**/*.{ts,js,yaml,json}`) |
300
+ | `--debounce <ms>` | number | Delay de debounce em ms (padrão: 500) |
301
+ | `--stream` | flag | Transmite tokens em tempo real |
302
+
303
+ ```bash
304
+ # Reexecuta qa-backend sempre que um .ts muda
305
+ omni watch qa-backend "valide os arquivos modificados" --glob "src/**/*.ts"
306
+ ```
307
+
308
+ ---
309
+
310
+ ### `omni eval`
311
+
312
+ Avalia um agente contra um dataset de pares `(input, expected)`.
313
+
314
+ ```
315
+ omni eval <agent> <dataset.json> [opções]
316
+ ```
317
+
318
+ | Opção | Tipo | Descrição |
319
+ |-------|------|-----------|
320
+ | `--config <path>` | string | Caminho para `omni-ai.yaml` |
321
+ | `--concurrency <n>` | number | Avaliações paralelas (padrão: 3) |
322
+ | `--output <file>` | string | Salva relatório JSON em arquivo |
323
+
324
+ **Formato do dataset:**
325
+
326
+ ```json
327
+ [
328
+ { "input": "qual é a capital do Brasil?", "expected": "Brasília" },
329
+ { "input": "o que é TypeScript?", "expected": "superset tipado de JavaScript" }
330
+ ]
331
+ ```
332
+
333
+ **Saída:**
334
+
335
+ ```
336
+ ◆ omni eval agent: backend-dev dataset: qa.json
337
+
338
+ ✓ q1 exact
339
+ ✓ q2 contains
340
+ ✗ q3 miss
341
+
342
+ Score: 2/3 (66.7%)
343
+ ```
344
+
345
+ ---
346
+
347
+ ### `omni export`
348
+
349
+ Exporta o histórico de uma sessão como Markdown ou JSON.
350
+
351
+ ```
352
+ omni export <sessionId> [opções]
353
+ ```
354
+
355
+ | Opção | Tipo | Descrição |
356
+ |-------|------|-----------|
357
+ | `--format <format>` | `markdown` \| `json` | Formato de saída (padrão: `markdown`) |
358
+ | `--output <file>` | string | Salva em arquivo em vez de stdout |
359
+ | `--limit <n>` | number | Limita às últimas N mensagens |
360
+
361
+ ```bash
362
+ # Exportar sessão como Markdown
363
+ omni export dev1:customers
364
+
365
+ # Exportar como JSON para arquivo
366
+ omni export dev1:customers --format json --output session.json
367
+ ```
368
+
369
+ ---
370
+
371
+ ### `omni mcp serve`
372
+
373
+ Expõe todas as skills registradas como ferramentas MCP sobre stdio. Permite que clientes MCP (como Claude Desktop) chamem as skills diretamente.
374
+
375
+ ```bash
376
+ omni mcp serve
377
+ ```
378
+
379
+ O servidor usa o transporte **stdio** — adequado para ser iniciado como subprocesso por um cliente MCP.
380
+
381
+ **Configuração no Claude Desktop (`claude_desktop_config.json`):**
382
+
383
+ ```json
384
+ {
385
+ "mcpServers": {
386
+ "omni-ai": {
387
+ "command": "omni",
388
+ "args": ["mcp", "serve"]
389
+ }
390
+ }
391
+ }
392
+ ```
393
+
394
+ ---
395
+
396
+ ## Providers
397
+
398
+ ### GitHub Copilot (recomendado para usuários GitHub)
399
+
400
+ Não requer conta separada — usa o seu token GitHub existente.
401
+
402
+ ```bash
403
+ # 1. Autenticar com GitHub CLI (se ainda não fez)
404
+ gh auth login
405
+
406
+ # 2. Obter o token
407
+ gh auth token
408
+ # Copia o valor e cola no .env abaixo
409
+ ```
410
+
411
+ ```bash
412
+ # .env
413
+ GITHUB_TOKEN=ghp_...
414
+ ```
415
+
416
+ ```yaml
417
+ # config/omni-ai.yaml
418
+ defaultProvider: copilot
419
+
420
+ providers:
421
+ - name: copilot
422
+ type: copilot
423
+ apiKey: ${GITHUB_TOKEN}
424
+ baseUrl: https://api.githubcopilot.com
425
+ defaultModel: gpt-4o
426
+ ```
427
+
428
+ > **Nota:** Requer uma assinatura ativa do GitHub Copilot (Individual, Business ou Enterprise).
429
+
430
+ ---
431
+
432
+ ### Anthropic (Claude)
433
+
434
+ ```bash
435
+ # .env
436
+ ANTHROPIC_API_KEY=sk-ant-api03-...
437
+ ```
438
+
439
+ ```yaml
440
+ # config/omni-ai.yaml
441
+ defaultProvider: anthropic
442
+
443
+ providers:
444
+ - name: anthropic
445
+ type: anthropic
446
+ apiKey: ${ANTHROPIC_API_KEY}
447
+ defaultModel: claude-sonnet-4-6
448
+ ```
449
+
450
+ Como obter: [console.anthropic.com](https://console.anthropic.com) → API Keys → Create key
451
+
452
+ **Modelos disponíveis:**
453
+
454
+ | Modelo | ID | Uso recomendado |
455
+ |--------|----|-----------------|
456
+ | Claude Opus 4.7 | `claude-opus-4-7` | Raciocínio complexo, contexto longo |
457
+ | Claude Sonnet 4.6 | `claude-sonnet-4-6` | Qualidade/velocidade balanceados ✓ |
458
+ | Claude Haiku 4.5 | `claude-haiku-4-5-20251001` | Tarefas rápidas e de baixo custo |
459
+
460
+ > **Atenção:** A API Anthropic requer `temperature <= 1.0`. O adapter valida isso automaticamente.
461
+
462
+ ---
463
+
464
+ ### OpenAI (GPT)
465
+
466
+ ```bash
467
+ # .env
468
+ OPENAI_API_KEY=sk-proj-...
469
+ ```
470
+
471
+ ```yaml
472
+ # config/omni-ai.yaml
473
+ defaultProvider: openai
474
+
475
+ providers:
476
+ - name: openai
477
+ type: openai
478
+ apiKey: ${OPENAI_API_KEY}
479
+ defaultModel: gpt-4o
480
+ ```
481
+
482
+ Como obter: [platform.openai.com](https://platform.openai.com) → API keys
483
+
484
+ **Modelos disponíveis:**
485
+
486
+ | Modelo | ID | Uso recomendado |
487
+ |--------|----|-----------------|
488
+ | GPT-4o | `gpt-4o` | Multimodal, raciocínio forte |
489
+ | GPT-4o mini | `gpt-4o-mini` | Rápido, custo eficiente |
490
+ | o1 | `o1` | Raciocínio avançado |
491
+ | o3-mini | `o3-mini` | Raciocínio rápido |
492
+
493
+ ---
494
+
495
+ ### Google Gemini
496
+
497
+ ```bash
498
+ # .env
499
+ GOOGLE_API_KEY=AIza...
500
+ ```
501
+
502
+ ```yaml
503
+ # config/omni-ai.yaml
504
+ defaultProvider: google
505
+
506
+ providers:
507
+ - name: google
508
+ type: google
509
+ apiKey: ${GOOGLE_API_KEY}
510
+ defaultModel: gemini-2.0-flash
511
+ ```
512
+
513
+ Como obter: [aistudio.google.com](https://aistudio.google.com) → Get API key
514
+
515
+ **Modelos disponíveis:**
516
+
517
+ | Modelo | ID | Uso recomendado |
518
+ |--------|----|-----------------|
519
+ | Gemini 2.0 Flash | `gemini-2.0-flash` | Rápido, multimodal, custo baixo ✓ |
520
+ | Gemini 1.5 Pro | `gemini-1.5-pro` | Contexto longo (1M tokens) |
521
+
522
+ ---
523
+
524
+ ### Groq (inferência ultrarrápida)
525
+
526
+ ```bash
527
+ # .env
528
+ GROQ_API_KEY=gsk_...
529
+ ```
530
+
531
+ ```yaml
532
+ # config/omni-ai.yaml
533
+ providers:
534
+ - name: groq
535
+ type: groq
536
+ apiKey: ${GROQ_API_KEY}
537
+ defaultModel: llama-3.3-70b-versatile
538
+ ```
539
+
540
+ Como obter: [console.groq.com](https://console.groq.com) → API Keys
541
+
542
+ ---
543
+
544
+ ### Ollama (local / self-hosted)
545
+
546
+ ```yaml
547
+ # config/omni-ai.yaml
548
+ providers:
549
+ - name: ollama
550
+ type: ollama
551
+ defaultModel: llama3.2
552
+ # baseUrl padrão: http://localhost:11434/v1
553
+ ```
554
+
555
+ Não requer API key. Requer [Ollama](https://ollama.com) em execução local.
556
+
557
+ ---
558
+
559
+ ### Custom / self-hosted (Azure, vLLM, LM Studio...)
560
+
561
+ Qualquer endpoint compatível com a API OpenAI de chat completions:
562
+
563
+ ```yaml
564
+ # config/omni-ai.yaml
565
+ providers:
566
+ - name: azure
567
+ type: custom
568
+ baseUrl: https://meu-recurso.openai.azure.com/openai/deployments/gpt-4o
569
+ apiKey: ${AZURE_API_KEY}
570
+ defaultModel: gpt-4o
571
+ ```
572
+
573
+ Endpoints compatíveis: **Azure OpenAI**, **LM Studio**, **vLLM**, **Together AI**, **Mistral AI**, **Perplexity**.
574
+
575
+ ---
576
+
577
+ ### Múltiplos providers
578
+
579
+ Você pode declarar vários providers e cada agente pode usar um diferente:
580
+
581
+ ```yaml
582
+ defaultProvider: copilot
583
+
584
+ providers:
585
+ - name: copilot
586
+ type: copilot
587
+ apiKey: ${GITHUB_TOKEN}
588
+ defaultModel: gpt-4o
589
+
590
+ - name: anthropic
591
+ type: anthropic
592
+ apiKey: ${ANTHROPIC_API_KEY}
593
+ defaultModel: claude-sonnet-4-6
594
+
595
+ - name: ollama
596
+ type: custom
597
+ baseUrl: http://localhost:11434/v1
598
+ defaultModel: llama3.2
599
+ ```
600
+
601
+ No arquivo YAML do agente, basta declarar `provider: anthropic` para sobrescrever o padrão apenas para aquele agente.
602
+
603
+ ---
604
+
605
+ ## Configuração — referência completa
606
+
607
+ ### `omni-ai.yaml`
608
+
609
+ ```yaml
610
+ version: "1"
611
+
612
+ # Provider padrão para todos os agentes (a menos que o agente sobrescreva)
613
+ defaultProvider: copilot
614
+
615
+ # Diretório dos YAML de agentes (relativo à raiz do omni-ai)
616
+ agentsDir: agents
617
+
618
+ providers:
619
+ - name: copilot
620
+ type: copilot # "anthropic" | "openai" | "copilot" | "google" | "groq" | "ollama" | "custom"
621
+ apiKey: ${GITHUB_TOKEN} # referência a variável de ambiente — nunca hardcode
622
+ baseUrl: https://api.githubcopilot.com
623
+ defaultModel: gpt-4o # modelo usado quando o agente não especifica
624
+
625
+ agents:
626
+ # Agente inline — definido diretamente no config (não precisa de arquivo YAML separado)
627
+ - name: code-reviewer
628
+ description: Revisa código para qualidade, bugs e segurança
629
+ systemPrompt: |
630
+ Você é um revisor de código especialista...
631
+ skills:
632
+ - read-file
633
+ - search-code
634
+ maxIterations: 5
635
+
636
+ # Agente com override de provider/modelo
637
+ - name: doc-writer
638
+ description: Gera documentação
639
+ provider: anthropic # sobrescreve defaultProvider só para este agente
640
+ model: claude-haiku-4-5-20251001 # sobrescreve defaultModel
641
+ systemPrompt: |
642
+ Você é um redator técnico...
643
+ maxIterations: 3
644
+ ```
645
+
646
+ ### Herança de provider e modelo
647
+
648
+ ```
649
+ omni-ai.yaml
650
+ └─ defaultProvider: copilot ← se aplica a todos os agentes
651
+ └─ providers[copilot]
652
+ └─ defaultModel: gpt-4o ← se aplica a todos os agentes
653
+
654
+ agents/backend/backend-dev.yaml
655
+ ├─ provider: (ausente) → usa defaultProvider (copilot)
656
+ ├─ provider: anthropic → sobrescreve só para este agente
657
+ ├─ model: (ausente) → usa defaultModel do provider resolvido
658
+ └─ model: gpt-4o-mini → sobrescreve só para este agente
659
+ ```
660
+
661
+ ### Campos do agente YAML
662
+
663
+ | Campo | Tipo | Padrão | Descrição |
664
+ |-------|------|--------|-----------|
665
+ | `name` | `string` | obrigatório | Identificador único |
666
+ | `description` | `string` | obrigatório | O que o agente faz |
667
+ | `provider` | `string` | herda | Nome do provider — omita para usar `defaultProvider` |
668
+ | `model` | `string` | herda | ID do modelo — omita para usar `defaultModel` do provider |
669
+ | `systemPrompt` | `string` | obrigatório | Instruções do agente |
670
+ | `skills` | `string[]` | `[]` | Skills que o agente pode chamar como ferramentas |
671
+ | `maxIterations` | `number` | `10` | Máximo de iterações do loop agentico |
672
+ | `temperature` | `number` | padrão do provider | Temperatura de amostragem (0–2; max 1.0 para Anthropic) |
673
+
674
+ ---
675
+
676
+ ## Catálogo de agentes
677
+
678
+ ### Backend (7 agentes)
679
+
680
+ | Agente | Arquivo | O que faz |
681
+ |--------|---------|-----------|
682
+ | `backend-dev` | `agents/backend/backend-dev.yaml` | Orquestrador — feature NestJS completa: schema → serviço → resolver → listeners → tests |
683
+ | `backend-schema` | `agents/backend/backend-schema.yaml` | Schema DynamoDB OneTable com `defineSchema()` |
684
+ | `backend-service` | `agents/backend/backend-service.yaml` | NestJS service com CRUD, eventos, error helpers, caching |
685
+ | `backend-resolver` | `agents/backend/backend-resolver.yaml` | GraphQL resolver com padrão federation + SDL |
686
+ | `backend-listener` | `agents/backend/backend-listener.yaml` | Event listeners com `@OnEventCatcher` |
687
+ | `backend-test` | `agents/backend/backend-test.yaml` | Testes Jest de integração com DynamoDB local real |
688
+ | `backend-atom-app` | `agents/backend/backend-atom-app.yaml` | Conectores Atom framework (sessões, ARNs, roteamento de mensagens) |
689
+
690
+ ### Frontend (5 agentes)
691
+
692
+ | Agente | Arquivo | O que faz |
693
+ |--------|---------|-----------|
694
+ | `frontend-dev` | `agents/frontend/frontend-dev.yaml` | Orquestrador — feature React completa: route → componentes → hooks |
695
+ | `frontend-ui-component` | `agents/frontend/frontend-ui-component.yaml` | Componentes UI primitivos estilo shadcn/ui com CVA + Radix |
696
+ | `frontend-module-component` | `agents/frontend/frontend-module-component.yaml` | Componentes de feature conectados a dados (TanStack Query) |
697
+ | `frontend-page-route` | `agents/frontend/frontend-page-route.yaml` | Páginas TanStack Router com layouts responsivos |
698
+ | `frontend-custom-hook` | `agents/frontend/frontend-custom-hook.yaml` | Custom React hooks tipados e SSR-safe |
699
+
700
+ ### UX (5 agentes)
701
+
702
+ | Agente | Arquivo | O que faz |
703
+ |--------|---------|-----------|
704
+ | `ux-lead` | `agents/ux/ux-lead.yaml` | Orquestrador — auditoria UX completa em 10 dimensões, corrige críticos e documenta os demais |
705
+ | `ux-reviewer` | `agents/ux/ux-reviewer.yaml` | Revisão UX detalhada com findings por severidade (Critical / Moderate / Low) |
706
+ | `ux-states` | `agents/ux/ux-states.yaml` | Componentes de estado: Skeleton, Empty, Error e Success |
707
+ | `ux-forms` | `agents/ux/ux-forms.yaml` | Formulários com validação, autocomplete, acessibilidade e estados de loading |
708
+ | `ux-motion` | `agents/ux/ux-motion.yaml` | Micro-interações e transições com `motion-safe:` obrigatório |
709
+
710
+ ### QA (4 agentes)
711
+
712
+ | Agente | Arquivo | O que faz |
713
+ |--------|---------|-----------|
714
+ | `qa-lead` | `agents/qa/qa-lead.yaml` | Orquestrador — classifica arquivos, delega aos agentes especializados e emite veredicto de merge |
715
+ | `qa-frontend` | `agents/qa/qa-frontend.yaml` | Valida React/TypeScript: imports, tokens Tailwind, responsividade, acessibilidade |
716
+ | `qa-ux` | `agents/qa/qa-ux.yaml` | Valida UX: feedback states, formulários, motion, content tone |
717
+ | `qa-backend` | `agents/qa/qa-backend.yaml` | Valida NestJS: services, resolvers, schema GraphQL, listeners, testes |
718
+
719
+ ---
720
+
721
+ ## Skills disponíveis
722
+
723
+ As skills são as ferramentas que os agentes podem chamar durante o loop agentico. Todas operam dentro do `cwd` (diretório do projeto alvo) — nunca fora dele. Disponíveis via subpath exports de `@ftarganski/omni-ai`.
724
+
725
+ **Filesystem (`@ftarganski/omni-ai/skills/fs`)**
726
+
727
+ | Skill | O que faz |
728
+ |-------|-----------|
729
+ | `read-file` | Lê o conteúdo completo de um arquivo |
730
+ | `write-file` | Escreve ou sobrescreve um arquivo (cria diretórios automaticamente) |
731
+ | `list-directory` | Lista arquivos em um diretório (recursivo, filtro por extensão) |
732
+
733
+ **Código (`@ftarganski/omni-ai/skills/code`)**
734
+
735
+ | Skill | O que faz |
736
+ |-------|-----------|
737
+ | `search-code` | Busca texto ou regex em arquivos TypeScript/TSX |
738
+
739
+ **UX (`@ftarganski/omni-ai/skills/ux`)**
740
+
741
+ | Skill | O que faz |
742
+ |-------|-----------|
743
+ | `audit-accessibility` | Scan heurístico de a11y em TSX (alt, aria-label, foco, contraste...) |
744
+
745
+ **Git (`@ftarganski/omni-ai/skills/git`)**
746
+
747
+ | Skill | O que faz |
748
+ |-------|-----------|
749
+ | `git-status` | Retorna o status atual do repositório |
750
+ | `git-diff` | Retorna o diff de um arquivo ou do repositório |
751
+ | `git-log` | Lista commits recentes com autoria e mensagem |
752
+ | `git-commit-message` | Gera mensagem de commit a partir de um diff (chamada LLM) |
753
+
754
+ **HTTP (`@ftarganski/omni-ai/skills/http`)**
755
+
756
+ | Skill | O que faz |
757
+ |-------|-----------|
758
+ | `http-request` | Requisição HTTP autenticada (Bearer, Basic, OAuth2 client-credentials) |
759
+
760
+ **Multimodal (`@ftarganski/omni-ai/skills/multimodal`)**
761
+
762
+ | Skill | O que faz |
763
+ |-------|-----------|
764
+ | `analyze-image` | Analisa screenshots, diagramas ou mockups via providers com visão |
765
+
766
+ **Backend (`@ftarganski/omni-ai/skills/backend`)**
767
+
768
+ | Skill | O que faz |
769
+ |-------|-----------|
770
+ | `find-code-pattern` | Localiza padrões de código em arquivos TypeScript |
771
+ | `analyze-nestjs-module` | Analisa estrutura de módulos NestJS |
772
+ | `analyze-dynamo-schema` | Analisa schemas DynamoDB/TableService |
773
+ | `analyze-graphql-schema` | Analisa schemas GraphQL |
774
+
775
+ **Frontend (`@ftarganski/omni-ai/skills/frontend`)**
776
+
777
+ | Skill | O que faz |
778
+ |-------|-----------|
779
+ | `find-component-pattern` | Localiza padrões em componentes React/TSX |
780
+ | `analyze-component` | Analisa props, hooks e estrutura de componentes |
781
+ | `analyze-module-structure` | Analisa a estrutura de módulos frontend |
782
+
783
+ **QA (`@ftarganski/omni-ai/skills/qa`)**
784
+
785
+ | Skill | O que faz |
786
+ |-------|-----------|
787
+ | `find-test-pattern` | Localiza padrões em arquivos de teste |
788
+ | `analyze-test-coverage` | Analisa cobertura de testes por módulo |
789
+
790
+ ### Segurança das skills de filesystem
791
+
792
+ `read-file`, `write-file` e `list-directory` resolvem todos os caminhos relativos ao `cwd` e **rejeitam qualquer path que escape o diretório do projeto** (bloqueando ataques de path traversal como `../../../etc/passwd`).
793
+
794
+ ---
795
+
796
+ ## Memória e sessões
797
+
798
+ ### Via CLI (--session)
799
+
800
+ ```bash
801
+ # Primeira execução — sessão é criada e armazenada em ~/.omni-ai/sessions.db
802
+ omni run backend-dev "crie o módulo de pedidos com CRUD" --session dev1:orders
803
+
804
+ # Segunda execução — o agente carrega o histórico da sessão anterior como contexto
805
+ omni run backend-dev "adicione o listener de busca ao módulo de pedidos" --session dev1:orders
806
+
807
+ # Consulta de contexto anterior
808
+ omni run backend-dev "quais arquivos você criou na sessão anterior?" --session dev1:orders
809
+ ```
810
+
811
+ O ID de sessão segue o formato `"resourceId:threadId"`. Use `resourceId` para identificar o usuário ou projeto, e `threadId` para a feature ou conversa específica.
812
+
813
+ ### Via API programática
814
+
815
+ ```typescript
816
+ import { createRuntime } from "@ftarganski/omni-ai";
817
+ import { SQLiteMemoryStore, ObservationMaskingCompactor } from "@ftarganski/omni-ai/memory";
818
+
819
+ const runtime = await createRuntime({
820
+ skills: [/* suas skills extras */],
821
+ });
822
+
823
+ // Sem memória — execução simples
824
+ const result = await runtime.run("backend-dev", "crie o módulo de clientes");
825
+ console.log(result.output);
826
+
827
+ // Com memória entre sessões
828
+ const store = new SQLiteMemoryStore({ path: "./sessions.db" });
829
+
830
+ const result2 = await runtime.run(
831
+ "backend-dev",
832
+ "adicione busca ao módulo de clientes",
833
+ {
834
+ session: { resourceId: "user-42", threadId: "feature-customers" },
835
+ memoryStore: store,
836
+ }
837
+ );
838
+ ```
839
+
840
+ ### Compactors — redução de consumo de tokens
841
+
842
+ Sem compaction, cada iteração reencaminha todo o histórico:
843
+
844
+ ```
845
+ Iteração 1: 1.000 tokens
846
+ Iteração 2: 3.500 tokens
847
+ Iteração 3: 8.200 tokens → Total: 26.700 tokens
848
+ Iteração 4: 14.000 tokens
849
+ ```
850
+
851
+ Com `ObservationMaskingCompactor`:
852
+
853
+ ```
854
+ Iteração 1: 1.000 tokens
855
+ Iteração 2: 3.500 tokens
856
+ Iteração 3: 1.800 tokens ← resultados antigos de tool mascarados
857
+ Iteração 4: 2.100 tokens → Total: 8.400 tokens (redução de 68%)
858
+ ```
859
+
860
+ | Compactor | Estratégia | Chamadas LLM | Ideal para |
861
+ |-----------|-----------|--------------|-----------|
862
+ | `ObservationMaskingCompactor` | Substitui corpo de tool results antigos por `[masked ~N tokens]` | 0 | Agentes intensivos em leitura de arquivos |
863
+ | `SummaryCompactor` | LLM resume mensagens antigas, mantém N recentes verbatim | 1 por trigger | Conversas longas, raciocínio multi-step |
864
+
865
+ ---
866
+
867
+ ### Busca semântica com embeddings
868
+
869
+ `SemanticMemoryStore` substitui a busca por palavras-chave (FTS5) por similaridade de coseno usando embeddings do provider.
870
+
871
+ ```typescript
872
+ import { createRuntime } from "@ftarganski/omni-ai";
873
+ import { SQLiteMemoryStore, SemanticMemoryStore } from "@ftarganski/omni-ai/memory";
874
+ import { OpenAIProvider } from "@ftarganski/omni-ai/provider-openai";
875
+
876
+ // Provider com suporte a embeddings (capabilities.embedding = true)
877
+ const embeddingProvider = new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY! });
878
+
879
+ // Persiste mensagens no SQLite + busca semântica em memória
880
+ const store = new SemanticMemoryStore(
881
+ embeddingProvider,
882
+ new SQLiteMemoryStore({ path: "./sessions.db" })
883
+ );
884
+
885
+ const runtime = await createRuntime({ skills, memoryStore: store });
886
+ ```
887
+
888
+ **Busca por similaridade:**
889
+
890
+ ```typescript
891
+ const results = await store.search(
892
+ { resourceId: "user1", threadId: "thread1" },
893
+ "como foi implementado o módulo de orders?",
894
+ 5 // topK
895
+ );
896
+ // results: [{ content: "...", score: 0.91 }, ...]
897
+ ```
898
+
899
+ **`VectorIndex`** — índice vetorial in-memory para uso direto:
900
+
901
+ ```typescript
902
+ import { VectorIndex } from "@ftarganski/omni-ai/memory";
903
+
904
+ const index = new VectorIndex<string>();
905
+ index.add("doc1", embeddingVector1);
906
+ index.add("doc2", embeddingVector2);
907
+
908
+ const results = index.query(queryVector, 3); // [{ id: "doc1", score: 0.94 }, ...]
909
+ ```
910
+
911
+ ---
912
+
913
+ ## Estrutura do repositório
914
+
915
+ ```
916
+ omni-ai/
917
+
918
+ ├── packages/ # pacotes npm (pnpm workspaces)
919
+ │ ├── core/ # @omni-ai/core
920
+ │ │ └── src/
921
+ │ │ ├── types.ts # IProvider, ISkill, IAgent, IMemoryStore...
922
+ │ │ ├── config/
923
+ │ │ │ ├── schema.ts # Zod schema do omni-ai.yaml
924
+ │ │ │ └── loader.ts # loadConfig() com substituição de env vars
925
+ │ │ ├── agents/
926
+ │ │ │ ├── agent.ts # Loop agentico + integração de memória
927
+ │ │ │ └── loader.ts # loadAgent() — carrega YAML + resolve provider
928
+ │ │ ├── providers/registry.ts # ProviderRegistry (factory por type string)
929
+ │ │ ├── skills/registry.ts # SkillRegistry
930
+ │ │ └── bootstrap.ts # createRuntime() — API de alto nível
931
+ │ │
932
+ │ ├── provider-anthropic/ # @omni-ai/provider-anthropic
933
+ │ │ └── src/
934
+ │ │ ├── provider.ts # AnthropicProvider implements IProvider
935
+ │ │ ├── mappers.ts # Conversão omni-ai ↔ Anthropic SDK types
936
+ │ │ └── index.ts # Registra "anthropic" no ProviderRegistry
937
+ │ │
938
+ │ ├── provider-openai/ # @omni-ai/provider-openai
939
+ │ │ └── src/
940
+ │ │ ├── provider.ts # OpenAIProvider implements IProvider
941
+ │ │ ├── mappers.ts # Conversão omni-ai ↔ OpenAI SDK types
942
+ │ │ └── index.ts # Registra "openai" e "copilot" no ProviderRegistry
943
+ │ │
944
+ │ ├── memory/ # @omni-ai/memory
945
+ │ │ └── src/
946
+ │ │ ├── stores/
947
+ │ │ │ ├── in-memory.ts # InMemoryStore (padrão, sem persistência)
948
+ │ │ │ ├── sqlite.ts # SQLiteMemoryStore (arquivo local, FTS5)
949
+ │ │ │ └── semantic-memory-store.ts # SemanticMemoryStore (busca por cosine similarity)
950
+ │ │ ├── compactors/
951
+ │ │ │ ├── observation-masking.ts # Mascara tool results antigos (zero LLM)
952
+ │ │ │ └── summary.ts # Resumo por LLM (1 chamada por trigger)
953
+ │ │ ├── vector.ts # VectorIndex + cosineSimilarity
954
+ │ │ └── utils.ts # estimateTokens() compartilhado
955
+ │ │
956
+ │ ├── skills-fs/ # @omni-ai/skills-fs
957
+ │ │ └── src/
958
+ │ │ ├── read-file.ts # Lê arquivo (com validação de path traversal)
959
+ │ │ ├── write-file.ts # Escreve arquivo (com validação de path)
960
+ │ │ └── list-directory.ts # Lista diretório (com validação de path)
961
+ │ │
962
+ │ ├── skills-code/ # @omni-ai/skills-code
963
+ │ │ └── src/
964
+ │ │ └── search-code.ts # Busca texto/regex em arquivos TypeScript
965
+ │ │
966
+ │ ├── skills-ux/ # @omni-ai/skills-ux
967
+ │ │ └── src/
968
+ │ │ └── audit-accessibility.ts # Scan heurístico a11y de componentes TSX
969
+ │ │
970
+ │ └── cli/ # @omni-ai/cli
971
+ │ └── src/
972
+ │ ├── bin.ts # Entry point, carrega .env
973
+ │ ├── commands/
974
+ │ │ ├── run.ts # omni run <agent> "<prompt>"
975
+ │ │ ├── chain.ts # omni chain "<prompt>" <agent1> <agent2>...
976
+ │ │ ├── list.ts # omni list agents|skills|providers
977
+ │ │ └── init.ts # omni init — wizard interativo
978
+ │ └── utils/
979
+ │ ├── format.ts # Output formatado (tokens, iterações, erros)
980
+ │ └── config-path.ts # Resolve caminho do omni-ai.yaml
981
+
982
+ ├── agents/ # Definições YAML dos agentes (21 agentes)
983
+ │ ├── backend/ # 7 agentes NestJS/TypeScript
984
+ │ ├── frontend/ # 5 agentes React/TypeScript
985
+ │ ├── ux/ # 5 agentes UX
986
+ │ └── qa/ # 4 agentes QA
987
+
988
+ ├── docs/ # Documentação
989
+ │ ├── providers/
990
+ │ │ ├── anthropic.md # Setup detalhado Anthropic
991
+ │ │ ├── openai.md # Setup detalhado OpenAI
992
+ │ │ └── copilot.md # Setup detalhado GitHub Copilot
993
+ │ └── templates/
994
+ │ ├── agent.yaml # Template para novos agentes
995
+ │ └── skill.ts # Template para novas skills
996
+
997
+ ├── config/
998
+ │ └── omni-ai.example.yaml # Template de configuração (copie → omni-ai.yaml)
999
+
1000
+ ├── .env.example # Template de variáveis de ambiente
1001
+ └── tsconfig.ide.json # Paths para resolução de tipos no VS Code
1002
+ ```
1003
+
1004
+ ---
1005
+
1006
+ ## Usando de outro projeto
1007
+
1008
+ O `omni-ai` é um repositório central — os agentes e o config ficam nele. Você usa o CLI de dentro de qualquer projeto alvo.
1009
+
1010
+ ### Setup único (instalação global)
1011
+
1012
+ ```bash
1013
+ npm install -g @ftarganski/omni-ai
1014
+ ```
1015
+
1016
+ ### Uso do dia a dia
1017
+
1018
+ ```bash
1019
+ # 1. Entrar no projeto alvo
1020
+ cd /caminho/para/meu-projeto
1021
+
1022
+ # 2. Rodar agentes normalmente
1023
+ omni run backend-dev "crie o módulo de produtos"
1024
+ omni run frontend-dev "crie a página de listagem de produtos"
1025
+ omni run qa-lead "valide src/products/"
1026
+ omni run ux-reviewer "audite src/components/modules/Products/"
1027
+ ```
1028
+
1029
+ As skills sempre operam em `/caminho/para/meu-projeto` — o agente lê, escreve e busca arquivos nesse diretório, nunca fora dele.
1030
+
1031
+ ### Alternativa sem instalação global
1032
+
1033
+ ```bash
1034
+ # Usando node diretamente (após pnpm build)
1035
+ node /caminho/para/omni-ai/bundle/omni-ai/dist/cli/bin.js run backend-dev "..."
1036
+
1037
+ # Ou com alias no shell (~/.bashrc, ~/.zshrc ou $PROFILE no PowerShell)
1038
+ alias omni="node /caminho/para/omni-ai/bundle/omni-ai/dist/cli/bin.js"
1039
+ ```
1040
+
1041
+ ---
1042
+
1043
+ ## Estendendo o framework
1044
+
1045
+ ### Criar um agente personalizado
1046
+
1047
+ Copie `docs/templates/agent.yaml` para `agents/<domínio>/<domínio>-<função>.yaml`:
1048
+
1049
+ ```yaml
1050
+ name: my-agent
1051
+ description: O que este agente faz em uma linha
1052
+ # provider: anthropic # opcional — herda defaultProvider do omni-ai.yaml
1053
+ # model: gpt-4o-mini # opcional — herda defaultModel do provider
1054
+ systemPrompt: |
1055
+ Você é um assistente especializado em...
1056
+ Descreva as restrições, formato de output e comportamento.
1057
+ skills:
1058
+ - read-file
1059
+ - search-code
1060
+ - write-file
1061
+ maxIterations: 10
1062
+ temperature: 0.2
1063
+ ```
1064
+
1065
+ O arquivo estará disponível via `omni run my-agent "..."` imediatamente — sem rebuild.
1066
+
1067
+ ### Criar uma skill personalizada
1068
+
1069
+ Copie `docs/templates/skill.ts` e implemente `ISkill`:
1070
+
1071
+ ```typescript
1072
+ import type { ISkill } from "@ftarganski/omni-ai";
1073
+ import { z } from "zod";
1074
+
1075
+ const InputSchema = z.object({
1076
+ query: z.string().describe("Termo a buscar"),
1077
+ });
1078
+
1079
+ type Input = z.infer<typeof InputSchema>;
1080
+
1081
+ export const myDatabaseSkill: ISkill<Input, string[]> = {
1082
+ name: "search-database",
1083
+ description: "Busca registros no banco de dados externo",
1084
+
1085
+ async execute(input: Input): Promise<string[]> {
1086
+ const { query } = InputSchema.parse(input);
1087
+ // sua lógica aqui
1088
+ return await fetchFromExternalApi(query);
1089
+ },
1090
+ };
1091
+ ```
1092
+
1093
+ Registre a skill ao criar o runtime:
1094
+
1095
+ ```typescript
1096
+ import { createRuntime } from "@ftarganski/omni-ai";
1097
+ import { myDatabaseSkill } from "./my-database-skill.js";
1098
+
1099
+ const runtime = await createRuntime({
1100
+ skills: [myDatabaseSkill],
1101
+ });
1102
+ ```
1103
+
1104
+ Ou passe diretamente no CLI customizando o `run.ts`.
1105
+
1106
+ ### Criar um provider personalizado
1107
+
1108
+ Implemente `IProvider` de `@ftarganski/omni-ai`:
1109
+
1110
+ ```typescript
1111
+ import type { IProvider, CompletionRequest, CompletionResponse } from "@ftarganski/omni-ai";
1112
+ import { registerProvider } from "@ftarganski/omni-ai";
1113
+
1114
+ class MyProvider implements IProvider {
1115
+ readonly name: string;
1116
+ readonly capabilities = {
1117
+ chat: true, embedding: false, streaming: false, toolUse: true, vision: false,
1118
+ };
1119
+
1120
+ constructor(private readonly config: { apiKey: string; name: string }) {
1121
+ this.name = config.name;
1122
+ }
1123
+
1124
+ async complete(request: CompletionRequest): Promise<CompletionResponse> {
1125
+ const response = await callMyApi(request);
1126
+ return {
1127
+ content: response.text,
1128
+ toolCalls: [],
1129
+ usage: { inputTokens: response.in, outputTokens: response.out },
1130
+ model: request.model ?? "my-model",
1131
+ provider: this.name,
1132
+ };
1133
+ }
1134
+ }
1135
+
1136
+ // Registrar o type string para o omni-ai.yaml
1137
+ registerProvider("my-provider", (config) => new MyProvider(config));
1138
+ ```
1139
+
1140
+ Adicione o `docs/providers/<nome>.md` e declare no `omni-ai.yaml`:
1141
+
1142
+ ```yaml
1143
+ providers:
1144
+ - name: my-provider
1145
+ type: my-provider
1146
+ apiKey: ${MY_API_KEY}
1147
+ defaultModel: my-model-v1
1148
+ ```
1149
+
1150
+ ---
1151
+
1152
+ ## Recursos avançados
1153
+
1154
+ ### Agentes paralelos — `parallel()`
1155
+
1156
+ Executa múltiplos agentes ao mesmo tempo no mesmo input e agrega os resultados.
1157
+
1158
+ ```typescript
1159
+ import { createRuntime, parallel } from "@ftarganski/omni-ai";
1160
+
1161
+ const runtime = await createRuntime({ skills });
1162
+
1163
+ const result = await parallel(runtime, {
1164
+ agents: ["backend-dev", "qa-backend", "ux-reviewer"],
1165
+ input: "revise o módulo de orders para qualidade, testes e acessibilidade",
1166
+ });
1167
+
1168
+ for (const [agent, outcome] of Object.entries(result.results)) {
1169
+ if ("error" in outcome) {
1170
+ console.error(`${agent}: ${outcome.error}`);
1171
+ } else {
1172
+ console.log(`${agent} (${outcome.iterations} iterações):\n${outcome.output}\n`);
1173
+ }
1174
+ }
1175
+
1176
+ console.log(`Tokens totais: ${result.usage.inputTokens + result.usage.outputTokens}`);
1177
+ ```
1178
+
1179
+ Um agente com falha não cancela os demais — `parallel()` usa `Promise.allSettled` internamente.
1180
+
1181
+ ---
1182
+
1183
+ ### SkillMiddleware
1184
+
1185
+ Intercepção configurável ao redor de cada chamada de skill. Útil para logging, rate-limiting, cache e auditoria.
1186
+
1187
+ ```typescript
1188
+ import { createRuntime } from "@ftarganski/omni-ai";
1189
+ import type { SkillMiddlewareFn } from "@ftarganski/omni-ai";
1190
+
1191
+ // Middleware de logging
1192
+ const loggingMiddleware: SkillMiddlewareFn = async (name, input, ctx, next) => {
1193
+ console.time(`skill:${name}`);
1194
+ const result = await next();
1195
+ console.timeEnd(`skill:${name}`);
1196
+ return result;
1197
+ };
1198
+
1199
+ // Middleware de cache em memória
1200
+ const cache = new Map<string, unknown>();
1201
+ const cachingMiddleware: SkillMiddlewareFn = async (name, input, ctx, next) => {
1202
+ const key = `${name}:${JSON.stringify(input)}`;
1203
+ if (cache.has(key)) return cache.get(key);
1204
+ const result = await next();
1205
+ cache.set(key, result);
1206
+ return result;
1207
+ };
1208
+
1209
+ const runtime = await createRuntime({ skills });
1210
+
1211
+ // Middleware configurado por agente no YAML ou programaticamente
1212
+ const result = await runtime.run("backend-dev", "revise os arquivos em src/", {
1213
+ middleware: [loggingMiddleware, cachingMiddleware],
1214
+ });
1215
+ ```
1216
+
1217
+ A cadeia executa na ordem de declaração: cada middleware chama `next()` para passar o controle ao próximo, com a skill real no fundo da pilha.
1218
+
1219
+ ---
1220
+
1221
+ ### MCP — Model Context Protocol
1222
+
1223
+ #### Servidor: expor skills como ferramentas MCP
1224
+
1225
+ ```typescript
1226
+ import { createMcpServer } from "@ftarganski/omni-ai/mcp";
1227
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1228
+ import { readFileSkill, writeFileSkill } from "@ftarganski/omni-ai/skills/fs";
1229
+
1230
+ const server = createMcpServer([readFileSkill, writeFileSkill], { name: "omni-ai" });
1231
+ await server.connect(new StdioServerTransport());
1232
+ ```
1233
+
1234
+ Via CLI:
1235
+
1236
+ ```bash
1237
+ omni mcp serve
1238
+ ```
1239
+
1240
+ #### Cliente: consumir um servidor MCP como skills
1241
+
1242
+ ```typescript
1243
+ import { connectMcpSkills } from "@ftarganski/omni-ai/mcp";
1244
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
1245
+ import { createRuntime } from "@ftarganski/omni-ai";
1246
+
1247
+ // Conecta a um servidor MCP externo e descobre seus tools
1248
+ const transport = new StdioClientTransport({ command: "npx", args: ["-y", "@my/mcp-server"] });
1249
+ const mcpSkills = await connectMcpSkills(transport);
1250
+
1251
+ // Usa os tools remotos como qualquer ISkill nativa
1252
+ const runtime = await createRuntime({ skills: mcpSkills });
1253
+ const result = await runtime.run("backend-dev", "pesquise na documentação o contrato da API");
1254
+ ```
1255
+
1256
+ ---
1257
+
1258
+ ## Interfaces TypeScript principais
1259
+
1260
+ ```typescript
1261
+ // @ftarganski/omni-ai
1262
+
1263
+ interface IProvider {
1264
+ readonly name: string;
1265
+ readonly capabilities: ProviderCapabilities;
1266
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
1267
+ embed?(request: EmbeddingRequest): Promise<EmbeddingResponse>; // requer capabilities.embedding = true
1268
+ }
1269
+
1270
+ interface ProviderCapabilities {
1271
+ chat: boolean;
1272
+ embedding: boolean;
1273
+ streaming: boolean; // suporte a onToken em CompletionRequest
1274
+ toolUse: boolean;
1275
+ vision: boolean;
1276
+ }
1277
+
1278
+ interface CompletionRequest {
1279
+ messages: Message[];
1280
+ model?: string;
1281
+ temperature?: number;
1282
+ systemPrompt?: string;
1283
+ tools?: ToolDefinition[];
1284
+ onToken?: (chunk: string) => void; // habilita streaming chunk a chunk
1285
+ }
1286
+
1287
+ interface ISkill<TInput = unknown, TOutput = unknown> {
1288
+ readonly name: string;
1289
+ readonly description: string;
1290
+ execute(input: TInput, ctx: SkillContext): Promise<TOutput>;
1291
+ }
1292
+
1293
+ interface IAgent {
1294
+ readonly config: AgentConfig;
1295
+ run(options: AgentRunOptions): Promise<AgentRunResult>;
1296
+ }
1297
+
1298
+ // Intercepta a execução de cada skill — chame next() para continuar a cadeia
1299
+ type SkillMiddlewareFn = (
1300
+ name: string,
1301
+ input: unknown,
1302
+ ctx: SkillContext,
1303
+ next: () => Promise<unknown>
1304
+ ) => Promise<unknown>;
1305
+
1306
+ interface AgentConfig {
1307
+ name: string;
1308
+ description: string;
1309
+ provider?: string; // opcional — herda defaultProvider
1310
+ model?: string; // opcional — herda defaultModel do provider
1311
+ systemPrompt: string;
1312
+ skills?: string[];
1313
+ maxIterations?: number; // padrão: 10
1314
+ temperature?: number;
1315
+ memory?: MemoryConfig;
1316
+ middleware?: SkillMiddlewareFn[]; // interceptação de tool calls
1317
+ }
1318
+
1319
+ interface AgentRunOptions {
1320
+ input: string;
1321
+ context?: Record<string, unknown>;
1322
+ session?: SessionId; // habilita persistência de memória
1323
+ onToken?: (chunk: string) => void; // habilita streaming de tokens em tempo real
1324
+ }
1325
+
1326
+ interface AgentRunResult {
1327
+ output: string;
1328
+ iterations: number;
1329
+ usage?: { inputTokens: number; outputTokens: number };
1330
+ }
1331
+
1332
+ interface SessionId {
1333
+ resourceId: string; // identificador estável (ex: user ID, workspace ID)
1334
+ threadId: string; // identificador da conversa ou feature
1335
+ }
1336
+ ```
1337
+
1338
+ ---
1339
+
1340
+ ## Arquitetura de pacotes
1341
+
1342
+ O npm publica um único pacote com subpath exports:
1343
+
1344
+ ```
1345
+ @ftarganski/omni-ai ← core: Agent, Runtime, ISkill, IProvider...
1346
+ @ftarganski/omni-ai/skills ← todas as skills
1347
+ @ftarganski/omni-ai/skills/fs ← read-file, write-file, list-directory
1348
+ @ftarganski/omni-ai/skills/git ← git-diff, git-log, git-status, git-commit-message
1349
+ @ftarganski/omni-ai/skills/code ← search-code
1350
+ @ftarganski/omni-ai/skills/http ← http-request
1351
+ @ftarganski/omni-ai/skills/ux ← audit-accessibility
1352
+ @ftarganski/omni-ai/skills/multimodal ← analyze-image
1353
+ @ftarganski/omni-ai/skills/backend ← analyze-dynamo-schema, analyze-graphql-schema, ...
1354
+ @ftarganski/omni-ai/skills/frontend ← analyze-component, analyze-module-structure, ...
1355
+ @ftarganski/omni-ai/skills/qa ← analyze-test-coverage, find-test-pattern
1356
+ @ftarganski/omni-ai/memory ← SQLiteMemoryStore, InMemoryStore, compactors, VectorIndex
1357
+ @ftarganski/omni-ai/mcp ← createMcpServer, connectMcpSkills, McpSkill
1358
+ @ftarganski/omni-ai/provider-anthropic ← AnthropicProvider
1359
+ @ftarganski/omni-ai/provider-openai ← OpenAIProvider (+ Copilot, Groq, Ollama)
1360
+ @ftarganski/omni-ai/provider-google ← GoogleProvider
1361
+ bin: omni ← CLI completo
1362
+ ```
1363
+
1364
+ Internamente o repositório é um monorepo com pacotes separados (`packages/core`, `packages/skills`, etc.) que são bundlados pelo tsup no pacote único publicado.
1365
+
1366
+ ---
1367
+
1368
+ ## Comandos de desenvolvimento
1369
+
1370
+ ```bash
1371
+ # Instalar dependências
1372
+ pnpm install
1373
+
1374
+ # Build de todos os pacotes
1375
+ pnpm build
1376
+
1377
+ # Type-check sem build
1378
+ pnpm typecheck
1379
+
1380
+ # Lint em todos os pacotes
1381
+ pnpm lint
1382
+
1383
+ # Rodar testes
1384
+ pnpm test
1385
+
1386
+ # Build de um pacote interno específico
1387
+ pnpm --filter @omni-ai/core build
1388
+
1389
+ # Reconstruir e testar o CLI
1390
+ pnpm build && omni list agents
1391
+ ```
1392
+
1393
+ ---
1394
+
1395
+ ## Roadmap
1396
+
1397
+ ### Concluído
1398
+
1399
+ **Pacote publicado**
1400
+ - [x] `@ftarganski/omni-ai` — pacote único com todos os subpaths, bin `omni`, bundlado via tsup
1401
+
1402
+ **Internamente (monorepo, não publicados)**
1403
+ - [x] core — interfaces, ProviderRegistry, SkillRegistry, config schema (Zod), `parallel()`, `SkillMiddleware`
1404
+ - [x] memory — InMemoryStore, SQLiteMemoryStore, SemanticMemoryStore, VectorIndex, ObservationMaskingCompactor, SummaryCompactor
1405
+ - [x] mcp — servidor MCP (expõe skills como tools) e cliente MCP (`McpSkill`, `connectMcpSkills`)
1406
+ - [x] provider-anthropic — adapter completo com mapeamento de tipos, tool use e streaming
1407
+ - [x] provider-openai — cobre OpenAI, GitHub Copilot, Groq, Ollama e qualquer endpoint OpenAI-compatible
1408
+ - [x] provider-google — adapter Google Gemini com chat, vision e embeddings
1409
+ - [x] skills — 20 skills em 8 subpaths: fs, code, ux, git, http, multimodal, backend, frontend, qa
1410
+ - [x] cli — `omni run`, `omni list`, `omni chain`, `omni init`, `omni new`, `omni serve`, `omni watch`, `omni eval`, `omni export`, `omni mcp serve`
1411
+
1412
+ **Core**
1413
+ - [x] Bootstrap `createRuntime()` — API de alto nível para uso programático
1414
+ - [x] 21 agentes prontos — backend (7), frontend (5), ux (5), qa (4)
1415
+ - [x] Herança de provider/modelo — agentes herdam do config, podem sobrescrever
1416
+ - [x] Agentes inline — definição direta no `omni-ai.yaml`
1417
+ - [x] Streaming de tokens em tempo real
1418
+ - [x] Memória e sessões — SQLite persistente com FTS5 e busca semântica por embeddings
1419
+ - [x] Compactors — redução automática de contexto (masking + summarization)
1420
+ - [x] Retry automático com backoff exponencial + fallback de provider
1421
+ - [x] `SkillMiddleware` — cadeia de interceptação configurável por agente
1422
+ - [x] `parallel()` — execução concorrente de múltiplos agentes com agregação de resultados
1423
+ - [x] Suporte multimodal — `ContentPart[]` em mensagens; `analyze-image` skill
1424
+ - [x] Compatibilidade MCP — `omni mcp serve` (stdio), `McpSkill` para consumir servers externos
1425
+ - [x] 296 testes automatizados — 41 arquivos, cobertura ≥ 80% em todas as métricas
1426
+ - [x] Biome — linting e formatação unificados em todos os pacotes
1427
+ - [x] CI/CD — GitHub Actions: lint → build → typecheck → test; branch protection; publish workflow
1428
+
1429
+ ### Próximos passos
1430
+
1431
+ **CLI & DX**
1432
+ - [x] `omni new` — scaffold interativo para criar agente, skill ou provider a partir de template
1433
+ - [x] `omni eval` — avaliação em lote: roda agente contra dataset de `(input, expected)` e reporta acurácia
1434
+ - [x] `omni serve` — inicia servidor HTTP local para chamar agentes via REST ou SSE (sem CLI)
1435
+ - [x] `omni watch` — reexecuta agente automaticamente quando arquivos do projeto mudam (modo dev)
1436
+ - [x] `omni export` — exporta histórico de sessão em markdown ou JSON
1437
+
1438
+ **Providers & resiliência**
1439
+ - [x] `@omni-ai/provider-google` — adapter para Gemini 1.5 / 2.0 (chat, vision, embeddings)
1440
+ - [x] Suporte a Groq — modelos Llama/DeepSeek via LPU (free tier, sem cartão)
1441
+ - [x] Suporte a Ollama — modelos locais sem API key (Llama, Qwen, Phi, DeepSeek)
1442
+ - [x] Retry automático com backoff exponencial — recuperação transparente de rate-limit e erros 5xx
1443
+ - [x] Fallback de provider — rota pedidos para um provider secundário quando o primário falha
1444
+
1445
+ **Skills**
1446
+ - [x] `@omni-ai/skills-git` — git status, diff, log, commit message (para agentes de review e release)
1447
+ - [x] `@omni-ai/skills-http` — chamadas HTTP autenticadas (OAuth/Bearer) para integrar APIs externas
1448
+ - [x] Suporte multimodal — skill `analyze-image` para análise de screenshots, diagramas e mockups
1449
+
1450
+ **Core**
1451
+ - [x] Compatibilidade MCP (Model Context Protocol) — expor skills como tools MCP e consumir servidores MCP externos
1452
+ - [x] Agentes paralelos — `parallel()` wrapper para rodar agentes concorrentemente e agregar resultados
1453
+ - [x] `SkillMiddleware` — hooks de interceptação para logging, rate-limiting e cache de tool calls
1454
+ - [x] Publicação npm — publicar os pacotes `@omni-ai/*` no registro público do npm
1455
+
1456
+ ---
1457
+
1458
+ ## Troubleshooting
1459
+
1460
+ **`omni: command not found`**
1461
+ O CLI não está vinculado globalmente. Execute `pnpm --filter @omni-ai/cli link --global` na raiz do `omni-ai`, ou use `node packages/cli/dist/bin.js` diretamente.
1462
+
1463
+ **`Provider "anthropic" not found in config`**
1464
+ O arquivo `config/omni-ai.yaml` não existe ou não declara o provider. Execute `omni init` para criá-lo, ou copie `config/omni-ai.example.yaml`.
1465
+
1466
+ **`Error: ANTHROPIC_API_KEY is not set`**
1467
+ A variável de ambiente não está carregada. Verifique se `.env` existe e contém a chave. O CLI carrega `.env` automaticamente, mas você pode validar com `node -e "require('dotenv').config(); console.log(process.env.ANTHROPIC_API_KEY)"`.
1468
+
1469
+ **`maxIterations exceeded`**
1470
+ O agente atingiu o limite de iterações sem concluir. Aumente `maxIterations` no YAML do agente ou torne o prompt mais específico para reduzir o número de tool calls.
1471
+
1472
+ **Tokens consumidos muito altos**
1473
+ Use `ObservationMaskingCompactor` via API programática para mascarar tool results antigos. Reduz o contexto em até 70% em agentes intensivos em leitura de arquivos.
1474
+
1475
+ **`Access denied: path resolves outside the working directory`**
1476
+ O agente tentou acessar um arquivo fora do `cwd`. Execute o comando de dentro do diretório do projeto alvo, ou verifique se o agente está usando paths relativos corretos.
1477
+
1478
+ **Build falha com `Cannot find module`**
1479
+ O pacote referenciado não foi buildado ainda. Execute `pnpm build` na raiz para compilar todos os pacotes na ordem correta de dependências.
1480
+
1481
+ ---
1482
+
1483
+ ## Licença
1484
+
1485
+ MIT