milens 0.6.1 → 0.6.3

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 (105) hide show
  1. package/README.md +157 -14
  2. package/dist/analyzer/config.d.ts.map +1 -1
  3. package/dist/analyzer/config.js +33 -1
  4. package/dist/analyzer/config.js.map +1 -1
  5. package/dist/analyzer/engine.d.ts +1 -0
  6. package/dist/analyzer/engine.d.ts.map +1 -1
  7. package/dist/analyzer/engine.js +27 -8
  8. package/dist/analyzer/engine.js.map +1 -1
  9. package/dist/analyzer/review.d.ts +23 -0
  10. package/dist/analyzer/review.d.ts.map +1 -0
  11. package/dist/analyzer/review.js +143 -0
  12. package/dist/analyzer/review.js.map +1 -0
  13. package/dist/analyzer/testplan.d.ts +59 -0
  14. package/dist/analyzer/testplan.d.ts.map +1 -0
  15. package/dist/analyzer/testplan.js +218 -0
  16. package/dist/analyzer/testplan.js.map +1 -0
  17. package/dist/cli.js +2 -0
  18. package/dist/cli.js.map +1 -1
  19. package/dist/gateway/analyzer.d.ts +6 -0
  20. package/dist/gateway/analyzer.d.ts.map +1 -0
  21. package/dist/gateway/analyzer.js +218 -0
  22. package/dist/gateway/analyzer.js.map +1 -0
  23. package/dist/gateway/cache.d.ts +35 -0
  24. package/dist/gateway/cache.d.ts.map +1 -0
  25. package/dist/gateway/cache.js +175 -0
  26. package/dist/gateway/cache.js.map +1 -0
  27. package/dist/gateway/config.d.ts +10 -0
  28. package/dist/gateway/config.d.ts.map +1 -0
  29. package/dist/gateway/config.js +167 -0
  30. package/dist/gateway/config.js.map +1 -0
  31. package/dist/gateway/context-memory.d.ts +68 -0
  32. package/dist/gateway/context-memory.d.ts.map +1 -0
  33. package/dist/gateway/context-memory.js +157 -0
  34. package/dist/gateway/context-memory.js.map +1 -0
  35. package/dist/gateway/observability.d.ts +83 -0
  36. package/dist/gateway/observability.d.ts.map +1 -0
  37. package/dist/gateway/observability.js +152 -0
  38. package/dist/gateway/observability.js.map +1 -0
  39. package/dist/gateway/privacy.d.ts +27 -0
  40. package/dist/gateway/privacy.d.ts.map +1 -0
  41. package/dist/gateway/privacy.js +139 -0
  42. package/dist/gateway/privacy.js.map +1 -0
  43. package/dist/gateway/providers.d.ts +66 -0
  44. package/dist/gateway/providers.d.ts.map +1 -0
  45. package/dist/gateway/providers.js +377 -0
  46. package/dist/gateway/providers.js.map +1 -0
  47. package/dist/gateway/router.d.ts +18 -0
  48. package/dist/gateway/router.d.ts.map +1 -0
  49. package/dist/gateway/router.js +102 -0
  50. package/dist/gateway/router.js.map +1 -0
  51. package/dist/gateway/server.d.ts +20 -0
  52. package/dist/gateway/server.d.ts.map +1 -0
  53. package/dist/gateway/server.js +387 -0
  54. package/dist/gateway/server.js.map +1 -0
  55. package/dist/gateway/translator.d.ts +19 -0
  56. package/dist/gateway/translator.d.ts.map +1 -0
  57. package/dist/gateway/translator.js +340 -0
  58. package/dist/gateway/translator.js.map +1 -0
  59. package/dist/gateway/types.d.ts +215 -0
  60. package/dist/gateway/types.d.ts.map +1 -0
  61. package/dist/gateway/types.js +3 -0
  62. package/dist/gateway/types.js.map +1 -0
  63. package/dist/parser/extract.d.ts +1 -0
  64. package/dist/parser/extract.d.ts.map +1 -1
  65. package/dist/parser/extract.js +8 -0
  66. package/dist/parser/extract.js.map +1 -1
  67. package/dist/parser/lang-go.d.ts.map +1 -1
  68. package/dist/parser/lang-go.js +41 -5
  69. package/dist/parser/lang-go.js.map +1 -1
  70. package/dist/parser/lang-java.d.ts.map +1 -1
  71. package/dist/parser/lang-java.js +1 -0
  72. package/dist/parser/lang-java.js.map +1 -1
  73. package/dist/parser/lang-js.d.ts.map +1 -1
  74. package/dist/parser/lang-js.js +23 -1
  75. package/dist/parser/lang-js.js.map +1 -1
  76. package/dist/parser/lang-py.d.ts.map +1 -1
  77. package/dist/parser/lang-py.js +22 -0
  78. package/dist/parser/lang-py.js.map +1 -1
  79. package/dist/parser/lang-ruby.d.ts.map +1 -1
  80. package/dist/parser/lang-ruby.js +1 -0
  81. package/dist/parser/lang-ruby.js.map +1 -1
  82. package/dist/parser/lang-ts.d.ts.map +1 -1
  83. package/dist/parser/lang-ts.js +62 -1
  84. package/dist/parser/lang-ts.js.map +1 -1
  85. package/dist/server/mcp.d.ts.map +1 -1
  86. package/dist/server/mcp.js +615 -106
  87. package/dist/server/mcp.js.map +1 -1
  88. package/dist/skills.js +32 -0
  89. package/dist/skills.js.map +1 -1
  90. package/dist/store/db.d.ts +44 -0
  91. package/dist/store/db.d.ts.map +1 -1
  92. package/dist/store/db.js +145 -25
  93. package/dist/store/db.js.map +1 -1
  94. package/dist/store/gateway-schema.sql +53 -0
  95. package/dist/store/schema.sql +33 -0
  96. package/dist/store/vectors.d.ts +65 -0
  97. package/dist/store/vectors.d.ts.map +1 -0
  98. package/dist/store/vectors.js +212 -0
  99. package/dist/store/vectors.js.map +1 -0
  100. package/dist/utils.d.ts +3 -0
  101. package/dist/utils.d.ts.map +1 -0
  102. package/dist/utils.js +9 -0
  103. package/dist/utils.js.map +1 -0
  104. package/docs/diagram2.svg +1 -1
  105. package/package.json +2 -1
@@ -0,0 +1,218 @@
1
+ // ── Message analyzer — detect code symbols, files, and intent from chat messages ──
2
+ // ── Intent classification ──
3
+ const INTENT_PATTERNS = [
4
+ { pattern: /\b(refactor|restructure|rewrite|reorganize|move|extract|split|merge)\b/i, intent: 'refactor' },
5
+ { pattern: /\b(test|spec|unit test|integration test|e2e|coverage|mock|stub|assert)\b/i, intent: 'test' },
6
+ { pattern: /\b(debug|fix|bug|error|issue|crash|broken|wrong|fail|exception|trace)\b/i, intent: 'debug' },
7
+ { pattern: /\b(review|audit|check|examine|inspect|assess|evaluate|analyze)\b/i, intent: 'review' },
8
+ { pattern: /\b(explain|describe|what does|how does|why does|understand|walk through)\b/i, intent: 'explain' },
9
+ { pattern: /\b(docstring|jsdoc|comment|document|annotation|describe the|add doc)\b/i, intent: 'docstring' },
10
+ { pattern: /\b(generate|create|write|implement|add|build|make|scaffold|new)\b/i, intent: 'generate' },
11
+ ];
12
+ // ── File path detection ──
13
+ // Match common source file paths (e.g., src/auth.ts, ./models/user.go, path/to/file.py)
14
+ const FILE_PATH_RE = /(?:^|\s|`|'|"|,|\()([.\/]*(?:[\w-]+\/)+[\w.-]+\.(?:ts|tsx|js|jsx|py|go|rs|java|php|rb|vue|html|css|md|sql|json|yaml|yml|toml|sh|c|cpp|h|hpp|cs|swift|kt))\b/gi;
15
+ // ── Symbol name detection ──
16
+ // camelCase, PascalCase, snake_case identifiers in backticks or after common keywords
17
+ const BACKTICK_SYMBOL_RE = /`([A-Za-z_][\w.]*)`/g;
18
+ const KEYWORD_SYMBOL_RE = /(?:function|class|method|interface|type|enum|struct|const|let|var|def|fn|func|mod|trait|impl)\s+([A-Za-z_]\w*)/gi;
19
+ // ── Code block extraction ──
20
+ const CODE_BLOCK_RE = /```[\w]*\n([\s\S]*?)```/g;
21
+ // ── Main analysis function ──
22
+ export function analyzeMessages(messages) {
23
+ const files = new Set();
24
+ const symbolNames = new Set();
25
+ const codeBlocks = [];
26
+ let intent = 'unknown';
27
+ // Only analyze user messages (recent ones have more weight)
28
+ const userMessages = messages
29
+ .filter(m => m.role === 'user')
30
+ .slice(-5); // Last 5 user messages
31
+ for (const msg of userMessages) {
32
+ const text = typeof msg.content === 'string'
33
+ ? msg.content
34
+ : Array.isArray(msg.content)
35
+ ? msg.content.filter(p => p.type === 'text').map(p => p.text ?? '').join('\n')
36
+ : '';
37
+ if (!text)
38
+ continue;
39
+ // Detect intent (first match wins, later messages override)
40
+ for (const { pattern, intent: i } of INTENT_PATTERNS) {
41
+ if (pattern.test(text)) {
42
+ intent = i;
43
+ break;
44
+ }
45
+ }
46
+ // Detect file paths
47
+ for (const match of text.matchAll(FILE_PATH_RE)) {
48
+ files.add(match[1].replace(/^\.\//, ''));
49
+ }
50
+ // Detect symbol names in backticks
51
+ for (const match of text.matchAll(BACKTICK_SYMBOL_RE)) {
52
+ const name = match[1];
53
+ // Filter out common non-symbol words and file paths
54
+ if (name.length > 1 && !name.includes('/') && !name.includes('.')) {
55
+ symbolNames.add(name);
56
+ }
57
+ }
58
+ // Detect symbol names after keywords
59
+ for (const match of text.matchAll(KEYWORD_SYMBOL_RE)) {
60
+ symbolNames.add(match[1]);
61
+ }
62
+ // Extract code blocks
63
+ for (const match of text.matchAll(CODE_BLOCK_RE)) {
64
+ codeBlocks.push(match[1]);
65
+ // Also extract function/class names from code blocks
66
+ for (const km of match[1].matchAll(KEYWORD_SYMBOL_RE)) {
67
+ symbolNames.add(km[1]);
68
+ }
69
+ }
70
+ }
71
+ return {
72
+ files: [...files],
73
+ symbolNames: [...symbolNames],
74
+ symbols: [], // Populated by lookupSymbols
75
+ intent,
76
+ complexity: 0, // Computed after symbol lookup
77
+ codeBlocks,
78
+ };
79
+ }
80
+ // ── Symbol lookup — enrich analysis with milens data ──
81
+ export function lookupSymbols(analysis, db) {
82
+ const symbols = [];
83
+ const seen = new Set();
84
+ // Look up each detected symbol name
85
+ for (const name of analysis.symbolNames) {
86
+ const found = db.findSymbolByName(name);
87
+ for (const sym of found) {
88
+ if (!seen.has(sym.id)) {
89
+ seen.add(sym.id);
90
+ symbols.push(sym);
91
+ }
92
+ }
93
+ }
94
+ // Look up symbols from detected file paths
95
+ for (const file of analysis.files) {
96
+ const fileSymbols = db.getSymbolsByFile(file);
97
+ for (const sym of fileSymbols) {
98
+ if (!seen.has(sym.id)) {
99
+ seen.add(sym.id);
100
+ symbols.push(sym);
101
+ }
102
+ }
103
+ }
104
+ // Compute complexity based on symbol roles and dependencies
105
+ let complexity = 0;
106
+ for (const sym of symbols) {
107
+ const upstream = db.findUpstream(sym.id, 1);
108
+ const dependentCount = upstream.length;
109
+ switch (sym.role) {
110
+ case 'entrypoint':
111
+ complexity += 10;
112
+ break;
113
+ case 'hub':
114
+ complexity += Math.max(dependentCount, 5);
115
+ break;
116
+ case 'utility':
117
+ complexity += 2;
118
+ break;
119
+ case 'leaf':
120
+ complexity += 1;
121
+ break;
122
+ case 'datatype':
123
+ complexity += 1;
124
+ break;
125
+ default:
126
+ complexity += Math.min(dependentCount + 1, 8);
127
+ break;
128
+ }
129
+ }
130
+ // Apply intent multiplier
131
+ const intentWeights = {
132
+ docstring: 0.3,
133
+ explain: 0.3,
134
+ review: 0.5,
135
+ test: 0.7,
136
+ generate: 0.8,
137
+ debug: 1.2,
138
+ refactor: 1.5,
139
+ unknown: 1.0,
140
+ };
141
+ complexity = Math.round(complexity * (intentWeights[analysis.intent] ?? 1.0));
142
+ return {
143
+ ...analysis,
144
+ symbols,
145
+ complexity,
146
+ };
147
+ }
148
+ // ── Context injection builder ──
149
+ export function buildContextInjection(analysis, db, maxTokens = 2000) {
150
+ if (!analysis.symbols.length)
151
+ return undefined;
152
+ const sections = [];
153
+ let estimatedTokens = 0;
154
+ const TOKEN_PER_CHAR = 0.25; // Rough: 1 token ≈ 4 chars
155
+ // 1. Blast radius warnings (highest priority)
156
+ for (const sym of analysis.symbols) {
157
+ if (estimatedTokens > maxTokens * 0.8)
158
+ break;
159
+ const upstream = db.findUpstream(sym.id, 1);
160
+ if (upstream.length > 5) {
161
+ const warning = `⚠ ${sym.name} [${sym.kind}] has ${upstream.length} direct dependents. Changes may affect: ${upstream.slice(0, 8).map(u => u.symbol.name).join(', ')}${upstream.length > 8 ? '...' : ''}`;
162
+ sections.push(warning);
163
+ estimatedTokens += warning.length * TOKEN_PER_CHAR;
164
+ }
165
+ }
166
+ // 2. Direct callers
167
+ for (const sym of analysis.symbols.slice(0, 5)) {
168
+ if (estimatedTokens > maxTokens * 0.9)
169
+ break;
170
+ const incoming = db.getIncomingLinks(sym.id);
171
+ const callers = incoming.filter(l => l.type === 'calls' || l.type === 'imports');
172
+ if (callers.length > 0) {
173
+ const callerNames = callers.slice(0, 6).map(l => {
174
+ const from = db.findSymbolById(l.fromId);
175
+ return from ? `${from.name} (${from.filePath})` : l.fromId;
176
+ });
177
+ const line = `${sym.name} is called/imported by: ${callerNames.join(', ')}`;
178
+ sections.push(line);
179
+ estimatedTokens += line.length * TOKEN_PER_CHAR;
180
+ }
181
+ }
182
+ // 3. Dependencies (what the symbol calls/imports)
183
+ for (const sym of analysis.symbols.slice(0, 3)) {
184
+ if (estimatedTokens > maxTokens)
185
+ break;
186
+ const outgoing = db.getOutgoingLinks(sym.id);
187
+ const deps = outgoing.filter(l => l.type === 'calls' || l.type === 'imports');
188
+ if (deps.length > 0) {
189
+ const depNames = deps.slice(0, 6).map(l => {
190
+ const to = db.findSymbolById(l.toId);
191
+ return to ? to.name : l.toId;
192
+ });
193
+ const line = `${sym.name} depends on: ${depNames.join(', ')}`;
194
+ sections.push(line);
195
+ estimatedTokens += line.length * TOKEN_PER_CHAR;
196
+ }
197
+ }
198
+ // 4. File outline (sibling symbols)
199
+ if (analysis.files.length > 0 && estimatedTokens < maxTokens * 0.9) {
200
+ for (const file of analysis.files.slice(0, 2)) {
201
+ const fileSymbols = db.getSymbolsByFile(file);
202
+ if (fileSymbols.length > 0) {
203
+ const outline = fileSymbols
204
+ .filter(s => !s.parentId) // Top-level only
205
+ .slice(0, 10)
206
+ .map(s => ` ${s.exported ? '▸' : '▹'} ${s.name} [${s.kind}]${s.signature ? ` — ${s.signature}` : ''}`)
207
+ .join('\n');
208
+ const section = `File ${file}:\n${outline}`;
209
+ sections.push(section);
210
+ estimatedTokens += section.length * TOKEN_PER_CHAR;
211
+ }
212
+ }
213
+ }
214
+ if (!sections.length)
215
+ return undefined;
216
+ return `[milens code context]\n${sections.join('\n\n')}`;
217
+ }
218
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/gateway/analyzer.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAMrF,8BAA8B;AAE9B,MAAM,eAAe,GAA+C;IAClE,EAAE,OAAO,EAAE,yEAAyE,EAAE,MAAM,EAAE,UAAU,EAAE;IAC1G,EAAE,OAAO,EAAE,2EAA2E,EAAE,MAAM,EAAE,MAAM,EAAE;IACxG,EAAE,OAAO,EAAE,0EAA0E,EAAE,MAAM,EAAE,OAAO,EAAE;IACxG,EAAE,OAAO,EAAE,mEAAmE,EAAE,MAAM,EAAE,QAAQ,EAAE;IAClG,EAAE,OAAO,EAAE,6EAA6E,EAAE,MAAM,EAAE,SAAS,EAAE;IAC7G,EAAE,OAAO,EAAE,yEAAyE,EAAE,MAAM,EAAE,WAAW,EAAE;IAC3G,EAAE,OAAO,EAAE,oEAAoE,EAAE,MAAM,EAAE,UAAU,EAAE;CACtG,CAAC;AAEF,4BAA4B;AAE5B,wFAAwF;AACxF,MAAM,YAAY,GAAG,+JAA+J,CAAC;AAErL,8BAA8B;AAE9B,sFAAsF;AACtF,MAAM,kBAAkB,GAAG,sBAAsB,CAAC;AAClD,MAAM,iBAAiB,GAAG,kHAAkH,CAAC;AAE7I,8BAA8B;AAE9B,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAEjD,+BAA+B;AAE/B,MAAM,UAAU,eAAe,CAAC,QAAuB;IACrD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,MAAM,GAAW,SAAS,CAAC;IAE/B,4DAA4D;IAC5D,MAAM,YAAY,GAAG,QAAQ;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SAC9B,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAuB;IAErC,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAC1C,CAAC,CAAC,GAAG,CAAC,OAAO;YACb,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;gBAC1B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC9E,CAAC,CAAC,EAAE,CAAC;QAET,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,4DAA4D;QAC5D,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,eAAe,EAAE,CAAC;YACrD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAC,MAAM,GAAG,CAAC,CAAC;gBAAC,MAAM;YAAC,CAAC;QAChD,CAAC;QAED,oBAAoB;QACpB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAChD,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,mCAAmC;QACnC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,oDAAoD;YACpD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,qCAAqC;QACrC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACrD,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;QAED,sBAAsB;QACtB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACjD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,qDAAqD;YACrD,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACtD,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;QACjB,WAAW,EAAE,CAAC,GAAG,WAAW,CAAC;QAC7B,OAAO,EAAE,EAAE,EAAE,6BAA6B;QAC1C,MAAM;QACN,UAAU,EAAE,CAAC,EAAE,+BAA+B;QAC9C,UAAU;KACX,CAAC;AACJ,CAAC;AAED,yDAAyD;AAEzD,MAAM,UAAU,aAAa,CAAC,QAAyB,EAAE,EAAY;IACnE,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,oCAAoC;IACpC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAClC,MAAM,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC9C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC;QAEvC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,YAAY;gBAAE,UAAU,IAAI,EAAE,CAAC;gBAAC,MAAM;YAC3C,KAAK,KAAK;gBAAE,UAAU,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;gBAAC,MAAM;YAC7D,KAAK,SAAS;gBAAE,UAAU,IAAI,CAAC,CAAC;gBAAC,MAAM;YACvC,KAAK,MAAM;gBAAE,UAAU,IAAI,CAAC,CAAC;gBAAC,MAAM;YACpC,KAAK,UAAU;gBAAE,UAAU,IAAI,CAAC,CAAC;gBAAC,MAAM;YACxC;gBAAS,UAAU,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAAC,MAAM;QAChE,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,MAAM,aAAa,GAA2B;QAC5C,SAAS,EAAE,GAAG;QACd,OAAO,EAAE,GAAG;QACZ,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,GAAG;QACb,KAAK,EAAE,GAAG;QACV,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE,GAAG;KACb,CAAC;IACF,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAE9E,OAAO;QACL,GAAG,QAAQ;QACX,OAAO;QACP,UAAU;KACX,CAAC;AACJ,CAAC;AAED,kCAAkC;AAElC,MAAM,UAAU,qBAAqB,CACnC,QAAyB,EACzB,EAAY,EACZ,YAAoB,IAAI;IAExB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAE/C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,MAAM,cAAc,GAAG,IAAI,CAAC,CAAC,2BAA2B;IAExD,8CAA8C;IAC9C,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,eAAe,GAAG,SAAS,GAAG,GAAG;YAAE,MAAM;QAC7C,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,SAAS,QAAQ,CAAC,MAAM,2CAA2C,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC1M,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,cAAc,CAAC;QACrD,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC/C,IAAI,eAAe,GAAG,SAAS,GAAG,GAAG;YAAE,MAAM;QAC7C,MAAM,QAAQ,GAAG,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QACjF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAC9C,MAAM,IAAI,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBACzC,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAC7D,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,2BAA2B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,eAAe,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC;QAClD,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC/C,IAAI,eAAe,GAAG,SAAS;YAAE,MAAM;QACvC,MAAM,QAAQ,GAAG,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAC9E,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBACxC,MAAM,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACrC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/B,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,gBAAgB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,eAAe,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC;QAClD,CAAC;IACH,CAAC;IAED,oCAAoC;IACpC,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,eAAe,GAAG,SAAS,GAAG,GAAG,EAAE,CAAC;QACnE,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9C,MAAM,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,OAAO,GAAG,WAAW;qBACxB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,iBAAiB;qBAC1C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;qBACZ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;qBACtG,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,MAAM,OAAO,GAAG,QAAQ,IAAI,MAAM,OAAO,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvB,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,cAAc,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAEvC,OAAO,0BAA0B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { ChatRequest, MessageAnalysis, CacheEntry, CacheConfig } from './types.js';
2
+ import type { CodeSymbol } from '../types.js';
3
+ import type BetterSqlite3 from 'better-sqlite3';
4
+ export declare class SemanticCache {
5
+ private rawDb;
6
+ private config;
7
+ private stmts;
8
+ constructor(rawDb: BetterSqlite3.Database, config: CacheConfig);
9
+ private prepareStatements;
10
+ /** Look up a cached response by AST hash + request hash */
11
+ lookup(req: ChatRequest, analysis?: MessageAnalysis): CacheEntry | null;
12
+ /** Store a response in the cache */
13
+ store(req: ChatRequest, analysis: MessageAnalysis, response: string, meta: {
14
+ model: string;
15
+ provider: string;
16
+ tokensIn: number;
17
+ tokensOut: number;
18
+ }): void;
19
+ /** Compute AST hash — captures code structure, survives renames/reformats */
20
+ computeASTHash(symbols: CodeSymbol[]): string;
21
+ /** Compute request hash — normalized version of the prompt */
22
+ private computeRequestHash;
23
+ /** Evict expired entries + enforce max capacity */
24
+ private ensureCapacity;
25
+ /** Invalidate cache entries related to changed files */
26
+ invalidateForFiles(filePaths: string[]): number;
27
+ /** Get cache statistics */
28
+ getStats(): {
29
+ totalEntries: number;
30
+ totalHits: number;
31
+ totalTokensCached: number;
32
+ totalCostSaved: number;
33
+ };
34
+ }
35
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/gateway/cache.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAEhD,qBAAa,aAAa;IAItB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IAJhB,OAAO,CAAC,KAAK,CAAiD;gBAGpD,KAAK,EAAE,aAAa,CAAC,QAAQ,EAC7B,MAAM,EAAE,WAAW;IAK7B,OAAO,CAAC,iBAAiB;IAoDzB,2DAA2D;IAC3D,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,UAAU,GAAG,IAAI;IA2BvE,oCAAoC;IACpC,KAAK,CACH,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAC7E,IAAI;IAmBP,6EAA6E;IAC7E,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM;IAe7C,8DAA8D;IAC9D,OAAO,CAAC,kBAAkB;IAgB1B,mDAAmD;IACnD,OAAO,CAAC,cAAc;IAStB,wDAAwD;IACxD,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM;IAU/C,2BAA2B;IAC3B,QAAQ,IAAI;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;CAS3G"}
@@ -0,0 +1,175 @@
1
+ // ── Semantic cache — AST-structure-aware caching for LLM responses ──
2
+ import { createHash } from 'node:crypto';
3
+ export class SemanticCache {
4
+ rawDb;
5
+ config;
6
+ stmts;
7
+ constructor(rawDb, config) {
8
+ this.rawDb = rawDb;
9
+ this.config = config;
10
+ this.stmts = this.prepareStatements();
11
+ }
12
+ prepareStatements() {
13
+ return {
14
+ lookup: this.rawDb.prepare(`SELECT * FROM gateway_cache
15
+ WHERE ast_hash = ? AND request_hash = ?
16
+ AND datetime(created_at, '+' || ttl_hours || ' hours') > datetime('now')
17
+ LIMIT 1`),
18
+ lookupByAst: this.rawDb.prepare(`SELECT * FROM gateway_cache
19
+ WHERE ast_hash = ?
20
+ AND datetime(created_at, '+' || ttl_hours || ' hours') > datetime('now')
21
+ ORDER BY hit_count DESC LIMIT 1`),
22
+ insert: this.rawDb.prepare(`INSERT OR REPLACE INTO gateway_cache
23
+ (id, ast_hash, request_hash, response, model, provider, tokens_in, tokens_out, cost_estimate, ttl_hours)
24
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),
25
+ recordHit: this.rawDb.prepare(`UPDATE gateway_cache SET hit_count = hit_count + 1, last_hit_at = datetime('now') WHERE id = ?`),
26
+ evictExpired: this.rawDb.prepare(`DELETE FROM gateway_cache WHERE datetime(created_at, '+' || ttl_hours || ' hours') <= datetime('now')`),
27
+ evictOldest: this.rawDb.prepare(`DELETE FROM gateway_cache WHERE id IN (
28
+ SELECT id FROM gateway_cache ORDER BY last_hit_at ASC NULLS FIRST, created_at ASC
29
+ LIMIT ?
30
+ )`),
31
+ count: this.rawDb.prepare('SELECT COUNT(*) as c FROM gateway_cache'),
32
+ invalidateByFile: this.rawDb.prepare(`DELETE FROM gateway_cache WHERE ast_hash IN (
33
+ SELECT DISTINCT gc.ast_hash FROM gateway_cache gc
34
+ WHERE gc.id IN (
35
+ SELECT gc2.id FROM gateway_cache gc2
36
+ JOIN json_each(gc2.response) -- Response contains symbol info referencing the file
37
+ )
38
+ )`),
39
+ stats: this.rawDb.prepare(`SELECT
40
+ COUNT(*) as total_entries,
41
+ SUM(hit_count) as total_hits,
42
+ SUM(tokens_in + tokens_out) as total_tokens_cached,
43
+ SUM(cost_estimate * hit_count) as total_cost_saved
44
+ FROM gateway_cache`),
45
+ };
46
+ }
47
+ /** Look up a cached response by AST hash + request hash */
48
+ lookup(req, analysis) {
49
+ if (!this.config.enabled)
50
+ return null;
51
+ const astHash = analysis?.symbols.length
52
+ ? this.computeASTHash(analysis.symbols)
53
+ : null;
54
+ const requestHash = this.computeRequestHash(req);
55
+ // Try exact match (ast + request)
56
+ if (astHash) {
57
+ const row = this.stmts.lookup.get(astHash, requestHash);
58
+ if (row) {
59
+ this.stmts.recordHit.run(row.id);
60
+ return rowToCacheEntry(row);
61
+ }
62
+ // Try AST-only match (structural cache hit — same code structure, different prompt wording)
63
+ const astRow = this.stmts.lookupByAst.get(astHash);
64
+ if (astRow) {
65
+ this.stmts.recordHit.run(astRow.id);
66
+ return rowToCacheEntry(astRow);
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ /** Store a response in the cache */
72
+ store(req, analysis, response, meta) {
73
+ if (!this.config.enabled || !analysis.symbols.length)
74
+ return;
75
+ // Evict if over capacity
76
+ this.ensureCapacity();
77
+ const astHash = this.computeASTHash(analysis.symbols);
78
+ const requestHash = this.computeRequestHash(req);
79
+ const id = createHash('sha256').update(astHash + requestHash).digest('hex').slice(0, 16);
80
+ const costEstimate = estimateCost(meta.tokensIn, meta.tokensOut, meta.model);
81
+ this.stmts.insert.run(id, astHash, requestHash, response, meta.model, meta.provider, meta.tokensIn, meta.tokensOut, costEstimate, this.config.ttlHours);
82
+ }
83
+ /** Compute AST hash — captures code structure, survives renames/reformats */
84
+ computeASTHash(symbols) {
85
+ // Hash based on structural properties, NOT code text or names
86
+ const structure = symbols
87
+ .sort((a, b) => a.filePath.localeCompare(b.filePath) || a.startLine - b.startLine)
88
+ .map(s => {
89
+ // Include: kind, export status, parent relationship, line span size
90
+ const span = s.endLine - s.startLine;
91
+ const parent = s.parentId ? '1' : '0';
92
+ return `${s.kind}:${s.exported ? 'E' : 'I'}:${parent}:${span}`;
93
+ })
94
+ .join('|');
95
+ return createHash('sha256').update(structure).digest('hex').slice(0, 16);
96
+ }
97
+ /** Compute request hash — normalized version of the prompt */
98
+ computeRequestHash(req) {
99
+ // Normalize: lowercase, collapse whitespace, remove timestamps
100
+ const normalized = req.messages
101
+ .filter(m => m.role === 'user')
102
+ .map(m => {
103
+ const text = typeof m.content === 'string' ? m.content
104
+ : Array.isArray(m.content)
105
+ ? m.content.filter(p => p.type === 'text').map(p => p.text ?? '').join(' ')
106
+ : '';
107
+ return text.toLowerCase().replace(/\s+/g, ' ').trim();
108
+ })
109
+ .join('\n');
110
+ return createHash('sha256').update(normalized).digest('hex').slice(0, 16);
111
+ }
112
+ /** Evict expired entries + enforce max capacity */
113
+ ensureCapacity() {
114
+ this.stmts.evictExpired.run();
115
+ const count = this.stmts.count.get()?.c ?? 0;
116
+ if (count >= this.config.maxEntries) {
117
+ const toDelete = Math.ceil(this.config.maxEntries * 0.1); // Remove 10%
118
+ this.stmts.evictOldest.run(toDelete);
119
+ }
120
+ }
121
+ /** Invalidate cache entries related to changed files */
122
+ invalidateForFiles(filePaths) {
123
+ // Simple approach: clear all cache when files change
124
+ // (More granular: match ast_hash to symbols in changed files)
125
+ if (filePaths.length > 0) {
126
+ const result = this.rawDb.prepare('DELETE FROM gateway_cache').run();
127
+ return result.changes;
128
+ }
129
+ return 0;
130
+ }
131
+ /** Get cache statistics */
132
+ getStats() {
133
+ const row = this.stmts.stats.get();
134
+ return {
135
+ totalEntries: row?.total_entries ?? 0,
136
+ totalHits: row?.total_hits ?? 0,
137
+ totalTokensCached: row?.total_tokens_cached ?? 0,
138
+ totalCostSaved: row?.total_cost_saved ?? 0,
139
+ };
140
+ }
141
+ }
142
+ function rowToCacheEntry(row) {
143
+ return {
144
+ id: row.id,
145
+ astHash: row.ast_hash,
146
+ requestHash: row.request_hash,
147
+ response: row.response,
148
+ model: row.model,
149
+ provider: row.provider,
150
+ tokensIn: row.tokens_in,
151
+ tokensOut: row.tokens_out,
152
+ costEstimate: row.cost_estimate,
153
+ createdAt: row.created_at,
154
+ hitCount: row.hit_count,
155
+ lastHitAt: row.last_hit_at,
156
+ ttlHours: row.ttl_hours,
157
+ };
158
+ }
159
+ // Rough cost estimation per 1M tokens (USD)
160
+ const MODEL_COSTS = {
161
+ 'gpt-4o': { input: 2.5, output: 10 },
162
+ 'gpt-4o-mini': { input: 0.15, output: 0.6 },
163
+ 'claude-3-5-sonnet': { input: 3, output: 15 },
164
+ 'claude-3-5-haiku': { input: 0.8, output: 4 },
165
+ 'gemini-1.5-pro': { input: 1.25, output: 5 },
166
+ 'gemini-1.5-flash': { input: 0.075, output: 0.3 },
167
+ };
168
+ function estimateCost(tokensIn, tokensOut, model) {
169
+ // Try exact match then prefix match
170
+ const costs = MODEL_COSTS[model]
171
+ ?? Object.entries(MODEL_COSTS).find(([k]) => model.includes(k))?.[1]
172
+ ?? { input: 1, output: 3 }; // Default fallback
173
+ return (tokensIn * costs.input + tokensOut * costs.output) / 1_000_000;
174
+ }
175
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/gateway/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { GatewayConfig } from './types.js';
2
+ /** Load gateway config from gateway.json, applying defaults for missing fields */
3
+ export declare function loadConfig(projectDir: string): GatewayConfig;
4
+ /** Create a default gateway.json if none exists */
5
+ export declare function initConfig(projectDir: string): string;
6
+ /** Validate config, returning errors */
7
+ export declare function validateConfig(config: GatewayConfig): string[];
8
+ /** Resolve env var references in api keys (${VAR_NAME} → process.env.VAR_NAME) */
9
+ export declare function resolveEnvVars(config: GatewayConfig): GatewayConfig;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAyF,MAAM,YAAY,CAAC;AA0CvI,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAgB5D;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAqCrD;AAED,wCAAwC;AACxC,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CA4B9D;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAQnE"}
@@ -0,0 +1,167 @@
1
+ // ── Config — gateway.json loader and validator ──
2
+ import { readFileSync, existsSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ const DEFAULT_ROUTING = {
5
+ thresholds: { economy: 5, standard: 20 },
6
+ intentMultipliers: {
7
+ generate: 1.0,
8
+ refactor: 1.5,
9
+ review: 0.8,
10
+ test: 0.7,
11
+ debug: 1.2,
12
+ explain: 0.5,
13
+ docstring: 0.3,
14
+ unknown: 1.0,
15
+ },
16
+ defaultTier: 'standard',
17
+ };
18
+ const DEFAULT_CACHE = {
19
+ enabled: true,
20
+ maxEntries: 1000,
21
+ ttlHours: 24,
22
+ };
23
+ const DEFAULT_CONTEXT_INJECTION = {
24
+ enabled: true,
25
+ maxTokens: 500,
26
+ includeCallers: true,
27
+ includeDependencies: true,
28
+ includeBlastRadius: true,
29
+ };
30
+ const DEFAULT_CONFIG = {
31
+ port: 4141,
32
+ host: '127.0.0.1',
33
+ providers: [],
34
+ routing: DEFAULT_ROUTING,
35
+ cache: DEFAULT_CACHE,
36
+ contextInjection: DEFAULT_CONTEXT_INJECTION,
37
+ privacy: { rules: [], defaultAction: 'allow' },
38
+ rateLimit: { windowMs: 60000, maxRequests: 60 },
39
+ };
40
+ /** Load gateway config from gateway.json, applying defaults for missing fields */
41
+ export function loadConfig(projectDir) {
42
+ const configPath = join(projectDir, 'gateway.json');
43
+ if (!existsSync(configPath)) {
44
+ return { ...DEFAULT_CONFIG };
45
+ }
46
+ const raw = readFileSync(configPath, 'utf-8');
47
+ let parsed;
48
+ try {
49
+ parsed = JSON.parse(raw);
50
+ }
51
+ catch {
52
+ throw new Error(`Invalid JSON in ${configPath}`);
53
+ }
54
+ return mergeConfig(parsed);
55
+ }
56
+ /** Create a default gateway.json if none exists */
57
+ export function initConfig(projectDir) {
58
+ const configPath = join(projectDir, 'gateway.json');
59
+ if (existsSync(configPath)) {
60
+ return configPath;
61
+ }
62
+ const template = {
63
+ $schema: './node_modules/milens/gateway-schema.json',
64
+ port: 4141,
65
+ host: '127.0.0.1',
66
+ providers: [
67
+ {
68
+ id: 'openai-main',
69
+ name: 'OpenAI',
70
+ tier: 'premium',
71
+ format: 'openai',
72
+ endpoint: 'https://api.openai.com/v1',
73
+ apiKey: '${OPENAI_API_KEY}',
74
+ models: ['gpt-4o', 'gpt-4o-mini'],
75
+ },
76
+ ],
77
+ routing: DEFAULT_ROUTING,
78
+ cache: DEFAULT_CACHE,
79
+ contextInjection: DEFAULT_CONTEXT_INJECTION,
80
+ privacy: {
81
+ rules: [
82
+ { pathPattern: '**/.env*', action: 'block', reason: 'Environment files contain secrets' },
83
+ { pathPattern: '**/secrets/**', action: 'block', reason: 'Secret files' },
84
+ ],
85
+ defaultAction: 'allow',
86
+ },
87
+ rateLimit: { windowMs: 60000, maxRequests: 60 },
88
+ };
89
+ writeFileSync(configPath, JSON.stringify(template, null, 2) + '\n', 'utf-8');
90
+ return configPath;
91
+ }
92
+ /** Validate config, returning errors */
93
+ export function validateConfig(config) {
94
+ const errors = [];
95
+ if (config.port < 1 || config.port > 65535) {
96
+ errors.push(`Invalid port: ${config.port}`);
97
+ }
98
+ if (!config.providers.length) {
99
+ errors.push('No providers configured — at least one provider is required');
100
+ }
101
+ for (const p of config.providers) {
102
+ if (!p.id)
103
+ errors.push('Provider missing "id"');
104
+ if (!p.format)
105
+ errors.push(`Provider "${p.id}": missing "format"`);
106
+ if (!p.endpoint)
107
+ errors.push(`Provider "${p.id}": missing "endpoint"`);
108
+ if (!p.apiKey)
109
+ errors.push(`Provider "${p.id}": missing "apiKey"`);
110
+ if (!p.models?.length)
111
+ errors.push(`Provider "${p.id}": missing "models"`);
112
+ // Check for env var references
113
+ if (p.apiKey.startsWith('${') && p.apiKey.endsWith('}')) {
114
+ const envVar = p.apiKey.slice(2, -1);
115
+ if (!process.env[envVar]) {
116
+ errors.push(`Provider "${p.id}": env var ${envVar} is not set`);
117
+ }
118
+ }
119
+ }
120
+ return errors;
121
+ }
122
+ /** Resolve env var references in api keys (${VAR_NAME} → process.env.VAR_NAME) */
123
+ export function resolveEnvVars(config) {
124
+ return {
125
+ ...config,
126
+ providers: config.providers.map(p => ({
127
+ ...p,
128
+ apiKey: resolveEnvValue(p.apiKey),
129
+ })),
130
+ };
131
+ }
132
+ function resolveEnvValue(value) {
133
+ if (value.startsWith('${') && value.endsWith('}')) {
134
+ const envVar = value.slice(2, -1);
135
+ return process.env[envVar] ?? value;
136
+ }
137
+ return value;
138
+ }
139
+ function mergeConfig(raw) {
140
+ return {
141
+ port: typeof raw.port === 'number' ? raw.port : DEFAULT_CONFIG.port,
142
+ host: typeof raw.host === 'string' ? raw.host : DEFAULT_CONFIG.host,
143
+ providers: Array.isArray(raw.providers) ? raw.providers : [],
144
+ routing: {
145
+ ...DEFAULT_ROUTING,
146
+ ...(typeof raw.routing === 'object' && raw.routing ? raw.routing : {}),
147
+ },
148
+ cache: {
149
+ ...DEFAULT_CACHE,
150
+ ...(typeof raw.cache === 'object' && raw.cache ? raw.cache : {}),
151
+ },
152
+ contextInjection: {
153
+ ...DEFAULT_CONTEXT_INJECTION,
154
+ ...(typeof raw.contextInjection === 'object' && raw.contextInjection
155
+ ? raw.contextInjection : {}),
156
+ },
157
+ privacy: {
158
+ rules: Array.isArray(raw.privacy?.rules) ? raw.privacy.rules : [],
159
+ defaultAction: raw.privacy?.defaultAction ?? 'allow',
160
+ },
161
+ rateLimit: {
162
+ windowMs: raw.rateLimit?.windowMs ?? 60000,
163
+ maxRequests: raw.rateLimit?.maxRequests ?? 60,
164
+ },
165
+ };
166
+ }
167
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/gateway/config.ts"],"names":[],"mappings":"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"}