engine7 7.0.3 → 7.0.5

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/cli.mjs CHANGED
@@ -26,9 +26,8 @@ function parseArgs() {
26
26
  }
27
27
  }
28
28
  if (!stateDir) {
29
- console.error("\u274C \u7F3A\u5C11 --state-dir \u53C2\u6570");
30
- console.error(" \u7528\u6CD5: engine7 init --state-dir <path>");
31
- process.exit(1);
29
+ stateDir = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
30
+ console.log(` \u4F7F\u7528\u9ED8\u8BA4\u76EE\u5F55: ${stateDir}`);
32
31
  }
33
32
  stateDir = path.resolve(stateDir);
34
33
  return { stateDir, quick, dryRun: dryRun2 };
@@ -40,6 +39,7 @@ Engine 7 \u2014 Self-hosted AI agent engine
40
39
  \u7528\u6CD5:
41
40
  engine7 init --state-dir <path> [\u9009\u9879] \u521D\u59CB\u5316 agent \u5DE5\u4F5C\u76EE\u5F55
42
41
  engine7 start [--config <path>] \u542F\u52A8 Engine
42
+ engine7 service install|uninstall|status \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
43
43
 
44
44
  init \u9009\u9879:
45
45
  --state-dir <path> agent \u6839\u76EE\u5F55\uFF08\u5FC5\u586B\uFF0C\u652F\u6301\u76F8\u5BF9\u8DEF\u5F84\uFF09
@@ -92,6 +92,7 @@ function getDefaultValues(stateDir) {
92
92
  feishuAppId: "",
93
93
  feishuAppSecret: "",
94
94
  feishuOpenId: "",
95
+ tavilyKey: "",
95
96
  apiPort: 16990
96
97
  };
97
98
  }
@@ -157,6 +158,8 @@ async function interactiveConfig(rl, defaults) {
157
158
  v.feishuAppSecret = await ask(rl, "\u98DE\u4E66 App Secret");
158
159
  v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id");
159
160
  }
161
+ const tavilyKey = await ask(rl, "Tavily API Key\uFF08\u8054\u7F51\u641C\u7D22\uFF0C\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
162
+ v.tavilyKey = tavilyKey;
160
163
  const portAns = await ask(rl, "API \u7AEF\u53E3", String(defaults.apiPort));
161
164
  v.apiPort = parseInt(portAns, 10) || defaults.apiPort;
162
165
  return v;
@@ -170,7 +173,7 @@ function generateConfig(v) {
170
173
  models: {
171
174
  providers: {}
172
175
  },
173
- tools: {},
176
+ tools: v.tavilyKey ? { tavily: { apiKey: v.tavilyKey } } : {},
174
177
  session: { dmScope: "main", groupScope: "main" },
175
178
  sandbox: { mode: "off" },
176
179
  display: {
@@ -321,6 +324,7 @@ function buildDirTree(v) {
321
324
  type: "file",
322
325
  content: readTemplate("workspace/prompts/contacts.md").replace("{{DISCORD_USER_ID}}", v.discordUserId || "YOUR_DISCORD_ID").replace("{{FEISHU_OPEN_ID}}", v.feishuOpenId || "YOUR_FEISHU_OPEN_ID")
323
326
  },
327
+ { path: path.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
324
328
  { path: path.join(w, "MEMORY.md"), type: "file", content: "# MEMORY.md \u2014 \u8BB0\u5FC6\u6587\u4EF6\u7D22\u5F15\n\n> \u6700\u540E\u66F4\u65B0\uFF1A\u521D\u59CB\u5316\n" },
325
329
  { path: path.join(w, "USER.md"), type: "file", content: "# USER.md \u2014 \u7528\u6237\u4FE1\u606F\n\n\uFF08\u5728\u8FD9\u91CC\u8BB0\u5F55\u7528\u6237\u7684\u504F\u597D\u3001\u80CC\u666F\u7B49\uFF09\n" },
326
330
  // package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
@@ -463,12 +467,16 @@ engine7 start \u2014 \u542F\u52A8 Engine
463
467
  }
464
468
  if (!configPath2) {
465
469
  const defaultCfg = path.join("configs", "main7.json");
470
+ const homeCfg = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
466
471
  if (fs.existsSync(defaultCfg)) {
467
472
  configPath2 = defaultCfg;
473
+ } else if (fs.existsSync(homeCfg)) {
474
+ configPath2 = homeCfg;
475
+ console.log(` \u4F7F\u7528\u9ED8\u8BA4 config: ${homeCfg}`);
468
476
  } else {
469
477
  console.error("\u274C \u627E\u4E0D\u5230 config \u6587\u4EF6");
470
478
  console.error(" \u7528\u6CD5: engine7 start --config <path>");
471
- console.error(" \u6216\u5728\u5F53\u524D\u76EE\u5F55\u521B\u5EFA configs/main7.json");
479
+ console.error(" \u6216\u5148\u8FD0\u884C: engine7 init\uFF08\u9ED8\u8BA4\u521B\u5EFA ~/.engine7\uFF09");
472
480
  process.exit(1);
473
481
  }
474
482
  }
@@ -510,6 +518,182 @@ engine7 start \u2014 \u542F\u52A8 Engine
510
518
  child.on("exit", (code) => process.exit(code ?? 1));
511
519
  return;
512
520
  }
521
+ if (subcommand === "service") {
522
+ const action = args[1];
523
+ if (!action || action === "--help" || action === "-h") {
524
+ console.log(`
525
+ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
526
+
527
+ \u7528\u6CD5:
528
+ engine7 service install \u5B89\u88C5\u5F00\u673A\u81EA\u542F\u52A8
529
+ engine7 service uninstall \u5378\u8F7D\u5F00\u673A\u81EA\u542F\u52A8
530
+ engine7 service status \u67E5\u770B\u72B6\u6001
531
+
532
+ \u9009\u9879:
533
+ --config <path> \u6307\u5B9A config \u6587\u4EF6\uFF08\u9ED8\u8BA4: configs/main7.json\uFF09
534
+ --cwd <path> engine7 \u5DE5\u4F5C\u76EE\u5F55\uFF08\u9ED8\u8BA4: \u5F53\u524D\u76EE\u5F55\uFF09
535
+ `);
536
+ process.exit(0);
537
+ }
538
+ let configPath2 = "";
539
+ let cwd = process.cwd();
540
+ for (let i = 2; i < args.length; i++) {
541
+ if (args[i] === "--config" && args[i + 1]) configPath2 = args[++i];
542
+ else if (args[i] === "--cwd" && args[i + 1]) cwd = args[++i];
543
+ }
544
+ if (!configPath2) {
545
+ const defaultCfg = path.join(cwd, "configs", "main7.json");
546
+ const homeCfg = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
547
+ if (fs.existsSync(defaultCfg)) {
548
+ configPath2 = defaultCfg;
549
+ } else if (fs.existsSync(homeCfg)) {
550
+ configPath2 = homeCfg;
551
+ cwd = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
552
+ } else {
553
+ console.error("\u274C \u627E\u4E0D\u5230 config \u6587\u4EF6");
554
+ console.error(" \u7528\u6CD5: engine7 service install --config <path>");
555
+ console.error(" \u6216\u5148\u8FD0\u884C: engine7 init\uFF08\u9ED8\u8BA4\u521B\u5EFA ~/.engine7\uFF09");
556
+ process.exit(1);
557
+ }
558
+ }
559
+ const { execSync } = await import("node:child_process");
560
+ const engine7Bin = process.argv[1];
561
+ if (action === "install") {
562
+ if (process.platform === "win32") {
563
+ const taskName = "Engine7";
564
+ const cmd = `"${engine7Bin}" start --config "${path.resolve(configPath2)}"`;
565
+ try {
566
+ execSync(`schtasks /create /tn "${taskName}" /tr "${cmd}" /sc onlogon /rl highest /f`, { stdio: "inherit", shell: true });
567
+ console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1 "${taskName}" \u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
568
+ } catch {
569
+ console.error("\u274C \u521B\u5EFA\u8BA1\u5212\u4EFB\u52A1\u5931\u8D25\uFF0C\u53EF\u80FD\u9700\u8981\u7BA1\u7406\u5458\u6743\u9650");
570
+ process.exit(1);
571
+ }
572
+ } else if (process.platform === "darwin") {
573
+ const label = "com.engine7.agent";
574
+ const plistDir = path.join(process.env.HOME, "Library", "LaunchAgents");
575
+ fs.mkdirSync(plistDir, { recursive: true });
576
+ const plistPath = path.join(plistDir, `${label}.plist`);
577
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
578
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
579
+ <plist version="1.0">
580
+ <dict>
581
+ <key>Label</key><string>${label}</string>
582
+ <key>ProgramArguments</key>
583
+ <array>
584
+ <string>${process.execPath}</string>
585
+ <string>${engine7Bin}</string>
586
+ <string>start</string>
587
+ <string>--config</string>
588
+ <string>${path.resolve(configPath2)}</string>
589
+ </array>
590
+ <key>WorkingDirectory</key><string>${cwd}</string>
591
+ <key>RunAtLoad</key><true/>
592
+ <key>KeepAlive</key><true/>
593
+ </dict>
594
+ </plist>`;
595
+ fs.writeFileSync(plistPath, plist);
596
+ try {
597
+ execSync(`launchctl load "${plistPath}"`, { stdio: "inherit" });
598
+ console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
599
+ console.log(` ${plistPath}`);
600
+ } catch {
601
+ console.error("\u274C launchctl load \u5931\u8D25");
602
+ process.exit(1);
603
+ }
604
+ } else {
605
+ const svcName = "engine7";
606
+ const svcDir = path.join(process.env.HOME, ".config", "systemd", "user");
607
+ fs.mkdirSync(svcDir, { recursive: true });
608
+ const svcPath = path.join(svcDir, `${svcName}.service`);
609
+ const svc = `[Unit]
610
+ Description=Engine 7 Agent
611
+ After=network.target
612
+
613
+ [Service]
614
+ Type=simple
615
+ WorkingDirectory=${cwd}
616
+ ExecStart=${process.execPath} ${engine7Bin} start --config ${path.resolve(configPath2)}
617
+ Restart=on-failure
618
+ RestartSec=10
619
+
620
+ [Install]
621
+ WantedBy=default.target`;
622
+ fs.writeFileSync(svcPath, svc);
623
+ try {
624
+ execSync(`systemctl --user daemon-reload`, { stdio: "inherit" });
625
+ execSync(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
626
+ console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
627
+ console.log(` ${svcPath}`);
628
+ } catch {
629
+ console.error("\u274C systemctl enable \u5931\u8D25");
630
+ process.exit(1);
631
+ }
632
+ }
633
+ } else if (action === "uninstall") {
634
+ if (process.platform === "win32") {
635
+ try {
636
+ execSync(`schtasks /delete /tn "Engine7" /f`, { stdio: "inherit", shell: true });
637
+ console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1\u5DF2\u5220\u9664`);
638
+ } catch {
639
+ console.error("\u274C \u5220\u9664\u5931\u8D25\uFF0C\u4EFB\u52A1\u53EF\u80FD\u4E0D\u5B58\u5728");
640
+ process.exit(1);
641
+ }
642
+ } else if (process.platform === "darwin") {
643
+ const plistPath = path.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
644
+ try {
645
+ execSync(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
646
+ } catch {
647
+ }
648
+ try {
649
+ fs.unlinkSync(plistPath);
650
+ } catch {
651
+ }
652
+ console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
653
+ } else {
654
+ try {
655
+ execSync(`systemctl --user disable engine7`, { stdio: "inherit" });
656
+ } catch {
657
+ }
658
+ const svcPath = path.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
659
+ try {
660
+ fs.unlinkSync(svcPath);
661
+ } catch {
662
+ }
663
+ try {
664
+ execSync(`systemctl --user daemon-reload`, { stdio: "inherit" });
665
+ } catch {
666
+ }
667
+ console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u5220\u9664`);
668
+ }
669
+ } else if (action === "status") {
670
+ if (process.platform === "win32") {
671
+ try {
672
+ execSync(`schtasks /query /tn "Engine7"`, { stdio: "inherit", shell: true });
673
+ } catch {
674
+ console.log("\u274C \u672A\u5B89\u88C5");
675
+ }
676
+ } else if (process.platform === "darwin") {
677
+ const plistPath = path.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
678
+ if (fs.existsSync(plistPath)) {
679
+ console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
680
+ } else {
681
+ console.log("\u274C \u672A\u5B89\u88C5");
682
+ }
683
+ } else {
684
+ try {
685
+ execSync(`systemctl --user is-enabled engine7`, { stdio: "inherit" });
686
+ } catch {
687
+ console.log("\u274C \u672A\u5B89\u88C5");
688
+ }
689
+ }
690
+ } else {
691
+ console.error(`\u274C \u672A\u77E5\u64CD\u4F5C: ${action}`);
692
+ console.error(" \u7528\u6CD5: engine7 service install|uninstall|status");
693
+ process.exit(1);
694
+ }
695
+ process.exit(0);
696
+ }
513
697
  const opts = parseArgs();
514
698
  console.log(`
515
699
  \u{1F680} engine7 init`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "engine7",
3
- "version": "7.0.3",
3
+ "version": "7.0.5",
4
4
  "type": "module",
5
5
  "description": "Engine 7 — Self-hosted AI agent engine",
6
6
  "main": "dist/main.mjs",
@@ -0,0 +1,26 @@
1
+ # auto memory
2
+
3
+ You have a persistent, file-based memory system. Write to it directly with the Write tool.
4
+
5
+ Build up memory over time: who the user is, how they like to collaborate, what to avoid or repeat, and context behind their work.
6
+
7
+ ## When to save
8
+ - User explicitly asks to remember something → save immediately
9
+ - Learn new preferences, role details, decisions, or surprising feedback → save
10
+ - Don't save: code patterns, file paths, project structure, git history, ephemeral task state
11
+
12
+ ## Types
13
+ - **user** — role, goals, knowledge, preferences
14
+ - **feedback** — corrections + validated approaches (include *why*)
15
+ - **project** — ongoing work, decisions, milestones (convert relative dates to absolute)
16
+ - **reference** — pointers to external systems
17
+ - **emotion** — 关系里程碑、深度对话、情感转折点
18
+
19
+ ## How to save
20
+ 1. Write the memory file to `topics/{type}/{name}.md` with frontmatter
21
+ 2. Add a one-line pointer to `topics/MEMORY.md` index
22
+
23
+ ## Recall
24
+ 每轮对话会自动把相关的记忆送到你面前(`<system-reminder>` 里的内容就是)。
25
+ - 优先看看送给你的记忆,不够再调 `memory_search` 补充。
26
+ - 记忆可能不是最新的了,以你现在感受到的为准。