nuxs-capsule 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +21 -0
  2. package/bin/nuxs-capsule-intercept.js +4 -0
  3. package/bin/nuxs-capsule.js +20 -0
  4. package/dist/install.d.ts +17 -0
  5. package/dist/install.d.ts.map +1 -0
  6. package/dist/install.js +243 -0
  7. package/dist/install.js.map +1 -0
  8. package/dist/intercept.d.ts +19 -0
  9. package/dist/intercept.d.ts.map +1 -0
  10. package/dist/intercept.js +232 -0
  11. package/dist/intercept.js.map +1 -0
  12. package/dist/lib/fileStat.d.ts +20 -0
  13. package/dist/lib/fileStat.d.ts.map +1 -0
  14. package/dist/lib/fileStat.js +71 -0
  15. package/dist/lib/fileStat.js.map +1 -0
  16. package/dist/lib/fingerprint.d.ts +10 -0
  17. package/dist/lib/fingerprint.d.ts.map +1 -0
  18. package/dist/lib/fingerprint.js +41 -0
  19. package/dist/lib/fingerprint.js.map +1 -0
  20. package/dist/lib/tokenCount.d.ts +13 -0
  21. package/dist/lib/tokenCount.d.ts.map +1 -0
  22. package/dist/lib/tokenCount.js +32 -0
  23. package/dist/lib/tokenCount.js.map +1 -0
  24. package/dist/license/check.d.ts +14 -0
  25. package/dist/license/check.d.ts.map +1 -0
  26. package/dist/license/check.js +141 -0
  27. package/dist/license/check.js.map +1 -0
  28. package/dist/providers/llmClient.d.ts +20 -0
  29. package/dist/providers/llmClient.d.ts.map +1 -0
  30. package/dist/providers/llmClient.js +40 -0
  31. package/dist/providers/llmClient.js.map +1 -0
  32. package/dist/server.d.ts +10 -0
  33. package/dist/server.d.ts.map +1 -0
  34. package/dist/server.js +268 -0
  35. package/dist/server.js.map +1 -0
  36. package/dist/setup.d.ts +14 -0
  37. package/dist/setup.d.ts.map +1 -0
  38. package/dist/setup.js +135 -0
  39. package/dist/setup.js.map +1 -0
  40. package/dist/telemetry/usage.d.ts +19 -0
  41. package/dist/telemetry/usage.d.ts.map +1 -0
  42. package/dist/telemetry/usage.js +114 -0
  43. package/dist/telemetry/usage.js.map +1 -0
  44. package/dist/tools/apiCapsule.d.ts +16 -0
  45. package/dist/tools/apiCapsule.d.ts.map +1 -0
  46. package/dist/tools/apiCapsule.js +169 -0
  47. package/dist/tools/apiCapsule.js.map +1 -0
  48. package/dist/tools/eventsCapsule.d.ts +15 -0
  49. package/dist/tools/eventsCapsule.d.ts.map +1 -0
  50. package/dist/tools/eventsCapsule.js +72 -0
  51. package/dist/tools/eventsCapsule.js.map +1 -0
  52. package/dist/tools/logCapsule.d.ts +38 -0
  53. package/dist/tools/logCapsule.d.ts.map +1 -0
  54. package/dist/tools/logCapsule.js +283 -0
  55. package/dist/tools/logCapsule.js.map +1 -0
  56. package/dist/tools/networkCapsule.d.ts +18 -0
  57. package/dist/tools/networkCapsule.d.ts.map +1 -0
  58. package/dist/tools/networkCapsule.js +151 -0
  59. package/dist/tools/networkCapsule.js.map +1 -0
  60. package/dist/tools/sessionCapsule.d.ts +21 -0
  61. package/dist/tools/sessionCapsule.d.ts.map +1 -0
  62. package/dist/tools/sessionCapsule.js +174 -0
  63. package/dist/tools/sessionCapsule.js.map +1 -0
  64. package/dist/tools/sqlCapsule.d.ts +17 -0
  65. package/dist/tools/sqlCapsule.d.ts.map +1 -0
  66. package/dist/tools/sqlCapsule.js +144 -0
  67. package/dist/tools/sqlCapsule.js.map +1 -0
  68. package/dist/tools/stackCapsule.d.ts +9 -0
  69. package/dist/tools/stackCapsule.d.ts.map +1 -0
  70. package/dist/tools/stackCapsule.js +132 -0
  71. package/dist/tools/stackCapsule.js.map +1 -0
  72. package/dist/tools/threadsCapsule.d.ts +14 -0
  73. package/dist/tools/threadsCapsule.d.ts.map +1 -0
  74. package/dist/tools/threadsCapsule.js +77 -0
  75. package/dist/tools/threadsCapsule.js.map +1 -0
  76. package/dist/types.d.ts +199 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +9 -0
  79. package/dist/types.js.map +1 -0
  80. package/dist/wrap.d.ts +14 -0
  81. package/dist/wrap.d.ts.map +1 -0
  82. package/dist/wrap.js +100 -0
  83. package/dist/wrap.js.map +1 -0
  84. package/package.json +60 -0
@@ -0,0 +1,151 @@
1
+ /**
2
+ * network_capsule — comprime HAR (HTTP Archive) do DevTools.
3
+ * Algoritmo puro, zero LLM, zero custo recorrente.
4
+ *
5
+ * Compressão típica: 50-100k tokens → 1-2k tokens (50-66×).
6
+ *
7
+ * Mecânica:
8
+ * 1. Parse JSON HAR
9
+ * 2. Sort por tempo total → top 10 slowest
10
+ * 3. Filter erros (4xx, 5xx, connection refused)
11
+ * 4. Agrega por host (count, total_ms, avg_ms)
12
+ * 5. Critical path — waterfall causal (req B começou depois de A terminar)
13
+ * 6. Blocking — reqs com timings.blocked > 100ms
14
+ */
15
+ import { readFileSync } from 'node:fs';
16
+ export function networkCapsuleFromFile(filePath) {
17
+ const raw = readFileSync(filePath, 'utf8');
18
+ return networkCapsule(raw);
19
+ }
20
+ export function networkCapsule(harJson) {
21
+ const har = JSON.parse(harJson);
22
+ const entries = har.log.entries;
23
+ // 1. Slowest 10
24
+ const sorted = [...entries].sort((a, b) => b.time - a.time);
25
+ const slowest = sorted.slice(0, 10).map((e) => ({
26
+ url: truncateUrl(e.request.url),
27
+ method: e.request.method,
28
+ duration_ms: Math.round(e.time),
29
+ status: e.response.status
30
+ }));
31
+ // 2. Errors
32
+ const errors = entries
33
+ .filter((e) => e.response.status >= 400 || e.response._error)
34
+ .slice(0, 20)
35
+ .map((e) => ({
36
+ url: truncateUrl(e.request.url),
37
+ status: e.response.status,
38
+ error: e.response._error ?? statusReason(e.response.status)
39
+ }));
40
+ // 3. By host
41
+ const byHost = {};
42
+ for (const e of entries) {
43
+ const host = safeHostname(e.request.url);
44
+ if (!byHost[host])
45
+ byHost[host] = { count: 0, total_ms: 0, avg_ms: 0 };
46
+ byHost[host].count++;
47
+ byHost[host].total_ms += e.time;
48
+ }
49
+ for (const h of Object.values(byHost)) {
50
+ h.avg_ms = Math.round(h.total_ms / h.count);
51
+ h.total_ms = Math.round(h.total_ms);
52
+ }
53
+ // 4. Critical path — sequência causal
54
+ const critical_path = computeCriticalPath(entries);
55
+ // 5. Blocking
56
+ const blocking = entries
57
+ .filter((e) => (e.timings.blocked ?? 0) > 100)
58
+ .slice(0, 10)
59
+ .map((e) => ({
60
+ url: truncateUrl(e.request.url),
61
+ blocked_by: detectBlocker(e, entries),
62
+ wait_ms: Math.round(e.timings.blocked)
63
+ }));
64
+ return {
65
+ total_requests: entries.length,
66
+ total_time_ms: Math.round(har.log.pages?.[0]?.pageTimings?.onLoad ?? sumTime(entries)),
67
+ slowest,
68
+ errors,
69
+ by_host: byHost,
70
+ critical_path,
71
+ blocking
72
+ };
73
+ }
74
+ function truncateUrl(url) {
75
+ // URLs absurdamente longas (query strings gigantes) — corta com elipse
76
+ if (url.length <= 120)
77
+ return url;
78
+ return url.slice(0, 117) + '...';
79
+ }
80
+ function safeHostname(url) {
81
+ try {
82
+ return new URL(url).hostname;
83
+ }
84
+ catch {
85
+ return 'invalid';
86
+ }
87
+ }
88
+ function statusReason(status) {
89
+ if (status >= 500)
90
+ return 'server_error';
91
+ if (status >= 400)
92
+ return 'client_error';
93
+ return '';
94
+ }
95
+ function sumTime(entries) {
96
+ return entries.reduce((acc, e) => acc + e.time, 0);
97
+ }
98
+ /**
99
+ * Critical path = sequência de requests que dominam o tempo total.
100
+ * Heurística: ordena por startedDateTime, identifica chains de requests
101
+ * que iniciam logo após o término de outro (gap < 50ms).
102
+ */
103
+ function computeCriticalPath(entries) {
104
+ if (entries.length === 0)
105
+ return [];
106
+ const sorted = [...entries].sort((a, b) => new Date(a.startedDateTime).getTime() - new Date(b.startedDateTime).getTime());
107
+ // Pega o request mais demorado em cada "fase" da página (chunks de tempo)
108
+ const totalDuration = new Date(sorted[sorted.length - 1].startedDateTime).getTime() +
109
+ sorted[sorted.length - 1].time -
110
+ new Date(sorted[0].startedDateTime).getTime();
111
+ const numPhases = Math.min(8, Math.max(3, Math.ceil(totalDuration / 1000)));
112
+ const phaseSize = totalDuration / numPhases;
113
+ const startTs = new Date(sorted[0].startedDateTime).getTime();
114
+ const phases = Array.from({ length: numPhases }, () => []);
115
+ for (const e of sorted) {
116
+ const offset = new Date(e.startedDateTime).getTime() - startTs;
117
+ const idx = Math.min(numPhases - 1, Math.floor(offset / phaseSize));
118
+ phases[idx].push(e);
119
+ }
120
+ const path = [];
121
+ for (const phase of phases) {
122
+ if (phase.length === 0)
123
+ continue;
124
+ const heaviest = phase.reduce((max, e) => (e.time > max.time ? e : max));
125
+ path.push(`${heaviest.request.method} ${truncateUrl(heaviest.request.url)} (${Math.round(heaviest.time)}ms)`);
126
+ }
127
+ return path;
128
+ }
129
+ /** Quem provavelmente bloqueou — request anterior do mesmo host. */
130
+ function detectBlocker(entry, entries) {
131
+ const host = safeHostname(entry.request.url);
132
+ const start = new Date(entry.startedDateTime).getTime();
133
+ // Pega o último request do mesmo host que terminou antes deste começar
134
+ let candidate = null;
135
+ let candidateEnd = 0;
136
+ for (const e of entries) {
137
+ if (e === entry)
138
+ continue;
139
+ if (safeHostname(e.request.url) !== host)
140
+ continue;
141
+ const eEnd = new Date(e.startedDateTime).getTime() + e.time;
142
+ if (eEnd <= start && eEnd > candidateEnd) {
143
+ candidateEnd = eEnd;
144
+ candidate = e;
145
+ }
146
+ }
147
+ if (!candidate)
148
+ return 'connection_pool';
149
+ return `${candidate.request.method} ${truncateUrl(candidate.request.url)}`;
150
+ }
151
+ //# sourceMappingURL=networkCapsule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networkCapsule.js","sourceRoot":"","sources":["../../src/tools/networkCapsule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * session_capsule — ÂNCORA do produto. Comprime sessão inteira do agente.
3
+ *
4
+ * FORMATO DIFERENTE: markdown bullets + YAML frontmatter.
5
+ * Razão: economiza ~30% tokens vs JSON pra prosa estruturada.
6
+ * Medido empiricamente — JSON ~95 tok, MD bullets ~67 tok pro mesmo conteúdo.
7
+ *
8
+ * Compressão típica: 50-100k tokens → 1.5-2k (40×).
9
+ *
10
+ * Disparado: automático quando contexto > 60k tokens OU manual via /compress.
11
+ */
12
+ import type { AgentKind } from '../types.js';
13
+ export interface Turn {
14
+ role: 'user' | 'assistant' | 'tool';
15
+ content: string;
16
+ tool_name?: string;
17
+ tool_input?: unknown;
18
+ timestamp?: string;
19
+ }
20
+ export declare function sessionCapsule(turns: Turn[], agent?: AgentKind): Promise<string>;
21
+ //# sourceMappingURL=sessionCapsule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionCapsule.d.ts","sourceRoot":"","sources":["../../src/tools/sessionCapsule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAA6B,SAAS,EAAE,MAAM,aAAa,CAAC;AAExE,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,KAAK,GAAE,SAAqB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAuDjB"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * session_capsule — ÂNCORA do produto. Comprime sessão inteira do agente.
3
+ *
4
+ * FORMATO DIFERENTE: markdown bullets + YAML frontmatter.
5
+ * Razão: economiza ~30% tokens vs JSON pra prosa estruturada.
6
+ * Medido empiricamente — JSON ~95 tok, MD bullets ~67 tok pro mesmo conteúdo.
7
+ *
8
+ * Compressão típica: 50-100k tokens → 1.5-2k (40×).
9
+ *
10
+ * Disparado: automático quando contexto > 60k tokens OU manual via /compress.
11
+ */
12
+ import { compressViaLlm } from '../providers/llmClient.js';
13
+ export async function sessionCapsule(turns, agent = 'unknown') {
14
+ if (turns.length === 0) {
15
+ return frontmatter({ agent, turns_compressed: 0 }) + '## Empty session.\n';
16
+ }
17
+ // 1. Dedupe turns repetitivos (3× Read mesmo file → 1 entry)
18
+ const dedup = deduplicateTurns(turns);
19
+ // 2. Chunk pra caber em context do Haiku (40k tokens max)
20
+ const chunks = chunkByApproxTokens(dedup, 40_000);
21
+ let summary;
22
+ let provider = 'unknown';
23
+ if (chunks.length === 1) {
24
+ // 1 chunk → 1 chamada LLM direta
25
+ const llm = await compressViaLlm({
26
+ capsule_type: 'session',
27
+ prompt: SESSION_PROMPT_DIRECT,
28
+ input: { turns: chunks[0], agent },
29
+ model_preference: 'cheap'
30
+ });
31
+ summary = llm?.result ?? fallbackSummary(dedup);
32
+ provider = llm?.provider_used ?? 'fallback';
33
+ }
34
+ else {
35
+ // N chunks → map-reduce
36
+ const partials = [];
37
+ for (const chunk of chunks) {
38
+ const r = await compressViaLlm({
39
+ capsule_type: 'session',
40
+ prompt: SESSION_PROMPT_PARTIAL,
41
+ input: { turns: chunk, agent },
42
+ model_preference: 'cheap'
43
+ });
44
+ partials.push(r?.result ?? '');
45
+ }
46
+ const reduceR = await compressViaLlm({
47
+ capsule_type: 'session',
48
+ prompt: SESSION_PROMPT_REDUCE,
49
+ input: { partials, agent },
50
+ model_preference: 'balanced'
51
+ });
52
+ summary = reduceR?.result ?? partials.join('\n\n');
53
+ provider = reduceR?.provider_used ?? 'fallback';
54
+ }
55
+ const fm = {
56
+ timestamp: new Date().toISOString(),
57
+ tokens_saved: 0, // setado pelo intercept depois de medir
58
+ provider_used: provider,
59
+ agent,
60
+ turns_compressed: turns.length
61
+ };
62
+ return frontmatter(fm) + summary.trim() + '\n';
63
+ }
64
+ function frontmatter(fm) {
65
+ const lines = ['---'];
66
+ for (const [k, v] of Object.entries(fm)) {
67
+ lines.push(`${k}: ${typeof v === 'string' ? JSON.stringify(v) : v}`);
68
+ }
69
+ lines.push('---', '');
70
+ return lines.join('\n');
71
+ }
72
+ function deduplicateTurns(turns) {
73
+ const seen = new Set();
74
+ const result = [];
75
+ for (const t of turns) {
76
+ // Hash: role + tool_name + first 200 chars content
77
+ const sig = `${t.role}|${t.tool_name ?? ''}|${(t.content ?? '').slice(0, 200)}`;
78
+ if (seen.has(sig))
79
+ continue;
80
+ seen.add(sig);
81
+ result.push(t);
82
+ }
83
+ return result;
84
+ }
85
+ function chunkByApproxTokens(turns, maxTokens) {
86
+ const chunks = [[]];
87
+ let current = 0;
88
+ for (const t of turns) {
89
+ const approxTokens = Math.ceil((t.content?.length ?? 0) / 3.5);
90
+ if (current + approxTokens > maxTokens && chunks[chunks.length - 1].length > 0) {
91
+ chunks.push([]);
92
+ current = 0;
93
+ }
94
+ chunks[chunks.length - 1].push(t);
95
+ current += approxTokens;
96
+ }
97
+ return chunks;
98
+ }
99
+ function fallbackSummary(turns) {
100
+ const userInputs = turns.filter((t) => t.role === 'user').slice(0, 3);
101
+ const tools = new Set(turns.map((t) => t.tool_name).filter(Boolean));
102
+ return [
103
+ '## Investigated',
104
+ ...userInputs.map((t) => `- ${t.content.slice(0, 200)}`),
105
+ '',
106
+ '## Tools used',
107
+ ...Array.from(tools).map((t) => `- ${t}`),
108
+ '',
109
+ '## Notes',
110
+ '- Fallback summary (LLM unavailable). Full context preserved in original session.'
111
+ ].join('\n');
112
+ }
113
+ const SESSION_PROMPT_DIRECT = `
114
+ Você recebe os turns de uma sessão de trabalho de agente IA.
115
+ Devolva APENAS markdown bullets (NÃO JSON):
116
+
117
+ ## Investigated
118
+ - bullets do que o agente explorou (problemas, áreas)
119
+
120
+ ## Findings
121
+ - bullets com descobertas concretas (citar evidência)
122
+
123
+ ## Decisions
124
+ - bullets com decisões tomadas (com razão)
125
+
126
+ ## Pending
127
+ - bullets com tarefas/perguntas em aberto
128
+
129
+ ## Relevant files
130
+ - "caminho/arquivo.ts:linha" — por quê é relevante
131
+
132
+ Foque no que importa pro PRÓXIMO agente continuar. Descarte exploração que não levou a nada.
133
+ Sem prosa de introdução, sem markdown além dos headers ## e bullets.
134
+ `;
135
+ const SESSION_PROMPT_PARTIAL = `
136
+ Você recebe um pedaço (chunk) de uma sessão grande.
137
+ Resuma APENAS este pedaço em markdown bullets:
138
+
139
+ ## Investigated (neste chunk)
140
+ - bullets
141
+
142
+ ## Findings (neste chunk)
143
+ - bullets
144
+
145
+ ## Decisions (neste chunk)
146
+ - bullets
147
+
148
+ ## Pending (neste chunk)
149
+ - bullets
150
+
151
+ Sem prosa extra. Vai virar input pra reduce final.
152
+ `;
153
+ const SESSION_PROMPT_REDUCE = `
154
+ Você recebe N resumos parciais de chunks de uma sessão.
155
+ Consolide num único resumo final em markdown bullets:
156
+
157
+ ## Investigated
158
+ - bullets consolidados (dedupe, prioridade ao mais recente)
159
+
160
+ ## Findings
161
+ - bullets consolidados
162
+
163
+ ## Decisions
164
+ - bullets consolidados (decisão mais recente vence)
165
+
166
+ ## Pending
167
+ - bullets do que ainda falta
168
+
169
+ ## Relevant files
170
+ - "path:line" — por quê
171
+
172
+ Sem prosa de introdução.
173
+ `;
174
+ //# sourceMappingURL=sessionCapsule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionCapsule.js","sourceRoot":"","sources":["../../src/tools/sessionCapsule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * sql_capsule — comprime slow query log (Postgres/MySQL).
3
+ * Parse + normaliza shape + agrupa + LLM sugere índice.
4
+ *
5
+ * Compressão típica: 50k tokens → 2k (25×).
6
+ */
7
+ import type { SqlCapsule } from '../types.js';
8
+ export interface ParsedSlowQuery {
9
+ query: string;
10
+ duration_ms: number;
11
+ rows_affected?: number;
12
+ database?: string;
13
+ user?: string;
14
+ timestamp?: string;
15
+ }
16
+ export declare function sqlCapsule(rawLog: string, source?: SqlCapsule['source']): Promise<SqlCapsule>;
17
+ //# sourceMappingURL=sqlCapsule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlCapsule.d.ts","sourceRoot":"","sources":["../../src/tools/sqlCapsule.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,UAAU,CAAC,QAAQ,CAAc,GACxC,OAAO,CAAC,UAAU,CAAC,CA4DrB"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * sql_capsule — comprime slow query log (Postgres/MySQL).
3
+ * Parse + normaliza shape + agrupa + LLM sugere índice.
4
+ *
5
+ * Compressão típica: 50k tokens → 2k (25×).
6
+ */
7
+ import { compressViaLlm } from '../providers/llmClient.js';
8
+ export async function sqlCapsule(rawLog, source = 'postgres') {
9
+ const queries = parseSlowLog(rawLog, source);
10
+ if (queries.length === 0) {
11
+ return { patterns: [], total_queries: 0, source };
12
+ }
13
+ // 1. Normaliza shape (algoritmo) — agrupa queries iguais com params diferentes
14
+ const groups = groupByShape(queries);
15
+ // 2. Ranking por impact (count × avg_ms)
16
+ const ranked = Array.from(groups.entries())
17
+ .map(([shape, items]) => {
18
+ const total_ms = items.reduce((acc, q) => acc + q.duration_ms, 0);
19
+ const sorted = [...items].sort((a, b) => a.duration_ms - b.duration_ms);
20
+ const p95 = sorted[Math.floor(sorted.length * 0.95)]?.duration_ms ?? items[0].duration_ms;
21
+ return {
22
+ shape,
23
+ count: items.length,
24
+ total_ms,
25
+ avg_ms: Math.round(total_ms / items.length),
26
+ p95_ms: p95,
27
+ sample_query: items[0].query
28
+ };
29
+ })
30
+ .sort((a, b) => b.total_ms - a.total_ms)
31
+ .slice(0, 10);
32
+ // 3. LLM sugere índice pra top patterns (custo: 10× $0.0001 = $0.001)
33
+ const withSuggestions = await Promise.all(ranked.map(async (p) => {
34
+ const llm = await compressViaLlm({
35
+ capsule_type: 'sql',
36
+ prompt: SQL_PROMPT,
37
+ input: {
38
+ query: p.sample_query,
39
+ avg_ms: p.avg_ms,
40
+ count: p.count,
41
+ source
42
+ },
43
+ model_preference: 'cheap'
44
+ });
45
+ if (!llm) {
46
+ return p; // sem suggested_index se LLM falhar
47
+ }
48
+ const out = llm.result;
49
+ return {
50
+ ...p,
51
+ suggested_index: out.suggested_index,
52
+ explanation: out.explanation
53
+ };
54
+ }));
55
+ return {
56
+ patterns: withSuggestions,
57
+ total_queries: queries.length,
58
+ source
59
+ };
60
+ }
61
+ /** Normaliza query: substitui literais por $N. */
62
+ function normalizeShape(query) {
63
+ return query
64
+ // Strings entre aspas
65
+ .replace(/'[^']*'/g, "'$STR'")
66
+ // Numeros
67
+ .replace(/\b\d+(\.\d+)?\b/g, '$NUM')
68
+ // Listas IN (1,2,3) — qualquer tamanho
69
+ .replace(/IN\s*\([^)]+\)/gi, 'IN ($LIST)')
70
+ // Espaços normalizados
71
+ .replace(/\s+/g, ' ')
72
+ .trim();
73
+ }
74
+ function groupByShape(queries) {
75
+ const groups = new Map();
76
+ for (const q of queries) {
77
+ const shape = normalizeShape(q.query);
78
+ if (!groups.has(shape))
79
+ groups.set(shape, []);
80
+ groups.get(shape).push(q);
81
+ }
82
+ return groups;
83
+ }
84
+ /**
85
+ * Parser de slow log. Detecta formato por source.
86
+ * Postgres: linhas com "duration: NNN.NNN ms" + query depois
87
+ * MySQL: blocos com "# Query_time: N" + USE + query
88
+ */
89
+ function parseSlowLog(raw, source) {
90
+ if (source === 'postgres')
91
+ return parsePostgres(raw);
92
+ if (source === 'mysql')
93
+ return parseMysql(raw);
94
+ // Fallback: tenta postgres primeiro, depois mysql
95
+ const pg = parsePostgres(raw);
96
+ if (pg.length > 0)
97
+ return pg;
98
+ return parseMysql(raw);
99
+ }
100
+ function parsePostgres(raw) {
101
+ const queries = [];
102
+ // Pattern: "LOG: duration: 1234.567 ms statement: SELECT ..."
103
+ // OU: "LOG: duration: 1234.567 ms execute <unnamed>: SELECT ..."
104
+ const pattern = /duration:\s*(\d+(?:\.\d+)?)\s*ms\s+(?:statement|execute(?:\s+<\w+>)?):\s*(.+?)(?=\n\d{4}-|\nLOG:|\n*$)/gs;
105
+ let m;
106
+ while ((m = pattern.exec(raw)) !== null) {
107
+ queries.push({
108
+ query: m[2].trim().replace(/\s+/g, ' '),
109
+ duration_ms: parseFloat(m[1])
110
+ });
111
+ }
112
+ return queries;
113
+ }
114
+ function parseMysql(raw) {
115
+ const queries = [];
116
+ // Blocos separados por "# Time: ..."
117
+ const blocks = raw.split(/^# Time:/m).slice(1);
118
+ for (const block of blocks) {
119
+ const queryTimeMatch = block.match(/# Query_time:\s*(\d+(?:\.\d+)?)/);
120
+ if (!queryTimeMatch)
121
+ continue;
122
+ const duration_ms = parseFloat(queryTimeMatch[1]) * 1000;
123
+ // Query é tudo depois do último "# ..." até o próximo bloco
124
+ const queryMatch = block.match(/(?:^|\n)([^#\n].+?;)/s);
125
+ if (!queryMatch)
126
+ continue;
127
+ queries.push({
128
+ query: queryMatch[1].trim().replace(/\s+/g, ' '),
129
+ duration_ms
130
+ });
131
+ }
132
+ return queries;
133
+ }
134
+ const SQL_PROMPT = `
135
+ Você recebe uma query SQL lenta com estatísticas.
136
+ Sugira um índice que reduziria o tempo OU explique se a query é mal escrita.
137
+ Devolva APENAS JSON:
138
+ {
139
+ "suggested_index": "CREATE INDEX ... ON ... (...) — ou null se não aplicável",
140
+ "explanation": "1 frase curta explicando por quê esse índice ajuda OU o que está errado na query"
141
+ }
142
+ Sem markdown, JSON puro.
143
+ `;
144
+ //# sourceMappingURL=sqlCapsule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlCapsule.js","sourceRoot":"","sources":["../../src/tools/sqlCapsule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * stack_capsule — comprime stack trace de erro client-side.
3
+ * Regex parser + LLM mini (Haiku/Flash/DeepSeek via router).
4
+ *
5
+ * Compressão típica: 8k tokens → 500 (16×).
6
+ */
7
+ import type { StackCapsule } from '../types.js';
8
+ export declare function stackCapsule(trace: string, source?: 'sentry' | 'console' | 'node'): Promise<StackCapsule>;
9
+ //# sourceMappingURL=stackCapsule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stackCapsule.d.ts","sourceRoot":"","sources":["../../src/tools/stackCapsule.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmChD,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GACrC,OAAO,CAAC,YAAY,CAAC,CA4CvB"}