engine7 7.1.29 → 7.1.30

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