openmemory-plus 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.
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/index.js ADDED
@@ -0,0 +1,630 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+ import chalk5 from "chalk";
6
+
7
+ // src/commands/install.ts
8
+ import chalk from "chalk";
9
+ import ora from "ora";
10
+ import inquirer from "inquirer";
11
+ import { exec as exec2 } from "child_process";
12
+ import { promisify as promisify2 } from "util";
13
+
14
+ // src/lib/detector.ts
15
+ import { exec } from "child_process";
16
+ import { promisify } from "util";
17
+ import which from "which";
18
+ var execAsync = promisify(exec);
19
+ async function checkCommand(cmd) {
20
+ try {
21
+ return await which(cmd);
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+ async function getVersion(cmd, args = "--version") {
27
+ try {
28
+ const { stdout } = await execAsync(`${cmd} ${args}`);
29
+ return stdout.trim().split("\n")[0];
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+ async function checkDocker() {
35
+ const path = await checkCommand("docker");
36
+ if (!path) {
37
+ return { name: "Docker", installed: false, error: "\u672A\u5B89\u88C5" };
38
+ }
39
+ const version = await getVersion("docker", "--version");
40
+ try {
41
+ await execAsync("docker info");
42
+ return { name: "Docker", installed: true, version: version || void 0, running: true };
43
+ } catch {
44
+ return { name: "Docker", installed: true, version: version || void 0, running: false, error: "Docker \u5B88\u62A4\u8FDB\u7A0B\u672A\u8FD0\u884C" };
45
+ }
46
+ }
47
+ async function checkOllama() {
48
+ const path = await checkCommand("ollama");
49
+ if (!path) {
50
+ return { name: "Ollama", installed: false, error: "\u672A\u5B89\u88C5" };
51
+ }
52
+ const version = await getVersion("ollama", "--version");
53
+ try {
54
+ await execAsync("curl -s http://localhost:11434/api/tags");
55
+ return { name: "Ollama", installed: true, version: version || void 0, running: true };
56
+ } catch {
57
+ return { name: "Ollama", installed: true, version: version || void 0, running: false, error: "Ollama \u670D\u52A1\u672A\u8FD0\u884C" };
58
+ }
59
+ }
60
+ async function checkQdrant() {
61
+ try {
62
+ const { stdout } = await execAsync("curl -s http://localhost:6333/collections");
63
+ const data = JSON.parse(stdout);
64
+ return { name: "Qdrant", installed: true, running: true, version: "container" };
65
+ } catch {
66
+ try {
67
+ const { stdout } = await execAsync('docker ps -a --filter name=qdrant --format "{{.Status}}"');
68
+ if (stdout.trim()) {
69
+ return { name: "Qdrant", installed: true, running: false, error: "\u5BB9\u5668\u5B58\u5728\u4F46\u672A\u8FD0\u884C" };
70
+ }
71
+ } catch {
72
+ }
73
+ return { name: "Qdrant", installed: false, error: "\u5BB9\u5668\u672A\u521B\u5EFA" };
74
+ }
75
+ }
76
+ async function checkOpenMemory() {
77
+ try {
78
+ await execAsync("curl -s http://localhost:8765/health || curl -s http://localhost:8765");
79
+ return { name: "OpenMemory MCP", installed: true, running: true };
80
+ } catch {
81
+ return { name: "OpenMemory MCP", installed: false, running: false, error: "\u670D\u52A1\u672A\u8FD0\u884C" };
82
+ }
83
+ }
84
+ async function checkBgeM3() {
85
+ try {
86
+ const { stdout } = await execAsync("curl -s http://localhost:11434/api/tags");
87
+ const data = JSON.parse(stdout);
88
+ const hasModel = data.models?.some((m) => m.name.includes("bge-m3"));
89
+ if (hasModel) {
90
+ return { name: "BGE-M3", installed: true, running: true };
91
+ }
92
+ return { name: "BGE-M3", installed: false, error: "\u6A21\u578B\u672A\u4E0B\u8F7D" };
93
+ } catch {
94
+ return { name: "BGE-M3", installed: false, error: "Ollama \u672A\u8FD0\u884C\uFF0C\u65E0\u6CD5\u68C0\u6D4B" };
95
+ }
96
+ }
97
+ async function checkAllDependencies() {
98
+ const [docker, ollama, qdrant, openmemory, bgeM3] = await Promise.all([
99
+ checkDocker(),
100
+ checkOllama(),
101
+ checkQdrant(),
102
+ checkOpenMemory(),
103
+ checkBgeM3()
104
+ ]);
105
+ return { docker, ollama, qdrant, openmemory, bgeM3 };
106
+ }
107
+ function isSystemReady(status) {
108
+ return status.docker.installed && status.docker.running && status.ollama.installed && status.ollama.running && status.qdrant.running && status.bgeM3.installed;
109
+ }
110
+
111
+ // src/commands/install.ts
112
+ var execAsync2 = promisify2(exec2);
113
+ async function openUrl(url) {
114
+ const { platform } = process;
115
+ const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
116
+ await execAsync2(`${cmd} ${url}`);
117
+ }
118
+ async function installOllama() {
119
+ const spinner = ora("\u5B89\u88C5 Ollama...").start();
120
+ try {
121
+ await execAsync2("brew install ollama");
122
+ spinner.succeed("Ollama \u5B89\u88C5\u6210\u529F");
123
+ return true;
124
+ } catch {
125
+ spinner.fail("Ollama \u5B89\u88C5\u5931\u8D25");
126
+ console.log(chalk.yellow("\u8BF7\u624B\u52A8\u5B89\u88C5: https://ollama.com/download"));
127
+ return false;
128
+ }
129
+ }
130
+ async function startOllama() {
131
+ const spinner = ora("\u542F\u52A8 Ollama \u670D\u52A1...").start();
132
+ try {
133
+ exec2("ollama serve &");
134
+ await new Promise((r) => setTimeout(r, 2e3));
135
+ spinner.succeed("Ollama \u670D\u52A1\u5DF2\u542F\u52A8");
136
+ return true;
137
+ } catch {
138
+ spinner.fail("Ollama \u542F\u52A8\u5931\u8D25");
139
+ return false;
140
+ }
141
+ }
142
+ async function pullBgeM3() {
143
+ const spinner = ora("\u4E0B\u8F7D BGE-M3 \u6A21\u578B (\u53EF\u80FD\u9700\u8981\u51E0\u5206\u949F)...").start();
144
+ try {
145
+ await execAsync2("ollama pull bge-m3", { timeout: 6e5 });
146
+ spinner.succeed("BGE-M3 \u6A21\u578B\u5DF2\u4E0B\u8F7D");
147
+ return true;
148
+ } catch {
149
+ spinner.fail("BGE-M3 \u4E0B\u8F7D\u5931\u8D25");
150
+ return false;
151
+ }
152
+ }
153
+ async function startQdrant() {
154
+ const spinner = ora("\u542F\u52A8 Qdrant \u5BB9\u5668...").start();
155
+ try {
156
+ await execAsync2("docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant");
157
+ spinner.succeed("Qdrant \u5BB9\u5668\u5DF2\u542F\u52A8");
158
+ return true;
159
+ } catch (e) {
160
+ if (e.message?.includes("already in use")) {
161
+ try {
162
+ await execAsync2("docker start qdrant");
163
+ spinner.succeed("Qdrant \u5BB9\u5668\u5DF2\u542F\u52A8");
164
+ return true;
165
+ } catch {
166
+ }
167
+ }
168
+ spinner.fail("Qdrant \u542F\u52A8\u5931\u8D25");
169
+ return false;
170
+ }
171
+ }
172
+ async function installCommand(options) {
173
+ console.log(chalk.cyan.bold("\n\u{1F9E0} OpenMemory Plus - \u5B89\u88C5\u5411\u5BFC\n"));
174
+ const spinner = ora("\u68C0\u6D4B\u7CFB\u7EDF\u4F9D\u8D56...").start();
175
+ const status = await checkAllDependencies();
176
+ spinner.stop();
177
+ console.log(chalk.bold("\u5F53\u524D\u72B6\u6001:"));
178
+ console.log(` \u{1F433} Docker: ${status.docker.installed ? chalk.green("\u2713") : chalk.red("\u2717")}`);
179
+ console.log(` \u{1F999} Ollama: ${status.ollama.installed ? chalk.green("\u2713") : chalk.red("\u2717")}`);
180
+ console.log(` \u{1F4E6} Qdrant: ${status.qdrant.running ? chalk.green("\u2713") : chalk.red("\u2717")}`);
181
+ console.log(` \u{1F524} BGE-M3: ${status.bgeM3.installed ? chalk.green("\u2713") : chalk.red("\u2717")}`);
182
+ console.log("");
183
+ if (isSystemReady(status)) {
184
+ console.log(chalk.green.bold("\u2705 \u6240\u6709\u4F9D\u8D56\u5DF2\u5C31\u7EEA! \u65E0\u9700\u5B89\u88C5\u3002\n"));
185
+ console.log(chalk.gray("\u8FD0\u884C ") + chalk.cyan("openmemory-plus init") + chalk.gray(" \u521D\u59CB\u5316\u9879\u76EE"));
186
+ return;
187
+ }
188
+ if (!options.yes) {
189
+ const { confirm } = await inquirer.prompt([{
190
+ type: "confirm",
191
+ name: "confirm",
192
+ message: "\u9700\u8981\u5B89\u88C5\u7F3A\u5931\u7684\u4F9D\u8D56\uFF0C\u662F\u5426\u7EE7\u7EED?",
193
+ default: true
194
+ }]);
195
+ if (!confirm) {
196
+ console.log(chalk.yellow("\u5DF2\u53D6\u6D88\u5B89\u88C5"));
197
+ return;
198
+ }
199
+ }
200
+ if (!status.docker.installed && !options.skipDocker) {
201
+ console.log(chalk.yellow("\n\u{1F4E6} Docker \u9700\u8981\u624B\u52A8\u5B89\u88C5"));
202
+ console.log(chalk.gray(" \u8BF7\u8BBF\u95EE https://docker.com/download \u4E0B\u8F7D\u5B89\u88C5"));
203
+ const { openDocker } = await inquirer.prompt([{
204
+ type: "confirm",
205
+ name: "openDocker",
206
+ message: "\u662F\u5426\u6253\u5F00 Docker \u4E0B\u8F7D\u9875\u9762?",
207
+ default: true
208
+ }]);
209
+ if (openDocker) await openUrl("https://docker.com/download");
210
+ await inquirer.prompt([{ type: "input", name: "wait", message: "\u5B89\u88C5\u5B8C\u6210\u540E\u6309 Enter \u7EE7\u7EED..." }]);
211
+ }
212
+ if (!status.ollama.installed && !options.skipOllama) {
213
+ await installOllama();
214
+ }
215
+ if (status.ollama.installed && !status.ollama.running) {
216
+ await startOllama();
217
+ }
218
+ if (!status.bgeM3.installed) {
219
+ await pullBgeM3();
220
+ }
221
+ if (!status.qdrant.running && status.docker.running) {
222
+ await startQdrant();
223
+ }
224
+ console.log(chalk.green.bold("\n\u2705 \u5B89\u88C5\u5B8C\u6210!\n"));
225
+ console.log(chalk.gray("\u8FD0\u884C ") + chalk.cyan("openmemory-plus status") + chalk.gray(" \u9A8C\u8BC1\u72B6\u6001"));
226
+ console.log(chalk.gray("\u8FD0\u884C ") + chalk.cyan("openmemory-plus init") + chalk.gray(" \u521D\u59CB\u5316\u9879\u76EE\n"));
227
+ }
228
+
229
+ // src/commands/init.ts
230
+ import chalk2 from "chalk";
231
+ import ora2 from "ora";
232
+ import inquirer2 from "inquirer";
233
+ import { existsSync, mkdirSync, copyFileSync, writeFileSync, readdirSync } from "fs";
234
+ import { join, dirname } from "path";
235
+ import { fileURLToPath } from "url";
236
+ var IDE_CONFIGS = {
237
+ augment: { dir: ".augment", configFile: "AGENTS.md", commandsDir: "commands", skillsDir: "skills", rulesDir: ".rules/memory" },
238
+ claude: { dir: ".", configFile: "CLAUDE.md", commandsDir: ".claude/commands", skillsDir: ".claude/skills", rulesDir: ".rules/memory" },
239
+ cursor: { dir: ".cursor", configFile: ".cursorrules", commandsDir: "commands", skillsDir: "skills", rulesDir: ".rules/memory" },
240
+ gemini: { dir: ".", configFile: "gemini.md", commandsDir: ".gemini/commands", skillsDir: ".gemini/skills", rulesDir: ".rules/memory" },
241
+ common: { dir: ".", configFile: "AGENTS.md", commandsDir: ".agents/commands", skillsDir: ".agents/skills", rulesDir: ".rules/memory" }
242
+ };
243
+ function getTemplatesDir() {
244
+ const __dirname = dirname(fileURLToPath(import.meta.url));
245
+ const possiblePaths = [
246
+ join(__dirname, "..", "templates"),
247
+ // npm 包: dist/../templates
248
+ join(__dirname, "..", "..", "templates"),
249
+ // 开发时 (从 dist/)
250
+ join(__dirname, "..", "..", "..", "templates")
251
+ // 旧路径 (从 src/)
252
+ ];
253
+ for (const p of possiblePaths) {
254
+ if (existsSync(join(p, "shared"))) {
255
+ return p;
256
+ }
257
+ }
258
+ return possiblePaths[0];
259
+ }
260
+ function copyDir(src, dest) {
261
+ if (!existsSync(src)) return;
262
+ mkdirSync(dest, { recursive: true });
263
+ for (const file of readdirSync(src, { withFileTypes: true })) {
264
+ const srcPath = join(src, file.name);
265
+ const destPath = join(dest, file.name);
266
+ if (file.isDirectory()) {
267
+ copyDir(srcPath, destPath);
268
+ } else {
269
+ copyFileSync(srcPath, destPath);
270
+ }
271
+ }
272
+ }
273
+ function generateProjectYaml(projectName) {
274
+ return `# OpenMemory Plus Project Configuration
275
+ # Generated: ${(/* @__PURE__ */ new Date()).toISOString()}
276
+
277
+ project:
278
+ name: "${projectName}"
279
+ version: "1.0.0"
280
+ description: ""
281
+
282
+ memory:
283
+ # \u9879\u76EE\u7EA7\u8BB0\u5FC6\u5B58\u50A8\u4F4D\u7F6E
284
+ project_store: ".memory/"
285
+ # \u7528\u6237\u7EA7\u8BB0\u5FC6 (openmemory MCP)
286
+ user_store: "openmemory"
287
+
288
+ classification:
289
+ # \u9879\u76EE\u7EA7\u4FE1\u606F\u5173\u952E\u8BCD (\u5B58\u5165 .memory/)
290
+ project_keywords:
291
+ - "\u9879\u76EE\u914D\u7F6E"
292
+ - "\u6280\u672F\u51B3\u7B56"
293
+ - "\u90E8\u7F72\u4FE1\u606F"
294
+ - "API \u5BC6\u94A5"
295
+ - "\u67B6\u6784\u8BBE\u8BA1"
296
+ - "\u6570\u636E\u5E93"
297
+ # \u7528\u6237\u7EA7\u4FE1\u606F\u5173\u952E\u8BCD (\u5B58\u5165 openmemory)
298
+ user_keywords:
299
+ - "\u7528\u6237\u504F\u597D"
300
+ - "\u7F16\u7801\u98CE\u683C"
301
+ - "\u6280\u80FD"
302
+ - "\u4E60\u60EF"
303
+ - "\u559C\u6B22"
304
+
305
+ agent:
306
+ # \u5BF9\u8BDD\u7ED3\u675F\u65F6\u81EA\u52A8\u63D0\u53D6\u8BB0\u5FC6
307
+ auto_extract: true
308
+ # \u5BF9\u8BDD\u5F00\u59CB\u65F6\u81EA\u52A8\u641C\u7D22\u4E0A\u4E0B\u6587
309
+ auto_search: true
310
+ # MCP \u4E0D\u53EF\u7528\u65F6\u964D\u7EA7\u5230\u6587\u4EF6\u5B58\u50A8
311
+ fallback_to_file: true
312
+ `;
313
+ }
314
+ async function initCommand(options) {
315
+ console.log(chalk2.cyan.bold("\n\u{1F9E0} OpenMemory Plus - \u9879\u76EE\u521D\u59CB\u5316\n"));
316
+ const spinner = ora2("\u68C0\u6D4B\u7CFB\u7EDF\u4F9D\u8D56...").start();
317
+ const status = await checkAllDependencies();
318
+ spinner.stop();
319
+ if (!isSystemReady(status)) {
320
+ console.log(chalk2.yellow("\u26A0\uFE0F \u7CFB\u7EDF\u4F9D\u8D56\u672A\u5C31\u7EEA"));
321
+ console.log(chalk2.gray("\u5EFA\u8BAE\u5148\u8FD0\u884C ") + chalk2.cyan("openmemory-plus install"));
322
+ if (!options.yes) {
323
+ const { cont } = await inquirer2.prompt([{
324
+ type: "confirm",
325
+ name: "cont",
326
+ message: "\u662F\u5426\u7EE7\u7EED\u521D\u59CB\u5316?",
327
+ default: false
328
+ }]);
329
+ if (!cont) return;
330
+ }
331
+ }
332
+ let ide = options.ide?.toLowerCase();
333
+ if (!ide || !IDE_CONFIGS[ide]) {
334
+ const { selectedIde } = await inquirer2.prompt([{
335
+ type: "list",
336
+ name: "selectedIde",
337
+ message: "\u9009\u62E9 IDE \u7C7B\u578B:",
338
+ choices: [
339
+ { name: "Augment", value: "augment" },
340
+ { name: "Claude Code", value: "claude" },
341
+ { name: "Cursor", value: "cursor" },
342
+ { name: "Gemini", value: "gemini" },
343
+ { name: "\u901A\u7528 (AGENTS.md)", value: "common" }
344
+ ],
345
+ default: "augment"
346
+ }]);
347
+ ide = selectedIde;
348
+ }
349
+ let projectName = options.projectName;
350
+ if (!projectName) {
351
+ const cwd2 = process.cwd();
352
+ const defaultName = cwd2.split("/").pop() || "my-project";
353
+ const { name } = await inquirer2.prompt([{
354
+ type: "input",
355
+ name: "name",
356
+ message: "\u9879\u76EE\u540D\u79F0:",
357
+ default: defaultName
358
+ }]);
359
+ projectName = name;
360
+ }
361
+ const config = IDE_CONFIGS[ide];
362
+ const cwd = process.cwd();
363
+ console.log(chalk2.bold("\n\u{1F4C1} \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6..."));
364
+ const memoryDir = join(cwd, ".memory");
365
+ if (!existsSync(memoryDir)) {
366
+ mkdirSync(memoryDir, { recursive: true });
367
+ console.log(chalk2.green(" \u2713 \u521B\u5EFA .memory/"));
368
+ }
369
+ const projectYaml = join(memoryDir, "project.yaml");
370
+ writeFileSync(projectYaml, generateProjectYaml(projectName));
371
+ console.log(chalk2.green(" \u2713 \u521B\u5EFA .memory/project.yaml"));
372
+ const templatesDir = getTemplatesDir();
373
+ const sharedTemplates = join(templatesDir, "shared");
374
+ const ideTemplates = join(templatesDir, ide === "common" ? "common" : ide);
375
+ const commandsDir = join(cwd, config.dir, config.commandsDir);
376
+ mkdirSync(commandsDir, { recursive: true });
377
+ copyDir(join(sharedTemplates, "commands"), commandsDir);
378
+ console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.commandsDir}/ (6 \u4E2A\u547D\u4EE4)`));
379
+ const skillsDir = join(cwd, config.dir, config.skillsDir);
380
+ mkdirSync(skillsDir, { recursive: true });
381
+ copyDir(join(sharedTemplates, "skills"), skillsDir);
382
+ console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.skillsDir}/ (memory-extraction)`));
383
+ const rulesDir = join(cwd, config.rulesDir);
384
+ mkdirSync(rulesDir, { recursive: true });
385
+ copyDir(join(sharedTemplates, "rules"), rulesDir);
386
+ console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.rulesDir}/ (classification.md)`));
387
+ if (existsSync(ideTemplates)) {
388
+ copyDir(ideTemplates, join(cwd, config.dir));
389
+ console.log(chalk2.green(` \u2713 \u590D\u5236 IDE \u914D\u7F6E\u6587\u4EF6`));
390
+ }
391
+ if (options.generateMcp) {
392
+ generateMcpConfig(ide);
393
+ }
394
+ console.log(chalk2.green.bold("\n\u{1F389} OpenMemory Plus \u521D\u59CB\u5316\u5B8C\u6210!\n"));
395
+ console.log(chalk2.gray("\u4F7F\u7528 ") + chalk2.cyan("/memory") + chalk2.gray(" \u67E5\u770B\u8BB0\u5FC6\u72B6\u6001"));
396
+ console.log(chalk2.gray("\u4F7F\u7528 ") + chalk2.cyan("/mem search <query>") + chalk2.gray(" \u641C\u7D22\u8BB0\u5FC6"));
397
+ if (!options.generateMcp) {
398
+ console.log(chalk2.gray("\n\u{1F4A1} \u63D0\u793A: \u8FD0\u884C ") + chalk2.cyan("openmemory-plus init --generate-mcp") + chalk2.gray(" \u751F\u6210 MCP \u914D\u7F6E\n"));
399
+ }
400
+ }
401
+ function generateMcpConfig(ide) {
402
+ console.log(chalk2.bold("\n\u{1F4CB} MCP \u914D\u7F6E (\u590D\u5236\u5230 IDE \u914D\u7F6E\u6587\u4EF6):"));
403
+ const mcpConfig = {
404
+ openmemory: {
405
+ command: "npx",
406
+ args: ["-y", "openmemory-mcp"],
407
+ env: {
408
+ OPENAI_API_KEY: "your-openai-key-or-use-ollama",
409
+ MEM0_EMBEDDING_MODEL: "bge-m3",
410
+ MEM0_EMBEDDING_PROVIDER: "ollama",
411
+ QDRANT_HOST: "localhost",
412
+ QDRANT_PORT: "6333"
413
+ }
414
+ }
415
+ };
416
+ console.log(chalk2.cyan("\n```json"));
417
+ console.log(JSON.stringify(mcpConfig, null, 2));
418
+ console.log(chalk2.cyan("```\n"));
419
+ const configPaths = {
420
+ augment: "~/.augment/settings.json (mcpServers \u5B57\u6BB5)",
421
+ claude: "~/.config/claude/mcp.json",
422
+ cursor: "~/.cursor/mcp.json",
423
+ gemini: "~/.config/gemini/mcp.json",
424
+ common: "\u53C2\u8003\u5404 IDE \u7684 MCP \u914D\u7F6E\u6587\u6863"
425
+ };
426
+ console.log(chalk2.gray(`\u914D\u7F6E\u6587\u4EF6\u4F4D\u7F6E: ${configPaths[ide] || configPaths.common}`));
427
+ }
428
+
429
+ // src/commands/status.ts
430
+ import chalk3 from "chalk";
431
+ import ora3 from "ora";
432
+ function formatStatus(dep) {
433
+ if (!dep.installed) {
434
+ return chalk3.red("\u2717 \u672A\u5B89\u88C5");
435
+ }
436
+ if (dep.running === false) {
437
+ return chalk3.yellow("\u26A0 \u5DF2\u5B89\u88C5\u4F46\u672A\u8FD0\u884C");
438
+ }
439
+ if (dep.running === true) {
440
+ const ver = dep.version ? chalk3.gray(` (${dep.version})`) : "";
441
+ return chalk3.green("\u2713 \u8FD0\u884C\u4E2D") + ver;
442
+ }
443
+ return chalk3.green("\u2713 \u5DF2\u5B89\u88C5");
444
+ }
445
+ function printStatusTable(status) {
446
+ console.log("\n" + chalk3.bold("\u4F9D\u8D56\u68C0\u6D4B\u7ED3\u679C:"));
447
+ console.log("");
448
+ const deps = [
449
+ { ...status.docker, icon: "\u{1F433}" },
450
+ { ...status.ollama, icon: "\u{1F999}" },
451
+ { ...status.qdrant, icon: "\u{1F4E6}" },
452
+ { ...status.openmemory, icon: "\u{1F9E0}" },
453
+ { ...status.bgeM3, icon: "\u{1F524}" }
454
+ ];
455
+ for (const dep of deps) {
456
+ const statusStr = formatStatus(dep);
457
+ const errorStr = dep.error && !dep.installed ? chalk3.gray(` - ${dep.error}`) : "";
458
+ console.log(` ${dep.icon} ${dep.name.padEnd(16)} ${statusStr}${errorStr}`);
459
+ }
460
+ console.log("");
461
+ }
462
+ async function statusCommand() {
463
+ console.log(chalk3.cyan.bold("\n\u{1F9E0} OpenMemory Plus - \u7CFB\u7EDF\u72B6\u6001\n"));
464
+ const spinner = ora3("\u68C0\u6D4B\u7CFB\u7EDF\u4F9D\u8D56...").start();
465
+ try {
466
+ const status = await checkAllDependencies();
467
+ spinner.stop();
468
+ printStatusTable(status);
469
+ if (isSystemReady(status)) {
470
+ console.log(chalk3.green.bold("\u2705 \u7CFB\u7EDF\u5C31\u7EEA! OpenMemory Plus \u53EF\u6B63\u5E38\u4F7F\u7528\u3002\n"));
471
+ console.log(chalk3.gray("\u63D0\u793A: \u4F7F\u7528 /memory \u547D\u4EE4\u67E5\u770B\u8BB0\u5FC6\u72B6\u6001"));
472
+ } else {
473
+ console.log(chalk3.yellow.bold("\u26A0\uFE0F \u7CFB\u7EDF\u672A\u5C31\u7EEA\uFF0C\u90E8\u5206\u4F9D\u8D56\u7F3A\u5931\u6216\u672A\u8FD0\u884C\u3002\n"));
474
+ console.log(chalk3.gray("\u8FD0\u884C ") + chalk3.cyan("openmemory-plus install") + chalk3.gray(" \u5B89\u88C5\u7F3A\u5931\u4F9D\u8D56"));
475
+ console.log(chalk3.gray("\u8FD0\u884C ") + chalk3.cyan("openmemory-plus doctor") + chalk3.gray(" \u8BCA\u65AD\u5E76\u4FEE\u590D\u95EE\u9898"));
476
+ }
477
+ } catch (error) {
478
+ spinner.fail("\u68C0\u6D4B\u5931\u8D25");
479
+ console.error(chalk3.red("\u9519\u8BEF:"), error);
480
+ process.exit(1);
481
+ }
482
+ }
483
+
484
+ // src/commands/doctor.ts
485
+ import chalk4 from "chalk";
486
+ import ora4 from "ora";
487
+ import { exec as exec3 } from "child_process";
488
+ import { promisify as promisify3 } from "util";
489
+ var execAsync3 = promisify3(exec3);
490
+ function diagnoseIssues(status) {
491
+ const issues = [];
492
+ if (!status.docker.installed) {
493
+ issues.push({
494
+ name: "Docker \u672A\u5B89\u88C5",
495
+ description: "\u9700\u8981\u624B\u52A8\u5B89\u88C5 Docker Desktop",
496
+ severity: "error"
497
+ });
498
+ } else if (!status.docker.running) {
499
+ issues.push({
500
+ name: "Docker \u5B88\u62A4\u8FDB\u7A0B\u672A\u8FD0\u884C",
501
+ description: "\u8BF7\u542F\u52A8 Docker Desktop \u5E94\u7528",
502
+ severity: "error",
503
+ fix: async () => {
504
+ console.log(chalk4.yellow(" \u8BF7\u624B\u52A8\u542F\u52A8 Docker Desktop"));
505
+ return false;
506
+ }
507
+ });
508
+ }
509
+ if (!status.ollama.installed) {
510
+ issues.push({
511
+ name: "Ollama \u672A\u5B89\u88C5",
512
+ description: "\u4F7F\u7528 brew install ollama \u5B89\u88C5",
513
+ severity: "error",
514
+ fix: async () => {
515
+ try {
516
+ await execAsync3("brew install ollama");
517
+ return true;
518
+ } catch {
519
+ return false;
520
+ }
521
+ }
522
+ });
523
+ } else if (!status.ollama.running) {
524
+ issues.push({
525
+ name: "Ollama \u670D\u52A1\u672A\u8FD0\u884C",
526
+ description: "\u4F7F\u7528 ollama serve \u542F\u52A8",
527
+ severity: "warning",
528
+ fix: async () => {
529
+ try {
530
+ exec3("ollama serve &");
531
+ await new Promise((r) => setTimeout(r, 2e3));
532
+ return true;
533
+ } catch {
534
+ return false;
535
+ }
536
+ }
537
+ });
538
+ }
539
+ if (!status.qdrant.running) {
540
+ issues.push({
541
+ name: "Qdrant \u672A\u8FD0\u884C",
542
+ description: "\u9700\u8981\u542F\u52A8 Qdrant \u5BB9\u5668",
543
+ severity: "error",
544
+ fix: async () => {
545
+ try {
546
+ await execAsync3("docker start qdrant || docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant");
547
+ return true;
548
+ } catch {
549
+ return false;
550
+ }
551
+ }
552
+ });
553
+ }
554
+ if (!status.bgeM3.installed) {
555
+ issues.push({
556
+ name: "BGE-M3 \u6A21\u578B\u672A\u4E0B\u8F7D",
557
+ description: "\u4F7F\u7528 ollama pull bge-m3 \u4E0B\u8F7D",
558
+ severity: "warning",
559
+ fix: async () => {
560
+ try {
561
+ await execAsync3("ollama pull bge-m3", { timeout: 6e5 });
562
+ return true;
563
+ } catch {
564
+ return false;
565
+ }
566
+ }
567
+ });
568
+ }
569
+ return issues;
570
+ }
571
+ async function doctorCommand(options) {
572
+ console.log(chalk4.cyan.bold("\n\u{1FA7A} OpenMemory Plus - \u95EE\u9898\u8BCA\u65AD\n"));
573
+ const spinner = ora4("\u68C0\u6D4B\u7CFB\u7EDF\u72B6\u6001...").start();
574
+ const status = await checkAllDependencies();
575
+ spinner.stop();
576
+ const issues = diagnoseIssues(status);
577
+ if (issues.length === 0) {
578
+ console.log(chalk4.green.bold("\u2705 \u672A\u53D1\u73B0\u95EE\u9898\uFF0C\u7CFB\u7EDF\u8FD0\u884C\u6B63\u5E38!\n"));
579
+ return;
580
+ }
581
+ console.log(chalk4.yellow.bold(`\u53D1\u73B0 ${issues.length} \u4E2A\u95EE\u9898:
582
+ `));
583
+ for (const issue of issues) {
584
+ const icon = issue.severity === "error" ? chalk4.red("\u2717") : chalk4.yellow("\u26A0");
585
+ console.log(` ${icon} ${chalk4.bold(issue.name)}`);
586
+ console.log(` ${chalk4.gray(issue.description)}`);
587
+ }
588
+ console.log("");
589
+ if (options.fix) {
590
+ console.log(chalk4.bold("\u5C1D\u8BD5\u81EA\u52A8\u4FEE\u590D...\n"));
591
+ for (const issue of issues) {
592
+ if (issue.fix) {
593
+ const fixSpinner = ora4(`\u4FEE\u590D: ${issue.name}`).start();
594
+ const success = await issue.fix();
595
+ if (success) {
596
+ fixSpinner.succeed(`\u5DF2\u4FEE\u590D: ${issue.name}`);
597
+ } else {
598
+ fixSpinner.fail(`\u65E0\u6CD5\u4FEE\u590D: ${issue.name}`);
599
+ }
600
+ }
601
+ }
602
+ console.log(chalk4.gray("\n\u8FD0\u884C ") + chalk4.cyan("openmemory-plus status") + chalk4.gray(" \u9A8C\u8BC1\u4FEE\u590D\u7ED3\u679C"));
603
+ } else {
604
+ const fixable = issues.filter((i) => i.fix).length;
605
+ if (fixable > 0) {
606
+ console.log(chalk4.gray(`${fixable} \u4E2A\u95EE\u9898\u53EF\u81EA\u52A8\u4FEE\u590D`));
607
+ console.log(chalk4.gray("\u8FD0\u884C ") + chalk4.cyan("openmemory-plus doctor --fix") + chalk4.gray(" \u5C1D\u8BD5\u4FEE\u590D"));
608
+ }
609
+ }
610
+ console.log("");
611
+ }
612
+
613
+ // src/index.ts
614
+ var program = new Command();
615
+ program.name("openmemory-plus").description("\u{1F9E0} Agent Memory Management CLI - Install, configure, and manage OpenMemory Plus").version("1.0.0");
616
+ program.command("install").description("Install and configure all dependencies (Docker, Ollama, Qdrant, OpenMemory)").option("-y, --yes", "Skip confirmation prompts").option("--skip-docker", "Skip Docker installation").option("--skip-ollama", "Skip Ollama installation").action(installCommand);
617
+ program.command("init").description("Initialize OpenMemory Plus in current project").option("-i, --ide <type>", "IDE type: augment, claude, cursor, gemini, common", "augment").option("-y, --yes", "Skip confirmation prompts").option("--project-name <name>", "Project name for configuration").option("--generate-mcp", "Generate MCP configuration snippet").action(initCommand);
618
+ program.command("status").description("Check OpenMemory Plus system status").action(statusCommand);
619
+ program.command("doctor").description("Diagnose and fix common issues").option("--fix", "Attempt to fix issues automatically").action(doctorCommand);
620
+ program.action(() => {
621
+ console.log(chalk5.cyan.bold("\n\u{1F9E0} OpenMemory Plus - Agent Memory Management\n"));
622
+ console.log("Usage: openmemory-plus <command> [options]\n");
623
+ console.log("Commands:");
624
+ console.log(" install Install and configure dependencies");
625
+ console.log(" init Initialize in current project");
626
+ console.log(" status Check system status");
627
+ console.log(" doctor Diagnose issues\n");
628
+ console.log('Run "openmemory-plus --help" for more information.');
629
+ });
630
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "openmemory-plus",
3
+ "version": "1.0.0",
4
+ "description": "Agent Memory Management CLI - Install, configure, and manage OpenMemory Plus",
5
+ "type": "module",
6
+ "bin": {
7
+ "openmemory-plus": "./dist/index.js",
8
+ "omp": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsup src/index.ts --format esm --dts --clean",
12
+ "dev": "tsx src/index.ts",
13
+ "start": "node dist/index.js",
14
+ "lint": "eslint src --ext .ts",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "ai",
19
+ "agent",
20
+ "memory",
21
+ "openmemory",
22
+ "cli",
23
+ "qdrant",
24
+ "ollama",
25
+ "mcp",
26
+ "llm",
27
+ "claude",
28
+ "cursor",
29
+ "augment"
30
+ ],
31
+ "author": "TreeRen Chou <miaojsi@outlook.com>",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/Alenryuichi/openmemory-plus.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/Alenryuichi/openmemory-plus/issues"
39
+ },
40
+ "homepage": "https://github.com/Alenryuichi/openmemory-plus#readme",
41
+ "dependencies": {
42
+ "chalk": "^5.3.0",
43
+ "commander": "^12.0.0",
44
+ "inquirer": "^9.2.0",
45
+ "ora": "^8.0.0",
46
+ "which": "^4.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/inquirer": "^9.0.7",
50
+ "@types/node": "^20.0.0",
51
+ "@types/which": "^3.0.0",
52
+ "tsup": "^8.0.0",
53
+ "tsx": "^4.0.0",
54
+ "typescript": "^5.0.0"
55
+ },
56
+ "engines": {
57
+ "node": ">=18.0.0"
58
+ },
59
+ "files": [
60
+ "dist",
61
+ "templates"
62
+ ]
63
+ }
64
+