openprompt-lang 0.4.0 → 0.5.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.
- package/README.md +70 -0
- package/bin/cli.js +222 -144
- package/bin/create.js +56 -56
- package/bin/lint.js +13 -13
- package/docs/AI-MANUAL.md +578 -0
- package/docs/ROADMAP-DESARROLLO.md +274 -0
- package/package.json +3 -2
- package/scaffolds/tailwind.config.js +3 -3
- package/src/ai/learn-prompt.js +90 -0
- package/src/ai/prompt-builder.js +75 -77
- package/src/ai/providers.js +74 -74
- package/src/annotations/registry.js +11 -11
- package/src/commands/ai-gen.js +58 -58
- package/src/commands/component.js +152 -94
- package/src/commands/context.js +320 -197
- package/src/commands/db-rules.js +117 -0
- package/src/commands/extract.js +377 -57
- package/src/commands/figma.js +37 -37
- package/src/commands/init.js +658 -245
- package/src/commands/integrate.js +238 -100
- package/src/commands/lang.js +26 -26
- package/src/commands/learn.js +182 -0
- package/src/commands/qa-gen.js +27 -27
- package/src/commands/scaffold.js +23 -23
- package/src/commands/suggest.js +22 -10
- package/src/commands/teach.js +37 -38
- package/src/commands/validate.js +93 -53
- package/src/commands/wizard.js +187 -185
- package/src/generators/figma-prompt.js +16 -16
- package/src/knowledge/db-rules.json +162 -0
- package/src/language-service/plugin.cjs +45 -45
- package/src/mcp-server.js +329 -224
- package/src/templates/semantic-index.json +84 -0
- package/src/ts-transformer/index.cjs +40 -40
- package/src/utils/ai.js +49 -42
- package/src/utils/annotations.js +148 -148
- package/src/utils/config.js +36 -33
- package/src/utils/doc-ingest.js +101 -0
- package/src/utils/error-learner.js +41 -39
- package/src/utils/file-utils.js +26 -26
- package/src/utils/language-loader.js +29 -29
- package/src/utils/module-generator.js +235 -0
- package/src/utils/semantic-index.js +93 -0
- package/src/utils/template-utils.js +11 -12
- package/src/vite-plugin/index.js +11 -11
package/README.md
CHANGED
|
@@ -11,6 +11,14 @@ openPrompt-Lang --version
|
|
|
11
11
|
## Índice
|
|
12
12
|
|
|
13
13
|
- [Instalación](#instalación)
|
|
14
|
+
- [Nuevas Capacidades (v0.4.0)](#nuevas-capacidades-v040)
|
|
15
|
+
- [Aprender de proyectos reales](#aprender-de-proyectos-reales---extract---learn)
|
|
16
|
+
- [Aprender de documentación](#aprender-de-documentación---learn)
|
|
17
|
+
- [Transferencia de contexto](#transferencia-de-contexto---integrate---fromto)
|
|
18
|
+
- [Contexto por dominio](#contexto-por-dominio---context---domain)
|
|
19
|
+
- [Presets pre-ensamblados](#presets-pre-ensamblados---init---preset)
|
|
20
|
+
- [Reglas de base de datos](#reglas-de-base-de-datos---db-rules)
|
|
21
|
+
- [Filtros de componentes](#filtros-de-componentes---component-list---styletechvalidated)
|
|
14
22
|
- [Anotaciones PromptLang (directorio completo)](#anotaciones-promptlang-directorio-completo)
|
|
15
23
|
- [Tags de definición](#tags-de-definición)
|
|
16
24
|
- [Tags de contrato](#tags-de-contrato)
|
|
@@ -406,6 +414,68 @@ export function Button(props: ButtonProps) { ... }
|
|
|
406
414
|
|
|
407
415
|
---
|
|
408
416
|
|
|
417
|
+
## Nuevas Capacidades (v0.4.0)
|
|
418
|
+
|
|
419
|
+
### Aprender de proyectos reales — `extract --learn`
|
|
420
|
+
Analiza un proyecto y extrae sus patrones: convención de nombres, arquitectura, estilo UI, hooks, anotaciones. Genera un perfil reutilizable.
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
openPrompt-Lang extract ./proyecto-pulido --learn
|
|
424
|
+
openPrompt-Lang init --name nuevo --learn-from ./aprendizaje-perfil.json
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Aprender de documentación — `learn`
|
|
428
|
+
Usa IA para transformar documentación local en módulos de lenguaje funcionales con templates, tests y prácticas.
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
openPrompt-Lang learn --docs ./docs-rust/ --name rust
|
|
432
|
+
openPrompt-Lang learn --docs ./docs-react/ --from ./proyecto-real/ --name react
|
|
433
|
+
openPrompt-Lang learn --docs ./docs/ --name django --integrate
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Los módulos se guardan en `~/.openprompt/knowledge/langs/<id>/` (accesibles para cualquier proyecto).
|
|
437
|
+
|
|
438
|
+
### Transferencia de contexto — `integrate --from/--to`
|
|
439
|
+
Copia el contexto de negocio entre proyectos: stack, convenciones, @kind/@contract detectados, arquitectura.
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
openPrompt-Lang integrate --from ./web-react --to ./app-mobile
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Contexto por dominio — `context --domain`
|
|
446
|
+
Filtra el contexto del proyecto por dominio de negocio: ecommerce, saas, mobile, api, admin, blog.
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
openPrompt-Lang context --domain ecommerce
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Presets pre-ensamblados — `init --preset`
|
|
453
|
+
Stacks completos con servicios incluidos: Supabase, Stripe, Ionic, Tauri, Firebase.
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
openPrompt-Lang init --preset react-supabase-stripe --name tienda
|
|
457
|
+
openPrompt-Lang init --list-presets
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Reglas de base de datos — `db-rules`
|
|
461
|
+
Knowledge base de buenas prácticas, anti-patrones y reglas para SQL, Supabase, Postgres, Docker.
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
openPrompt-Lang db-rules --id db-001
|
|
465
|
+
openPrompt-Lang db-rules --tag performance
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Filtros de componentes — `component list --style/--tech/--validated`
|
|
469
|
+
```bash
|
|
470
|
+
openPrompt-Lang component list --style shadcn
|
|
471
|
+
openPrompt-Lang component list --tech vue
|
|
472
|
+
openPrompt-Lang component list --validated
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
> 📖 **Manual completo para IA:** `docs/AI-MANUAL.md` — todos los comandos, workflows ordenados y configuración.
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
409
479
|
## Comandos CLI
|
|
410
480
|
|
|
411
481
|
| Comando | Descripción |
|
package/bin/cli.js
CHANGED
|
@@ -1,301 +1,379 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { Command } from
|
|
4
|
-
import chalk from
|
|
5
|
-
import { readFileSync, existsSync } from
|
|
6
|
-
import { join, dirname } from
|
|
7
|
-
import { fileURLToPath } from
|
|
3
|
+
import { Command } from 'commander'
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
import { readFileSync, existsSync } from 'fs'
|
|
6
|
+
import { join, dirname } from 'path'
|
|
7
|
+
import { fileURLToPath } from 'url'
|
|
8
8
|
|
|
9
9
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
10
|
-
const pkg = JSON.parse(readFileSync(join(__dirname,
|
|
10
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'))
|
|
11
11
|
|
|
12
12
|
const program = new Command()
|
|
13
13
|
|
|
14
14
|
program
|
|
15
|
-
.name(
|
|
16
|
-
.description(chalk.cyan(
|
|
15
|
+
.name('openPrompt-Lang')
|
|
16
|
+
.description(chalk.cyan('Framework de anotaciones para desarrollo asistido por IA'))
|
|
17
17
|
.version(pkg.version)
|
|
18
18
|
|
|
19
19
|
program
|
|
20
|
-
.command(
|
|
21
|
-
.description(
|
|
22
|
-
.option(
|
|
23
|
-
.option(
|
|
24
|
-
.option(
|
|
20
|
+
.command('init')
|
|
21
|
+
.description('Inicializar proyecto con estructura PromptLang')
|
|
22
|
+
.option('--name <name>', 'Nombre del proyecto')
|
|
23
|
+
.option('--describe <text>', 'Descripción del proyecto para sugerencia IA')
|
|
24
|
+
.option('--existing', 'Configurar en proyecto existente (solo archivos de configuración)')
|
|
25
|
+
.option('--dry-run', 'Previsualizar sin crear archivos')
|
|
26
|
+
.option('--stack <items>', 'Stack base (separado por comas, ej: react,typescript,vite,tailwind)')
|
|
27
|
+
.option('--preset <name>', 'Usar preset pre-ensamblado (ej: react-supabase-stripe, vue-firebase-netlify)')
|
|
28
|
+
.option('--list-presets', 'Listar presets disponibles y salir')
|
|
29
|
+
.option('--list-stacks', 'Listar stacks disponibles y salir')
|
|
30
|
+
.option('--learn-from <file>', 'Ruta a perfil de aprendizaje (aprendizaje-perfil.json) para heredar patrones')
|
|
31
|
+
.option('--no-interactive', 'Saltar preguntas interactivas y usar defaults')
|
|
25
32
|
.action(async (options) => {
|
|
26
|
-
|
|
33
|
+
if (options.listStacks) {
|
|
34
|
+
const { listStacks } = await import('../src/commands/init.js')
|
|
35
|
+
await listStacks()
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if (options.listPresets) {
|
|
39
|
+
const { listPresets } = await import('../src/commands/init.js')
|
|
40
|
+
await listPresets()
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
const { init } = await import('../src/commands/init.js')
|
|
27
44
|
await init(options)
|
|
28
45
|
})
|
|
29
46
|
|
|
30
47
|
program
|
|
31
|
-
.command(
|
|
32
|
-
.description(
|
|
48
|
+
.command('figma')
|
|
49
|
+
.description('Generar prompt para diseño en Figma con convenciones React + Tailwind')
|
|
33
50
|
.action(async () => {
|
|
34
|
-
const { figma } = await import(
|
|
51
|
+
const { figma } = await import('../src/commands/figma.js')
|
|
35
52
|
await figma()
|
|
36
53
|
})
|
|
37
54
|
|
|
38
55
|
program
|
|
39
|
-
.command(
|
|
40
|
-
.description(
|
|
41
|
-
.option(
|
|
42
|
-
.option(
|
|
43
|
-
.option(
|
|
56
|
+
.command('context')
|
|
57
|
+
.description('Extraer contexto del proyecto para la IA')
|
|
58
|
+
.option('--output <file>', 'Archivo de salida', 'contexto.md')
|
|
59
|
+
.option('--scope <module>', 'Filtrar por módulo (@scope)')
|
|
60
|
+
.option('--no-ai', 'No incluir anotaciones PromptLang en el output')
|
|
61
|
+
.option('--mode <mode>', 'Modo de extracción: raw (solo archivos), index (solo índice), full (ambos)', 'full')
|
|
62
|
+
.option('--query <text>', 'Consulta semántica para sugerencias de componentes/patrones')
|
|
63
|
+
.option('--domain <domain>', 'Filtrar por dominio de negocio (ecommerce, saas, mobile, api, admin, blog)')
|
|
64
|
+
.option('--projects <list>', 'Proyectos vecinos a referenciar (separados por coma)')
|
|
65
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
44
66
|
.action(async (options) => {
|
|
45
|
-
const { context } = await import(
|
|
67
|
+
const { context } = await import('../src/commands/context.js')
|
|
46
68
|
await context(options)
|
|
47
69
|
})
|
|
48
70
|
|
|
49
71
|
program
|
|
50
|
-
.command(
|
|
51
|
-
.description(
|
|
52
|
-
.option(
|
|
72
|
+
.command('validate')
|
|
73
|
+
.description('Ejecutar pipeline de validación y verificar anotaciones')
|
|
74
|
+
.option('--fix', 'Auto-corregir errores cuando sea posible')
|
|
53
75
|
.action(async (options) => {
|
|
54
|
-
const { validate } = await import(
|
|
76
|
+
const { validate } = await import('../src/commands/validate.js')
|
|
55
77
|
await validate(options)
|
|
56
78
|
})
|
|
57
79
|
|
|
58
80
|
program
|
|
59
|
-
.command(
|
|
60
|
-
.description(
|
|
61
|
-
.argument(
|
|
81
|
+
.command('suggest')
|
|
82
|
+
.description('IA sugiere estructura/stack según descripción del proyecto')
|
|
83
|
+
.argument('<description>', 'Descripción del proyecto')
|
|
62
84
|
.action(async (description) => {
|
|
63
|
-
const { suggest } = await import(
|
|
85
|
+
const { suggest } = await import('../src/commands/suggest.js')
|
|
64
86
|
await suggest(description)
|
|
65
87
|
})
|
|
66
88
|
|
|
67
89
|
const component = program
|
|
68
|
-
.command(
|
|
69
|
-
.description(
|
|
90
|
+
.command('component')
|
|
91
|
+
.description('Gestionar biblioteca de componentes reutilizables')
|
|
70
92
|
|
|
71
93
|
component
|
|
72
|
-
.command(
|
|
73
|
-
.description(
|
|
74
|
-
.option(
|
|
94
|
+
.command('list')
|
|
95
|
+
.description('Listar componentes disponibles')
|
|
96
|
+
.option('--library <path>', 'Ruta a la biblioteca de componentes')
|
|
97
|
+
.option('--style <style>', 'Filtrar por estilo UI (shadcn, mantine, chakra, headless, mui)')
|
|
98
|
+
.option('--tech <tech>', 'Filtrar por tecnología (react, vue, angular)')
|
|
99
|
+
.option('--validated', 'Mostrar solo componentes validados/aprendidos')
|
|
75
100
|
.action(async (options) => {
|
|
76
|
-
const { componentList } = await import(
|
|
101
|
+
const { componentList } = await import('../src/commands/component.js')
|
|
77
102
|
await componentList(options)
|
|
78
103
|
})
|
|
79
104
|
|
|
80
105
|
component
|
|
81
|
-
.command(
|
|
82
|
-
.description(
|
|
83
|
-
.option(
|
|
84
|
-
.option(
|
|
85
|
-
.option(
|
|
86
|
-
.option(
|
|
87
|
-
.option(
|
|
88
|
-
.option(
|
|
106
|
+
.command('add <name>')
|
|
107
|
+
.description('Agregar componente desde biblioteca o template del módulo de lenguaje')
|
|
108
|
+
.option('--library <path>', 'Ruta a la biblioteca de componentes')
|
|
109
|
+
.option('--template', 'Usar template del módulo de lenguaje (INDEX.json)')
|
|
110
|
+
.option('--lang <lang>', 'Lenguaje del template (default: de prompt-lang.json)')
|
|
111
|
+
.option('--variants <list>', 'Variantes a incluir (separadas por coma)')
|
|
112
|
+
.option('--output <name>', 'Nombre del archivo de salida (sin extensión)')
|
|
113
|
+
.option('--force', 'Sobrescribir archivo existente')
|
|
114
|
+
.option('--save', 'Marcar componente como validado/aprendido')
|
|
89
115
|
.action(async (name, options) => {
|
|
90
|
-
const { componentAdd } = await import(
|
|
116
|
+
const { componentAdd } = await import('../src/commands/component.js')
|
|
91
117
|
await componentAdd(name, options)
|
|
92
118
|
})
|
|
93
119
|
|
|
94
120
|
component
|
|
95
|
-
.command(
|
|
96
|
-
.description(
|
|
97
|
-
.option(
|
|
98
|
-
.option(
|
|
121
|
+
.command('init')
|
|
122
|
+
.description('Inicializar una biblioteca de componentes')
|
|
123
|
+
.option('--library <path>', 'Ruta donde crear la biblioteca')
|
|
124
|
+
.option('--name <name>', 'Nombre de la biblioteca')
|
|
99
125
|
.action(async (options) => {
|
|
100
|
-
const { componentInit } = await import(
|
|
126
|
+
const { componentInit } = await import('../src/commands/component.js')
|
|
101
127
|
await componentInit(options)
|
|
102
128
|
})
|
|
103
129
|
|
|
104
130
|
component
|
|
105
|
-
.command(
|
|
106
|
-
.description(
|
|
107
|
-
.option(
|
|
131
|
+
.command('manifest')
|
|
132
|
+
.description('Mostrar el manifiesto de la biblioteca de componentes')
|
|
133
|
+
.option('--library <path>', 'Ruta a la biblioteca de componentes')
|
|
108
134
|
.action(async (options) => {
|
|
109
|
-
const { componentManifest } = await import(
|
|
135
|
+
const { componentManifest } = await import('../src/commands/component.js')
|
|
110
136
|
await componentManifest(options)
|
|
111
137
|
})
|
|
112
138
|
|
|
113
139
|
// ─── Wizard command ──────────────────────────────────────────────────────────
|
|
114
140
|
|
|
115
141
|
program
|
|
116
|
-
.command(
|
|
117
|
-
.description(
|
|
142
|
+
.command('wizard')
|
|
143
|
+
.description('Asistente interactivo para configurar proyecto openPrompt-Lang')
|
|
118
144
|
.action(async () => {
|
|
119
|
-
const { wizard } = await import(
|
|
145
|
+
const { wizard } = await import('../src/commands/wizard.js')
|
|
120
146
|
await wizard()
|
|
121
147
|
})
|
|
122
148
|
|
|
123
149
|
// ─── Teach command ───────────────────────────────────────────────────────────
|
|
124
150
|
|
|
125
151
|
program
|
|
126
|
-
.command(
|
|
127
|
-
.description(
|
|
128
|
-
.option(
|
|
129
|
-
.option(
|
|
130
|
-
.option(
|
|
152
|
+
.command('teach <templateId>')
|
|
153
|
+
.description('Enseñanza estructurada desde template con @teachMe')
|
|
154
|
+
.option('--lang <lang>', 'Lenguaje del template (default: react)')
|
|
155
|
+
.option('--code', 'Mostrar código completo del template')
|
|
156
|
+
.option('--force', 'Mostrar template aunque no tenga @teachMe')
|
|
131
157
|
.action(async (templateId, options) => {
|
|
132
|
-
const { teach } = await import(
|
|
158
|
+
const { teach } = await import('../src/commands/teach.js')
|
|
133
159
|
await teach(templateId, options)
|
|
134
160
|
})
|
|
135
161
|
|
|
162
|
+
// ─── Learn command (Phase D.1) ────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
program
|
|
165
|
+
.command('learn')
|
|
166
|
+
.description('Aprender desde documentación: genera módulos de lenguaje usando IA')
|
|
167
|
+
.option('--docs <paths...>', 'Rutas a archivos/directorios de documentación')
|
|
168
|
+
.option('--from <paths...>', 'Proyectos reales para extraer patrones (opcional)')
|
|
169
|
+
.option('--name <name>', 'Nombre del lenguaje (si no se puede detectar automáticamente)')
|
|
170
|
+
.option('--output <dir>', 'Directorio de salida (default: ~/.openprompt/knowledge/langs/<name>)')
|
|
171
|
+
.option('--update <dir>', 'Actualizar módulo existente en lugar de crear nuevo')
|
|
172
|
+
.option('--integrate', 'Copiar el módulo generado a src/templates/langs/ (solo maintainers)')
|
|
173
|
+
.option('--dry-run', 'Analizar y mostrar preview sin escribir archivos')
|
|
174
|
+
.option('--provider <provider>', 'AI provider: openai | anthropic | ollama | mock')
|
|
175
|
+
.action(async (options) => {
|
|
176
|
+
const { learn } = await import('../src/commands/learn.js')
|
|
177
|
+
await learn(options)
|
|
178
|
+
})
|
|
179
|
+
|
|
136
180
|
// ─── QA commands ─────────────────────────────────────────────────────────────
|
|
137
181
|
|
|
138
182
|
program
|
|
139
|
-
.command(
|
|
140
|
-
.description(
|
|
141
|
-
.option(
|
|
142
|
-
.option(
|
|
143
|
-
.option(
|
|
144
|
-
.option(
|
|
145
|
-
.option(
|
|
146
|
-
.option(
|
|
183
|
+
.command('qa-gen')
|
|
184
|
+
.description('Generate tests from learned errors (@learn-error)')
|
|
185
|
+
.option('--lang <lang>', 'Language module (default: from INDEX.json)')
|
|
186
|
+
.option('--source <dir>', 'Source directory to scan for @learn-error')
|
|
187
|
+
.option('--output <dir>', 'Output directory for generated tests (default: src/__tests__)')
|
|
188
|
+
.option('--template <id>', 'Generate tests only for a specific template')
|
|
189
|
+
.option('--dry-run', 'Preview without writing files')
|
|
190
|
+
.option('--no-scan', 'Skip scanning source for new @learn-error annotations')
|
|
147
191
|
.action(async (options) => {
|
|
148
|
-
const { qaGen } = await import(
|
|
192
|
+
const { qaGen } = await import('../src/commands/qa-gen.js')
|
|
149
193
|
await qaGen(options)
|
|
150
194
|
})
|
|
151
195
|
|
|
152
196
|
program
|
|
153
|
-
.command(
|
|
154
|
-
.description(
|
|
155
|
-
.option(
|
|
156
|
-
.option(
|
|
197
|
+
.command('qa-learn')
|
|
198
|
+
.description('Parse @learn-error from a file and persist to language module')
|
|
199
|
+
.option('--file <path>', 'Source file to scan for @learn-error annotations')
|
|
200
|
+
.option('--lang <lang>', 'Language module (default: react)')
|
|
157
201
|
.action(async (options) => {
|
|
158
|
-
const { qaLearn } = await import(
|
|
202
|
+
const { qaLearn } = await import('../src/commands/qa-gen.js')
|
|
159
203
|
await qaLearn(options)
|
|
160
204
|
})
|
|
161
205
|
|
|
162
206
|
// ─── Lang command ────────────────────────────────────────────────────────────
|
|
163
207
|
|
|
164
|
-
const lang = program.command(
|
|
208
|
+
const lang = program.command('lang').description('Gestionar módulos de lenguaje plugables')
|
|
165
209
|
|
|
166
210
|
lang
|
|
167
|
-
.command(
|
|
168
|
-
.description(
|
|
211
|
+
.command('list')
|
|
212
|
+
.description('Listar lenguajes disponibles')
|
|
169
213
|
.action(async () => {
|
|
170
|
-
const { langList } = await import(
|
|
214
|
+
const { langList } = await import('../src/commands/lang.js')
|
|
171
215
|
await langList()
|
|
172
216
|
})
|
|
173
217
|
|
|
174
218
|
lang
|
|
175
|
-
.command(
|
|
176
|
-
.description(
|
|
177
|
-
.option(
|
|
219
|
+
.command('index <langId>')
|
|
220
|
+
.description('Mostrar índice de templates de un lenguaje')
|
|
221
|
+
.option('--category <category>', 'Filtrar por categoría')
|
|
178
222
|
.action(async (langId, options) => {
|
|
179
|
-
const { langIndex } = await import(
|
|
223
|
+
const { langIndex } = await import('../src/commands/lang.js')
|
|
180
224
|
await langIndex(langId, options)
|
|
181
225
|
})
|
|
182
226
|
|
|
183
227
|
lang
|
|
184
|
-
.command(
|
|
185
|
-
.description(
|
|
186
|
-
.option(
|
|
228
|
+
.command('search <query>')
|
|
229
|
+
.description('Buscar templates en todos los lenguajes')
|
|
230
|
+
.option('--lang <lang>', 'Filtrar por lenguaje')
|
|
187
231
|
.action(async (query, options) => {
|
|
188
|
-
const { langSearch } = await import(
|
|
232
|
+
const { langSearch } = await import('../src/commands/lang.js')
|
|
189
233
|
await langSearch(query, options)
|
|
190
234
|
})
|
|
191
235
|
|
|
192
236
|
lang
|
|
193
|
-
.command(
|
|
194
|
-
.description(
|
|
195
|
-
.option(
|
|
237
|
+
.command('errors [langId]')
|
|
238
|
+
.description('Mostrar errores aprendidos')
|
|
239
|
+
.option('--template <id>', 'Filtrar por template ID')
|
|
196
240
|
.action(async (langId, options) => {
|
|
197
|
-
const { langErrors } = await import(
|
|
198
|
-
await langErrors(langId ||
|
|
241
|
+
const { langErrors } = await import('../src/commands/lang.js')
|
|
242
|
+
await langErrors(langId || 'react', options)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
// ─── DB Rules command ────────────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
program
|
|
248
|
+
.command('db-rules')
|
|
249
|
+
.description('Consultar reglas de base de datos, anti-patrones y buenas prácticas')
|
|
250
|
+
.option('--list', 'Listar todas las reglas disponibles')
|
|
251
|
+
.option('--id <id>', 'Ver detalle de una regla específica (ej: db-001)')
|
|
252
|
+
.option('--tag <tag>', 'Filtrar por tag (ej: performance, security, supabase)')
|
|
253
|
+
.option('--category <cat>', 'Filtrar por categoría (ej: rendimiento, arquitectura)')
|
|
254
|
+
.action(async (options) => {
|
|
255
|
+
const { dbRules } = await import('../src/commands/db-rules.js')
|
|
256
|
+
await dbRules(options)
|
|
199
257
|
})
|
|
200
258
|
|
|
201
259
|
// ─── Extract command ─────────────────────────────────────────────────────────
|
|
202
260
|
|
|
203
261
|
program
|
|
204
|
-
.command(
|
|
205
|
-
.description(
|
|
206
|
-
.option(
|
|
207
|
-
.option(
|
|
208
|
-
.option(
|
|
262
|
+
.command('extract [sourceDir]')
|
|
263
|
+
.description('Analyze project and extract reusable components as templates')
|
|
264
|
+
.option('--lang <lang>', 'Language module to extract into (default: from prompt-lang.json)')
|
|
265
|
+
.option('--min-reuse <n>', 'Minimum imports to qualify (default: 2)')
|
|
266
|
+
.option('--dry-run', "Analyze only, don't write files")
|
|
267
|
+
.option('--learn', 'Deep project analysis: extract patterns, conventions and ways of working')
|
|
268
|
+
.option('--output <file>', 'Output file for --learn profile (default: aprendizaje-perfil.json)')
|
|
209
269
|
.action(async (sourceDir, options) => {
|
|
210
|
-
|
|
211
|
-
|
|
270
|
+
if (options.learn) {
|
|
271
|
+
const { extractLearn } = await import('../src/commands/extract.js')
|
|
272
|
+
await extractLearn(sourceDir || 'src', options)
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
const { extractTemplates } = await import('../src/commands/extract.js')
|
|
276
|
+
await extractTemplates(sourceDir || 'src', options)
|
|
212
277
|
})
|
|
213
278
|
|
|
214
279
|
program
|
|
215
|
-
.command(
|
|
216
|
-
.description(
|
|
280
|
+
.command('analyze [sourceDir]')
|
|
281
|
+
.description('Analyze project structure, deps, and code health')
|
|
217
282
|
.action(async (sourceDir) => {
|
|
218
|
-
const { extractAnalyze } = await import(
|
|
219
|
-
await extractAnalyze(sourceDir ||
|
|
283
|
+
const { extractAnalyze } = await import('../src/commands/extract.js')
|
|
284
|
+
await extractAnalyze(sourceDir || 'src', {})
|
|
220
285
|
})
|
|
221
286
|
|
|
222
287
|
// ─── Integrate command ────────────────────────────────────────────────────────
|
|
223
288
|
|
|
224
289
|
program
|
|
225
|
-
.command(
|
|
226
|
-
.description(
|
|
227
|
-
.option(
|
|
228
|
-
.option(
|
|
229
|
-
.option(
|
|
290
|
+
.command('integrate')
|
|
291
|
+
.description('Configure Opencode, Cursor, and VS Code for the project')
|
|
292
|
+
.option('--all', 'Setup all integrations without prompting')
|
|
293
|
+
.option('--lang <lang>', 'Language (auto-detects from prompt-lang.json)')
|
|
294
|
+
.option('--no-ask', 'Skip interactive prompts')
|
|
295
|
+
.option('--from <dir>', 'Transferir contexto desde otro proyecto (memoria estructurada)')
|
|
296
|
+
.option('--to <dir>', 'Proyecto destino para la transferencia de contexto')
|
|
297
|
+
.option('--migrate', 'Modo migración: copiar contexto de negocio entre proyectos')
|
|
230
298
|
.action(async (options) => {
|
|
231
|
-
|
|
299
|
+
if (options.migrate || options.from) {
|
|
300
|
+
const { migrateContext } = await import('../src/commands/integrate.js')
|
|
301
|
+
await migrateContext(options)
|
|
302
|
+
return
|
|
303
|
+
}
|
|
304
|
+
const { integrate } = await import('../src/commands/integrate.js')
|
|
232
305
|
await integrate(options)
|
|
233
306
|
})
|
|
234
307
|
|
|
235
308
|
// ─── AI commands ─────────────────────────────────────────────────────────────
|
|
236
309
|
|
|
237
310
|
program
|
|
238
|
-
.command(
|
|
239
|
-
.description(
|
|
240
|
-
.option(
|
|
241
|
-
.option(
|
|
242
|
-
.option(
|
|
243
|
-
.option(
|
|
311
|
+
.command('ai-gen')
|
|
312
|
+
.description('Generate components from natural language descriptions')
|
|
313
|
+
.option('--description <text>', 'Description of what to generate')
|
|
314
|
+
.option('--name <name>', 'Component name (auto-suggested if omitted)')
|
|
315
|
+
.option('--lang <lang>', 'Language module (default: react)')
|
|
316
|
+
.option('--profile <profile>', 'senior | mid | junior (default: mid)')
|
|
244
317
|
.option(
|
|
245
|
-
|
|
246
|
-
|
|
318
|
+
'--provider <provider>',
|
|
319
|
+
'AI provider: openai | anthropic | ollama | mock (default: auto-detect)'
|
|
247
320
|
)
|
|
248
|
-
.option(
|
|
249
|
-
.option(
|
|
250
|
-
.option(
|
|
251
|
-
.option(
|
|
252
|
-
.option(
|
|
253
|
-
.option(
|
|
321
|
+
.option('--output <dir>', 'Output directory (default: src/components)')
|
|
322
|
+
.option('--force', 'Overwrite existing files without asking')
|
|
323
|
+
.option('--validate', 'Run annotation validation after generation')
|
|
324
|
+
.option('--verbose', 'Show prompt and extended output')
|
|
325
|
+
.option('--temperature <num>', 'Temperature for generation (default: 0.3)')
|
|
326
|
+
.option('--max-tokens <num>', 'Max tokens for generation (default: 4096)')
|
|
254
327
|
.action(async (options) => {
|
|
255
|
-
const { aiGen } = await import(
|
|
328
|
+
const { aiGen } = await import('../src/commands/ai-gen.js')
|
|
256
329
|
await aiGen(options)
|
|
257
330
|
})
|
|
258
331
|
|
|
259
332
|
program
|
|
260
|
-
.command(
|
|
261
|
-
.description(
|
|
333
|
+
.command('ai-providers')
|
|
334
|
+
.description('List available AI providers and their status')
|
|
262
335
|
.action(async () => {
|
|
263
|
-
const { aiProviders } = await import(
|
|
336
|
+
const { aiProviders } = await import('../src/commands/ai-gen.js')
|
|
264
337
|
await aiProviders()
|
|
265
338
|
})
|
|
266
339
|
|
|
267
340
|
// ─── Scaffold command ────────────────────────────────────────────────────────
|
|
268
341
|
|
|
269
342
|
const scaffold = program
|
|
270
|
-
.command(
|
|
271
|
-
.description(
|
|
343
|
+
.command('scaffold')
|
|
344
|
+
.description('Gestionar scafffolding de proyectos por framework')
|
|
272
345
|
|
|
273
346
|
scaffold
|
|
274
|
-
.command(
|
|
275
|
-
.description(
|
|
276
|
-
.option(
|
|
277
|
-
.option(
|
|
347
|
+
.command('folders <framework>')
|
|
348
|
+
.description('Crear estructura de carpetas según framework')
|
|
349
|
+
.option('--name <name>', 'Nombre del proyecto (directorio)')
|
|
350
|
+
.option('--force', 'Sobrescribir archivos existentes')
|
|
278
351
|
.action(async (framework, options) => {
|
|
279
|
-
const { scaffoldFolders } = await import(
|
|
352
|
+
const { scaffoldFolders } = await import('../src/commands/scaffold.js')
|
|
280
353
|
await scaffoldFolders(framework, options)
|
|
281
354
|
})
|
|
282
355
|
|
|
283
356
|
scaffold
|
|
284
|
-
.command(
|
|
285
|
-
.description(
|
|
357
|
+
.command('list')
|
|
358
|
+
.description('Listar frameworks disponibles en el catálogo')
|
|
286
359
|
.action(async () => {
|
|
287
|
-
const { scaffoldList } = await import(
|
|
360
|
+
const { scaffoldList } = await import('../src/commands/scaffold.js')
|
|
288
361
|
await scaffoldList()
|
|
289
362
|
})
|
|
290
363
|
|
|
291
364
|
// ─── MCP server command ───────────────────────────────────────────────────────
|
|
292
365
|
|
|
293
366
|
program
|
|
294
|
-
.command(
|
|
295
|
-
.description(
|
|
367
|
+
.command('mcp')
|
|
368
|
+
.description('Start MCP server for opencode integration via stdio')
|
|
296
369
|
.action(async () => {
|
|
297
|
-
const { startServer } = await import(
|
|
370
|
+
const { startServer } = await import('../src/mcp-server.js')
|
|
298
371
|
await startServer()
|
|
299
372
|
})
|
|
300
373
|
|
|
301
|
-
|
|
374
|
+
try {
|
|
375
|
+
await program.parseAsync(process.argv)
|
|
376
|
+
} catch (err) {
|
|
377
|
+
console.error(chalk.red(`✘ Error: ${err.message}`))
|
|
378
|
+
process.exitCode = 1
|
|
379
|
+
}
|