ccsetup 1.1.1 → 1.2.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 (88) hide show
  1. package/README.md +96 -363
  2. package/bin/create-project.js +1616 -60
  3. package/bin/lib/claudeInterface.js +209 -0
  4. package/bin/lib/contextGenerator.js +287 -0
  5. package/bin/lib/scanner/index.js +28 -0
  6. package/bin/scan.js +367 -0
  7. package/lib/aiAgentSelector.js +155 -0
  8. package/lib/aiMergeHelper.js +112 -0
  9. package/lib/contextGenerator.js +574 -0
  10. package/lib/contextMerger.js +812 -0
  11. package/lib/progressReporter.js +88 -0
  12. package/lib/scanConfig.js +200 -0
  13. package/lib/scanner/fileAnalyzer.js +605 -0
  14. package/lib/scanner/index.js +164 -0
  15. package/lib/scanner/patterns.js +277 -0
  16. package/lib/scanner/projectDetector.js +147 -0
  17. package/lib/templates/README.md +176 -0
  18. package/lib/templates/catalog.js +230 -0
  19. package/lib/templates/filter.js +257 -0
  20. package/lib/templates/index.js +45 -0
  21. package/lib/templates/metadata/agents.json +413 -0
  22. package/lib/templates/metadata-extractor.js +329 -0
  23. package/lib/templates/search.js +356 -0
  24. package/package.json +11 -4
  25. package/template/{agents → .claude/agents}/checker.md +29 -0
  26. package/template/.claude/settings.json +15 -0
  27. package/template/.claude/skills/prd/SKILL.md +343 -0
  28. package/template/.claude/skills/ralph/SKILL.md +339 -0
  29. package/template/CLAUDE.md +39 -21
  30. package/template/CONTRIBUTING.md +37 -0
  31. package/template/agents/README.md +15 -171
  32. package/template/docs/ROADMAP.md +0 -36
  33. package/template/docs/agent-orchestration.md +24 -141
  34. package/template/hooks/workflow-selector/index.js +398 -0
  35. package/template/scripts/ralph/CLAUDE.md +174 -0
  36. package/template/scripts/ralph/ralph.sh +127 -0
  37. package/template/tickets/ticket-list.md +17 -68
  38. package/template/agents/ai-engineer.md +0 -31
  39. package/template/agents/api-documenter.md +0 -31
  40. package/template/agents/architect-review.md +0 -42
  41. package/template/agents/backend-architect.md +0 -29
  42. package/template/agents/business-analyst.md +0 -34
  43. package/template/agents/c-pro.md +0 -34
  44. package/template/agents/cloud-architect.md +0 -31
  45. package/template/agents/code-reviewer.md +0 -28
  46. package/template/agents/content-marketer.md +0 -34
  47. package/template/agents/context-manager.md +0 -63
  48. package/template/agents/cpp-pro.md +0 -37
  49. package/template/agents/customer-support.md +0 -34
  50. package/template/agents/data-engineer.md +0 -31
  51. package/template/agents/data-scientist.md +0 -28
  52. package/template/agents/database-admin.md +0 -31
  53. package/template/agents/database-optimizer.md +0 -31
  54. package/template/agents/debugger.md +0 -29
  55. package/template/agents/deployment-engineer.md +0 -31
  56. package/template/agents/devops-troubleshooter.md +0 -31
  57. package/template/agents/dx-optimizer.md +0 -62
  58. package/template/agents/error-detective.md +0 -31
  59. package/template/agents/frontend-developer.md +0 -30
  60. package/template/agents/golang-pro.md +0 -31
  61. package/template/agents/graphql-architect.md +0 -31
  62. package/template/agents/incident-responder.md +0 -73
  63. package/template/agents/javascript-pro.md +0 -34
  64. package/template/agents/legacy-modernizer.md +0 -31
  65. package/template/agents/ml-engineer.md +0 -31
  66. package/template/agents/mlops-engineer.md +0 -56
  67. package/template/agents/mobile-developer.md +0 -31
  68. package/template/agents/network-engineer.md +0 -31
  69. package/template/agents/payment-integration.md +0 -31
  70. package/template/agents/performance-engineer.md +0 -31
  71. package/template/agents/prompt-engineer.md +0 -58
  72. package/template/agents/python-pro.md +0 -31
  73. package/template/agents/quant-analyst.md +0 -31
  74. package/template/agents/risk-manager.md +0 -40
  75. package/template/agents/rust-pro.md +0 -34
  76. package/template/agents/sales-automator.md +0 -34
  77. package/template/agents/search-specialist.md +0 -58
  78. package/template/agents/security-auditor.md +0 -31
  79. package/template/agents/sql-pro.md +0 -34
  80. package/template/agents/terraform-specialist.md +0 -34
  81. package/template/agents/test-automator.md +0 -31
  82. /package/template/{agents → .claude/agents}/backend.md +0 -0
  83. /package/template/{agents → .claude/agents}/blockchain.md +0 -0
  84. /package/template/{agents → .claude/agents}/coder.md +0 -0
  85. /package/template/{agents → .claude/agents}/frontend.md +0 -0
  86. /package/template/{agents → .claude/agents}/planner.md +0 -0
  87. /package/template/{agents → .claude/agents}/researcher.md +0 -0
  88. /package/template/{agents → .claude/agents}/shadcn.md +0 -0
@@ -0,0 +1,164 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const ProjectDetector = require('./projectDetector');
4
+ const FileAnalyzer = require('./fileAnalyzer');
5
+
6
+ class RepositoryScanner {
7
+ constructor(projectPath, options = {}) {
8
+ this.projectPath = path.resolve(projectPath);
9
+ this.options = {
10
+ maxFiles: 1000,
11
+ timeout: 30000,
12
+ respectGitignore: true,
13
+ maxFileSize: 1024 * 1024, // 1MB
14
+ maxDepth: options.maxDepth || options.depth || 5,
15
+ ignorePatterns: this.parseIgnorePatterns(options.ignorePatterns || options.ignore),
16
+ ...options
17
+ };
18
+ this.projectDetector = new ProjectDetector(this.projectPath);
19
+ this.fileAnalyzer = new FileAnalyzer(this.projectPath, this.options);
20
+ }
21
+
22
+ parseIgnorePatterns(patterns) {
23
+ if (!patterns) return [];
24
+ if (typeof patterns === 'string') {
25
+ return patterns.split(',').map(p => p.trim()).filter(Boolean);
26
+ }
27
+ if (Array.isArray(patterns)) {
28
+ return patterns.map(p => String(p).trim()).filter(Boolean);
29
+ }
30
+ return [];
31
+ }
32
+
33
+ shouldIgnorePath(filePath) {
34
+ const relativePath = path.relative(this.projectPath, filePath);
35
+ const depth = relativePath.split(path.sep).length;
36
+
37
+ if (depth > this.options.maxDepth) {
38
+ return true;
39
+ }
40
+
41
+ for (const pattern of this.options.ignorePatterns) {
42
+ try {
43
+ const minimatch = require('minimatch');
44
+ if (minimatch(relativePath, pattern)) {
45
+ return true;
46
+ }
47
+ } catch (error) {
48
+ if (relativePath.includes(pattern)) {
49
+ return true;
50
+ }
51
+ }
52
+ }
53
+
54
+ return false;
55
+ }
56
+
57
+ async scan(progressReporter = null) {
58
+ const startTime = Date.now();
59
+
60
+ try {
61
+ if (progressReporter) {
62
+ progressReporter.start('Scanning repository...');
63
+ }
64
+
65
+ let projectType, structure, dependencies, commands, patterns;
66
+
67
+ if (progressReporter) {
68
+ progressReporter.phase('Analyzing project structure');
69
+ structure = await this.analyzeStructure();
70
+ progressReporter.phaseComplete('Analyzing project structure', `${structure.totalFiles || 0} files`);
71
+
72
+ progressReporter.phase('Detecting project type');
73
+ projectType = await this.detectProjectType();
74
+ progressReporter.phaseComplete('Detecting project type', projectType?.primary?.type || 'unknown');
75
+
76
+ progressReporter.phase('Extracting dependencies');
77
+ dependencies = await this.extractDependencies();
78
+ const depCount = dependencies?.runtime?.length || 0;
79
+ progressReporter.phaseComplete('Extracting dependencies', `${depCount} packages`);
80
+
81
+ progressReporter.phase('Extracting commands');
82
+ commands = await this.extractCommands();
83
+ const cmdCount = Object.values(commands || {}).reduce((sum, cmds) => sum + cmds.length, 0);
84
+ progressReporter.phaseComplete('Extracting commands', `${cmdCount} scripts`);
85
+
86
+ progressReporter.phase('Detecting patterns');
87
+ patterns = await this.detectPatterns();
88
+ const patternCount = Object.values(patterns || {}).reduce((sum, patterns) => sum + patterns.length, 0);
89
+ progressReporter.phaseComplete('Detecting patterns', `${patternCount} patterns`);
90
+ } else {
91
+ [projectType, structure, dependencies, commands, patterns] = await Promise.all([
92
+ this.detectProjectType(),
93
+ this.analyzeStructure(),
94
+ this.extractDependencies(),
95
+ this.extractCommands(),
96
+ this.detectPatterns()
97
+ ]);
98
+ }
99
+
100
+ const scanTime = Date.now() - startTime;
101
+
102
+ const results = {
103
+ projectType,
104
+ structure,
105
+ dependencies,
106
+ commands,
107
+ patterns,
108
+ scanDate: new Date().toISOString(),
109
+ scanTimeMs: scanTime,
110
+ projectPath: this.projectPath
111
+ };
112
+
113
+ if (progressReporter) {
114
+ progressReporter.success('Repository scan completed');
115
+ }
116
+
117
+ return results;
118
+ } catch (error) {
119
+ if (progressReporter) {
120
+ progressReporter.fail(`Repository scan failed: ${error.message}`);
121
+ }
122
+ throw new Error(`Repository scan failed: ${error.message}`);
123
+ }
124
+ }
125
+
126
+ async detectProjectType() {
127
+ return await this.projectDetector.detect();
128
+ }
129
+
130
+ async analyzeStructure() {
131
+ return await this.fileAnalyzer.analyzeStructure();
132
+ }
133
+
134
+ async extractDependencies() {
135
+ return await this.fileAnalyzer.extractDependencies();
136
+ }
137
+
138
+ async extractCommands() {
139
+ return await this.fileAnalyzer.extractCommands();
140
+ }
141
+
142
+ async detectPatterns() {
143
+ return await this.fileAnalyzer.detectPatterns();
144
+ }
145
+
146
+ isValidProject() {
147
+ try {
148
+ const stats = fs.statSync(this.projectPath);
149
+ return stats.isDirectory();
150
+ } catch (error) {
151
+ return false;
152
+ }
153
+ }
154
+
155
+ static async quickScan(projectPath) {
156
+ const scanner = new RepositoryScanner(projectPath, {
157
+ maxFiles: 100,
158
+ timeout: 10000
159
+ });
160
+ return await scanner.scan();
161
+ }
162
+ }
163
+
164
+ module.exports = RepositoryScanner;
@@ -0,0 +1,277 @@
1
+ const PROJECT_TYPES = {
2
+ nodejs: {
3
+ indicators: [
4
+ { type: 'file', file: 'package.json', weight: 30 },
5
+ { type: 'file', file: 'package-lock.json', weight: 10 },
6
+ { type: 'file', file: 'yarn.lock', weight: 10 },
7
+ { type: 'directory', file: 'node_modules', weight: 20 },
8
+ { type: 'file', file: '.nvmrc', weight: 5 }
9
+ ]
10
+ },
11
+ python: {
12
+ indicators: [
13
+ { type: 'file', file: 'requirements.txt', weight: 25 },
14
+ { type: 'file', file: 'setup.py', weight: 20 },
15
+ { type: 'file', file: 'pyproject.toml', weight: 20 },
16
+ { type: 'file', file: 'Pipfile', weight: 15 },
17
+ { type: 'file', file: 'poetry.lock', weight: 10 },
18
+ { type: 'directory', file: 'venv', weight: 10 },
19
+ { type: 'directory', file: '.venv', weight: 10 }
20
+ ]
21
+ },
22
+ go: {
23
+ indicators: [
24
+ { type: 'file', file: 'go.mod', weight: 30 },
25
+ { type: 'file', file: 'go.sum', weight: 15 },
26
+ { type: 'file', file: 'main.go', weight: 20 },
27
+ { type: 'directory', file: 'cmd', weight: 10 },
28
+ { type: 'directory', file: 'pkg', weight: 10 }
29
+ ]
30
+ },
31
+ rust: {
32
+ indicators: [
33
+ { type: 'file', file: 'Cargo.toml', weight: 30 },
34
+ { type: 'file', file: 'Cargo.lock', weight: 15 },
35
+ { type: 'directory', file: 'src', weight: 20 },
36
+ { type: 'directory', file: 'target', weight: 10 }
37
+ ]
38
+ },
39
+ java: {
40
+ indicators: [
41
+ { type: 'file', file: 'pom.xml', weight: 25 },
42
+ { type: 'file', file: 'build.gradle', weight: 25 },
43
+ { type: 'file', file: 'settings.gradle', weight: 10 },
44
+ { type: 'directory', file: 'src/main/java', weight: 20 },
45
+ { type: 'directory', file: 'target', weight: 10 },
46
+ { type: 'directory', file: 'build', weight: 10 }
47
+ ]
48
+ },
49
+ csharp: {
50
+ indicators: [
51
+ { type: 'file', file: '*.csproj', weight: 30 },
52
+ { type: 'file', file: '*.sln', weight: 25 },
53
+ { type: 'directory', file: 'bin', weight: 10 },
54
+ { type: 'directory', file: 'obj', weight: 10 }
55
+ ]
56
+ },
57
+ php: {
58
+ indicators: [
59
+ { type: 'file', file: 'composer.json', weight: 25 },
60
+ { type: 'file', file: 'composer.lock', weight: 15 },
61
+ { type: 'directory', file: 'vendor', weight: 20 },
62
+ { type: 'file', file: 'index.php', weight: 15 }
63
+ ]
64
+ },
65
+ ruby: {
66
+ indicators: [
67
+ { type: 'file', file: 'Gemfile', weight: 25 },
68
+ { type: 'file', file: 'Gemfile.lock', weight: 15 },
69
+ { type: 'file', file: 'config.ru', weight: 20 },
70
+ { type: 'directory', file: 'app', weight: 15 }
71
+ ]
72
+ },
73
+ flutter: {
74
+ indicators: [
75
+ { type: 'file', file: 'pubspec.yaml', weight: 30 },
76
+ { type: 'file', file: 'pubspec.lock', weight: 10 },
77
+ { type: 'directory', file: 'lib', weight: 20 },
78
+ { type: 'directory', file: 'android', weight: 15 },
79
+ { type: 'directory', file: 'ios', weight: 15 }
80
+ ]
81
+ },
82
+ react: {
83
+ indicators: [
84
+ { type: 'content', file: 'package.json', pattern: '"react"', weight: 25 },
85
+ { type: 'directory', file: 'src', weight: 15 },
86
+ { type: 'directory', file: 'public', weight: 10 },
87
+ { type: 'file', file: 'src/App.js', weight: 20 },
88
+ { type: 'file', file: 'src/App.tsx', weight: 20 }
89
+ ]
90
+ },
91
+ vue: {
92
+ indicators: [
93
+ { type: 'content', file: 'package.json', pattern: '"vue"', weight: 25 },
94
+ { type: 'file', file: 'vue.config.js', weight: 15 },
95
+ { type: 'directory', file: 'src', weight: 15 },
96
+ { type: 'file', file: 'src/App.vue', weight: 20 }
97
+ ]
98
+ },
99
+ angular: {
100
+ indicators: [
101
+ { type: 'file', file: 'angular.json', weight: 30 },
102
+ { type: 'content', file: 'package.json', pattern: '"@angular/core"', weight: 25 },
103
+ { type: 'directory', file: 'src/app', weight: 20 },
104
+ { type: 'file', file: 'src/main.ts', weight: 15 }
105
+ ]
106
+ }
107
+ };
108
+
109
+ const FRAMEWORKS = {
110
+ nodejs: {
111
+ express: [
112
+ { type: 'content', file: 'package.json', pattern: '"express"' }
113
+ ],
114
+ nestjs: [
115
+ { type: 'content', file: 'package.json', pattern: '"@nestjs/core"' }
116
+ ],
117
+ fastify: [
118
+ { type: 'content', file: 'package.json', pattern: '"fastify"' }
119
+ ],
120
+ koa: [
121
+ { type: 'content', file: 'package.json', pattern: '"koa"' }
122
+ ],
123
+ next: [
124
+ { type: 'content', file: 'package.json', pattern: '"next"' },
125
+ { type: 'file', file: 'next.config.js' }
126
+ ],
127
+ nuxt: [
128
+ { type: 'content', file: 'package.json', pattern: '"nuxt"' },
129
+ { type: 'file', file: 'nuxt.config.js' }
130
+ ]
131
+ },
132
+ python: {
133
+ django: [
134
+ { type: 'content', file: 'requirements.txt', pattern: 'Django' },
135
+ { type: 'file', file: 'manage.py' }
136
+ ],
137
+ flask: [
138
+ { type: 'content', file: 'requirements.txt', pattern: 'Flask' }
139
+ ],
140
+ fastapi: [
141
+ { type: 'content', file: 'requirements.txt', pattern: 'fastapi' }
142
+ ]
143
+ },
144
+ go: {
145
+ gin: [
146
+ { type: 'content', file: 'go.mod', pattern: 'gin-gonic/gin' }
147
+ ],
148
+ echo: [
149
+ { type: 'content', file: 'go.mod', pattern: 'labstack/echo' }
150
+ ],
151
+ fiber: [
152
+ { type: 'content', file: 'go.mod', pattern: 'gofiber/fiber' }
153
+ ]
154
+ }
155
+ };
156
+
157
+ const BUILD_TOOLS = {
158
+ webpack: [
159
+ { type: 'file', file: 'webpack.config.js' },
160
+ { type: 'content', file: 'package.json', pattern: '"webpack"' }
161
+ ],
162
+ vite: [
163
+ { type: 'file', file: 'vite.config.js' },
164
+ { type: 'file', file: 'vite.config.ts' },
165
+ { type: 'content', file: 'package.json', pattern: '"vite"' }
166
+ ],
167
+ rollup: [
168
+ { type: 'file', file: 'rollup.config.js' },
169
+ { type: 'content', file: 'package.json', pattern: '"rollup"' }
170
+ ],
171
+ parcel: [
172
+ { type: 'content', file: 'package.json', pattern: '"parcel"' }
173
+ ],
174
+ esbuild: [
175
+ { type: 'content', file: 'package.json', pattern: '"esbuild"' }
176
+ ],
177
+ make: [
178
+ { type: 'file', file: 'Makefile' }
179
+ ],
180
+ cmake: [
181
+ { type: 'file', file: 'CMakeLists.txt' }
182
+ ],
183
+ gradle: [
184
+ { type: 'file', file: 'build.gradle' },
185
+ { type: 'file', file: 'settings.gradle' }
186
+ ],
187
+ maven: [
188
+ { type: 'file', file: 'pom.xml' }
189
+ ]
190
+ };
191
+
192
+ const KEY_FILES = [
193
+ 'readme.md', 'readme.txt', 'readme.rst',
194
+ 'license', 'license.txt', 'license.md',
195
+ 'changelog.md', 'changelog.txt',
196
+ 'contributing.md', 'contributing.txt',
197
+ 'package.json', 'package-lock.json', 'yarn.lock',
198
+ 'requirements.txt', 'setup.py', 'pyproject.toml',
199
+ 'go.mod', 'go.sum',
200
+ 'cargo.toml', 'cargo.lock',
201
+ 'pom.xml', 'build.gradle',
202
+ 'dockerfile', 'docker-compose.yml',
203
+ 'makefile', 'cmakeLists.txt',
204
+ '.gitignore', '.env.example', '.env.template',
205
+ 'tsconfig.json', 'jsconfig.json',
206
+ '.eslintrc.js', '.eslintrc.json',
207
+ '.prettierrc', 'prettier.config.js'
208
+ ];
209
+
210
+ const CONFIG_FILES = [
211
+ /.*config\.(js|json|yaml|yml|toml)$/i,
212
+ /.*\.config\.(js|json|yaml|yml|toml)$/i,
213
+ /.*rc\.(js|json|yaml|yml)$/i,
214
+ /^\.(.*rc|.*config)$/i
215
+ ];
216
+
217
+ const FRAMEWORK_PACKAGES = {
218
+ 'express': 'Express.js',
219
+ '@nestjs/core': 'NestJS',
220
+ 'fastify': 'Fastify',
221
+ 'koa': 'Koa.js',
222
+ 'next': 'Next.js',
223
+ 'nuxt': 'Nuxt.js',
224
+ 'react': 'React',
225
+ 'vue': 'Vue.js',
226
+ '@angular/core': 'Angular',
227
+ 'svelte': 'Svelte',
228
+ 'solid-js': 'SolidJS',
229
+ 'lit': 'Lit',
230
+ 'astro': 'Astro',
231
+ 'gatsby': 'Gatsby',
232
+ 'remix': 'Remix',
233
+ 'vite': 'Vite',
234
+ 'webpack': 'Webpack',
235
+ 'rollup': 'Rollup',
236
+ 'parcel': 'Parcel',
237
+ 'esbuild': 'esbuild',
238
+ 'typescript': 'TypeScript',
239
+ 'babel': 'Babel',
240
+ 'eslint': 'ESLint',
241
+ 'prettier': 'Prettier',
242
+ 'jest': 'Jest',
243
+ 'vitest': 'Vitest',
244
+ 'cypress': 'Cypress',
245
+ 'playwright': 'Playwright',
246
+ 'storybook': 'Storybook',
247
+ 'tailwindcss': 'Tailwind CSS',
248
+ 'styled-components': 'Styled Components',
249
+ '@emotion/react': 'Emotion',
250
+ 'sass': 'Sass',
251
+ 'less': 'Less',
252
+ 'prisma': 'Prisma',
253
+ 'mongoose': 'Mongoose',
254
+ 'sequelize': 'Sequelize',
255
+ 'typeorm': 'TypeORM',
256
+ 'apollo-server': 'Apollo Server',
257
+ 'graphql': 'GraphQL',
258
+ 'socket.io': 'Socket.IO',
259
+ 'passport': 'Passport.js',
260
+ 'jsonwebtoken': 'JWT',
261
+ 'bcrypt': 'bcrypt',
262
+ 'lodash': 'Lodash',
263
+ 'moment': 'Moment.js',
264
+ 'dayjs': 'Day.js',
265
+ 'axios': 'Axios',
266
+ 'got': 'Got',
267
+ 'node-fetch': 'node-fetch'
268
+ };
269
+
270
+ module.exports = {
271
+ PROJECT_TYPES,
272
+ FRAMEWORKS,
273
+ BUILD_TOOLS,
274
+ KEY_FILES,
275
+ CONFIG_FILES,
276
+ FRAMEWORK_PACKAGES
277
+ };
@@ -0,0 +1,147 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const patterns = require('./patterns');
4
+
5
+ class ProjectDetector {
6
+ constructor(projectPath) {
7
+ this.projectPath = projectPath;
8
+ }
9
+
10
+ async detect() {
11
+ const detectionResults = [];
12
+
13
+ try {
14
+ for (const [projectType, config] of Object.entries(patterns.PROJECT_TYPES)) {
15
+ const confidence = await this.calculateConfidence(projectType, config);
16
+ if (confidence > 0) {
17
+ detectionResults.push({
18
+ type: projectType,
19
+ confidence,
20
+ indicators: config.indicators.filter(indicator =>
21
+ this.checkIndicator(indicator)
22
+ )
23
+ });
24
+ }
25
+ }
26
+
27
+ detectionResults.sort((a, b) => b.confidence - a.confidence);
28
+
29
+ const primaryType = detectionResults[0] || { type: 'unknown', confidence: 0, indicators: [] };
30
+ const secondaryTypes = detectionResults.slice(1, 3);
31
+
32
+ return {
33
+ primary: primaryType,
34
+ secondary: secondaryTypes,
35
+ framework: await this.detectFramework(primaryType.type),
36
+ language: await this.detectLanguage(),
37
+ buildTools: await this.detectBuildTools()
38
+ };
39
+ } catch (error) {
40
+ return {
41
+ primary: { type: 'unknown', confidence: 0, indicators: [] },
42
+ secondary: [],
43
+ framework: null,
44
+ language: 'unknown',
45
+ buildTools: []
46
+ };
47
+ }
48
+ }
49
+
50
+ async calculateConfidence(projectType, config) {
51
+ let confidence = 0;
52
+ const maxConfidence = config.indicators.length * 10;
53
+
54
+ for (const indicator of config.indicators) {
55
+ if (this.checkIndicator(indicator)) {
56
+ confidence += indicator.weight || 10;
57
+ }
58
+ }
59
+
60
+ return Math.min(100, (confidence / maxConfidence) * 100);
61
+ }
62
+
63
+ checkIndicator(indicator) {
64
+ const filePath = path.join(this.projectPath, indicator.file);
65
+
66
+ try {
67
+ if (indicator.type === 'file') {
68
+ return fs.existsSync(filePath);
69
+ } else if (indicator.type === 'directory') {
70
+ const stats = fs.statSync(filePath);
71
+ return stats.isDirectory();
72
+ } else if (indicator.type === 'content') {
73
+ if (!fs.existsSync(filePath)) return false;
74
+ const content = fs.readFileSync(filePath, 'utf8');
75
+ return indicator.pattern ? new RegExp(indicator.pattern).test(content) : true;
76
+ }
77
+ } catch (error) {
78
+ return false;
79
+ }
80
+
81
+ return false;
82
+ }
83
+
84
+ async detectFramework(projectType) {
85
+ const frameworkPatterns = patterns.FRAMEWORKS[projectType];
86
+ if (!frameworkPatterns) return null;
87
+
88
+ for (const [framework, indicators] of Object.entries(frameworkPatterns)) {
89
+ let matches = 0;
90
+ for (const indicator of indicators) {
91
+ if (this.checkIndicator(indicator)) {
92
+ matches++;
93
+ }
94
+ }
95
+ if (matches > 0) {
96
+ return { name: framework, confidence: (matches / indicators.length) * 100 };
97
+ }
98
+ }
99
+
100
+ return null;
101
+ }
102
+
103
+ async detectLanguage() {
104
+ const languageIndicators = {
105
+ javascript: ['package.json', '*.js', '*.mjs'],
106
+ typescript: ['tsconfig.json', '*.ts', '*.tsx'],
107
+ python: ['requirements.txt', 'pyproject.toml', '*.py'],
108
+ go: ['go.mod', 'go.sum', '*.go'],
109
+ rust: ['Cargo.toml', 'Cargo.lock', '*.rs'],
110
+ java: ['pom.xml', 'build.gradle', '*.java'],
111
+ csharp: ['*.csproj', '*.sln'],
112
+ php: ['composer.json', '*.php'],
113
+ ruby: ['Gemfile', '*.rb'],
114
+ cpp: ['CMakeLists.txt', '*.cpp', '*.cc', '*.cxx'],
115
+ c: ['Makefile', '*.c', '*.h']
116
+ };
117
+
118
+ for (const [language, indicators] of Object.entries(languageIndicators)) {
119
+ for (const indicator of indicators) {
120
+ const fullPath = path.join(this.projectPath, indicator);
121
+ if (fs.existsSync(fullPath)) {
122
+ return language;
123
+ }
124
+ }
125
+ }
126
+
127
+ return 'unknown';
128
+ }
129
+
130
+ async detectBuildTools() {
131
+ const buildTools = [];
132
+ const buildToolPatterns = patterns.BUILD_TOOLS;
133
+
134
+ for (const [tool, indicators] of Object.entries(buildToolPatterns)) {
135
+ for (const indicator of indicators) {
136
+ if (this.checkIndicator(indicator)) {
137
+ buildTools.push(tool);
138
+ break;
139
+ }
140
+ }
141
+ }
142
+
143
+ return buildTools;
144
+ }
145
+ }
146
+
147
+ module.exports = ProjectDetector;