engine7 7.1.117 → 7.1.119

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
@@ -408,14 +408,14 @@ var init_live = __esm({
408
408
  }
409
409
  /** 把改动写回 config 文件对应段(找不到文件路径则只内存生效) */
410
410
  async persistToFile(dotPath, val) {
411
- const fs43 = await import("node:fs");
411
+ const fs44 = await import("node:fs");
412
412
  const cfgPath = this.current?._configFilePath;
413
- if (!cfgPath || !fs43.existsSync(cfgPath)) {
413
+ if (!cfgPath || !fs44.existsSync(cfgPath)) {
414
414
  console.warn(`[liveConfig] set: no config file path, in-memory only (${dotPath})`);
415
415
  return;
416
416
  }
417
417
  try {
418
- const raw = JSON.parse(fs43.readFileSync(cfgPath, "utf-8"));
418
+ const raw = JSON.parse(fs44.readFileSync(cfgPath, "utf-8"));
419
419
  const keys = dotPath.split(".");
420
420
  let o = raw;
421
421
  for (let i = 0; i < keys.length - 1; i++) {
@@ -423,7 +423,7 @@ var init_live = __esm({
423
423
  o = o[keys[i]];
424
424
  }
425
425
  o[keys[keys.length - 1]] = val;
426
- fs43.writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
426
+ fs44.writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
427
427
  console.log(`[liveConfig] persisted ${dotPath} = ${JSON.stringify(val)} to ${cfgPath}`);
428
428
  markSelfWrite();
429
429
  } catch (e) {
@@ -714,8 +714,8 @@ function listSchemaFields() {
714
714
  if (process.env.ENGINE7_INTERNAL === "1") return FIELDS.slice();
715
715
  return FIELDS.filter((f) => !f.internal);
716
716
  }
717
- function getField(path43) {
718
- return FIELDS.find((f) => f.path === path43);
717
+ function getField(path44) {
718
+ return FIELDS.find((f) => f.path === path44);
719
719
  }
720
720
  function pick(obj, dotPath) {
721
721
  let cur = obj;
@@ -2073,6 +2073,19 @@ function resolveConfigIdentity(configPath) {
2073
2073
  const stateDir = basename2(cfgDir) === "configs" ? dirname2(cfgDir) : cfgDir;
2074
2074
  return { stateDir, configName: cfgName };
2075
2075
  }
2076
+ function engineStateDirOfConfig(configPath, env = process.env) {
2077
+ let raw;
2078
+ try {
2079
+ raw = JSON.parse(readFileSync3(configPath, "utf-8"));
2080
+ } catch {
2081
+ return null;
2082
+ }
2083
+ if (typeof raw?.stateDir === "string" && raw.stateDir.trim()) return raw.stateDir.trim();
2084
+ const fromEnv = env.ENGINE_STATE_DIR;
2085
+ if (fromEnv && fromEnv.trim()) return fromEnv.trim();
2086
+ if (basename2(dirname2(configPath)) !== "configs") return null;
2087
+ return resolveConfigIdentity(configPath).stateDir;
2088
+ }
2076
2089
  function writeSecretsValue(configPath, envKey, value) {
2077
2090
  const { stateDir, configName } = resolveConfigIdentity(configPath);
2078
2091
  const dir = join3(secretsHome(), ".engine7-secrets");
@@ -2191,8 +2204,8 @@ __export(loader_exports, {
2191
2204
  resolveTimezone: () => resolveTimezone,
2192
2205
  takeLoadWarnings: () => takeLoadWarnings
2193
2206
  });
2194
- import * as fs3 from "node:fs";
2195
- import * as path3 from "node:path";
2207
+ import * as fs4 from "node:fs";
2208
+ import * as path4 from "node:path";
2196
2209
  function parseModelRef(ref) {
2197
2210
  const idx = ref.indexOf("/");
2198
2211
  if (idx <= 0 || idx === ref.length - 1) {
@@ -2232,13 +2245,13 @@ function isUnresolvedEnvRef(value) {
2232
2245
  return typeof value === "string" && ENV_REF_RE.test(value);
2233
2246
  }
2234
2247
  function loadConfig(configPath) {
2235
- const resolvedPath = path3.resolve(
2248
+ const resolvedPath = path4.resolve(
2236
2249
  configPath || process.env.ENGINE_CONFIG || "engine-config.json"
2237
2250
  );
2238
- if (!fs3.existsSync(resolvedPath)) {
2251
+ if (!fs4.existsSync(resolvedPath)) {
2239
2252
  throw new Error(`Config file not found: ${resolvedPath}`);
2240
2253
  }
2241
- const raw = JSON.parse(fs3.readFileSync(resolvedPath, "utf-8"));
2254
+ const raw = JSON.parse(fs4.readFileSync(resolvedPath, "utf-8"));
2242
2255
  const missingEnvKeys = /* @__PURE__ */ new Set();
2243
2256
  const resolveEnv = (node) => {
2244
2257
  if (typeof node === "string") {
@@ -2341,9 +2354,9 @@ function loadConfig(configPath) {
2341
2354
  }
2342
2355
  }
2343
2356
  }
2344
- const stateDir = raw.stateDir || process.env.ENGINE_STATE_DIR || path3.resolve(".engine");
2345
- const workspace = process.env.ENGINE_WORKSPACE || agentDefaults.workspace || path3.join(stateDir, "workspace");
2346
- const mediaDir = raw.mediaDir || path3.join(stateDir, "media", "inbound");
2357
+ const stateDir = raw.stateDir || process.env.ENGINE_STATE_DIR || path4.resolve(".engine");
2358
+ const workspace = process.env.ENGINE_WORKSPACE || agentDefaults.workspace || path4.join(stateDir, "workspace");
2359
+ const mediaDir = raw.mediaDir || path4.join(stateDir, "media", "inbound");
2347
2360
  if (!agentDefaults.features) agentDefaults.features = {};
2348
2361
  for (const [k, v] of Object.entries(FEATURE_DEFAULTS)) {
2349
2362
  if (agentDefaults.features[k] === void 0) {
@@ -2615,17 +2628,17 @@ var init_registry2 = __esm({
2615
2628
  });
2616
2629
 
2617
2630
  // src/calendar/db.ts
2618
- import * as path4 from "node:path";
2619
- import * as fs4 from "node:fs";
2631
+ import * as path5 from "node:path";
2632
+ import * as fs5 from "node:fs";
2620
2633
  import { createRequire as createRequire2 } from "node:module";
2621
2634
  function getSqlite() {
2622
2635
  if (!_sqlite) _sqlite = createRequire2(import.meta.url)("node:sqlite");
2623
2636
  return _sqlite;
2624
2637
  }
2625
2638
  function openDb(workspace) {
2626
- const dir = path4.join(workspace, ".calendar");
2627
- fs4.mkdirSync(dir, { recursive: true });
2628
- const dbPath = path4.join(dir, "calendar.db");
2639
+ const dir = path5.join(workspace, ".calendar");
2640
+ fs5.mkdirSync(dir, { recursive: true });
2641
+ const dbPath = path5.join(dir, "calendar.db");
2629
2642
  const db2 = new DatabaseSync(dbPath);
2630
2643
  db2.exec("PRAGMA journal_mode=WAL");
2631
2644
  db2.exec(`CREATE TABLE IF NOT EXISTS events (
@@ -2699,14 +2712,14 @@ var init_db = __esm({
2699
2712
  });
2700
2713
 
2701
2714
  // src/goals/store.ts
2702
- import fs5 from "node:fs";
2703
- import path5 from "node:path";
2715
+ import fs6 from "node:fs";
2716
+ import path6 from "node:path";
2704
2717
  import crypto from "node:crypto";
2705
2718
  function file(stateDir) {
2706
- return path5.join(stateDir, "goals.json");
2719
+ return path6.join(stateDir, "goals.json");
2707
2720
  }
2708
2721
  function eventFile(stateDir) {
2709
- return path5.join(stateDir, "goal-events.jsonl");
2722
+ return path6.join(stateDir, "goal-events.jsonl");
2710
2723
  }
2711
2724
  function db(stateDir) {
2712
2725
  const d = openDb(stateDir);
@@ -2723,17 +2736,17 @@ function db(stateDir) {
2723
2736
  return d;
2724
2737
  }
2725
2738
  function event(stateDir, goalId, type2, payload = {}) {
2726
- fs5.mkdirSync(stateDir, { recursive: true });
2739
+ fs6.mkdirSync(stateDir, { recursive: true });
2727
2740
  const id = `ge-${Date.now()}-${crypto.randomBytes(3).toString("hex")}`;
2728
2741
  const at = (/* @__PURE__ */ new Date()).toISOString();
2729
- fs5.appendFileSync(eventFile(stateDir), JSON.stringify({ eventId: id, goalId, type: type2, at, ...payload }) + "\n", "utf8");
2742
+ fs6.appendFileSync(eventFile(stateDir), JSON.stringify({ eventId: id, goalId, type: type2, at, ...payload }) + "\n", "utf8");
2730
2743
  const d = db(stateDir);
2731
2744
  d.prepare("INSERT INTO goal_events (event_id, goal_id, type, payload_json, created_at) VALUES (?, ?, ?, ?, ?)").run(id, goalId, type2, JSON.stringify(payload), at);
2732
2745
  d.close?.();
2733
2746
  }
2734
2747
  function read(stateDir) {
2735
2748
  try {
2736
- const v = JSON.parse(fs5.readFileSync(file(stateDir), "utf8"));
2749
+ const v = JSON.parse(fs6.readFileSync(file(stateDir), "utf8"));
2737
2750
  return Array.isArray(v) ? v : [];
2738
2751
  } catch {
2739
2752
  return [];
@@ -2756,7 +2769,7 @@ function listGoals(stateDir) {
2756
2769
  }
2757
2770
  function listGoalEvents(stateDir) {
2758
2771
  try {
2759
- return fs5.readFileSync(eventFile(stateDir), "utf8").split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line));
2772
+ return fs6.readFileSync(eventFile(stateDir), "utf8").split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line));
2760
2773
  } catch {
2761
2774
  return [];
2762
2775
  }
@@ -2826,9 +2839,9 @@ function isAutoMemPath(absolutePath, workspace) {
2826
2839
  return normalizedPath.startsWith(getAutoMemPath(workspace));
2827
2840
  }
2828
2841
  async function ensureMemoryDirExists(memoryDir) {
2829
- const fs43 = await import("node:fs");
2842
+ const fs44 = await import("node:fs");
2830
2843
  try {
2831
- await fs43.promises.mkdir(memoryDir, { recursive: true });
2844
+ await fs44.promises.mkdir(memoryDir, { recursive: true });
2832
2845
  } catch (e) {
2833
2846
  const code = e?.code;
2834
2847
  if (code !== "EEXIST") {
@@ -3159,13 +3172,13 @@ __export(prompt_exports, {
3159
3172
  buildSystemPrompt: () => buildSystemPrompt,
3160
3173
  buildVolatileRuntimeContext: () => buildVolatileRuntimeContext
3161
3174
  });
3162
- import * as path6 from "node:path";
3163
- import * as fs6 from "node:fs";
3175
+ import * as path7 from "node:path";
3176
+ import * as fs7 from "node:fs";
3164
3177
  import * as os2 from "node:os";
3165
3178
  function readFileIfExists(filePath) {
3166
3179
  try {
3167
- if (fs6.existsSync(filePath)) {
3168
- return fs6.readFileSync(filePath, "utf-8");
3180
+ if (fs7.existsSync(filePath)) {
3181
+ return fs7.readFileSync(filePath, "utf-8");
3169
3182
  }
3170
3183
  } catch {
3171
3184
  }
@@ -3324,7 +3337,7 @@ function loadStaticFiles(workspace, staticFiles) {
3324
3337
  if (!staticFiles || staticFiles.length === 0) return null;
3325
3338
  const parts = [];
3326
3339
  for (const file2 of staticFiles) {
3327
- const filePath = path6.isAbsolute(file2) ? file2 : path6.join(workspace, file2);
3340
+ const filePath = path7.isAbsolute(file2) ? file2 : path7.join(workspace, file2);
3328
3341
  const content = readFileIfExists(filePath);
3329
3342
  if (content) parts.push(content);
3330
3343
  }
@@ -3343,7 +3356,7 @@ function loadMemoryInstructions(workspace) {
3343
3356
  }
3344
3357
  }
3345
3358
  function resolveBlockContent(block, ctx) {
3346
- const overridePath = path6.join(ctx.workspace, "prompts", `${block.name}.md`);
3359
+ const overridePath = path7.join(ctx.workspace, "prompts", `${block.name}.md`);
3347
3360
  const override = readFileIfExists(overridePath);
3348
3361
  if (override) return override;
3349
3362
  return block.generate(ctx);
@@ -3392,7 +3405,7 @@ function buildCustomPrompt(workspace, config) {
3392
3405
  continue;
3393
3406
  }
3394
3407
  if (name.endsWith(".md")) {
3395
- const filePath = path6.isAbsolute(name) ? name : path6.join(workspace, name);
3408
+ const filePath = path7.isAbsolute(name) ? name : path7.join(workspace, name);
3396
3409
  const content = readFileIfExists(filePath);
3397
3410
  if (content) {
3398
3411
  parts.push(content);
@@ -3508,7 +3521,7 @@ var init_prompt = __esm({
3508
3521
  { name: "tone-style", description: "\u8BED\u6C14\u98CE\u683C\uFF08\u7B80\u6D01\u3001\u4E0D\u7528emoji\uFF09", generate: (_) => getToneAndStyleSection() },
3509
3522
  { name: "output-efficiency", description: "\u8F93\u51FA\u6548\u7387\uFF08\u76F4\u5954\u4E3B\u9898\uFF09", generate: (_) => getOutputEfficiencySection() },
3510
3523
  // OpenClaw 叠加层
3511
- { name: "soul", description: "SOUL.md \u4EBA\u683C\u8EAB\u4EFD", generate: (ctx) => readFileIfExists(path6.join(ctx.workspace, "SOUL.md")) },
3524
+ { name: "soul", description: "SOUL.md \u4EBA\u683C\u8EAB\u4EFD", generate: (ctx) => readFileIfExists(path7.join(ctx.workspace, "SOUL.md")) },
3512
3525
  { name: "static-files", description: "\u914D\u7F6E\u6587\u4EF6\u6307\u5B9A\u7684\u989D\u5916\u6587\u4EF6\uFF08AGENTS/USER/MEMORY\u7B49\uFF09", generate: (ctx) => loadStaticFiles(ctx.workspace, ctx.staticFiles) },
3513
3526
  { name: "auto-memory-instructions", description: "auto memory \u5B8C\u6574\u6307\u4EE4\uFF08\u5B58+\u8BFB+recall\u8BF4\u660E\uFF09", generate: (ctx) => loadMemoryInstructions(ctx.workspace) },
3514
3527
  // Boundary(永远在最后)
@@ -6462,8 +6475,8 @@ var init_attachments = __esm({
6462
6475
  });
6463
6476
 
6464
6477
  // src/utils/context-dump.ts
6465
- import * as fs7 from "node:fs";
6466
- import * as path7 from "node:path";
6478
+ import * as fs8 from "node:fs";
6479
+ import * as path8 from "node:path";
6467
6480
  function dumpApiRequest(opts) {
6468
6481
  const lines = [
6469
6482
  "=== API Request Debug\uFF08\u53D1\u7ED9 LLM \u7684\u6700\u7EC8\u8BF7\u6C42\u4F53\uFF0C\u6BCF\u6B21\u8986\u76D6\u5199\uFF09===",
@@ -6496,7 +6509,7 @@ function dumpApiRequest(opts) {
6496
6509
  lines.push(`[${i}] ${m.role}: (empty)`);
6497
6510
  }
6498
6511
  }
6499
- fs7.writeFileSync(path7.join(opts.workspace, ".context-debug.txt"), lines.join("\n") + "\n", "utf-8");
6512
+ fs8.writeFileSync(path8.join(opts.workspace, ".context-debug.txt"), lines.join("\n") + "\n", "utf-8");
6500
6513
  }
6501
6514
  var init_context_dump = __esm({
6502
6515
  "src/utils/context-dump.ts"() {
@@ -7556,7 +7569,7 @@ var init_contextOverflow = __esm({
7556
7569
  });
7557
7570
 
7558
7571
  // src/utils/path.ts
7559
- import * as path8 from "node:path";
7572
+ import * as path9 from "node:path";
7560
7573
  function fixMsysPath(p) {
7561
7574
  let fixed = p.includes("\\") ? p.replace(/\\/g, "/") : p;
7562
7575
  if (process.platform === "win32") {
@@ -7566,15 +7579,15 @@ function fixMsysPath(p) {
7566
7579
  }
7567
7580
  function resolvePath(p, workspace) {
7568
7581
  const fixed = fixMsysPath(p);
7569
- const resolved = path8.isAbsolute(fixed) ? path8.normalize(fixed) : path8.resolve(workspace, fixed);
7570
- const normalized = path8.normalize(resolved);
7571
- const normalizedWorkspace = path8.normalize(workspace);
7582
+ const resolved = path9.isAbsolute(fixed) ? path9.normalize(fixed) : path9.resolve(workspace, fixed);
7583
+ const normalized = path9.normalize(resolved);
7584
+ const normalizedWorkspace = path9.normalize(workspace);
7572
7585
  if (sandboxOff) return normalized;
7573
- if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace + path8.sep)) {
7586
+ if (normalized === normalizedWorkspace || normalized.startsWith(normalizedWorkspace + path9.sep)) {
7574
7587
  return normalized;
7575
7588
  }
7576
7589
  for (const allowed of extraAllowedPaths) {
7577
- if (normalized === allowed || normalized.startsWith(allowed + path8.sep)) {
7590
+ if (normalized === allowed || normalized.startsWith(allowed + path9.sep)) {
7578
7591
  return normalized;
7579
7592
  }
7580
7593
  }
@@ -7809,9 +7822,9 @@ __export(BashTool_exports, {
7809
7822
  findShell: () => findShell,
7810
7823
  killChild: () => killChild
7811
7824
  });
7812
- import { spawn as spawn2, execSync } from "node:child_process";
7813
- import * as fs8 from "node:fs";
7814
- import * as path9 from "node:path";
7825
+ import { spawn as spawn2, execSync as execSync2 } from "node:child_process";
7826
+ import * as fs9 from "node:fs";
7827
+ import * as path10 from "node:path";
7815
7828
  function isWslBash(p) {
7816
7829
  const normalized = p.replace(/\//g, "\\").toLowerCase();
7817
7830
  return WSL_PATH_MARKERS.some((m) => normalized.includes(m.toLowerCase()));
@@ -7823,14 +7836,14 @@ function findShell() {
7823
7836
  return cachedShell;
7824
7837
  }
7825
7838
  try {
7826
- const result = execSync("where.exe bash", {
7839
+ const result = execSync2("where.exe bash", {
7827
7840
  encoding: "utf-8",
7828
7841
  timeout: 5e3,
7829
7842
  stdio: ["ignore", "pipe", "ignore"]
7830
7843
  });
7831
7844
  const candidates = result.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
7832
7845
  const nonWsl = candidates.find((p) => !isWslBash(p));
7833
- if (nonWsl && fs8.existsSync(nonWsl)) {
7846
+ if (nonWsl && fs9.existsSync(nonWsl)) {
7834
7847
  cachedShell = { shell: nonWsl, args: ["-c"] };
7835
7848
  return cachedShell;
7836
7849
  }
@@ -7840,10 +7853,10 @@ function findShell() {
7840
7853
  "C:\\Program Files\\Git\\bin\\bash.exe",
7841
7854
  "C:\\Program Files (x86)\\Git\\bin\\bash.exe",
7842
7855
  "C:\\Program Files\\Git\\usr\\bin\\bash.exe",
7843
- path9.join(process.env.LOCALAPPDATA || "", "Programs", "Git", "bin", "bash.exe")
7856
+ path10.join(process.env.LOCALAPPDATA || "", "Programs", "Git", "bin", "bash.exe")
7844
7857
  ];
7845
7858
  for (const p of knownPaths) {
7846
- if (p && fs8.existsSync(p)) {
7859
+ if (p && fs9.existsSync(p)) {
7847
7860
  cachedShell = { shell: p, args: ["-c"] };
7848
7861
  return cachedShell;
7849
7862
  }
@@ -7946,8 +7959,8 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
7946
7959
  }
7947
7960
  const MAX_OUTPUT = 100 * 1024;
7948
7961
  const osMod = await import("node:os");
7949
- const outputFile = path9.join(osMod.tmpdir(), `exec-${Date.now()}-${Math.random().toString(36).slice(2)}.out`);
7950
- const outputHandle = await fs8.promises.open(outputFile, "w");
7962
+ const outputFile = path10.join(osMod.tmpdir(), `exec-${Date.now()}-${Math.random().toString(36).slice(2)}.out`);
7963
+ const outputHandle = await fs9.promises.open(outputFile, "w");
7951
7964
  return new Promise((resolve12) => {
7952
7965
  const { shell, args: shellArgs } = findShell();
7953
7966
  const child = spawn2(shell, [...shellArgs, command], {
@@ -7966,21 +7979,21 @@ For commands that are harder to parse at a glance (piped commands, obscure flags
7966
7979
  let fileOutput = "";
7967
7980
  let truncated = false;
7968
7981
  try {
7969
- const st = await fs8.promises.stat(outputFile);
7982
+ const st = await fs9.promises.stat(outputFile);
7970
7983
  if (st.size > MAX_OUTPUT) {
7971
- const rfd = await fs8.promises.open(outputFile, "r");
7984
+ const rfd = await fs9.promises.open(outputFile, "r");
7972
7985
  const buf = Buffer.alloc(MAX_OUTPUT);
7973
7986
  await rfd.read(buf, 0, MAX_OUTPUT, 0);
7974
7987
  await rfd.close();
7975
7988
  fileOutput = buf.toString("utf-8");
7976
7989
  truncated = true;
7977
7990
  } else {
7978
- fileOutput = await fs8.promises.readFile(outputFile, "utf-8");
7991
+ fileOutput = await fs9.promises.readFile(outputFile, "utf-8");
7979
7992
  }
7980
7993
  } catch {
7981
7994
  }
7982
7995
  try {
7983
- await fs8.promises.unlink(outputFile);
7996
+ await fs9.promises.unlink(outputFile);
7984
7997
  } catch {
7985
7998
  }
7986
7999
  const processedStdout = fileOutput.replace(/^(\s*\n)+/, "").trimEnd();
@@ -8057,8 +8070,8 @@ __export(task_manager_exports, {
8057
8070
  });
8058
8071
  import { randomBytes } from "node:crypto";
8059
8072
  import { spawn as spawn3 } from "node:child_process";
8060
- import * as fs9 from "node:fs";
8061
- import * as path10 from "node:path";
8073
+ import * as fs10 from "node:fs";
8074
+ import * as path11 from "node:path";
8062
8075
  function generateTaskId(type2 = "local_bash") {
8063
8076
  const prefix = TASK_ID_PREFIXES[type2] ?? "x";
8064
8077
  const bytes = randomBytes(8);
@@ -8071,42 +8084,42 @@ function generateTaskId(type2 = "local_bash") {
8071
8084
  function getTaskOutputDir() {
8072
8085
  if (_taskOutputDir === void 0) {
8073
8086
  const stateDir = process.env.ENGINE_STATE_DIR || process.cwd();
8074
- _taskOutputDir = path10.join(stateDir, "tasks");
8087
+ _taskOutputDir = path11.join(stateDir, "tasks");
8075
8088
  }
8076
8089
  return _taskOutputDir;
8077
8090
  }
8078
8091
  function getTaskOutputPath(taskId) {
8079
- return path10.join(getTaskOutputDir(), `${taskId}.output`);
8092
+ return path11.join(getTaskOutputDir(), `${taskId}.output`);
8080
8093
  }
8081
8094
  function ensureOutputDir() {
8082
8095
  const dir = getTaskOutputDir();
8083
- if (!fs9.existsSync(dir)) {
8084
- fs9.mkdirSync(dir, { recursive: true });
8096
+ if (!fs10.existsSync(dir)) {
8097
+ fs10.mkdirSync(dir, { recursive: true });
8085
8098
  }
8086
8099
  }
8087
8100
  function initTaskOutput(taskId) {
8088
8101
  ensureOutputDir();
8089
8102
  const outputPath = getTaskOutputPath(taskId);
8090
- fs9.writeFileSync(outputPath, "", "utf-8");
8103
+ fs10.writeFileSync(outputPath, "", "utf-8");
8091
8104
  return outputPath;
8092
8105
  }
8093
8106
  function persistTask(state2) {
8094
8107
  try {
8095
8108
  ensureOutputDir();
8096
8109
  const p = taskIndexPath();
8097
- const existing = fs9.existsSync(p) ? JSON.parse(fs9.readFileSync(p, "utf8")) : [];
8110
+ const existing = fs10.existsSync(p) ? JSON.parse(fs10.readFileSync(p, "utf8")) : [];
8098
8111
  const next = existing.filter((t) => t.id !== state2.id);
8099
8112
  next.push({ ...state2 });
8100
8113
  const tmp = `${p}.${process.pid}.tmp`;
8101
- fs9.writeFileSync(tmp, JSON.stringify(next, null, 2));
8102
- fs9.renameSync(tmp, p);
8114
+ fs10.writeFileSync(tmp, JSON.stringify(next, null, 2));
8115
+ fs10.renameSync(tmp, p);
8103
8116
  } catch (err) {
8104
8117
  console.warn(`[task-manager] persist failed: ${err.message}`);
8105
8118
  }
8106
8119
  }
8107
8120
  function loadPersistedTasks() {
8108
8121
  try {
8109
- const v = JSON.parse(fs9.readFileSync(taskIndexPath(), "utf8"));
8122
+ const v = JSON.parse(fs10.readFileSync(taskIndexPath(), "utf8"));
8110
8123
  return Array.isArray(v) ? v : [];
8111
8124
  } catch {
8112
8125
  return [];
@@ -8116,7 +8129,7 @@ function loadNotificationQueue() {
8116
8129
  if (notificationsLoaded) return;
8117
8130
  notificationsLoaded = true;
8118
8131
  try {
8119
- const value = JSON.parse(fs9.readFileSync(notificationQueuePath(), "utf8"));
8132
+ const value = JSON.parse(fs10.readFileSync(notificationQueuePath(), "utf8"));
8120
8133
  if (Array.isArray(value)) pendingNotifications.push(...value.filter((x) => x && typeof x.notification === "string"));
8121
8134
  } catch {
8122
8135
  }
@@ -8126,8 +8139,8 @@ function persistNotificationQueue() {
8126
8139
  ensureOutputDir();
8127
8140
  const p = notificationQueuePath();
8128
8141
  const tmp = `${p}.${process.pid}.tmp`;
8129
- fs9.writeFileSync(tmp, JSON.stringify(pendingNotifications, null, 2), "utf8");
8130
- fs9.renameSync(tmp, p);
8142
+ fs10.writeFileSync(tmp, JSON.stringify(pendingNotifications, null, 2), "utf8");
8143
+ fs10.renameSync(tmp, p);
8131
8144
  } catch (err) {
8132
8145
  console.warn(`[task-manager] notification persist failed: ${err.message}`);
8133
8146
  }
@@ -8264,14 +8277,14 @@ function spawnBackgroundTask(opts) {
8264
8277
  const taskId = generateTaskId("local_bash");
8265
8278
  const outputPath = initTaskOutput(taskId);
8266
8279
  const { shell, args: shellArgs } = findShell();
8267
- const outputFd = fs9.openSync(outputPath, "w");
8280
+ const outputFd = fs10.openSync(outputPath, "w");
8268
8281
  const child = spawn3(shell, [...shellArgs, opts.command], {
8269
8282
  cwd: opts.cwd,
8270
8283
  env: opts.env || process.env,
8271
8284
  stdio: ["ignore", outputFd, outputFd]
8272
8285
  });
8273
8286
  try {
8274
- fs9.closeSync(outputFd);
8287
+ fs10.closeSync(outputFd);
8275
8288
  } catch {
8276
8289
  }
8277
8290
  processes.set(taskId, child);
@@ -8303,12 +8316,12 @@ function spawnBackgroundTask(opts) {
8303
8316
  let killedForSize = false;
8304
8317
  sizeWatchdog = setInterval(() => {
8305
8318
  if (tasks.get(taskId)?.status !== "running") return;
8306
- fs9.stat(outputPath, (err, st) => {
8319
+ fs10.stat(outputPath, (err, st) => {
8307
8320
  if (err || st.size <= MAX_TASK_OUTPUT_BYTES) return;
8308
8321
  killedForSize = true;
8309
8322
  if (sizeWatchdog) clearInterval(sizeWatchdog);
8310
8323
  try {
8311
- fs9.appendFileSync(outputPath, "\n[output truncated: exceeded 5GB disk cap]\n");
8324
+ fs10.appendFileSync(outputPath, "\n[output truncated: exceeded 5GB disk cap]\n");
8312
8325
  } catch {
8313
8326
  }
8314
8327
  killChild(child);
@@ -8438,16 +8451,16 @@ function getTaskOutput(taskId, maxBytes = 8 * 1024 * 1024) {
8438
8451
  if (!state2) return "";
8439
8452
  try {
8440
8453
  const outputPath = state2.outputFile;
8441
- if (!fs9.existsSync(outputPath)) return "";
8442
- const stat4 = fs9.statSync(outputPath);
8454
+ if (!fs10.existsSync(outputPath)) return "";
8455
+ const stat4 = fs10.statSync(outputPath);
8443
8456
  if (stat4.size <= maxBytes) {
8444
- return fs9.readFileSync(outputPath, "utf-8");
8457
+ return fs10.readFileSync(outputPath, "utf-8");
8445
8458
  }
8446
- const fd = fs9.openSync(outputPath, "r");
8459
+ const fd = fs10.openSync(outputPath, "r");
8447
8460
  const start = stat4.size - maxBytes;
8448
8461
  const buf = Buffer.alloc(maxBytes);
8449
- fs9.readSync(fd, buf, 0, maxBytes, start);
8450
- fs9.closeSync(fd);
8462
+ fs10.readSync(fd, buf, 0, maxBytes, start);
8463
+ fs10.closeSync(fd);
8451
8464
  const content = buf.toString("utf-8");
8452
8465
  const omitted = Math.round((stat4.size - maxBytes) / 1024);
8453
8466
  return `[${omitted}KB of earlier output omitted]
@@ -8461,14 +8474,14 @@ function getTaskOutputDelta(taskId, fromOffset, maxBytes = 8 * 1024 * 1024) {
8461
8474
  if (!state2) return { content: "", newOffset: fromOffset };
8462
8475
  try {
8463
8476
  const outputPath = state2.outputFile;
8464
- if (!fs9.existsSync(outputPath)) return { content: "", newOffset: fromOffset };
8465
- const stat4 = fs9.statSync(outputPath);
8477
+ if (!fs10.existsSync(outputPath)) return { content: "", newOffset: fromOffset };
8478
+ const stat4 = fs10.statSync(outputPath);
8466
8479
  if (fromOffset >= stat4.size) return { content: "", newOffset: stat4.size };
8467
8480
  const readLen = Math.min(maxBytes, stat4.size - fromOffset);
8468
8481
  const buf = Buffer.alloc(readLen);
8469
- const fd = fs9.openSync(outputPath, "r");
8470
- fs9.readSync(fd, buf, 0, readLen, fromOffset);
8471
- fs9.closeSync(fd);
8482
+ const fd = fs10.openSync(outputPath, "r");
8483
+ fs10.readSync(fd, buf, 0, readLen, fromOffset);
8484
+ fs10.closeSync(fd);
8472
8485
  return { content: buf.toString("utf-8"), newOffset: fromOffset + readLen };
8473
8486
  } catch {
8474
8487
  return { content: "", newOffset: fromOffset };
@@ -8478,8 +8491,8 @@ function getTaskOutputSize(taskId) {
8478
8491
  const state2 = tasks.get(taskId);
8479
8492
  if (!state2) return 0;
8480
8493
  try {
8481
- if (!fs9.existsSync(state2.outputFile)) return 0;
8482
- return fs9.statSync(state2.outputFile).size;
8494
+ if (!fs10.existsSync(state2.outputFile)) return 0;
8495
+ return fs10.statSync(state2.outputFile).size;
8483
8496
  } catch {
8484
8497
  return 0;
8485
8498
  }
@@ -8517,10 +8530,10 @@ var init_task_manager = __esm({
8517
8530
  MAX_TASK_OUTPUT_BYTES = 5 * 1024 * 1024 * 1024;
8518
8531
  tasks = /* @__PURE__ */ new Map();
8519
8532
  processes = /* @__PURE__ */ new Map();
8520
- taskIndexPath = () => path10.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "index.json");
8533
+ taskIndexPath = () => path11.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "index.json");
8521
8534
  pendingNotifications = [];
8522
8535
  notificationsLoaded = false;
8523
- notificationQueuePath = () => path10.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "notifications.json");
8536
+ notificationQueuePath = () => path11.join(process.env.ENGINE_STATE_DIR || process.cwd(), "tasks", "notifications.json");
8524
8537
  notificationCallback = null;
8525
8538
  DEAD_LETTER_MAX_ATTEMPTS = 10;
8526
8539
  RETRY_BASE_MS = 1e3;
@@ -8662,8 +8675,8 @@ __export(context_analyzer_exports, {
8662
8675
  formatContextReport: () => formatContextReport,
8663
8676
  scanMemoryFiles: () => scanMemoryFiles
8664
8677
  });
8665
- import * as fs10 from "node:fs";
8666
- import * as path11 from "node:path";
8678
+ import * as fs11 from "node:fs";
8679
+ import * as path12 from "node:path";
8667
8680
  function estimateMessageTokens2(m) {
8668
8681
  let tokens = 0;
8669
8682
  if (typeof m.content === "string") {
@@ -8773,9 +8786,9 @@ function breakdownMessages(messages) {
8773
8786
  }
8774
8787
  async function scanMemoryFiles(workspace) {
8775
8788
  const files = [];
8776
- const soul = readFileIfExists2(path11.join(workspace, "SOUL.md"));
8789
+ const soul = readFileIfExists2(path12.join(workspace, "SOUL.md"));
8777
8790
  if (soul) files.push({ path: "SOUL.md", tokens: roughTokenCountEstimation(soul), stable: true });
8778
- const agents = readFileIfExists2(path11.join(workspace, "AGENTS.md"));
8791
+ const agents = readFileIfExists2(path12.join(workspace, "AGENTS.md"));
8779
8792
  if (agents) files.push({ path: "AGENTS.md", tokens: roughTokenCountEstimation(agents), stable: true });
8780
8793
  try {
8781
8794
  const { buildMemoryPrompt: buildMemoryPrompt2 } = await Promise.resolve().then(() => (init_memdir(), memdir_exports));
@@ -8791,7 +8804,7 @@ async function scanMemoryFiles(workspace) {
8791
8804
  }
8792
8805
  function readFileIfExists2(filePath) {
8793
8806
  try {
8794
- if (fs10.existsSync(filePath)) return fs10.readFileSync(filePath, "utf-8");
8807
+ if (fs11.existsSync(filePath)) return fs11.readFileSync(filePath, "utf-8");
8795
8808
  } catch {
8796
8809
  }
8797
8810
  return null;
@@ -9770,8 +9783,8 @@ ${perTurnSystemDynamic}` : deferredHint || perTurnSystemDynamic;
9770
9783
  });
9771
9784
 
9772
9785
  // src/session/writer.ts
9773
- import * as fs11 from "node:fs";
9774
- import * as path12 from "node:path";
9786
+ import * as fs12 from "node:fs";
9787
+ import * as path13 from "node:path";
9775
9788
  import * as crypto2 from "node:crypto";
9776
9789
  function assistantWriteParamsFrom(m) {
9777
9790
  const anyM = m;
@@ -9807,7 +9820,7 @@ var init_writer = __esm({
9807
9820
  this.sessionId = sessionId || crypto2.randomUUID();
9808
9821
  this.engineSessionId = "";
9809
9822
  const filename = `${this.sessionId}.jsonl`;
9810
- this.filePath = path12.join(sessionsDir, filename);
9823
+ this.filePath = path13.join(sessionsDir, filename);
9811
9824
  }
9812
9825
  get id() {
9813
9826
  return this.sessionId;
@@ -9818,9 +9831,9 @@ var init_writer = __esm({
9818
9831
  /** 打开文件写入 header(新文件才写 header) */
9819
9832
  open(cwd, engineSessionId) {
9820
9833
  this.engineSessionId = engineSessionId || "";
9821
- fs11.mkdirSync(path12.dirname(this.filePath), { recursive: true });
9822
- const fileExists = fs11.existsSync(this.filePath) && fs11.statSync(this.filePath).size > 0;
9823
- this.stream = fs11.createWriteStream(this.filePath, { flags: "a" });
9834
+ fs12.mkdirSync(path13.dirname(this.filePath), { recursive: true });
9835
+ const fileExists = fs12.existsSync(this.filePath) && fs12.statSync(this.filePath).size > 0;
9836
+ this.stream = fs12.createWriteStream(this.filePath, { flags: "a" });
9824
9837
  this.stream.on("error", (err) => {
9825
9838
  console.error(`[SessionWriter] write error on ${this.filePath}:`, err.message);
9826
9839
  });
@@ -10023,17 +10036,17 @@ var init_writer = __esm({
10023
10036
  this.stream.end();
10024
10037
  this.stream = null;
10025
10038
  }
10026
- if (!fs11.existsSync(this.filePath)) return null;
10027
- const fileSize = fs11.statSync(this.filePath).size;
10039
+ if (!fs12.existsSync(this.filePath)) return null;
10040
+ const fileSize = fs12.statSync(this.filePath).size;
10028
10041
  if (fileSize === 0) return null;
10029
10042
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
10030
10043
  const archivedPath = `${this.filePath}.${reason}.${ts}`;
10031
- fs11.renameSync(this.filePath, archivedPath);
10044
+ fs12.renameSync(this.filePath, archivedPath);
10032
10045
  const sizeMB = (fileSize / 1024 / 1024).toFixed(1);
10033
- console.log(`[SessionWriter] Archived JSONL: ${path12.basename(this.filePath)} \u2192 ${path12.basename(archivedPath)} (${sizeMB}MB)`);
10046
+ console.log(`[SessionWriter] Archived JSONL: ${path13.basename(this.filePath)} \u2192 ${path13.basename(archivedPath)} (${sizeMB}MB)`);
10034
10047
  const postBoundaryData = this.readPostBoundaryFromArchived(archivedPath);
10035
- const dir = path12.dirname(this.filePath);
10036
- fs11.mkdirSync(dir, { recursive: true });
10048
+ const dir = path13.dirname(this.filePath);
10049
+ fs12.mkdirSync(dir, { recursive: true });
10037
10050
  const header = {
10038
10051
  type: "session",
10039
10052
  version: 3,
@@ -10047,8 +10060,8 @@ var init_writer = __esm({
10047
10060
  if (postBoundaryData.length > 0) {
10048
10061
  initialData += postBoundaryData.toString("utf-8");
10049
10062
  }
10050
- fs11.writeFileSync(this.filePath, initialData, "utf-8");
10051
- this.stream = fs11.createWriteStream(this.filePath, { flags: "a" });
10063
+ fs12.writeFileSync(this.filePath, initialData, "utf-8");
10064
+ this.stream = fs12.createWriteStream(this.filePath, { flags: "a" });
10052
10065
  this.stream.on("error", (err) => {
10053
10066
  console.error(`[SessionWriter] write error on ${this.filePath}:`, err.message);
10054
10067
  });
@@ -10058,10 +10071,10 @@ var init_writer = __esm({
10058
10071
  * 从归档文件中读取最后一个 compact_boundary 之后的内容
10059
10072
  */
10060
10073
  readPostBoundaryFromArchived(archivedPath) {
10061
- const fileSize = fs11.statSync(archivedPath).size;
10074
+ const fileSize = fs12.statSync(archivedPath).size;
10062
10075
  if (fileSize === 0) return Buffer.alloc(0);
10063
10076
  if (fileSize <= 5 * 1024 * 1024) {
10064
- const content = fs11.readFileSync(archivedPath, "utf-8");
10077
+ const content = fs12.readFileSync(archivedPath, "utf-8");
10065
10078
  const lines = content.split("\n");
10066
10079
  let lastBoundaryIdx = -1;
10067
10080
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -10078,11 +10091,11 @@ var init_writer = __esm({
10078
10091
  {
10079
10092
  const probeSize = Math.min(fileSize, 1024 * 1024);
10080
10093
  const probeBuf = Buffer.allocUnsafe(probeSize);
10081
- const probeFd = fs11.openSync(archivedPath, "r");
10094
+ const probeFd = fs12.openSync(archivedPath, "r");
10082
10095
  let hasBoundary = false;
10083
10096
  let probed = 0;
10084
10097
  while (probed < fileSize) {
10085
- const n = fs11.readSync(probeFd, probeBuf, 0, Math.min(probeSize, fileSize - probed), probed);
10098
+ const n = fs12.readSync(probeFd, probeBuf, 0, Math.min(probeSize, fileSize - probed), probed);
10086
10099
  if (n === 0) break;
10087
10100
  if (probeBuf.subarray(0, n).includes(Buffer.from(boundaryMarker))) {
10088
10101
  hasBoundary = true;
@@ -10090,19 +10103,19 @@ var init_writer = __esm({
10090
10103
  }
10091
10104
  probed += n;
10092
10105
  }
10093
- fs11.closeSync(probeFd);
10106
+ fs12.closeSync(probeFd);
10094
10107
  if (!hasBoundary) return Buffer.alloc(0);
10095
10108
  }
10096
10109
  const outBuf = Buffer.allocUnsafe(Math.min(fileSize, 8 * 1024 * 1024));
10097
10110
  let outLen = 0;
10098
10111
  const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
10099
- const fd = fs11.openSync(archivedPath, "r");
10112
+ const fd = fs12.openSync(archivedPath, "r");
10100
10113
  try {
10101
10114
  let filePos = 0;
10102
10115
  let carryBuf;
10103
10116
  let carryLen = 0;
10104
10117
  while (filePos < fileSize) {
10105
- const bytesRead = fs11.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
10118
+ const bytesRead = fs12.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
10106
10119
  if (bytesRead === 0) break;
10107
10120
  filePos += bytesRead;
10108
10121
  let scanBuf;
@@ -10151,7 +10164,7 @@ var init_writer = __esm({
10151
10164
  }
10152
10165
  }
10153
10166
  } finally {
10154
- fs11.closeSync(fd);
10167
+ fs12.closeSync(fd);
10155
10168
  }
10156
10169
  return outBuf.subarray(0, outLen);
10157
10170
  }
@@ -10163,15 +10176,15 @@ var init_writer = __esm({
10163
10176
  */
10164
10177
  readLastId() {
10165
10178
  try {
10166
- const stat4 = fs11.statSync(this.filePath);
10179
+ const stat4 = fs12.statSync(this.filePath);
10167
10180
  if (stat4.size === 0) return null;
10168
10181
  const readSize = Math.min(stat4.size, 4096);
10169
10182
  const buf = Buffer.alloc(readSize);
10170
- const fd = fs11.openSync(this.filePath, "r");
10183
+ const fd = fs12.openSync(this.filePath, "r");
10171
10184
  try {
10172
- fs11.readSync(fd, buf, 0, readSize, stat4.size - readSize);
10185
+ fs12.readSync(fd, buf, 0, readSize, stat4.size - readSize);
10173
10186
  } finally {
10174
- fs11.closeSync(fd);
10187
+ fs12.closeSync(fd);
10175
10188
  }
10176
10189
  const text = buf.toString("utf-8");
10177
10190
  const lines = text.split("\n").filter((l) => l.trim().length > 0);
@@ -10218,11 +10231,11 @@ var init_writer = __esm({
10218
10231
  });
10219
10232
 
10220
10233
  // src/session/reader.ts
10221
- import * as fs12 from "node:fs";
10222
- import * as path13 from "node:path";
10234
+ import * as fs13 from "node:fs";
10235
+ import * as path14 from "node:path";
10223
10236
  import * as readline from "node:readline";
10224
10237
  async function readSessionHeader(filePath) {
10225
- const stream = fs12.createReadStream(filePath, { encoding: "utf-8" });
10238
+ const stream = fs13.createReadStream(filePath, { encoding: "utf-8" });
10226
10239
  const rl = readline.createInterface({ input: stream });
10227
10240
  return new Promise((resolve12) => {
10228
10241
  let resolved = false;
@@ -10253,7 +10266,7 @@ async function readSessionHeader(filePath) {
10253
10266
  });
10254
10267
  }
10255
10268
  async function readLargeFilePostBoundary(filePath) {
10256
- const stat4 = fs12.statSync(filePath);
10269
+ const stat4 = fs13.statSync(filePath);
10257
10270
  const fileSize = stat4.size;
10258
10271
  const boundaryMarker = '"compact_boundary"';
10259
10272
  const CHUNK_SIZE = TRANSCRIPT_READ_CHUNK_SIZE;
@@ -10261,13 +10274,13 @@ async function readLargeFilePostBoundary(filePath) {
10261
10274
  let outLen = 0;
10262
10275
  let boundaryStartOffset = 0;
10263
10276
  const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
10264
- const fd = fs12.openSync(filePath, "r");
10277
+ const fd = fs13.openSync(filePath, "r");
10265
10278
  try {
10266
10279
  let filePos = 0;
10267
10280
  let carryBuf;
10268
10281
  let carryLen = 0;
10269
10282
  while (filePos < fileSize) {
10270
- const bytesRead = fs12.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
10283
+ const bytesRead = fs13.readSync(fd, chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
10271
10284
  if (bytesRead === 0) break;
10272
10285
  filePos += bytesRead;
10273
10286
  let scanBuf;
@@ -10319,7 +10332,7 @@ async function readLargeFilePostBoundary(filePath) {
10319
10332
  }
10320
10333
  }
10321
10334
  } finally {
10322
- fs12.closeSync(fd);
10335
+ fs13.closeSync(fd);
10323
10336
  }
10324
10337
  const postBoundaryText = outBuf.subarray(0, outLen).toString("utf-8");
10325
10338
  return postBoundaryText.split("\n").filter((l) => l.trim().length > 0);
@@ -10443,7 +10456,7 @@ function recoverOrphanedParallelToolResults(allEntries, chain, byUuid, seen) {
10443
10456
  return result;
10444
10457
  }
10445
10458
  async function readSessionHistory(filePath) {
10446
- const stat4 = fs12.statSync(filePath);
10459
+ const stat4 = fs13.statSync(filePath);
10447
10460
  const fileSize = stat4.size;
10448
10461
  if (fileSize > MAX_TRANSCRIPT_READ_BYTES) {
10449
10462
  console.warn(`[reader] Session file exceeds 50MB limit (${(fileSize / 1024 / 1024).toFixed(1)}MB), using chunked fd read with boundary skip`);
@@ -10482,7 +10495,7 @@ async function readSessionHistory(filePath) {
10482
10495
  return [...sessionStarts, ...filtered, ...restAttachments];
10483
10496
  }
10484
10497
  async function readAllLines(filePath) {
10485
- const stream = fs12.createReadStream(filePath, { encoding: "utf-8" });
10498
+ const stream = fs13.createReadStream(filePath, { encoding: "utf-8" });
10486
10499
  const rl = readline.createInterface({ input: stream });
10487
10500
  const lines = [];
10488
10501
  return new Promise((resolve12, reject) => {
@@ -10636,12 +10649,12 @@ function extractText(content) {
10636
10649
  return content.filter((b) => b.type === "text").map((b) => b.text || "").join("") || null;
10637
10650
  }
10638
10651
  function listSessions(sessionsDir) {
10639
- if (!fs12.existsSync(sessionsDir)) return [];
10640
- const files = fs12.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") || f.includes(".jsonl.")).map((f) => ({
10641
- file: path13.join(sessionsDir, f),
10652
+ if (!fs13.existsSync(sessionsDir)) return [];
10653
+ const files = fs13.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") || f.includes(".jsonl.")).map((f) => ({
10654
+ file: path14.join(sessionsDir, f),
10642
10655
  id: f.replace(/\.jsonl.*$/, ""),
10643
10656
  // strip .jsonl and everything after (archived suffix)
10644
- modified: new Date(fs12.statSync(path13.join(sessionsDir, f)).mtimeMs)
10657
+ modified: new Date(fs13.statSync(path14.join(sessionsDir, f)).mtimeMs)
10645
10658
  })).sort((a, b) => b.modified.getTime() - a.modified.getTime());
10646
10659
  return files;
10647
10660
  }
@@ -10662,8 +10675,8 @@ __export(session_manager_exports, {
10662
10675
  SessionManager: () => SessionManager,
10663
10676
  alignRestoreHeadToTurnBoundary: () => alignRestoreHeadToTurnBoundary
10664
10677
  });
10665
- import * as path14 from "node:path";
10666
- import * as fs13 from "node:fs";
10678
+ import * as path15 from "node:path";
10679
+ import * as fs14 from "node:fs";
10667
10680
  import * as crypto3 from "node:crypto";
10668
10681
  function alignRestoreHeadToTurnBoundary(messages, minKeep = RESTORE_MIN_KEEP_MESSAGES) {
10669
10682
  const isTurnBoundary = (m) => isAttachmentMessage(m) ? true : m.role === "user";
@@ -10702,24 +10715,24 @@ var init_session_manager = __esm({
10702
10715
  constructor(config) {
10703
10716
  this.config = config;
10704
10717
  this.scopeConfig = config.scopeConfig;
10705
- this.sessionsDir = path14.join(config.stateDir, "agents", "main", "sessions");
10706
- this.indexPath = path14.join(this.sessionsDir, "session-index.json");
10707
- this.platformMapPath = path14.join(this.sessionsDir, "platform-map.json");
10708
- fs13.mkdirSync(this.sessionsDir, { recursive: true });
10718
+ this.sessionsDir = path15.join(config.stateDir, "agents", "main", "sessions");
10719
+ this.indexPath = path15.join(this.sessionsDir, "session-index.json");
10720
+ this.platformMapPath = path15.join(this.sessionsDir, "platform-map.json");
10721
+ fs14.mkdirSync(this.sessionsDir, { recursive: true });
10709
10722
  }
10710
10723
  // === 索引操作 ===
10711
10724
  loadIndex() {
10712
10725
  try {
10713
- if (fs13.existsSync(this.indexPath)) {
10714
- const raw = fs13.readFileSync(this.indexPath, "utf-8");
10726
+ if (fs14.existsSync(this.indexPath)) {
10727
+ const raw = fs14.readFileSync(this.indexPath, "utf-8");
10715
10728
  const obj = JSON.parse(raw);
10716
10729
  this.index = new Map(Object.entries(obj));
10717
10730
  let fixed = 0;
10718
10731
  for (const [key, entry] of this.index) {
10719
- if (fs13.existsSync(entry.file)) continue;
10720
- const basename10 = path14.basename(entry.file);
10721
- const localPath = path14.join(this.sessionsDir, basename10);
10722
- if (fs13.existsSync(localPath)) {
10732
+ if (fs14.existsSync(entry.file)) continue;
10733
+ const basename10 = path15.basename(entry.file);
10734
+ const localPath = path15.join(this.sessionsDir, basename10);
10735
+ if (fs14.existsSync(localPath)) {
10723
10736
  entry.file = localPath;
10724
10737
  fixed++;
10725
10738
  }
@@ -10738,7 +10751,7 @@ var init_session_manager = __esm({
10738
10751
  try {
10739
10752
  const obj = {};
10740
10753
  for (const [k, v] of this.index) obj[k] = v;
10741
- fs13.writeFileSync(this.indexPath, JSON.stringify(obj, null, 2));
10754
+ fs14.writeFileSync(this.indexPath, JSON.stringify(obj, null, 2));
10742
10755
  } catch (err) {
10743
10756
  console.error(`[session] Failed to save index: ${err.message}`);
10744
10757
  }
@@ -10746,8 +10759,8 @@ var init_session_manager = __esm({
10746
10759
  // === 平台映射 ===
10747
10760
  loadPlatformMap() {
10748
10761
  try {
10749
- if (fs13.existsSync(this.platformMapPath)) {
10750
- const raw = fs13.readFileSync(this.platformMapPath, "utf-8");
10762
+ if (fs14.existsSync(this.platformMapPath)) {
10763
+ const raw = fs14.readFileSync(this.platformMapPath, "utf-8");
10751
10764
  const obj = JSON.parse(raw);
10752
10765
  this.platformMap = new Map(Object.entries(obj));
10753
10766
  console.log(`[session] Platform map loaded: ${this.platformMap.size} entries`);
@@ -10759,7 +10772,7 @@ var init_session_manager = __esm({
10759
10772
  try {
10760
10773
  const obj = {};
10761
10774
  for (const [k, v] of this.platformMap) obj[k] = v;
10762
- fs13.writeFileSync(this.platformMapPath, JSON.stringify(obj, null, 2));
10775
+ fs14.writeFileSync(this.platformMapPath, JSON.stringify(obj, null, 2));
10763
10776
  } catch (err) {
10764
10777
  console.error(`[session] Failed to save platform map: ${err.message}`);
10765
10778
  }
@@ -10798,17 +10811,17 @@ var init_session_manager = __esm({
10798
10811
  */
10799
10812
  getSessionFilePath(sessionId) {
10800
10813
  const entry = this.index.get(sessionId);
10801
- if (entry && fs13.existsSync(entry.file)) return entry.file;
10802
- const direct = path14.join(this.sessionsDir, `${sessionId}.jsonl`);
10803
- return fs13.existsSync(direct) ? direct : null;
10814
+ if (entry && fs14.existsSync(entry.file)) return entry.file;
10815
+ const direct = path15.join(this.sessionsDir, `${sessionId}.jsonl`);
10816
+ return fs14.existsSync(direct) ? direct : null;
10804
10817
  }
10805
10818
  // === Writer 管理 ===
10806
10819
  getWriter(sessionId) {
10807
10820
  let writer = this.writers.get(sessionId);
10808
10821
  if (!writer) {
10809
10822
  const existing = this.index.get(sessionId);
10810
- if (existing && fs13.existsSync(existing.file)) {
10811
- const existingFileId = path14.basename(existing.file, ".jsonl");
10823
+ if (existing && fs14.existsSync(existing.file)) {
10824
+ const existingFileId = path15.basename(existing.file, ".jsonl");
10812
10825
  writer = new SessionWriter(this.sessionsDir, existingFileId);
10813
10826
  writer.open(this.config.workspace, sessionId);
10814
10827
  } else {
@@ -10820,7 +10833,7 @@ var init_session_manager = __esm({
10820
10833
  this.saveIndex();
10821
10834
  this.writers.set(sessionId, writer);
10822
10835
  this.onWriterCreated?.(writer, sessionId);
10823
- console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${path14.basename(writer.path)}`);
10836
+ console.log(`[session] ${existing ? "Resumed" : "New"}: ${sessionId} \u2192 ${path15.basename(writer.path)}`);
10824
10837
  }
10825
10838
  return writer;
10826
10839
  }
@@ -10839,7 +10852,7 @@ var init_session_manager = __esm({
10839
10852
  if (!writer) return null;
10840
10853
  try {
10841
10854
  this.lastArchiveCheck = Date.now();
10842
- const stat4 = fs13.statSync(writer.path);
10855
+ const stat4 = fs14.statSync(writer.path);
10843
10856
  if (stat4.size < threshold) return null;
10844
10857
  const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
10845
10858
  const thresholdMB = (threshold / 1024 / 1024).toFixed(1);
@@ -10848,10 +10861,10 @@ var init_session_manager = __esm({
10848
10861
  if (archivedPath) {
10849
10862
  this.index.set(sessionId, { file: writer.path, updatedAt: Date.now() });
10850
10863
  this.saveIndex();
10851
- const newSize = fs13.statSync(writer.path).size;
10864
+ const newSize = fs14.statSync(writer.path).size;
10852
10865
  const oldSizeMB = (stat4.size / 1024 / 1024).toFixed(1);
10853
- console.log(`[session] Archive complete: ${path14.basename(archivedPath)} (${oldSizeMB}MB) \u2192 new JSONL created (${newSize} bytes)`);
10854
- const fileId = path14.basename(writer.path).replace(/\.jsonl$/, "");
10866
+ console.log(`[session] Archive complete: ${path15.basename(archivedPath)} (${oldSizeMB}MB) \u2192 new JSONL created (${newSize} bytes)`);
10867
+ const fileId = path15.basename(writer.path).replace(/\.jsonl$/, "");
10855
10868
  this.purgeOldArchives(fileId, 3);
10856
10869
  return archivedPath;
10857
10870
  }
@@ -10867,15 +10880,15 @@ var init_session_manager = __esm({
10867
10880
  purgeOldArchives(sessionId, keepCount = 3) {
10868
10881
  try {
10869
10882
  const dir = this.sessionsDir;
10870
- if (!fs13.existsSync(dir)) return;
10871
- const allFiles = fs13.readdirSync(dir);
10883
+ if (!fs14.existsSync(dir)) return;
10884
+ const allFiles = fs14.readdirSync(dir);
10872
10885
  const archiveFiles = allFiles.filter((f) => {
10873
10886
  if (!f.startsWith(sessionId)) return false;
10874
10887
  return f.includes(".archived.") || f.includes(".compaction.");
10875
10888
  }).map((f) => ({
10876
10889
  name: f,
10877
- path: path14.join(dir, f),
10878
- mtime: fs13.statSync(path14.join(dir, f)).mtimeMs
10890
+ path: path15.join(dir, f),
10891
+ mtime: fs14.statSync(path15.join(dir, f)).mtimeMs
10879
10892
  })).sort((a, b) => b.mtime - a.mtime);
10880
10893
  console.log(`[session] purgeOldArchives: sessionId=${sessionId.substring(0, 8)}... found=${archiveFiles.length} keep=${keepCount}`);
10881
10894
  if (archiveFiles.length <= keepCount) return;
@@ -10885,7 +10898,7 @@ var init_session_manager = __esm({
10885
10898
  console.log(`[session] Skipping archived (kept for history): ${f.name}`);
10886
10899
  continue;
10887
10900
  }
10888
- fs13.unlinkSync(f.path);
10901
+ fs14.unlinkSync(f.path);
10889
10902
  console.log(`[session] Purged old archive: ${f.name}`);
10890
10903
  }
10891
10904
  if (toDelete.length > 0) {
@@ -10934,29 +10947,29 @@ var init_session_manager = __esm({
10934
10947
  /** 列出 session 的所有文件(当前 + 归档),按修改时间排序 */
10935
10948
  findAllSessionFiles(sessionId) {
10936
10949
  const results = [];
10937
- const mainFile = path14.join(this.sessionsDir, `${sessionId}.jsonl`);
10938
- if (fs13.existsSync(mainFile)) {
10950
+ const mainFile = path15.join(this.sessionsDir, `${sessionId}.jsonl`);
10951
+ if (fs14.existsSync(mainFile)) {
10939
10952
  results.push(mainFile);
10940
10953
  }
10941
- if (fs13.existsSync(this.sessionsDir)) {
10942
- const compactionFiles = fs13.readdirSync(this.sessionsDir).filter((f) => f.startsWith(`${sessionId}.jsonl.compaction.`)).map((f) => ({
10954
+ if (fs14.existsSync(this.sessionsDir)) {
10955
+ const compactionFiles = fs14.readdirSync(this.sessionsDir).filter((f) => f.startsWith(`${sessionId}.jsonl.compaction.`)).map((f) => ({
10943
10956
  name: f,
10944
- path: path14.join(this.sessionsDir, f),
10945
- mtime: fs13.statSync(path14.join(this.sessionsDir, f)).mtimeMs
10957
+ path: path15.join(this.sessionsDir, f),
10958
+ mtime: fs14.statSync(path15.join(this.sessionsDir, f)).mtimeMs
10946
10959
  })).sort((a, b) => b.mtime - a.mtime);
10947
10960
  if (compactionFiles.length > 0) {
10948
10961
  results.push(compactionFiles[0].path);
10949
10962
  }
10950
10963
  }
10951
10964
  results.sort((a, b) => {
10952
- const ta = fs13.statSync(a).mtimeMs;
10953
- const tb = fs13.statSync(b).mtimeMs;
10965
+ const ta = fs14.statSync(a).mtimeMs;
10966
+ const tb = fs14.statSync(b).mtimeMs;
10954
10967
  return ta - tb;
10955
10968
  });
10956
10969
  return results;
10957
10970
  }
10958
10971
  async findSessionFiles(sessionId) {
10959
- if (!fs13.existsSync(this.sessionsDir)) {
10972
+ if (!fs14.existsSync(this.sessionsDir)) {
10960
10973
  console.log(`[session:find] SESSIONS_DIR not found: ${this.sessionsDir}`);
10961
10974
  return [];
10962
10975
  }
@@ -10968,15 +10981,15 @@ var init_session_manager = __esm({
10968
10981
  return mappedFiles;
10969
10982
  }
10970
10983
  const indexedEntry = this.index.get(mappedId);
10971
- if (indexedEntry && fs13.existsSync(indexedEntry.file)) {
10972
- const fileUuid = path14.basename(indexedEntry.file, ".jsonl");
10984
+ if (indexedEntry && fs14.existsSync(indexedEntry.file)) {
10985
+ const fileUuid = path15.basename(indexedEntry.file, ".jsonl");
10973
10986
  return this.findAllSessionFiles(fileUuid);
10974
10987
  }
10975
10988
  }
10976
10989
  const allFiles = this.findAllSessionFiles(sessionId);
10977
10990
  if (allFiles.length > 0) {
10978
10991
  const labels = allFiles.map((f) => {
10979
- const base = path14.basename(f);
10992
+ const base = path15.basename(f);
10980
10993
  return base.endsWith(".jsonl") ? base : `${base} (archived)`;
10981
10994
  });
10982
10995
  console.log(`[session:find] Found ${allFiles.length} file(s) for ${sessionId}: ${labels.join(", ")}`);
@@ -10984,9 +10997,9 @@ var init_session_manager = __esm({
10984
10997
  }
10985
10998
  const indexed = this.index.get(sessionId);
10986
10999
  if (indexed) {
10987
- console.log(`[session:find] Index hit: ${sessionId} \u2192 ${indexed.file} (exists=${fs13.existsSync(indexed.file)})`);
10988
- if (fs13.existsSync(indexed.file)) {
10989
- return this.findAllSessionFiles(path14.basename(indexed.file, ".jsonl"));
11000
+ console.log(`[session:find] Index hit: ${sessionId} \u2192 ${indexed.file} (exists=${fs14.existsSync(indexed.file)})`);
11001
+ if (fs14.existsSync(indexed.file)) {
11002
+ return this.findAllSessionFiles(path15.basename(indexed.file, ".jsonl"));
10990
11003
  }
10991
11004
  } else {
10992
11005
  console.log(`[session:find] Index miss: ${sessionId} (index has ${this.index.size} entries)`);
@@ -11015,8 +11028,8 @@ var init_session_manager = __esm({
11015
11028
  return [];
11016
11029
  }
11017
11030
  files.sort((a, b) => {
11018
- const ta = fs13.statSync(a).mtimeMs;
11019
- const tb = fs13.statSync(b).mtimeMs;
11031
+ const ta = fs14.statSync(a).mtimeMs;
11032
+ const tb = fs14.statSync(b).mtimeMs;
11020
11033
  return ta - tb;
11021
11034
  });
11022
11035
  const latestFile = files[files.length - 1];
@@ -11024,7 +11037,7 @@ var init_session_manager = __esm({
11024
11037
  if (!currentEntry || currentEntry.file !== latestFile) {
11025
11038
  this.index.set(sessionId, { file: latestFile, updatedAt: Date.now() });
11026
11039
  this.saveIndex();
11027
- console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${path14.basename(latestFile)}`);
11040
+ console.log(`[session:restore] Synced index: ${sessionId} \u2192 ${path15.basename(latestFile)}`);
11028
11041
  }
11029
11042
  const allMessages = [];
11030
11043
  for (const file2 of files) {
@@ -11063,7 +11076,7 @@ var init_session_manager = __esm({
11063
11076
  if (isAttachmentMessage(m) && m.attachment.type === "relevant_memories") {
11064
11077
  for (const mem of m.attachment.memories) {
11065
11078
  rawCount++;
11066
- restoredPaths.add(path14.resolve(mem.path));
11079
+ restoredPaths.add(path15.resolve(mem.path));
11067
11080
  }
11068
11081
  }
11069
11082
  }
@@ -11095,15 +11108,15 @@ var init_session_manager = __esm({
11095
11108
  */
11096
11109
  rotateMainSession() {
11097
11110
  const entry = this.index.get("main");
11098
- if (!entry || !fs13.existsSync(entry.file)) return;
11099
- const oldFileId = path14.basename(entry.file, ".jsonl");
11100
- const stat4 = fs13.statSync(entry.file);
11111
+ if (!entry || !fs14.existsSync(entry.file)) return;
11112
+ const oldFileId = path15.basename(entry.file, ".jsonl");
11113
+ const stat4 = fs14.statSync(entry.file);
11101
11114
  if (stat4.size < 1024) return;
11102
11115
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
11103
11116
  const archivedPath = `${entry.file}.archived.${ts}`;
11104
- fs13.renameSync(entry.file, archivedPath);
11117
+ fs14.renameSync(entry.file, archivedPath);
11105
11118
  const sizeMB = (stat4.size / 1024 / 1024).toFixed(1);
11106
- console.log(`[session] Archived: ${path14.basename(entry.file)} \u2192 ${path14.basename(archivedPath)} (${sizeMB}MB)`);
11119
+ console.log(`[session] Archived: ${path15.basename(entry.file)} \u2192 ${path15.basename(archivedPath)} (${sizeMB}MB)`);
11107
11120
  const newWriter = new SessionWriter(this.sessionsDir);
11108
11121
  newWriter.open(this.config.workspace, "main");
11109
11122
  newWriter.writeModelChange(this.config.providerId, this.config.model);
@@ -11112,7 +11125,7 @@ var init_session_manager = __esm({
11112
11125
  this.index.set("main", { file: newPath, updatedAt: Date.now() });
11113
11126
  this.saveIndex();
11114
11127
  this.purgeOldArchives(oldFileId, 3);
11115
- console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${path14.basename(newPath)}`);
11128
+ console.log(`[session] Rotated main: ${oldFileId}.jsonl \u2192 ${path15.basename(newPath)}`);
11116
11129
  }
11117
11130
  // === 迁移 ===
11118
11131
  /** 迁移旧索引:session-index.json 里有 "discord:xxx" 格式的 key 时,生成 UUID 替换 */
@@ -11177,15 +11190,15 @@ var init_session_manager = __esm({
11177
11190
  });
11178
11191
 
11179
11192
  // src/tools/read.ts
11180
- import * as fs14 from "node:fs";
11181
- import * as path15 from "node:path";
11193
+ import * as fs15 from "node:fs";
11194
+ import * as path16 from "node:path";
11182
11195
  function isBlockedDevicePath(filePath) {
11183
11196
  if (BLOCKED_DEVICE_PATHS.has(filePath)) return true;
11184
11197
  if (filePath.startsWith("/proc/") && (filePath.endsWith("/fd/0") || filePath.endsWith("/fd/1") || filePath.endsWith("/fd/2"))) return true;
11185
11198
  return false;
11186
11199
  }
11187
11200
  function checkReadLoop(filePath, offset, limit) {
11188
- const stat4 = fs14.statSync(filePath);
11201
+ const stat4 = fs15.statSync(filePath);
11189
11202
  const mtimeMs = stat4.mtimeMs;
11190
11203
  const prev = readHistory.get(filePath);
11191
11204
  if (prev && prev.offset === offset && prev.limit === limit && prev.mtimeMs === mtimeMs) {
@@ -11199,19 +11212,19 @@ function checkReadLoop(filePath, offset, limit) {
11199
11212
  return null;
11200
11213
  }
11201
11214
  function readFileContent(filePath) {
11202
- const fd = fs14.openSync(filePath, "r");
11215
+ const fd = fs15.openSync(filePath, "r");
11203
11216
  const bom = Buffer.alloc(2);
11204
- fs14.readSync(fd, bom, 0, 2, 0);
11205
- fs14.closeSync(fd);
11217
+ fs15.readSync(fd, bom, 0, 2, 0);
11218
+ fs15.closeSync(fd);
11206
11219
  let encoding = "utf8";
11207
11220
  if (bom[0] === 255 && bom[1] === 254) {
11208
11221
  encoding = "utf16le";
11209
11222
  }
11210
- const stat4 = fs14.statSync(filePath);
11223
+ const stat4 = fs15.statSync(filePath);
11211
11224
  if (stat4.size > MAX_FILE_SIZE) {
11212
11225
  throw new Error(`\u6587\u4EF6\u592A\u5927 (${(stat4.size / 1024).toFixed(1)}KB)\uFF0C\u8D85\u8FC7 ${MAX_FILE_SIZE / 1024}KB \u9650\u5236\u3002\u8BF7\u4F7F\u7528 offset + limit \u5206\u6BB5\u8BFB\u53D6\u3002`);
11213
11226
  }
11214
- const raw = fs14.readFileSync(filePath, encoding);
11227
+ const raw = fs15.readFileSync(filePath, encoding);
11215
11228
  const content = raw.toString().replaceAll("\r\n", "\n");
11216
11229
  return { content, encoding };
11217
11230
  }
@@ -11353,11 +11366,11 @@ Usage:
11353
11366
  } catch (e) {
11354
11367
  return { content: e.message, isError: true };
11355
11368
  }
11356
- if (!fs14.existsSync(filePath)) {
11369
+ if (!fs15.existsSync(filePath)) {
11357
11370
  return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
11358
11371
  }
11359
- const stat4 = fs14.statSync(filePath);
11360
- const baseName = path15.basename(filePath).toUpperCase();
11372
+ const stat4 = fs15.statSync(filePath);
11373
+ const baseName = path16.basename(filePath).toUpperCase();
11361
11374
  if (BLOCKED_BASENAMES.has(baseName)) {
11362
11375
  return { content: `\u8BBE\u5907\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6: ${filePath}`, isError: true };
11363
11376
  }
@@ -11365,11 +11378,11 @@ Usage:
11365
11378
  return { content: `\u8BBE\u5907\u6587\u4EF6\u4F1A\u963B\u585E\u6216\u4EA7\u751F\u65E0\u9650\u8F93\u51FA: ${filePath}`, isError: true };
11366
11379
  }
11367
11380
  if (stat4.isDirectory()) {
11368
- const entries2 = fs14.readdirSync(filePath);
11381
+ const entries2 = fs15.readdirSync(filePath);
11369
11382
  const items = entries2.map((e) => {
11370
- const full = path15.join(filePath, e);
11383
+ const full = path16.join(filePath, e);
11371
11384
  try {
11372
- const s = fs14.statSync(full);
11385
+ const s = fs15.statSync(full);
11373
11386
  return s.isDirectory() ? `${e}/` : e;
11374
11387
  } catch {
11375
11388
  return e;
@@ -11378,7 +11391,7 @@ Usage:
11378
11391
  return { content: `\u76EE\u5F55 (${entries2.length} \u9879):
11379
11392
  ${items.join("\n")}` };
11380
11393
  }
11381
- const ext = path15.extname(filePath).toLowerCase();
11394
+ const ext = path16.extname(filePath).toLowerCase();
11382
11395
  if (BINARY_EXTENSIONS.has(ext)) {
11383
11396
  return { content: `\u4E8C\u8FDB\u5236\u6587\u4EF6\u4E0D\u652F\u6301\u8BFB\u53D6 (${ext}): ${filePath}`, isError: true };
11384
11397
  }
@@ -11425,22 +11438,22 @@ ${result}` : result };
11425
11438
  });
11426
11439
 
11427
11440
  // src/tools/write.ts
11428
- import * as fs15 from "node:fs";
11429
- import * as path16 from "node:path";
11441
+ import * as fs16 from "node:fs";
11442
+ import * as path17 from "node:path";
11430
11443
  function isBlockedPath(filePath) {
11431
11444
  return BLOCKED_PATTERNS.some((p) => p.test(filePath));
11432
11445
  }
11433
11446
  function atomicWrite(filePath, content) {
11434
11447
  const tmpPath = filePath + ".tmp." + Date.now() + ".write";
11435
- fs15.writeFileSync(tmpPath, content, "utf-8");
11448
+ fs16.writeFileSync(tmpPath, content, "utf-8");
11436
11449
  try {
11437
- fs15.renameSync(tmpPath, filePath);
11450
+ fs16.renameSync(tmpPath, filePath);
11438
11451
  } catch (e) {
11439
11452
  try {
11440
- fs15.unlinkSync(tmpPath);
11453
+ fs16.unlinkSync(tmpPath);
11441
11454
  } catch {
11442
11455
  }
11443
- fs15.writeFileSync(filePath, content, "utf-8");
11456
+ fs16.writeFileSync(filePath, content, "utf-8");
11444
11457
  }
11445
11458
  }
11446
11459
  function simpleDiff(oldContent, newContent) {
@@ -11534,15 +11547,15 @@ Usage:
11534
11547
  }
11535
11548
  const rawContent = args.content;
11536
11549
  const content = rawContent.replaceAll("\r\n", "\n");
11537
- if (fs15.existsSync(filePath) && fs15.statSync(filePath).isDirectory()) {
11550
+ if (fs16.existsSync(filePath) && fs16.statSync(filePath).isDirectory()) {
11538
11551
  return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
11539
11552
  }
11540
11553
  let oldContent = null;
11541
11554
  let isCreate = true;
11542
- if (fs15.existsSync(filePath)) {
11555
+ if (fs16.existsSync(filePath)) {
11543
11556
  isCreate = false;
11544
11557
  try {
11545
- oldContent = fs15.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
11558
+ oldContent = fs16.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
11546
11559
  } catch {
11547
11560
  isCreate = true;
11548
11561
  }
@@ -11558,10 +11571,10 @@ Usage:
11558
11571
  isError: true
11559
11572
  };
11560
11573
  }
11561
- const currentStat = fs15.statSync(filePath);
11574
+ const currentStat = fs16.statSync(filePath);
11562
11575
  const lastWriteTime = Math.floor(currentStat.mtimeMs);
11563
11576
  if (lastWriteTime > readState.timestamp) {
11564
- const currentContent = fs15.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
11577
+ const currentContent = fs16.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n");
11565
11578
  if (currentContent !== oldContent) {
11566
11579
  return {
11567
11580
  content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u5199\u5165: ${filePath}`,
@@ -11570,9 +11583,9 @@ Usage:
11570
11583
  }
11571
11584
  }
11572
11585
  }
11573
- const dir = path16.dirname(filePath);
11586
+ const dir = path17.dirname(filePath);
11574
11587
  try {
11575
- fs15.mkdirSync(dir, { recursive: true });
11588
+ fs16.mkdirSync(dir, { recursive: true });
11576
11589
  } catch (e) {
11577
11590
  return { content: `\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55: ${dir} \u2014 ${e.message}`, isError: true };
11578
11591
  }
@@ -11581,11 +11594,11 @@ Usage:
11581
11594
  } catch (e) {
11582
11595
  return { content: `\u5199\u5165\u5931\u8D25: ${e.message}`, isError: true };
11583
11596
  }
11584
- readFileState.set(filePath, { timestamp: fs15.statSync(filePath).mtimeMs });
11597
+ readFileState.set(filePath, { timestamp: fs16.statSync(filePath).mtimeMs });
11585
11598
  const action = isCreate ? "\u521B\u5EFA" : "\u66F4\u65B0";
11586
11599
  const lines = content.split("\n").length;
11587
11600
  const chars = content.length;
11588
- const stat4 = fs15.statSync(filePath);
11601
+ const stat4 = fs16.statSync(filePath);
11589
11602
  let diff = "";
11590
11603
  if (!isCreate && oldContent !== null) {
11591
11604
  diff = `
@@ -11604,8 +11617,8 @@ ${simpleDiff(oldContent, content)}`;
11604
11617
  });
11605
11618
 
11606
11619
  // src/tools/edit.ts
11607
- import * as fs16 from "node:fs";
11608
- import * as path17 from "node:path";
11620
+ import * as fs17 from "node:fs";
11621
+ import * as path18 from "node:path";
11609
11622
  function normalizeQuotes(str) {
11610
11623
  return str.replaceAll(LEFT_SINGLE_CURLY, "'").replaceAll(RIGHT_SINGLE_CURLY, "'").replaceAll(LEFT_DOUBLE_CURLY, '"').replaceAll(RIGHT_DOUBLE_CURLY, '"');
11611
11624
  }
@@ -11758,7 +11771,7 @@ Usage:
11758
11771
  }
11759
11772
  let fileContent = null;
11760
11773
  try {
11761
- const stat4 = fs16.statSync(filePath);
11774
+ const stat4 = fs17.statSync(filePath);
11762
11775
  if (stat4.isDirectory()) {
11763
11776
  return { content: `\u8DEF\u5F84\u662F\u76EE\u5F55\u4E0D\u662F\u6587\u4EF6: ${filePath}`, isError: true };
11764
11777
  }
@@ -11768,21 +11781,21 @@ Usage:
11768
11781
  } catch (e) {
11769
11782
  if (e.code === "ENOENT") {
11770
11783
  if (oldString === "") {
11771
- const dir = path17.dirname(filePath);
11772
- fs16.mkdirSync(dir, { recursive: true });
11773
- fs16.writeFileSync(filePath, newString, "utf-8");
11774
- readFileState.set(filePath, { timestamp: fs16.statSync(filePath).mtimeMs });
11784
+ const dir = path18.dirname(filePath);
11785
+ fs17.mkdirSync(dir, { recursive: true });
11786
+ fs17.writeFileSync(filePath, newString, "utf-8");
11787
+ readFileState.set(filePath, { timestamp: fs17.statSync(filePath).mtimeMs });
11775
11788
  return { content: `\u521B\u5EFA\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
11776
11789
  }
11777
11790
  return { content: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, isError: true };
11778
11791
  }
11779
11792
  throw e;
11780
11793
  }
11781
- const rawContent = fs16.readFileSync(filePath, "utf-8");
11794
+ const rawContent = fs17.readFileSync(filePath, "utf-8");
11782
11795
  fileContent = rawContent.replaceAll("\r\n", "\n");
11783
11796
  if (oldString === "" && fileContent.trim() === "") {
11784
- fs16.writeFileSync(filePath, newString, "utf-8");
11785
- readFileState.set(filePath, { timestamp: fs16.statSync(filePath).mtimeMs });
11797
+ fs17.writeFileSync(filePath, newString, "utf-8");
11798
+ readFileState.set(filePath, { timestamp: fs17.statSync(filePath).mtimeMs });
11786
11799
  return { content: `\u5199\u5165\u7A7A\u6587\u4EF6: ${filePath} (${newString.split("\n").length} \u884C)` };
11787
11800
  }
11788
11801
  const readState = readFileState.get(filePath);
@@ -11792,11 +11805,11 @@ Usage:
11792
11805
  isError: true
11793
11806
  };
11794
11807
  }
11795
- const currentStat = fs16.statSync(filePath);
11808
+ const currentStat = fs17.statSync(filePath);
11796
11809
  const lastWriteTime = Math.floor(currentStat.mtimeMs);
11797
11810
  if (lastWriteTime > readState.timestamp) {
11798
11811
  if (fileContent !== rawContent.replaceAll("\r\n", "\n")) {
11799
- if (fileContent !== fs16.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n")) {
11812
+ if (fileContent !== fs17.readFileSync(filePath, "utf-8").replaceAll("\r\n", "\n")) {
11800
11813
  return {
11801
11814
  content: `\u6587\u4EF6\u5728\u8BFB\u53D6\u540E\u88AB\u4FEE\u6539\u3002\u8BF7\u5148\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\u518D\u7F16\u8F91: ${filePath}`,
11802
11815
  isError: true
@@ -11828,8 +11841,8 @@ ${preview}
11828
11841
  const actualNewString = preserveQuoteStyle(oldString, actualOldString, newString);
11829
11842
  const diffView = generateEditDiff(fileContent, actualOldString, actualNewString);
11830
11843
  const newContent = applyEditToFile(fileContent, actualOldString, actualNewString, replaceAll);
11831
- fs16.writeFileSync(filePath, newContent, "utf-8");
11832
- readFileState.set(filePath, { timestamp: fs16.statSync(filePath).mtimeMs });
11844
+ fs17.writeFileSync(filePath, newContent, "utf-8");
11845
+ readFileState.set(filePath, { timestamp: fs17.statSync(filePath).mtimeMs });
11833
11846
  const strategy = actualOldString === oldString ? "\u7CBE\u786E\u5339\u914D" : "\u5F15\u53F7\u89C4\u8303\u5316\u5339\u914D";
11834
11847
  const count = replaceAll ? matchCount : 1;
11835
11848
  const diff = `${oldString.length}\u2192${newString.length}\u5B57\u7B26`;
@@ -11846,8 +11859,8 @@ ${diffView}`
11846
11859
  });
11847
11860
 
11848
11861
  // src/tools/glob.ts
11849
- import * as fs17 from "node:fs";
11850
- import * as path18 from "node:path";
11862
+ import * as fs18 from "node:fs";
11863
+ import * as path19 from "node:path";
11851
11864
  function globMatch(pattern, filename) {
11852
11865
  const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/\{\{GLOBSTAR\}\}/g, ".*");
11853
11866
  try {
@@ -11867,18 +11880,18 @@ function findFiles(dir, pattern, limit, baseDir) {
11867
11880
  }
11868
11881
  let entries2;
11869
11882
  try {
11870
- entries2 = fs17.readdirSync(currentDir, { withFileTypes: true });
11883
+ entries2 = fs18.readdirSync(currentDir, { withFileTypes: true });
11871
11884
  } catch {
11872
11885
  return;
11873
11886
  }
11874
11887
  for (const entry of entries2) {
11875
11888
  if (truncated) return;
11876
- const fullPath = path18.join(currentDir, entry.name);
11889
+ const fullPath = path19.join(currentDir, entry.name);
11877
11890
  if (entry.isDirectory()) {
11878
11891
  if (VCS_DIRS.has(entry.name)) continue;
11879
11892
  walk(fullPath);
11880
11893
  } else if (entry.isFile()) {
11881
- const relativePath = path18.relative(baseDir, fullPath).replace(/\\/g, "/");
11894
+ const relativePath = path19.relative(baseDir, fullPath).replace(/\\/g, "/");
11882
11895
  const patternsToTry = [pattern];
11883
11896
  if (pattern.startsWith("**/")) {
11884
11897
  patternsToTry.push(pattern.slice(3));
@@ -11888,7 +11901,7 @@ function findFiles(dir, pattern, limit, baseDir) {
11888
11901
  );
11889
11902
  if (matched) {
11890
11903
  try {
11891
- const stat4 = fs17.statSync(fullPath);
11904
+ const stat4 = fs18.statSync(fullPath);
11892
11905
  results.push({ path: fullPath, mtimeMs: stat4.mtimeMs });
11893
11906
  } catch {
11894
11907
  }
@@ -11905,7 +11918,7 @@ function findFiles(dir, pattern, limit, baseDir) {
11905
11918
  };
11906
11919
  }
11907
11920
  function toRelativePath(absolutePath, cwd) {
11908
- if (absolutePath.startsWith(cwd + path18.sep)) {
11921
+ if (absolutePath.startsWith(cwd + path19.sep)) {
11909
11922
  return absolutePath.slice(cwd.length + 1);
11910
11923
  }
11911
11924
  return absolutePath;
@@ -11938,10 +11951,10 @@ var init_glob = __esm({
11938
11951
  const searchPath = args.path ? resolvePath(args.path, ctx.workspace) : ctx.workspace;
11939
11952
  const pattern = args.pattern;
11940
11953
  const limit = args.limit || DEFAULT_LIMIT;
11941
- if (!fs17.existsSync(searchPath)) {
11954
+ if (!fs18.existsSync(searchPath)) {
11942
11955
  return { content: `\u76EE\u5F55\u4E0D\u5B58\u5728: ${searchPath}`, isError: true };
11943
11956
  }
11944
- if (!fs17.statSync(searchPath).isDirectory()) {
11957
+ if (!fs18.statSync(searchPath).isDirectory()) {
11945
11958
  return { content: `\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${searchPath}`, isError: true };
11946
11959
  }
11947
11960
  const start = Date.now();
@@ -11965,7 +11978,7 @@ ${filenames.join("\n")}${truncatedNote}`
11965
11978
 
11966
11979
  // src/tools/grep.ts
11967
11980
  import { execFile } from "node:child_process";
11968
- import * as path19 from "node:path";
11981
+ import * as path20 from "node:path";
11969
11982
  function ripGrep(args, searchPath, signal) {
11970
11983
  return new Promise((resolve12) => {
11971
11984
  const fullArgs = [...args, searchPath];
@@ -11997,7 +12010,7 @@ function applyHeadLimit(items, limit, offset = 0) {
11997
12010
  };
11998
12011
  }
11999
12012
  function toRelativePath2(absolutePath, cwd) {
12000
- if (absolutePath.startsWith(cwd + path19.sep)) {
12013
+ if (absolutePath.startsWith(cwd + path20.sep)) {
12001
12014
  return absolutePath.slice(cwd.length + 1);
12002
12015
  }
12003
12016
  if (absolutePath.startsWith(cwd)) {
@@ -13247,7 +13260,7 @@ async function acquireLock(inboxPath) {
13247
13260
  for (let i = 0; i < LOCK_RETRIES; i++) {
13248
13261
  if (await isLockStale(lockPath2)) {
13249
13262
  try {
13250
- await import("node:fs/promises").then((fs43) => fs43.rm(lockPath2, { force: true }));
13263
+ await import("node:fs/promises").then((fs44) => fs44.rm(lockPath2, { force: true }));
13251
13264
  } catch {
13252
13265
  }
13253
13266
  }
@@ -13255,7 +13268,7 @@ async function acquireLock(inboxPath) {
13255
13268
  await writeFile2(lockPath2, `${process.pid}-${Date.now()}`, { encoding: "utf-8", flag: "wx" });
13256
13269
  return async () => {
13257
13270
  try {
13258
- await import("node:fs/promises").then((fs43) => fs43.rm(lockPath2, { force: true }));
13271
+ await import("node:fs/promises").then((fs44) => fs44.rm(lockPath2, { force: true }));
13259
13272
  } catch {
13260
13273
  }
13261
13274
  };
@@ -14498,12 +14511,12 @@ Examples:
14498
14511
  });
14499
14512
 
14500
14513
  // src/tools/msg-husband.ts
14501
- import fs18 from "node:fs";
14502
- import path20 from "node:path";
14514
+ import fs19 from "node:fs";
14515
+ import path21 from "node:path";
14503
14516
  function getHusbandFeishuId(workspace) {
14504
- const contactsPath = path20.join(workspace, "prompts", "contacts.md");
14517
+ const contactsPath = path21.join(workspace, "prompts", "contacts.md");
14505
14518
  try {
14506
- const text = fs18.readFileSync(contactsPath, "utf-8");
14519
+ const text = fs19.readFileSync(contactsPath, "utf-8");
14507
14520
  const m = text.match(/\|\s*翀哥\s*\|\s*(ou_[a-f0-9]+)\s*\|/);
14508
14521
  return m ? m[1] : null;
14509
14522
  } catch {
@@ -14656,8 +14669,8 @@ Examples:
14656
14669
  if (!to && !resolvedChannelId) {
14657
14670
  return { content: "to \u548C channel_id \u4E0D\u80FD\u540C\u65F6\u4E3A\u7A7A\uFF0C\u4E14\u6CA1\u6709\u53EF\u7528\u7684\u6765\u6E90\u9891\u9053", isError: true };
14658
14671
  }
14659
- const fs43 = await import("node:fs");
14660
- if (!fs43.existsSync(filePath)) {
14672
+ const fs44 = await import("node:fs");
14673
+ if (!fs44.existsSync(filePath)) {
14661
14674
  return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6\u4E0D\u5B58\u5728 ${filePath}`, isError: true };
14662
14675
  }
14663
14676
  const toIds = to ? to.split(",").map((s) => s.trim()).filter(Boolean) : [];
@@ -14685,7 +14698,7 @@ Examples:
14685
14698
  md: "text/markdown"
14686
14699
  };
14687
14700
  const mimeType = mimeTypeMap[ext] || "application/octet-stream";
14688
- const stat4 = fs43.statSync(filePath);
14701
+ const stat4 = fs44.statSync(filePath);
14689
14702
  const sizeMB = stat4.size / 1024 / 1024;
14690
14703
  if (sizeMB > 25) {
14691
14704
  return { content: `\u53D1\u9001\u5931\u8D25: \u6587\u4EF6 ${sizeMB.toFixed(1)}MB \u8D85\u8FC7 Discord 25MB \u9650\u5236`, isError: true };
@@ -14714,8 +14727,8 @@ Examples:
14714
14727
  });
14715
14728
 
14716
14729
  // src/tools/my-eyes.ts
14717
- import * as fs19 from "node:fs";
14718
- import * as path21 from "node:path";
14730
+ import * as fs20 from "node:fs";
14731
+ import * as path22 from "node:path";
14719
14732
  function extractUsage(data) {
14720
14733
  try {
14721
14734
  const u = data?.usage ?? data?.usageMetadata;
@@ -14730,9 +14743,9 @@ function extractUsage(data) {
14730
14743
  }
14731
14744
  }
14732
14745
  function resolveLatestImage(specifiedPath, mediaDir) {
14733
- if (specifiedPath && fs19.existsSync(specifiedPath)) return specifiedPath;
14734
- if (!fs19.existsSync(mediaDir)) return null;
14735
- const files = fs19.readdirSync(mediaDir).filter((f) => /\.(jpg|jpeg|png|webp|gif|bmp|mp4|mov)$/i.test(f)).map((f) => ({ name: f, p: path21.join(mediaDir, f), mtime: fs19.statSync(path21.join(mediaDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
14746
+ if (specifiedPath && fs20.existsSync(specifiedPath)) return specifiedPath;
14747
+ if (!fs20.existsSync(mediaDir)) return null;
14748
+ const files = fs20.readdirSync(mediaDir).filter((f) => /\.(jpg|jpeg|png|webp|gif|bmp|mp4|mov)$/i.test(f)).map((f) => ({ name: f, p: path22.join(mediaDir, f), mtime: fs20.statSync(path22.join(mediaDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
14736
14749
  return files[0]?.p || null;
14737
14750
  }
14738
14751
  var MIME_MAP, VIDEO_EXT, VIDEO_MAX_BYTES;
@@ -14780,15 +14793,15 @@ var init_my_eyes = __esm({
14780
14793
  if (!provider?.streamChat) {
14781
14794
  return { content: "Error: provider \u4E0D\u53EF\u7528\u3002", isError: true };
14782
14795
  }
14783
- const mediaDir = path21.join(ctx.stateDir, "media", "inbound");
14796
+ const mediaDir = path22.join(ctx.stateDir, "media", "inbound");
14784
14797
  const imagePath = resolveLatestImage(args.image_path, mediaDir);
14785
14798
  if (!imagePath) {
14786
14799
  return { content: "Error: no image found. Provide image_path or ensure media/inbound has images.", isError: true };
14787
14800
  }
14788
14801
  const rawPrompt = args.prompt?.trim() || "\u63CF\u8FF0\u8FD9\u5F20\u56FE\u7247\u7684\u5185\u5BB9";
14789
- const ext = path21.extname(imagePath).toLowerCase();
14802
+ const ext = path22.extname(imagePath).toLowerCase();
14790
14803
  if (VIDEO_EXT.test(imagePath)) {
14791
- const stat4 = fs19.statSync(imagePath);
14804
+ const stat4 = fs20.statSync(imagePath);
14792
14805
  if (stat4.size > VIDEO_MAX_BYTES) {
14793
14806
  return { content: `Error: video too large (${(stat4.size / 1e6).toFixed(1)}MB > ${(VIDEO_MAX_BYTES / 1e6).toFixed(0)}MB). Compress or trim first.`, isError: true };
14794
14807
  }
@@ -14802,7 +14815,7 @@ var init_my_eyes = __esm({
14802
14815
  }
14803
14816
  const explicit = liveConfig.get("tools.my_eyes.videoBaseUrl");
14804
14817
  const baseUrl = explicit || vProviderCfg.baseUrl.replace(/\/anthropic\/?$/, "/v1").replace(/\/$/, "");
14805
- const vidB64 = fs19.readFileSync(imagePath).toString("base64");
14818
+ const vidB64 = fs20.readFileSync(imagePath).toString("base64");
14806
14819
  try {
14807
14820
  const res = await fetch(`${baseUrl}/chat/completions`, {
14808
14821
  method: "POST",
@@ -14833,7 +14846,7 @@ var init_my_eyes = __esm({
14833
14846
  }
14834
14847
  }
14835
14848
  const mime = MIME_MAP[ext] || "jpeg";
14836
- const imgB64 = fs19.readFileSync(imagePath).toString("base64");
14849
+ const imgB64 = fs20.readFileSync(imagePath).toString("base64");
14837
14850
  const userMsg = {
14838
14851
  role: "user",
14839
14852
  content: [
@@ -14868,7 +14881,7 @@ var init_my_eyes = __esm({
14868
14881
  });
14869
14882
 
14870
14883
  // src/tools/opus-encoder.ts
14871
- import * as fs20 from "node:fs";
14884
+ import * as fs21 from "node:fs";
14872
14885
  function oggCrc32(buf) {
14873
14886
  let crc = 0;
14874
14887
  for (let i = 0; i < buf.length; i++) {
@@ -14928,7 +14941,7 @@ async function wavToOggOpusNative(wavPath) {
14928
14941
  const mod = await import("@discordjs/opus");
14929
14942
  const OpusEncoder = mod.OpusEncoder ?? mod.default?.OpusEncoder;
14930
14943
  if (!OpusEncoder) throw new Error("@discordjs/opus export shape unexpected");
14931
- const wav = parseWav(fs20.readFileSync(wavPath));
14944
+ const wav = parseWav(fs21.readFileSync(wavPath));
14932
14945
  if (wav.channels !== 1) throw new Error(`unsupported ${wav.channels}ch (need mono)`);
14933
14946
  if (!NATIVE_RATES.includes(wav.sampleRate)) throw new Error(`unsupported rate ${wav.sampleRate}`);
14934
14947
  if (wav.pcm.length === 0) throw new Error("empty pcm data");
@@ -14964,7 +14977,7 @@ async function wavToOggOpusNative(wavPath) {
14964
14977
  }
14965
14978
  ogg.page(cur, pageGranule, false, true);
14966
14979
  const oggPath = wavPath.replace(/\.wav$/, ".ogg");
14967
- fs20.writeFileSync(oggPath, ogg.finish());
14980
+ fs21.writeFileSync(oggPath, ogg.finish());
14968
14981
  return oggPath;
14969
14982
  }
14970
14983
  var FRAME_MS, PRESKIP_48K, OPUS_RATE, NATIVE_RATES, BITRATE, CRC_TABLE, OggWriter;
@@ -15072,8 +15085,8 @@ var init_voice_chat_tts_daemon = __esm({
15072
15085
  import { execFile as execFile2 } from "node:child_process";
15073
15086
  import { createInterface as createInterface2 } from "node:readline";
15074
15087
  import { promisify } from "node:util";
15075
- import * as fs21 from "node:fs";
15076
- import * as path22 from "node:path";
15088
+ import * as fs22 from "node:fs";
15089
+ import * as path23 from "node:path";
15077
15090
  import * as os4 from "node:os";
15078
15091
  function wavDurationSec(buf) {
15079
15092
  if (buf.length < 12 || buf.toString("ascii", 0, 4) !== "RIFF" || buf.toString("ascii", 8, 12) !== "WAVE") {
@@ -15128,8 +15141,8 @@ function resolvePython(configuredPath) {
15128
15141
  // LOCALAPPDATA 缺席(非 Windows / 精简环境)时**不加这两个候选**:
15129
15142
  // 拼出来会是相对路径 'Microsoft/WindowsApps/python.exe',那可能撞上 cwd 里的东西。
15130
15143
  ...localAppData ? [
15131
- path22.join(localAppData, "Microsoft", "WindowsApps", "python3.exe"),
15132
- path22.join(localAppData, "Microsoft", "WindowsApps", "python.exe")
15144
+ path23.join(localAppData, "Microsoft", "WindowsApps", "python3.exe"),
15145
+ path23.join(localAppData, "Microsoft", "WindowsApps", "python.exe")
15133
15146
  ] : []
15134
15147
  ];
15135
15148
  for (const c of candidates) {
@@ -15149,8 +15162,8 @@ async function ttsCosyvoice(text, apiKey, model, voice, workspaceId, instruction
15149
15162
  }
15150
15163
  async function ttsCosyvoiceStream(text, cfg, onChunk) {
15151
15164
  const { apiKey, model, voice, workspaceId, instruction } = cfg;
15152
- fs21.mkdirSync(VOICE_DIR, { recursive: true });
15153
- const output = path22.join(VOICE_DIR, `tts_${Date.now()}.wav`);
15165
+ fs22.mkdirSync(VOICE_DIR, { recursive: true });
15166
+ const output = path23.join(VOICE_DIR, `tts_${Date.now()}.wav`);
15154
15167
  const script = `
15155
15168
  import sys, json, base64, threading
15156
15169
  import dashscope
@@ -15235,7 +15248,7 @@ print('EOS')
15235
15248
  header.writeUInt16LE(16, 34);
15236
15249
  header.write("data", 36);
15237
15250
  header.writeUInt32LE(pcm.length, 40);
15238
- fs21.writeFileSync(output, Buffer.concat([header, pcm]));
15251
+ fs22.writeFileSync(output, Buffer.concat([header, pcm]));
15239
15252
  return output;
15240
15253
  }
15241
15254
  async function ttsQwen3Local(text, cfg, onChunk) {
@@ -15287,9 +15300,9 @@ async function ttsQwen3Opus(text, cfg) {
15287
15300
  const ogg = Buffer.from(await res.arrayBuffer());
15288
15301
  if (ogg.length < 20) throw new Error("qwen3-3060 opus: empty output");
15289
15302
  const durationMs = parseInt(res.headers.get("x-duration-ms") || "0", 10);
15290
- fs21.mkdirSync(VOICE_DIR, { recursive: true });
15291
- const oggPath = path22.join(VOICE_DIR, `tts_${Date.now()}.ogg`);
15292
- fs21.writeFileSync(oggPath, ogg);
15303
+ fs22.mkdirSync(VOICE_DIR, { recursive: true });
15304
+ const oggPath = path23.join(VOICE_DIR, `tts_${Date.now()}.ogg`);
15305
+ fs22.writeFileSync(oggPath, ogg);
15293
15306
  return { oggPath, durationMs };
15294
15307
  }
15295
15308
  async function ttsGptsovits(text, c) {
@@ -15301,8 +15314,8 @@ async function ttsGptsovits(text, c) {
15301
15314
  "gptsovits \u672A\u914D\u7F6E\uFF1A\u9700\u8981 tools.my_voice \u91CC\u7684 gptsovitsUrl / gptsovitsRefWav / gptsovitsRefText\u3002\u53C2\u8003\u97F3\u9891\u4E0E\u53C2\u8003\u6587\u672C**\u5FC5\u987B\u9010\u5B57\u5BF9\u5E94**\uFF0C\u5426\u5219\u5408\u6210\u51FA\u6765\u7684\u58F0\u97F3\u4F1A\u5E26\u6742\u97F3\uFF080925 \u8E29\u8FC7\u88C1\u574F ref.wav \u7684\u5751\uFF09\u3002"
15302
15315
  );
15303
15316
  }
15304
- fs21.mkdirSync(VOICE_DIR, { recursive: true });
15305
- const output = path22.join(VOICE_DIR, `tts_${Date.now()}.wav`);
15317
+ fs22.mkdirSync(VOICE_DIR, { recursive: true });
15318
+ const output = path23.join(VOICE_DIR, `tts_${Date.now()}.wav`);
15306
15319
  const params = new URLSearchParams({
15307
15320
  text,
15308
15321
  text_language: "zh",
@@ -15313,12 +15326,12 @@ async function ttsGptsovits(text, c) {
15313
15326
  const res = await fetch(`${url}/?${params}`);
15314
15327
  if (!res.ok) throw new Error(`GPT-SoVITS API ${res.status}`);
15315
15328
  const buf = Buffer.from(await res.arrayBuffer());
15316
- fs21.writeFileSync(output, buf);
15329
+ fs22.writeFileSync(output, buf);
15317
15330
  return output;
15318
15331
  }
15319
15332
  async function ttsEdge(text) {
15320
- fs21.mkdirSync(VOICE_DIR, { recursive: true });
15321
- const output = path22.join(VOICE_DIR, `tts_${Date.now()}.mp3`);
15333
+ fs22.mkdirSync(VOICE_DIR, { recursive: true });
15334
+ const output = path23.join(VOICE_DIR, `tts_${Date.now()}.mp3`);
15322
15335
  const script = `
15323
15336
  import asyncio, edge_tts, sys
15324
15337
  async def main():
@@ -15356,8 +15369,8 @@ async function synthQwen3(text, _sink) {
15356
15369
  const pcmChunks = [];
15357
15370
  await ttsQwen3Local(text, { url: c.url, voice: c.voice, lang: c.lang }, (pcm2) => pcmChunks.push(pcm2));
15358
15371
  const pcm = Buffer.concat(pcmChunks);
15359
- fs21.mkdirSync(VOICE_DIR, { recursive: true });
15360
- const wavPath = path22.join(VOICE_DIR, `tts_${Date.now()}.wav`);
15372
+ fs22.mkdirSync(VOICE_DIR, { recursive: true });
15373
+ const wavPath = path23.join(VOICE_DIR, `tts_${Date.now()}.wav`);
15361
15374
  const header = Buffer.alloc(44);
15362
15375
  header.write("RIFF", 0);
15363
15376
  header.writeUInt32LE(36 + pcm.length, 4);
@@ -15372,7 +15385,7 @@ async function synthQwen3(text, _sink) {
15372
15385
  header.writeUInt16LE(16, 34);
15373
15386
  header.write("data", 36);
15374
15387
  header.writeUInt32LE(pcm.length, 40);
15375
- fs21.writeFileSync(wavPath, Buffer.concat([header, pcm]));
15388
+ fs22.writeFileSync(wavPath, Buffer.concat([header, pcm]));
15376
15389
  return { path: wavPath, format: "wav", unit: unit(text), voice: c.voice };
15377
15390
  }
15378
15391
  }
@@ -15388,7 +15401,7 @@ var init_impl = __esm({
15388
15401
  init_well_formed();
15389
15402
  init_voice_chat_tts_daemon();
15390
15403
  execFileAsync = promisify(execFile2);
15391
- VOICE_DIR = path22.join(os4.tmpdir(), "engine-voice");
15404
+ VOICE_DIR = path23.join(os4.tmpdir(), "engine-voice");
15392
15405
  _pyCache = null;
15393
15406
  EDGE_VOICE = "zh-CN-XiaoxiaoNeural";
15394
15407
  unit = (text) => ({ kind: "chars", amount: [...text].length });
@@ -15402,9 +15415,9 @@ var init_impl = __esm({
15402
15415
  });
15403
15416
 
15404
15417
  // src/tools/tts/relay.ts
15405
- import * as fs22 from "node:fs";
15418
+ import * as fs23 from "node:fs";
15406
15419
  import * as os5 from "node:os";
15407
- import * as path23 from "node:path";
15420
+ import * as path24 from "node:path";
15408
15421
  async function synthRelay(text, cfg) {
15409
15422
  const res = await fetchFn(`${cfg.baseUrl}/audio/speech`, {
15410
15423
  method: "POST",
@@ -15422,9 +15435,9 @@ async function synthRelay(text, cfg) {
15422
15435
  }
15423
15436
  const buf = Buffer.from(await res.arrayBuffer());
15424
15437
  if (buf.length < 20) throw new Error(`relay tts: \u54CD\u5E94\u4F53\u53EA\u6709 ${buf.length} \u5B57\u8282\uFF0C\u4E0D\u662F\u6709\u6548\u97F3\u9891`);
15425
- fs22.mkdirSync(VOICE_DIR2, { recursive: true });
15426
- const out = path23.join(VOICE_DIR2, `tts_relay_${Date.now()}.mp3`);
15427
- fs22.writeFileSync(out, buf);
15438
+ fs23.mkdirSync(VOICE_DIR2, { recursive: true });
15439
+ const out = path24.join(VOICE_DIR2, `tts_relay_${Date.now()}.mp3`);
15440
+ fs23.writeFileSync(out, buf);
15428
15441
  return {
15429
15442
  path: out,
15430
15443
  format: "mp3",
@@ -15437,7 +15450,7 @@ var VOICE_DIR2, fetchFn;
15437
15450
  var init_relay = __esm({
15438
15451
  "src/tools/tts/relay.ts"() {
15439
15452
  "use strict";
15440
- VOICE_DIR2 = path23.join(os5.tmpdir(), "engine-voice");
15453
+ VOICE_DIR2 = path24.join(os5.tmpdir(), "engine-voice");
15441
15454
  fetchFn = fetch;
15442
15455
  }
15443
15456
  });
@@ -15608,13 +15621,13 @@ var init_providers = __esm({
15608
15621
  });
15609
15622
 
15610
15623
  // src/utils/ffmpeg-path.ts
15611
- import * as fs23 from "node:fs";
15624
+ import * as fs24 from "node:fs";
15612
15625
  function resolveFfmpegPath() {
15613
15626
  const env = (process.env.E7_FFMPEG_PATH || "").trim();
15614
- if (env && fs23.existsSync(env)) return env;
15627
+ if (env && fs24.existsSync(env)) return env;
15615
15628
  try {
15616
15629
  const p = __require("@ffmpeg-installer/ffmpeg")?.path;
15617
- if (p && fs23.existsSync(p)) return p;
15630
+ if (p && fs24.existsSync(p)) return p;
15618
15631
  } catch {
15619
15632
  }
15620
15633
  return "ffmpeg";
@@ -15628,8 +15641,8 @@ var init_ffmpeg_path = __esm({
15628
15641
  // src/tools/my-voice.ts
15629
15642
  import { execFile as execFile3 } from "node:child_process";
15630
15643
  import { promisify as promisify2 } from "node:util";
15631
- import * as fs24 from "node:fs";
15632
- import * as path24 from "node:path";
15644
+ import * as fs25 from "node:fs";
15645
+ import * as path25 from "node:path";
15633
15646
  async function toWav24kWithDuration(audioPath) {
15634
15647
  let wavPath = audioPath;
15635
15648
  if (!audioPath.endsWith(".wav")) {
@@ -15646,15 +15659,15 @@ async function toWav24kWithDuration(audioPath) {
15646
15659
  "pcm_s16le",
15647
15660
  wavPath
15648
15661
  ], { timeout: 3e4 });
15649
- if (!fs24.existsSync(wavPath) || fs24.statSync(wavPath).size < 44) {
15662
+ if (!fs25.existsSync(wavPath) || fs25.statSync(wavPath).size < 44) {
15650
15663
  throw new Error("toWav24k produced empty output");
15651
15664
  }
15652
15665
  try {
15653
- fs24.unlinkSync(audioPath);
15666
+ fs25.unlinkSync(audioPath);
15654
15667
  } catch {
15655
15668
  }
15656
15669
  }
15657
- const durationSec = wavDurationSec(fs24.readFileSync(wavPath));
15670
+ const durationSec = wavDurationSec(fs25.readFileSync(wavPath));
15658
15671
  return { wavPath, durationSec };
15659
15672
  }
15660
15673
  async function compressWav(wavPath) {
@@ -15672,7 +15685,7 @@ async function compressWav(wavPath) {
15672
15685
  "+faststart",
15673
15686
  m4aPath
15674
15687
  ], { timeout: 3e4 });
15675
- fs24.unlinkSync(wavPath);
15688
+ fs25.unlinkSync(wavPath);
15676
15689
  return m4aPath;
15677
15690
  } catch {
15678
15691
  return wavPath;
@@ -15699,10 +15712,10 @@ async function wavToOggOpus(wavPath) {
15699
15712
  oggPath
15700
15713
  ], { timeout: 3e4 });
15701
15714
  }
15702
- if (!fs24.existsSync(oggPath) || fs24.statSync(oggPath).size < 20) {
15715
+ if (!fs25.existsSync(oggPath) || fs25.statSync(oggPath).size < 20) {
15703
15716
  throw new Error("ogg/opus encode produced empty output");
15704
15717
  }
15705
- fs24.unlinkSync(wavPath);
15718
+ fs25.unlinkSync(wavPath);
15706
15719
  return oggPath;
15707
15720
  }
15708
15721
  async function sendVoiceToMulticaIssue(text, issueId, opts) {
@@ -15717,7 +15730,7 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
15717
15730
  } catch (e) {
15718
15731
  return { content: `\u8BED\u97F3\u751F\u6210\u5931\u8D25\uFF08headless\u2192multaca\uFF09\uFF1A${e.message}\u3002\u8BF7\u7528\u6587\u5B57\u56DE\u590D\u4EE3\u66FF\u3002`, isError: true };
15719
15732
  }
15720
- if (!audioPath || !fs24.existsSync(audioPath)) {
15733
+ if (!audioPath || !fs25.existsSync(audioPath)) {
15721
15734
  return { content: "\u8BED\u97F3\u751F\u6210\u5931\u8D25\uFF08headless\u2192multaca\uFF09\uFF1ATTS \u672A\u4EA7\u51FA\u6587\u4EF6\u3002\u8BF7\u7528\u6587\u5B57\u56DE\u590D\u4EE3\u66FF\u3002", isError: true };
15722
15735
  }
15723
15736
  if (audioPath.endsWith(".wav")) {
@@ -15727,21 +15740,21 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
15727
15740
  console.warn(`[my-voice:multaca] opus encode failed (${e.message}), attaching wav`);
15728
15741
  }
15729
15742
  }
15730
- const ext = path24.extname(audioPath).toLowerCase();
15731
- const sizeKB = fs24.statSync(audioPath).size / 1024;
15743
+ const ext = path25.extname(audioPath).toLowerCase();
15744
+ const sizeKB = fs25.statSync(audioPath).size / 1024;
15732
15745
  const voiceFile = `voice_${Date.now()}${ext}`;
15733
- const cwdCopy = path24.join(process.cwd(), voiceFile);
15746
+ const cwdCopy = path25.join(process.cwd(), voiceFile);
15734
15747
  try {
15735
- fs24.copyFileSync(audioPath, cwdCopy);
15748
+ fs25.copyFileSync(audioPath, cwdCopy);
15736
15749
  } catch (e) {
15737
15750
  try {
15738
- fs24.unlinkSync(audioPath);
15751
+ fs25.unlinkSync(audioPath);
15739
15752
  } catch {
15740
15753
  }
15741
15754
  return { content: `\u8BED\u97F3\u6302\u8F7D\u5931\u8D25\uFF08\u62F7\u8D1D\u5230\u5DE5\u4F5C\u76EE\u5F55\uFF09\uFF1A${e.message}`, isError: true };
15742
15755
  }
15743
15756
  try {
15744
- fs24.unlinkSync(audioPath);
15757
+ fs25.unlinkSync(audioPath);
15745
15758
  } catch {
15746
15759
  }
15747
15760
  const content = opts.caption || `\u{1F399}\uFE0F \u8BED\u97F3\u6D88\u606F\uFF08${text.length} \u5B57\uFF09`;
@@ -15770,13 +15783,13 @@ async function sendVoiceToMulticaIssue(text, issueId, opts) {
15770
15783
  }
15771
15784
  if (!ok) throw new Error(`unexpected CLI output: ${String(stdout).slice(0, 200)}`);
15772
15785
  try {
15773
- fs24.unlinkSync(cwdCopy);
15786
+ fs25.unlinkSync(cwdCopy);
15774
15787
  } catch {
15775
15788
  }
15776
15789
  return { content: `Voice sent to multaca issue ${issueId}! (${actualEngine}, ${sizeKB.toFixed(0)}KB, \u9644\u4EF6\u5DF2\u6302\u5230\u8BC4\u8BBA\u2014\u2014\u5728 multaca \u5BA2\u6237\u7AEF\u64AD\u653E)` };
15777
15790
  } catch (e) {
15778
15791
  try {
15779
- fs24.unlinkSync(cwdCopy);
15792
+ fs25.unlinkSync(cwdCopy);
15780
15793
  } catch {
15781
15794
  }
15782
15795
  return { content: `\u8BED\u97F3\u6302\u5230 multaca issue \u5931\u8D25\uFF1A${e.message}\u3002\u8BF7\u7528\u6587\u5B57\u56DE\u590D\u4EE3\u66FF\u3002`, isError: true };
@@ -15906,10 +15919,10 @@ var init_my_voice = __esm({
15906
15919
  audioPath = await compressWav(audioPath);
15907
15920
  }
15908
15921
  }
15909
- const ext = path24.extname(audioPath).toLowerCase();
15922
+ const ext = path25.extname(audioPath).toLowerCase();
15910
15923
  const mimeMap = { ".mp3": "audio/mpeg", ".wav": "audio/wav", ".m4a": "audio/mp4", ".ogg": "audio/ogg", ".silk": "audio/silk" };
15911
15924
  const mimeType = mimeMap[ext] || "audio/mpeg";
15912
- const sizeKB = fs24.statSync(audioPath).size / 1024;
15925
+ const sizeKB = fs25.statSync(audioPath).size / 1024;
15913
15926
  try {
15914
15927
  await mgr.sendFile(resolvedChannel, target, caption, {
15915
15928
  path: audioPath,
@@ -15918,7 +15931,7 @@ var init_my_voice = __esm({
15918
15931
  ...voiceDurationSec !== void 0 ? { voiceDurationSec } : {}
15919
15932
  });
15920
15933
  try {
15921
- fs24.unlinkSync(audioPath);
15934
+ fs25.unlinkSync(audioPath);
15922
15935
  } catch {
15923
15936
  }
15924
15937
  return { content: `Voice sent! (${actualEngine}, ${sizeKB.toFixed(0)}KB, ${resolvedChannel})` };
@@ -15940,8 +15953,8 @@ __export(my_selfie_exports, {
15940
15953
  dimsOf: () => dimsOf,
15941
15954
  resolvePortraitDesc: () => resolvePortraitDesc
15942
15955
  });
15943
- import * as fs25 from "node:fs";
15944
- import * as path25 from "node:path";
15956
+ import * as fs26 from "node:fs";
15957
+ import * as path26 from "node:path";
15945
15958
  function getProxyDispatcher2() {
15946
15959
  const cfg = liveConfig.all();
15947
15960
  const proxy = cfg.providers?.xai?.proxy;
@@ -15955,7 +15968,7 @@ function getProxyDispatcher2() {
15955
15968
  }
15956
15969
  function dimsOf(p) {
15957
15970
  try {
15958
- const b = fs25.readFileSync(p);
15971
+ const b = fs26.readFileSync(p);
15959
15972
  let w = 0, h = 0;
15960
15973
  if (b.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) {
15961
15974
  w = b.readUInt32BE(16);
@@ -16068,9 +16081,9 @@ function registerPortrait(relPath, name) {
16068
16081
  const cur = cfg?.tools?.my_selfie?.references || cfg?.my_selfie?.references || [];
16069
16082
  const next = Array.isArray(cur) ? cur.filter((r) => r?.name !== name) : [];
16070
16083
  next.unshift({ name, path: relPath });
16071
- const path43 = cfg?.tools?.my_selfie ? "tools.my_selfie.references" : "my_selfie.references";
16072
- void liveConfig.set(path43, next);
16073
- console.log(`[my-selfie] \u5F62\u8C61\u5DF2\u767B\u8BB0\uFF1A${path43}[0] = ${relPath}`);
16084
+ const path44 = cfg?.tools?.my_selfie ? "tools.my_selfie.references" : "my_selfie.references";
16085
+ void liveConfig.set(path44, next);
16086
+ console.log(`[my-selfie] \u5F62\u8C61\u5DF2\u767B\u8BB0\uFF1A${path44}[0] = ${relPath}`);
16074
16087
  } catch (e) {
16075
16088
  console.warn(`[my-selfie] \u5199\u5165 references \u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u672C\u6B21\u51FA\u56FE\uFF09: ${e.message}`);
16076
16089
  }
@@ -16368,10 +16381,10 @@ var init_my_selfie = __esm({
16368
16381
  const REFERENCES = getReferences(ctx);
16369
16382
  const refName = args.reference || "default";
16370
16383
  const refEntry = REFERENCES.find((r) => r.name === refName) || REFERENCES[0];
16371
- let refPath = path25.join(ctx.workspace, refEntry.p);
16384
+ let refPath = path26.join(ctx.workspace, refEntry.p);
16372
16385
  const adoptImg = args.referenceImage?.trim();
16373
16386
  if (adoptImg) {
16374
- if (!fs25.existsSync(adoptImg)) {
16387
+ if (!fs26.existsSync(adoptImg)) {
16375
16388
  return { content: `\u627E\u4E0D\u5230\u90A3\u5F20\u56FE\uFF1A${adoptImg}`, isError: true };
16376
16389
  }
16377
16390
  const acheck = dimsOf(adoptImg);
@@ -16382,16 +16395,16 @@ var init_my_selfie = __esm({
16382
16395
  isError: true
16383
16396
  };
16384
16397
  }
16385
- const adir = path25.join(ctx.workspace, "images");
16386
- if (!fs25.existsSync(adir)) fs25.mkdirSync(adir, { recursive: true });
16387
- const aext = (path25.extname(adoptImg) || ".png").toLowerCase();
16398
+ const adir = path26.join(ctx.workspace, "images");
16399
+ if (!fs26.existsSync(adir)) fs26.mkdirSync(adir, { recursive: true });
16400
+ const aext = (path26.extname(adoptImg) || ".png").toLowerCase();
16388
16401
  const afname = `portrait_${Date.now()}${aext}`;
16389
- fs25.copyFileSync(adoptImg, path25.join(adir, afname));
16402
+ fs26.copyFileSync(adoptImg, path26.join(adir, afname));
16390
16403
  registerPortrait(`images/${afname}`, refName);
16391
- refPath = path25.join(adir, afname);
16404
+ refPath = path26.join(adir, afname);
16392
16405
  console.log(`[my-selfie] \u91C7\u7EB3\u73B0\u6210\u56FE\u5F53\u5F62\u8C61\uFF1Aimages/${afname}${acheck ? ` (${acheck})` : ""}`);
16393
16406
  }
16394
- if (provider !== "autodl" && !fs25.existsSync(refPath)) {
16407
+ if (provider !== "autodl" && !fs26.existsSync(refPath)) {
16395
16408
  const cfgAll = liveConfig.all();
16396
16409
  const portraitDesc = resolvePortraitDesc(
16397
16410
  args.portrait,
@@ -16416,16 +16429,16 @@ var init_my_selfie = __esm({
16416
16429
  } catch (e) {
16417
16430
  return { content: `\u5851\u9020\u5F62\u8C61\u5931\u8D25\uFF1A${e.message}`, isError: true };
16418
16431
  }
16419
- const pdir = path25.join(ctx.workspace, "images");
16420
- if (!fs25.existsSync(pdir)) fs25.mkdirSync(pdir, { recursive: true });
16432
+ const pdir = path26.join(ctx.workspace, "images");
16433
+ if (!fs26.existsSync(pdir)) fs26.mkdirSync(pdir, { recursive: true });
16421
16434
  const pfname = `portrait_${Date.now()}.png`;
16422
- fs25.writeFileSync(path25.join(pdir, pfname), portraitBuf);
16435
+ fs26.writeFileSync(path26.join(pdir, pfname), portraitBuf);
16423
16436
  registerPortrait(`images/${pfname}`, refName);
16424
- refPath = path25.join(pdir, pfname);
16437
+ refPath = path26.join(pdir, pfname);
16425
16438
  console.log(`[my-selfie] \u5F62\u8C61\u5DF2\u5B58 images/${pfname}\uFF0C\u7EE7\u7EED\u8FD9\u6B21\u81EA\u62CD`);
16426
16439
  }
16427
16440
  const resolution = args.resolution || DEFAULT_RESOLUTION;
16428
- const refB64 = fs25.existsSync(refPath) ? fs25.readFileSync(refPath).toString("base64") : "";
16441
+ const refB64 = fs26.existsSync(refPath) ? fs26.readFileSync(refPath).toString("base64") : "";
16429
16442
  let imageBuffer;
16430
16443
  try {
16431
16444
  if (provider === "autodl") {
@@ -16441,7 +16454,7 @@ var init_my_selfie = __esm({
16441
16454
  return { content: `Error: relay provider \u672A\u914D\u7F6E\u3002config \u91CC\u8981\u6709 models.providers.${cfgAll?.my_selfie?.relayProviderId || "7yi"} \u7684 baseUrl \u548C apiKey\u3002`, isError: true };
16442
16455
  }
16443
16456
  const model = cfgAll?.my_selfie?.relayModel || cfgAll?.tools?.my_selfie?.relayModel || "engine7-img-free";
16444
- const ext = path25.extname(refPath).toLowerCase();
16457
+ const ext = path26.extname(refPath).toLowerCase();
16445
16458
  const mime = ext === ".png" ? "image/png" : ext === ".webp" ? "image/webp" : "image/jpeg";
16446
16459
  imageBuffer = await generateWithRelay(refB64, fullPrompt, mime, relay.baseUrl, relay.apiKey, model);
16447
16460
  } else {
@@ -16450,11 +16463,11 @@ var init_my_selfie = __esm({
16450
16463
  } catch (err) {
16451
16464
  return { content: `Selfie generation failed: ${err.message}`, isError: true };
16452
16465
  }
16453
- const imagesDir = path25.join(ctx.workspace, "images");
16454
- if (!fs25.existsSync(imagesDir)) fs25.mkdirSync(imagesDir, { recursive: true });
16466
+ const imagesDir = path26.join(ctx.workspace, "images");
16467
+ if (!fs26.existsSync(imagesDir)) fs26.mkdirSync(imagesDir, { recursive: true });
16455
16468
  const filename = `selfie_${Date.now()}.jpg`;
16456
- const outputPath = path25.join(imagesDir, filename);
16457
- fs25.writeFileSync(outputPath, imageBuffer);
16469
+ const outputPath = path26.join(imagesDir, filename);
16470
+ fs26.writeFileSync(outputPath, imageBuffer);
16458
16471
  const mgr = ctx.channelManager;
16459
16472
  if (mgr) {
16460
16473
  const resolvedChannel = ctx.channel || "feishu";
@@ -16465,11 +16478,11 @@ var init_my_selfie = __esm({
16465
16478
  mimeType: "image/jpeg"
16466
16479
  });
16467
16480
  } catch (err) {
16468
- return { content: `Selfie generated but send failed: ${err.message}. Image: ${path25.resolve(outputPath)}`, isError: false };
16481
+ return { content: `Selfie generated but send failed: ${err.message}. Image: ${path26.resolve(outputPath)}`, isError: false };
16469
16482
  }
16470
16483
  return { content: `Selfie sent! Mode: ${mode}, Provider: ${provider}, Ref: ${refEntry.name}` };
16471
16484
  }
16472
- return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${path25.resolve(outputPath)}` };
16485
+ return { content: `Selfie generated! Mode: ${mode}, Ref: ${refEntry.name}. Image: ${path26.resolve(outputPath)}` };
16473
16486
  },
16474
16487
  isConcurrencySafe: () => false,
16475
16488
  interruptBehavior: () => "block",
@@ -17299,8 +17312,8 @@ var init_calendar = __esm({
17299
17312
  });
17300
17313
 
17301
17314
  // src/tools/service.ts
17302
- import * as fs26 from "node:fs";
17303
- import * as path26 from "node:path";
17315
+ import * as fs27 from "node:fs";
17316
+ import * as path27 from "node:path";
17304
17317
  import { exec, spawn as spawn4 } from "node:child_process";
17305
17318
  import { promisify as promisify3 } from "node:util";
17306
17319
  function getServices() {
@@ -17308,9 +17321,9 @@ function getServices() {
17308
17321
  }
17309
17322
  function serviceLogPath(fileName) {
17310
17323
  const stateDir = String(liveConfig.get("stateDir") ?? "");
17311
- const logDir = path26.join(stateDir, "logs");
17312
- if (!fs26.existsSync(logDir)) fs26.mkdirSync(logDir, { recursive: true });
17313
- return path26.join(logDir, fileName);
17324
+ const logDir = path27.join(stateDir, "logs");
17325
+ if (!fs27.existsSync(logDir)) fs27.mkdirSync(logDir, { recursive: true });
17326
+ return path27.join(logDir, fileName);
17314
17327
  }
17315
17328
  async function runCmd(cmd, timeoutMs = 15e3) {
17316
17329
  try {
@@ -17525,24 +17538,24 @@ var init_constants5 = __esm({
17525
17538
  });
17526
17539
 
17527
17540
  // src/tools/TodoWriteTool/TodoWriteTool.ts
17528
- import fs27 from "node:fs";
17529
- import path27 from "node:path";
17541
+ import fs28 from "node:fs";
17542
+ import path28 from "node:path";
17530
17543
  function todoFilePath(sessionId) {
17531
- return path27.join(todosDir, `${sessionId}.json`);
17544
+ return path28.join(todosDir, `${sessionId}.json`);
17532
17545
  }
17533
17546
  function loadTodos(sessionId) {
17534
17547
  if (!todosDir) return [];
17535
17548
  try {
17536
17549
  const filePath = todoFilePath(sessionId);
17537
- if (!fs27.existsSync(filePath)) return [];
17538
- return JSON.parse(fs27.readFileSync(filePath, "utf-8"));
17550
+ if (!fs28.existsSync(filePath)) return [];
17551
+ return JSON.parse(fs28.readFileSync(filePath, "utf-8"));
17539
17552
  } catch {
17540
17553
  return [];
17541
17554
  }
17542
17555
  }
17543
17556
  function saveTodos(sessionId, todos) {
17544
17557
  if (!todosDir) return;
17545
- fs27.writeFileSync(todoFilePath(sessionId), JSON.stringify(todos, null, 2), "utf-8");
17558
+ fs28.writeFileSync(todoFilePath(sessionId), JSON.stringify(todos, null, 2), "utf-8");
17546
17559
  }
17547
17560
  var todosDir;
17548
17561
  var init_TodoWriteTool = __esm({
@@ -17799,15 +17812,15 @@ var init_constants7 = __esm({
17799
17812
  });
17800
17813
 
17801
17814
  // src/utils/plans.ts
17802
- import * as fs28 from "node:fs";
17803
- import * as path28 from "node:path";
17815
+ import * as fs29 from "node:fs";
17816
+ import * as path29 from "node:path";
17804
17817
  import * as crypto4 from "node:crypto";
17805
17818
  function generateSlug() {
17806
17819
  return crypto4.randomBytes(4).toString("hex");
17807
17820
  }
17808
17821
  function getPlansDirectory(stateDir) {
17809
- const plansDir = path28.join(stateDir, "plans");
17810
- fs28.mkdirSync(plansDir, { recursive: true });
17822
+ const plansDir = path29.join(stateDir, "plans");
17823
+ fs29.mkdirSync(plansDir, { recursive: true });
17811
17824
  return plansDir;
17812
17825
  }
17813
17826
  function getPlanSlug(sessionId, stateDir) {
@@ -17816,8 +17829,8 @@ function getPlanSlug(sessionId, stateDir) {
17816
17829
  const plansDir = getPlansDirectory(stateDir);
17817
17830
  for (let i = 0; i < MAX_SLUG_RETRIES; i++) {
17818
17831
  slug = generateSlug();
17819
- const filePath = path28.join(plansDir, `${slug}.md`);
17820
- if (!fs28.existsSync(filePath)) {
17832
+ const filePath = path29.join(plansDir, `${slug}.md`);
17833
+ if (!fs29.existsSync(filePath)) {
17821
17834
  break;
17822
17835
  }
17823
17836
  }
@@ -17828,21 +17841,21 @@ function getPlanSlug(sessionId, stateDir) {
17828
17841
  function getPlanFilePath(sessionId, stateDir, agentId) {
17829
17842
  const slug = getPlanSlug(sessionId, stateDir);
17830
17843
  if (!agentId) {
17831
- return path28.join(getPlansDirectory(stateDir), `${slug}.md`);
17844
+ return path29.join(getPlansDirectory(stateDir), `${slug}.md`);
17832
17845
  }
17833
- return path28.join(getPlansDirectory(stateDir), `${slug}-agent-${agentId}.md`);
17846
+ return path29.join(getPlansDirectory(stateDir), `${slug}-agent-${agentId}.md`);
17834
17847
  }
17835
17848
  function getPlan(sessionId, stateDir, agentId) {
17836
17849
  const filePath = getPlanFilePath(sessionId, stateDir, agentId);
17837
17850
  try {
17838
- return fs28.readFileSync(filePath, "utf-8");
17851
+ return fs29.readFileSync(filePath, "utf-8");
17839
17852
  } catch {
17840
17853
  return null;
17841
17854
  }
17842
17855
  }
17843
17856
  function writePlan(sessionId, stateDir, content, agentId) {
17844
17857
  const filePath = getPlanFilePath(sessionId, stateDir, agentId);
17845
- fs28.writeFileSync(filePath, content, "utf-8");
17858
+ fs29.writeFileSync(filePath, content, "utf-8");
17846
17859
  return filePath;
17847
17860
  }
17848
17861
  var MAX_SLUG_RETRIES, planSlugCache;
@@ -17990,28 +18003,28 @@ var init_constants8 = __esm({
17990
18003
  });
17991
18004
 
17992
18005
  // src/utils/tasks.ts
17993
- import * as fs29 from "node:fs";
17994
- import * as path29 from "node:path";
18006
+ import * as fs30 from "node:fs";
18007
+ import * as path30 from "node:path";
17995
18008
  function sanitizePathComponent2(input) {
17996
18009
  return input.replace(/[^a-zA-Z0-9_-]/g, "-");
17997
18010
  }
17998
18011
  function getTasksDir2(stateDir, listId) {
17999
- return path29.join(stateDir, "tasks", sanitizePathComponent2(listId));
18012
+ return path30.join(stateDir, "tasks", sanitizePathComponent2(listId));
18000
18013
  }
18001
18014
  function getTaskPath(stateDir, listId, taskId) {
18002
- return path29.join(getTasksDir2(stateDir, listId), `${sanitizePathComponent2(taskId)}.json`);
18015
+ return path30.join(getTasksDir2(stateDir, listId), `${sanitizePathComponent2(taskId)}.json`);
18003
18016
  }
18004
18017
  function ensureTasksDir2(stateDir, listId) {
18005
18018
  const dir = getTasksDir2(stateDir, listId);
18006
- fs29.mkdirSync(dir, { recursive: true });
18019
+ fs30.mkdirSync(dir, { recursive: true });
18007
18020
  return dir;
18008
18021
  }
18009
18022
  function getHighWaterMarkPath(stateDir, listId) {
18010
- return path29.join(getTasksDir2(stateDir, listId), HIGH_WATER_MARK_FILE);
18023
+ return path30.join(getTasksDir2(stateDir, listId), HIGH_WATER_MARK_FILE);
18011
18024
  }
18012
18025
  function readHighWaterMark(stateDir, listId) {
18013
18026
  try {
18014
- const content = fs29.readFileSync(getHighWaterMarkPath(stateDir, listId), "utf-8").trim();
18027
+ const content = fs30.readFileSync(getHighWaterMarkPath(stateDir, listId), "utf-8").trim();
18015
18028
  const value = parseInt(content, 10);
18016
18029
  return isNaN(value) ? 0 : value;
18017
18030
  } catch {
@@ -18019,13 +18032,13 @@ function readHighWaterMark(stateDir, listId) {
18019
18032
  }
18020
18033
  }
18021
18034
  function writeHighWaterMark(stateDir, listId, value) {
18022
- fs29.writeFileSync(getHighWaterMarkPath(stateDir, listId), String(value));
18035
+ fs30.writeFileSync(getHighWaterMarkPath(stateDir, listId), String(value));
18023
18036
  }
18024
18037
  function findHighestTaskIdFromFiles(stateDir, listId) {
18025
18038
  const dir = getTasksDir2(stateDir, listId);
18026
18039
  let files;
18027
18040
  try {
18028
- files = fs29.readdirSync(dir);
18041
+ files = fs30.readdirSync(dir);
18029
18042
  } catch {
18030
18043
  return 0;
18031
18044
  }
@@ -18051,14 +18064,14 @@ function createTask(stateDir, listId, taskData) {
18051
18064
  const id = String(highestId + 1);
18052
18065
  const task = { id, ...taskData };
18053
18066
  const filePath = getTaskPath(stateDir, listId, id);
18054
- fs29.writeFileSync(filePath, JSON.stringify(task, null, 2));
18067
+ fs30.writeFileSync(filePath, JSON.stringify(task, null, 2));
18055
18068
  return id;
18056
18069
  });
18057
18070
  }
18058
18071
  function getTask2(stateDir, listId, taskId) {
18059
18072
  const filePath = getTaskPath(stateDir, listId, taskId);
18060
18073
  try {
18061
- const content = fs29.readFileSync(filePath, "utf-8");
18074
+ const content = fs30.readFileSync(filePath, "utf-8");
18062
18075
  return JSON.parse(content);
18063
18076
  } catch {
18064
18077
  return null;
@@ -18068,7 +18081,7 @@ function listTasks2(stateDir, listId) {
18068
18081
  const dir = getTasksDir2(stateDir, listId);
18069
18082
  let files;
18070
18083
  try {
18071
- files = fs29.readdirSync(dir);
18084
+ files = fs30.readdirSync(dir);
18072
18085
  } catch {
18073
18086
  return [];
18074
18087
  }
@@ -18080,7 +18093,7 @@ function updateTask(stateDir, listId, taskId, updates) {
18080
18093
  if (!existing) return null;
18081
18094
  const updated = { ...existing, ...updates, id: taskId };
18082
18095
  const filePath = getTaskPath(stateDir, listId, taskId);
18083
- fs29.writeFileSync(filePath, JSON.stringify(updated, null, 2));
18096
+ fs30.writeFileSync(filePath, JSON.stringify(updated, null, 2));
18084
18097
  return updated;
18085
18098
  }
18086
18099
  function deleteTask(stateDir, listId, taskId) {
@@ -18094,7 +18107,7 @@ function deleteTask(stateDir, listId, taskId) {
18094
18107
  }
18095
18108
  }
18096
18109
  try {
18097
- fs29.unlinkSync(filePath);
18110
+ fs30.unlinkSync(filePath);
18098
18111
  } catch {
18099
18112
  return false;
18100
18113
  }
@@ -19527,10 +19540,10 @@ function ensureLoaded(workspace, configIds) {
19527
19540
  if (!state.blockedUserIds.includes(id)) state.blockedUserIds.push(id);
19528
19541
  }
19529
19542
  }
19530
- const path43 = join28(workspace, ".reply-blocklist.json");
19543
+ const path44 = join28(workspace, ".reply-blocklist.json");
19531
19544
  try {
19532
- if (existsSync22(path43)) {
19533
- const raw = readFileSync21(path43, "utf-8");
19545
+ if (existsSync22(path44)) {
19546
+ const raw = readFileSync21(path44, "utf-8");
19534
19547
  const parsed = JSON.parse(raw);
19535
19548
  if (parsed.blockedUserIds) {
19536
19549
  for (const id of parsed.blockedUserIds) {
@@ -19546,9 +19559,9 @@ function ensureLoaded(workspace, configIds) {
19546
19559
  loaded = true;
19547
19560
  }
19548
19561
  function save(workspace) {
19549
- const path43 = join28(workspace, ".reply-blocklist.json");
19562
+ const path44 = join28(workspace, ".reply-blocklist.json");
19550
19563
  try {
19551
- writeFileSync16(path43, JSON.stringify(state, null, 2), "utf-8");
19564
+ writeFileSync16(path44, JSON.stringify(state, null, 2), "utf-8");
19552
19565
  } catch (err) {
19553
19566
  console.warn(`[reply-blocklist] Failed to save: ${err.message}`);
19554
19567
  }
@@ -20744,8 +20757,8 @@ var extractMemories_exports = {};
20744
20757
  __export(extractMemories_exports, {
20745
20758
  createMemoryExtractor: () => createMemoryExtractor
20746
20759
  });
20747
- import * as fs30 from "fs";
20748
- import * as path30 from "path";
20760
+ import * as fs31 from "fs";
20761
+ import * as path31 from "path";
20749
20762
  function isModelVisibleMessage(message) {
20750
20763
  return message.role === "user" || message.role === "assistant";
20751
20764
  }
@@ -20768,13 +20781,13 @@ function getMemoryTools() {
20768
20781
  return allDefs.filter((d) => MEMORY_TOOL_NAMES.includes(d.function.name));
20769
20782
  }
20770
20783
  function getStatePath(workspace) {
20771
- return path30.join(workspace, STATE_FILE);
20784
+ return path31.join(workspace, STATE_FILE);
20772
20785
  }
20773
20786
  function loadPersistedState(workspace) {
20774
20787
  try {
20775
20788
  const p = getStatePath(workspace);
20776
- if (fs30.existsSync(p)) {
20777
- const data = JSON.parse(fs30.readFileSync(p, "utf-8"));
20789
+ if (fs31.existsSync(p)) {
20790
+ const data = JSON.parse(fs31.readFileSync(p, "utf-8"));
20778
20791
  for (const [sid, ts] of Object.entries(data.lastTs ?? {})) {
20779
20792
  lastTsMap.set(sid, ts);
20780
20793
  }
@@ -20794,7 +20807,7 @@ function persistState(workspace) {
20794
20807
  for (const [sid, ts] of lastTsMap.entries()) lastTs[sid] = ts;
20795
20808
  for (const [sid, ts] of lastExtractTimeMap.entries()) timestamps[sid] = ts;
20796
20809
  const data = JSON.stringify({ lastTs, timestamps }, null, 2);
20797
- fs30.writeFileSync(getStatePath(workspace), data, "utf-8");
20810
+ fs31.writeFileSync(getStatePath(workspace), data, "utf-8");
20798
20811
  } catch (e) {
20799
20812
  console.warn(`[memory] failed to persist extract state: ${e?.message ?? e}`);
20800
20813
  }
@@ -20835,11 +20848,11 @@ function createMemoryExtractor(workspace, enabled) {
20835
20848
  const existingMemories = formatMemoryManifest(
20836
20849
  await scanMemoryFiles2(memoryDir, new AbortController().signal)
20837
20850
  );
20838
- const extractOverridePath = path30.join(workspace, "prompts", "extract.md");
20851
+ const extractOverridePath = path31.join(workspace, "prompts", "extract.md");
20839
20852
  let systemPrompt;
20840
20853
  try {
20841
- if (fs30.existsSync(extractOverridePath)) {
20842
- systemPrompt = fs30.readFileSync(extractOverridePath, { encoding: "utf-8" });
20854
+ if (fs31.existsSync(extractOverridePath)) {
20855
+ systemPrompt = fs31.readFileSync(extractOverridePath, { encoding: "utf-8" });
20843
20856
  if (existingMemories.length > 0) {
20844
20857
  systemPrompt += `
20845
20858
 
@@ -20965,8 +20978,8 @@ __export(ingest_exports, {
20965
20978
  pushConversation: () => pushConversation,
20966
20979
  toPayload: () => toPayload
20967
20980
  });
20968
- import fs31 from "node:fs";
20969
- import path31 from "node:path";
20981
+ import fs32 from "node:fs";
20982
+ import path32 from "node:path";
20970
20983
  async function readConfig() {
20971
20984
  const defaults = {
20972
20985
  url: "http://127.0.0.1:8100",
@@ -20996,9 +21009,9 @@ async function readConfig() {
20996
21009
  }
20997
21010
  function loadPushTs(workspace, sessionId) {
20998
21011
  try {
20999
- const p = path31.join(workspace, PUSH_STATE_FILE);
21000
- if (fs31.existsSync(p)) {
21001
- const data = JSON.parse(fs31.readFileSync(p, "utf-8"));
21012
+ const p = path32.join(workspace, PUSH_STATE_FILE);
21013
+ if (fs32.existsSync(p)) {
21014
+ const data = JSON.parse(fs32.readFileSync(p, "utf-8"));
21002
21015
  return typeof data[sessionId] === "number" ? data[sessionId] : 0;
21003
21016
  }
21004
21017
  } catch (e) {
@@ -21008,14 +21021,14 @@ function loadPushTs(workspace, sessionId) {
21008
21021
  }
21009
21022
  function savePushTs(workspace, sessionId, ts) {
21010
21023
  try {
21011
- const p = path31.join(workspace, PUSH_STATE_FILE);
21024
+ const p = path32.join(workspace, PUSH_STATE_FILE);
21012
21025
  let data = {};
21013
21026
  try {
21014
- if (fs31.existsSync(p)) data = JSON.parse(fs31.readFileSync(p, "utf-8"));
21027
+ if (fs32.existsSync(p)) data = JSON.parse(fs32.readFileSync(p, "utf-8"));
21015
21028
  } catch {
21016
21029
  }
21017
21030
  data[sessionId] = ts;
21018
- fs31.writeFileSync(p, JSON.stringify(data, null, 2), "utf-8");
21031
+ fs32.writeFileSync(p, JSON.stringify(data, null, 2), "utf-8");
21019
21032
  } catch (e) {
21020
21033
  console.warn(`[everos-ingest] save pushTs failed: ${e?.message ?? e}`);
21021
21034
  }
@@ -27940,11 +27953,11 @@ async function readLastConsolidatedAt(memoryDir) {
27940
27953
  }
27941
27954
  }
27942
27955
  async function tryAcquireConsolidationLock(memoryDir) {
27943
- const path43 = lockPath(memoryDir);
27956
+ const path44 = lockPath(memoryDir);
27944
27957
  let mtimeMs;
27945
27958
  let holderPid;
27946
27959
  try {
27947
- const [s, raw] = await Promise.all([stat3(path43), readFile5(path43, "utf8")]);
27960
+ const [s, raw] = await Promise.all([stat3(path44), readFile5(path44, "utf8")]);
27948
27961
  mtimeMs = s.mtimeMs;
27949
27962
  const parsed = parseInt(raw.trim(), 10);
27950
27963
  holderPid = Number.isFinite(parsed) ? parsed : void 0;
@@ -27957,10 +27970,10 @@ async function tryAcquireConsolidationLock(memoryDir) {
27957
27970
  }
27958
27971
  }
27959
27972
  await mkdir3(memoryDir, { recursive: true });
27960
- await writeFile4(path43, String(process.pid));
27973
+ await writeFile4(path44, String(process.pid));
27961
27974
  let verify2;
27962
27975
  try {
27963
- verify2 = await readFile5(path43, "utf8");
27976
+ verify2 = await readFile5(path44, "utf8");
27964
27977
  } catch {
27965
27978
  return null;
27966
27979
  }
@@ -27968,15 +27981,15 @@ async function tryAcquireConsolidationLock(memoryDir) {
27968
27981
  return mtimeMs ?? 0;
27969
27982
  }
27970
27983
  async function rollbackConsolidationLock(memoryDir, priorMtime) {
27971
- const path43 = lockPath(memoryDir);
27984
+ const path44 = lockPath(memoryDir);
27972
27985
  try {
27973
27986
  if (priorMtime === 0) {
27974
- await unlink(path43);
27987
+ await unlink(path44);
27975
27988
  return;
27976
27989
  }
27977
- await writeFile4(path43, "");
27990
+ await writeFile4(path44, "");
27978
27991
  const t = priorMtime / 1e3;
27979
- await utimes(path43, t, t);
27992
+ await utimes(path44, t, t);
27980
27993
  } catch (e) {
27981
27994
  console.log(`[autoDream] rollback failed: ${e.message} \u2014 next trigger delayed to minHours`);
27982
27995
  }
@@ -28263,7 +28276,7 @@ __export(handle_query_exports, {
28263
28276
  });
28264
28277
  import { readFileSync as readFileSync37, existsSync as existsSync31, statSync as statSync13 } from "node:fs";
28265
28278
  import { join as join48, resolve as resolve8 } from "node:path";
28266
- import * as path32 from "node:path";
28279
+ import * as path33 from "node:path";
28267
28280
  function resolveSystemPrompt(v) {
28268
28281
  return typeof v === "function" ? v() : v || "";
28269
28282
  }
@@ -28271,18 +28284,18 @@ function resetSessionStartInjection(sessionId) {
28271
28284
  sessionStartDone.delete(sessionId);
28272
28285
  }
28273
28286
  function loadExternalChanRules(workspace) {
28274
- const path43 = join48(workspace, "prompts", "external-chan-rules.md");
28275
- if (externalChanRulesCache && externalChanRulesCache.path === path43) return externalChanRulesCache;
28287
+ const path44 = join48(workspace, "prompts", "external-chan-rules.md");
28288
+ if (externalChanRulesCache && externalChanRulesCache.path === path44) return externalChanRulesCache;
28276
28289
  let content = "";
28277
- if (existsSync31(path43)) {
28290
+ if (existsSync31(path44)) {
28278
28291
  try {
28279
- content = readFileSync37(path43, "utf-8").trim();
28292
+ content = readFileSync37(path44, "utf-8").trim();
28280
28293
  } catch (e) {
28281
28294
  console.warn(`[external-chan-rules] Failed to load: ${e}`);
28282
28295
  }
28283
28296
  }
28284
- externalChanRulesCache = { path: path43, content };
28285
- console.log(`[external-chan-rules] Loaded ${content.length} chars from ${path43}`);
28297
+ externalChanRulesCache = { path: path44, content };
28298
+ console.log(`[external-chan-rules] Loaded ${content.length} chars from ${path44}`);
28286
28299
  return externalChanRulesCache;
28287
28300
  }
28288
28301
  function getExternalChanRulesBlock(inboundMeta, workspace) {
@@ -29097,7 +29110,7 @@ stack: ${err.stack ?? "(none)"}`);
29097
29110
  }
29098
29111
  } catch (err) {
29099
29112
  try {
29100
- (await import("node:fs")).appendFileSync(join48(process.env.ENGINE7_STATE_DIR || path32.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
29113
+ (await import("node:fs")).appendFileSync(join48(process.env.ENGINE7_STATE_DIR || path33.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
29101
29114
  stack: ${err.stack ?? "(none)"}
29102
29115
  `);
29103
29116
  } catch {
@@ -29785,8 +29798,8 @@ __export(free_tier_apply_exports, {
29785
29798
  isFreeTierConfig: () => isFreeTierConfig,
29786
29799
  resolveConfigPath: () => resolveConfigPath
29787
29800
  });
29788
- import * as fs32 from "node:fs";
29789
- import * as path33 from "node:path";
29801
+ import * as fs33 from "node:fs";
29802
+ import * as path34 from "node:path";
29790
29803
  function isFreeTierConfig(cfg) {
29791
29804
  const hasProvider = !!cfg?.models?.providers?.[FREE_TIER_PROVIDER_ID];
29792
29805
  const primary = String(cfg?.agents?.defaults?.model?.primary || "");
@@ -29835,18 +29848,18 @@ function applyFreeTier(cfg, opts = {}) {
29835
29848
  return cfg;
29836
29849
  }
29837
29850
  function resolveConfigPath(stateDir, configName) {
29838
- const configsDir = path33.join(stateDir, "configs");
29851
+ const configsDir = path34.join(stateDir, "configs");
29839
29852
  if (configName) {
29840
- const p = path33.join(configsDir, configName);
29841
- return fs32.existsSync(p) ? p : "";
29842
- }
29843
- const main2 = path33.join(configsDir, "main7.json");
29844
- if (fs32.existsSync(main2)) return main2;
29845
- if (!fs32.existsSync(configsDir)) return "";
29846
- for (const f of fs32.readdirSync(configsDir).filter((x) => x.endsWith(".json"))) {
29847
- const full = path33.join(configsDir, f);
29853
+ const p = path34.join(configsDir, configName);
29854
+ return fs33.existsSync(p) ? p : "";
29855
+ }
29856
+ const main2 = path34.join(configsDir, "main7.json");
29857
+ if (fs33.existsSync(main2)) return main2;
29858
+ if (!fs33.existsSync(configsDir)) return "";
29859
+ for (const f of fs33.readdirSync(configsDir).filter((x) => x.endsWith(".json"))) {
29860
+ const full = path34.join(configsDir, f);
29848
29861
  try {
29849
- if (JSON.parse(fs32.readFileSync(full, "utf8")).models?.providers) return full;
29862
+ if (JSON.parse(fs33.readFileSync(full, "utf8")).models?.providers) return full;
29850
29863
  } catch {
29851
29864
  }
29852
29865
  }
@@ -29855,16 +29868,16 @@ function resolveConfigPath(stateDir, configName) {
29855
29868
  function applyFreeTierToConfig(configPath, opts = {}) {
29856
29869
  let cfg;
29857
29870
  try {
29858
- cfg = JSON.parse(fs32.readFileSync(configPath, "utf8"));
29871
+ cfg = JSON.parse(fs33.readFileSync(configPath, "utf8"));
29859
29872
  } catch (e) {
29860
29873
  throw new Error(`\u8BFB\u53D6 config \u5931\u8D25: ${configPath}\uFF08${e?.message || e}\uFF09`);
29861
29874
  }
29862
29875
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
29863
29876
  const backupPath = `${configPath}.bak-${stamp}`;
29864
- fs32.copyFileSync(configPath, backupPath);
29877
+ fs33.copyFileSync(configPath, backupPath);
29865
29878
  applyFreeTier(cfg, opts);
29866
29879
  try {
29867
- fs32.writeFileSync(configPath, JSON.stringify(cfg, null, 2), "utf8");
29880
+ fs33.writeFileSync(configPath, JSON.stringify(cfg, null, 2), "utf8");
29868
29881
  } catch (e) {
29869
29882
  throw new Error(`\u5199\u5165 config \u5931\u8D25: ${configPath}\uFF08${e?.message || e}\uFF09\uFF1B\u539F\u6587\u4EF6\u672A\u6539\u52A8\uFF0C\u5907\u4EFD\u5728 ${backupPath}`);
29870
29883
  }
@@ -29894,15 +29907,15 @@ __export(cli_doctor_exports, {
29894
29907
  resolveStateDirFromArgs: () => resolveStateDirFromArgs,
29895
29908
  runDoctor: () => runDoctor
29896
29909
  });
29897
- import * as fs33 from "node:fs";
29898
- import * as path34 from "node:path";
29910
+ import * as fs34 from "node:fs";
29911
+ import * as path35 from "node:path";
29899
29912
  import * as net from "node:net";
29900
29913
  import { fileURLToPath as fileURLToPath6 } from "node:url";
29901
29914
  function readVersion() {
29902
- const here = path34.dirname(fileURLToPath6(import.meta.url));
29903
- for (const p of [path34.join(here, "..", "package.json"), path34.join(here, "..", "..", "package.json")]) {
29915
+ const here = path35.dirname(fileURLToPath6(import.meta.url));
29916
+ for (const p of [path35.join(here, "..", "package.json"), path35.join(here, "..", "..", "package.json")]) {
29904
29917
  try {
29905
- return JSON.parse(fs33.readFileSync(p, "utf8")).version || "unknown";
29918
+ return JSON.parse(fs34.readFileSync(p, "utf8")).version || "unknown";
29906
29919
  } catch {
29907
29920
  }
29908
29921
  }
@@ -29932,7 +29945,7 @@ function probePort(port, timeoutMs) {
29932
29945
  });
29933
29946
  }
29934
29947
  async function runDoctor(stateDir, opts) {
29935
- const configPath = path34.join(stateDir, "configs", "main7.json");
29948
+ const configPath = path35.join(stateDir, "configs", "main7.json");
29936
29949
  const report = {
29937
29950
  version: readVersion(),
29938
29951
  stateDir,
@@ -29948,10 +29961,10 @@ async function runDoctor(stateDir, opts) {
29948
29961
  };
29949
29962
  let config = null;
29950
29963
  try {
29951
- config = JSON.parse(fs33.readFileSync(configPath, "utf8"));
29964
+ config = JSON.parse(fs34.readFileSync(configPath, "utf8"));
29952
29965
  report.configValid = true;
29953
29966
  } catch (e) {
29954
- report.configError = fs33.existsSync(configPath) ? `\u89E3\u6790\u5931\u8D25: ${e.message}` : "config \u4E0D\u5B58\u5728\uFF08\u5148 engine7 init\uFF09";
29967
+ report.configError = fs34.existsSync(configPath) ? `\u89E3\u6790\u5931\u8D25: ${e.message}` : "config \u4E0D\u5B58\u5728\uFF08\u5148 engine7 init\uFF09";
29955
29968
  }
29956
29969
  if (config?.channels) {
29957
29970
  for (const [name, conf] of Object.entries(config.channels)) {
@@ -29959,13 +29972,13 @@ async function runDoctor(stateDir, opts) {
29959
29972
  report.channels.push({ name, enabled: !!c.enabled, hasCredentials: channelHasCredentials(name, c) });
29960
29973
  }
29961
29974
  }
29962
- const cfgBase = path34.basename(report.configPath, ".json") || "main7";
29975
+ const cfgBase = path35.basename(report.configPath, ".json") || "main7";
29963
29976
  const candidates = secretsCandidates(stateDir, cfgBase);
29964
- const secretsFile = candidates.find((p) => fs33.existsSync(p)) || candidates[0];
29977
+ const secretsFile = candidates.find((p) => fs34.existsSync(p)) || candidates[0];
29965
29978
  report.secrets.file = secretsFile;
29966
- if (fs33.existsSync(secretsFile)) {
29979
+ if (fs34.existsSync(secretsFile)) {
29967
29980
  report.secrets.exists = true;
29968
- for (const line of fs33.readFileSync(secretsFile, "utf8").split("\n")) {
29981
+ for (const line of fs34.readFileSync(secretsFile, "utf8").split("\n")) {
29969
29982
  const eq = line.indexOf("=");
29970
29983
  if (eq > 0 && !line.startsWith("#")) report.secrets.keys.push(line.slice(0, eq).trim());
29971
29984
  }
@@ -30005,10 +30018,10 @@ async function runDoctor(stateDir, opts) {
30005
30018
  report.missingEnvKeys = [...missing].sort();
30006
30019
  const stale = [];
30007
30020
  for (const rel of ["workspace/SESSION-STATE.md", "SESSION-STATE.md"]) {
30008
- const p = path34.join(stateDir, rel);
30021
+ const p = path35.join(stateDir, rel);
30009
30022
  try {
30010
- if (!fs33.existsSync(p)) continue;
30011
- const head = fs33.readFileSync(p, "utf8").split("\n").slice(0, 10).join("\n");
30023
+ if (!fs34.existsSync(p)) continue;
30024
+ const head = fs34.readFileSync(p, "utf8").split("\n").slice(0, 10).join("\n");
30012
30025
  const m = head.match(/^#{1,3}\s*当前时间\s*$\n+\s*(\d{4}-\d{2}-\d{2})/m);
30013
30026
  if (!m) continue;
30014
30027
  const ageH = (Date.now() - (/* @__PURE__ */ new Date(`${m[1]}T00:00:00Z`)).getTime()) / 36e5;
@@ -30026,19 +30039,19 @@ function resolveStateDirFromArgs(args) {
30026
30039
  for (let i = 0; i < args.length; i++) {
30027
30040
  if (args[i] === "--state-dir" && args[i + 1]) stateDir = args[++i].trim();
30028
30041
  }
30029
- if (stateDir) return path34.resolve(stateDir);
30042
+ if (stateDir) return path35.resolve(stateDir);
30030
30043
  const home = process.env.HOME || process.env.USERPROFILE || ".";
30031
- const cwd = path34.resolve(process.cwd());
30032
- if (fs33.existsSync(path34.join(cwd, "configs"))) return cwd;
30033
- const pointer = path34.join(home, ".engine7.json");
30034
- if (fs33.existsSync(pointer)) {
30044
+ const cwd = path35.resolve(process.cwd());
30045
+ if (fs34.existsSync(path35.join(cwd, "configs"))) return cwd;
30046
+ const pointer = path35.join(home, ".engine7.json");
30047
+ if (fs34.existsSync(pointer)) {
30035
30048
  try {
30036
- const ptrStateDir = JSON.parse(fs33.readFileSync(pointer, "utf8")).stateDir;
30037
- if (typeof ptrStateDir === "string" && ptrStateDir.trim()) return path34.resolve(ptrStateDir);
30049
+ const ptrStateDir = JSON.parse(fs34.readFileSync(pointer, "utf8")).stateDir;
30050
+ if (typeof ptrStateDir === "string" && ptrStateDir.trim()) return path35.resolve(ptrStateDir);
30038
30051
  } catch {
30039
30052
  }
30040
30053
  }
30041
- return path34.join(home, ".engine7");
30054
+ return path35.join(home, ".engine7");
30042
30055
  }
30043
30056
  var init_cli_doctor = __esm({
30044
30057
  "src/cli-doctor.ts"() {
@@ -30051,8 +30064,8 @@ var init_cli_doctor = __esm({
30051
30064
  });
30052
30065
 
30053
30066
  // src/config/writer.ts
30054
- import fs34 from "node:fs";
30055
- import path35 from "node:path";
30067
+ import fs35 from "node:fs";
30068
+ import path36 from "node:path";
30056
30069
  function isNormalized(text) {
30057
30070
  if (text === "") return true;
30058
30071
  if (text.includes("\r")) return false;
@@ -30067,13 +30080,13 @@ function isNormalized(text) {
30067
30080
  return minIndent === 2 || minIndent === Infinity;
30068
30081
  }
30069
30082
  function rotateBaks(filePath) {
30070
- const dir = path35.dirname(filePath);
30071
- const base = path35.basename(filePath);
30072
- const baks = fs34.readdirSync(dir).filter((n) => n.startsWith(base + ".bak-")).sort();
30083
+ const dir = path36.dirname(filePath);
30084
+ const base = path36.basename(filePath);
30085
+ const baks = fs35.readdirSync(dir).filter((n) => n.startsWith(base + ".bak-")).sort();
30073
30086
  while (baks.length >= KEEP_BAKS) {
30074
30087
  const victim = baks.shift();
30075
30088
  try {
30076
- fs34.unlinkSync(path35.join(dir, victim));
30089
+ fs35.unlinkSync(path36.join(dir, victim));
30077
30090
  } catch {
30078
30091
  }
30079
30092
  }
@@ -30092,7 +30105,7 @@ function writeFailure(filePath, primary, extra) {
30092
30105
  function renameWithRetry(from, to) {
30093
30106
  for (let attempt = 1; ; attempt++) {
30094
30107
  try {
30095
- fs34.renameSync(from, to);
30108
+ fs35.renameSync(from, to);
30096
30109
  return;
30097
30110
  } catch (err) {
30098
30111
  if (attempt >= RENAME_ATTEMPTS || !RETRYABLE_CODES.has(errCode(err))) throw err;
@@ -30107,32 +30120,32 @@ function commitFile(tmp, filePath) {
30107
30120
  } catch (primaryErr) {
30108
30121
  const old = `${filePath}.old`;
30109
30122
  try {
30110
- fs34.renameSync(filePath, old);
30123
+ fs35.renameSync(filePath, old);
30111
30124
  } catch (err) {
30112
30125
  throw writeFailure(filePath, primaryErr, `\u6539\u540D .old \u5907\u4EFD\u4E5F\u5931\u8D25\uFF08${errCode(err) || "\u672A\u77E5"}\uFF09`);
30113
30126
  }
30114
30127
  try {
30115
- fs34.renameSync(tmp, filePath);
30128
+ fs35.renameSync(tmp, filePath);
30116
30129
  } catch (err) {
30117
30130
  try {
30118
- fs34.renameSync(old, filePath);
30131
+ fs35.renameSync(old, filePath);
30119
30132
  } catch {
30120
30133
  throw writeFailure(filePath, primaryErr, `\u65B0\u5185\u5BB9\u843D\u76D8\u4E0E\u56DE\u6EDA\u90FD\u5931\u8D25\uFF0C\u65E7\u5185\u5BB9\u7559\u5728 ${old}`);
30121
30134
  }
30122
30135
  throw writeFailure(filePath, primaryErr, `\u6362\u540D\u843D\u76D8\u5931\u8D25\uFF08${errCode(err) || "\u672A\u77E5"}\uFF09`);
30123
30136
  }
30124
30137
  try {
30125
- fs34.unlinkSync(old);
30138
+ fs35.unlinkSync(old);
30126
30139
  } catch {
30127
30140
  }
30128
30141
  }
30129
30142
  }
30130
30143
  function writeConfigAtomic(filePath, obj) {
30131
- const existed = fs34.existsSync(filePath);
30144
+ const existed = fs35.existsSync(filePath);
30132
30145
  let prevText = "";
30133
30146
  if (existed) {
30134
30147
  try {
30135
- prevText = fs34.readFileSync(filePath, "utf-8");
30148
+ prevText = fs35.readFileSync(filePath, "utf-8");
30136
30149
  } catch (err) {
30137
30150
  throw writeFailure(filePath, err);
30138
30151
  }
@@ -30140,27 +30153,27 @@ function writeConfigAtomic(filePath, obj) {
30140
30153
  const normalized = !existed || !isNormalized(prevText);
30141
30154
  if (prevText) {
30142
30155
  try {
30143
- fs34.copyFileSync(filePath, `${filePath}.bak-${Date.now()}`);
30156
+ fs35.copyFileSync(filePath, `${filePath}.bak-${Date.now()}`);
30144
30157
  } catch {
30145
30158
  }
30146
30159
  rotateBaks(filePath);
30147
30160
  }
30148
30161
  const content = JSON.stringify(obj, null, 2) + "\n";
30149
- const tmp = path35.join(path35.dirname(filePath), `.${path35.basename(filePath)}.tmp-${process.pid}`);
30162
+ const tmp = path36.join(path36.dirname(filePath), `.${path36.basename(filePath)}.tmp-${process.pid}`);
30150
30163
  try {
30151
- const fd = fs34.openSync(tmp, "w");
30164
+ const fd = fs35.openSync(tmp, "w");
30152
30165
  try {
30153
- fs34.writeFileSync(fd, content, "utf-8");
30154
- fs34.fsyncSync(fd);
30166
+ fs35.writeFileSync(fd, content, "utf-8");
30167
+ fs35.fsyncSync(fd);
30155
30168
  } finally {
30156
- fs34.closeSync(fd);
30169
+ fs35.closeSync(fd);
30157
30170
  }
30158
30171
  commitFile(tmp, filePath);
30159
30172
  } catch (err) {
30160
30173
  throw err instanceof ConfigWriteError ? err : writeFailure(filePath, err);
30161
30174
  } finally {
30162
30175
  try {
30163
- fs34.unlinkSync(tmp);
30176
+ fs35.unlinkSync(tmp);
30164
30177
  } catch {
30165
30178
  }
30166
30179
  }
@@ -30186,18 +30199,18 @@ var init_writer2 = __esm({
30186
30199
  });
30187
30200
 
30188
30201
  // src/config/secrets-io.ts
30189
- import fs35 from "node:fs";
30190
- import path36 from "node:path";
30202
+ import fs36 from "node:fs";
30203
+ import path37 from "node:path";
30191
30204
  function resolveSecretPath(stateDir, configName) {
30192
30205
  return secretsCandidates(stateDir, configName)[0];
30193
30206
  }
30194
30207
  function resolveSecretReadPath(stateDir, configName) {
30195
- return secretsCandidates(stateDir, configName).find((c) => fs35.existsSync(c)) ?? null;
30208
+ return secretsCandidates(stateDir, configName).find((c) => fs36.existsSync(c)) ?? null;
30196
30209
  }
30197
30210
  function readSecretStatus(stateDir, configName, names) {
30198
30211
  const p = resolveSecretReadPath(stateDir, configName);
30199
30212
  const out = {};
30200
- const text = p ? fs35.readFileSync(p, "utf-8") : "";
30213
+ const text = p ? fs36.readFileSync(p, "utf-8") : "";
30201
30214
  const present = /* @__PURE__ */ new Set();
30202
30215
  for (const line of text.split("\n")) {
30203
30216
  const t = line.trim();
@@ -30210,7 +30223,7 @@ function readSecretStatus(stateDir, configName, names) {
30210
30223
  return out;
30211
30224
  }
30212
30225
  function writeSecret(stateDir, configName, name, value) {
30213
- writeSecretsValue(path36.join(stateDir, "configs", `${configName}.json`), name, value);
30226
+ writeSecretsValue(path37.join(stateDir, "configs", `${configName}.json`), name, value);
30214
30227
  }
30215
30228
  var init_secrets_io = __esm({
30216
30229
  "src/config/secrets-io.ts"() {
@@ -30220,8 +30233,8 @@ var init_secrets_io = __esm({
30220
30233
  });
30221
30234
 
30222
30235
  // src/config/migrations/index.ts
30223
- import fs36 from "node:fs";
30224
- import path37 from "node:path";
30236
+ import fs37 from "node:fs";
30237
+ import path38 from "node:path";
30225
30238
  function registerMigration(m) {
30226
30239
  if (REGISTRY.has(m.name)) {
30227
30240
  throw new Error(`[migrations] \u8FC1\u79FB "${m.name}" \u91CD\u590D\u6CE8\u518C\u2014\u2014\u540C\u540D\u4F1A\u6309 import \u987A\u5E8F\u9759\u9ED8\u8986\u76D6`);
@@ -30237,21 +30250,21 @@ async function runMigration(name, ctx) {
30237
30250
  return await m.run(ctx);
30238
30251
  }
30239
30252
  function rotateBaks2(filePath) {
30240
- const dir = path37.dirname(filePath);
30241
- const base = path37.basename(filePath);
30242
- const baks = fs36.readdirSync(dir).filter((n) => n.startsWith(base + ".bak-")).sort();
30253
+ const dir = path38.dirname(filePath);
30254
+ const base = path38.basename(filePath);
30255
+ const baks = fs37.readdirSync(dir).filter((n) => n.startsWith(base + ".bak-")).sort();
30243
30256
  while (baks.length > KEEP_BAKS2) {
30244
30257
  const victim = baks.shift();
30245
30258
  try {
30246
- fs36.unlinkSync(path37.join(dir, victim));
30259
+ fs37.unlinkSync(path38.join(dir, victim));
30247
30260
  } catch {
30248
30261
  }
30249
30262
  }
30250
30263
  }
30251
30264
  function backupFile(filePath) {
30252
- if (!fs36.existsSync(filePath)) return null;
30265
+ if (!fs37.existsSync(filePath)) return null;
30253
30266
  const bak = `${filePath}.bak-${Date.now()}`;
30254
- fs36.copyFileSync(filePath, bak);
30267
+ fs37.copyFileSync(filePath, bak);
30255
30268
  rotateBaks2(filePath);
30256
30269
  return bak;
30257
30270
  }
@@ -30265,11 +30278,11 @@ var init_migrations = __esm({
30265
30278
  });
30266
30279
 
30267
30280
  // src/config/migrations/persona.ts
30268
- import fs37 from "node:fs";
30269
- import path38 from "node:path";
30281
+ import fs38 from "node:fs";
30282
+ import path39 from "node:path";
30270
30283
  function readFileOrNull(p) {
30271
30284
  try {
30272
- return fs37.readFileSync(p, "utf-8");
30285
+ return fs38.readFileSync(p, "utf-8");
30273
30286
  } catch {
30274
30287
  return null;
30275
30288
  }
@@ -30289,22 +30302,22 @@ var init_persona = __esm({
30289
30302
  run(ctx) {
30290
30303
  const persona = ctx.values?.agents?.defaults?.persona;
30291
30304
  if (typeof persona !== "string" || !persona) return { changed: [] };
30292
- const dir = path38.join(ctx.workspace, "personas", persona);
30293
- if (!fs37.existsSync(dir)) {
30305
+ const dir = path39.join(ctx.workspace, "personas", persona);
30306
+ if (!fs38.existsSync(dir)) {
30294
30307
  return { changed: [] };
30295
30308
  }
30296
30309
  const changed = [];
30297
30310
  for (const name of POINTER_FILES) {
30298
- const src = path38.join(dir, name);
30311
+ const src = path39.join(dir, name);
30299
30312
  const content = readFileOrNull(src);
30300
30313
  if (content === null) continue;
30301
- const legacy = path38.join(ctx.workspace, LEGACY_PATHS[name]);
30314
+ const legacy = path39.join(ctx.workspace, LEGACY_PATHS[name]);
30302
30315
  const legacyContent = readFileOrNull(legacy);
30303
30316
  if (legacyContent !== null && legacyContent === content) {
30304
- fs37.renameSync(legacy, `${legacy}.migrated-${Date.now()}`);
30317
+ fs38.renameSync(legacy, `${legacy}.migrated-${Date.now()}`);
30305
30318
  changed.push(`${LEGACY_PATHS[name]} \u2192 personas/${persona}/${name}`);
30306
30319
  } else if (legacyContent !== null) {
30307
- fs37.renameSync(legacy, `${legacy}.bak-${Date.now()}`);
30320
+ fs38.renameSync(legacy, `${legacy}.bak-${Date.now()}`);
30308
30321
  changed.push(`${LEGACY_PATHS[name]} \u2192 .bak\uFF08\u5185\u5BB9\u4E0E\u6A21\u677F\u4E0D\u540C\uFF0C\u4FDD\u5B88\u4FDD\u7559\uFF09`);
30309
30322
  }
30310
30323
  }
@@ -30316,7 +30329,7 @@ var init_persona = __esm({
30316
30329
  });
30317
30330
 
30318
30331
  // src/config/migrations/channel-secrets.ts
30319
- import fs38 from "node:fs";
30332
+ import fs39 from "node:fs";
30320
30333
  function envNameFor(dotPath) {
30321
30334
  const declared = getField(dotPath)?.envKey;
30322
30335
  if (declared) return declared;
@@ -30358,15 +30371,15 @@ function planChannelSecretMoves(config) {
30358
30371
  }
30359
30372
  function restoreEnv(envPath, before) {
30360
30373
  try {
30361
- if (before === null) fs38.unlinkSync(envPath);
30362
- else fs38.writeFileSync(envPath, before, "utf8");
30374
+ if (before === null) fs39.unlinkSync(envPath);
30375
+ else fs39.writeFileSync(envPath, before, "utf8");
30363
30376
  } catch {
30364
30377
  }
30365
30378
  }
30366
30379
  function dropBackup(backup) {
30367
30380
  if (backup) {
30368
30381
  try {
30369
- fs38.unlinkSync(backup);
30382
+ fs39.unlinkSync(backup);
30370
30383
  } catch {
30371
30384
  }
30372
30385
  }
@@ -30375,7 +30388,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
30375
30388
  const writeConfig = deps.writeConfig ?? ((p, obj) => writeConfigAtomic(p, obj));
30376
30389
  let text;
30377
30390
  try {
30378
- text = fs38.readFileSync(configPath, "utf-8");
30391
+ text = fs39.readFileSync(configPath, "utf-8");
30379
30392
  } catch {
30380
30393
  return { changed: [], backup: null, secretsFile: null };
30381
30394
  }
@@ -30392,7 +30405,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
30392
30405
  if (moves.length === 0) return { changed: [], backup: null, secretsFile: null };
30393
30406
  const { stateDir, configName } = resolveConfigIdentity(configPath);
30394
30407
  const envPath = secretsCandidates(stateDir, configName)[0];
30395
- const envBefore = fs38.existsSync(envPath) ? fs38.readFileSync(envPath, "utf-8") : null;
30408
+ const envBefore = fs39.existsSync(envPath) ? fs39.readFileSync(envPath, "utf-8") : null;
30396
30409
  const backup = backupFile(configPath);
30397
30410
  try {
30398
30411
  for (const m of moves) writeSecret(stateDir, configName, m.envName, m.value);
@@ -30413,7 +30426,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
30413
30426
  const problem = verify(configPath, envPath, moves);
30414
30427
  if (problem) {
30415
30428
  try {
30416
- if (backup) fs38.copyFileSync(backup, configPath);
30429
+ if (backup) fs39.copyFileSync(backup, configPath);
30417
30430
  } catch {
30418
30431
  }
30419
30432
  restoreEnv(envPath, envBefore);
@@ -30425,7 +30438,7 @@ function migrateChannelSecrets(configPath, deps = {}) {
30425
30438
  function verify(configPath, envPath, moves) {
30426
30439
  let cfg;
30427
30440
  try {
30428
- cfg = JSON.parse(fs38.readFileSync(configPath, "utf-8"));
30441
+ cfg = JSON.parse(fs39.readFileSync(configPath, "utf-8"));
30429
30442
  } catch (e) {
30430
30443
  return `config \u8BFB\u4E0D\u56DE\u6765\u4E86\uFF08${e?.message || String(e)}\uFF09`;
30431
30444
  }
@@ -30435,7 +30448,7 @@ function verify(configPath, envPath, moves) {
30435
30448
  }
30436
30449
  let env = "";
30437
30450
  try {
30438
- env = fs38.readFileSync(envPath, "utf-8");
30451
+ env = fs39.readFileSync(envPath, "utf-8");
30439
30452
  } catch (e) {
30440
30453
  return `secrets \u6587\u4EF6\u8BFB\u4E0D\u56DE\u6765\uFF08${e?.message || String(e)}\uFF09`;
30441
30454
  }
@@ -30473,14 +30486,14 @@ __export(cli_config_exports, {
30473
30486
  isSafeConfigName: () => isSafeConfigName,
30474
30487
  runConfigCommand: () => runConfigCommand
30475
30488
  });
30476
- import fs39 from "node:fs";
30477
- import path39 from "node:path";
30489
+ import fs40 from "node:fs";
30490
+ import path40 from "node:path";
30478
30491
  function isSafeConfigName(name) {
30479
30492
  return /^[\w.-]+$/.test(name);
30480
30493
  }
30481
30494
  function sameDir(a, b) {
30482
30495
  const norm = (s) => {
30483
- const r = path39.resolve(s);
30496
+ const r = path40.resolve(s);
30484
30497
  return process.platform === "win32" ? r.toLowerCase() : r;
30485
30498
  };
30486
30499
  return norm(a) === norm(b);
@@ -30508,7 +30521,7 @@ function parseArgs(args) {
30508
30521
  badArgs.push(a);
30509
30522
  }
30510
30523
  if (config) {
30511
- const configPath = path39.resolve(config);
30524
+ const configPath = path40.resolve(config);
30512
30525
  if (!/\.json$/i.test(configPath)) {
30513
30526
  return {
30514
30527
  stateDir,
@@ -30532,9 +30545,9 @@ function parseArgs(args) {
30532
30545
  }
30533
30546
  return { stateDir: ident.stateDir, configPath, configName: ident.configName, file: file2, badArgs };
30534
30547
  }
30535
- if (!stateDir) stateDir = process.env.ENGINE_STATE_DIR || path39.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
30548
+ if (!stateDir) stateDir = process.env.ENGINE_STATE_DIR || path40.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
30536
30549
  const configName = CONFIG_NAME;
30537
- return { stateDir, configPath: path39.join(stateDir, "configs", `${configName}.json`), configName, file: file2, badArgs };
30550
+ return { stateDir, configPath: path40.join(stateDir, "configs", `${configName}.json`), configName, file: file2, badArgs };
30538
30551
  }
30539
30552
  function emit2(obj) {
30540
30553
  process.stdout.write(JSON.stringify(obj) + "\n");
@@ -30572,7 +30585,7 @@ function shapeOf(v) {
30572
30585
  function readConfigObject(configPath) {
30573
30586
  let text;
30574
30587
  try {
30575
- text = fs39.readFileSync(configPath, "utf-8");
30588
+ text = fs40.readFileSync(configPath, "utf-8");
30576
30589
  } catch {
30577
30590
  return { obj: {}, corrupt: false };
30578
30591
  }
@@ -30630,7 +30643,7 @@ function findMaskedCredentials(value, prefix, out) {
30630
30643
  function readEnvKeys(file2) {
30631
30644
  const out = [];
30632
30645
  try {
30633
- for (const line of fs39.readFileSync(file2, "utf-8").split("\n")) {
30646
+ for (const line of fs40.readFileSync(file2, "utf-8").split("\n")) {
30634
30647
  const t = line.trim();
30635
30648
  if (!t || t.startsWith("#")) continue;
30636
30649
  const eq = t.indexOf("=");
@@ -30686,7 +30699,7 @@ async function runConfigCommand(args) {
30686
30699
  }
30687
30700
  let parsedPayload;
30688
30701
  try {
30689
- parsedPayload = JSON.parse(fs39.readFileSync(p.file, "utf-8"));
30702
+ parsedPayload = JSON.parse(fs40.readFileSync(p.file, "utf-8"));
30690
30703
  } catch (e) {
30691
30704
  process.stderr.write(`[config] \u8BFB\u4E0D\u4E86 payload: ${e.message}
30692
30705
  `);
@@ -30792,7 +30805,7 @@ async function runConfigCommand(args) {
30792
30805
  }
30793
30806
  if (secretWrites.length > 0) {
30794
30807
  const writePath2 = resolveSecretPath(p.stateDir, p.configName);
30795
- const fallback = fs39.existsSync(writePath2) ? void 0 : secretsCandidates(p.stateDir, p.configName).find((c) => fs39.existsSync(c));
30808
+ const fallback = fs40.existsSync(writePath2) ? void 0 : secretsCandidates(p.stateDir, p.configName).find((c) => fs40.existsSync(c));
30796
30809
  if (fallback) {
30797
30810
  const writing = new Set(secretWrites.map((s) => s.name));
30798
30811
  const others = readEnvKeys(fallback).filter((k) => !writing.has(k));
@@ -30801,11 +30814,11 @@ async function runConfigCommand(args) {
30801
30814
  }
30802
30815
  }
30803
30816
  }
30804
- if (fs39.existsSync(p.configPath) && !isNormalized(fs39.readFileSync(p.configPath, "utf-8"))) {
30817
+ if (fs40.existsSync(p.configPath) && !isNormalized(fs40.readFileSync(p.configPath, "utf-8"))) {
30805
30818
  warnings.push("config \u9996\u6B21\u89C4\u8303\u5316\uFF1A\u884C\u5C3E\u7EDF\u4E00\u4E3A LF\u3001\u7F29\u8FDB\u7EDF\u4E00\u4E3A 2 \u7A7A\u683C\uFF08\u4E00\u6B21\u6027\u5927 diff\uFF09");
30806
30819
  }
30807
- const configDir = path39.dirname(p.configPath);
30808
- if (!fs39.existsSync(configDir)) fs39.mkdirSync(configDir, { recursive: true });
30820
+ const configDir = path40.dirname(p.configPath);
30821
+ if (!fs40.existsSync(configDir)) fs40.mkdirSync(configDir, { recursive: true });
30809
30822
  try {
30810
30823
  writeConfigAtomic(p.configPath, merged);
30811
30824
  } catch (e) {
@@ -30820,7 +30833,7 @@ async function runConfigCommand(args) {
30820
30833
  warnings.push(`secrets \u5199\u5165\u5931\u8D25\uFF08${s.name}\uFF09\uFF1A${e?.message || String(e)}\u2014\u2014config \u5DF2\u5199\u5165`);
30821
30834
  }
30822
30835
  }
30823
- const workspace = path39.join(p.stateDir, "workspace");
30836
+ const workspace = path40.join(p.stateDir, "workspace");
30824
30837
  const ctx = { workspace, stateDir: p.stateDir, values: nested, all: merged, configPath: p.configPath };
30825
30838
  for (const dotPath of [...new Set(changed)]) {
30826
30839
  const migrationName = getField(dotPath)?.migration;
@@ -30909,41 +30922,41 @@ __export(cli_reconfig_exports, {
30909
30922
  doReconfigFeishu: () => doReconfigFeishu,
30910
30923
  doReconfigWechat: () => doReconfigWechat
30911
30924
  });
30912
- import * as fs40 from "node:fs";
30913
- import * as path40 from "node:path";
30925
+ import * as fs41 from "node:fs";
30926
+ import * as path41 from "node:path";
30914
30927
  function scanForChannelsConfig(configsDir) {
30915
- if (!fs40.existsSync(configsDir)) return "";
30916
- for (const f of fs40.readdirSync(configsDir).filter((x) => x.endsWith(".json"))) {
30917
- const full = path40.join(configsDir, f);
30928
+ if (!fs41.existsSync(configsDir)) return "";
30929
+ for (const f of fs41.readdirSync(configsDir).filter((x) => x.endsWith(".json"))) {
30930
+ const full = path41.join(configsDir, f);
30918
30931
  try {
30919
- if (JSON.parse(fs40.readFileSync(full, "utf8")).channels) return full;
30932
+ if (JSON.parse(fs41.readFileSync(full, "utf8")).channels) return full;
30920
30933
  } catch {
30921
30934
  }
30922
30935
  }
30923
30936
  return "";
30924
30937
  }
30925
30938
  function findFeishuConfigFile(stateDir, configName) {
30926
- const configsDir = path40.join(stateDir, "configs");
30939
+ const configsDir = path41.join(stateDir, "configs");
30927
30940
  if (configName) {
30928
- const p = path40.join(configsDir, configName);
30929
- if (fs40.existsSync(p)) return p;
30941
+ const p = path41.join(configsDir, configName);
30942
+ if (fs41.existsSync(p)) return p;
30930
30943
  }
30931
30944
  return scanForChannelsConfig(configsDir);
30932
30945
  }
30933
30946
  function findWechatConfigFile(stateDir, configName) {
30934
- const configsDir = path40.join(stateDir, "configs");
30947
+ const configsDir = path41.join(stateDir, "configs");
30935
30948
  if (configName) {
30936
- const p = path40.join(configsDir, configName);
30937
- return fs40.existsSync(p) ? p : "";
30949
+ const p = path41.join(configsDir, configName);
30950
+ return fs41.existsSync(p) ? p : "";
30938
30951
  }
30939
30952
  const scanned = scanForChannelsConfig(configsDir);
30940
30953
  if (scanned) return scanned;
30941
- if (fs40.existsSync(configsDir)) {
30942
- const candidates = fs40.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
30954
+ if (fs41.existsSync(configsDir)) {
30955
+ const candidates = fs41.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
30943
30956
  if (candidates.length) {
30944
- const first = path40.join(configsDir, candidates[0]);
30957
+ const first = path41.join(configsDir, candidates[0]);
30945
30958
  try {
30946
- JSON.parse(fs40.readFileSync(first, "utf8"));
30959
+ JSON.parse(fs41.readFileSync(first, "utf8"));
30947
30960
  return first;
30948
30961
  } catch {
30949
30962
  }
@@ -30982,11 +30995,11 @@ async function doReconfigFeishu(opts) {
30982
30995
  return 2;
30983
30996
  }
30984
30997
  const configFile = findFeishuConfigFile(stateDir, configName);
30985
- if (configFile && fs40.existsSync(configFile)) {
30998
+ if (configFile && fs41.existsSync(configFile)) {
30986
30999
  if (events) emit3?.({ event: "progress", step: "write_config" });
30987
31000
  let j;
30988
31001
  try {
30989
- j = JSON.parse(fs40.readFileSync(configFile, "utf8"));
31002
+ j = JSON.parse(fs41.readFileSync(configFile, "utf8"));
30990
31003
  } catch (err) {
30991
31004
  if (events) emit3?.({ event: "error", message: `\u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
30992
31005
  else console.error(`\u274C \u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
@@ -31004,7 +31017,7 @@ async function doReconfigFeishu(opts) {
31004
31017
  }
31005
31018
  j.channels.feishu = { enabled: true, appId: result.appId, appSecret: secretRef(feishuSecretEnv, result.appSecret), connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
31006
31019
  try {
31007
- fs40.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
31020
+ fs41.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
31008
31021
  } catch (err) {
31009
31022
  if (events) emit3?.({ event: "error", message: `\u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
31010
31023
  else console.error(`\u274C \u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
@@ -31037,7 +31050,7 @@ async function doReconfigWechat(opts) {
31037
31050
  return 2;
31038
31051
  }
31039
31052
  const configFile = findWechatConfigFile(stateDir, configName);
31040
- if (!configFile || !fs40.existsSync(configFile)) {
31053
+ if (!configFile || !fs41.existsSync(configFile)) {
31041
31054
  console.log("\n\u26A0\uFE0F \u6CA1\u627E\u5230 config \u6587\u4EF6\uFF0C\u8BF7\u624B\u52A8\u628A\u4EE5\u4E0B\u6BB5\u52A0\u8FDB\u4F60\u7684 config \u7684 channels \u91CC\uFF1A");
31042
31055
  console.log(JSON.stringify({ wechat: { enabled: true, token: cred.token, accountId: cred.accountId, dmPolicy: "pairing", group: { policy: "disabled" } } }, null, 2));
31043
31056
  if (events) emit3?.({ event: "done", channel: "wechat", detail: cred.accountId, restart_required: true });
@@ -31046,7 +31059,7 @@ async function doReconfigWechat(opts) {
31046
31059
  if (events) emit3?.({ event: "progress", step: "write_config" });
31047
31060
  let j;
31048
31061
  try {
31049
- j = JSON.parse(fs40.readFileSync(configFile, "utf8"));
31062
+ j = JSON.parse(fs41.readFileSync(configFile, "utf8"));
31050
31063
  } catch (err) {
31051
31064
  if (events) emit3?.({ event: "error", message: `\u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
31052
31065
  else console.error(`\u274C \u8BFB\u53D6 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
@@ -31064,7 +31077,7 @@ async function doReconfigWechat(opts) {
31064
31077
  }
31065
31078
  j.channels.wechat = { enabled: true, token: secretRef(wechatSecretEnv, cred.token), accountId: cred.accountId, dmPolicy: "pairing", group: { policy: "disabled" } };
31066
31079
  try {
31067
- fs40.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
31080
+ fs41.writeFileSync(configFile, JSON.stringify(j, null, 2), "utf8");
31068
31081
  } catch (err) {
31069
31082
  if (events) emit3?.({ event: "error", message: `\u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09` });
31070
31083
  else console.error(`\u274C \u5199\u5165 config \u5931\u8D25: ${configFile}\uFF08${err?.message || err}\uFF09`);
@@ -31101,20 +31114,20 @@ __export(cli_travel_exports, {
31101
31114
  resolveArchiveForTest: () => resolveArchiveForTest,
31102
31115
  saveTravelConfig: () => saveTravelConfig
31103
31116
  });
31104
- import * as path41 from "node:path";
31105
- import * as fs41 from "node:fs";
31117
+ import * as path42 from "node:path";
31118
+ import * as fs42 from "node:fs";
31106
31119
  import * as os6 from "node:os";
31107
- import { execSync as execSync2 } from "node:child_process";
31120
+ import { execSync as execSync3 } from "node:child_process";
31108
31121
  function loadTravelConfig() {
31109
31122
  try {
31110
- if (!fs41.existsSync(CONFIG_PATH)) return null;
31111
- return JSON.parse(fs41.readFileSync(CONFIG_PATH, "utf-8"));
31123
+ if (!fs42.existsSync(CONFIG_PATH)) return null;
31124
+ return JSON.parse(fs42.readFileSync(CONFIG_PATH, "utf-8"));
31112
31125
  } catch {
31113
31126
  return null;
31114
31127
  }
31115
31128
  }
31116
31129
  function saveTravelConfig(cfg) {
31117
- fs41.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
31130
+ fs42.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
31118
31131
  }
31119
31132
  function sanitizeContent(content, dirs) {
31120
31133
  let result = content;
@@ -31139,7 +31152,7 @@ function restoreContent(content, dirs) {
31139
31152
  return result;
31140
31153
  }
31141
31154
  function isTextFile(filePath) {
31142
- const ext = path41.extname(filePath).toLowerCase();
31155
+ const ext = path42.extname(filePath).toLowerCase();
31143
31156
  return TEXT_EXTENSIONS.has(ext);
31144
31157
  }
31145
31158
  function shouldExclude(name) {
@@ -31154,14 +31167,14 @@ function shouldExclude(name) {
31154
31167
  }
31155
31168
  function collectFiles(rootDir, includeSet, optionalSet) {
31156
31169
  const files = [];
31157
- const entries2 = fs41.readdirSync(rootDir, { withFileTypes: true });
31170
+ const entries2 = fs42.readdirSync(rootDir, { withFileTypes: true });
31158
31171
  for (const entry of entries2) {
31159
31172
  if (shouldExclude(entry.name)) continue;
31160
- const fullPath = path41.join(rootDir, entry.name);
31161
- const realPath = fs41.realpathSync(fullPath);
31173
+ const fullPath = path42.join(rootDir, entry.name);
31174
+ const realPath = fs42.realpathSync(fullPath);
31162
31175
  if (realPath !== fullPath) {
31163
31176
  try {
31164
- const lstat = fs41.lstatSync(fullPath);
31177
+ const lstat = fs42.lstatSync(fullPath);
31165
31178
  if (lstat.isSymbolicLink()) {
31166
31179
  continue;
31167
31180
  }
@@ -31182,12 +31195,12 @@ function collectFiles(rootDir, includeSet, optionalSet) {
31182
31195
  function collectAllFiles(dir) {
31183
31196
  const files = [];
31184
31197
  try {
31185
- const entries2 = fs41.readdirSync(dir, { withFileTypes: true });
31198
+ const entries2 = fs42.readdirSync(dir, { withFileTypes: true });
31186
31199
  for (const entry of entries2) {
31187
31200
  if (shouldExclude(entry.name)) continue;
31188
- const fullPath = path41.join(dir, entry.name);
31201
+ const fullPath = path42.join(dir, entry.name);
31189
31202
  try {
31190
- if (fs41.lstatSync(fullPath).isSymbolicLink()) continue;
31203
+ if (fs42.lstatSync(fullPath).isSymbolicLink()) continue;
31191
31204
  } catch {
31192
31205
  }
31193
31206
  if (entry.isDirectory()) {
@@ -31202,16 +31215,16 @@ function collectAllFiles(dir) {
31202
31215
  }
31203
31216
  function readMainEngineUuid(agentsDir) {
31204
31217
  try {
31205
- const platformMapPath = path41.join(agentsDir, "main", "sessions", "platform-map.json");
31206
- const indexMapPath = path41.join(agentsDir, "main", "sessions", "session-index.json");
31207
- if (!fs41.existsSync(platformMapPath) || !fs41.existsSync(indexMapPath)) return null;
31208
- const platformMap = JSON.parse(fs41.readFileSync(platformMapPath, "utf-8"));
31218
+ const platformMapPath = path42.join(agentsDir, "main", "sessions", "platform-map.json");
31219
+ const indexMapPath = path42.join(agentsDir, "main", "sessions", "session-index.json");
31220
+ if (!fs42.existsSync(platformMapPath) || !fs42.existsSync(indexMapPath)) return null;
31221
+ const platformMap = JSON.parse(fs42.readFileSync(platformMapPath, "utf-8"));
31209
31222
  const mainPlatformId = platformMap["scope:main"] || platformMap["main"];
31210
31223
  if (!mainPlatformId) return null;
31211
- const indexMap = JSON.parse(fs41.readFileSync(indexMapPath, "utf-8"));
31224
+ const indexMap = JSON.parse(fs42.readFileSync(indexMapPath, "utf-8"));
31212
31225
  const entry = indexMap[mainPlatformId];
31213
31226
  if (!entry || !entry.file) return null;
31214
- const basename10 = path41.basename(entry.file).replace(/\.jsonl$/, "");
31227
+ const basename10 = path42.basename(entry.file).replace(/\.jsonl$/, "");
31215
31228
  return basename10;
31216
31229
  } catch {
31217
31230
  return null;
@@ -31219,13 +31232,13 @@ function readMainEngineUuid(agentsDir) {
31219
31232
  }
31220
31233
  function collectRecentSessions(agentsDir, _days = 7) {
31221
31234
  const files = [];
31222
- if (!fs41.existsSync(agentsDir)) return files;
31235
+ if (!fs42.existsSync(agentsDir)) return files;
31223
31236
  const sessionGroups = /* @__PURE__ */ new Map();
31224
31237
  function scanSessionsDir(dir) {
31225
31238
  try {
31226
- const entries2 = fs41.readdirSync(dir, { withFileTypes: true });
31239
+ const entries2 = fs42.readdirSync(dir, { withFileTypes: true });
31227
31240
  for (const entry of entries2) {
31228
- const fullPath = path41.join(dir, entry.name);
31241
+ const fullPath = path42.join(dir, entry.name);
31229
31242
  if (entry.isDirectory()) {
31230
31243
  scanSessionsDir(fullPath);
31231
31244
  continue;
@@ -31249,7 +31262,7 @@ function collectRecentSessions(agentsDir, _days = 7) {
31249
31262
  if (entry.name.endsWith(".jsonl")) {
31250
31263
  group.jsonl = fullPath;
31251
31264
  } else {
31252
- const stat4 = fs41.statSync(fullPath);
31265
+ const stat4 = fs42.statSync(fullPath);
31253
31266
  group.archived.push({ file: fullPath, mtime: stat4.mtimeMs });
31254
31267
  }
31255
31268
  }
@@ -31268,21 +31281,21 @@ function collectRecentSessions(agentsDir, _days = 7) {
31268
31281
  }
31269
31282
  function collectExportFileSet(stateDir, workspace) {
31270
31283
  const wsFiles = collectFiles(workspace, WORKSPACE_INCLUDE, WORKSPACE_OPTIONAL);
31271
- const sessionFiles = collectRecentSessions(path41.join(stateDir, "agents"), 7);
31272
- const configsDir = path41.join(stateDir, "configs");
31284
+ const sessionFiles = collectRecentSessions(path42.join(stateDir, "agents"), 7);
31285
+ const configsDir = path42.join(stateDir, "configs");
31273
31286
  const configFiles = [];
31274
- if (fs41.existsSync(configsDir)) {
31287
+ if (fs42.existsSync(configsDir)) {
31275
31288
  for (const f of collectAllFiles(configsDir)) {
31276
- if (shouldExclude(path41.basename(f))) continue;
31289
+ if (shouldExclude(path42.basename(f))) continue;
31277
31290
  configFiles.push(f);
31278
31291
  }
31279
31292
  }
31280
31293
  const EVEROS_SKIP = /* @__PURE__ */ new Set([".tmp", ".lock", "import.log", "import_progress.json"]);
31281
- const everosDir = path41.join(stateDir, ".everos");
31294
+ const everosDir = path42.join(stateDir, ".everos");
31282
31295
  const everosFiles = [];
31283
- if (fs41.existsSync(everosDir)) {
31296
+ if (fs42.existsSync(everosDir)) {
31284
31297
  for (const f of collectAllFiles(everosDir)) {
31285
- if (EVEROS_SKIP.has(path41.basename(f))) continue;
31298
+ if (EVEROS_SKIP.has(path42.basename(f))) continue;
31286
31299
  everosFiles.push(f);
31287
31300
  }
31288
31301
  }
@@ -31290,13 +31303,13 @@ function collectExportFileSet(stateDir, workspace) {
31290
31303
  }
31291
31304
  async function doExport(opts) {
31292
31305
  const { agentName, stateDir, note, dryRun: dryRun2 } = opts;
31293
- const workspace = (opts.workspace || path41.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
31294
- const engineHome = path41.join(os6.homedir(), ".engine7").replace(/[/\\]+$/, "");
31306
+ const workspace = (opts.workspace || path42.join(stateDir, "workspace")).replace(/[/\\]+$/, "");
31307
+ const engineHome = path42.join(os6.homedir(), ".engine7").replace(/[/\\]+$/, "");
31295
31308
  console.log(`\u{1F4E6} engine7 export`);
31296
31309
  console.log(` agent: ${agentName}`);
31297
31310
  console.log(` state: ${stateDir}`);
31298
31311
  console.log(` workspace: ${workspace}`);
31299
- if (!fs41.existsSync(workspace)) {
31312
+ if (!fs42.existsSync(workspace)) {
31300
31313
  console.error(`\u274C workspace \u4E0D\u5B58\u5728: ${workspace}`);
31301
31314
  process.exit(1);
31302
31315
  }
@@ -31305,16 +31318,16 @@ async function doExport(opts) {
31305
31318
  console.log(` workspace \u6587\u4EF6: ${wsFiles.length}`);
31306
31319
  console.log(` session jsonl: ${sessionFiles.length} (\u6700\u8FD17\u5929)`);
31307
31320
  console.log(` configs: ${configFiles.length}`);
31308
- console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s + fs41.statSync(f).size, 0) / 1024 / 1024).toFixed(1)} MB)`);
31321
+ console.log(` everos: ${everosFiles.length} (${(everosFiles.reduce((s, f) => s + fs42.statSync(f).size, 0) / 1024 / 1024).toFixed(1)} MB)`);
31309
31322
  if (dryRun2) {
31310
31323
  console.log(`
31311
31324
  [DRY RUN] \u4F1A\u6253\u5305\u4EE5\u4E0B\u6587\u4EF6:`);
31312
- wsFiles.slice(0, 20).forEach((f) => console.log(` ${path41.relative(workspace, f)}`));
31325
+ wsFiles.slice(0, 20).forEach((f) => console.log(` ${path42.relative(workspace, f)}`));
31313
31326
  if (wsFiles.length > 20) console.log(` ... \u8FD8\u6709 ${wsFiles.length - 20} \u4E2A\u6587\u4EF6`);
31314
31327
  if (everosFiles.length > 0) {
31315
31328
  console.log(`
31316
31329
  [DRY RUN] everos (${everosFiles.length} \u6587\u4EF6):`);
31317
- everosFiles.slice(0, 10).forEach((f) => console.log(` ${path41.relative(stateDir, f)}`));
31330
+ everosFiles.slice(0, 10).forEach((f) => console.log(` ${path42.relative(stateDir, f)}`));
31318
31331
  if (everosFiles.length > 10) console.log(` ... \u8FD8\u6709 ${everosFiles.length - 10} \u4E2A\u6587\u4EF6`);
31319
31332
  }
31320
31333
  console.log(`
@@ -31322,46 +31335,46 @@ async function doExport(opts) {
31322
31335
  return;
31323
31336
  }
31324
31337
  const version = formatLog().replace(/[-: ]/g, "").slice(0, 12).replace(/(d{8})(d{4})/, "$1-$2");
31325
- const tmpDir = path41.join(os6.tmpdir(), `engine7-export-${agentName}-${version}`);
31326
- fs41.mkdirSync(tmpDir, { recursive: true });
31327
- const stagingDir = path41.join(tmpDir, agentName);
31328
- fs41.mkdirSync(stagingDir, { recursive: true });
31338
+ const tmpDir = path42.join(os6.tmpdir(), `engine7-export-${agentName}-${version}`);
31339
+ fs42.mkdirSync(tmpDir, { recursive: true });
31340
+ const stagingDir = path42.join(tmpDir, agentName);
31341
+ fs42.mkdirSync(stagingDir, { recursive: true });
31329
31342
  let fileCount = 0;
31330
31343
  let totalSize = 0;
31331
31344
  let copyFail = 0;
31332
31345
  const copyOne = (srcFile, relRoot, destRoot) => {
31333
- const relPath = path41.relative(relRoot, srcFile);
31334
- const destFile = path41.join(destRoot, relPath);
31335
- fs41.mkdirSync(path41.dirname(destFile), { recursive: true });
31346
+ const relPath = path42.relative(relRoot, srcFile);
31347
+ const destFile = path42.join(destRoot, relPath);
31348
+ fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
31336
31349
  try {
31337
31350
  if (isTextFile(srcFile)) {
31338
- const content = fs41.readFileSync(srcFile, "utf-8");
31339
- fs41.writeFileSync(destFile, sanitizeContent(content, dirs));
31351
+ const content = fs42.readFileSync(srcFile, "utf-8");
31352
+ fs42.writeFileSync(destFile, sanitizeContent(content, dirs));
31340
31353
  } else {
31341
- fs41.copyFileSync(srcFile, destFile);
31354
+ fs42.copyFileSync(srcFile, destFile);
31342
31355
  }
31343
31356
  fileCount++;
31344
- totalSize += fs41.statSync(srcFile).size;
31357
+ totalSize += fs42.statSync(srcFile).size;
31345
31358
  } catch (e) {
31346
31359
  copyFail++;
31347
31360
  console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
31348
31361
  }
31349
31362
  };
31350
- for (const srcFile of wsFiles) copyOne(srcFile, workspace, path41.join(stagingDir, "workspace"));
31363
+ for (const srcFile of wsFiles) copyOne(srcFile, workspace, path42.join(stagingDir, "workspace"));
31351
31364
  for (const srcFile of sessionFiles) {
31352
- const relPath = path41.relative(stateDir, srcFile);
31353
- const destFile = path41.join(stagingDir, relPath);
31354
- fs41.mkdirSync(path41.dirname(destFile), { recursive: true });
31365
+ const relPath = path42.relative(stateDir, srcFile);
31366
+ const destFile = path42.join(stagingDir, relPath);
31367
+ fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
31355
31368
  try {
31356
- let content = fs41.readFileSync(srcFile, "utf-8");
31369
+ let content = fs42.readFileSync(srcFile, "utf-8");
31357
31370
  content = sanitizeContent(content, dirs);
31358
- const baseName = path41.basename(srcFile);
31371
+ const baseName = path42.basename(srcFile);
31359
31372
  if (baseName === "session-index.json" || baseName === "platform-map.json") {
31360
31373
  content = content.split("\\\\").join("/");
31361
31374
  }
31362
- fs41.writeFileSync(destFile, content);
31375
+ fs42.writeFileSync(destFile, content);
31363
31376
  fileCount++;
31364
- totalSize += fs41.statSync(srcFile).size;
31377
+ totalSize += fs42.statSync(srcFile).size;
31365
31378
  } catch (e) {
31366
31379
  copyFail++;
31367
31380
  console.warn(` \u26A0\uFE0F \u62F7\u8D1D\u5931\u8D25: ${relPath} (${e.code || e.message})`);
@@ -31383,13 +31396,13 @@ async function doExport(opts) {
31383
31396
  totalSize,
31384
31397
  note
31385
31398
  };
31386
- fs41.writeFileSync(path41.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2));
31387
- const archiveFile = path41.join(tmpDir, `${agentName}-${version}.tar.gz`);
31399
+ fs42.writeFileSync(path42.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2));
31400
+ const archiveFile = path42.join(tmpDir, `${agentName}-${version}.tar.gz`);
31388
31401
  console.log(`
31389
31402
  \u{1F5DC}\uFE0F \u6253\u5305\u4E2D...`);
31390
31403
  const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
31391
- execSync2(`"${tarExe}" -czf "${archiveFile}" -C "${tmpDir}" ${agentName}`, { stdio: "pipe" });
31392
- const archiveSize = fs41.statSync(archiveFile).size;
31404
+ execSync3(`"${tarExe}" -czf "${archiveFile}" -C "${tmpDir}" ${agentName}`, { stdio: "pipe" });
31405
+ const archiveSize = fs42.statSync(archiveFile).size;
31393
31406
  console.log(`\u2705 \u6253\u5305\u5B8C\u6210: ${archiveFile} (${(archiveSize / 1024 / 1024).toFixed(1)} MB, ${fileCount} \u6587\u4EF6${copyFail ? `, \u5931\u8D25 ${copyFail}` : ""})`);
31394
31407
  const cfg = loadTravelConfig();
31395
31408
  if (!cfg || !cfg.githubToken) {
@@ -31415,12 +31428,12 @@ function parseImportArgs(args) {
31415
31428
  else if (args[i] === "--dry-run") dryRun2 = true;
31416
31429
  }
31417
31430
  if (!stateDir) throw new Error("import \u9700\u8981 --state-dir <path>");
31418
- if (!agentName) agentName = path41.basename(stateDir);
31431
+ if (!agentName) agentName = path42.basename(stateDir);
31419
31432
  return { stateDir, agentName, version, archiveFile, dryRun: dryRun2 };
31420
31433
  }
31421
31434
  async function resolveArchiveForTest(opts) {
31422
31435
  if (opts.archiveFile) {
31423
- if (!fs41.existsSync(opts.archiveFile)) {
31436
+ if (!fs42.existsSync(opts.archiveFile)) {
31424
31437
  throw new Error(`\u672C\u5730\u5305\u4E0D\u5B58\u5728: ${opts.archiveFile}`);
31425
31438
  }
31426
31439
  return opts.archiveFile;
@@ -31432,8 +31445,8 @@ async function doImport(opts) {
31432
31445
  console.log(`\u{1F4E5} engine7 import`);
31433
31446
  console.log(` agent: ${agentName}`);
31434
31447
  console.log(` target: ${stateDir}`);
31435
- const tmpDir = path41.join(os6.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
31436
- fs41.mkdirSync(tmpDir, { recursive: true });
31448
+ const tmpDir = path42.join(os6.tmpdir(), `engine7-import-${agentName}-${Date.now()}`);
31449
+ fs42.mkdirSync(tmpDir, { recursive: true });
31437
31450
  const resolved = await resolveArchiveForTest({
31438
31451
  archiveFile: archiveFile || "",
31439
31452
  tmpDir,
@@ -31457,100 +31470,100 @@ async function doImport(opts) {
31457
31470
  }
31458
31471
  console.log(`\u{1F4C2} \u89E3\u5305\u4E2D...`);
31459
31472
  const tarExe = process.platform === "win32" ? "C:\\Windows\\System32\\tar.exe" : "tar";
31460
- execSync2(`"${tarExe}" -xzf "${finalArchive}" -C "${tmpDir}"`, { stdio: "pipe" });
31461
- const stagingDir = path41.join(tmpDir, agentName);
31462
- const manifestPath = path41.join(stagingDir, "manifest.json");
31463
- if (!fs41.existsSync(manifestPath)) {
31473
+ execSync3(`"${tarExe}" -xzf "${finalArchive}" -C "${tmpDir}"`, { stdio: "pipe" });
31474
+ const stagingDir = path42.join(tmpDir, agentName);
31475
+ const manifestPath = path42.join(stagingDir, "manifest.json");
31476
+ if (!fs42.existsSync(manifestPath)) {
31464
31477
  console.error(`\u274C manifest.json \u4E0D\u5B58\u5728\uFF0C\u6587\u4EF6\u53EF\u80FD\u635F\u574F`);
31465
31478
  process.exit(1);
31466
31479
  }
31467
- const manifest = JSON.parse(fs41.readFileSync(manifestPath, "utf-8"));
31468
- const workspace = path41.join(stateDir, "workspace").replace(/\\/g, "/").replace(/[/\\]+$/, "");
31469
- const engineHome = path41.join(os6.homedir(), ".engine7").replace(/\\/g, "/").replace(/[/\\]+$/, "");
31480
+ const manifest = JSON.parse(fs42.readFileSync(manifestPath, "utf-8"));
31481
+ const workspace = path42.join(stateDir, "workspace").replace(/\\/g, "/").replace(/[/\\]+$/, "");
31482
+ const engineHome = path42.join(os6.homedir(), ".engine7").replace(/\\/g, "/").replace(/[/\\]+$/, "");
31470
31483
  const dirs = { workspace, stateDir: stateDir.replace(/\\/g, "/").replace(/[/\\]+$/, ""), engineHome };
31471
31484
  console.log(` \u7248\u672C: ${manifest.version}`);
31472
31485
  console.log(` \u521B\u5EFA: ${manifest.createdAt}`);
31473
31486
  console.log(` \u6587\u4EF6\u6570: ${manifest.fileCount}`);
31474
- const wsStaging = path41.join(stagingDir, "workspace");
31487
+ const wsStaging = path42.join(stagingDir, "workspace");
31475
31488
  let restoredCount = 0;
31476
31489
  let skipCount = 0;
31477
- if (fs41.existsSync(wsStaging)) {
31490
+ if (fs42.existsSync(wsStaging)) {
31478
31491
  const allFiles = collectAllFiles(wsStaging);
31479
31492
  for (const srcFile of allFiles) {
31480
- const relPath = path41.relative(wsStaging, srcFile);
31481
- const destFile = path41.join(workspace, relPath);
31482
- fs41.mkdirSync(path41.dirname(destFile), { recursive: true });
31493
+ const relPath = path42.relative(wsStaging, srcFile);
31494
+ const destFile = path42.join(workspace, relPath);
31495
+ fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
31483
31496
  try {
31484
31497
  if (isTextFile(srcFile)) {
31485
- const content = fs41.readFileSync(srcFile, "utf-8");
31486
- fs41.writeFileSync(destFile, restoreContent(content, dirs));
31498
+ const content = fs42.readFileSync(srcFile, "utf-8");
31499
+ fs42.writeFileSync(destFile, restoreContent(content, dirs));
31487
31500
  } else {
31488
- fs41.copyFileSync(srcFile, destFile);
31501
+ fs42.copyFileSync(srcFile, destFile);
31489
31502
  }
31490
31503
  restoredCount++;
31491
31504
  } catch (e) {
31492
31505
  skipCount++;
31493
- console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path41.relative(wsStaging, srcFile)} (${e.code || e.message})`);
31506
+ console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path42.relative(wsStaging, srcFile)} (${e.code || e.message})`);
31494
31507
  }
31495
31508
  }
31496
31509
  }
31497
- const agentsStaging = path41.join(stagingDir, "agents");
31498
- if (fs41.existsSync(agentsStaging)) {
31510
+ const agentsStaging = path42.join(stagingDir, "agents");
31511
+ if (fs42.existsSync(agentsStaging)) {
31499
31512
  const sessionFiles = collectAllFiles(agentsStaging);
31500
31513
  for (const srcFile of sessionFiles) {
31501
- const relPath = path41.relative(stagingDir, srcFile);
31502
- const destFile = path41.join(stateDir, relPath);
31503
- fs41.mkdirSync(path41.dirname(destFile), { recursive: true });
31504
- const content = fs41.readFileSync(srcFile, "utf-8");
31505
- fs41.writeFileSync(destFile, restoreContent(content, dirs));
31514
+ const relPath = path42.relative(stagingDir, srcFile);
31515
+ const destFile = path42.join(stateDir, relPath);
31516
+ fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
31517
+ const content = fs42.readFileSync(srcFile, "utf-8");
31518
+ fs42.writeFileSync(destFile, restoreContent(content, dirs));
31506
31519
  restoredCount++;
31507
31520
  }
31508
31521
  }
31509
- const configsStaging = path41.join(stagingDir, "configs");
31510
- if (fs41.existsSync(configsStaging)) {
31522
+ const configsStaging = path42.join(stagingDir, "configs");
31523
+ if (fs42.existsSync(configsStaging)) {
31511
31524
  const cfgFiles = collectAllFiles(configsStaging);
31512
31525
  for (const srcFile of cfgFiles) {
31513
- const relPath = path41.relative(stagingDir, srcFile);
31514
- const destFile = path41.join(stateDir, relPath);
31515
- fs41.mkdirSync(path41.dirname(destFile), { recursive: true });
31526
+ const relPath = path42.relative(stagingDir, srcFile);
31527
+ const destFile = path42.join(stateDir, relPath);
31528
+ fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
31516
31529
  if (isTextFile(srcFile)) {
31517
- const content = fs41.readFileSync(srcFile, "utf-8");
31518
- fs41.writeFileSync(destFile, restoreContent(content, dirs));
31530
+ const content = fs42.readFileSync(srcFile, "utf-8");
31531
+ fs42.writeFileSync(destFile, restoreContent(content, dirs));
31519
31532
  } else {
31520
- fs41.copyFileSync(srcFile, destFile);
31533
+ fs42.copyFileSync(srcFile, destFile);
31521
31534
  }
31522
31535
  restoredCount++;
31523
31536
  }
31524
31537
  }
31525
- const everosStaging = path41.join(stagingDir, ".everos");
31526
- if (fs41.existsSync(everosStaging)) {
31538
+ const everosStaging = path42.join(stagingDir, ".everos");
31539
+ if (fs42.existsSync(everosStaging)) {
31527
31540
  const everosFiles = collectAllFiles(everosStaging);
31528
31541
  for (const srcFile of everosFiles) {
31529
- const relPath = path41.relative(stagingDir, srcFile);
31530
- const destFile = path41.join(stateDir, relPath);
31531
- fs41.mkdirSync(path41.dirname(destFile), { recursive: true });
31542
+ const relPath = path42.relative(stagingDir, srcFile);
31543
+ const destFile = path42.join(stateDir, relPath);
31544
+ fs42.mkdirSync(path42.dirname(destFile), { recursive: true });
31532
31545
  try {
31533
31546
  if (isTextFile(srcFile)) {
31534
- const content = fs41.readFileSync(srcFile, "utf-8");
31535
- fs41.writeFileSync(destFile, restoreContent(content, dirs));
31547
+ const content = fs42.readFileSync(srcFile, "utf-8");
31548
+ fs42.writeFileSync(destFile, restoreContent(content, dirs));
31536
31549
  } else {
31537
- fs41.copyFileSync(srcFile, destFile);
31550
+ fs42.copyFileSync(srcFile, destFile);
31538
31551
  }
31539
31552
  restoredCount++;
31540
31553
  } catch (e) {
31541
31554
  skipCount++;
31542
- console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path41.relative(everosStaging, srcFile)} (${e.code || e.message})`);
31555
+ console.log(` \u26A0\uFE0F \u8DF3\u8FC7: ${path42.relative(everosStaging, srcFile)} (${e.code || e.message})`);
31543
31556
  }
31544
31557
  }
31545
31558
  console.log(` everos: ${everosFiles.length} \u6587\u4EF6\u5DF2\u6062\u590D`);
31546
31559
  }
31547
31560
  console.log(`\u2705 \u6062\u590D\u5B8C\u6210: ${restoredCount} \u6587\u4EF6 \u2192 ${stateDir}${skipCount ? ` (\u8DF3\u8FC7 ${skipCount})` : ""}`);
31548
31561
  const platformConfigName = process.platform === "darwin" ? "xiaoke-mac.json" : "xiaoke-win.json";
31549
- const restoredConfigPath = path41.join(stateDir, "configs", platformConfigName);
31550
- const configToUse = fs41.existsSync(restoredConfigPath) ? restoredConfigPath : path41.join(stateDir, "configs", "xiaoke.json");
31562
+ const restoredConfigPath = path42.join(stateDir, "configs", platformConfigName);
31563
+ const configToUse = fs42.existsSync(restoredConfigPath) ? restoredConfigPath : path42.join(stateDir, "configs", "xiaoke.json");
31551
31564
  console.log(`
31552
31565
  \u{1F4A1} \u4E0B\u4E00\u6B65: engine7 start --config "${configToUse}"`);
31553
- fs41.rmSync(tmpDir, { recursive: true, force: true });
31566
+ fs42.rmSync(tmpDir, { recursive: true, force: true });
31554
31567
  }
31555
31568
  async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
31556
31569
  const repo = `${cfg.githubOwner}/${cfg.repoName}`;
@@ -31580,8 +31593,8 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
31580
31593
  }
31581
31594
  const release2 = await createRes.json();
31582
31595
  const uploadUrl = release2.upload_url.replace("{?name,label}", "");
31583
- const fileBuffer = fs41.readFileSync(archiveFile);
31584
- const fileName = path41.basename(archiveFile);
31596
+ const fileBuffer = fs42.readFileSync(archiveFile);
31597
+ const fileName = path42.basename(archiveFile);
31585
31598
  const uploadRes = await fetch(`${uploadUrl}?name=${fileName}`, {
31586
31599
  method: "POST",
31587
31600
  headers: {
@@ -31604,7 +31617,7 @@ async function uploadToGitHub(cfg, archiveFile, agentName, version, manifest) {
31604
31617
  throw e;
31605
31618
  }
31606
31619
  try {
31607
- fs41.rmSync(path41.dirname(archiveFile), { recursive: true, force: true });
31620
+ fs42.rmSync(path42.dirname(archiveFile), { recursive: true, force: true });
31608
31621
  } catch {
31609
31622
  }
31610
31623
  }
@@ -31636,8 +31649,8 @@ async function downloadFromGitHub(cfg, agentName, version, destDir) {
31636
31649
  throw new Error(`\u4E0B\u8F7D asset \u5931\u8D25: ${downloadRes.status}`);
31637
31650
  }
31638
31651
  const buffer = Buffer.from(await downloadRes.arrayBuffer());
31639
- const archiveFile = path41.join(destDir, asset.name);
31640
- fs41.writeFileSync(archiveFile, buffer);
31652
+ const archiveFile = path42.join(destDir, asset.name);
31653
+ fs42.writeFileSync(archiveFile, buffer);
31641
31654
  return archiveFile;
31642
31655
  }
31643
31656
  async function getLatestReleaseTag(cfg, agentName) {
@@ -31663,7 +31676,7 @@ var init_cli_travel = __esm({
31663
31676
  "src/cli-travel.ts"() {
31664
31677
  "use strict";
31665
31678
  init_clock();
31666
- CONFIG_PATH = path41.join(os6.homedir(), ".engine7-travel.json");
31679
+ CONFIG_PATH = path42.join(os6.homedir(), ".engine7-travel.json");
31667
31680
  PATH_PLACEHOLDERS = [
31668
31681
  { placeholder: "{{WORKSPACE}}", getOriginal: (d) => d.workspace },
31669
31682
  { placeholder: "{{ENGINE_HOME}}", getOriginal: (d) => d.engineHome },
@@ -31736,8 +31749,8 @@ var init_cli_travel = __esm({
31736
31749
  });
31737
31750
 
31738
31751
  // src/cli-init.ts
31739
- import * as path42 from "node:path";
31740
- import * as fs42 from "node:fs";
31752
+ import * as path43 from "node:path";
31753
+ import * as fs43 from "node:fs";
31741
31754
 
31742
31755
  // src/cli-service.ts
31743
31756
  function parseServiceArgs(args) {
@@ -31892,6 +31905,136 @@ function buildConfigValuesFromAnswers(stateDir, a, existing = {}) {
31892
31905
 
31893
31906
  // src/cli-init.ts
31894
31907
  init_secrets_env();
31908
+
31909
+ // src/pid-lock.ts
31910
+ import fs3 from "node:fs";
31911
+ import path3 from "node:path";
31912
+ import { execSync } from "node:child_process";
31913
+ function enginePidFile(stateDir) {
31914
+ return path3.join(stateDir, ".engine.pid");
31915
+ }
31916
+ function isEngineImage(text) {
31917
+ return /node|engine7|electron/i.test(text);
31918
+ }
31919
+ function isPidAlive(pid) {
31920
+ try {
31921
+ process.kill(pid, 0);
31922
+ return true;
31923
+ } catch {
31924
+ return false;
31925
+ }
31926
+ }
31927
+ function probeImage(pid) {
31928
+ try {
31929
+ if (process.platform === "win32") {
31930
+ return execSync(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, {
31931
+ encoding: "utf-8",
31932
+ timeout: 3e3,
31933
+ stdio: ["ignore", "pipe", "ignore"]
31934
+ });
31935
+ }
31936
+ if (process.platform === "darwin") {
31937
+ return execSync(`ps -p ${pid} -o comm=`, {
31938
+ encoding: "utf-8",
31939
+ timeout: 3e3,
31940
+ stdio: ["ignore", "pipe", "ignore"]
31941
+ });
31942
+ }
31943
+ return fs3.readFileSync(`/proc/${pid}/comm`, "utf-8");
31944
+ } catch {
31945
+ return null;
31946
+ }
31947
+ }
31948
+ function probeEngineImage(pid) {
31949
+ return isEngineImage(probeImage(pid) ?? "");
31950
+ }
31951
+ function isCliWrapperImage(text) {
31952
+ return /node/i.test(text);
31953
+ }
31954
+ function probeIsCliWrapper(pid) {
31955
+ return isCliWrapperImage(probeImage(pid) ?? "");
31956
+ }
31957
+ function readOwnEnginePidText(stateDir) {
31958
+ try {
31959
+ return fs3.readFileSync(enginePidFile(stateDir), "utf-8");
31960
+ } catch (err) {
31961
+ if (err?.code !== "ENOENT") console.warn(`[pid-lock] read lock failed: ${err.message}`);
31962
+ return null;
31963
+ }
31964
+ }
31965
+ function pickOwnEnginePid(probe) {
31966
+ const pid = parseInt((probe.pidFileContent ?? "").trim(), 10);
31967
+ if (!Number.isInteger(pid) || pid <= 0) return null;
31968
+ if (pid === probe.myPid) return null;
31969
+ if (!probe.isAlive(pid)) return null;
31970
+ if (!probe.isEngineImage(pid)) return null;
31971
+ return pid;
31972
+ }
31973
+ function ownEnginePid(stateDir, myPid = process.pid) {
31974
+ return pickOwnEnginePid({
31975
+ pidFileContent: readOwnEnginePidText(stateDir),
31976
+ myPid,
31977
+ isAlive: isPidAlive,
31978
+ isEngineImage: probeEngineImage
31979
+ });
31980
+ }
31981
+ function killOwnEngineForStateDir(stateDir) {
31982
+ const pid = ownEnginePid(stateDir);
31983
+ if (pid === null) return null;
31984
+ killTree(pid);
31985
+ return pid;
31986
+ }
31987
+ async function waitForPidGone(pid, timeoutMs = 5e3) {
31988
+ const t0 = Date.now();
31989
+ while (Date.now() - t0 < timeoutMs) {
31990
+ if (!isPidAlive(pid)) return true;
31991
+ await new Promise((r) => setTimeout(r, 100));
31992
+ }
31993
+ return !isPidAlive(pid);
31994
+ }
31995
+ function pickParentPid(procStatus, psOutput) {
31996
+ const fromProc = Number(/PPid:\s*(\d+)/.exec(procStatus ?? "")?.[1] ?? NaN);
31997
+ if (Number.isInteger(fromProc) && fromProc > 0) return fromProc;
31998
+ const fromPs = Number((psOutput ?? "").trim());
31999
+ return Number.isInteger(fromPs) && fromPs > 0 ? fromPs : 0;
32000
+ }
32001
+ function killTree(pid) {
32002
+ try {
32003
+ if (process.platform === "win32") {
32004
+ execSync(`taskkill /PID ${pid} /T /F`, { stdio: "ignore", timeout: 8e3 });
32005
+ try {
32006
+ const parentPid = parseInt(execSync(`wmic process where ProcessId=${pid} get ParentProcessId /value`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).match(/ParentProcessId=(\d+)/)?.[1] ?? "0", 10);
32007
+ if (parentPid && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
32008
+ execSync(`taskkill /PID ${parentPid} /F`, { stdio: "ignore", timeout: 3e3 });
32009
+ }
32010
+ } catch {
32011
+ }
32012
+ } else {
32013
+ process.kill(pid, "SIGKILL");
32014
+ let parentPid = 0;
32015
+ try {
32016
+ parentPid = pickParentPid(fs3.readFileSync(`/proc/${pid}/status`, "utf-8"), null);
32017
+ } catch {
32018
+ }
32019
+ if (!parentPid) {
32020
+ try {
32021
+ parentPid = pickParentPid(null, execSync(`ps -p ${pid} -o ppid=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }));
32022
+ } catch {
32023
+ }
32024
+ }
32025
+ if (parentPid > 1 && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
32026
+ try {
32027
+ process.kill(parentPid, "SIGKILL");
32028
+ } catch {
32029
+ }
32030
+ }
32031
+ }
32032
+ } catch (err) {
32033
+ console.warn(`[pid-lock] kill ${pid} failed: ${err.message}`);
32034
+ }
32035
+ }
32036
+
32037
+ // src/cli-init.ts
31895
32038
  init_clock();
31896
32039
  init_cli_init_config();
31897
32040
  init_registry();
@@ -31910,7 +32053,7 @@ function describeCurrentToken(v) {
31910
32053
  return /^(?:env:|{{\s*)[A-Z0-9_]+/.test(v) ? "\u5DF2\u5B58\u5728 secrets \u4E2D" : v.slice(0, 12) + "...";
31911
32054
  }
31912
32055
  var __filename2 = fileURLToPath7(import.meta.url);
31913
- var __dirname = path42.dirname(__filename2);
32056
+ var __dirname = path43.dirname(__filename2);
31914
32057
  function parseArgs2() {
31915
32058
  const args = process.argv.slice(2);
31916
32059
  let stateDir = "";
@@ -31937,10 +32080,10 @@ function parseArgs2() {
31937
32080
  }
31938
32081
  }
31939
32082
  if (!stateDir) {
31940
- stateDir = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
32083
+ stateDir = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
31941
32084
  console.log(` \u4F7F\u7528\u9ED8\u8BA4\u76EE\u5F55: ${stateDir}`);
31942
32085
  }
31943
- stateDir = path42.resolve(stateDir);
32086
+ stateDir = path43.resolve(stateDir);
31944
32087
  return { stateDir, quick, dryRun: dryRun2, force, answersPath };
31945
32088
  }
31946
32089
  function printHelp() {
@@ -32061,16 +32204,16 @@ function getDefaultValues(stateDir) {
32061
32204
  };
32062
32205
  }
32063
32206
  function loadExistingValues(stateDir) {
32064
- const configPath = path42.join(stateDir, "configs", "main7.json");
32207
+ const configPath = path43.join(stateDir, "configs", "main7.json");
32065
32208
  try {
32066
- if (!fs42.existsSync(configPath)) return {};
32067
- const j = JSON.parse(fs42.readFileSync(configPath, "utf8"));
32209
+ if (!fs43.existsSync(configPath)) return {};
32210
+ const j = JSON.parse(fs43.readFileSync(configPath, "utf8"));
32068
32211
  const out = {};
32069
32212
  if (typeof j.timezone === "string" && j.timezone) out.timezone = j.timezone;
32070
32213
  if (j.agents?.defaults?.name) out.agentName = j.agents.defaults.name;
32071
32214
  if (j.agents?.defaults?.persona) out.persona = j.agents.defaults.persona;
32072
32215
  try {
32073
- const wm = fs42.readFileSync(path42.join(stateDir, "workspace", ".work-mode"), "utf8").trim();
32216
+ const wm = fs43.readFileSync(path43.join(stateDir, "workspace", ".work-mode"), "utf8").trim();
32074
32217
  if (wm === "on") out.chatMode = "work";
32075
32218
  else if (wm === "off") out.chatMode = "emotion";
32076
32219
  } catch {
@@ -32127,8 +32270,8 @@ function readSecretsValue(stateDir, envName) {
32127
32270
  try {
32128
32271
  const cfgBase = "main7";
32129
32272
  for (const p of secretsCandidates(stateDir, cfgBase)) {
32130
- if (fs42.existsSync(p)) {
32131
- for (const line of fs42.readFileSync(p, "utf8").split("\n")) {
32273
+ if (fs43.existsSync(p)) {
32274
+ for (const line of fs43.readFileSync(p, "utf8").split("\n")) {
32132
32275
  const eq = line.indexOf("=");
32133
32276
  if (eq > 0 && line.slice(0, eq).trim() === envName) {
32134
32277
  return line.slice(eq + 1).trim();
@@ -32362,29 +32505,29 @@ async function configureWechat(rl, v) {
32362
32505
  }
32363
32506
  function buildDirTree(v) {
32364
32507
  const d = v.stateDir;
32365
- const w = path42.join(d, "workspace");
32508
+ const w = path43.join(d, "workspace");
32366
32509
  return [
32367
32510
  // 目录
32368
- { path: path42.join(d, "configs"), type: "dir" },
32369
- { path: path42.join(d, "state", "agents", "main", "sessions"), type: "dir" },
32370
- { path: path42.join(w, "prompts"), type: "dir" },
32371
- { path: path42.join(w, "memory", "daily"), type: "dir" },
32372
- { path: path42.join(w, "docs", "research"), type: "dir" },
32373
- { path: path42.join(w, "docs", "todo"), type: "dir" },
32374
- { path: path42.join(w, "docs", "decisions"), type: "dir" },
32375
- { path: path42.join(w, "docs", "knowledge"), type: "dir" },
32376
- { path: path42.join(w, "docs", "sop"), type: "dir" },
32377
- { path: path42.join(d, "logs"), type: "dir" },
32378
- { path: path42.join(d, "media", "inbound"), type: "dir" },
32511
+ { path: path43.join(d, "configs"), type: "dir" },
32512
+ { path: path43.join(d, "state", "agents", "main", "sessions"), type: "dir" },
32513
+ { path: path43.join(w, "prompts"), type: "dir" },
32514
+ { path: path43.join(w, "memory", "daily"), type: "dir" },
32515
+ { path: path43.join(w, "docs", "research"), type: "dir" },
32516
+ { path: path43.join(w, "docs", "todo"), type: "dir" },
32517
+ { path: path43.join(w, "docs", "decisions"), type: "dir" },
32518
+ { path: path43.join(w, "docs", "knowledge"), type: "dir" },
32519
+ { path: path43.join(w, "docs", "sop"), type: "dir" },
32520
+ { path: path43.join(d, "logs"), type: "dir" },
32521
+ { path: path43.join(d, "media", "inbound"), type: "dir" },
32379
32522
  // workspace 文件
32380
32523
  {
32381
- path: path42.join(w, "SESSION-STATE.md"),
32524
+ path: path43.join(w, "SESSION-STATE.md"),
32382
32525
  type: "file",
32383
32526
  content: readTemplate("workspace/SESSION-STATE.md")
32384
32527
  },
32385
- { path: path42.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
32528
+ { path: path43.join(w, "HEARTBEAT.md"), type: "file", content: readTemplate("workspace/HEARTBEAT.md") },
32386
32529
  {
32387
- path: path42.join(w, "SOUL.md"),
32530
+ path: path43.join(w, "SOUL.md"),
32388
32531
  type: "file",
32389
32532
  // 0917:SOUL 按人设取模板(templates/workspace/souls/<persona>.md),
32390
32533
  // 单一人设模板缺失时回退通用骨架(workspace/SOUL.md)
@@ -32396,12 +32539,12 @@ function buildDirTree(v) {
32396
32539
  }
32397
32540
  })()
32398
32541
  },
32399
- { path: path42.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
32542
+ { path: path43.join(w, "AGENTS.md"), type: "file", content: readTemplate("workspace/AGENTS.md") },
32400
32543
  {
32401
32544
  // 0920 翀哥拍板:EMOTION.md 模板按人设装(templates/workspace/emotion/<persona>.md)
32402
32545
  // 冷启动默认带"想 TA 了就直接发(msg_send)"那段(写在每份模板 §一)
32403
32546
  // 单一人设模板缺失时回退通用骨架(emotion/_default.md)
32404
- path: path42.join(w, "EMOTION.md"),
32547
+ path: path43.join(w, "EMOTION.md"),
32405
32548
  type: "file",
32406
32549
  content: (() => {
32407
32550
  try {
@@ -32412,39 +32555,39 @@ function buildDirTree(v) {
32412
32555
  })()
32413
32556
  },
32414
32557
  {
32415
- path: path42.join(w, "prompts", "contacts.md"),
32558
+ path: path43.join(w, "prompts", "contacts.md"),
32416
32559
  type: "file",
32417
32560
  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")
32418
32561
  },
32419
- { path: path42.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
32562
+ { path: path43.join(w, "prompts", "auto-memory-instructions.md"), type: "file", content: readTemplate("workspace/prompts/auto-memory-instructions.md") },
32420
32563
  {
32421
32564
  // 0925:proactive 到期处理规则。此前仓内**零模板**——那份规则只在私有部署的
32422
32565
  // stateDir 里手工存在,装机用户吃的是引擎内置兜底文案(那份也没点名工具)。
32423
32566
  // 结果:agent 用正文写判定、不调工具,判定全部不落库。
32424
32567
  // 注意 readTemplate 找不到模板会 **throw**,所以本文件与 templates/ 下那份必须成对存在。
32425
- path: path42.join(w, "prompts", "proactive.md"),
32568
+ path: path43.join(w, "prompts", "proactive.md"),
32426
32569
  type: "file",
32427
32570
  content: readTemplate("workspace/prompts/proactive.md")
32428
32571
  },
32429
32572
  {
32430
32573
  // 0917:inner-voice 定制 prompt 按人设装(templates/workspace/inner-voice/<persona>.md)
32431
- path: path42.join(w, "prompts", "my-inner-voice.md"),
32574
+ path: path43.join(w, "prompts", "my-inner-voice.md"),
32432
32575
  type: "file",
32433
32576
  content: readTemplate(`workspace/inner-voice/${v.persona}.md`).replace(/\{\{AGENT_NAME\}\}/g, v.agentName)
32434
32577
  },
32435
- { path: path42.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" },
32436
- { path: path42.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" },
32578
+ { path: path43.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" },
32579
+ { path: path43.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" },
32437
32580
  // 情绪状态机(0917):脚本 + hook 接线 + 人设情绪表(用户在 init 选的 persona)
32438
32581
  //
32439
32582
  // 0920 起装的是 **.mjs 版**(原来是 .py,见下面 hook 命令那段)。老装机的 workspace
32440
32583
  // 里那份 .py 不动它——没被引用就不会跑,删了反而无据可查。
32441
32584
  {
32442
- path: path42.join(w, "scripts", "emotion_state_machine.mjs"),
32585
+ path: path43.join(w, "scripts", "emotion_state_machine.mjs"),
32443
32586
  type: "file",
32444
32587
  content: readTemplate("workspace/scripts/emotion_state_machine.mjs")
32445
32588
  },
32446
32589
  {
32447
- path: path42.join(w, ".hooks.json"),
32590
+ path: path43.join(w, ".hooks.json"),
32448
32591
  type: "file",
32449
32592
  content: JSON.stringify({
32450
32593
  hooks: {
@@ -32459,26 +32602,26 @@ function buildDirTree(v) {
32459
32602
  // (hook 的 env 是 {...process.env} 继承的),所以它就是个 node。
32460
32603
  // 与 `service install --node-exe` 同一个路子。
32461
32604
  // 路径两侧都加引号:stateDir 可能带空格(C:\Users\Foo Bar\...)。
32462
- { hooks: [{ type: "command", command: '"${E7_NODE}" "' + path42.join(w, "scripts", "emotion_state_machine.mjs") + '"' }] }
32605
+ { hooks: [{ type: "command", command: '"${E7_NODE}" "' + path43.join(w, "scripts", "emotion_state_machine.mjs") + '"' }] }
32463
32606
  ]
32464
32607
  }
32465
32608
  }, null, 2) + "\n"
32466
32609
  },
32467
32610
  {
32468
- path: path42.join(w, ".emotion_states.json"),
32611
+ path: path43.join(w, ".emotion_states.json"),
32469
32612
  type: "file",
32470
32613
  content: readTemplate(`workspace/emotion-states/${v.persona}.json`)
32471
32614
  },
32472
32615
  // 模式档位(0920):与 /work 命令写的是同一个文件,读端只认 on/off,
32473
32616
  // 没有这个键就是 auto。auto 刻意不写——写个 "auto" 进去反而多一种除了这里没人认得的状态。
32474
32617
  ...v.chatMode === "work" || v.chatMode === "emotion" ? [{
32475
- path: path42.join(w, ".work-mode"),
32618
+ path: path43.join(w, ".work-mode"),
32476
32619
  type: "file",
32477
32620
  content: v.chatMode === "work" ? "on" : "off"
32478
32621
  }] : [],
32479
32622
  // package.json — 让 agent 目录成为独立 npm 项目根,防止 npm hoisting
32480
32623
  {
32481
- path: path42.join(d, "package.json"),
32624
+ path: path43.join(d, "package.json"),
32482
32625
  type: "file",
32483
32626
  content: JSON.stringify({
32484
32627
  name: v.agentName.toLowerCase().replace(/[^a-z0-9-]/g, "-") || "agent",
@@ -32489,7 +32632,7 @@ function buildDirTree(v) {
32489
32632
  },
32490
32633
  // 启动脚本(根据 OS 生成)
32491
32634
  ...process.platform === "win32" ? [{
32492
- path: path42.join(d, "start.cmd"),
32635
+ path: path43.join(d, "start.cmd"),
32493
32636
  type: "file",
32494
32637
  content: `@echo off
32495
32638
  rem Engine 7 startup script
@@ -32521,7 +32664,7 @@ if %ERRORLEVEL% NEQ 0 (
32521
32664
  )
32522
32665
  `
32523
32666
  }] : [{
32524
- path: path42.join(d, "start.sh"),
32667
+ path: path43.join(d, "start.sh"),
32525
32668
  type: "file",
32526
32669
  content: `#!/bin/bash
32527
32670
  # Engine 7 startup script
@@ -32555,24 +32698,24 @@ node "$ENGINE7_BIN" --engine-config "$CFG_ABS"
32555
32698
  }
32556
32699
  function readTemplate(relativePath) {
32557
32700
  const candidates = [
32558
- path42.join(__dirname, "..", "templates", relativePath),
32559
- path42.join(__dirname, "..", "..", "templates", relativePath),
32560
- path42.join(process.cwd(), "templates", relativePath)
32701
+ path43.join(__dirname, "..", "templates", relativePath),
32702
+ path43.join(__dirname, "..", "..", "templates", relativePath),
32703
+ path43.join(process.cwd(), "templates", relativePath)
32561
32704
  ];
32562
32705
  for (const p of candidates) {
32563
- if (fs42.existsSync(p)) {
32564
- return fs42.readFileSync(p, "utf-8");
32706
+ if (fs43.existsSync(p)) {
32707
+ return fs43.readFileSync(p, "utf-8");
32565
32708
  }
32566
32709
  }
32567
32710
  throw new Error(`\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728: ${relativePath}\uFF08\u627E\u4E86: ${candidates.join(", ")}\uFF09`);
32568
32711
  }
32569
32712
  function looksLikeAppInstall(dir) {
32570
- return ["", "install"].some((sub) => fs42.existsSync(path42.join(dir, sub, "Engine7.exe")) && fs42.existsSync(path42.join(dir, sub, "resources", "engine7", "dist", "cli.mjs")));
32713
+ return ["", "install"].some((sub) => fs43.existsSync(path43.join(dir, sub, "Engine7.exe")) && fs43.existsSync(path43.join(dir, sub, "resources", "engine7", "dist", "cli.mjs")));
32571
32714
  }
32572
32715
  var PHOTO_EXTS = [".png", ".jpg", ".jpeg", ".webp"];
32573
32716
  function hasOnlyEngineBookkeeping(dir) {
32574
32717
  try {
32575
- const entries2 = fs42.readdirSync(dir);
32718
+ const entries2 = fs43.readdirSync(dir);
32576
32719
  return entries2.length > 0 && entries2.every((e) => e === "install-identity.json");
32577
32720
  } catch {
32578
32721
  return false;
@@ -32588,11 +32731,11 @@ function dryRun(entries2) {
32588
32731
  function execute(entries2) {
32589
32732
  for (const e of entries2) {
32590
32733
  if (e.type === "dir") {
32591
- fs42.mkdirSync(e.path, { recursive: true });
32734
+ fs43.mkdirSync(e.path, { recursive: true });
32592
32735
  console.log(` \u{1F4C1} ${e.path}`);
32593
32736
  } else {
32594
- fs42.mkdirSync(path42.dirname(e.path), { recursive: true });
32595
- fs42.writeFileSync(e.path, e.content || "", "utf-8");
32737
+ fs43.mkdirSync(path43.dirname(e.path), { recursive: true });
32738
+ fs43.writeFileSync(e.path, e.content || "", "utf-8");
32596
32739
  console.log(` \u{1F4C4} ${e.path}`);
32597
32740
  }
32598
32741
  }
@@ -32626,8 +32769,8 @@ async function main() {
32626
32769
  if (subcommand === "--version" || subcommand === "-v") {
32627
32770
  let ver = "unknown";
32628
32771
  try {
32629
- const pkgPath = path42.join(path42.dirname(__filename2), "..", "package.json");
32630
- ver = JSON.parse(fs42.readFileSync(pkgPath, "utf8")).version || "unknown";
32772
+ const pkgPath = path43.join(path43.dirname(__filename2), "..", "package.json");
32773
+ ver = JSON.parse(fs43.readFileSync(pkgPath, "utf8")).version || "unknown";
32631
32774
  } catch {
32632
32775
  }
32633
32776
  console.log(`engine7 ${ver}`);
@@ -32656,14 +32799,14 @@ async function main() {
32656
32799
  relay = resolveRelayUrl(relay, process.env);
32657
32800
  if (!relayFromArg) console.error(` \u4E2D\u8F6C\u7AD9: ${relay}\uFF08\u8981\u6362\u5730\u5740\u7528 --relay <\u5730\u5740>\uFF09`);
32658
32801
  const { resolveStateDirFromArgs: resolveStateDirFromArgs2 } = await Promise.resolve().then(() => (init_cli_doctor(), cli_doctor_exports));
32659
- stateDir = stateDir ? path42.resolve(stateDir) : resolveStateDirFromArgs2(args.slice(1));
32802
+ stateDir = stateDir ? path43.resolve(stateDir) : resolveStateDirFromArgs2(args.slice(1));
32660
32803
  try {
32661
32804
  const { provisionFreeToken: provisionFreeToken2 } = await Promise.resolve().then(() => (init_provision_free(), provision_free_exports));
32662
32805
  const result = await provisionFreeToken2({
32663
32806
  relayBaseUrl: relay,
32664
32807
  stateDir,
32665
32808
  // 和 init 写 config 的路径一致(cli-init.ts 里 configPath 就是这么拼的)
32666
- configPath: path42.join(stateDir, "configs", "main7.json")
32809
+ configPath: path43.join(stateDir, "configs", "main7.json")
32667
32810
  });
32668
32811
  console.log(JSON.stringify(result, null, 2));
32669
32812
  process.exit(0);
@@ -32690,18 +32833,18 @@ async function main() {
32690
32833
  else if (args[i] === "--base-url" && args[i + 1]) relayBaseUrl = args[++i].trim();
32691
32834
  }
32692
32835
  if (!stateDir) {
32693
- const cwd = path42.resolve(process.cwd());
32694
- if (fs42.existsSync(path42.join(cwd, "configs"))) {
32836
+ const cwd = path43.resolve(process.cwd());
32837
+ if (fs43.existsSync(path43.join(cwd, "configs"))) {
32695
32838
  stateDir = cwd;
32696
32839
  } else {
32697
- const pointer = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
32698
- if (fs42.existsSync(pointer)) {
32840
+ const pointer = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
32841
+ if (fs43.existsSync(pointer)) {
32699
32842
  try {
32700
- stateDir = JSON.parse(fs42.readFileSync(pointer, "utf8")).stateDir || "";
32843
+ stateDir = JSON.parse(fs43.readFileSync(pointer, "utf8")).stateDir || "";
32701
32844
  } catch {
32702
32845
  }
32703
32846
  }
32704
- if (!stateDir) stateDir = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
32847
+ if (!stateDir) stateDir = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
32705
32848
  }
32706
32849
  }
32707
32850
  if (!target && !isLegacyAddchannel) {
@@ -32721,12 +32864,12 @@ async function main() {
32721
32864
  process.exit(0);
32722
32865
  }
32723
32866
  if (channel === "channels") {
32724
- const configsDir = path42.join(stateDir, "configs");
32725
- if (fs42.existsSync(configsDir)) {
32726
- const files = fs42.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
32867
+ const configsDir = path43.join(stateDir, "configs");
32868
+ if (fs43.existsSync(configsDir)) {
32869
+ const files = fs43.readdirSync(configsDir).filter((f) => f.endsWith(".json"));
32727
32870
  for (const f of files) {
32728
32871
  try {
32729
- const j = JSON.parse(fs42.readFileSync(path42.join(configsDir, f), "utf8"));
32872
+ const j = JSON.parse(fs43.readFileSync(path43.join(configsDir, f), "utf8"));
32730
32873
  if (!j.channels) continue;
32731
32874
  console.log(`
32732
32875
  \u{1F4C4} ${f}:`);
@@ -32763,7 +32906,7 @@ async function main() {
32763
32906
  }
32764
32907
  const configFile = resolveConfigPath2(stateDir, configName);
32765
32908
  if (!configFile) {
32766
- fail2(`\u6CA1\u627E\u5230\u53EF\u6539\u7684 config\uFF1A\u5728 ${path42.join(stateDir, "configs")} \u4E0B\u65E2\u6CA1\u6709 main7.json\uFF0C\u4E5F\u6CA1\u6709\u542B models.providers \u7684 json\u3002\u7528 --config <\u6587\u4EF6\u540D> \u6307\u5B9A\u3002`);
32909
+ fail2(`\u6CA1\u627E\u5230\u53EF\u6539\u7684 config\uFF1A\u5728 ${path43.join(stateDir, "configs")} \u4E0B\u65E2\u6CA1\u6709 main7.json\uFF0C\u4E5F\u6CA1\u6709\u542B models.providers \u7684 json\u3002\u7528 --config <\u6587\u4EF6\u540D> \u6307\u5B9A\u3002`);
32767
32910
  }
32768
32911
  if (!readSecretsValue(stateDir, FREE_TIER_ENV_KEY2)) {
32769
32912
  fail2(`\u514D\u8D39\u6863\u7F3A\u5C11\u4EE4\u724C\uFF1Asecrets \u91CC\u6CA1\u6709 ${FREE_TIER_ENV_KEY2}\u3002\u5148\u9886\u53F7\uFF1A
@@ -32830,8 +32973,8 @@ async function main() {
32830
32973
  else if (args[i] === "--note" && args[i + 1]) note = args[++i];
32831
32974
  else if (args[i] === "--dry-run") dryRun2 = true;
32832
32975
  }
32833
- if (!exportStateDir) exportStateDir = path42.resolve(process.cwd());
32834
- if (!agentName) agentName = path42.basename(exportStateDir);
32976
+ if (!exportStateDir) exportStateDir = path43.resolve(process.cwd());
32977
+ if (!agentName) agentName = path43.basename(exportStateDir);
32835
32978
  await doExport2({ agentName, stateDir: exportStateDir, note, dryRun: dryRun2 });
32836
32979
  process.exit(0);
32837
32980
  }
@@ -32853,7 +32996,7 @@ async function main() {
32853
32996
  console.error("\u274C import \u9700\u8981 --state-dir <path>");
32854
32997
  process.exit(1);
32855
32998
  }
32856
- if (!agentName) agentName = path42.basename(importStateDir);
32999
+ if (!agentName) agentName = path43.basename(importStateDir);
32857
33000
  await doImport2({ agentName, stateDir: importStateDir, version, archiveFile: archiveFile || void 0, dryRun: dryRun2 });
32858
33001
  process.exit(0);
32859
33002
  }
@@ -32881,18 +33024,18 @@ engine7 start \u2014 \u542F\u52A8 Engine
32881
33024
  }
32882
33025
  }
32883
33026
  if (!configPath2) {
32884
- const defaultCfg = path42.join("configs", "main7.json");
32885
- const homeCfg = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
32886
- if (fs42.existsSync(defaultCfg)) {
33027
+ const defaultCfg = path43.join("configs", "main7.json");
33028
+ const homeCfg = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
33029
+ if (fs43.existsSync(defaultCfg)) {
32887
33030
  configPath2 = defaultCfg;
32888
- } else if (fs42.existsSync(homeCfg)) {
33031
+ } else if (fs43.existsSync(homeCfg)) {
32889
33032
  configPath2 = homeCfg;
32890
33033
  console.log(` \u4F7F\u7528\u9ED8\u8BA4 config: ${homeCfg}`);
32891
33034
  } else {
32892
33035
  const ptr = readHomePointer();
32893
33036
  if (ptr?.stateDir) {
32894
- const ptrCfg = path42.join(ptr.stateDir, "configs", "main7.json");
32895
- if (fs42.existsSync(ptrCfg)) {
33037
+ const ptrCfg = path43.join(ptr.stateDir, "configs", "main7.json");
33038
+ if (fs43.existsSync(ptrCfg)) {
32896
33039
  configPath2 = ptrCfg;
32897
33040
  console.log(` \u4F7F\u7528 config: ${ptrCfg}`);
32898
33041
  }
@@ -32905,26 +33048,26 @@ engine7 start \u2014 \u542F\u52A8 Engine
32905
33048
  }
32906
33049
  }
32907
33050
  }
32908
- if (configPath2 && !fs42.existsSync(configPath2)) {
33051
+ if (configPath2 && !fs43.existsSync(configPath2)) {
32909
33052
  console.error(`\u274C config \u6587\u4EF6\u4E0D\u5B58\u5728: ${configPath2}`);
32910
33053
  console.error(" \u7528\u6CD5: engine7 start [configs/xxx.json | --config <path>]");
32911
33054
  process.exit(1);
32912
33055
  }
32913
- const { execSync: execSync3, spawn: spawn5 } = await import("node:child_process");
33056
+ const { execSync: execSync4, spawn: spawn5 } = await import("node:child_process");
32914
33057
  let enginePath;
32915
- const localPath = path42.join("node_modules", "engine7", "dist", "main.mjs");
32916
- if (fs42.existsSync(localPath)) {
33058
+ const localPath = path43.join("node_modules", "engine7", "dist", "main.mjs");
33059
+ if (fs43.existsSync(localPath)) {
32917
33060
  enginePath = localPath;
32918
33061
  } else {
32919
- const cliPath = path42.resolve(process.argv[1]);
32920
- const distDir = path42.dirname(cliPath);
32921
- const candidate = path42.join(distDir, "main.mjs");
32922
- if (fs42.existsSync(candidate)) {
33062
+ const cliPath = path43.resolve(process.argv[1]);
33063
+ const distDir = path43.dirname(cliPath);
33064
+ const candidate = path43.join(distDir, "main.mjs");
33065
+ if (fs43.existsSync(candidate)) {
32923
33066
  enginePath = candidate;
32924
33067
  } else {
32925
33068
  try {
32926
- const globalRoot = execSync3("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
32927
- enginePath = path42.join(globalRoot, "engine7", "dist", "main.mjs");
33069
+ const globalRoot = execSync4("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
33070
+ enginePath = path43.join(globalRoot, "engine7", "dist", "main.mjs");
32928
33071
  } catch {
32929
33072
  console.error("\u274C \u627E\u4E0D\u5230 engine7 main.mjs");
32930
33073
  process.exit(1);
@@ -32934,29 +33077,23 @@ engine7 start \u2014 \u542F\u52A8 Engine
32934
33077
  console.log(label);
32935
33078
  console.log(` config: ${configPath2}`);
32936
33079
  console.log(` engine: ${enginePath}`);
32937
- const configName = path42.basename(configPath2);
32938
- const configAbs = path42.resolve(configPath2);
32939
- const myPid = process.pid;
33080
+ const configAbs = path43.resolve(configPath2);
32940
33081
  try {
32941
- if (process.platform === "win32") {
32942
- execSync3(`powershell -Command "Get-WmiObject Win32_Process | Where-Object { $_.Name -eq 'node.exe' -and $_.CommandLine.Contains('${configAbs}') -and $_.CommandLine -like '*dist*' -and $_.ProcessId -ne ${myPid} } | ForEach-Object { Write-Host '[start] Killing PID' $_.ProcessId; Stop-Process -Id $_.ProcessId -Force }"`, { stdio: "inherit" });
32943
- } else {
32944
- const psOut = execSync3(`ps -axo pid=,command= | grep -F 'dist/main.mjs' | grep -F '${configAbs}' | grep -vF 'ps -axo' | awk '{print $1}' 2>/dev/null || true`, { encoding: "utf-8" }).trim();
32945
- const otherPids = psOut.split("\n").map((p) => p.trim()).filter((p) => p && /^\d+$/.test(p) && p !== String(myPid)).join("\n").trim();
32946
- if (otherPids) {
32947
- console.log(`[start] Killing existing engine (PID: ${otherPids})...`);
32948
- execSync3(`echo "${otherPids}" | xargs kill -9 2>/dev/null || true`);
32949
- await new Promise((r) => setTimeout(r, 2e3));
32950
- }
33082
+ const stateDir = engineStateDirOfConfig(configAbs);
33083
+ const killed = stateDir ? killOwnEngineForStateDir(stateDir) : null;
33084
+ if (killed !== null) {
33085
+ console.log(`[start] Killing existing engine (PID: ${killed})...`);
33086
+ await waitForPidGone(killed);
32951
33087
  }
32952
- } catch {
33088
+ } catch (err) {
33089
+ console.warn(`[start] \u6740\u65E7\u8FDB\u7A0B\u5931\u8D25\uFF08\u4E0D\u6321\u542F\u52A8\uFF09\uFF1A${err.message}`);
32953
33090
  }
32954
33091
  console.log("");
32955
33092
  const envForChild = { ...process.env };
32956
33093
  const { stateDir: secretsStateDir, configName: secretsCfgName } = resolveConfigIdentity(configPath2);
32957
33094
  for (const secretPath of secretsCandidates(secretsStateDir, secretsCfgName)) {
32958
- if (fs42.existsSync(secretPath)) {
32959
- const content = fs42.readFileSync(secretPath, "utf-8");
33095
+ if (fs43.existsSync(secretPath)) {
33096
+ const content = fs43.readFileSync(secretPath, "utf-8");
32960
33097
  for (const line of content.split("\n")) {
32961
33098
  const trimmed = line.trim();
32962
33099
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -33004,7 +33141,6 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
33004
33141
  process.exit(0);
33005
33142
  }
33006
33143
  if (action === "reset") {
33007
- const { execSync: execSync3 } = await import("node:child_process");
33008
33144
  let configPath2 = "";
33009
33145
  let mode = "archive";
33010
33146
  let dropN = 3;
@@ -33031,14 +33167,14 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
33031
33167
  console.error(`\u274C \u672A\u77E5\u6A21\u5F0F: ${mode}\uFF08\u53EF\u9009: archive / drop-last / strip-images\uFF09`);
33032
33168
  process.exit(1);
33033
33169
  }
33034
- const configRaw = JSON.parse(fs42.readFileSync(configPath2, "utf-8"));
33170
+ const configRaw = JSON.parse(fs43.readFileSync(configPath2, "utf-8"));
33035
33171
  const stateDir = configRaw.stateDir;
33036
33172
  if (!stateDir) {
33037
33173
  console.error("\u274C config \u91CC\u6CA1\u6709 stateDir");
33038
33174
  process.exit(1);
33039
33175
  }
33040
- const sessionsDir = path42.join(stateDir, "agents", "main", "sessions");
33041
- if (!fs42.existsSync(sessionsDir)) {
33176
+ const sessionsDir = path43.join(stateDir, "agents", "main", "sessions");
33177
+ if (!fs43.existsSync(sessionsDir)) {
33042
33178
  console.error(`\u274C sessions \u76EE\u5F55\u4E0D\u5B58\u5728: ${sessionsDir}`);
33043
33179
  process.exit(1);
33044
33180
  }
@@ -33046,56 +33182,54 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
33046
33182
  console.log(` config: ${configPath2}`);
33047
33183
  console.log(` mode: ${mode}`);
33048
33184
  if (mode === "drop-last") console.log(` n: ${dropN}`);
33049
- const platformMapPath = path42.join(sessionsDir, "platform-map.json");
33050
- const indexPath = path42.join(sessionsDir, "session-index.json");
33185
+ const platformMapPath = path43.join(sessionsDir, "platform-map.json");
33186
+ const indexPath = path43.join(sessionsDir, "session-index.json");
33051
33187
  let sessionFileUUID = null;
33052
- if (fs42.existsSync(indexPath)) {
33053
- const index = JSON.parse(fs42.readFileSync(indexPath, "utf-8"));
33188
+ if (fs43.existsSync(indexPath)) {
33189
+ const index = JSON.parse(fs43.readFileSync(indexPath, "utf-8"));
33054
33190
  const entries2 = Object.values(index);
33055
33191
  if (entries2.length > 0) {
33056
33192
  const fileVal = entries2[0].file || "";
33057
- sessionFileUUID = path42.isAbsolute(fileVal) ? path42.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
33193
+ sessionFileUUID = path43.isAbsolute(fileVal) ? path43.basename(fileVal, ".jsonl") : fileVal.replace(".jsonl", "");
33058
33194
  }
33059
33195
  }
33060
33196
  if (!sessionFileUUID) {
33061
- const jsonlFiles = fs42.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs42.statSync(path42.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
33197
+ const jsonlFiles = fs43.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs43.statSync(path43.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
33062
33198
  if (jsonlFiles.length === 0) {
33063
33199
  console.error("\u274C \u627E\u4E0D\u5230\u6D3B\u8DC3\u7684 session JSONL \u6587\u4EF6");
33064
33200
  process.exit(1);
33065
33201
  }
33066
33202
  sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
33067
33203
  }
33068
- let jsonlPath = path42.join(sessionsDir, `${sessionFileUUID}.jsonl`);
33069
- if (!fs42.existsSync(jsonlPath)) {
33070
- const jsonlFiles = fs42.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs42.statSync(path42.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
33204
+ let jsonlPath = path43.join(sessionsDir, `${sessionFileUUID}.jsonl`);
33205
+ if (!fs43.existsSync(jsonlPath)) {
33206
+ const jsonlFiles = fs43.readdirSync(sessionsDir).filter((f) => f.endsWith(".jsonl") && !f.includes(".archived.") && !f.includes(".compaction.")).map((f) => ({ name: f, mtime: fs43.statSync(path43.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
33071
33207
  if (jsonlFiles.length === 0) {
33072
33208
  console.error(`\u274C JSONL \u6587\u4EF6\u4E0D\u5B58\u5728: ${jsonlPath}`);
33073
33209
  process.exit(1);
33074
33210
  }
33075
33211
  sessionFileUUID = jsonlFiles[0].name.replace(".jsonl", "");
33076
- jsonlPath = path42.join(sessionsDir, `${sessionFileUUID}.jsonl`);
33212
+ jsonlPath = path43.join(sessionsDir, `${sessionFileUUID}.jsonl`);
33077
33213
  }
33078
33214
  console.log(` file: ${jsonlPath}`);
33079
- const configName = path42.basename(configPath2);
33080
33215
  if (autoRestart) {
33081
33216
  try {
33082
- const myPid = process.pid;
33083
- const pids = execSync3(`pgrep -f "dist/main.mjs.*${configName}" 2>/dev/null || true`, { encoding: "utf-8" }).trim();
33084
- const otherPids = pids.split("\n").filter((p) => p && p.trim() !== String(myPid)).join("\n").trim();
33085
- if (otherPids) {
33217
+ const stateDir2 = engineStateDirOfConfig(path43.resolve(configPath2));
33218
+ const killed = stateDir2 ? killOwnEngineForStateDir(stateDir2) : null;
33219
+ if (killed !== null) {
33086
33220
  console.log(`
33087
- Killing engine (PID: ${otherPids})...`);
33088
- execSync3(`echo "${otherPids}" | xargs kill -9 2>/dev/null || true`);
33089
- await new Promise((r) => setTimeout(r, 2e3));
33221
+ Killing engine (PID: ${killed})...`);
33222
+ await waitForPidGone(killed);
33090
33223
  }
33091
- } catch {
33224
+ } catch (err) {
33225
+ console.warn(`[session] \u6740\u65E7\u8FDB\u7A0B\u5931\u8D25\uFF08\u4E0D\u6321\u91CD\u7F6E\uFF09\uFF1A${err.message}`);
33092
33226
  }
33093
33227
  }
33094
33228
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
33095
- const { readFileSync: readFileSync45, writeFileSync: writeFileSync26, renameSync: renameSync5 } = fs42;
33229
+ const { readFileSync: readFileSync45, writeFileSync: writeFileSync26, renameSync: renameSync5 } = fs43;
33096
33230
  if (mode === "archive") {
33097
33231
  const archiveName = `${sessionFileUUID}.jsonl.archived.${timestamp}`;
33098
- renameSync5(jsonlPath, path42.join(sessionsDir, archiveName));
33232
+ renameSync5(jsonlPath, path43.join(sessionsDir, archiveName));
33099
33233
  console.log(`
33100
33234
  \u2705 \u5F52\u6863\u5B8C\u6210: ${archiveName}`);
33101
33235
  console.log(` \u91CD\u542F\u540E\u5C06\u4ECE\u7A7A\u767D\u4F1A\u8BDD\u5F00\u59CB`);
@@ -33170,12 +33304,12 @@ engine7 session \u2014 \u4F1A\u8BDD\u7BA1\u7406\u5DE5\u5177
33170
33304
  \u2705 \u6458\u9664 ${stripped} \u884C\u56FE\u7247\u76F8\u5173\u5185\u5BB9`);
33171
33305
  }
33172
33306
  if (autoRestart) {
33173
- const realCliPath = fs42.realpathSync(process.argv[1]);
33174
- const cliDir = path42.dirname(realCliPath);
33175
- const pkgRoot = path42.resolve(cliDir, "..");
33176
- let enginePath = path42.join(pkgRoot, "dist", "main.mjs");
33177
- if (!fs42.existsSync(enginePath)) {
33178
- enginePath = path42.join(cliDir, "main.mjs");
33307
+ const realCliPath = fs43.realpathSync(process.argv[1]);
33308
+ const cliDir = path43.dirname(realCliPath);
33309
+ const pkgRoot = path43.resolve(cliDir, "..");
33310
+ let enginePath = path43.join(pkgRoot, "dist", "main.mjs");
33311
+ if (!fs43.existsSync(enginePath)) {
33312
+ enginePath = path43.join(cliDir, "main.mjs");
33179
33313
  }
33180
33314
  console.log(`
33181
33315
  \u{1F680} \u62C9\u8D77 engine...`);
@@ -33215,18 +33349,18 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
33215
33349
  let configPath2 = cfg;
33216
33350
  let cwd = svcCwd;
33217
33351
  if (!configPath2) {
33218
- const defaultCfg = path42.join(cwd, "configs", "main7.json");
33219
- const homeCfg = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
33220
- if (fs42.existsSync(defaultCfg)) {
33352
+ const defaultCfg = path43.join(cwd, "configs", "main7.json");
33353
+ const homeCfg = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7", "configs", "main7.json");
33354
+ if (fs43.existsSync(defaultCfg)) {
33221
33355
  configPath2 = defaultCfg;
33222
- } else if (fs42.existsSync(homeCfg)) {
33356
+ } else if (fs43.existsSync(homeCfg)) {
33223
33357
  configPath2 = homeCfg;
33224
- cwd = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
33358
+ cwd = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
33225
33359
  } else {
33226
33360
  const ptr = readHomePointer();
33227
33361
  if (ptr?.stateDir) {
33228
- const ptrCfg = path42.join(ptr.stateDir, "configs", "main7.json");
33229
- if (fs42.existsSync(ptrCfg)) {
33362
+ const ptrCfg = path43.join(ptr.stateDir, "configs", "main7.json");
33363
+ if (fs43.existsSync(ptrCfg)) {
33230
33364
  configPath2 = ptrCfg;
33231
33365
  cwd = ptr.stateDir;
33232
33366
  }
@@ -33239,32 +33373,32 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
33239
33373
  }
33240
33374
  }
33241
33375
  }
33242
- const { execSync: execSync3 } = await import("node:child_process");
33376
+ const { execSync: execSync4 } = await import("node:child_process");
33243
33377
  const engine7Bin = process.argv[1];
33244
33378
  if (action === "install") {
33245
33379
  if (process.platform === "win32") {
33246
33380
  const taskName = "Engine7";
33247
- const wrapperPath = path42.join(cwd, "engine7-start.cmd");
33381
+ const wrapperPath = path43.join(cwd, "engine7-start.cmd");
33248
33382
  const wrapperContent = buildServiceWrapper({
33249
33383
  cwd,
33250
33384
  nodeExe: nodeExe || void 0,
33251
- cliMjs: path42.resolve(engine7Bin),
33252
- configPath: path42.resolve(configPath2)
33385
+ cliMjs: path43.resolve(engine7Bin),
33386
+ configPath: path43.resolve(configPath2)
33253
33387
  });
33254
- fs42.writeFileSync(wrapperPath, wrapperContent);
33255
- const startupDir = path42.join(
33256
- process.env.APPDATA || path42.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
33388
+ fs43.writeFileSync(wrapperPath, wrapperContent);
33389
+ const startupDir = path43.join(
33390
+ process.env.APPDATA || path43.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
33257
33391
  "Microsoft",
33258
33392
  "Windows",
33259
33393
  "Start Menu",
33260
33394
  "Programs",
33261
33395
  "Startup"
33262
33396
  );
33263
- fs42.mkdirSync(startupDir, { recursive: true });
33264
- const vbsPath = path42.join(startupDir, "Engine7.vbs");
33397
+ fs43.mkdirSync(startupDir, { recursive: true });
33398
+ const vbsPath = path43.join(startupDir, "Engine7.vbs");
33265
33399
  const nodeExePath = nodeExe || process.execPath;
33266
- const cliMjsPath = path42.resolve(engine7Bin);
33267
- const absCfg = path42.resolve(configPath2);
33400
+ const cliMjsPath = path43.resolve(engine7Bin);
33401
+ const absCfg = path43.resolve(configPath2);
33268
33402
  const vbs = [
33269
33403
  "' Engine 7 \u5F00\u673A\u81EA\u542F\uFF08\u542F\u52A8\u6587\u4EF6\u5939\uFF0C\u514D\u7BA1\u7406\u5458\uFF09",
33270
33404
  'Set fso = CreateObject("Scripting.FileSystemObject")',
@@ -33280,15 +33414,15 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
33280
33414
  's.Run """' + nodeExePath + '"" ""' + cliMjsPath + '"" start --config ""' + absCfg + '""", 0, False',
33281
33415
  ""
33282
33416
  ].join(String.fromCharCode(13) + String.fromCharCode(10));
33283
- fs42.writeFileSync(vbsPath, vbs);
33417
+ fs43.writeFileSync(vbsPath, vbs);
33284
33418
  console.log(`\u2705 \u5F00\u673A\u81EA\u542F\u52A8\u5DF2\u6CE8\u518C\uFF08\u542F\u52A8\u6587\u4EF6\u5939: ${vbsPath}\uFF09`);
33285
33419
  } else if (process.platform === "darwin") {
33286
33420
  const label = "com.engine7.agent";
33287
- const plistDir = path42.join(process.env.HOME, "Library", "LaunchAgents");
33288
- fs42.mkdirSync(plistDir, { recursive: true });
33289
- const plistPath = path42.join(plistDir, `${label}.plist`);
33290
- const localCli = path42.join("node_modules", "engine7", "dist", "cli.mjs");
33291
- const cliMjs = fs42.existsSync(localCli) ? path42.resolve(localCli) : path42.join(path42.dirname(path42.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
33421
+ const plistDir = path43.join(process.env.HOME, "Library", "LaunchAgents");
33422
+ fs43.mkdirSync(plistDir, { recursive: true });
33423
+ const plistPath = path43.join(plistDir, `${label}.plist`);
33424
+ const localCli = path43.join("node_modules", "engine7", "dist", "cli.mjs");
33425
+ const cliMjs = fs43.existsSync(localCli) ? path43.resolve(localCli) : path43.join(path43.dirname(path43.dirname(engine7Bin)), "lib", "node_modules", "engine7", "dist", "cli.mjs");
33292
33426
  const plist = `<?xml version="1.0" encoding="UTF-8"?>
33293
33427
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33294
33428
  <plist version="1.0">
@@ -33300,16 +33434,16 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
33300
33434
  <string>${cliMjs}</string>
33301
33435
  <string>start</string>
33302
33436
  <string>--config</string>
33303
- <string>${path42.resolve(configPath2)}</string>
33437
+ <string>${path43.resolve(configPath2)}</string>
33304
33438
  </array>
33305
33439
  <key>WorkingDirectory</key><string>${cwd}</string>
33306
33440
  <key>RunAtLoad</key><true/>
33307
33441
  <key>KeepAlive</key><true/>
33308
33442
  </dict>
33309
33443
  </plist>`;
33310
- fs42.writeFileSync(plistPath, plist);
33444
+ fs43.writeFileSync(plistPath, plist);
33311
33445
  try {
33312
- execSync3(`launchctl load "${plistPath}"`, { stdio: "inherit" });
33446
+ execSync4(`launchctl load "${plistPath}"`, { stdio: "inherit" });
33313
33447
  console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
33314
33448
  console.log(` ${plistPath}`);
33315
33449
  } catch {
@@ -33318,9 +33452,9 @@ engine7 service \u2014 \u5F00\u673A\u81EA\u542F\u52A8\u7BA1\u7406
33318
33452
  }
33319
33453
  } else {
33320
33454
  const svcName = "engine7";
33321
- const svcDir = path42.join(process.env.HOME, ".config", "systemd", "user");
33322
- fs42.mkdirSync(svcDir, { recursive: true });
33323
- const svcPath = path42.join(svcDir, `${svcName}.service`);
33455
+ const svcDir = path43.join(process.env.HOME, ".config", "systemd", "user");
33456
+ fs43.mkdirSync(svcDir, { recursive: true });
33457
+ const svcPath = path43.join(svcDir, `${svcName}.service`);
33324
33458
  const svc = `[Unit]
33325
33459
  Description=Engine 7 Agent
33326
33460
  After=network.target
@@ -33328,16 +33462,16 @@ After=network.target
33328
33462
  [Service]
33329
33463
  Type=simple
33330
33464
  WorkingDirectory=${cwd}
33331
- ExecStart=${process.execPath} ${engine7Bin} start --config ${path42.resolve(configPath2)}
33465
+ ExecStart=${process.execPath} ${engine7Bin} start --config ${path43.resolve(configPath2)}
33332
33466
  Restart=on-failure
33333
33467
  RestartSec=10
33334
33468
 
33335
33469
  [Install]
33336
33470
  WantedBy=default.target`;
33337
- fs42.writeFileSync(svcPath, svc);
33471
+ fs43.writeFileSync(svcPath, svc);
33338
33472
  try {
33339
- execSync3(`systemctl --user daemon-reload`, { stdio: "inherit" });
33340
- execSync3(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
33473
+ execSync4(`systemctl --user daemon-reload`, { stdio: "inherit" });
33474
+ execSync4(`systemctl --user enable ${svcName}`, { stdio: "inherit" });
33341
33475
  console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u521B\u5EFA\uFF08\u5F00\u673A\u81EA\u542F\u52A8\uFF09`);
33342
33476
  console.log(` ${svcPath}`);
33343
33477
  } catch {
@@ -33347,8 +33481,8 @@ WantedBy=default.target`;
33347
33481
  }
33348
33482
  } else if (action === "uninstall") {
33349
33483
  if (process.platform === "win32") {
33350
- const vbsPath = path42.join(
33351
- process.env.APPDATA || path42.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
33484
+ const vbsPath = path43.join(
33485
+ process.env.APPDATA || path43.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
33352
33486
  "Microsoft",
33353
33487
  "Windows",
33354
33488
  "Start Menu",
@@ -33357,46 +33491,46 @@ WantedBy=default.target`;
33357
33491
  "Engine7.vbs"
33358
33492
  );
33359
33493
  try {
33360
- execSync3(`schtasks /delete /tn "Engine7" /f`, { stdio: "ignore" });
33494
+ execSync4(`schtasks /delete /tn "Engine7" /f`, { stdio: "ignore" });
33361
33495
  } catch {
33362
33496
  }
33363
- if (fs42.existsSync(vbsPath)) {
33364
- fs42.rmSync(vbsPath, { force: true });
33497
+ if (fs43.existsSync(vbsPath)) {
33498
+ fs43.rmSync(vbsPath, { force: true });
33365
33499
  console.log(`\u2705 \u5F00\u673A\u81EA\u542F\u52A8\u5DF2\u79FB\u9664\uFF08${vbsPath}\uFF09`);
33366
33500
  } else {
33367
33501
  console.log("\uFF08\u5F00\u673A\u81EA\u542F\u52A8\u672C\u6765\u5C31\u6CA1\u6CE8\u518C\uFF09");
33368
33502
  }
33369
33503
  } else if (process.platform === "darwin") {
33370
- const plistPath = path42.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
33504
+ const plistPath = path43.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
33371
33505
  try {
33372
- execSync3(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
33506
+ execSync4(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
33373
33507
  } catch {
33374
33508
  }
33375
33509
  try {
33376
- fs42.unlinkSync(plistPath);
33510
+ fs43.unlinkSync(plistPath);
33377
33511
  } catch {
33378
33512
  }
33379
33513
  console.log(`\u2705 Mac launchd \u670D\u52A1\u5DF2\u5220\u9664`);
33380
33514
  } else {
33381
33515
  try {
33382
- execSync3(`systemctl --user disable engine7`, { stdio: "inherit" });
33516
+ execSync4(`systemctl --user disable engine7`, { stdio: "inherit" });
33383
33517
  } catch {
33384
33518
  }
33385
- const svcPath = path42.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
33519
+ const svcPath = path43.join(process.env.HOME, ".config", "systemd", "user", "engine7.service");
33386
33520
  try {
33387
- fs42.unlinkSync(svcPath);
33521
+ fs43.unlinkSync(svcPath);
33388
33522
  } catch {
33389
33523
  }
33390
33524
  try {
33391
- execSync3(`systemctl --user daemon-reload`, { stdio: "inherit" });
33525
+ execSync4(`systemctl --user daemon-reload`, { stdio: "inherit" });
33392
33526
  } catch {
33393
33527
  }
33394
33528
  console.log(`\u2705 systemd \u7528\u6237\u670D\u52A1\u5DF2\u5220\u9664`);
33395
33529
  }
33396
33530
  } else if (action === "status") {
33397
33531
  if (process.platform === "win32") {
33398
- const vbsPath = path42.join(
33399
- process.env.APPDATA || path42.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
33532
+ const vbsPath = path43.join(
33533
+ process.env.APPDATA || path43.join(process.env.USERPROFILE || "", "AppData", "Roaming"),
33400
33534
  "Microsoft",
33401
33535
  "Windows",
33402
33536
  "Start Menu",
@@ -33404,17 +33538,17 @@ WantedBy=default.target`;
33404
33538
  "Startup",
33405
33539
  "Engine7.vbs"
33406
33540
  );
33407
- console.log(fs42.existsSync(vbsPath) ? `\u2705 \u5DF2\u6CE8\u518C\uFF08\u542F\u52A8\u6587\u4EF6\u5939\uFF09: ${vbsPath}` : "\u274C \u672A\u6CE8\u518C");
33541
+ console.log(fs43.existsSync(vbsPath) ? `\u2705 \u5DF2\u6CE8\u518C\uFF08\u542F\u52A8\u6587\u4EF6\u5939\uFF09: ${vbsPath}` : "\u274C \u672A\u6CE8\u518C");
33408
33542
  } else if (process.platform === "darwin") {
33409
- const plistPath = path42.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
33410
- if (fs42.existsSync(plistPath)) {
33543
+ const plistPath = path43.join(process.env.HOME, "Library", "LaunchAgents", "com.engine7.agent.plist");
33544
+ if (fs43.existsSync(plistPath)) {
33411
33545
  console.log("\u2705 \u5DF2\u5B89\u88C5\uFF08launchd\uFF09");
33412
33546
  } else {
33413
33547
  console.log("\u274C \u672A\u5B89\u88C5");
33414
33548
  }
33415
33549
  } else {
33416
33550
  try {
33417
- execSync3(`systemctl --user is-enabled engine7`, { stdio: "inherit" });
33551
+ execSync4(`systemctl --user is-enabled engine7`, { stdio: "inherit" });
33418
33552
  } catch {
33419
33553
  console.log("\u274C \u672A\u5B89\u88C5");
33420
33554
  }
@@ -33440,8 +33574,8 @@ WantedBy=default.target`;
33440
33574
  console.log(`
33441
33575
  \u{1F680} engine7 init`);
33442
33576
  console.log(` state-dir: ${opts.stateDir}`);
33443
- if (fs42.existsSync(opts.stateDir) && !opts.dryRun) {
33444
- const files = fs42.readdirSync(opts.stateDir);
33577
+ if (fs43.existsSync(opts.stateDir) && !opts.dryRun) {
33578
+ const files = fs43.readdirSync(opts.stateDir);
33445
33579
  if (files.length > 0) {
33446
33580
  if (opts.force) {
33447
33581
  if (looksLikeAppInstall(opts.stateDir)) {
@@ -33454,10 +33588,10 @@ WantedBy=default.target`;
33454
33588
  }
33455
33589
  console.log(`
33456
33590
  \u26A0\uFE0F --force: \u6E05\u7A7A\u5DF2\u6709\u76EE\u5F55 ${opts.stateDir}`);
33457
- fs42.rmSync(opts.stateDir, { recursive: true, force: true });
33591
+ fs43.rmSync(opts.stateDir, { recursive: true, force: true });
33458
33592
  } else {
33459
- const existingConfig = path42.join(opts.stateDir, "configs", "main7.json");
33460
- if (fs42.existsSync(existingConfig)) {
33593
+ const existingConfig = path43.join(opts.stateDir, "configs", "main7.json");
33594
+ if (fs43.existsSync(existingConfig)) {
33461
33595
  console.log(`
33462
33596
  \u267B\uFE0F \u68C0\u6D4B\u5230\u5DF2\u6709\u914D\u7F6E: ${existingConfig}`);
33463
33597
  console.log(` \u2192 \u590D\u8DD1\u6A21\u5F0F\uFF1A\u663E\u793A\u73B0\u6709\u914D\u7F6E\uFF0C\u56DE\u8F66\u4FDD\u7559\uFF0C\u6539\u4E86\u624D\u751F\u6548\uFF08\u4E0D\u4F1A\u6E05\u7A7A\u76EE\u5F55\uFF09`);
@@ -33538,12 +33672,12 @@ WantedBy=default.target`;
33538
33672
  let photoSrc = "";
33539
33673
  if (answers?.selfie?.photoPath) {
33540
33674
  const { dimsOf: dimsOf2 } = await Promise.resolve().then(() => (init_my_selfie(), my_selfie_exports));
33541
- const src = path42.resolve(answers.selfie.photoPath.trim());
33542
- const ext = path42.extname(src).toLowerCase();
33675
+ const src = path43.resolve(answers.selfie.photoPath.trim());
33676
+ const ext = path43.extname(src).toLowerCase();
33543
33677
  if (!PHOTO_EXTS.includes(ext)) {
33544
33678
  throw new Error(`\u7167\u7247\u683C\u5F0F\u4E0D\u652F\u6301\uFF1A${ext || "(\u6CA1\u6709\u540E\u7F00)"}\u3002\u8BF7\u7528 PNG / JPEG / WebP\u3002`);
33545
33679
  }
33546
- if (!fs42.existsSync(src)) {
33680
+ if (!fs43.existsSync(src)) {
33547
33681
  throw new Error(`\u7167\u7247\u4E0D\u5B58\u5728\uFF1A${src}`);
33548
33682
  }
33549
33683
  const dims = dimsOf2(src);
@@ -33554,7 +33688,7 @@ WantedBy=default.target`;
33554
33688
  photoSrc = src;
33555
33689
  }
33556
33690
  const config = generateConfig(values);
33557
- const configPath = path42.join(opts.stateDir, "configs", "main7.json");
33691
+ const configPath = path43.join(opts.stateDir, "configs", "main7.json");
33558
33692
  const tree = buildDirTree(values);
33559
33693
  if (headlessEmit) headlessEmit({ event: "progress", step: "write_config" });
33560
33694
  tree.push({
@@ -33566,22 +33700,22 @@ WantedBy=default.target`;
33566
33700
  dryRun(tree);
33567
33701
  const skillsSrc = findTemplateDir("skills");
33568
33702
  if (skillsSrc) {
33569
- const skills = fs42.readdirSync(skillsSrc);
33703
+ const skills = fs43.readdirSync(skillsSrc);
33570
33704
  for (const s of skills) {
33571
- console.log(` \u{1F4C1} ${path42.join(opts.stateDir, "workspace", "skills", s)}`);
33705
+ console.log(` \u{1F4C1} ${path43.join(opts.stateDir, "workspace", "skills", s)}`);
33572
33706
  }
33573
33707
  }
33574
33708
  } else {
33575
33709
  if (values.chatMode === "auto") {
33576
33710
  try {
33577
- fs42.unlinkSync(path42.join(opts.stateDir, "workspace", ".work-mode"));
33711
+ fs43.unlinkSync(path43.join(opts.stateDir, "workspace", ".work-mode"));
33578
33712
  } catch {
33579
33713
  }
33580
33714
  }
33581
33715
  if (photoSrc && values.selfiePhotoRelPath) {
33582
- const dest = path42.join(opts.stateDir, "workspace", values.selfiePhotoRelPath);
33583
- fs42.mkdirSync(path42.dirname(dest), { recursive: true });
33584
- fs42.copyFileSync(photoSrc, dest);
33716
+ const dest = path43.join(opts.stateDir, "workspace", values.selfiePhotoRelPath);
33717
+ fs43.mkdirSync(path43.dirname(dest), { recursive: true });
33718
+ fs43.copyFileSync(photoSrc, dest);
33585
33719
  console.log(` \u{1F5BC} \u5F62\u8C61: ${dest}`);
33586
33720
  }
33587
33721
  if (headlessEmit) headlessEmit({ event: "progress", step: "create_dirs" });
@@ -33610,58 +33744,58 @@ WantedBy=default.target`;
33610
33744
  if (headlessEmit) headlessEmit({ event: "progress", step: "copy_skills" });
33611
33745
  const skillsSrc = findTemplateDir("skills");
33612
33746
  if (skillsSrc) {
33613
- const skillsDest = path42.join(opts.stateDir, "workspace", "skills");
33614
- fs42.mkdirSync(skillsDest, { recursive: true });
33615
- const skills = fs42.readdirSync(skillsSrc);
33747
+ const skillsDest = path43.join(opts.stateDir, "workspace", "skills");
33748
+ fs43.mkdirSync(skillsDest, { recursive: true });
33749
+ const skills = fs43.readdirSync(skillsSrc);
33616
33750
  for (const s of skills) {
33617
- copyDirRecursive(path42.join(skillsSrc, s), path42.join(skillsDest, s));
33751
+ copyDirRecursive(path43.join(skillsSrc, s), path43.join(skillsDest, s));
33618
33752
  console.log(` \u{1F4E6} skill: ${s}`);
33619
33753
  }
33620
33754
  }
33621
33755
  console.log(`
33622
33756
  \u2705 \u521D\u59CB\u5316\u5B8C\u6210\uFF01
33623
33757
  `);
33624
- const homePointer = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
33758
+ const homePointer = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
33625
33759
  const pointerData = { stateDir: opts.stateDir };
33626
- fs42.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
33760
+ fs43.writeFileSync(homePointer, JSON.stringify(pointerData, null, 2) + "\n");
33627
33761
  console.log(` \u{1F4C4} ${homePointer}\uFF08\u4ECE\u4EFB\u610F\u76EE\u5F55\u90FD\u80FD\u627E\u5230\u6B64 agent\uFF09`);
33628
33762
  console.log(`\u4E0B\u4E00\u6B65\uFF1A`);
33629
33763
  console.log(` 1. \u68C0\u67E5\u5E76\u4FEE\u6539 ${opts.stateDir}/configs/main7.json`);
33630
33764
  console.log(` 2. \u542F\u52A8 Engine: engine7 start\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
33631
33765
  console.log(` 3. \u5F00\u673A\u81EA\u542F: engine7 service install\uFF08\u5728\u4EFB\u610F\u76EE\u5F55\u90FD\u884C\uFF09`);
33632
- console.log(` 4. \u67E5\u770B workspace: ${path42.join(opts.stateDir, "workspace")}`);
33766
+ console.log(` 4. \u67E5\u770B workspace: ${path43.join(opts.stateDir, "workspace")}`);
33633
33767
  if (headlessEmit) {
33634
33768
  headlessEmit({ event: "done", stateDir: opts.stateDir.replace(/\\/g, "/"), configPath: configPath.replace(/\\/g, "/") });
33635
33769
  }
33636
33770
  }
33637
33771
  }
33638
33772
  function copyDirRecursive(src, dest) {
33639
- fs42.mkdirSync(dest, { recursive: true });
33640
- for (const entry of fs42.readdirSync(src, { withFileTypes: true })) {
33641
- const srcPath = path42.join(src, entry.name);
33642
- const destPath = path42.join(dest, entry.name);
33773
+ fs43.mkdirSync(dest, { recursive: true });
33774
+ for (const entry of fs43.readdirSync(src, { withFileTypes: true })) {
33775
+ const srcPath = path43.join(src, entry.name);
33776
+ const destPath = path43.join(dest, entry.name);
33643
33777
  if (entry.isDirectory()) {
33644
33778
  copyDirRecursive(srcPath, destPath);
33645
33779
  } else {
33646
- fs42.copyFileSync(srcPath, destPath);
33780
+ fs43.copyFileSync(srcPath, destPath);
33647
33781
  }
33648
33782
  }
33649
33783
  }
33650
33784
  function findTemplateDir(name) {
33651
33785
  const candidates = [
33652
- path42.join(__dirname, "..", "templates", name),
33653
- path42.join(__dirname, "..", "..", "templates", name),
33654
- path42.join(process.cwd(), "templates", name)
33786
+ path43.join(__dirname, "..", "templates", name),
33787
+ path43.join(__dirname, "..", "..", "templates", name),
33788
+ path43.join(process.cwd(), "templates", name)
33655
33789
  ];
33656
33790
  for (const p of candidates) {
33657
- if (fs42.existsSync(p)) return p;
33791
+ if (fs43.existsSync(p)) return p;
33658
33792
  }
33659
33793
  return null;
33660
33794
  }
33661
33795
  function readHomePointer() {
33662
- const ptrPath = path42.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
33796
+ const ptrPath = path43.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7.json");
33663
33797
  try {
33664
- return JSON.parse(fs42.readFileSync(ptrPath, "utf-8"));
33798
+ return JSON.parse(fs43.readFileSync(ptrPath, "utf-8"));
33665
33799
  } catch {
33666
33800
  return null;
33667
33801
  }