mnueron 0.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/ARCHITECTURE.md +161 -0
- package/INSTALL.md +262 -0
- package/LICENSE +21 -0
- package/README.md +305 -0
- package/dashboard/index.html +838 -0
- package/dist/cli.js +685 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/dashboard/server.js +234 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/detectors/claude_code.js +72 -0
- package/dist/detectors/claude_code.js.map +1 -0
- package/dist/detectors/claude_desktop.js +37 -0
- package/dist/detectors/claude_desktop.js.map +1 -0
- package/dist/detectors/cursor.js +36 -0
- package/dist/detectors/cursor.js.map +1 -0
- package/dist/detectors/extra.js +59 -0
- package/dist/detectors/extra.js.map +1 -0
- package/dist/detectors/index.js +14 -0
- package/dist/detectors/index.js.map +1 -0
- package/dist/detectors/json_detector.js +95 -0
- package/dist/detectors/json_detector.js.map +1 -0
- package/dist/detectors/types.js +13 -0
- package/dist/detectors/types.js.map +1 -0
- package/dist/import/claude.js +82 -0
- package/dist/import/claude.js.map +1 -0
- package/dist/import/openai.js +102 -0
- package/dist/import/openai.js.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/loader.js +175 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/types.js +24 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/setup.js +123 -0
- package/dist/setup.js.map +1 -0
- package/dist/store/chunking.js +150 -0
- package/dist/store/chunking.js.map +1 -0
- package/dist/store/embeddings.js +126 -0
- package/dist/store/embeddings.js.map +1 -0
- package/dist/store/local.js +720 -0
- package/dist/store/local.js.map +1 -0
- package/dist/store/provider.js +7 -0
- package/dist/store/provider.js.map +1 -0
- package/dist/store/redactor.js +114 -0
- package/dist/store/redactor.js.map +1 -0
- package/dist/store/remote.js +62 -0
- package/dist/store/remote.js.map +1 -0
- package/dist/tools.js +312 -0
- package/dist/tools.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for tools that store MCP config as `{ "mcpServers": { ... } }`
|
|
3
|
+
* in a JSON file. Claude Desktop, Cursor, and Claude Code all follow this
|
|
4
|
+
* pattern with different paths.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
7
|
+
import { dirname } from 'node:path';
|
|
8
|
+
export class JsonMcpDetector {
|
|
9
|
+
/** Optional extra check (e.g. confirm app is actually installed, not just config-present). */
|
|
10
|
+
isInstalled() {
|
|
11
|
+
return this.configPath() !== null;
|
|
12
|
+
}
|
|
13
|
+
status() {
|
|
14
|
+
const path = this.configPath();
|
|
15
|
+
const installed = this.isInstalled();
|
|
16
|
+
if (!path || !installed) {
|
|
17
|
+
return {
|
|
18
|
+
id: this.id, displayName: this.displayName,
|
|
19
|
+
installed: false, configPath: null,
|
|
20
|
+
configExists: false, alreadyConfigured: false,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const configExists = existsSync(path);
|
|
24
|
+
let alreadyConfigured = false;
|
|
25
|
+
if (configExists) {
|
|
26
|
+
try {
|
|
27
|
+
const cfg = JSON.parse(readFileSync(path, 'utf8'));
|
|
28
|
+
alreadyConfigured = !!cfg?.mcpServers?.[this.serverNameInConfig()];
|
|
29
|
+
}
|
|
30
|
+
catch { /* malformed config */ }
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
id: this.id, displayName: this.displayName,
|
|
34
|
+
installed: true, configPath: path,
|
|
35
|
+
configExists, alreadyConfigured,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
install(serverName, entry) {
|
|
39
|
+
const path = this.configPath();
|
|
40
|
+
if (!path)
|
|
41
|
+
return { ok: false, changed: false, message: `${this.displayName} not detected` };
|
|
42
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
43
|
+
let cfg = { mcpServers: {} };
|
|
44
|
+
if (existsSync(path)) {
|
|
45
|
+
try {
|
|
46
|
+
const raw = readFileSync(path, 'utf8');
|
|
47
|
+
cfg = raw.trim() ? JSON.parse(raw) : { mcpServers: {} };
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return {
|
|
51
|
+
ok: false, changed: false,
|
|
52
|
+
message: `${path} is not valid JSON — not touching it. Fix it by hand first.`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
cfg.mcpServers = cfg.mcpServers ?? {};
|
|
57
|
+
// Don't blow away any other servers the user has configured.
|
|
58
|
+
const before = JSON.stringify(cfg.mcpServers[serverName] ?? null);
|
|
59
|
+
cfg.mcpServers[serverName] = entry;
|
|
60
|
+
const after = JSON.stringify(cfg.mcpServers[serverName]);
|
|
61
|
+
const changed = before !== after;
|
|
62
|
+
writeFileSync(path, JSON.stringify(cfg, null, 2));
|
|
63
|
+
this.lastServerName = serverName;
|
|
64
|
+
return {
|
|
65
|
+
ok: true, changed,
|
|
66
|
+
configPath: path,
|
|
67
|
+
message: changed
|
|
68
|
+
? (before === 'null' ? 'added' : 'updated existing entry')
|
|
69
|
+
: 'already up to date',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
uninstall(serverName) {
|
|
73
|
+
const path = this.configPath();
|
|
74
|
+
if (!path || !existsSync(path)) {
|
|
75
|
+
return { ok: true, removed: false, message: 'nothing to remove' };
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const cfg = JSON.parse(readFileSync(path, 'utf8'));
|
|
79
|
+
if (cfg?.mcpServers?.[serverName]) {
|
|
80
|
+
delete cfg.mcpServers[serverName];
|
|
81
|
+
writeFileSync(path, JSON.stringify(cfg, null, 2));
|
|
82
|
+
return { ok: true, removed: true, message: 'removed' };
|
|
83
|
+
}
|
|
84
|
+
return { ok: true, removed: false, message: 'not registered' };
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
return { ok: false, removed: false, message: `failed: ${e?.message}` };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
lastServerName;
|
|
91
|
+
serverNameInConfig() {
|
|
92
|
+
return this.lastServerName ?? 'engrama';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=json_detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json_detector.js","sourceRoot":"","sources":["../../src/detectors/json_detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool detector interface.
|
|
3
|
+
*
|
|
4
|
+
* Every AI dev tool that supports MCP gets a detector that knows:
|
|
5
|
+
* - whether the tool is installed on this machine
|
|
6
|
+
* - where its MCP config file lives
|
|
7
|
+
* - how to add/remove an MCP server entry without clobbering other entries
|
|
8
|
+
*
|
|
9
|
+
* Adding support for a new tool = adding a new file in this directory and
|
|
10
|
+
* registering it in detectors/index.ts.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/detectors/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude conversation export importer.
|
|
3
|
+
*
|
|
4
|
+
* Get the file: claude.ai → Settings → Privacy → Export data.
|
|
5
|
+
* You receive an email with a download link; the ZIP contains
|
|
6
|
+
* `conversations.json` and (often) `users.json` + `projects.json`.
|
|
7
|
+
*
|
|
8
|
+
* Format (one entry per conversation):
|
|
9
|
+
* {
|
|
10
|
+
* "uuid": "...",
|
|
11
|
+
* "name": "Conversation title",
|
|
12
|
+
* "created_at": "2025-...",
|
|
13
|
+
* "updated_at": "2025-...",
|
|
14
|
+
* "chat_messages": [
|
|
15
|
+
* { "uuid", "text", "sender": "human" | "assistant", "created_at", ... }
|
|
16
|
+
* ]
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* Each conversation becomes ONE memory containing a flattened transcript.
|
|
20
|
+
* For very long chats we truncate at MAX_CHARS — you can re-run with
|
|
21
|
+
* `summarize: true` later (requires a summarizer service).
|
|
22
|
+
*/
|
|
23
|
+
import { readFile } from 'node:fs/promises';
|
|
24
|
+
const MAX_CHARS = 8000; // ~2K tokens. Tune for your use case.
|
|
25
|
+
export async function importClaudeExport(path, namespace) {
|
|
26
|
+
const raw = await readFile(path, 'utf8');
|
|
27
|
+
const data = JSON.parse(raw);
|
|
28
|
+
const conversations = Array.isArray(data) ? data : (data.conversations ?? []);
|
|
29
|
+
const memories = [];
|
|
30
|
+
for (const conv of conversations) {
|
|
31
|
+
const transcript = renderTranscript(conv);
|
|
32
|
+
if (!transcript)
|
|
33
|
+
continue;
|
|
34
|
+
memories.push({
|
|
35
|
+
content: transcript,
|
|
36
|
+
namespace,
|
|
37
|
+
source: 'claude-export',
|
|
38
|
+
source_ref: conv.uuid,
|
|
39
|
+
tags: ['imported', 'claude'],
|
|
40
|
+
metadata: {
|
|
41
|
+
title: conv.name,
|
|
42
|
+
created_at: conv.created_at,
|
|
43
|
+
updated_at: conv.updated_at,
|
|
44
|
+
message_count: conv.chat_messages?.length ?? 0,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return memories;
|
|
49
|
+
}
|
|
50
|
+
function renderTranscript(conv) {
|
|
51
|
+
const parts = [];
|
|
52
|
+
if (conv.name)
|
|
53
|
+
parts.push(`# ${conv.name}`);
|
|
54
|
+
if (conv.created_at)
|
|
55
|
+
parts.push(`(${conv.created_at})`);
|
|
56
|
+
parts.push('');
|
|
57
|
+
for (const msg of conv.chat_messages ?? []) {
|
|
58
|
+
const who = msg.sender === 'assistant' ? 'Claude' : 'User';
|
|
59
|
+
const text = extractText(msg);
|
|
60
|
+
if (!text)
|
|
61
|
+
continue;
|
|
62
|
+
parts.push(`**${who}:** ${text}`);
|
|
63
|
+
parts.push('');
|
|
64
|
+
}
|
|
65
|
+
let out = parts.join('\n').trim();
|
|
66
|
+
if (out.length > MAX_CHARS) {
|
|
67
|
+
out = out.slice(0, MAX_CHARS) + `\n\n[truncated — original ${out.length} chars]`;
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
function extractText(msg) {
|
|
72
|
+
if (typeof msg.text === 'string' && msg.text)
|
|
73
|
+
return msg.text;
|
|
74
|
+
if (Array.isArray(msg.content)) {
|
|
75
|
+
return msg.content
|
|
76
|
+
.filter(p => p.type === 'text' && p.text)
|
|
77
|
+
.map(p => p.text)
|
|
78
|
+
.join('\n');
|
|
79
|
+
}
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/import/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI / ChatGPT conversation export importer.
|
|
3
|
+
*
|
|
4
|
+
* Get the file: chatgpt.com → Settings → Data Controls → Export.
|
|
5
|
+
* Email arrives with a ZIP containing `conversations.json`.
|
|
6
|
+
*
|
|
7
|
+
* Format is a TREE per conversation (parent/child message IDs), not a flat
|
|
8
|
+
* list. We linearize by walking from the root through the current_node
|
|
9
|
+
* pointer when present, otherwise by created_at.
|
|
10
|
+
*/
|
|
11
|
+
import { readFile } from 'node:fs/promises';
|
|
12
|
+
const MAX_CHARS = 8000;
|
|
13
|
+
export async function importOpenAIExport(path, namespace) {
|
|
14
|
+
const raw = await readFile(path, 'utf8');
|
|
15
|
+
const data = JSON.parse(raw);
|
|
16
|
+
const conversations = Array.isArray(data) ? data : (data.conversations ?? []);
|
|
17
|
+
const memories = [];
|
|
18
|
+
for (const conv of conversations) {
|
|
19
|
+
const transcript = renderTranscript(conv);
|
|
20
|
+
if (!transcript)
|
|
21
|
+
continue;
|
|
22
|
+
memories.push({
|
|
23
|
+
content: transcript,
|
|
24
|
+
namespace,
|
|
25
|
+
source: 'openai-export',
|
|
26
|
+
source_ref: conv.id,
|
|
27
|
+
tags: ['imported', 'openai', 'chatgpt'],
|
|
28
|
+
metadata: {
|
|
29
|
+
title: conv.title,
|
|
30
|
+
create_time: conv.create_time,
|
|
31
|
+
update_time: conv.update_time,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return memories;
|
|
36
|
+
}
|
|
37
|
+
function renderTranscript(conv) {
|
|
38
|
+
if (!conv.mapping)
|
|
39
|
+
return '';
|
|
40
|
+
const linear = linearize(conv);
|
|
41
|
+
if (linear.length === 0)
|
|
42
|
+
return '';
|
|
43
|
+
const parts = [];
|
|
44
|
+
if (conv.title)
|
|
45
|
+
parts.push(`# ${conv.title}`);
|
|
46
|
+
if (conv.create_time) {
|
|
47
|
+
parts.push(`(${new Date(conv.create_time * 1000).toISOString()})`);
|
|
48
|
+
}
|
|
49
|
+
parts.push('');
|
|
50
|
+
for (const msg of linear) {
|
|
51
|
+
const role = msg.author?.role;
|
|
52
|
+
if (role === 'system' || role === 'tool')
|
|
53
|
+
continue;
|
|
54
|
+
const who = role === 'assistant' ? 'ChatGPT' : 'User';
|
|
55
|
+
const text = extractText(msg);
|
|
56
|
+
if (!text.trim())
|
|
57
|
+
continue;
|
|
58
|
+
parts.push(`**${who}:** ${text}`);
|
|
59
|
+
parts.push('');
|
|
60
|
+
}
|
|
61
|
+
let out = parts.join('\n').trim();
|
|
62
|
+
if (out.length > MAX_CHARS) {
|
|
63
|
+
out = out.slice(0, MAX_CHARS) + `\n\n[truncated — original ${out.length} chars]`;
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
function linearize(conv) {
|
|
68
|
+
// Prefer current_node path (the active branch). Walk parent pointers up
|
|
69
|
+
// to the root, then reverse.
|
|
70
|
+
const mapping = conv.mapping;
|
|
71
|
+
const result = [];
|
|
72
|
+
let cursor = conv.current_node;
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
while (cursor && !seen.has(cursor)) {
|
|
75
|
+
seen.add(cursor);
|
|
76
|
+
const node = mapping[cursor];
|
|
77
|
+
if (!node)
|
|
78
|
+
break;
|
|
79
|
+
if (node.message)
|
|
80
|
+
result.push(node.message);
|
|
81
|
+
cursor = node.parent ?? null;
|
|
82
|
+
}
|
|
83
|
+
result.reverse();
|
|
84
|
+
if (result.length === 0) {
|
|
85
|
+
// Fallback: sort all messages by create_time
|
|
86
|
+
return Object.values(mapping)
|
|
87
|
+
.map(n => n.message)
|
|
88
|
+
.filter((m) => !!m)
|
|
89
|
+
.sort((a, b) => (a.create_time ?? 0) - (b.create_time ?? 0));
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
function extractText(msg) {
|
|
94
|
+
const parts = msg.content?.parts;
|
|
95
|
+
if (!Array.isArray(parts))
|
|
96
|
+
return '';
|
|
97
|
+
return parts
|
|
98
|
+
.map(p => (typeof p === 'string' ? p : ''))
|
|
99
|
+
.filter(Boolean)
|
|
100
|
+
.join('\n');
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/import/openai.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* mnueron MCP server (stdio).
|
|
4
|
+
* Claude Desktop / Claude Code spawn this as a subprocess and talk to it
|
|
5
|
+
* via JSON-RPC on stdin/stdout. Add to claude_desktop_config.json:
|
|
6
|
+
*
|
|
7
|
+
* { "mcpServers": { "mnueron": { "command": "node",
|
|
8
|
+
* "args": ["C:\\path\\to\\mnueron\\dist\\index.js"] } } }
|
|
9
|
+
*
|
|
10
|
+
* In hosted mode, set MNUERON_API_URL + MNUERON_API_TOKEN env vars instead.
|
|
11
|
+
*
|
|
12
|
+
* Plugin wiring (W1):
|
|
13
|
+
* - At startup we load any plugins listed under ~/.mnueron/config.json's
|
|
14
|
+
* enabledPlugins[] via `loadPlugins(provider)`.
|
|
15
|
+
* - The returned registry is passed into every tool call so `memory_save`
|
|
16
|
+
* can run onBeforeSave hooks and `memory_recall` can run onAfterRecall
|
|
17
|
+
* hooks. See src/tools.ts for the invocation points.
|
|
18
|
+
* - On shutdown we call `deactivatePlugins(registry)` so plugins can flush
|
|
19
|
+
* state, close connections, etc.
|
|
20
|
+
*/
|
|
21
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
22
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
23
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
24
|
+
import { loadConfig, makeProvider } from './config.js';
|
|
25
|
+
import { TOOL_DEFINITIONS, handleToolCall } from './tools.js';
|
|
26
|
+
import { loadPlugins, deactivatePlugins } from './plugins/loader.js';
|
|
27
|
+
async function main() {
|
|
28
|
+
const cfg = loadConfig();
|
|
29
|
+
const provider = makeProvider(cfg);
|
|
30
|
+
// Important: log to stderr only. stdout is the JSON-RPC channel; anything
|
|
31
|
+
// we write to stdout that isn't a proper JSON-RPC message corrupts the
|
|
32
|
+
// stream and Claude Desktop drops the connection.
|
|
33
|
+
process.stderr.write(`[mnueron] mode=${cfg.mode} ns=${cfg.defaultNamespace} ` +
|
|
34
|
+
`${cfg.mode === 'local' ? `db=${cfg.dbPath}` : `api=${cfg.apiUrl}`}\n`);
|
|
35
|
+
// Load enabled plugins (no-op if none configured). Failures here MUST NOT
|
|
36
|
+
// crash the MCP server — a broken plugin should degrade to "feature off",
|
|
37
|
+
// not "tool offline." loadPlugins itself catches per-plugin errors.
|
|
38
|
+
const pluginRegistry = await loadPlugins(provider).catch(e => {
|
|
39
|
+
process.stderr.write(`[mnueron] plugin loader error: ${e?.message ?? e}\n`);
|
|
40
|
+
return { processors: [], sources: [], exporters: [], embedders: [], loaded: [] };
|
|
41
|
+
});
|
|
42
|
+
if (pluginRegistry.loaded.length > 0) {
|
|
43
|
+
process.stderr.write(`[mnueron] plugins active: ${pluginRegistry.loaded.map(p => p.manifest.name).join(', ')}\n`);
|
|
44
|
+
}
|
|
45
|
+
const server = new Server({ name: 'mnueron', version: '0.1.0' }, { capabilities: { tools: {} } });
|
|
46
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
47
|
+
tools: TOOL_DEFINITIONS,
|
|
48
|
+
}));
|
|
49
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
50
|
+
try {
|
|
51
|
+
const result = await handleToolCall(provider, cfg.defaultNamespace, req.params.name, (req.params.arguments ?? {}), pluginRegistry);
|
|
52
|
+
return {
|
|
53
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: 'text', text: `error: ${e?.message ?? String(e)}` }],
|
|
59
|
+
isError: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const transport = new StdioServerTransport();
|
|
64
|
+
await server.connect(transport);
|
|
65
|
+
const shutdown = async () => {
|
|
66
|
+
await deactivatePlugins(pluginRegistry).catch(() => { });
|
|
67
|
+
await provider.close().catch(() => { });
|
|
68
|
+
process.exit(0);
|
|
69
|
+
};
|
|
70
|
+
process.on('SIGINT', shutdown);
|
|
71
|
+
process.on('SIGTERM', shutdown);
|
|
72
|
+
}
|
|
73
|
+
main().catch(e => {
|
|
74
|
+
process.stderr.write(`[mnueron] fatal: ${e?.stack ?? e}\n`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin loader.
|
|
3
|
+
*
|
|
4
|
+
* Discovery: reads ~/.mnueron/config.json for an `enabledPlugins: string[]`
|
|
5
|
+
* list, then dynamically imports each one by npm name. Plugins must follow
|
|
6
|
+
* the naming convention `mnueron-plugin-*` or be scoped under a trusted
|
|
7
|
+
* org (e.g. `@mnueron-community/*`).
|
|
8
|
+
*
|
|
9
|
+
* Loading: validates the default export against the MnueronPlugin shape,
|
|
10
|
+
* builds a sandboxed PluginContext, calls onActivate(), and returns the
|
|
11
|
+
* registered capabilities.
|
|
12
|
+
*
|
|
13
|
+
* The MCP server is responsible for actually invoking the registered
|
|
14
|
+
* processors at save/recall time. This file just collects them.
|
|
15
|
+
*/
|
|
16
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
17
|
+
import { existsSync } from 'node:fs';
|
|
18
|
+
import { join, dirname } from 'node:path';
|
|
19
|
+
import { homedir } from 'node:os';
|
|
20
|
+
const CONFIG_DIR = join(homedir(), '.mnueron');
|
|
21
|
+
const CONFIG_PATH = join(CONFIG_DIR, 'config.json');
|
|
22
|
+
const PLUGINS_STATE_DIR = join(CONFIG_DIR, 'plugins-state');
|
|
23
|
+
const ALLOWED_NAME = /^(?:mnueron-plugin-[a-z0-9-]+|@[a-z0-9-]+\/mnueron-plugin-[a-z0-9-]+)$/;
|
|
24
|
+
export async function loadPlugins(provider) {
|
|
25
|
+
const cfg = await readConfig();
|
|
26
|
+
const registry = {
|
|
27
|
+
processors: [],
|
|
28
|
+
sources: [],
|
|
29
|
+
exporters: [],
|
|
30
|
+
embedders: [],
|
|
31
|
+
loaded: [],
|
|
32
|
+
};
|
|
33
|
+
for (const name of cfg.enabledPlugins ?? []) {
|
|
34
|
+
if (!ALLOWED_NAME.test(name)) {
|
|
35
|
+
console.warn(`[plugins] refusing to load "${name}": doesn't match allowed naming convention`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const loaded = await loadOne(name, provider, cfg.pluginConfig?.[name] ?? {});
|
|
40
|
+
if (loaded) {
|
|
41
|
+
registry.processors.push(...(loaded.manifest.processors ?? []));
|
|
42
|
+
registry.sources.push(...(loaded.manifest.sources ?? []));
|
|
43
|
+
registry.exporters.push(...(loaded.manifest.exporters ?? []));
|
|
44
|
+
registry.embedders.push(...(loaded.manifest.embedders ?? []));
|
|
45
|
+
registry.loaded.push(loaded);
|
|
46
|
+
console.log(`[plugins] activated ${name}@${loaded.manifest.version}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
console.warn(`[plugins] failed to load ${name}: ${e?.message ?? e}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return registry;
|
|
54
|
+
}
|
|
55
|
+
async function loadOne(name, provider, pluginConfig) {
|
|
56
|
+
// Dynamic import — plugin must be installed in this Node's resolution path.
|
|
57
|
+
const mod = await import(name);
|
|
58
|
+
const manifest = mod.default ?? mod.plugin ?? mod;
|
|
59
|
+
if (!manifest || typeof manifest !== 'object' || !manifest.name) {
|
|
60
|
+
throw new Error('plugin does not export a valid manifest');
|
|
61
|
+
}
|
|
62
|
+
if (manifest.name !== name && manifest.name !== name.replace(/^@[^/]+\//, '')) {
|
|
63
|
+
throw new Error(`manifest name "${manifest.name}" does not match package name "${name}"`);
|
|
64
|
+
}
|
|
65
|
+
const context = {
|
|
66
|
+
provider,
|
|
67
|
+
config: pluginConfig,
|
|
68
|
+
storage: makePluginStorage(name),
|
|
69
|
+
logger: makePluginLogger(name),
|
|
70
|
+
};
|
|
71
|
+
if (manifest.onInstall) {
|
|
72
|
+
const installed = await context.storage.get('_installed');
|
|
73
|
+
if (!installed) {
|
|
74
|
+
await manifest.onInstall(context);
|
|
75
|
+
await context.storage.set('_installed', true);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (manifest.onActivate)
|
|
79
|
+
await manifest.onActivate(context);
|
|
80
|
+
return { manifest, context };
|
|
81
|
+
}
|
|
82
|
+
export async function deactivatePlugins(registry) {
|
|
83
|
+
for (const { manifest, context } of registry.loaded) {
|
|
84
|
+
try {
|
|
85
|
+
await manifest.onDeactivate?.(context);
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
console.warn(`[plugins] deactivate of ${manifest.name} failed: ${e?.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Helpers
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
async function readConfig() {
|
|
96
|
+
if (!existsSync(CONFIG_PATH))
|
|
97
|
+
return {};
|
|
98
|
+
try {
|
|
99
|
+
return JSON.parse(await readFile(CONFIG_PATH, 'utf8'));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function makePluginStorage(name) {
|
|
106
|
+
const dir = join(PLUGINS_STATE_DIR, sanitize(name));
|
|
107
|
+
return {
|
|
108
|
+
async get(key) {
|
|
109
|
+
const path = join(dir, sanitize(key) + '.json');
|
|
110
|
+
if (!existsSync(path))
|
|
111
|
+
return null;
|
|
112
|
+
try {
|
|
113
|
+
return JSON.parse(await readFile(path, 'utf8'));
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
async set(key, value) {
|
|
120
|
+
const path = join(dir, sanitize(key) + '.json');
|
|
121
|
+
await mkdir(dirname(path), { recursive: true });
|
|
122
|
+
await writeFile(path, JSON.stringify(value));
|
|
123
|
+
},
|
|
124
|
+
async delete(key) {
|
|
125
|
+
const path = join(dir, sanitize(key) + '.json');
|
|
126
|
+
if (existsSync(path)) {
|
|
127
|
+
const { unlink } = await import('node:fs/promises');
|
|
128
|
+
await unlink(path);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
async list() {
|
|
132
|
+
if (!existsSync(dir))
|
|
133
|
+
return [];
|
|
134
|
+
const { readdir } = await import('node:fs/promises');
|
|
135
|
+
const files = await readdir(dir);
|
|
136
|
+
return files.filter(f => f.endsWith('.json')).map(f => f.replace(/\.json$/, ''));
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function makePluginLogger(name) {
|
|
141
|
+
const prefix = `[plugin:${name}]`;
|
|
142
|
+
return {
|
|
143
|
+
debug: (...a) => console.debug(prefix, ...a),
|
|
144
|
+
info: (...a) => console.log(prefix, ...a),
|
|
145
|
+
warn: (...a) => console.warn(prefix, ...a),
|
|
146
|
+
error: (...a) => console.error(prefix, ...a),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function sanitize(s) {
|
|
150
|
+
return s.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
151
|
+
}
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// Public CLI helpers — used by `mnueron plugin add/remove/list`
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
export async function listEnabledPlugins() {
|
|
156
|
+
return (await readConfig()).enabledPlugins ?? [];
|
|
157
|
+
}
|
|
158
|
+
export async function enablePlugin(name) {
|
|
159
|
+
if (!ALLOWED_NAME.test(name)) {
|
|
160
|
+
throw new Error(`plugin name "${name}" must match mnueron-plugin-* or @scope/mnueron-plugin-*`);
|
|
161
|
+
}
|
|
162
|
+
const cfg = await readConfig();
|
|
163
|
+
const enabled = new Set(cfg.enabledPlugins ?? []);
|
|
164
|
+
enabled.add(name);
|
|
165
|
+
cfg.enabledPlugins = Array.from(enabled);
|
|
166
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
167
|
+
await writeFile(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
168
|
+
}
|
|
169
|
+
export async function disablePlugin(name) {
|
|
170
|
+
const cfg = await readConfig();
|
|
171
|
+
cfg.enabledPlugins = (cfg.enabledPlugins ?? []).filter(n => n !== name);
|
|
172
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
173
|
+
await writeFile(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MNUERON plugin system — public types.
|
|
3
|
+
*
|
|
4
|
+
* Third-party plugins implement these interfaces and publish as npm
|
|
5
|
+
* packages prefixed with `mnueron-plugin-` (e.g. `mnueron-plugin-github-issues`).
|
|
6
|
+
*
|
|
7
|
+
* Plugins extend MNUERON in five ways:
|
|
8
|
+
*
|
|
9
|
+
* 1. PROCESSORS — transform memories on save or recall (PII redaction,
|
|
10
|
+
* translation, sentiment tagging, etc.)
|
|
11
|
+
* 2. SOURCES — pull memories in from external systems (GitHub issues,
|
|
12
|
+
* Slack mentions, Linear tasks, calendar events)
|
|
13
|
+
* 3. EXPORTERS — push memories out to external systems (daily digest
|
|
14
|
+
* email, Notion sync, Slack bot updates)
|
|
15
|
+
* 4. DETECTORS — add support for new AI dev tools (Aider, Goose, Zed,
|
|
16
|
+
* custom in-house tools)
|
|
17
|
+
* 5. EMBEDDERS — alternative embedding providers (local ONNX, Cohere,
|
|
18
|
+
* Voyage, self-hosted)
|
|
19
|
+
*
|
|
20
|
+
* A plugin can implement any combination. The simplest plugin implements
|
|
21
|
+
* one hook and is ~20 lines of code.
|
|
22
|
+
*/
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
|