sdd-mcp-server 1.3.4 → 1.3.6

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.
@@ -34,3 +34,4 @@ export declare function generateTechDocument(analysis: ProjectAnalysis): string;
34
34
  * Generates dynamic structure.md content based on project analysis
35
35
  */
36
36
  export declare function generateStructureDocument(analysis: ProjectAnalysis): string;
37
+ export declare function extractDevCommands(analysis: ProjectAnalysis): string;
@@ -93,6 +93,209 @@ export async function analyzeProject(projectPath) {
93
93
  analysis.buildTool = 'Rollup';
94
94
  }
95
95
  }
96
+ // Check for Java/Maven/Gradle projects
97
+ const pomPath = path.join(projectPath, 'pom.xml');
98
+ const gradlePath = path.join(projectPath, 'build.gradle');
99
+ const gradleKtsPath = path.join(projectPath, 'build.gradle.kts');
100
+ if (fs.existsSync(pomPath) || fs.existsSync(gradlePath) || fs.existsSync(gradleKtsPath)) {
101
+ analysis.language = 'java';
102
+ if (fs.existsSync(pomPath)) {
103
+ analysis.packageManager = 'maven';
104
+ analysis.buildTool = 'Maven';
105
+ try {
106
+ const pom = fs.readFileSync(pomPath, 'utf8');
107
+ if (/spring-boot/i.test(pom) || /org\.springframework\.boot/i.test(pom)) {
108
+ analysis.framework = 'Spring Boot';
109
+ analysis.architecture = 'Spring Boot Application';
110
+ }
111
+ const moduleMatches = pom.match(/<module>[^<]+<\/module>/g) || [];
112
+ if (moduleMatches.length > 1) {
113
+ analysis.architecture = 'Microservices (Spring Boot)';
114
+ }
115
+ if (/junit|jupiter/i.test(pom)) {
116
+ analysis.testFramework = 'JUnit';
117
+ analysis.hasTests = true;
118
+ }
119
+ }
120
+ catch { }
121
+ }
122
+ else {
123
+ analysis.packageManager = 'gradle';
124
+ analysis.buildTool = 'Gradle';
125
+ try {
126
+ const gradle = fs.readFileSync(fs.existsSync(gradlePath) ? gradlePath : gradleKtsPath, 'utf8');
127
+ if (/org\.springframework\.boot|spring-boot/i.test(gradle)) {
128
+ analysis.framework = 'Spring Boot';
129
+ analysis.architecture = 'Spring Boot Application';
130
+ }
131
+ if (/subprojects\s*\{|include\s+\(/i.test(gradle)) {
132
+ analysis.architecture = 'Microservices (Spring Boot)';
133
+ }
134
+ if (/junit|jupiter|testImplementation\s+['"]org\.junit/i.test(gradle)) {
135
+ analysis.testFramework = 'JUnit';
136
+ analysis.hasTests = true;
137
+ }
138
+ }
139
+ catch { }
140
+ }
141
+ if (fs.existsSync(path.join(projectPath, 'src', 'test', 'java'))) {
142
+ analysis.hasTests = true;
143
+ if (!analysis.testFramework)
144
+ analysis.testFramework = 'JUnit';
145
+ }
146
+ }
147
+ // Detect Python projects
148
+ const pyproject = path.join(projectPath, 'pyproject.toml');
149
+ const requirements = path.join(projectPath, 'requirements.txt');
150
+ const pipfile = path.join(projectPath, 'Pipfile');
151
+ const setupPy = path.join(projectPath, 'setup.py');
152
+ if (fs.existsSync(pyproject) || fs.existsSync(requirements) || fs.existsSync(pipfile) || fs.existsSync(setupPy)) {
153
+ analysis.language = 'python';
154
+ analysis.packageManager = fs.existsSync(pyproject) ? 'poetry/pip' : (fs.existsSync(pipfile) ? 'pipenv' : 'pip');
155
+ analysis.buildTool = fs.existsSync(pyproject) ? 'Poetry' : 'Pip';
156
+ try {
157
+ const req = fs.existsSync(pyproject) ? fs.readFileSync(pyproject, 'utf8') : (fs.existsSync(requirements) ? fs.readFileSync(requirements, 'utf8') : '');
158
+ if (/django/i.test(req)) {
159
+ analysis.framework = 'Django';
160
+ analysis.architecture = 'Django Web Application';
161
+ }
162
+ else if (/fastapi/i.test(req)) {
163
+ analysis.framework = 'FastAPI';
164
+ analysis.architecture = 'REST API Server';
165
+ }
166
+ else if (/flask/i.test(req)) {
167
+ analysis.framework = 'Flask';
168
+ analysis.architecture = 'REST API Server';
169
+ }
170
+ if (/pytest/i.test(req)) {
171
+ analysis.testFramework = 'pytest';
172
+ analysis.hasTests = true;
173
+ }
174
+ }
175
+ catch { }
176
+ if (fs.existsSync(path.join(projectPath, 'tests')) || fs.existsSync(path.join(projectPath, 'test'))) {
177
+ analysis.hasTests = true;
178
+ if (!analysis.testFramework)
179
+ analysis.testFramework = 'pytest/unittest';
180
+ }
181
+ }
182
+ // Detect Go projects
183
+ const goMod = path.join(projectPath, 'go.mod');
184
+ if (fs.existsSync(goMod)) {
185
+ analysis.language = 'go';
186
+ analysis.packageManager = 'go';
187
+ analysis.buildTool = 'Go Toolchain';
188
+ try {
189
+ const gomod = fs.readFileSync(goMod, 'utf8');
190
+ if (/github.com\/(gin-gonic\/gin)/i.test(gomod)) {
191
+ analysis.framework = 'Gin';
192
+ analysis.architecture = 'REST API Server';
193
+ }
194
+ else if (/github.com\/(labstack\/echo)/i.test(gomod)) {
195
+ analysis.framework = 'Echo';
196
+ analysis.architecture = 'REST API Server';
197
+ }
198
+ else {
199
+ analysis.architecture = analysis.architecture === 'unknown' ? 'Go Application' : analysis.architecture;
200
+ }
201
+ }
202
+ catch { }
203
+ analysis.hasTests = analysis.hasTests || false;
204
+ analysis.testFramework = analysis.testFramework || 'go test';
205
+ }
206
+ // Detect Ruby projects
207
+ const gemfile = path.join(projectPath, 'Gemfile');
208
+ if (fs.existsSync(gemfile)) {
209
+ analysis.language = 'ruby';
210
+ analysis.packageManager = 'bundler';
211
+ analysis.buildTool = 'Rake';
212
+ try {
213
+ const gem = fs.readFileSync(gemfile, 'utf8');
214
+ if (/rails/i.test(gem)) {
215
+ analysis.framework = 'Rails';
216
+ analysis.architecture = 'Rails MVC Application';
217
+ }
218
+ else if (/sinatra/i.test(gem)) {
219
+ analysis.framework = 'Sinatra';
220
+ analysis.architecture = 'Web Application';
221
+ }
222
+ if (/rspec/i.test(gem)) {
223
+ analysis.testFramework = 'RSpec';
224
+ analysis.hasTests = true;
225
+ }
226
+ }
227
+ catch { }
228
+ }
229
+ // Detect PHP projects
230
+ const composerJsonPath = path.join(projectPath, 'composer.json');
231
+ if (fs.existsSync(composerJsonPath)) {
232
+ analysis.language = 'php';
233
+ analysis.packageManager = 'composer';
234
+ analysis.buildTool = 'Composer';
235
+ try {
236
+ const composer = JSON.parse(fs.readFileSync(composerJsonPath, 'utf8'));
237
+ const require = composer.require || {};
238
+ if (require['laravel/framework']) {
239
+ analysis.framework = 'Laravel';
240
+ analysis.architecture = 'Laravel MVC Application';
241
+ }
242
+ else if (require['symfony/symfony'] || require['symfony/framework-bundle']) {
243
+ analysis.framework = 'Symfony';
244
+ analysis.architecture = 'Symfony Application';
245
+ }
246
+ if (require['phpunit/phpunit']) {
247
+ analysis.testFramework = 'PHPUnit';
248
+ analysis.hasTests = true;
249
+ }
250
+ }
251
+ catch { }
252
+ }
253
+ // Detect Rust projects
254
+ const cargoToml = path.join(projectPath, 'Cargo.toml');
255
+ if (fs.existsSync(cargoToml)) {
256
+ analysis.language = 'rust';
257
+ analysis.packageManager = 'cargo';
258
+ analysis.buildTool = 'Cargo';
259
+ try {
260
+ const cargo = fs.readFileSync(cargoToml, 'utf8');
261
+ if (/actix-web/i.test(cargo)) {
262
+ analysis.framework = 'Actix Web';
263
+ analysis.architecture = 'REST API Server';
264
+ }
265
+ else if (/rocket =/i.test(cargo)) {
266
+ analysis.framework = 'Rocket';
267
+ analysis.architecture = 'Web Application';
268
+ }
269
+ else if (/axum/i.test(cargo)) {
270
+ analysis.framework = 'Axum';
271
+ analysis.architecture = 'REST API Server';
272
+ }
273
+ }
274
+ catch { }
275
+ analysis.testFramework = 'cargo test';
276
+ }
277
+ // Detect .NET projects
278
+ const entries = fs.readdirSync(projectPath);
279
+ const csproj = entries.find(f => f.endsWith('.csproj')) || null;
280
+ const sln = entries.find(f => f.endsWith('.sln')) || null;
281
+ if (csproj || sln) {
282
+ analysis.language = 'csharp';
283
+ analysis.packageManager = 'dotnet';
284
+ analysis.buildTool = '.NET SDK';
285
+ analysis.framework = 'ASP.NET Core';
286
+ analysis.architecture = analysis.architecture === 'unknown' ? 'ASP.NET Application' : analysis.architecture;
287
+ analysis.testFramework = analysis.testFramework || 'xUnit/NUnit/MSTest';
288
+ }
289
+ // Detect Scala projects
290
+ const sbtBuild = path.join(projectPath, 'build.sbt');
291
+ if (fs.existsSync(sbtBuild)) {
292
+ analysis.language = 'scala';
293
+ analysis.packageManager = 'sbt';
294
+ analysis.buildTool = 'SBT';
295
+ analysis.framework = analysis.framework || 'Play?/Akka?';
296
+ analysis.architecture = analysis.architecture === 'unknown' ? 'Scala Application' : analysis.architecture;
297
+ analysis.testFramework = analysis.testFramework || 'ScalaTest';
298
+ }
96
299
  // Check for yarn or pnpm
97
300
  if (fs.existsSync(path.join(projectPath, 'yarn.lock'))) {
98
301
  analysis.packageManager = 'yarn';
@@ -193,8 +396,8 @@ export function generateTechDocument(analysis) {
193
396
 
194
397
  ## Architecture
195
398
  **Type**: ${analysis.architecture}
196
- **Language**: ${analysis.language === 'typescript' ? 'TypeScript' : 'JavaScript'}
197
- **Module System**: ${analysis.type}
399
+ **Language**: ${analysis.language === 'typescript' ? 'TypeScript' : analysis.language === 'java' ? 'Java' : analysis.language === 'python' ? 'Python' : analysis.language === 'go' ? 'Go' : analysis.language === 'ruby' ? 'Ruby' : analysis.language === 'php' ? 'PHP' : analysis.language === 'rust' ? 'Rust' : analysis.language === 'csharp' ? 'C#' : analysis.language === 'scala' ? 'Scala' : 'JavaScript'}
400
+ ${(analysis.language === 'javascript' || analysis.language === 'typescript') ? `**Module System**: ${analysis.type} ` : ''}
198
401
  ${analysis.framework ? `**Framework**: ${analysis.framework}` : ''}
199
402
  ${analysis.buildTool ? `**Build Tool**: ${analysis.buildTool}` : ''}
200
403
 
@@ -204,9 +407,8 @@ ${architecture}
204
407
  ${techStack.map(t => `- **${t.name}**: ${t.description}`).join('\n')}
205
408
 
206
409
  ## Development Environment
207
- - **Node Version**: ${getNodeVersion()}
208
- - **Package Manager**: ${analysis.packageManager}
209
- - **Language**: ${analysis.language === 'typescript' ? 'TypeScript with type safety' : 'JavaScript'}
410
+ ${analysis.language === 'java' ? `- **JDK**: ${getJavaVersion(projectPathFromCwd())}\n` : analysis.language === 'go' ? `- **Go**: ${getGoVersion(projectPathFromCwd())}\n` : analysis.language === 'python' ? `- **Python**: ${getPythonVersion(projectPathFromCwd())}\n` : analysis.language === 'ruby' ? `- **Ruby**: ${getRubyVersion(projectPathFromCwd())}\n` : analysis.language === 'php' ? `- **PHP**: ${getPhpVersion(projectPathFromCwd())}\n` : analysis.language === 'rust' ? `- **Rust**: ${getRustToolchain(projectPathFromCwd())}\n` : analysis.language === 'csharp' ? `- **.NET SDK**: ${getDotnetTarget(projectPathFromCwd())}\n` : `- **Node Version**: ${getNodeVersion()}\n`}- **Package Manager/Build**: ${analysis.packageManager}
411
+ - **Language**: ${analysis.language === 'typescript' ? 'TypeScript with type safety' : analysis.language ? analysis.language[0].toUpperCase() + analysis.language.slice(1) : 'JavaScript'}
210
412
  ${analysis.testFramework ? `- **Testing**: ${analysis.testFramework}` : ''}
211
413
 
212
414
  ## Dependencies Analysis
@@ -395,10 +597,33 @@ function generateTechnicalAdvantages(analysis) {
395
597
  function buildTechStack(analysis) {
396
598
  const stack = [];
397
599
  // Core runtime
398
- stack.push({
399
- name: 'Node.js',
400
- description: 'JavaScript runtime for server-side execution'
401
- });
600
+ if (analysis.language === 'java') {
601
+ stack.push({ name: 'Java', description: 'JDK runtime for backend services' });
602
+ }
603
+ else if (analysis.language === 'python') {
604
+ stack.push({ name: 'Python', description: 'Python runtime for applications and APIs' });
605
+ }
606
+ else if (analysis.language === 'go') {
607
+ stack.push({ name: 'Go', description: 'Go toolchain for building static binaries' });
608
+ }
609
+ else if (analysis.language === 'ruby') {
610
+ stack.push({ name: 'Ruby', description: 'Ruby runtime for web applications' });
611
+ }
612
+ else if (analysis.language === 'php') {
613
+ stack.push({ name: 'PHP', description: 'PHP runtime for web applications' });
614
+ }
615
+ else if (analysis.language === 'rust') {
616
+ stack.push({ name: 'Rust', description: 'Rust toolchain for systems and APIs' });
617
+ }
618
+ else if (analysis.language === 'csharp') {
619
+ stack.push({ name: 'C#/.NET', description: '.NET runtime and SDK' });
620
+ }
621
+ else if (analysis.language === 'scala') {
622
+ stack.push({ name: 'Scala', description: 'JVM language for backend systems' });
623
+ }
624
+ else {
625
+ stack.push({ name: 'Node.js', description: 'JavaScript runtime for server-side execution' });
626
+ }
402
627
  // Language
403
628
  if (analysis.language === 'typescript') {
404
629
  stack.push({
@@ -406,6 +631,9 @@ function buildTechStack(analysis) {
406
631
  description: 'Typed superset of JavaScript for enhanced developer experience'
407
632
  });
408
633
  }
634
+ else if (analysis.language === 'java') {
635
+ stack.push({ name: 'Spring Boot', description: 'Opinionated framework for building production-ready services' });
636
+ }
409
637
  // Framework
410
638
  if (analysis.framework) {
411
639
  stack.push({
@@ -438,28 +666,145 @@ function buildTechStack(analysis) {
438
666
  }
439
667
  return stack;
440
668
  }
441
- function extractDevCommands(analysis) {
442
- if (Object.keys(analysis.scripts).length === 0) {
443
- return 'No npm scripts defined';
444
- }
669
+ export function extractDevCommands(analysis) {
445
670
  let commands = '```bash\n';
446
- // Common commands in order of importance
447
- const commandOrder = ['dev', 'start', 'build', 'test', 'lint', 'typecheck', 'coverage'];
448
- for (const cmd of commandOrder) {
449
- if (analysis.scripts[cmd]) {
450
- commands += `${analysis.packageManager} run ${cmd} # ${describeCommand(cmd, analysis.scripts[cmd])}\n`;
451
- }
452
- }
453
- // Add other commands
454
- for (const [cmd, script] of Object.entries(analysis.scripts)) {
455
- if (!commandOrder.includes(cmd)) {
456
- commands += `${analysis.packageManager} run ${cmd} # ${script.substring(0, 50)}${script.length > 50 ? '...' : ''}\n`;
457
- }
671
+ switch (analysis.language) {
672
+ case 'java':
673
+ if (analysis.packageManager === 'maven') {
674
+ commands += 'mvn clean install # Build project\n';
675
+ commands += 'mvn test # Run tests\n';
676
+ if (analysis.framework === 'Spring Boot')
677
+ commands += 'mvn spring-boot:run # Run application\n';
678
+ }
679
+ else {
680
+ commands += 'gradle build # Build project\n';
681
+ commands += 'gradle test # Run tests\n';
682
+ if (analysis.framework === 'Spring Boot')
683
+ commands += 'gradle bootRun # Run application\n';
684
+ }
685
+ commands += '```';
686
+ return commands;
687
+ case 'python':
688
+ commands += 'pip install -r requirements.txt # Install deps\n';
689
+ commands += (analysis.framework === 'Django') ? 'python manage.py runserver # Run server\n' :
690
+ (analysis.framework === 'FastAPI' || analysis.framework === 'Flask') ? 'uvicorn app:app --reload # Run dev server\n' : '';
691
+ commands += 'pytest # Run tests\n';
692
+ commands += '```';
693
+ return commands;
694
+ case 'go':
695
+ commands += 'go build ./... # Build\n';
696
+ commands += 'go test ./... # Tests\n';
697
+ commands += 'go run ./cmd/... # Run (example)\n';
698
+ commands += '```';
699
+ return commands;
700
+ case 'ruby':
701
+ commands += 'bundle install # Install deps\n';
702
+ commands += (analysis.framework === 'Rails') ? 'rails server # Run server\n' : '';
703
+ commands += (analysis.testFramework === 'RSpec') ? 'rspec # Run tests\n' : 'rake test # Run tests\n';
704
+ commands += '```';
705
+ return commands;
706
+ case 'php':
707
+ commands += 'composer install # Install deps\n';
708
+ commands += (analysis.framework === 'Laravel') ? 'php artisan serve # Run server\n' : '';
709
+ commands += 'vendor/bin/phpunit # Run tests\n';
710
+ commands += '```';
711
+ return commands;
712
+ case 'rust':
713
+ commands += 'cargo build # Build\n';
714
+ commands += 'cargo test # Tests\n';
715
+ commands += 'cargo run # Run\n';
716
+ commands += '```';
717
+ return commands;
718
+ case 'csharp':
719
+ commands += 'dotnet build # Build\n';
720
+ commands += 'dotnet test # Tests\n';
721
+ commands += 'dotnet run # Run\n';
722
+ commands += '```';
723
+ return commands;
724
+ case 'scala':
725
+ commands += 'sbt compile # Build\n';
726
+ commands += 'sbt test # Tests\n';
727
+ commands += 'sbt run # Run\n';
728
+ commands += '```';
729
+ return commands;
730
+ default:
731
+ if (Object.keys(analysis.scripts).length === 0) {
732
+ return 'No npm scripts defined';
733
+ }
734
+ const commandOrder = ['dev', 'start', 'build', 'test', 'lint', 'typecheck', 'coverage'];
735
+ for (const cmd of commandOrder) {
736
+ if (analysis.scripts[cmd]) {
737
+ commands += `${analysis.packageManager} run ${cmd} # ${describeCommand(cmd, analysis.scripts[cmd])}\n`;
738
+ }
739
+ }
740
+ for (const [cmd, script] of Object.entries(analysis.scripts)) {
741
+ if (!commandOrder.includes(cmd)) {
742
+ commands += `${analysis.packageManager} run ${cmd} # ${script.substring(0, 50)}${script.length > 50 ? '...' : ''}\n`;
743
+ }
744
+ }
745
+ commands += '```';
746
+ return commands;
458
747
  }
459
- commands += '```';
460
- return commands;
461
748
  }
462
749
  function describeArchitecture(analysis) {
750
+ if (analysis.architecture.includes('Spring Boot')) {
751
+ return `
752
+ ### Spring Boot Service Architecture
753
+ The project uses Spring Boot conventions:
754
+ - **Configuration**: application.yml/properties per service
755
+ - **Layers**: Controller → Service → Repository
756
+ - **Build**: ${analysis.buildTool || 'Maven/Gradle'} with ${analysis.testFramework || 'JUnit'} tests
757
+ ${analysis.architecture.includes('Microservices') ? '- **Topology**: Multiple modules/services (microservices)\n' : ''}`;
758
+ }
759
+ if (analysis.framework === 'Django') {
760
+ return `
761
+ ### Django MVC Architecture
762
+ - **Apps**: Modular apps with models, views, templates
763
+ - **ORM**: Django ORM for database access
764
+ - **Routing**: URLconf-based routing`;
765
+ }
766
+ if (analysis.framework === 'FastAPI' || analysis.framework === 'Flask') {
767
+ return `
768
+ ### Python REST API Architecture
769
+ - **Routing**: Decorator-based route handlers
770
+ - **Middleware**: Request processing chain
771
+ - **Data**: Pydantic/Marshmallow schemas`;
772
+ }
773
+ if (analysis.framework === 'Rails') {
774
+ return `
775
+ ### Rails MVC Architecture
776
+ - **Models**: ActiveRecord ORM
777
+ - **Controllers/Views**: Conventional structure with routing
778
+ - **Tasks**: Rake-based automation`;
779
+ }
780
+ if (analysis.framework === 'Laravel' || analysis.framework === 'Symfony') {
781
+ return `
782
+ ### PHP Web Architecture
783
+ - **MVC**: Controllers, models, views
784
+ - **Routing**: Framework router
785
+ - **Artisan/Console**: CLI tooling`;
786
+ }
787
+ if (analysis.language === 'go') {
788
+ return `
789
+ ### Go Service Architecture
790
+ - **Handlers**: HTTP handlers with router (Gin/Echo/net/http)
791
+ - **Services**: Business logic in packages
792
+ - **Build**: Single binary via go build`;
793
+ }
794
+ if (analysis.language === 'rust') {
795
+ return `
796
+ ### Rust Web Service Architecture
797
+ - **Framework**: ${analysis.framework || 'Actix/Axum/Rocket'}
798
+ - **Async**: Tokio runtime
799
+ - **Testing**: cargo test`;
800
+ }
801
+ if (analysis.language === 'csharp') {
802
+ return `
803
+ ### ASP.NET Core Architecture
804
+ - **Controllers**: MVC/Web API controllers
805
+ - **Dependency Injection**: Built-in DI
806
+ - **Configuration**: appsettings.json per environment`;
807
+ }
463
808
  if (analysis.architecture === 'Domain-Driven Design (DDD)') {
464
809
  return `
465
810
  ### Domain-Driven Design Architecture
@@ -585,7 +930,39 @@ function buildDirectoryTree(analysis) {
585
930
  if (analysis.hasDocker) {
586
931
  tree += `├── Dockerfile # Container configuration\n`;
587
932
  }
588
- tree += `├── package.json # Project configuration\n`;
933
+ if (analysis.language === 'java') {
934
+ tree += `├── pom.xml or build.gradle # Build configuration\n`;
935
+ }
936
+ else {
937
+ tree += `├── package.json # Project configuration\n`;
938
+ }
939
+ if (analysis.language === 'java') {
940
+ tree += `├── pom.xml or build.gradle # Build configuration\n`;
941
+ }
942
+ else if (analysis.language === 'python') {
943
+ tree += `├── pyproject.toml / requirements.txt # Python config\n`;
944
+ }
945
+ else if (analysis.language === 'go') {
946
+ tree += `├── go.mod # Go modules\n`;
947
+ }
948
+ else if (analysis.language === 'ruby') {
949
+ tree += `├── Gemfile # Ruby dependencies\n`;
950
+ }
951
+ else if (analysis.language === 'php') {
952
+ tree += `├── composer.json # PHP dependencies\n`;
953
+ }
954
+ else if (analysis.language === 'rust') {
955
+ tree += `├── Cargo.toml # Rust package config\n`;
956
+ }
957
+ else if (analysis.language === 'csharp') {
958
+ tree += `├── *.csproj # .NET project file\n`;
959
+ }
960
+ else if (analysis.language === 'scala') {
961
+ tree += `├── build.sbt # SBT build\n`;
962
+ }
963
+ else {
964
+ tree += `├── package.json # Project configuration\n`;
965
+ }
589
966
  if (analysis.language === 'typescript') {
590
967
  tree += `├── tsconfig.json # TypeScript configuration\n`;
591
968
  }
@@ -822,4 +1199,121 @@ function getNodeVersion() {
822
1199
  }
823
1200
  return '>= 18.0.0';
824
1201
  }
1202
+ function projectPathFromCwd() {
1203
+ try {
1204
+ return process.cwd();
1205
+ }
1206
+ catch {
1207
+ return '.';
1208
+ }
1209
+ }
1210
+ function getGoVersion(projectPath) {
1211
+ try {
1212
+ const gomod = path.join(projectPath, 'go.mod');
1213
+ if (fs.existsSync(gomod)) {
1214
+ const content = fs.readFileSync(gomod, 'utf8');
1215
+ const m = content.match(/^go\s+([0-9.]+)/m);
1216
+ if (m)
1217
+ return `Go ${m[1]}`;
1218
+ }
1219
+ }
1220
+ catch { }
1221
+ return 'Go (version unknown)';
1222
+ }
1223
+ function getPythonVersion(projectPath) {
1224
+ try {
1225
+ const pyproject = path.join(projectPath, 'pyproject.toml');
1226
+ if (fs.existsSync(pyproject)) {
1227
+ const txt = fs.readFileSync(pyproject, 'utf8');
1228
+ const m = txt.match(/python\s*[=><~!]*\s*['"]([^'"]+)['"]/i);
1229
+ if (m)
1230
+ return `Python ${m[1]}`;
1231
+ }
1232
+ const vfile = path.join(projectPath, '.python-version');
1233
+ if (fs.existsSync(vfile)) {
1234
+ return `Python ${fs.readFileSync(vfile, 'utf8').trim()}`;
1235
+ }
1236
+ }
1237
+ catch { }
1238
+ return 'Python (version unknown)';
1239
+ }
1240
+ function getRubyVersion(projectPath) {
1241
+ try {
1242
+ const rv = path.join(projectPath, '.ruby-version');
1243
+ if (fs.existsSync(rv))
1244
+ return `Ruby ${fs.readFileSync(rv, 'utf8').trim()}`;
1245
+ const gem = path.join(projectPath, 'Gemfile');
1246
+ if (fs.existsSync(gem)) {
1247
+ const txt = fs.readFileSync(gem, 'utf8');
1248
+ const m = txt.match(/ruby\s+['"]([^'"]+)['"]/i);
1249
+ if (m)
1250
+ return `Ruby ${m[1]}`;
1251
+ }
1252
+ }
1253
+ catch { }
1254
+ return 'Ruby (version unknown)';
1255
+ }
1256
+ function getPhpVersion(projectPath) {
1257
+ try {
1258
+ const composer = path.join(projectPath, 'composer.json');
1259
+ if (fs.existsSync(composer)) {
1260
+ const pkg = JSON.parse(fs.readFileSync(composer, 'utf8'));
1261
+ const req = pkg.require || {};
1262
+ if (req.php)
1263
+ return `PHP ${req.php}`;
1264
+ }
1265
+ }
1266
+ catch { }
1267
+ return 'PHP (version unknown)';
1268
+ }
1269
+ function getRustToolchain(projectPath) {
1270
+ try {
1271
+ const tool = path.join(projectPath, 'rust-toolchain');
1272
+ if (fs.existsSync(tool))
1273
+ return `Rust ${fs.readFileSync(tool, 'utf8').trim()}`;
1274
+ const cargo = path.join(projectPath, 'Cargo.toml');
1275
+ if (fs.existsSync(cargo)) {
1276
+ const txt = fs.readFileSync(cargo, 'utf8');
1277
+ const m = txt.match(/edition\s*=\s*"(\d{4})"/);
1278
+ if (m)
1279
+ return `Rust (edition ${m[1]})`;
1280
+ }
1281
+ }
1282
+ catch { }
1283
+ return 'Rust (toolchain unknown)';
1284
+ }
1285
+ function getDotnetTarget(projectPath) {
1286
+ try {
1287
+ const files = fs.readdirSync(projectPath).filter(f => f.endsWith('.csproj'));
1288
+ for (const f of files) {
1289
+ const txt = fs.readFileSync(path.join(projectPath, f), 'utf8');
1290
+ const m = txt.match(/<TargetFramework>([^<]+)<\/TargetFramework>/);
1291
+ if (m)
1292
+ return m[1];
1293
+ }
1294
+ }
1295
+ catch { }
1296
+ return '.NET (target unknown)';
1297
+ }
1298
+ function getJavaVersion(projectPath) {
1299
+ try {
1300
+ const pomPath = path.join(projectPath, 'pom.xml');
1301
+ if (fs.existsSync(pomPath)) {
1302
+ const pom = fs.readFileSync(pomPath, 'utf8');
1303
+ const m = pom.match(/<maven\.compiler\.source>([^<]+)<\/maven\.compiler\.source>/);
1304
+ const v = m?.[1] || (pom.match(/<java\.version>([^<]+)<\/java\.version>/)?.[1]);
1305
+ if (v)
1306
+ return `JDK ${v}`;
1307
+ }
1308
+ const gradlePath = fs.existsSync(path.join(projectPath, 'build.gradle.kts')) ? path.join(projectPath, 'build.gradle.kts') : path.join(projectPath, 'build.gradle');
1309
+ if (fs.existsSync(gradlePath)) {
1310
+ const gradle = fs.readFileSync(gradlePath, 'utf8');
1311
+ const m = gradle.match(/sourceCompatibility\s*=\s*['"]([^'"]+)['"]/i) || gradle.match(/sourceCompatibility\s+['"]([^'"]+)['"]/i);
1312
+ if (m?.[1])
1313
+ return `JDK ${m[1]}`;
1314
+ }
1315
+ }
1316
+ catch { }
1317
+ return 'JDK (version unknown)';
1318
+ }
825
1319
  //# sourceMappingURL=documentGenerator.js.map