engine7 7.1.6 → 7.1.8

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
@@ -1,10 +1,494 @@
1
- // src/cli-init.ts
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // src/cli-travel.ts
12
+ var cli_travel_exports = {};
13
+ __export(cli_travel_exports, {
14
+ doExport: () => doExport,
15
+ doImport: () => doImport,
16
+ loadTravelConfig: () => loadTravelConfig,
17
+ saveTravelConfig: () => saveTravelConfig
18
+ });
2
19
  import * as path from "node:path";
3
20
  import * as fs from "node:fs";
21
+ import * as os from "node:os";
22
+ import { execSync } from "node:child_process";
23
+ function loadTravelConfig() {
24
+ try {
25
+ if (!fs.existsSync(CONFIG_PATH)) return null;
26
+ return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+ function saveTravelConfig(cfg) {
32
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
33
+ }
34
+ function sanitizeContent(content, dirs) {
35
+ let result = content;
36
+ for (const { placeholder, getOriginal } of PATH_PLACEHOLDERS) {
37
+ const original = getOriginal(dirs);
38
+ if (original) {
39
+ result = result.split(original).join(placeholder);
40
+ result = result.split(original.replace(/\//g, "\\")).join(placeholder);
41
+ }
42
+ }
43
+ return result;
44
+ }
45
+ function restoreContent(content, dirs) {
46
+ let result = content;
47
+ for (const { placeholder, getOriginal } of PATH_PLACEHOLDERS) {
48
+ const target = getOriginal(dirs);
49
+ if (target) {
50
+ result = result.split(placeholder).join(target);
51
+ }
52
+ }
53
+ return result;
54
+ }
55
+ function isTextFile(filePath) {
56
+ const ext = path.extname(filePath).toLowerCase();
57
+ return TEXT_EXTENSIONS.has(ext);
58
+ }
59
+ function shouldExclude(name) {
60
+ for (const pattern of WORKSPACE_EXCLUDE) {
61
+ if (pattern.startsWith("*")) {
62
+ if (name.includes(pattern.slice(1).replace("*", ""))) return true;
63
+ } else if (name === pattern) {
64
+ return true;
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+ function collectFiles(rootDir, includeSet, optionalSet) {
70
+ const files = [];
71
+ const entries = fs.readdirSync(rootDir, { withFileTypes: true });
72
+ for (const entry of entries) {
73
+ if (shouldExclude(entry.name)) continue;
74
+ const fullPath = path.join(rootDir, entry.name);
75
+ const realPath = fs.realpathSync(fullPath);
76
+ if (realPath !== fullPath) {
77
+ try {
78
+ const lstat = fs.lstatSync(fullPath);
79
+ if (lstat.isSymbolicLink()) {
80
+ continue;
81
+ }
82
+ } catch {
83
+ }
84
+ }
85
+ const isInclude = includeSet.has(entry.name) || optionalSet.has(entry.name);
86
+ if (!isInclude) continue;
87
+ if (entry.isDirectory()) {
88
+ const subFiles = collectAllFiles(fullPath);
89
+ files.push(...subFiles);
90
+ } else {
91
+ files.push(fullPath);
92
+ }
93
+ }
94
+ return files;
95
+ }
96
+ function collectAllFiles(dir) {
97
+ const files = [];
98
+ try {
99
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
100
+ for (const entry of entries) {
101
+ if (shouldExclude(entry.name)) continue;
102
+ const fullPath = path.join(dir, entry.name);
103
+ try {
104
+ if (fs.lstatSync(fullPath).isSymbolicLink()) continue;
105
+ } catch {
106
+ }
107
+ if (entry.isDirectory()) {
108
+ files.push(...collectAllFiles(fullPath));
109
+ } else {
110
+ files.push(fullPath);
111
+ }
112
+ }
113
+ } catch {
114
+ }
115
+ return files;
116
+ }
117
+ function collectRecentSessions(agentsDir, days = 7) {
118
+ const files = [];
119
+ if (!fs.existsSync(agentsDir)) return files;
120
+ const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
121
+ try {
122
+ const entries = fs.readdirSync(agentsDir, { withFileTypes: true });
123
+ for (const entry of entries) {
124
+ const fullPath = path.join(agentsDir, entry.name);
125
+ if (entry.isDirectory()) {
126
+ const sub = collectAllFiles(fullPath);
127
+ for (const f of sub) {
128
+ if (!f.endsWith(".jsonl")) continue;
129
+ const stat = fs.statSync(f);
130
+ if (stat.mtimeMs > cutoff) files.push(f);
131
+ }
132
+ } else if (entry.name.endsWith(".jsonl")) {
133
+ const stat = fs.statSync(fullPath);
134
+ if (stat.mtimeMs > cutoff) files.push(fullPath);
135
+ }
136
+ }
137
+ } catch {
138
+ }
139
+ return files;
140
+ }
141
+ async function doExport(opts) {
142
+ const { agentName, stateDir, note, dryRun: dryRun2 } = opts;
143
+ const workspace = opts.workspace || path.join(stateDir, "workspace");
144
+ const engineHome = path.join(os.homedir(), ".openclaw");
145
+ console.log(`\u{1F4E6} engine7 export`);
146
+ console.log(` agent: ${agentName}`);
147
+ console.log(` state: ${stateDir}`);
148
+ console.log(` workspace: ${workspace}`);
149
+ if (!fs.existsSync(workspace)) {
150
+ console.error(`\u274C workspace \u4E0D\u5B58\u5728: ${workspace}`);
151
+ process.exit(1);
152
+ }
153
+ const dirs = { workspace, stateDir, engineHome };
154
+ const wsFiles = collectFiles(workspace, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL);
155
+ const sessionFiles = collectRecentSessions(path.join(stateDir, "agents"), 7);
156
+ console.log(` workspace \u6587\u4EF6: ${wsFiles.length}`);
157
+ console.log(` session jsonl: ${sessionFiles.length} (\u6700\u8FD17\u5929)`);
158
+ if (dryRun2) {
159
+ console.log(`
160
+ [DRY RUN] \u4F1A\u6253\u5305\u4EE5\u4E0B\u6587\u4EF6:`);
161
+ wsFiles.slice(0, 20).forEach((f) => console.log(` ${path.relative(workspace, f)}`));
162
+ if (wsFiles.length > 20) console.log(` ... \u8FD8\u6709 ${wsFiles.length - 20} \u4E2A\u6587\u4EF6`);
163
+ console.log(`
164
+ [DRY RUN] \u4E0D\u5B9E\u9645\u6253\u5305`);
165
+ return;
166
+ }
167
+ const now = /* @__PURE__ */ new Date();
168
+ 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")}`;
169
+ const tmpDir = path.join(os.tmpdir(), `engine7-export-${agentName}-${version}`);
170
+ fs.mkdirSync(tmpDir, { recursive: true });
171
+ const stagingDir = path.join(tmpDir, agentName);
172
+ fs.mkdirSync(stagingDir, { recursive: true });
173
+ let fileCount = 0;
174
+ let totalSize = 0;
175
+ for (const srcFile of wsFiles) {
176
+ const relPath = path.relative(workspace, srcFile);
177
+ const destFile = path.join(stagingDir, "workspace", relPath);
178
+ fs.mkdirSync(path.dirname(destFile), { recursive: true });
179
+ if (isTextFile(srcFile)) {
180
+ const content = fs.readFileSync(srcFile, "utf-8");
181
+ fs.writeFileSync(destFile, sanitizeContent(content, dirs));
182
+ } else {
183
+ fs.copyFileSync(srcFile, destFile);
184
+ }
185
+ fileCount++;
186
+ totalSize += fs.statSync(srcFile).size;
187
+ }
188
+ for (const srcFile of sessionFiles) {
189
+ const relPath = path.relative(stateDir, srcFile);
190
+ const destFile = path.join(stagingDir, relPath);
191
+ fs.mkdirSync(path.dirname(destFile), { recursive: true });
192
+ fs.copyFileSync(srcFile, destFile);
193
+ fileCount++;
194
+ totalSize += fs.statSync(srcFile).size;
195
+ }
196
+ const manifest = {
197
+ agentName,
198
+ version,
199
+ createdAt: now.toISOString(),
200
+ engineVersion: "7.x",
201
+ originalPaths: {
202
+ WORKSPACE: workspace,
203
+ STATE_DIR: stateDir,
204
+ ENGINE_HOME: engineHome
205
+ },
206
+ fileCount,
207
+ totalSize,
208
+ note
209
+ };
210
+ fs.writeFileSync(path.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2));
211
+ const tarFile = path.join(tmpDir, `${agentName}-${version}.tar.gz`);
212
+ console.log(`
213
+ \u{1F5DC}\uFE0F \u6253\u5305\u4E2D...`);
214
+ if (process.platform === "win32") {
215
+ const zipFile = tarFile.replace(".tar.gz", ".zip");
216
+ const stagingParent = path.dirname(stagingDir);
217
+ const childName = path.basename(stagingDir);
218
+ execSync(`powershell -Command "Compress-Archive -Path '${stagingParent}/${childName}/*' -DestinationPath '${zipFile}' -Force"`, { stdio: "pipe" });
219
+ fs.renameSync(zipFile, tarFile);
220
+ } else {
221
+ execSync(`tar -czf "${tarFile}" -C "${tmpDir}" ${agentName}`, { stdio: "pipe" });
222
+ }
223
+ const tarSize = fs.statSync(tarFile).size;
224
+ console.log(`\u2705 \u6253\u5305\u5B8C\u6210: ${tarFile} (${(tarSize / 1024 / 1024).toFixed(1)} MB, ${fileCount} \u6587\u4EF6)`);
225
+ const cfg = loadTravelConfig();
226
+ if (!cfg || !cfg.githubToken) {
227
+ console.log(`
228
+ \u26A0\uFE0F \u672A\u914D\u7F6E GitHub\uFF0Ctar.gz \u5DF2\u751F\u6210: ${tarFile}`);
229
+ console.log(` \u914D\u7F6E GitHub: \u7F16\u8F91 ${CONFIG_PATH}`);
230
+ console.log(` \u6216\u624B\u52A8\u4E0A\u4F20\u5230 GitHub private repo release`);
231
+ return;
232
+ }
233
+ await uploadToGitHub(cfg, tarFile, agentName, version, manifest);
234
+ }
235
+ async function doImport(opts) {
236
+ const { agentName, stateDir, version, dryRun: dryRun2 } = opts;
237
+ console.log(`\u{1F4E5} engine7 import`);
238
+ console.log(` agent: ${agentName}`);
239
+ console.log(` target: ${stateDir}`);
240
+ const cfg = loadTravelConfig();
241
+ if (!cfg || !cfg.githubToken) {
242
+ console.error(`\u274C \u672A\u914D\u7F6E GitHub\uFF0C\u65E0\u6CD5\u4E0B\u8F7D`);
243
+ console.error(` \u914D\u7F6E: \u7F16\u8F91 ${CONFIG_PATH}`);
244
+ process.exit(1);
245
+ }
246
+ const tmpDir = path.join(os.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
247
+ fs.mkdirSync(tmpDir, { recursive: true });
248
+ const tarFile = await downloadFromGitHub(cfg, agentName, version, tmpDir);
249
+ console.log(`\u2705 \u4E0B\u8F7D\u5B8C\u6210: ${tarFile}`);
250
+ if (dryRun2) {
251
+ console.log(`
252
+ [DRY RUN] \u53EA\u4E0B\u8F7D\u4E0D\u6062\u590D`);
253
+ return;
254
+ }
255
+ console.log(`\u{1F4C2} \u89E3\u5305\u4E2D...`);
256
+ if (process.platform === "win32") {
257
+ execSync(`powershell -Command "Expand-Archive -Path '${tarFile}' -DestinationPath '${tmpDir}' -Force"`, { stdio: "pipe" });
258
+ } else {
259
+ execSync(`tar -xzf "${tarFile}" -C "${tmpDir}"`, { stdio: "pipe" });
260
+ }
261
+ const stagingDir = path.join(tmpDir, agentName);
262
+ const manifestPath = path.join(stagingDir, "manifest.json");
263
+ if (!fs.existsSync(manifestPath)) {
264
+ console.error(`\u274C manifest.json \u4E0D\u5B58\u5728\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);
265
+ process.exit(1);
266
+ }
267
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
268
+ const workspace = path.join(stateDir, "workspace");
269
+ const engineHome = path.join(os.homedir(), ".openclaw");
270
+ const dirs = { workspace, stateDir, engineHome };
271
+ console.log(` \u7248\u672C: ${manifest.version}`);
272
+ console.log(` \u521B\u5EFA: ${manifest.createdAt}`);
273
+ console.log(` \u6587\u4EF6\u6570: ${manifest.fileCount}`);
274
+ const wsStaging = path.join(stagingDir, "workspace");
275
+ let restoredCount = 0;
276
+ if (fs.existsSync(wsStaging)) {
277
+ const allFiles = collectAllFiles(wsStaging);
278
+ for (const srcFile of allFiles) {
279
+ const relPath = path.relative(wsStaging, srcFile);
280
+ const destFile = path.join(workspace, relPath);
281
+ fs.mkdirSync(path.dirname(destFile), { recursive: true });
282
+ if (isTextFile(srcFile)) {
283
+ const content = fs.readFileSync(srcFile, "utf-8");
284
+ fs.writeFileSync(destFile, restoreContent(content, dirs));
285
+ } else {
286
+ fs.copyFileSync(srcFile, destFile);
287
+ }
288
+ restoredCount++;
289
+ }
290
+ }
291
+ const agentsStaging = path.join(stagingDir, "agents");
292
+ if (fs.existsSync(agentsStaging)) {
293
+ const sessionFiles = collectAllFiles(agentsStaging);
294
+ for (const srcFile of sessionFiles) {
295
+ const relPath = path.relative(stagingDir, srcFile);
296
+ const destFile = path.join(stateDir, relPath);
297
+ fs.mkdirSync(path.dirname(destFile), { recursive: true });
298
+ fs.copyFileSync(srcFile, destFile);
299
+ restoredCount++;
300
+ }
301
+ }
302
+ console.log(`\u2705 \u6062\u590D\u5B8C\u6210: ${restoredCount} \u6587\u4EF6 \u2192 ${stateDir}`);
303
+ console.log(`
304
+ \u{1F4A1} \u4E0B\u4E00\u6B65: engine7 start --config <path>`);
305
+ fs.rmSync(tmpDir, { recursive: true, force: true });
306
+ }
307
+ async function uploadToGitHub(cfg, tarFile, agentName, version, manifest) {
308
+ const repo = `${cfg.githubOwner}/${cfg.repoName}`;
309
+ const tag = `${agentName}-${version}`;
310
+ console.log(`
311
+ \u{1F4E4} \u4E0A\u4F20\u5230 GitHub: ${repo} release ${tag}`);
312
+ try {
313
+ const releaseBody = Object.entries(manifest).map(([k, v]) => `- **${k}**: ${typeof v === "object" ? JSON.stringify(v) : v}`).join("\n");
314
+ const createRes = await fetch(`https://api.github.com/repos/${repo}/releases`, {
315
+ method: "POST",
316
+ headers: {
317
+ "Authorization": `Bearer ${cfg.githubToken}`,
318
+ "Accept": "application/vnd.github+json",
319
+ "Content-Type": "application/json"
320
+ },
321
+ body: JSON.stringify({
322
+ tag_name: tag,
323
+ name: `${agentName} ${version}`,
324
+ body: releaseBody,
325
+ prerelease: false,
326
+ make_latest: "true"
327
+ })
328
+ });
329
+ if (!createRes.ok) {
330
+ const err = await createRes.text();
331
+ throw new Error(`\u521B\u5EFA release \u5931\u8D25: ${createRes.status} ${err}`);
332
+ }
333
+ const release = await createRes.json();
334
+ const uploadUrl = release.upload_url.replace("{?name,label}", "");
335
+ const fileBuffer = fs.readFileSync(tarFile);
336
+ const fileName = path.basename(tarFile);
337
+ const uploadRes = await fetch(`${uploadUrl}?name=${fileName}`, {
338
+ method: "POST",
339
+ headers: {
340
+ "Authorization": `Bearer ${cfg.githubToken}`,
341
+ "Accept": "application/vnd.github+json",
342
+ "Content-Type": "application/gzip",
343
+ "Content-Length": String(fileBuffer.length)
344
+ },
345
+ body: fileBuffer
346
+ });
347
+ if (!uploadRes.ok) {
348
+ const err = await uploadRes.text();
349
+ throw new Error(`\u4E0A\u4F20 asset \u5931\u8D25: ${uploadRes.status} ${err}`);
350
+ }
351
+ console.log(`\u2705 \u4E0A\u4F20\u6210\u529F!`);
352
+ console.log(` release: ${release.html_url}`);
353
+ } catch (e) {
354
+ console.error(`\u274C GitHub \u4E0A\u4F20\u5931\u8D25: ${e.message}`);
355
+ console.error(` tar.gz \u4ECD\u5728: ${tarFile}`);
356
+ throw e;
357
+ }
358
+ try {
359
+ fs.rmSync(path.dirname(tarFile), { recursive: true, force: true });
360
+ } catch {
361
+ }
362
+ }
363
+ async function downloadFromGitHub(cfg, agentName, version, destDir) {
364
+ const repo = `${cfg.githubOwner}/${cfg.repoName}`;
365
+ const tag = version || await getLatestReleaseTag(cfg, agentName);
366
+ console.log(`\u2B07\uFE0F \u4E0B\u8F7D: ${repo} release ${tag}`);
367
+ const res = await fetch(`https://api.github.com/repos/${repo}/releases/tags/${tag}`, {
368
+ headers: {
369
+ "Authorization": `Bearer ${cfg.githubToken}`,
370
+ "Accept": "application/vnd.github+json"
371
+ }
372
+ });
373
+ if (!res.ok) {
374
+ throw new Error(`\u83B7\u53D6 release \u5931\u8D25: ${res.status}`);
375
+ }
376
+ const release = await res.json();
377
+ const asset = release.assets?.find((a) => a.name.endsWith(".tar.gz"));
378
+ if (!asset) {
379
+ throw new Error(`release ${tag} \u6CA1\u6709 tar.gz asset`);
380
+ }
381
+ const downloadRes = await fetch(asset.url, {
382
+ headers: {
383
+ "Authorization": `Bearer ${cfg.githubToken}`,
384
+ "Accept": "application/octet-stream"
385
+ }
386
+ });
387
+ if (!downloadRes.ok) {
388
+ throw new Error(`\u4E0B\u8F7D asset \u5931\u8D25: ${downloadRes.status}`);
389
+ }
390
+ const buffer = Buffer.from(await downloadRes.arrayBuffer());
391
+ const tarFile = path.join(destDir, asset.name);
392
+ fs.writeFileSync(tarFile, buffer);
393
+ return tarFile;
394
+ }
395
+ async function getLatestReleaseTag(cfg, agentName) {
396
+ const repo = `${cfg.githubOwner}/${cfg.repoName}`;
397
+ const res = await fetch(`https://api.github.com/repos/${repo}/releases?per_page=30`, {
398
+ headers: {
399
+ "Authorization": `Bearer ${cfg.githubToken}`,
400
+ "Accept": "application/vnd.github+json"
401
+ }
402
+ });
403
+ if (!res.ok) {
404
+ throw new Error(`\u83B7\u53D6 release \u5217\u8868\u5931\u8D25: ${res.status}`);
405
+ }
406
+ const releases = await res.json();
407
+ const match = releases.find((r) => r.tag_name?.startsWith(`${agentName}-`));
408
+ if (!match) {
409
+ throw new Error(`\u6CA1\u6709\u627E\u5230 ${agentName} \u7684 release`);
410
+ }
411
+ return match.tag_name;
412
+ }
413
+ var CONFIG_PATH, PATH_PLACEHOLDERS, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL, WORKSPACE_EXCLUDE, TEXT_EXTENSIONS;
414
+ var init_cli_travel = __esm({
415
+ "src/cli-travel.ts"() {
416
+ "use strict";
417
+ CONFIG_PATH = path.join(os.homedir(), ".engine7-travel.json");
418
+ PATH_PLACEHOLDERS = [
419
+ { placeholder: "{{WORKSPACE}}", getOriginal: (d) => d.workspace },
420
+ { placeholder: "{{ENGINE_HOME}}", getOriginal: (d) => d.engineHome },
421
+ { placeholder: "{{STATE_DIR}}", getOriginal: (d) => d.stateDir }
422
+ ];
423
+ WORKSPACE_INCLUDE = /* @__PURE__ */ new Set([
424
+ // 核心文件
425
+ "AGENTS.md",
426
+ "SOUL.md",
427
+ "MEMORY.md",
428
+ "USER.md",
429
+ "HEARTBEAT.md",
430
+ "INDEX.md",
431
+ "SESSION-STATE.md",
432
+ // 核心目录
433
+ "prompts",
434
+ "topics",
435
+ "memory",
436
+ "inner-voice",
437
+ "docs",
438
+ "skills",
439
+ "voice-chat",
440
+ "scripts",
441
+ "selfie",
442
+ "moodboard",
443
+ // 状态文件
444
+ "calendar.db",
445
+ "nudge-state.json"
446
+ ]);
447
+ WORKSPACE_OPTIONAL = /* @__PURE__ */ new Set([
448
+ "images",
449
+ "tools"
450
+ ]);
451
+ WORKSPACE_EXCLUDE = /* @__PURE__ */ new Set([
452
+ "livestream",
453
+ "content-library",
454
+ "tmp",
455
+ ".git",
456
+ "node_modules",
457
+ "memory_runs",
458
+ "workspace",
459
+ "prompt-archive",
460
+ "aim-archive",
461
+ "test-agent",
462
+ "nul",
463
+ "*.bak*",
464
+ "*.bak-*"
465
+ ]);
466
+ TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
467
+ ".md",
468
+ ".json",
469
+ ".txt",
470
+ ".js",
471
+ ".ts",
472
+ ".mjs",
473
+ ".py",
474
+ ".yaml",
475
+ ".yml",
476
+ ".cmd",
477
+ ".bat",
478
+ ".sh",
479
+ ".csv",
480
+ ".html"
481
+ ]);
482
+ }
483
+ });
484
+
485
+ // src/cli-init.ts
486
+ import * as path2 from "node:path";
487
+ import * as fs2 from "node:fs";
4
488
  import * as readline from "node:readline";
5
489
  import { fileURLToPath } from "node:url";
6
490
  var __filename = fileURLToPath(import.meta.url);
7
- var __dirname = path.dirname(__filename);
491
+ var __dirname = path2.dirname(__filename);
8
492
  var SCHEMA_VERSION = 1;
9
493
  function parseArgs() {
10
494
  const args = process.argv.slice(2);
@@ -26,10 +510,10 @@ function parseArgs() {
26
510
  }
27
511
  }
28
512
  if (!stateDir) {
29
- stateDir = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
513
+ stateDir = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
30
514
  console.log(` \u4F7F\u7528\u9ED8\u8BA4\u76EE\u5F55: ${stateDir}`);
31
515
  }
32
- stateDir = path.resolve(stateDir);
516
+ stateDir = path2.resolve(stateDir);
33
517
  return { stateDir, quick, dryRun: dryRun2 };
34
518
  }
35
519
  function printHelp() {
@@ -41,6 +525,8 @@ Engine 7 \u2014 Self-hosted AI agent engine
41
525
  engine7 start [--config <path>] \u542F\u52A8 Engine
42
526
  engine7 restart [--config <path>] \u91CD\u542F Engine\uFF08\u6740\u65E7\u8FDB\u7A0B+\u542F\u52A8\uFF09
43
527
  engine7 service install|uninstall|status \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
528
+ engine7 export [--state-dir <path>] \u6253\u5305 agent workspace \u2192 GitHub release
529
+ engine7 import --state-dir <path> \u4ECE GitHub release \u6062\u590D agent
44
530
 
45
531
  init \u9009\u9879:
46
532
  --state-dir <path> agent \u6839\u76EE\u5F55\uFF08\u5FC5\u586B\uFF0C\u652F\u6301\u76F8\u5BF9\u8DEF\u5F84\uFF09
@@ -50,11 +536,25 @@ init \u9009\u9879:
50
536
  start \u9009\u9879:
51
537
  --config <path> config \u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4: configs/main7.json\uFF09
52
538
 
539
+ export \u9009\u9879:
540
+ --state-dir <path> agent \u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4: \u5F53\u524D\u76EE\u5F55\u4E0A\u7EA7\uFF09
541
+ --agent <name> agent \u540D\u79F0\uFF08\u9ED8\u8BA4: state-dir basename\uFF09
542
+ --note <text> \u7248\u672C\u5907\u6CE8
543
+ --dry-run \u53EA\u5217\u51FA\u4F1A\u6253\u5305\u4EC0\u4E48\uFF0C\u4E0D\u5B9E\u9645\u4E0A\u4F20
544
+
545
+ import \u9009\u9879:
546
+ --state-dir <path> \u76EE\u6807 agent \u6839\u76EE\u5F55\uFF08\u5FC5\u586B\uFF09
547
+ --agent <name> agent \u540D\u79F0
548
+ --version <tag> \u6307\u5B9A\u7248\u672C\uFF08\u9ED8\u8BA4: \u6700\u65B0\uFF09
549
+ --dry-run \u53EA\u4E0B\u8F7D\u4E0D\u6062\u590D
550
+
53
551
  \u793A\u4F8B:
54
552
  engine7 init --state-dir D:/my-agent
55
553
  engine7 init --state-dir ./my-agent --quick
56
554
  engine7 start
57
555
  engine7 start --config configs/xiaowen.json
556
+ engine7 export --state-dir D:/xiaoke --agent xiaoke --note "travel test"
557
+ engine7 import --state-dir D:/xiaoke --agent xiaoke
58
558
  `);
59
559
  }
60
560
  function createReadline() {
@@ -166,7 +666,7 @@ async function interactiveConfig(rl, defaults) {
166
666
  return v;
167
667
  }
168
668
  function generateConfig(v) {
169
- const workspace = path.join(v.stateDir, "workspace").replace(/\\/g, "/");
669
+ const workspace = path2.join(v.stateDir, "workspace").replace(/\\/g, "/");
170
670
  const config = {
171
671
  schemaVersion: SCHEMA_VERSION,
172
672
  stateDir: v.stateDir.replace(/\\/g, "/"),
@@ -292,45 +792,45 @@ function generateConfig(v) {
292
792
  }
293
793
  function buildDirTree(v) {
294
794
  const d = v.stateDir;
295
- const w = path.join(d, "workspace");
795
+ const w = path2.join(d, "workspace");
296
796
  const now = (/* @__PURE__ */ new Date()).toLocaleString("sv-SE", { timeZone: "Asia/Shanghai", hour12: false });
297
797
  return [
298
798
  // 目录
299
- { path: path.join(d, "configs"), type: "dir" },
300
- { path: path.join(d, "state", "agents", "main", "sessions"), type: "dir" },
301
- { path: path.join(w, "prompts"), type: "dir" },
302
- { path: path.join(w, "memory", "daily"), type: "dir" },
303
- { path: path.join(w, "docs", "research"), type: "dir" },
304
- { path: path.join(w, "docs", "todo"), type: "dir" },
305
- { path: path.join(w, "docs", "decisions"), type: "dir" },
306
- { path: path.join(w, "docs", "knowledge"), type: "dir" },
307
- { path: path.join(w, "docs", "sop"), type: "dir" },
308
- { path: path.join(d, "logs"), type: "dir" },
309
- { path: path.join(d, "media", "inbound"), type: "dir" },
799
+ { path: path2.join(d, "configs"), type: "dir" },
800
+ { path: path2.join(d, "state", "agents", "main", "sessions"), type: "dir" },
801
+ { path: path2.join(w, "prompts"), type: "dir" },
802
+ { path: path2.join(w, "memory", "daily"), type: "dir" },
803
+ { path: path2.join(w, "docs", "research"), type: "dir" },
804
+ { path: path2.join(w, "docs", "todo"), type: "dir" },
805
+ { path: path2.join(w, "docs", "decisions"), type: "dir" },
806
+ { path: path2.join(w, "docs", "knowledge"), type: "dir" },
807
+ { path: path2.join(w, "docs", "sop"), type: "dir" },
808
+ { path: path2.join(d, "logs"), type: "dir" },
809
+ { path: path2.join(d, "media", "inbound"), type: "dir" },
310
810
  // workspace 文件
311
811
  {
312
- path: path.join(w, "SESSION-STATE.md"),
812
+ path: path2.join(w, "SESSION-STATE.md"),
313
813
  type: "file",
314
814
  content: readTemplate("workspace/SESSION-STATE.md").replace("{{CURRENT_TIME}}", now)
315
815
  },
316
- { path: path.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
816
+ { path: path2.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
317
817
  {
318
- path: path.join(w, "SOUL.md"),
818
+ path: path2.join(w, "SOUL.md"),
319
819
  type: "file",
320
820
  content: readTemplate("workspace/SOUL.md").replace(/\{\{AGENT_NAME\}\}/g, v.agentName)
321
821
  },
322
- { path: path.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
822
+ { path: path2.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
323
823
  {
324
- path: path.join(w, "prompts", "contacts.md"),
824
+ path: path2.join(w, "prompts", "contacts.md"),
325
825
  type: "file",
326
826
  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")
327
827
  },
328
- { path: path.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
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" },
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" },
828
+ { path: path2.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
829
+ { 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" },
830
+ { 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" },
331
831
  // package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
332
832
  {
333
- path: path.join(d, "package.json"),
833
+ path: path2.join(d, "package.json"),
334
834
  type: "file",
335
835
  content: JSON.stringify({
336
836
  name: v.agentName.toLowerCase().replace(/[^a-z0-9-]/g, "-") || "agent",
@@ -341,7 +841,7 @@ function buildDirTree(v) {
341
841
  },
342
842
  // 启动脚本(根据 OS 生成)
343
843
  ...process.platform === "win32" ? [{
344
- path: path.join(d, "start.cmd"),
844
+ path: path2.join(d, "start.cmd"),
345
845
  type: "file",
346
846
  content: `@echo off
347
847
  rem Engine 7 startup script
@@ -373,7 +873,7 @@ if %ERRORLEVEL% NEQ 0 (
373
873
  )
374
874
  `
375
875
  }] : [{
376
- path: path.join(d, "start.sh"),
876
+ path: path2.join(d, "start.sh"),
377
877
  type: "file",
378
878
  content: `#!/bin/bash
379
879
  # Engine 7 startup script
@@ -406,13 +906,13 @@ node "$ENGINE7_BIN" --engine-config configs/main7.json
406
906
  }
407
907
  function readTemplate(relativePath) {
408
908
  const candidates = [
409
- path.join(__dirname, "..", "templates", relativePath),
410
- path.join(__dirname, "..", "..", "templates", relativePath),
411
- path.join(process.cwd(), "templates", relativePath)
909
+ path2.join(__dirname, "..", "templates", relativePath),
910
+ path2.join(__dirname, "..", "..", "templates", relativePath),
911
+ path2.join(process.cwd(), "templates", relativePath)
412
912
  ];
413
913
  for (const p of candidates) {
414
- if (fs.existsSync(p)) {
415
- return fs.readFileSync(p, "utf-8");
914
+ if (fs2.existsSync(p)) {
915
+ return fs2.readFileSync(p, "utf-8");
416
916
  }
417
917
  }
418
918
  throw new Error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${relativePath}\uFF08\u627E\u4E86: ${candidates.join(", ")}\uFF09`);
@@ -427,11 +927,11 @@ function dryRun(entries) {
427
927
  function execute(entries) {
428
928
  for (const e of entries) {
429
929
  if (e.type === "dir") {
430
- fs.mkdirSync(e.path, { recursive: true });
930
+ fs2.mkdirSync(e.path, { recursive: true });
431
931
  console.log(` \u{1F4C1} ${e.path}`);
432
932
  } else {
433
- fs.mkdirSync(path.dirname(e.path), { recursive: true });
434
- fs.writeFileSync(e.path, e.content || "", "utf-8");
933
+ fs2.mkdirSync(path2.dirname(e.path), { recursive: true });
934
+ fs2.writeFileSync(e.path, e.content || "", "utf-8");
435
935
  console.log(` \u{1F4C4} ${e.path}`);
436
936
  }
437
937
  }
@@ -447,7 +947,45 @@ async function main() {
447
947
  printHelp();
448
948
  process.exit(0);
449
949
  }
450
- if (subcommand === "start") {
950
+ if (subcommand === "export") {
951
+ const { doExport: doExport2 } = await Promise.resolve().then(() => (init_cli_travel(), cli_travel_exports));
952
+ let exportStateDir = "";
953
+ let agentName = "";
954
+ let note = "";
955
+ let dryRun2 = false;
956
+ for (let i = 1; i < args.length; i++) {
957
+ if (args[i] === "--state-dir" && args[i + 1]) exportStateDir = args[++i];
958
+ else if (args[i] === "--agent" && args[i + 1]) agentName = args[++i];
959
+ else if (args[i] === "--note" && args[i + 1]) note = args[++i];
960
+ else if (args[i] === "--dry-run") dryRun2 = true;
961
+ }
962
+ if (!exportStateDir) exportStateDir = path2.resolve(process.cwd());
963
+ if (!agentName) agentName = path2.basename(exportStateDir);
964
+ await doExport2({ agentName, stateDir: exportStateDir, note, dryRun: dryRun2 });
965
+ process.exit(0);
966
+ }
967
+ if (subcommand === "import") {
968
+ const { doImport: doImport2 } = await Promise.resolve().then(() => (init_cli_travel(), cli_travel_exports));
969
+ let importStateDir = "";
970
+ let agentName = "";
971
+ let version = "";
972
+ let dryRun2 = false;
973
+ for (let i = 1; i < args.length; i++) {
974
+ if (args[i] === "--state-dir" && args[i + 1]) importStateDir = args[++i];
975
+ else if (args[i] === "--agent" && args[i + 1]) agentName = args[++i];
976
+ else if (args[i] === "--version" && args[i + 1]) version = args[++i];
977
+ else if (args[i] === "--dry-run") dryRun2 = true;
978
+ }
979
+ if (!importStateDir) {
980
+ console.error("\u274C import \u9700\u8981 --state-dir <path>");
981
+ process.exit(1);
982
+ }
983
+ if (!agentName) agentName = path2.basename(importStateDir);
984
+ await doImport2({ agentName, stateDir: importStateDir, version, dryRun: dryRun2 });
985
+ process.exit(0);
986
+ }
987
+ if (subcommand === "start" || subcommand === "restart") {
988
+ const label = subcommand === "restart" ? "\u{1F504} engine7 restart" : "\u{1F680} engine7 start";
451
989
  let configPath2 = "";
452
990
  for (let i = 1; i < args.length; i++) {
453
991
  if (args[i] === "--config" && args[i + 1]) {
@@ -467,18 +1005,18 @@ engine7 start \u2014 \u542F\u52A8 Engine
467
1005
  }
468
1006
  }
469
1007
  if (!configPath2) {
470
- const defaultCfg = path.join("configs", "main7.json");
471
- const homeCfg = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
472
- if (fs.existsSync(defaultCfg)) {
1008
+ const defaultCfg = path2.join("configs", "main7.json");
1009
+ const homeCfg = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
1010
+ if (fs2.existsSync(defaultCfg)) {
473
1011
  configPath2 = defaultCfg;
474
- } else if (fs.existsSync(homeCfg)) {
1012
+ } else if (fs2.existsSync(homeCfg)) {
475
1013
  configPath2 = homeCfg;
476
1014
  console.log(` \u4F7F\u7528\u9ED8\u8BA4 config: ${homeCfg}`);
477
1015
  } else {
478
1016
  const ptr = readHomePointer();
479
1017
  if (ptr?.stateDir) {
480
- const ptrCfg = path.join(ptr.stateDir, "configs", "main7.json");
481
- if (fs.existsSync(ptrCfg)) {
1018
+ const ptrCfg = path2.join(ptr.stateDir, "configs", "main7.json");
1019
+ if (fs2.existsSync(ptrCfg)) {
482
1020
  configPath2 = ptrCfg;
483
1021
  console.log(` \u4F7F\u7528 config: ${ptrCfg}`);
484
1022
  }
@@ -491,41 +1029,41 @@ engine7 start \u2014 \u542F\u52A8 Engine
491
1029
  }
492
1030
  }
493
1031
  }
494
- const { execSync, spawn } = await import("node:child_process");
1032
+ const { execSync: execSync2, spawn } = await import("node:child_process");
495
1033
  let enginePath;
496
- const localPath = path.join("node_modules", "engine7", "dist", "main.mjs");
497
- if (fs.existsSync(localPath)) {
1034
+ const localPath = path2.join("node_modules", "engine7", "dist", "main.mjs");
1035
+ if (fs2.existsSync(localPath)) {
498
1036
  enginePath = localPath;
499
1037
  } else {
500
- const cliPath = path.resolve(process.argv[1]);
501
- const distDir = path.dirname(cliPath);
502
- const candidate = path.join(distDir, "main.mjs");
503
- if (fs.existsSync(candidate)) {
1038
+ const cliPath = path2.resolve(process.argv[1]);
1039
+ const distDir = path2.dirname(cliPath);
1040
+ const candidate = path2.join(distDir, "main.mjs");
1041
+ if (fs2.existsSync(candidate)) {
504
1042
  enginePath = candidate;
505
1043
  } else {
506
1044
  try {
507
- const globalRoot = execSync("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
508
- enginePath = path.join(globalRoot, "engine7", "dist", "main.mjs");
1045
+ const globalRoot = execSync2("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1046
+ enginePath = path2.join(globalRoot, "engine7", "dist", "main.mjs");
509
1047
  } catch {
510
1048
  console.error("\u274C \u627E\u4E0D\u5230 engine7 main.mjs");
511
1049
  process.exit(1);
512
1050
  }
513
1051
  }
514
1052
  }
515
- console.log(`\u{1F680} engine7 start`);
1053
+ console.log(label);
516
1054
  console.log(` config: ${configPath2}`);
517
1055
  console.log(` engine: ${enginePath}`);
518
- const configName = path.basename(configPath2);
1056
+ const configName = path2.basename(configPath2);
519
1057
  const myPid = process.pid;
520
1058
  try {
521
1059
  if (process.platform === "win32") {
522
- execSync(`powershell -Command "Get-WmiObject Win32_Process | Where-Object { $_.Name -eq 'node.exe' -and $_.CommandLine -like '*${configName}*' -and $_.CommandLine -like '*dist*' -and $_.ProcessId -ne ${myPid} } | ForEach-Object { Write-Host '[start] Killing PID' $_.ProcessId; Stop-Process -Id $_.ProcessId -Force }"`, { stdio: "inherit" });
1060
+ execSync2(`powershell -Command "Get-WmiObject Win32_Process | Where-Object { $_.Name -eq 'node.exe' -and $_.CommandLine -like '*${configName}*' -and $_.CommandLine -like '*dist*' -and $_.ProcessId -ne ${myPid} } | ForEach-Object { Write-Host '[start] Killing PID' $_.ProcessId; Stop-Process -Id $_.ProcessId -Force }"`, { stdio: "inherit" });
523
1061
  } else {
524
- const pids = execSync(`pgrep -f "dist/main.mjs.*${configName}" 2>/dev/null || true`, { encoding: "utf-8" }).trim();
1062
+ const pids = execSync2(`pgrep -f "dist/main.mjs.*${configName}" 2>/dev/null || true`, { encoding: "utf-8" }).trim();
525
1063
  const otherPids = pids.split("\n").filter((p) => p && p.trim() !== String(myPid)).join("\n").trim();
526
1064
  if (otherPids) {
527
1065
  console.log(`[start] Killing existing engine (PID: ${otherPids})...`);
528
- execSync(`echo "${otherPids}" | xargs kill -9 2>/dev/null || true`);
1066
+ execSync2(`echo "${otherPids}" | xargs kill -9 2>/dev/null || true`);
529
1067
  await new Promise((r) => setTimeout(r, 2e3));
530
1068
  }
531
1069
  }
@@ -539,56 +1077,6 @@ engine7 start \u2014 \u542F\u52A8 Engine
539
1077
  child.on("exit", (code) => process.exit(code ?? 1));
540
1078
  return;
541
1079
  }
542
- if (subcommand === "restart") {
543
- const { execSync } = await import("node:child_process");
544
- const myPid = process.pid;
545
- console.log("\u{1F504} engine7 restart");
546
- try {
547
- if (process.platform === "win32") {
548
- execSync(`powershell -Command "Get-WmiObject Win32_Process | Where-Object { $_.Name -eq 'node.exe' -and $_.CommandLine -like '*dist/main.mjs*' -and $_.ProcessId -ne ${myPid} } | ForEach-Object { Write-Host '[restart] Killing PID' $_.ProcessId; Stop-Process -Id $_.ProcessId -Force }"`, { stdio: "inherit" });
549
- } else {
550
- const pids = execSync(`pgrep -f "dist/main.mjs" 2>/dev/null || true`, { encoding: "utf-8" }).trim();
551
- const otherPids = pids.split("\n").filter((p) => p && p.trim() !== String(myPid)).join("\n").trim();
552
- if (otherPids) {
553
- console.log(`[restart] Killing existing engine (PID: ${otherPids})...`);
554
- execSync(`echo "${otherPids}" | xargs kill -9 2>/dev/null || true`);
555
- await new Promise((r) => setTimeout(r, 2e3));
556
- }
557
- }
558
- } catch {
559
- }
560
- let configPath2 = "";
561
- for (let i = 1; i < args.length; i++) {
562
- if (args[i] === "--config" && args[i + 1]) configPath2 = args[++i];
563
- }
564
- if (!configPath2) {
565
- const defaultCfg = path.join("configs", "main7.json");
566
- const homeCfg = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
567
- if (fs.existsSync(defaultCfg)) configPath2 = defaultCfg;
568
- else if (fs.existsSync(homeCfg)) configPath2 = homeCfg;
569
- else {
570
- const ptr = readHomePointer();
571
- if (ptr?.stateDir) {
572
- const ptrCfg = path.join(ptr.stateDir, "configs", "main7.json");
573
- if (fs.existsSync(ptrCfg)) configPath2 = ptrCfg;
574
- }
575
- }
576
- }
577
- if (!configPath2) {
578
- console.error("\u274C \u627E\u4E0D\u5230 config");
579
- process.exit(1);
580
- }
581
- const cliPath = path.resolve(process.argv[1]);
582
- const distDir = path.dirname(cliPath);
583
- const enginePath = fs.existsSync(path.join(distDir, "main.mjs")) ? path.join(distDir, "main.mjs") : path.join(path.dirname(path.dirname(cliPath)), "lib", "node_modules", "engine7", "dist", "main.mjs");
584
- console.log(` config: ${configPath2}`);
585
- console.log(` engine: ${enginePath}`);
586
- console.log("");
587
- const { spawn } = await import("node:child_process");
588
- const child = spawn(process.execPath, [enginePath, "--engine-config", configPath2], { stdio: "inherit", shell: false });
589
- child.on("exit", (code) => process.exit(code ?? 1));
590
- return;
591
- }
592
1080
  if (subcommand === "service") {
593
1081
  const action = args[1];
594
1082
  if (!action || action === "--help" || action === "-h") {
@@ -613,18 +1101,18 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
613
1101
  else if (args[i] === "--cwd" && args[i + 1]) cwd = args[++i];
614
1102
  }
615
1103
  if (!configPath2) {
616
- const defaultCfg = path.join(cwd, "configs", "main7.json");
617
- const homeCfg = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
618
- if (fs.existsSync(defaultCfg)) {
1104
+ const defaultCfg = path2.join(cwd, "configs", "main7.json");
1105
+ const homeCfg = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
1106
+ if (fs2.existsSync(defaultCfg)) {
619
1107
  configPath2 = defaultCfg;
620
- } else if (fs.existsSync(homeCfg)) {
1108
+ } else if (fs2.existsSync(homeCfg)) {
621
1109
  configPath2 = homeCfg;
622
- cwd = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
1110
+ cwd = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
623
1111
  } else {
624
1112
  const ptr = readHomePointer();
625
1113
  if (ptr?.stateDir) {
626
- const ptrCfg = path.join(ptr.stateDir, "configs", "main7.json");
627
- if (fs.existsSync(ptrCfg)) {
1114
+ const ptrCfg = path2.join(ptr.stateDir, "configs", "main7.json");
1115
+ if (fs2.existsSync(ptrCfg)) {
628
1116
  configPath2 = ptrCfg;
629
1117
  cwd = ptr.stateDir;
630
1118
  }
@@ -637,22 +1125,22 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
637
1125
  }
638
1126
  }
639
1127
  }
640
- const { execSync } = await import("node:child_process");
1128
+ const { execSync: execSync2 } = await import("node:child_process");
641
1129
  const engine7Bin = process.argv[1];
642
1130
  if (action === "install") {
643
1131
  if (process.platform === "win32") {
644
1132
  const taskName = "Engine7";
645
1133
  const nodeExe = process.execPath;
646
- const cliMjs = path.resolve(engine7Bin);
647
- const absConfig = path.resolve(configPath2);
648
- const wrapperPath = path.join(cwd, "engine7-start.cmd");
1134
+ const cliMjs = path2.resolve(engine7Bin);
1135
+ const absConfig = path2.resolve(configPath2);
1136
+ const wrapperPath = path2.join(cwd, "engine7-start.cmd");
649
1137
  const wrapperContent = `@echo off\r
650
1138
  cd /d "${cwd}"\r
651
1139
  "${nodeExe}" "${cliMjs}" start --config "${absConfig}"\r
652
1140
  `;
653
- fs.writeFileSync(wrapperPath, wrapperContent);
1141
+ fs2.writeFileSync(wrapperPath, wrapperContent);
654
1142
  try {
655
- execSync(`schtasks /create /tn "${taskName}" /tr "${wrapperPath}" /sc onlogon /rl highest /f`, { stdio: "inherit", shell: true });
1143
+ execSync2(`schtasks /create /tn "${taskName}" /tr "${wrapperPath}" /sc onlogon /rl highest /f`, { stdio: "inherit", shell: true });
656
1144
  console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1 "${taskName}" \u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
657
1145
  console.log(` wrapper: ${wrapperPath}`);
658
1146
  } catch {
@@ -661,11 +1149,11 @@ cd /d "${cwd}"\r
661
1149
  }
662
1150
  } else if (process.platform === "darwin") {
663
1151
  const label = "com.engine7.agent";
664
- const plistDir = path.join(process.env.HOME, "Library", "LaunchAgents");
665
- fs.mkdirSync(plistDir, { recursive: true });
666
- const plistPath = path.join(plistDir, `${label}.plist`);
667
- const localCli = path.join("node_modules", "engine7", "dist", "cli.mjs");
668
- const cliMjs = fs.existsSync(localCli) ? path.resolve(localCli) : path.join(path.dirname(path.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
1152
+ const plistDir = path2.join(process.env.HOME, "Library", "LaunchAgents");
1153
+ fs2.mkdirSync(plistDir, { recursive: true });
1154
+ const plistPath = path2.join(plistDir, `${label}.plist`);
1155
+ const localCli = path2.join("node_modules", "engine7", "dist", "cli.mjs");
1156
+ const cliMjs = fs2.existsSync(localCli) ? path2.resolve(localCli) : path2.join(path2.dirname(path2.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
669
1157
  const plist = `<?xml version="1.0" encoding="UTF-8"?>
670
1158
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
671
1159
  <plist version="1.0">
@@ -677,16 +1165,16 @@ cd /d "${cwd}"\r
677
1165
  <string>${cliMjs}</string>
678
1166
  <string>start</string>
679
1167
  <string>--config</string>
680
- <string>${path.resolve(configPath2)}</string>
1168
+ <string>${path2.resolve(configPath2)}</string>
681
1169
  </array>
682
1170
  <key>WorkingDirectory</key><string>${cwd}</string>
683
1171
  <key>RunAtLoad</key><true/>
684
1172
  <key>KeepAlive</key><true/>
685
1173
  </dict>
686
1174
  </plist>`;
687
- fs.writeFileSync(plistPath, plist);
1175
+ fs2.writeFileSync(plistPath, plist);
688
1176
  try {
689
- execSync(`launchctl load "${plistPath}"`, { stdio: "inherit" });
1177
+ execSync2(`launchctl load "${plistPath}"`, { stdio: "inherit" });
690
1178
  console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
691
1179
  console.log(` ${plistPath}`);
692
1180
  } catch {
@@ -695,9 +1183,9 @@ cd /d "${cwd}"\r
695
1183
  }
696
1184
  } else {
697
1185
  const svcName = "engine7";
698
- const svcDir = path.join(process.env.HOME, ".config", "systemd", "user");
699
- fs.mkdirSync(svcDir, { recursive: true });
700
- const svcPath = path.join(svcDir, `${svcName}.service`);
1186
+ const svcDir = path2.join(process.env.HOME, ".config", "systemd", "user");
1187
+ fs2.mkdirSync(svcDir, { recursive: true });
1188
+ const svcPath = path2.join(svcDir, `${svcName}.service`);
701
1189
  const svc = `[Unit]
702
1190
  Description=Engine 7 Agent
703
1191
  After=network.target
@@ -705,16 +1193,16 @@ After=network.target
705
1193
  [Service]
706
1194
  Type=simple
707
1195
  WorkingDirectory=${cwd}
708
- ExecStart=${process.execPath} ${engine7Bin} start --config ${path.resolve(configPath2)}
1196
+ ExecStart=${process.execPath} ${engine7Bin} start --config ${path2.resolve(configPath2)}
709
1197
  Restart=on-failure
710
1198
  RestartSec=10
711
1199
 
712
1200
  [Install]
713
1201
  WantedBy=default.target`;
714
- fs.writeFileSync(svcPath, svc);
1202
+ fs2.writeFileSync(svcPath, svc);
715
1203
  try {
716
- execSync(`systemctl --user daemon-reload`, { stdio: "inherit" });
717
- execSync(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
1204
+ execSync2(`systemctl --user daemon-reload`, { stdio: "inherit" });
1205
+ execSync2(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
718
1206
  console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
719
1207
  console.log(` ${svcPath}`);
720
1208
  } catch {
@@ -725,35 +1213,35 @@ WantedBy=default.target`;
725
1213
  } else if (action === "uninstall") {
726
1214
  if (process.platform === "win32") {
727
1215
  try {
728
- execSync(`schtasks /delete /tn "Engine7" /f`, { stdio: "inherit", shell: true });
1216
+ execSync2(`schtasks /delete /tn "Engine7" /f`, { stdio: "inherit", shell: true });
729
1217
  console.log(`\u2705 Windows \u8BA1\u5212\u4EFB\u52A1\u5DF2\u5220\u9664`);
730
1218
  } catch {
731
1219
  console.error("\u274C \u5220\u9664\u5931\u8D25\uFF0C\u4EFB\u52A1\u53EF\u80FD\u4E0D\u5B58\u5728");
732
1220
  process.exit(1);
733
1221
  }
734
1222
  } else if (process.platform === "darwin") {
735
- const plistPath = path.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
1223
+ const plistPath = path2.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
736
1224
  try {
737
- execSync(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
1225
+ execSync2(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
738
1226
  } catch {
739
1227
  }
740
1228
  try {
741
- fs.unlinkSync(plistPath);
1229
+ fs2.unlinkSync(plistPath);
742
1230
  } catch {
743
1231
  }
744
1232
  console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
745
1233
  } else {
746
1234
  try {
747
- execSync(`systemctl --user disable engine7`, { stdio: "inherit" });
1235
+ execSync2(`systemctl --user disable engine7`, { stdio: "inherit" });
748
1236
  } catch {
749
1237
  }
750
- const svcPath = path.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
1238
+ const svcPath = path2.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
751
1239
  try {
752
- fs.unlinkSync(svcPath);
1240
+ fs2.unlinkSync(svcPath);
753
1241
  } catch {
754
1242
  }
755
1243
  try {
756
- execSync(`systemctl --user daemon-reload`, { stdio: "inherit" });
1244
+ execSync2(`systemctl --user daemon-reload`, { stdio: "inherit" });
757
1245
  } catch {
758
1246
  }
759
1247
  console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u5220\u9664`);
@@ -761,20 +1249,20 @@ WantedBy=default.target`;
761
1249
  } else if (action === "status") {
762
1250
  if (process.platform === "win32") {
763
1251
  try {
764
- execSync(`schtasks /query /tn "Engine7"`, { stdio: "inherit", shell: true });
1252
+ execSync2(`schtasks /query /tn "Engine7"`, { stdio: "inherit", shell: true });
765
1253
  } catch {
766
1254
  console.log("\u274C \u672A\u5B89\u88C5");
767
1255
  }
768
1256
  } else if (process.platform === "darwin") {
769
- const plistPath = path.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
770
- if (fs.existsSync(plistPath)) {
1257
+ const plistPath = path2.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
1258
+ if (fs2.existsSync(plistPath)) {
771
1259
  console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
772
1260
  } else {
773
1261
  console.log("\u274C \u672A\u5B89\u88C5");
774
1262
  }
775
1263
  } else {
776
1264
  try {
777
- execSync(`systemctl --user is-enabled engine7`, { stdio: "inherit" });
1265
+ execSync2(`systemctl --user is-enabled engine7`, { stdio: "inherit" });
778
1266
  } catch {
779
1267
  console.log("\u274C \u672A\u5B89\u88C5");
780
1268
  }
@@ -790,8 +1278,8 @@ WantedBy=default.target`;
790
1278
  console.log(`
791
1279
  \u{1F680} engine7 init`);
792
1280
  console.log(` state-dir: ${opts.stateDir}`);
793
- if (fs.existsSync(opts.stateDir) && !opts.dryRun) {
794
- const files = fs.readdirSync(opts.stateDir);
1281
+ if (fs2.existsSync(opts.stateDir) && !opts.dryRun) {
1282
+ const files = fs2.readdirSync(opts.stateDir);
795
1283
  if (files.length > 0) {
796
1284
  console.error(`
797
1285
  \u274C \u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u975E\u7A7A: ${opts.stateDir}`);
@@ -809,7 +1297,7 @@ WantedBy=default.target`;
809
1297
  rl.close();
810
1298
  }
811
1299
  const config = generateConfig(values);
812
- const configPath = path.join(opts.stateDir, "configs", "main7.json");
1300
+ const configPath = path2.join(opts.stateDir, "configs", "main7.json");
813
1301
  const tree = buildDirTree(values);
814
1302
  tree.push({
815
1303
  path: configPath,
@@ -820,9 +1308,9 @@ WantedBy=default.target`;
820
1308
  dryRun(tree);
821
1309
  const skillsSrc = findTemplateDir("skills");
822
1310
  if (skillsSrc) {
823
- const skills = fs.readdirSync(skillsSrc);
1311
+ const skills = fs2.readdirSync(skillsSrc);
824
1312
  for (const s of skills) {
825
- console.log(` \u{1F4C1} ${path.join(opts.stateDir, "workspace", "skills", s)}`);
1313
+ console.log(` \u{1F4C1} ${path2.join(opts.stateDir, "workspace", "skills", s)}`);
826
1314
  }
827
1315
  }
828
1316
  } else {
@@ -830,55 +1318,55 @@ WantedBy=default.target`;
830
1318
  execute(tree);
831
1319
  const skillsSrc = findTemplateDir("skills");
832
1320
  if (skillsSrc) {
833
- const skillsDest = path.join(opts.stateDir, "workspace", "skills");
834
- fs.mkdirSync(skillsDest, { recursive: true });
835
- const skills = fs.readdirSync(skillsSrc);
1321
+ const skillsDest = path2.join(opts.stateDir, "workspace", "skills");
1322
+ fs2.mkdirSync(skillsDest, { recursive: true });
1323
+ const skills = fs2.readdirSync(skillsSrc);
836
1324
  for (const s of skills) {
837
- copyDirRecursive(path.join(skillsSrc, s), path.join(skillsDest, s));
1325
+ copyDirRecursive(path2.join(skillsSrc, s), path2.join(skillsDest, s));
838
1326
  console.log(` \u{1F4E6} skill: ${s}`);
839
1327
  }
840
1328
  }
841
1329
  console.log(`
842
1330
  \u2705 \u521D\u59CB\u5316\u5B8C\u6210\uFF01
843
1331
  `);
844
- const homePointer = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
1332
+ const homePointer = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
845
1333
  const pointerData = { stateDir: opts.stateDir };
846
- fs.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
1334
+ fs2.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
847
1335
  console.log(` \u{1F4C4} ${homePointer}\uFF08\u4ECE\u4EFB\u610F\u76EE\u5F55\u90FD\u80FD\u627E\u5230\u6B64 agent\uFF09`);
848
1336
  console.log(`\u4E0B\u4E00\u6B65\uFF1A`);
849
1337
  console.log(` 1. \u68C0\u67E5\u5E76\u4FEE\u6539 ${opts.stateDir}/configs/main7.json`);
850
1338
  console.log(` 2. \u542F\u52A8 Engine: engine7 start\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
851
1339
  console.log(` 3. \u5F00\u673A\u81EA\u542F: engine7 service install\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
852
- console.log(` 4. \u67E5\u770B workspace: ${path.join(opts.stateDir, "workspace")}`);
1340
+ console.log(` 4. \u67E5\u770B workspace: ${path2.join(opts.stateDir, "workspace")}`);
853
1341
  }
854
1342
  }
855
1343
  function copyDirRecursive(src, dest) {
856
- fs.mkdirSync(dest, { recursive: true });
857
- for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
858
- const srcPath = path.join(src, entry.name);
859
- const destPath = path.join(dest, entry.name);
1344
+ fs2.mkdirSync(dest, { recursive: true });
1345
+ for (const entry of fs2.readdirSync(src, { withFileTypes: true })) {
1346
+ const srcPath = path2.join(src, entry.name);
1347
+ const destPath = path2.join(dest, entry.name);
860
1348
  if (entry.isDirectory()) {
861
1349
  copyDirRecursive(srcPath, destPath);
862
1350
  } else {
863
- fs.copyFileSync(srcPath, destPath);
1351
+ fs2.copyFileSync(srcPath, destPath);
864
1352
  }
865
1353
  }
866
1354
  }
867
1355
  function findTemplateDir(name) {
868
1356
  const candidates = [
869
- path.join(__dirname, "..", "templates", name),
870
- path.join(__dirname, "..", "..", "templates", name),
871
- path.join(process.cwd(), "templates", name)
1357
+ path2.join(__dirname, "..", "templates", name),
1358
+ path2.join(__dirname, "..", "..", "templates", name),
1359
+ path2.join(process.cwd(), "templates", name)
872
1360
  ];
873
1361
  for (const p of candidates) {
874
- if (fs.existsSync(p)) return p;
1362
+ if (fs2.existsSync(p)) return p;
875
1363
  }
876
1364
  return null;
877
1365
  }
878
1366
  function readHomePointer() {
879
- const ptrPath = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
1367
+ const ptrPath = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
880
1368
  try {
881
- return JSON.parse(fs.readFileSync(ptrPath, "utf-8"));
1369
+ return JSON.parse(fs2.readFileSync(ptrPath, "utf-8"));
882
1370
  } catch {
883
1371
  return null;
884
1372
  }