openprompt-lang 0.9.0 → 0.10.1
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/LICENSE +1 -1
- package/package.json +14 -2
- package/schemas/prompt-lang.json +53 -0
- package/src/cli/commands-context.js +91 -5
- package/src/cli/commands-knowledge.js +3 -2
- package/src/cli/commands-learning.js +1 -0
- package/src/cli/commands-misc.js +4 -0
- package/src/commands/context.js +59 -19
- package/src/commands/domain.js +257 -0
- package/src/commands/knowledge-query.js +22 -4
- package/src/commands/learning.js +8 -5
- package/src/commands/pattern.js +412 -0
- package/src/commands/recall.js +16 -3
- package/src/commands/ticket.js +20 -15
- package/src/mcp-server.js +358 -10
- package/src/mcp-session.js +120 -0
- package/src/mcp-workflow.js +205 -0
- package/src/utils/domains.js +139 -0
- package/src/utils/knowledge-search.js +28 -2
package/LICENSE
CHANGED
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openprompt-lang",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "PromptLang CLI — Context Engine de anotaciones para desarrollo asistido por IA",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./bin/cli.js",
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
"src/ts-transformer/",
|
|
22
22
|
"src/vite-plugin/",
|
|
23
23
|
"src/mcp-server.js",
|
|
24
|
+
"src/mcp-session.js",
|
|
25
|
+
"src/mcp-workflow.js",
|
|
24
26
|
"src/templates/langs/",
|
|
25
27
|
"src/templates/knowledge-repo/",
|
|
26
28
|
"src/templates/semantic-index.json",
|
|
@@ -88,6 +90,7 @@
|
|
|
88
90
|
},
|
|
89
91
|
"devDependencies": {
|
|
90
92
|
"eslint": "^10.3.0",
|
|
93
|
+
"husky": "^9.1.7",
|
|
91
94
|
"prettier": "^3.8.3",
|
|
92
95
|
"vitest": "^4.1.6"
|
|
93
96
|
},
|
|
@@ -98,5 +101,14 @@
|
|
|
98
101
|
"bugs": {
|
|
99
102
|
"url": "https://github.com/DeadJustLive/OpenPrompt-Lang/issues"
|
|
100
103
|
},
|
|
101
|
-
"homepage": "https://github.com/DeadJustLive/OpenPrompt-Lang#readme"
|
|
104
|
+
"homepage": "https://github.com/DeadJustLive/OpenPrompt-Lang#readme",
|
|
105
|
+
"lint-staged": {
|
|
106
|
+
"*.{ts,tsx,js,jsx,mjs,cjs}": [
|
|
107
|
+
"eslint --fix",
|
|
108
|
+
"prettier --write"
|
|
109
|
+
],
|
|
110
|
+
"*.{ts,tsx,js,jsx}": [
|
|
111
|
+
"openprompt-lang lint-file"
|
|
112
|
+
]
|
|
113
|
+
}
|
|
102
114
|
}
|
package/schemas/prompt-lang.json
CHANGED
|
@@ -127,6 +127,59 @@
|
|
|
127
127
|
"description": "Archivo de salida del extractor"
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
},
|
|
131
|
+
"domain": {
|
|
132
|
+
"type": "object",
|
|
133
|
+
"description": "Configuración de dominio modular de contexto",
|
|
134
|
+
"properties": {
|
|
135
|
+
"active": {
|
|
136
|
+
"type": "array",
|
|
137
|
+
"items": { "type": "string" },
|
|
138
|
+
"description": "Dominios activos (ej: programming, shared)"
|
|
139
|
+
},
|
|
140
|
+
"default": {
|
|
141
|
+
"type": "string",
|
|
142
|
+
"description": "Dominio por defecto"
|
|
143
|
+
},
|
|
144
|
+
"patterns": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"description": "Patrones por dominio",
|
|
147
|
+
"additionalProperties": {
|
|
148
|
+
"type": "array",
|
|
149
|
+
"items": { "type": "string" }
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"workflow": {
|
|
155
|
+
"type": "object",
|
|
156
|
+
"description": "Configuración de enforcement de workflow para IA",
|
|
157
|
+
"properties": {
|
|
158
|
+
"strictMode": {
|
|
159
|
+
"type": "boolean",
|
|
160
|
+
"default": false,
|
|
161
|
+
"description": "Bloquea herramientas si no se cumplen prerrequisitos"
|
|
162
|
+
},
|
|
163
|
+
"autoTicket": {
|
|
164
|
+
"type": "boolean",
|
|
165
|
+
"default": true,
|
|
166
|
+
"description": "Crea tickets automáticos cuando se detecta fricción en el workflow"
|
|
167
|
+
},
|
|
168
|
+
"suggestionsLevel": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"enum": ["minimal", "standard", "full"],
|
|
171
|
+
"default": "full",
|
|
172
|
+
"description": "Nivel de sugerencias de workflow"
|
|
173
|
+
},
|
|
174
|
+
"requiredToolsBefore": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"description": "Tools que requieren otros tools antes de ejecutarse",
|
|
177
|
+
"additionalProperties": {
|
|
178
|
+
"type": "array",
|
|
179
|
+
"items": { "type": "string" }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
130
183
|
}
|
|
131
184
|
},
|
|
132
185
|
"required": ["name", "stack"]
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// @use(commander, kind, contract, limit)
|
|
2
2
|
// @kind(util)
|
|
3
|
-
// @contract(in: program -> out: void, sideEffect: registra comandos context/validate/extract/analyze)
|
|
4
|
-
// @limit(lines:
|
|
3
|
+
// @contract(in: program -> out: void, sideEffect: registra comandos context/validate/extract/analyze y dominios)
|
|
4
|
+
// @limit(lines: 180)
|
|
5
5
|
|
|
6
6
|
export function register(program) {
|
|
7
|
-
program
|
|
7
|
+
const contextCmd = program
|
|
8
8
|
.command('context')
|
|
9
9
|
.description('Extraer contexto del proyecto para la IA')
|
|
10
|
+
|
|
11
|
+
contextCmd
|
|
10
12
|
.option('--output <file>', 'Archivo de salida', 'contexto.md')
|
|
11
13
|
.option('--scope <module>', 'Filtrar por módulo (@scope)')
|
|
12
14
|
.option('--no-ai', 'No incluir anotaciones PromptLang en el output')
|
|
@@ -17,14 +19,75 @@ export function register(program) {
|
|
|
17
19
|
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
18
20
|
.option('--unified', 'Búsqueda unificada: knowledge + learning + templates + tickets + semántico')
|
|
19
21
|
.action(async (options) => {
|
|
20
|
-
const { context, contextUnified } = await import('../commands/context.js')
|
|
21
22
|
if (options.unified) {
|
|
23
|
+
const { contextUnified } = await import('../commands/context.js')
|
|
22
24
|
await contextUnified(options)
|
|
23
25
|
return
|
|
24
26
|
}
|
|
27
|
+
const { context } = await import('../commands/context.js')
|
|
25
28
|
await context(options)
|
|
26
29
|
})
|
|
27
30
|
|
|
31
|
+
// Sub-comandos de dominios modulares
|
|
32
|
+
const domainCmd = contextCmd
|
|
33
|
+
.command('domain')
|
|
34
|
+
.description('Gestionar dominios modulares de contexto')
|
|
35
|
+
|
|
36
|
+
domainCmd
|
|
37
|
+
.command('init')
|
|
38
|
+
.description('Inicializar sistema de dominios modulares')
|
|
39
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
const { domainInit } = await import('../commands/domain.js')
|
|
42
|
+
await domainInit(options)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
domainCmd
|
|
46
|
+
.command('use <domains>')
|
|
47
|
+
.description('Activar dominios de contexto (separar con +, ej: programming+shared)')
|
|
48
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
49
|
+
.option('--no-shared', 'No incluir el dominio shared automaticamente')
|
|
50
|
+
.action(async (domains, options) => {
|
|
51
|
+
const { domainUse } = await import('../commands/domain.js')
|
|
52
|
+
await domainUse(domains, options)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
domainCmd
|
|
56
|
+
.command('switch <domain>')
|
|
57
|
+
.description('Cambiar el dominio activo')
|
|
58
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
59
|
+
.action(async (domain, options) => {
|
|
60
|
+
const { domainSwitch } = await import('../commands/domain.js')
|
|
61
|
+
await domainSwitch(domain, options)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
domainCmd
|
|
65
|
+
.command('clear')
|
|
66
|
+
.description('Desactivar todos los dominios (solo shared permanece)')
|
|
67
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
68
|
+
.action(async (options) => {
|
|
69
|
+
const { domainClear } = await import('../commands/domain.js')
|
|
70
|
+
await domainClear(options)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
domainCmd
|
|
74
|
+
.command('status')
|
|
75
|
+
.description('Mostrar dominios activos y su contenido')
|
|
76
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
77
|
+
.action(async (options) => {
|
|
78
|
+
const { domainStatus } = await import('../commands/domain.js')
|
|
79
|
+
await domainStatus(options)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
domainCmd
|
|
83
|
+
.command('load <domain>')
|
|
84
|
+
.description('Cargar un dominio sin activarlo (solo consulta)')
|
|
85
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
86
|
+
.action(async (domain, options) => {
|
|
87
|
+
const { domainLoad } = await import('../commands/domain.js')
|
|
88
|
+
await domainLoad(domain, options)
|
|
89
|
+
})
|
|
90
|
+
|
|
28
91
|
program
|
|
29
92
|
.command('docs')
|
|
30
93
|
.description('Generar FRAMEWORK.md desde el estado actual del proyecto')
|
|
@@ -83,4 +146,27 @@ export function register(program) {
|
|
|
83
146
|
const { extractAnalyze } = await import('../commands/extract.js')
|
|
84
147
|
await extractAnalyze(sourceDir || 'src', {})
|
|
85
148
|
})
|
|
86
|
-
|
|
149
|
+
|
|
150
|
+
program
|
|
151
|
+
.command('learn-pattern')
|
|
152
|
+
.description('Extraer patron de estructura/tono/formato de documentos ejemplo')
|
|
153
|
+
.option('--from <path>', 'Ruta a archivo o directorio con documentos ejemplo')
|
|
154
|
+
.option('--type <type>', 'Tipo de patron: report, code, technical-writing, legal, business, product', 'report')
|
|
155
|
+
.option('--name <name>', 'Nombre del patron')
|
|
156
|
+
.option('--domain <domain>', 'Dominio destino (default: tipo del patron)')
|
|
157
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
158
|
+
.action(async (options) => {
|
|
159
|
+
const { patternExtract } = await import('../commands/pattern.js')
|
|
160
|
+
await patternExtract(options)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
program
|
|
164
|
+
.command('pattern-list')
|
|
165
|
+
.description('Listar patrones extraidos por dominio')
|
|
166
|
+
.option('--domain <domain>', 'Filtrar por dominio especifico')
|
|
167
|
+
.option('--dir <path>', 'Directorio base del proyecto (default: cwd)')
|
|
168
|
+
.action(async (options) => {
|
|
169
|
+
const { patternList } = await import('../commands/pattern.js')
|
|
170
|
+
await patternList(options)
|
|
171
|
+
})
|
|
172
|
+
}
|
|
@@ -31,9 +31,10 @@ export function register(program) {
|
|
|
31
31
|
knowledge
|
|
32
32
|
.command('list')
|
|
33
33
|
.description('Listar PDFs procesados con metadatos')
|
|
34
|
-
.
|
|
34
|
+
.option('--domain <domain>', 'Filtrar por dominio (programming, reports, business, legal, product, technical-writing)')
|
|
35
|
+
.action(async (options) => {
|
|
35
36
|
const { list } = await import('../commands/knowledge.js')
|
|
36
|
-
await list()
|
|
37
|
+
await list(options)
|
|
37
38
|
})
|
|
38
39
|
|
|
39
40
|
knowledge
|
|
@@ -20,6 +20,7 @@ export function register(program) {
|
|
|
20
20
|
.command('search <query>')
|
|
21
21
|
.description('Buscar conceptos por nombre, tipo o tag')
|
|
22
22
|
.option('--category <cat>', 'Filtrar por categoría (visual, ui, backend, product, ai)')
|
|
23
|
+
.option('--domain <domain>', 'Filtrar por dominio (programming, reports, business, etc.)')
|
|
23
24
|
.action(async (query, options) => {
|
|
24
25
|
const { search } = await import('../commands/learning.js')
|
|
25
26
|
await search(query, options)
|
package/src/cli/commands-misc.js
CHANGED
|
@@ -201,6 +201,7 @@ export function register(program) {
|
|
|
201
201
|
.option('--description <desc>', 'Descripción del bug')
|
|
202
202
|
.option('--learn-error <id>', 'ID de @learn-error relacionado')
|
|
203
203
|
.option('--type <type>', 'Tipo: OPL (framework) o project (default)')
|
|
204
|
+
.option('--domain <domain>', 'Dominio (programming, reports, business, legal, product, technical-writing)')
|
|
204
205
|
.action(async (options) => {
|
|
205
206
|
const { ticketCreate } = await import('../commands/ticket.js')
|
|
206
207
|
await ticketCreate(options)
|
|
@@ -212,6 +213,7 @@ export function register(program) {
|
|
|
212
213
|
.option('--status <status>', 'Filtrar por estado: open, wip, fixed, wontfix')
|
|
213
214
|
.option('--severity <severity>', 'Filtrar por severidad')
|
|
214
215
|
.option('--project <name>', 'Filtrar por proyecto')
|
|
216
|
+
.option('--domain <domain>', 'Filtrar por dominio (programming, reports, business, etc.)')
|
|
215
217
|
.action(async (options) => {
|
|
216
218
|
const { ticketList } = await import('../commands/ticket.js')
|
|
217
219
|
await ticketList(options)
|
|
@@ -241,6 +243,8 @@ export function register(program) {
|
|
|
241
243
|
.description('Buscar en memoria del proyecto: aprendizajes, conceptos, errores, tickets')
|
|
242
244
|
.option('--lang <lang>', 'Módulo de lenguaje (default: react)')
|
|
243
245
|
.option('--dir <path>', 'Directorio del proyecto (default: cwd)')
|
|
246
|
+
.option('--domain <domain>', 'Filtrar por dominio (programming, reports, business, legal, product, technical-writing)')
|
|
247
|
+
.option('--all', 'Buscar en todos los dominios disponibles')
|
|
244
248
|
.action(async (query, options) => {
|
|
245
249
|
const { recall } = await import('../commands/recall.js')
|
|
246
250
|
await recall(query, options)
|
package/src/commands/context.js
CHANGED
|
@@ -12,6 +12,7 @@ import { searchConcepts } from '../utils/semantic-index.js'
|
|
|
12
12
|
import { searchKnowledge } from '../utils/knowledge-search.js'
|
|
13
13
|
import { searchTemplates as langSearchTemplates } from '../utils/language-loader.js'
|
|
14
14
|
import { scanForLearnErrors } from '../utils/error-learner.js'
|
|
15
|
+
import { DOMAIN_KEYWORDS, getActiveDomains, getDomainKeywordsForFiltering, resolveCategoryForDomain } from '../utils/domains.js'
|
|
15
16
|
import chalk from 'chalk'
|
|
16
17
|
|
|
17
18
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
@@ -61,15 +62,6 @@ const LANG_MAP = {
|
|
|
61
62
|
|
|
62
63
|
const KIND_TYPES = new Set(['component', 'hook', 'service', 'page', 'store', 'util', 'type', 'layout', 'feature'])
|
|
63
64
|
|
|
64
|
-
const DOMAIN_KEYWORDS = {
|
|
65
|
-
ecommerce: ['product', 'cart', 'checkout', 'order', 'payment', 'shop', 'store', 'inventory', 'price', 'discount', 'customer', 'review', 'wishlist', 'shipping', 'invoice'],
|
|
66
|
-
saas: ['subscription', 'tenant', 'workspace', 'organization', 'billing', 'plan', 'pricing', 'feature-flag', 'usage', 'quota', 'team', 'invite', 'role', 'permission'],
|
|
67
|
-
mobile: ['push', 'notification', 'offline', 'sync', 'capacitor', 'camera', 'geolocation', 'biometric', 'deep-link', 'app-state', 'background'],
|
|
68
|
-
api: ['endpoint', 'route', 'controller', 'middleware', 'schema', 'validator', 'resolver', 'api-key', 'rate-limit', 'webhook', 'swagger', 'openapi'],
|
|
69
|
-
admin: ['dashboard', 'crud', 'datatable', 'filter', 'bulk', 'admin', 'management', 'report', 'analytics', 'chart', 'export', 'import'],
|
|
70
|
-
blog: ['post', 'article', 'author', 'category', 'tag', 'comment', 'archive', 'search', 'rss', 'feed', 'content', 'editor']
|
|
71
|
-
}
|
|
72
|
-
|
|
73
65
|
function shouldIgnore (name, isDir) {
|
|
74
66
|
if (isDir) return IGNORED_DIRS.has(name)
|
|
75
67
|
if (IGNORED_FILES.has(name)) return true
|
|
@@ -112,7 +104,7 @@ function generateTree (dirPath, prefix = '', configIgnore = []) {
|
|
|
112
104
|
function collectFiles (baseDir, options) {
|
|
113
105
|
const files = []
|
|
114
106
|
const domain = options.domain
|
|
115
|
-
const domainKeywords = domain ?
|
|
107
|
+
const domainKeywords = domain ? getDomainKeywordsForFiltering(domain) : null
|
|
116
108
|
|
|
117
109
|
const walkDir = (dirPath) => {
|
|
118
110
|
let entries
|
|
@@ -415,7 +407,13 @@ export async function contextUnified (options) {
|
|
|
415
407
|
const domain = options.domain
|
|
416
408
|
const langId = options.lang || 'react'
|
|
417
409
|
|
|
418
|
-
|
|
410
|
+
const resolvedDomain = domain || getActiveDomains(baseDir)[0] || 'shared'
|
|
411
|
+
const domainCategories = resolveCategoryForDomain(resolvedDomain)
|
|
412
|
+
|
|
413
|
+
console.log(chalk.cyan(`\n🔍 Búsqueda unificada: "${query || resolvedDomain || 'todo'}"`))
|
|
414
|
+
if (resolvedDomain && resolvedDomain !== 'shared') {
|
|
415
|
+
console.log(chalk.dim(` Dominio activo: ${resolvedDomain}`))
|
|
416
|
+
}
|
|
419
417
|
|
|
420
418
|
const results = {
|
|
421
419
|
knowledge: [],
|
|
@@ -423,14 +421,15 @@ export async function contextUnified (options) {
|
|
|
423
421
|
semantic: [],
|
|
424
422
|
templates: [],
|
|
425
423
|
tickets: [],
|
|
426
|
-
errors: []
|
|
424
|
+
errors: [],
|
|
425
|
+
patterns: []
|
|
427
426
|
}
|
|
428
427
|
|
|
429
428
|
// 1. Knowledge search
|
|
430
429
|
if (query) {
|
|
431
430
|
console.log(chalk.blue(' 📚 Buscando en knowledge...'))
|
|
432
431
|
try {
|
|
433
|
-
const kResults = searchKnowledge(query, { limit: 5 })
|
|
432
|
+
const kResults = searchKnowledge(query, { limit: 5, domain: resolvedDomain })
|
|
434
433
|
results.knowledge = (kResults || []).map(r => ({
|
|
435
434
|
title: r.title || r.bookTitle,
|
|
436
435
|
bookTitle: r.bookTitle || r.bookId,
|
|
@@ -461,12 +460,13 @@ export async function contextUnified (options) {
|
|
|
461
460
|
} catch {}
|
|
462
461
|
}
|
|
463
462
|
|
|
464
|
-
// 4. Learning concepts
|
|
463
|
+
// 4. Learning concepts (filtered by domain categories)
|
|
465
464
|
const learningDir = join(baseDir, '.opencode', 'learning', 'concepts')
|
|
466
465
|
if (existsSync(learningDir)) {
|
|
467
466
|
try {
|
|
468
467
|
for (const cat of readdirSync(learningDir)) {
|
|
469
|
-
if (cat === 'knowledge') continue
|
|
468
|
+
if (cat === 'knowledge') continue
|
|
469
|
+
if (domainCategories && !domainCategories.includes(cat)) continue
|
|
470
470
|
const catDir = join(learningDir, cat)
|
|
471
471
|
for (const entry of readdirSync(catDir)) {
|
|
472
472
|
const conceptMd = join(catDir, entry, 'concept.md')
|
|
@@ -481,7 +481,7 @@ export async function contextUnified (options) {
|
|
|
481
481
|
} catch {}
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
-
// 5. Tickets
|
|
484
|
+
// 5. Tickets (filtered by domain)
|
|
485
485
|
const ticketDirs = [
|
|
486
486
|
join(baseDir, '.opencode', 'bugs'),
|
|
487
487
|
join(__dirname, '..', '..', 'BUGS-IDENTIFIED-IN-PROJECTS')
|
|
@@ -496,7 +496,10 @@ export async function contextUnified (options) {
|
|
|
496
496
|
if (line.includes('| BUG-') && (!query || line.toLowerCase().includes(query.toLowerCase()))) {
|
|
497
497
|
const cols = line.split('|').map(c => c.trim()).filter(Boolean)
|
|
498
498
|
if (cols.length >= 4 && cols[3] !== 'fixed') {
|
|
499
|
-
|
|
499
|
+
const ticketDomain = cols.length >= 7 ? cols[5] : null
|
|
500
|
+
if (!domain || !ticketDomain || ticketDomain === resolvedDomain) {
|
|
501
|
+
results.tickets.push({ id: cols[0], title: cols[1], severity: cols[2], status: cols[3] })
|
|
502
|
+
}
|
|
500
503
|
}
|
|
501
504
|
}
|
|
502
505
|
}
|
|
@@ -515,9 +518,38 @@ export async function contextUnified (options) {
|
|
|
515
518
|
} catch {}
|
|
516
519
|
}
|
|
517
520
|
|
|
521
|
+
// 7. Patterns from active domains
|
|
522
|
+
const domainsDir = join(baseDir, '.openprompt', 'domains')
|
|
523
|
+
if (existsSync(domainsDir)) {
|
|
524
|
+
try {
|
|
525
|
+
const activeDomains = getActiveDomains(baseDir)
|
|
526
|
+
for (const d of activeDomains) {
|
|
527
|
+
const patternsDir = join(domainsDir, d, 'patterns')
|
|
528
|
+
if (!existsSync(patternsDir)) continue
|
|
529
|
+
for (const f of readdirSync(patternsDir)) {
|
|
530
|
+
if (!f.endsWith('.json')) continue
|
|
531
|
+
const patternName = f.replace('.json', '')
|
|
532
|
+
if (!query || patternName.toLowerCase().includes(query.toLowerCase())) {
|
|
533
|
+
try {
|
|
534
|
+
const patternContent = JSON.parse(readFileSync(join(patternsDir, f), 'utf-8'))
|
|
535
|
+
results.patterns.push({
|
|
536
|
+
name: patternName,
|
|
537
|
+
domain: d,
|
|
538
|
+
type: patternContent.type || 'unknown',
|
|
539
|
+
sections: patternContent.structure?.sections?.length || 0,
|
|
540
|
+
rules: patternContent.rules?.length || 0,
|
|
541
|
+
createdAt: patternContent.createdAt || ''
|
|
542
|
+
})
|
|
543
|
+
} catch { /* skip corrupt */ }
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
} catch {}
|
|
548
|
+
}
|
|
549
|
+
|
|
518
550
|
// Output
|
|
519
551
|
let totalResults = results.knowledge.length + results.learning.length + results.semantic.length +
|
|
520
|
-
results.templates.length + results.tickets.length + results.errors.length
|
|
552
|
+
results.templates.length + results.tickets.length + results.errors.length + results.patterns.length
|
|
521
553
|
|
|
522
554
|
if (totalResults === 0) {
|
|
523
555
|
console.log(chalk.yellow(' 📭 Sin resultados para esta búsqueda.\n'))
|
|
@@ -571,6 +603,14 @@ export async function contextUnified (options) {
|
|
|
571
603
|
}
|
|
572
604
|
}
|
|
573
605
|
|
|
574
|
-
|
|
606
|
+
if (results.patterns.length > 0) {
|
|
607
|
+
console.log(chalk.cyan(`\n📐 Patrones (${results.patterns.length}):\n`))
|
|
608
|
+
for (const p of results.patterns.slice(0, 5)) {
|
|
609
|
+
console.log(` ${chalk.bold(p.name)} [${p.domain}]`)
|
|
610
|
+
console.log(chalk.gray(` Tipo: ${p.type} | Secciones: ${p.sections} | Reglas: ${p.rules}`))
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
console.log(chalk.green(`\n ✅ ${totalResults} resultados en 7 fuentes\n`))
|
|
575
615
|
return results
|
|
576
616
|
}
|