openmemory-plus 1.0.0 → 1.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/dist/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk5 from "chalk";
6
5
 
7
6
  // src/commands/install.ts
8
7
  import chalk from "chalk";
@@ -10,6 +9,9 @@ import ora from "ora";
10
9
  import inquirer from "inquirer";
11
10
  import { exec as exec2 } from "child_process";
12
11
  import { promisify as promisify2 } from "util";
12
+ import { existsSync, mkdirSync, copyFileSync, writeFileSync, readdirSync } from "fs";
13
+ import { join, dirname } from "path";
14
+ import { fileURLToPath } from "url";
13
15
 
14
16
  // src/lib/detector.ts
15
17
  import { exec } from "child_process";
@@ -110,6 +112,22 @@ function isSystemReady(status) {
110
112
 
111
113
  // src/commands/install.ts
112
114
  var execAsync2 = promisify2(exec2);
115
+ var IDE_CONFIGS = {
116
+ augment: { dir: ".augment", configFile: "AGENTS.md", commandsDir: "commands", skillsDir: "skills", rulesDir: ".rules/memory" },
117
+ claude: { dir: ".", configFile: "CLAUDE.md", commandsDir: ".claude/commands", skillsDir: ".claude/skills", rulesDir: ".rules/memory" },
118
+ cursor: { dir: ".cursor", configFile: ".cursorrules", commandsDir: "commands", skillsDir: "skills", rulesDir: ".rules/memory" },
119
+ gemini: { dir: ".", configFile: "gemini.md", commandsDir: ".gemini/commands", skillsDir: ".gemini/skills", rulesDir: ".rules/memory" },
120
+ common: { dir: ".", configFile: "AGENTS.md", commandsDir: ".agents/commands", skillsDir: ".agents/skills", rulesDir: ".rules/memory" }
121
+ };
122
+ var BANNER = `
123
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
124
+ \u2551 \u2551
125
+ \u2551 \u{1F9E0} OpenMemory Plus - Agent Memory Management \u2551
126
+ \u2551 \u2551
127
+ \u2551 \u8BA9\u4EFB\u4F55 AI Agent \u5728 5 \u5206\u949F\u5185\u83B7\u5F97\u6301\u4E45\u8BB0\u5FC6\u80FD\u529B \u2551
128
+ \u2551 \u2551
129
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
130
+ `;
113
131
  async function openUrl(url) {
114
132
  const { platform } = process;
115
133
  const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
@@ -123,7 +141,7 @@ async function installOllama() {
123
141
  return true;
124
142
  } catch {
125
143
  spinner.fail("Ollama \u5B89\u88C5\u5931\u8D25");
126
- console.log(chalk.yellow("\u8BF7\u624B\u52A8\u5B89\u88C5: https://ollama.com/download"));
144
+ console.log(chalk.yellow(" \u8BF7\u624B\u52A8\u5B89\u88C5: https://ollama.com/download"));
127
145
  return false;
128
146
  }
129
147
  }
@@ -157,7 +175,7 @@ async function startQdrant() {
157
175
  spinner.succeed("Qdrant \u5BB9\u5668\u5DF2\u542F\u52A8");
158
176
  return true;
159
177
  } catch (e) {
160
- if (e.message?.includes("already in use")) {
178
+ if (e.message?.includes("already in use") || e.message?.includes("Conflict")) {
161
179
  try {
162
180
  await execAsync2("docker start qdrant");
163
181
  spinner.succeed("Qdrant \u5BB9\u5668\u5DF2\u542F\u52A8");
@@ -169,86 +187,12 @@ async function startQdrant() {
169
187
  return false;
170
188
  }
171
189
  }
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
190
  function getTemplatesDir() {
244
191
  const __dirname = dirname(fileURLToPath(import.meta.url));
245
192
  const possiblePaths = [
246
193
  join(__dirname, "..", "templates"),
247
- // npm 包: dist/../templates
248
194
  join(__dirname, "..", "..", "templates"),
249
- // 开发时 (从 dist/)
250
195
  join(__dirname, "..", "..", "..", "templates")
251
- // 旧路径 (从 src/)
252
196
  ];
253
197
  for (const p of possiblePaths) {
254
198
  if (existsSync(join(p, "shared"))) {
@@ -280,13 +224,10 @@ project:
280
224
  description: ""
281
225
 
282
226
  memory:
283
- # \u9879\u76EE\u7EA7\u8BB0\u5FC6\u5B58\u50A8\u4F4D\u7F6E
284
227
  project_store: ".memory/"
285
- # \u7528\u6237\u7EA7\u8BB0\u5FC6 (openmemory MCP)
286
228
  user_store: "openmemory"
287
229
 
288
230
  classification:
289
- # \u9879\u76EE\u7EA7\u4FE1\u606F\u5173\u952E\u8BCD (\u5B58\u5165 .memory/)
290
231
  project_keywords:
291
232
  - "\u9879\u76EE\u914D\u7F6E"
292
233
  - "\u6280\u672F\u51B3\u7B56"
@@ -294,7 +235,6 @@ classification:
294
235
  - "API \u5BC6\u94A5"
295
236
  - "\u67B6\u6784\u8BBE\u8BA1"
296
237
  - "\u6570\u636E\u5E93"
297
- # \u7528\u6237\u7EA7\u4FE1\u606F\u5173\u952E\u8BCD (\u5B58\u5165 openmemory)
298
238
  user_keywords:
299
239
  - "\u7528\u6237\u504F\u597D"
300
240
  - "\u7F16\u7801\u98CE\u683C"
@@ -303,35 +243,104 @@ classification:
303
243
  - "\u559C\u6B22"
304
244
 
305
245
  agent:
306
- # \u5BF9\u8BDD\u7ED3\u675F\u65F6\u81EA\u52A8\u63D0\u53D6\u8BB0\u5FC6
307
246
  auto_extract: true
308
- # \u5BF9\u8BDD\u5F00\u59CB\u65F6\u81EA\u52A8\u641C\u7D22\u4E0A\u4E0B\u6587
309
247
  auto_search: true
310
- # MCP \u4E0D\u53EF\u7528\u65F6\u964D\u7EA7\u5230\u6587\u4EF6\u5B58\u50A8
311
248
  fallback_to_file: true
312
249
  `;
313
250
  }
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();
251
+ function showMcpConfig(ide) {
252
+ console.log(chalk.bold("\n\u{1F4CB} MCP \u914D\u7F6E (\u590D\u5236\u5230 IDE \u914D\u7F6E\u6587\u4EF6):"));
253
+ const mcpConfig = {
254
+ openmemory: {
255
+ command: "npx",
256
+ args: ["-y", "openmemory-mcp"],
257
+ env: {
258
+ OPENAI_API_KEY: "your-openai-key-or-use-ollama",
259
+ MEM0_EMBEDDING_MODEL: "bge-m3",
260
+ MEM0_EMBEDDING_PROVIDER: "ollama",
261
+ QDRANT_HOST: "localhost",
262
+ QDRANT_PORT: "6333"
263
+ }
264
+ }
265
+ };
266
+ console.log(chalk.cyan("\n```json"));
267
+ console.log(JSON.stringify(mcpConfig, null, 2));
268
+ console.log(chalk.cyan("```\n"));
269
+ const configPaths = {
270
+ augment: "~/.augment/settings.json (mcpServers \u5B57\u6BB5)",
271
+ claude: "~/.config/claude/mcp.json",
272
+ cursor: "~/.cursor/mcp.json",
273
+ gemini: "~/.config/gemini/mcp.json",
274
+ common: "\u53C2\u8003\u5404 IDE \u7684 MCP \u914D\u7F6E\u6587\u6863"
275
+ };
276
+ console.log(chalk.gray(`\u914D\u7F6E\u6587\u4EF6\u4F4D\u7F6E: ${configPaths[ide] || configPaths.common}
277
+ `));
278
+ }
279
+ async function phase1_checkAndInstallDeps(options) {
280
+ console.log(chalk.bold.cyan("\n\u2501\u2501\u2501 \u7B2C 1 \u6B65: \u68C0\u6D4B\u7CFB\u7EDF\u4F9D\u8D56 \u2501\u2501\u2501\n"));
281
+ const spinner = ora("\u68C0\u6D4B\u7CFB\u7EDF\u72B6\u6001...").start();
317
282
  const status = await checkAllDependencies();
318
283
  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"));
284
+ console.log(chalk.bold("\u5F53\u524D\u72B6\u6001:"));
285
+ console.log(` \u{1F433} Docker: ${status.docker.installed ? status.docker.running ? chalk.green("\u2713 \u8FD0\u884C\u4E2D") : chalk.yellow("\u26A0 \u5DF2\u5B89\u88C5\u672A\u8FD0\u884C") : chalk.red("\u2717 \u672A\u5B89\u88C5")}`);
286
+ console.log(` \u{1F999} Ollama: ${status.ollama.installed ? status.ollama.running ? chalk.green("\u2713 \u8FD0\u884C\u4E2D") : chalk.yellow("\u26A0 \u5DF2\u5B89\u88C5\u672A\u8FD0\u884C") : chalk.red("\u2717 \u672A\u5B89\u88C5")}`);
287
+ console.log(` \u{1F4E6} Qdrant: ${status.qdrant.running ? chalk.green("\u2713 \u8FD0\u884C\u4E2D") : chalk.red("\u2717 \u672A\u8FD0\u884C")}`);
288
+ console.log(` \u{1F524} BGE-M3: ${status.bgeM3.installed ? chalk.green("\u2713 \u5DF2\u5B89\u88C5") : chalk.red("\u2717 \u672A\u5B89\u88C5")}`);
289
+ console.log("");
290
+ if (isSystemReady(status)) {
291
+ console.log(chalk.green("\u2705 \u6240\u6709\u4F9D\u8D56\u5DF2\u5C31\u7EEA!\n"));
292
+ return true;
293
+ }
294
+ if (options.skipDeps) {
295
+ console.log(chalk.yellow("\u26A0\uFE0F \u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5 (--skip-deps)\n"));
296
+ return true;
297
+ }
298
+ if (!options.yes) {
299
+ const { confirm } = await inquirer.prompt([{
300
+ type: "confirm",
301
+ name: "confirm",
302
+ message: "\u9700\u8981\u5B89\u88C5/\u542F\u52A8\u7F3A\u5931\u7684\u4F9D\u8D56\uFF0C\u662F\u5426\u7EE7\u7EED?",
303
+ default: true
304
+ }]);
305
+ if (!confirm) {
306
+ console.log(chalk.yellow("\n\u5DF2\u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5\uFF0C\u7EE7\u7EED\u9879\u76EE\u914D\u7F6E...\n"));
307
+ return true;
308
+ }
309
+ }
310
+ if (!status.docker.installed) {
311
+ console.log(chalk.yellow("\n\u{1F4E6} Docker \u9700\u8981\u624B\u52A8\u5B89\u88C5"));
312
+ console.log(chalk.gray(" \u8BF7\u8BBF\u95EE https://docker.com/download \u4E0B\u8F7D\u5B89\u88C5"));
322
313
  if (!options.yes) {
323
- const { cont } = await inquirer2.prompt([{
314
+ const { openDocker } = await inquirer.prompt([{
324
315
  type: "confirm",
325
- name: "cont",
326
- message: "\u662F\u5426\u7EE7\u7EED\u521D\u59CB\u5316?",
327
- default: false
316
+ name: "openDocker",
317
+ message: "\u662F\u5426\u6253\u5F00 Docker \u4E0B\u8F7D\u9875\u9762?",
318
+ default: true
328
319
  }]);
329
- if (!cont) return;
320
+ if (openDocker) await openUrl("https://docker.com/download");
321
+ await inquirer.prompt([{ type: "input", name: "wait", message: "\u5B89\u88C5\u5B8C\u6210\u540E\u6309 Enter \u7EE7\u7EED..." }]);
330
322
  }
331
323
  }
324
+ if (!status.ollama.installed) {
325
+ await installOllama();
326
+ }
327
+ if (status.ollama.installed && !status.ollama.running) {
328
+ await startOllama();
329
+ }
330
+ if (!status.bgeM3.installed) {
331
+ await pullBgeM3();
332
+ }
333
+ if (!status.qdrant.running && (status.docker.running || status.docker.installed)) {
334
+ await startQdrant();
335
+ }
336
+ console.log(chalk.green("\n\u2705 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210!\n"));
337
+ return true;
338
+ }
339
+ async function phase2_initProject(options) {
340
+ console.log(chalk.bold.cyan("\n\u2501\u2501\u2501 \u7B2C 2 \u6B65: \u914D\u7F6E\u9879\u76EE \u2501\u2501\u2501\n"));
332
341
  let ide = options.ide?.toLowerCase();
333
342
  if (!ide || !IDE_CONFIGS[ide]) {
334
- const { selectedIde } = await inquirer2.prompt([{
343
+ const { selectedIde } = await inquirer.prompt([{
335
344
  type: "list",
336
345
  name: "selectedIde",
337
346
  message: "\u9009\u62E9 IDE \u7C7B\u578B:",
@@ -346,11 +355,11 @@ async function initCommand(options) {
346
355
  }]);
347
356
  ide = selectedIde;
348
357
  }
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([{
358
+ const cwd = process.cwd();
359
+ const defaultName = cwd.split("/").pop() || "my-project";
360
+ let projectName = defaultName;
361
+ if (!options.yes) {
362
+ const { name } = await inquirer.prompt([{
354
363
  type: "input",
355
364
  name: "name",
356
365
  message: "\u9879\u76EE\u540D\u79F0:",
@@ -359,91 +368,82 @@ async function initCommand(options) {
359
368
  projectName = name;
360
369
  }
361
370
  const config = IDE_CONFIGS[ide];
362
- const cwd = process.cwd();
363
- console.log(chalk2.bold("\n\u{1F4C1} \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6..."));
371
+ console.log(chalk.bold("\n\u{1F4C1} \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6...\n"));
364
372
  const memoryDir = join(cwd, ".memory");
365
373
  if (!existsSync(memoryDir)) {
366
374
  mkdirSync(memoryDir, { recursive: true });
367
- console.log(chalk2.green(" \u2713 \u521B\u5EFA .memory/"));
368
375
  }
376
+ console.log(chalk.green(" \u2713 \u521B\u5EFA .memory/"));
369
377
  const projectYaml = join(memoryDir, "project.yaml");
370
378
  writeFileSync(projectYaml, generateProjectYaml(projectName));
371
- console.log(chalk2.green(" \u2713 \u521B\u5EFA .memory/project.yaml"));
379
+ console.log(chalk.green(" \u2713 \u521B\u5EFA .memory/project.yaml"));
372
380
  const templatesDir = getTemplatesDir();
373
381
  const sharedTemplates = join(templatesDir, "shared");
374
382
  const ideTemplates = join(templatesDir, ide === "common" ? "common" : ide);
375
383
  const commandsDir = join(cwd, config.dir, config.commandsDir);
376
384
  mkdirSync(commandsDir, { recursive: true });
377
385
  copyDir(join(sharedTemplates, "commands"), commandsDir);
378
- console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.commandsDir}/ (6 \u4E2A\u547D\u4EE4)`));
386
+ const cmdCount = existsSync(join(sharedTemplates, "commands")) ? readdirSync(join(sharedTemplates, "commands")).length : 0;
387
+ console.log(chalk.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.commandsDir}/ (${cmdCount} \u4E2A\u547D\u4EE4)`));
379
388
  const skillsDir = join(cwd, config.dir, config.skillsDir);
380
389
  mkdirSync(skillsDir, { recursive: true });
381
390
  copyDir(join(sharedTemplates, "skills"), skillsDir);
382
- console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.skillsDir}/ (memory-extraction)`));
391
+ console.log(chalk.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.skillsDir}/ (memory-extraction)`));
383
392
  const rulesDir = join(cwd, config.rulesDir);
384
393
  mkdirSync(rulesDir, { recursive: true });
385
394
  copyDir(join(sharedTemplates, "rules"), rulesDir);
386
- console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.rulesDir}/ (classification.md)`));
395
+ console.log(chalk.green(` \u2713 \u521B\u5EFA ${config.rulesDir}/ (classification.md)`));
387
396
  if (existsSync(ideTemplates)) {
388
397
  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);
398
+ console.log(chalk.green(` \u2713 \u590D\u5236 ${config.configFile}`));
393
399
  }
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"));
400
+ return ide;
401
+ }
402
+ function phase3_showCompletion(ide, showMcp) {
403
+ console.log(chalk.bold.cyan("\n\u2501\u2501\u2501 \u5B89\u88C5\u5B8C\u6210 \u2501\u2501\u2501\n"));
404
+ console.log(chalk.green.bold("\u{1F389} OpenMemory Plus \u5DF2\u6210\u529F\u5B89\u88C5!\n"));
405
+ console.log(chalk.bold("\u{1F4A1} \u4E0B\u4E00\u6B65:"));
406
+ console.log(chalk.gray(" 1. \u5728 IDE \u4E2D\u6253\u5F00\u9879\u76EE"));
407
+ console.log(chalk.gray(" 2. \u4F7F\u7528 ") + chalk.cyan("/memory") + chalk.gray(" \u67E5\u770B\u8BB0\u5FC6\u72B6\u6001"));
408
+ console.log(chalk.gray(" 3. \u4F7F\u7528 ") + chalk.cyan("/mem search <query>") + chalk.gray(" \u641C\u7D22\u8BB0\u5FC6"));
409
+ console.log("");
410
+ if (showMcp) {
411
+ showMcpConfig(ide);
412
+ } else {
413
+ console.log(chalk.gray("\u{1F4CB} \u67E5\u770B MCP \u914D\u7F6E: ") + chalk.cyan("npx openmemory-plus install --show-mcp"));
399
414
  }
415
+ console.log("");
400
416
  }
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}`));
417
+ async function installCommand(options) {
418
+ console.log(chalk.cyan(BANNER));
419
+ if (options.showMcp) {
420
+ const ide2 = options.ide || "augment";
421
+ showMcpConfig(ide2);
422
+ return;
423
+ }
424
+ await phase1_checkAndInstallDeps(options);
425
+ const ide = await phase2_initProject(options);
426
+ phase3_showCompletion(ide, false);
427
427
  }
428
428
 
429
429
  // src/commands/status.ts
430
- import chalk3 from "chalk";
431
- import ora3 from "ora";
430
+ import chalk2 from "chalk";
431
+ import ora2 from "ora";
432
432
  function formatStatus(dep) {
433
433
  if (!dep.installed) {
434
- return chalk3.red("\u2717 \u672A\u5B89\u88C5");
434
+ return chalk2.red("\u2717 \u672A\u5B89\u88C5");
435
435
  }
436
436
  if (dep.running === false) {
437
- return chalk3.yellow("\u26A0 \u5DF2\u5B89\u88C5\u4F46\u672A\u8FD0\u884C");
437
+ return chalk2.yellow("\u26A0 \u5DF2\u5B89\u88C5\u4F46\u672A\u8FD0\u884C");
438
438
  }
439
439
  if (dep.running === true) {
440
- const ver = dep.version ? chalk3.gray(` (${dep.version})`) : "";
441
- return chalk3.green("\u2713 \u8FD0\u884C\u4E2D") + ver;
440
+ const ver = dep.version ? chalk2.gray(` (${dep.version})`) : "";
441
+ return chalk2.green("\u2713 \u8FD0\u884C\u4E2D") + ver;
442
442
  }
443
- return chalk3.green("\u2713 \u5DF2\u5B89\u88C5");
443
+ return chalk2.green("\u2713 \u5DF2\u5B89\u88C5");
444
444
  }
445
445
  function printStatusTable(status) {
446
- console.log("\n" + chalk3.bold("\u4F9D\u8D56\u68C0\u6D4B\u7ED3\u679C:"));
446
+ console.log("\n" + chalk2.bold("\u4F9D\u8D56\u68C0\u6D4B\u7ED3\u679C:"));
447
447
  console.log("");
448
448
  const deps = [
449
449
  { ...status.docker, icon: "\u{1F433}" },
@@ -454,36 +454,36 @@ function printStatusTable(status) {
454
454
  ];
455
455
  for (const dep of deps) {
456
456
  const statusStr = formatStatus(dep);
457
- const errorStr = dep.error && !dep.installed ? chalk3.gray(` - ${dep.error}`) : "";
457
+ const errorStr = dep.error && !dep.installed ? chalk2.gray(` - ${dep.error}`) : "";
458
458
  console.log(` ${dep.icon} ${dep.name.padEnd(16)} ${statusStr}${errorStr}`);
459
459
  }
460
460
  console.log("");
461
461
  }
462
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();
463
+ console.log(chalk2.cyan.bold("\n\u{1F9E0} OpenMemory Plus - \u7CFB\u7EDF\u72B6\u6001\n"));
464
+ const spinner = ora2("\u68C0\u6D4B\u7CFB\u7EDF\u4F9D\u8D56...").start();
465
465
  try {
466
466
  const status = await checkAllDependencies();
467
467
  spinner.stop();
468
468
  printStatusTable(status);
469
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"));
470
+ console.log(chalk2.green.bold("\u2705 \u7CFB\u7EDF\u5C31\u7EEA! OpenMemory Plus \u53EF\u6B63\u5E38\u4F7F\u7528\u3002\n"));
471
+ console.log(chalk2.gray("\u63D0\u793A: \u4F7F\u7528 /memory \u547D\u4EE4\u67E5\u770B\u8BB0\u5FC6\u72B6\u6001"));
472
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"));
473
+ console.log(chalk2.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(chalk2.gray("\u8FD0\u884C ") + chalk2.cyan("openmemory-plus install") + chalk2.gray(" \u5B89\u88C5\u7F3A\u5931\u4F9D\u8D56"));
475
+ console.log(chalk2.gray("\u8FD0\u884C ") + chalk2.cyan("openmemory-plus doctor") + chalk2.gray(" \u8BCA\u65AD\u5E76\u4FEE\u590D\u95EE\u9898"));
476
476
  }
477
477
  } catch (error) {
478
478
  spinner.fail("\u68C0\u6D4B\u5931\u8D25");
479
- console.error(chalk3.red("\u9519\u8BEF:"), error);
479
+ console.error(chalk2.red("\u9519\u8BEF:"), error);
480
480
  process.exit(1);
481
481
  }
482
482
  }
483
483
 
484
484
  // src/commands/doctor.ts
485
- import chalk4 from "chalk";
486
- import ora4 from "ora";
485
+ import chalk3 from "chalk";
486
+ import ora3 from "ora";
487
487
  import { exec as exec3 } from "child_process";
488
488
  import { promisify as promisify3 } from "util";
489
489
  var execAsync3 = promisify3(exec3);
@@ -501,7 +501,7 @@ function diagnoseIssues(status) {
501
501
  description: "\u8BF7\u542F\u52A8 Docker Desktop \u5E94\u7528",
502
502
  severity: "error",
503
503
  fix: async () => {
504
- console.log(chalk4.yellow(" \u8BF7\u624B\u52A8\u542F\u52A8 Docker Desktop"));
504
+ console.log(chalk3.yellow(" \u8BF7\u624B\u52A8\u542F\u52A8 Docker Desktop"));
505
505
  return false;
506
506
  }
507
507
  });
@@ -569,28 +569,28 @@ function diagnoseIssues(status) {
569
569
  return issues;
570
570
  }
571
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();
572
+ console.log(chalk3.cyan.bold("\n\u{1FA7A} OpenMemory Plus - \u95EE\u9898\u8BCA\u65AD\n"));
573
+ const spinner = ora3("\u68C0\u6D4B\u7CFB\u7EDF\u72B6\u6001...").start();
574
574
  const status = await checkAllDependencies();
575
575
  spinner.stop();
576
576
  const issues = diagnoseIssues(status);
577
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"));
578
+ console.log(chalk3.green.bold("\u2705 \u672A\u53D1\u73B0\u95EE\u9898\uFF0C\u7CFB\u7EDF\u8FD0\u884C\u6B63\u5E38!\n"));
579
579
  return;
580
580
  }
581
- console.log(chalk4.yellow.bold(`\u53D1\u73B0 ${issues.length} \u4E2A\u95EE\u9898:
581
+ console.log(chalk3.yellow.bold(`\u53D1\u73B0 ${issues.length} \u4E2A\u95EE\u9898:
582
582
  `));
583
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)}`);
584
+ const icon = issue.severity === "error" ? chalk3.red("\u2717") : chalk3.yellow("\u26A0");
585
+ console.log(` ${icon} ${chalk3.bold(issue.name)}`);
586
+ console.log(` ${chalk3.gray(issue.description)}`);
587
587
  }
588
588
  console.log("");
589
589
  if (options.fix) {
590
- console.log(chalk4.bold("\u5C1D\u8BD5\u81EA\u52A8\u4FEE\u590D...\n"));
590
+ console.log(chalk3.bold("\u5C1D\u8BD5\u81EA\u52A8\u4FEE\u590D...\n"));
591
591
  for (const issue of issues) {
592
592
  if (issue.fix) {
593
- const fixSpinner = ora4(`\u4FEE\u590D: ${issue.name}`).start();
593
+ const fixSpinner = ora3(`\u4FEE\u590D: ${issue.name}`).start();
594
594
  const success = await issue.fix();
595
595
  if (success) {
596
596
  fixSpinner.succeed(`\u5DF2\u4FEE\u590D: ${issue.name}`);
@@ -599,12 +599,12 @@ async function doctorCommand(options) {
599
599
  }
600
600
  }
601
601
  }
602
- console.log(chalk4.gray("\n\u8FD0\u884C ") + chalk4.cyan("openmemory-plus status") + chalk4.gray(" \u9A8C\u8BC1\u4FEE\u590D\u7ED3\u679C"));
602
+ console.log(chalk3.gray("\n\u8FD0\u884C ") + chalk3.cyan("openmemory-plus status") + chalk3.gray(" \u9A8C\u8BC1\u4FEE\u590D\u7ED3\u679C"));
603
603
  } else {
604
604
  const fixable = issues.filter((i) => i.fix).length;
605
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"));
606
+ console.log(chalk3.gray(`${fixable} \u4E2A\u95EE\u9898\u53EF\u81EA\u52A8\u4FEE\u590D`));
607
+ console.log(chalk3.gray("\u8FD0\u884C ") + chalk3.cyan("openmemory-plus doctor --fix") + chalk3.gray(" \u5C1D\u8BD5\u4FEE\u590D"));
608
608
  }
609
609
  }
610
610
  console.log("");
@@ -612,19 +612,8 @@ async function doctorCommand(options) {
612
612
 
613
613
  // src/index.ts
614
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
- });
615
+ program.name("openmemory-plus").description("\u{1F9E0} Agent Memory Management - \u8BA9\u4EFB\u4F55 AI Agent \u83B7\u5F97\u6301\u4E45\u8BB0\u5FC6\u80FD\u529B").version("1.0.0");
616
+ program.command("install", { isDefault: true }).description("\u4E00\u952E\u5B89\u88C5\u548C\u914D\u7F6E OpenMemory Plus (\u63A8\u8350)").option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4\u63D0\u793A").option("-i, --ide <type>", "IDE \u7C7B\u578B: augment, claude, cursor, gemini, common").option("--skip-deps", "\u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5\uFF0C\u4EC5\u914D\u7F6E\u9879\u76EE").option("--show-mcp", "\u663E\u793A MCP \u914D\u7F6E").action(installCommand);
617
+ program.command("status").description("\u68C0\u67E5\u7CFB\u7EDF\u72B6\u6001").action(statusCommand);
618
+ program.command("doctor").description("\u8BCA\u65AD\u5E76\u4FEE\u590D\u95EE\u9898").option("--fix", "\u81EA\u52A8\u4FEE\u590D\u95EE\u9898").action(doctorCommand);
630
619
  program.parse();
package/package.json CHANGED
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "name": "openmemory-plus",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Agent Memory Management CLI - Install, configure, and manage OpenMemory Plus",
5
5
  "type": "module",
6
6
  "bin": {
7
- "openmemory-plus": "./dist/index.js",
8
- "omp": "./dist/index.js"
7
+ "openmemory-plus": "dist/index.js",
8
+ "omp": "dist/index.js"
9
9
  },
10
10
  "scripts": {
11
11
  "build": "tsup src/index.ts --format esm --dts --clean",
12
12
  "dev": "tsx src/index.ts",
13
13
  "start": "node dist/index.js",
14
+ "test": "vitest run",
15
+ "test:watch": "vitest",
16
+ "test:coverage": "vitest run --coverage",
14
17
  "lint": "eslint src --ext .ts",
15
- "prepublishOnly": "npm run build"
18
+ "prepublishOnly": "npm run build && npm run test"
16
19
  },
17
20
  "keywords": [
18
21
  "ai",
@@ -49,9 +52,11 @@
49
52
  "@types/inquirer": "^9.0.7",
50
53
  "@types/node": "^20.0.0",
51
54
  "@types/which": "^3.0.0",
55
+ "@vitest/coverage-v8": "^4.0.18",
52
56
  "tsup": "^8.0.0",
53
57
  "tsx": "^4.0.0",
54
- "typescript": "^5.0.0"
58
+ "typescript": "^5.0.0",
59
+ "vitest": "^4.0.18"
55
60
  },
56
61
  "engines": {
57
62
  "node": ">=18.0.0"
@@ -61,4 +66,3 @@
61
66
  "templates"
62
67
  ]
63
68
  }
64
-