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 +200 -190
- package/package.json +10 -6
- package/templates/augment/AGENTS.md +78 -0
- package/templates/claude/CLAUDE.md +52 -0
- package/templates/common/AGENTS.md +51 -0
- package/templates/cursor/.cursorrules +57 -0
- package/templates/gemini/gemini.md +77 -0
- package/templates/shared/commands/memory.md +86 -0
- package/templates/shared/memory/activeContext.md +34 -0
- package/templates/shared/memory/productContext.md +30 -0
- package/templates/shared/memory/progress.md +41 -0
- package/templates/shared/memory/projectbrief.md +36 -0
- package/templates/shared/memory/systemPatterns.md +39 -0
- package/templates/shared/memory/techContext.md +51 -0
- package/templates/shared/memory-actions/clean.md +54 -0
- package/templates/shared/memory-actions/decay.md +64 -0
- package/templates/shared/memory-actions/graph.md +75 -0
- package/templates/shared/memory-actions/search.md +38 -0
- package/templates/shared/memory-actions/status.md +35 -0
- package/templates/shared/memory-actions/store.md +45 -0
- package/templates/shared/memory-actions/sync.md +50 -0
- package/templates/shared/rules/classification.md +108 -0
- package/templates/shared/skills/memory-extraction/SKILL.md +394 -0
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
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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 {
|
|
318
|
+
const { openDocker } = await inquirer.prompt([{
|
|
324
319
|
type: "confirm",
|
|
325
|
-
name: "
|
|
326
|
-
message: "\u662F\u5426\
|
|
327
|
-
default:
|
|
320
|
+
name: "openDocker",
|
|
321
|
+
message: "\u662F\u5426\u6253\u5F00 Docker \u4E0B\u8F7D\u9875\u9762?",
|
|
322
|
+
default: true
|
|
328
323
|
}]);
|
|
329
|
-
if (
|
|
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
|
|
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
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const { name } = await
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
390
|
-
}
|
|
391
|
-
if (options.generateMcp) {
|
|
392
|
-
generateMcpConfig(ide);
|
|
419
|
+
console.log(chalk.green(` \u2713 \u590D\u5236 ${config.configFile}`));
|
|
393
420
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
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
|
|
402
|
-
console.log(
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
|
431
|
-
import
|
|
451
|
+
import chalk2 from "chalk";
|
|
452
|
+
import ora2 from "ora";
|
|
432
453
|
function formatStatus(dep) {
|
|
433
454
|
if (!dep.installed) {
|
|
434
|
-
return
|
|
455
|
+
return chalk2.red("\u2717 \u672A\u5B89\u88C5");
|
|
435
456
|
}
|
|
436
457
|
if (dep.running === false) {
|
|
437
|
-
return
|
|
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 ?
|
|
441
|
-
return
|
|
461
|
+
const ver = dep.version ? chalk2.gray(` (${dep.version})`) : "";
|
|
462
|
+
return chalk2.green("\u2713 \u8FD0\u884C\u4E2D") + ver;
|
|
442
463
|
}
|
|
443
|
-
return
|
|
464
|
+
return chalk2.green("\u2713 \u5DF2\u5B89\u88C5");
|
|
444
465
|
}
|
|
445
466
|
function printStatusTable(status) {
|
|
446
|
-
console.log("\n" +
|
|
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 ?
|
|
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(
|
|
464
|
-
const spinner =
|
|
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(
|
|
471
|
-
console.log(
|
|
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(
|
|
474
|
-
console.log(
|
|
475
|
-
console.log(
|
|
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(
|
|
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
|
|
486
|
-
import
|
|
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(
|
|
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(
|
|
573
|
-
const spinner =
|
|
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(
|
|
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(
|
|
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" ?
|
|
585
|
-
console.log(` ${icon} ${
|
|
586
|
-
console.log(` ${
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
607
|
-
console.log(
|
|
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
|
|
616
|
-
program.command("install").description("
|
|
617
|
-
program.command("
|
|
618
|
-
program.command("
|
|
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.
|
|
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": "
|
|
8
|
-
"omp": "
|
|
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
|
-
|