pikakit 3.0.1 → 3.0.3
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,344 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Dashboard Server v6.0 - AutoLearn Precision Learning Engine
|
|
4
|
+
*
|
|
5
|
+
* Serves real-time metrics from the new v6.0 modules:
|
|
6
|
+
* - metrics-collector.js (18 KPIs)
|
|
7
|
+
* - dashboard-data.js (aggregation)
|
|
8
|
+
* - causality-engine.js (patterns)
|
|
9
|
+
* - reinforcement.js (loop stats)
|
|
10
|
+
* - ab-testing.js (experiment stats)
|
|
11
|
+
* - precision-skill-generator.js (skills)
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node dashboard_server.js --start
|
|
15
|
+
* node dashboard_server.js --port 3030
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import fs from 'fs';
|
|
19
|
+
import path from 'path';
|
|
20
|
+
import http from 'http';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
|
|
23
|
+
// Import v6.0 modules
|
|
24
|
+
import { getDashboardData, getSummary, getMetricHistory } from '../lib/metrics-collector.js';
|
|
25
|
+
import { getFullDashboardData, getKeyTrends, generateAlerts, getGaugeWidgets, getCounterWidgets } from '../lib/dashboard-data.js';
|
|
26
|
+
import { getReinforcementStats } from '../lib/reinforcement.js';
|
|
27
|
+
import { getABTestStats, getActiveTests } from '../lib/ab-testing.js';
|
|
28
|
+
import { getSkillStats, loadAutoSkills } from '../lib/precision-skill-generator.js';
|
|
29
|
+
import { loadCausalPatterns } from '../lib/causality-engine.js';
|
|
30
|
+
|
|
31
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
32
|
+
const __dirname = path.dirname(__filename);
|
|
33
|
+
|
|
34
|
+
// Colors
|
|
35
|
+
const c = {
|
|
36
|
+
reset: '\x1b[0m',
|
|
37
|
+
red: '\x1b[31m',
|
|
38
|
+
green: '\x1b[32m',
|
|
39
|
+
yellow: '\x1b[33m',
|
|
40
|
+
cyan: '\x1b[36m',
|
|
41
|
+
gray: '\x1b[90m',
|
|
42
|
+
bold: '\x1b[1m'
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Find project root
|
|
46
|
+
function findProjectRoot() {
|
|
47
|
+
let current = process.cwd();
|
|
48
|
+
while (current !== path.dirname(current)) {
|
|
49
|
+
if (fs.existsSync(path.join(current, '.agent'))) {
|
|
50
|
+
return current;
|
|
51
|
+
}
|
|
52
|
+
current = path.dirname(current);
|
|
53
|
+
}
|
|
54
|
+
return process.cwd();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const projectRoot = findProjectRoot();
|
|
58
|
+
const dashboardPath = path.join(__dirname, '..', 'dashboard');
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// API v6.0 HANDLERS
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
const api = {
|
|
65
|
+
// Full dashboard data (all metrics aggregated)
|
|
66
|
+
'/api/dashboard': () => {
|
|
67
|
+
try {
|
|
68
|
+
return getFullDashboardData();
|
|
69
|
+
} catch (e) {
|
|
70
|
+
return { error: e.message, version: '6.0.0' };
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
// KPIs only
|
|
75
|
+
'/api/kpis': () => {
|
|
76
|
+
try {
|
|
77
|
+
return getDashboardData();
|
|
78
|
+
} catch (e) {
|
|
79
|
+
return { error: e.message };
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// Summary stats
|
|
84
|
+
'/api/summary': () => {
|
|
85
|
+
try {
|
|
86
|
+
return getSummary();
|
|
87
|
+
} catch (e) {
|
|
88
|
+
return { error: e.message };
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// Trends over time
|
|
93
|
+
'/api/trends': () => {
|
|
94
|
+
try {
|
|
95
|
+
return getKeyTrends();
|
|
96
|
+
} catch (e) {
|
|
97
|
+
return { error: e.message };
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
// Active alerts
|
|
102
|
+
'/api/alerts': () => {
|
|
103
|
+
try {
|
|
104
|
+
return { alerts: generateAlerts() };
|
|
105
|
+
} catch (e) {
|
|
106
|
+
return { alerts: [], error: e.message };
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
// Gauge widget data
|
|
111
|
+
'/api/gauges': () => {
|
|
112
|
+
try {
|
|
113
|
+
return { gauges: getGaugeWidgets() };
|
|
114
|
+
} catch (e) {
|
|
115
|
+
return { gauges: [], error: e.message };
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
// Counter widget data
|
|
120
|
+
'/api/counters': () => {
|
|
121
|
+
try {
|
|
122
|
+
return { counters: getCounterWidgets() };
|
|
123
|
+
} catch (e) {
|
|
124
|
+
return { counters: [], error: e.message };
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// Reinforcement loop stats
|
|
129
|
+
'/api/reinforcement': () => {
|
|
130
|
+
try {
|
|
131
|
+
return getReinforcementStats();
|
|
132
|
+
} catch (e) {
|
|
133
|
+
return { error: e.message };
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
// A/B testing stats
|
|
138
|
+
'/api/ab-testing': () => {
|
|
139
|
+
try {
|
|
140
|
+
return {
|
|
141
|
+
stats: getABTestStats(),
|
|
142
|
+
active: getActiveTests()
|
|
143
|
+
};
|
|
144
|
+
} catch (e) {
|
|
145
|
+
return { error: e.message };
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
// Auto-generated skills
|
|
150
|
+
'/api/skills': () => {
|
|
151
|
+
try {
|
|
152
|
+
return {
|
|
153
|
+
stats: getSkillStats(),
|
|
154
|
+
skills: loadAutoSkills()
|
|
155
|
+
};
|
|
156
|
+
} catch (e) {
|
|
157
|
+
return { error: e.message };
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
// Causal patterns
|
|
162
|
+
'/api/patterns': () => {
|
|
163
|
+
try {
|
|
164
|
+
const patterns = loadCausalPatterns();
|
|
165
|
+
return {
|
|
166
|
+
total: patterns.length,
|
|
167
|
+
patterns: patterns.slice(0, 20) // Limit to 20 most recent
|
|
168
|
+
};
|
|
169
|
+
} catch (e) {
|
|
170
|
+
return { total: 0, patterns: [], error: e.message };
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
// Metric history (query param: ?metric=task_success_rate&limit=168)
|
|
175
|
+
'/api/history': (query) => {
|
|
176
|
+
try {
|
|
177
|
+
const metric = query.get('metric') || 'task_success_rate';
|
|
178
|
+
const limit = parseInt(query.get('limit') || '168', 10);
|
|
179
|
+
return {
|
|
180
|
+
metric,
|
|
181
|
+
history: getMetricHistory(metric, limit)
|
|
182
|
+
};
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return { error: e.message };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// ============================================================================
|
|
190
|
+
// LEGACY API COMPATIBILITY (v4.0 endpoints that still work)
|
|
191
|
+
// ============================================================================
|
|
192
|
+
|
|
193
|
+
const legacyApi = {
|
|
194
|
+
'/api/errors': () => ({
|
|
195
|
+
deprecation: 'Use /api/patterns instead',
|
|
196
|
+
redirect: '/api/patterns'
|
|
197
|
+
}),
|
|
198
|
+
'/api/corrections': () => ({
|
|
199
|
+
deprecation: 'Use /api/patterns instead',
|
|
200
|
+
redirect: '/api/patterns'
|
|
201
|
+
}),
|
|
202
|
+
'/api/lessons': () => {
|
|
203
|
+
const filePath = path.join(projectRoot, '.agent', 'knowledge', 'lessons-learned.json');
|
|
204
|
+
try {
|
|
205
|
+
if (fs.existsSync(filePath)) {
|
|
206
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
207
|
+
}
|
|
208
|
+
} catch { }
|
|
209
|
+
return { lessons: [] };
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// MIME types
|
|
214
|
+
const mimeTypes = {
|
|
215
|
+
'.html': 'text/html',
|
|
216
|
+
'.css': 'text/css',
|
|
217
|
+
'.js': 'application/javascript',
|
|
218
|
+
'.json': 'application/json',
|
|
219
|
+
'.png': 'image/png',
|
|
220
|
+
'.jpg': 'image/jpeg',
|
|
221
|
+
'.svg': 'image/svg+xml'
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Create server
|
|
225
|
+
function createServer(port) {
|
|
226
|
+
const server = http.createServer((req, res) => {
|
|
227
|
+
const urlParts = req.url.split('?');
|
|
228
|
+
const url = urlParts[0];
|
|
229
|
+
const query = new URLSearchParams(urlParts[1] || '');
|
|
230
|
+
|
|
231
|
+
// CORS headers for local development
|
|
232
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
233
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
234
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
235
|
+
|
|
236
|
+
// Handle API requests
|
|
237
|
+
if (url.startsWith('/api/')) {
|
|
238
|
+
const handler = api[url] || legacyApi[url];
|
|
239
|
+
if (handler) {
|
|
240
|
+
res.setHeader('Content-Type', 'application/json');
|
|
241
|
+
res.writeHead(200);
|
|
242
|
+
res.end(JSON.stringify(handler(query)));
|
|
243
|
+
} else {
|
|
244
|
+
res.writeHead(404);
|
|
245
|
+
res.end(JSON.stringify({ error: 'Not found', availableEndpoints: Object.keys(api) }));
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Serve static files
|
|
251
|
+
let filePath = url === '/' ? '/index.html' : url;
|
|
252
|
+
filePath = path.join(dashboardPath, filePath);
|
|
253
|
+
|
|
254
|
+
if (fs.existsSync(filePath)) {
|
|
255
|
+
const ext = path.extname(filePath);
|
|
256
|
+
const mimeType = mimeTypes[ext] || 'text/plain';
|
|
257
|
+
|
|
258
|
+
res.setHeader('Content-Type', mimeType);
|
|
259
|
+
res.writeHead(200);
|
|
260
|
+
res.end(fs.readFileSync(filePath));
|
|
261
|
+
} else {
|
|
262
|
+
res.writeHead(404);
|
|
263
|
+
res.end('Not found');
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return server;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function startServer(port = 3030) {
|
|
271
|
+
const server = createServer(port);
|
|
272
|
+
|
|
273
|
+
server.listen(port, () => {
|
|
274
|
+
console.log(`${c.cyan}╔════════════════════════════════════════════════════╗${c.reset}`);
|
|
275
|
+
console.log(`${c.cyan}║${c.reset} 🧠 AutoLearn v6.0 Dashboard Server ${c.cyan}║${c.reset}`);
|
|
276
|
+
console.log(`${c.cyan}║${c.reset} ${c.green}Precision Learning Engine${c.reset} ${c.cyan}║${c.reset}`);
|
|
277
|
+
console.log(`${c.cyan}╚════════════════════════════════════════════════════╝${c.reset}\n`);
|
|
278
|
+
console.log(`${c.green}✓ Server running at:${c.reset}`);
|
|
279
|
+
console.log(` ${c.bold}http://localhost:${port}${c.reset}\n`);
|
|
280
|
+
console.log(`${c.gray}API Endpoints (v6.0):${c.reset}`);
|
|
281
|
+
console.log(` GET /api/dashboard - Full dashboard data`);
|
|
282
|
+
console.log(` GET /api/kpis - 18 KPIs`);
|
|
283
|
+
console.log(` GET /api/summary - Summary stats`);
|
|
284
|
+
console.log(` GET /api/trends - Key trends`);
|
|
285
|
+
console.log(` GET /api/alerts - Active alerts`);
|
|
286
|
+
console.log(` GET /api/reinforcement - Reinforcement loop`);
|
|
287
|
+
console.log(` GET /api/ab-testing - A/B experiments`);
|
|
288
|
+
console.log(` GET /api/skills - Auto-generated skills`);
|
|
289
|
+
console.log(` GET /api/patterns - Causal patterns\n`);
|
|
290
|
+
console.log(`${c.yellow}Press Ctrl+C to stop${c.reset}`);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
server.on('error', (err) => {
|
|
294
|
+
if (err.code === 'EADDRINUSE') {
|
|
295
|
+
console.log(`${c.red}Error: Port ${port} is already in use${c.reset}`);
|
|
296
|
+
console.log(`${c.gray}Try: node dashboard_server.js --port ${port + 1}${c.reset}`);
|
|
297
|
+
} else {
|
|
298
|
+
console.error(`${c.red}Server error:${c.reset}`, err);
|
|
299
|
+
}
|
|
300
|
+
process.exit(1);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
return server;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Parse CLI args
|
|
307
|
+
const args = process.argv.slice(2);
|
|
308
|
+
|
|
309
|
+
if (args.includes('--start') || args.includes('-s') || args.length === 0 || args.includes('--port') || args.includes('-p')) {
|
|
310
|
+
let port = 3030;
|
|
311
|
+
const portIdx = args.findIndex(a => a === '--port' || a === '-p');
|
|
312
|
+
if (portIdx >= 0 && args[portIdx + 1]) {
|
|
313
|
+
port = parseInt(args[portIdx + 1], 10);
|
|
314
|
+
}
|
|
315
|
+
startServer(port);
|
|
316
|
+
} else if (args.includes('--help') || args.includes('-h')) {
|
|
317
|
+
console.log(`${c.cyan}AutoLearn v6.0 Dashboard Server${c.reset}
|
|
318
|
+
|
|
319
|
+
${c.bold}Usage:${c.reset}
|
|
320
|
+
node dashboard_server.js Start server (default port 3030)
|
|
321
|
+
node dashboard_server.js --port 8080 Start on custom port
|
|
322
|
+
node dashboard_server.js --help Show this help
|
|
323
|
+
|
|
324
|
+
${c.bold}API Endpoints (v6.0):${c.reset}
|
|
325
|
+
GET /api/dashboard - Full dashboard aggregation
|
|
326
|
+
GET /api/kpis - 18 KPIs for Dashboard
|
|
327
|
+
GET /api/summary - Summary statistics
|
|
328
|
+
GET /api/trends - Week-over-week trends
|
|
329
|
+
GET /api/alerts - Active alerts
|
|
330
|
+
GET /api/gauges - Gauge widget data
|
|
331
|
+
GET /api/counters - Counter widget data
|
|
332
|
+
GET /api/reinforcement - Reinforcement loop stats
|
|
333
|
+
GET /api/ab-testing - A/B testing experiments
|
|
334
|
+
GET /api/skills - Auto-generated skills
|
|
335
|
+
GET /api/patterns - Causal patterns
|
|
336
|
+
GET /api/history?metric=X - Metric history
|
|
337
|
+
|
|
338
|
+
${c.bold}Example:${c.reset}
|
|
339
|
+
node dashboard_server.js --port 3030
|
|
340
|
+
# Open http://localhost:3030 in browser
|
|
341
|
+
`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export { createServer, startServer };
|
|
@@ -27,7 +27,7 @@ export const RULES_DIR = path.join(AGENT_DIR, "rules");
|
|
|
27
27
|
/** CLI version - read from package.json */
|
|
28
28
|
export const VERSION = (() => {
|
|
29
29
|
try { return require("../package.json").version; }
|
|
30
|
-
catch { return "3.0.
|
|
30
|
+
catch { return "3.0.3"; }
|
|
31
31
|
})();
|
|
32
32
|
|
|
33
33
|
/** Debug mode */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pikakit",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
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>",
|