archicore 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +530 -0
  2. package/dist/analyzers/dead-code.d.ts +95 -0
  3. package/dist/analyzers/dead-code.js +327 -0
  4. package/dist/analyzers/duplication.d.ts +90 -0
  5. package/dist/analyzers/duplication.js +344 -0
  6. package/dist/analyzers/security.d.ts +79 -0
  7. package/dist/analyzers/security.js +484 -0
  8. package/dist/architecture/index.d.ts +35 -0
  9. package/dist/architecture/index.js +249 -0
  10. package/dist/cli/commands/analyzers.d.ts +6 -0
  11. package/dist/cli/commands/analyzers.js +431 -0
  12. package/dist/cli/commands/export.d.ts +6 -0
  13. package/dist/cli/commands/export.js +78 -0
  14. package/dist/cli/commands/index.d.ts +8 -0
  15. package/dist/cli/commands/index.js +8 -0
  16. package/dist/cli/commands/init.d.ts +26 -0
  17. package/dist/cli/commands/init.js +140 -0
  18. package/dist/cli/commands/interactive.d.ts +7 -0
  19. package/dist/cli/commands/interactive.js +522 -0
  20. package/dist/cli/commands/projects.d.ts +6 -0
  21. package/dist/cli/commands/projects.js +249 -0
  22. package/dist/cli/index.d.ts +7 -0
  23. package/dist/cli/index.js +7 -0
  24. package/dist/cli/ui/box.d.ts +17 -0
  25. package/dist/cli/ui/box.js +62 -0
  26. package/dist/cli/ui/colors.d.ts +49 -0
  27. package/dist/cli/ui/colors.js +86 -0
  28. package/dist/cli/ui/index.d.ts +9 -0
  29. package/dist/cli/ui/index.js +9 -0
  30. package/dist/cli/ui/prompt.d.ts +34 -0
  31. package/dist/cli/ui/prompt.js +122 -0
  32. package/dist/cli/ui/spinner.d.ts +29 -0
  33. package/dist/cli/ui/spinner.js +80 -0
  34. package/dist/cli/ui/table.d.ts +33 -0
  35. package/dist/cli/ui/table.js +84 -0
  36. package/dist/cli/utils/config.d.ts +23 -0
  37. package/dist/cli/utils/config.js +73 -0
  38. package/dist/cli/utils/index.d.ts +6 -0
  39. package/dist/cli/utils/index.js +6 -0
  40. package/dist/cli/utils/session.d.ts +27 -0
  41. package/dist/cli/utils/session.js +117 -0
  42. package/dist/cli.d.ts +8 -0
  43. package/dist/cli.js +295 -0
  44. package/dist/code-index/ast-parser.d.ts +16 -0
  45. package/dist/code-index/ast-parser.js +330 -0
  46. package/dist/code-index/dependency-graph.d.ts +16 -0
  47. package/dist/code-index/dependency-graph.js +161 -0
  48. package/dist/code-index/index.d.ts +44 -0
  49. package/dist/code-index/index.js +124 -0
  50. package/dist/code-index/symbol-extractor.d.ts +13 -0
  51. package/dist/code-index/symbol-extractor.js +150 -0
  52. package/dist/export/index.d.ts +92 -0
  53. package/dist/export/index.js +676 -0
  54. package/dist/github/github-service.d.ts +146 -0
  55. package/dist/github/github-service.js +609 -0
  56. package/dist/impact-engine/index.d.ts +25 -0
  57. package/dist/impact-engine/index.js +284 -0
  58. package/dist/index.d.ts +60 -0
  59. package/dist/index.js +149 -0
  60. package/dist/metrics/index.d.ts +136 -0
  61. package/dist/metrics/index.js +525 -0
  62. package/dist/orchestrator/deepseek-optimizer.d.ts +67 -0
  63. package/dist/orchestrator/deepseek-optimizer.js +320 -0
  64. package/dist/orchestrator/index.d.ts +34 -0
  65. package/dist/orchestrator/index.js +305 -0
  66. package/dist/pr-guardian/index.d.ts +143 -0
  67. package/dist/pr-guardian/index.js +553 -0
  68. package/dist/refactoring/index.d.ts +108 -0
  69. package/dist/refactoring/index.js +580 -0
  70. package/dist/rules-engine/index.d.ts +129 -0
  71. package/dist/rules-engine/index.js +482 -0
  72. package/dist/semantic-memory/embedding-service.d.ts +24 -0
  73. package/dist/semantic-memory/embedding-service.js +120 -0
  74. package/dist/semantic-memory/index.d.ts +45 -0
  75. package/dist/semantic-memory/index.js +206 -0
  76. package/dist/semantic-memory/vector-store.d.ts +27 -0
  77. package/dist/semantic-memory/vector-store.js +166 -0
  78. package/dist/server/index.d.ts +28 -0
  79. package/dist/server/index.js +141 -0
  80. package/dist/server/middleware/api-auth.d.ts +43 -0
  81. package/dist/server/middleware/api-auth.js +256 -0
  82. package/dist/server/routes/admin.d.ts +5 -0
  83. package/dist/server/routes/admin.js +123 -0
  84. package/dist/server/routes/api.d.ts +7 -0
  85. package/dist/server/routes/api.js +362 -0
  86. package/dist/server/routes/auth.d.ts +16 -0
  87. package/dist/server/routes/auth.js +191 -0
  88. package/dist/server/routes/developer.d.ts +8 -0
  89. package/dist/server/routes/developer.js +439 -0
  90. package/dist/server/routes/github.d.ts +7 -0
  91. package/dist/server/routes/github.js +495 -0
  92. package/dist/server/routes/upload.d.ts +7 -0
  93. package/dist/server/routes/upload.js +196 -0
  94. package/dist/server/services/api-key-service.d.ts +81 -0
  95. package/dist/server/services/api-key-service.js +281 -0
  96. package/dist/server/services/auth-service.d.ts +40 -0
  97. package/dist/server/services/auth-service.js +315 -0
  98. package/dist/server/services/project-service.d.ts +123 -0
  99. package/dist/server/services/project-service.js +533 -0
  100. package/dist/server/services/token-service.d.ts +107 -0
  101. package/dist/server/services/token-service.js +416 -0
  102. package/dist/server/services/upload-service.d.ts +93 -0
  103. package/dist/server/services/upload-service.js +464 -0
  104. package/dist/types/api.d.ts +188 -0
  105. package/dist/types/api.js +86 -0
  106. package/dist/types/github.d.ts +335 -0
  107. package/dist/types/github.js +5 -0
  108. package/dist/types/index.d.ts +265 -0
  109. package/dist/types/index.js +32 -0
  110. package/dist/types/user.d.ts +69 -0
  111. package/dist/types/user.js +42 -0
  112. package/dist/utils/file-utils.d.ts +20 -0
  113. package/dist/utils/file-utils.js +163 -0
  114. package/dist/utils/logger.d.ts +17 -0
  115. package/dist/utils/logger.js +41 -0
  116. package/dist/watcher/index.d.ts +125 -0
  117. package/dist/watcher/index.js +397 -0
  118. package/package.json +71 -0
@@ -0,0 +1,320 @@
1
+ /**
2
+ * DeepSeek Optimizer
3
+ *
4
+ * Оптимизирует промпты и контекст специально для DeepSeek,
5
+ * чтобы минимизировать ошибки и получать точные ответы.
6
+ */
7
+ import { Logger } from '../utils/logger.js';
8
+ export class DeepSeekOptimizer {
9
+ config;
10
+ constructor(config) {
11
+ this.config = {
12
+ maxContextLength: 8000, // DeepSeek лучше работает с коротким контекстом
13
+ simplifyPrompts: true,
14
+ useEnglish: true, // DeepSeek лучше понимает английский
15
+ reduceExamples: true,
16
+ structuredOutput: true,
17
+ ...config
18
+ };
19
+ }
20
+ /**
21
+ * Оптимизирует промпт для DeepSeek
22
+ */
23
+ optimizePrompt(prompt) {
24
+ Logger.debug('Optimizing prompt for DeepSeek...');
25
+ let optimizedSystem = prompt.system;
26
+ let optimizedUser = prompt.user;
27
+ // 1. Упрощаем системный промпт
28
+ if (this.config.simplifyPrompts) {
29
+ optimizedSystem = this.simplifySystemPrompt(prompt.system);
30
+ }
31
+ // 2. Сокращаем контекст
32
+ if (prompt.context) {
33
+ optimizedSystem = this.reduceContext(optimizedSystem, prompt.context);
34
+ }
35
+ // 3. Упрощаем пользовательский запрос
36
+ if (this.config.simplifyPrompts) {
37
+ optimizedUser = this.simplifyUserPrompt(prompt.user);
38
+ }
39
+ // 4. Добавляем требование структурированного вывода
40
+ if (this.config.structuredOutput) {
41
+ optimizedUser = this.addStructuredOutputRequest(optimizedUser);
42
+ }
43
+ // 5. Переводим на английский (если нужно)
44
+ if (this.config.useEnglish) {
45
+ optimizedSystem = this.translateToEnglish(optimizedSystem);
46
+ optimizedUser = this.translateToEnglish(optimizedUser);
47
+ }
48
+ // 6. Обрезаем до максимальной длины
49
+ optimizedSystem = this.truncateText(optimizedSystem, this.config.maxContextLength);
50
+ optimizedUser = this.truncateText(optimizedUser, this.config.maxContextLength);
51
+ Logger.debug(`Prompt optimized: ${prompt.system.length + prompt.user.length} -> ${optimizedSystem.length + optimizedUser.length} chars`);
52
+ return {
53
+ system: optimizedSystem,
54
+ user: optimizedUser,
55
+ context: prompt.context
56
+ };
57
+ }
58
+ /**
59
+ * Упрощает системный промпт
60
+ */
61
+ simplifySystemPrompt(prompt) {
62
+ let simplified = prompt;
63
+ // Убираем избыточные формулировки
64
+ simplified = simplified
65
+ .replace(/с глубокими знаниями/g, 'with knowledge')
66
+ .replace(/Вы являетесь/g, 'You are')
67
+ .replace(/должны/g, 'should')
68
+ .replace(/необходимо/g, 'need to');
69
+ // Сокращаем длинные списки правил
70
+ const lines = simplified.split('\n');
71
+ const importantLines = lines.filter(line => {
72
+ // Оставляем только важные строки
73
+ return (line.includes('You are') ||
74
+ line.includes('Your role') ||
75
+ line.includes('Important') ||
76
+ line.includes('Rules') ||
77
+ line.includes('Bounded Context') ||
78
+ line.trim().startsWith('-'));
79
+ });
80
+ return importantLines.join('\n');
81
+ }
82
+ /**
83
+ * Упрощает пользовательский промпт
84
+ */
85
+ simplifyUserPrompt(prompt) {
86
+ let simplified = prompt;
87
+ // Убираем эмодзи (DeepSeek может путаться)
88
+ simplified = simplified.replace(/[\u{1F300}-\u{1F9FF}]/gu, '');
89
+ // Убираем markdown форматирование, которое может сбивать
90
+ simplified = simplified
91
+ .replace(/\*\*\*([^*]+)\*\*\*/g, '$1') // *** text ***
92
+ .replace(/\*\*([^*]+)\*\*/g, '$1'); // ** text **
93
+ // Упрощаем структуру
94
+ simplified = simplified
95
+ .replace(/Пожалуйста, предоставьте:/g, 'Provide:')
96
+ .replace(/Пожалуйста/g, 'Please')
97
+ .replace(/Необходимо/g, 'Need');
98
+ return simplified;
99
+ }
100
+ /**
101
+ * Сокращает контекст до самого важного
102
+ */
103
+ reduceContext(systemPrompt, context) {
104
+ let reduced = systemPrompt;
105
+ // Сокращаем semantic memory до 3 самых релевантных
106
+ if (context.semanticMemory && context.semanticMemory.length > 3) {
107
+ const topResults = context.semanticMemory.slice(0, 3);
108
+ reduced += '\n\n**Relevant Code (top 3):**\n';
109
+ for (const result of topResults) {
110
+ // Берем только путь к файлу и короткий контекст
111
+ const shortContext = result.context.substring(0, 150);
112
+ reduced += `- ${result.chunk.metadata.filePath}: ${shortContext}...\n`;
113
+ }
114
+ }
115
+ // Сокращаем информацию об архитектуре
116
+ if (context.architecture?.boundedContexts) {
117
+ reduced += '\n\n**Architecture:**\n';
118
+ for (const bc of context.architecture.boundedContexts.slice(0, 3)) {
119
+ reduced += `- ${bc.name}: ${bc.description}\n`;
120
+ }
121
+ }
122
+ return reduced;
123
+ }
124
+ /**
125
+ * Добавляет требование структурированного вывода
126
+ */
127
+ addStructuredOutputRequest(userPrompt) {
128
+ // Добавляем четкое требование к формату ответа
129
+ return userPrompt + '\n\n**Output Format:**\nProvide a clear, structured response. Use numbered lists. Be specific and concise.';
130
+ }
131
+ /**
132
+ * Упрощенный перевод ключевых терминов на английский
133
+ */
134
+ translateToEnglish(text) {
135
+ // Базовый словарь для перевода
136
+ const translations = {
137
+ 'Вы': 'You',
138
+ 'являетесь': 'are',
139
+ 'архитектором': 'architect',
140
+ 'системным': 'system',
141
+ 'программного обеспечения': 'software',
142
+ 'Ваша роль': 'Your role',
143
+ 'Понимать': 'Understand',
144
+ 'весь код': 'entire codebase',
145
+ 'структуру кодовой базы': 'codebase structure',
146
+ 'Принимать': 'Make',
147
+ 'архитектурные решения': 'architectural decisions',
148
+ 'на основе контекста': 'based on context',
149
+ 'Определять': 'Identify',
150
+ 'риски': 'risks',
151
+ 'потенциальные проблемы': 'potential issues',
152
+ 'Предлагать': 'Suggest',
153
+ 'улучшения': 'improvements',
154
+ 'сохраняя': 'maintaining',
155
+ 'целостность системы': 'system integrity',
156
+ 'Следовать': 'Follow',
157
+ 'установленным': 'established',
158
+ 'правилам': 'rules',
159
+ 'паттернам': 'patterns',
160
+ 'Принципы': 'Principles',
161
+ 'Минимизировать': 'Minimize',
162
+ 'breaking changes': 'breaking changes',
163
+ 'Поддерживать': 'Maintain',
164
+ 'обратную совместимость': 'backward compatibility',
165
+ 'когда возможно': 'when possible',
166
+ 'Предпочитать': 'Prefer',
167
+ 'инкрементальные улучшения': 'incremental improvements',
168
+ 'большим переписываниям': 'big rewrites',
169
+ 'Учитывать': 'Consider',
170
+ 'производительность': 'performance',
171
+ 'безопасность': 'security',
172
+ 'поддерживаемость': 'maintainability',
173
+ 'Уважать': 'Respect',
174
+ 'границы контекстов': 'bounded contexts',
175
+ 'доменные границы': 'domain boundaries',
176
+ 'Анализировать': 'Analyze',
177
+ 'влияние изменений': 'impact of changes',
178
+ 'Описание изменения': 'Change Description',
179
+ 'Тип': 'Type',
180
+ 'Файлы': 'Files',
181
+ 'Затронутые компоненты': 'Affected Components',
182
+ 'Критические': 'Critical',
183
+ 'Высокие': 'High',
184
+ 'Средние': 'Medium',
185
+ 'Низкие': 'Low',
186
+ 'Выявленные риски': 'Identified Risks',
187
+ 'Текущие рекомендации': 'Current Recommendations',
188
+ 'Предоставьте': 'Provide',
189
+ 'Дополнительные риски или проблемы': 'Additional risks or concerns',
190
+ 'Конкретные шаги миграции': 'Specific migration steps',
191
+ 'при необходимости': 'if needed',
192
+ 'Стратегия тестирования': 'Testing strategy',
193
+ 'План отката': 'Rollback plan',
194
+ 'Долгосрочные архитектурные последствия': 'Long-term architectural implications'
195
+ };
196
+ let translated = text;
197
+ // Если текст в основном на русском, переводим ключевые части
198
+ if (this.isMostlyRussian(text)) {
199
+ for (const [russian, english] of Object.entries(translations)) {
200
+ translated = translated.replace(new RegExp(russian, 'g'), english);
201
+ }
202
+ }
203
+ return translated;
204
+ }
205
+ /**
206
+ * Проверяет, в основном ли текст на русском
207
+ */
208
+ isMostlyRussian(text) {
209
+ const russianChars = text.match(/[а-яА-ЯёЁ]/g);
210
+ const totalChars = text.replace(/\s/g, '').length;
211
+ return russianChars ? (russianChars.length / totalChars) > 0.3 : false;
212
+ }
213
+ /**
214
+ * Обрезает текст до максимальной длины
215
+ */
216
+ truncateText(text, maxLength) {
217
+ if (text.length <= maxLength) {
218
+ return text;
219
+ }
220
+ // Обрезаем, но стараемся сохранить смысл
221
+ const truncated = text.substring(0, maxLength);
222
+ // Находим последнюю точку или перенос строки
223
+ const lastPeriod = truncated.lastIndexOf('.');
224
+ const lastNewline = truncated.lastIndexOf('\n');
225
+ const cutPoint = Math.max(lastPeriod, lastNewline);
226
+ if (cutPoint > maxLength * 0.8) {
227
+ return truncated.substring(0, cutPoint + 1);
228
+ }
229
+ return truncated + '...';
230
+ }
231
+ /**
232
+ * Разбивает сложную задачу на простые подзадачи
233
+ */
234
+ splitComplexTask(task) {
235
+ const subtasks = [];
236
+ // Определяем тип задачи
237
+ if (task.includes('analyze') || task.includes('анализ')) {
238
+ subtasks.push('Step 1: List all affected components');
239
+ subtasks.push('Step 2: Identify direct dependencies');
240
+ subtasks.push('Step 3: Assess risk level for each component');
241
+ subtasks.push('Step 4: Provide recommendations');
242
+ }
243
+ else if (task.includes('refactor') || task.includes('рефакторинг')) {
244
+ subtasks.push('Step 1: Identify code to refactor');
245
+ subtasks.push('Step 2: Propose refactoring approach');
246
+ subtasks.push('Step 3: List potential risks');
247
+ subtasks.push('Step 4: Define testing requirements');
248
+ }
249
+ else if (task.includes('review') || task.includes('ревью')) {
250
+ subtasks.push('Step 1: Check architecture compliance');
251
+ subtasks.push('Step 2: Find potential bugs');
252
+ subtasks.push('Step 3: Identify performance issues');
253
+ subtasks.push('Step 4: Suggest improvements');
254
+ }
255
+ else {
256
+ // Общий подход
257
+ subtasks.push('Step 1: Understand the context');
258
+ subtasks.push('Step 2: Analyze the requirements');
259
+ subtasks.push('Step 3: Provide solution');
260
+ subtasks.push('Step 4: List considerations');
261
+ }
262
+ return subtasks;
263
+ }
264
+ /**
265
+ * Валидирует и очищает ответ от DeepSeek
266
+ */
267
+ validateAndCleanResponse(response) {
268
+ let cleaned = response;
269
+ // Убираем возможный мусор в начале/конце
270
+ cleaned = cleaned.trim();
271
+ // Убираем повторяющиеся переносы строк
272
+ cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
273
+ // Убираем незавершенные предложения в конце
274
+ const lastChar = cleaned[cleaned.length - 1];
275
+ if (lastChar !== '.' && lastChar !== '!' && lastChar !== '?' && lastChar !== '\n') {
276
+ const lastCompleteSentence = cleaned.lastIndexOf('.');
277
+ if (lastCompleteSentence > cleaned.length * 0.8) {
278
+ cleaned = cleaned.substring(0, lastCompleteSentence + 1);
279
+ }
280
+ }
281
+ return cleaned;
282
+ }
283
+ /**
284
+ * Создает retry-стратегию с упрощением
285
+ */
286
+ createRetryStrategy(originalPrompt, attemptNumber) {
287
+ Logger.info(`Creating retry strategy, attempt ${attemptNumber}`);
288
+ // С каждой попыткой упрощаем еще больше
289
+ const config = {
290
+ ...this.config,
291
+ maxContextLength: this.config.maxContextLength / attemptNumber,
292
+ simplifyPrompts: true,
293
+ useEnglish: true
294
+ };
295
+ const optimizer = new DeepSeekOptimizer(config);
296
+ return optimizer.optimizePrompt(originalPrompt);
297
+ }
298
+ }
299
+ /**
300
+ * Создает оптимизированный промпт для простых задач DeepSeek
301
+ */
302
+ export function createSimplePrompt(task, context) {
303
+ const systemPrompt = `You are a helpful AI assistant for code analysis.
304
+
305
+ Rules:
306
+ - Be concise and specific
307
+ - Use structured output
308
+ - Focus on facts, not speculation
309
+ - If unsure, say so
310
+
311
+ ${context ? `Context:\n${context.substring(0, 500)}` : ''}`;
312
+ const userPrompt = `Task: ${task}
313
+
314
+ Provide a clear, structured response.`;
315
+ return {
316
+ system: systemPrompt,
317
+ user: userPrompt
318
+ };
319
+ }
320
+ //# sourceMappingURL=deepseek-optimizer.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * LLM Orchestrator
3
+ *
4
+ * Оркестрация взаимодействия с LLM:
5
+ * - Управление контекстом
6
+ * - Генерация промптов с архитектурными знаниями
7
+ * - Интеграция с Claude/GPT
8
+ * - Принятие архитектурных решений
9
+ */
10
+ import { LLMConfig, LLMPrompt, LLMContext, LLMResponse, ChangeImpact } from '../types/index.js';
11
+ export declare class LLMOrchestrator {
12
+ private anthropic?;
13
+ private openai?;
14
+ private config;
15
+ private deepseekOptimizer?;
16
+ private initialized;
17
+ private _isAvailable;
18
+ constructor(config: LLMConfig);
19
+ private ensureInitialized;
20
+ isAvailable(): boolean;
21
+ query(prompt: LLMPrompt, retryCount?: number): Promise<LLMResponse>;
22
+ analyzeImpact(impact: ChangeImpact, context?: LLMContext): Promise<string>;
23
+ suggestRefactoring(code: string, goal: string, context?: LLMContext): Promise<string>;
24
+ answerArchitecturalQuestion(question: string, context: LLMContext): Promise<string>;
25
+ generateDocumentation(codebase: string, context: LLMContext): Promise<string>;
26
+ reviewCode(code: string, changedFiles: string[], context: LLMContext): Promise<string>;
27
+ private queryAnthropic;
28
+ private queryOpenAI;
29
+ private buildImpactAnalysisPrompt;
30
+ private buildRefactoringPrompt;
31
+ private buildArchitecturalPrompt;
32
+ private buildSystemPrompt;
33
+ }
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,305 @@
1
+ /**
2
+ * LLM Orchestrator
3
+ *
4
+ * Оркестрация взаимодействия с LLM:
5
+ * - Управление контекстом
6
+ * - Генерация промптов с архитектурными знаниями
7
+ * - Интеграция с Claude/GPT
8
+ * - Принятие архитектурных решений
9
+ */
10
+ import Anthropic from '@anthropic-ai/sdk';
11
+ import OpenAI from 'openai';
12
+ import { Logger } from '../utils/logger.js';
13
+ import { DeepSeekOptimizer } from './deepseek-optimizer.js';
14
+ export class LLMOrchestrator {
15
+ anthropic;
16
+ openai;
17
+ config;
18
+ deepseekOptimizer;
19
+ initialized = false;
20
+ _isAvailable = false;
21
+ constructor(config) {
22
+ this.config = config;
23
+ // Lazy initialization
24
+ }
25
+ ensureInitialized() {
26
+ if (this.initialized)
27
+ return;
28
+ this.initialized = true;
29
+ try {
30
+ if (this.config.provider === 'anthropic') {
31
+ const apiKey = process.env.ANTHROPIC_API_KEY;
32
+ if (!apiKey) {
33
+ Logger.warn('ANTHROPIC_API_KEY not set - LLM disabled');
34
+ return;
35
+ }
36
+ this.anthropic = new Anthropic({ apiKey });
37
+ this._isAvailable = true;
38
+ }
39
+ else if (this.config.provider === 'deepseek') {
40
+ const apiKey = process.env.DEEPSEEK_API_KEY;
41
+ if (!apiKey) {
42
+ Logger.warn('DEEPSEEK_API_KEY not set - LLM disabled');
43
+ return;
44
+ }
45
+ this.openai = new OpenAI({
46
+ apiKey,
47
+ baseURL: this.config.baseURL || 'https://api.deepseek.com'
48
+ });
49
+ this.deepseekOptimizer = new DeepSeekOptimizer({
50
+ maxContextLength: 8000,
51
+ simplifyPrompts: true,
52
+ useEnglish: true,
53
+ reduceExamples: true,
54
+ structuredOutput: true
55
+ });
56
+ Logger.info('DeepSeek optimizer enabled');
57
+ this._isAvailable = true;
58
+ }
59
+ else {
60
+ const apiKey = process.env.OPENAI_API_KEY;
61
+ if (!apiKey) {
62
+ Logger.warn('OPENAI_API_KEY not set - LLM disabled');
63
+ return;
64
+ }
65
+ this.openai = new OpenAI({ apiKey });
66
+ this._isAvailable = true;
67
+ }
68
+ }
69
+ catch (error) {
70
+ Logger.warn('LLM init failed: ' + error);
71
+ }
72
+ }
73
+ isAvailable() {
74
+ this.ensureInitialized();
75
+ return this._isAvailable;
76
+ }
77
+ async query(prompt, retryCount = 0) {
78
+ this.ensureInitialized();
79
+ if (!this._isAvailable) {
80
+ return {
81
+ content: 'LLM not available - API key not configured',
82
+ metadata: { tokensUsed: 0, model: this.config.model, timestamp: Date.now() }
83
+ };
84
+ }
85
+ Logger.progress('Querying LLM...');
86
+ try {
87
+ // Оптимизируем промпт для DeepSeek
88
+ let optimizedPrompt = prompt;
89
+ if (this.config.provider === 'deepseek' && this.deepseekOptimizer) {
90
+ if (retryCount > 0) {
91
+ // При повторных попытках упрощаем еще больше
92
+ optimizedPrompt = this.deepseekOptimizer.createRetryStrategy(prompt, retryCount + 1);
93
+ Logger.info(`Using retry strategy ${retryCount + 1} for DeepSeek`);
94
+ }
95
+ else {
96
+ optimizedPrompt = this.deepseekOptimizer.optimizePrompt(prompt);
97
+ Logger.info('Prompt optimized for DeepSeek');
98
+ }
99
+ }
100
+ // Выполняем запрос
101
+ if (this.config.provider === 'anthropic' && this.anthropic) {
102
+ return await this.queryAnthropic(optimizedPrompt);
103
+ }
104
+ else if ((this.config.provider === 'openai' || this.config.provider === 'deepseek') &&
105
+ this.openai) {
106
+ const response = await this.queryOpenAI(optimizedPrompt);
107
+ // Для DeepSeek валидируем и очищаем ответ
108
+ if (this.config.provider === 'deepseek' && this.deepseekOptimizer) {
109
+ response.content = this.deepseekOptimizer.validateAndCleanResponse(response.content);
110
+ }
111
+ return response;
112
+ }
113
+ throw new Error('No LLM provider configured');
114
+ }
115
+ catch (error) {
116
+ // Retry логика для DeepSeek
117
+ if (this.config.provider === 'deepseek' && retryCount < 2) {
118
+ Logger.warn(`DeepSeek query failed, retrying (${retryCount + 1}/2)...`);
119
+ await new Promise(resolve => setTimeout(resolve, 1000 * (retryCount + 1)));
120
+ return this.query(prompt, retryCount + 1);
121
+ }
122
+ Logger.error('LLM query failed', error);
123
+ throw error;
124
+ }
125
+ }
126
+ async analyzeImpact(impact, context) {
127
+ const prompt = this.buildImpactAnalysisPrompt(impact, context);
128
+ const response = await this.query(prompt);
129
+ return response.content;
130
+ }
131
+ async suggestRefactoring(code, goal, context) {
132
+ const prompt = this.buildRefactoringPrompt(code, goal, context);
133
+ const response = await this.query(prompt);
134
+ return response.content;
135
+ }
136
+ async answerArchitecturalQuestion(question, context) {
137
+ const prompt = this.buildArchitecturalPrompt(question, context);
138
+ const response = await this.query(prompt);
139
+ return response.content;
140
+ }
141
+ async generateDocumentation(codebase, context) {
142
+ const prompt = {
143
+ system: this.buildSystemPrompt(context),
144
+ user: `Generate comprehensive documentation for this codebase:\n\n${codebase}\n\nInclude:\n- Architecture overview\n- Key components\n- Data flows\n- Design decisions\n- Usage examples`
145
+ };
146
+ const response = await this.query(prompt);
147
+ return response.content;
148
+ }
149
+ async reviewCode(code, changedFiles, context) {
150
+ const prompt = {
151
+ system: this.buildSystemPrompt(context),
152
+ user: `Review this code change:\n\nChanged files: ${changedFiles.join(', ')}\n\n${code}\n\nProvide:\n- Architecture compliance check\n- Potential bugs\n- Performance issues\n- Security concerns\n- Improvement suggestions`
153
+ };
154
+ const response = await this.query(prompt);
155
+ return response.content;
156
+ }
157
+ async queryAnthropic(prompt) {
158
+ if (!this.anthropic) {
159
+ throw new Error('Anthropic client not initialized');
160
+ }
161
+ const response = await this.anthropic.messages.create({
162
+ model: this.config.model,
163
+ max_tokens: this.config.maxTokens,
164
+ temperature: this.config.temperature,
165
+ system: prompt.system,
166
+ messages: [
167
+ {
168
+ role: 'user',
169
+ content: prompt.user
170
+ }
171
+ ]
172
+ });
173
+ const content = response.content[0];
174
+ const text = content.type === 'text' ? content.text : '';
175
+ return {
176
+ content: text,
177
+ metadata: {
178
+ tokensUsed: response.usage.input_tokens + response.usage.output_tokens,
179
+ model: this.config.model,
180
+ timestamp: Date.now()
181
+ }
182
+ };
183
+ }
184
+ async queryOpenAI(prompt) {
185
+ if (!this.openai) {
186
+ throw new Error('OpenAI client not initialized');
187
+ }
188
+ const response = await this.openai.chat.completions.create({
189
+ model: this.config.model,
190
+ temperature: this.config.temperature,
191
+ max_tokens: this.config.maxTokens,
192
+ messages: [
193
+ {
194
+ role: 'system',
195
+ content: prompt.system
196
+ },
197
+ {
198
+ role: 'user',
199
+ content: prompt.user
200
+ }
201
+ ]
202
+ });
203
+ const message = response.choices[0]?.message;
204
+ return {
205
+ content: message?.content || '',
206
+ metadata: {
207
+ tokensUsed: response.usage?.total_tokens || 0,
208
+ model: this.config.model,
209
+ timestamp: Date.now()
210
+ }
211
+ };
212
+ }
213
+ buildImpactAnalysisPrompt(impact, context) {
214
+ const systemPrompt = this.buildSystemPrompt(context);
215
+ const userPrompt = `Analyze the impact of this change:
216
+
217
+ **Change Description:** ${impact.change.description}
218
+ **Type:** ${impact.change.type}
219
+ **Files:** ${impact.change.files.join(', ')}
220
+
221
+ **Affected Components:** ${impact.affectedNodes.length}
222
+ - Critical: ${impact.affectedNodes.filter(n => n.impactLevel === 'critical').length}
223
+ - High: ${impact.affectedNodes.filter(n => n.impactLevel === 'high').length}
224
+ - Medium: ${impact.affectedNodes.filter(n => n.impactLevel === 'medium').length}
225
+
226
+ **Risks Identified:** ${impact.risks.length}
227
+ ${impact.risks.map(r => `- [${r.severity}] ${r.description}`).join('\n')}
228
+
229
+ **Current Recommendations:**
230
+ ${impact.recommendations.map(r => `- [${r.priority}] ${r.description}`).join('\n')}
231
+
232
+ Please provide:
233
+ 1. Additional risks or concerns
234
+ 2. Specific migration steps if needed
235
+ 3. Testing strategy
236
+ 4. Rollback plan
237
+ 5. Long-term architectural implications`;
238
+ return {
239
+ system: systemPrompt,
240
+ user: userPrompt,
241
+ context
242
+ };
243
+ }
244
+ buildRefactoringPrompt(code, goal, context) {
245
+ const systemPrompt = this.buildSystemPrompt(context);
246
+ const userPrompt = `Suggest refactoring for this code to achieve: ${goal}
247
+
248
+ Code:
249
+ \`\`\`
250
+ ${code}
251
+ \`\`\`
252
+
253
+ Please provide:
254
+ 1. Proposed refactoring approach
255
+ 2. Step-by-step implementation plan
256
+ 3. Potential risks
257
+ 4. Testing requirements
258
+ 5. Before/after comparison`;
259
+ return {
260
+ system: systemPrompt,
261
+ user: userPrompt,
262
+ context
263
+ };
264
+ }
265
+ buildArchitecturalPrompt(question, context) {
266
+ return {
267
+ system: this.buildSystemPrompt(context),
268
+ user: question,
269
+ context
270
+ };
271
+ }
272
+ buildSystemPrompt(context) {
273
+ let prompt = `###CRITICAL INSTRUCTION - LANGUAGE###
274
+ If the user's question contains Cyrillic characters (Russian), you MUST respond ENTIRELY in Russian.
275
+ Если вопрос на русском - отвечай ТОЛЬКО на русском языке. Ни одного слова на английском!
276
+ ###END LANGUAGE INSTRUCTION###
277
+
278
+ You are an AI assistant analyzing a specific codebase.
279
+
280
+ ABSOLUTE RULES:
281
+ 1. ONLY USE PROVIDED DATA: You may ONLY mention files that appear in "PROJECT FILES" section below.
282
+ 2. NO INVENTION: NEVER invent file paths, class names, or code. If not shown - it doesn't exist.
283
+ 3. WHEN NO DATA: Say "Нет данных в индексе" (Russian) or "No indexed data" (English).
284
+ 4. BE HONEST: If you don't know - say so. Don't guess.`;
285
+ if (context?.architecture?.boundedContexts && context.architecture.boundedContexts.length > 0) {
286
+ prompt += '\n\n**Defined Architecture:**\n';
287
+ for (const bc of context.architecture.boundedContexts) {
288
+ prompt += `- ${bc.name}: ${bc.description}\n`;
289
+ }
290
+ }
291
+ if (context?.semanticMemory && context.semanticMemory.length > 0) {
292
+ prompt += '\n\n###PROJECT FILES (ONLY reference these - nothing else exists)###\n';
293
+ for (const result of context.semanticMemory.slice(0, 10)) {
294
+ prompt += `\nФайл: ${result.chunk.metadata.filePath}\n`;
295
+ prompt += `${result.context}\n`;
296
+ }
297
+ prompt += '\n###END PROJECT FILES###';
298
+ }
299
+ else {
300
+ prompt += '\n\n###PROJECT FILES: EMPTY###\nNo code indexed. Respond: "Проект не проиндексирован. Запустите индексацию."';
301
+ }
302
+ return prompt;
303
+ }
304
+ }
305
+ //# sourceMappingURL=index.js.map