@triedotdev/mcp 1.0.94 → 1.0.99

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 (83) hide show
  1. package/README.md +145 -137
  2. package/dist/{chunk-JAAIHNOE.js → chunk-APMV77PU.js} +21 -6
  3. package/dist/chunk-APMV77PU.js.map +1 -0
  4. package/dist/{chunk-HLSBTOVE.js → chunk-B3MNN3XB.js} +13 -18
  5. package/dist/{chunk-HLSBTOVE.js.map → chunk-B3MNN3XB.js.map} +1 -1
  6. package/dist/{chunk-IIF5XDCJ.js → chunk-DIZFGLXE.js} +787 -4696
  7. package/dist/chunk-DIZFGLXE.js.map +1 -0
  8. package/dist/{chunk-JO6RVXS6.js → chunk-F4NJ4CBP.js} +2 -2
  9. package/dist/{chunk-AZRCKBGF.js → chunk-FNCCZ3XB.js} +1222 -75
  10. package/dist/chunk-FNCCZ3XB.js.map +1 -0
  11. package/dist/chunk-G76DYVGX.js +136 -0
  12. package/dist/chunk-G76DYVGX.js.map +1 -0
  13. package/dist/chunk-HSNE46VE.js +956 -0
  14. package/dist/chunk-HSNE46VE.js.map +1 -0
  15. package/dist/{chunk-STEFLYPR.js → chunk-IXO4G4D3.js} +2 -2
  16. package/dist/{chunk-OEYIOOYB.js → chunk-JDHR5BDR.js} +2 -3
  17. package/dist/chunk-NIASHOAB.js +1304 -0
  18. package/dist/chunk-NIASHOAB.js.map +1 -0
  19. package/dist/{chunk-CKM6A3G6.js → chunk-OVRG5RP3.js} +6 -7
  20. package/dist/chunk-OVRG5RP3.js.map +1 -0
  21. package/dist/{chunk-RYRVEO2B.js → chunk-R3I2GCZC.js} +3 -3
  22. package/dist/{chunk-WT3XQCG2.js → chunk-R4AAPFXC.js} +2 -2
  23. package/dist/cli/create-agent.js +931 -7
  24. package/dist/cli/create-agent.js.map +1 -1
  25. package/dist/cli/main.js +151 -383
  26. package/dist/cli/main.js.map +1 -1
  27. package/dist/cli/yolo-daemon.js +13 -20
  28. package/dist/cli/yolo-daemon.js.map +1 -1
  29. package/dist/{goal-manager-HOZ7R2QV.js → goal-manager-LAOT4QQX.js} +6 -6
  30. package/dist/guardian-agent-M352CBE5.js +19 -0
  31. package/dist/index.js +1025 -1550
  32. package/dist/index.js.map +1 -1
  33. package/dist/{issue-store-DXIOP6AK.js → issue-store-W2X33X2X.js} +4 -4
  34. package/dist/{progress-LHI66U7B.js → progress-PQVEM7BR.js} +2 -2
  35. package/dist/{vibe-code-signatures-C5A4BHXD.js → vibe-code-signatures-ELEWJFGZ.js} +3 -3
  36. package/dist/{vulnerability-signatures-SVIHJQO5.js → vulnerability-signatures-EIJQX2TS.js} +3 -3
  37. package/dist/workers/agent-worker.js +2 -11
  38. package/dist/workers/agent-worker.js.map +1 -1
  39. package/package.json +2 -2
  40. package/dist/agent-smith-MYQ35URL.js +0 -14
  41. package/dist/agent-smith-runner-4TBONXCP.js +0 -573
  42. package/dist/agent-smith-runner-4TBONXCP.js.map +0 -1
  43. package/dist/cache-manager-RMPRPD5T.js +0 -10
  44. package/dist/chunk-AZRCKBGF.js.map +0 -1
  45. package/dist/chunk-CKM6A3G6.js.map +0 -1
  46. package/dist/chunk-E2ZATINO.js +0 -10879
  47. package/dist/chunk-E2ZATINO.js.map +0 -1
  48. package/dist/chunk-FFWNZUG2.js +0 -266
  49. package/dist/chunk-FFWNZUG2.js.map +0 -1
  50. package/dist/chunk-FK6DQKDY.js +0 -175
  51. package/dist/chunk-FK6DQKDY.js.map +0 -1
  52. package/dist/chunk-IFGF33R5.js +0 -279
  53. package/dist/chunk-IFGF33R5.js.map +0 -1
  54. package/dist/chunk-IIF5XDCJ.js.map +0 -1
  55. package/dist/chunk-JAAIHNOE.js.map +0 -1
  56. package/dist/chunk-ODWDESYP.js +0 -141
  57. package/dist/chunk-ODWDESYP.js.map +0 -1
  58. package/dist/chunk-OWBWNXSC.js +0 -955
  59. package/dist/chunk-OWBWNXSC.js.map +0 -1
  60. package/dist/chunk-Q764X2WD.js +0 -2124
  61. package/dist/chunk-Q764X2WD.js.map +0 -1
  62. package/dist/chunk-RE6ZWXJC.js +0 -279
  63. package/dist/chunk-RE6ZWXJC.js.map +0 -1
  64. package/dist/chunk-RNJ6JKMA.js +0 -2270
  65. package/dist/chunk-RNJ6JKMA.js.map +0 -1
  66. package/dist/chunk-Y62VM3ER.js +0 -536
  67. package/dist/chunk-Y62VM3ER.js.map +0 -1
  68. package/dist/git-45LZUUYA.js +0 -29
  69. package/dist/guardian-agent-RB2UQP5V.js +0 -21
  70. package/dist/progress-LHI66U7B.js.map +0 -1
  71. package/dist/vibe-code-signatures-C5A4BHXD.js.map +0 -1
  72. package/dist/vulnerability-signatures-SVIHJQO5.js.map +0 -1
  73. /package/dist/{chunk-JO6RVXS6.js.map → chunk-F4NJ4CBP.js.map} +0 -0
  74. /package/dist/{chunk-STEFLYPR.js.map → chunk-IXO4G4D3.js.map} +0 -0
  75. /package/dist/{chunk-OEYIOOYB.js.map → chunk-JDHR5BDR.js.map} +0 -0
  76. /package/dist/{chunk-RYRVEO2B.js.map → chunk-R3I2GCZC.js.map} +0 -0
  77. /package/dist/{chunk-WT3XQCG2.js.map → chunk-R4AAPFXC.js.map} +0 -0
  78. /package/dist/{agent-smith-MYQ35URL.js.map → goal-manager-LAOT4QQX.js.map} +0 -0
  79. /package/dist/{cache-manager-RMPRPD5T.js.map → guardian-agent-M352CBE5.js.map} +0 -0
  80. /package/dist/{git-45LZUUYA.js.map → issue-store-W2X33X2X.js.map} +0 -0
  81. /package/dist/{goal-manager-HOZ7R2QV.js.map → progress-PQVEM7BR.js.map} +0 -0
  82. /package/dist/{guardian-agent-RB2UQP5V.js.map → vibe-code-signatures-ELEWJFGZ.js.map} +0 -0
  83. /package/dist/{issue-store-DXIOP6AK.js.map → vulnerability-signatures-EIJQX2TS.js.map} +0 -0
@@ -1,955 +0,0 @@
1
- import {
2
- getTrieDirectory,
3
- getWorkingDirectory
4
- } from "./chunk-WT3XQCG2.js";
5
-
6
- // src/ingest/agent-builder.ts
7
- import Anthropic2 from "@anthropic-ai/sdk";
8
-
9
- // src/ingest/document-parser.ts
10
- import { readFile } from "fs/promises";
11
- import { extname, basename } from "path";
12
- async function parseDocument(filePath) {
13
- const ext = extname(filePath).toLowerCase();
14
- const fileType = getFileType(ext);
15
- if (!fileType) {
16
- throw new Error(`Unsupported file type: ${ext}. Supported: .pdf, .txt, .md, .rtf`);
17
- }
18
- let rawText;
19
- let metadata = {
20
- fileType,
21
- originalPath: filePath,
22
- parsedAt: (/* @__PURE__ */ new Date()).toISOString()
23
- };
24
- switch (fileType) {
25
- case "pdf":
26
- const pdfResult = await parsePDF(filePath);
27
- rawText = pdfResult.text;
28
- metadata.pageCount = pdfResult.pageCount;
29
- if (pdfResult.title !== void 0) {
30
- metadata.title = pdfResult.title;
31
- }
32
- break;
33
- case "txt":
34
- rawText = await parseTXT(filePath);
35
- break;
36
- case "md":
37
- rawText = await parseMarkdown(filePath);
38
- break;
39
- case "rtf":
40
- rawText = await parseRTF(filePath);
41
- break;
42
- default:
43
- throw new Error(`Unsupported file type: ${fileType}`);
44
- }
45
- metadata.wordCount = countWords(rawText);
46
- const sections = extractSections(rawText, fileType);
47
- if (!metadata.title) {
48
- metadata.title = extractTitle(rawText, sections) || basename(filePath, ext);
49
- }
50
- return {
51
- rawText,
52
- metadata,
53
- sections
54
- };
55
- }
56
- function getFileType(ext) {
57
- const typeMap = {
58
- ".pdf": "pdf",
59
- ".txt": "txt",
60
- ".md": "md",
61
- ".markdown": "md",
62
- ".rtf": "rtf"
63
- };
64
- return typeMap[ext] || null;
65
- }
66
- async function parsePDF(filePath) {
67
- try {
68
- const pdfParse = (await import("pdf-parse")).default;
69
- const dataBuffer = await readFile(filePath);
70
- const data = await pdfParse(dataBuffer);
71
- const result = {
72
- text: data.text,
73
- pageCount: data.numpages
74
- };
75
- if (data.info?.Title) {
76
- result.title = data.info.Title;
77
- }
78
- return result;
79
- } catch (error) {
80
- if (error.code === "MODULE_NOT_FOUND") {
81
- throw new Error(
82
- "PDF parsing requires the pdf-parse package. Install it with: npm install pdf-parse"
83
- );
84
- }
85
- throw error;
86
- }
87
- }
88
- async function parseTXT(filePath) {
89
- return await readFile(filePath, "utf-8");
90
- }
91
- async function parseMarkdown(filePath) {
92
- const content = await readFile(filePath, "utf-8");
93
- return content.replace(/^[-*_]{3,}$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
94
- }
95
- async function parseRTF(filePath) {
96
- const content = await readFile(filePath, "utf-8");
97
- return stripRTF(content);
98
- }
99
- function stripRTF(rtf) {
100
- let text = rtf.replace(/^{\\rtf1[^}]*}/i, "");
101
- text = text.replace(/\\[a-z]+(-?\d+)?[ ]?/gi, "");
102
- text = text.replace(/{[^{}]*}/g, "");
103
- text = text.replace(/\\'([0-9a-f]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16))).replace(/\\par\b/g, "\n").replace(/\\tab\b/g, " ").replace(/\\line\b/g, "\n").replace(/[{}\\]/g, "");
104
- text = text.replace(/\r\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
105
- return text;
106
- }
107
- function countWords(text) {
108
- return text.split(/\s+/).filter((word) => word.length > 0).length;
109
- }
110
- function extractSections(text, fileType) {
111
- const sections = [];
112
- if (fileType === "md") {
113
- const headingRegex = /^(#{1,6})\s+(.+)$/gm;
114
- let match;
115
- while ((match = headingRegex.exec(text)) !== null) {
116
- const level = match[1].length;
117
- const title = match[2].trim();
118
- const startIndex = match.index;
119
- if (sections.length > 0) {
120
- const lastSection = sections[sections.length - 1];
121
- lastSection.endIndex = startIndex;
122
- lastSection.content = text.slice(
123
- lastSection.startIndex,
124
- startIndex
125
- ).trim();
126
- }
127
- sections.push({
128
- title,
129
- level,
130
- startIndex,
131
- endIndex: text.length,
132
- content: ""
133
- });
134
- }
135
- if (sections.length > 0) {
136
- const lastSection = sections[sections.length - 1];
137
- lastSection.content = text.slice(
138
- lastSection.startIndex
139
- ).trim();
140
- }
141
- } else {
142
- const chapterPatterns = [
143
- /^chapter\s+(\d+|[ivxlc]+)[:\.\s]+(.*)$/gim,
144
- /^section\s+(\d+|[ivxlc]+)[:\.\s]+(.*)$/gim,
145
- /^part\s+(\d+|[ivxlc]+)[:\.\s]+(.*)$/gim,
146
- /^(\d+)\.\s+([A-Z][^.]+)$/gm,
147
- /^([A-Z][A-Z\s]+)$/gm
148
- // ALL CAPS headings
149
- ];
150
- for (const pattern of chapterPatterns) {
151
- let match;
152
- pattern.lastIndex = 0;
153
- while ((match = pattern.exec(text)) !== null) {
154
- const title = match[2] || match[1] || match[0];
155
- sections.push({
156
- title: title.trim(),
157
- level: 1,
158
- startIndex: match.index,
159
- endIndex: text.length,
160
- content: ""
161
- });
162
- }
163
- if (sections.length > 0) break;
164
- }
165
- sections.sort((a, b) => a.startIndex - b.startIndex);
166
- for (let i = 0; i < sections.length; i++) {
167
- const section = sections[i];
168
- const nextSection = sections[i + 1];
169
- const endIndex = nextSection !== void 0 ? nextSection.startIndex : text.length;
170
- section.endIndex = endIndex;
171
- section.content = text.slice(section.startIndex, endIndex).trim();
172
- }
173
- }
174
- if (sections.length === 0) {
175
- sections.push({
176
- title: "Document Content",
177
- level: 1,
178
- startIndex: 0,
179
- endIndex: text.length,
180
- content: text.trim()
181
- });
182
- }
183
- return sections;
184
- }
185
- function extractTitle(text, sections) {
186
- const firstSection = sections[0];
187
- if (firstSection !== void 0 && firstSection.title !== "Document Content") {
188
- return firstSection.title;
189
- }
190
- const firstLine = text.split("\n")[0]?.trim();
191
- if (firstLine && firstLine.length < 100 && !firstLine.includes(".")) {
192
- return firstLine;
193
- }
194
- return null;
195
- }
196
- function chunkDocument(result, maxChunkSize = 4e3) {
197
- const chunks = [];
198
- if (result.rawText.length <= maxChunkSize) {
199
- return [result.rawText];
200
- }
201
- if (result.sections.length > 1) {
202
- let currentChunk = "";
203
- for (const section of result.sections) {
204
- const sectionText = `## ${section.title}
205
-
206
- ${section.content}
207
-
208
- `;
209
- if (currentChunk.length + sectionText.length > maxChunkSize) {
210
- if (currentChunk) chunks.push(currentChunk.trim());
211
- if (sectionText.length > maxChunkSize) {
212
- chunks.push(...splitByParagraphs(sectionText, maxChunkSize));
213
- currentChunk = "";
214
- } else {
215
- currentChunk = sectionText;
216
- }
217
- } else {
218
- currentChunk += sectionText;
219
- }
220
- }
221
- if (currentChunk) chunks.push(currentChunk.trim());
222
- } else {
223
- chunks.push(...splitByParagraphs(result.rawText, maxChunkSize));
224
- }
225
- return chunks;
226
- }
227
- function splitByParagraphs(text, maxSize) {
228
- const chunks = [];
229
- const paragraphs = text.split(/\n\s*\n/);
230
- let currentChunk = "";
231
- for (const para of paragraphs) {
232
- if (currentChunk.length + para.length + 2 > maxSize) {
233
- if (currentChunk) chunks.push(currentChunk.trim());
234
- if (para.length > maxSize) {
235
- chunks.push(...splitBySentences(para, maxSize));
236
- currentChunk = "";
237
- } else {
238
- currentChunk = para;
239
- }
240
- } else {
241
- currentChunk += (currentChunk ? "\n\n" : "") + para;
242
- }
243
- }
244
- if (currentChunk) chunks.push(currentChunk.trim());
245
- return chunks;
246
- }
247
- function splitBySentences(text, maxSize) {
248
- const chunks = [];
249
- const sentences = text.match(/[^.!?]+[.!?]+/g) || [text];
250
- let currentChunk = "";
251
- for (const sentence of sentences) {
252
- if (currentChunk.length + sentence.length > maxSize) {
253
- if (currentChunk) chunks.push(currentChunk.trim());
254
- currentChunk = sentence;
255
- } else {
256
- currentChunk += sentence;
257
- }
258
- }
259
- if (currentChunk) chunks.push(currentChunk.trim());
260
- return chunks;
261
- }
262
-
263
- // src/ingest/knowledge-compressor.ts
264
- import Anthropic from "@anthropic-ai/sdk";
265
-
266
- // src/ingest/compression-prompts.ts
267
- var COMPRESSION_PROMPTS = {
268
- /**
269
- * System prompt for the knowledge extractor
270
- */
271
- system: `You are an expert knowledge extraction system. Your job is to analyze documents and extract structured, actionable knowledge that can be used by a code review agent.
272
-
273
- You must output valid JSON that matches the required schema exactly. Be thorough but concise - extract the essence of the knowledge without unnecessary verbosity.
274
-
275
- Focus on:
276
- 1. Core concepts that are fundamental to understand the material
277
- 2. Best practices that should be followed
278
- 3. Anti-patterns and mistakes to avoid
279
- 4. Detection patterns that could identify issues in code
280
- 5. Key terminology and definitions`,
281
- /**
282
- * Prompt for extracting knowledge from a chunk
283
- */
284
- extractChunk: `Analyze this document chunk and extract structured knowledge.
285
-
286
- ## Document Chunk:
287
- {{chunk}}
288
-
289
- ## Instructions:
290
- Extract the following from this chunk:
291
-
292
- 1. **Core Concepts**: Key ideas, principles, or rules that are taught
293
- 2. **Best Practices**: Recommended approaches or patterns
294
- 3. **Anti-Patterns**: Things to avoid, common mistakes
295
- 4. **Code Patterns**: Any code patterns or detection rules that could identify issues
296
- 5. **Terminology**: Important terms and their definitions
297
-
298
- Output as JSON:
299
- {
300
- "coreConcepts": [
301
- {
302
- "name": "string",
303
- "description": "string",
304
- "importance": "critical" | "important" | "supplementary",
305
- "keywords": ["string"]
306
- }
307
- ],
308
- "bestPractices": [
309
- {
310
- "name": "string",
311
- "description": "string",
312
- "rationale": "string",
313
- "codeExample": "string or null"
314
- }
315
- ],
316
- "antiPatterns": [
317
- {
318
- "name": "string",
319
- "description": "string",
320
- "whyBad": "string",
321
- "betterAlternative": "string"
322
- }
323
- ],
324
- "codePatterns": [
325
- {
326
- "name": "string",
327
- "description": "string",
328
- "type": "best-practice" | "anti-pattern" | "security" | "compliance",
329
- "regexHint": "string (a regex pattern that might detect this, or null)",
330
- "keywords": ["string"]
331
- }
332
- ],
333
- "terminology": {
334
- "term": "definition"
335
- }
336
- }
337
-
338
- Only include items that are clearly present in the chunk. Quality over quantity.`,
339
- /**
340
- * Prompt for merging extracted knowledge
341
- */
342
- mergeKnowledge: `Merge and deduplicate these knowledge extractions into a cohesive summary.
343
-
344
- ## Extractions to Merge:
345
- {{extractions}}
346
-
347
- ## Instructions:
348
- 1. Combine similar concepts
349
- 2. Remove duplicates
350
- 3. Prioritize the most important items
351
- 4. Ensure consistency in terminology
352
- 5. Rank items by importance
353
-
354
- Output a single merged JSON with the same structure, keeping only the most valuable and distinct items.
355
- Limit to top 20 core concepts, 15 best practices, 15 anti-patterns, and 25 code patterns.`,
356
- /**
357
- * Prompt for generating detection rules
358
- */
359
- generateDetectionRules: `Based on this knowledge base, generate detection rules for a code review agent.
360
-
361
- ## Knowledge Base:
362
- {{knowledge}}
363
-
364
- ## Document Context:
365
- - Title: {{title}}
366
- - Domain: {{domain}}
367
- - Word Count: {{wordCount}}
368
-
369
- ## Instructions:
370
- For each anti-pattern and best practice, generate detection rules that could find violations in code.
371
-
372
- For each rule, provide:
373
- 1. A unique ID (format: {{prefix}}-XXX)
374
- 2. Clear name and description
375
- 3. Severity (critical, serious, moderate, low, info)
376
- 4. Detection patterns:
377
- - regex: Array of regex patterns (JavaScript-compatible)
378
- - keywords: Words that might indicate this issue
379
- - semantic: Natural language description for AI-based detection
380
- 5. Fix information:
381
- - description: How to fix
382
- - example: Code example if applicable
383
- - autoFixable: boolean
384
-
385
- Output as JSON array of detection rules:
386
- [
387
- {
388
- "id": "string",
389
- "name": "string",
390
- "description": "string",
391
- "severity": "critical" | "serious" | "moderate" | "low" | "info",
392
- "patterns": {
393
- "regex": ["string"],
394
- "keywords": ["string"],
395
- "semantic": "string"
396
- },
397
- "fix": {
398
- "description": "string",
399
- "example": "string or null",
400
- "autoFixable": boolean
401
- },
402
- "regulation": "string or null (for legal/compliance rules)",
403
- "category": "string"
404
- }
405
- ]
406
-
407
- Generate 15-30 detection rules prioritizing the most impactful issues.`,
408
- /**
409
- * Prompt for generating agent prompts
410
- */
411
- generateAgentPrompts: `Generate system and analysis prompts for a code review agent based on this knowledge.
412
-
413
- ## Knowledge Base Summary:
414
- {{summary}}
415
-
416
- ## Core Concepts:
417
- {{concepts}}
418
-
419
- ## Detection Focus:
420
- {{patterns}}
421
-
422
- ## Agent Info:
423
- - Name: {{agentName}}
424
- - Category: {{category}}
425
- - Domain: {{domain}}
426
-
427
- ## Instructions:
428
- Generate:
429
- 1. A system prompt that gives the agent its persona and expertise
430
- 2. An analysis prompt template for reviewing code
431
- 3. A fix prompt template for suggesting fixes
432
-
433
- The prompts should:
434
- - Reference the specific knowledge from the document
435
- - Be authoritative but helpful
436
- - Include the key concepts and terminology
437
- - Guide the agent to look for the specific patterns
438
-
439
- Output as JSON:
440
- {
441
- "systemPrompt": "string",
442
- "analysisPrompt": "string (use {{code}}, {{filePath}}, {{language}} as placeholders)",
443
- "fixPrompt": "string (use {{issue}}, {{code}}, {{filePath}} as placeholders)"
444
- }`,
445
- /**
446
- * Prompt for detecting document domain
447
- */
448
- detectDomain: `Analyze this document and determine its primary domain/category.
449
-
450
- ## Document Title:
451
- {{title}}
452
-
453
- ## Sample Content:
454
- {{sample}}
455
-
456
- ## Instructions:
457
- Determine the primary domain of this document. Choose ONE:
458
- - "technical": Programming, frameworks, libraries, code patterns
459
- - "legal": Laws, regulations, compliance (GDPR, HIPAA, etc.)
460
- - "policy": Company policies, internal rules, guidelines
461
- - "security": Security practices, vulnerability prevention
462
- - "architecture": System design, patterns, architecture principles
463
- - "general": General knowledge, doesn't fit other categories
464
-
465
- Also determine:
466
- 1. What types of code/files this knowledge applies to
467
- 2. What context signals should trigger this agent
468
- 3. Key content patterns to look for
469
-
470
- Output as JSON:
471
- {
472
- "domain": "technical" | "legal" | "policy" | "security" | "architecture" | "general",
473
- "filePatterns": ["*.ext", ...],
474
- "contentPatterns": ["regex pattern", ...],
475
- "contextSignals": ["touchesAuth", "touchesUI", ...],
476
- "reasoning": "Brief explanation of why this domain was chosen"
477
- }`,
478
- /**
479
- * Prompt for generating a summary
480
- */
481
- generateSummary: `Create a concise executive summary of this document for use in an AI agent's context.
482
-
483
- ## Document:
484
- {{content}}
485
-
486
- ## Instructions:
487
- Write a 2-3 paragraph summary that:
488
- 1. Explains what the document covers
489
- 2. Highlights the most important takeaways
490
- 3. Describes how this knowledge applies to code review
491
-
492
- The summary will be used as context for an AI code review agent, so focus on actionable insights.
493
-
494
- Keep it under 500 words.`
495
- };
496
-
497
- // src/ingest/knowledge-compressor.ts
498
- async function compressKnowledge(document, options) {
499
- const { agentName, maxChunkSize = 4e3, verbose = false } = options;
500
- const client = new Anthropic();
501
- const log = verbose ? console.error.bind(console) : () => {
502
- };
503
- log("\u{1F4DA} Starting knowledge compression...");
504
- log(" \u251C\u2500 Detecting document domain...");
505
- const domainInfo = await detectDomain(client, document);
506
- log(` \u2502 \u2514\u2500 Domain: ${domainInfo.domain}`);
507
- const chunks = chunkDocument(document, maxChunkSize);
508
- log(` \u251C\u2500 Document chunked into ${chunks.length} pieces`);
509
- log(" \u251C\u2500 Extracting knowledge from chunks...");
510
- const extractions = [];
511
- for (let i = 0; i < chunks.length; i++) {
512
- log(` \u2502 \u251C\u2500 Processing chunk ${i + 1}/${chunks.length}...`);
513
- try {
514
- const chunk = chunks[i];
515
- if (chunk !== void 0) {
516
- const extraction = await extractFromChunk(client, chunk);
517
- extractions.push(extraction);
518
- }
519
- } catch (error) {
520
- log(` \u2502 \u2502 \u2514\u2500 Warning: Failed to extract from chunk ${i + 1}`);
521
- }
522
- }
523
- log(" \u251C\u2500 Merging and deduplicating knowledge...");
524
- const mergedKnowledge = await mergeExtractions(client, extractions);
525
- log(" \u251C\u2500 Generating detection rules...");
526
- const detectionRules = await generateDetectionRules(
527
- client,
528
- mergedKnowledge,
529
- document.metadata.title || agentName,
530
- domainInfo.domain,
531
- agentName
532
- );
533
- log(` \u2502 \u2514\u2500 Generated ${detectionRules.length} detection rules`);
534
- log(" \u2514\u2500 Generating knowledge summary...");
535
- const summary = await generateSummary(client, document.rawText.slice(0, 8e3));
536
- const compressed = {
537
- domain: domainInfo.domain,
538
- summary,
539
- coreConcepts: mergedKnowledge.coreConcepts,
540
- bestPractices: mergedKnowledge.bestPractices,
541
- antiPatterns: mergedKnowledge.antiPatterns,
542
- detectionRules,
543
- glossary: mergedKnowledge.terminology,
544
- sourceDocument: {
545
- title: document.metadata.title || agentName,
546
- wordCount: document.metadata.wordCount,
547
- compressionRatio: Math.round(document.metadata.wordCount / (summary.length + JSON.stringify(detectionRules).length / 5))
548
- }
549
- };
550
- return compressed;
551
- }
552
- async function detectDomain(client, document) {
553
- const sampleSize = Math.min(document.rawText.length, 3e3);
554
- const sample = document.rawText.slice(0, sampleSize);
555
- const prompt = COMPRESSION_PROMPTS.detectDomain.replace("{{title}}", document.metadata.title || "Unknown").replace("{{sample}}", sample);
556
- const response = await client.messages.create({
557
- model: "claude-sonnet-4-20250514",
558
- max_tokens: 1e3,
559
- system: COMPRESSION_PROMPTS.system,
560
- messages: [{ role: "user", content: prompt }]
561
- });
562
- const firstContent = response.content[0];
563
- const text = firstContent !== void 0 && firstContent.type === "text" ? firstContent.text : "";
564
- try {
565
- const jsonMatch = text.match(/\{[\s\S]*\}/);
566
- if (jsonMatch) {
567
- return JSON.parse(jsonMatch[0]);
568
- }
569
- } catch (e) {
570
- }
571
- return {
572
- domain: "general",
573
- filePatterns: ["*"],
574
- contentPatterns: [],
575
- contextSignals: [],
576
- reasoning: "Could not determine domain, using general"
577
- };
578
- }
579
- async function extractFromChunk(client, chunk) {
580
- const prompt = COMPRESSION_PROMPTS.extractChunk.replace("{{chunk}}", chunk);
581
- const response = await client.messages.create({
582
- model: "claude-sonnet-4-20250514",
583
- max_tokens: 4e3,
584
- system: COMPRESSION_PROMPTS.system,
585
- messages: [{ role: "user", content: prompt }]
586
- });
587
- const firstContent = response.content[0];
588
- const text = firstContent !== void 0 && firstContent.type === "text" ? firstContent.text : "";
589
- try {
590
- const jsonMatch = text.match(/\{[\s\S]*\}/);
591
- if (jsonMatch) {
592
- const parsed = JSON.parse(jsonMatch[0]);
593
- return {
594
- coreConcepts: parsed.coreConcepts || [],
595
- bestPractices: parsed.bestPractices || [],
596
- antiPatterns: parsed.antiPatterns || [],
597
- codePatterns: parsed.codePatterns || [],
598
- terminology: parsed.terminology || {}
599
- };
600
- }
601
- } catch (e) {
602
- }
603
- return {
604
- coreConcepts: [],
605
- bestPractices: [],
606
- antiPatterns: [],
607
- codePatterns: [],
608
- terminology: {}
609
- };
610
- }
611
- async function mergeExtractions(client, extractions) {
612
- if (extractions.length <= 2) {
613
- return combineExtractions(extractions);
614
- }
615
- const prompt = COMPRESSION_PROMPTS.mergeKnowledge.replace("{{extractions}}", JSON.stringify(extractions, null, 2));
616
- const response = await client.messages.create({
617
- model: "claude-sonnet-4-20250514",
618
- max_tokens: 8e3,
619
- system: COMPRESSION_PROMPTS.system,
620
- messages: [{ role: "user", content: prompt }]
621
- });
622
- const firstContent = response.content[0];
623
- const text = firstContent !== void 0 && firstContent.type === "text" ? firstContent.text : "";
624
- try {
625
- const jsonMatch = text.match(/\{[\s\S]*\}/);
626
- if (jsonMatch) {
627
- return JSON.parse(jsonMatch[0]);
628
- }
629
- } catch (e) {
630
- }
631
- return combineExtractions(extractions);
632
- }
633
- function combineExtractions(extractions) {
634
- const combined = {
635
- coreConcepts: [],
636
- bestPractices: [],
637
- antiPatterns: [],
638
- codePatterns: [],
639
- terminology: {}
640
- };
641
- const seenConcepts = /* @__PURE__ */ new Set();
642
- const seenPractices = /* @__PURE__ */ new Set();
643
- const seenAntiPatterns = /* @__PURE__ */ new Set();
644
- const seenPatterns = /* @__PURE__ */ new Set();
645
- for (const extraction of extractions) {
646
- for (const concept of extraction.coreConcepts) {
647
- const key = concept.name.toLowerCase();
648
- if (!seenConcepts.has(key)) {
649
- seenConcepts.add(key);
650
- combined.coreConcepts.push(concept);
651
- }
652
- }
653
- for (const practice of extraction.bestPractices) {
654
- const key = practice.name.toLowerCase();
655
- if (!seenPractices.has(key)) {
656
- seenPractices.add(key);
657
- combined.bestPractices.push(practice);
658
- }
659
- }
660
- for (const anti of extraction.antiPatterns) {
661
- const key = anti.name.toLowerCase();
662
- if (!seenAntiPatterns.has(key)) {
663
- seenAntiPatterns.add(key);
664
- combined.antiPatterns.push(anti);
665
- }
666
- }
667
- for (const pattern of extraction.codePatterns) {
668
- const key = pattern.name.toLowerCase();
669
- if (!seenPatterns.has(key)) {
670
- seenPatterns.add(key);
671
- combined.codePatterns.push(pattern);
672
- }
673
- }
674
- Object.assign(combined.terminology, extraction.terminology);
675
- }
676
- return combined;
677
- }
678
- async function generateDetectionRules(client, knowledge, title, domain, agentName) {
679
- const prefix = agentName.toUpperCase().replace(/[^A-Z]/g, "").slice(0, 4) || "CUST";
680
- const prompt = COMPRESSION_PROMPTS.generateDetectionRules.replace("{{knowledge}}", JSON.stringify(knowledge, null, 2)).replace("{{title}}", title).replace("{{domain}}", domain).replace("{{wordCount}}", String(knowledge.coreConcepts.length * 100)).replace(/\{\{prefix\}\}/g, prefix);
681
- const response = await client.messages.create({
682
- model: "claude-sonnet-4-20250514",
683
- max_tokens: 8e3,
684
- system: COMPRESSION_PROMPTS.system,
685
- messages: [{ role: "user", content: prompt }]
686
- });
687
- const firstContent = response.content[0];
688
- const text = firstContent !== void 0 && firstContent.type === "text" ? firstContent.text : "";
689
- try {
690
- const jsonMatch = text.match(/\[[\s\S]*\]/);
691
- if (jsonMatch) {
692
- const rules = JSON.parse(jsonMatch[0]);
693
- return rules.map((rule, i) => ({
694
- id: rule.id || `${prefix}-${String(i + 1).padStart(3, "0")}`,
695
- name: rule.name || "Unknown Rule",
696
- description: rule.description || "",
697
- severity: rule.severity || "moderate",
698
- patterns: {
699
- regex: rule.patterns?.regex || [],
700
- keywords: rule.patterns?.keywords || [],
701
- semantic: rule.patterns?.semantic || ""
702
- },
703
- fix: {
704
- description: rule.fix?.description || "Review and fix manually",
705
- example: rule.fix?.example || void 0,
706
- autoFixable: rule.fix?.autoFixable || false
707
- },
708
- regulation: rule.regulation || void 0,
709
- category: rule.category || domain
710
- }));
711
- }
712
- } catch (e) {
713
- console.error("Failed to parse detection rules:", e);
714
- }
715
- return [];
716
- }
717
- async function generateSummary(client, content) {
718
- const prompt = COMPRESSION_PROMPTS.generateSummary.replace("{{content}}", content);
719
- const response = await client.messages.create({
720
- model: "claude-sonnet-4-20250514",
721
- max_tokens: 1e3,
722
- system: COMPRESSION_PROMPTS.system,
723
- messages: [{ role: "user", content: prompt }]
724
- });
725
- const firstContent = response.content[0];
726
- return firstContent !== void 0 && firstContent.type === "text" ? firstContent.text : "";
727
- }
728
- async function generateAgentPrompts(client, knowledge, agentName, category) {
729
- const prompt = COMPRESSION_PROMPTS.generateAgentPrompts.replace("{{summary}}", knowledge.summary).replace("{{concepts}}", JSON.stringify(knowledge.coreConcepts.slice(0, 10), null, 2)).replace("{{patterns}}", JSON.stringify(knowledge.detectionRules.slice(0, 10), null, 2)).replace("{{agentName}}", agentName).replace("{{category}}", category).replace("{{domain}}", knowledge.domain);
730
- const response = await client.messages.create({
731
- model: "claude-sonnet-4-20250514",
732
- max_tokens: 4e3,
733
- system: COMPRESSION_PROMPTS.system,
734
- messages: [{ role: "user", content: prompt }]
735
- });
736
- const firstContent = response.content[0];
737
- const text = firstContent !== void 0 && firstContent.type === "text" ? firstContent.text : "";
738
- try {
739
- const jsonMatch = text.match(/\{[\s\S]*\}/);
740
- if (jsonMatch) {
741
- return JSON.parse(jsonMatch[0]);
742
- }
743
- } catch (e) {
744
- }
745
- return {
746
- systemPrompt: `You are an expert code reviewer specializing in ${category}. Review code based on best practices and patterns from "${agentName}".`,
747
- analysisPrompt: `Review this code for issues related to ${category}:
748
-
749
- \`\`\`{{language}}
750
- {{code}}
751
- \`\`\`
752
-
753
- File: {{filePath}}`,
754
- fixPrompt: `Fix this issue: {{issue}}
755
-
756
- Code:
757
- \`\`\`{{language}}
758
- {{code}}
759
- \`\`\`
760
-
761
- File: {{filePath}}`
762
- };
763
- }
764
-
765
- // src/ingest/agent-builder.ts
766
- import { mkdir, writeFile, readFile as readFile2 } from "fs/promises";
767
- import { join } from "path";
768
- async function buildAgentFromDocument(options, verbose = true) {
769
- const { filePath, agentName, category } = options;
770
- const log = verbose ? console.error.bind(console) : () => {
771
- };
772
- try {
773
- log("\u{1F4DA} Parsing document...");
774
- const document = await parseDocument(filePath);
775
- log(` \u251C\u2500 File type: ${document.metadata.fileType}`);
776
- log(` \u251C\u2500 Words: ${document.metadata.wordCount.toLocaleString()}`);
777
- log(` \u2514\u2500 Sections: ${document.sections.length}`);
778
- log("\n\u{1F9E0} Compressing knowledge...");
779
- const compressOptions = {
780
- agentName,
781
- verbose
782
- };
783
- if (category !== void 0) {
784
- compressOptions.category = category;
785
- }
786
- const knowledge = await compressKnowledge(document, compressOptions);
787
- log(` \u251C\u2500 Core concepts: ${knowledge.coreConcepts.length}`);
788
- log(` \u251C\u2500 Best practices: ${knowledge.bestPractices.length}`);
789
- log(` \u251C\u2500 Anti-patterns: ${knowledge.antiPatterns.length}`);
790
- log(` \u2514\u2500 Detection rules: ${knowledge.detectionRules.length}`);
791
- log("\n\u{1F4DD} Generating agent prompts...");
792
- const client = new Anthropic2();
793
- const prompts = await generateAgentPrompts(
794
- client,
795
- knowledge,
796
- agentName,
797
- category || knowledge.domain
798
- );
799
- log("\n\u{1F916} Building agent configuration...");
800
- const agentConfig = buildAgentConfig(
801
- document,
802
- knowledge,
803
- prompts,
804
- options
805
- );
806
- const configPath = await saveAgentConfig(agentConfig);
807
- log(` \u2514\u2500 Saved to: ${configPath}`);
808
- return {
809
- success: true,
810
- agentName: agentConfig.name,
811
- configPath,
812
- stats: {
813
- documentWords: document.metadata.wordCount,
814
- conceptsExtracted: knowledge.coreConcepts.length,
815
- patternsGenerated: knowledge.detectionRules.length,
816
- compressionRatio: knowledge.sourceDocument.compressionRatio
817
- }
818
- };
819
- } catch (error) {
820
- const errorMessage = error instanceof Error ? error.message : String(error);
821
- log(`
822
- \u274C Error: ${errorMessage}`);
823
- return {
824
- success: false,
825
- agentName,
826
- configPath: "",
827
- stats: {
828
- documentWords: 0,
829
- conceptsExtracted: 0,
830
- patternsGenerated: 0,
831
- compressionRatio: 0
832
- },
833
- error: errorMessage
834
- };
835
- }
836
- }
837
- function buildAgentConfig(document, knowledge, prompts, options) {
838
- const { agentName, displayName, description, category } = options;
839
- const docTitle = document.metadata.title;
840
- const activationRules = buildActivationRules(knowledge);
841
- return {
842
- name: sanitizeAgentName(agentName),
843
- displayName: displayName || formatDisplayName(agentName),
844
- description: description || `Code review agent based on "${document.metadata.title || agentName}"`,
845
- version: "1.0.0",
846
- category: category || knowledge.domain,
847
- source: {
848
- type: "document",
849
- originalFile: document.metadata.originalPath,
850
- fileType: document.metadata.fileType,
851
- compressedAt: (/* @__PURE__ */ new Date()).toISOString(),
852
- ...docTitle !== void 0 && { documentTitle: docTitle }
853
- },
854
- systemPrompt: prompts.systemPrompt,
855
- analysisPrompt: prompts.analysisPrompt,
856
- fixPrompt: prompts.fixPrompt,
857
- activationRules,
858
- patterns: knowledge.detectionRules,
859
- knowledge
860
- };
861
- }
862
- function buildActivationRules(knowledge) {
863
- const domainRules = {
864
- technical: {
865
- filePatterns: ["*.ts", "*.tsx", "*.js", "*.jsx", "*.py", "*.go", "*.rs"],
866
- contextSignals: ["touchesUI", "touchesAPI"],
867
- priority: 2
868
- },
869
- legal: {
870
- filePatterns: ["*"],
871
- contextSignals: ["touchesUserData", "touchesAuth", "touchesPayments"],
872
- priority: 2
873
- },
874
- policy: {
875
- filePatterns: ["*"],
876
- contextSignals: ["touchesAuth", "touchesAPI", "touchesDatabase"],
877
- priority: 3
878
- },
879
- security: {
880
- filePatterns: ["*"],
881
- contextSignals: ["touchesAuth", "touchesCrypto", "touchesAPI", "touchesDatabase"],
882
- priority: 1
883
- },
884
- architecture: {
885
- filePatterns: ["*.ts", "*.tsx", "*.js", "*.jsx", "*.py", "*.go"],
886
- contextSignals: ["touchesAPI", "touchesDatabase"],
887
- priority: 2
888
- },
889
- general: {
890
- filePatterns: ["*"],
891
- contextSignals: [],
892
- priority: 3
893
- }
894
- };
895
- const domainDefaults = domainRules[knowledge.domain] ?? domainRules.general;
896
- const contentPatterns = [];
897
- for (const rule of knowledge.detectionRules) {
898
- if (rule.patterns.keywords) {
899
- contentPatterns.push(...rule.patterns.keywords.slice(0, 3));
900
- }
901
- }
902
- for (const concept of knowledge.coreConcepts.slice(0, 5)) {
903
- if (concept.keywords) {
904
- contentPatterns.push(...concept.keywords.slice(0, 2));
905
- }
906
- }
907
- const uniquePatterns = [...new Set(contentPatterns)].slice(0, 20);
908
- return {
909
- filePatterns: domainDefaults.filePatterns ?? ["*"],
910
- contentPatterns: uniquePatterns,
911
- contextSignals: domainDefaults.contextSignals ?? [],
912
- minConfidence: 0.3,
913
- priority: domainDefaults.priority ?? 2
914
- };
915
- }
916
- async function saveAgentConfig(config) {
917
- const trieDir = join(getTrieDirectory(getWorkingDirectory(void 0, true)), "agents");
918
- await mkdir(trieDir, { recursive: true });
919
- const configPath = join(trieDir, `${config.name}.json`);
920
- await writeFile(configPath, JSON.stringify(config, null, 2));
921
- return configPath;
922
- }
923
- async function loadAgentConfig(name) {
924
- try {
925
- const configPath = join(getTrieDirectory(getWorkingDirectory(void 0, true)), "agents", `${name}.json`);
926
- const content = await readFile2(configPath, "utf-8");
927
- return JSON.parse(content);
928
- } catch {
929
- return null;
930
- }
931
- }
932
- async function listCustomAgents() {
933
- try {
934
- const { readdir } = await import("fs/promises");
935
- const trieDir = join(getTrieDirectory(getWorkingDirectory(void 0, true)), "agents");
936
- const files = await readdir(trieDir);
937
- return files.filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
938
- } catch {
939
- return [];
940
- }
941
- }
942
- function sanitizeAgentName(name) {
943
- return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
944
- }
945
- function formatDisplayName(name) {
946
- return name.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
947
- }
948
-
949
- export {
950
- parseDocument,
951
- buildAgentFromDocument,
952
- loadAgentConfig,
953
- listCustomAgents
954
- };
955
- //# sourceMappingURL=chunk-OWBWNXSC.js.map