vg-coder-cli 1.0.16 → 2.0.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 (78) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/PUBLISHING.md +86 -0
  3. package/README.md +92 -318
  4. package/SYSTEM_PROMPT.md +157 -0
  5. package/init-nx-monorepo.sh +107 -0
  6. package/package.json +11 -4
  7. package/src/server/api-server.js +6 -1
  8. package/src/server/views/dashboard.html +69 -4
  9. package/vg/.vscode/extensions.json +8 -0
  10. package/vg/.vscode/launch.json +23 -0
  11. package/vg/README.md +85 -0
  12. package/vg/apps/api/project.json +83 -0
  13. package/vg/apps/api/src/app/analyze.controller.ts +17 -0
  14. package/vg/apps/api/src/app/analyze.service.ts +57 -0
  15. package/vg/apps/api/src/app/app.controller.ts +12 -0
  16. package/vg/apps/api/src/app/app.module.ts +29 -0
  17. package/vg/apps/api/src/app/app.service.ts +8 -0
  18. package/vg/apps/api/src/app/clean.controller.ts +40 -0
  19. package/vg/apps/api/src/app/execute.controller.ts +19 -0
  20. package/vg/apps/api/src/app/execute.service.ts +46 -0
  21. package/vg/apps/api/src/app/info.controller.ts +12 -0
  22. package/vg/apps/api/src/app/info.service.ts +65 -0
  23. package/vg/apps/api/src/assets/.gitkeep +0 -0
  24. package/vg/apps/api/src/main.ts +28 -0
  25. package/vg/apps/api/webpack.config.js +25 -0
  26. package/vg/apps/api-e2e/jest.config.cts +18 -0
  27. package/vg/apps/api-e2e/project.json +17 -0
  28. package/vg/apps/api-e2e/src/support/global-setup.ts +16 -0
  29. package/vg/apps/api-e2e/src/support/global-teardown.ts +10 -0
  30. package/vg/apps/api-e2e/src/support/test-setup.ts +9 -0
  31. package/vg/apps/ng-app/jest.config.ts +21 -0
  32. package/vg/apps/ng-app/project.json +110 -0
  33. package/vg/apps/ng-app/proxy.conf.json +8 -0
  34. package/vg/apps/ng-app/public/favicon.ico +0 -0
  35. package/vg/apps/ng-app/src/app/app.config.ts +17 -0
  36. package/vg/apps/ng-app/src/app/app.html +1 -0
  37. package/vg/apps/ng-app/src/app/app.routes.ts +7 -0
  38. package/vg/apps/ng-app/src/app/app.scss +0 -0
  39. package/vg/apps/ng-app/src/app/app.ts +12 -0
  40. package/vg/apps/ng-app/src/app/dashboard/dashboard.component.html +87 -0
  41. package/vg/apps/ng-app/src/app/dashboard/dashboard.component.scss +290 -0
  42. package/vg/apps/ng-app/src/app/dashboard/dashboard.component.ts +236 -0
  43. package/vg/apps/ng-app/src/app/nx-welcome.ts +872 -0
  44. package/vg/apps/ng-app/src/app/services/api.service.ts +28 -0
  45. package/vg/apps/ng-app/src/index.html +13 -0
  46. package/vg/apps/ng-app/src/main.ts +5 -0
  47. package/vg/apps/ng-app/src/styles.scss +1 -0
  48. package/vg/apps/ng-app/src/test-setup.ts +6 -0
  49. package/vg/jest.config.ts +6 -0
  50. package/vg/nx.json +85 -0
  51. package/vg/package-lock.json +30707 -0
  52. package/vg/package.json +75 -0
  53. package/vg/packages/client/data-access/README.md +7 -0
  54. package/vg/packages/client/data-access/jest.config.ts +21 -0
  55. package/vg/packages/client/data-access/project.json +21 -0
  56. package/vg/packages/client/data-access/src/index.ts +1 -0
  57. package/vg/packages/client/data-access/src/lib/data-access/data-access.html +1 -0
  58. package/vg/packages/client/data-access/src/lib/data-access/data-access.scss +0 -0
  59. package/vg/packages/client/data-access/src/lib/data-access/data-access.ts +9 -0
  60. package/vg/packages/client/data-access/src/test-setup.ts +6 -0
  61. package/vg/packages/core/README.md +11 -0
  62. package/vg/packages/core/jest.config.ts +10 -0
  63. package/vg/packages/core/package.json +11 -0
  64. package/vg/packages/core/project.json +26 -0
  65. package/vg/packages/core/src/index.ts +6 -0
  66. package/vg/packages/core/src/lib/core.ts +3 -0
  67. package/vg/packages/core/src/lib/detectors/project-detector.ts +343 -0
  68. package/vg/packages/core/src/lib/ignore/ignore-manager.ts +315 -0
  69. package/vg/packages/core/src/lib/scanner/file-scanner.ts +675 -0
  70. package/vg/packages/core/src/lib/tokenizer/token-manager.ts +435 -0
  71. package/vg/packages/core/src/lib/utils/bash-executor.ts +146 -0
  72. package/vg/packages/shared/data-types/README.md +11 -0
  73. package/vg/packages/shared/data-types/jest.config.ts +10 -0
  74. package/vg/packages/shared/data-types/package.json +11 -0
  75. package/vg/packages/shared/data-types/project.json +26 -0
  76. package/vg/packages/shared/data-types/src/index.ts +1 -0
  77. package/vg/packages/shared/data-types/src/lib/data-types.ts +3 -0
  78. package/vg/start-dev.sh +22 -0
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@vg/source",
3
+ "version": "0.0.0",
4
+ "license": "MIT",
5
+ "scripts": {},
6
+ "private": true,
7
+ "devDependencies": {
8
+ "@angular-devkit/core": "~20.3.0",
9
+ "@angular-devkit/schematics": "~20.3.0",
10
+ "@angular/build": "~20.3.0",
11
+ "@angular/cli": "~20.3.0",
12
+ "@angular/compiler-cli": "~20.3.0",
13
+ "@angular/language-service": "~20.3.0",
14
+ "@eslint/js": "^9.8.0",
15
+ "@nestjs/schematics": "^11.0.0",
16
+ "@nestjs/testing": "^11.0.0",
17
+ "@nx/angular": "^22.1.3",
18
+ "@nx/eslint": "22.1.3",
19
+ "@nx/eslint-plugin": "22.1.3",
20
+ "@nx/jest": "22.1.3",
21
+ "@nx/js": "^22.1.3",
22
+ "@nx/nest": "^22.1.3",
23
+ "@nx/node": "22.1.3",
24
+ "@nx/web": "22.1.3",
25
+ "@nx/webpack": "22.1.3",
26
+ "@nx/workspace": "22.1.3",
27
+ "@schematics/angular": "~20.3.0",
28
+ "@swc-node/register": "~1.9.1",
29
+ "@swc/core": "~1.5.7",
30
+ "@swc/helpers": "~0.5.11",
31
+ "@types/fs-extra": "^11.0.4",
32
+ "@types/jest": "^29.5.12",
33
+ "@types/node": "20.19.9",
34
+ "@types/supertest": "^6.0.3",
35
+ "@typescript-eslint/utils": "^8.40.0",
36
+ "angular-eslint": "^20.3.0",
37
+ "eslint": "^9.8.0",
38
+ "eslint-config-prettier": "^10.0.0",
39
+ "jest": "^29.7.0",
40
+ "jest-environment-jsdom": "^29.7.0",
41
+ "jest-environment-node": "^29.7.0",
42
+ "jest-preset-angular": "~14.6.1",
43
+ "jest-util": "^29.7.0",
44
+ "jsonc-eslint-parser": "^2.1.0",
45
+ "nx": "22.1.3",
46
+ "prettier": "^2.6.2",
47
+ "supertest": "^7.1.4",
48
+ "ts-jest": "^29.1.0",
49
+ "ts-node": "10.9.1",
50
+ "tslib": "^2.3.0",
51
+ "typescript": "~5.9.2",
52
+ "typescript-eslint": "^8.40.0",
53
+ "webpack-cli": "^5.1.4"
54
+ },
55
+ "dependencies": {
56
+ "@angular/common": "~20.3.0",
57
+ "@angular/compiler": "~20.3.0",
58
+ "@angular/core": "~20.3.0",
59
+ "@angular/forms": "~20.3.0",
60
+ "@angular/platform-browser": "~20.3.0",
61
+ "@angular/platform-browser-dynamic": "~20.3.0",
62
+ "@angular/router": "~20.3.0",
63
+ "@nestjs/common": "^11.0.0",
64
+ "@nestjs/core": "^11.0.0",
65
+ "@nestjs/platform-express": "^11.0.0",
66
+ "axios": "^1.6.0",
67
+ "directory-tree": "^3.5.2",
68
+ "fs-extra": "^11.3.2",
69
+ "ignore": "^7.0.5",
70
+ "reflect-metadata": "^0.1.13",
71
+ "rxjs": "^7.8.0",
72
+ "tiktoken": "^1.0.22",
73
+ "zone.js": "~0.15.0"
74
+ }
75
+ }
@@ -0,0 +1,7 @@
1
+ # data-access
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Running unit tests
6
+
7
+ Run `nx test data-access` to execute the unit tests.
@@ -0,0 +1,21 @@
1
+ export default {
2
+ displayName: 'data-access',
3
+ preset: '../../../jest.preset.js',
4
+ setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
5
+ coverageDirectory: '../../../coverage/packages/client/data-access',
6
+ transform: {
7
+ '^.+\\.(ts|mjs|js|html)$': [
8
+ 'jest-preset-angular',
9
+ {
10
+ tsconfig: '<rootDir>/tsconfig.spec.json',
11
+ stringifyContentPathRegex: '\\.(html|svg)$',
12
+ },
13
+ ],
14
+ },
15
+ transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
16
+ snapshotSerializers: [
17
+ 'jest-preset-angular/build/serializers/no-ng-attributes',
18
+ 'jest-preset-angular/build/serializers/ng-snapshot',
19
+ 'jest-preset-angular/build/serializers/html-comment',
20
+ ],
21
+ };
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "data-access",
3
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/client/data-access/src",
5
+ "prefix": "lib",
6
+ "projectType": "library",
7
+ "tags": ["scope:client", "type:lib"],
8
+ "targets": {
9
+ "test": {
10
+ "executor": "@nx/jest:jest",
11
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
12
+ "options": {
13
+ "jestConfig": "packages/client/data-access/jest.config.ts",
14
+ "tsConfig": "packages/client/data-access/tsconfig.spec.json"
15
+ }
16
+ },
17
+ "lint": {
18
+ "executor": "@nx/eslint:lint"
19
+ }
20
+ }
21
+ }
@@ -0,0 +1 @@
1
+ export * from './lib/data-access/data-access';
@@ -0,0 +1 @@
1
+ <p>DataAccess works!</p>
@@ -0,0 +1,9 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'lib-data-access',
5
+ imports: [],
6
+ templateUrl: './data-access.html',
7
+ styleUrl: './data-access.scss',
8
+ })
9
+ export class DataAccess {}
@@ -0,0 +1,6 @@
1
+ import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
2
+
3
+ setupZoneTestEnv({
4
+ errorOnUnknownElements: true,
5
+ errorOnUnknownProperties: true,
6
+ });
@@ -0,0 +1,11 @@
1
+ # core
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Building
6
+
7
+ Run `nx build core` to build the library.
8
+
9
+ ## Running unit tests
10
+
11
+ Run `nx test core` to execute the unit tests via [Jest](https://jestjs.io).
@@ -0,0 +1,10 @@
1
+ export default {
2
+ displayName: 'core',
3
+ preset: '../../jest.preset.js',
4
+ testEnvironment: 'node',
5
+ transform: {
6
+ '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
7
+ },
8
+ moduleFileExtensions: ['ts', 'js', 'html'],
9
+ coverageDirectory: '../../coverage/packages/core',
10
+ };
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@vg/core",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "commonjs",
6
+ "main": "./src/index.js",
7
+ "types": "./src/index.d.ts",
8
+ "dependencies": {
9
+ "tslib": "^2.3.0"
10
+ }
11
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "core",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/core/src",
5
+ "projectType": "library",
6
+ "tags": [],
7
+ "targets": {
8
+ "build": {
9
+ "executor": "@nx/js:tsc",
10
+ "outputs": ["{options.outputPath}"],
11
+ "options": {
12
+ "outputPath": "dist/packages/core",
13
+ "main": "packages/core/src/index.ts",
14
+ "tsConfig": "packages/core/tsconfig.lib.json",
15
+ "assets": ["packages/core/*.md"]
16
+ }
17
+ },
18
+ "test": {
19
+ "executor": "@nx/jest:jest",
20
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
21
+ "options": {
22
+ "jestConfig": "packages/core/jest.config.ts"
23
+ }
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,6 @@
1
+ export * from './lib/core';
2
+ export * from './lib/detectors/project-detector';
3
+ export * from './lib/scanner/file-scanner';
4
+ export * from './lib/tokenizer/token-manager';
5
+ export * from './lib/utils/bash-executor';
6
+ export * from './lib/ignore/ignore-manager';
@@ -0,0 +1,3 @@
1
+ export function core(): string {
2
+ return 'core';
3
+ }
@@ -0,0 +1,343 @@
1
+ import * as fs from 'fs-extra';
2
+ import * as path from 'path';
3
+
4
+ export interface ProjectTypeInfo {
5
+ detected: boolean;
6
+ confidence?: 'high' | 'medium' | 'low';
7
+ version?: string;
8
+ buildTool?: string;
9
+ indicators?: Record<string, any>;
10
+ }
11
+
12
+ export interface DetectionResult {
13
+ detected: Record<string, ProjectTypeInfo>;
14
+ primary: string;
15
+ all: Record<string, ProjectTypeInfo>;
16
+ }
17
+
18
+ /**
19
+ * Detect project type based on configuration files
20
+ */
21
+ export class ProjectDetector {
22
+ constructor(private projectPath: string) { }
23
+
24
+ /**
25
+ * Detect all possible project types
26
+ */
27
+ async detectAll(): Promise<DetectionResult> {
28
+ const results: Record<string, ProjectTypeInfo> = {
29
+ angular: await this.detectAngular(),
30
+ springBoot: await this.detectSpringBoot(),
31
+ react: await this.detectReact(),
32
+ vue: await this.detectVue(),
33
+ nodejs: await this.detectNodeJS(),
34
+ java: await this.detectJava(),
35
+ python: await this.detectPython(),
36
+ dotnet: await this.detectDotNet()
37
+ };
38
+
39
+ // Filter detected types
40
+ const detected = Object.entries(results)
41
+ .filter(([_, info]) => info.detected)
42
+ .reduce((acc, [type, info]) => {
43
+ acc[type] = info;
44
+ return acc;
45
+ }, {} as Record<string, ProjectTypeInfo>);
46
+
47
+ return {
48
+ detected,
49
+ primary: this.determinePrimaryType(detected),
50
+ all: results
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Detect Angular project
56
+ */
57
+ async detectAngular(): Promise<ProjectTypeInfo> {
58
+ try {
59
+ const packageJsonPath = path.join(this.projectPath, 'package.json');
60
+ const angularJsonPath = path.join(this.projectPath, 'angular.json');
61
+
62
+ if (await fs.pathExists(packageJsonPath)) {
63
+ const packageJson = await fs.readJson(packageJsonPath);
64
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
65
+
66
+ const hasAngularCore = deps['@angular/core'];
67
+ const hasAngularCli = deps['@angular/cli'];
68
+ const hasAngularJson = await fs.pathExists(angularJsonPath);
69
+
70
+ if (hasAngularCore || hasAngularCli || hasAngularJson) {
71
+ return {
72
+ detected: true,
73
+ confidence: hasAngularCore && hasAngularJson ? 'high' : 'medium',
74
+ version: hasAngularCore || 'unknown',
75
+ indicators: {
76
+ packageJson: !!hasAngularCore || !!hasAngularCli,
77
+ angularJson: hasAngularJson,
78
+ dependencies: Object.keys(deps).filter(dep => dep.startsWith('@angular/'))
79
+ }
80
+ };
81
+ }
82
+ }
83
+ } catch (error) {
84
+ // Ignore errors
85
+ }
86
+
87
+ return { detected: false };
88
+ }
89
+
90
+ /**
91
+ * Detect Spring Boot project
92
+ */
93
+ async detectSpringBoot(): Promise<ProjectTypeInfo> {
94
+ try {
95
+ const pomPath = path.join(this.projectPath, 'pom.xml');
96
+ const gradlePath = path.join(this.projectPath, 'build.gradle');
97
+ const gradleKtsPath = path.join(this.projectPath, 'build.gradle.kts');
98
+
99
+ // Check Maven (pom.xml)
100
+ if (await fs.pathExists(pomPath)) {
101
+ const pomContent = await fs.readFile(pomPath, 'utf8');
102
+ if (pomContent.includes('spring-boot-starter') || pomContent.includes('org.springframework.boot')) {
103
+ return {
104
+ detected: true,
105
+ confidence: 'high',
106
+ buildTool: 'maven',
107
+ indicators: {
108
+ pomXml: true,
109
+ springBootStarter: pomContent.includes('spring-boot-starter')
110
+ }
111
+ };
112
+ }
113
+ }
114
+
115
+ // Check Gradle
116
+ for (const gradleFile of [gradlePath, gradleKtsPath]) {
117
+ if (await fs.pathExists(gradleFile)) {
118
+ const gradleContent = await fs.readFile(gradleFile, 'utf8');
119
+ if (gradleContent.includes('spring-boot') || gradleContent.includes('org.springframework.boot')) {
120
+ return {
121
+ detected: true,
122
+ confidence: 'high',
123
+ buildTool: gradleFile.endsWith('.kts') ? 'gradle-kotlin' : 'gradle',
124
+ indicators: {
125
+ buildGradle: true,
126
+ springBootPlugin: gradleContent.includes('org.springframework.boot')
127
+ }
128
+ };
129
+ }
130
+ }
131
+ }
132
+ } catch (error) {
133
+ // Ignore errors
134
+ }
135
+
136
+ return { detected: false };
137
+ }
138
+
139
+ /**
140
+ * Detect React project
141
+ */
142
+ async detectReact(): Promise<ProjectTypeInfo> {
143
+ try {
144
+ const packageJsonPath = path.join(this.projectPath, 'package.json');
145
+ if (await fs.pathExists(packageJsonPath)) {
146
+ const packageJson = await fs.readJson(packageJsonPath);
147
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
148
+
149
+ if (deps.react) {
150
+ return {
151
+ detected: true,
152
+ confidence: 'high',
153
+ version: deps.react,
154
+ indicators: {
155
+ react: true,
156
+ reactDom: !!deps['react-dom'],
157
+ nextJs: !!deps.next,
158
+ createReactApp: !!deps['react-scripts']
159
+ }
160
+ };
161
+ }
162
+ }
163
+ } catch (error) {
164
+ // Ignore errors
165
+ }
166
+
167
+ return { detected: false };
168
+ }
169
+
170
+ /**
171
+ * Detect Vue project
172
+ */
173
+ async detectVue(): Promise<ProjectTypeInfo> {
174
+ try {
175
+ const packageJsonPath = path.join(this.projectPath, 'package.json');
176
+ if (await fs.pathExists(packageJsonPath)) {
177
+ const packageJson = await fs.readJson(packageJsonPath);
178
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
179
+
180
+ if (deps.vue) {
181
+ return {
182
+ detected: true,
183
+ confidence: 'high',
184
+ version: deps.vue,
185
+ indicators: {
186
+ vue: true,
187
+ vueRouter: !!deps['vue-router'],
188
+ vuex: !!deps.vuex,
189
+ nuxt: !!deps.nuxt
190
+ }
191
+ };
192
+ }
193
+ }
194
+ } catch (error) {
195
+ // Ignore errors
196
+ }
197
+
198
+ return { detected: false };
199
+ }
200
+
201
+ /**
202
+ * Detect Node.js project
203
+ */
204
+ async detectNodeJS(): Promise<ProjectTypeInfo> {
205
+ try {
206
+ const packageJsonPath = path.join(this.projectPath, 'package.json');
207
+ const exists = await fs.pathExists(packageJsonPath);
208
+ return {
209
+ detected: exists,
210
+ confidence: 'high',
211
+ indicators: {
212
+ packageJson: exists
213
+ }
214
+ };
215
+ } catch (error) {
216
+ return { detected: false };
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Detect Java project
222
+ */
223
+ async detectJava(): Promise<ProjectTypeInfo> {
224
+ try {
225
+ const pomPath = path.join(this.projectPath, 'pom.xml');
226
+ const gradlePath = path.join(this.projectPath, 'build.gradle');
227
+ const gradleKtsPath = path.join(this.projectPath, 'build.gradle.kts');
228
+
229
+ const hasPom = await fs.pathExists(pomPath);
230
+ const hasGradle = await fs.pathExists(gradlePath) || await fs.pathExists(gradleKtsPath);
231
+
232
+ if (hasPom || hasGradle) {
233
+ return {
234
+ detected: true,
235
+ confidence: 'high',
236
+ buildTool: hasPom ? 'maven' : 'gradle',
237
+ indicators: {
238
+ maven: hasPom,
239
+ gradle: hasGradle
240
+ }
241
+ };
242
+ }
243
+ } catch (error) {
244
+ // Ignore errors
245
+ }
246
+
247
+ return { detected: false };
248
+ }
249
+
250
+ /**
251
+ * Detect Python project
252
+ */
253
+ async detectPython(): Promise<ProjectTypeInfo> {
254
+ try {
255
+ const requirementsPath = path.join(this.projectPath, 'requirements.txt');
256
+ const pipfilePath = path.join(this.projectPath, 'Pipfile');
257
+ const pyprojectPath = path.join(this.projectPath, 'pyproject.toml');
258
+ const setupPyPath = path.join(this.projectPath, 'setup.py');
259
+
260
+ const hasRequirements = await fs.pathExists(requirementsPath);
261
+ const hasPipfile = await fs.pathExists(pipfilePath);
262
+ const hasPyproject = await fs.pathExists(pyprojectPath);
263
+ const hasSetupPy = await fs.pathExists(setupPyPath);
264
+
265
+ if (hasRequirements || hasPipfile || hasPyproject || hasSetupPy) {
266
+ return {
267
+ detected: true,
268
+ confidence: 'high',
269
+ indicators: {
270
+ requirements: hasRequirements,
271
+ pipfile: hasPipfile,
272
+ pyproject: hasPyproject,
273
+ setupPy: hasSetupPy
274
+ }
275
+ };
276
+ }
277
+ } catch (error) {
278
+ // Ignore errors
279
+ }
280
+
281
+ return { detected: false };
282
+ }
283
+
284
+ /**
285
+ * Detect .NET project
286
+ */
287
+ async detectDotNet(): Promise<ProjectTypeInfo> {
288
+ try {
289
+ const csprojFiles = await this.findFilesByExtension('.csproj');
290
+ const vbprojFiles = await this.findFilesByExtension('.vbproj');
291
+ const fsprojFiles = await this.findFilesByExtension('.fsproj');
292
+ const slnFiles = await this.findFilesByExtension('.sln');
293
+
294
+ const hasProjectFiles = csprojFiles.length > 0 || vbprojFiles.length > 0 || fsprojFiles.length > 0;
295
+ const hasSolution = slnFiles.length > 0;
296
+
297
+ if (hasProjectFiles || hasSolution) {
298
+ return {
299
+ detected: true,
300
+ confidence: 'high',
301
+ indicators: {
302
+ csproj: csprojFiles.length,
303
+ vbproj: vbprojFiles.length,
304
+ fsproj: fsprojFiles.length,
305
+ solution: slnFiles.length
306
+ }
307
+ };
308
+ }
309
+ } catch (error) {
310
+ // Ignore errors
311
+ }
312
+
313
+ return { detected: false };
314
+ }
315
+
316
+ /**
317
+ * Find files by extension
318
+ */
319
+ async findFilesByExtension(extension: string): Promise<string[]> {
320
+ try {
321
+ const files = await fs.readdir(this.projectPath);
322
+ return files.filter(file => file.endsWith(extension));
323
+ } catch (error) {
324
+ return [];
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Determine primary project type
330
+ */
331
+ determinePrimaryType(detected: Record<string, ProjectTypeInfo>): string {
332
+ const priorities = ['angular', 'springBoot', 'react', 'vue', 'nodejs', 'java', 'python', 'dotnet'];
333
+
334
+ for (const type of priorities) {
335
+ if (detected[type] && detected[type].confidence === 'high') {
336
+ return type;
337
+ }
338
+ }
339
+
340
+ // Fallback to first detected
341
+ return Object.keys(detected)[0] || 'unknown';
342
+ }
343
+ }