pikakit 3.0.3 → 3.0.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.
|
@@ -1,55 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Dashboard Server
|
|
3
|
+
* Dashboard Server v7.0 - PikaKit Precision Learning Engine
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* - metrics
|
|
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)
|
|
5
|
+
* Modern ES Modules server with REST API endpoints.
|
|
6
|
+
* Serves real-time metrics from PikaKit learning system.
|
|
12
7
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* node dashboard_server.js --port 3030
|
|
8
|
+
* @version 7.0.0
|
|
9
|
+
* @author PikaKit
|
|
16
10
|
*/
|
|
17
11
|
|
|
12
|
+
import http from 'http';
|
|
18
13
|
import fs from 'fs';
|
|
19
14
|
import path from 'path';
|
|
20
|
-
import http from 'http';
|
|
21
15
|
import { fileURLToPath } from 'url';
|
|
22
16
|
|
|
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
17
|
const __filename = fileURLToPath(import.meta.url);
|
|
32
18
|
const __dirname = path.dirname(__filename);
|
|
33
19
|
|
|
34
|
-
// Colors
|
|
20
|
+
// Colors for terminal
|
|
35
21
|
const c = {
|
|
36
22
|
reset: '\x1b[0m',
|
|
37
|
-
|
|
23
|
+
bold: '\x1b[1m',
|
|
24
|
+
cyan: '\x1b[36m',
|
|
38
25
|
green: '\x1b[32m',
|
|
39
26
|
yellow: '\x1b[33m',
|
|
40
|
-
|
|
41
|
-
gray: '\x1b[90m',
|
|
42
|
-
bold: '\x1b[1m'
|
|
27
|
+
gray: '\x1b[90m'
|
|
43
28
|
};
|
|
44
29
|
|
|
45
30
|
// Find project root
|
|
46
31
|
function findProjectRoot() {
|
|
47
|
-
let
|
|
48
|
-
while (
|
|
49
|
-
if (fs.existsSync(path.join(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
current = path.dirname(current);
|
|
32
|
+
let dir = process.cwd();
|
|
33
|
+
while (dir !== path.dirname(dir)) {
|
|
34
|
+
if (fs.existsSync(path.join(dir, '.agent'))) return dir;
|
|
35
|
+
if (fs.existsSync(path.join(dir, 'package.json'))) return dir;
|
|
36
|
+
dir = path.dirname(dir);
|
|
53
37
|
}
|
|
54
38
|
return process.cwd();
|
|
55
39
|
}
|
|
@@ -58,159 +42,146 @@ const projectRoot = findProjectRoot();
|
|
|
58
42
|
const dashboardPath = path.join(__dirname, '..', 'dashboard');
|
|
59
43
|
|
|
60
44
|
// ============================================================================
|
|
61
|
-
//
|
|
45
|
+
// DATA PROVIDERS
|
|
46
|
+
// ============================================================================
|
|
47
|
+
|
|
48
|
+
// Safe import helper
|
|
49
|
+
async function safeImport(modulePath) {
|
|
50
|
+
try {
|
|
51
|
+
return await import(modulePath);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Load data modules dynamically
|
|
58
|
+
let metricsCollector = null;
|
|
59
|
+
let causalityEngine = null;
|
|
60
|
+
let skillGenerator = null;
|
|
61
|
+
let abTesting = null;
|
|
62
|
+
let reinforcement = null;
|
|
63
|
+
|
|
64
|
+
async function loadModules() {
|
|
65
|
+
const libPath = path.join(__dirname, '..', 'lib');
|
|
66
|
+
metricsCollector = await safeImport(path.join(libPath, 'metrics-collector.js'));
|
|
67
|
+
causalityEngine = await safeImport(path.join(libPath, 'causality-engine.js'));
|
|
68
|
+
skillGenerator = await safeImport(path.join(libPath, 'skill-generator.js'));
|
|
69
|
+
abTesting = await safeImport(path.join(libPath, 'ab-testing.js'));
|
|
70
|
+
reinforcement = await safeImport(path.join(libPath, 'reinforcement-loop.js'));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// API HANDLERS
|
|
62
75
|
// ============================================================================
|
|
63
76
|
|
|
64
77
|
const api = {
|
|
65
|
-
// Full dashboard data
|
|
78
|
+
// Full dashboard data
|
|
66
79
|
'/api/dashboard': () => {
|
|
67
80
|
try {
|
|
68
|
-
|
|
81
|
+
const kpis = metricsCollector?.getKPIs?.() || { kpis: {} };
|
|
82
|
+
const summary = {
|
|
83
|
+
totalTasks: metricsCollector?.getMetricValue?.('total_tasks') || 0,
|
|
84
|
+
patternsLearned: causalityEngine?.getPatternCount?.() || 0,
|
|
85
|
+
skillsGenerated: skillGenerator?.getSkillCount?.() || 0,
|
|
86
|
+
version: '7.0.0'
|
|
87
|
+
};
|
|
88
|
+
return { kpis: { kpis }, summary, version: '7.0.0' };
|
|
69
89
|
} catch (e) {
|
|
70
|
-
return { error: e.message, version: '
|
|
90
|
+
return { kpis: { kpis: {} }, summary: {}, error: e.message, version: '7.0.0' };
|
|
71
91
|
}
|
|
72
92
|
},
|
|
73
93
|
|
|
74
94
|
// KPIs only
|
|
75
95
|
'/api/kpis': () => {
|
|
76
96
|
try {
|
|
77
|
-
return
|
|
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();
|
|
97
|
+
return metricsCollector?.getKPIs?.() || { kpis: {} };
|
|
96
98
|
} catch (e) {
|
|
97
|
-
return { error: e.message };
|
|
99
|
+
return { kpis: {}, error: e.message };
|
|
98
100
|
}
|
|
99
101
|
},
|
|
100
102
|
|
|
101
|
-
//
|
|
103
|
+
// Alerts
|
|
102
104
|
'/api/alerts': () => {
|
|
103
105
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return { alerts: [], error: e.message };
|
|
107
|
-
}
|
|
108
|
-
},
|
|
106
|
+
const kpis = metricsCollector?.getKPIs?.()?.kpis || {};
|
|
107
|
+
const alerts = [];
|
|
109
108
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
},
|
|
109
|
+
// Generate alerts based on KPI thresholds
|
|
110
|
+
if (kpis.task_success_rate && parseFloat(kpis.task_success_rate.value) < 80) {
|
|
111
|
+
alerts.push({ id: 'low_success', severity: 'warning', message: 'Task success rate below 80%' });
|
|
112
|
+
}
|
|
113
|
+
if (kpis.error_repeat_rate && parseFloat(kpis.error_repeat_rate.value) > 10) {
|
|
114
|
+
alerts.push({ id: 'high_error', severity: 'warning', message: 'Error repeat rate above 10%' });
|
|
115
|
+
}
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
'/api/counters': () => {
|
|
121
|
-
try {
|
|
122
|
-
return { counters: getCounterWidgets() };
|
|
117
|
+
return { alerts, count: alerts.length };
|
|
123
118
|
} catch (e) {
|
|
124
|
-
return {
|
|
119
|
+
return { alerts: [], error: e.message };
|
|
125
120
|
}
|
|
126
121
|
},
|
|
127
122
|
|
|
128
|
-
//
|
|
129
|
-
'/api/
|
|
123
|
+
// Skills
|
|
124
|
+
'/api/skills': () => {
|
|
130
125
|
try {
|
|
131
|
-
|
|
126
|
+
const skills = skillGenerator?.getAllSkills?.() || [];
|
|
127
|
+
return {
|
|
128
|
+
skills,
|
|
129
|
+
stats: { total: skills.length }
|
|
130
|
+
};
|
|
132
131
|
} catch (e) {
|
|
133
|
-
return { error: e.message };
|
|
132
|
+
return { skills: [], stats: { total: 0 }, error: e.message };
|
|
134
133
|
}
|
|
135
134
|
},
|
|
136
135
|
|
|
137
|
-
// A/B
|
|
136
|
+
// A/B Testing
|
|
138
137
|
'/api/ab-testing': () => {
|
|
139
138
|
try {
|
|
139
|
+
const active = abTesting?.getActiveTests?.() || [];
|
|
140
|
+
const completed = abTesting?.getCompletedTests?.() || [];
|
|
140
141
|
return {
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
active,
|
|
143
|
+
completed,
|
|
144
|
+
stats: { running: active.length, completed: completed.length }
|
|
143
145
|
};
|
|
144
146
|
} catch (e) {
|
|
145
|
-
return { error: e.message };
|
|
147
|
+
return { active: [], completed: [], stats: { running: 0, completed: 0 }, error: e.message };
|
|
146
148
|
}
|
|
147
149
|
},
|
|
148
150
|
|
|
149
|
-
//
|
|
150
|
-
'/api/
|
|
151
|
+
// Reinforcement Loop
|
|
152
|
+
'/api/reinforcement': () => {
|
|
151
153
|
try {
|
|
154
|
+
const stats = reinforcement?.getStats?.() || {};
|
|
152
155
|
return {
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
totalRewards: stats.rewards || 0,
|
|
157
|
+
totalPenalties: stats.penalties || 0,
|
|
158
|
+
averageConfidence: stats.avgConfidence || null
|
|
155
159
|
};
|
|
156
160
|
} catch (e) {
|
|
157
|
-
return { error: e.message };
|
|
161
|
+
return { totalRewards: 0, totalPenalties: 0, error: e.message };
|
|
158
162
|
}
|
|
159
163
|
},
|
|
160
164
|
|
|
161
|
-
//
|
|
165
|
+
// Patterns
|
|
162
166
|
'/api/patterns': () => {
|
|
163
167
|
try {
|
|
164
|
-
const patterns = loadCausalPatterns();
|
|
165
|
-
return {
|
|
166
|
-
total: patterns.length,
|
|
167
|
-
patterns: patterns.slice(0, 20) // Limit to 20 most recent
|
|
168
|
-
};
|
|
168
|
+
const patterns = causalityEngine?.loadCausalPatterns?.() || [];
|
|
169
|
+
return { total: patterns.length, patterns: patterns.slice(0, 20) };
|
|
169
170
|
} catch (e) {
|
|
170
171
|
return { total: 0, patterns: [], error: e.message };
|
|
171
172
|
}
|
|
172
173
|
},
|
|
173
174
|
|
|
174
|
-
//
|
|
175
|
-
'/api/
|
|
176
|
-
|
|
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
|
-
}
|
|
175
|
+
// Summary (legacy support)
|
|
176
|
+
'/api/summary': () => {
|
|
177
|
+
return { status: 'ok', version: '7.0.0', server: 'PikaKit Dashboard Server' };
|
|
186
178
|
}
|
|
187
179
|
};
|
|
188
180
|
|
|
189
181
|
// ============================================================================
|
|
190
|
-
//
|
|
182
|
+
// MIME TYPES
|
|
191
183
|
// ============================================================================
|
|
192
184
|
|
|
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
185
|
const mimeTypes = {
|
|
215
186
|
'.html': 'text/html',
|
|
216
187
|
'.css': 'text/css',
|
|
@@ -221,124 +192,121 @@ const mimeTypes = {
|
|
|
221
192
|
'.svg': 'image/svg+xml'
|
|
222
193
|
};
|
|
223
194
|
|
|
224
|
-
//
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const urlParts = req.url.split('?');
|
|
228
|
-
const url = urlParts[0];
|
|
229
|
-
const query = new URLSearchParams(urlParts[1] || '');
|
|
195
|
+
// ============================================================================
|
|
196
|
+
// SERVER
|
|
197
|
+
// ============================================================================
|
|
230
198
|
|
|
231
|
-
|
|
199
|
+
function createServer(port) {
|
|
200
|
+
const server = http.createServer(async (req, res) => {
|
|
201
|
+
// CORS headers
|
|
232
202
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
233
203
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
234
204
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
235
205
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
206
|
+
if (req.method === 'OPTIONS') {
|
|
207
|
+
res.writeHead(204);
|
|
208
|
+
res.end();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const url = new URL(req.url, `http://localhost:${port}`);
|
|
213
|
+
const pathname = url.pathname;
|
|
214
|
+
|
|
215
|
+
// API routes
|
|
216
|
+
if (api[pathname]) {
|
|
217
|
+
const data = api[pathname](url.searchParams);
|
|
218
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
219
|
+
res.end(JSON.stringify(data, null, 2));
|
|
247
220
|
return;
|
|
248
221
|
}
|
|
249
222
|
|
|
250
|
-
//
|
|
251
|
-
let filePath =
|
|
223
|
+
// Static files
|
|
224
|
+
let filePath = pathname === '/' ? 'index.html' : pathname.slice(1);
|
|
252
225
|
filePath = path.join(dashboardPath, filePath);
|
|
253
226
|
|
|
254
227
|
if (fs.existsSync(filePath)) {
|
|
255
228
|
const ext = path.extname(filePath);
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
res.
|
|
259
|
-
res.
|
|
260
|
-
|
|
261
|
-
} else {
|
|
262
|
-
res.writeHead(404);
|
|
263
|
-
res.end('Not found');
|
|
229
|
+
const contentType = mimeTypes[ext] || 'application/octet-stream';
|
|
230
|
+
const content = fs.readFileSync(filePath);
|
|
231
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
232
|
+
res.end(content);
|
|
233
|
+
return;
|
|
264
234
|
}
|
|
235
|
+
|
|
236
|
+
// 404
|
|
237
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
238
|
+
res.end(JSON.stringify({ error: 'Not found', path: pathname }));
|
|
265
239
|
});
|
|
266
240
|
|
|
267
241
|
return server;
|
|
268
242
|
}
|
|
269
243
|
|
|
270
|
-
function startServer(port = 3030) {
|
|
244
|
+
async function startServer(port = 3030) {
|
|
245
|
+
await loadModules();
|
|
246
|
+
|
|
271
247
|
const server = createServer(port);
|
|
272
248
|
|
|
273
249
|
server.listen(port, () => {
|
|
274
|
-
console.log(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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}`);
|
|
250
|
+
console.log(`
|
|
251
|
+
${c.bold}${c.cyan}╔════════════════════════════════════════════════════════════╗${c.reset}
|
|
252
|
+
${c.bold}${c.cyan}║${c.reset} ${c.cyan}║${c.reset}
|
|
253
|
+
${c.bold}${c.cyan}║${c.reset} 🧠 ${c.bold}PikaKit Dashboard Server v7.0${c.reset} ${c.cyan}║${c.reset}
|
|
254
|
+
${c.bold}${c.cyan}║${c.reset} ${c.cyan}║${c.reset}
|
|
255
|
+
${c.bold}${c.cyan}║${c.reset} ${c.green}→${c.reset} Dashboard: ${c.yellow}http://localhost:${port}${c.reset} ${c.cyan}║${c.reset}
|
|
256
|
+
${c.bold}${c.cyan}║${c.reset} ${c.green}→${c.reset} API Base: ${c.yellow}http://localhost:${port}/api${c.reset} ${c.cyan}║${c.reset}
|
|
257
|
+
${c.bold}${c.cyan}║${c.reset} ${c.cyan}║${c.reset}
|
|
258
|
+
${c.bold}${c.cyan}║${c.reset} ${c.gray}Press Ctrl+C to stop${c.reset} ${c.cyan}║${c.reset}
|
|
259
|
+
${c.bold}${c.cyan}║${c.reset} ${c.cyan}║${c.reset}
|
|
260
|
+
${c.bold}${c.cyan}╚════════════════════════════════════════════════════════════╝${c.reset}
|
|
261
|
+
`);
|
|
291
262
|
});
|
|
292
263
|
|
|
293
|
-
server.on('error', (
|
|
294
|
-
if (
|
|
295
|
-
console.log(`${c.
|
|
296
|
-
|
|
264
|
+
server.on('error', (e) => {
|
|
265
|
+
if (e.code === 'EADDRINUSE') {
|
|
266
|
+
console.log(`${c.yellow}Port ${port} in use, trying ${port + 1}...${c.reset}`);
|
|
267
|
+
startServer(port + 1);
|
|
297
268
|
} else {
|
|
298
|
-
console.error(`${c.red}Server error:${c.reset}`,
|
|
269
|
+
console.error(`${c.red}Server error:${c.reset}`, e.message);
|
|
299
270
|
}
|
|
300
|
-
process.exit(1);
|
|
301
271
|
});
|
|
302
272
|
|
|
303
273
|
return server;
|
|
304
274
|
}
|
|
305
275
|
|
|
306
|
-
//
|
|
276
|
+
// CLI handling
|
|
307
277
|
const args = process.argv.slice(2);
|
|
308
278
|
|
|
309
|
-
if (args.includes('--
|
|
310
|
-
|
|
311
|
-
|
|
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}
|
|
279
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
280
|
+
console.log(`
|
|
281
|
+
${c.bold}PikaKit Dashboard Server v7.0${c.reset}
|
|
318
282
|
|
|
319
283
|
${c.bold}Usage:${c.reset}
|
|
320
|
-
node
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
GET /api/
|
|
328
|
-
GET /api/
|
|
329
|
-
GET /api/alerts
|
|
330
|
-
GET /api/
|
|
331
|
-
GET /api/
|
|
332
|
-
GET /api/reinforcement
|
|
333
|
-
GET /api/
|
|
334
|
-
GET /api/
|
|
335
|
-
GET /api/patterns - Causal patterns
|
|
336
|
-
GET /api/history?metric=X - Metric history
|
|
284
|
+
node dashboard-server.js [options]
|
|
285
|
+
|
|
286
|
+
${c.bold}Options:${c.reset}
|
|
287
|
+
--port, -p <number> Port to run on (default: 3030)
|
|
288
|
+
--help, -h Show this help
|
|
289
|
+
|
|
290
|
+
${c.bold}API Endpoints:${c.reset}
|
|
291
|
+
GET /api/dashboard Full dashboard data
|
|
292
|
+
GET /api/kpis KPI metrics only
|
|
293
|
+
GET /api/alerts Active alerts
|
|
294
|
+
GET /api/skills Auto-generated skills
|
|
295
|
+
GET /api/ab-testing A/B test experiments
|
|
296
|
+
GET /api/reinforcement Reinforcement loop stats
|
|
297
|
+
GET /api/patterns Causal patterns
|
|
298
|
+
GET /api/summary Server status
|
|
337
299
|
|
|
338
300
|
${c.bold}Example:${c.reset}
|
|
339
|
-
node
|
|
340
|
-
# Open http://localhost:3030 in browser
|
|
301
|
+
node dashboard-server.js --port 3030
|
|
341
302
|
`);
|
|
303
|
+
} else {
|
|
304
|
+
let port = 3030;
|
|
305
|
+
const portIdx = args.findIndex(a => a === '--port' || a === '-p');
|
|
306
|
+
if (portIdx !== -1 && args[portIdx + 1]) {
|
|
307
|
+
port = parseInt(args[portIdx + 1], 10) || 3030;
|
|
308
|
+
}
|
|
309
|
+
startServer(port);
|
|
342
310
|
}
|
|
343
311
|
|
|
344
312
|
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.4"; }
|
|
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.4",
|
|
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>",
|