engine7 7.0.3 → 7.0.4

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
@@ -40,6 +40,7 @@ Engine 7 \u2014 Self-hosted AI agent engine
40
40
  \u7528\u6CD5:
41
41
  engine7 init --state-dir <path> [\u9009\u9879] \u521D\u59CB\u5316 agent \u5DE5\u4F5C\u76EE\u5F55
42
42
  engine7 start [--config <path>] \u542F\u52A8 Engine
43
+ engine7 service install|uninstall|status \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
43
44
 
44
45
  init \u9009\u9879:
45
46
  --state-dir <path> agent \u6839\u76EE\u5F55\uFF08\u5FC5\u586B\uFF0C\u652F\u6301\u76F8\u5BF9\u8DEF\u5F84\uFF09
@@ -92,6 +93,7 @@ function getDefaultValues(stateDir) {
92
93
  feishuAppId: "",
93
94
  feishuAppSecret: "",
94
95
  feishuOpenId: "",
96
+ tavilyKey: "",
95
97
  apiPort: 16990
96
98
  };
97
99
  }
@@ -157,6 +159,8 @@ async function interactiveConfig(rl, defaults) {
157
159
  v.feishuAppSecret = await ask(rl, "\u98DE\u4E66 App Secret");
158
160
  v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id");
159
161
  }
162
+ const tavilyKey = await ask(rl, "Tavily API Key\uFF08\u8054\u7F51\u641C\u7D22\uFF0C\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
163
+ v.tavilyKey = tavilyKey;
160
164
  const portAns = await ask(rl, "API \u7AEF\u53E3", String(defaults.apiPort));
161
165
  v.apiPort = parseInt(portAns, 10) || defaults.apiPort;
162
166
  return v;
@@ -170,7 +174,7 @@ function generateConfig(v) {
170
174
  models: {
171
175
  providers: {}
172
176
  },
173
- tools: {},
177
+ tools: v.tavilyKey ? { tavily: { apiKey: v.tavilyKey } } : {},
174
178
  session: { dmScope: "main", groupScope: "main" },
175
179
  sandbox: { mode: "off" },
176
180
  display: {
@@ -321,6 +325,7 @@ function buildDirTree(v) {
321
325
  type: "file",
322
326
  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
327
  },
328
+ { path: path.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
324
329
  { 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
330
  { 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
331
  // package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
@@ -510,6 +515,171 @@ engine7 start \u2014 \u542F\u52A8 Engine
510
515
  child.on("exit", (code) => process.exit(code ?? 1));
511
516
  return;
512
517
  }
518
+ if (subcommand === "service") {
519
+ const action = args[1];
520
+ if (!action || action === "--help" || action === "-h") {
521
+ console.log(`
522
+ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
523
+
524
+ \u7528\u6CD5:
525
+ engine7 service install \u5B89\u88C5\u5F00\u673A\u81EA\u542F\u52A8
526
+ engine7 service uninstall \u5378\u8F7D\u5F00\u673A\u81EA\u542F\u52A8
527
+ engine7 service status \u67E5\u770B\u72B6\u6001
528
+
529
+ \u9009\u9879:
530
+ --config <path> \u6307\u5B9A config \u6587\u4EF6\uFF08\u9ED8\u8BA4: configs/main7.json\uFF09
531
+ --cwd <path> engine7 \u5DE5\u4F5C\u76EE\u5F55\uFF08\u9ED8\u8BA4: \u5F53\u524D\u76EE\u5F55\uFF09
532
+ `);
533
+ process.exit(0);
534
+ }
535
+ let configPath2 = "";
536
+ let cwd = process.cwd();
537
+ for (let i = 2; i < args.length; i++) {
538
+ if (args[i] === "--config" && args[i + 1]) configPath2 = args[++i];
539
+ else if (args[i] === "--cwd" && args[i + 1]) cwd = args[++i];
540
+ }
541
+ if (!configPath2) {
542
+ const defaultCfg = path.join(cwd, "configs", "main7.json");
543
+ configPath2 = fs.existsSync(defaultCfg) ? defaultCfg : path.join(cwd, "configs", "main7.json");
544
+ }
545
+ const { execSync } = await import("node:child_process");
546
+ const engine7Bin = process.argv[1];
547
+ if (action === "install") {
548
+ if (process.platform === "win32") {
549
+ const taskName = "Engine7";
550
+ const cmd = `"${engine7Bin}" start --config "${path.resolve(configPath2)}"`;
551
+ try {
552
+ execSync(`schtasks /create /tn "${taskName}" /tr "${cmd}" /sc onlogon /rl highest /f`, { stdio: "inherit", shell: true });
553
+ console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1 "${taskName}" \u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
554
+ } catch {
555
+ console.error("\u274C \u521B\u5EFA\u8BA1\u5212\u4EFB\u52A1\u5931\u8D25\uFF0C\u53EF\u80FD\u9700\u8981\u7BA1\u7406\u5458\u6743\u9650");
556
+ process.exit(1);
557
+ }
558
+ } else if (process.platform === "darwin") {
559
+ const label = "com.engine7.agent";
560
+ const plistDir = path.join(process.env.HOME, "Library", "LaunchAgents");
561
+ fs.mkdirSync(plistDir, { recursive: true });
562
+ const plistPath = path.join(plistDir, `${label}.plist`);
563
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
564
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
565
+ <plist version="1.0">
566
+ <dict>
567
+ <key>Label</key><string>${label}</string>
568
+ <key>ProgramArguments</key>
569
+ <array>
570
+ <string>${process.execPath}</string>
571
+ <string>${engine7Bin}</string>
572
+ <string>start</string>
573
+ <string>--config</string>
574
+ <string>${path.resolve(configPath2)}</string>
575
+ </array>
576
+ <key>WorkingDirectory</key><string>${cwd}</string>
577
+ <key>RunAtLoad</key><true/>
578
+ <key>KeepAlive</key><true/>
579
+ </dict>
580
+ </plist>`;
581
+ fs.writeFileSync(plistPath, plist);
582
+ try {
583
+ execSync(`launchctl load "${plistPath}"`, { stdio: "inherit" });
584
+ console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
585
+ console.log(` ${plistPath}`);
586
+ } catch {
587
+ console.error("\u274C launchctl load \u5931\u8D25");
588
+ process.exit(1);
589
+ }
590
+ } else {
591
+ const svcName = "engine7";
592
+ const svcDir = path.join(process.env.HOME, ".config", "systemd", "user");
593
+ fs.mkdirSync(svcDir, { recursive: true });
594
+ const svcPath = path.join(svcDir, `${svcName}.service`);
595
+ const svc = `[Unit]
596
+ Description=Engine 7 Agent
597
+ After=network.target
598
+
599
+ [Service]
600
+ Type=simple
601
+ WorkingDirectory=${cwd}
602
+ ExecStart=${process.execPath} ${engine7Bin} start --config ${path.resolve(configPath2)}
603
+ Restart=on-failure
604
+ RestartSec=10
605
+
606
+ [Install]
607
+ WantedBy=default.target`;
608
+ fs.writeFileSync(svcPath, svc);
609
+ try {
610
+ execSync(`systemctl --user daemon-reload`, { stdio: "inherit" });
611
+ execSync(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
612
+ console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
613
+ console.log(` ${svcPath}`);
614
+ } catch {
615
+ console.error("\u274C systemctl enable \u5931\u8D25");
616
+ process.exit(1);
617
+ }
618
+ }
619
+ } else if (action === "uninstall") {
620
+ if (process.platform === "win32") {
621
+ try {
622
+ execSync(`schtasks /delete /tn "Engine7" /f`, { stdio: "inherit", shell: true });
623
+ console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1\u5DF2\u5220\u9664`);
624
+ } catch {
625
+ console.error("\u274C \u5220\u9664\u5931\u8D25\uFF0C\u4EFB\u52A1\u53EF\u80FD\u4E0D\u5B58\u5728");
626
+ process.exit(1);
627
+ }
628
+ } else if (process.platform === "darwin") {
629
+ const plistPath = path.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
630
+ try {
631
+ execSync(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
632
+ } catch {
633
+ }
634
+ try {
635
+ fs.unlinkSync(plistPath);
636
+ } catch {
637
+ }
638
+ console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
639
+ } else {
640
+ try {
641
+ execSync(`systemctl --user disable engine7`, { stdio: "inherit" });
642
+ } catch {
643
+ }
644
+ const svcPath = path.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
645
+ try {
646
+ fs.unlinkSync(svcPath);
647
+ } catch {
648
+ }
649
+ try {
650
+ execSync(`systemctl --user daemon-reload`, { stdio: "inherit" });
651
+ } catch {
652
+ }
653
+ console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u5220\u9664`);
654
+ }
655
+ } else if (action === "status") {
656
+ if (process.platform === "win32") {
657
+ try {
658
+ execSync(`schtasks /query /tn "Engine7"`, { stdio: "inherit", shell: true });
659
+ } catch {
660
+ console.log("\u274C \u672A\u5B89\u88C5");
661
+ }
662
+ } else if (process.platform === "darwin") {
663
+ const plistPath = path.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
664
+ if (fs.existsSync(plistPath)) {
665
+ console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
666
+ } else {
667
+ console.log("\u274C \u672A\u5B89\u88C5");
668
+ }
669
+ } else {
670
+ try {
671
+ execSync(`systemctl --user is-enabled engine7`, { stdio: "inherit" });
672
+ } catch {
673
+ console.log("\u274C \u672A\u5B89\u88C5");
674
+ }
675
+ }
676
+ } else {
677
+ console.error(`\u274C \u672A\u77E5\u64CD\u4F5C: ${action}`);
678
+ console.error(" \u7528\u6CD5: engine7 service install|uninstall|status");
679
+ process.exit(1);
680
+ }
681
+ process.exit(0);
682
+ }
513
683
  const opts = parseArgs();
514
684
  console.log(`
515
685
  \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.4",
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
+ - 记忆可能不是最新的了,以你现在感受到的为准。