@sebasgc0399/agents-md 0.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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +203 -0
  3. package/dist/cli.d.ts +6 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +128 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/detect/command-detector.d.ts +6 -0
  8. package/dist/detect/command-detector.d.ts.map +1 -0
  9. package/dist/detect/command-detector.js +62 -0
  10. package/dist/detect/command-detector.js.map +1 -0
  11. package/dist/detect/folder-detector.d.ts +6 -0
  12. package/dist/detect/folder-detector.d.ts.map +1 -0
  13. package/dist/detect/folder-detector.js +69 -0
  14. package/dist/detect/folder-detector.js.map +1 -0
  15. package/dist/detect/framework-detector.d.ts +10 -0
  16. package/dist/detect/framework-detector.d.ts.map +1 -0
  17. package/dist/detect/framework-detector.js +121 -0
  18. package/dist/detect/framework-detector.js.map +1 -0
  19. package/dist/detect/index.d.ts +11 -0
  20. package/dist/detect/index.d.ts.map +1 -0
  21. package/dist/detect/index.js +70 -0
  22. package/dist/detect/index.js.map +1 -0
  23. package/dist/detect/package-detector.d.ts +6 -0
  24. package/dist/detect/package-detector.d.ts.map +1 -0
  25. package/dist/detect/package-detector.js +34 -0
  26. package/dist/detect/package-detector.js.map +1 -0
  27. package/dist/detect/runtime-detector.d.ts +6 -0
  28. package/dist/detect/runtime-detector.d.ts.map +1 -0
  29. package/dist/detect/runtime-detector.js +35 -0
  30. package/dist/detect/runtime-detector.js.map +1 -0
  31. package/dist/index.d.ts +12 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +15 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/render/data-builder.d.ts +9 -0
  36. package/dist/render/data-builder.d.ts.map +1 -0
  37. package/dist/render/data-builder.js +138 -0
  38. package/dist/render/data-builder.js.map +1 -0
  39. package/dist/render/index.d.ts +12 -0
  40. package/dist/render/index.d.ts.map +1 -0
  41. package/dist/render/index.js +29 -0
  42. package/dist/render/index.js.map +1 -0
  43. package/dist/render/mustache-renderer.d.ts +13 -0
  44. package/dist/render/mustache-renderer.d.ts.map +1 -0
  45. package/dist/render/mustache-renderer.js +51 -0
  46. package/dist/render/mustache-renderer.js.map +1 -0
  47. package/dist/render/validators.d.ts +9 -0
  48. package/dist/render/validators.d.ts.map +1 -0
  49. package/dist/render/validators.js +107 -0
  50. package/dist/render/validators.js.map +1 -0
  51. package/dist/templates/base.mustache +296 -0
  52. package/dist/templates/firebase.mustache +236 -0
  53. package/dist/templates/monorepo.mustache +253 -0
  54. package/dist/templates/react.mustache +231 -0
  55. package/dist/types.d.ts +112 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +5 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/utils/fs-utils.d.ts +20 -0
  60. package/dist/utils/fs-utils.d.ts.map +1 -0
  61. package/dist/utils/fs-utils.js +121 -0
  62. package/dist/utils/fs-utils.js.map +1 -0
  63. package/dist/utils/logger.d.ts +14 -0
  64. package/dist/utils/logger.d.ts.map +1 -0
  65. package/dist/utils/logger.js +32 -0
  66. package/dist/utils/logger.js.map +1 -0
  67. package/dist/utils/token-counter.d.ts +18 -0
  68. package/dist/utils/token-counter.d.ts.map +1 -0
  69. package/dist/utils/token-counter.js +45 -0
  70. package/dist/utils/token-counter.js.map +1 -0
  71. package/package.json +75 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sebasgc0399
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # agents-md
2
+
3
+ CLI para generar archivos `AGENTS.md` automaticamente para proyectos Node.js.
4
+
5
+ ## Tabla de contenido
6
+
7
+ - [¿Que es AGENTS.md?](#que-es-agentsmd)
8
+ - [Quickstart](#quickstart)
9
+ - [Instalacion](#instalacion)
10
+ - [Uso](#uso)
11
+ - [Perfiles de salida](#perfiles-de-salida)
12
+ - [Proyectos soportados](#proyectos-soportados)
13
+ - [Releases y novedades](#releases-y-novedades)
14
+ - [Desarrollo](#desarrollo)
15
+ - [Contribuciones](#contribuciones)
16
+ - [Soporte](#soporte)
17
+ - [Licencia](#licencia)
18
+
19
+ ## ¿Que es AGENTS.md?
20
+
21
+ `AGENTS.md` es un "README para AI agents" que reduce alucinaciones al proporcionar:
22
+
23
+ - Comandos canonicos (setup, test, build, lint)
24
+ - Convenciones de codigo y estilo
25
+ - Guias de testing
26
+ - Reglas de seguridad
27
+ - Definition of Done
28
+
29
+ ## Quickstart
30
+
31
+ Nombres importantes para evitar confusion:
32
+
33
+ - Package en npm: `@sebasgc0399/agents-md`
34
+ - Comando instalado: `agents-md`
35
+ - No usar `npx agents-md ...` sin scope
36
+
37
+ Uso sin instalacion (recomendado):
38
+
39
+ ```bash
40
+ npx -p @sebasgc0399/agents-md agents-md init
41
+ npx -p @sebasgc0399/agents-md agents-md init --dry-run
42
+ npx -p @sebasgc0399/agents-md agents-md init --profile compact
43
+ npx -p @sebasgc0399/agents-md agents-md init --profile standard
44
+ npx -p @sebasgc0399/agents-md agents-md init --profile full
45
+ ```
46
+
47
+ ## Instalacion
48
+
49
+ Opcion 1: sin instalacion (npx)
50
+
51
+ ```bash
52
+ npx -p @sebasgc0399/agents-md agents-md init
53
+ ```
54
+
55
+ Opcion 2: instalacion global
56
+
57
+ ```bash
58
+ npm install -g @sebasgc0399/agents-md
59
+ agents-md init
60
+ ```
61
+
62
+ Requisitos:
63
+
64
+ - Node.js >= 18
65
+ - `package.json` en la raiz del proyecto
66
+
67
+ ## Uso
68
+
69
+ ```bash
70
+ # Generar AGENTS.md en el directorio actual
71
+ agents-md init
72
+
73
+ # Preview sin escribir archivo
74
+ agents-md init --dry-run
75
+
76
+ # Elegir perfil de salida (default: compact)
77
+ agents-md init --profile compact
78
+ agents-md init --profile standard
79
+ agents-md init --profile full
80
+
81
+ # Sobrescribir archivo existente
82
+ agents-md init --force
83
+
84
+ # Modo verbose (mostrar detalles de deteccion)
85
+ agents-md init --verbose
86
+
87
+ # Especificar ruta de salida
88
+ agents-md init --out ./docs/AGENTS.md
89
+ ```
90
+
91
+ Nota: en la version `v0.2.x`, las flags `-y/--yes` y `-i/--interactive` estan reservadas y actualmente no cambian el comportamiento del comando.
92
+
93
+ ## Perfiles de salida
94
+
95
+ - `compact` (default): salida corta y directa (hasta ~110 lineas)
96
+ - `standard`: salida mas completa para equipos (~150-230 lineas)
97
+ - `full`: salida mas detallada para handoff y CI (~220-360 lineas)
98
+
99
+ ## Limites de salida (soft limits)
100
+
101
+ - `compact`: 50-110 lines, max ~900 tokens
102
+ - `standard`: 150-230 lines, max ~1600 tokens
103
+ - `full`: 220-360 lines, max ~2400 tokens
104
+
105
+ Exceder estos rangos genera warnings y no bloquea la generacion. La generacion solo se bloquea cuando hay errors de validacion.
106
+
107
+ ## Proyectos soportados
108
+
109
+ - React (Vite, CRA, Next.js)
110
+ - Vue (Vite, Nuxt)
111
+ - Firebase Functions
112
+ - Proyectos Node.js genericos
113
+ - Monorepos (Turborepo/Nx)
114
+
115
+ ## Como funciona
116
+
117
+ 1. Lee `package.json`.
118
+ 2. Detecta framework y estructura de carpetas.
119
+ 3. Extrae comandos canonicos desde scripts.
120
+ 4. Genera un `AGENTS.md` limpio y conciso segun el perfil seleccionado.
121
+
122
+ ## Releases y novedades
123
+
124
+ Version actual: `v0.2.0`
125
+
126
+ Cambios en esta version:
127
+
128
+ - Benchmark de calidad P0/P1/P2 integrado (`benchmark:lite`, `benchmark:p1`, `benchmark:p2`)
129
+ - Gates de calidad en CI para benchmark lite + baseline semantico P1
130
+ - Workflow semanal/manual de tendencias (`benchmark-trends`) con reporte JSON/Markdown
131
+
132
+ Actualizar a la ultima version global:
133
+
134
+ ```bash
135
+ npm update -g @sebasgc0399/agents-md
136
+ ```
137
+
138
+ [Ver historial completo de versiones](https://github.com/sebasgc0399/agents-md/releases)
139
+
140
+ ## Desarrollo
141
+
142
+ ```bash
143
+ # Instalar dependencias
144
+ npm install
145
+
146
+ # Build
147
+ npm run build
148
+
149
+ # Modo desarrollo (watch)
150
+ npm run dev
151
+
152
+ # Tests
153
+ npm test
154
+
155
+ # Coverage
156
+ npm run test:coverage
157
+
158
+ # Lint (verificar tipos)
159
+ npm run lint
160
+
161
+ # Benchmark lite (P0 quality gate)
162
+ npm run benchmark:lite
163
+
164
+ # Benchmark P1 (semantic baseline + regression budget)
165
+ npm run benchmark:p1
166
+
167
+ # Regenerar baseline P1 (solo cuando el cambio es intencional)
168
+ npm run benchmark:p1:update
169
+
170
+ # Benchmark P2 (weekly trends report, non-blocking)
171
+ npm run benchmark:p2
172
+
173
+ # Smoke del CLI compilado
174
+ node dist/cli.js init --dry-run
175
+ ```
176
+
177
+ ## Contribuciones
178
+
179
+ Gracias por ayudar a mejorar `agents-md`.
180
+
181
+ Para mantener el proyecto de alta calidad:
182
+
183
+ - Abre un issue primero para cambios no triviales.
184
+ - Incluye problema, solucion propuesta y trade-off tecnico.
185
+ - Si usaste IA, revisa manualmente el resultado antes de abrir PR.
186
+ - Manten los PRs pequenos y enfocados.
187
+ - Agrega o actualiza tests cuando cambie el comportamiento.
188
+ - Ejecuta `npm test` antes de enviar.
189
+
190
+ Comandos de desarrollo y validacion: ver seccion `## Desarrollo`.
191
+
192
+ ## Soporte
193
+
194
+ Si esta herramienta te resulta util, puedes apoyar el proyecto de estas formas:
195
+
196
+ - Dar estrella al repo
197
+ - Compartirlo con tu equipo
198
+ - Reportar bugs con pasos reproducibles
199
+ - Proponer mejoras via issues o PRs acotados
200
+
201
+ ## Licencia
202
+
203
+ MIT © 2026 sebasgc0399
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for agents-md
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;GAEG"}
package/dist/cli.js ADDED
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for agents-md
4
+ */
5
+ import { Command } from 'commander';
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { detectProject } from './detect/index.js';
9
+ import { renderAgentsMd } from './render/index.js';
10
+ import { Logger } from './utils/logger.js';
11
+ import { directoryExists, isPathSafe } from './utils/fs-utils.js';
12
+ const program = new Command();
13
+ const VALID_PROFILES = ['compact', 'standard', 'full'];
14
+ program
15
+ .name('agents-md')
16
+ .description('Generate AGENTS.md files for AI coding agents')
17
+ .version('0.1.0');
18
+ program
19
+ .command('init')
20
+ .description('Generate AGENTS.md file')
21
+ .argument('[path]', 'Project directory', process.cwd())
22
+ .option('--out <path>', 'Output file path', './AGENTS.md')
23
+ .option('--force', 'Overwrite existing file', false)
24
+ .option('--dry-run', 'Preview without writing', false)
25
+ .option('-y, --yes', 'Skip confirmations', false)
26
+ .option('-i, --interactive', 'Interactive mode', false)
27
+ .option('--profile <profile>', 'Output profile: compact|standard|full', 'compact')
28
+ .option('--verbose', 'Verbose output', false)
29
+ .action(async (projectPath, options) => {
30
+ const logger = new Logger(options.verbose);
31
+ try {
32
+ const profile = String(options.profile || 'compact');
33
+ if (!VALID_PROFILES.includes(profile)) {
34
+ logger.error(`Invalid profile "${profile}". Valid values: ${VALID_PROFILES.join(', ')}`);
35
+ process.exit(1);
36
+ }
37
+ // Validate project path
38
+ if (!directoryExists(projectPath)) {
39
+ logger.error(`Directory not found: ${projectPath}`);
40
+ process.exit(1);
41
+ }
42
+ // Resolve output path
43
+ const outputPath = path.resolve(projectPath, options.out);
44
+ // Validate output path is safe (prevent path traversal)
45
+ if (!isPathSafe(projectPath, outputPath)) {
46
+ logger.error('Output path must be within the project directory');
47
+ process.exit(1);
48
+ }
49
+ // Check if output file exists
50
+ if (fs.existsSync(outputPath) && !options.force && !options.dryRun) {
51
+ logger.error(`${options.out} already exists. Use --force to overwrite.`);
52
+ process.exit(1);
53
+ }
54
+ // Run detection
55
+ logger.verbose('Reading package.json...');
56
+ const detection = await detectProject(projectPath);
57
+ logger.verbose(`Found: ${detection.packageInfo?.name} v${detection.packageInfo?.version || '?'}`);
58
+ logger.verbose('Detecting framework...');
59
+ logger.verbose(`Framework: ${detection.framework.type} (confidence: ${detection.framework.confidence})`);
60
+ if (options.verbose && detection.framework.indicators.length > 0) {
61
+ detection.framework.indicators.forEach(indicator => {
62
+ logger.verbose(` - ${indicator}`);
63
+ });
64
+ }
65
+ logger.verbose('Extracting commands...');
66
+ if (options.verbose) {
67
+ logger.verbose(` - install: ${detection.commands.install}`);
68
+ if (detection.commands.dev)
69
+ logger.verbose(` - dev: ${detection.commands.dev}`);
70
+ if (detection.commands.build)
71
+ logger.verbose(` - build: ${detection.commands.build}`);
72
+ if (detection.commands.test)
73
+ logger.verbose(` - test: ${detection.commands.test}`);
74
+ if (detection.commands.lint)
75
+ logger.verbose(` - lint: ${detection.commands.lint}`);
76
+ }
77
+ // Render AGENTS.md
78
+ logger.verbose('Rendering template...');
79
+ logger.verbose(`Profile: ${profile}`);
80
+ const result = renderAgentsMd(detection, profile);
81
+ logger.verbose('Validating output...');
82
+ logger.verbose(` - Lines: ${result.validation.lineCount}`);
83
+ logger.verbose(` - Tokens: ~${result.validation.estimatedTokens}`);
84
+ // Show validation warnings
85
+ if (result.validation.warnings.length > 0) {
86
+ result.validation.warnings.forEach(warning => {
87
+ logger.warning(warning);
88
+ });
89
+ }
90
+ // Show validation errors (should stop generation)
91
+ if (result.validation.errors.length > 0) {
92
+ result.validation.errors.forEach(error => {
93
+ logger.error(error);
94
+ });
95
+ logger.error('Generation failed due to validation errors');
96
+ process.exit(1);
97
+ }
98
+ // Dry run or write
99
+ if (options.dryRun) {
100
+ logger.info('--- Preview (--dry-run mode) ---');
101
+ console.log(result.content);
102
+ logger.info('--- End of preview ---');
103
+ }
104
+ else {
105
+ if (fs.existsSync(outputPath) && options.force) {
106
+ logger.warning(`${options.out} already exists. Overwriting...`);
107
+ }
108
+ fs.writeFileSync(outputPath, result.content, 'utf-8');
109
+ logger.success(`Generated ${options.out}`);
110
+ if (!options.verbose) {
111
+ logger.info(`Detected: ${detection.framework.type !== 'unknown' ? detection.framework.type : 'Node.js project'}`);
112
+ logger.info(`${result.validation.lineCount} lines, ~${result.validation.estimatedTokens} tokens`);
113
+ }
114
+ }
115
+ }
116
+ catch (error) {
117
+ if (error instanceof Error) {
118
+ logger.error(error.message);
119
+ }
120
+ else {
121
+ logger.error('An unknown error occurred');
122
+ }
123
+ process.exit(1);
124
+ }
125
+ });
126
+ // Parse CLI arguments
127
+ program.parse();
128
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Canonical command extraction from package.json scripts
3
+ */
4
+ import { CanonicalCommands, PackageInfo, RuntimeInfo } from '../types.js';
5
+ export declare function detectCommands(packageInfo: PackageInfo, runtime: RuntimeInfo): CanonicalCommands;
6
+ //# sourceMappingURL=command-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-detector.d.ts","sourceRoot":"","sources":["../../src/detect/command-detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1E,wBAAgB,cAAc,CAC5B,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,WAAW,GACnB,iBAAiB,CA8BnB"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Canonical command extraction from package.json scripts
3
+ */
4
+ export function detectCommands(packageInfo, runtime) {
5
+ const scripts = packageInfo.scripts || {};
6
+ const pm = runtime.packageManager;
7
+ // Install command (inferred from package manager)
8
+ const install = pm === 'npm' ? 'npm install' : pm === 'yarn' ? 'yarn' : `${pm} install`;
9
+ // Dev command (priority: dev > start > serve)
10
+ const dev = findScript(scripts, ['dev', 'start', 'serve'], pm);
11
+ // Build command (priority: build > compile)
12
+ const build = findScript(scripts, ['build', 'compile'], pm);
13
+ // Test command (priority: test > test:unit > vitest > jest)
14
+ const test = findScript(scripts, ['test', 'test:unit', 'vitest', 'jest'], pm);
15
+ // Lint command (priority: lint > eslint)
16
+ const lint = findScript(scripts, ['lint', 'eslint'], pm);
17
+ // Format command (priority: format > prettier)
18
+ const format = findScript(scripts, ['format', 'prettier'], pm);
19
+ return {
20
+ install,
21
+ dev,
22
+ build,
23
+ test,
24
+ lint,
25
+ format,
26
+ };
27
+ }
28
+ /**
29
+ * Find first matching script from priority list
30
+ */
31
+ function findScript(scripts, priorities, packageManager) {
32
+ for (const scriptName of priorities) {
33
+ if (scripts[scriptName]) {
34
+ return buildCommand(scriptName, packageManager);
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+ /**
40
+ * Build command string with package manager
41
+ */
42
+ function buildCommand(scriptName, packageManager) {
43
+ // Special case: "start" and "test" don't need "run" in npm
44
+ if ((scriptName === 'start' || scriptName === 'test') && packageManager === 'npm') {
45
+ return `npm ${scriptName}`;
46
+ }
47
+ // Yarn also doesn't need "run" for built-in scripts
48
+ if ((scriptName === 'start' || scriptName === 'test') && packageManager === 'yarn') {
49
+ return `yarn ${scriptName}`;
50
+ }
51
+ // All other cases
52
+ if (packageManager === 'npm') {
53
+ return `npm run ${scriptName}`;
54
+ }
55
+ else if (packageManager === 'yarn') {
56
+ return `yarn ${scriptName}`;
57
+ }
58
+ else {
59
+ return `${packageManager} run ${scriptName}`;
60
+ }
61
+ }
62
+ //# sourceMappingURL=command-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-detector.js","sourceRoot":"","sources":["../../src/detect/command-detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,cAAc,CAC5B,WAAwB,EACxB,OAAoB;IAEpB,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC;IAC1C,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAElC,kDAAkD;IAClD,MAAM,OAAO,GAAG,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC;IAExF,8CAA8C;IAC9C,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAE/D,4CAA4C;IAC5C,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;IAE5D,4DAA4D;IAC5D,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IAE9E,yCAAyC;IACzC,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEzD,+CAA+C;IAC/C,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;IAE/D,OAAO;QACL,OAAO;QACP,GAAG;QACH,KAAK;QACL,IAAI;QACJ,IAAI;QACJ,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CACjB,OAA+B,EAC/B,UAAoB,EACpB,cAAsB;IAEtB,KAAK,MAAM,UAAU,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACxB,OAAO,YAAY,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,UAAkB,EAAE,cAAsB;IAC9D,2DAA2D;IAC3D,IAAI,CAAC,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,MAAM,CAAC,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAClF,OAAO,OAAO,UAAU,EAAE,CAAC;IAC7B,CAAC;IAED,oDAAoD;IACpD,IAAI,CAAC,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,MAAM,CAAC,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QACnF,OAAO,QAAQ,UAAU,EAAE,CAAC;IAC9B,CAAC;IAED,kBAAkB;IAClB,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO,WAAW,UAAU,EAAE,CAAC;IACjC,CAAC;SAAM,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QACrC,OAAO,QAAQ,UAAU,EAAE,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,cAAc,QAAQ,UAAU,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Folder structure detection
3
+ */
4
+ import { FolderStructure, PackageInfo } from '../types.js';
5
+ export declare function detectFolderStructure(rootPath: string, packageInfo?: PackageInfo | null): FolderStructure;
6
+ //# sourceMappingURL=folder-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-detector.d.ts","sourceRoot":"","sources":["../../src/detect/folder-detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG3D,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,GAC/B,eAAe,CAsDjB"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Folder structure detection
3
+ */
4
+ import path from 'path';
5
+ import { directoryExists, fileExists } from '../utils/fs-utils.js';
6
+ export function detectFolderStructure(rootPath, packageInfo) {
7
+ const checkDir = (dir) => directoryExists(path.join(rootPath, dir));
8
+ const checkFile = (fileName) => fileExists(path.join(rootPath, fileName));
9
+ const hasSrc = checkDir('src');
10
+ const hasFunctions = checkDir('functions');
11
+ const hasApps = checkDir('apps');
12
+ const hasPackages = checkDir('packages');
13
+ const hasPublic = checkDir('public');
14
+ const hasDocs = checkDir('docs');
15
+ // Check for test directories (multiple common names)
16
+ const hasTests = checkDir('tests') || checkDir('test') || checkDir('__tests__');
17
+ const hasWorkspaces = hasWorkspaceDefinition(packageInfo?.workspaces);
18
+ const hasMonorepoTool = Boolean(packageInfo?.devDependencies?.turbo) ||
19
+ Boolean(packageInfo?.devDependencies?.nx);
20
+ const hasMonorepoToolWithFolderHints = hasMonorepoTool && (hasApps || hasPackages);
21
+ const hasMonorepoMarkers = checkFile('pnpm-workspace.yaml') ||
22
+ checkFile('turbo.json') ||
23
+ checkFile('nx.json') ||
24
+ checkFile('lerna.json');
25
+ // Monorepo signals: folder structure, workspaces, tools, or marker files.
26
+ const isMonorepo = (hasApps && hasPackages) ||
27
+ hasWorkspaces ||
28
+ hasMonorepoToolWithFolderHints ||
29
+ hasMonorepoMarkers;
30
+ const folders = [];
31
+ if (hasSrc)
32
+ folders.push('src');
33
+ if (hasFunctions)
34
+ folders.push('functions');
35
+ if (hasTests)
36
+ folders.push('tests');
37
+ if (hasApps)
38
+ folders.push('apps');
39
+ if (hasPackages)
40
+ folders.push('packages');
41
+ if (hasPublic)
42
+ folders.push('public');
43
+ if (hasDocs)
44
+ folders.push('docs');
45
+ return {
46
+ hasSrc,
47
+ hasFunctions,
48
+ hasTests,
49
+ hasApps,
50
+ hasPackages,
51
+ hasPublic,
52
+ hasDocs,
53
+ isMonorepo,
54
+ folders,
55
+ };
56
+ }
57
+ function hasWorkspaceDefinition(workspaces) {
58
+ if (!workspaces) {
59
+ return false;
60
+ }
61
+ if (Array.isArray(workspaces)) {
62
+ return workspaces.length > 0;
63
+ }
64
+ if (Array.isArray(workspaces.packages)) {
65
+ return workspaces.packages.length > 0;
66
+ }
67
+ return false;
68
+ }
69
+ //# sourceMappingURL=folder-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-detector.js","sourceRoot":"","sources":["../../src/detect/folder-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Framework detection based on dependencies
3
+ */
4
+ import { FrameworkInfo, PackageInfo } from '../types.js';
5
+ export declare function detectFramework(packageInfo: PackageInfo): FrameworkInfo;
6
+ /**
7
+ * Detect build tools
8
+ */
9
+ export declare function detectBuildTools(packageInfo: PackageInfo): string[];
10
+ //# sourceMappingURL=framework-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-detector.d.ts","sourceRoot":"","sources":["../../src/detect/framework-detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAExE,wBAAgB,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,CA2GvE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,EAAE,CAanE"}