add-skill-kit 3.2.2 → 3.2.4

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 (72) hide show
  1. package/bin/lib/commands/install.js +67 -45
  2. package/lib/agent-cli/README.md +21 -0
  3. package/lib/agent-cli/bin/ag-smart.js +158 -0
  4. package/lib/agent-cli/lib/audit.js +154 -0
  5. package/lib/agent-cli/lib/audit.test.js +100 -0
  6. package/lib/agent-cli/lib/auto-learn.js +319 -0
  7. package/lib/agent-cli/lib/auto_preview.py +148 -0
  8. package/lib/agent-cli/lib/backup.js +138 -0
  9. package/lib/agent-cli/lib/backup.test.js +78 -0
  10. package/lib/agent-cli/lib/checklist.py +222 -0
  11. package/lib/agent-cli/lib/cognitive-lesson.js +476 -0
  12. package/lib/agent-cli/lib/completion.js +149 -0
  13. package/lib/agent-cli/lib/config.js +35 -0
  14. package/lib/agent-cli/lib/eslint-fix.js +238 -0
  15. package/lib/agent-cli/lib/evolution-signal.js +215 -0
  16. package/lib/agent-cli/lib/export.js +86 -0
  17. package/lib/agent-cli/lib/export.test.js +65 -0
  18. package/lib/agent-cli/lib/fix.js +337 -0
  19. package/lib/agent-cli/lib/fix.test.js +80 -0
  20. package/lib/agent-cli/lib/gemini-export.js +83 -0
  21. package/lib/agent-cli/lib/generate-registry.js +42 -0
  22. package/lib/agent-cli/lib/hooks/install-hooks.js +152 -0
  23. package/lib/agent-cli/lib/hooks/lint-learn.js +172 -0
  24. package/lib/agent-cli/lib/ignore.js +116 -0
  25. package/lib/agent-cli/lib/ignore.test.js +58 -0
  26. package/lib/agent-cli/lib/init.js +124 -0
  27. package/lib/agent-cli/lib/learn.js +255 -0
  28. package/lib/agent-cli/lib/learn.test.js +70 -0
  29. package/lib/agent-cli/lib/migrate-to-v4.js +322 -0
  30. package/lib/agent-cli/lib/proposals.js +199 -0
  31. package/lib/agent-cli/lib/proposals.test.js +56 -0
  32. package/lib/agent-cli/lib/recall.js +820 -0
  33. package/lib/agent-cli/lib/recall.test.js +107 -0
  34. package/lib/agent-cli/lib/selfevolution-bridge.js +167 -0
  35. package/lib/agent-cli/lib/session_manager.py +120 -0
  36. package/lib/agent-cli/lib/settings.js +203 -0
  37. package/lib/agent-cli/lib/skill-learn.js +296 -0
  38. package/lib/agent-cli/lib/stats.js +132 -0
  39. package/lib/agent-cli/lib/stats.test.js +94 -0
  40. package/lib/agent-cli/lib/types.js +33 -0
  41. package/lib/agent-cli/lib/ui/audit-ui.js +146 -0
  42. package/lib/agent-cli/lib/ui/backup-ui.js +107 -0
  43. package/lib/agent-cli/lib/ui/clack-helpers.js +317 -0
  44. package/lib/agent-cli/lib/ui/common.js +83 -0
  45. package/lib/agent-cli/lib/ui/completion-ui.js +126 -0
  46. package/lib/agent-cli/lib/ui/custom-select.js +69 -0
  47. package/lib/agent-cli/lib/ui/dashboard-ui.js +123 -0
  48. package/lib/agent-cli/lib/ui/evolution-signals-ui.js +107 -0
  49. package/lib/agent-cli/lib/ui/export-ui.js +94 -0
  50. package/lib/agent-cli/lib/ui/fix-all-ui.js +191 -0
  51. package/lib/agent-cli/lib/ui/help-ui.js +49 -0
  52. package/lib/agent-cli/lib/ui/index.js +169 -0
  53. package/lib/agent-cli/lib/ui/init-ui.js +56 -0
  54. package/lib/agent-cli/lib/ui/knowledge-ui.js +55 -0
  55. package/lib/agent-cli/lib/ui/learn-ui.js +706 -0
  56. package/lib/agent-cli/lib/ui/lessons-ui.js +148 -0
  57. package/lib/agent-cli/lib/ui/pretty.js +145 -0
  58. package/lib/agent-cli/lib/ui/proposals-ui.js +99 -0
  59. package/lib/agent-cli/lib/ui/recall-ui.js +342 -0
  60. package/lib/agent-cli/lib/ui/routing-demo.js +79 -0
  61. package/lib/agent-cli/lib/ui/routing-ui.js +325 -0
  62. package/lib/agent-cli/lib/ui/settings-ui.js +381 -0
  63. package/lib/agent-cli/lib/ui/stats-ui.js +123 -0
  64. package/lib/agent-cli/lib/ui/watch-ui.js +236 -0
  65. package/lib/agent-cli/lib/verify_all.py +327 -0
  66. package/lib/agent-cli/lib/watcher.js +181 -0
  67. package/lib/agent-cli/lib/watcher.test.js +85 -0
  68. package/lib/agent-cli/package.json +51 -0
  69. package/lib/agentskillskit-cli/README.md +21 -0
  70. package/lib/agentskillskit-cli/ag-smart.js +158 -0
  71. package/lib/agentskillskit-cli/package.json +51 -0
  72. package/package.json +11 -6
@@ -0,0 +1,706 @@
1
+ /**
2
+ * Learn UI - Teach new patterns
3
+ */
4
+ import {
5
+ showIntro,
6
+ showActionMenu,
7
+ textInput,
8
+ confirm,
9
+ createSpinner,
10
+ showSuccessNote,
11
+ showErrorNote,
12
+ showNote,
13
+ theme
14
+ } from "./clack-helpers.js";
15
+ import { getKnowledge } from "./common.js";
16
+ import { saveKnowledge } from "../recall.js";
17
+ import * as p from "@clack/prompts";
18
+ import { spawnSync } from 'child_process';
19
+ import path from 'path';
20
+ import { fileURLToPath } from 'url';
21
+
22
+ export async function runLearnUI() {
23
+ showIntro("📚 Learn New Pattern");
24
+
25
+ // Action menu - Simplified to core functions
26
+ const action = await showActionMenu({
27
+ message: "What would you like to do?",
28
+ items: [
29
+ { value: "view", label: "📚 View Lessons", hint: "Browse all learned patterns" },
30
+ { value: "add", label: "➕ Add Lesson", hint: "Teach a new pattern manually" },
31
+ { value: "remove", label: "🗑️ Remove Lesson", hint: "Delete a pattern" },
32
+ // REMOVED: Query Lessons (niche, AI auto-recalls)
33
+ // REMOVED: Auto-Learn (redundant with Add)
34
+ // REMOVED: Status/Versions/History (broken execCommand, low value)
35
+ ],
36
+ includeExit: true
37
+ });
38
+
39
+ // ESC returns to main menu (don't execute action)
40
+ if (p.isCancel(action)) {
41
+ return;
42
+ }
43
+
44
+ switch (action) {
45
+ case "view":
46
+ await viewLessonsFlow();
47
+ break;
48
+ case "add":
49
+ await addLessonFlow();
50
+ break;
51
+ case "remove":
52
+ await removeLessonFlow();
53
+ break;
54
+ // REMOVED CASES (commented out for rollback):
55
+ // case "status": await statusFlow(); break;
56
+ // case "query": await queryLessonsFlow(); break;
57
+ // case "auto": await autoLearnFlow(); break;
58
+ // case "versions": await versionsFlow(); break;
59
+ // case "history": await historyFlow(); break;
60
+ }
61
+ }
62
+
63
+ // ============================================================================
64
+ // CORE FLOWS - Simplified Menu
65
+ // ============================================================================
66
+
67
+ /**
68
+ * View all learned lessons (Cognitive Engine v4.x)
69
+ * Displays synthesis of mistakes + improvements
70
+ */
71
+ async function viewLessonsFlow() {
72
+ // Import cognitive engine
73
+ const { synthesizeLessons } = await import('../cognitive-lesson.js');
74
+
75
+ const lessons = synthesizeLessons();
76
+
77
+ if (lessons.length === 0) {
78
+ showErrorNote("No lessons learned yet. Use 'Add Lesson' to teach your first pattern!", "No Lessons");
79
+ return;
80
+ }
81
+
82
+ // Build enhanced cognitive view
83
+ const content = lessons.map((lesson, i) => {
84
+ // State icon
85
+ const stateIcons = {
86
+ 'RAW': '🟥',
87
+ 'LEARNING': '🟨',
88
+ 'MATURE': '🟩',
89
+ 'IDEAL': '🟦',
90
+ };
91
+ const stateIcon = stateIcons[lesson.maturity.state] || '⚪';
92
+
93
+ const mistakeCount = lesson.mistakes.length;
94
+ const improveCount = lesson.improvements.length;
95
+
96
+ // Build lesson display
97
+ const parts = [
98
+ `${theme.primary(`${i + 1}.`)} ${stateIcon} ${theme.bold(lesson.id)}: ${lesson.title}`,
99
+ ` ${theme.dim(`Intent: ${lesson.intent.goal} (${Math.round(lesson.intent.strength * 100)}%)`)}`,
100
+ ` ${theme.dim(`Confidence: ${Math.round(lesson.maturity.confidence * 100)}% | ${lesson.maturity.recommendation}`)}`,
101
+ '',
102
+ ` 🔴 Mistakes (${mistakeCount})`,
103
+ ];
104
+
105
+ // Show first 2 mistakes
106
+ if (mistakeCount > 0) {
107
+ lesson.mistakes.slice(0, 2).forEach(m => {
108
+ parts.push(` • ${theme.dim(m.title || m.message.substring(0, 60))}`);
109
+ });
110
+ if (mistakeCount > 2) {
111
+ parts.push(` ${theme.dim(`... and ${mistakeCount - 2} more`)}`);
112
+ }
113
+ } else {
114
+ parts.push(` ${theme.dim('None')}`);
115
+ }
116
+
117
+ parts.push('');
118
+ parts.push(` 🟢 Improvements (${improveCount})`);
119
+
120
+ // Show first 2 improvements
121
+ if (improveCount > 0) {
122
+ lesson.improvements.slice(0, 2).forEach(imp => {
123
+ parts.push(` • ${theme.dim(imp.title || imp.message.substring(0, 60))}`);
124
+ });
125
+ if (improveCount > 2) {
126
+ parts.push(` ${theme.dim(`... and ${improveCount - 2} more`)}`);
127
+ }
128
+ } else {
129
+ parts.push(` ${theme.warning('⚠️ No best practices learned yet')}`);
130
+ }
131
+
132
+ // Show evolution signals if any
133
+ if (lesson.evolution.signals.length > 0) {
134
+ parts.push('');
135
+ parts.push(` 💡 Evolution Signals:`);
136
+ lesson.evolution.signals.slice(0, 1).forEach(signal => {
137
+ parts.push(` ${signal.type}: ${signal.reason}`);
138
+ });
139
+ }
140
+
141
+ return parts.join('\n');
142
+ }).join('\n\n');
143
+
144
+ showSuccessNote(content, `🧠 Cognitive Lessons (${lessons.length})`);
145
+
146
+ // Wait for user to read
147
+ await p.text({
148
+ message: "Press Enter to continue...",
149
+ placeholder: "",
150
+ initialValue: "",
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Add a new lesson manually
156
+ * Renamed from addPatternFlow for consistency
157
+ */
158
+ async function addLessonFlow() {
159
+ const pattern = await textInput({
160
+ message: "Pattern to detect:",
161
+ placeholder: "e.g., console.log",
162
+ validate: (value) => {
163
+ if (!value) return "Please enter a pattern";
164
+ }
165
+ });
166
+
167
+ if (p.isCancel(pattern)) {
168
+ p.cancel("Cancelled.");
169
+ return;
170
+ }
171
+
172
+ const message = await textInput({
173
+ message: "Error message:",
174
+ placeholder: "e.g., Remove console.log in production",
175
+ validate: (value) => {
176
+ if (!value) return "Please enter a message";
177
+ }
178
+ });
179
+
180
+ if (p.isCancel(message)) {
181
+ p.cancel("Cancelled.");
182
+ return;
183
+ }
184
+
185
+ const severity = await p.select({
186
+ message: "Severity level:",
187
+ options: [
188
+ { value: "ERROR", label: "Error", hint: "Critical issue" },
189
+ { value: "WARNING", label: "Warning", hint: "Should be fixed" },
190
+ ]
191
+ });
192
+
193
+ if (p.isCancel(severity)) {
194
+ p.cancel("Operation cancelled.");
195
+ return;
196
+ }
197
+
198
+ const confirmed = await confirm(
199
+ `Add pattern "${theme.primary(pattern)}" with message "${message}"?`,
200
+ true
201
+ );
202
+
203
+ if (!confirmed) {
204
+ p.cancel("Cancelled.");
205
+ return;
206
+ }
207
+
208
+ const spinner = createSpinner("Adding lesson...");
209
+
210
+ try {
211
+ const db = getKnowledge();
212
+ const id = `LEARN-${String(db.lessons.length + 1).padStart(3, '0')}`;
213
+
214
+ const lesson = {
215
+ id,
216
+ pattern,
217
+ message,
218
+ severity,
219
+ hitCount: 0,
220
+ added: new Date().toISOString()
221
+ };
222
+
223
+ db.lessons.push(lesson);
224
+ saveKnowledge(db);
225
+
226
+ spinner.stopSuccess("Lesson added");
227
+
228
+ showSuccessNote(
229
+ `${theme.primary('Pattern:')} ${pattern}\n` +
230
+ `${theme.primary('Message:')} ${message}\n` +
231
+ `${theme.primary('Severity:')} ${severity}`,
232
+ `✓ Lesson ${id} Added`
233
+ );
234
+ } catch (error) {
235
+ spinner.stopError("Failed to add lesson");
236
+ showErrorNote(error.message, "✗ Error");
237
+ }
238
+
239
+ // Wait to continue
240
+ await p.text({
241
+ message: "Press Enter to continue...",
242
+ placeholder: "",
243
+ initialValue: "",
244
+ });
245
+ }
246
+
247
+ /**
248
+ * Remove a lesson by ID
249
+ * Renamed from removePatternFlow for consistency
250
+ */
251
+ async function removeLessonFlow() {
252
+ const db = getKnowledge();
253
+ const patterns = db.lessons || [];
254
+
255
+ if (patterns.length === 0) {
256
+ showErrorNote("No patterns to remove.", "No Patterns");
257
+ return;
258
+ }
259
+
260
+ // Show list first
261
+ const listContent = patterns.map((p, i) =>
262
+ `${theme.primary(p.id)}: ${p.message}`
263
+ ).join('\n');
264
+
265
+ showNote(listContent, "Available Patterns");
266
+
267
+ const patternId = await textInput({
268
+ message: "Pattern ID to remove:",
269
+ placeholder: "e.g., LEARN-001",
270
+ validate: (value) => {
271
+ if (!value) return "Please enter a pattern ID";
272
+ if (!patterns.find(p => p.id === value)) {
273
+ return `Pattern ${value} not found`;
274
+ }
275
+ }
276
+ });
277
+
278
+ if (p.isCancel(patternId)) {
279
+ p.cancel("Cancelled.");
280
+ return;
281
+ }
282
+
283
+ const confirmed = await confirm(
284
+ `Remove pattern ${theme.primary(patternId)}?`,
285
+ false
286
+ );
287
+
288
+ if (!confirmed) {
289
+ p.cancel("Cancelled.");
290
+ return;
291
+ }
292
+
293
+ db.lessons = db.lessons.filter(l => l.id !== patternId);
294
+ saveKnowledge(db);
295
+
296
+ showSuccessNote(`Pattern ${patternId} removed`, "✓ Removed");
297
+
298
+ // Wait to continue
299
+ await p.text({
300
+ message: "Press Enter to continue...",
301
+ placeholder: "",
302
+ initialValue: "",
303
+ });
304
+ }
305
+
306
+ // ============================================================================
307
+ // DEPRECATED FUNCTIONS (Kept for rollback safety)
308
+ // ============================================================================
309
+
310
+ // DEPRECATED: Query Lessons - Low usage, AI auto-recalls
311
+ /*
312
+ async function queryLessonsFlow() {
313
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
314
+ const scriptPath = path.join(__dirname, '../../../../.agent/skills/SelfEvolution/scripts/query_lessons.py');
315
+
316
+ p.note("Query learns what you learned before to avoid repeating mistakes.\nDescribe what you're about to code.", theme.primary("🔍 Query Lessons"));
317
+
318
+ // Get coding context
319
+ const context = await textInput({
320
+ message: "What are you about to code?",
321
+ placeholder: "e.g., menu navigation with ESC handling",
322
+ validate: (value) => {
323
+ if (!value || value.length < 5) return "Please describe what you're coding (min 5 chars)";
324
+ }
325
+ });
326
+
327
+ if (p.isCancel(context)) {
328
+ p.cancel("Cancelled.");
329
+ return;
330
+ }
331
+
332
+ // Optional scope filter
333
+ const wantScope = await confirm("Filter by scope?", false);
334
+
335
+ let scope = null;
336
+ if (wantScope) {
337
+ const scopeOptions = [
338
+ { value: "cli-navigation", label: "CLI Navigation" },
339
+ { value: "api-design", label: "API Design" },
340
+ { value: "code-quality", label: "Code Quality" },
341
+ { value: "file-safety", label: "File Safety" },
342
+ { value: "user-experience", label: "User Experience" },
343
+ ];
344
+
345
+ scope = await p.select({
346
+ message: "Select scope:",
347
+ options: scopeOptions
348
+ });
349
+
350
+ if (p.isCancel(scope)) {
351
+ p.cancel("Cancelled.");
352
+ return;
353
+ }
354
+ }
355
+
356
+ const spinner = createSpinner("Querying lessons...");
357
+
358
+ try {
359
+ // Call Python script
360
+ const args = [scriptPath, context];
361
+ if (scope) {
362
+ args.push('--scope', scope);
363
+ }
364
+ args.push('--json');
365
+
366
+ const result = spawnSync('python', args, {
367
+ encoding: 'utf-8',
368
+ cwd: path.join(__dirname, '../../../..')
369
+ });
370
+
371
+ spinner.stop("Query complete");
372
+
373
+ if (result.error) {
374
+ throw new Error(`Failed to run query_lessons.py: ${result.error.message}`);
375
+ }
376
+
377
+ if (result.status !== 0) {
378
+ throw new Error(`query_lessons.py failed: ${result.stderr || result.stdout}`);
379
+ }
380
+
381
+ const lessons = JSON.parse(result.stdout);
382
+
383
+ if (lessons.length === 0) {
384
+ showNote("No relevant lessons found for this context.", "📭 No Matches");
385
+ return;
386
+ }
387
+
388
+ // Display lessons
389
+ let output = `Found ${theme.primary(lessons.length)} relevant lesson(s):\n\n`;
390
+
391
+ for (const lesson of lessons) {
392
+ const relevance = Math.round(lesson.relevance * 100);
393
+ output += `${theme.primary('[' + lesson.id + ']')} ${relevance}% relevant | ${lesson.severity}\n`;
394
+ output += `${lesson.message}\n`;
395
+ if (lesson.scope) {
396
+ output += `${theme.dim('Scope: ' + lesson.scope)}\n`;
397
+ }
398
+ output += '\n';
399
+ }
400
+
401
+ output += theme.dim("💡 Use these lessons to avoid repeating past mistakes!");
402
+
403
+ showSuccessNote(output, `📚 ${lessons.length} Lesson(s) Found`);
404
+
405
+ } catch (error) {
406
+ spinner.stop("Failed");
407
+ showErrorNote(`Error: ${error.message}`, "❌ Query Failed");
408
+ }
409
+ }
410
+ */
411
+
412
+ // DEPRECATED: Auto-Learn - Redundant with Add Lesson
413
+ /*
414
+ async function autoLearnFlow() {
415
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
416
+ const scriptPath = path.join(__dirname, '../../../../.agent/skills/SelfEvolution/scripts/auto_learn.py');
417
+
418
+ p.note("Auto-learn helps you capture mistakes automatically.\nDescribe what went wrong and what should be done instead.", theme.primary("📚 Auto-Learn"));
419
+
420
+ // Get mistake description
421
+ const mistake = await textInput({
422
+ message: "What went wrong?",
423
+ placeholder: "e.g., Used customSelect instead of p.select",
424
+ validate: (value) => {
425
+ if (!value || value.length < 10) return "Please describe the mistake (min 10 chars)";
426
+ }
427
+ });
428
+
429
+ if (p.isCancel(mistake)) {
430
+ p.cancel("Cancelled.");
431
+ return;
432
+ }
433
+
434
+ // Get correction
435
+ const correction = await textInput({
436
+ message: "What should be done instead?",
437
+ placeholder: "e.g., Always use p.select() + p.isCancel()",
438
+ validate: (value) => {
439
+ if (!value || value.length < 10) return "Please describe the correction (min 10 chars)";
440
+ }
441
+ });
442
+
443
+ if (p.isCancel(correction)) {
444
+ p.cancel("Cancelled.");
445
+ return;
446
+ }
447
+
448
+ // Get impact
449
+ const impact = await textInput({
450
+ message: "What was the impact?",
451
+ placeholder: "e.g., Menu navigation broken, ESC key stuck",
452
+ validate: (value) => {
453
+ if (!value) return "Please describe the impact";
454
+ }
455
+ });
456
+
457
+ if (p.isCancel(impact)) {
458
+ p.cancel("Cancelled.");
459
+ return;
460
+ }
461
+
462
+ const spinner = createSpinner("Extracting lesson...");
463
+
464
+ try {
465
+ // Call Python script to add lesson
466
+ const context = JSON.stringify({
467
+ mistake,
468
+ correction,
469
+ impact,
470
+ mistake_type: "auto-detected"
471
+ });
472
+
473
+ const result = spawnSync('python', [scriptPath, 'add', '--context', context], {
474
+ encoding: 'utf-8',
475
+ cwd: path.join(__dirname, '../../../..')
476
+ });
477
+
478
+ spinner.stop("Lesson extracted");
479
+
480
+ if (result.error) {
481
+ throw new Error(`Failed to run auto_learn.py: ${result.error.message}`);
482
+ }
483
+
484
+ if (result.status !== 0) {
485
+ throw new Error(`auto_learn.py failed: ${result.stderr || result.stdout}`);
486
+ }
487
+
488
+ const output = JSON.parse(result.stdout);
489
+
490
+ if (!output.success) {
491
+ showErrorNote(output.message, "❌ Failed");
492
+ return;
493
+ }
494
+
495
+ showSuccessNote(
496
+ `Lesson ID: ${theme.primary(output.lesson_id)}\n` +
497
+ `Pattern: ${theme.dim(output.lesson.pattern)}\n` +
498
+ `Message: ${output.lesson.message}`,
499
+ `📚 Đã học: ${output.lesson_id}`
500
+ );
501
+
502
+ } catch (error) {
503
+ spinner.stop("Failed");
504
+ showErrorNote(`Error: ${error.message}`, "❌ Auto-Learn Failed");
505
+ }
506
+ }
507
+ */
508
+
509
+ // DEPRECATED: Old addPatternFlow - Replaced by addLessonFlow
510
+ /*
511
+ async function addPatternFlow() {
512
+ const pattern = await textInput({
513
+ message: "Pattern to detect:",
514
+ placeholder: "e.g., console.log",
515
+ validate: (value) => {
516
+ if (!value) return "Please enter a pattern";
517
+ }
518
+ });
519
+
520
+ const message = await textInput({
521
+ message: "Error message:",
522
+ placeholder: "e.g., Remove console.log in production",
523
+ validate: (value) => {
524
+ if (!value) return "Please enter a message";
525
+ }
526
+ });
527
+
528
+ const severity = await p.select({
529
+ message: "Severity level:",
530
+ options: [
531
+ { value: "ERROR", label: "Error", hint: "Critical issue" },
532
+ { value: "WARNING", label: "Warning", hint: "Should be fixed" },
533
+ ]
534
+ });
535
+
536
+ if (p.isCancel(severity)) {
537
+ p.cancel("Operation cancelled.");
538
+ return;
539
+ }
540
+
541
+ const confirmed = await confirm(
542
+ `Add pattern "${theme.primary(pattern)}" with message "${message}"?`,
543
+ true
544
+ );
545
+
546
+ if (!confirmed) {
547
+ p.cancel("Cancelled.");
548
+ return;
549
+ }
550
+
551
+ const spinner = createSpinner("Adding lesson...");
552
+
553
+ try {
554
+ const db = getKnowledge();
555
+ const id = `LEARN-${String(db.lessons.length + 1).padStart(3, '0')}`;
556
+
557
+ const lesson = {
558
+ id,
559
+ pattern,
560
+ message,
561
+ severity,
562
+ hitCount: 0,
563
+ added: new Date().toISOString()
564
+ };
565
+
566
+ db.lessons.push(lesson);
567
+ saveKnowledge(db);
568
+
569
+ spinner.stopSuccess("Lesson added");
570
+
571
+ showSuccessNote(
572
+ `${theme.primary('Pattern:')} ${pattern}\n` +
573
+ `${theme.primary('Message:')} ${message}\n` +
574
+ `${theme.primary('Severity:')} ${severity}`,
575
+ `✓ Lesson ${id} Added`
576
+ );
577
+ } catch (error) {
578
+ spinner.stopError("Failed to add lesson");
579
+ showErrorNote(error.message, "✗ Error");
580
+ }
581
+ }
582
+ */
583
+
584
+ // DEPRECATED: Old listPatternsFlow - Replaced by viewLessonsFlow
585
+ /*
586
+ async function listPatternsFlow() {
587
+ const db = getKnowledge();
588
+ const patterns = db.lessons || [];
589
+
590
+ if (patterns.length === 0) {
591
+ showErrorNote("No patterns learned yet.", "No Patterns");
592
+ return;
593
+ }
594
+
595
+ const content = patterns.map((p, i) =>
596
+ `${theme.primary(`${i + 1}.`)} ${theme.bold(p.id)}: ${p.pattern}\n` +
597
+ ` ${theme.dim(p.message)} ${theme.cyan(`[${p.severity}]`)}`
598
+ ).join('\n\n');
599
+
600
+ showSuccessNote(content, `📚 Learned Patterns (${patterns.length})`);
601
+ }
602
+ */
603
+
604
+ // DEPRECATED: Old removePatternFlow - Replaced by removeLessonFlow
605
+ /*
606
+ async function removePatternFlow() {
607
+ const db = getKnowledge();
608
+ const patterns = db.lessons || [];
609
+
610
+ if (patterns.length === 0) {
611
+ showErrorNote("No patterns to remove.", "No Patterns");
612
+ return;
613
+ }
614
+
615
+ const patternId = await textInput({
616
+ message: "Pattern ID to remove:",
617
+ placeholder: "e.g., LEARN-001",
618
+ validate: (value) => {
619
+ if (!value) return "Please enter a pattern ID";
620
+ if (!patterns.find(p => p.id === value)) {
621
+ return `Pattern ${value} not found`;
622
+ }
623
+ }
624
+ });
625
+
626
+ const confirmed = await confirm(
627
+ `Remove pattern ${theme.primary(patternId)}?`,
628
+ false
629
+ );
630
+
631
+ if (!confirmed) {
632
+ p.cancel("Cancelled.");
633
+ return;
634
+ }
635
+
636
+ db.lessons = db.lessons.filter(l => l.id !== patternId);
637
+ saveKnowledge(db);
638
+
639
+ showSuccessNote(`Pattern ${patternId} removed`, "✓ Removed");
640
+ }
641
+ */
642
+
643
+ // ============================================================================
644
+ // DEPRECATED: v4.0 Flows (execCommand undefined, broken)
645
+ // ============================================================================
646
+
647
+ /*
648
+ async function statusFlow() {
649
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
650
+ const scriptPath = path.join(__dirname, '../../../../.agent/skills/SelfEvolution/scripts/learning_status.py');
651
+
652
+ p.note("View active mistakes and improvements for this project", theme.primary("📊 Learning Status"));
653
+
654
+ try {
655
+ const result = await execCommand('python', [scriptPath, 'status'], '.');
656
+
657
+ if (result.code === 0) {
658
+ showInfoNote(`${result.output}`, "📊 Learning Status");
659
+ } else {
660
+ showErrorNote(`Failed to get status:\n${result.error}`, "Error");
661
+ }
662
+ } catch (error) {
663
+ showErrorNote(`Python script failed: ${error.message}`, "Error");
664
+ }
665
+ }
666
+
667
+ async function versionsFlow() {
668
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
669
+ const scriptPath = path.join(__dirname, '../../../../.agent/skills/SelfEvolution/scripts/learning_status.py');
670
+
671
+ p.note("View version history of your learnings", theme.primary("📚 Version History"));
672
+
673
+ try {
674
+ const result = await execCommand('python', [scriptPath, 'versions'], '.');
675
+
676
+ if (result.code === 0) {
677
+ showInfoNote(`${result.output}`, "📚 Versions");
678
+ } else {
679
+ showErrorNote(`Failed to get versions:\n${result.error}`, "Error");
680
+ }
681
+ } catch (error) {
682
+ showErrorNote(`Python script failed: ${error.message}`, "Error");
683
+ }
684
+ }
685
+
686
+ async function historyFlow() {
687
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
688
+ const scriptPath = path.join(__dirname, '../../../../.agent/skills/SelfEvolution/scripts/learning_status.py');
689
+
690
+ p.note("View self-improve cycle history", theme.primary("🔄 Self-Improve History"));
691
+
692
+ try {
693
+ const result = await execCommand('python', [scriptPath, 'history'], '.');
694
+
695
+ if (result.code === 0) {
696
+ showInfoNote(`${result.output}`, "🔄 History");
697
+ } else {
698
+ showErrorNote(`Failed to get history:\n${result.error}`, "Error");
699
+ }
700
+ } catch (error) {
701
+ showErrorNote(`Python script failed: ${error.message}`, "Error");
702
+ }
703
+ }
704
+ */
705
+
706
+ export default runLearnUI;