openprompt-lang 1.2.7 → 1.4.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 (79) hide show
  1. package/README.md +62 -8
  2. package/bin/cli.js +2 -0
  3. package/docs/00-ARCHITECTURE/OPL-BOOST-MULTI-AGENT.md +406 -0
  4. package/docs/02-STANDARDS/AGENTS.template.md +89 -0
  5. package/docs/02-STANDARDS/ticket-driven-development.md +99 -0
  6. package/docs/04-TICKETS/BOOST-001-profile-registry.md +66 -0
  7. package/docs/04-TICKETS/BOOST-002-context-compression.md +58 -0
  8. package/docs/04-TICKETS/BOOST-003-template-hydration.md +69 -0
  9. package/docs/04-TICKETS/BOOST-004-fewshot-engine.md +58 -0
  10. package/docs/04-TICKETS/BOOST-005-agent-pool.md +69 -0
  11. package/docs/04-TICKETS/BOOST-006-specialized-agents.md +53 -0
  12. package/docs/04-TICKETS/BOOST-007-validation-loop.md +56 -0
  13. package/docs/04-TICKETS/BOOST-008-orchestrator.md +71 -0
  14. package/docs/04-TICKETS/BOOST-009-cache-system.md +56 -0
  15. package/docs/04-TICKETS/BOOST-010-cli-mcp.md +67 -0
  16. package/docs/04-TICKETS/BOOST-011-self-learning.md +50 -0
  17. package/docs/04-TICKETS/BOOST-012-prompt-preamble.md +109 -0
  18. package/docs/04-TICKETS/BOOST-013-hydrator-duplicate-code.md +132 -0
  19. package/docs/04-TICKETS/BOOST-014-multiagent-missing-parts.md +87 -0
  20. package/docs/04-TICKETS/BOOST-015-skeleton-type-missing.md +76 -0
  21. package/docs/04-TICKETS/BOOST-016-output-path-duplicate.md +68 -0
  22. package/docs/04-TICKETS/INDEX.md +89 -0
  23. package/docs/04-TICKETS/_archive/BOOST-005-micro-tasking.md +67 -0
  24. package/docs/04-TICKETS/_archive/BOOST-006-validation-loop.md +66 -0
  25. package/docs/04-TICKETS/_archive/BOOST-007-progressive-pipeline.md +69 -0
  26. package/docs/04-TICKETS/_archive/BOOST-008-cli-mcp-integration.md +74 -0
  27. package/docs/AI_CONTEXT.md +16 -0
  28. package/docs/EMBEDDINGS.md +214 -0
  29. package/docs/ONBOARDING_WORKFLOW.md +151 -0
  30. package/docs/OPL_ACADEMIC_ISSUES.md +158 -0
  31. package/docs/WEB_SCRAPER_PLAN.md +454 -0
  32. package/package.json +9 -2
  33. package/scripts/postinstall.js +37 -0
  34. package/src/boost/agent-pool.js +442 -0
  35. package/src/boost/agents/index.js +79 -0
  36. package/src/boost/cache.js +241 -0
  37. package/src/boost/context-compressor.js +354 -0
  38. package/src/boost/fewshot-retriever.js +332 -0
  39. package/src/boost/hardware-detector.js +486 -0
  40. package/src/boost/hydrator.js +398 -0
  41. package/src/boost/index.js +60 -0
  42. package/src/boost/orchestrator.js +615 -0
  43. package/src/boost/preamble.js +217 -0
  44. package/src/boost/profile-registry.js +264 -0
  45. package/src/boost/self-learn.js +247 -0
  46. package/src/boost/skeletons/component.skeleton.js +24 -0
  47. package/src/boost/skeletons/hook.skeleton.js +27 -0
  48. package/src/boost/skeletons/index.js +67 -0
  49. package/src/boost/skeletons/page.skeleton.js +22 -0
  50. package/src/boost/skeletons/service.skeleton.js +20 -0
  51. package/src/boost/skeletons/store.skeleton.js +18 -0
  52. package/src/boost/skeletons/type.skeleton.js +11 -0
  53. package/src/boost/task-dispatcher.js +142 -0
  54. package/src/boost/validation-loop.js +495 -0
  55. package/src/cli/commands-boost.js +394 -0
  56. package/src/cli/commands-knowledge.js +1 -0
  57. package/src/cli/commands-opl.js +79 -1
  58. package/src/cli/commands-workflow.js +125 -6
  59. package/src/commands/init-core.js +169 -5
  60. package/src/commands/knowledge-ops.js +52 -0
  61. package/src/commands/opl-embeddings.js +556 -0
  62. package/src/commands/opl-help.js +26 -2
  63. package/src/commands/opl-search.js +106 -2
  64. package/src/commands/opl-webscrape.js +390 -0
  65. package/src/commands/workflow/epic-cli.js +192 -0
  66. package/src/commands/workflow/select.js +146 -0
  67. package/src/commands/workflow/sprint-cli.js +174 -0
  68. package/src/core/webscrape/analyzer.js +481 -0
  69. package/src/core/webscrape/deep-scraper.js +1027 -0
  70. package/src/core/workflow/epic-manager.js +845 -0
  71. package/src/core/workflow/gates.js +180 -1
  72. package/src/core/workflow/selector.js +707 -0
  73. package/src/embeddings/chunker.js +450 -0
  74. package/src/embeddings/embedder.js +431 -0
  75. package/src/embeddings/index-pipeline.js +320 -0
  76. package/src/embeddings/vector-store.js +505 -0
  77. package/src/mcp-refactor/handlers/boost.js +295 -0
  78. package/src/mcp-refactor/router.js +19 -0
  79. package/src/mcp-refactor/tools.js +113 -0
@@ -0,0 +1,295 @@
1
+ // @use(kind, contract, limit)
2
+ // @kind(util)
3
+ // @contract(in: toolName, args -> out: toolResult)
4
+ // @limit(lines: 250)
5
+
6
+ /**
7
+ * Handlers MCP para OPL Boost.
8
+ *
9
+ * Tools expuestas:
10
+ * boost_generate → Genera código usando el pipeline completo
11
+ * boost_compress → Comprime contexto según perfil
12
+ * boost_profile → Muestra perfil Boost activo y estado del sistema
13
+ * boost_plan → Planifica DAG de micro-tareas
14
+ * boost_validate → Ejecuta validation loop sobre código
15
+ */
16
+
17
+ import { toolResult } from "../utils.js"
18
+ import { boost, generateCode } from "../../boost/orchestrator.js"
19
+ import { getProfile, listProfiles, isBoostEnabled } from "../../boost/profile-registry.js"
20
+ import { compressContext, compressAgentsMd } from "../../boost/context-compressor.js"
21
+ import { plan, detectKind, listKinds } from "../../boost/task-dispatcher.js"
22
+ import { quickValidate, validateCode, buildFeedback, generateReport } from "../../boost/validation-loop.js"
23
+ import {
24
+ checkOllama,
25
+ listOllamaModels,
26
+ } from "../../boost/agent-pool.js"
27
+ import {
28
+ detectHardware,
29
+ getRuntimeStatus,
30
+ getSafeParallelism,
31
+ getRAMWarning,
32
+ } from "../../boost/hardware-detector.js"
33
+
34
+ // ──────────────────────────────────────────────
35
+ // boost_generate
36
+ // ──────────────────────────────────────────────
37
+
38
+ export async function handleBoostGenerate(args) {
39
+ const { description, kind, contextMode, multiAgent, validate } = args
40
+
41
+ if (!description) {
42
+ return toolResult("Error: se requiere 'description' (descripción de la tarea)", true)
43
+ }
44
+
45
+ try {
46
+ const result = await boost(description, {
47
+ kind: kind || undefined,
48
+ contextMode: contextMode || "safe",
49
+ multiAgent: multiAgent || false,
50
+ validate: validate !== false,
51
+ })
52
+
53
+ const output = []
54
+
55
+ if (result.code) {
56
+ output.push("## Código Generado\n")
57
+ output.push("```typescript")
58
+ output.push(result.code)
59
+ output.push("```\n")
60
+ }
61
+
62
+ if (result.report) {
63
+ output.push("## Reporte\n")
64
+ output.push(result.report.summary)
65
+ }
66
+
67
+ if (result.metadata?.stages) {
68
+ output.push("\n## Etapas\n")
69
+ for (const stage of result.metadata.stages) {
70
+ const icon = stage.error ? "✖" : "✓"
71
+ output.push(`- ${icon} ${stage.name}: ${stage.duration || 0}ms`)
72
+ }
73
+ }
74
+
75
+ return toolResult(output.join("\n"))
76
+ } catch (error) {
77
+ return toolResult(`Error en boost_generate: ${error.message}\n${error.stack}`, true)
78
+ }
79
+ }
80
+
81
+ // ──────────────────────────────────────────────
82
+ // boost_compress
83
+ // ──────────────────────────────────────────────
84
+
85
+ export async function handleBoostCompress(args) {
86
+ const { task, context, kind, mode } = args
87
+
88
+ if (!task && !context) {
89
+ return toolResult("Error: se requiere 'task' (descripción de la tarea) o 'context' (contexto markdown)", true)
90
+ }
91
+
92
+ try {
93
+ const profile = getProfile()
94
+ const fullContext = context || ""
95
+ const compressed = compressContext(task || "general", fullContext, profile, {
96
+ mode: mode || "safe",
97
+ kind: kind || "",
98
+ })
99
+
100
+ const output = []
101
+ output.push("## Contexto Comprimido\n")
102
+ output.push(compressed.context)
103
+ output.push("\n## Métricas\n")
104
+ output.push(`- Original: ${compressed.metrics.originalChars} caracteres`)
105
+ output.push(`- Comprimido: ${compressed.metrics.compressedChars} caracteres`)
106
+ output.push(`- Reducción: ${compressed.metrics.reductionPercent}%`)
107
+ output.push(`- Secciones preservadas: ${compressed.metrics.sectionsKept}`)
108
+ output.push(`- Secciones removidas: ${compressed.metrics.sectionsRemoved}`)
109
+ output.push(`- Modo: ${compressed.metrics.mode}`)
110
+
111
+ return toolResult(output.join("\n"))
112
+ } catch (error) {
113
+ return toolResult(`Error en boost_compress: ${error.message}`, true)
114
+ }
115
+ }
116
+
117
+ // ──────────────────────────────────────────────
118
+ // boost_profile
119
+ // ──────────────────────────────────────────────
120
+
121
+ export async function handleBoostProfile(args) {
122
+ const { action } = args // "status", "list", "set"
123
+
124
+ try {
125
+ const enabled = isBoostEnabled()
126
+ const profile = getProfile()
127
+
128
+ if (action === "list") {
129
+ const profiles = listProfiles()
130
+ const lines = ["## Perfiles Boost Disponibles\n"]
131
+ for (const p of profiles) {
132
+ const active = p.name === profile?.name ? " ← activo" : ""
133
+ lines.push(`- **${p.name}**: ${p.description}${active}`)
134
+ lines.push(` - Contexto: ${p.contextWindow.toLocaleString()} tokens, Compresión: ${p.compressionLevel}%`)
135
+ }
136
+ return toolResult(lines.join("\n"))
137
+ }
138
+
139
+ // Default: status
140
+ const runtime = getRuntimeStatus()
141
+ const safety = getSafeParallelism(profile)
142
+
143
+ const lines = [
144
+ "## Estado Boost\n",
145
+ `- **Habilitado**: ${enabled ? "Sí" : "No"}`,
146
+ `- **Perfil activo**: ${profile?.name || "No detectado"}`,
147
+ `- **Descripción**: ${profile?.description || profile?.label || "—"}`,
148
+ `- **Ventana de contexto**: ${profile?.contextWindow?.toLocaleString() || "—"} tokens`,
149
+ `- **Compresión**: ${profile?.compressionLevel || 0}%`,
150
+ `- **Validación loops**: ${profile?.validationLoops || "—"}`,
151
+ `- **Micro-tasking**: ${profile?.microTasks ? "Sí" : "No"}`,
152
+ `- **Template hydration**: ${profile?.templateHydration ? "Sí" : "No"}`,
153
+ `- **Few-shot**: ${profile?.fewShot ? "Sí" : "No"}`,
154
+ "",
155
+ "## Estado del Sistema\n",
156
+ `- **RAM libre**: ${runtime.ram.freeGB} GB / ${runtime.ram.totalGB} GB`,
157
+ `- **CPU load**: ${runtime.cpu.loadAvg1m} / ${runtime.cpu.cores} núcleos`,
158
+ `- **Modo**: ${safety.mode}`,
159
+ `- **Agentes**: ${safety.maxAgents} simultáneo(s)`,
160
+ ]
161
+
162
+ const warning = getRAMWarning()
163
+ if (warning) {
164
+ lines.push(`\n⚠️ ${warning}`)
165
+ }
166
+
167
+ // Ollama status
168
+ try {
169
+ const ollamaUp = await checkOllama()
170
+ lines.push(`\n- **Ollama**: ${ollamaUp ? "🟢 Conectado" : "🔴 No detectado"}`)
171
+ if (ollamaUp) {
172
+ const models = await listOllamaModels()
173
+ if (models.length > 0) {
174
+ lines.push(" - Modelos disponibles:")
175
+ for (const m of models.slice(0, 5)) {
176
+ lines.push(` - ${m.name} (${(m.size / 1024 / 1024 / 1024).toFixed(1)} GB)`)
177
+ }
178
+ }
179
+ }
180
+ } catch {
181
+ lines.push("\n- **Ollama**: No disponible")
182
+ }
183
+
184
+ return toolResult(lines.join("\n"))
185
+ } catch (error) {
186
+ return toolResult(`Error en boost_profile: ${error.message}`, true)
187
+ }
188
+ }
189
+
190
+ // ──────────────────────────────────────────────
191
+ // boost_plan
192
+ // ──────────────────────────────────────────────
193
+
194
+ export async function handleBoostPlan(args) {
195
+ const { task, kind } = args
196
+
197
+ if (!task) {
198
+ return toolResult("Error: se requiere 'task' (descripción de la tarea)", true)
199
+ }
200
+
201
+ try {
202
+ const detectedKind = kind || detectKind(task)
203
+ const dag = plan(task, detectedKind)
204
+
205
+ const lines = [
206
+ "## Plan de Micro-Tareas (DAG)\n",
207
+ `- **Tarea**: ${task}`,
208
+ `- **Kind detectado**: ${detectedKind}`,
209
+ `- **Nodos**: ${dag.nodeCount}`,
210
+ `- **Paralelos**: ${dag.stages.parallel.join(", ") || "ninguno"}`,
211
+ `- **Secuenciales**: ${dag.stages.sequential.join(", ") || "ninguno"}`,
212
+ "",
213
+ "### Nodos\n",
214
+ ]
215
+
216
+ for (const node of dag.nodes) {
217
+ const deps = node.deps.length > 0 ? ` (espera: ${node.deps.join(", ")})` : " (inmediato)"
218
+ lines.push(`- **${node.id}** → ${node.description}${deps}`)
219
+ lines.push(` - Agente: \`${node.agent}\``)
220
+ }
221
+
222
+ lines.push("\n### Aristas\n")
223
+ for (const edge of dag.edges) {
224
+ lines.push(`- \`${edge.from}\` → \`${edge.to}\``)
225
+ }
226
+
227
+ lines.push("\n### Mermaid\n")
228
+ lines.push("```mermaid")
229
+ lines.push("graph TD")
230
+ for (const node of dag.nodes) {
231
+ lines.push(` ${node.id}["${node.description}"]`)
232
+ }
233
+ for (const edge of dag.edges) {
234
+ lines.push(` ${edge.from} --> ${edge.to}`)
235
+ }
236
+ lines.push("```")
237
+
238
+ return toolResult(lines.join("\n"))
239
+ } catch (error) {
240
+ return toolResult(`Error en boost_plan: ${error.message}`, true)
241
+ }
242
+ }
243
+
244
+ // ──────────────────────────────────────────────
245
+ // boost_validate
246
+ // ──────────────────────────────────────────────
247
+
248
+ export async function handleBoostValidate(args) {
249
+ const { code, kind } = args
250
+
251
+ if (!code) {
252
+ return toolResult("Error: se requiere 'code' (código a validar)", true)
253
+ }
254
+
255
+ try {
256
+ // QuickValidate: no necesita Ollama
257
+ const quick = quickValidate(code, kind || "component")
258
+
259
+ // Si se quiere validación completa, ejecutar validateCode
260
+ const full = validateCode(code, kind || "component")
261
+
262
+ const lines = [
263
+ "## Validación Boost\n",
264
+ `- **QuickValidate**: ${quick.valid ? "✅ Pasa" : "❌ Falla"}`,
265
+ ]
266
+
267
+ if (quick.warnings.length > 0) {
268
+ lines.push("\n### Advertencias QuickValidate\n")
269
+ for (const w of quick.warnings) {
270
+ lines.push(`- ⚠️ ${w}`)
271
+ }
272
+ }
273
+
274
+ lines.push(`\n- **Validación OPL**: ${full.valid ? "✅ Pasa" : "❌ Falla"}`)
275
+ if (full.errors.length > 0) {
276
+ lines.push("\n### Errores OPL\n")
277
+ for (const err of full.errors) {
278
+ lines.push(`- ❌ [${err.type}] ${err.message}${err.line > 0 ? ` (línea ${err.line})` : ""}`)
279
+ }
280
+ }
281
+
282
+ if (full.valid && quick.valid) {
283
+ lines.push("\n✅ Código listo para commit.")
284
+ } else {
285
+ lines.push("\n⚠️ Corrige los errores antes de commit.")
286
+ const feedback = buildFeedback(full.errors)
287
+ lines.push("\n### Feedback sugerido\n")
288
+ lines.push(feedback)
289
+ }
290
+
291
+ return toolResult(lines.join("\n"))
292
+ } catch (error) {
293
+ return toolResult(`Error en boost_validate: ${error.message}`, true)
294
+ }
295
+ }
@@ -33,6 +33,13 @@ import {
33
33
  import { handleExecuteSandbox } from "./handlers/sandbox.js"
34
34
  import { handleAnalyzeBlastRadius } from "./handlers/blast.js"
35
35
  import { handleAstPatchMutate } from "./handlers/mutate.js"
36
+ import {
37
+ handleBoostGenerate,
38
+ handleBoostCompress,
39
+ handleBoostProfile,
40
+ handleBoostPlan,
41
+ handleBoostValidate,
42
+ } from "./handlers/boost.js"
36
43
  import { toolResult } from "./utils.js"
37
44
 
38
45
  /**
@@ -118,6 +125,18 @@ export async function handleToolCall(name, args) {
118
125
  case "ast_patch_mutate":
119
126
  return await handleAstPatchMutate(args)
120
127
 
128
+ // Boost — Multi-agent generation pipeline
129
+ case "boost_generate":
130
+ return await handleBoostGenerate(args)
131
+ case "boost_compress":
132
+ return await handleBoostCompress(args)
133
+ case "boost_profile":
134
+ return await handleBoostProfile(args)
135
+ case "boost_plan":
136
+ return await handleBoostPlan(args)
137
+ case "boost_validate":
138
+ return await handleBoostValidate(args)
139
+
121
140
  default:
122
141
  return toolResult(`Unknown tool: ${name}`, true)
123
142
  }
@@ -493,4 +493,117 @@ export const TOOLS = [
493
493
  required: ["target", "action", "codeContent"],
494
494
  },
495
495
  },
496
+ // ──────────────────────────────────────────────
497
+ // OPL Boost — Multi-agent generation pipeline
498
+ // ──────────────────────────────────────────────
499
+ {
500
+ name: "boost_generate",
501
+ description:
502
+ "[BOOST GENERATE] Generate code using the full Boost pipeline. Uses profile detection, context compression, few-shot examples, agent pool, skeleton hydration, and validation loop. Returns generated code with metadata.",
503
+ inputSchema: {
504
+ type: "object",
505
+ properties: {
506
+ description: {
507
+ type: "string",
508
+ description: "Task description (e.g., 'create hook useAuth with Supabase')",
509
+ },
510
+ kind: {
511
+ type: "string",
512
+ description: "File type: hook, component, page, service, store (auto-detected if omitted)",
513
+ },
514
+ contextMode: {
515
+ type: "string",
516
+ description: "Context compression mode: safe, aggressive, disabled (default: safe)",
517
+ },
518
+ multiAgent: {
519
+ type: "boolean",
520
+ description: "Use multi-agent pipeline instead of single-pass (default: false)",
521
+ },
522
+ validate: {
523
+ type: "boolean",
524
+ description: "Run validation loop after generation (default: true)",
525
+ },
526
+ },
527
+ required: ["description"],
528
+ },
529
+ },
530
+ {
531
+ name: "boost_compress",
532
+ description:
533
+ "[BOOST COMPRESS] Compress project context (AGENTS.md) to only sections relevant to a specific task. Returns compressed context with reduction metrics.",
534
+ inputSchema: {
535
+ type: "object",
536
+ properties: {
537
+ task: {
538
+ type: "string",
539
+ description: "Task description for relevance matching (e.g., 'create hook useAuth')",
540
+ },
541
+ context: {
542
+ type: "string",
543
+ description: "Full context markdown to compress (uses project AGENTS.md if omitted)",
544
+ },
545
+ kind: {
546
+ type: "string",
547
+ description: "File type for keyword matching: hook, component, page, service, store",
548
+ },
549
+ mode: {
550
+ type: "string",
551
+ description: "Compression mode: safe (preserves enforcement), aggressive (minimal), disabled (no compression)",
552
+ },
553
+ },
554
+ required: ["task"],
555
+ },
556
+ },
557
+ {
558
+ name: "boost_profile",
559
+ description:
560
+ "[BOOST PROFILE] Show current Boost profile, system status (RAM, CPU, Ollama), and safe parallelism. Use before generating code to check if system can handle agents.",
561
+ inputSchema: {
562
+ type: "object",
563
+ properties: {
564
+ action: {
565
+ type: "string",
566
+ description: "Action: 'status' (default), 'list' (list all profiles)",
567
+ },
568
+ },
569
+ },
570
+ },
571
+ {
572
+ name: "boost_plan",
573
+ description:
574
+ "[BOOST PLAN] Decompose a code generation task into a DAG of micro-tasks. Returns the execution plan with parallel and sequential stages before actually generating code. Use with boost_generate or standalone for planning.",
575
+ inputSchema: {
576
+ type: "object",
577
+ properties: {
578
+ task: {
579
+ type: "string",
580
+ description: "Task description (e.g., 'create hook useAuth with Supabase')",
581
+ },
582
+ kind: {
583
+ type: "string",
584
+ description: "File type: hook, component, page, service, store (auto-detected if omitted)",
585
+ },
586
+ },
587
+ required: ["task"],
588
+ },
589
+ },
590
+ {
591
+ name: "boost_validate",
592
+ description:
593
+ "[BOOST VALIDATE] Run OPL validation and quick-check on generated code. Returns structured errors, warnings, and suggested fixes. Use after boost_generate to verify output quality.",
594
+ inputSchema: {
595
+ type: "object",
596
+ properties: {
597
+ code: {
598
+ type: "string",
599
+ description: "Code to validate",
600
+ },
601
+ kind: {
602
+ type: "string",
603
+ description: "File type for @kind-specific limits: hook (80), component (120), page (200), service (150), store (100)",
604
+ },
605
+ },
606
+ required: ["code"],
607
+ },
608
+ },
496
609
  ]