@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +196 -0
  3. package/dist/agent.md +48 -0
  4. package/dist/bin/dfe-agent.d.ts +2 -0
  5. package/dist/bin/dfe-agent.d.ts.map +1 -0
  6. package/dist/bin/dfe-agent.js +19 -0
  7. package/dist/bin/dfe-agent.js.map +1 -0
  8. package/dist/cli.d.ts +25 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +105 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/install.d.ts +23 -0
  13. package/dist/commands/install.d.ts.map +1 -0
  14. package/dist/commands/install.js +74 -0
  15. package/dist/commands/install.js.map +1 -0
  16. package/dist/commands/query.d.ts +14 -0
  17. package/dist/commands/query.d.ts.map +1 -0
  18. package/dist/commands/query.js +18 -0
  19. package/dist/commands/query.js.map +1 -0
  20. package/dist/commands/status.d.ts +10 -0
  21. package/dist/commands/status.d.ts.map +1 -0
  22. package/dist/commands/status.js +58 -0
  23. package/dist/commands/status.js.map +1 -0
  24. package/dist/commands/update.d.ts +26 -0
  25. package/dist/commands/update.d.ts.map +1 -0
  26. package/dist/commands/update.js +144 -0
  27. package/dist/commands/update.js.map +1 -0
  28. package/dist/index.d.ts +6 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +8 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/query/cache.d.ts +38 -0
  33. package/dist/query/cache.d.ts.map +1 -0
  34. package/dist/query/cache.js +80 -0
  35. package/dist/query/cache.js.map +1 -0
  36. package/dist/query/constants.d.ts +20 -0
  37. package/dist/query/constants.d.ts.map +1 -0
  38. package/dist/query/constants.js +20 -0
  39. package/dist/query/constants.js.map +1 -0
  40. package/dist/query/contextBuilder.d.ts +40 -0
  41. package/dist/query/contextBuilder.d.ts.map +1 -0
  42. package/dist/query/contextBuilder.js +54 -0
  43. package/dist/query/contextBuilder.js.map +1 -0
  44. package/dist/query/embedder.d.ts +30 -0
  45. package/dist/query/embedder.d.ts.map +1 -0
  46. package/dist/query/embedder.js +69 -0
  47. package/dist/query/embedder.js.map +1 -0
  48. package/dist/query/ftsSearch.d.ts +28 -0
  49. package/dist/query/ftsSearch.d.ts.map +1 -0
  50. package/dist/query/ftsSearch.js +48 -0
  51. package/dist/query/ftsSearch.js.map +1 -0
  52. package/dist/query/hybrid.d.ts +31 -0
  53. package/dist/query/hybrid.d.ts.map +1 -0
  54. package/dist/query/hybrid.js +67 -0
  55. package/dist/query/hybrid.js.map +1 -0
  56. package/dist/query/index.d.ts +45 -0
  57. package/dist/query/index.d.ts.map +1 -0
  58. package/dist/query/index.js +153 -0
  59. package/dist/query/index.js.map +1 -0
  60. package/dist/query/vectorSearch.d.ts +32 -0
  61. package/dist/query/vectorSearch.d.ts.map +1 -0
  62. package/dist/query/vectorSearch.js +54 -0
  63. package/dist/query/vectorSearch.js.map +1 -0
  64. package/dist/skill/dfe-fiscal/SKILL.md +140 -0
  65. package/package.json +59 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * commands/status.ts — info da base instalada.
3
+ *
4
+ * @see PLAN_SPRINT14.md Task C.4
5
+ */
6
+ import { existsSync, statSync } from "node:fs";
7
+ import { resolve, dirname } from "node:path";
8
+ import { homedir, tmpdir } from "node:os";
9
+ import { fileURLToPath } from "node:url";
10
+ const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
11
+ import { VERSION } from "../index.js";
12
+ export async function status(opts) {
13
+ const baseDir = process.env.DFE_AGENT_BASE_DIR
14
+ ?? process.env.HOME
15
+ ?? homedir()
16
+ ?? tmpdir();
17
+ const dbPath = resolve(baseDir, "dfe.db");
18
+ const info = {
19
+ version: VERSION,
20
+ packageName: "@wiati/dfe-agent",
21
+ basePath: dbPath,
22
+ baseExists: existsSync(dbPath),
23
+ };
24
+ if (info.baseExists) {
25
+ const mtime = statSync(dbPath).mtime;
26
+ info.baseMtime = mtime.toISOString();
27
+ info.baseSizeBytes = statSync(dbPath).size;
28
+ info.baseEmbeddingModel = process.env.DFE_EMBEDDING_MODEL
29
+ ?? "paraphrase-multilingual-MiniLM-L12-v2";
30
+ // Best-effort: contar docs (ESM: usa dynamic import; nunca `require`)
31
+ try {
32
+ const { default: Database } = await import("better-sqlite3");
33
+ const handle = new Database(dbPath, { readonly: true });
34
+ const row = handle.prepare("SELECT COUNT(*) as c FROM documents").get();
35
+ info.baseDocCount = row.c;
36
+ const uv = handle.prepare("PRAGMA user_version").get();
37
+ info.baseSchemaVersion = uv.user_version;
38
+ handle.close();
39
+ }
40
+ catch (err) {
41
+ info.baseQueryError = err.message;
42
+ }
43
+ }
44
+ else {
45
+ info.hint = "rode 'dfe-agent update' para baixar a base";
46
+ }
47
+ console.log(JSON.stringify(info, null, 2));
48
+ return 0;
49
+ }
50
+ const invokedDirectly = process.argv[1]?.endsWith("status.ts")
51
+ || process.argv[1]?.endsWith("status.js");
52
+ if (invokedDirectly) {
53
+ status({}).then((code) => process.exit(code), (err) => {
54
+ console.error(`[dfe-agent] erro fatal: ${err.message}`);
55
+ process.exit(1);
56
+ });
57
+ }
58
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * commands/update.ts — baixa base RAG do GitHub Releases e popula ~/.dfe-agent/dfe.db.
3
+ *
4
+ * @see PLAN_SPRINT14.md Task C.2
5
+ *
6
+ * Fluxo:
7
+ * 1. fetch GitHub Releases API (latest release em dfe-agent/DFe-Agent)
8
+ * 2. localizar assets: dfe.db.gz + dfe.db.gz.sha256
9
+ * 3. download gz + sha256
10
+ * 4. verificar SHA-256 (gate B.3)
11
+ * 5. extrair atomicamente para ~/.dfe-agent/dfe.db (ou $DFE_AGENT_BASE_DIR)
12
+ * 6. validar schema via PRAGMA user_version >= 6
13
+ *
14
+ * Fallback: se GitHub inacessivel, usa seed bundled em dist/seed/dfe.db.gz.
15
+ *
16
+ * Exit codes:
17
+ * 0 sucesso
18
+ * 1 erro generico
19
+ * 3 SHA mismatch / sem asset / rede off sem seed
20
+ */
21
+ export interface UpdateOptions {
22
+ /** Override base path (default: $DFE_AGENT_BASE_DIR ou ~/.dfe-agent). Usado por testes. */
23
+ baseDirOverride?: string;
24
+ }
25
+ export declare function update(opts: UpdateOptions): Promise<number>;
26
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAsBH,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAsDD,wBAAsB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAqEjE"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * commands/update.ts — baixa base RAG do GitHub Releases e popula ~/.dfe-agent/dfe.db.
3
+ *
4
+ * @see PLAN_SPRINT14.md Task C.2
5
+ *
6
+ * Fluxo:
7
+ * 1. fetch GitHub Releases API (latest release em dfe-agent/DFe-Agent)
8
+ * 2. localizar assets: dfe.db.gz + dfe.db.gz.sha256
9
+ * 3. download gz + sha256
10
+ * 4. verificar SHA-256 (gate B.3)
11
+ * 5. extrair atomicamente para ~/.dfe-agent/dfe.db (ou $DFE_AGENT_BASE_DIR)
12
+ * 6. validar schema via PRAGMA user_version >= 6
13
+ *
14
+ * Fallback: se GitHub inacessivel, usa seed bundled em dist/seed/dfe.db.gz.
15
+ *
16
+ * Exit codes:
17
+ * 0 sucesso
18
+ * 1 erro generico
19
+ * 3 SHA mismatch / sem asset / rede off sem seed
20
+ */
21
+ import { createHash } from "node:crypto";
22
+ import { gunzipSync } from "node:zlib";
23
+ import { existsSync, writeFileSync, renameSync, mkdirSync, readFileSync, } from "node:fs";
24
+ import { resolve, dirname } from "node:path";
25
+ import { tmpdir, homedir } from "node:os";
26
+ import { fileURLToPath } from "node:url";
27
+ const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
28
+ const GH_REPO = process.env.DFE_AGENT_GH_REPO ?? "dfe-agent/DFe-Agent";
29
+ const GH_API = `https://api.github.com/repos/${GH_REPO}/releases/latest`;
30
+ const ASSET_DB = "dfe.db.gz";
31
+ const ASSET_SHA = "dfe.db.gz.sha256";
32
+ function resolveBaseDir() {
33
+ return process.env.DFE_AGENT_BASE_DIR
34
+ ?? process.env.HOME
35
+ ?? homedir()
36
+ ?? tmpdir();
37
+ }
38
+ async function fetchJson(url, token) {
39
+ const headers = {
40
+ "User-Agent": "dfe-agent-cli/0.1.0",
41
+ Accept: "application/vnd.github+json",
42
+ };
43
+ if (token)
44
+ headers["Authorization"] = `Bearer ${token}`;
45
+ const r = await fetch(url, { headers });
46
+ if (!r.ok)
47
+ throw new Error(`GitHub API ${r.status} ${r.statusText}`);
48
+ return r.json();
49
+ }
50
+ async function downloadBuffer(url, token) {
51
+ const headers = {
52
+ "User-Agent": "dfe-agent-cli/0.1.0",
53
+ };
54
+ if (token)
55
+ headers["Authorization"] = `Bearer ${token}`;
56
+ const r = await fetch(url, { headers });
57
+ if (!r.ok)
58
+ throw new Error(`download ${url} -> ${r.status}`);
59
+ return Buffer.from(await r.arrayBuffer());
60
+ }
61
+ function writeAtomic(path, data) {
62
+ const tmp = `${path}.tmp`;
63
+ writeFileSync(tmp, data);
64
+ renameSync(tmp, path);
65
+ }
66
+ function fallbackToSeed(dbPath) {
67
+ const seedPath = resolve(PKG_ROOT, "dist/seed/dfe.db.gz");
68
+ if (!existsSync(seedPath)) {
69
+ console.error(`[dfe-agent] rede off e sem seed bundled em ${seedPath}.\n` +
70
+ `[dfe-agent] aguarde o proximo release do DFe-Agent ou rode com rede.`);
71
+ return 3;
72
+ }
73
+ console.warn(`[dfe-agent] rede off — usando seed bundled (snapshot antigo)`);
74
+ const gz = readFileSync(seedPath);
75
+ const db = gunzipSync(gz);
76
+ mkdirSync(dirname(dbPath), { recursive: true });
77
+ writeAtomic(dbPath, db);
78
+ console.info(`[dfe-agent] base (seed) -> ${dbPath} (${db.length} bytes)`);
79
+ return 0;
80
+ }
81
+ export async function update(opts) {
82
+ const baseDir = opts.baseDirOverride ?? resolveBaseDir();
83
+ const dbPath = resolve(baseDir, "dfe.db");
84
+ mkdirSync(baseDir, { recursive: true });
85
+ // 1. fetch release metadata
86
+ let release;
87
+ try {
88
+ release = await fetchJson(GH_API, process.env.GITHUB_TOKEN);
89
+ }
90
+ catch (err) {
91
+ console.warn(`[dfe-agent] GitHub API inacessivel: ${err.message}`);
92
+ return fallbackToSeed(dbPath);
93
+ }
94
+ // 2. localizar assets
95
+ const dbAsset = release.assets?.find((a) => a.name === ASSET_DB);
96
+ const shaAsset = release.assets?.find((a) => a.name === ASSET_SHA);
97
+ if (!dbAsset || !shaAsset) {
98
+ console.error(`[dfe-agent] release sem assets ${ASSET_DB} / ${ASSET_SHA}`);
99
+ return 3;
100
+ }
101
+ // 3. download
102
+ let gz;
103
+ let expectedSha;
104
+ try {
105
+ [gz, expectedSha] = await Promise.all([
106
+ downloadBuffer(dbAsset.browser_download_url, process.env.GITHUB_TOKEN),
107
+ downloadBuffer(shaAsset.browser_download_url, process.env.GITHUB_TOKEN).then((b) => b.toString().trim()),
108
+ ]);
109
+ }
110
+ catch (err) {
111
+ console.warn(`[dfe-agent] download falhou: ${err.message}`);
112
+ return fallbackToSeed(dbPath);
113
+ }
114
+ // 4. verify SHA-256
115
+ const actualSha = createHash("sha256").update(gz).digest("hex");
116
+ if (actualSha !== expectedSha) {
117
+ console.error(`[dfe-agent] SHA mismatch: expected ${expectedSha}, got ${actualSha}`);
118
+ return 3;
119
+ }
120
+ // 5. atomic write
121
+ const db = gunzipSync(gz);
122
+ writeAtomic(dbPath, db);
123
+ // 6. validate schema (best-effort)
124
+ // Import lazy para nao quebrar quando better-sqlite3 nao compila
125
+ try {
126
+ const Database = (await import("better-sqlite3")).default;
127
+ const sqliteVec = await import("sqlite-vec");
128
+ const handle = new Database(dbPath, { readonly: true });
129
+ sqliteVec.load(handle);
130
+ const uv = handle.prepare("PRAGMA user_version").get();
131
+ handle.close();
132
+ if (uv.user_version < 6) {
133
+ console.error(`[dfe-agent] base com schema antigo (user_version=${uv.user_version} < 6)`);
134
+ return 3;
135
+ }
136
+ }
137
+ catch (err) {
138
+ console.warn(`[dfe-agent] nao foi possivel validar schema: ${err.message}`);
139
+ // nao falha o update — arquivo ja foi escrito com SHA valido
140
+ }
141
+ console.info(`[dfe-agent] base atualizada: ${dbPath} (${db.length} bytes, sha=${actualSha.slice(0, 16)}...)`);
142
+ return 0;
143
+ }
144
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare const VERSION = "0.1.0";
2
+ export declare const PACKAGE_NAME = "@wiati/dfe-agent";
3
+ export { runCli } from "./cli.js";
4
+ export { search } from "./query/index.js";
5
+ export { NO_EVIDENCE_MESSAGE } from "./query/index.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,UAAU,CAAC;AAC/B,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // @dfe-agent/dfe-agent — entry point
2
+ // Documentado em PLAN_SPRINT14.md Task A.1 (Sprint 14)
3
+ export const VERSION = "0.1.0";
4
+ export const PACKAGE_NAME = "@wiati/dfe-agent";
5
+ export { runCli } from "./cli.js";
6
+ export { search } from "./query/index.js";
7
+ export { NO_EVIDENCE_MESSAGE } from "./query/index.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,uDAAuD;AAEvD,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAC/B,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * cache.ts — cache SQLite de embeddings de query.
3
+ *
4
+ * @see PLAN_SPRINT14.md Task E.4 + Sprint 13 I13.2 (QueryEmbeddingCache)
5
+ *
6
+ * Persiste em `<baseDir>/cache.db`. Chave = sha256(model|mode|q_normalized).
7
+ *
8
+ * HIT na 2a chamada idêntica (mesmo modelo + mesmo mode + mesma query
9
+ * normalizada) NAO invoca o embedder. Gate Sprint 13 + canonico em
10
+ * src/query/embedding_cache.py.
11
+ */
12
+ import type { Database as BetterSqlite3Database } from "better-sqlite3";
13
+ export declare const QUERY_CACHE_SCHEMA = "\n CREATE TABLE IF NOT EXISTS query_cache (\n query_hash TEXT PRIMARY KEY,\n embedding BLOB NOT NULL,\n model TEXT NOT NULL,\n mode TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n";
14
+ export interface QueryCacheOptions {
15
+ model?: string;
16
+ }
17
+ export declare class QueryCache {
18
+ private readonly model;
19
+ private readonly handle;
20
+ constructor(handle: BetterSqlite3Database, opts?: QueryCacheOptions);
21
+ /**
22
+ * Busca embedding em cache. Retorna null em miss.
23
+ */
24
+ get(mode: string, question: string): Float32Array | null;
25
+ /**
26
+ * Persiste embedding. INSERT OR REPLACE para idempotencia.
27
+ */
28
+ set(mode: string, question: string, embedding: Float32Array): void;
29
+ /**
30
+ * Limpa cache (util apos troca de modelo).
31
+ */
32
+ clear(): void;
33
+ /**
34
+ * Estatisticas: numero de entradas.
35
+ */
36
+ size(): number;
37
+ }
38
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/query/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAExE,eAAO,MAAM,kBAAkB,yPAQ9B,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAYD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;gBAEnC,MAAM,EAAE,qBAAqB,EAAE,IAAI,GAAE,iBAAsB;IAQvE;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAUxD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI;IAWlE;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,MAAM;CAMf"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * cache.ts — cache SQLite de embeddings de query.
3
+ *
4
+ * @see PLAN_SPRINT14.md Task E.4 + Sprint 13 I13.2 (QueryEmbeddingCache)
5
+ *
6
+ * Persiste em `<baseDir>/cache.db`. Chave = sha256(model|mode|q_normalized).
7
+ *
8
+ * HIT na 2a chamada idêntica (mesmo modelo + mesmo mode + mesma query
9
+ * normalizada) NAO invoca o embedder. Gate Sprint 13 + canonico em
10
+ * src/query/embedding_cache.py.
11
+ */
12
+ import { createHash } from "node:crypto";
13
+ export const QUERY_CACHE_SCHEMA = `
14
+ CREATE TABLE IF NOT EXISTS query_cache (
15
+ query_hash TEXT PRIMARY KEY,
16
+ embedding BLOB NOT NULL,
17
+ model TEXT NOT NULL,
18
+ mode TEXT NOT NULL,
19
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
20
+ )
21
+ `;
22
+ function normalizeQuery(q) {
23
+ return q.trim().toLowerCase();
24
+ }
25
+ function hashKey(model, mode, q) {
26
+ return createHash("sha256")
27
+ .update(`${model}|${mode}|${normalizeQuery(q)}`)
28
+ .digest("hex");
29
+ }
30
+ export class QueryCache {
31
+ model;
32
+ handle;
33
+ constructor(handle, opts = {}) {
34
+ this.handle = handle;
35
+ this.model = opts.model
36
+ ?? process.env.DFE_EMBEDDING_MODEL
37
+ ?? "paraphrase-multilingual-MiniLM-L12-v2";
38
+ handle.exec(QUERY_CACHE_SCHEMA);
39
+ }
40
+ /**
41
+ * Busca embedding em cache. Retorna null em miss.
42
+ */
43
+ get(mode, question) {
44
+ const key = hashKey(this.model, mode, question);
45
+ const row = this.handle
46
+ .prepare("SELECT embedding FROM query_cache WHERE query_hash = ?")
47
+ .get(key);
48
+ if (!row)
49
+ return null;
50
+ const buf = row.embedding;
51
+ return new Float32Array(buf.buffer, buf.byteOffset, buf.byteLength / 4);
52
+ }
53
+ /**
54
+ * Persiste embedding. INSERT OR REPLACE para idempotencia.
55
+ */
56
+ set(mode, question, embedding) {
57
+ const key = hashKey(this.model, mode, question);
58
+ const buf = Buffer.from(embedding.buffer);
59
+ this.handle
60
+ .prepare(`INSERT OR REPLACE INTO query_cache (query_hash, embedding, model, mode)
61
+ VALUES (?, ?, ?, ?)`)
62
+ .run(key, buf, this.model, mode);
63
+ }
64
+ /**
65
+ * Limpa cache (util apos troca de modelo).
66
+ */
67
+ clear() {
68
+ this.handle.exec("DELETE FROM query_cache");
69
+ }
70
+ /**
71
+ * Estatisticas: numero de entradas.
72
+ */
73
+ size() {
74
+ const row = this.handle
75
+ .prepare("SELECT COUNT(*) AS c FROM query_cache")
76
+ .get();
77
+ return row.c;
78
+ }
79
+ }
80
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/query/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;CAQjC,CAAC;AAMF,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,OAAO,CAAC,KAAa,EAAE,IAAY,EAAE,CAAS;IACrD,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,GAAG,KAAK,IAAI,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/C,MAAM,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,OAAO,UAAU;IACJ,KAAK,CAAS;IACd,MAAM,CAAwB;IAE/C,YAAY,MAA6B,EAAE,OAA0B,EAAE;QACrE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;eAClB,OAAO,CAAC,GAAG,CAAC,mBAAmB;eAC/B,uCAAuC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,IAAY,EAAE,QAAgB;QAChC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM;aACpB,OAAO,CAAC,wDAAwD,CAAC;aACjE,GAAG,CAAC,GAAG,CAAsC,CAAC;QACjD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC;QAC1B,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,SAAuB;QACzD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM;aACR,OAAO,CACN;6BACqB,CACtB;aACA,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,IAAI;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM;aACpB,OAAO,CAAC,uCAAuC,CAAC;aAChD,GAAG,EAAmB,CAAC;QAC1B,OAAO,GAAG,CAAC,CAAC,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * constants.ts — constantes canonicas do query engine.
3
+ *
4
+ * Separado de index.ts para evitar ciclos de import com contextBuilder.
5
+ *
6
+ * NO_EVIDENCE_MESSAGE: string canonica que sinaliza ausencia de chunks.
7
+ * - Gate dfe-rules.md #4 + convencoes-gerais.md
8
+ * - NUNCA duplique este literal
9
+ * - Espelha `src/query/context_builder.py` no Py
10
+ *
11
+ * SUPPORTED_MODES: union type dos modos de busca opt-in.
12
+ */
13
+ export declare const NO_EVIDENCE_MESSAGE = "Nao encontrei base para responder";
14
+ export declare const SUPPORTED_MODES: readonly ["semantic", "fts", "hybrid"];
15
+ export type SearchMode = (typeof SUPPORTED_MODES)[number];
16
+ export declare const DEFAULT_TOP_K = 5;
17
+ export declare const MIN_RELEVANCE_SCORE = 0.5;
18
+ export declare const RECENCY_WEIGHT = 0.3;
19
+ export declare const RECENCY_HALF_LIFE_DAYS = 180;
20
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/query/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,mBAAmB,sCAAsC,CAAC;AAEvE,eAAO,MAAM,eAAe,wCAAyC,CAAC;AACtE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAG1D,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,sBAAsB,MAAQ,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * constants.ts — constantes canonicas do query engine.
3
+ *
4
+ * Separado de index.ts para evitar ciclos de import com contextBuilder.
5
+ *
6
+ * NO_EVIDENCE_MESSAGE: string canonica que sinaliza ausencia de chunks.
7
+ * - Gate dfe-rules.md #4 + convencoes-gerais.md
8
+ * - NUNCA duplique este literal
9
+ * - Espelha `src/query/context_builder.py` no Py
10
+ *
11
+ * SUPPORTED_MODES: union type dos modos de busca opt-in.
12
+ */
13
+ export const NO_EVIDENCE_MESSAGE = "Nao encontrei base para responder";
14
+ export const SUPPORTED_MODES = ["semantic", "fts", "hybrid"];
15
+ // Defaults alinhados com src/query/constants.py (gate paridade Py ↔Node)
16
+ export const DEFAULT_TOP_K = 5;
17
+ export const MIN_RELEVANCE_SCORE = 0.5;
18
+ export const RECENCY_WEIGHT = 0.3;
19
+ export const RECENCY_HALF_LIFE_DAYS = 180.0;
20
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/query/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,mCAAmC,CAAC;AAEvE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAU,CAAC;AAGtE,yEAAyE;AACzE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAClC,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * contextBuilder.ts — monta o contexto final (answer + sources).
3
+ *
4
+ * @see PLAN_SPRINT14.md Task E.5
5
+ *
6
+ * Constante NO_EVIDENCE_MESSAGE canonica em `src/query/index.ts` (mesma
7
+ * string em src/query/context_builder.py do Py). NUNCA duplique o literal
8
+ * em outro arquivo — gate dfe-rules.md #4 + convencoes-gerais.md.
9
+ */
10
+ import type { Source } from "./index.js";
11
+ export interface HydratedChunk {
12
+ chunk_id: number;
13
+ doc_id: number;
14
+ text: string;
15
+ url: string;
16
+ title: string;
17
+ score: number;
18
+ published_at?: string | null;
19
+ }
20
+ export interface ContextResult {
21
+ answer: string;
22
+ sources: Source[];
23
+ }
24
+ /**
25
+ * Heuristica de evidencia suficiente (gate dfe-rules.md #4 + paridade Py).
26
+ *
27
+ * Convencao Py (`src/query/context_builder.py:60-71`): olhamos apenas o
28
+ * PRIMEIRO chunk (mais relevante no ranking). Se ele nao atinge o minimo,
29
+ * qualquer outro posterior tera score menor.
30
+ *
31
+ * Antes da Sprint 14.1, Node usava `Math.max(...)` que retornava True em
32
+ * cenarios com 1 chunk bom + N chunks ruins, divergindo do Py. Corrigido
33
+ * para paridade.
34
+ */
35
+ export declare function hasSufficientEvidence(chunks: HydratedChunk[]): boolean;
36
+ /**
37
+ * Constroi o contexto final: dedup por URL, ordena por score, monta answer.
38
+ */
39
+ export declare function buildContext(chunks: HydratedChunk[]): ContextResult;
40
+ //# sourceMappingURL=contextBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextBuilder.d.ts","sourceRoot":"","sources":["../../src/query/contextBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAGtE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,aAAa,CA4BnE"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * contextBuilder.ts — monta o contexto final (answer + sources).
3
+ *
4
+ * @see PLAN_SPRINT14.md Task E.5
5
+ *
6
+ * Constante NO_EVIDENCE_MESSAGE canonica em `src/query/index.ts` (mesma
7
+ * string em src/query/context_builder.py do Py). NUNCA duplique o literal
8
+ * em outro arquivo — gate dfe-rules.md #4 + convencoes-gerais.md.
9
+ */
10
+ import { NO_EVIDENCE_MESSAGE, MIN_RELEVANCE_SCORE } from "./constants.js";
11
+ /**
12
+ * Heuristica de evidencia suficiente (gate dfe-rules.md #4 + paridade Py).
13
+ *
14
+ * Convencao Py (`src/query/context_builder.py:60-71`): olhamos apenas o
15
+ * PRIMEIRO chunk (mais relevante no ranking). Se ele nao atinge o minimo,
16
+ * qualquer outro posterior tera score menor.
17
+ *
18
+ * Antes da Sprint 14.1, Node usava `Math.max(...)` que retornava True em
19
+ * cenarios com 1 chunk bom + N chunks ruins, divergindo do Py. Corrigido
20
+ * para paridade.
21
+ */
22
+ export function hasSufficientEvidence(chunks) {
23
+ if (chunks.length === 0)
24
+ return false;
25
+ return chunks[0].score >= MIN_RELEVANCE_SCORE;
26
+ }
27
+ /**
28
+ * Constroi o contexto final: dedup por URL, ordena por score, monta answer.
29
+ */
30
+ export function buildContext(chunks) {
31
+ if (!hasSufficientEvidence(chunks)) {
32
+ return {
33
+ answer: NO_EVIDENCE_MESSAGE,
34
+ sources: [],
35
+ };
36
+ }
37
+ // Dedup por URL (preferir chunk com maior score)
38
+ const byUrl = new Map();
39
+ for (const c of chunks) {
40
+ const existing = byUrl.get(c.url);
41
+ if (!existing || c.score > existing.score) {
42
+ byUrl.set(c.url, c);
43
+ }
44
+ }
45
+ const sorted = Array.from(byUrl.values()).sort((a, b) => b.score - a.score);
46
+ const sources = sorted.map((c) => ({
47
+ url: c.url,
48
+ title: c.title,
49
+ score: c.score,
50
+ }));
51
+ const answer = sorted.map((c) => c.text).join("\n\n---\n\n");
52
+ return { answer, sources };
53
+ }
54
+ //# sourceMappingURL=contextBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextBuilder.js","sourceRoot":"","sources":["../../src/query/contextBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAkB1E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAuB;IAC3D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,mBAAmB,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,EAAE;SACZ,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC1C,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAE5E,MAAM,OAAO,GAAa,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3C,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,CAAC,CAAC,CAAC;IAEJ,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE7D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * embedder.ts — wrapper de @xenova/transformers com LRU cache em memoria.
3
+ *
4
+ * @see PLAN_SPRINT14.md Task E.1
5
+ *
6
+ * Decisao D6: modelo canonico e `paraphrase-multilingual-MiniLM-L12-v2`
7
+ * (mesmo do DFe-Agent Py via sentence-transformers). Drift entre Py e Node
8
+ * deve ser < 0.01 (gate D.7 validado por tests/integration/test_embedding_parity).
9
+ *
10
+ * LRU 128: cobre uso interativo; descarta entradas mais antigas.
11
+ */
12
+ export declare const EMBEDDING_MODEL_NAME = "Xenova/paraphrase-multilingual-MiniLM-L12-v2";
13
+ export declare const EMBEDDING_DIMENSION = 384;
14
+ export interface EmbeddingCacheEntry {
15
+ vec: Float32Array;
16
+ hash: string;
17
+ }
18
+ /**
19
+ * Codifica `text` em vetor 384-d (cosine-normalized).
20
+ *
21
+ * Cache LRU: 2a chamada com mesmo texto retorna o mesmo Float32Array sem
22
+ * nova inferencia.
23
+ *
24
+ * @throws se o modelo nao conseguir carregar (problema conhecido: Node
25
+ * v22.21.1 com sharp/better-sqlite3 nativos; ver Sprint 13).
26
+ */
27
+ export declare function encode(text: string): Promise<Float32Array>;
28
+ export declare function clearCache(): void;
29
+ export declare function cacheSize(): number;
30
+ //# sourceMappingURL=embedder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedder.d.ts","sourceRoot":"","sources":["../../src/query/embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,eAAO,MAAM,oBAAoB,iDAAa,CAAC;AAC/C,eAAO,MAAM,mBAAmB,MAAgB,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,YAAY,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAoBD;;;;;;;;GAQG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBhE;AAED,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC"}