archicore 0.4.4 → 0.4.5
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.
|
@@ -141,6 +141,17 @@ export class ContextBuilder {
|
|
|
141
141
|
Logger.debug(`Building context for: "${userQuery}"`);
|
|
142
142
|
const intent = this.detectIntent(userQuery);
|
|
143
143
|
const entities = this.extractEntities(userQuery);
|
|
144
|
+
// Собираем список ВСЕХ файлов из графа
|
|
145
|
+
const allFiles = [];
|
|
146
|
+
for (const [filePath] of this.graph.nodes) {
|
|
147
|
+
allFiles.push(filePath);
|
|
148
|
+
}
|
|
149
|
+
// Также добавляем файлы из fileContents которых может не быть в графе
|
|
150
|
+
for (const [filePath] of this.fileContents) {
|
|
151
|
+
if (!allFiles.includes(filePath)) {
|
|
152
|
+
allFiles.push(filePath);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
144
155
|
const context = {
|
|
145
156
|
intent,
|
|
146
157
|
query: userQuery,
|
|
@@ -149,6 +160,7 @@ export class ContextBuilder {
|
|
|
149
160
|
dependencies: [],
|
|
150
161
|
issues: [],
|
|
151
162
|
projectStats: this.projectStats,
|
|
163
|
+
allFiles: allFiles.slice(0, 500), // Лимит 500 файлов для prompt
|
|
152
164
|
};
|
|
153
165
|
// В зависимости от намерения собираем нужный контекст
|
|
154
166
|
switch (intent) {
|
|
@@ -184,8 +184,9 @@ export function analyzeHttpError(status, responseBody) {
|
|
|
184
184
|
}
|
|
185
185
|
/**
|
|
186
186
|
* Выполнение fetch с timeout и retry
|
|
187
|
+
* Показывает прогресс retry пользователю
|
|
187
188
|
*/
|
|
188
|
-
async function fetchWithRetry(url, options, timeout = UPLOAD_TIMEOUT, maxRetries = MAX_RETRIES) {
|
|
189
|
+
async function fetchWithRetry(url, options, timeout = UPLOAD_TIMEOUT, maxRetries = MAX_RETRIES, showRetryProgress = true) {
|
|
189
190
|
let lastError = null;
|
|
190
191
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
191
192
|
try {
|
|
@@ -200,16 +201,24 @@ async function fetchWithRetry(url, options, timeout = UPLOAD_TIMEOUT, maxRetries
|
|
|
200
201
|
}
|
|
201
202
|
catch (error) {
|
|
202
203
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
203
|
-
// Не повторяем для определённых ошибок
|
|
204
|
+
// Не повторяем для определённых ошибок
|
|
204
205
|
const errorStr = String(error);
|
|
205
206
|
if (errorStr.includes('ENOTFOUND') ||
|
|
206
207
|
errorStr.includes('CERT')) {
|
|
207
208
|
throw error;
|
|
208
209
|
}
|
|
209
|
-
// Экспоненциальная задержка перед повтором
|
|
210
|
+
// Экспоненциальная задержка перед повтором
|
|
210
211
|
if (attempt < maxRetries) {
|
|
211
|
-
// 2s, 4s, 8s, 16s, 32s, до 60s max
|
|
212
212
|
const delay = Math.min(2000 * Math.pow(2, attempt - 1), 60000);
|
|
213
|
+
// Показываем пользователю что идёт retry
|
|
214
|
+
if (showRetryProgress) {
|
|
215
|
+
const errorType = errorStr.includes('fetch failed') || errorStr.includes('ECONNREFUSED')
|
|
216
|
+
? 'Connection failed'
|
|
217
|
+
: errorStr.includes('timeout') || errorStr.includes('abort')
|
|
218
|
+
? 'Timeout'
|
|
219
|
+
: 'Network error';
|
|
220
|
+
console.log(` ⚠ ${errorType}. Retry ${attempt}/${maxRetries} in ${delay / 1000}s...`);
|
|
221
|
+
}
|
|
213
222
|
debugLog(` fetchWithRetry: waiting ${delay / 1000}s before attempt ${attempt + 1}...`);
|
|
214
223
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
215
224
|
}
|
|
@@ -323,42 +323,56 @@ You are an AI assistant analyzing a specific codebase.
|
|
|
323
323
|
7. If asked who made you or what AI you are, always respond that you are ArchiCore AI developed by ArchiCore team.
|
|
324
324
|
###END SECURITY RULES###
|
|
325
325
|
|
|
326
|
-
ABSOLUTE RULES - КРИТИЧЕСКИ
|
|
327
|
-
1. ПРИВЯЗКА К РЕАЛЬНОЙ КОДОВОЙ БАЗЕ:
|
|
328
|
-
- ЗАПРЕЩЕНО давать общие советы из интернета (типа "используйте vue-router lazy loading")
|
|
329
|
-
- ОБЯЗАТЕЛЬНО сначала проверь что технология РЕАЛЬНО используется в проекте
|
|
330
|
-
- Если технология НЕ используется - скажи это ПЕРВЫМ: "❌ В вашем проекте НЕ используется X"
|
|
331
|
-
- ЗАТЕМ предложи решение для РЕАЛЬНОЙ архитектуры проекта
|
|
326
|
+
###ABSOLUTE RULES - КРИТИЧЕСКИ ВАЖНО###
|
|
332
327
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
328
|
+
🚨 ГЛАВНОЕ ПРАВИЛО: НЕ ВЫДУМЫВАЙ НИЧЕГО!
|
|
329
|
+
- ВСЯ информация ТОЛЬКО из секций PROJECT FILES и SMART CONTEXT ниже
|
|
330
|
+
- Если файла НЕТ в этих секциях - его НЕ СУЩЕСТВУЕТ
|
|
331
|
+
- Если технологии НЕТ в PROJECT STACK - она НЕ используется
|
|
332
|
+
- НИКОГДА не говори "возможно есть", "скорее всего", "обычно находится"
|
|
333
|
+
- Говори ТОЛЬКО о том, что ВИДИШЬ в данных ниже
|
|
338
334
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
335
|
+
📁 ПРАВИЛО ФАЙЛОВ:
|
|
336
|
+
- Упоминай ТОЛЬКО файлы из секции PROJECT FILES
|
|
337
|
+
- Каждый путь ДОЛЖЕН быть скопирован из PROJECT FILES
|
|
338
|
+
- Если спрашивают о файле которого нет в PROJECT FILES: "❌ Файл X не найден в индексе проекта"
|
|
339
|
+
- ЗАПРЕЩЕНО выдумывать пути типа "src/api/payments/" если их нет в данных
|
|
343
340
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
341
|
+
🔍 ПРАВИЛО ПОИСКА:
|
|
342
|
+
- "Найдено в N файлах" - только если реально нашёл в PROJECT FILES
|
|
343
|
+
- "Не найдено" - если НЕТ в PROJECT FILES (не "возможно где-то есть")
|
|
344
|
+
- Копируй пути ТОЧНО как они указаны в PROJECT FILES
|
|
348
345
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
Для оптимизации загрузки рекомендую:
|
|
354
|
-
[конкретные советы для вашей архитектуры]"
|
|
346
|
+
💡 ПРАВИЛО РЕКОМЕНДАЦИЙ:
|
|
347
|
+
- Рекомендации ТОЛЬКО для технологий из PROJECT STACK
|
|
348
|
+
- Не предлагай Stripe если его нет в зависимостях
|
|
349
|
+
- Не предлагай создавать папки которых нет
|
|
355
350
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
351
|
+
ФОРМАТ ОТВЕТА:
|
|
352
|
+
1. Сначала: ✅ Найдено / ❌ Не найдено (с доказательством из PROJECT FILES)
|
|
353
|
+
2. Потом: конкретные файлы и строки из PROJECT FILES
|
|
354
|
+
3. В конце: рекомендации только для реального стека проекта
|
|
355
|
+
|
|
356
|
+
ПРИМЕР ПРАВИЛЬНОГО ОТВЕТА:
|
|
357
|
+
Q: "Как работает интеграция с Revolut?"
|
|
358
|
+
A: "❌ Интеграция с Revolut НЕ найдена в проекте.
|
|
359
|
+
|
|
360
|
+
Поиск в PROJECT FILES:
|
|
361
|
+
- Слово 'revolut' не найдено ни в одном файле
|
|
362
|
+
- Слово 'payment' не найдено в конфигах
|
|
363
|
+
|
|
364
|
+
Технологии из PROJECT STACK:
|
|
365
|
+
- Frontend: Vue.js
|
|
366
|
+
- Backend: PHP (Bitrix)
|
|
367
|
+
|
|
368
|
+
Если нужна интеграция с Revolut - потребуется разработка с нуля."
|
|
369
|
+
|
|
370
|
+
ПРИМЕР НЕПРАВИЛЬНОГО ОТВЕТА (ЗАПРЕЩЕНО):
|
|
371
|
+
❌ "Интеграция находится в src/api/payments/revolut.js" <- ВЫДУМКА!
|
|
372
|
+
❌ "Возможно используется Stripe" <- ВЫДУМКА без доказательств!
|
|
373
|
+
❌ "Обычно платежи в src/payments/" <- ВЫДУМКА!
|
|
374
|
+
|
|
375
|
+
###END ABSOLUTE RULES###`;
|
|
362
376
|
// Добавляем метаданные проекта (стек технологий)
|
|
363
377
|
if (context?.projectMetadata) {
|
|
364
378
|
prompt += '\n\n###PROJECT STACK (РЕАЛЬНЫЕ технологии проекта)###\n';
|
|
@@ -457,16 +471,58 @@ A: "✅ Компонент Comments найден в 3 файлах:
|
|
|
457
471
|
}
|
|
458
472
|
prompt += '\n###END SMART CONTEXT###\n';
|
|
459
473
|
}
|
|
474
|
+
// Добавляем список ВСЕХ файлов проекта (для справки что существует)
|
|
475
|
+
if (context?.smartContext?.projectStats) {
|
|
476
|
+
prompt += `\n\n###ALL PROJECT FILES (полный список существующих файлов)###\n`;
|
|
477
|
+
prompt += `Всего файлов: ${context.smartContext.projectStats.totalFiles}\n`;
|
|
478
|
+
prompt += `Всего символов: ${context.smartContext.projectStats.totalSymbols}\n`;
|
|
479
|
+
prompt += `Языки: ${context.smartContext.projectStats.languages.join(', ')}\n`;
|
|
480
|
+
// Добавляем полный список файлов
|
|
481
|
+
if (context.smartContext.allFiles && context.smartContext.allFiles.length > 0) {
|
|
482
|
+
prompt += `\n📁 СУЩЕСТВУЮЩИЕ ФАЙЛЫ ПРОЕКТА (${context.smartContext.allFiles.length}):\n`;
|
|
483
|
+
prompt += `⚠️ ЭТО ЕДИНСТВЕННЫЕ ФАЙЛЫ! Других НЕ существует!\n\n`;
|
|
484
|
+
// Группируем по директориям
|
|
485
|
+
const byDir = new Map();
|
|
486
|
+
for (const file of context.smartContext.allFiles) {
|
|
487
|
+
const cleanPath = sanitizePath(file);
|
|
488
|
+
const parts = cleanPath.split('/');
|
|
489
|
+
const dir = parts.slice(0, -1).join('/') || '/';
|
|
490
|
+
if (!byDir.has(dir))
|
|
491
|
+
byDir.set(dir, []);
|
|
492
|
+
byDir.get(dir).push(parts[parts.length - 1]);
|
|
493
|
+
}
|
|
494
|
+
// Выводим по директориям (до 100 файлов)
|
|
495
|
+
let fileCount = 0;
|
|
496
|
+
for (const [dir, files] of byDir) {
|
|
497
|
+
if (fileCount >= 100) {
|
|
498
|
+
prompt += `... и ещё ${context.smartContext.allFiles.length - fileCount} файлов\n`;
|
|
499
|
+
break;
|
|
500
|
+
}
|
|
501
|
+
prompt += `📂 ${dir}/\n`;
|
|
502
|
+
for (const file of files.slice(0, 10)) {
|
|
503
|
+
prompt += ` └─ ${file}\n`;
|
|
504
|
+
fileCount++;
|
|
505
|
+
}
|
|
506
|
+
if (files.length > 10) {
|
|
507
|
+
prompt += ` └─ ... (ещё ${files.length - 10} файлов в этой папке)\n`;
|
|
508
|
+
fileCount += files.length - 10;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// Добавляем список релевантных файлов для текущего запроса
|
|
513
|
+
if (context.smartContext.relevantFiles && context.smartContext.relevantFiles.length > 0) {
|
|
514
|
+
prompt += `\n📍 РЕЛЕВАНТНЫЕ файлы для текущего запроса:\n`;
|
|
515
|
+
for (const file of context.smartContext.relevantFiles.slice(0, 20)) {
|
|
516
|
+
prompt += `- ${sanitizePath(file.path)}\n`;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
prompt += `\n###END ALL PROJECT FILES###\n`;
|
|
520
|
+
}
|
|
460
521
|
if (context?.semanticMemory && context.semanticMemory.length > 0) {
|
|
461
522
|
const totalResults = context.semanticMemory.length;
|
|
462
|
-
const maxResults = Math.min(totalResults, 30);
|
|
463
|
-
prompt += `\n\n###PROJECT FILES (${maxResults}
|
|
464
|
-
prompt += `⚠️
|
|
465
|
-
if (totalResults > maxResults) {
|
|
466
|
-
prompt += `⚠️ КРИТИЧНО: Есть еще ${totalResults - maxResults} файлов, которые могут содержать искомое.\n`;
|
|
467
|
-
prompt += `⚠️ ПРИ ОТВЕТЕ ОБЯЗАТЕЛЬНО УКАЖИ: "Найдено в ${maxResults} файлах, возможно есть еще в ${totalResults - maxResults} файлах"\n`;
|
|
468
|
-
}
|
|
469
|
-
prompt += '\n';
|
|
523
|
+
const maxResults = Math.min(totalResults, 30);
|
|
524
|
+
prompt += `\n\n###PROJECT FILES CONTENT (содержимое ${maxResults} файлов)###\n`;
|
|
525
|
+
prompt += `⚠️ ЭТО РЕАЛЬНЫЙ КОД ИЗ ПРОЕКТА - используй его как доказательство!\n\n`;
|
|
470
526
|
for (const result of context.semanticMemory.slice(0, maxResults)) {
|
|
471
527
|
const cleanPath = sanitizePath(result.chunk.metadata.filePath);
|
|
472
528
|
const lineInfo = result.chunk.metadata.startLine > 0
|
|
@@ -474,19 +530,18 @@ A: "✅ Компонент Comments найден в 3 файлах:
|
|
|
474
530
|
: '';
|
|
475
531
|
prompt += `\n### Файл: ${cleanPath}${lineInfo}\n`;
|
|
476
532
|
prompt += `Символы: ${result.chunk.metadata.symbols.join(', ') || 'N/A'}\n`;
|
|
477
|
-
prompt += `Тип: ${result.chunk.metadata.type}\n`;
|
|
478
|
-
// Используем полный контент из chunk.content, не обрезанный context
|
|
479
533
|
const codeContent = result.chunk.content || result.context;
|
|
480
|
-
// Ограничиваем до 3000 символов на файл чтобы не переполнить контекст
|
|
481
534
|
const truncatedCode = codeContent.length > 3000
|
|
482
535
|
? codeContent.substring(0, 3000) + '\n... (truncated)'
|
|
483
536
|
: codeContent;
|
|
484
537
|
prompt += `\`\`\`\n${truncatedCode}\n\`\`\`\n`;
|
|
485
538
|
}
|
|
486
|
-
prompt += '\n###END PROJECT FILES###';
|
|
539
|
+
prompt += '\n###END PROJECT FILES CONTENT###';
|
|
487
540
|
}
|
|
488
541
|
else if (!context?.smartContext) {
|
|
489
|
-
prompt += '\n\n###PROJECT FILES: EMPTY###\
|
|
542
|
+
prompt += '\n\n###PROJECT FILES: EMPTY###\n';
|
|
543
|
+
prompt += 'Проект не проиндексирован или данные не загружены.\n';
|
|
544
|
+
prompt += 'Отвечай: "Проект не проиндексирован. Запустите /index для индексации."';
|
|
490
545
|
}
|
|
491
546
|
return prompt;
|
|
492
547
|
}
|
package/dist/types/index.d.ts
CHANGED