fivocell 1.0.5 → 3.0.0
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/README.md +63 -464
- package/bin/cell.js +2 -2
- package/dist/behavior-intelligence.d.ts +90 -0
- package/dist/behavior-intelligence.d.ts.map +1 -0
- package/dist/behavior-intelligence.js +595 -0
- package/dist/behavior-intelligence.js.map +1 -0
- package/dist/behavioral-tracker.d.ts +90 -0
- package/dist/behavioral-tracker.d.ts.map +1 -0
- package/dist/behavioral-tracker.js +185 -0
- package/dist/behavioral-tracker.js.map +1 -0
- package/dist/cli.js +417 -1659
- package/dist/cli.js.map +1 -1
- package/dist/cloud-sync.d.ts +66 -0
- package/dist/cloud-sync.d.ts.map +1 -0
- package/dist/cloud-sync.js +328 -0
- package/dist/cloud-sync.js.map +1 -0
- package/dist/code-scanner.d.ts +51 -0
- package/dist/code-scanner.d.ts.map +1 -0
- package/dist/code-scanner.js +966 -0
- package/dist/code-scanner.js.map +1 -0
- package/dist/community-intel.d.ts +34 -0
- package/dist/community-intel.d.ts.map +1 -0
- package/dist/community-intel.js +148 -0
- package/dist/community-intel.js.map +1 -0
- package/dist/community-intelligence.d.ts +42 -0
- package/dist/community-intelligence.d.ts.map +1 -0
- package/dist/community-intelligence.js +160 -0
- package/dist/community-intelligence.js.map +1 -0
- package/dist/community-v2.d.ts +106 -0
- package/dist/community-v2.d.ts.map +1 -0
- package/dist/community-v2.js +378 -0
- package/dist/community-v2.js.map +1 -0
- package/dist/core/__tests__/chapter8-hostile.test.js +1 -1
- package/dist/core/__tests__/chapter8-hostile.test.js.map +1 -1
- package/dist/core/__tests__/chapter9-hostile.test.js +1 -1
- package/dist/core/__tests__/chapter9-hostile.test.js.map +1 -1
- package/dist/core/__tests__/complexity-analyzer.test.js +15 -15
- package/dist/core/__tests__/team-composer.test.js +2 -1
- package/dist/core/__tests__/team-composer.test.js.map +1 -1
- package/dist/core/convention-detector.d.ts.map +1 -1
- package/dist/core/convention-detector.js +11 -23
- package/dist/core/convention-detector.js.map +1 -1
- package/dist/core/cost-optimizer.d.ts.map +1 -1
- package/dist/core/cost-optimizer.js +13 -25
- package/dist/core/cost-optimizer.js.map +1 -1
- package/dist/core/database.d.ts +28 -0
- package/dist/core/database.d.ts.map +1 -0
- package/dist/core/database.js +587 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/knowledge-graph.d.ts.map +1 -1
- package/dist/core/knowledge-graph.js +9 -24
- package/dist/core/knowledge-graph.js.map +1 -1
- package/dist/core/logger.d.ts +9 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +26 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/playbook-generator.js +48 -48
- package/dist/core/privacy-manager.d.ts.map +1 -1
- package/dist/core/privacy-manager.js +5 -0
- package/dist/core/privacy-manager.js.map +1 -1
- package/dist/core/project-dna.d.ts.map +1 -1
- package/dist/core/project-dna.js +6 -19
- package/dist/core/project-dna.js.map +1 -1
- package/dist/core/prompt-builder.d.ts +18 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +325 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/session-memory.d.ts +90 -0
- package/dist/core/session-memory.d.ts.map +1 -0
- package/dist/core/session-memory.js +229 -0
- package/dist/core/session-memory.js.map +1 -0
- package/dist/core/signal-capture.d.ts +5 -0
- package/dist/core/signal-capture.d.ts.map +1 -1
- package/dist/core/signal-capture.js +67 -0
- package/dist/core/signal-capture.js.map +1 -1
- package/dist/core/team-composer.d.ts.map +1 -1
- package/dist/core/team-composer.js +16 -6
- package/dist/core/team-composer.js.map +1 -1
- package/dist/cross-model-memory.d.ts +95 -0
- package/dist/cross-model-memory.d.ts.map +1 -0
- package/dist/cross-model-memory.js +229 -0
- package/dist/cross-model-memory.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +3 -0
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +98 -64
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +637 -25
- package/dist/daemon/server.js.map +1 -1
- package/dist/developer-intelligence.d.ts +18 -0
- package/dist/developer-intelligence.d.ts.map +1 -0
- package/dist/developer-intelligence.js +180 -0
- package/dist/developer-intelligence.js.map +1 -0
- package/dist/first-run.d.ts +8 -0
- package/dist/first-run.d.ts.map +1 -0
- package/dist/first-run.js +182 -0
- package/dist/first-run.js.map +1 -0
- package/dist/focus-report.d.ts +32 -0
- package/dist/focus-report.d.ts.map +1 -0
- package/dist/focus-report.js +293 -0
- package/dist/focus-report.js.map +1 -0
- package/dist/ide-intelligence.d.ts +118 -0
- package/dist/ide-intelligence.d.ts.map +1 -0
- package/dist/ide-intelligence.js +284 -0
- package/dist/ide-intelligence.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +119 -2
- package/dist/index.js.map +1 -1
- package/dist/insight-generator.d.ts +58 -0
- package/dist/insight-generator.d.ts.map +1 -0
- package/dist/insight-generator.js +314 -0
- package/dist/insight-generator.js.map +1 -0
- package/dist/journey-memory.d.ts +75 -0
- package/dist/journey-memory.d.ts.map +1 -0
- package/dist/journey-memory.js +360 -0
- package/dist/journey-memory.js.map +1 -0
- package/dist/layers.d.ts +92 -0
- package/dist/layers.d.ts.map +1 -0
- package/dist/layers.js +226 -0
- package/dist/layers.js.map +1 -0
- package/dist/mcp-server.d.ts +406 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +414 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/onboarding-scan.d.ts +174 -0
- package/dist/onboarding-scan.d.ts.map +1 -0
- package/dist/onboarding-scan.js +1039 -0
- package/dist/onboarding-scan.js.map +1 -0
- package/dist/pc-scanner.d.ts +46 -0
- package/dist/pc-scanner.d.ts.map +1 -0
- package/dist/pc-scanner.js +488 -0
- package/dist/pc-scanner.js.map +1 -0
- package/dist/personal-intelligence.d.ts +97 -0
- package/dist/personal-intelligence.d.ts.map +1 -0
- package/dist/personal-intelligence.js +408 -0
- package/dist/personal-intelligence.js.map +1 -0
- package/dist/predictive-engine.d.ts +19 -0
- package/dist/predictive-engine.d.ts.map +1 -0
- package/dist/predictive-engine.js +107 -0
- package/dist/predictive-engine.js.map +1 -0
- package/dist/predictive-intelligence.d.ts +95 -0
- package/dist/predictive-intelligence.d.ts.map +1 -0
- package/dist/predictive-intelligence.js +544 -0
- package/dist/predictive-intelligence.js.map +1 -0
- package/dist/production.d.ts +67 -0
- package/dist/production.d.ts.map +1 -0
- package/dist/production.js +333 -0
- package/dist/production.js.map +1 -0
- package/dist/senior-features.d.ts +63 -0
- package/dist/senior-features.d.ts.map +1 -0
- package/dist/senior-features.js +325 -0
- package/dist/senior-features.js.map +1 -0
- package/dist/style-pull.d.ts +40 -0
- package/dist/style-pull.d.ts.map +1 -0
- package/dist/style-pull.js +385 -0
- package/dist/style-pull.js.map +1 -0
- package/dist/team-collaboration.d.ts +116 -0
- package/dist/team-collaboration.d.ts.map +1 -0
- package/dist/team-collaboration.js +375 -0
- package/dist/team-collaboration.js.map +1 -0
- package/dist/team-git.d.ts +47 -0
- package/dist/team-git.d.ts.map +1 -0
- package/dist/team-git.js +305 -0
- package/dist/team-git.js.map +1 -0
- package/dist/team-intelligence.d.ts +64 -0
- package/dist/team-intelligence.d.ts.map +1 -0
- package/dist/team-intelligence.js +289 -0
- package/dist/team-intelligence.js.map +1 -0
- package/dist/test-watch.d.ts +2 -0
- package/dist/test-watch.d.ts.map +1 -0
- package/dist/test-watch.js +8 -0
- package/dist/test-watch.js.map +1 -0
- package/dist/user-intelligence.d.ts +69 -0
- package/dist/user-intelligence.d.ts.map +1 -0
- package/dist/user-intelligence.js +553 -0
- package/dist/user-intelligence.js.map +1 -0
- package/dist/work-style.d.ts +49 -0
- package/dist/work-style.d.ts.map +1 -0
- package/dist/work-style.js +247 -0
- package/dist/work-style.js.map +1 -0
- package/package.json +3 -2
package/dist/daemon/server.js
CHANGED
|
@@ -113,7 +113,10 @@ const recommendation_store_1 = require("../core/recommendation-store");
|
|
|
113
113
|
const community_intelligence_1 = require("../core/community-intelligence");
|
|
114
114
|
const org_intelligence_1 = require("../core/org-intelligence");
|
|
115
115
|
const cross_layer_intelligence_1 = require("../core/cross-layer-intelligence");
|
|
116
|
+
const database_1 = require("../core/database");
|
|
117
|
+
const logger_1 = require("../core/logger");
|
|
116
118
|
const CELL_DIR = path.join(os.homedir(), '.fivo', 'cell');
|
|
119
|
+
(0, database_1.initializeDatabase)();
|
|
117
120
|
const META_PATH = path.join(CELL_DIR, 'cell-meta.json');
|
|
118
121
|
const PORT = 9876;
|
|
119
122
|
function getCloudConfig() {
|
|
@@ -121,7 +124,9 @@ function getCloudConfig() {
|
|
|
121
124
|
if (fs.existsSync(META_PATH))
|
|
122
125
|
return JSON.parse(fs.readFileSync(META_PATH, 'utf-8'));
|
|
123
126
|
}
|
|
124
|
-
catch {
|
|
127
|
+
catch (e) {
|
|
128
|
+
logger_1.logger.warn('Failed to read cell-meta.json: ' + String(e));
|
|
129
|
+
}
|
|
125
130
|
return { cloudSyncEnabled: true };
|
|
126
131
|
}
|
|
127
132
|
const app = (0, express_1.default)();
|
|
@@ -199,16 +204,104 @@ app.get('/health', (_req, res) => {
|
|
|
199
204
|
});
|
|
200
205
|
});
|
|
201
206
|
app.post('/signal', (req, res) => {
|
|
202
|
-
const { type, originalCode, editedCode, context } = req.body;
|
|
203
|
-
if (!type
|
|
204
|
-
res.status(400).json({ error: 'type
|
|
207
|
+
const { type, originalCode, editedCode, context, file, fromFile, costMs, durationMs, switchCount, language, errorMessage, errorType, line, fixApplied, fixWorked, timeToFixMs, decision, approach, result, worked, task, files, description, stuckId, resolution, project } = req.body;
|
|
208
|
+
if (!type) {
|
|
209
|
+
res.status(400).json({ error: 'type required' });
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
// ─── Behavioral Signals ───────────────────────────────────────
|
|
213
|
+
if (type === 'error') {
|
|
214
|
+
const { logError, getErrorPatterns } = require('../behavioral-tracker');
|
|
215
|
+
const r = logError({ project, file, errorType, errorMessage, line });
|
|
216
|
+
// Check if repeat mistake — send warning
|
|
217
|
+
let warning = null;
|
|
218
|
+
try {
|
|
219
|
+
const patterns = getErrorPatterns(project);
|
|
220
|
+
const match = patterns.find((p) => p.error_type === errorType);
|
|
221
|
+
if (match && match.count >= 2) {
|
|
222
|
+
warning = `⚠ Repeat mistake! "${errorType}" has occurred ${match.count}x before. Fix the root cause.`;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch { }
|
|
226
|
+
res.json({ recorded: true, id: r.id, warning });
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (type === 'error_fix') {
|
|
230
|
+
const { logErrorFix } = require('../behavioral-tracker');
|
|
231
|
+
logErrorFix({ errorId: stuckId || 0, fixApplied: fixApplied || '', worked: fixWorked || false, timeToFixMs: timeToFixMs || 0 });
|
|
232
|
+
res.json({ recorded: true });
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (type === 'decision') {
|
|
236
|
+
const { logDecision } = require('../behavioral-tracker');
|
|
237
|
+
const r = logDecision({ project, file, decision, approach, result, worked, context: req.body.context || '' });
|
|
238
|
+
// Auto-track in session memory
|
|
239
|
+
try {
|
|
240
|
+
const { SessionMemory } = require('../core/session-memory');
|
|
241
|
+
const mem = new SessionMemory();
|
|
242
|
+
const lastSess = mem.getLastSessionForProject(project || '');
|
|
243
|
+
if (lastSess && !lastSess.endTime) {
|
|
244
|
+
const decs = JSON.parse(String(lastSess.keyDecisions || '[]'));
|
|
245
|
+
decs.push(`${decision}: ${approach || result || ''}`);
|
|
246
|
+
mem.endSession(lastSess.id, { keyDecisions: decs, contextSnapshot: req.body.context || decision });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
catch { }
|
|
250
|
+
res.json({ recorded: true, id: r.id });
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (type === 'context') {
|
|
254
|
+
const { logContext } = require('../behavioral-tracker');
|
|
255
|
+
const r = logContext({ project, task, files });
|
|
256
|
+
// Auto-start session if none exists
|
|
257
|
+
try {
|
|
258
|
+
const { SessionMemory } = require('../core/session-memory');
|
|
259
|
+
const mem = new SessionMemory();
|
|
260
|
+
const lastSess = mem.getLastSessionForProject(project || '');
|
|
261
|
+
if (!lastSess || lastSess.endTime) {
|
|
262
|
+
const tool = req.body.tool || 'cli';
|
|
263
|
+
mem.startSession(tool, project || '');
|
|
264
|
+
if (files && files.length > 0) {
|
|
265
|
+
const newSess = mem.getLastSessionForProject(project || '');
|
|
266
|
+
if (newSess)
|
|
267
|
+
mem.endSession(newSess.id, { filesTouched: files, contextSnapshot: task });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch { }
|
|
272
|
+
res.json({ recorded: true, id: r.id });
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (type === 'stuck') {
|
|
276
|
+
const { logStuck } = require('../behavioral-tracker');
|
|
277
|
+
const r = logStuck({ project, file, description });
|
|
278
|
+
res.json({ recorded: true, id: r.id });
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (type === 'stuck_resolved') {
|
|
282
|
+
const { logStuckResolved } = require('../behavioral-tracker');
|
|
283
|
+
logStuckResolved(stuckId || 0, resolution || '');
|
|
284
|
+
res.json({ recorded: true });
|
|
205
285
|
return;
|
|
206
286
|
}
|
|
287
|
+
// ─── IDE Signals ──────────────────────────────────────────────
|
|
288
|
+
if (type === 'tab_switch' || type === 'focus_block' || type === 'file_save') {
|
|
289
|
+
try {
|
|
290
|
+
const db = (0, database_1.getDb)();
|
|
291
|
+
db.prepare('INSERT INTO behavior_events (event_type, project, file_path, description, severity, evidence) VALUES (?, ?, ?, ?, ?, ?)')
|
|
292
|
+
.run(type, '', file || '', JSON.stringify({ fromFile, costMs, durationMs, switchCount, language }), 'low', JSON.stringify(req.body));
|
|
293
|
+
}
|
|
294
|
+
catch { }
|
|
295
|
+
res.json({ recorded: true, type });
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// ─── Legacy Signals ──────────────────────────────────────────
|
|
299
|
+
const ctx = context || {};
|
|
207
300
|
let signal;
|
|
208
301
|
let patternsExtracted = 0;
|
|
209
302
|
switch (type) {
|
|
210
303
|
case 'edit_diff': {
|
|
211
|
-
signal = engines.signalCapture.captureEditDiff(originalCode || '', editedCode || '',
|
|
304
|
+
signal = engines.signalCapture.captureEditDiff(originalCode || '', editedCode || '', ctx);
|
|
212
305
|
try {
|
|
213
306
|
const result = engines.extractionCascade.extract(originalCode || '', editedCode || '');
|
|
214
307
|
patternsExtracted = engines.learningLayer.process(result, true);
|
|
@@ -221,35 +314,28 @@ app.post('/signal', (req, res) => {
|
|
|
221
314
|
break;
|
|
222
315
|
}
|
|
223
316
|
case 'accept': {
|
|
224
|
-
signal = engines.signalCapture.captureAccept(originalCode || '',
|
|
317
|
+
signal = engines.signalCapture.captureAccept(originalCode || '', ctx);
|
|
225
318
|
const dummy = engines.patternStore.getAllPatterns().slice(0, 1);
|
|
226
319
|
for (const p of dummy) {
|
|
227
320
|
const step = (0, workflow_tracker_1.recordStep)(p, 'accept');
|
|
228
321
|
(0, outcome_recorder_1.recordOutcome)(p, 'accept', step.sessionId, true, 0);
|
|
229
|
-
(0, failure_memory_1.recordFailure)(p, false,
|
|
230
|
-
(0, time_saved_1.recordTimeSaved)({
|
|
231
|
-
patternId: p.patternId,
|
|
232
|
-
category: p.category,
|
|
233
|
-
description: p.description,
|
|
234
|
-
from: p.from,
|
|
235
|
-
to: p.to,
|
|
236
|
-
language: context?.language || 'unknown',
|
|
237
|
-
});
|
|
322
|
+
(0, failure_memory_1.recordFailure)(p, false, ctx.language || 'unknown');
|
|
323
|
+
(0, time_saved_1.recordTimeSaved)({ patternId: p.patternId, category: p.category, description: p.description, from: p.from, to: p.to, language: ctx.language || 'unknown' });
|
|
238
324
|
}
|
|
239
325
|
break;
|
|
240
326
|
}
|
|
241
327
|
case 'reject': {
|
|
242
|
-
signal = engines.signalCapture.captureReject(originalCode || '',
|
|
328
|
+
signal = engines.signalCapture.captureReject(originalCode || '', ctx);
|
|
243
329
|
const dummyR = engines.patternStore.getAllPatterns().slice(0, 1);
|
|
244
330
|
for (const p of dummyR) {
|
|
245
331
|
const step = (0, workflow_tracker_1.recordStep)(p, 'reject');
|
|
246
332
|
(0, outcome_recorder_1.recordOutcome)(p, 'reject', step.sessionId, false, 0);
|
|
247
|
-
(0, failure_memory_1.recordFailure)(p, true,
|
|
333
|
+
(0, failure_memory_1.recordFailure)(p, true, ctx.language || 'unknown');
|
|
248
334
|
}
|
|
249
335
|
break;
|
|
250
336
|
}
|
|
251
337
|
case 'retry': {
|
|
252
|
-
signal = engines.signalCapture.captureRetry(originalCode || '',
|
|
338
|
+
signal = engines.signalCapture.captureRetry(originalCode || '', ctx);
|
|
253
339
|
const dummyRt = engines.patternStore.getAllPatterns().slice(0, 1);
|
|
254
340
|
for (const p of dummyRt) {
|
|
255
341
|
const step = (0, workflow_tracker_1.recordStep)(p, 'retry');
|
|
@@ -318,15 +404,25 @@ app.get('/confidence/:patternId', (req, res) => {
|
|
|
318
404
|
});
|
|
319
405
|
// ─── IMPACT TRACKING ──────────────────────────────────
|
|
320
406
|
const impactLog = [];
|
|
407
|
+
function persistImpact(entry) {
|
|
408
|
+
try {
|
|
409
|
+
const db = (0, database_1.getDb)();
|
|
410
|
+
db.prepare('INSERT INTO outcomes (outcome_type, pattern_id, project, description, created_at) VALUES (?, ?, ?, ?, ?)')
|
|
411
|
+
.run('impact', entry.patternId, '', `Applied via ${entry.surface}`, new Date(entry.timestamp).toISOString());
|
|
412
|
+
}
|
|
413
|
+
catch { /* best-effort */ }
|
|
414
|
+
}
|
|
321
415
|
app.post('/impact/record', (req, res) => {
|
|
322
416
|
const { patternId, surface } = req.body;
|
|
323
417
|
if (!patternId) {
|
|
324
418
|
res.status(400).json({ error: 'patternId required' });
|
|
325
419
|
return;
|
|
326
420
|
}
|
|
327
|
-
|
|
421
|
+
const entry = { patternId, timestamp: Date.now(), surface: surface || 'unknown' };
|
|
422
|
+
impactLog.push(entry);
|
|
328
423
|
if (impactLog.length > 10000)
|
|
329
424
|
impactLog.splice(0, impactLog.length - 10000);
|
|
425
|
+
persistImpact(entry);
|
|
330
426
|
res.json({ recorded: true });
|
|
331
427
|
});
|
|
332
428
|
app.get('/impact/weekly', (_req, res) => {
|
|
@@ -368,7 +464,9 @@ app.post('/onboarding/scan', (req, res) => {
|
|
|
368
464
|
insights.push('TypeScript strict mode → You likely prefer const over let');
|
|
369
465
|
}
|
|
370
466
|
}
|
|
371
|
-
catch {
|
|
467
|
+
catch (e) {
|
|
468
|
+
logger_1.logger.warn('Failed to read tsconfig: ' + String(e));
|
|
469
|
+
}
|
|
372
470
|
try {
|
|
373
471
|
const eslintPaths = ['.eslintrc.json', '.eslintrc.js', '.eslintrc.yaml', '.eslintrc.yml', 'eslint.config.js'];
|
|
374
472
|
for (const eslintFile of eslintPaths) {
|
|
@@ -379,12 +477,16 @@ app.post('/onboarding/scan', (req, res) => {
|
|
|
379
477
|
if (JSON.stringify(eslint).includes('singlequote') || JSON.stringify(eslint).includes('single'))
|
|
380
478
|
insights.push('ESLint single quotes → You prefer \' over \"');
|
|
381
479
|
}
|
|
382
|
-
catch {
|
|
480
|
+
catch (e) {
|
|
481
|
+
logger_1.logger.warn('Failed to parse eslint config: ' + String(e));
|
|
482
|
+
}
|
|
383
483
|
break;
|
|
384
484
|
}
|
|
385
485
|
}
|
|
386
486
|
}
|
|
387
|
-
catch {
|
|
487
|
+
catch (e) {
|
|
488
|
+
logger_1.logger.warn('Failed to read eslint: ' + String(e));
|
|
489
|
+
}
|
|
388
490
|
try {
|
|
389
491
|
const pkgPath = path.join(dir, 'package.json');
|
|
390
492
|
if (fs.existsSync(pkgPath)) {
|
|
@@ -404,7 +506,9 @@ app.post('/onboarding/scan', (req, res) => {
|
|
|
404
506
|
insights.push('Zod → You prefer schema validation');
|
|
405
507
|
}
|
|
406
508
|
}
|
|
407
|
-
catch {
|
|
509
|
+
catch (e) {
|
|
510
|
+
logger_1.logger.warn('Failed to read package.json: ' + String(e));
|
|
511
|
+
}
|
|
408
512
|
res.json({ insights, count: insights.length, projectPath: dir });
|
|
409
513
|
});
|
|
410
514
|
// ─── LOCAL DASHBOARD HTML ─────────────────────────────
|
|
@@ -1299,20 +1403,528 @@ app.post('/intelligence/reset', (_req, res) => {
|
|
|
1299
1403
|
(0, cross_layer_intelligence_1.resetCrossLayer)();
|
|
1300
1404
|
res.json({ reset: true });
|
|
1301
1405
|
});
|
|
1406
|
+
// ─── CONTEXT INJECTION ───────────────────────────────
|
|
1407
|
+
const prompt_builder_1 = require("../core/prompt-builder");
|
|
1408
|
+
const session_memory_1 = require("../core/session-memory");
|
|
1409
|
+
const sessionMemory = new session_memory_1.SessionMemory();
|
|
1410
|
+
app.post('/session/start', (req, res) => {
|
|
1411
|
+
const { toolName, project } = req.body;
|
|
1412
|
+
const id = sessionMemory.startSession(toolName || 'unknown', project || 'unknown');
|
|
1413
|
+
res.json({ sessionId: id });
|
|
1414
|
+
});
|
|
1415
|
+
app.post('/session/end', (req, res) => {
|
|
1416
|
+
const { sessionId, filesTouched, keyDecisions, contextSnapshot } = req.body;
|
|
1417
|
+
sessionMemory.endSession(Number(sessionId), { filesTouched, keyDecisions, contextSnapshot });
|
|
1418
|
+
res.json({ ended: true });
|
|
1419
|
+
});
|
|
1420
|
+
app.get('/session/history', (req, res) => {
|
|
1421
|
+
const limit = Number(req.query.limit) || 10;
|
|
1422
|
+
const sessions = sessionMemory.getRecentSessions(limit);
|
|
1423
|
+
const stats = sessionMemory.getSessionStats();
|
|
1424
|
+
const chain = sessionMemory.buildContextChain();
|
|
1425
|
+
res.json({ sessions, stats, contextChain: chain });
|
|
1426
|
+
});
|
|
1427
|
+
app.get('/session/search', (req, res) => {
|
|
1428
|
+
const query = String(req.query.q || '');
|
|
1429
|
+
const results = query ? sessionMemory.searchSessions(query) : [];
|
|
1430
|
+
res.json({ query, results: results.slice(0, 10) });
|
|
1431
|
+
});
|
|
1432
|
+
app.get('/session/bugs', (req, res) => {
|
|
1433
|
+
const bugs = sessionMemory.getBugHistory(String(req.query.project || ''));
|
|
1434
|
+
const repeats = sessionMemory.getRepeatBugs();
|
|
1435
|
+
res.json({ bugs: bugs.slice(0, 20), repeatBugs: repeats });
|
|
1436
|
+
});
|
|
1437
|
+
app.get('/session/decisions', (req, res) => {
|
|
1438
|
+
const decisions = sessionMemory.getDecisionHistory(String(req.query.project || ''));
|
|
1439
|
+
const summary = sessionMemory.getDecisionSummary();
|
|
1440
|
+
res.json({ decisions: decisions.slice(0, 20), summary });
|
|
1441
|
+
});
|
|
1442
|
+
app.get('/context/inject', (req, res) => {
|
|
1443
|
+
const projectPath = req.query.projectPath;
|
|
1444
|
+
const toolName = req.query.tool;
|
|
1445
|
+
const compact = req.query.compact === 'true' || req.query.compact === '1';
|
|
1446
|
+
const ctx = (0, prompt_builder_1.buildContext)(projectPath, toolName);
|
|
1447
|
+
const text = (0, prompt_builder_1.formatContextForInjection)(ctx, compact);
|
|
1448
|
+
res.json({ content: [{ type: 'text', text }], context: ctx });
|
|
1449
|
+
});
|
|
1450
|
+
app.get('/predict', (req, res) => {
|
|
1451
|
+
const project = String(req.query.project || '');
|
|
1452
|
+
const type = String(req.query.type || '');
|
|
1453
|
+
Promise.resolve().then(() => __importStar(require('../predictive-intelligence'))).then(({ getAllPredictions }) => {
|
|
1454
|
+
const predictions = getAllPredictions(project || undefined);
|
|
1455
|
+
const filtered = type ? predictions.filter(p => p.type === type) : predictions;
|
|
1456
|
+
res.json({ predictions: filtered, count: filtered.length });
|
|
1457
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1458
|
+
});
|
|
1459
|
+
app.get('/predict-risk/:file', (req, res) => {
|
|
1460
|
+
const file = req.params.file;
|
|
1461
|
+
Promise.resolve().then(() => __importStar(require('../predictive-intelligence'))).then(({ calculateFileRisk }) => {
|
|
1462
|
+
res.json(calculateFileRisk(file));
|
|
1463
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1464
|
+
});
|
|
1465
|
+
app.get('/predict-time/:feature', (req, res) => {
|
|
1466
|
+
const feature = req.params.feature;
|
|
1467
|
+
Promise.resolve().then(() => __importStar(require('../predictive-intelligence'))).then(({ estimateFeatureTime }) => {
|
|
1468
|
+
res.json(estimateFeatureTime(feature));
|
|
1469
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1470
|
+
});
|
|
1471
|
+
app.get('/tools/compare', (_req, res) => {
|
|
1472
|
+
Promise.resolve().then(() => __importStar(require('../cross-model-memory'))).then(({ compareTools }) => {
|
|
1473
|
+
res.json({ tools: compareTools() });
|
|
1474
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1475
|
+
});
|
|
1476
|
+
app.get('/tools/suggest', (req, res) => {
|
|
1477
|
+
const taskType = String(req.query.task || '');
|
|
1478
|
+
if (!taskType) {
|
|
1479
|
+
res.status(400).json({ error: 'task query param required' });
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
Promise.resolve().then(() => __importStar(require('../cross-model-memory'))).then(({ suggestTool }) => {
|
|
1483
|
+
res.json({ suggestions: suggestTool(taskType) });
|
|
1484
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1485
|
+
});
|
|
1486
|
+
app.get('/tools/history', (_req, res) => {
|
|
1487
|
+
Promise.resolve().then(() => __importStar(require('../cross-model-memory'))).then(({ getModelHistory }) => {
|
|
1488
|
+
res.json({ history: getModelHistory() });
|
|
1489
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1490
|
+
});
|
|
1491
|
+
app.get('/tools/context/:tool', (req, res) => {
|
|
1492
|
+
const tool = req.params.tool;
|
|
1493
|
+
Promise.resolve().then(() => __importStar(require('../cross-model-memory'))).then(({ buildToolSpecificContext }) => {
|
|
1494
|
+
res.json({ context: buildToolSpecificContext(tool) });
|
|
1495
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1496
|
+
});
|
|
1497
|
+
app.get('/team/health', (req, res) => {
|
|
1498
|
+
const project = String(req.query.project || '') || undefined;
|
|
1499
|
+
Promise.resolve().then(() => __importStar(require('../team-collaboration'))).then(({ getTeamHealth }) => {
|
|
1500
|
+
res.json(getTeamHealth(project));
|
|
1501
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1502
|
+
});
|
|
1503
|
+
app.get('/team/silos', (_req, res) => {
|
|
1504
|
+
Promise.resolve().then(() => __importStar(require('../team-collaboration'))).then(({ detectKnowledgeSilos, calculateBusFactor, suggestKnowledgeTransfer }) => {
|
|
1505
|
+
res.json({ silos: detectKnowledgeSilos(), busFactor: calculateBusFactor(), transfers: suggestKnowledgeTransfer() });
|
|
1506
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1507
|
+
});
|
|
1508
|
+
app.get('/team/style', (req, res) => {
|
|
1509
|
+
const project = String(req.query.project || '') || undefined;
|
|
1510
|
+
Promise.resolve().then(() => __importStar(require('../team-collaboration'))).then(({ composeTeamStyle }) => {
|
|
1511
|
+
res.json(composeTeamStyle(project));
|
|
1512
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1513
|
+
});
|
|
1514
|
+
app.get('/team/retro', (req, res) => {
|
|
1515
|
+
const days = parseInt(String(req.query.days || '14')) || 14;
|
|
1516
|
+
const project = String(req.query.project || '') || undefined;
|
|
1517
|
+
Promise.resolve().then(() => __importStar(require('../team-collaboration'))).then(({ generateSprintRetro }) => {
|
|
1518
|
+
res.json(generateSprintRetro(days, project));
|
|
1519
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1520
|
+
});
|
|
1521
|
+
app.get('/team/onboard/:team', (req, res) => {
|
|
1522
|
+
const team = req.params.team;
|
|
1523
|
+
const project = String(req.query.project || '') || undefined;
|
|
1524
|
+
Promise.resolve().then(() => __importStar(require('../team-collaboration'))).then(({ generateOnboardingDoc }) => {
|
|
1525
|
+
res.json(generateOnboardingDoc(team, project));
|
|
1526
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1527
|
+
});
|
|
1528
|
+
app.get('/community/compare', (_req, res) => {
|
|
1529
|
+
Promise.resolve().then(() => __importStar(require('../community-v2'))).then(({ benchmarkPersonal, benchmarkBlindSpots }) => {
|
|
1530
|
+
res.json({ benchmarks: benchmarkPersonal(), blindSpots: benchmarkBlindSpots() });
|
|
1531
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1532
|
+
});
|
|
1533
|
+
app.get('/community/trends', (_req, res) => {
|
|
1534
|
+
Promise.resolve().then(() => __importStar(require('../community-v2'))).then(({ detectTrends, getCommunityStats }) => {
|
|
1535
|
+
res.json({ trends: detectTrends(), stats: getCommunityStats() });
|
|
1536
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1537
|
+
});
|
|
1538
|
+
app.get('/community/insights', (_req, res) => {
|
|
1539
|
+
Promise.resolve().then(() => __importStar(require('../community-v2'))).then(({ generateInsights }) => {
|
|
1540
|
+
res.json({ insights: generateInsights() });
|
|
1541
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1542
|
+
});
|
|
1543
|
+
app.get('/personal/rhythm', (_req, res) => {
|
|
1544
|
+
Promise.resolve().then(() => __importStar(require('../personal-intelligence'))).then(({ detectCodingRhythm }) => {
|
|
1545
|
+
res.json(detectCodingRhythm());
|
|
1546
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1547
|
+
});
|
|
1548
|
+
app.get('/personal/burnout', (_req, res) => {
|
|
1549
|
+
Promise.resolve().then(() => __importStar(require('../personal-intelligence'))).then(({ detectBurnout }) => {
|
|
1550
|
+
res.json(detectBurnout());
|
|
1551
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1552
|
+
});
|
|
1553
|
+
app.get('/personal/mastery', (_req, res) => {
|
|
1554
|
+
Promise.resolve().then(() => __importStar(require('../personal-intelligence'))).then(({ getTechMasteryMap }) => {
|
|
1555
|
+
res.json({ mastery: getTechMasteryMap() });
|
|
1556
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1557
|
+
});
|
|
1558
|
+
app.get('/personal/growth', (_req, res) => {
|
|
1559
|
+
Promise.resolve().then(() => __importStar(require('../personal-intelligence'))).then(({ getCareerTrajectory }) => {
|
|
1560
|
+
res.json(getCareerTrajectory());
|
|
1561
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1562
|
+
});
|
|
1563
|
+
app.get('/personal/weekly', (_req, res) => {
|
|
1564
|
+
Promise.resolve().then(() => __importStar(require('../personal-intelligence'))).then(({ generateWeeklyDigest }) => {
|
|
1565
|
+
res.json(generateWeeklyDigest());
|
|
1566
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1567
|
+
});
|
|
1568
|
+
app.get('/production/health', (_req, res) => {
|
|
1569
|
+
Promise.resolve().then(() => __importStar(require('../production'))).then(({ getHealthStatus }) => {
|
|
1570
|
+
res.json(getHealthStatus());
|
|
1571
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1572
|
+
});
|
|
1573
|
+
app.get('/production/metrics', (_req, res) => {
|
|
1574
|
+
Promise.resolve().then(() => __importStar(require('../production'))).then(({ getMetrics }) => {
|
|
1575
|
+
res.json(getMetrics());
|
|
1576
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1577
|
+
});
|
|
1578
|
+
app.get('/production/security', (_req, res) => {
|
|
1579
|
+
Promise.resolve().then(() => __importStar(require('../production'))).then(() => {
|
|
1580
|
+
const fs = require('fs');
|
|
1581
|
+
const path = require('path');
|
|
1582
|
+
const os = require('os');
|
|
1583
|
+
const secFile = path.join(os.homedir(), '.fivo', 'cell', 'security.json');
|
|
1584
|
+
if (fs.existsSync(secFile)) {
|
|
1585
|
+
res.json(JSON.parse(fs.readFileSync(secFile, 'utf-8')));
|
|
1586
|
+
}
|
|
1587
|
+
else {
|
|
1588
|
+
res.status(404).json({ error: 'no security config' });
|
|
1589
|
+
}
|
|
1590
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1591
|
+
});
|
|
1592
|
+
app.post('/production/backup', (_req, res) => {
|
|
1593
|
+
Promise.resolve().then(() => __importStar(require('../production'))).then(({ autoBackup }) => {
|
|
1594
|
+
res.json(autoBackup());
|
|
1595
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1596
|
+
});
|
|
1597
|
+
app.post('/production/optimize', (_req, res) => {
|
|
1598
|
+
Promise.resolve().then(() => __importStar(require('../production'))).then(({ optimizeDatabase }) => {
|
|
1599
|
+
res.json(optimizeDatabase());
|
|
1600
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1601
|
+
});
|
|
1602
|
+
app.get('/ide/debug-style', (_req, res) => {
|
|
1603
|
+
Promise.resolve().then(() => __importStar(require('../ide-intelligence'))).then(({ initializeIDETables, getDebugStyle }) => {
|
|
1604
|
+
initializeIDETables();
|
|
1605
|
+
res.json(getDebugStyle());
|
|
1606
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1607
|
+
});
|
|
1608
|
+
app.get('/ide/prompt-style', (_req, res) => {
|
|
1609
|
+
Promise.resolve().then(() => __importStar(require('../ide-intelligence'))).then(({ initializeIDETables, getPromptStyle }) => {
|
|
1610
|
+
initializeIDETables();
|
|
1611
|
+
res.json(getPromptStyle());
|
|
1612
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1613
|
+
});
|
|
1614
|
+
app.get('/ide/focus', (_req, res) => {
|
|
1615
|
+
Promise.resolve().then(() => __importStar(require('../ide-intelligence'))).then(({ initializeIDETables, getFocusAnalysis }) => {
|
|
1616
|
+
initializeIDETables();
|
|
1617
|
+
res.json(getFocusAnalysis());
|
|
1618
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1619
|
+
});
|
|
1620
|
+
app.get('/ide/insights', (_req, res) => {
|
|
1621
|
+
Promise.resolve().then(() => __importStar(require('../ide-intelligence'))).then(({ initializeIDETables, getIDEInsights }) => {
|
|
1622
|
+
initializeIDETables();
|
|
1623
|
+
res.json(getIDEInsights());
|
|
1624
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1625
|
+
});
|
|
1626
|
+
app.get('/cloud/status', (_req, res) => {
|
|
1627
|
+
Promise.resolve().then(() => __importStar(require('../cloud-sync'))).then(({ getSyncStatus }) => {
|
|
1628
|
+
res.json(getSyncStatus());
|
|
1629
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1630
|
+
});
|
|
1631
|
+
app.post('/cloud/validate', (req, res) => {
|
|
1632
|
+
Promise.resolve().then(() => __importStar(require('../cloud-sync'))).then(({ validatePayload }) => {
|
|
1633
|
+
res.json(validatePayload(req.body || {}));
|
|
1634
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1635
|
+
});
|
|
1636
|
+
app.get('/cloud/queue', (_req, res) => {
|
|
1637
|
+
Promise.resolve().then(() => __importStar(require('../cloud-sync'))).then(({ getPendingQueue, retryFailedEntries }) => {
|
|
1638
|
+
res.json({ pending: getPendingQueue(), retryable: retryFailedEntries() });
|
|
1639
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1640
|
+
});
|
|
1641
|
+
app.post('/cloud/push', (req, res) => {
|
|
1642
|
+
Promise.resolve().then(() => __importStar(require('../cloud-sync'))).then(({ pushToCloud }) => {
|
|
1643
|
+
pushToCloud(req.body?.data || {}, req.body?.type || 'pattern').then(r => res.json(r));
|
|
1644
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1645
|
+
});
|
|
1646
|
+
// ─── CODE SCANNER (Deep Learning) ──────────────────────
|
|
1647
|
+
app.post('/scan/codebase', (req, res) => {
|
|
1648
|
+
const { dir, project } = req.body;
|
|
1649
|
+
if (!dir) {
|
|
1650
|
+
res.status(400).json({ error: 'dir required' });
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1653
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ scanCodebase }) => {
|
|
1654
|
+
const result = scanCodebase(dir, project || require('path').basename(dir));
|
|
1655
|
+
res.json(result);
|
|
1656
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1657
|
+
});
|
|
1658
|
+
app.get('/scan/profile/:project', (req, res) => {
|
|
1659
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ getDeveloperProfile }) => {
|
|
1660
|
+
const profile = getDeveloperProfile(req.params.project);
|
|
1661
|
+
if (!profile) {
|
|
1662
|
+
res.status(404).json({ error: 'no profile — run scan first' });
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
res.json(profile);
|
|
1666
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1667
|
+
});
|
|
1668
|
+
app.get('/scan/patterns/:project', (req, res) => {
|
|
1669
|
+
const category = req.query.category;
|
|
1670
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ getCodePatterns }) => {
|
|
1671
|
+
res.json({ patterns: getCodePatterns(req.params.project, category) });
|
|
1672
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1673
|
+
});
|
|
1674
|
+
app.get('/scan/report/:project', (req, res) => {
|
|
1675
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ getDeveloperProfile, getCodePatterns }) => {
|
|
1676
|
+
const profile = getDeveloperProfile(req.params.project);
|
|
1677
|
+
const patterns = getCodePatterns(req.params.project);
|
|
1678
|
+
res.json({ project: req.params.project, profile, patterns, patternCount: patterns.length });
|
|
1679
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1680
|
+
});
|
|
1681
|
+
// ─── BEHAVIORAL TRACKING ──────────────────────────────────────
|
|
1682
|
+
app.get('/behavior/summary', (req, res) => {
|
|
1683
|
+
const { getBehaviorSummary } = require('../behavioral-tracker');
|
|
1684
|
+
res.json(getBehaviorSummary(String(req.query.project || undefined)));
|
|
1685
|
+
});
|
|
1686
|
+
app.get('/behavior/errors', (req, res) => {
|
|
1687
|
+
const { getErrorPatterns, getRecentErrors } = require('../behavioral-tracker');
|
|
1688
|
+
res.json({ patterns: getErrorPatterns(String(req.query.project || undefined)), recent: getRecentErrors(10, String(req.query.project || undefined)) });
|
|
1689
|
+
});
|
|
1690
|
+
app.get('/behavior/decisions', (req, res) => {
|
|
1691
|
+
const { getDecisions } = require('../behavioral-tracker');
|
|
1692
|
+
res.json({ decisions: getDecisions(String(req.query.project || undefined), 20) });
|
|
1693
|
+
});
|
|
1694
|
+
app.get('/behavior/context', (req, res) => {
|
|
1695
|
+
const { getCurrentContext } = require('../behavioral-tracker');
|
|
1696
|
+
res.json(getCurrentContext(String(req.query.project || undefined)) || { task: 'none', files: [] });
|
|
1697
|
+
});
|
|
1698
|
+
app.get('/behavior/stuck', (req, res) => {
|
|
1699
|
+
const { getStuckPatterns } = require('../behavioral-tracker');
|
|
1700
|
+
res.json({ stuck: getStuckPatterns(String(req.query.project || undefined)) });
|
|
1701
|
+
});
|
|
1702
|
+
// ─── Session Bridge Helper ────────────────────────────────────────────────
|
|
1703
|
+
function formatSessionBridge(fromTool, toTool, context, decisions) {
|
|
1704
|
+
const lines = [];
|
|
1705
|
+
lines.push(`═══ CROSS-SESSION BRIDGE ═══`);
|
|
1706
|
+
lines.push(`From: ${fromTool} → To: ${toTool}`);
|
|
1707
|
+
if (context)
|
|
1708
|
+
lines.push(`Last context: ${context}`);
|
|
1709
|
+
if (decisions && decisions !== 'none' && decisions !== '[]') {
|
|
1710
|
+
lines.push(`Decisions made: ${decisions}`);
|
|
1711
|
+
}
|
|
1712
|
+
lines.push(`Cell remembers. No need to re-explain.`);
|
|
1713
|
+
return lines.join('\n');
|
|
1714
|
+
}
|
|
1715
|
+
// ─── MCP ENDPOINTS (merged from mcp-server.ts) ─────────────────────────────
|
|
1716
|
+
const MCP_TOOLS = [
|
|
1717
|
+
{ name: 'cell_get_dev_profile', description: 'Developer profile — naming, style, errors, architecture', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: ['project'] } },
|
|
1718
|
+
{ name: 'cell_get_code_patterns', description: 'Code patterns by category', inputSchema: { type: 'object', properties: { project: { type: 'string' }, category: { type: 'string' } }, required: ['project'] } },
|
|
1719
|
+
{ name: 'cell_deep_scan', description: 'Deep scan codebase', inputSchema: { type: 'object', properties: { dir: { type: 'string' }, project: { type: 'string' } }, required: ['dir'] } },
|
|
1720
|
+
{ name: 'cell_scan_report', description: 'Full scan report', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: ['project'] } },
|
|
1721
|
+
{ name: 'cell_send_signal', description: 'Send learning signal', inputSchema: { type: 'object', properties: { type: { type: 'string' }, originalCode: { type: 'string' }, editedCode: { type: 'string' }, file: { type: 'string' }, language: { type: 'string' } }, required: ['type'] } },
|
|
1722
|
+
{ name: 'cell_get_context', description: 'Full context injection', inputSchema: { type: 'object', properties: { project: { type: 'string' }, tool: { type: 'string' } }, required: ['project'] } },
|
|
1723
|
+
{ name: 'cell_scan_full_pc', description: 'Scan entire PC for all code projects', inputSchema: { type: 'object', properties: {} } },
|
|
1724
|
+
{ name: 'cell_behavior_summary', description: 'Behavioral summary', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: ['project'] } },
|
|
1725
|
+
{ name: 'cell_log_error', description: 'Log an error encounter', inputSchema: { type: 'object', properties: { project: { type: 'string' }, file: { type: 'string' }, errorType: { type: 'string' }, errorMessage: { type: 'string' }, line: { type: 'number' } }, required: ['errorType', 'errorMessage'] } },
|
|
1726
|
+
{ name: 'cell_log_fix', description: 'Log how an error was fixed', inputSchema: { type: 'object', properties: { errorId: { type: 'number' }, fixApplied: { type: 'string' }, worked: { type: 'boolean' }, timeToFixMs: { type: 'number' } }, required: ['errorId', 'fixApplied', 'worked'] } },
|
|
1727
|
+
{ name: 'cell_log_decision', description: 'Log a coding decision', inputSchema: { type: 'object', properties: { project: { type: 'string' }, file: { type: 'string' }, decision: { type: 'string' }, approach: { type: 'string' }, worked: { type: 'boolean' } }, required: ['decision'] } },
|
|
1728
|
+
{ name: 'cell_log_context', description: 'Log current context', inputSchema: { type: 'object', properties: { project: { type: 'string' }, task: { type: 'string' }, files: { type: 'array', items: { type: 'string' } } }, required: ['task'] } },
|
|
1729
|
+
{ name: 'cell_log_stuck', description: 'Log when stuck', inputSchema: { type: 'object', properties: { project: { type: 'string' }, file: { type: 'string' }, description: { type: 'string' } }, required: ['description'] } },
|
|
1730
|
+
{ name: 'cell_session_bridge', description: 'Cross-session memory bridge — get last session context when switching tools', inputSchema: { type: 'object', properties: { project: { type: 'string' }, tool: { type: 'string' } }, required: ['project'] } },
|
|
1731
|
+
{ name: 'cell_predict', description: 'Predictive intelligence — repeat mistakes, decision regret, energy warnings, complexity traps', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: [] } },
|
|
1732
|
+
];
|
|
1733
|
+
async function handleMCPToolCall(name, args) {
|
|
1734
|
+
switch (name) {
|
|
1735
|
+
case 'cell_get_dev_profile': {
|
|
1736
|
+
const { getDeveloperProfile } = require('../code-scanner');
|
|
1737
|
+
const profile = getDeveloperProfile(args.project);
|
|
1738
|
+
if (!profile)
|
|
1739
|
+
return { error: 'no profile — run cell scan first' };
|
|
1740
|
+
return { project: args.project, profile };
|
|
1741
|
+
}
|
|
1742
|
+
case 'cell_get_code_patterns': {
|
|
1743
|
+
const { getCodePatterns } = require('../code-scanner');
|
|
1744
|
+
return { project: args.project, patterns: getCodePatterns(args.project, args.category) };
|
|
1745
|
+
}
|
|
1746
|
+
case 'cell_deep_scan': {
|
|
1747
|
+
const { scanCodebase } = require('../code-scanner');
|
|
1748
|
+
const result = scanCodebase(args.dir, args.project || path.basename(args.dir));
|
|
1749
|
+
return { project: result.project, filesScanned: result.filesScanned, totalLines: result.totalLines, profile: result.profile, strengths: result.profile.strengths, improvements: result.profile.improvements };
|
|
1750
|
+
}
|
|
1751
|
+
case 'cell_scan_report': {
|
|
1752
|
+
const { getDeveloperProfile, getCodePatterns } = require('../code-scanner');
|
|
1753
|
+
const profile = getDeveloperProfile(args.project);
|
|
1754
|
+
const patterns = getCodePatterns(args.project);
|
|
1755
|
+
return { project: args.project, profile, patterns, patternCount: patterns.length };
|
|
1756
|
+
}
|
|
1757
|
+
case 'cell_send_signal': {
|
|
1758
|
+
const { logError, logDecision, logContext, logStuck } = require('../behavioral-tracker');
|
|
1759
|
+
const type = args.type;
|
|
1760
|
+
if (type === 'error')
|
|
1761
|
+
return logError({ project: args.project, file: args.file, errorType: 'manual', errorMessage: String(args.editedCode || ''), line: 0 });
|
|
1762
|
+
if (type === 'decision')
|
|
1763
|
+
return logDecision({ project: args.project, file: args.file, decision: String(args.originalCode || ''), approach: String(args.editedCode || ''), worked: true });
|
|
1764
|
+
if (type === 'context')
|
|
1765
|
+
return logContext({ project: args.project, task: String(args.originalCode || ''), files: [] });
|
|
1766
|
+
if (type === 'stuck')
|
|
1767
|
+
return logStuck({ project: args.project, file: args.file, description: String(args.originalCode || '') });
|
|
1768
|
+
return { recorded: true };
|
|
1769
|
+
}
|
|
1770
|
+
case 'cell_get_context': {
|
|
1771
|
+
const { buildContext, formatContextForInjection } = require('../core/prompt-builder');
|
|
1772
|
+
const ctx = buildContext(args.project, args.tool);
|
|
1773
|
+
return { content: [{ type: 'text', text: formatContextForInjection(ctx, false) }], context: ctx };
|
|
1774
|
+
}
|
|
1775
|
+
case 'cell_scan_full_pc': {
|
|
1776
|
+
const { scanFullPC } = require('../pc-scanner');
|
|
1777
|
+
const result = scanFullPC();
|
|
1778
|
+
return { totalProjects: result.totalProjects, totalFiles: result.totalFiles, totalLines: result.totalLines, profile: result.aggregatedProfile };
|
|
1779
|
+
}
|
|
1780
|
+
case 'cell_behavior_summary': {
|
|
1781
|
+
const { getBehaviorSummary } = require('../behavioral-tracker');
|
|
1782
|
+
return getBehaviorSummary(args.project);
|
|
1783
|
+
}
|
|
1784
|
+
case 'cell_log_error': {
|
|
1785
|
+
const { logError } = require('../behavioral-tracker');
|
|
1786
|
+
return logError({ project: args.project, file: args.file, errorType: args.errorType, errorMessage: args.errorMessage, line: args.line });
|
|
1787
|
+
}
|
|
1788
|
+
case 'cell_log_fix': {
|
|
1789
|
+
const { logErrorFix } = require('../behavioral-tracker');
|
|
1790
|
+
logErrorFix({ errorId: args.errorId, fixApplied: args.fixApplied, worked: args.worked, timeToFixMs: args.timeToFixMs });
|
|
1791
|
+
return { recorded: true };
|
|
1792
|
+
}
|
|
1793
|
+
case 'cell_log_decision': {
|
|
1794
|
+
const { logDecision } = require('../behavioral-tracker');
|
|
1795
|
+
return logDecision({ project: args.project, file: args.file, decision: args.decision, approach: args.approach, worked: args.worked });
|
|
1796
|
+
}
|
|
1797
|
+
case 'cell_log_context': {
|
|
1798
|
+
const { logContext } = require('../behavioral-tracker');
|
|
1799
|
+
return logContext({ project: args.project, task: args.task, files: args.files });
|
|
1800
|
+
}
|
|
1801
|
+
case 'cell_log_stuck': {
|
|
1802
|
+
const { logStuck } = require('../behavioral-tracker');
|
|
1803
|
+
return logStuck({ project: args.project, file: args.file, description: args.description });
|
|
1804
|
+
}
|
|
1805
|
+
case 'cell_session_bridge': {
|
|
1806
|
+
const { SessionMemory } = require('../core/session-memory');
|
|
1807
|
+
const memory = new SessionMemory();
|
|
1808
|
+
const project = args.project;
|
|
1809
|
+
const tool = args.tool || 'unknown';
|
|
1810
|
+
try {
|
|
1811
|
+
// Get last session for this project
|
|
1812
|
+
const lastSession = memory.getLastSessionForProject(project);
|
|
1813
|
+
// Start new session for current tool
|
|
1814
|
+
const newSessionId = memory.startSession(tool, project);
|
|
1815
|
+
// If there was a previous session with a different tool, bridge it
|
|
1816
|
+
let bridgeContext = '';
|
|
1817
|
+
if (lastSession && lastSession.toolName !== tool) {
|
|
1818
|
+
const decisions = lastSession.keyDecisions ? JSON.stringify(lastSession.keyDecisions) : 'none';
|
|
1819
|
+
bridgeContext = formatSessionBridge(lastSession.toolName, tool, lastSession.contextSnapshot, decisions);
|
|
1820
|
+
}
|
|
1821
|
+
// Get recent sessions for context chain
|
|
1822
|
+
const recentSessions = memory.getRecentSessions(3).filter((s) => s.project === project);
|
|
1823
|
+
const sessionHistory = recentSessions.map((s) => ({
|
|
1824
|
+
tool: s.toolName,
|
|
1825
|
+
when: s.startTime,
|
|
1826
|
+
files: JSON.parse(String(s.filesTouched || '[]')),
|
|
1827
|
+
decisions: JSON.parse(String(s.keyDecisions || '[]')),
|
|
1828
|
+
}));
|
|
1829
|
+
return {
|
|
1830
|
+
newSessionId,
|
|
1831
|
+
lastSession: lastSession ? {
|
|
1832
|
+
tool: lastSession.toolName,
|
|
1833
|
+
startedAt: lastSession.startTime,
|
|
1834
|
+
context: lastSession.contextSnapshot,
|
|
1835
|
+
} : null,
|
|
1836
|
+
bridgeContext,
|
|
1837
|
+
sessionHistory,
|
|
1838
|
+
message: bridgeContext || 'No previous session to bridge. Start a new session!',
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1841
|
+
catch (err) {
|
|
1842
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1843
|
+
return { error: `Session bridge failed: ${msg}`, crossedSession: false };
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
case 'cell_predict': {
|
|
1847
|
+
const { generatePredictions } = require('../predictive-engine');
|
|
1848
|
+
return generatePredictions(args.project);
|
|
1849
|
+
}
|
|
1850
|
+
default:
|
|
1851
|
+
return { error: `unknown tool: ${name}` };
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
app.post('/mcp', async (req, res) => {
|
|
1855
|
+
const rpc = req.body;
|
|
1856
|
+
const { method, params, id } = rpc;
|
|
1857
|
+
try {
|
|
1858
|
+
let result;
|
|
1859
|
+
switch (method) {
|
|
1860
|
+
case 'initialize':
|
|
1861
|
+
result = { protocolVersion: params?.protocolVersion || '2024-11-05', capabilities: { tools: { listChanged: false } }, serverInfo: { name: 'fivo-cell', version: '3.0.0' } };
|
|
1862
|
+
break;
|
|
1863
|
+
case 'notifications/initialized':
|
|
1864
|
+
res.status(204).end();
|
|
1865
|
+
return;
|
|
1866
|
+
case 'ping':
|
|
1867
|
+
result = {};
|
|
1868
|
+
break;
|
|
1869
|
+
case 'tools/list':
|
|
1870
|
+
result = { tools: MCP_TOOLS };
|
|
1871
|
+
break;
|
|
1872
|
+
case 'tools/call':
|
|
1873
|
+
result = await handleMCPToolCall(params?.name || '', params?.arguments || {});
|
|
1874
|
+
break;
|
|
1875
|
+
default:
|
|
1876
|
+
res.status(200).json({ jsonrpc: '2.0', id, error: { code: -32601, message: `Method not found: ${method}` } });
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1879
|
+
res.status(200).json({ jsonrpc: '2.0', id, result });
|
|
1880
|
+
}
|
|
1881
|
+
catch (err) {
|
|
1882
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1883
|
+
res.status(200).json({ jsonrpc: '2.0', id, error: { code: -1, message } });
|
|
1884
|
+
}
|
|
1885
|
+
});
|
|
1302
1886
|
app.use((_req, res) => { res.status(404).json({ error: 'not found' }); });
|
|
1303
1887
|
app.use((err, _req, res, _next) => {
|
|
1304
1888
|
console.error('Daemon error:', err.message);
|
|
1305
1889
|
res.status(500).json({ error: 'internal server error' });
|
|
1306
1890
|
});
|
|
1891
|
+
// ─── Self-Healing ──────────────────────────────────────────────────────
|
|
1892
|
+
process.on('uncaughtException', (err) => {
|
|
1893
|
+
console.error('[cell] Uncaught:', err.message);
|
|
1894
|
+
// Don't exit — keep serving
|
|
1895
|
+
});
|
|
1896
|
+
process.on('unhandledRejection', (reason) => {
|
|
1897
|
+
console.error('[cell] Unhandled rejection:', String(reason));
|
|
1898
|
+
});
|
|
1307
1899
|
try {
|
|
1308
1900
|
(0, ai_memory_1.initializeMemory)();
|
|
1309
1901
|
}
|
|
1310
1902
|
catch (e) {
|
|
1311
1903
|
console.error('AI memory init failed:', e);
|
|
1312
1904
|
}
|
|
1313
|
-
|
|
1905
|
+
// ─── Start with port conflict handling ─────────────────────────────────
|
|
1906
|
+
const server = app.listen(PORT, () => {
|
|
1314
1907
|
console.log(`Cell Daemon running on http://localhost:${PORT}`);
|
|
1315
|
-
console.log(`
|
|
1908
|
+
console.log(`MCP endpoint: POST http://localhost:${PORT}/mcp`);
|
|
1316
1909
|
console.log(`Health: http://localhost:${PORT}/health`);
|
|
1317
1910
|
});
|
|
1911
|
+
server.on('error', (err) => {
|
|
1912
|
+
if (err.code === 'EADDRINUSE') {
|
|
1913
|
+
console.error(`[cell] Port ${PORT} in use. Kill existing daemon first: cell stop`);
|
|
1914
|
+
}
|
|
1915
|
+
else {
|
|
1916
|
+
console.error(`[cell] Server error: ${err.message}`);
|
|
1917
|
+
}
|
|
1918
|
+
});
|
|
1919
|
+
server.on('close', () => {
|
|
1920
|
+
console.log('[cell] Daemon stopped.');
|
|
1921
|
+
});
|
|
1922
|
+
// Graceful shutdown
|
|
1923
|
+
const gracefulShutdown = () => {
|
|
1924
|
+
console.log('[cell] Daemon shutting down...');
|
|
1925
|
+
server.close();
|
|
1926
|
+
process.exit(0);
|
|
1927
|
+
};
|
|
1928
|
+
process.on('SIGTERM', gracefulShutdown);
|
|
1929
|
+
process.on('SIGINT', gracefulShutdown);
|
|
1318
1930
|
//# sourceMappingURL=server.js.map
|