openmemory-plus 1.0.0 → 1.2.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, readFileSync } 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,108 @@ 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 processTemplate(content, projectName) {
252
+ const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
253
+ return content.replace(/\{\{PROJECT_NAME\}\}/g, projectName).replace(/\{\{CREATED_AT\}\}/g, now);
254
+ }
255
+ function showMcpConfig(ide) {
256
+ console.log(chalk.bold("\n\u{1F4CB} MCP \u914D\u7F6E (\u590D\u5236\u5230 IDE \u914D\u7F6E\u6587\u4EF6):"));
257
+ const mcpConfig = {
258
+ openmemory: {
259
+ command: "npx",
260
+ args: ["-y", "openmemory-mcp"],
261
+ env: {
262
+ OPENAI_API_KEY: "your-openai-key-or-use-ollama",
263
+ MEM0_EMBEDDING_MODEL: "bge-m3",
264
+ MEM0_EMBEDDING_PROVIDER: "ollama",
265
+ QDRANT_HOST: "localhost",
266
+ QDRANT_PORT: "6333"
267
+ }
268
+ }
269
+ };
270
+ console.log(chalk.cyan("\n```json"));
271
+ console.log(JSON.stringify(mcpConfig, null, 2));
272
+ console.log(chalk.cyan("```\n"));
273
+ const configPaths = {
274
+ augment: "~/.augment/settings.json (mcpServers \u5B57\u6BB5)",
275
+ claude: "~/.config/claude/mcp.json",
276
+ cursor: "~/.cursor/mcp.json",
277
+ gemini: "~/.config/gemini/mcp.json",
278
+ common: "\u53C2\u8003\u5404 IDE \u7684 MCP \u914D\u7F6E\u6587\u6863"
279
+ };
280
+ console.log(chalk.gray(`\u914D\u7F6E\u6587\u4EF6\u4F4D\u7F6E: ${configPaths[ide] || configPaths.common}
281
+ `));
282
+ }
283
+ async function phase1_checkAndInstallDeps(options) {
284
+ console.log(chalk.bold.cyan("\n\u2501\u2501\u2501 \u7B2C 1 \u6B65: \u68C0\u6D4B\u7CFB\u7EDF\u4F9D\u8D56 \u2501\u2501\u2501\n"));
285
+ const spinner = ora("\u68C0\u6D4B\u7CFB\u7EDF\u72B6\u6001...").start();
317
286
  const status = await checkAllDependencies();
318
287
  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"));
288
+ console.log(chalk.bold("\u5F53\u524D\u72B6\u6001:"));
289
+ 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")}`);
290
+ 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")}`);
291
+ console.log(` \u{1F4E6} Qdrant: ${status.qdrant.running ? chalk.green("\u2713 \u8FD0\u884C\u4E2D") : chalk.red("\u2717 \u672A\u8FD0\u884C")}`);
292
+ console.log(` \u{1F524} BGE-M3: ${status.bgeM3.installed ? chalk.green("\u2713 \u5DF2\u5B89\u88C5") : chalk.red("\u2717 \u672A\u5B89\u88C5")}`);
293
+ console.log("");
294
+ if (isSystemReady(status)) {
295
+ console.log(chalk.green("\u2705 \u6240\u6709\u4F9D\u8D56\u5DF2\u5C31\u7EEA!\n"));
296
+ return true;
297
+ }
298
+ if (options.skipDeps) {
299
+ console.log(chalk.yellow("\u26A0\uFE0F \u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5 (--skip-deps)\n"));
300
+ return true;
301
+ }
302
+ if (!options.yes) {
303
+ const { confirm } = await inquirer.prompt([{
304
+ type: "confirm",
305
+ name: "confirm",
306
+ message: "\u9700\u8981\u5B89\u88C5/\u542F\u52A8\u7F3A\u5931\u7684\u4F9D\u8D56\uFF0C\u662F\u5426\u7EE7\u7EED?",
307
+ default: true
308
+ }]);
309
+ if (!confirm) {
310
+ console.log(chalk.yellow("\n\u5DF2\u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5\uFF0C\u7EE7\u7EED\u9879\u76EE\u914D\u7F6E...\n"));
311
+ return true;
312
+ }
313
+ }
314
+ if (!status.docker.installed) {
315
+ console.log(chalk.yellow("\n\u{1F4E6} Docker \u9700\u8981\u624B\u52A8\u5B89\u88C5"));
316
+ console.log(chalk.gray(" \u8BF7\u8BBF\u95EE https://docker.com/download \u4E0B\u8F7D\u5B89\u88C5"));
322
317
  if (!options.yes) {
323
- const { cont } = await inquirer2.prompt([{
318
+ const { openDocker } = await inquirer.prompt([{
324
319
  type: "confirm",
325
- name: "cont",
326
- message: "\u662F\u5426\u7EE7\u7EED\u521D\u59CB\u5316?",
327
- default: false
320
+ name: "openDocker",
321
+ message: "\u662F\u5426\u6253\u5F00 Docker \u4E0B\u8F7D\u9875\u9762?",
322
+ default: true
328
323
  }]);
329
- if (!cont) return;
324
+ if (openDocker) await openUrl("https://docker.com/download");
325
+ await inquirer.prompt([{ type: "input", name: "wait", message: "\u5B89\u88C5\u5B8C\u6210\u540E\u6309 Enter \u7EE7\u7EED..." }]);
330
326
  }
331
327
  }
328
+ if (!status.ollama.installed) {
329
+ await installOllama();
330
+ }
331
+ if (status.ollama.installed && !status.ollama.running) {
332
+ await startOllama();
333
+ }
334
+ if (!status.bgeM3.installed) {
335
+ await pullBgeM3();
336
+ }
337
+ if (!status.qdrant.running && (status.docker.running || status.docker.installed)) {
338
+ await startQdrant();
339
+ }
340
+ console.log(chalk.green("\n\u2705 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210!\n"));
341
+ return true;
342
+ }
343
+ async function phase2_initProject(options) {
344
+ console.log(chalk.bold.cyan("\n\u2501\u2501\u2501 \u7B2C 2 \u6B65: \u914D\u7F6E\u9879\u76EE \u2501\u2501\u2501\n"));
332
345
  let ide = options.ide?.toLowerCase();
333
346
  if (!ide || !IDE_CONFIGS[ide]) {
334
- const { selectedIde } = await inquirer2.prompt([{
347
+ const { selectedIde } = await inquirer.prompt([{
335
348
  type: "list",
336
349
  name: "selectedIde",
337
350
  message: "\u9009\u62E9 IDE \u7C7B\u578B:",
@@ -346,11 +359,11 @@ async function initCommand(options) {
346
359
  }]);
347
360
  ide = selectedIde;
348
361
  }
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([{
362
+ const cwd = process.cwd();
363
+ const defaultName = cwd.split("/").pop() || "my-project";
364
+ let projectName = defaultName;
365
+ if (!options.yes) {
366
+ const { name } = await inquirer.prompt([{
354
367
  type: "input",
355
368
  name: "name",
356
369
  message: "\u9879\u76EE\u540D\u79F0:",
@@ -359,91 +372,99 @@ async function initCommand(options) {
359
372
  projectName = name;
360
373
  }
361
374
  const config = IDE_CONFIGS[ide];
362
- const cwd = process.cwd();
363
- console.log(chalk2.bold("\n\u{1F4C1} \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6..."));
375
+ console.log(chalk.bold("\n\u{1F4C1} \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6...\n"));
364
376
  const memoryDir = join(cwd, ".memory");
365
377
  if (!existsSync(memoryDir)) {
366
378
  mkdirSync(memoryDir, { recursive: true });
367
- console.log(chalk2.green(" \u2713 \u521B\u5EFA .memory/"));
368
379
  }
380
+ console.log(chalk.green(" \u2713 \u521B\u5EFA .memory/"));
369
381
  const projectYaml = join(memoryDir, "project.yaml");
370
382
  writeFileSync(projectYaml, generateProjectYaml(projectName));
371
- console.log(chalk2.green(" \u2713 \u521B\u5EFA .memory/project.yaml"));
383
+ console.log(chalk.green(" \u2713 \u521B\u5EFA .memory/project.yaml"));
372
384
  const templatesDir = getTemplatesDir();
385
+ const memoryTemplatesDir = join(templatesDir, "shared", "memory");
386
+ if (existsSync(memoryTemplatesDir)) {
387
+ const memoryFiles = readdirSync(memoryTemplatesDir);
388
+ for (const file of memoryFiles) {
389
+ const srcPath = join(memoryTemplatesDir, file);
390
+ const destPath = join(memoryDir, file);
391
+ const content = readFileSync(srcPath, "utf-8");
392
+ writeFileSync(destPath, processTemplate(content, projectName));
393
+ }
394
+ console.log(chalk.green(` \u2713 \u521B\u5EFA .memory/ (${memoryFiles.length} \u4E2A\u6838\u5FC3\u6587\u4EF6)`));
395
+ }
373
396
  const sharedTemplates = join(templatesDir, "shared");
374
397
  const ideTemplates = join(templatesDir, ide === "common" ? "common" : ide);
375
398
  const commandsDir = join(cwd, config.dir, config.commandsDir);
376
399
  mkdirSync(commandsDir, { recursive: true });
377
400
  copyDir(join(sharedTemplates, "commands"), commandsDir);
378
- console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.commandsDir}/ (6 \u4E2A\u547D\u4EE4)`));
401
+ console.log(chalk.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.commandsDir}/ (memory.md)`));
402
+ const commandsParentDir = dirname(join(cwd, config.dir, config.commandsDir));
403
+ const memoryActionsDir = join(commandsParentDir, "memory-actions");
404
+ mkdirSync(memoryActionsDir, { recursive: true });
405
+ copyDir(join(sharedTemplates, "memory-actions"), memoryActionsDir);
406
+ const actionsCount = existsSync(join(sharedTemplates, "memory-actions")) ? readdirSync(join(sharedTemplates, "memory-actions")).length : 0;
407
+ const memoryActionsDisplayPath = memoryActionsDir.replace(cwd + "/", "");
408
+ console.log(chalk.green(` \u2713 \u521B\u5EFA ${memoryActionsDisplayPath}/ (${actionsCount} \u4E2A\u5B50\u52A8\u4F5C)`));
379
409
  const skillsDir = join(cwd, config.dir, config.skillsDir);
380
410
  mkdirSync(skillsDir, { recursive: true });
381
411
  copyDir(join(sharedTemplates, "skills"), skillsDir);
382
- console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.skillsDir}/ (memory-extraction)`));
412
+ console.log(chalk.green(` \u2713 \u521B\u5EFA ${config.dir}/${config.skillsDir}/ (memory-extraction)`));
383
413
  const rulesDir = join(cwd, config.rulesDir);
384
414
  mkdirSync(rulesDir, { recursive: true });
385
415
  copyDir(join(sharedTemplates, "rules"), rulesDir);
386
- console.log(chalk2.green(` \u2713 \u521B\u5EFA ${config.rulesDir}/ (classification.md)`));
416
+ console.log(chalk.green(` \u2713 \u521B\u5EFA ${config.rulesDir}/ (classification.md)`));
387
417
  if (existsSync(ideTemplates)) {
388
418
  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);
419
+ console.log(chalk.green(` \u2713 \u590D\u5236 ${config.configFile}`));
393
420
  }
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"));
421
+ return ide;
422
+ }
423
+ function phase3_showCompletion(ide, showMcp) {
424
+ console.log(chalk.bold.cyan("\n\u2501\u2501\u2501 \u5B89\u88C5\u5B8C\u6210 \u2501\u2501\u2501\n"));
425
+ console.log(chalk.green.bold("\u{1F389} OpenMemory Plus \u5DF2\u6210\u529F\u5B89\u88C5!\n"));
426
+ console.log(chalk.bold("\u{1F4A1} \u4E0B\u4E00\u6B65:"));
427
+ console.log(chalk.gray(" 1. \u5728 IDE \u4E2D\u6253\u5F00\u9879\u76EE"));
428
+ console.log(chalk.gray(" 2. \u4F7F\u7528 ") + chalk.cyan("/memory") + chalk.gray(" \u6253\u5F00\u8BB0\u5FC6\u7BA1\u7406\u83DC\u5355"));
429
+ console.log(chalk.gray(" 3. \u9009\u62E9\u64CD\u4F5C\u6216\u7528\u81EA\u7136\u8BED\u8A00\u63CF\u8FF0\u9700\u6C42"));
430
+ console.log("");
431
+ if (showMcp) {
432
+ showMcpConfig(ide);
433
+ } else {
434
+ console.log(chalk.gray("\u{1F4CB} \u67E5\u770B MCP \u914D\u7F6E: ") + chalk.cyan("npx openmemory-plus install --show-mcp"));
399
435
  }
436
+ console.log("");
400
437
  }
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}`));
438
+ async function installCommand(options) {
439
+ console.log(chalk.cyan(BANNER));
440
+ if (options.showMcp) {
441
+ const ide2 = options.ide || "augment";
442
+ showMcpConfig(ide2);
443
+ return;
444
+ }
445
+ await phase1_checkAndInstallDeps(options);
446
+ const ide = await phase2_initProject(options);
447
+ phase3_showCompletion(ide, false);
427
448
  }
428
449
 
429
450
  // src/commands/status.ts
430
- import chalk3 from "chalk";
431
- import ora3 from "ora";
451
+ import chalk2 from "chalk";
452
+ import ora2 from "ora";
432
453
  function formatStatus(dep) {
433
454
  if (!dep.installed) {
434
- return chalk3.red("\u2717 \u672A\u5B89\u88C5");
455
+ return chalk2.red("\u2717 \u672A\u5B89\u88C5");
435
456
  }
436
457
  if (dep.running === false) {
437
- return chalk3.yellow("\u26A0 \u5DF2\u5B89\u88C5\u4F46\u672A\u8FD0\u884C");
458
+ return chalk2.yellow("\u26A0 \u5DF2\u5B89\u88C5\u4F46\u672A\u8FD0\u884C");
438
459
  }
439
460
  if (dep.running === true) {
440
- const ver = dep.version ? chalk3.gray(` (${dep.version})`) : "";
441
- return chalk3.green("\u2713 \u8FD0\u884C\u4E2D") + ver;
461
+ const ver = dep.version ? chalk2.gray(` (${dep.version})`) : "";
462
+ return chalk2.green("\u2713 \u8FD0\u884C\u4E2D") + ver;
442
463
  }
443
- return chalk3.green("\u2713 \u5DF2\u5B89\u88C5");
464
+ return chalk2.green("\u2713 \u5DF2\u5B89\u88C5");
444
465
  }
445
466
  function printStatusTable(status) {
446
- console.log("\n" + chalk3.bold("\u4F9D\u8D56\u68C0\u6D4B\u7ED3\u679C:"));
467
+ console.log("\n" + chalk2.bold("\u4F9D\u8D56\u68C0\u6D4B\u7ED3\u679C:"));
447
468
  console.log("");
448
469
  const deps = [
449
470
  { ...status.docker, icon: "\u{1F433}" },
@@ -454,36 +475,36 @@ function printStatusTable(status) {
454
475
  ];
455
476
  for (const dep of deps) {
456
477
  const statusStr = formatStatus(dep);
457
- const errorStr = dep.error && !dep.installed ? chalk3.gray(` - ${dep.error}`) : "";
478
+ const errorStr = dep.error && !dep.installed ? chalk2.gray(` - ${dep.error}`) : "";
458
479
  console.log(` ${dep.icon} ${dep.name.padEnd(16)} ${statusStr}${errorStr}`);
459
480
  }
460
481
  console.log("");
461
482
  }
462
483
  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();
484
+ console.log(chalk2.cyan.bold("\n\u{1F9E0} OpenMemory Plus - \u7CFB\u7EDF\u72B6\u6001\n"));
485
+ const spinner = ora2("\u68C0\u6D4B\u7CFB\u7EDF\u4F9D\u8D56...").start();
465
486
  try {
466
487
  const status = await checkAllDependencies();
467
488
  spinner.stop();
468
489
  printStatusTable(status);
469
490
  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"));
491
+ console.log(chalk2.green.bold("\u2705 \u7CFB\u7EDF\u5C31\u7EEA! OpenMemory Plus \u53EF\u6B63\u5E38\u4F7F\u7528\u3002\n"));
492
+ console.log(chalk2.gray("\u63D0\u793A: \u4F7F\u7528 /memory \u547D\u4EE4\u67E5\u770B\u8BB0\u5FC6\u72B6\u6001"));
472
493
  } 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"));
494
+ 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"));
495
+ console.log(chalk2.gray("\u8FD0\u884C ") + chalk2.cyan("openmemory-plus install") + chalk2.gray(" \u5B89\u88C5\u7F3A\u5931\u4F9D\u8D56"));
496
+ console.log(chalk2.gray("\u8FD0\u884C ") + chalk2.cyan("openmemory-plus doctor") + chalk2.gray(" \u8BCA\u65AD\u5E76\u4FEE\u590D\u95EE\u9898"));
476
497
  }
477
498
  } catch (error) {
478
499
  spinner.fail("\u68C0\u6D4B\u5931\u8D25");
479
- console.error(chalk3.red("\u9519\u8BEF:"), error);
500
+ console.error(chalk2.red("\u9519\u8BEF:"), error);
480
501
  process.exit(1);
481
502
  }
482
503
  }
483
504
 
484
505
  // src/commands/doctor.ts
485
- import chalk4 from "chalk";
486
- import ora4 from "ora";
506
+ import chalk3 from "chalk";
507
+ import ora3 from "ora";
487
508
  import { exec as exec3 } from "child_process";
488
509
  import { promisify as promisify3 } from "util";
489
510
  var execAsync3 = promisify3(exec3);
@@ -501,7 +522,7 @@ function diagnoseIssues(status) {
501
522
  description: "\u8BF7\u542F\u52A8 Docker Desktop \u5E94\u7528",
502
523
  severity: "error",
503
524
  fix: async () => {
504
- console.log(chalk4.yellow(" \u8BF7\u624B\u52A8\u542F\u52A8 Docker Desktop"));
525
+ console.log(chalk3.yellow(" \u8BF7\u624B\u52A8\u542F\u52A8 Docker Desktop"));
505
526
  return false;
506
527
  }
507
528
  });
@@ -569,28 +590,28 @@ function diagnoseIssues(status) {
569
590
  return issues;
570
591
  }
571
592
  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();
593
+ console.log(chalk3.cyan.bold("\n\u{1FA7A} OpenMemory Plus - \u95EE\u9898\u8BCA\u65AD\n"));
594
+ const spinner = ora3("\u68C0\u6D4B\u7CFB\u7EDF\u72B6\u6001...").start();
574
595
  const status = await checkAllDependencies();
575
596
  spinner.stop();
576
597
  const issues = diagnoseIssues(status);
577
598
  if (issues.length === 0) {
578
- console.log(chalk4.green.bold("\u2705 \u672A\u53D1\u73B0\u95EE\u9898\uFF0C\u7CFB\u7EDF\u8FD0\u884C\u6B63\u5E38!\n"));
599
+ console.log(chalk3.green.bold("\u2705 \u672A\u53D1\u73B0\u95EE\u9898\uFF0C\u7CFB\u7EDF\u8FD0\u884C\u6B63\u5E38!\n"));
579
600
  return;
580
601
  }
581
- console.log(chalk4.yellow.bold(`\u53D1\u73B0 ${issues.length} \u4E2A\u95EE\u9898:
602
+ console.log(chalk3.yellow.bold(`\u53D1\u73B0 ${issues.length} \u4E2A\u95EE\u9898:
582
603
  `));
583
604
  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)}`);
605
+ const icon = issue.severity === "error" ? chalk3.red("\u2717") : chalk3.yellow("\u26A0");
606
+ console.log(` ${icon} ${chalk3.bold(issue.name)}`);
607
+ console.log(` ${chalk3.gray(issue.description)}`);
587
608
  }
588
609
  console.log("");
589
610
  if (options.fix) {
590
- console.log(chalk4.bold("\u5C1D\u8BD5\u81EA\u52A8\u4FEE\u590D...\n"));
611
+ console.log(chalk3.bold("\u5C1D\u8BD5\u81EA\u52A8\u4FEE\u590D...\n"));
591
612
  for (const issue of issues) {
592
613
  if (issue.fix) {
593
- const fixSpinner = ora4(`\u4FEE\u590D: ${issue.name}`).start();
614
+ const fixSpinner = ora3(`\u4FEE\u590D: ${issue.name}`).start();
594
615
  const success = await issue.fix();
595
616
  if (success) {
596
617
  fixSpinner.succeed(`\u5DF2\u4FEE\u590D: ${issue.name}`);
@@ -599,12 +620,12 @@ async function doctorCommand(options) {
599
620
  }
600
621
  }
601
622
  }
602
- console.log(chalk4.gray("\n\u8FD0\u884C ") + chalk4.cyan("openmemory-plus status") + chalk4.gray(" \u9A8C\u8BC1\u4FEE\u590D\u7ED3\u679C"));
623
+ console.log(chalk3.gray("\n\u8FD0\u884C ") + chalk3.cyan("openmemory-plus status") + chalk3.gray(" \u9A8C\u8BC1\u4FEE\u590D\u7ED3\u679C"));
603
624
  } else {
604
625
  const fixable = issues.filter((i) => i.fix).length;
605
626
  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"));
627
+ console.log(chalk3.gray(`${fixable} \u4E2A\u95EE\u9898\u53EF\u81EA\u52A8\u4FEE\u590D`));
628
+ console.log(chalk3.gray("\u8FD0\u884C ") + chalk3.cyan("openmemory-plus doctor --fix") + chalk3.gray(" \u5C1D\u8BD5\u4FEE\u590D"));
608
629
  }
609
630
  }
610
631
  console.log("");
@@ -612,19 +633,8 @@ async function doctorCommand(options) {
612
633
 
613
634
  // src/index.ts
614
635
  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
- });
636
+ 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");
637
+ 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);
638
+ program.command("status").description("\u68C0\u67E5\u7CFB\u7EDF\u72B6\u6001").action(statusCommand);
639
+ program.command("doctor").description("\u8BCA\u65AD\u5E76\u4FEE\u590D\u95EE\u9898").option("--fix", "\u81EA\u52A8\u4FEE\u590D\u95EE\u9898").action(doctorCommand);
630
640
  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.2.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
-