@wiati/dfe-agent 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +196 -0
- package/dist/agent.md +48 -0
- package/dist/bin/dfe-agent.d.ts +2 -0
- package/dist/bin/dfe-agent.d.ts.map +1 -0
- package/dist/bin/dfe-agent.js +19 -0
- package/dist/bin/dfe-agent.js.map +1 -0
- package/dist/cli.d.ts +25 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +105 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/install.d.ts +23 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +74 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/query.d.ts +14 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +18 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/status.d.ts +10 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +58 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +26 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +144 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/query/cache.d.ts +38 -0
- package/dist/query/cache.d.ts.map +1 -0
- package/dist/query/cache.js +80 -0
- package/dist/query/cache.js.map +1 -0
- package/dist/query/constants.d.ts +20 -0
- package/dist/query/constants.d.ts.map +1 -0
- package/dist/query/constants.js +20 -0
- package/dist/query/constants.js.map +1 -0
- package/dist/query/contextBuilder.d.ts +40 -0
- package/dist/query/contextBuilder.d.ts.map +1 -0
- package/dist/query/contextBuilder.js +54 -0
- package/dist/query/contextBuilder.js.map +1 -0
- package/dist/query/embedder.d.ts +30 -0
- package/dist/query/embedder.d.ts.map +1 -0
- package/dist/query/embedder.js +69 -0
- package/dist/query/embedder.js.map +1 -0
- package/dist/query/ftsSearch.d.ts +28 -0
- package/dist/query/ftsSearch.d.ts.map +1 -0
- package/dist/query/ftsSearch.js +48 -0
- package/dist/query/ftsSearch.js.map +1 -0
- package/dist/query/hybrid.d.ts +31 -0
- package/dist/query/hybrid.d.ts.map +1 -0
- package/dist/query/hybrid.js +67 -0
- package/dist/query/hybrid.js.map +1 -0
- package/dist/query/index.d.ts +45 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +153 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/vectorSearch.d.ts +32 -0
- package/dist/query/vectorSearch.d.ts.map +1 -0
- package/dist/query/vectorSearch.js +54 -0
- package/dist/query/vectorSearch.js.map +1 -0
- package/dist/skill/dfe-fiscal/SKILL.md +140 -0
- package/package.json +59 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dfe-fiscal
|
|
3
|
+
description: "Use ONLY when the user asks about Brazilian Electronic Fiscal Documents (DF-e) — NF-e, NFC-e, CT-e, MDF-e, SPED — or about Nota Técnica (NT), schemas XML da NF-e (tags UB/IBSCBS/cMunFGIBS/pIBSUF/etc.), Reforma Tributária do Consumo (RTC, LC 214/2025, IBS/CBS/Imposto Seletivo), IBPT, regras de validação, cClassTrib, CST, cCredPres, contributors exclusivos do IBS/CBS, eIBPT, ou when the request maps to the RAG pipeline of the DFe-Agent project (python -m src.collector, python -m src.indexer.ingest, python -m src.query, python -m src.ragctl). Triggers: NT 2025.002, tag UB, BSCBS, vIBSUF, grupo W03, cBenef, LC 214, monofasia, RAG fiscal."
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: dfe-fiscal
|
|
8
|
+
|
|
9
|
+
Esta skill encapsula a logica do dominio fiscal eletronico do DFe-Agent: coleta, ingestao e consulta RAG de documentacao oficial (NF-e, NFC-e, CT-e, MDF-e, SPED, CONFAZ).
|
|
10
|
+
|
|
11
|
+
## Contexto de uso (Sprint 14+)
|
|
12
|
+
|
|
13
|
+
Esta skill tem **2 modos de invocacao** dependendo do contexto de execucao:
|
|
14
|
+
|
|
15
|
+
### Em DFe-Agent root (desenvolvimento local)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
python -m src.query "<pergunta em linguagem natural>" --mode=hybrid
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Fonte canonica dos dados: `python -m src.ragctl migrate && python -m src.collector --once && python -m src.indexer.ingest`.
|
|
22
|
+
|
|
23
|
+
### Em consumidor npm (`@dfe-agent/dfe-agent`)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx dfe-agent query "<pergunta em linguagem natural>" --mode=hybrid
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Fonte dos dados: `npx dfe-agent update` (baixa `dfe.db.gz` do GitHub Releases do DFe-Agent).
|
|
30
|
+
|
|
31
|
+
O **contrato de saida e identico**: `{answer, sources[]}` em ambos os modos. A escolha do comando depende apenas do `cwd` (root DFe-Agent vs projeto consumidor).
|
|
32
|
+
|
|
33
|
+
Quando o agente `dfe-agent` estiver ativo no opencode TUI, **usar o comando `npx dfe-agent query`** se o `.opencode/agent/dfe-agent.md` foi instalado via `npx dfe-agent install`; usar `python -m src.query` se estiver no proprio DFe-Agent root.
|
|
34
|
+
|
|
35
|
+
## Comandos invocaveis
|
|
36
|
+
|
|
37
|
+
### 1. Varredura completa dos portais oficiais
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python -m src.collector --once
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Executa `DocumentCollector.discover_and_register()` + `DocumentCollector.download_pending()`. Acessa os portais oficiais (apenas dominios em `ALLOWED_DOMAINS`), identifica novos documentos, baixa PDFs/HTML com throttling.
|
|
44
|
+
|
|
45
|
+
Flags opcionais:
|
|
46
|
+
- `--once`: executa uma varredura unica
|
|
47
|
+
- `--dry-run`: descobre URLs sem inserir no banco nem baixar
|
|
48
|
+
|
|
49
|
+
### 2. Ingestao de documentos pendentes no RAG
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python -m src.indexer.ingest
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Executa `RagIndexer.ingest_pending()` — para cada documento com status `nao_ingerido`:
|
|
56
|
+
- Extrai texto via parser (PDF ou HTML)
|
|
57
|
+
- Calcula hash SHA-256 do texto (idempotencia)
|
|
58
|
+
- Extrai metadados estruturados (NT number, data, versao) via `metadata_extractor.extract_document_metadata`
|
|
59
|
+
- Chunkifica (flat ou `structural`) + gera embeddings multilingues
|
|
60
|
+
- Persiste na base vetorial SQLite (`sqlite-vec`)
|
|
61
|
+
- Persiste summary deterministico via `summarizer.summarize` em `doc_summaries`
|
|
62
|
+
- Marca documento como `ingerido`
|
|
63
|
+
|
|
64
|
+
Flags opcionais:
|
|
65
|
+
- `--chunker={flat,structural}`: flat (default, pre-Sprint-2) ou structural (preserva contexto de secao NT via `structural_chunker`).
|
|
66
|
+
|
|
67
|
+
Documentos ja ingeridos (mesmo hash) sao pulados automaticamente.
|
|
68
|
+
|
|
69
|
+
### 3. Consulta RAG
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m src.query "<pergunta em linguagem natural>"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Executa `QueryEngine.search(pergunta)` com cache de embedding (default ON). Modos opt-in via flag:
|
|
76
|
+
|
|
77
|
+
| Flag | Algoritmo | Uso |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| (nenhuma) | cosseno no vec_chunks + dedup + boost temporal | Default pre-Sprint-2 |
|
|
80
|
+
| `--hybrid` | RRF (k=60) entre semantico e FTS5 (BM25) | Termos literais (numero NT, codigo) |
|
|
81
|
+
| `--hierarchical` | two-stage: embedding -> top-10 summaries -> vec_chunks filtrado | Bases grandes (>1000 docs) |
|
|
82
|
+
| `--rerank` | cross-encoder opt-in (top-5*5 candidatos) | Quando benchmark Fase 16 mostra ganho de MRR |
|
|
83
|
+
| `--no-cache` | Desativa cache de embedding de query | Debug/teste |
|
|
84
|
+
|
|
85
|
+
Quando a busca tem chunks relevantes: monta contexto via `context_builder.build_context` e imprime JSON com `answer` + `sources`. Sem chunks: `"Nao encontrei base para responder"`.
|
|
86
|
+
|
|
87
|
+
### 4. CLI administrativo
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
python -m src.ragctl migrate # aplica migrations pendentes
|
|
91
|
+
python -m src.ragctl benchmark # roda eval_set + grava benchmark_report.json
|
|
92
|
+
python -m src.ragctl reindex --chunker=flat # dropa chunks e reingerir
|
|
93
|
+
python -m src.ragctl stats # contadores da base
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Diagnostico de `NO_EVIDENCE_MESSAGE` espurio
|
|
97
|
+
|
|
98
|
+
Se `python -m src.query "<pergunta>"` retornar
|
|
99
|
+
`"answer": "Nao encontrei base para responder"` MAS o corpus possui
|
|
100
|
+
documentos indexados (verificar com `python -m src.ragctl stats`),
|
|
101
|
+
investigar nesta ordem:
|
|
102
|
+
|
|
103
|
+
1. `python main.py --health` — confere se todos os modulos importam.
|
|
104
|
+
2. `python -c "from src.indexer.embeddings import EmbeddingProvider; e = EmbeddingProvider(); print(e.dim)"` — dispara o load; se levantar `RuntimeError` com substring `DFE_EMBEDDING_DTYPE`, ver Task F.1.
|
|
105
|
+
3. Workaround de ultimo recurso: `DFE_EMBEDDING_MODEL=all-MiniLM-L6-v2` (~80 MB, ingles-only — perde semantica em PT-BR).
|
|
106
|
+
4. Hardening completo do ambiente: `pwsh scripts/check_env.ps1`.
|
|
107
|
+
|
|
108
|
+
NUNCA escrever SQL raw em `scripts/` para "contornar" o RAG — isso viola o guardrail de veracidade. Usar sempre o CLI documentado.
|
|
109
|
+
|
|
110
|
+
Origem deste guardrail (PLAN_SPRINT5 F.2): 4 scripts ad-hoc
|
|
111
|
+
(`scripts/answer_nf_e_10_2026.py`, `scripts/buscar_dfereferenciado.py`,
|
|
112
|
+
`scripts/demo_query.py`, `scripts/demo_query_2026.py`) foram gerados
|
|
113
|
+
pelo proprio agente LLM apos `python -m src.query` retornar
|
|
114
|
+
`NO_EVIDENCE_MESSAGE` em razao de `OSError 1455` (page file do
|
|
115
|
+
Windows insuficiente) no load do
|
|
116
|
+
`paraphrase-multilingual-MiniLM-L12-v2`. O agente interpretou
|
|
117
|
+
"sem evidencia" como "CLI quebrado" e escreveu SQL raw no DB,
|
|
118
|
+
contornando o guardrail de veracidade.
|
|
119
|
+
|
|
120
|
+
## Classes principais referenciadas
|
|
121
|
+
|
|
122
|
+
- **`DocumentCollector`** (`src.collector.downloader`): orquestra descoberta + download com throttling
|
|
123
|
+
- **`RagIndexer`** (`src.indexer.rag_indexer`): ingere documentos com idempotencia por hash
|
|
124
|
+
- **`StructuralChunker`** (`src.indexer.structural_chunker`): chunker ciente de secoes NT (opcional via `--chunker=structural`)
|
|
125
|
+
- **`Summarizer`** (`src.indexer.summarizer`): extracao deterministica de sumario (sem LLM)
|
|
126
|
+
- **`MetadataExtractor`** (`src.parser.metadata_extractor`): regex para NT/convenio/data/versao no cabecalho
|
|
127
|
+
- **`QueryEngine`** (`src.query.query_engine`): busca semantica + boost temporal + dedup
|
|
128
|
+
- **`FtsStore`** (`src.db.fts_store`): indice FTS5/BM25 (criado pela migration 0004)
|
|
129
|
+
- **`DocSummaryStore`** (`src.db.doc_summaries`): summaries persistidos (criado pela migration 0005) — alimenta `--hierarchical`
|
|
130
|
+
- **`CrossEncoderReranker`** (`src.query.reranker`): reranker opt-in via `--rerank`
|
|
131
|
+
- **`QueryEmbeddingCache`** (`src.query.embedding_cache`): cache SQLite de embeddings (Fase 13)
|
|
132
|
+
|
|
133
|
+
## Guardrails
|
|
134
|
+
|
|
135
|
+
- Apenas dominios em `ALLOWED_DOMAINS` (enforced por hook `domain_guard`)
|
|
136
|
+
- Respeitar intervalo entre requisicoes (Throttler) — nao "metralhar" portais
|
|
137
|
+
- Documento ja ingerido (mesmo hash) NAO e reprocessado (idempotencia)
|
|
138
|
+
- Sem chunks relevantes: retornar `"Nao encontrei base para responder"`
|
|
139
|
+
- Toda resposta cita a fonte (URL + nome do documento) presente na base
|
|
140
|
+
- Migration framework garante upgrade v1->v6 sem perda de dados via `PRAGMA user_version`
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wiati/dfe-agent",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Agente opencode + base RAG com documentacao fiscal eletronica oficial brasileira (NF-e, NFC-e, CT-e, MDF-e, SPED) distribuido como pacote npm.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"dfe-agent": "dist/bin/dfe-agent.js"
|
|
10
|
+
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=20"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"README.md",
|
|
17
|
+
"CHANGELOG.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"pretest": "npm run build",
|
|
22
|
+
"test": "tsx --test tests/scaffold.test.ts tests/sync-assets.test.ts tests/drift-check.test.ts tests/cli/skeleton.test.ts tests/query/embedder.test.ts tests/query/ftsSearch.test.ts tests/query/hybrid.test.ts tests/query/cache.test.ts tests/query/orchestrator.test.ts tests/integration/test_embedding_parity.test.ts",
|
|
23
|
+
"test:e2e": "powershell -ExecutionPolicy Bypass -File tests/e2e/smoke-test.ps1",
|
|
24
|
+
"lint": "tsc --noEmit",
|
|
25
|
+
"sync": "tsx scripts/sync-assets.ts",
|
|
26
|
+
"drift-check": "tsx scripts/drift-check.ts"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@xenova/transformers": "2.17.2",
|
|
30
|
+
"better-sqlite3": "11.5.0",
|
|
31
|
+
"sqlite-vec": "0.1.6"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"typescript": "5.6.3",
|
|
35
|
+
"tsx": "4.19.2",
|
|
36
|
+
"@types/node": "22.9.0",
|
|
37
|
+
"@types/better-sqlite3": "7.6.12"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"dfe-agent",
|
|
41
|
+
"nfe",
|
|
42
|
+
"fiscal",
|
|
43
|
+
"rag",
|
|
44
|
+
"opencode"
|
|
45
|
+
],
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/wia-ti/dfe-agent.git",
|
|
50
|
+
"directory": "packages/dfe-agent"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"allowScripts": {
|
|
56
|
+
"sharp@0.32.6": true,
|
|
57
|
+
"better-sqlite3@11.5.0": true
|
|
58
|
+
}
|
|
59
|
+
}
|