eon-memory 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/eon.js +32 -0
- package/package.json +21 -0
- package/src/init.js +215 -0
- package/src/status.js +76 -0
- package/src/test-connection.js +105 -0
package/bin/eon.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const args = process.argv.slice(2);
|
|
4
|
+
const command = args[0];
|
|
5
|
+
|
|
6
|
+
if (command === "init") {
|
|
7
|
+
require("../src/init.js");
|
|
8
|
+
} else if (command === "status") {
|
|
9
|
+
require("../src/status.js");
|
|
10
|
+
} else if (command === "test") {
|
|
11
|
+
require("../src/test-connection.js");
|
|
12
|
+
} else if (command === "--help" || command === "-h" || !command) {
|
|
13
|
+
console.log(`
|
|
14
|
+
eon-memory - Persistent AI Memory System
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
npx eon-memory init Set up EON Memory for this project
|
|
18
|
+
npx eon-memory status Check connection status
|
|
19
|
+
npx eon-memory test Test MCP connectivity
|
|
20
|
+
|
|
21
|
+
Setup:
|
|
22
|
+
1. Register at https://app.ai-developer.ch
|
|
23
|
+
2. Create an API key in Settings
|
|
24
|
+
3. Run: npx eon-memory init
|
|
25
|
+
|
|
26
|
+
Docs: https://app.ai-developer.ch/capabilities
|
|
27
|
+
`);
|
|
28
|
+
} else {
|
|
29
|
+
console.error(`Unknown command: ${command}`);
|
|
30
|
+
console.log("Run 'npx eon-memory --help' for usage.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eon-memory",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "EON Memory - Persistent AI memory system. Connect Claude Code, Cursor, or VS Code to your memory.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"eon-memory": "./bin/eon.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": ["mcp", "memory", "ai", "claude", "cursor", "context"],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/vasic-solutions/eon-memory"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"bin/",
|
|
19
|
+
"src/"
|
|
20
|
+
]
|
|
21
|
+
}
|
package/src/init.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* eon-memory init
|
|
5
|
+
*
|
|
6
|
+
* Sets up EON Memory for the current project:
|
|
7
|
+
* 1. Prompts for API key
|
|
8
|
+
* 2. Validates against the server
|
|
9
|
+
* 3. Adds MCP config to Claude Code settings
|
|
10
|
+
* 4. Generates CLAUDE.md in the project
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require("fs");
|
|
14
|
+
const path = require("path");
|
|
15
|
+
const readline = require("readline");
|
|
16
|
+
const https = require("https");
|
|
17
|
+
const os = require("os");
|
|
18
|
+
|
|
19
|
+
const MCP_URL = "https://mcp.ai-developer.ch/mcp";
|
|
20
|
+
const API_BASE = "https://app.ai-developer.ch";
|
|
21
|
+
const INIT_ENDPOINT = "https://app.ai-developer.ch/api/proxy/cli/init";
|
|
22
|
+
const CLAUDE_MD_ENDPOINT = "https://app.ai-developer.ch/api/proxy/cli/claude-md";
|
|
23
|
+
|
|
24
|
+
function ask(question) {
|
|
25
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
rl.question(question, (answer) => {
|
|
28
|
+
rl.close();
|
|
29
|
+
resolve(answer.trim());
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function httpPost(url, body, headers = {}) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const parsed = new URL(url);
|
|
37
|
+
const data = JSON.stringify(body);
|
|
38
|
+
const req = https.request(
|
|
39
|
+
{
|
|
40
|
+
hostname: parsed.hostname,
|
|
41
|
+
port: 443,
|
|
42
|
+
path: parsed.pathname,
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: {
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
"Content-Length": Buffer.byteLength(data),
|
|
47
|
+
...headers,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
(res) => {
|
|
51
|
+
let body = "";
|
|
52
|
+
res.on("data", (chunk) => (body += chunk));
|
|
53
|
+
res.on("end", () => {
|
|
54
|
+
try {
|
|
55
|
+
resolve({ status: res.statusCode, data: JSON.parse(body) });
|
|
56
|
+
} catch {
|
|
57
|
+
resolve({ status: res.statusCode, data: body });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
req.on("error", reject);
|
|
63
|
+
req.write(data);
|
|
64
|
+
req.end();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function httpGet(url, headers = {}) {
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
const parsed = new URL(url);
|
|
71
|
+
const req = https.request(
|
|
72
|
+
{
|
|
73
|
+
hostname: parsed.hostname,
|
|
74
|
+
port: 443,
|
|
75
|
+
path: parsed.pathname,
|
|
76
|
+
method: "GET",
|
|
77
|
+
headers,
|
|
78
|
+
},
|
|
79
|
+
(res) => {
|
|
80
|
+
let body = "";
|
|
81
|
+
res.on("data", (chunk) => (body += chunk));
|
|
82
|
+
res.on("end", () => {
|
|
83
|
+
try {
|
|
84
|
+
resolve({ status: res.statusCode, data: JSON.parse(body) });
|
|
85
|
+
} catch {
|
|
86
|
+
resolve({ status: res.statusCode, data: body });
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
req.on("error", reject);
|
|
92
|
+
req.end();
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function addToClaudeConfig(apiKey) {
|
|
97
|
+
// Try Claude Code's config locations
|
|
98
|
+
const configPaths = [
|
|
99
|
+
// Project-level (preferred)
|
|
100
|
+
path.join(process.cwd(), ".mcp.json"),
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
const mcpEntry = {
|
|
104
|
+
"eon-memory": {
|
|
105
|
+
type: "streamable-http",
|
|
106
|
+
url: MCP_URL,
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: `Bearer ${apiKey}`,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// Write to .mcp.json in project root (Claude Code auto-discovers this)
|
|
114
|
+
const mcpConfigPath = configPaths[0];
|
|
115
|
+
let existing = {};
|
|
116
|
+
if (fs.existsSync(mcpConfigPath)) {
|
|
117
|
+
try {
|
|
118
|
+
existing = JSON.parse(fs.readFileSync(mcpConfigPath, "utf-8"));
|
|
119
|
+
} catch {
|
|
120
|
+
existing = {};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!existing.mcpServers) existing.mcpServers = {};
|
|
125
|
+
existing.mcpServers["eon-memory"] = mcpEntry["eon-memory"];
|
|
126
|
+
|
|
127
|
+
fs.writeFileSync(mcpConfigPath, JSON.stringify(existing, null, 2) + "\n");
|
|
128
|
+
return mcpConfigPath;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function writeClaudeMd(content) {
|
|
132
|
+
const claudeMdPath = path.join(process.cwd(), "CLAUDE.md");
|
|
133
|
+
|
|
134
|
+
// Don't overwrite existing CLAUDE.md, append instead
|
|
135
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
136
|
+
const existing = fs.readFileSync(claudeMdPath, "utf-8");
|
|
137
|
+
if (existing.includes("EON Memory")) {
|
|
138
|
+
console.log(" CLAUDE.md already contains EON Memory config - skipping.");
|
|
139
|
+
return claudeMdPath;
|
|
140
|
+
}
|
|
141
|
+
fs.appendFileSync(claudeMdPath, "\n\n" + content);
|
|
142
|
+
console.log(" Appended EON Memory section to existing CLAUDE.md");
|
|
143
|
+
} else {
|
|
144
|
+
fs.writeFileSync(claudeMdPath, content);
|
|
145
|
+
console.log(" Created CLAUDE.md with EON Memory instructions");
|
|
146
|
+
}
|
|
147
|
+
return claudeMdPath;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function main() {
|
|
151
|
+
console.log("\n EON Memory - Setup\n");
|
|
152
|
+
console.log(" This will configure EON Memory for your project.\n");
|
|
153
|
+
|
|
154
|
+
// Step 1: Get API key
|
|
155
|
+
const apiKey = await ask(" Enter your API key (from app.ai-developer.ch/settings): ");
|
|
156
|
+
|
|
157
|
+
if (!apiKey) {
|
|
158
|
+
console.error("\n Error: API key is required.");
|
|
159
|
+
console.log(" Get one at: https://app.ai-developer.ch/settings\n");
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Step 2: Validate API key
|
|
164
|
+
console.log("\n Validating API key...");
|
|
165
|
+
try {
|
|
166
|
+
const res = await httpPost(INIT_ENDPOINT, { api_key: apiKey });
|
|
167
|
+
|
|
168
|
+
if (res.status !== 200) {
|
|
169
|
+
console.error(" Error: Invalid API key.");
|
|
170
|
+
console.log(" Check your key at: https://app.ai-developer.ch/settings\n");
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const info = res.data;
|
|
175
|
+
console.log(` Connected as: ${info.name || info.tenant_id} (${info.tier} plan)`);
|
|
176
|
+
console.log(` Projects: ${(info.projects || []).length}`);
|
|
177
|
+
console.log(` Tools: ${info.tools_count}`);
|
|
178
|
+
} catch (err) {
|
|
179
|
+
console.error(` Error: Could not reach server - ${err.message}`);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Step 3: Write MCP config
|
|
184
|
+
console.log("\n Configuring MCP...");
|
|
185
|
+
const configPath = addToClaudeConfig(apiKey);
|
|
186
|
+
console.log(` Wrote: ${path.relative(process.cwd(), configPath)}`);
|
|
187
|
+
|
|
188
|
+
// Step 4: Fetch and write CLAUDE.md
|
|
189
|
+
console.log("\n Generating CLAUDE.md...");
|
|
190
|
+
try {
|
|
191
|
+
const res = await httpGet(CLAUDE_MD_ENDPOINT, { "X-API-Key": apiKey });
|
|
192
|
+
if (res.status === 200 && res.data.content) {
|
|
193
|
+
const claudeMdPath = writeClaudeMd(res.data.content);
|
|
194
|
+
console.log(` Wrote: ${path.relative(process.cwd(), claudeMdPath)}`);
|
|
195
|
+
} else {
|
|
196
|
+
console.log(" Warning: Could not fetch CLAUDE.md template (non-critical).");
|
|
197
|
+
}
|
|
198
|
+
} catch {
|
|
199
|
+
console.log(" Warning: Could not fetch CLAUDE.md template (non-critical).");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Done
|
|
203
|
+
console.log("\n Setup complete!\n");
|
|
204
|
+
console.log(" Next steps:");
|
|
205
|
+
console.log(" 1. Open this project in Claude Code or Cursor");
|
|
206
|
+
console.log(" 2. The EON Memory tools will be available automatically");
|
|
207
|
+
console.log(" 3. Try: \"Search my memories for...\" or \"Create a memory about...\"\n");
|
|
208
|
+
console.log(` Dashboard: ${API_BASE}`);
|
|
209
|
+
console.log(` Run 'npx eon-memory status' to check connection.\n`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
main().catch((err) => {
|
|
213
|
+
console.error(`\n Error: ${err.message}\n`);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
});
|
package/src/status.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* eon-memory status
|
|
5
|
+
*
|
|
6
|
+
* Checks if EON Memory is configured and connected.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const https = require("https");
|
|
12
|
+
|
|
13
|
+
function checkMcpConfig() {
|
|
14
|
+
const mcpPath = path.join(process.cwd(), ".mcp.json");
|
|
15
|
+
if (!fs.existsSync(mcpPath)) return null;
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const config = JSON.parse(fs.readFileSync(mcpPath, "utf-8"));
|
|
19
|
+
return config.mcpServers?.["eon-memory"] || null;
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function checkHealth() {
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
const req = https.get("https://mcp.ai-developer.ch/health", (res) => {
|
|
28
|
+
let body = "";
|
|
29
|
+
res.on("data", (chunk) => (body += chunk));
|
|
30
|
+
res.on("end", () => {
|
|
31
|
+
try {
|
|
32
|
+
resolve({ ok: res.statusCode === 200, data: JSON.parse(body) });
|
|
33
|
+
} catch {
|
|
34
|
+
resolve({ ok: false });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
req.on("error", () => resolve({ ok: false }));
|
|
39
|
+
req.setTimeout(5000, () => { req.destroy(); resolve({ ok: false }); });
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function main() {
|
|
44
|
+
console.log("\n EON Memory - Status\n");
|
|
45
|
+
|
|
46
|
+
// Check config
|
|
47
|
+
const config = checkMcpConfig();
|
|
48
|
+
if (config) {
|
|
49
|
+
console.log(" MCP Config: found (.mcp.json)");
|
|
50
|
+
console.log(` Server URL: ${config.url || "not set"}`);
|
|
51
|
+
console.log(` Auth: ${config.headers?.Authorization ? "configured" : "missing"}`);
|
|
52
|
+
} else {
|
|
53
|
+
console.log(" MCP Config: not found");
|
|
54
|
+
console.log(" Run 'npx eon-memory init' to set up.\n");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check CLAUDE.md
|
|
59
|
+
const claudeMd = path.join(process.cwd(), "CLAUDE.md");
|
|
60
|
+
console.log(` CLAUDE.md: ${fs.existsSync(claudeMd) ? "found" : "not found"}`);
|
|
61
|
+
|
|
62
|
+
// Check server health
|
|
63
|
+
console.log("\n Checking server...");
|
|
64
|
+
const health = await checkHealth();
|
|
65
|
+
if (health.ok) {
|
|
66
|
+
console.log(` Server: online`);
|
|
67
|
+
console.log(` Tools: ${health.data?.tools || "?"}`);
|
|
68
|
+
console.log(` Version: ${health.data?.version || "?"}`);
|
|
69
|
+
} else {
|
|
70
|
+
console.log(" Server: unreachable");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.log("");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
main();
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* eon-memory test
|
|
5
|
+
*
|
|
6
|
+
* Tests the MCP connection with the configured API key.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const https = require("https");
|
|
12
|
+
|
|
13
|
+
function getApiKey() {
|
|
14
|
+
// Try .mcp.json
|
|
15
|
+
const mcpPath = path.join(process.cwd(), ".mcp.json");
|
|
16
|
+
if (fs.existsSync(mcpPath)) {
|
|
17
|
+
try {
|
|
18
|
+
const config = JSON.parse(fs.readFileSync(mcpPath, "utf-8"));
|
|
19
|
+
const auth = config.mcpServers?.["eon-memory"]?.headers?.Authorization;
|
|
20
|
+
if (auth) return auth.replace("Bearer ", "");
|
|
21
|
+
} catch {}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Try env
|
|
25
|
+
if (process.env.EON_API_KEY) return process.env.EON_API_KEY;
|
|
26
|
+
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function httpPost(url, body, headers = {}) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const parsed = new URL(url);
|
|
33
|
+
const data = JSON.stringify(body);
|
|
34
|
+
const req = https.request(
|
|
35
|
+
{
|
|
36
|
+
hostname: parsed.hostname,
|
|
37
|
+
port: 443,
|
|
38
|
+
path: parsed.pathname,
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: {
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
"Content-Length": Buffer.byteLength(data),
|
|
43
|
+
...headers,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
(res) => {
|
|
47
|
+
let body = "";
|
|
48
|
+
res.on("data", (chunk) => (body += chunk));
|
|
49
|
+
res.on("end", () => {
|
|
50
|
+
try {
|
|
51
|
+
resolve({ status: res.statusCode, data: JSON.parse(body) });
|
|
52
|
+
} catch {
|
|
53
|
+
resolve({ status: res.statusCode, data: body });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
req.on("error", reject);
|
|
59
|
+
req.write(data);
|
|
60
|
+
req.end();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function main() {
|
|
65
|
+
console.log("\n EON Memory - Connection Test\n");
|
|
66
|
+
|
|
67
|
+
const apiKey = getApiKey();
|
|
68
|
+
if (!apiKey) {
|
|
69
|
+
console.log(" No API key found.");
|
|
70
|
+
console.log(" Run 'npx eon-memory init' first.\n");
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(" Testing connection...");
|
|
75
|
+
const start = Date.now();
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const res = await httpPost("https://app.ai-developer.ch/api/proxy/cli/test", {
|
|
79
|
+
api_key: apiKey,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const latency = Date.now() - start;
|
|
83
|
+
|
|
84
|
+
if (res.status === 200) {
|
|
85
|
+
const d = res.data;
|
|
86
|
+
console.log(` Status: ${d.status}`);
|
|
87
|
+
console.log(` Tenant: ${d.tenant_id}`);
|
|
88
|
+
console.log(` Plan: ${d.tier}`);
|
|
89
|
+
console.log(` Memories: ${d.memory_count}`);
|
|
90
|
+
console.log(` Tools: ${d.tools_available}`);
|
|
91
|
+
console.log(` Latency: ${latency}ms`);
|
|
92
|
+
console.log("\n Connection successful!\n");
|
|
93
|
+
} else {
|
|
94
|
+
console.log(` Error: ${res.data?.detail || "Authentication failed"}`);
|
|
95
|
+
console.log(" Check your API key in .mcp.json\n");
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
console.log(` Error: ${err.message}`);
|
|
100
|
+
console.log(" Could not reach server.\n");
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
main();
|