engine7 7.1.29 → 7.1.31

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,3 +1,4 @@
1
+ const require=(await import('node:module')).createRequire(import.meta.url)
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
4
  var __esm = (fn, res) => function __init() {
@@ -183,8 +184,8 @@ function collectRecentSessions(agentsDir, _days = 7) {
183
184
  }
184
185
  async function doExport(opts) {
185
186
  const { agentName, stateDir, note, dryRun: dryRun2 } = opts;
186
- const workspace = opts.workspace || path.join(stateDir, "workspace");
187
- const engineHome = path.join(os.homedir(), ".engine7");
187
+ const workspace = (opts.workspace || path.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
188
+ const engineHome = path.join(os.homedir(), ".engine7").replace(/[/\\]+$/, "");
188
189
  console.log(`\u{1F4E6} engine7 export`);
189
190
  console.log(` agent: ${agentName}`);
190
191
  console.log(` state: ${stateDir}`);
@@ -326,9 +327,9 @@ async function doImport(opts) {
326
327
  process.exit(1);
327
328
  }
328
329
  const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
329
- const workspace = path.join(stateDir, "workspace").replace(/\\/g, "/");
330
- const engineHome = path.join(os.homedir(), ".engine7").replace(/\\/g, "/");
331
- const dirs = { workspace, stateDir: stateDir.replace(/\\/g, "/"), engineHome };
330
+ const workspace = path.join(stateDir, "workspace").replace(/\\/g, "/").replace(/[/\\]+$/, "");
331
+ const engineHome = path.join(os.homedir(), ".engine7").replace(/\\/g, "/").replace(/[/\\]+$/, "");
332
+ const dirs = { workspace, stateDir: stateDir.replace(/\\/g, "/").replace(/[/\\]+$/, ""), engineHome };
332
333
  console.log(` \u7248\u672C: ${manifest.version}`);
333
334
  console.log(` \u521B\u5EFA: ${manifest.createdAt}`);
334
335
  console.log(` \u6587\u4EF6\u6570: ${manifest.fileCount}`);
@@ -1332,13 +1333,253 @@ engine7 start \u2014 \u542F\u52A8 Engine
1332
1333
  } catch {
1333
1334
  }
1334
1335
  console.log("");
1336
+ const envForChild = { ...process.env };
1337
+ const secretsDir = path2.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7-secrets");
1338
+ const cfgBase = path2.basename(configPath2, ".json");
1339
+ const secretCandidates = [
1340
+ path2.join(secretsDir, `${cfgBase}.env`),
1341
+ path2.join(path2.dirname(configPath2), `.env.${cfgBase}`),
1342
+ path2.join(path2.dirname(configPath2), ".env")
1343
+ ];
1344
+ for (const secretPath of secretCandidates) {
1345
+ if (fs2.existsSync(secretPath)) {
1346
+ const content = fs2.readFileSync(secretPath, "utf-8");
1347
+ for (const line of content.split("\n")) {
1348
+ const trimmed = line.trim();
1349
+ if (!trimmed || trimmed.startsWith("#")) continue;
1350
+ const eq = trimmed.indexOf("=");
1351
+ if (eq > 0) {
1352
+ const k = trimmed.slice(0, eq).trim();
1353
+ const v = trimmed.slice(eq + 1).trim();
1354
+ if (k && !(k in envForChild)) envForChild[k] = v;
1355
+ }
1356
+ }
1357
+ console.log(`[start] Loaded API keys from ${secretPath}`);
1358
+ break;
1359
+ }
1360
+ }
1335
1361
  const child = spawn(process.execPath, [enginePath, "--engine-config", configPath2], {
1336
1362
  stdio: "inherit",
1337
- shell: false
1363
+ shell: false,
1364
+ env: envForChild
1338
1365
  });
1339
1366
  child.on("exit", (code) => process.exit(code ?? 1));
1340
1367
  return;
1341
1368
  }
1369
+ if (subcommand === "session") {
1370
+ const action = args[1];
1371
+ if (!action || action === "--help" || action === "-h") {
1372
+ console.log(`
1373
+ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
1374
+
1375
+ \u7528\u6CD5:
1376
+ engine7 session reset --config <path> [--mode archive|drop-last|strip-images] [--n N] [--restart]
1377
+
1378
+ \u6A21\u5F0F:
1379
+ archive \u5F52\u6863\u6574\u4E2A\u4F1A\u8BDD\uFF0C\u91CD\u542F\u540E\u4ECE\u7A7A\u767D\u5F00\u59CB
1380
+ drop-last \u780D\u6700\u8FD1 N \u8F6E\u5BF9\u8BDD\uFF08\u9ED8\u8BA4 N=3\uFF09\uFF0C\u4FDD\u7559\u66F4\u65E9\u7684\u5386\u53F2
1381
+ strip-images \u53EA\u6458\u9664 image block / [\u56FE\u7247\xD7N] \u6807\u8BB0\uFF0C\u4FDD\u7559\u6587\u5B57\uFF08\u6025\u6551\u654F\u611F\u56FE\uFF09
1382
+
1383
+ \u9009\u9879:
1384
+ --config <path> config \u6587\u4EF6\u8DEF\u5F84\uFF08\u5FC5\u987B\u6307\u5B9A\uFF09
1385
+ --mode <mode> \u91CD\u7F6E\u6A21\u5F0F\uFF08\u9ED8\u8BA4: archive\uFF09
1386
+ --n <N> drop-last \u6A21\u5F0F\u780D\u51E0\u8F6E\uFF08\u9ED8\u8BA4: 3\uFF09
1387
+ --restart \u6539\u5B8C\u81EA\u52A8 kill + \u62C9\u8D77 engine
1388
+ -h, --help \u663E\u793A\u5E2E\u52A9
1389
+ `);
1390
+ process.exit(0);
1391
+ }
1392
+ if (action === "reset") {
1393
+ const { execSync: execSync2 } = await import("node:child_process");
1394
+ let configPath2 = "";
1395
+ let mode = "archive";
1396
+ let dropN = 3;
1397
+ let autoRestart = false;
1398
+ for (let i = 2; i < args.length; i++) {
1399
+ if (args[i] === "--config" && args[i + 1]) {
1400
+ configPath2 = args[++i];
1401
+ } else if (args[i] === "--mode" && args[i + 1]) {
1402
+ mode = args[++i];
1403
+ } else if (args[i] === "--n" && args[i + 1]) {
1404
+ dropN = parseInt(args[++i], 10);
1405
+ } else if (args[i] === "--restart") {
1406
+ autoRestart = true;
1407
+ } else if (args[i] === "-h" || args[i] === "--help") {
1408
+ console.log(`engine7 session reset --config <path> [--mode archive|drop-last|strip-images] [--n N] [--restart]`);
1409
+ process.exit(0);
1410
+ }
1411
+ }
1412
+ if (!configPath2) {
1413
+ console.error("\u274C \u5FC5\u987B\u6307\u5B9A --config <path>");
1414
+ process.exit(1);
1415
+ }
1416
+ if (!["archive", "drop-last", "strip-images"].includes(mode)) {
1417
+ console.error(`\u274C \u672A\u77E5\u6A21\u5F0F: ${mode}\uFF08\u53EF\u9009: archive / drop-last / strip-images\uFF09`);
1418
+ process.exit(1);
1419
+ }
1420
+ const configRaw = JSON.parse(fs2.readFileSync(configPath2, "utf-8"));
1421
+ const stateDir = configRaw.stateDir;
1422
+ if (!stateDir) {
1423
+ console.error("\u274C config \u91CC\u6CA1\u6709 stateDir");
1424
+ process.exit(1);
1425
+ }
1426
+ const sessionsDir = path2.join(stateDir, "agents", "main", "sessions");
1427
+ if (!fs2.existsSync(sessionsDir)) {
1428
+ console.error(`\u274C sessions \u76EE\u5F55\u4E0D\u5B58\u5728: ${sessionsDir}`);
1429
+ process.exit(1);
1430
+ }
1431
+ console.log(`\u{1F504} session reset`);
1432
+ console.log(` config: ${configPath2}`);
1433
+ console.log(` mode: ${mode}`);
1434
+ if (mode === "drop-last") console.log(` n: ${dropN}`);
1435
+ const platformMapPath = path2.join(sessionsDir, "platform-map.json");
1436
+ const indexPath = path2.join(sessionsDir, "session-index.json");
1437
+ let sessionFileUUID = null;
1438
+ if (fs2.existsSync(indexPath)) {
1439
+ const index = JSON.parse(fs2.readFileSync(indexPath, "utf-8"));
1440
+ const entries = Object.values(index);
1441
+ if (entries.length > 0) {
1442
+ const fileVal = entries[0].file || "";
1443
+ sessionFileUUID = path2.isAbsolute(fileVal) ? path2.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
1444
+ }
1445
+ }
1446
+ if (!sessionFileUUID) {
1447
+ 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);
1448
+ if (jsonlFiles.length === 0) {
1449
+ console.error("\u274C \u627E\u4E0D\u5230\u6D3B\u8DC3\u7684 session JSONL \u6587\u4EF6");
1450
+ process.exit(1);
1451
+ }
1452
+ sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
1453
+ }
1454
+ let jsonlPath = path2.join(sessionsDir, `${sessionFileUUID}.jsonl`);
1455
+ if (!fs2.existsSync(jsonlPath)) {
1456
+ 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);
1457
+ if (jsonlFiles.length === 0) {
1458
+ console.error(`\u274C JSONL \u6587\u4EF6\u4E0D\u5B58\u5728: ${jsonlPath}`);
1459
+ process.exit(1);
1460
+ }
1461
+ sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
1462
+ jsonlPath = path2.join(sessionsDir, `${sessionFileUUID}.jsonl`);
1463
+ }
1464
+ console.log(` file: ${jsonlPath}`);
1465
+ const configName = path2.basename(configPath2);
1466
+ if (autoRestart) {
1467
+ try {
1468
+ const myPid = process.pid;
1469
+ const pids = execSync2(`pgrep -f "dist/main.mjs.*${configName}" 2>/dev/null || true`, { encoding: "utf-8" }).trim();
1470
+ const otherPids = pids.split("\n").filter((p) => p && p.trim() !== String(myPid)).join("\n").trim();
1471
+ if (otherPids) {
1472
+ console.log(`
1473
+ Killing engine (PID: ${otherPids})...`);
1474
+ execSync2(`echo "${otherPids}" | xargs kill -9 2>/dev/null || true`);
1475
+ await new Promise((r) => setTimeout(r, 2e3));
1476
+ }
1477
+ } catch {
1478
+ }
1479
+ }
1480
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
1481
+ const { readFileSync: readFileSync3, writeFileSync: writeFileSync3, renameSync } = fs2;
1482
+ if (mode === "archive") {
1483
+ const archiveName = `${sessionFileUUID}.jsonl.archived.${timestamp}`;
1484
+ renameSync(jsonlPath, path2.join(sessionsDir, archiveName));
1485
+ console.log(`
1486
+ \u2705 \u5F52\u6863\u5B8C\u6210: ${archiveName}`);
1487
+ console.log(` \u91CD\u542F\u540E\u5C06\u4ECE\u7A7A\u767D\u4F1A\u8BDD\u5F00\u59CB`);
1488
+ } else if (mode === "drop-last") {
1489
+ const lines = readFileSync3(jsonlPath, "utf-8").trim().split("\n");
1490
+ const parsed = lines.map((l) => {
1491
+ try {
1492
+ return JSON.parse(l);
1493
+ } catch {
1494
+ return null;
1495
+ }
1496
+ }).filter(Boolean);
1497
+ let cutIndex = parsed.length;
1498
+ let userCount = 0;
1499
+ for (let i = parsed.length - 1; i >= 0; i--) {
1500
+ if (parsed[i].type === "message" && parsed[i].role === "user") {
1501
+ userCount++;
1502
+ cutIndex = i;
1503
+ if (userCount >= dropN) break;
1504
+ }
1505
+ }
1506
+ const kept = parsed.slice(0, cutIndex);
1507
+ const newContent = kept.map((p) => JSON.stringify(p)).join("\n") + "\n";
1508
+ writeFileSync3(jsonlPath, newContent);
1509
+ console.log(`
1510
+ \u2705 \u780D\u6389\u6700\u8FD1 ${parsed.length - cutIndex} \u884C\uFF08${dropN} \u8F6E\uFF09`);
1511
+ console.log(` \u4FDD\u7559 ${kept.length} \u884C`);
1512
+ } else if (mode === "strip-images") {
1513
+ const lines = readFileSync3(jsonlPath, "utf-8").trim().split("\n");
1514
+ let stripped = 0;
1515
+ const newLines = lines.map((line) => {
1516
+ try {
1517
+ const obj = JSON.parse(line);
1518
+ let changed = false;
1519
+ if (obj.type === "message") {
1520
+ const msg = obj.message || obj;
1521
+ if (typeof msg.content === "string") {
1522
+ const cleaned = msg.content.replace(/\n?\[图片×\d+\]/g, "").replace(/\n?\[图片来自[^\]]*\]/g, "");
1523
+ if (cleaned !== msg.content) {
1524
+ msg.content = cleaned;
1525
+ changed = true;
1526
+ }
1527
+ }
1528
+ if (Array.isArray(msg.content)) {
1529
+ msg.content = msg.content.map((block) => {
1530
+ if (block.type === "text" && typeof block.text === "string") {
1531
+ const cleaned = block.text.replace(/\n?\[图片×\d+\]/g, "").replace(/\n?\[图片来自[^\]]*\]/g, "");
1532
+ if (cleaned !== block.text) {
1533
+ changed = true;
1534
+ return { ...block, text: cleaned };
1535
+ }
1536
+ }
1537
+ if (block.type === "toolCall" && block.arguments?.image_path) {
1538
+ changed = true;
1539
+ return { ...block, arguments: { ...block.arguments, image_path: "[stripped]" } };
1540
+ }
1541
+ return block;
1542
+ });
1543
+ }
1544
+ }
1545
+ if (changed) {
1546
+ stripped++;
1547
+ return JSON.stringify(obj);
1548
+ }
1549
+ return line;
1550
+ } catch {
1551
+ return line;
1552
+ }
1553
+ });
1554
+ writeFileSync3(jsonlPath, newLines.join("\n") + "\n");
1555
+ console.log(`
1556
+ \u2705 \u6458\u9664 ${stripped} \u884C\u56FE\u7247\u76F8\u5173\u5185\u5BB9`);
1557
+ }
1558
+ if (autoRestart) {
1559
+ const realCliPath = fs2.realpathSync(process.argv[1]);
1560
+ const cliDir = path2.dirname(realCliPath);
1561
+ const pkgRoot = path2.resolve(cliDir, "..");
1562
+ let enginePath = path2.join(pkgRoot, "dist", "main.mjs");
1563
+ if (!fs2.existsSync(enginePath)) {
1564
+ enginePath = path2.join(cliDir, "main.mjs");
1565
+ }
1566
+ console.log(`
1567
+ \u{1F680} \u62C9\u8D77 engine...`);
1568
+ const { spawn } = await import("node:child_process");
1569
+ const child = spawn(process.execPath, [enginePath, "--engine-config", configPath2], {
1570
+ detached: true,
1571
+ stdio: "inherit"
1572
+ });
1573
+ child.on("exit", (code) => process.exit(code ?? 0));
1574
+ return;
1575
+ } else {
1576
+ console.log(`
1577
+ \u26A0\uFE0F \u8BF7\u624B\u52A8\u91CD\u542F engine \u4F7F\u6539\u52A8\u751F\u6548`);
1578
+ }
1579
+ process.exit(0);
1580
+ }
1581
+ process.exit(0);
1582
+ }
1342
1583
  if (subcommand === "service") {
1343
1584
  const action = args[1];
1344
1585
  if (!action || action === "--help" || action === "-h") {