pikakit 1.0.36 → 1.0.37

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.
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Command Failure Learner v1.0
3
+ *
4
+ * Learns from terminal command failures and prevents recurring mistakes.
5
+ * Part of PikaKit AutoLearn system.
6
+ *
7
+ * @version 1.0.0
8
+ * @author PikaKit
9
+ */
10
+
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+ import { addLesson, loadKnowledge } from './knowledge.js';
14
+
15
+ // ============================================================================
16
+ // KNOWN COMMAND FAILURE PATTERNS
17
+ // ============================================================================
18
+
19
+ /**
20
+ * Pre-defined patterns for common command failures
21
+ * These are learned from real-world agent execution errors
22
+ */
23
+ const COMMAND_PATTERNS = [
24
+ {
25
+ id: 'CMD-001',
26
+ match: /&& is not a valid statement separator/i,
27
+ shell: 'powershell',
28
+ message: 'PowerShell không hỗ trợ &&. Dùng ; hoặc chạy lệnh riêng biệt.',
29
+ fix: 'Replace && with ; or run commands separately',
30
+ severity: 'ERROR'
31
+ },
32
+ {
33
+ id: 'CMD-002',
34
+ match: /pre-commit.*hook.*(failed|exit|error)/i,
35
+ shell: 'all',
36
+ message: 'Pre-commit hook failed. Thử dùng --no-verify flag.',
37
+ fix: 'git commit --no-verify -m "message"',
38
+ severity: 'WARNING'
39
+ },
40
+ {
41
+ id: 'CMD-003',
42
+ match: /ENOENT.*npm|npm.*not found/i,
43
+ shell: 'all',
44
+ message: 'npm không tìm thấy. Chạy npm install trước.',
45
+ fix: 'Run npm install first',
46
+ severity: 'ERROR'
47
+ },
48
+ {
49
+ id: 'CMD-004',
50
+ match: /Cannot find module/i,
51
+ shell: 'all',
52
+ message: 'Module không tìm thấy. Kiểm tra dependencies.',
53
+ fix: 'Run npm install or check import path',
54
+ severity: 'ERROR'
55
+ },
56
+ {
57
+ id: 'CMD-005',
58
+ match: /permission denied/i,
59
+ shell: 'all',
60
+ message: 'Permission denied. Cần quyền admin hoặc sudo.',
61
+ fix: 'Run with elevated permissions',
62
+ severity: 'ERROR'
63
+ },
64
+ {
65
+ id: 'CMD-006',
66
+ match: /EADDRINUSE.*port/i,
67
+ shell: 'all',
68
+ message: 'Port đang được sử dụng bởi process khác.',
69
+ fix: 'Kill existing process or use different port',
70
+ severity: 'ERROR'
71
+ },
72
+ {
73
+ id: 'CMD-007',
74
+ match: /fatal: not a git repository/i,
75
+ shell: 'all',
76
+ message: 'Không phải git repository. Cần git init trước.',
77
+ fix: 'Run git init or navigate to correct directory',
78
+ severity: 'ERROR'
79
+ },
80
+ {
81
+ id: 'CMD-008',
82
+ match: /npm ERR! code ERESOLVE/i,
83
+ shell: 'all',
84
+ message: 'Dependency conflict. Thử --legacy-peer-deps.',
85
+ fix: 'npm install --legacy-peer-deps',
86
+ severity: 'WARNING'
87
+ },
88
+ {
89
+ id: 'CMD-009',
90
+ match: /the term .* is not recognized/i,
91
+ shell: 'powershell',
92
+ message: 'Command không được nhận dạng trong PowerShell.',
93
+ fix: 'Check command name or install required tool',
94
+ severity: 'ERROR'
95
+ },
96
+ {
97
+ id: 'CMD-010',
98
+ match: /TypeError|ReferenceError|SyntaxError/i,
99
+ shell: 'all',
100
+ message: 'JavaScript runtime error.',
101
+ fix: 'Check code syntax and variable definitions',
102
+ severity: 'ERROR'
103
+ }
104
+ ];
105
+
106
+ // ============================================================================
107
+ // CORE FUNCTIONS
108
+ // ============================================================================
109
+
110
+ /**
111
+ * Analyze command output for failure patterns
112
+ * @param {string} command - The command that was executed
113
+ * @param {string} output - The command output/error message
114
+ * @param {number} exitCode - Command exit code
115
+ * @param {string} shell - Shell type (powershell, bash, cmd)
116
+ * @returns {Object|null} - Matched pattern with suggestion, or null
117
+ */
118
+ export function analyzeFailure(command, output, exitCode, shell = 'powershell') {
119
+ // Only analyze failures (non-zero exit code)
120
+ if (exitCode === 0) return null;
121
+
122
+ const outputLower = (output || '').toLowerCase();
123
+ const commandLower = (command || '').toLowerCase();
124
+
125
+ for (const pattern of COMMAND_PATTERNS) {
126
+ // Check if pattern applies to this shell
127
+ if (pattern.shell !== 'all' && pattern.shell !== shell) continue;
128
+
129
+ // Test against output
130
+ if (pattern.match.test(output)) {
131
+ return {
132
+ patternId: pattern.id,
133
+ command,
134
+ shell,
135
+ message: pattern.message,
136
+ fix: pattern.fix,
137
+ severity: pattern.severity,
138
+ matchedPattern: pattern.match.toString()
139
+ };
140
+ }
141
+ }
142
+
143
+ return null;
144
+ }
145
+
146
+ /**
147
+ * Learn from a command failure and save to knowledge base
148
+ * @param {string} command - The failed command
149
+ * @param {string} output - Error output
150
+ * @param {number} exitCode - Exit code
151
+ * @param {string} shell - Shell type
152
+ * @returns {boolean} - True if lesson was learned/matched
153
+ */
154
+ export function learnFromFailure(command, output, exitCode, shell = 'powershell') {
155
+ const analysis = analyzeFailure(command, output, exitCode, shell);
156
+
157
+ if (!analysis) {
158
+ // Unknown pattern - could add to pending for review
159
+ console.log('[CommandLearner] Unknown failure pattern, no lesson available');
160
+ return false;
161
+ }
162
+
163
+ console.log(`[CommandLearner] Detected: ${analysis.patternId}`);
164
+ console.log(`[CommandLearner] Fix: ${analysis.fix}`);
165
+
166
+ // Check if already in knowledge base
167
+ const knowledge = loadKnowledge();
168
+ const existing = knowledge.lessons.find(l => l.id === analysis.patternId);
169
+
170
+ if (existing) {
171
+ console.log(`[CommandLearner] Pattern ${analysis.patternId} already known`);
172
+ return true;
173
+ }
174
+
175
+ // Add as new lesson
176
+ const lesson = {
177
+ id: analysis.patternId,
178
+ type: 'command',
179
+ shell: analysis.shell,
180
+ pattern: analysis.matchedPattern,
181
+ message: analysis.message,
182
+ severity: analysis.severity,
183
+ intent: 'prevent',
184
+ confidence: 0.9,
185
+ maturity: 'stable',
186
+ hitCount: 1,
187
+ lastHit: new Date().toISOString(),
188
+ excludePaths: [],
189
+ tags: ['command', 'shell', analysis.shell],
190
+ autoFix: { suggestion: analysis.fix }
191
+ };
192
+
193
+ const added = addLesson(lesson);
194
+ if (added) {
195
+ console.log(`[CommandLearner] Learned new pattern: ${analysis.patternId}`);
196
+ }
197
+
198
+ return true;
199
+ }
200
+
201
+ /**
202
+ * Get suggestion for a command before execution
203
+ * Checks if command matches any known failure patterns
204
+ * @param {string} command - Command to check
205
+ * @param {string} shell - Target shell
206
+ * @returns {Object|null} - Warning if pattern detected
207
+ */
208
+ export function checkCommandBeforeExec(command, shell = 'powershell') {
209
+ // Pre-execution checks
210
+ if (shell === 'powershell' && command.includes('&&')) {
211
+ return {
212
+ warning: true,
213
+ patternId: 'CMD-001',
214
+ message: 'PowerShell không hỗ trợ &&. Dùng ; thay thế.',
215
+ suggestedCommand: command.replace(/\s*&&\s*/g, '; ')
216
+ };
217
+ }
218
+
219
+ return null;
220
+ }
221
+
222
+ /**
223
+ * Get all known command patterns
224
+ * @returns {Array} - Array of patterns
225
+ */
226
+ export function getKnownPatterns() {
227
+ return COMMAND_PATTERNS.map(p => ({
228
+ id: p.id,
229
+ shell: p.shell,
230
+ message: p.message,
231
+ severity: p.severity
232
+ }));
233
+ }
234
+
235
+ /**
236
+ * Get pattern count
237
+ * @returns {number}
238
+ */
239
+ export function getPatternCount() {
240
+ return COMMAND_PATTERNS.length;
241
+ }
242
+
243
+ // ============================================================================
244
+ // EXPORTS
245
+ // ============================================================================
246
+
247
+ export default {
248
+ analyzeFailure,
249
+ learnFromFailure,
250
+ checkCommandBeforeExec,
251
+ getKnownPatterns,
252
+ getPatternCount,
253
+ COMMAND_PATTERNS
254
+ };
@@ -9,7 +9,8 @@
9
9
  */
10
10
 
11
11
  import { getKPIs, getMetricValue, getMetricHistory } from './metrics-collector.js';
12
- import { loadKnowledge } from './knowledge.js';
12
+ import { loadKnowledge, getCommandLessons } from './knowledge.js';
13
+ import { getPatternCount } from './command-failure-learner.js';
13
14
 
14
15
  // ============================================================================
15
16
  // DASHBOARD DATA AGGREGATION
@@ -24,15 +25,19 @@ export function getFullDashboardData() {
24
25
  const kpis = getKPIs();
25
26
  const knowledge = loadKnowledge();
26
27
  const lessons = knowledge.lessons || [];
28
+ const commandLessons = getCommandLessons();
29
+ const commandPatternCount = getPatternCount();
27
30
 
28
31
  return {
29
- version: '7.0.0',
32
+ version: '7.1.0',
30
33
  timestamp: new Date().toISOString(),
31
34
  kpis,
32
35
  summary: {
33
36
  totalTasks: getMetricValue('total_tasks') || 0,
34
37
  patternsLearned: lessons.length,
35
38
  lessonsCount: lessons.length,
39
+ commandPatterns: commandPatternCount,
40
+ commandLessonsLearned: commandLessons.length,
36
41
  skillsGenerated: 0,
37
42
  abTestsActive: 0
38
43
  },
@@ -32,8 +32,9 @@ const LEGACY_FILES = {
32
32
 
33
33
  /**
34
34
  * @typedef {Object} Lesson
35
- * @property {string} id - Unique identifier (LESSON-XXX)
36
- * @property {string} type - Type: 'mistake' | 'improvement' | 'pattern'
35
+ * @property {string} id - Unique identifier (LESSON-XXX or CMD-XXX)
36
+ * @property {string} type - Type: 'mistake' | 'improvement' | 'pattern' | 'command'
37
+ * @property {string} [shell] - Shell type for command lessons: 'powershell' | 'bash' | 'all'
37
38
  * @property {string} pattern - Regex pattern to match
38
39
  * @property {string} message - Human-readable explanation
39
40
  * @property {string} severity - 'ERROR' | 'WARNING' | 'INFO'
@@ -283,7 +284,7 @@ export function removeLesson(id) {
283
284
 
284
285
  /**
285
286
  * Get lessons by type
286
- * @param {'mistake' | 'improvement' | 'pattern'} type
287
+ * @param {'mistake' | 'improvement' | 'pattern' | 'command'} type
287
288
  * @returns {Lesson[]}
288
289
  */
289
290
  export function getLessonsByType(type) {
@@ -291,6 +292,20 @@ export function getLessonsByType(type) {
291
292
  return knowledge.lessons.filter(l => l.type === type);
292
293
  }
293
294
 
295
+ /**
296
+ * Get command-type lessons (for Command Failure Learner)
297
+ * @param {string} [shell] - Optional filter by shell type
298
+ * @returns {Lesson[]}
299
+ */
300
+ export function getCommandLessons(shell = null) {
301
+ const knowledge = loadKnowledge();
302
+ return knowledge.lessons.filter(l => {
303
+ if (l.type !== 'command') return false;
304
+ if (shell && l.shell !== shell && l.shell !== 'all') return false;
305
+ return true;
306
+ });
307
+ }
308
+
294
309
  /**
295
310
  * Get total lesson count
296
311
  * @returns {number}
@@ -336,6 +351,7 @@ export default {
336
351
  updateLesson,
337
352
  removeLesson,
338
353
  getLessonsByType,
354
+ getCommandLessons,
339
355
  getLessonCount,
340
356
  recordHit,
341
357
  createEmptyKnowledge,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pikakit",
3
- "version": "1.0.36",
3
+ "version": "1.0.37",
4
4
  "description": "Enterprise-grade Agent Skill Manager with Antigravity Skills support, Progressive Disclosure detection, and semantic routing validation",
5
5
  "license": "MIT",
6
6
  "author": "pikakit <pikakit@gmail.com>",