pikakit 1.0.14 → 1.0.15
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/bin/cli.mjs +1 -1
- package/bin/kit.js +1 -1
- package/lib/agent-cli/dashboard/index.html +845 -231
- package/lib/agent-cli/lib/dashboard-data.js +79 -242
- package/lib/agent-cli/lib/ui/dashboard-ui.js +20 -30
- package/lib/agent-cli/scripts/dashboard-server.js +324 -0
- package/package.json +2 -2
- package/lib/agent-cli/scripts/dashboard_server.js +0 -344
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Dashboard Data v7.0 - PikaKit Data Aggregation
|
|
3
3
|
*
|
|
4
4
|
* Aggregates data from all engines for Dashboard display.
|
|
5
5
|
* Provides real-time metrics, trends, and alerts.
|
|
6
6
|
*
|
|
7
|
-
* @version
|
|
7
|
+
* @version 7.0.0
|
|
8
8
|
* @author PikaKit
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import { getReinforcementStats } from './reinforcement.js';
|
|
13
|
-
import { getABTestStats, getActiveTests } from './ab-testing.js';
|
|
14
|
-
import { getSkillStats, loadAutoSkills } from './precision-skill-generator.js';
|
|
11
|
+
import { getKPIs, getMetricValue, getMetricHistory } from './metrics-collector.js';
|
|
15
12
|
import { loadCausalPatterns } from './causality-engine.js';
|
|
16
13
|
|
|
17
14
|
// ============================================================================
|
|
@@ -23,122 +20,51 @@ import { loadCausalPatterns } from './causality-engine.js';
|
|
|
23
20
|
* @returns {Object} - Full dashboard data
|
|
24
21
|
*/
|
|
25
22
|
export function getFullDashboardData() {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
patternB: t.patternB.name || t.patternB.id,
|
|
51
|
-
samplesA: t.metrics.patternA.applied,
|
|
52
|
-
samplesB: t.metrics.patternB.applied
|
|
53
|
-
})),
|
|
54
|
-
skills: loadAutoSkills().slice(0, 10) // Last 10
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
// Alerts
|
|
58
|
-
alerts: generateAlerts()
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
return data;
|
|
23
|
+
try {
|
|
24
|
+
const kpis = getKPIs();
|
|
25
|
+
const patterns = loadCausalPatterns();
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
version: '7.0.0',
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
kpis,
|
|
31
|
+
summary: {
|
|
32
|
+
totalTasks: getMetricValue('total_tasks') || 0,
|
|
33
|
+
patternsLearned: patterns.length,
|
|
34
|
+
skillsGenerated: 0,
|
|
35
|
+
abTestsActive: 0
|
|
36
|
+
},
|
|
37
|
+
patterns: patterns.slice(0, 10)
|
|
38
|
+
};
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return {
|
|
41
|
+
version: '7.0.0',
|
|
42
|
+
error: e.message,
|
|
43
|
+
kpis: { kpis: {} },
|
|
44
|
+
summary: {}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
62
47
|
}
|
|
63
48
|
|
|
64
49
|
/**
|
|
65
50
|
* Get pattern statistics
|
|
51
|
+
* @returns {Object} - Pattern stats
|
|
66
52
|
*/
|
|
67
|
-
function getPatternStats() {
|
|
53
|
+
export function getPatternStats() {
|
|
68
54
|
const patterns = loadCausalPatterns();
|
|
69
|
-
|
|
70
|
-
if (patterns.length === 0) {
|
|
71
|
-
return { total: 0, avgConfidence: 0, categories: [] };
|
|
72
|
-
}
|
|
73
|
-
|
|
74
55
|
return {
|
|
75
56
|
total: patterns.length,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Get trend data for a specific metric
|
|
87
|
-
* @param {string} metricId - Metric ID
|
|
88
|
-
* @param {string} period - 'day' | 'week' | 'month'
|
|
89
|
-
* @returns {Object} - Trend data
|
|
90
|
-
*/
|
|
91
|
-
export function getMetricTrend(metricId, period = 'week') {
|
|
92
|
-
const limits = { day: 24, week: 168, month: 720 };
|
|
93
|
-
const limit = limits[period] || 168;
|
|
94
|
-
|
|
95
|
-
const history = getMetricHistory(metricId, limit);
|
|
96
|
-
|
|
97
|
-
if (history.length < 2) {
|
|
98
|
-
return { trend: 'stable', change: 0, data: history };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Calculate trend
|
|
102
|
-
const firstValue = parseFloat(history[0].value) || 0;
|
|
103
|
-
const lastValue = parseFloat(history[history.length - 1].value) || 0;
|
|
104
|
-
const change = firstValue > 0 ? ((lastValue - firstValue) / firstValue * 100) : 0;
|
|
105
|
-
|
|
106
|
-
let trend = 'stable';
|
|
107
|
-
if (change > 5) trend = 'up';
|
|
108
|
-
if (change < -5) trend = 'down';
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
metricId,
|
|
112
|
-
period,
|
|
113
|
-
trend,
|
|
114
|
-
change: change.toFixed(2),
|
|
115
|
-
firstValue,
|
|
116
|
-
lastValue,
|
|
117
|
-
dataPoints: history.length,
|
|
118
|
-
data: history
|
|
57
|
+
byCategory: patterns.reduce((acc, p) => {
|
|
58
|
+
const cat = p.category || 'other';
|
|
59
|
+
acc[cat] = (acc[cat] || 0) + 1;
|
|
60
|
+
return acc;
|
|
61
|
+
}, {}),
|
|
62
|
+
avgConfidence: patterns.length > 0
|
|
63
|
+
? patterns.reduce((sum, p) => sum + (p.confidence || 0), 0) / patterns.length
|
|
64
|
+
: 0
|
|
119
65
|
};
|
|
120
66
|
}
|
|
121
67
|
|
|
122
|
-
/**
|
|
123
|
-
* Get all key trends
|
|
124
|
-
* @returns {Object} - Key trends
|
|
125
|
-
*/
|
|
126
|
-
export function getKeyTrends() {
|
|
127
|
-
const keyMetrics = [
|
|
128
|
-
'task_success_rate',
|
|
129
|
-
'error_repeat_rate',
|
|
130
|
-
'skill_effectiveness',
|
|
131
|
-
'pattern_precision'
|
|
132
|
-
];
|
|
133
|
-
|
|
134
|
-
const trends = {};
|
|
135
|
-
for (const metricId of keyMetrics) {
|
|
136
|
-
trends[metricId] = getMetricTrend(metricId, 'week');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return trends;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
68
|
// ============================================================================
|
|
143
69
|
// ALERTS
|
|
144
70
|
// ============================================================================
|
|
@@ -146,33 +72,21 @@ export function getKeyTrends() {
|
|
|
146
72
|
const ALERT_RULES = [
|
|
147
73
|
{
|
|
148
74
|
id: 'low_success_rate',
|
|
149
|
-
check: (kpis) => parseFloat(kpis.task_success_rate
|
|
75
|
+
check: (kpis) => kpis.task_success_rate && parseFloat(kpis.task_success_rate.value) < 80,
|
|
150
76
|
severity: 'warning',
|
|
151
77
|
message: 'Task success rate below 80%'
|
|
152
78
|
},
|
|
153
79
|
{
|
|
154
80
|
id: 'high_error_repeat',
|
|
155
|
-
check: (kpis) => parseFloat(kpis.error_repeat_rate
|
|
81
|
+
check: (kpis) => kpis.error_repeat_rate && parseFloat(kpis.error_repeat_rate.value) > 10,
|
|
156
82
|
severity: 'warning',
|
|
157
83
|
message: 'Error repeat rate above 10%'
|
|
158
84
|
},
|
|
159
85
|
{
|
|
160
86
|
id: 'low_skill_effectiveness',
|
|
161
|
-
check: (kpis) => parseFloat(kpis.skill_effectiveness
|
|
87
|
+
check: (kpis) => kpis.skill_effectiveness && parseFloat(kpis.skill_effectiveness.value) < 50,
|
|
162
88
|
severity: 'info',
|
|
163
89
|
message: 'Skill effectiveness below 50%'
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
id: 'high_false_positive',
|
|
167
|
-
check: (kpis) => parseFloat(kpis.false_positive_rate?.value) > 15,
|
|
168
|
-
severity: 'warning',
|
|
169
|
-
message: 'False positive rate above 15%'
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
id: 'pattern_confidence_low',
|
|
173
|
-
check: (kpis) => parseFloat(kpis.pattern_confidence_avg?.value) < 0.5,
|
|
174
|
-
severity: 'info',
|
|
175
|
-
message: 'Average pattern confidence below 50%'
|
|
176
90
|
}
|
|
177
91
|
];
|
|
178
92
|
|
|
@@ -181,12 +95,11 @@ const ALERT_RULES = [
|
|
|
181
95
|
* @returns {Array} - Active alerts
|
|
182
96
|
*/
|
|
183
97
|
export function generateAlerts() {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
98
|
+
try {
|
|
99
|
+
const kpis = getKPIs().kpis || {};
|
|
100
|
+
const alerts = [];
|
|
187
101
|
|
|
188
|
-
|
|
189
|
-
try {
|
|
102
|
+
for (const rule of ALERT_RULES) {
|
|
190
103
|
if (rule.check(kpis)) {
|
|
191
104
|
alerts.push({
|
|
192
105
|
id: rule.id,
|
|
@@ -195,39 +108,16 @@ export function generateAlerts() {
|
|
|
195
108
|
timestamp: new Date().toISOString()
|
|
196
109
|
});
|
|
197
110
|
}
|
|
198
|
-
} catch {
|
|
199
|
-
// Skip rules that fail
|
|
200
111
|
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Check for skills needing attention
|
|
204
|
-
const skills = loadAutoSkills();
|
|
205
|
-
const underperforming = skills.filter(s => s.state === 'underperforming');
|
|
206
|
-
if (underperforming.length > 0) {
|
|
207
|
-
alerts.push({
|
|
208
|
-
id: 'underperforming_skills',
|
|
209
|
-
severity: 'info',
|
|
210
|
-
message: `${underperforming.length} skills underperforming`,
|
|
211
|
-
timestamp: new Date().toISOString()
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
112
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
alerts.push({
|
|
219
|
-
id: 'too_many_ab_tests',
|
|
220
|
-
severity: 'info',
|
|
221
|
-
message: `${abStats.running} A/B tests running simultaneously`,
|
|
222
|
-
timestamp: new Date().toISOString()
|
|
223
|
-
});
|
|
113
|
+
return alerts;
|
|
114
|
+
} catch (e) {
|
|
115
|
+
return [];
|
|
224
116
|
}
|
|
225
|
-
|
|
226
|
-
return alerts;
|
|
227
117
|
}
|
|
228
118
|
|
|
229
119
|
// ============================================================================
|
|
230
|
-
//
|
|
120
|
+
// WIDGET DATA
|
|
231
121
|
// ============================================================================
|
|
232
122
|
|
|
233
123
|
/**
|
|
@@ -235,17 +125,13 @@ export function generateAlerts() {
|
|
|
235
125
|
* @returns {Array} - Gauge data
|
|
236
126
|
*/
|
|
237
127
|
export function getGaugeWidgets() {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
{ id: '
|
|
243
|
-
{ id: '
|
|
244
|
-
{ id: 'first_time_success', label: 'First-Time', ...kpis.first_time_success },
|
|
245
|
-
{ id: 'skill_effectiveness', label: 'Skill Effect', ...kpis.skill_effectiveness }
|
|
128
|
+
const kpis = getKPIs().kpis || {};
|
|
129
|
+
return [
|
|
130
|
+
{ id: 'success_rate', label: 'Task Success', value: parseFloat(kpis.task_success_rate?.value) || 0, target: 85 },
|
|
131
|
+
{ id: 'error_repeat', label: 'Error Repeat', value: parseFloat(kpis.error_repeat_rate?.value) || 0, target: 5, inverse: true },
|
|
132
|
+
{ id: 'first_time', label: 'First-Time Success', value: parseFloat(kpis.first_time_success?.value) || 0, target: 80 },
|
|
133
|
+
{ id: 'skill_eff', label: 'Skill Effectiveness', value: parseFloat(kpis.skill_effectiveness?.value) || 0, target: 70 }
|
|
246
134
|
];
|
|
247
|
-
|
|
248
|
-
return gauges;
|
|
249
135
|
}
|
|
250
136
|
|
|
251
137
|
/**
|
|
@@ -253,15 +139,12 @@ export function getGaugeWidgets() {
|
|
|
253
139
|
* @returns {Array} - Counter data
|
|
254
140
|
*/
|
|
255
141
|
export function getCounterWidgets() {
|
|
256
|
-
const
|
|
257
|
-
const kpis = dashboard.kpis;
|
|
258
|
-
const summary = getSummary();
|
|
259
|
-
|
|
142
|
+
const patterns = loadCausalPatterns();
|
|
260
143
|
return [
|
|
261
|
-
{ id: '
|
|
262
|
-
{ id: '
|
|
263
|
-
{ id: '
|
|
264
|
-
{ id: '
|
|
144
|
+
{ id: 'tasks', label: 'Total Tasks', value: getMetricValue('total_tasks') || 0 },
|
|
145
|
+
{ id: 'patterns', label: 'Patterns', value: patterns.length },
|
|
146
|
+
{ id: 'skills', label: 'Skills', value: 0 },
|
|
147
|
+
{ id: 'tests', label: 'A/B Tests', value: 0 }
|
|
265
148
|
];
|
|
266
149
|
}
|
|
267
150
|
|
|
@@ -270,36 +153,16 @@ export function getCounterWidgets() {
|
|
|
270
153
|
* @returns {Object} - Chart data
|
|
271
154
|
*/
|
|
272
155
|
export function getLearningVelocityChart() {
|
|
273
|
-
const history = getMetricHistory('
|
|
274
|
-
|
|
275
|
-
return {
|
|
276
|
-
title: 'Learning Velocity (Patterns/Week)',
|
|
277
|
-
labels: history.map((_, i) => `W${i + 1}`),
|
|
278
|
-
data: history.map(h => parseFloat(h.value) || 0)
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Get skill effectiveness breakdown
|
|
284
|
-
* @returns {Object} - Breakdown data
|
|
285
|
-
*/
|
|
286
|
-
export function getSkillEffectivenessBreakdown() {
|
|
287
|
-
const skills = loadAutoSkills();
|
|
288
|
-
|
|
289
|
-
const breakdown = {
|
|
290
|
-
high: skills.filter(s => s.confidence >= 0.8).length,
|
|
291
|
-
medium: skills.filter(s => s.confidence >= 0.5 && s.confidence < 0.8).length,
|
|
292
|
-
low: skills.filter(s => s.confidence < 0.5).length
|
|
293
|
-
};
|
|
294
|
-
|
|
156
|
+
const history = getMetricHistory('patterns_learned', 7);
|
|
295
157
|
return {
|
|
296
|
-
|
|
297
|
-
|
|
158
|
+
labels: history.map(h => h.date),
|
|
159
|
+
values: history.map(h => h.value),
|
|
160
|
+
type: 'bar'
|
|
298
161
|
};
|
|
299
162
|
}
|
|
300
163
|
|
|
301
164
|
// ============================================================================
|
|
302
|
-
//
|
|
165
|
+
// CLI FORMAT
|
|
303
166
|
// ============================================================================
|
|
304
167
|
|
|
305
168
|
/**
|
|
@@ -308,44 +171,20 @@ export function getSkillEffectivenessBreakdown() {
|
|
|
308
171
|
*/
|
|
309
172
|
export function formatDashboardForCLI() {
|
|
310
173
|
const data = getFullDashboardData();
|
|
311
|
-
const kpis = data.kpis
|
|
312
|
-
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
];
|
|
326
|
-
|
|
327
|
-
// Add alerts
|
|
328
|
-
if (data.alerts.length > 0) {
|
|
329
|
-
lines.push('│ ⚠️ Alerts: │');
|
|
330
|
-
for (const alert of data.alerts.slice(0, 3)) {
|
|
331
|
-
lines.push(`│ • ${alert.message.padEnd(55)}│`);
|
|
332
|
-
}
|
|
333
|
-
} else {
|
|
334
|
-
lines.push('│ ✅ No alerts │');
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
lines.push('│ │');
|
|
338
|
-
lines.push('└─────────────────────────────────────────────────────────────────┘');
|
|
339
|
-
lines.push('');
|
|
340
|
-
|
|
341
|
-
return lines.join('\n');
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function formatValue(kpi) {
|
|
345
|
-
if (!kpi) return ' --.-%';
|
|
346
|
-
const val = parseFloat(kpi.value).toFixed(1);
|
|
347
|
-
const status = kpi.status === 'good' ? '✓' : kpi.status === 'critical' ? '✗' : '~';
|
|
348
|
-
return `${status} ${val.padStart(5)}%`;
|
|
174
|
+
const kpis = data.kpis?.kpis || {};
|
|
175
|
+
|
|
176
|
+
const formatValue = (kpi) => kpi?.value ? `${parseFloat(kpi.value).toFixed(1)}%` : '--';
|
|
177
|
+
|
|
178
|
+
return `
|
|
179
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
180
|
+
║ 🧠 PikaKit Dashboard v7.0 ║
|
|
181
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
182
|
+
║ Task Success: ${formatValue(kpis.task_success_rate).padEnd(8)} │ Error Repeat: ${formatValue(kpis.error_repeat_rate).padEnd(8)} ║
|
|
183
|
+
║ First-Time: ${formatValue(kpis.first_time_success).padEnd(8)} │ Skill Effect: ${formatValue(kpis.skill_effectiveness).padEnd(8)} ║
|
|
184
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
185
|
+
║ Tasks: ${String(data.summary?.totalTasks || 0).padEnd(6)} Patterns: ${String(data.summary?.patternsLearned || 0).padEnd(6)} Skills: ${String(data.summary?.skillsGenerated || 0).padEnd(6)} ║
|
|
186
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
187
|
+
`;
|
|
349
188
|
}
|
|
350
189
|
|
|
351
190
|
// ============================================================================
|
|
@@ -354,12 +193,10 @@ function formatValue(kpi) {
|
|
|
354
193
|
|
|
355
194
|
export default {
|
|
356
195
|
getFullDashboardData,
|
|
357
|
-
|
|
358
|
-
getKeyTrends,
|
|
196
|
+
getPatternStats,
|
|
359
197
|
generateAlerts,
|
|
360
198
|
getGaugeWidgets,
|
|
361
199
|
getCounterWidgets,
|
|
362
200
|
getLearningVelocityChart,
|
|
363
|
-
getSkillEffectivenessBreakdown,
|
|
364
201
|
formatDashboardForCLI
|
|
365
202
|
};
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dashboard UI - Launch
|
|
2
|
+
* Dashboard UI v7.0 - Launch PikaKit Dashboard in browser
|
|
3
|
+
*
|
|
4
|
+
* @version 7.0.0
|
|
5
|
+
* @author PikaKit
|
|
3
6
|
*/
|
|
4
7
|
import * as p from "@clack/prompts";
|
|
5
8
|
import { spawn, exec } from "child_process";
|
|
@@ -18,7 +21,6 @@ let runningPort = null;
|
|
|
18
21
|
async function checkPortInUse(port) {
|
|
19
22
|
return new Promise((resolve) => {
|
|
20
23
|
const req = http.get(`http://localhost:${port}/api/summary`, (res) => {
|
|
21
|
-
// If we get 200 response from /api/summary, it's our dashboard
|
|
22
24
|
if (res.statusCode === 200) {
|
|
23
25
|
resolve(true);
|
|
24
26
|
} else {
|
|
@@ -29,7 +31,6 @@ async function checkPortInUse(port) {
|
|
|
29
31
|
req.on('error', () => {
|
|
30
32
|
resolve(false);
|
|
31
33
|
});
|
|
32
|
-
// Faster timeout - 500ms is enough for localhost
|
|
33
34
|
req.setTimeout(500, () => {
|
|
34
35
|
req.destroy();
|
|
35
36
|
resolve(false);
|
|
@@ -41,15 +42,12 @@ async function checkPortInUse(port) {
|
|
|
41
42
|
* Find existing dashboard server on ports 3030-3040
|
|
42
43
|
*/
|
|
43
44
|
async function findExistingServer() {
|
|
44
|
-
// Check ports in parallel for faster detection
|
|
45
45
|
const portChecks = [];
|
|
46
46
|
for (let port = 3030; port <= 3040; port++) {
|
|
47
47
|
portChecks.push(checkPortInUse(port).then(inUse => inUse ? port : null));
|
|
48
48
|
}
|
|
49
|
-
|
|
50
49
|
const results = await Promise.all(portChecks);
|
|
51
|
-
|
|
52
|
-
return existingPort || null;
|
|
50
|
+
return results.find(port => port !== null) || null;
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
/**
|
|
@@ -71,21 +69,19 @@ async function findAvailablePort(startPort = 3030) {
|
|
|
71
69
|
* Find dashboard server script
|
|
72
70
|
*/
|
|
73
71
|
function findDashboardScript() {
|
|
74
|
-
// Get the directory where this module is located
|
|
75
72
|
const moduleDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/i, '$1'));
|
|
76
73
|
const cliRoot = path.resolve(moduleDir, '..', '..');
|
|
77
|
-
|
|
78
|
-
// User home directory
|
|
79
74
|
const homeDir = process.env.USERPROFILE || process.env.HOME || '';
|
|
80
75
|
|
|
81
76
|
const possiblePaths = [
|
|
82
|
-
// PRIORITY 1:
|
|
83
|
-
path.join(cliRoot, "
|
|
84
|
-
// PRIORITY 2:
|
|
85
|
-
path.join(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
77
|
+
// PRIORITY 1: New v7.0 script bundled with CLI package
|
|
78
|
+
path.join(cliRoot, "scripts", "dashboard-server.js"),
|
|
79
|
+
// PRIORITY 2: Dashboard folder (legacy)
|
|
80
|
+
path.join(cliRoot, "dashboard", "dashboard-server.js"),
|
|
81
|
+
// PRIORITY 3: Current project paths
|
|
82
|
+
path.join(process.cwd(), ".agent", "skills", "auto-learner", "scripts", "dashboard-server.js"),
|
|
83
|
+
// PRIORITY 4: Fallback - agent-skill-kit
|
|
84
|
+
path.join(homeDir, "Desktop", "agent-skill-kit", ".agent", "skills", "auto-learner", "scripts", "dashboard-server.js"),
|
|
89
85
|
];
|
|
90
86
|
|
|
91
87
|
for (const searchPath of possiblePaths) {
|
|
@@ -102,7 +98,6 @@ function findDashboardScript() {
|
|
|
102
98
|
function openBrowser(url) {
|
|
103
99
|
const platform = process.platform;
|
|
104
100
|
let command;
|
|
105
|
-
|
|
106
101
|
if (platform === "win32") {
|
|
107
102
|
command = `start "" "${url}"`;
|
|
108
103
|
} else if (platform === "darwin") {
|
|
@@ -110,10 +105,9 @@ function openBrowser(url) {
|
|
|
110
105
|
} else {
|
|
111
106
|
command = `xdg-open "${url}"`;
|
|
112
107
|
}
|
|
113
|
-
|
|
114
108
|
exec(command, (err) => {
|
|
115
109
|
if (err) {
|
|
116
|
-
p.log.warn(`Could not open browser
|
|
110
|
+
p.log.warn(`Could not open browser. Visit: ${url}`);
|
|
117
111
|
}
|
|
118
112
|
});
|
|
119
113
|
}
|
|
@@ -124,7 +118,7 @@ function openBrowser(url) {
|
|
|
124
118
|
export async function runDashboardUI() {
|
|
125
119
|
const spinner = p.spinner();
|
|
126
120
|
|
|
127
|
-
// Check
|
|
121
|
+
// Check for existing server
|
|
128
122
|
spinner.start("Checking for existing dashboard server...");
|
|
129
123
|
const existingPort = await findExistingServer();
|
|
130
124
|
|
|
@@ -132,10 +126,10 @@ export async function runDashboardUI() {
|
|
|
132
126
|
spinner.stop(`Found existing server on port ${existingPort}`);
|
|
133
127
|
const url = `http://localhost:${existingPort}`;
|
|
134
128
|
|
|
135
|
-
p.log.success(`Dashboard
|
|
129
|
+
p.log.success(`Dashboard running at: ${url}`);
|
|
136
130
|
openBrowser(url);
|
|
137
131
|
|
|
138
|
-
p.note(`Server running on port ${existingPort}\nUsing existing server`, "
|
|
132
|
+
p.note(`Server running on port ${existingPort}\nUsing existing server`, "🧠 PikaKit Dashboard v7.0");
|
|
139
133
|
|
|
140
134
|
const action = await p.select({
|
|
141
135
|
message: "Dashboard is running. What would you like to do?",
|
|
@@ -146,7 +140,6 @@ export async function runDashboardUI() {
|
|
|
146
140
|
});
|
|
147
141
|
|
|
148
142
|
if (action === "stop") {
|
|
149
|
-
// Kill all node processes on that port
|
|
150
143
|
p.log.info("Stopping existing server...");
|
|
151
144
|
if (process.platform === "win32") {
|
|
152
145
|
exec(`for /f "tokens=5" %a in ('netstat -aon ^| findstr :${existingPort}') do taskkill /F /PID %a`, () => { });
|
|
@@ -166,7 +159,7 @@ export async function runDashboardUI() {
|
|
|
166
159
|
|
|
167
160
|
if (!scriptPath) {
|
|
168
161
|
p.log.error("Dashboard script not found!");
|
|
169
|
-
p.log.info("
|
|
162
|
+
p.log.info("Looking for: dashboard-server.js in scripts folder");
|
|
170
163
|
return;
|
|
171
164
|
}
|
|
172
165
|
|
|
@@ -177,7 +170,7 @@ export async function runDashboardUI() {
|
|
|
177
170
|
spinner.stop(`Using port ${port}`);
|
|
178
171
|
|
|
179
172
|
// Start dashboard server
|
|
180
|
-
spinner.start("Starting
|
|
173
|
+
spinner.start("Starting PikaKit Dashboard v7.0...");
|
|
181
174
|
|
|
182
175
|
const child = spawn("node", [scriptPath, "--port", String(port)], {
|
|
183
176
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -193,14 +186,11 @@ export async function runDashboardUI() {
|
|
|
193
186
|
|
|
194
187
|
const url = `http://localhost:${port}`;
|
|
195
188
|
|
|
196
|
-
// Open browser
|
|
197
189
|
p.log.success(`Dashboard running at: ${url}`);
|
|
198
190
|
openBrowser(url);
|
|
199
191
|
|
|
200
|
-
p.
|
|
201
|
-
p.note(`Server running on port ${port}\nPress Ctrl+C in terminal to stop`, "📊 Auto-Learn Dashboard");
|
|
192
|
+
p.note(`Server: http://localhost:${port}\nPress Ctrl+C to stop`, "🧠 PikaKit Dashboard v7.0");
|
|
202
193
|
|
|
203
|
-
// Keep server running and wait for user
|
|
204
194
|
const action = await p.select({
|
|
205
195
|
message: "Dashboard is running. What would you like to do?",
|
|
206
196
|
options: [
|