fivocell 2.0.0 → 3.1.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 +104 -697
- 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.d.ts +1 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +430 -3862
- package/dist/cli.js.map +1 -1
- 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/cross-model-engine.d.ts +38 -0
- package/dist/cross-model-engine.d.ts.map +1 -0
- package/dist/cross-model-engine.js +98 -0
- package/dist/cross-model-engine.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +0 -15
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +88 -231
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +403 -19
- 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/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 +194 -1842
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +169 -875
- package/dist/mcp-server.js.map +1 -1
- 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/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/style-pull.d.ts +1 -1
- package/dist/style-pull.js +2 -2
- 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/package.json +1 -1
package/dist/daemon/server.js
CHANGED
|
@@ -204,16 +204,121 @@ app.get('/health', (_req, res) => {
|
|
|
204
204
|
});
|
|
205
205
|
});
|
|
206
206
|
app.post('/signal', (req, res) => {
|
|
207
|
-
const { type, originalCode, editedCode, context } = req.body;
|
|
208
|
-
if (!type
|
|
209
|
-
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
210
|
return;
|
|
211
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 });
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
// ─── IDE Signals ──────────────────────────────────────────────
|
|
288
|
+
if (type === 'model_use') {
|
|
289
|
+
// Track AI model interaction
|
|
290
|
+
try {
|
|
291
|
+
const { recordModelInteraction } = require('../cross-model-engine');
|
|
292
|
+
recordModelInteraction({
|
|
293
|
+
modelName: req.body.modelName || 'unknown',
|
|
294
|
+
taskType: req.body.taskType || req.body.type || 'general',
|
|
295
|
+
accepted: req.body.accepted !== false,
|
|
296
|
+
responseTimeMs: req.body.responseTimeMs,
|
|
297
|
+
project,
|
|
298
|
+
suggestion: req.body.suggestion,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
catch { }
|
|
302
|
+
res.json({ recorded: true });
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (type === 'tab_switch' || type === 'focus_block' || type === 'file_save') {
|
|
306
|
+
try {
|
|
307
|
+
const db = (0, database_1.getDb)();
|
|
308
|
+
db.prepare('INSERT INTO behavior_events (event_type, project, file_path, description, severity, evidence) VALUES (?, ?, ?, ?, ?, ?)')
|
|
309
|
+
.run(type, '', file || '', JSON.stringify({ fromFile, costMs, durationMs, switchCount, language }), 'low', JSON.stringify(req.body));
|
|
310
|
+
}
|
|
311
|
+
catch { }
|
|
312
|
+
res.json({ recorded: true, type });
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
// ─── Legacy Signals ──────────────────────────────────────────
|
|
316
|
+
const ctx = context || {};
|
|
212
317
|
let signal;
|
|
213
318
|
let patternsExtracted = 0;
|
|
214
319
|
switch (type) {
|
|
215
320
|
case 'edit_diff': {
|
|
216
|
-
signal = engines.signalCapture.captureEditDiff(originalCode || '', editedCode || '',
|
|
321
|
+
signal = engines.signalCapture.captureEditDiff(originalCode || '', editedCode || '', ctx);
|
|
217
322
|
try {
|
|
218
323
|
const result = engines.extractionCascade.extract(originalCode || '', editedCode || '');
|
|
219
324
|
patternsExtracted = engines.learningLayer.process(result, true);
|
|
@@ -226,35 +331,28 @@ app.post('/signal', (req, res) => {
|
|
|
226
331
|
break;
|
|
227
332
|
}
|
|
228
333
|
case 'accept': {
|
|
229
|
-
signal = engines.signalCapture.captureAccept(originalCode || '',
|
|
334
|
+
signal = engines.signalCapture.captureAccept(originalCode || '', ctx);
|
|
230
335
|
const dummy = engines.patternStore.getAllPatterns().slice(0, 1);
|
|
231
336
|
for (const p of dummy) {
|
|
232
337
|
const step = (0, workflow_tracker_1.recordStep)(p, 'accept');
|
|
233
338
|
(0, outcome_recorder_1.recordOutcome)(p, 'accept', step.sessionId, true, 0);
|
|
234
|
-
(0, failure_memory_1.recordFailure)(p, false,
|
|
235
|
-
(0, time_saved_1.recordTimeSaved)({
|
|
236
|
-
patternId: p.patternId,
|
|
237
|
-
category: p.category,
|
|
238
|
-
description: p.description,
|
|
239
|
-
from: p.from,
|
|
240
|
-
to: p.to,
|
|
241
|
-
language: context?.language || 'unknown',
|
|
242
|
-
});
|
|
339
|
+
(0, failure_memory_1.recordFailure)(p, false, ctx.language || 'unknown');
|
|
340
|
+
(0, time_saved_1.recordTimeSaved)({ patternId: p.patternId, category: p.category, description: p.description, from: p.from, to: p.to, language: ctx.language || 'unknown' });
|
|
243
341
|
}
|
|
244
342
|
break;
|
|
245
343
|
}
|
|
246
344
|
case 'reject': {
|
|
247
|
-
signal = engines.signalCapture.captureReject(originalCode || '',
|
|
345
|
+
signal = engines.signalCapture.captureReject(originalCode || '', ctx);
|
|
248
346
|
const dummyR = engines.patternStore.getAllPatterns().slice(0, 1);
|
|
249
347
|
for (const p of dummyR) {
|
|
250
348
|
const step = (0, workflow_tracker_1.recordStep)(p, 'reject');
|
|
251
349
|
(0, outcome_recorder_1.recordOutcome)(p, 'reject', step.sessionId, false, 0);
|
|
252
|
-
(0, failure_memory_1.recordFailure)(p, true,
|
|
350
|
+
(0, failure_memory_1.recordFailure)(p, true, ctx.language || 'unknown');
|
|
253
351
|
}
|
|
254
352
|
break;
|
|
255
353
|
}
|
|
256
354
|
case 'retry': {
|
|
257
|
-
signal = engines.signalCapture.captureRetry(originalCode || '',
|
|
355
|
+
signal = engines.signalCapture.captureRetry(originalCode || '', ctx);
|
|
258
356
|
const dummyRt = engines.patternStore.getAllPatterns().slice(0, 1);
|
|
259
357
|
for (const p of dummyRt) {
|
|
260
358
|
const step = (0, workflow_tracker_1.recordStep)(p, 'retry');
|
|
@@ -1562,20 +1660,306 @@ app.post('/cloud/push', (req, res) => {
|
|
|
1562
1660
|
pushToCloud(req.body?.data || {}, req.body?.type || 'pattern').then(r => res.json(r));
|
|
1563
1661
|
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1564
1662
|
});
|
|
1663
|
+
// ─── CODE SCANNER (Deep Learning) ──────────────────────
|
|
1664
|
+
app.post('/scan/codebase', (req, res) => {
|
|
1665
|
+
const { dir, project } = req.body;
|
|
1666
|
+
if (!dir) {
|
|
1667
|
+
res.status(400).json({ error: 'dir required' });
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
1670
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ scanCodebase }) => {
|
|
1671
|
+
const result = scanCodebase(dir, project || require('path').basename(dir));
|
|
1672
|
+
res.json(result);
|
|
1673
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1674
|
+
});
|
|
1675
|
+
app.get('/scan/profile/:project', (req, res) => {
|
|
1676
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ getDeveloperProfile }) => {
|
|
1677
|
+
const profile = getDeveloperProfile(req.params.project);
|
|
1678
|
+
if (!profile) {
|
|
1679
|
+
res.status(404).json({ error: 'no profile — run scan first' });
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
res.json(profile);
|
|
1683
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1684
|
+
});
|
|
1685
|
+
app.get('/scan/patterns/:project', (req, res) => {
|
|
1686
|
+
const category = req.query.category;
|
|
1687
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ getCodePatterns }) => {
|
|
1688
|
+
res.json({ patterns: getCodePatterns(req.params.project, category) });
|
|
1689
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1690
|
+
});
|
|
1691
|
+
app.get('/scan/report/:project', (req, res) => {
|
|
1692
|
+
Promise.resolve().then(() => __importStar(require('../code-scanner'))).then(({ getDeveloperProfile, getCodePatterns }) => {
|
|
1693
|
+
const profile = getDeveloperProfile(req.params.project);
|
|
1694
|
+
const patterns = getCodePatterns(req.params.project);
|
|
1695
|
+
res.json({ project: req.params.project, profile, patterns, patternCount: patterns.length });
|
|
1696
|
+
}).catch(e => res.status(500).json({ error: String(e) }));
|
|
1697
|
+
});
|
|
1698
|
+
// ─── BEHAVIORAL TRACKING ──────────────────────────────────────
|
|
1699
|
+
app.get('/behavior/summary', (req, res) => {
|
|
1700
|
+
const { getBehaviorSummary } = require('../behavioral-tracker');
|
|
1701
|
+
res.json(getBehaviorSummary(String(req.query.project || undefined)));
|
|
1702
|
+
});
|
|
1703
|
+
app.get('/behavior/errors', (req, res) => {
|
|
1704
|
+
const { getErrorPatterns, getRecentErrors } = require('../behavioral-tracker');
|
|
1705
|
+
res.json({ patterns: getErrorPatterns(String(req.query.project || undefined)), recent: getRecentErrors(10, String(req.query.project || undefined)) });
|
|
1706
|
+
});
|
|
1707
|
+
app.get('/behavior/decisions', (req, res) => {
|
|
1708
|
+
const { getDecisions } = require('../behavioral-tracker');
|
|
1709
|
+
res.json({ decisions: getDecisions(String(req.query.project || undefined), 20) });
|
|
1710
|
+
});
|
|
1711
|
+
app.get('/behavior/context', (req, res) => {
|
|
1712
|
+
const { getCurrentContext } = require('../behavioral-tracker');
|
|
1713
|
+
res.json(getCurrentContext(String(req.query.project || undefined)) || { task: 'none', files: [] });
|
|
1714
|
+
});
|
|
1715
|
+
app.get('/behavior/stuck', (req, res) => {
|
|
1716
|
+
const { getStuckPatterns } = require('../behavioral-tracker');
|
|
1717
|
+
res.json({ stuck: getStuckPatterns(String(req.query.project || undefined)) });
|
|
1718
|
+
});
|
|
1719
|
+
// ─── Session Bridge Helper ────────────────────────────────────────────────
|
|
1720
|
+
function formatSessionBridge(fromTool, toTool, context, decisions) {
|
|
1721
|
+
const lines = [];
|
|
1722
|
+
lines.push(`═══ CROSS-SESSION BRIDGE ═══`);
|
|
1723
|
+
lines.push(`From: ${fromTool} → To: ${toTool}`);
|
|
1724
|
+
if (context)
|
|
1725
|
+
lines.push(`Last context: ${context}`);
|
|
1726
|
+
if (decisions && decisions !== 'none' && decisions !== '[]') {
|
|
1727
|
+
lines.push(`Decisions made: ${decisions}`);
|
|
1728
|
+
}
|
|
1729
|
+
lines.push(`Cell remembers. No need to re-explain.`);
|
|
1730
|
+
return lines.join('\n');
|
|
1731
|
+
}
|
|
1732
|
+
// ─── MCP ENDPOINTS (merged from mcp-server.ts) ─────────────────────────────
|
|
1733
|
+
const MCP_TOOLS = [
|
|
1734
|
+
{ name: 'cell_get_dev_profile', description: 'Developer profile — naming, style, errors, architecture', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: ['project'] } },
|
|
1735
|
+
{ name: 'cell_get_code_patterns', description: 'Code patterns by category', inputSchema: { type: 'object', properties: { project: { type: 'string' }, category: { type: 'string' } }, required: ['project'] } },
|
|
1736
|
+
{ name: 'cell_deep_scan', description: 'Deep scan codebase', inputSchema: { type: 'object', properties: { dir: { type: 'string' }, project: { type: 'string' } }, required: ['dir'] } },
|
|
1737
|
+
{ name: 'cell_scan_report', description: 'Full scan report', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: ['project'] } },
|
|
1738
|
+
{ 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'] } },
|
|
1739
|
+
{ name: 'cell_get_context', description: 'Full context injection', inputSchema: { type: 'object', properties: { project: { type: 'string' }, tool: { type: 'string' } }, required: ['project'] } },
|
|
1740
|
+
{ name: 'cell_scan_full_pc', description: 'Scan entire PC for all code projects', inputSchema: { type: 'object', properties: {} } },
|
|
1741
|
+
{ name: 'cell_behavior_summary', description: 'Behavioral summary', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: ['project'] } },
|
|
1742
|
+
{ 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'] } },
|
|
1743
|
+
{ 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'] } },
|
|
1744
|
+
{ 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'] } },
|
|
1745
|
+
{ 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'] } },
|
|
1746
|
+
{ name: 'cell_log_stuck', description: 'Log when stuck', inputSchema: { type: 'object', properties: { project: { type: 'string' }, file: { type: 'string' }, description: { type: 'string' } }, required: ['description'] } },
|
|
1747
|
+
{ 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'] } },
|
|
1748
|
+
{ name: 'cell_predict', description: 'Predictive intelligence — repeat mistakes, decision regret, energy warnings, complexity traps', inputSchema: { type: 'object', properties: { project: { type: 'string' } }, required: [] } },
|
|
1749
|
+
{ name: 'cell_model_track', description: 'Track AI model interaction — which tool was used, what task, accepted/rejected', inputSchema: { type: 'object', properties: { modelName: { type: 'string' }, taskType: { type: 'string' }, accepted: { type: 'boolean' }, responseTimeMs: { type: 'number' }, project: { type: 'string' }, suggestion: { type: 'string' } }, required: ['modelName', 'taskType', 'accepted'] } },
|
|
1750
|
+
{ name: 'cell_model_recommend', description: 'Get AI model recommendations — which tool works best for which task', inputSchema: { type: 'object', properties: {} } },
|
|
1751
|
+
];
|
|
1752
|
+
async function handleMCPToolCall(name, args) {
|
|
1753
|
+
switch (name) {
|
|
1754
|
+
case 'cell_get_dev_profile': {
|
|
1755
|
+
const { getDeveloperProfile } = require('../code-scanner');
|
|
1756
|
+
const profile = getDeveloperProfile(args.project);
|
|
1757
|
+
if (!profile)
|
|
1758
|
+
return { error: 'no profile — run cell scan first' };
|
|
1759
|
+
return { project: args.project, profile };
|
|
1760
|
+
}
|
|
1761
|
+
case 'cell_get_code_patterns': {
|
|
1762
|
+
const { getCodePatterns } = require('../code-scanner');
|
|
1763
|
+
return { project: args.project, patterns: getCodePatterns(args.project, args.category) };
|
|
1764
|
+
}
|
|
1765
|
+
case 'cell_deep_scan': {
|
|
1766
|
+
const { scanCodebase } = require('../code-scanner');
|
|
1767
|
+
const result = scanCodebase(args.dir, args.project || path.basename(args.dir));
|
|
1768
|
+
return { project: result.project, filesScanned: result.filesScanned, totalLines: result.totalLines, profile: result.profile, strengths: result.profile.strengths, improvements: result.profile.improvements };
|
|
1769
|
+
}
|
|
1770
|
+
case 'cell_scan_report': {
|
|
1771
|
+
const { getDeveloperProfile, getCodePatterns } = require('../code-scanner');
|
|
1772
|
+
const profile = getDeveloperProfile(args.project);
|
|
1773
|
+
const patterns = getCodePatterns(args.project);
|
|
1774
|
+
return { project: args.project, profile, patterns, patternCount: patterns.length };
|
|
1775
|
+
}
|
|
1776
|
+
case 'cell_send_signal': {
|
|
1777
|
+
const { logError, logDecision, logContext, logStuck } = require('../behavioral-tracker');
|
|
1778
|
+
const type = args.type;
|
|
1779
|
+
if (type === 'error')
|
|
1780
|
+
return logError({ project: args.project, file: args.file, errorType: 'manual', errorMessage: String(args.editedCode || ''), line: 0 });
|
|
1781
|
+
if (type === 'decision')
|
|
1782
|
+
return logDecision({ project: args.project, file: args.file, decision: String(args.originalCode || ''), approach: String(args.editedCode || ''), worked: true });
|
|
1783
|
+
if (type === 'context')
|
|
1784
|
+
return logContext({ project: args.project, task: String(args.originalCode || ''), files: [] });
|
|
1785
|
+
if (type === 'stuck')
|
|
1786
|
+
return logStuck({ project: args.project, file: args.file, description: String(args.originalCode || '') });
|
|
1787
|
+
return { recorded: true };
|
|
1788
|
+
}
|
|
1789
|
+
case 'cell_get_context': {
|
|
1790
|
+
const { buildContext, formatContextForInjection } = require('../core/prompt-builder');
|
|
1791
|
+
const ctx = buildContext(args.project, args.tool);
|
|
1792
|
+
return { content: [{ type: 'text', text: formatContextForInjection(ctx, false) }], context: ctx };
|
|
1793
|
+
}
|
|
1794
|
+
case 'cell_scan_full_pc': {
|
|
1795
|
+
const { scanFullPC } = require('../pc-scanner');
|
|
1796
|
+
const result = scanFullPC();
|
|
1797
|
+
return { totalProjects: result.totalProjects, totalFiles: result.totalFiles, totalLines: result.totalLines, profile: result.aggregatedProfile };
|
|
1798
|
+
}
|
|
1799
|
+
case 'cell_behavior_summary': {
|
|
1800
|
+
const { getBehaviorSummary } = require('../behavioral-tracker');
|
|
1801
|
+
return getBehaviorSummary(args.project);
|
|
1802
|
+
}
|
|
1803
|
+
case 'cell_log_error': {
|
|
1804
|
+
const { logError } = require('../behavioral-tracker');
|
|
1805
|
+
return logError({ project: args.project, file: args.file, errorType: args.errorType, errorMessage: args.errorMessage, line: args.line });
|
|
1806
|
+
}
|
|
1807
|
+
case 'cell_log_fix': {
|
|
1808
|
+
const { logErrorFix } = require('../behavioral-tracker');
|
|
1809
|
+
logErrorFix({ errorId: args.errorId, fixApplied: args.fixApplied, worked: args.worked, timeToFixMs: args.timeToFixMs });
|
|
1810
|
+
return { recorded: true };
|
|
1811
|
+
}
|
|
1812
|
+
case 'cell_log_decision': {
|
|
1813
|
+
const { logDecision } = require('../behavioral-tracker');
|
|
1814
|
+
return logDecision({ project: args.project, file: args.file, decision: args.decision, approach: args.approach, worked: args.worked });
|
|
1815
|
+
}
|
|
1816
|
+
case 'cell_log_context': {
|
|
1817
|
+
const { logContext } = require('../behavioral-tracker');
|
|
1818
|
+
return logContext({ project: args.project, task: args.task, files: args.files });
|
|
1819
|
+
}
|
|
1820
|
+
case 'cell_log_stuck': {
|
|
1821
|
+
const { logStuck } = require('../behavioral-tracker');
|
|
1822
|
+
return logStuck({ project: args.project, file: args.file, description: args.description });
|
|
1823
|
+
}
|
|
1824
|
+
case 'cell_session_bridge': {
|
|
1825
|
+
const { SessionMemory } = require('../core/session-memory');
|
|
1826
|
+
const memory = new SessionMemory();
|
|
1827
|
+
const project = args.project;
|
|
1828
|
+
const tool = args.tool || 'unknown';
|
|
1829
|
+
try {
|
|
1830
|
+
// Get last session for this project
|
|
1831
|
+
const lastSession = memory.getLastSessionForProject(project);
|
|
1832
|
+
// Start new session for current tool
|
|
1833
|
+
const newSessionId = memory.startSession(tool, project);
|
|
1834
|
+
// If there was a previous session with a different tool, bridge it
|
|
1835
|
+
let bridgeContext = '';
|
|
1836
|
+
if (lastSession && lastSession.toolName !== tool) {
|
|
1837
|
+
const decisions = lastSession.keyDecisions ? JSON.stringify(lastSession.keyDecisions) : 'none';
|
|
1838
|
+
bridgeContext = formatSessionBridge(lastSession.toolName, tool, lastSession.contextSnapshot, decisions);
|
|
1839
|
+
}
|
|
1840
|
+
// Get recent sessions for context chain
|
|
1841
|
+
const recentSessions = memory.getRecentSessions(3).filter((s) => s.project === project);
|
|
1842
|
+
const sessionHistory = recentSessions.map((s) => ({
|
|
1843
|
+
tool: s.toolName,
|
|
1844
|
+
when: s.startTime,
|
|
1845
|
+
files: JSON.parse(String(s.filesTouched || '[]')),
|
|
1846
|
+
decisions: JSON.parse(String(s.keyDecisions || '[]')),
|
|
1847
|
+
}));
|
|
1848
|
+
return {
|
|
1849
|
+
newSessionId,
|
|
1850
|
+
lastSession: lastSession ? {
|
|
1851
|
+
tool: lastSession.toolName,
|
|
1852
|
+
startedAt: lastSession.startTime,
|
|
1853
|
+
context: lastSession.contextSnapshot,
|
|
1854
|
+
} : null,
|
|
1855
|
+
bridgeContext,
|
|
1856
|
+
sessionHistory,
|
|
1857
|
+
message: bridgeContext || 'No previous session to bridge. Start a new session!',
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
catch (err) {
|
|
1861
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1862
|
+
return { error: `Session bridge failed: ${msg}`, crossedSession: false };
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
case 'cell_predict': {
|
|
1866
|
+
const { generatePredictions } = require('../predictive-engine');
|
|
1867
|
+
return generatePredictions(args.project);
|
|
1868
|
+
}
|
|
1869
|
+
case 'cell_model_track': {
|
|
1870
|
+
const { recordModelInteraction } = require('../cross-model-engine');
|
|
1871
|
+
recordModelInteraction({
|
|
1872
|
+
modelName: args.modelName,
|
|
1873
|
+
taskType: args.taskType,
|
|
1874
|
+
accepted: args.accepted,
|
|
1875
|
+
responseTimeMs: args.responseTimeMs,
|
|
1876
|
+
project: args.project,
|
|
1877
|
+
suggestion: args.suggestion,
|
|
1878
|
+
});
|
|
1879
|
+
return { recorded: true };
|
|
1880
|
+
}
|
|
1881
|
+
case 'cell_model_recommend': {
|
|
1882
|
+
const { getModelRecommendations } = require('../cross-model-engine');
|
|
1883
|
+
return { recommendations: getModelRecommendations() };
|
|
1884
|
+
}
|
|
1885
|
+
default:
|
|
1886
|
+
return { error: `unknown tool: ${name}` };
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
app.post('/mcp', async (req, res) => {
|
|
1890
|
+
const rpc = req.body;
|
|
1891
|
+
const { method, params, id } = rpc;
|
|
1892
|
+
try {
|
|
1893
|
+
let result;
|
|
1894
|
+
switch (method) {
|
|
1895
|
+
case 'initialize':
|
|
1896
|
+
result = { protocolVersion: params?.protocolVersion || '2024-11-05', capabilities: { tools: { listChanged: false } }, serverInfo: { name: 'fivo-cell', version: '3.0.0' } };
|
|
1897
|
+
break;
|
|
1898
|
+
case 'notifications/initialized':
|
|
1899
|
+
res.status(204).end();
|
|
1900
|
+
return;
|
|
1901
|
+
case 'ping':
|
|
1902
|
+
result = {};
|
|
1903
|
+
break;
|
|
1904
|
+
case 'tools/list':
|
|
1905
|
+
result = { tools: MCP_TOOLS };
|
|
1906
|
+
break;
|
|
1907
|
+
case 'tools/call':
|
|
1908
|
+
result = await handleMCPToolCall(params?.name || '', params?.arguments || {});
|
|
1909
|
+
break;
|
|
1910
|
+
default:
|
|
1911
|
+
res.status(200).json({ jsonrpc: '2.0', id, error: { code: -32601, message: `Method not found: ${method}` } });
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
res.status(200).json({ jsonrpc: '2.0', id, result });
|
|
1915
|
+
}
|
|
1916
|
+
catch (err) {
|
|
1917
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1918
|
+
res.status(200).json({ jsonrpc: '2.0', id, error: { code: -1, message } });
|
|
1919
|
+
}
|
|
1920
|
+
});
|
|
1565
1921
|
app.use((_req, res) => { res.status(404).json({ error: 'not found' }); });
|
|
1566
1922
|
app.use((err, _req, res, _next) => {
|
|
1567
1923
|
console.error('Daemon error:', err.message);
|
|
1568
1924
|
res.status(500).json({ error: 'internal server error' });
|
|
1569
1925
|
});
|
|
1926
|
+
// ─── Self-Healing ──────────────────────────────────────────────────────
|
|
1927
|
+
process.on('uncaughtException', (err) => {
|
|
1928
|
+
console.error('[cell] Uncaught:', err.message);
|
|
1929
|
+
// Don't exit — keep serving
|
|
1930
|
+
});
|
|
1931
|
+
process.on('unhandledRejection', (reason) => {
|
|
1932
|
+
console.error('[cell] Unhandled rejection:', String(reason));
|
|
1933
|
+
});
|
|
1570
1934
|
try {
|
|
1571
1935
|
(0, ai_memory_1.initializeMemory)();
|
|
1572
1936
|
}
|
|
1573
1937
|
catch (e) {
|
|
1574
1938
|
console.error('AI memory init failed:', e);
|
|
1575
1939
|
}
|
|
1576
|
-
|
|
1940
|
+
// ─── Start with port conflict handling ─────────────────────────────────
|
|
1941
|
+
const server = app.listen(PORT, () => {
|
|
1577
1942
|
console.log(`Cell Daemon running on http://localhost:${PORT}`);
|
|
1578
|
-
console.log(`
|
|
1943
|
+
console.log(`MCP endpoint: POST http://localhost:${PORT}/mcp`);
|
|
1579
1944
|
console.log(`Health: http://localhost:${PORT}/health`);
|
|
1580
1945
|
});
|
|
1946
|
+
server.on('error', (err) => {
|
|
1947
|
+
if (err.code === 'EADDRINUSE') {
|
|
1948
|
+
console.error(`[cell] Port ${PORT} in use. Kill existing daemon first: cell stop`);
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
console.error(`[cell] Server error: ${err.message}`);
|
|
1952
|
+
}
|
|
1953
|
+
});
|
|
1954
|
+
server.on('close', () => {
|
|
1955
|
+
console.log('[cell] Daemon stopped.');
|
|
1956
|
+
});
|
|
1957
|
+
// Graceful shutdown
|
|
1958
|
+
const gracefulShutdown = () => {
|
|
1959
|
+
console.log('[cell] Daemon shutting down...');
|
|
1960
|
+
server.close();
|
|
1961
|
+
process.exit(0);
|
|
1962
|
+
};
|
|
1963
|
+
process.on('SIGTERM', gracefulShutdown);
|
|
1964
|
+
process.on('SIGINT', gracefulShutdown);
|
|
1581
1965
|
//# sourceMappingURL=server.js.map
|