@theihtisham/agent-shadow-brain 7.0.0 → 7.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +47 -385
- package/dist/activity-cli.d.ts +3 -0
- package/dist/activity-cli.d.ts.map +1 -0
- package/dist/activity-cli.js +78 -0
- package/dist/activity-cli.js.map +1 -0
- package/dist/adapters/index.d.ts +2 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +3 -2
- package/dist/adapters/index.js.map +1 -1
- package/dist/brain/activity-journal.d.ts +82 -0
- package/dist/brain/activity-journal.d.ts.map +1 -0
- package/dist/brain/activity-journal.js +314 -0
- package/dist/brain/activity-journal.js.map +1 -0
- package/dist/brain/activity-reporting.d.ts +14 -0
- package/dist/brain/activity-reporting.d.ts.map +1 -0
- package/dist/brain/activity-reporting.js +17 -0
- package/dist/brain/activity-reporting.js.map +1 -0
- package/dist/brain/auto-update.js +1 -1
- package/dist/brain/brain-portability.js +1 -1
- package/dist/brain/client-integrations.d.ts +61 -0
- package/dist/brain/client-integrations.d.ts.map +1 -0
- package/dist/brain/client-integrations.js +98 -0
- package/dist/brain/client-integrations.js.map +1 -0
- package/dist/brain/context-assembly.d.ts +76 -0
- package/dist/brain/context-assembly.d.ts.map +1 -0
- package/dist/brain/context-assembly.js +305 -0
- package/dist/brain/context-assembly.js.map +1 -0
- package/dist/brain/feature-settings.d.ts +58 -0
- package/dist/brain/feature-settings.d.ts.map +1 -0
- package/dist/brain/feature-settings.js +241 -0
- package/dist/brain/feature-settings.js.map +1 -0
- package/dist/brain/global-brain.d.ts +7 -0
- package/dist/brain/global-brain.d.ts.map +1 -1
- package/dist/brain/global-brain.js +19 -4
- package/dist/brain/global-brain.js.map +1 -1
- package/dist/brain/mcp-server.d.ts +23 -1
- package/dist/brain/mcp-server.d.ts.map +1 -1
- package/dist/brain/mcp-server.js +224 -24
- package/dist/brain/mcp-server.js.map +1 -1
- package/dist/brain/mcp-stdio.d.ts +12 -0
- package/dist/brain/mcp-stdio.d.ts.map +1 -0
- package/dist/brain/mcp-stdio.js +134 -0
- package/dist/brain/mcp-stdio.js.map +1 -0
- package/dist/brain/memory-annotations.d.ts +97 -0
- package/dist/brain/memory-annotations.d.ts.map +1 -0
- package/dist/brain/memory-annotations.js +388 -0
- package/dist/brain/memory-annotations.js.map +1 -0
- package/dist/brain/memory-graph.d.ts.map +1 -1
- package/dist/brain/memory-graph.js +12 -23
- package/dist/brain/memory-graph.js.map +1 -1
- package/dist/brain/memory-sources.d.ts +8 -0
- package/dist/brain/memory-sources.d.ts.map +1 -0
- package/dist/brain/memory-sources.js +27 -0
- package/dist/brain/memory-sources.js.map +1 -0
- package/dist/brain/orchestrator.js +1 -1
- package/dist/brain/subconscious.d.ts +21 -24
- package/dist/brain/subconscious.d.ts.map +1 -1
- package/dist/brain/subconscious.js +82 -218
- package/dist/brain/subconscious.js.map +1 -1
- package/dist/brain/task-workflow.d.ts +22 -0
- package/dist/brain/task-workflow.d.ts.map +1 -0
- package/dist/brain/task-workflow.js +182 -0
- package/dist/brain/task-workflow.js.map +1 -0
- package/dist/brain/workflow-skills.d.ts +86 -0
- package/dist/brain/workflow-skills.d.ts.map +1 -0
- package/dist/brain/workflow-skills.js +514 -0
- package/dist/brain/workflow-skills.js.map +1 -0
- package/dist/cli.js +21 -2
- package/dist/cli.js.map +1 -1
- package/dist/context-cli.d.ts +3 -0
- package/dist/context-cli.d.ts.map +1 -0
- package/dist/context-cli.js +56 -0
- package/dist/context-cli.js.map +1 -0
- package/dist/curation-cli.d.ts +4 -0
- package/dist/curation-cli.d.ts.map +1 -0
- package/dist/curation-cli.js +118 -0
- package/dist/curation-cli.js.map +1 -0
- package/dist/dashboard/live-workspace-html.d.ts +2 -0
- package/dist/dashboard/live-workspace-html.d.ts.map +1 -0
- package/dist/dashboard/live-workspace-html.js +893 -0
- package/dist/dashboard/live-workspace-html.js.map +1 -0
- package/dist/dashboard/server.d.ts +1 -0
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +53 -18
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/v6-dashboard-html.d.ts +1 -1
- package/dist/dashboard/v6-dashboard-html.d.ts.map +1 -1
- package/dist/dashboard/v6-dashboard-html.js +7 -29
- package/dist/dashboard/v6-dashboard-html.js.map +1 -1
- package/dist/dashboard/workspace-api.d.ts +16 -0
- package/dist/dashboard/workspace-api.d.ts.map +1 -0
- package/dist/dashboard/workspace-api.js +309 -0
- package/dist/dashboard/workspace-api.js.map +1 -0
- package/dist/dashboard/workspace-html.d.ts +2 -0
- package/dist/dashboard/workspace-html.d.ts.map +1 -0
- package/dist/dashboard/workspace-html.js +2132 -0
- package/dist/dashboard/workspace-html.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-cli.d.ts +3 -0
- package/dist/integration-cli.d.ts.map +1 -0
- package/dist/integration-cli.js +14 -0
- package/dist/integration-cli.js.map +1 -0
- package/dist/types.d.ts +12 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/workflow-cli.d.ts +3 -0
- package/dist/workflow-cli.d.ts.map +1 -0
- package/dist/workflow-cli.js +100 -0
- package/dist/workflow-cli.js.map +1 -0
- package/docs/WORKFLOW_INTEGRATION.md +105 -0
- package/docs/WORKSPACE.md +111 -0
- package/docs/assets/context-flow-v7.2.png +0 -0
- package/docs/assets/live-v7.1.3.png +0 -0
- package/docs/assets/memory-detail-v7.1.3.png +0 -0
- package/docs/assets/overview-v7.1.3.png +0 -0
- package/docs/assets/workspace-graph-v7.2.png +0 -0
- package/docs/assets/workspace-overview-v7.2.png +0 -0
- package/docs/launch/RELEASE_NOTES_v7.1.0.md +32 -0
- package/docs/launch/RELEASE_NOTES_v7.1.3.md +40 -0
- package/docs/launch/RELEASE_NOTES_v7.2.0.md +24 -0
- package/package.json +112 -207
- package/skills/shadow-debug/SKILL.md +16 -0
- package/skills/shadow-implement/SKILL.md +16 -0
- package/skills/shadow-release/SKILL.md +16 -0
- package/skills/shadow-research/SKILL.md +12 -0
- package/skills/shadow-review/SKILL.md +14 -0
- package/skills/shadow-workflow/SKILL.md +31 -0
package/dist/brain/mcp-server.js
CHANGED
|
@@ -2,17 +2,28 @@
|
|
|
2
2
|
// Exposes analysis tools via Model Context Protocol
|
|
3
3
|
// v6.0.0 — Hive Mind Edition (Cursor + Claude Code + Codex + Copilot + sub-agent frameworks)
|
|
4
4
|
import * as http from 'http';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import { performance } from 'node:perf_hooks';
|
|
8
|
+
const MEMORY_TOOLS = new Set(['global_recall', 'global_recall_scored', 'global_stats', 'global_storage_health',
|
|
9
|
+
'global_timeline', 'workflow_analyze', 'workflow_skills', 'context_pack', 'feature_flags', 'activity_report']);
|
|
5
10
|
export class MCPServer {
|
|
6
|
-
constructor(orchestrator, options) {
|
|
11
|
+
constructor(orchestrator, options, dependencies = {}) {
|
|
12
|
+
this.dependencies = dependencies;
|
|
7
13
|
this.server = null;
|
|
8
14
|
this.sseClients = new Map();
|
|
9
15
|
this.lastHealthScore = null;
|
|
16
|
+
this.telemetrySession = 'mcp-' + randomUUID();
|
|
17
|
+
this.telemetryAgent = 'mcp-client';
|
|
18
|
+
this.telemetryInitialized = false;
|
|
19
|
+
this.telemetryWarning = false;
|
|
10
20
|
this.orchestrator = orchestrator;
|
|
11
21
|
this.options = {
|
|
12
22
|
port: options?.port ?? 7342,
|
|
13
23
|
host: options?.host ?? 'localhost',
|
|
14
24
|
authToken: options?.authToken ?? process.env.SHADOW_BRAIN_MCP_TOKEN ?? '',
|
|
15
25
|
corsOrigin: options?.corsOrigin ?? `http://${options?.host ?? 'localhost'}:${options?.port ?? 7342}`,
|
|
26
|
+
toolProfile: options?.toolProfile ?? 'full',
|
|
16
27
|
};
|
|
17
28
|
this.toolHandlers = {
|
|
18
29
|
analyze: this.handleAnalyze.bind(this),
|
|
@@ -40,6 +51,11 @@ export class MCPServer {
|
|
|
40
51
|
global_recall_scored: this.handleGlobalRecallScored.bind(this),
|
|
41
52
|
global_stats: this.handleGlobalStats.bind(this),
|
|
42
53
|
global_storage_health: this.handleGlobalStorageHealth.bind(this),
|
|
54
|
+
workflow_analyze: this.handleWorkflowAnalyze.bind(this),
|
|
55
|
+
workflow_skills: this.handleWorkflowSkills.bind(this),
|
|
56
|
+
context_pack: this.handleContextPack.bind(this),
|
|
57
|
+
feature_flags: this.handleFeatureFlags.bind(this),
|
|
58
|
+
activity_report: this.handleActivityReport.bind(this),
|
|
43
59
|
attach_status: this.handleAttachStatus.bind(this),
|
|
44
60
|
global_timeline: this.handleGlobalTimeline.bind(this),
|
|
45
61
|
firewall_check: this.handleFirewallCheck.bind(this),
|
|
@@ -312,10 +328,10 @@ export class MCPServer {
|
|
|
312
328
|
const tokens = getTokenEconomy();
|
|
313
329
|
const formal = getFormalBridge();
|
|
314
330
|
const airgap = getAirGapMode();
|
|
315
|
-
const brain = getGlobalBrain();
|
|
331
|
+
const brain = this.dependencies.brain ?? getGlobalBrain();
|
|
316
332
|
await Promise.all([sabb.init(), causal.init(), collisions.init(), dream.init(), rep.init(), tokens.init(), formal.init(), airgap.init(), brain.init()]);
|
|
317
333
|
return {
|
|
318
|
-
version: '7.
|
|
334
|
+
version: '7.1.3',
|
|
319
335
|
modules: {
|
|
320
336
|
sabb: sabb.getStats(),
|
|
321
337
|
causal: causal.stats(),
|
|
@@ -348,7 +364,7 @@ export class MCPServer {
|
|
|
348
364
|
}
|
|
349
365
|
async handleGlobalRecall(params) {
|
|
350
366
|
const { getGlobalBrain } = await import('./global-brain.js');
|
|
351
|
-
const brain = getGlobalBrain();
|
|
367
|
+
const brain = this.dependencies.brain ?? getGlobalBrain();
|
|
352
368
|
await brain.init();
|
|
353
369
|
return brain.recall({
|
|
354
370
|
projectId: params.projectId,
|
|
@@ -361,7 +377,7 @@ export class MCPServer {
|
|
|
361
377
|
}
|
|
362
378
|
async handleGlobalRecallScored(params) {
|
|
363
379
|
const { getGlobalBrain } = await import('./global-brain.js');
|
|
364
|
-
const brain = getGlobalBrain();
|
|
380
|
+
const brain = this.dependencies.brain ?? getGlobalBrain();
|
|
365
381
|
await brain.init();
|
|
366
382
|
return brain.recallScored({
|
|
367
383
|
projectId: params.projectId,
|
|
@@ -376,7 +392,7 @@ export class MCPServer {
|
|
|
376
392
|
async handleGlobalStats(_params) {
|
|
377
393
|
const { getGlobalBrain } = await import('./global-brain.js');
|
|
378
394
|
const { getAllCacheStats } = await import('./l0-cache.js');
|
|
379
|
-
const brain = getGlobalBrain();
|
|
395
|
+
const brain = this.dependencies.brain ?? getGlobalBrain();
|
|
380
396
|
await brain.init();
|
|
381
397
|
return {
|
|
382
398
|
brain: brain.getStats(),
|
|
@@ -385,7 +401,50 @@ export class MCPServer {
|
|
|
385
401
|
}
|
|
386
402
|
async handleGlobalStorageHealth(_params) {
|
|
387
403
|
const { getGlobalBrain } = await import('./global-brain.js');
|
|
388
|
-
return getGlobalBrain().getStorageHealth();
|
|
404
|
+
return (this.dependencies.brain ?? getGlobalBrain()).getStorageHealth();
|
|
405
|
+
}
|
|
406
|
+
async handleWorkflowAnalyze(params) {
|
|
407
|
+
const { analyzeTask } = await import('./task-workflow.js');
|
|
408
|
+
return analyzeTask(params.request, {
|
|
409
|
+
mode: params.mode,
|
|
410
|
+
taskType: params.taskType,
|
|
411
|
+
complexity: params.complexity,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
async handleWorkflowSkills(params) {
|
|
415
|
+
const { getBundledSkill, listBundledSkills } = await import('./workflow-skills.js');
|
|
416
|
+
if (params.name !== undefined && typeof params.name !== 'string')
|
|
417
|
+
throw new TypeError('name must be a bundled skill name.');
|
|
418
|
+
return params.name === undefined ? listBundledSkills() : getBundledSkill(params.name);
|
|
419
|
+
}
|
|
420
|
+
async handleContextPack(params) {
|
|
421
|
+
const { assembleContext } = await import('./context-assembly.js');
|
|
422
|
+
const { getFeatureSettings } = await import('./feature-settings.js');
|
|
423
|
+
const { getGlobalBrain } = await import('./global-brain.js');
|
|
424
|
+
if (typeof params.projectId !== 'string' || !params.projectId.trim())
|
|
425
|
+
throw new TypeError('A project ID is required.');
|
|
426
|
+
if (params.query !== undefined && typeof params.query !== 'string')
|
|
427
|
+
throw new TypeError('Query must be text.');
|
|
428
|
+
if (params.tokenBudget !== undefined && (!Number.isSafeInteger(params.tokenBudget) || Number(params.tokenBudget) < 0 || Number(params.tokenBudget) > 12000))
|
|
429
|
+
throw new TypeError('Token budget must be an integer from 0 to 12000.');
|
|
430
|
+
if (params.includeCrossProject !== undefined && typeof params.includeCrossProject !== 'boolean')
|
|
431
|
+
throw new TypeError('Cross-project choice must be boolean.');
|
|
432
|
+
const features = (this.dependencies.settings ?? getFeatureSettings()).get().features;
|
|
433
|
+
const brain = this.dependencies.brain ?? getGlobalBrain();
|
|
434
|
+
if (features.contextAssembly) {
|
|
435
|
+
await brain.init();
|
|
436
|
+
await brain.sync();
|
|
437
|
+
if (brain.getStorageHealth().lastError)
|
|
438
|
+
throw new Error('Memory store is not readable. Check global_storage_health.');
|
|
439
|
+
}
|
|
440
|
+
const { memoryAnnotationsFor } = await import('./memory-annotations.js');
|
|
441
|
+
return assembleContext(brain, { projectId: params.projectId, query: params.query,
|
|
442
|
+
tokenBudget: params.tokenBudget, includeCrossProject: params.includeCrossProject, features,
|
|
443
|
+
annotations: features.contextAssembly ? memoryAnnotationsFor(brain).get() : undefined });
|
|
444
|
+
}
|
|
445
|
+
async handleFeatureFlags(_params) {
|
|
446
|
+
const { getFeatureSettings, FEATURE_DEFINITIONS } = await import('./feature-settings.js');
|
|
447
|
+
return { ...(this.dependencies.settings ?? getFeatureSettings()).get(), definitions: FEATURE_DEFINITIONS };
|
|
389
448
|
}
|
|
390
449
|
async handleAttachStatus(params) {
|
|
391
450
|
const { getHookInstaller } = await import('./session-hooks.js');
|
|
@@ -396,7 +455,7 @@ export class MCPServer {
|
|
|
396
455
|
async handleGlobalTimeline(params) {
|
|
397
456
|
const { getGlobalBrain, GlobalBrain } = await import('./global-brain.js');
|
|
398
457
|
const projectDir = params.projectDir;
|
|
399
|
-
const brain = getGlobalBrain();
|
|
458
|
+
const brain = this.dependencies.brain ?? getGlobalBrain();
|
|
400
459
|
await brain.init();
|
|
401
460
|
return brain.timeline({
|
|
402
461
|
projectId: projectDir ? GlobalBrain.projectIdFor(projectDir) : params.projectId,
|
|
@@ -500,7 +559,7 @@ export class MCPServer {
|
|
|
500
559
|
// Lightweight health endpoint for tool connectivity checks
|
|
501
560
|
this.sendJSON(res, 200, {
|
|
502
561
|
status: 'ok',
|
|
503
|
-
version: '7.
|
|
562
|
+
version: '7.1.3',
|
|
504
563
|
uptime: process.uptime(),
|
|
505
564
|
tools: Object.keys(this.toolHandlers).length,
|
|
506
565
|
});
|
|
@@ -554,14 +613,26 @@ export class MCPServer {
|
|
|
554
613
|
}
|
|
555
614
|
}
|
|
556
615
|
async handleRequest(request) {
|
|
557
|
-
if (request.jsonrpc !== '2.0'
|
|
558
|
-
|
|
616
|
+
if (!request || typeof request !== 'object' || Array.isArray(request) || request.jsonrpc !== '2.0' ||
|
|
617
|
+
typeof request.method !== 'string' || (request.id !== undefined && typeof request.id !== 'string' && typeof request.id !== 'number') ||
|
|
618
|
+
(request.params !== undefined && (!request.params || typeof request.params !== 'object' || Array.isArray(request.params)))) {
|
|
619
|
+
return this.makeError(undefined, -32600, 'Invalid JSON-RPC request.');
|
|
559
620
|
}
|
|
560
621
|
const { method, params } = request;
|
|
561
622
|
try {
|
|
562
623
|
switch (method) {
|
|
563
|
-
case 'initialize':
|
|
564
|
-
|
|
624
|
+
case 'initialize': {
|
|
625
|
+
if (this.options.toolProfile === 'memory') {
|
|
626
|
+
const name = String(params?.clientInfo?.name ?? '').toLowerCase();
|
|
627
|
+
this.telemetryAgent = name.includes('codex') ? 'codex' : name.includes('claude') ? 'claude-code' :
|
|
628
|
+
name.includes('opencode') ? 'opencode' : name.includes('deepseek') ? 'deepseek-harness' : 'mcp-client';
|
|
629
|
+
this.telemetryInitialized = true;
|
|
630
|
+
await this.recordMeasured({ kind: 'session-start' });
|
|
631
|
+
}
|
|
632
|
+
return this.makeResult(request.id, this.handleInitialize(params));
|
|
633
|
+
}
|
|
634
|
+
case 'ping':
|
|
635
|
+
return this.makeResult(request.id, {});
|
|
565
636
|
case 'notifications/initialized':
|
|
566
637
|
// Cursor sends this after initialize — acknowledge silently
|
|
567
638
|
return this.makeResult(request.id, {});
|
|
@@ -574,15 +645,44 @@ export class MCPServer {
|
|
|
574
645
|
case 'tools/call': {
|
|
575
646
|
const toolName = params?.name;
|
|
576
647
|
const toolArgs = params?.arguments ?? {};
|
|
577
|
-
if (!toolName) {
|
|
648
|
+
if (typeof toolName !== 'string' || !toolName || !toolArgs || typeof toolArgs !== 'object' || Array.isArray(toolArgs)) {
|
|
578
649
|
return this.makeError(request.id, -32602, 'Missing tool name in params.name');
|
|
579
650
|
}
|
|
580
651
|
const handler = this.toolHandlers[toolName];
|
|
581
|
-
if (!handler) {
|
|
652
|
+
if (!Object.hasOwn(this.toolHandlers, toolName) || !handler || (this.options.toolProfile === 'memory' && !MEMORY_TOOLS.has(toolName))) {
|
|
582
653
|
return this.makeError(request.id, -32601, `Unknown tool: ${toolName}`);
|
|
583
654
|
}
|
|
584
|
-
|
|
585
|
-
|
|
655
|
+
try {
|
|
656
|
+
if (this.options.toolProfile === 'memory')
|
|
657
|
+
this.validateMemoryArguments(toolName, toolArgs);
|
|
658
|
+
const measured = this.options.toolProfile === 'memory' && toolName !== 'activity_report';
|
|
659
|
+
const correlationId = randomUUID();
|
|
660
|
+
const projectId = typeof toolArgs.projectId === 'string' && /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/.test(toolArgs.projectId)
|
|
661
|
+
? toolArgs.projectId : undefined;
|
|
662
|
+
if (measured)
|
|
663
|
+
await this.recordMeasured({ kind: 'tool-start', tool: toolName, correlationId, ...(projectId ? { projectId } : {}) });
|
|
664
|
+
const started = performance.now();
|
|
665
|
+
let result;
|
|
666
|
+
try {
|
|
667
|
+
result = await handler(toolArgs);
|
|
668
|
+
if (measured)
|
|
669
|
+
await this.recordMeasured({ kind: 'tool-end', tool: toolName, correlationId, outcome: 'success',
|
|
670
|
+
durationMs: Math.max(0, Math.round((performance.now() - started) * 1000) / 1000), ...(projectId ? { projectId } : {}) });
|
|
671
|
+
}
|
|
672
|
+
catch (error) {
|
|
673
|
+
if (measured)
|
|
674
|
+
await this.recordMeasured({ kind: 'tool-end', tool: toolName, correlationId, outcome: 'error',
|
|
675
|
+
durationMs: Math.max(0, Math.round((performance.now() - started) * 1000) / 1000), ...(projectId ? { projectId } : {}) });
|
|
676
|
+
throw error;
|
|
677
|
+
}
|
|
678
|
+
return this.makeResult(request.id, { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] });
|
|
679
|
+
}
|
|
680
|
+
catch (error) {
|
|
681
|
+
const message = error instanceof Error ? error.message : 'Tool execution failed.';
|
|
682
|
+
if (error instanceof TypeError || error instanceof RangeError)
|
|
683
|
+
return this.makeError(request.id, -32602, message);
|
|
684
|
+
return this.makeResult(request.id, { content: [{ type: 'text', text: message }], isError: true });
|
|
685
|
+
}
|
|
586
686
|
}
|
|
587
687
|
default:
|
|
588
688
|
return this.makeError(request.id, -32601, `Method not found: ${method}`);
|
|
@@ -593,18 +693,77 @@ export class MCPServer {
|
|
|
593
693
|
}
|
|
594
694
|
}
|
|
595
695
|
// ── Tool Handlers ──────────────────────────────────────────────────────
|
|
596
|
-
|
|
696
|
+
async telemetryProject() {
|
|
697
|
+
if (this.dependencies.projectId)
|
|
698
|
+
return this.dependencies.projectId;
|
|
699
|
+
const { GlobalBrain } = await import('./global-brain.js');
|
|
700
|
+
return GlobalBrain.projectIdFor(path.resolve(this.dependencies.projectDir ?? process.cwd()));
|
|
701
|
+
}
|
|
702
|
+
async recordMeasured(event) {
|
|
703
|
+
if (this.options.toolProfile !== 'memory')
|
|
704
|
+
return;
|
|
705
|
+
try {
|
|
706
|
+
const { getFeatureSettings } = await import('./feature-settings.js');
|
|
707
|
+
if (!(this.dependencies.settings ?? getFeatureSettings()).get().features.activityRecording)
|
|
708
|
+
return;
|
|
709
|
+
const { getGlobalBrain } = await import('./global-brain.js');
|
|
710
|
+
const { ActivityJournal, ACTIVITY_JOURNAL_FILENAME } = await import('./activity-journal.js');
|
|
711
|
+
const brain = this.dependencies.brain ?? getGlobalBrain();
|
|
712
|
+
const journal = new ActivityJournal({ filePath: path.join(path.dirname(brain.dbPath), ACTIVITY_JOURNAL_FILENAME), lockTimeoutMs: 250 });
|
|
713
|
+
await journal.append({ projectId: await this.telemetryProject(), sessionId: this.telemetrySession,
|
|
714
|
+
agent: this.telemetryAgent, ...event, source: 'measured', transport: 'mcp' });
|
|
715
|
+
}
|
|
716
|
+
catch {
|
|
717
|
+
if (!this.telemetryWarning) {
|
|
718
|
+
this.telemetryWarning = true;
|
|
719
|
+
console.error('Shadow Brain activity recording is unavailable. Tool execution continues.');
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
async finishMemorySession() {
|
|
724
|
+
if (this.telemetryInitialized) {
|
|
725
|
+
this.telemetryInitialized = false;
|
|
726
|
+
await this.recordMeasured({ kind: 'session-end' });
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
async handleActivityReport(params) {
|
|
730
|
+
const { reportAgentActivity } = await import('./activity-reporting.js');
|
|
731
|
+
const { getFeatureSettings } = await import('./feature-settings.js');
|
|
732
|
+
const { getGlobalBrain } = await import('./global-brain.js');
|
|
733
|
+
return reportAgentActivity(this.dependencies.brain ?? getGlobalBrain(), this.dependencies.settings ?? getFeatureSettings(), {
|
|
734
|
+
projectId: await this.telemetryProject(), sessionId: this.telemetrySession, agent: this.telemetryAgent, ...params,
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
validateMemoryArguments(name, args) {
|
|
738
|
+
if (!['global_recall', 'global_recall_scored', 'global_timeline'].includes(name))
|
|
739
|
+
return;
|
|
740
|
+
if (args.limit !== undefined && (!Number.isSafeInteger(args.limit) || Number(args.limit) < 1 || Number(args.limit) > 200)) {
|
|
741
|
+
throw new TypeError('limit must be an integer from 1 to 200.');
|
|
742
|
+
}
|
|
743
|
+
for (const key of ['projectId', 'projectDir', 'agentTool', 'category']) {
|
|
744
|
+
if (args[key] !== undefined && (typeof args[key] !== 'string' || args[key].length > 1000))
|
|
745
|
+
throw new TypeError(key + ' must be bounded text.');
|
|
746
|
+
}
|
|
747
|
+
for (const key of ['minImportance', 'minConfidence']) {
|
|
748
|
+
if (args[key] !== undefined && (typeof args[key] !== 'number' || !Number.isFinite(args[key]) || Number(args[key]) < 0 || Number(args[key]) > 1))
|
|
749
|
+
throw new TypeError(key + ' must be from 0 to 1.');
|
|
750
|
+
}
|
|
751
|
+
if (args.keywords !== undefined && (!Array.isArray(args.keywords) || args.keywords.length > 32 || args.keywords.some(word => typeof word !== 'string' || word.length > 256))) {
|
|
752
|
+
throw new TypeError('keywords must contain at most 32 text terms of at most 256 characters.');
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
handleInitialize(params) {
|
|
756
|
+
const versions = ['2025-06-18', '2024-11-05'];
|
|
597
757
|
return {
|
|
598
|
-
protocolVersion:
|
|
758
|
+
protocolVersion: versions.includes(String(params?.protocolVersion)) ? params.protocolVersion : versions[0],
|
|
599
759
|
capabilities: {
|
|
600
760
|
tools: { listChanged: false },
|
|
601
761
|
resources: { subscribe: false, listChanged: false },
|
|
602
762
|
prompts: { listChanged: false },
|
|
603
|
-
logging: {},
|
|
604
763
|
},
|
|
605
764
|
serverInfo: {
|
|
606
765
|
name: 'agent-shadow-brain',
|
|
607
|
-
version: '7.
|
|
766
|
+
version: '7.1.3',
|
|
608
767
|
description: 'Cross-agent memory and safety layer for AI coding agents',
|
|
609
768
|
},
|
|
610
769
|
};
|
|
@@ -893,7 +1052,7 @@ export class MCPServer {
|
|
|
893
1052
|
async handleStatus(params) {
|
|
894
1053
|
const status = this.orchestrator.getStatus?.() || {};
|
|
895
1054
|
return {
|
|
896
|
-
version: '7.
|
|
1055
|
+
version: '7.1.3',
|
|
897
1056
|
...status,
|
|
898
1057
|
};
|
|
899
1058
|
}
|
|
@@ -919,7 +1078,7 @@ export class MCPServer {
|
|
|
919
1078
|
const instance = this.orchestrator[mod.key];
|
|
920
1079
|
modules.push({
|
|
921
1080
|
name: mod.name,
|
|
922
|
-
version: '7.
|
|
1081
|
+
version: '7.1.3',
|
|
923
1082
|
status: instance ? 'active' : 'idle',
|
|
924
1083
|
});
|
|
925
1084
|
}
|
|
@@ -946,7 +1105,14 @@ export class MCPServer {
|
|
|
946
1105
|
}
|
|
947
1106
|
// ── Tool Definitions ───────────────────────────────────────────────────
|
|
948
1107
|
getToolDefinitions() {
|
|
949
|
-
|
|
1108
|
+
const definitions = [
|
|
1109
|
+
{ name: 'activity_report', description: 'Explicitly report an agent phase or tool span to the live portal. Writes only bounded activity labels/timing; reports remain labelled host-reported. Do not send request text, arguments, file paths, or secrets.',
|
|
1110
|
+
inputSchema: { type: 'object', additionalProperties: false, required: ['kind'], properties: {
|
|
1111
|
+
kind: { type: 'string', enum: ['session-start', 'phase', 'tool-start', 'tool-end', 'session-end'] },
|
|
1112
|
+
projectId: { type: 'string' }, sessionId: { type: 'string' }, agent: { type: 'string' },
|
|
1113
|
+
phase: { type: 'string', enum: ['understand', 'plan', 'work', 'verify'] }, tool: { type: 'string' }, correlationId: { type: 'string' },
|
|
1114
|
+
outcome: { type: 'string', enum: ['success', 'error', 'cancelled'] }, durationMs: { type: 'number', minimum: 0 },
|
|
1115
|
+
} }, annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false } },
|
|
950
1116
|
{
|
|
951
1117
|
name: 'analyze',
|
|
952
1118
|
description: 'Run full analysis on project files and return insights',
|
|
@@ -1166,6 +1332,37 @@ export class MCPServer {
|
|
|
1166
1332
|
description: 'Inspect this process memory-store status, pending operations, last successful save, and last storage error. Does not initialize or flush the store. (v7.0.0)',
|
|
1167
1333
|
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
1168
1334
|
},
|
|
1335
|
+
{
|
|
1336
|
+
name: 'workflow_analyze',
|
|
1337
|
+
description: 'Suggest a focused workflow and relevant bundled skills for a user request. Pure local heuristic: no execution, file changes, provider calls, or permission grants. (v7.1.0)',
|
|
1338
|
+
inputSchema: {
|
|
1339
|
+
type: 'object', required: ['request'], additionalProperties: false,
|
|
1340
|
+
properties: {
|
|
1341
|
+
request: { type: 'string', description: 'The requested task, including scope and planning-only constraints.' },
|
|
1342
|
+
mode: { type: 'string', enum: ['auto', 'plan-only', 'execute'] },
|
|
1343
|
+
taskType: { type: 'string', enum: ['auto', 'implement', 'debug', 'review', 'research', 'release'] },
|
|
1344
|
+
complexity: { type: 'string', enum: ['auto', 'simple', 'complex'] },
|
|
1345
|
+
},
|
|
1346
|
+
},
|
|
1347
|
+
},
|
|
1348
|
+
{
|
|
1349
|
+
name: 'workflow_skills',
|
|
1350
|
+
description: 'List bundled workflow skills, or read one by name. Does not install skills or change client settings. (v7.1.0)',
|
|
1351
|
+
inputSchema: { type: 'object', properties: { name: { type: 'string' } }, additionalProperties: false },
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
name: 'context_pack',
|
|
1355
|
+
description: 'Build a bounded reference context pack for a specified project and task, with provenance, selection reasons, and exclusions. Cross-project content requires both the persisted feature and an explicit request. No provider calls or source-file reads. Token counts are estimates. (v7.1.3)',
|
|
1356
|
+
inputSchema: { type: 'object', required: ['projectId'], additionalProperties: false, properties: {
|
|
1357
|
+
projectId: { type: 'string' }, query: { type: 'string' },
|
|
1358
|
+
tokenBudget: { type: 'integer', minimum: 0, maximum: 12000 }, includeCrossProject: { type: 'boolean' },
|
|
1359
|
+
} },
|
|
1360
|
+
},
|
|
1361
|
+
{
|
|
1362
|
+
name: 'feature_flags',
|
|
1363
|
+
description: 'Read the five persisted context, briefing, and activity controls. Does not modify settings or expose provider configuration. (v7.1.3)',
|
|
1364
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
1365
|
+
},
|
|
1169
1366
|
{
|
|
1170
1367
|
name: 'attach_status',
|
|
1171
1368
|
description: 'Detect which AI agents are installed on this machine (v5.2.0)',
|
|
@@ -1256,6 +1453,9 @@ export class MCPServer {
|
|
|
1256
1453
|
},
|
|
1257
1454
|
},
|
|
1258
1455
|
];
|
|
1456
|
+
return this.options.toolProfile === 'memory'
|
|
1457
|
+
? definitions.filter(tool => MEMORY_TOOLS.has(tool.name)).map(tool => ({ ...tool, annotations: { readOnlyHint: tool.name !== 'activity_report', destructiveHint: false, openWorldHint: false } }))
|
|
1458
|
+
: definitions;
|
|
1259
1459
|
}
|
|
1260
1460
|
// ── HTTP Handling ──────────────────────────────────────────────────────
|
|
1261
1461
|
async handleHTTPMCPRequest(req, res) {
|