engine7 7.1.39 → 7.1.41

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.
Files changed (55) hide show
  1. package/dist/cli.mjs +438 -255
  2. package/dist/engine-startup.mjs +3862 -3486
  3. package/dist/main.mjs +4982 -4606
  4. package/package.json +1 -1
  5. package/templates/config.template.json +2 -1
  6. package/templates/skills/superpowers/brainstorming/SKILL.md +151 -0
  7. package/templates/skills/superpowers/brainstorming/scripts/frame-template.html +213 -0
  8. package/templates/skills/superpowers/brainstorming/scripts/helper.js +167 -0
  9. package/templates/skills/superpowers/brainstorming/scripts/server.cjs +723 -0
  10. package/templates/skills/superpowers/brainstorming/scripts/start-server.sh +209 -0
  11. package/templates/skills/superpowers/brainstorming/scripts/stop-server.sh +120 -0
  12. package/templates/skills/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
  13. package/templates/skills/superpowers/brainstorming/visual-companion.md +298 -0
  14. package/templates/skills/superpowers/dispatching-parallel-agents/SKILL.md +167 -0
  15. package/templates/skills/superpowers/executing-plans/SKILL.md +64 -0
  16. package/templates/skills/superpowers/finishing-a-development-branch/SKILL.md +201 -0
  17. package/templates/skills/superpowers/receiving-code-review/SKILL.md +205 -0
  18. package/templates/skills/superpowers/requesting-code-review/SKILL.md +95 -0
  19. package/templates/skills/superpowers/requesting-code-review/code-reviewer.md +172 -0
  20. package/templates/skills/superpowers/subagent-driven-development/SKILL.md +503 -0
  21. package/templates/skills/superpowers/subagent-driven-development/implementer-prompt.md +142 -0
  22. package/templates/skills/superpowers/subagent-driven-development/re-review-prompt.md +106 -0
  23. package/templates/skills/superpowers/subagent-driven-development/scripts/review-package +46 -0
  24. package/templates/skills/superpowers/subagent-driven-development/scripts/sdd-workspace +40 -0
  25. package/templates/skills/superpowers/subagent-driven-development/scripts/task-brief +41 -0
  26. package/templates/skills/superpowers/subagent-driven-development/task-reviewer-prompt.md +185 -0
  27. package/templates/skills/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
  28. package/templates/skills/superpowers/systematic-debugging/SKILL.md +283 -0
  29. package/templates/skills/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
  30. package/templates/skills/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
  31. package/templates/skills/superpowers/systematic-debugging/defense-in-depth.md +122 -0
  32. package/templates/skills/superpowers/systematic-debugging/find-polluter.sh +72 -0
  33. package/templates/skills/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
  34. package/templates/skills/superpowers/systematic-debugging/test-academic.md +14 -0
  35. package/templates/skills/superpowers/systematic-debugging/test-pressure-1.md +58 -0
  36. package/templates/skills/superpowers/systematic-debugging/test-pressure-2.md +68 -0
  37. package/templates/skills/superpowers/systematic-debugging/test-pressure-3.md +69 -0
  38. package/templates/skills/superpowers/test-driven-development/SKILL.md +320 -0
  39. package/templates/skills/superpowers/test-driven-development/writing-good-tests.md +198 -0
  40. package/templates/skills/superpowers/using-git-worktrees/SKILL.md +167 -0
  41. package/templates/skills/superpowers/using-superpowers/SKILL.md +62 -0
  42. package/templates/skills/superpowers/using-superpowers/references/antigravity-tools.md +23 -0
  43. package/templates/skills/superpowers/using-superpowers/references/codex-tools.md +39 -0
  44. package/templates/skills/superpowers/using-superpowers/references/gemini-tools.md +63 -0
  45. package/templates/skills/superpowers/using-superpowers/references/pi-tools.md +16 -0
  46. package/templates/skills/superpowers/verification-before-completion/SKILL.md +120 -0
  47. package/templates/skills/superpowers/writing-plans/SKILL.md +168 -0
  48. package/templates/skills/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
  49. package/templates/skills/superpowers/writing-skills/SKILL.md +679 -0
  50. package/templates/skills/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
  51. package/templates/skills/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  52. package/templates/skills/superpowers/writing-skills/graphviz-conventions.dot +172 -0
  53. package/templates/skills/superpowers/writing-skills/persuasion-principles.md +187 -0
  54. package/templates/skills/superpowers/writing-skills/render-graphs.js +168 -0
  55. package/templates/skills/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
package/dist/cli.mjs CHANGED
@@ -22,20 +22,20 @@ __export(cli_travel_exports, {
22
22
  loadTravelConfig: () => loadTravelConfig,
23
23
  saveTravelConfig: () => saveTravelConfig
24
24
  });
25
- import * as path from "node:path";
26
- import * as fs from "node:fs";
27
- import * as os from "node:os";
25
+ import * as path2 from "node:path";
26
+ import * as fs2 from "node:fs";
27
+ import * as os2 from "node:os";
28
28
  import { execSync } from "node:child_process";
29
29
  function loadTravelConfig() {
30
30
  try {
31
- if (!fs.existsSync(CONFIG_PATH)) return null;
32
- return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
31
+ if (!fs2.existsSync(CONFIG_PATH)) return null;
32
+ return JSON.parse(fs2.readFileSync(CONFIG_PATH, "utf-8"));
33
33
  } catch {
34
34
  return null;
35
35
  }
36
36
  }
37
37
  function saveTravelConfig(cfg) {
38
- fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
38
+ fs2.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
39
39
  }
40
40
  function sanitizeContent(content, dirs) {
41
41
  let result = content;
@@ -60,7 +60,7 @@ function restoreContent(content, dirs) {
60
60
  return result;
61
61
  }
62
62
  function isTextFile(filePath) {
63
- const ext = path.extname(filePath).toLowerCase();
63
+ const ext = path2.extname(filePath).toLowerCase();
64
64
  return TEXT_EXTENSIONS.has(ext);
65
65
  }
66
66
  function shouldExclude(name) {
@@ -75,14 +75,14 @@ function shouldExclude(name) {
75
75
  }
76
76
  function collectFiles(rootDir, includeSet, optionalSet) {
77
77
  const files = [];
78
- const entries = fs.readdirSync(rootDir, { withFileTypes: true });
78
+ const entries = fs2.readdirSync(rootDir, { withFileTypes: true });
79
79
  for (const entry of entries) {
80
80
  if (shouldExclude(entry.name)) continue;
81
- const fullPath = path.join(rootDir, entry.name);
82
- const realPath = fs.realpathSync(fullPath);
81
+ const fullPath = path2.join(rootDir, entry.name);
82
+ const realPath = fs2.realpathSync(fullPath);
83
83
  if (realPath !== fullPath) {
84
84
  try {
85
- const lstat = fs.lstatSync(fullPath);
85
+ const lstat = fs2.lstatSync(fullPath);
86
86
  if (lstat.isSymbolicLink()) {
87
87
  continue;
88
88
  }
@@ -103,12 +103,12 @@ function collectFiles(rootDir, includeSet, optionalSet) {
103
103
  function collectAllFiles(dir) {
104
104
  const files = [];
105
105
  try {
106
- const entries = fs.readdirSync(dir, { withFileTypes: true });
106
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
107
107
  for (const entry of entries) {
108
108
  if (shouldExclude(entry.name)) continue;
109
- const fullPath = path.join(dir, entry.name);
109
+ const fullPath = path2.join(dir, entry.name);
110
110
  try {
111
- if (fs.lstatSync(fullPath).isSymbolicLink()) continue;
111
+ if (fs2.lstatSync(fullPath).isSymbolicLink()) continue;
112
112
  } catch {
113
113
  }
114
114
  if (entry.isDirectory()) {
@@ -123,30 +123,30 @@ function collectAllFiles(dir) {
123
123
  }
124
124
  function readMainEngineUuid(agentsDir) {
125
125
  try {
126
- const platformMapPath = path.join(agentsDir, "main", "sessions", "platform-map.json");
127
- const indexMapPath = path.join(agentsDir, "main", "sessions", "session-index.json");
128
- if (!fs.existsSync(platformMapPath) || !fs.existsSync(indexMapPath)) return null;
129
- const platformMap = JSON.parse(fs.readFileSync(platformMapPath, "utf-8"));
126
+ const platformMapPath = path2.join(agentsDir, "main", "sessions", "platform-map.json");
127
+ const indexMapPath = path2.join(agentsDir, "main", "sessions", "session-index.json");
128
+ if (!fs2.existsSync(platformMapPath) || !fs2.existsSync(indexMapPath)) return null;
129
+ const platformMap = JSON.parse(fs2.readFileSync(platformMapPath, "utf-8"));
130
130
  const mainPlatformId = platformMap["scope:main"] || platformMap["main"];
131
131
  if (!mainPlatformId) return null;
132
- const indexMap = JSON.parse(fs.readFileSync(indexMapPath, "utf-8"));
132
+ const indexMap = JSON.parse(fs2.readFileSync(indexMapPath, "utf-8"));
133
133
  const entry = indexMap[mainPlatformId];
134
134
  if (!entry || !entry.file) return null;
135
- const basename3 = path.basename(entry.file).replace(/\.jsonl$/, "");
136
- return basename3;
135
+ const basename4 = path2.basename(entry.file).replace(/\.jsonl$/, "");
136
+ return basename4;
137
137
  } catch {
138
138
  return null;
139
139
  }
140
140
  }
141
141
  function collectRecentSessions(agentsDir, _days = 7) {
142
142
  const files = [];
143
- if (!fs.existsSync(agentsDir)) return files;
143
+ if (!fs2.existsSync(agentsDir)) return files;
144
144
  const sessionGroups = /* @__PURE__ */ new Map();
145
145
  function scanSessionsDir(dir) {
146
146
  try {
147
- const entries = fs.readdirSync(dir, { withFileTypes: true });
147
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
148
148
  for (const entry of entries) {
149
- const fullPath = path.join(dir, entry.name);
149
+ const fullPath = path2.join(dir, entry.name);
150
150
  if (entry.isDirectory()) {
151
151
  scanSessionsDir(fullPath);
152
152
  continue;
@@ -170,7 +170,7 @@ function collectRecentSessions(agentsDir, _days = 7) {
170
170
  if (entry.name.endsWith(".jsonl")) {
171
171
  group.jsonl = fullPath;
172
172
  } else {
173
- const stat = fs.statSync(fullPath);
173
+ const stat = fs2.statSync(fullPath);
174
174
  group.archived.push({ file: fullPath, mtime: stat.mtimeMs });
175
175
  }
176
176
  }
@@ -189,37 +189,37 @@ function collectRecentSessions(agentsDir, _days = 7) {
189
189
  }
190
190
  async function doExport(opts) {
191
191
  const { agentName, stateDir, note, dryRun: dryRun2 } = opts;
192
- const workspace = (opts.workspace || path.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
193
- const engineHome = path.join(os.homedir(), ".engine7").replace(/[/\\]+$/, "");
192
+ const workspace = (opts.workspace || path2.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
193
+ const engineHome = path2.join(os2.homedir(), ".engine7").replace(/[/\\]+$/, "");
194
194
  console.log(`\u{1F4E6} engine7 export`);
195
195
  console.log(` agent: ${agentName}`);
196
196
  console.log(` state: ${stateDir}`);
197
197
  console.log(` workspace: ${workspace}`);
198
- if (!fs.existsSync(workspace)) {
198
+ if (!fs2.existsSync(workspace)) {
199
199
  console.error(`\u274C workspace \u4E0D\u5B58\u5728: ${workspace}`);
200
200
  process.exit(1);
201
201
  }
202
202
  const dirs = { workspace, stateDir, engineHome };
203
203
  const wsFiles = collectFiles(workspace, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL);
204
- const sessionFiles = collectRecentSessions(path.join(stateDir, "agents"), 7);
205
- const configsDir = path.join(stateDir, "configs");
204
+ const sessionFiles = collectRecentSessions(path2.join(stateDir, "agents"), 7);
205
+ const configsDir = path2.join(stateDir, "configs");
206
206
  const configFiles = [];
207
- if (fs.existsSync(configsDir)) {
207
+ if (fs2.existsSync(configsDir)) {
208
208
  for (const f of collectAllFiles(configsDir)) {
209
- if (shouldExclude(path.basename(f))) continue;
209
+ if (shouldExclude(path2.basename(f))) continue;
210
210
  configFiles.push(f);
211
211
  }
212
212
  }
213
213
  const EVEROS_SKIP = /* @__PURE__ */ new Set([".tmp", ".lock", "import.log", "import_progress.json"]);
214
- const everosDir = path.join(stateDir, ".everos");
214
+ const everosDir = path2.join(stateDir, ".everos");
215
215
  const everosFiles = [];
216
- if (fs.existsSync(everosDir)) {
216
+ if (fs2.existsSync(everosDir)) {
217
217
  for (const f of collectAllFiles(everosDir)) {
218
- if (EVEROS_SKIP.has(path.basename(f))) continue;
218
+ if (EVEROS_SKIP.has(path2.basename(f))) continue;
219
219
  everosFiles.push(f);
220
220
  }
221
- const walFile = path.join(everosDir, ".index", "sqlite", "system.db-wal");
222
- if (fs.existsSync(walFile) && fs.statSync(walFile).size > 0) {
221
+ const walFile = path2.join(everosDir, ".index", "sqlite", "system.db-wal");
222
+ if (fs2.existsSync(walFile) && fs2.statSync(walFile).size > 0) {
223
223
  console.warn(`\u26A0\uFE0F .everos/system.db-wal \u975E\u7A7A\u2014\u2014everos \u670D\u52A1\u53EF\u80FD\u6B63\u5728\u5199\u5165\uFF0C\u5FEB\u7167\u53EF\u80FD\u4E0D\u4E00\u81F4`);
224
224
  console.warn(` \u5EFA\u8BAE: \u5148\u505C everos \u670D\u52A1\u518D export\uFF0C\u6216 import \u540E\u91CD\u5EFA\u7D22\u5F15`);
225
225
  }
@@ -227,16 +227,16 @@ async function doExport(opts) {
227
227
  console.log(` workspace \u6587\u4EF6: ${wsFiles.length}`);
228
228
  console.log(` session jsonl: ${sessionFiles.length} (\u6700\u8FD17\u5929)`);
229
229
  console.log(` configs: ${configFiles.length}`);
230
- console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s + fs.statSync(f).size, 0) / 1024 / 1024).toFixed(1)} MB)`);
230
+ console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s + fs2.statSync(f).size, 0) / 1024 / 1024).toFixed(1)} MB)`);
231
231
  if (dryRun2) {
232
232
  console.log(`
233
233
  [DRY RUN] \u4F1A\u6253\u5305\u4EE5\u4E0B\u6587\u4EF6:`);
234
- wsFiles.slice(0, 20).forEach((f) => console.log(` ${path.relative(workspace, f)}`));
234
+ wsFiles.slice(0, 20).forEach((f) => console.log(` ${path2.relative(workspace, f)}`));
235
235
  if (wsFiles.length > 20) console.log(` ... \u8FD8\u6709 ${wsFiles.length - 20} \u4E2A\u6587\u4EF6`);
236
236
  if (everosFiles.length > 0) {
237
237
  console.log(`
238
238
  [DRY RUN] everos (${everosFiles.length} \u6587\u4EF6):`);
239
- everosFiles.slice(0, 10).forEach((f) => console.log(` ${path.relative(stateDir, f)}`));
239
+ everosFiles.slice(0, 10).forEach((f) => console.log(` ${path2.relative(stateDir, f)}`));
240
240
  if (everosFiles.length > 10) console.log(` ... \u8FD8\u6709 ${everosFiles.length - 10} \u4E2A\u6587\u4EF6`);
241
241
  }
242
242
  console.log(`
@@ -245,46 +245,46 @@ async function doExport(opts) {
245
245
  }
246
246
  const now = /* @__PURE__ */ new Date();
247
247
  const version = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}-${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}`;
248
- const tmpDir = path.join(os.tmpdir(), `engine7-export-${agentName}-${version}`);
249
- fs.mkdirSync(tmpDir, { recursive: true });
250
- const stagingDir = path.join(tmpDir, agentName);
251
- fs.mkdirSync(stagingDir, { recursive: true });
248
+ const tmpDir = path2.join(os2.tmpdir(), `engine7-export-${agentName}-${version}`);
249
+ fs2.mkdirSync(tmpDir, { recursive: true });
250
+ const stagingDir = path2.join(tmpDir, agentName);
251
+ fs2.mkdirSync(stagingDir, { recursive: true });
252
252
  let fileCount = 0;
253
253
  let totalSize = 0;
254
254
  let copyFail = 0;
255
255
  const copyOne = (srcFile, relRoot, destRoot) => {
256
- const relPath = path.relative(relRoot, srcFile);
257
- const destFile = path.join(destRoot, relPath);
258
- fs.mkdirSync(path.dirname(destFile), { recursive: true });
256
+ const relPath = path2.relative(relRoot, srcFile);
257
+ const destFile = path2.join(destRoot, relPath);
258
+ fs2.mkdirSync(path2.dirname(destFile), { recursive: true });
259
259
  try {
260
260
  if (isTextFile(srcFile)) {
261
- const content = fs.readFileSync(srcFile, "utf-8");
262
- fs.writeFileSync(destFile, sanitizeContent(content, dirs));
261
+ const content = fs2.readFileSync(srcFile, "utf-8");
262
+ fs2.writeFileSync(destFile, sanitizeContent(content, dirs));
263
263
  } else {
264
- fs.copyFileSync(srcFile, destFile);
264
+ fs2.copyFileSync(srcFile, destFile);
265
265
  }
266
266
  fileCount++;
267
- totalSize += fs.statSync(srcFile).size;
267
+ totalSize += fs2.statSync(srcFile).size;
268
268
  } catch (e) {
269
269
  copyFail++;
270
270
  console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
271
271
  }
272
272
  };
273
- for (const srcFile of wsFiles) copyOne(srcFile, workspace, path.join(stagingDir, "workspace"));
273
+ for (const srcFile of wsFiles) copyOne(srcFile, workspace, path2.join(stagingDir, "workspace"));
274
274
  for (const srcFile of sessionFiles) {
275
- const relPath = path.relative(stateDir, srcFile);
276
- const destFile = path.join(stagingDir, relPath);
277
- fs.mkdirSync(path.dirname(destFile), { recursive: true });
275
+ const relPath = path2.relative(stateDir, srcFile);
276
+ const destFile = path2.join(stagingDir, relPath);
277
+ fs2.mkdirSync(path2.dirname(destFile), { recursive: true });
278
278
  try {
279
- let content = fs.readFileSync(srcFile, "utf-8");
279
+ let content = fs2.readFileSync(srcFile, "utf-8");
280
280
  content = sanitizeContent(content, dirs);
281
- const baseName = path.basename(srcFile);
281
+ const baseName = path2.basename(srcFile);
282
282
  if (baseName === "session-index.json" || baseName === "platform-map.json") {
283
283
  content = content.split("\\\\").join("/");
284
284
  }
285
- fs.writeFileSync(destFile, content);
285
+ fs2.writeFileSync(destFile, content);
286
286
  fileCount++;
287
- totalSize += fs.statSync(srcFile).size;
287
+ totalSize += fs2.statSync(srcFile).size;
288
288
  } catch (e) {
289
289
  copyFail++;
290
290
  console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
@@ -306,13 +306,13 @@ async function doExport(opts) {
306
306
  totalSize,
307
307
  note
308
308
  };
309
- fs.writeFileSync(path.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2));
310
- const archiveFile = path.join(tmpDir, `${agentName}-${version}.tar.gz`);
309
+ fs2.writeFileSync(path2.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2));
310
+ const archiveFile = path2.join(tmpDir, `${agentName}-${version}.tar.gz`);
311
311
  console.log(`
312
312
  \u{1F5DC}\uFE0F \u6253\u5305\u4E2D...`);
313
313
  const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
314
314
  execSync(`"${tarExe}" -czf "${archiveFile}" -C "${tmpDir}" ${agentName}`, { stdio: "pipe" });
315
- const archiveSize = fs.statSync(archiveFile).size;
315
+ const archiveSize = fs2.statSync(archiveFile).size;
316
316
  console.log(`\u2705 \u6253\u5305\u5B8C\u6210: ${archiveFile} (${(archiveSize / 1024 / 1024).toFixed(1)} MB, ${fileCount} \u6587\u4EF6${copyFail ? `, \u5931\u8D25 ${copyFail}` : ""})`);
317
317
  const cfg = loadTravelConfig();
318
318
  if (!cfg || !cfg.githubToken) {
@@ -335,8 +335,8 @@ async function doImport(opts) {
335
335
  console.error(` \u914D\u7F6E: \u7F16\u8F91 ${CONFIG_PATH}`);
336
336
  process.exit(1);
337
337
  }
338
- const tmpDir = path.join(os.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
339
- fs.mkdirSync(tmpDir, { recursive: true });
338
+ const tmpDir = path2.join(os2.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
339
+ fs2.mkdirSync(tmpDir, { recursive: true });
340
340
  const archiveFile = await downloadFromGitHub(cfg, agentName, version, tmpDir);
341
341
  console.log(`\u2705 \u4E0B\u8F7D\u5B8C\u6210: ${archiveFile}`);
342
342
  if (dryRun2) {
@@ -347,99 +347,99 @@ async function doImport(opts) {
347
347
  console.log(`\u{1F4C2} \u89E3\u5305\u4E2D...`);
348
348
  const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
349
349
  execSync(`"${tarExe}" -xzf "${archiveFile}" -C "${tmpDir}"`, { stdio: "pipe" });
350
- const stagingDir = path.join(tmpDir, agentName);
351
- const manifestPath = path.join(stagingDir, "manifest.json");
352
- if (!fs.existsSync(manifestPath)) {
350
+ const stagingDir = path2.join(tmpDir, agentName);
351
+ const manifestPath = path2.join(stagingDir, "manifest.json");
352
+ if (!fs2.existsSync(manifestPath)) {
353
353
  console.error(`\u274C manifest.json \u4E0D\u5B58\u5728\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);
354
354
  process.exit(1);
355
355
  }
356
- const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
357
- const workspace = path.join(stateDir, "workspace").replace(/\\/g, "/").replace(/[/\\]+$/, "");
358
- const engineHome = path.join(os.homedir(), ".engine7").replace(/\\/g, "/").replace(/[/\\]+$/, "");
356
+ const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
357
+ const workspace = path2.join(stateDir, "workspace").replace(/\\/g, "/").replace(/[/\\]+$/, "");
358
+ const engineHome = path2.join(os2.homedir(), ".engine7").replace(/\\/g, "/").replace(/[/\\]+$/, "");
359
359
  const dirs = { workspace, stateDir: stateDir.replace(/\\/g, "/").replace(/[/\\]+$/, ""), engineHome };
360
360
  console.log(` \u7248\u672C: ${manifest.version}`);
361
361
  console.log(` \u521B\u5EFA: ${manifest.createdAt}`);
362
362
  console.log(` \u6587\u4EF6\u6570: ${manifest.fileCount}`);
363
- const wsStaging = path.join(stagingDir, "workspace");
363
+ const wsStaging = path2.join(stagingDir, "workspace");
364
364
  let restoredCount = 0;
365
365
  let skipCount = 0;
366
- if (fs.existsSync(wsStaging)) {
366
+ if (fs2.existsSync(wsStaging)) {
367
367
  const allFiles = collectAllFiles(wsStaging);
368
368
  for (const srcFile of allFiles) {
369
- const relPath = path.relative(wsStaging, srcFile);
370
- const destFile = path.join(workspace, relPath);
371
- fs.mkdirSync(path.dirname(destFile), { recursive: true });
369
+ const relPath = path2.relative(wsStaging, srcFile);
370
+ const destFile = path2.join(workspace, relPath);
371
+ fs2.mkdirSync(path2.dirname(destFile), { recursive: true });
372
372
  try {
373
373
  if (isTextFile(srcFile)) {
374
- const content = fs.readFileSync(srcFile, "utf-8");
375
- fs.writeFileSync(destFile, restoreContent(content, dirs));
374
+ const content = fs2.readFileSync(srcFile, "utf-8");
375
+ fs2.writeFileSync(destFile, restoreContent(content, dirs));
376
376
  } else {
377
- fs.copyFileSync(srcFile, destFile);
377
+ fs2.copyFileSync(srcFile, destFile);
378
378
  }
379
379
  restoredCount++;
380
380
  } catch (e) {
381
381
  skipCount++;
382
- console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path.relative(wsStaging, srcFile)} (${e.code || e.message})`);
382
+ console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path2.relative(wsStaging, srcFile)} (${e.code || e.message})`);
383
383
  }
384
384
  }
385
385
  }
386
- const agentsStaging = path.join(stagingDir, "agents");
387
- if (fs.existsSync(agentsStaging)) {
386
+ const agentsStaging = path2.join(stagingDir, "agents");
387
+ if (fs2.existsSync(agentsStaging)) {
388
388
  const sessionFiles = collectAllFiles(agentsStaging);
389
389
  for (const srcFile of sessionFiles) {
390
- const relPath = path.relative(stagingDir, srcFile);
391
- const destFile = path.join(stateDir, relPath);
392
- fs.mkdirSync(path.dirname(destFile), { recursive: true });
393
- const content = fs.readFileSync(srcFile, "utf-8");
394
- fs.writeFileSync(destFile, restoreContent(content, dirs));
390
+ const relPath = path2.relative(stagingDir, srcFile);
391
+ const destFile = path2.join(stateDir, relPath);
392
+ fs2.mkdirSync(path2.dirname(destFile), { recursive: true });
393
+ const content = fs2.readFileSync(srcFile, "utf-8");
394
+ fs2.writeFileSync(destFile, restoreContent(content, dirs));
395
395
  restoredCount++;
396
396
  }
397
397
  }
398
- const configsStaging = path.join(stagingDir, "configs");
399
- if (fs.existsSync(configsStaging)) {
398
+ const configsStaging = path2.join(stagingDir, "configs");
399
+ if (fs2.existsSync(configsStaging)) {
400
400
  const cfgFiles = collectAllFiles(configsStaging);
401
401
  for (const srcFile of cfgFiles) {
402
- const relPath = path.relative(stagingDir, srcFile);
403
- const destFile = path.join(stateDir, relPath);
404
- fs.mkdirSync(path.dirname(destFile), { recursive: true });
402
+ const relPath = path2.relative(stagingDir, srcFile);
403
+ const destFile = path2.join(stateDir, relPath);
404
+ fs2.mkdirSync(path2.dirname(destFile), { recursive: true });
405
405
  if (isTextFile(srcFile)) {
406
- const content = fs.readFileSync(srcFile, "utf-8");
407
- fs.writeFileSync(destFile, restoreContent(content, dirs));
406
+ const content = fs2.readFileSync(srcFile, "utf-8");
407
+ fs2.writeFileSync(destFile, restoreContent(content, dirs));
408
408
  } else {
409
- fs.copyFileSync(srcFile, destFile);
409
+ fs2.copyFileSync(srcFile, destFile);
410
410
  }
411
411
  restoredCount++;
412
412
  }
413
413
  }
414
- const everosStaging = path.join(stagingDir, ".everos");
415
- if (fs.existsSync(everosStaging)) {
414
+ const everosStaging = path2.join(stagingDir, ".everos");
415
+ if (fs2.existsSync(everosStaging)) {
416
416
  const everosFiles = collectAllFiles(everosStaging);
417
417
  for (const srcFile of everosFiles) {
418
- const relPath = path.relative(stagingDir, srcFile);
419
- const destFile = path.join(stateDir, relPath);
420
- fs.mkdirSync(path.dirname(destFile), { recursive: true });
418
+ const relPath = path2.relative(stagingDir, srcFile);
419
+ const destFile = path2.join(stateDir, relPath);
420
+ fs2.mkdirSync(path2.dirname(destFile), { recursive: true });
421
421
  try {
422
422
  if (isTextFile(srcFile)) {
423
- const content = fs.readFileSync(srcFile, "utf-8");
424
- fs.writeFileSync(destFile, restoreContent(content, dirs));
423
+ const content = fs2.readFileSync(srcFile, "utf-8");
424
+ fs2.writeFileSync(destFile, restoreContent(content, dirs));
425
425
  } else {
426
- fs.copyFileSync(srcFile, destFile);
426
+ fs2.copyFileSync(srcFile, destFile);
427
427
  }
428
428
  restoredCount++;
429
429
  } catch (e) {
430
430
  skipCount++;
431
- console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path.relative(everosStaging, srcFile)} (${e.code || e.message})`);
431
+ console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path2.relative(everosStaging, srcFile)} (${e.code || e.message})`);
432
432
  }
433
433
  }
434
434
  console.log(` everos: ${everosFiles.length} \u6587\u4EF6\u5DF2\u6062\u590D`);
435
435
  }
436
436
  console.log(`\u2705 \u6062\u590D\u5B8C\u6210: ${restoredCount} \u6587\u4EF6 \u2192 ${stateDir}${skipCount ? ` (\u8DF3\u8FC7 ${skipCount})` : ""}`);
437
437
  const platformConfigName = process.platform === "darwin" ? "xiaoke-mac.json" : "xiaoke-win.json";
438
- const restoredConfigPath = path.join(stateDir, "configs", platformConfigName);
439
- const configToUse = fs.existsSync(restoredConfigPath) ? restoredConfigPath : path.join(stateDir, "configs", "xiaoke.json");
438
+ const restoredConfigPath = path2.join(stateDir, "configs", platformConfigName);
439
+ const configToUse = fs2.existsSync(restoredConfigPath) ? restoredConfigPath : path2.join(stateDir, "configs", "xiaoke.json");
440
440
  console.log(`
441
441
  \u{1F4A1} \u4E0B\u4E00\u6B65: engine7 start --config "${configToUse}"`);
442
- fs.rmSync(tmpDir, { recursive: true, force: true });
442
+ fs2.rmSync(tmpDir, { recursive: true, force: true });
443
443
  }
444
444
  async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
445
445
  const repo = `${cfg.githubOwner}/${cfg.repoName}`;
@@ -469,8 +469,8 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
469
469
  }
470
470
  const release = await createRes.json();
471
471
  const uploadUrl = release.upload_url.replace("{?name,label}", "");
472
- const fileBuffer = fs.readFileSync(archiveFile);
473
- const fileName = path.basename(archiveFile);
472
+ const fileBuffer = fs2.readFileSync(archiveFile);
473
+ const fileName = path2.basename(archiveFile);
474
474
  const uploadRes = await fetch(`${uploadUrl}?name=${fileName}`, {
475
475
  method: "POST",
476
476
  headers: {
@@ -493,7 +493,7 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
493
493
  throw e;
494
494
  }
495
495
  try {
496
- fs.rmSync(path.dirname(archiveFile), { recursive: true, force: true });
496
+ fs2.rmSync(path2.dirname(archiveFile), { recursive: true, force: true });
497
497
  } catch {
498
498
  }
499
499
  }
@@ -525,8 +525,8 @@ async function downloadFromGitHub(cfg, agentName, version, destDir) {
525
525
  throw new Error(`\u4E0B\u8F7D asset \u5931\u8D25: ${downloadRes.status}`);
526
526
  }
527
527
  const buffer = Buffer.from(await downloadRes.arrayBuffer());
528
- const archiveFile = path.join(destDir, asset.name);
529
- fs.writeFileSync(archiveFile, buffer);
528
+ const archiveFile = path2.join(destDir, asset.name);
529
+ fs2.writeFileSync(archiveFile, buffer);
530
530
  return archiveFile;
531
531
  }
532
532
  async function getLatestReleaseTag(cfg, agentName) {
@@ -551,7 +551,7 @@ var CONFIG_PATH, PATH_PLACEHOLDERS, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL, WORKS
551
551
  var init_cli_travel = __esm({
552
552
  "src/cli-travel.ts"() {
553
553
  "use strict";
554
- CONFIG_PATH = path.join(os.homedir(), ".engine7-travel.json");
554
+ CONFIG_PATH = path2.join(os2.homedir(), ".engine7-travel.json");
555
555
  PATH_PLACEHOLDERS = [
556
556
  { placeholder: "{{WORKSPACE}}", getOriginal: (d) => d.workspace },
557
557
  { placeholder: "{{ENGINE_HOME}}", getOriginal: (d) => d.engineHome },
@@ -624,8 +624,8 @@ var init_cli_travel = __esm({
624
624
  });
625
625
 
626
626
  // src/cli-init.ts
627
- import * as path2 from "node:path";
628
- import * as fs2 from "node:fs";
627
+ import * as path3 from "node:path";
628
+ import * as fs3 from "node:fs";
629
629
  import * as readline from "node:readline";
630
630
  import { fileURLToPath } from "node:url";
631
631
 
@@ -743,6 +743,128 @@ function sleep(ms) {
743
743
  return new Promise((resolve2) => setTimeout(resolve2, ms));
744
744
  }
745
745
 
746
+ // src/channels/wechat.ts
747
+ import * as fs from "fs";
748
+ import * as path from "path";
749
+ import * as os from "os";
750
+ function sleep2(ms) {
751
+ return new Promise((r) => setTimeout(r, ms));
752
+ }
753
+ var ILINK_BASE_URL = "https://ilinkai.weixin.qq.com";
754
+ var ILINK_APP_CLIENT_VERSION = 2 << 16 | 2 << 8 | 0;
755
+ var EP_GET_BOT_QR = "ilink/bot/get_bot_qrcode";
756
+ var EP_GET_QR_STATUS = "ilink/bot/get_qrcode_status";
757
+ var QR_TIMEOUT_MS = 15e3;
758
+ async function wechatQrLogin(options) {
759
+ const botType = options?.botType || "3";
760
+ const timeoutSeconds = options?.timeoutSeconds || 480;
761
+ const stateDir = options?.stateDir || path.join(os.homedir?.() || "/tmp", ".engine7");
762
+ console.log("[wechat] Fetching QR code from iLink...");
763
+ let qrResp;
764
+ try {
765
+ qrResp = await apiGet(ILINK_BASE_URL, `${EP_GET_BOT_QR}?bot_type=${botType}`, "", QR_TIMEOUT_MS);
766
+ } catch (err) {
767
+ console.error(`[wechat] Failed to fetch QR code: ${err.message}`);
768
+ return null;
769
+ }
770
+ const qrcodeValue = String(qrResp?.qrcode || "");
771
+ const qrcodeUrl = String(qrResp?.qrcode_img_content || "");
772
+ if (!qrcodeValue) {
773
+ console.error("[wechat] QR response missing qrcode field");
774
+ return null;
775
+ }
776
+ const qrScanData = qrcodeUrl || qrcodeValue;
777
+ console.log("\n========== \u5FAE\u4FE1\u626B\u7801\u767B\u5F55 ==========");
778
+ if (qrcodeUrl) {
779
+ console.log(`\u626B\u7801\u94FE\u63A5: ${qrcodeUrl}`);
780
+ }
781
+ console.log("\u8BF7\u7528\u5FAE\u4FE1\u626B\u63CF\u4E8C\u7EF4\u7801\uFF08\u6216\u6253\u5F00\u4E0A\u9762\u7684\u94FE\u63A5\uFF09:");
782
+ console.log("===================================\n");
783
+ const deadline = Date.now() + timeoutSeconds * 1e3;
784
+ let currentBaseUrl = ILINK_BASE_URL;
785
+ let refreshCount = 0;
786
+ while (Date.now() < deadline) {
787
+ let statusResp;
788
+ try {
789
+ statusResp = await apiGet(currentBaseUrl, `${EP_GET_QR_STATUS}?qrcode=${qrcodeValue}`, "", QR_TIMEOUT_MS);
790
+ } catch {
791
+ await sleep2(1e3);
792
+ continue;
793
+ }
794
+ const status = String(statusResp?.status || "wait");
795
+ if (status === "wait") {
796
+ process.stdout.write(".");
797
+ } else if (status === "scaned") {
798
+ console.log("\n\u5DF2\u626B\u7801\uFF0C\u8BF7\u5728\u5FAE\u4FE1\u91CC\u786E\u8BA4...");
799
+ } else if (status === "scaned_but_redirect") {
800
+ const redirectHost = String(statusResp?.redirect_host || "");
801
+ if (redirectHost) currentBaseUrl = `https://${redirectHost}`;
802
+ } else if (status === "expired") {
803
+ refreshCount++;
804
+ if (refreshCount > 3) {
805
+ console.log("\n\u4E8C\u7EF4\u7801\u591A\u6B21\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C\u767B\u5F55\u3002");
806
+ return null;
807
+ }
808
+ console.log(`
809
+ \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u5237\u65B0\u4E2D... (${refreshCount}/3)`);
810
+ try {
811
+ qrResp = await apiGet(ILINK_BASE_URL, `${EP_GET_BOT_QR}?bot_type=${botType}`, "", QR_TIMEOUT_MS);
812
+ const newQrValue = String(qrResp?.qrcode || "");
813
+ const newQrUrl = String(qrResp?.qrcode_img_content || "");
814
+ if (newQrUrl) console.log(`\u65B0\u626B\u7801\u94FE\u63A5: ${newQrUrl}`);
815
+ } catch (err) {
816
+ console.error(`[wechat] QR refresh failed: ${err.message}`);
817
+ return null;
818
+ }
819
+ } else if (status === "confirmed") {
820
+ const accountId = String(statusResp?.ilink_bot_id || "");
821
+ const token = String(statusResp?.bot_token || "");
822
+ const baseUrl = String(statusResp?.baseurl || ILINK_BASE_URL);
823
+ const userId = String(statusResp?.ilink_user_id || "");
824
+ if (!accountId || !token) {
825
+ console.error("[wechat] QR confirmed but credential payload incomplete");
826
+ return null;
827
+ }
828
+ if (!fs.existsSync(stateDir)) fs.mkdirSync(stateDir, { recursive: true });
829
+ const credFile = path.join(stateDir, `weixin-${accountId}.json`);
830
+ fs.writeFileSync(credFile, JSON.stringify({ accountId, token, baseUrl, userId }, null, 2), "utf8");
831
+ console.log(`
832
+ \u2705 \u5FAE\u4FE1\u767B\u5F55\u6210\u529F!`);
833
+ console.log(` accountId: ${accountId}`);
834
+ console.log(` \u51ED\u8BC1\u5DF2\u4FDD\u5B58: ${credFile}`);
835
+ console.log(`
836
+ \u8BF7\u5C06\u4EE5\u4E0B\u914D\u7F6E\u6DFB\u52A0\u5230 xiaoke.json:`);
837
+ console.log(JSON.stringify({
838
+ wechat: {
839
+ token,
840
+ accountId,
841
+ baseUrl: baseUrl !== ILINK_BASE_URL ? baseUrl : void 0
842
+ }
843
+ }, null, 2));
844
+ return { accountId, token, baseUrl, userId };
845
+ }
846
+ await sleep2(1e3);
847
+ }
848
+ console.log("\n[wechat] QR login timed out");
849
+ return null;
850
+ }
851
+ async function apiGet(baseUrl, endpoint, _token, timeoutMs) {
852
+ const url = `${baseUrl.replace(/\/$/, "")}/${endpoint.replace(/^\//, "")}`;
853
+ const controller = new AbortController();
854
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
855
+ try {
856
+ const resp = await fetch(url, {
857
+ method: "GET",
858
+ signal: controller.signal,
859
+ headers: { "Accept": "application/json" }
860
+ });
861
+ if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
862
+ return await resp.json();
863
+ } finally {
864
+ clearTimeout(timer);
865
+ }
866
+ }
867
+
746
868
  // src/qr-render.ts
747
869
  import { createRequire } from "node:module";
748
870
  var require2 = createRequire(import.meta.url);
@@ -761,7 +883,7 @@ async function renderQrTerminal(url, options) {
761
883
 
762
884
  // src/cli-init.ts
763
885
  var __filename = fileURLToPath(import.meta.url);
764
- var __dirname = path2.dirname(__filename);
886
+ var __dirname = path3.dirname(__filename);
765
887
  var SCHEMA_VERSION = 1;
766
888
  function parseArgs() {
767
889
  const args = process.argv.slice(2);
@@ -786,10 +908,10 @@ function parseArgs() {
786
908
  }
787
909
  }
788
910
  if (!stateDir) {
789
- stateDir = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
911
+ stateDir = path3.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
790
912
  console.log(` \u4F7F\u7528\u9ED8\u8BA4\u76EE\u5F55: ${stateDir}`);
791
913
  }
792
- stateDir = path2.resolve(stateDir);
914
+ stateDir = path3.resolve(stateDir);
793
915
  return { stateDir, quick, dryRun: dryRun2, force };
794
916
  }
795
917
  function printHelp() {
@@ -860,6 +982,7 @@ function getDefaultValues(stateDir) {
860
982
  stateDir,
861
983
  agentName: "Agent",
862
984
  primaryProvider: "dashscope",
985
+ zhipuPlan: "",
863
986
  primaryApiKey: "",
864
987
  primaryModel: "dashscope/qwen3.7-max",
865
988
  visionModel: "dashscope/qwen3.7-max",
@@ -870,6 +993,9 @@ function getDefaultValues(stateDir) {
870
993
  feishuAppId: "",
871
994
  feishuAppSecret: "",
872
995
  feishuOpenId: "",
996
+ wechatEnabled: false,
997
+ wechatToken: "",
998
+ wechatAccountId: "",
873
999
  tavilyKey: "",
874
1000
  apiPort: 16990
875
1001
  };
@@ -887,6 +1013,12 @@ async function interactiveConfig(rl, defaults) {
887
1013
  };
888
1014
  const chosenProvider = await askChoice(rl, "\u4E3B\u6A21\u578B Provider:", providers, 0);
889
1015
  v.primaryProvider = providerMap[chosenProvider] || "dashscope";
1016
+ v.zhipuPlan = "";
1017
+ if (v.primaryProvider === "zhipu") {
1018
+ const planOptions = ["coding-plan (GLM Coding \u8BA2\u9605)", "token-plan (\u666E\u901A\u6309\u91CF/TokenPlan)"];
1019
+ const chosenPlan = await askChoice(rl, "\u667A\u8C31\u8BA2\u9605\u7C7B\u578B:", planOptions, 0);
1020
+ v.zhipuPlan = chosenPlan.startsWith("coding") ? "coding" : "token";
1021
+ }
890
1022
  const keyMap = {
891
1023
  dashscope: "DashScope API Key",
892
1024
  minimax: "MiniMax API Key",
@@ -974,6 +1106,44 @@ async function interactiveConfig(rl, defaults) {
974
1106
  v.feishuOpenId = await ask(rl, "\u4F60\u7684\u98DE\u4E66 open_id\uFF08\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
975
1107
  }
976
1108
  }
1109
+ const wechatAns = await ask(rl, "\u542F\u7528\u5FAE\u4FE1? (y/n)", "n");
1110
+ v.wechatEnabled = wechatAns.toLowerCase() === "y";
1111
+ if (v.wechatEnabled) {
1112
+ console.log("\n \u5FAE\u4FE1\u63A5\u5165\u65B9\u5F0F\uFF1A");
1113
+ console.log(" 1. \u626B\u7801\u7ED1\u5B9A\uFF08\u63A8\u8350\uFF0C\u7528\u4F60\u81EA\u5DF1\u7684\u5FAE\u4FE1\u626B\u4E00\u4E0B\u5C31\u884C\uFF09");
1114
+ console.log(" 2. \u624B\u52A8\u8F93\u5165 token\uFF08\u5DF2\u6709\u51ED\u8BC1\u65F6\uFF09");
1115
+ const wechatMode = await ask(rl, "\u9009\u62E9 (1/2)", "1");
1116
+ if (wechatMode === "1") {
1117
+ console.log("\n\u{1F4DD} \u6B63\u5728\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801...\n");
1118
+ console.log(" \u63D0\u793A\uFF1A\u4E00\u4E2A\u5FAE\u4FE1\u53F7\u53EA\u80FD\u7ED1\u4E00\u4E2A bot\uFF1Bbot \u4E0D\u8FDB\u7FA4\uFF08\u817E\u8BAF\u9650\u5236\uFF09\uFF0C\u79C1\u804A 1v1");
1119
+ const cred = await wechatQrLogin({ timeoutSeconds: 300, stateDir: v.stateDir });
1120
+ if (cred) {
1121
+ v.wechatToken = cred.token;
1122
+ v.wechatAccountId = cred.accountId;
1123
+ console.log(`
1124
+ \u2705 accountId: ${cred.accountId}`);
1125
+ console.log(` \u2705 \u51ED\u8BC1\u5DF2\u81EA\u52A8\u4FDD\u5B58\uFF0Cconfig \u5C06\u81EA\u52A8\u5199\u5165`);
1126
+ } else {
1127
+ console.log("\n \u26A0\uFE0F \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25");
1128
+ const retry = await ask(rl, "\u91CD\u8BD5\u626B\u7801? (y/n)", "y");
1129
+ if (retry.toLowerCase() === "y") {
1130
+ const cred2 = await wechatQrLogin({ timeoutSeconds: 300, stateDir: v.stateDir });
1131
+ if (cred2) {
1132
+ v.wechatToken = cred2.token;
1133
+ v.wechatAccountId = cred2.accountId;
1134
+ } else {
1135
+ console.log("\n \u26A0\uFE0F \u518D\u6B21\u5931\u8D25\uFF0C\u8DF3\u8FC7\u5FAE\u4FE1\uFF08\u4E4B\u540E\u53EF\u624B\u52A8\u914D\u7F6E\uFF09");
1136
+ v.wechatEnabled = false;
1137
+ }
1138
+ } else {
1139
+ v.wechatEnabled = false;
1140
+ }
1141
+ }
1142
+ } else {
1143
+ v.wechatToken = await ask(rl, "\u5FAE\u4FE1 token");
1144
+ v.wechatAccountId = await ask(rl, "\u5FAE\u4FE1 accountId");
1145
+ }
1146
+ }
977
1147
  const tavilyKey = await ask(rl, "Tavily API Key\uFF08\u8054\u7F51\u641C\u7D22\uFF0C\u56DE\u8F66\u8DF3\u8FC7\uFF09", "");
978
1148
  v.tavilyKey = tavilyKey;
979
1149
  const portAns = await ask(rl, "API \u7AEF\u53E3", String(defaults.apiPort));
@@ -981,7 +1151,7 @@ async function interactiveConfig(rl, defaults) {
981
1151
  return v;
982
1152
  }
983
1153
  function generateConfig(v) {
984
- const workspace = path2.join(v.stateDir, "workspace").replace(/\\/g, "/");
1154
+ const workspace = path3.join(v.stateDir, "workspace").replace(/\\/g, "/");
985
1155
  const config = {
986
1156
  schemaVersion: SCHEMA_VERSION,
987
1157
  stateDir: v.stateDir.replace(/\\/g, "/"),
@@ -1041,7 +1211,16 @@ function generateConfig(v) {
1041
1211
  connectionMode: "websocket",
1042
1212
  dmPolicy: "pairing",
1043
1213
  groupPolicy: "open"
1044
- }
1214
+ },
1215
+ ...v.wechatEnabled && v.wechatToken ? {
1216
+ wechat: {
1217
+ enabled: true,
1218
+ token: v.wechatToken,
1219
+ accountId: v.wechatAccountId,
1220
+ dmPolicy: "pairing",
1221
+ group: { policy: "disabled" }
1222
+ }
1223
+ } : {}
1045
1224
  },
1046
1225
  api: { port: v.apiPort },
1047
1226
  prompt: {
@@ -1080,7 +1259,7 @@ function generateConfig(v) {
1080
1259
  ]
1081
1260
  },
1082
1261
  zhipu: {
1083
- baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4 ",
1262
+ baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
1084
1263
  api: "openai-completions",
1085
1264
  models: [
1086
1265
  { id: "glm-5.1", name: "GLM-5.1", reasoning: true, input: ["text"], contextWindow: 204800, maxTokens: 131072 },
@@ -1098,8 +1277,12 @@ function generateConfig(v) {
1098
1277
  }
1099
1278
  };
1100
1279
  if (providerDefs[v.primaryProvider]) {
1280
+ const def = { ...providerDefs[v.primaryProvider] };
1281
+ if (v.primaryProvider === "zhipu" && v.zhipuPlan === "token") {
1282
+ def.baseUrl = "https://open.bigmodel.cn/api/paas/v4";
1283
+ }
1101
1284
  config.models.providers[v.primaryProvider] = {
1102
- ...providerDefs[v.primaryProvider],
1285
+ ...def,
1103
1286
  apiKey: v.primaryApiKey
1104
1287
  };
1105
1288
  }
@@ -1107,45 +1290,45 @@ function generateConfig(v) {
1107
1290
  }
1108
1291
  function buildDirTree(v) {
1109
1292
  const d = v.stateDir;
1110
- const w = path2.join(d, "workspace");
1293
+ const w = path3.join(d, "workspace");
1111
1294
  const now = (/* @__PURE__ */ new Date()).toLocaleString("sv-SE", { timeZone: "Asia/Shanghai", hour12: false });
1112
1295
  return [
1113
1296
  // 目录
1114
- { path: path2.join(d, "configs"), type: "dir" },
1115
- { path: path2.join(d, "state", "agents", "main", "sessions"), type: "dir" },
1116
- { path: path2.join(w, "prompts"), type: "dir" },
1117
- { path: path2.join(w, "memory", "daily"), type: "dir" },
1118
- { path: path2.join(w, "docs", "research"), type: "dir" },
1119
- { path: path2.join(w, "docs", "todo"), type: "dir" },
1120
- { path: path2.join(w, "docs", "decisions"), type: "dir" },
1121
- { path: path2.join(w, "docs", "knowledge"), type: "dir" },
1122
- { path: path2.join(w, "docs", "sop"), type: "dir" },
1123
- { path: path2.join(d, "logs"), type: "dir" },
1124
- { path: path2.join(d, "media", "inbound"), type: "dir" },
1297
+ { path: path3.join(d, "configs"), type: "dir" },
1298
+ { path: path3.join(d, "state", "agents", "main", "sessions"), type: "dir" },
1299
+ { path: path3.join(w, "prompts"), type: "dir" },
1300
+ { path: path3.join(w, "memory", "daily"), type: "dir" },
1301
+ { path: path3.join(w, "docs", "research"), type: "dir" },
1302
+ { path: path3.join(w, "docs", "todo"), type: "dir" },
1303
+ { path: path3.join(w, "docs", "decisions"), type: "dir" },
1304
+ { path: path3.join(w, "docs", "knowledge"), type: "dir" },
1305
+ { path: path3.join(w, "docs", "sop"), type: "dir" },
1306
+ { path: path3.join(d, "logs"), type: "dir" },
1307
+ { path: path3.join(d, "media", "inbound"), type: "dir" },
1125
1308
  // workspace 文件
1126
1309
  {
1127
- path: path2.join(w, "SESSION-STATE.md"),
1310
+ path: path3.join(w, "SESSION-STATE.md"),
1128
1311
  type: "file",
1129
1312
  content: readTemplate("workspace/SESSION-STATE.md").replace("{{CURRENT_TIME}}", now)
1130
1313
  },
1131
- { path: path2.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
1314
+ { path: path3.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
1132
1315
  {
1133
- path: path2.join(w, "SOUL.md"),
1316
+ path: path3.join(w, "SOUL.md"),
1134
1317
  type: "file",
1135
1318
  content: readTemplate("workspace/SOUL.md").replace(/\{\{AGENT_NAME\}\}/g, v.agentName)
1136
1319
  },
1137
- { path: path2.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
1320
+ { path: path3.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
1138
1321
  {
1139
- path: path2.join(w, "prompts", "contacts.md"),
1322
+ path: path3.join(w, "prompts", "contacts.md"),
1140
1323
  type: "file",
1141
1324
  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")
1142
1325
  },
1143
- { path: path2.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
1144
- { path: path2.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" },
1145
- { path: path2.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" },
1326
+ { path: path3.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
1327
+ { path: path3.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" },
1328
+ { path: path3.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" },
1146
1329
  // package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
1147
1330
  {
1148
- path: path2.join(d, "package.json"),
1331
+ path: path3.join(d, "package.json"),
1149
1332
  type: "file",
1150
1333
  content: JSON.stringify({
1151
1334
  name: v.agentName.toLowerCase().replace(/[^a-z0-9-]/g, "-") || "agent",
@@ -1156,7 +1339,7 @@ function buildDirTree(v) {
1156
1339
  },
1157
1340
  // 启动脚本(根据 OS 生成)
1158
1341
  ...process.platform === "win32" ? [{
1159
- path: path2.join(d, "start.cmd"),
1342
+ path: path3.join(d, "start.cmd"),
1160
1343
  type: "file",
1161
1344
  content: `@echo off
1162
1345
  rem Engine 7 startup script
@@ -1188,7 +1371,7 @@ if %ERRORLEVEL% NEQ 0 (
1188
1371
  )
1189
1372
  `
1190
1373
  }] : [{
1191
- path: path2.join(d, "start.sh"),
1374
+ path: path3.join(d, "start.sh"),
1192
1375
  type: "file",
1193
1376
  content: `#!/bin/bash
1194
1377
  # Engine 7 startup script
@@ -1221,13 +1404,13 @@ node "$ENGINE7_BIN" --engine-config configs/main7.json
1221
1404
  }
1222
1405
  function readTemplate(relativePath) {
1223
1406
  const candidates = [
1224
- path2.join(__dirname, "..", "templates", relativePath),
1225
- path2.join(__dirname, "..", "..", "templates", relativePath),
1226
- path2.join(process.cwd(), "templates", relativePath)
1407
+ path3.join(__dirname, "..", "templates", relativePath),
1408
+ path3.join(__dirname, "..", "..", "templates", relativePath),
1409
+ path3.join(process.cwd(), "templates", relativePath)
1227
1410
  ];
1228
1411
  for (const p of candidates) {
1229
- if (fs2.existsSync(p)) {
1230
- return fs2.readFileSync(p, "utf-8");
1412
+ if (fs3.existsSync(p)) {
1413
+ return fs3.readFileSync(p, "utf-8");
1231
1414
  }
1232
1415
  }
1233
1416
  throw new Error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${relativePath}\uFF08\u627E\u4E86: ${candidates.join(", ")}\uFF09`);
@@ -1242,11 +1425,11 @@ function dryRun(entries) {
1242
1425
  function execute(entries) {
1243
1426
  for (const e of entries) {
1244
1427
  if (e.type === "dir") {
1245
- fs2.mkdirSync(e.path, { recursive: true });
1428
+ fs3.mkdirSync(e.path, { recursive: true });
1246
1429
  console.log(` \u{1F4C1} ${e.path}`);
1247
1430
  } else {
1248
- fs2.mkdirSync(path2.dirname(e.path), { recursive: true });
1249
- fs2.writeFileSync(e.path, e.content || "", "utf-8");
1431
+ fs3.mkdirSync(path3.dirname(e.path), { recursive: true });
1432
+ fs3.writeFileSync(e.path, e.content || "", "utf-8");
1250
1433
  console.log(` \u{1F4C4} ${e.path}`);
1251
1434
  }
1252
1435
  }
@@ -1274,8 +1457,8 @@ async function main() {
1274
1457
  else if (args[i] === "--note" && args[i + 1]) note = args[++i];
1275
1458
  else if (args[i] === "--dry-run") dryRun2 = true;
1276
1459
  }
1277
- if (!exportStateDir) exportStateDir = path2.resolve(process.cwd());
1278
- if (!agentName) agentName = path2.basename(exportStateDir);
1460
+ if (!exportStateDir) exportStateDir = path3.resolve(process.cwd());
1461
+ if (!agentName) agentName = path3.basename(exportStateDir);
1279
1462
  await doExport2({ agentName, stateDir: exportStateDir, note, dryRun: dryRun2 });
1280
1463
  process.exit(0);
1281
1464
  }
@@ -1295,7 +1478,7 @@ async function main() {
1295
1478
  console.error("\u274C import \u9700\u8981 --state-dir <path>");
1296
1479
  process.exit(1);
1297
1480
  }
1298
- if (!agentName) agentName = path2.basename(importStateDir);
1481
+ if (!agentName) agentName = path3.basename(importStateDir);
1299
1482
  await doImport2({ agentName, stateDir: importStateDir, version, dryRun: dryRun2 });
1300
1483
  process.exit(0);
1301
1484
  }
@@ -1320,18 +1503,18 @@ engine7 start \u2014 \u542F\u52A8 Engine
1320
1503
  }
1321
1504
  }
1322
1505
  if (!configPath2) {
1323
- const defaultCfg = path2.join("configs", "main7.json");
1324
- const homeCfg = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
1325
- if (fs2.existsSync(defaultCfg)) {
1506
+ const defaultCfg = path3.join("configs", "main7.json");
1507
+ const homeCfg = path3.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
1508
+ if (fs3.existsSync(defaultCfg)) {
1326
1509
  configPath2 = defaultCfg;
1327
- } else if (fs2.existsSync(homeCfg)) {
1510
+ } else if (fs3.existsSync(homeCfg)) {
1328
1511
  configPath2 = homeCfg;
1329
1512
  console.log(` \u4F7F\u7528\u9ED8\u8BA4 config: ${homeCfg}`);
1330
1513
  } else {
1331
1514
  const ptr = readHomePointer();
1332
1515
  if (ptr?.stateDir) {
1333
- const ptrCfg = path2.join(ptr.stateDir, "configs", "main7.json");
1334
- if (fs2.existsSync(ptrCfg)) {
1516
+ const ptrCfg = path3.join(ptr.stateDir, "configs", "main7.json");
1517
+ if (fs3.existsSync(ptrCfg)) {
1335
1518
  configPath2 = ptrCfg;
1336
1519
  console.log(` \u4F7F\u7528 config: ${ptrCfg}`);
1337
1520
  }
@@ -1346,19 +1529,19 @@ engine7 start \u2014 \u542F\u52A8 Engine
1346
1529
  }
1347
1530
  const { execSync: execSync2, spawn } = await import("node:child_process");
1348
1531
  let enginePath;
1349
- const localPath = path2.join("node_modules", "engine7", "dist", "main.mjs");
1350
- if (fs2.existsSync(localPath)) {
1532
+ const localPath = path3.join("node_modules", "engine7", "dist", "main.mjs");
1533
+ if (fs3.existsSync(localPath)) {
1351
1534
  enginePath = localPath;
1352
1535
  } else {
1353
- const cliPath = path2.resolve(process.argv[1]);
1354
- const distDir = path2.dirname(cliPath);
1355
- const candidate = path2.join(distDir, "main.mjs");
1356
- if (fs2.existsSync(candidate)) {
1536
+ const cliPath = path3.resolve(process.argv[1]);
1537
+ const distDir = path3.dirname(cliPath);
1538
+ const candidate = path3.join(distDir, "main.mjs");
1539
+ if (fs3.existsSync(candidate)) {
1357
1540
  enginePath = candidate;
1358
1541
  } else {
1359
1542
  try {
1360
1543
  const globalRoot = execSync2("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1361
- enginePath = path2.join(globalRoot, "engine7", "dist", "main.mjs");
1544
+ enginePath = path3.join(globalRoot, "engine7", "dist", "main.mjs");
1362
1545
  } catch {
1363
1546
  console.error("\u274C \u627E\u4E0D\u5230 engine7 main.mjs");
1364
1547
  process.exit(1);
@@ -1368,7 +1551,7 @@ engine7 start \u2014 \u542F\u52A8 Engine
1368
1551
  console.log(label);
1369
1552
  console.log(` config: ${configPath2}`);
1370
1553
  console.log(` engine: ${enginePath}`);
1371
- const configName = path2.basename(configPath2);
1554
+ const configName = path3.basename(configPath2);
1372
1555
  const myPid = process.pid;
1373
1556
  try {
1374
1557
  if (process.platform === "win32") {
@@ -1386,16 +1569,16 @@ engine7 start \u2014 \u542F\u52A8 Engine
1386
1569
  }
1387
1570
  console.log("");
1388
1571
  const envForChild = { ...process.env };
1389
- const secretsDir = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7-secrets");
1390
- const cfgBase = path2.basename(configPath2, ".json");
1572
+ const secretsDir = path3.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7-secrets");
1573
+ const cfgBase = path3.basename(configPath2, ".json");
1391
1574
  const secretCandidates = [
1392
- path2.join(secretsDir, `${cfgBase}.env`),
1393
- path2.join(path2.dirname(configPath2), `.env.${cfgBase}`),
1394
- path2.join(path2.dirname(configPath2), ".env")
1575
+ path3.join(secretsDir, `${cfgBase}.env`),
1576
+ path3.join(path3.dirname(configPath2), `.env.${cfgBase}`),
1577
+ path3.join(path3.dirname(configPath2), ".env")
1395
1578
  ];
1396
1579
  for (const secretPath of secretCandidates) {
1397
- if (fs2.existsSync(secretPath)) {
1398
- const content = fs2.readFileSync(secretPath, "utf-8");
1580
+ if (fs3.existsSync(secretPath)) {
1581
+ const content = fs3.readFileSync(secretPath, "utf-8");
1399
1582
  for (const line of content.split("\n")) {
1400
1583
  const trimmed = line.trim();
1401
1584
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -1469,14 +1652,14 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
1469
1652
  console.error(`\u274C \u672A\u77E5\u6A21\u5F0F: ${mode}\uFF08\u53EF\u9009: archive / drop-last / strip-images\uFF09`);
1470
1653
  process.exit(1);
1471
1654
  }
1472
- const configRaw = JSON.parse(fs2.readFileSync(configPath2, "utf-8"));
1655
+ const configRaw = JSON.parse(fs3.readFileSync(configPath2, "utf-8"));
1473
1656
  const stateDir = configRaw.stateDir;
1474
1657
  if (!stateDir) {
1475
1658
  console.error("\u274C config \u91CC\u6CA1\u6709 stateDir");
1476
1659
  process.exit(1);
1477
1660
  }
1478
- const sessionsDir = path2.join(stateDir, "agents", "main", "sessions");
1479
- if (!fs2.existsSync(sessionsDir)) {
1661
+ const sessionsDir = path3.join(stateDir, "agents", "main", "sessions");
1662
+ if (!fs3.existsSync(sessionsDir)) {
1480
1663
  console.error(`\u274C sessions \u76EE\u5F55\u4E0D\u5B58\u5728: ${sessionsDir}`);
1481
1664
  process.exit(1);
1482
1665
  }
@@ -1484,37 +1667,37 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
1484
1667
  console.log(` config: ${configPath2}`);
1485
1668
  console.log(` mode: ${mode}`);
1486
1669
  if (mode === "drop-last") console.log(` n: ${dropN}`);
1487
- const platformMapPath = path2.join(sessionsDir, "platform-map.json");
1488
- const indexPath = path2.join(sessionsDir, "session-index.json");
1670
+ const platformMapPath = path3.join(sessionsDir, "platform-map.json");
1671
+ const indexPath = path3.join(sessionsDir, "session-index.json");
1489
1672
  let sessionFileUUID = null;
1490
- if (fs2.existsSync(indexPath)) {
1491
- const index = JSON.parse(fs2.readFileSync(indexPath, "utf-8"));
1673
+ if (fs3.existsSync(indexPath)) {
1674
+ const index = JSON.parse(fs3.readFileSync(indexPath, "utf-8"));
1492
1675
  const entries = Object.values(index);
1493
1676
  if (entries.length > 0) {
1494
1677
  const fileVal = entries[0].file || "";
1495
- sessionFileUUID = path2.isAbsolute(fileVal) ? path2.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
1678
+ sessionFileUUID = path3.isAbsolute(fileVal) ? path3.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
1496
1679
  }
1497
1680
  }
1498
1681
  if (!sessionFileUUID) {
1499
- const jsonlFiles = fs2.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs2.statSync(path2.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
1682
+ const jsonlFiles = fs3.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs3.statSync(path3.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
1500
1683
  if (jsonlFiles.length === 0) {
1501
1684
  console.error("\u274C \u627E\u4E0D\u5230\u6D3B\u8DC3\u7684 session JSONL \u6587\u4EF6");
1502
1685
  process.exit(1);
1503
1686
  }
1504
1687
  sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
1505
1688
  }
1506
- let jsonlPath = path2.join(sessionsDir, `${sessionFileUUID}.jsonl`);
1507
- if (!fs2.existsSync(jsonlPath)) {
1508
- const jsonlFiles = fs2.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs2.statSync(path2.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
1689
+ let jsonlPath = path3.join(sessionsDir, `${sessionFileUUID}.jsonl`);
1690
+ if (!fs3.existsSync(jsonlPath)) {
1691
+ const jsonlFiles = fs3.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs3.statSync(path3.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
1509
1692
  if (jsonlFiles.length === 0) {
1510
1693
  console.error(`\u274C JSONL \u6587\u4EF6\u4E0D\u5B58\u5728: ${jsonlPath}`);
1511
1694
  process.exit(1);
1512
1695
  }
1513
1696
  sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
1514
- jsonlPath = path2.join(sessionsDir, `${sessionFileUUID}.jsonl`);
1697
+ jsonlPath = path3.join(sessionsDir, `${sessionFileUUID}.jsonl`);
1515
1698
  }
1516
1699
  console.log(` file: ${jsonlPath}`);
1517
- const configName = path2.basename(configPath2);
1700
+ const configName = path3.basename(configPath2);
1518
1701
  if (autoRestart) {
1519
1702
  try {
1520
1703
  const myPid = process.pid;
@@ -1530,15 +1713,15 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
1530
1713
  }
1531
1714
  }
1532
1715
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
1533
- const { readFileSync: readFileSync3, writeFileSync: writeFileSync3, renameSync } = fs2;
1716
+ const { readFileSync: readFileSync4, writeFileSync: writeFileSync4, renameSync } = fs3;
1534
1717
  if (mode === "archive") {
1535
1718
  const archiveName = `${sessionFileUUID}.jsonl.archived.${timestamp}`;
1536
- renameSync(jsonlPath, path2.join(sessionsDir, archiveName));
1719
+ renameSync(jsonlPath, path3.join(sessionsDir, archiveName));
1537
1720
  console.log(`
1538
1721
  \u2705 \u5F52\u6863\u5B8C\u6210: ${archiveName}`);
1539
1722
  console.log(` \u91CD\u542F\u540E\u5C06\u4ECE\u7A7A\u767D\u4F1A\u8BDD\u5F00\u59CB`);
1540
1723
  } else if (mode === "drop-last") {
1541
- const lines = readFileSync3(jsonlPath, "utf-8").trim().split("\n");
1724
+ const lines = readFileSync4(jsonlPath, "utf-8").trim().split("\n");
1542
1725
  const parsed = lines.map((l) => {
1543
1726
  try {
1544
1727
  return JSON.parse(l);
@@ -1557,12 +1740,12 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
1557
1740
  }
1558
1741
  const kept = parsed.slice(0, cutIndex);
1559
1742
  const newContent = kept.map((p) => JSON.stringify(p)).join("\n") + "\n";
1560
- writeFileSync3(jsonlPath, newContent);
1743
+ writeFileSync4(jsonlPath, newContent);
1561
1744
  console.log(`
1562
1745
  \u2705 \u780D\u6389\u6700\u8FD1 ${parsed.length - cutIndex} \u884C\uFF08${dropN} \u8F6E\uFF09`);
1563
1746
  console.log(` \u4FDD\u7559 ${kept.length} \u884C`);
1564
1747
  } else if (mode === "strip-images") {
1565
- const lines = readFileSync3(jsonlPath, "utf-8").trim().split("\n");
1748
+ const lines = readFileSync4(jsonlPath, "utf-8").trim().split("\n");
1566
1749
  let stripped = 0;
1567
1750
  const newLines = lines.map((line) => {
1568
1751
  try {
@@ -1603,17 +1786,17 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
1603
1786
  return line;
1604
1787
  }
1605
1788
  });
1606
- writeFileSync3(jsonlPath, newLines.join("\n") + "\n");
1789
+ writeFileSync4(jsonlPath, newLines.join("\n") + "\n");
1607
1790
  console.log(`
1608
1791
  \u2705 \u6458\u9664 ${stripped} \u884C\u56FE\u7247\u76F8\u5173\u5185\u5BB9`);
1609
1792
  }
1610
1793
  if (autoRestart) {
1611
- const realCliPath = fs2.realpathSync(process.argv[1]);
1612
- const cliDir = path2.dirname(realCliPath);
1613
- const pkgRoot = path2.resolve(cliDir, "..");
1614
- let enginePath = path2.join(pkgRoot, "dist", "main.mjs");
1615
- if (!fs2.existsSync(enginePath)) {
1616
- enginePath = path2.join(cliDir, "main.mjs");
1794
+ const realCliPath = fs3.realpathSync(process.argv[1]);
1795
+ const cliDir = path3.dirname(realCliPath);
1796
+ const pkgRoot = path3.resolve(cliDir, "..");
1797
+ let enginePath = path3.join(pkgRoot, "dist", "main.mjs");
1798
+ if (!fs3.existsSync(enginePath)) {
1799
+ enginePath = path3.join(cliDir, "main.mjs");
1617
1800
  }
1618
1801
  console.log(`
1619
1802
  \u{1F680} \u62C9\u8D77 engine...`);
@@ -1656,18 +1839,18 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
1656
1839
  else if (args[i] === "--cwd" && args[i + 1]) cwd = args[++i];
1657
1840
  }
1658
1841
  if (!configPath2) {
1659
- const defaultCfg = path2.join(cwd, "configs", "main7.json");
1660
- const homeCfg = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
1661
- if (fs2.existsSync(defaultCfg)) {
1842
+ const defaultCfg = path3.join(cwd, "configs", "main7.json");
1843
+ const homeCfg = path3.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
1844
+ if (fs3.existsSync(defaultCfg)) {
1662
1845
  configPath2 = defaultCfg;
1663
- } else if (fs2.existsSync(homeCfg)) {
1846
+ } else if (fs3.existsSync(homeCfg)) {
1664
1847
  configPath2 = homeCfg;
1665
- cwd = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
1848
+ cwd = path3.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
1666
1849
  } else {
1667
1850
  const ptr = readHomePointer();
1668
1851
  if (ptr?.stateDir) {
1669
- const ptrCfg = path2.join(ptr.stateDir, "configs", "main7.json");
1670
- if (fs2.existsSync(ptrCfg)) {
1852
+ const ptrCfg = path3.join(ptr.stateDir, "configs", "main7.json");
1853
+ if (fs3.existsSync(ptrCfg)) {
1671
1854
  configPath2 = ptrCfg;
1672
1855
  cwd = ptr.stateDir;
1673
1856
  }
@@ -1686,14 +1869,14 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
1686
1869
  if (process.platform === "win32") {
1687
1870
  const taskName = "Engine7";
1688
1871
  const nodeExe = process.execPath;
1689
- const cliMjs = path2.resolve(engine7Bin);
1690
- const absConfig = path2.resolve(configPath2);
1691
- const wrapperPath = path2.join(cwd, "engine7-start.cmd");
1872
+ const cliMjs = path3.resolve(engine7Bin);
1873
+ const absConfig = path3.resolve(configPath2);
1874
+ const wrapperPath = path3.join(cwd, "engine7-start.cmd");
1692
1875
  const wrapperContent = `@echo off\r
1693
1876
  cd /d "${cwd}"\r
1694
1877
  "${nodeExe}" "${cliMjs}" start --config "${absConfig}"\r
1695
1878
  `;
1696
- fs2.writeFileSync(wrapperPath, wrapperContent);
1879
+ fs3.writeFileSync(wrapperPath, wrapperContent);
1697
1880
  try {
1698
1881
  execSync2(`schtasks /create /tn "${taskName}" /tr "${wrapperPath}" /sc onlogon /rl highest /f`, { stdio: "inherit", shell: true });
1699
1882
  console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1 "${taskName}" \u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
@@ -1704,11 +1887,11 @@ cd /d "${cwd}"\r
1704
1887
  }
1705
1888
  } else if (process.platform === "darwin") {
1706
1889
  const label = "com.engine7.agent";
1707
- const plistDir = path2.join(process.env.HOME, "Library", "LaunchAgents");
1708
- fs2.mkdirSync(plistDir, { recursive: true });
1709
- const plistPath = path2.join(plistDir, `${label}.plist`);
1710
- const localCli = path2.join("node_modules", "engine7", "dist", "cli.mjs");
1711
- const cliMjs = fs2.existsSync(localCli) ? path2.resolve(localCli) : path2.join(path2.dirname(path2.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
1890
+ const plistDir = path3.join(process.env.HOME, "Library", "LaunchAgents");
1891
+ fs3.mkdirSync(plistDir, { recursive: true });
1892
+ const plistPath = path3.join(plistDir, `${label}.plist`);
1893
+ const localCli = path3.join("node_modules", "engine7", "dist", "cli.mjs");
1894
+ const cliMjs = fs3.existsSync(localCli) ? path3.resolve(localCli) : path3.join(path3.dirname(path3.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
1712
1895
  const plist = `<?xml version="1.0" encoding="UTF-8"?>
1713
1896
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
1714
1897
  <plist version="1.0">
@@ -1720,14 +1903,14 @@ cd /d "${cwd}"\r
1720
1903
  <string>${cliMjs}</string>
1721
1904
  <string>start</string>
1722
1905
  <string>--config</string>
1723
- <string>${path2.resolve(configPath2)}</string>
1906
+ <string>${path3.resolve(configPath2)}</string>
1724
1907
  </array>
1725
1908
  <key>WorkingDirectory</key><string>${cwd}</string>
1726
1909
  <key>RunAtLoad</key><true/>
1727
1910
  <key>KeepAlive</key><true/>
1728
1911
  </dict>
1729
1912
  </plist>`;
1730
- fs2.writeFileSync(plistPath, plist);
1913
+ fs3.writeFileSync(plistPath, plist);
1731
1914
  try {
1732
1915
  execSync2(`launchctl load "${plistPath}"`, { stdio: "inherit" });
1733
1916
  console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
@@ -1738,9 +1921,9 @@ cd /d "${cwd}"\r
1738
1921
  }
1739
1922
  } else {
1740
1923
  const svcName = "engine7";
1741
- const svcDir = path2.join(process.env.HOME, ".config", "systemd", "user");
1742
- fs2.mkdirSync(svcDir, { recursive: true });
1743
- const svcPath = path2.join(svcDir, `${svcName}.service`);
1924
+ const svcDir = path3.join(process.env.HOME, ".config", "systemd", "user");
1925
+ fs3.mkdirSync(svcDir, { recursive: true });
1926
+ const svcPath = path3.join(svcDir, `${svcName}.service`);
1744
1927
  const svc = `[Unit]
1745
1928
  Description=Engine 7 Agent
1746
1929
  After=network.target
@@ -1748,13 +1931,13 @@ After=network.target
1748
1931
  [Service]
1749
1932
  Type=simple
1750
1933
  WorkingDirectory=${cwd}
1751
- ExecStart=${process.execPath} ${engine7Bin} start --config ${path2.resolve(configPath2)}
1934
+ ExecStart=${process.execPath} ${engine7Bin} start --config ${path3.resolve(configPath2)}
1752
1935
  Restart=on-failure
1753
1936
  RestartSec=10
1754
1937
 
1755
1938
  [Install]
1756
1939
  WantedBy=default.target`;
1757
- fs2.writeFileSync(svcPath, svc);
1940
+ fs3.writeFileSync(svcPath, svc);
1758
1941
  try {
1759
1942
  execSync2(`systemctl --user daemon-reload`, { stdio: "inherit" });
1760
1943
  execSync2(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
@@ -1775,13 +1958,13 @@ WantedBy=default.target`;
1775
1958
  process.exit(1);
1776
1959
  }
1777
1960
  } else if (process.platform === "darwin") {
1778
- const plistPath = path2.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
1961
+ const plistPath = path3.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
1779
1962
  try {
1780
1963
  execSync2(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
1781
1964
  } catch {
1782
1965
  }
1783
1966
  try {
1784
- fs2.unlinkSync(plistPath);
1967
+ fs3.unlinkSync(plistPath);
1785
1968
  } catch {
1786
1969
  }
1787
1970
  console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
@@ -1790,9 +1973,9 @@ WantedBy=default.target`;
1790
1973
  execSync2(`systemctl --user disable engine7`, { stdio: "inherit" });
1791
1974
  } catch {
1792
1975
  }
1793
- const svcPath = path2.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
1976
+ const svcPath = path3.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
1794
1977
  try {
1795
- fs2.unlinkSync(svcPath);
1978
+ fs3.unlinkSync(svcPath);
1796
1979
  } catch {
1797
1980
  }
1798
1981
  try {
@@ -1809,8 +1992,8 @@ WantedBy=default.target`;
1809
1992
  console.log("\u274C \u672A\u5B89\u88C5");
1810
1993
  }
1811
1994
  } else if (process.platform === "darwin") {
1812
- const plistPath = path2.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
1813
- if (fs2.existsSync(plistPath)) {
1995
+ const plistPath = path3.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
1996
+ if (fs3.existsSync(plistPath)) {
1814
1997
  console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
1815
1998
  } else {
1816
1999
  console.log("\u274C \u672A\u5B89\u88C5");
@@ -1833,13 +2016,13 @@ WantedBy=default.target`;
1833
2016
  console.log(`
1834
2017
  \u{1F680} engine7 init`);
1835
2018
  console.log(` state-dir: ${opts.stateDir}`);
1836
- if (fs2.existsSync(opts.stateDir) && !opts.dryRun) {
1837
- const files = fs2.readdirSync(opts.stateDir);
2019
+ if (fs3.existsSync(opts.stateDir) && !opts.dryRun) {
2020
+ const files = fs3.readdirSync(opts.stateDir);
1838
2021
  if (files.length > 0) {
1839
2022
  if (opts.force) {
1840
2023
  console.log(`
1841
2024
  \u26A0\uFE0F --force: \u6E05\u7A7A\u5DF2\u6709\u76EE\u5F55 ${opts.stateDir}`);
1842
- fs2.rmSync(opts.stateDir, { recursive: true, force: true });
2025
+ fs3.rmSync(opts.stateDir, { recursive: true, force: true });
1843
2026
  } else {
1844
2027
  console.error(`
1845
2028
  \u274C \u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u975E\u7A7A: ${opts.stateDir}`);
@@ -1859,7 +2042,7 @@ WantedBy=default.target`;
1859
2042
  rl.close();
1860
2043
  }
1861
2044
  const config = generateConfig(values);
1862
- const configPath = path2.join(opts.stateDir, "configs", "main7.json");
2045
+ const configPath = path3.join(opts.stateDir, "configs", "main7.json");
1863
2046
  const tree = buildDirTree(values);
1864
2047
  tree.push({
1865
2048
  path: configPath,
@@ -1870,9 +2053,9 @@ WantedBy=default.target`;
1870
2053
  dryRun(tree);
1871
2054
  const skillsSrc = findTemplateDir("skills");
1872
2055
  if (skillsSrc) {
1873
- const skills = fs2.readdirSync(skillsSrc);
2056
+ const skills = fs3.readdirSync(skillsSrc);
1874
2057
  for (const s of skills) {
1875
- console.log(` \u{1F4C1} ${path2.join(opts.stateDir, "workspace", "skills", s)}`);
2058
+ console.log(` \u{1F4C1} ${path3.join(opts.stateDir, "workspace", "skills", s)}`);
1876
2059
  }
1877
2060
  }
1878
2061
  } else {
@@ -1880,55 +2063,55 @@ WantedBy=default.target`;
1880
2063
  execute(tree);
1881
2064
  const skillsSrc = findTemplateDir("skills");
1882
2065
  if (skillsSrc) {
1883
- const skillsDest = path2.join(opts.stateDir, "workspace", "skills");
1884
- fs2.mkdirSync(skillsDest, { recursive: true });
1885
- const skills = fs2.readdirSync(skillsSrc);
2066
+ const skillsDest = path3.join(opts.stateDir, "workspace", "skills");
2067
+ fs3.mkdirSync(skillsDest, { recursive: true });
2068
+ const skills = fs3.readdirSync(skillsSrc);
1886
2069
  for (const s of skills) {
1887
- copyDirRecursive(path2.join(skillsSrc, s), path2.join(skillsDest, s));
2070
+ copyDirRecursive(path3.join(skillsSrc, s), path3.join(skillsDest, s));
1888
2071
  console.log(` \u{1F4E6} skill: ${s}`);
1889
2072
  }
1890
2073
  }
1891
2074
  console.log(`
1892
2075
  \u2705 \u521D\u59CB\u5316\u5B8C\u6210\uFF01
1893
2076
  `);
1894
- const homePointer = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
2077
+ const homePointer = path3.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
1895
2078
  const pointerData = { stateDir: opts.stateDir };
1896
- fs2.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
2079
+ fs3.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
1897
2080
  console.log(` \u{1F4C4} ${homePointer}\uFF08\u4ECE\u4EFB\u610F\u76EE\u5F55\u90FD\u80FD\u627E\u5230\u6B64 agent\uFF09`);
1898
2081
  console.log(`\u4E0B\u4E00\u6B65\uFF1A`);
1899
2082
  console.log(` 1. \u68C0\u67E5\u5E76\u4FEE\u6539 ${opts.stateDir}/configs/main7.json`);
1900
2083
  console.log(` 2. \u542F\u52A8 Engine: engine7 start\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
1901
2084
  console.log(` 3. \u5F00\u673A\u81EA\u542F: engine7 service install\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
1902
- console.log(` 4. \u67E5\u770B workspace: ${path2.join(opts.stateDir, "workspace")}`);
2085
+ console.log(` 4. \u67E5\u770B workspace: ${path3.join(opts.stateDir, "workspace")}`);
1903
2086
  }
1904
2087
  }
1905
2088
  function copyDirRecursive(src, dest) {
1906
- fs2.mkdirSync(dest, { recursive: true });
1907
- for (const entry of fs2.readdirSync(src, { withFileTypes: true })) {
1908
- const srcPath = path2.join(src, entry.name);
1909
- const destPath = path2.join(dest, entry.name);
2089
+ fs3.mkdirSync(dest, { recursive: true });
2090
+ for (const entry of fs3.readdirSync(src, { withFileTypes: true })) {
2091
+ const srcPath = path3.join(src, entry.name);
2092
+ const destPath = path3.join(dest, entry.name);
1910
2093
  if (entry.isDirectory()) {
1911
2094
  copyDirRecursive(srcPath, destPath);
1912
2095
  } else {
1913
- fs2.copyFileSync(srcPath, destPath);
2096
+ fs3.copyFileSync(srcPath, destPath);
1914
2097
  }
1915
2098
  }
1916
2099
  }
1917
2100
  function findTemplateDir(name) {
1918
2101
  const candidates = [
1919
- path2.join(__dirname, "..", "templates", name),
1920
- path2.join(__dirname, "..", "..", "templates", name),
1921
- path2.join(process.cwd(), "templates", name)
2102
+ path3.join(__dirname, "..", "templates", name),
2103
+ path3.join(__dirname, "..", "..", "templates", name),
2104
+ path3.join(process.cwd(), "templates", name)
1922
2105
  ];
1923
2106
  for (const p of candidates) {
1924
- if (fs2.existsSync(p)) return p;
2107
+ if (fs3.existsSync(p)) return p;
1925
2108
  }
1926
2109
  return null;
1927
2110
  }
1928
2111
  function readHomePointer() {
1929
- const ptrPath = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
2112
+ const ptrPath = path3.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
1930
2113
  try {
1931
- return JSON.parse(fs2.readFileSync(ptrPath, "utf-8"));
2114
+ return JSON.parse(fs3.readFileSync(ptrPath, "utf-8"));
1932
2115
  } catch {
1933
2116
  return null;
1934
2117
  }