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,397 @@
1
+ /**
2
+ * Real-time File Watcher
3
+ *
4
+ * Мониторинг изменений файлов:
5
+ * - Автоматическая переиндексация при изменениях
6
+ * - Debounce для избежания лишних обновлений
7
+ * - Поддержка .gitignore паттернов
8
+ * - События для уведомления о изменениях
9
+ */
10
+ import { EventEmitter } from 'events';
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import { Logger } from '../utils/logger.js';
14
+ const DEFAULT_CONFIG = {
15
+ debounceMs: 300,
16
+ ignorePatterns: [
17
+ 'node_modules',
18
+ '.git',
19
+ 'dist',
20
+ 'build',
21
+ 'coverage',
22
+ '.next',
23
+ '.nuxt',
24
+ '__pycache__',
25
+ '*.log',
26
+ '*.lock',
27
+ '.DS_Store',
28
+ 'Thumbs.db'
29
+ ],
30
+ watchExtensions: [
31
+ '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
32
+ '.py', '.java', '.go', '.rs', '.cpp', '.c', '.h',
33
+ '.cs', '.rb', '.php', '.swift', '.kt', '.scala',
34
+ '.vue', '.svelte', '.astro'
35
+ ],
36
+ recursive: true
37
+ };
38
+ export class FileWatcher extends EventEmitter {
39
+ config;
40
+ watchers = new Map();
41
+ pendingChanges = new Map();
42
+ debounceTimers = new Map();
43
+ stats = {
44
+ watchedFiles: 0,
45
+ watchedDirectories: 0,
46
+ totalChanges: 0,
47
+ isWatching: false
48
+ };
49
+ rootPath = '';
50
+ constructor(config = {}) {
51
+ super();
52
+ this.config = { ...DEFAULT_CONFIG, ...config };
53
+ }
54
+ /**
55
+ * Начать мониторинг директории
56
+ */
57
+ async watch(dirPath) {
58
+ this.rootPath = path.resolve(dirPath);
59
+ if (!fs.existsSync(this.rootPath)) {
60
+ throw new Error(`Directory not found: ${this.rootPath}`);
61
+ }
62
+ Logger.progress(`Starting file watcher on: ${this.rootPath}`);
63
+ // Загружаем .gitignore если есть
64
+ await this.loadGitignore();
65
+ // Сканируем и устанавливаем watchers
66
+ await this.setupWatchers(this.rootPath);
67
+ this.stats.isWatching = true;
68
+ Logger.success(`Watching ${this.stats.watchedDirectories} directories, ${this.stats.watchedFiles} files`);
69
+ this.emit('ready', this.stats);
70
+ }
71
+ /**
72
+ * Остановить мониторинг
73
+ */
74
+ stop() {
75
+ Logger.progress('Stopping file watcher...');
76
+ // Очищаем все таймеры
77
+ for (const timer of this.debounceTimers.values()) {
78
+ clearTimeout(timer);
79
+ }
80
+ this.debounceTimers.clear();
81
+ // Закрываем все watchers
82
+ for (const watcher of this.watchers.values()) {
83
+ watcher.close();
84
+ }
85
+ this.watchers.clear();
86
+ this.stats.isWatching = false;
87
+ this.emit('stopped');
88
+ Logger.success('File watcher stopped');
89
+ }
90
+ /**
91
+ * Получить статистику
92
+ */
93
+ getStats() {
94
+ return { ...this.stats };
95
+ }
96
+ /**
97
+ * Загрузка паттернов из .gitignore
98
+ */
99
+ async loadGitignore() {
100
+ const gitignorePath = path.join(this.rootPath, '.gitignore');
101
+ if (fs.existsSync(gitignorePath)) {
102
+ try {
103
+ const content = fs.readFileSync(gitignorePath, 'utf-8');
104
+ const patterns = content
105
+ .split('\n')
106
+ .map(line => line.trim())
107
+ .filter(line => line && !line.startsWith('#'));
108
+ this.config.ignorePatterns = [
109
+ ...new Set([...this.config.ignorePatterns, ...patterns])
110
+ ];
111
+ Logger.info(`Loaded ${patterns.length} patterns from .gitignore`);
112
+ }
113
+ catch (error) {
114
+ Logger.warn('Failed to load .gitignore');
115
+ }
116
+ }
117
+ }
118
+ /**
119
+ * Установка watchers рекурсивно
120
+ */
121
+ async setupWatchers(dirPath) {
122
+ if (this.shouldIgnore(dirPath)) {
123
+ return;
124
+ }
125
+ try {
126
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
127
+ // Создаём watcher для директории
128
+ this.createDirectoryWatcher(dirPath);
129
+ for (const entry of entries) {
130
+ const fullPath = path.join(dirPath, entry.name);
131
+ if (entry.isDirectory()) {
132
+ if (this.config.recursive) {
133
+ await this.setupWatchers(fullPath);
134
+ }
135
+ }
136
+ else if (entry.isFile()) {
137
+ if (this.shouldWatchFile(fullPath)) {
138
+ this.stats.watchedFiles++;
139
+ }
140
+ }
141
+ }
142
+ }
143
+ catch (error) {
144
+ Logger.warn(`Cannot access directory: ${dirPath}`);
145
+ }
146
+ }
147
+ /**
148
+ * Создание watcher для директории
149
+ */
150
+ createDirectoryWatcher(dirPath) {
151
+ if (this.watchers.has(dirPath)) {
152
+ return;
153
+ }
154
+ try {
155
+ const watcher = fs.watch(dirPath, { persistent: true }, (eventType, filename) => {
156
+ if (filename) {
157
+ const fullPath = path.join(dirPath, filename);
158
+ this.handleFileEvent(eventType, fullPath);
159
+ }
160
+ });
161
+ watcher.on('error', (error) => {
162
+ Logger.warn(`Watcher error for ${dirPath}: ${error.message}`);
163
+ this.watchers.delete(dirPath);
164
+ });
165
+ this.watchers.set(dirPath, watcher);
166
+ this.stats.watchedDirectories++;
167
+ }
168
+ catch (error) {
169
+ Logger.warn(`Failed to watch directory: ${dirPath}`);
170
+ }
171
+ }
172
+ /**
173
+ * Обработка события файла
174
+ */
175
+ handleFileEvent(eventType, filePath) {
176
+ if (this.shouldIgnore(filePath)) {
177
+ return;
178
+ }
179
+ // Определяем тип события
180
+ let changeType;
181
+ if (!fs.existsSync(filePath)) {
182
+ changeType = 'delete';
183
+ }
184
+ else {
185
+ const stat = fs.statSync(filePath);
186
+ if (stat.isDirectory()) {
187
+ // Новая директория - добавляем watcher
188
+ if (!this.watchers.has(filePath)) {
189
+ this.setupWatchers(filePath);
190
+ }
191
+ return;
192
+ }
193
+ if (!this.shouldWatchFile(filePath)) {
194
+ return;
195
+ }
196
+ // Проверяем, новый ли файл
197
+ changeType = eventType === 'rename' ? 'add' : 'change';
198
+ }
199
+ const event = {
200
+ type: changeType,
201
+ path: filePath,
202
+ timestamp: new Date()
203
+ };
204
+ // Debounce
205
+ this.debounceEvent(event);
206
+ }
207
+ /**
208
+ * Debounce обработки события
209
+ */
210
+ debounceEvent(event) {
211
+ const key = event.path;
212
+ // Отменяем предыдущий таймер
213
+ const existingTimer = this.debounceTimers.get(key);
214
+ if (existingTimer) {
215
+ clearTimeout(existingTimer);
216
+ }
217
+ // Сохраняем событие
218
+ this.pendingChanges.set(key, event);
219
+ // Устанавливаем новый таймер
220
+ const timer = setTimeout(() => {
221
+ this.processPendingChange(key);
222
+ }, this.config.debounceMs);
223
+ this.debounceTimers.set(key, timer);
224
+ }
225
+ /**
226
+ * Обработка отложенного изменения
227
+ */
228
+ processPendingChange(key) {
229
+ const event = this.pendingChanges.get(key);
230
+ if (!event)
231
+ return;
232
+ this.pendingChanges.delete(key);
233
+ this.debounceTimers.delete(key);
234
+ // Обновляем статистику
235
+ this.stats.totalChanges++;
236
+ this.stats.lastChangeTime = event.timestamp;
237
+ // Если файл удалён, обновляем счётчик
238
+ if (event.type === 'delete') {
239
+ this.stats.watchedFiles = Math.max(0, this.stats.watchedFiles - 1);
240
+ }
241
+ else if (event.type === 'add') {
242
+ this.stats.watchedFiles++;
243
+ }
244
+ // Эмитим событие
245
+ this.emit('change', event);
246
+ this.emit(event.type, event);
247
+ Logger.info(`File ${event.type}: ${path.relative(this.rootPath, event.path)}`);
248
+ }
249
+ /**
250
+ * Проверка, нужно ли игнорировать путь
251
+ */
252
+ shouldIgnore(filePath) {
253
+ const relativePath = path.relative(this.rootPath, filePath);
254
+ const parts = relativePath.split(path.sep);
255
+ for (const pattern of this.config.ignorePatterns) {
256
+ // Простая проверка паттернов
257
+ if (pattern.startsWith('*.')) {
258
+ // Расширение файла
259
+ const ext = pattern.slice(1);
260
+ if (filePath.endsWith(ext))
261
+ return true;
262
+ }
263
+ else if (pattern.includes('*')) {
264
+ // Glob паттерн (упрощённый)
265
+ const regex = new RegExp('^' + pattern.replace(/\*/g, '.*').replace(/\?/g, '.') + '$');
266
+ if (parts.some(p => regex.test(p)))
267
+ return true;
268
+ }
269
+ else {
270
+ // Точное совпадение с любой частью пути
271
+ if (parts.includes(pattern))
272
+ return true;
273
+ }
274
+ }
275
+ return false;
276
+ }
277
+ /**
278
+ * Проверка, нужно ли отслеживать файл
279
+ */
280
+ shouldWatchFile(filePath) {
281
+ const ext = path.extname(filePath).toLowerCase();
282
+ return this.config.watchExtensions.includes(ext);
283
+ }
284
+ /**
285
+ * Добавить паттерн для игнорирования
286
+ */
287
+ addIgnorePattern(pattern) {
288
+ if (!this.config.ignorePatterns.includes(pattern)) {
289
+ this.config.ignorePatterns.push(pattern);
290
+ }
291
+ }
292
+ /**
293
+ * Удалить паттерн игнорирования
294
+ */
295
+ removeIgnorePattern(pattern) {
296
+ const index = this.config.ignorePatterns.indexOf(pattern);
297
+ if (index !== -1) {
298
+ this.config.ignorePatterns.splice(index, 1);
299
+ }
300
+ }
301
+ /**
302
+ * Получить все отслеживаемые файлы
303
+ */
304
+ getWatchedFiles() {
305
+ const files = [];
306
+ const scanDir = (dirPath) => {
307
+ if (this.shouldIgnore(dirPath))
308
+ return;
309
+ try {
310
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
311
+ for (const entry of entries) {
312
+ const fullPath = path.join(dirPath, entry.name);
313
+ if (entry.isDirectory()) {
314
+ scanDir(fullPath);
315
+ }
316
+ else if (entry.isFile() && this.shouldWatchFile(fullPath)) {
317
+ files.push(fullPath);
318
+ }
319
+ }
320
+ }
321
+ catch {
322
+ // Ignore errors
323
+ }
324
+ };
325
+ scanDir(this.rootPath);
326
+ return files;
327
+ }
328
+ }
329
+ /**
330
+ * Менеджер автоматической переиндексации
331
+ */
332
+ export class AutoReindexManager {
333
+ watcher;
334
+ reindexCallback;
335
+ batchTimeout;
336
+ pendingReindex = false;
337
+ batchDelayMs;
338
+ constructor(batchDelayMs = 1000) {
339
+ this.watcher = new FileWatcher();
340
+ this.batchDelayMs = batchDelayMs;
341
+ // Подписываемся на изменения
342
+ this.watcher.on('change', () => this.scheduleReindex());
343
+ this.watcher.on('add', () => this.scheduleReindex());
344
+ this.watcher.on('delete', () => this.scheduleReindex());
345
+ }
346
+ /**
347
+ * Запуск мониторинга с callback для переиндексации
348
+ */
349
+ async start(dirPath, reindexCallback) {
350
+ this.reindexCallback = reindexCallback;
351
+ await this.watcher.watch(dirPath);
352
+ }
353
+ /**
354
+ * Остановка мониторинга
355
+ */
356
+ stop() {
357
+ if (this.batchTimeout) {
358
+ clearTimeout(this.batchTimeout);
359
+ }
360
+ this.watcher.stop();
361
+ }
362
+ /**
363
+ * Планирование переиндексации (с батчингом)
364
+ */
365
+ scheduleReindex() {
366
+ this.pendingReindex = true;
367
+ if (this.batchTimeout) {
368
+ clearTimeout(this.batchTimeout);
369
+ }
370
+ this.batchTimeout = setTimeout(async () => {
371
+ if (this.pendingReindex && this.reindexCallback) {
372
+ this.pendingReindex = false;
373
+ Logger.progress('Auto-reindexing triggered...');
374
+ try {
375
+ await this.reindexCallback();
376
+ Logger.success('Auto-reindex completed');
377
+ }
378
+ catch (error) {
379
+ Logger.error(`Auto-reindex failed: ${error}`);
380
+ }
381
+ }
382
+ }, this.batchDelayMs);
383
+ }
384
+ /**
385
+ * Получить статистику watcher'а
386
+ */
387
+ getStats() {
388
+ return this.watcher.getStats();
389
+ }
390
+ /**
391
+ * Получить экземпляр watcher'а
392
+ */
393
+ getWatcher() {
394
+ return this.watcher;
395
+ }
396
+ }
397
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "archicore",
3
+ "version": "0.1.0",
4
+ "description": "AI Software Architect - code analysis, impact prediction, semantic search",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "archicore": "./dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist/**/*.js",
12
+ "dist/**/*.d.ts",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsx watch src/index.ts",
19
+ "start": "node dist/index.js",
20
+ "server": "tsx src/server/index.ts",
21
+ "server:dev": "tsx watch src/server/index.ts",
22
+ "cli": "tsx src/cli.ts",
23
+ "index": "tsx src/cli.ts index",
24
+ "analyze": "tsx src/cli.ts analyze",
25
+ "impact": "tsx src/cli.ts impact"
26
+ },
27
+ "keywords": [
28
+ "ai",
29
+ "architecture",
30
+ "code-analysis",
31
+ "ast",
32
+ "vector-db",
33
+ "impact-analysis"
34
+ ],
35
+ "author": "",
36
+ "license": "MIT",
37
+ "dependencies": {
38
+ "@anthropic-ai/sdk": "^0.32.0",
39
+ "@qdrant/js-client-rest": "^1.11.0",
40
+ "adm-zip": "^0.5.16",
41
+ "boxen": "^8.0.1",
42
+ "chalk": "^5.4.1",
43
+ "cli-table3": "^0.6.5",
44
+ "commander": "^12.1.0",
45
+ "figures": "^6.1.0",
46
+ "cors": "^2.8.5",
47
+ "dotenv": "^16.4.7",
48
+ "express": "^5.2.1",
49
+ "glob": "^11.0.0",
50
+ "mime-types": "^3.0.2",
51
+ "multer": "^2.0.2",
52
+ "openai": "^4.73.0",
53
+ "ora": "^8.1.1",
54
+ "tree-sitter": "^0.21.1",
55
+ "tree-sitter-javascript": "^0.21.4",
56
+ "tree-sitter-python": "^0.21.0",
57
+ "tree-sitter-typescript": "^0.21.2",
58
+ "uuid": "^11.0.3",
59
+ "zod": "^3.24.1"
60
+ },
61
+ "devDependencies": {
62
+ "@types/adm-zip": "^0.5.7",
63
+ "@types/cors": "^2.8.19",
64
+ "@types/express": "^5.0.6",
65
+ "@types/mime-types": "^3.0.1",
66
+ "@types/multer": "^2.0.0",
67
+ "@types/node": "^22.10.2",
68
+ "tsx": "^4.19.2",
69
+ "typescript": "^5.7.2"
70
+ }
71
+ }