@exaudeus/memory-mcp 1.9.5 → 1.9.7
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/dist/config-manager.d.ts +6 -0
- package/dist/config-manager.js +11 -0
- package/dist/index.js +46 -22
- package/package.json +1 -1
package/dist/config-manager.d.ts
CHANGED
|
@@ -35,6 +35,12 @@ export declare class ConfigManager {
|
|
|
35
35
|
constructor(configPath: string, initial: LoadedConfig, initialStores: Map<string, MarkdownMemoryStore>, initialHealth: Map<string, LobeHealth>);
|
|
36
36
|
/** Derive alwaysInclude lobe names from config — pure, no side effects. */
|
|
37
37
|
private static computeAlwaysIncludeLobes;
|
|
38
|
+
/**
|
|
39
|
+
* Adopt a newly created config file that didn't exist at startup.
|
|
40
|
+
* Used by memory_bootstrap when it creates memory-config.json from scratch.
|
|
41
|
+
* Switches the manager from default/env mode to file-based mode and reloads.
|
|
42
|
+
*/
|
|
43
|
+
adoptNewConfigFile(filePath: string): Promise<void>;
|
|
38
44
|
/**
|
|
39
45
|
* Ensure config is fresh. Call at the start of every tool handler.
|
|
40
46
|
* Stats config file, reloads if mtime changed. Graceful on all errors.
|
package/dist/config-manager.js
CHANGED
|
@@ -36,6 +36,17 @@ export class ConfigManager {
|
|
|
36
36
|
.filter(([, config]) => config.alwaysInclude === true)
|
|
37
37
|
.map(([name]) => name);
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Adopt a newly created config file that didn't exist at startup.
|
|
41
|
+
* Used by memory_bootstrap when it creates memory-config.json from scratch.
|
|
42
|
+
* Switches the manager from default/env mode to file-based mode and reloads.
|
|
43
|
+
*/
|
|
44
|
+
async adoptNewConfigFile(filePath) {
|
|
45
|
+
this.configPath = filePath;
|
|
46
|
+
this.configOrigin = { source: 'file', path: filePath };
|
|
47
|
+
this.configMtime = 0; // Force reload on next ensureFresh
|
|
48
|
+
await this.ensureFresh();
|
|
49
|
+
}
|
|
39
50
|
/**
|
|
40
51
|
* Ensure config is fresh. Call at the start of every tool handler.
|
|
41
52
|
* Stats config file, reloads if mtime changed. Graceful on all errors.
|
package/dist/index.js
CHANGED
|
@@ -201,6 +201,13 @@ async function resolveLobesForRead(isFirstMemoryToolCall = true) {
|
|
|
201
201
|
/** Build the shared lobe property for tool schemas — called on each ListTools request
|
|
202
202
|
* so the description and enum stay in sync after a hot-reload adds or removes lobes. */
|
|
203
203
|
function buildLobeProperty(currentLobeNames) {
|
|
204
|
+
if (currentLobeNames.length === 0) {
|
|
205
|
+
return {
|
|
206
|
+
type: 'string',
|
|
207
|
+
description: 'Memory lobe name. No lobes configured yet — run memory_bootstrap(lobe: "your-project", root: "/absolute/path/to/repo") first.',
|
|
208
|
+
enum: undefined,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
204
211
|
const isSingle = currentLobeNames.length === 1;
|
|
205
212
|
return {
|
|
206
213
|
type: 'string',
|
|
@@ -563,6 +570,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
563
570
|
sections.push(crashSection);
|
|
564
571
|
if (degradedSection)
|
|
565
572
|
sections.push(degradedSection);
|
|
573
|
+
// Zero lobes — guide agent to bootstrap before anything else
|
|
574
|
+
if (configManager.getLobeNames().length === 0) {
|
|
575
|
+
sections.push('## No Lobes Configured\n\n' +
|
|
576
|
+
'No memory lobes exist yet. Run **memory_bootstrap** to create one for this project:\n\n' +
|
|
577
|
+
'```\nmemory_bootstrap(lobe: "your-project-name", root: "/absolute/path/to/repo")\n```\n\n' +
|
|
578
|
+
'After bootstrapping, call **brief** again to load project context.');
|
|
579
|
+
return { content: [{ type: 'text', text: sections.join('\n\n---\n\n') }] };
|
|
580
|
+
}
|
|
566
581
|
// Collect briefing across all lobes (or specified lobe + alwaysInclude)
|
|
567
582
|
const briefingLobeNames = allBriefingLobes;
|
|
568
583
|
const allStale = [];
|
|
@@ -637,9 +652,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
637
652
|
break;
|
|
638
653
|
}
|
|
639
654
|
case 'global-only': {
|
|
640
|
-
// No project lobes matched — ask agent to specify
|
|
655
|
+
// No project lobes matched — ask agent to specify or bootstrap
|
|
656
|
+
const lobeNames = configManager.getLobeNames();
|
|
657
|
+
const recallHint = lobeNames.length === 0
|
|
658
|
+
? `No lobes configured. Run memory_bootstrap(lobe: "your-project-name", root: "/absolute/path/to/repo") to create one, then retry.`
|
|
659
|
+
: `Cannot determine which lobe to search. Specify the lobe: recall(lobe: "...", context: "${context}")\nAvailable: ${lobeNames.join(', ')}\nIf this is a new project, run memory_bootstrap(lobe: "your-project-name", root: "/absolute/path/to/repo") to create a lobe.`;
|
|
641
660
|
return {
|
|
642
|
-
content: [{ type: 'text', text:
|
|
661
|
+
content: [{ type: 'text', text: recallHint }],
|
|
643
662
|
isError: true,
|
|
644
663
|
};
|
|
645
664
|
}
|
|
@@ -1492,39 +1511,44 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1492
1511
|
root: z.string().optional(),
|
|
1493
1512
|
budgetMB: z.number().positive().optional(),
|
|
1494
1513
|
}).parse(args);
|
|
1495
|
-
// Auto-create lobe: if the lobe is unknown AND root is provided
|
|
1496
|
-
//
|
|
1497
|
-
//
|
|
1514
|
+
// Auto-create lobe: if the lobe is unknown AND root is provided, write the new
|
|
1515
|
+
// lobe entry into memory-config.json and hot-reload. If no config file exists yet,
|
|
1516
|
+
// create one at cwd()/memory-config.json — this is the zero-config bootstrap path.
|
|
1498
1517
|
if (rawLobe && root && !configManager.getStore(rawLobe)) {
|
|
1499
1518
|
const origin = configManager.getConfigOrigin();
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
}],
|
|
1507
|
-
isError: true,
|
|
1508
|
-
};
|
|
1509
|
-
}
|
|
1519
|
+
// Determine the config file path to write to:
|
|
1520
|
+
// - If already file-based, use the existing file
|
|
1521
|
+
// - Otherwise, create memory-config.json in cwd() (the server's working directory)
|
|
1522
|
+
const targetConfigPath = origin.source === 'file'
|
|
1523
|
+
? origin.path
|
|
1524
|
+
: path.join(process.cwd(), 'memory-config.json');
|
|
1510
1525
|
try {
|
|
1511
|
-
|
|
1512
|
-
|
|
1526
|
+
let config = {};
|
|
1527
|
+
if (origin.source === 'file') {
|
|
1528
|
+
const raw = await readFile(targetConfigPath, 'utf-8');
|
|
1529
|
+
config = JSON.parse(raw);
|
|
1530
|
+
}
|
|
1513
1531
|
if (!config.lobes || typeof config.lobes !== 'object')
|
|
1514
1532
|
config.lobes = {};
|
|
1515
1533
|
config.lobes[rawLobe] = { root, budgetMB: budgetMB ?? 2 };
|
|
1516
|
-
await writeFile(
|
|
1517
|
-
process.stderr.write(`[memory-mcp] Auto-added lobe "${rawLobe}" (root: ${root}) to
|
|
1534
|
+
await writeFile(targetConfigPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
1535
|
+
process.stderr.write(`[memory-mcp] Auto-added lobe "${rawLobe}" (root: ${root}) to ${targetConfigPath}\n`);
|
|
1518
1536
|
}
|
|
1519
1537
|
catch (err) {
|
|
1520
1538
|
const message = err instanceof Error ? err.message : String(err);
|
|
1521
1539
|
return {
|
|
1522
|
-
content: [{ type: 'text', text: `Failed to
|
|
1540
|
+
content: [{ type: 'text', text: `Failed to write lobe "${rawLobe}" to ${targetConfigPath}: ${message}` }],
|
|
1523
1541
|
isError: true,
|
|
1524
1542
|
};
|
|
1525
1543
|
}
|
|
1526
|
-
// Reload config to pick up the new lobe
|
|
1527
|
-
|
|
1544
|
+
// Reload config to pick up the new lobe.
|
|
1545
|
+
// If the file was just created from scratch, adopt it as the new config source.
|
|
1546
|
+
if (origin.source !== 'file') {
|
|
1547
|
+
await configManager.adoptNewConfigFile(targetConfigPath);
|
|
1548
|
+
}
|
|
1549
|
+
else {
|
|
1550
|
+
await configManager.ensureFresh();
|
|
1551
|
+
}
|
|
1528
1552
|
}
|
|
1529
1553
|
// Resolve store — after this point, rawLobe is never used again
|
|
1530
1554
|
const ctx = resolveToolContext(rawLobe);
|