engine7 7.1.119 → 7.1.120

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.
@@ -2429,6 +2429,17 @@ var init_live = __esm({
2429
2429
  Object.assign(this.current, newConfig);
2430
2430
  }
2431
2431
  /** 改活树上的值;文件承载路径同步持久化(read-modify-write 回 config 文件) */
2432
+ /**
2433
+ * 改活树 + 落盘。
2434
+ *
2435
+ * 返回值 = **落盘**是否成功(活树无论成败都已同步——它是先改的)。绝大多数调用点照旧
2436
+ * `void liveConfig.set(...)` 不理它;但**要打成功日志的调用点必须 await 这个布尔值**。
2437
+ *
2438
+ * 为什么把这个信号交出去(1001 审查捞回):本方法本来是 fire-and-forget,落盘失败只在
2439
+ * `persistToFile` 里 warn 一行;而启动早段的调用点(两个免费档 fixup)紧接着打了句
2440
+ * "免费档补齐 xxx" 的成功日志 ⇒ 配置**没写进文件**却被读成"写好了":进程内生效、托盘
2441
+ * 读文件还是旧值、下次启动重放同一句——正是本仓最恨的假信号。
2442
+ */
2432
2443
  async set(dotPath, val) {
2433
2444
  if (!this.current) throw new Error("[liveConfig] not initialized \u2014 call liveConfig.init() first");
2434
2445
  const keys = dotPath.split(".");
@@ -2438,15 +2449,15 @@ var init_live = __esm({
2438
2449
  obj = obj[keys[i]];
2439
2450
  }
2440
2451
  obj[keys[keys.length - 1]] = val;
2441
- await this.persistToFile(dotPath, val);
2452
+ return this.persistToFile(dotPath, val);
2442
2453
  }
2443
- /** 把改动写回 config 文件对应段(找不到文件路径则只内存生效) */
2454
+ /** 把改动写回 config 文件对应段(找不到文件路径则只内存生效)。返回是否真的落盘。 */
2444
2455
  async persistToFile(dotPath, val) {
2445
2456
  const fs60 = await import("node:fs");
2446
2457
  const cfgPath = this.current?._configFilePath;
2447
2458
  if (!cfgPath || !fs60.existsSync(cfgPath)) {
2448
2459
  console.warn(`[liveConfig] set: no config file path, in-memory only (${dotPath})`);
2449
- return;
2460
+ return false;
2450
2461
  }
2451
2462
  try {
2452
2463
  const raw = JSON.parse(fs60.readFileSync(cfgPath, "utf-8"));
@@ -2460,8 +2471,10 @@ var init_live = __esm({
2460
2471
  fs60.writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
2461
2472
  console.log(`[liveConfig] persisted ${dotPath} = ${JSON.stringify(val)} to ${cfgPath}`);
2462
2473
  markSelfWrite();
2474
+ return true;
2463
2475
  } catch (e) {
2464
2476
  console.warn(`[liveConfig] persist failed (${dotPath}): ${e.message}`);
2477
+ return false;
2465
2478
  }
2466
2479
  }
2467
2480
  /** 是否已初始化 */
@@ -8176,30 +8189,30 @@ __export(teamHelpers_exports, {
8176
8189
  writeTeamFile: () => writeTeamFile,
8177
8190
  writeTeamFileAsync: () => writeTeamFileAsync
8178
8191
  });
8179
- import { mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "node:fs";
8192
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "node:fs";
8180
8193
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
8181
- import { join as join16 } from "node:path";
8194
+ import { join as join17 } from "node:path";
8182
8195
  function initTeamDirs(stateDir) {
8183
8196
  _stateDir = stateDir;
8184
8197
  }
8185
8198
  function getTeamsDir() {
8186
- return join16(_stateDir, "teams");
8199
+ return join17(_stateDir, "teams");
8187
8200
  }
8188
8201
  function getTasksDir() {
8189
- return join16(_stateDir, "tasks");
8202
+ return join17(_stateDir, "tasks");
8190
8203
  }
8191
8204
  function sanitizeName(name) {
8192
8205
  return name.replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
8193
8206
  }
8194
8207
  function getTeamDir(teamName) {
8195
- return join16(getTeamsDir(), sanitizeName(teamName));
8208
+ return join17(getTeamsDir(), sanitizeName(teamName));
8196
8209
  }
8197
8210
  function getTeamFilePath(teamName) {
8198
- return join16(getTeamDir(teamName), "config.json");
8211
+ return join17(getTeamDir(teamName), "config.json");
8199
8212
  }
8200
8213
  function readTeamFile(teamName) {
8201
8214
  try {
8202
- const content = readFileSync10(getTeamFilePath(teamName), "utf-8");
8215
+ const content = readFileSync11(getTeamFilePath(teamName), "utf-8");
8203
8216
  return JSON.parse(content);
8204
8217
  } catch (e) {
8205
8218
  if (e?.code === "ENOENT") return null;
@@ -8219,8 +8232,8 @@ async function readTeamFileAsync(teamName) {
8219
8232
  }
8220
8233
  function writeTeamFile(teamName, teamFile) {
8221
8234
  const teamDir = getTeamDir(teamName);
8222
- mkdirSync7(teamDir, { recursive: true });
8223
- writeFileSync4(getTeamFilePath(teamName), JSON.stringify(teamFile, null, 2));
8235
+ mkdirSync8(teamDir, { recursive: true });
8236
+ writeFileSync5(getTeamFilePath(teamName), JSON.stringify(teamFile, null, 2));
8224
8237
  }
8225
8238
  async function writeTeamFileAsync(teamName, teamFile) {
8226
8239
  const teamDir = getTeamDir(teamName);
@@ -8300,7 +8313,7 @@ async function cleanupTeamDirectories(teamName) {
8300
8313
  } catch (error) {
8301
8314
  console.warn(`[teamHelpers] Failed to clean up team directory ${teamDir}: ${error.message}`);
8302
8315
  }
8303
- const tasksDir = join16(getTasksDir(), sanitizedName);
8316
+ const tasksDir = join17(getTasksDir(), sanitizedName);
8304
8317
  try {
8305
8318
  await rm(tasksDir, { recursive: true, force: true });
8306
8319
  console.log(`[teamHelpers] Cleaned up tasks directory: ${tasksDir}`);
@@ -8309,8 +8322,8 @@ async function cleanupTeamDirectories(teamName) {
8309
8322
  }
8310
8323
  }
8311
8324
  function ensureTasksDir(taskListId) {
8312
- const dir = join16(getTasksDir(), taskListId);
8313
- mkdirSync7(dir, { recursive: true });
8325
+ const dir = join17(getTasksDir(), taskListId);
8326
+ mkdirSync8(dir, { recursive: true });
8314
8327
  }
8315
8328
  function setLeaderTeamName(name) {
8316
8329
  _leaderTeamName = name;
@@ -8355,9 +8368,9 @@ __export(teammateMailbox_exports, {
8355
8368
  writeToMailbox: () => writeToMailbox
8356
8369
  });
8357
8370
  import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
8358
- import { join as join17 } from "node:path";
8371
+ import { join as join18 } from "node:path";
8359
8372
  function getTeamsDir2() {
8360
- return join17(process.env.ENGINE_STATE_DIR || ".", "teams");
8373
+ return join18(process.env.ENGINE_STATE_DIR || ".", "teams");
8361
8374
  }
8362
8375
  function sanitizePathComponent(s) {
8363
8376
  return s.replace(/[^a-zA-Z0-9_-]/g, "-");
@@ -8366,12 +8379,12 @@ function getInboxPath(agentName, teamName) {
8366
8379
  const team = teamName || "default";
8367
8380
  const safeTeam = sanitizePathComponent(team);
8368
8381
  const safeAgentName = sanitizePathComponent(agentName);
8369
- return join17(getTeamsDir2(), safeTeam, "inboxes", `${safeAgentName}.json`);
8382
+ return join18(getTeamsDir2(), safeTeam, "inboxes", `${safeAgentName}.json`);
8370
8383
  }
8371
8384
  async function ensureInboxDir(teamName) {
8372
8385
  const team = teamName || "default";
8373
8386
  const safeTeam = sanitizePathComponent(team);
8374
- const inboxDir = join17(getTeamsDir2(), safeTeam, "inboxes");
8387
+ const inboxDir = join18(getTeamsDir2(), safeTeam, "inboxes");
8375
8388
  await mkdir2(inboxDir, { recursive: true });
8376
8389
  }
8377
8390
  async function sleep2(ms) {
@@ -8680,7 +8693,7 @@ var init_inboxPoller = __esm({
8680
8693
 
8681
8694
  // src/memory/memdir/memoryScan.ts
8682
8695
  import { readdir, stat as stat2, readFile as readFile3 } from "node:fs/promises";
8683
- import { basename as basename4, join as join18, sep as sep3 } from "node:path";
8696
+ import { basename as basename4, join as join19, sep as sep3 } from "node:path";
8684
8697
  function isArchivedPath(relativePath) {
8685
8698
  return relativePath.split(sep3).includes("archive");
8686
8699
  }
@@ -8730,7 +8743,7 @@ async function scanMemoryFiles2(memoryDir, signal, maxFiles) {
8730
8743
  );
8731
8744
  const headerResults = await Promise.allSettled(
8732
8745
  mdFiles.map(async (relativePath) => {
8733
- const filePath = join18(memoryDir, relativePath);
8746
+ const filePath = join19(memoryDir, relativePath);
8734
8747
  const { content, mtimeMs } = await readFileHeader(
8735
8748
  filePath,
8736
8749
  FRONTMATTER_MAX_LINES,
@@ -9664,8 +9677,8 @@ var init_filters = __esm({
9664
9677
 
9665
9678
  // src/mem7/core/vector-store.ts
9666
9679
  import { Schema, Field, Utf8, Float32, Int64, FixedSizeList, TimestampMicrosecond, List } from "apache-arrow";
9667
- import { mkdirSync as mkdirSync8 } from "node:fs";
9668
- import { join as join23 } from "node:path";
9680
+ import { mkdirSync as mkdirSync9 } from "node:fs";
9681
+ import { join as join24 } from "node:path";
9669
9682
  function lanceSpecifierFor(platform2, arch) {
9670
9683
  return platform2 === "darwin" && arch === "x64" ? "@engine7/lancedb-intel" : "@lancedb/lancedb";
9671
9684
  }
@@ -9761,13 +9774,13 @@ var init_vector_store = __esm({
9761
9774
  dir;
9762
9775
  tables = /* @__PURE__ */ new Map();
9763
9776
  constructor(stateDir) {
9764
- this.dir = join23(mem7Root(stateDir), "index", "lancedb");
9777
+ this.dir = join24(mem7Root(stateDir), "index", "lancedb");
9765
9778
  }
9766
9779
  async conn() {
9767
9780
  if (!this.db) {
9768
9781
  const lance = await loadLance();
9769
9782
  if (!lance) throw new Mem7VectorUnavailableError();
9770
- mkdirSync8(this.dir, { recursive: true });
9783
+ mkdirSync9(this.dir, { recursive: true });
9771
9784
  this.db = await lance.connect(this.dir);
9772
9785
  }
9773
9786
  return this.db;
@@ -10056,14 +10069,14 @@ Follow these principles when generating episodic memories:
10056
10069
 
10057
10070
  // src/mem7/core/store.ts
10058
10071
  import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
10059
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync6, existsSync as existsSync15, readdirSync as readdirSync2 } from "node:fs";
10060
- import { join as join24 } from "node:path";
10072
+ import { mkdirSync as mkdirSync10, readFileSync as readFileSync16, writeFileSync as writeFileSync7, existsSync as existsSync16, readdirSync as readdirSync2 } from "node:fs";
10073
+ import { join as join25 } from "node:path";
10061
10074
  import { createHash as createHash2 } from "node:crypto";
10062
10075
  function contentHash(text) {
10063
10076
  return createHash2("sha256").update(text.replace(/\s+/g, "")).digest("hex").slice(0, 40);
10064
10077
  }
10065
10078
  function mem7Root(stateDir) {
10066
- return join24(stateDir, "mem7");
10079
+ return join25(stateDir, "mem7");
10067
10080
  }
10068
10081
  var SCHEMA, Mem7Store;
10069
10082
  var init_store2 = __esm({
@@ -10099,8 +10112,8 @@ CREATE TABLE IF NOT EXISTS watermarks (
10099
10112
  constructor(stateDir) {
10100
10113
  this.stateDir = stateDir;
10101
10114
  this.root = mem7Root(stateDir);
10102
- mkdirSync9(join24(this.root, "index"), { recursive: true });
10103
- this.db = new DatabaseSync2(join24(this.root, "index", "mem7.db"));
10115
+ mkdirSync10(join25(this.root, "index"), { recursive: true });
10116
+ this.db = new DatabaseSync2(join25(this.root, "index", "mem7.db"));
10104
10117
  this.db.exec("PRAGMA journal_mode=WAL");
10105
10118
  this.db.exec(SCHEMA);
10106
10119
  }
@@ -10231,14 +10244,14 @@ CREATE TABLE IF NOT EXISTS watermarks (
10231
10244
  /** md 追加通用:frontmatter(存在则更新计数)+ 既有 entry 块全保留 + 追加新块 */
10232
10245
  appendMd(ownerId, dirName, filePrefix, type2, dateStr, entries2, render) {
10233
10246
  if (entries2.length === 0) return;
10234
- const dir = join24(this.root, "users", ownerId, dirName);
10235
- mkdirSync9(dir, { recursive: true });
10236
- const file2 = join24(dir, `${filePrefix}-${dateStr}.md`);
10247
+ const dir = join25(this.root, "users", ownerId, dirName);
10248
+ mkdirSync10(dir, { recursive: true });
10249
+ const file2 = join25(dir, `${filePrefix}-${dateStr}.md`);
10237
10250
  let head;
10238
10251
  let existingBlocks = "";
10239
10252
  let count;
10240
- if (existsSync15(file2)) {
10241
- const text = readFileSync15(file2, "utf8");
10253
+ if (existsSync16(file2)) {
10254
+ const text = readFileSync16(file2, "utf8");
10242
10255
  const fmEnd = text.indexOf("\n---", 3);
10243
10256
  const split = fmEnd >= 0 ? fmEnd + 4 : text.length;
10244
10257
  head = text.slice(0, split);
@@ -10269,7 +10282,7 @@ CREATE TABLE IF NOT EXISTS watermarks (
10269
10282
  count++;
10270
10283
  }
10271
10284
  head = head.replace(/entry_count: \d+/, `entry_count: ${count}`).replace(/last_appended_at: '[^']*'/, `last_appended_at: '${formatMdTimestamp()}'`);
10272
- writeFileSync6(file2, head + "\n\n" + blocks.join("\n\n") + "\n", "utf8");
10285
+ writeFileSync7(file2, head + "\n\n" + blocks.join("\n\n") + "\n", "utf8");
10273
10286
  }
10274
10287
  /**
10275
10288
  * entry_id:前缀_YYYYMMDD_六位序号。
@@ -10289,11 +10302,11 @@ CREATE TABLE IF NOT EXISTS watermarks (
10289
10302
  af: [".atomic_facts", "atomic-facts"]
10290
10303
  };
10291
10304
  const [dirName, filePrefix] = dirByPrefix[prefix];
10292
- const file2 = join24(this.root, "users", ownerId, dirName, `${filePrefix}-${dateStr}.md`);
10305
+ const file2 = join25(this.root, "users", ownerId, dirName, `${filePrefix}-${dateStr}.md`);
10293
10306
  let max = 0;
10294
- if (existsSync15(file2)) {
10307
+ if (existsSync16(file2)) {
10295
10308
  const re = new RegExp(`${prefix}_${dateStr.replace(/-/g, "")}_(\\d+)`, "g");
10296
- for (const m of readFileSync15(file2, "utf8").matchAll(re)) max = Math.max(max, Number(m[1]));
10309
+ for (const m of readFileSync16(file2, "utf8").matchAll(re)) max = Math.max(max, Number(m[1]));
10297
10310
  }
10298
10311
  return max;
10299
10312
  }
@@ -10360,17 +10373,17 @@ CREATE TABLE IF NOT EXISTS watermarks (
10360
10373
  getOpenPredictions(now, limit = 50) {
10361
10374
  const today3 = todayKey(now);
10362
10375
  const out = [];
10363
- const usersDir = join24(this.root, "users");
10364
- if (!existsSync15(usersDir)) return out;
10376
+ const usersDir = join25(this.root, "users");
10377
+ if (!existsSync16(usersDir)) return out;
10365
10378
  for (const owner of readdirSync2(usersDir, { withFileTypes: true })) {
10366
10379
  if (!owner.isDirectory()) continue;
10367
- const dir = join24(usersDir, owner.name, ".foresights");
10368
- if (!existsSync15(dir)) continue;
10380
+ const dir = join25(usersDir, owner.name, ".foresights");
10381
+ if (!existsSync16(dir)) continue;
10369
10382
  for (const f of readdirSync2(dir)) {
10370
10383
  if (!/^foresight-\d{4}-\d{2}-\d{2}\.md$/.test(f)) continue;
10371
10384
  let content;
10372
10385
  try {
10373
- content = readFileSync15(join24(dir, f), "utf8");
10386
+ content = readFileSync16(join25(dir, f), "utf8");
10374
10387
  } catch {
10375
10388
  continue;
10376
10389
  }
@@ -10449,9 +10462,9 @@ var init_ingest2 = __esm({
10449
10462
  });
10450
10463
 
10451
10464
  // src/mem7/core/ids.ts
10452
- import { randomBytes as randomBytes3 } from "node:crypto";
10465
+ import { randomBytes as randomBytes4 } from "node:crypto";
10453
10466
  function hex(len) {
10454
- return randomBytes3(Math.ceil(len / 2)).toString("hex").slice(0, len);
10467
+ return randomBytes4(Math.ceil(len / 2)).toString("hex").slice(0, len);
10455
10468
  }
10456
10469
  function randomCellId() {
10457
10470
  return `mc_${hex(12)}`;
@@ -10463,9 +10476,9 @@ var init_ids = __esm({
10463
10476
  });
10464
10477
 
10465
10478
  // src/mem7/core/boundary.ts
10466
- import { readFileSync as readFileSync16 } from "node:fs";
10467
- import { join as join25, dirname as dirname4 } from "node:path";
10468
- import { fileURLToPath as fileURLToPath2 } from "node:url";
10479
+ import { readFileSync as readFileSync17 } from "node:fs";
10480
+ import { join as join26, dirname as dirname5 } from "node:path";
10481
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
10469
10482
  function renderBoundaryInput(messages) {
10470
10483
  return messages.map((m, i) => `[${i + 1}] [${new Date(m.tsMs).toISOString()}] ${m.senderName ?? m.senderId}: ${m.text}`).join("\n");
10471
10484
  }
@@ -10558,14 +10571,14 @@ var init_boundary = __esm({
10558
10571
  HARD_TOKEN_LIMIT = 8192;
10559
10572
  HARD_MSG_LIMIT = 50;
10560
10573
  RETRIES = 3;
10561
- PROMPT2 = readFileSync16(join25(dirname4(fileURLToPath2(import.meta.url)), "prompts", "boundary.md"), "utf8");
10574
+ PROMPT2 = readFileSync17(join26(dirname5(fileURLToPath3(import.meta.url)), "prompts", "boundary.md"), "utf8");
10562
10575
  }
10563
10576
  });
10564
10577
 
10565
10578
  // src/mem7/core/episode.ts
10566
- import { readFileSync as readFileSync17 } from "node:fs";
10567
- import { join as join26, dirname as dirname5 } from "node:path";
10568
- import { fileURLToPath as fileURLToPath3 } from "node:url";
10579
+ import { readFileSync as readFileSync18 } from "node:fs";
10580
+ import { join as join27, dirname as dirname6 } from "node:path";
10581
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
10569
10582
  function renderConversation(cell) {
10570
10583
  return cell.messages.map((m) => `
10571
10584
  {
@@ -10621,14 +10634,14 @@ var init_episode = __esm({
10621
10634
  "use strict";
10622
10635
  init_prompt_render();
10623
10636
  RETRIES2 = 2;
10624
- PROMPT3 = readFileSync17(join26(dirname5(fileURLToPath3(import.meta.url)), "prompts", "episode.md"), "utf8");
10637
+ PROMPT3 = readFileSync18(join27(dirname6(fileURLToPath4(import.meta.url)), "prompts", "episode.md"), "utf8");
10625
10638
  }
10626
10639
  });
10627
10640
 
10628
10641
  // src/mem7/core/atomic-facts.ts
10629
- import { readFileSync as readFileSync18 } from "node:fs";
10630
- import { join as join27, dirname as dirname6 } from "node:path";
10631
- import { fileURLToPath as fileURLToPath4 } from "node:url";
10642
+ import { readFileSync as readFileSync19 } from "node:fs";
10643
+ import { join as join28, dirname as dirname7 } from "node:path";
10644
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
10632
10645
  async function extractAtomicFacts(cell, provider, model) {
10633
10646
  const userPrompt = renderPrompt(PROMPT4, {
10634
10647
  INPUT_TEXT: renderConversationText(cell.messages),
@@ -10663,14 +10676,14 @@ var init_atomic_facts = __esm({
10663
10676
  init_episode();
10664
10677
  init_prompt_render();
10665
10678
  RETRIES3 = 5;
10666
- PROMPT4 = readFileSync18(join27(dirname6(fileURLToPath4(import.meta.url)), "prompts", "atomic-facts-memcell.md"), "utf8");
10679
+ PROMPT4 = readFileSync19(join28(dirname7(fileURLToPath5(import.meta.url)), "prompts", "atomic-facts-memcell.md"), "utf8");
10667
10680
  }
10668
10681
  });
10669
10682
 
10670
10683
  // src/mem7/core/foresight.ts
10671
- import { readFileSync as readFileSync19 } from "node:fs";
10672
- import { join as join28, dirname as dirname7 } from "node:path";
10673
- import { fileURLToPath as fileURLToPath5 } from "node:url";
10684
+ import { readFileSync as readFileSync20 } from "node:fs";
10685
+ import { join as join29, dirname as dirname8 } from "node:path";
10686
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
10674
10687
  function cleanDateString(dateStr) {
10675
10688
  if (typeof dateStr !== "string" || !dateStr) return null;
10676
10689
  const cleaned = dateStr.replace(/[^\d-]/g, "");
@@ -10753,7 +10766,7 @@ var init_foresight = __esm({
10753
10766
  MAX_COUNT = 10;
10754
10767
  MIN_COUNT = 4;
10755
10768
  TEMPERATURE = 0.3;
10756
- PROMPT5 = readFileSync19(join28(dirname7(fileURLToPath5(import.meta.url)), "prompts", "foresight.md"), "utf8");
10769
+ PROMPT5 = readFileSync20(join29(dirname8(fileURLToPath6(import.meta.url)), "prompts", "foresight.md"), "utf8");
10757
10770
  }
10758
10771
  });
10759
10772
 
@@ -10954,7 +10967,7 @@ var init_mem7 = __esm({
10954
10967
  });
10955
10968
 
10956
10969
  // src/memory/proactive/config.ts
10957
- import { join as join29 } from "node:path";
10970
+ import { join as join30 } from "node:path";
10958
10971
  function parseProactiveConfig(raw) {
10959
10972
  const obj = raw && typeof raw === "object" ? raw : {};
10960
10973
  const modelRef = typeof obj.model === "string" ? obj.model.trim() : "";
@@ -10981,7 +10994,7 @@ function parseProactiveConfig(raw) {
10981
10994
  };
10982
10995
  }
10983
10996
  function proactiveDbPath(workspace) {
10984
- return join29(workspace, ".proactive", "proactive.db");
10997
+ return join30(workspace, ".proactive", "proactive.db");
10985
10998
  }
10986
10999
  var init_config3 = __esm({
10987
11000
  "src/memory/proactive/config.ts"() {
@@ -11325,8 +11338,8 @@ var init_graph_store = __esm({
11325
11338
 
11326
11339
  // src/memory/proactive/persistence.ts
11327
11340
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
11328
- import { mkdirSync as mkdirSync10 } from "node:fs";
11329
- import { dirname as dirname8 } from "node:path";
11341
+ import { mkdirSync as mkdirSync11 } from "node:fs";
11342
+ import { dirname as dirname9 } from "node:path";
11330
11343
  function rowToAction(r) {
11331
11344
  return {
11332
11345
  id: r.id,
@@ -11427,7 +11440,7 @@ CREATE INDEX IF NOT EXISTS idx_proactive_decisions_created ON proactive_decision
11427
11440
  Persistence = class {
11428
11441
  db;
11429
11442
  constructor(dbPath) {
11430
- mkdirSync10(dirname8(dbPath), { recursive: true });
11443
+ mkdirSync11(dirname9(dbPath), { recursive: true });
11431
11444
  this.db = new DatabaseSync3(dbPath);
11432
11445
  this.db.exec("PRAGMA journal_mode=WAL");
11433
11446
  this.db.exec(SCHEMA2);
@@ -12174,8 +12187,8 @@ var init_agent_tools = __esm({
12174
12187
  });
12175
12188
 
12176
12189
  // src/memory/proactive/prompts.ts
12177
- import { readFileSync as readFileSync20 } from "node:fs";
12178
- import { join as join30 } from "node:path";
12190
+ import { readFileSync as readFileSync21 } from "node:fs";
12191
+ import { join as join31 } from "node:path";
12179
12192
  function buildSectionRegistry(D) {
12180
12193
  const SECTION_CORE_ROLE = `You are a cognitive graph update agent for a proactive memory system that maintains a dynamic knowledge graph representing ${D.domain_description}.
12181
12194
 
@@ -12787,9 +12800,9 @@ Return your response as JSON.`;
12787
12800
  }
12788
12801
  function loadPersona(workspace) {
12789
12802
  if (!workspace) return "";
12790
- const file2 = join30(workspace, "prompts", "proactive-persona.md");
12803
+ const file2 = join31(workspace, "prompts", "proactive-persona.md");
12791
12804
  try {
12792
- const text = readFileSync20(file2, "utf8").trim();
12805
+ const text = readFileSync21(file2, "utf8").trim();
12793
12806
  if (text) console.log(`[proactive] persona loaded from ${file2} (${text.length} chars)`);
12794
12807
  return text;
12795
12808
  } catch {
@@ -12798,9 +12811,9 @@ function loadPersona(workspace) {
12798
12811
  }
12799
12812
  function loadDomain(workspace) {
12800
12813
  if (!workspace) return DEFAULT_DOMAIN;
12801
- const file2 = join30(workspace, "prompts", "proactive-domain.json");
12814
+ const file2 = join31(workspace, "prompts", "proactive-domain.json");
12802
12815
  try {
12803
- const raw = JSON.parse(readFileSync20(file2, "utf8"));
12816
+ const raw = JSON.parse(readFileSync21(file2, "utf8"));
12804
12817
  if (raw && typeof raw === "object") {
12805
12818
  const allowed = new Set(Object.keys(DEFAULT_DOMAIN));
12806
12819
  const clean = {};
@@ -13308,7 +13321,7 @@ var init_helpers = __esm({
13308
13321
  });
13309
13322
 
13310
13323
  // src/calendar/commands.ts
13311
- import { existsSync as existsSync16, statSync as statSync4 } from "node:fs";
13324
+ import { existsSync as existsSync17, statSync as statSync4 } from "node:fs";
13312
13325
  import { isAbsolute as isAbsolute4, resolve as resolve6 } from "node:path";
13313
13326
  function fmtEnd(start, durationMin) {
13314
13327
  const [hh, mm] = start.split(":").map(Number);
@@ -13477,7 +13490,7 @@ function addTask(db2, args) {
13477
13490
  }
13478
13491
  try {
13479
13492
  const absPath = isAbsolute4(docPath) ? docPath : resolve6(process.cwd(), docPath);
13480
- if (!existsSync16(absPath)) {
13493
+ if (!existsSync17(absPath)) {
13481
13494
  return `\u274C \u521B\u5EFA\u5931\u8D25\uFF1Adoc_path \u6307\u5411\u7684\u6587\u4EF6\u4E0D\u5B58\u5728
13482
13495
  \u8DEF\u5F84: ${docPath}
13483
13496
  \u89E3\u6790\u540E: ${absPath}
@@ -13910,8 +13923,8 @@ var init_recall_score = __esm({
13910
13923
  });
13911
13924
 
13912
13925
  // src/memory/proactive/opportunity.ts
13913
- import { readdirSync as readdirSync3, readFileSync as readFileSync21, existsSync as existsSync17 } from "node:fs";
13914
- import { join as join31 } from "node:path";
13926
+ import { readdirSync as readdirSync3, readFileSync as readFileSync22, existsSync as existsSync18 } from "node:fs";
13927
+ import { join as join32 } from "node:path";
13915
13928
  function normalizeOpportunity(raw) {
13916
13929
  if (!raw || typeof raw !== "object") return null;
13917
13930
  const o = raw;
@@ -13996,8 +14009,8 @@ function parseForesightEntries(everosRoot, now, userId) {
13996
14009
  const today3 = todayKey(now);
13997
14010
  let files;
13998
14011
  if (userId) {
13999
- const ownDir = join31(everosRoot, userId, "default_project", "users", userId, ".foresights");
14000
- files = existsSync17(ownDir) ? listForesightMds(ownDir) : findForesightFiles(everosRoot);
14012
+ const ownDir = join32(everosRoot, userId, "default_project", "users", userId, ".foresights");
14013
+ files = existsSync18(ownDir) ? listForesightMds(ownDir) : findForesightFiles(everosRoot);
14001
14014
  } else {
14002
14015
  files = findForesightFiles(everosRoot);
14003
14016
  }
@@ -14006,7 +14019,7 @@ function parseForesightEntries(everosRoot, now, userId) {
14006
14019
  for (const file2 of files) {
14007
14020
  let content;
14008
14021
  try {
14009
- content = readFileSync21(file2, "utf8");
14022
+ content = readFileSync22(file2, "utf8");
14010
14023
  } catch {
14011
14024
  continue;
14012
14025
  }
@@ -14046,7 +14059,7 @@ function matchForesightForEvent(entries2, message, maxHits = 2) {
14046
14059
  }
14047
14060
  function listForesightMds(dir) {
14048
14061
  try {
14049
- return readdirSync3(dir).filter((f) => /^foresight-\d{4}-\d{2}-\d{2}\.md$/.test(f)).map((f) => join31(dir, f)).sort();
14062
+ return readdirSync3(dir).filter((f) => /^foresight-\d{4}-\d{2}-\d{2}\.md$/.test(f)).map((f) => join32(dir, f)).sort();
14050
14063
  } catch {
14051
14064
  return [];
14052
14065
  }
@@ -14062,7 +14075,7 @@ function findForesightFiles(everosRoot) {
14062
14075
  return;
14063
14076
  }
14064
14077
  for (const e of entries2) {
14065
- const p = join31(dir, e.name);
14078
+ const p = join32(dir, e.name);
14066
14079
  if (e.isDirectory()) {
14067
14080
  if (e.name === ".foresights") {
14068
14081
  files.push(...listForesightMds(p));
@@ -15188,7 +15201,7 @@ var init_intent = __esm({
15188
15201
  });
15189
15202
 
15190
15203
  // src/memory/proactive/sweep.ts
15191
- import { readFileSync as readFileSync22 } from "node:fs";
15204
+ import { readFileSync as readFileSync23 } from "node:fs";
15192
15205
  function sharesTerm(a, b) {
15193
15206
  const x = normalizeTitle(a);
15194
15207
  const y = normalizeTitle(b);
@@ -15408,7 +15421,7 @@ ${JSON.stringify(payload, null, 2)}
15408
15421
  const file2 = this.deps.promptFile;
15409
15422
  if (!file2) return DEFAULT_PROMPT;
15410
15423
  try {
15411
- const text = readFileSync22(file2, "utf8").trim();
15424
+ const text = readFileSync23(file2, "utf8").trim();
15412
15425
  return text || DEFAULT_PROMPT;
15413
15426
  } catch {
15414
15427
  return DEFAULT_PROMPT;
@@ -15419,14 +15432,14 @@ ${JSON.stringify(payload, null, 2)}
15419
15432
  });
15420
15433
 
15421
15434
  // src/memory/proactive/proactive-tools.ts
15422
- import { existsSync as existsSync18 } from "node:fs";
15435
+ import { existsSync as existsSync19 } from "node:fs";
15423
15436
  function setProactiveWorkspace(workspace) {
15424
15437
  toolWorkspace = workspace;
15425
15438
  }
15426
15439
  function withStore(fn) {
15427
15440
  if (!toolWorkspace) return null;
15428
15441
  const p = proactiveDbPath(toolWorkspace);
15429
- if (!existsSync18(p)) return null;
15442
+ if (!existsSync19(p)) return null;
15430
15443
  const store = new Persistence(p);
15431
15444
  try {
15432
15445
  return fn(store);
@@ -15679,8 +15692,8 @@ __export(plugin_exports, {
15679
15692
  ProactivePlugin: () => ProactivePlugin,
15680
15693
  feedMem7Cell: () => feedMem7Cell
15681
15694
  });
15682
- import { join as join32 } from "node:path";
15683
- import { existsSync as existsSync19, readFileSync as readFileSync23, appendFileSync as appendFileSync3 } from "node:fs";
15695
+ import { join as join33 } from "node:path";
15696
+ import { existsSync as existsSync20, readFileSync as readFileSync24, appendFileSync as appendFileSync3 } from "node:fs";
15684
15697
  function isFiller(text) {
15685
15698
  const t = text.trim();
15686
15699
  if (t.length >= 5) return false;
@@ -15705,7 +15718,7 @@ function buildPlanningContext(calDb, workspace) {
15705
15718
  }
15706
15719
  }
15707
15720
  try {
15708
- const state2 = readFileSync23(join32(workspace, "SESSION-STATE.md"), "utf8");
15721
+ const state2 = readFileSync24(join33(workspace, "SESSION-STATE.md"), "utf8");
15709
15722
  const active = extractActiveState(state2);
15710
15723
  if (active) {
15711
15724
  lines.push("\n[SESSION-STATE active work]");
@@ -15902,8 +15915,8 @@ var init_plugin = __esm({
15902
15915
  });
15903
15916
  this.actionAgent = new ActionAgent(this.provider, this.config.modelId, persona);
15904
15917
  this.ingestWorkspace = workspace;
15905
- const calDbPath = join32(workspace, ".calendar", "calendar.db");
15906
- this.calDb = existsSync19(calDbPath) ? openDb(workspace) : null;
15918
+ const calDbPath = join33(workspace, ".calendar", "calendar.db");
15919
+ this.calDb = existsSync20(calDbPath) ? openDb(workspace) : null;
15907
15920
  registerCallbackHook("PostToolUse", {
15908
15921
  type: "callback",
15909
15922
  id: "proactive-completion-evidence",
@@ -15942,7 +15955,7 @@ ${String(input.tool_output ?? "")}`
15942
15955
  const pluginCalDb = this.calDb;
15943
15956
  this.sweep = new Sweep({
15944
15957
  persist: this.persist,
15945
- promptFile: join32(workspace, "prompts", "proactive.md"),
15958
+ promptFile: join33(workspace, "prompts", "proactive.md"),
15946
15959
  // 三个都走 getter **每轮现读** —— 热加载规则(config 改了立刻生效)+
15947
15960
  // calendar 会变,都不能在 start() 时快照。
15948
15961
  get minLeadDays() {
@@ -15960,7 +15973,7 @@ ${String(input.tool_output ?? "")}`
15960
15973
  },
15961
15974
  // 闸掉的必须留痕:她要能"扫一眼标题,真有冤案我喊"。
15962
15975
  onGated: (items) => {
15963
- const gatedPath = join32(workspace, ".proactive", "gated.jsonl");
15976
+ const gatedPath = join33(workspace, ".proactive", "gated.jsonl");
15964
15977
  try {
15965
15978
  appendFileSync3(
15966
15979
  gatedPath,
@@ -16036,7 +16049,7 @@ ${String(input.tool_output ?? "")}`
16036
16049
  const nowDate = /* @__PURE__ */ new Date();
16037
16050
  const stateDir = String(liveConfig.get("stateDir") ?? "");
16038
16051
  if (stateDir) {
16039
- const all = loadForesightEntries(join32(stateDir, "mem7"), nowDate);
16052
+ const all = loadForesightEntries(join33(stateDir, "mem7"), nowDate);
16040
16053
  const events = all.filter((e) => e.kind !== "profile");
16041
16054
  const mem7Entries = capForesightEntries(events, todayKey(nowDate));
16042
16055
  if (all.length > 0) {
@@ -16178,7 +16191,7 @@ ${String(input.tool_output ?? "")}`
16178
16191
  if (!stateDir) this.warnOnce("stateDir", "[proactive] stateDir \u4E3A\u7A7A \u2192 mem7 \u53EC\u56DE\u6574\u6BB5\u8DF3\u8FC7\uFF08\u914D\u7F6E/\u521D\u59CB\u5316\u5F02\u5E38\uFF1F\uFF09");
16179
16192
  if (senderScoped) console.log(`[proactive] sender-scoped recall owners=[${(scopedOwners ?? []).join(",")}]`);
16180
16193
  if (stateDir && scopeReady) {
16181
- const mem7Entries = loadForesightEntries(join32(stateDir, "mem7"), now, void 0, scopedOwners);
16194
+ const mem7Entries = loadForesightEntries(join33(stateDir, "mem7"), now, void 0, scopedOwners);
16182
16195
  const bigram = matchForesightForEvent(mem7Entries, prompt);
16183
16196
  for (const h of bigram) hitSet.add(`[mem7] ${h.replace(/^- /, "")}`);
16184
16197
  if (bigram.length === 0) {
@@ -16302,17 +16315,17 @@ ${String(input.tool_output ?? "")}`
16302
16315
  });
16303
16316
 
16304
16317
  // src/memory/sessionMemory/sessionMemoryUtils.ts
16305
- import { join as join33 } from "node:path";
16306
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync24 } from "node:fs";
16318
+ import { join as join34 } from "node:path";
16319
+ import { mkdirSync as mkdirSync12, readFileSync as readFileSync25 } from "node:fs";
16307
16320
  function setSessionMemoryStateDir(dir) {
16308
16321
  _stateDir2 = dir;
16309
- mkdirSync11(dir, { recursive: true });
16322
+ mkdirSync12(dir, { recursive: true });
16310
16323
  }
16311
16324
  function getSessionMemoryDir() {
16312
16325
  return _stateDir2;
16313
16326
  }
16314
16327
  function getSessionMemoryPath() {
16315
- return join33(_stateDir2, "session-notes.md");
16328
+ return join34(_stateDir2, "session-notes.md");
16316
16329
  }
16317
16330
  function markExtractionStarted() {
16318
16331
  extractionStartedAt = Date.now();
@@ -16360,7 +16373,7 @@ var init_sessionMemoryUtils = __esm({
16360
16373
 
16361
16374
  // src/memory/sessionMemory/prompts.ts
16362
16375
  import { readFile as readFile4 } from "node:fs/promises";
16363
- import { join as join34 } from "node:path";
16376
+ import { join as join35 } from "node:path";
16364
16377
  function roughTokenCountEstimation4(text) {
16365
16378
  return Math.ceil(text.length / 4);
16366
16379
  }
@@ -16405,7 +16418,7 @@ REMEMBER: Use the Edit tool in parallel and stop. Do not continue after the edit
16405
16418
  }
16406
16419
  async function loadSessionMemoryTemplate() {
16407
16420
  const configHome = process.env.CLAUDE_CONFIG_HOME || process.env.HOME || "";
16408
- const templatePath = join34(configHome, ".claude", "session-memory", "config", "template.md");
16421
+ const templatePath = join35(configHome, ".claude", "session-memory", "config", "template.md");
16409
16422
  try {
16410
16423
  return await readFile4(templatePath, { encoding: "utf-8" });
16411
16424
  } catch {
@@ -16414,7 +16427,7 @@ async function loadSessionMemoryTemplate() {
16414
16427
  }
16415
16428
  async function loadSessionMemoryPrompt() {
16416
16429
  const configHome = process.env.CLAUDE_CONFIG_HOME || process.env.HOME || "";
16417
- const promptPath = join34(configHome, ".claude", "session-memory", "config", "prompt.md");
16430
+ const promptPath = join35(configHome, ".claude", "session-memory", "config", "prompt.md");
16418
16431
  try {
16419
16432
  return await readFile4(promptPath, { encoding: "utf-8" });
16420
16433
  } catch {
@@ -16578,7 +16591,7 @@ __export(sessionMemory_exports, {
16578
16591
  resetLastMemoryMessageUuid: () => resetLastMemoryMessageUuid,
16579
16592
  shouldExtractMemory: () => shouldExtractMemory
16580
16593
  });
16581
- import { readFileSync as readFileSync25, mkdirSync as mkdirSync12 } from "node:fs";
16594
+ import { readFileSync as readFileSync26, mkdirSync as mkdirSync13 } from "node:fs";
16582
16595
  import { writeFile as writeFile3 } from "node:fs/promises";
16583
16596
  function initSessionMemory(deps) {
16584
16597
  _deps = deps;
@@ -16637,11 +16650,11 @@ function shouldExtractMemory(estimatedTokens, messages) {
16637
16650
  }
16638
16651
  async function setupSessionMemoryFile() {
16639
16652
  const memoryDir = getSessionMemoryDir();
16640
- mkdirSync12(memoryDir, { recursive: true });
16653
+ mkdirSync13(memoryDir, { recursive: true });
16641
16654
  const memoryPath = getSessionMemoryPath();
16642
16655
  let currentMemory;
16643
16656
  try {
16644
- currentMemory = readFileSync25(memoryPath, { encoding: "utf-8" });
16657
+ currentMemory = readFileSync26(memoryPath, { encoding: "utf-8" });
16645
16658
  } catch {
16646
16659
  const template = await loadSessionMemoryTemplate();
16647
16660
  await writeFile3(memoryPath, template, { encoding: "utf-8" });
@@ -16718,7 +16731,7 @@ ${messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-20)
16718
16731
  }
16719
16732
  function getSessionMemoryForCompaction() {
16720
16733
  try {
16721
- const content = readFileSync25(getSessionMemoryPath(), { encoding: "utf-8" }).trim();
16734
+ const content = readFileSync26(getSessionMemoryPath(), { encoding: "utf-8" }).trim();
16722
16735
  if (!content) return null;
16723
16736
  const { truncatedContent, wasTruncated } = truncateSessionMemoryForCompact(content);
16724
16737
  if (wasTruncated) {
@@ -16751,9 +16764,9 @@ var init_sessionMemory = __esm({
16751
16764
 
16752
16765
  // src/memory/autoDream/consolidationLock.ts
16753
16766
  import { mkdir as mkdir3, readFile as readFile5, stat as stat3, unlink, utimes, writeFile as writeFile4 } from "node:fs/promises";
16754
- import { join as join35 } from "node:path";
16767
+ import { join as join36 } from "node:path";
16755
16768
  function lockPath(memoryDir) {
16756
- return join35(memoryDir, LOCK_FILE);
16769
+ return join36(memoryDir, LOCK_FILE);
16757
16770
  }
16758
16771
  async function readLastConsolidatedAt(memoryDir) {
16759
16772
  try {
@@ -16821,7 +16834,7 @@ async function listSessionsTouchedSince(sessionsDir, sinceMs) {
16821
16834
  const results = [];
16822
16835
  for (const f of jsonlFiles) {
16823
16836
  try {
16824
- const s = await stat3(join35(sessionsDir, f));
16837
+ const s = await stat3(join36(sessionsDir, f));
16825
16838
  if (s.mtimeMs > sinceMs) {
16826
16839
  results.push(f.replace(/\.jsonl$/, ""));
16827
16840
  }
@@ -18357,18 +18370,18 @@ var init_tasks2 = __esm({
18357
18370
  });
18358
18371
 
18359
18372
  // src/version.ts
18360
- import { readFileSync as readFileSync31 } from "node:fs";
18361
- import { dirname as dirname10, join as join43 } from "node:path";
18362
- import { fileURLToPath as fileURLToPath6 } from "node:url";
18373
+ import { readFileSync as readFileSync32 } from "node:fs";
18374
+ import { dirname as dirname11, join as join44 } from "node:path";
18375
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
18363
18376
  function candidates() {
18364
- if (_pkgDirOverride !== null) return [join43(_pkgDirOverride, "package.json")];
18365
- const here = dirname10(fileURLToPath6(import.meta.url));
18366
- return [join43(here, "..", "package.json"), join43(here, "..", "..", "package.json")];
18377
+ if (_pkgDirOverride !== null) return [join44(_pkgDirOverride, "package.json")];
18378
+ const here = dirname11(fileURLToPath7(import.meta.url));
18379
+ return [join44(here, "..", "package.json"), join44(here, "..", "..", "package.json")];
18367
18380
  }
18368
18381
  function readFromDisk() {
18369
18382
  for (const p of candidates()) {
18370
18383
  try {
18371
- return JSON.parse(readFileSync31(p, "utf-8")).version || "unknown";
18384
+ return JSON.parse(readFileSync32(p, "utf-8")).version || "unknown";
18372
18385
  } catch {
18373
18386
  }
18374
18387
  }
@@ -18517,8 +18530,8 @@ var reply_blocklist_exports = {};
18517
18530
  __export(reply_blocklist_exports, {
18518
18531
  isUserBlocked: () => isUserBlocked
18519
18532
  });
18520
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync10, existsSync as existsSync23 } from "node:fs";
18521
- import { join as join44 } from "node:path";
18533
+ import { readFileSync as readFileSync33, writeFileSync as writeFileSync11, existsSync as existsSync24 } from "node:fs";
18534
+ import { join as join45 } from "node:path";
18522
18535
  function ensureLoaded(workspace, configIds) {
18523
18536
  if (loaded) return;
18524
18537
  if (configIds?.length) {
@@ -18526,10 +18539,10 @@ function ensureLoaded(workspace, configIds) {
18526
18539
  if (!state.blockedUserIds.includes(id)) state.blockedUserIds.push(id);
18527
18540
  }
18528
18541
  }
18529
- const path61 = join44(workspace, ".reply-blocklist.json");
18542
+ const path61 = join45(workspace, ".reply-blocklist.json");
18530
18543
  try {
18531
- if (existsSync23(path61)) {
18532
- const raw = readFileSync32(path61, "utf-8");
18544
+ if (existsSync24(path61)) {
18545
+ const raw = readFileSync33(path61, "utf-8");
18533
18546
  const parsed = JSON.parse(raw);
18534
18547
  if (parsed.blockedUserIds) {
18535
18548
  for (const id of parsed.blockedUserIds) {
@@ -18545,9 +18558,9 @@ function ensureLoaded(workspace, configIds) {
18545
18558
  loaded = true;
18546
18559
  }
18547
18560
  function save(workspace) {
18548
- const path61 = join44(workspace, ".reply-blocklist.json");
18561
+ const path61 = join45(workspace, ".reply-blocklist.json");
18549
18562
  try {
18550
- writeFileSync10(path61, JSON.stringify(state, null, 2), "utf-8");
18563
+ writeFileSync11(path61, JSON.stringify(state, null, 2), "utf-8");
18551
18564
  } catch (err) {
18552
18565
  console.warn(`[reply-blocklist] Failed to save: ${err.message}`);
18553
18566
  }
@@ -23662,6 +23675,7 @@ function startConfigWatcher(config, deps, provider) {
23662
23675
  }
23663
23676
  });
23664
23677
  };
23678
+ consumeSelfWrite();
23665
23679
  startWatch();
23666
23680
  console.log(`[config-watch] watching ${configPath}`);
23667
23681
  try {
@@ -25524,6 +25538,18 @@ var FIELDS = [
25524
25538
 
25525
25539
  // src/cli-init-config.ts
25526
25540
  var FREE_TIER_RELAY_URL = "https://www.twinsun.top:8866";
25541
+ var FREE_TIER_PROVIDER_ID = "7yi";
25542
+ var DEFAULT_FREE_VOICE = "Chinese (Mandarin)_Warm_Girl";
25543
+ function freeTierVoiceConfig(existing) {
25544
+ const mv = existing && typeof existing === "object" ? existing : {};
25545
+ return {
25546
+ ...mv,
25547
+ provider: "relay",
25548
+ relayProviderId: FREE_TIER_PROVIDER_ID,
25549
+ relayModel: "engine7-tts",
25550
+ voice: mv.voice || DEFAULT_FREE_VOICE
25551
+ };
25552
+ }
25527
25553
  var VISION_CAPABLE = {
25528
25554
  // 0917:原先标 true,但同一个文件里 qwen3.8-max 的 input 是 ['text'],安装器目录
25529
25555
  // 也明确标 vision=false(只有 Flash 叫"多模态")。矛盾直接导致**默认 CLI 装机路径**
@@ -25758,6 +25784,104 @@ function applyFreeTierVideoFixup(io) {
25758
25784
  return changed;
25759
25785
  }
25760
25786
 
25787
+ // src/provision-free.ts
25788
+ import { randomBytes as randomBytes2, randomUUID as randomUUID5 } from "node:crypto";
25789
+ import { chmodSync, existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
25790
+ import { dirname as dirname3, join as join14 } from "node:path";
25791
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
25792
+ var __filename = fileURLToPath2(import.meta.url);
25793
+ var IDENTITY_FILE = "install-identity.json";
25794
+ function readContactEmailOf(parsed) {
25795
+ return typeof parsed?.contactEmail === "string" ? parsed.contactEmail.trim() : "";
25796
+ }
25797
+ function loadOrCreateInstallIdentity(stateDir) {
25798
+ const file2 = join14(stateDir, IDENTITY_FILE);
25799
+ if (existsSync9(file2)) {
25800
+ let parsed;
25801
+ try {
25802
+ parsed = JSON.parse(readFileSync8(file2, "utf8"));
25803
+ } catch (e) {
25804
+ throw new Error(
25805
+ `${IDENTITY_FILE} \u5B58\u5728\u4F46\u4E0D\u662F\u5408\u6CD5 JSON\uFF08${e.message}\uFF09\u2014\u2014\u5220\u6389\u5B83\u91CD\u8DD1\u4F1A\u9886\u4E00\u628A\u65B0\u4EE4\u724C\uFF0C\u65E7\u7684\u90A3\u628A\u53D6\u4E0D\u56DE\u6765`
25806
+ );
25807
+ }
25808
+ if (typeof parsed?.installId !== "string" || typeof parsed?.installSecret !== "string") {
25809
+ throw new Error(`${IDENTITY_FILE} \u7F3A installId / installSecret \u5B57\u6BB5`);
25810
+ }
25811
+ const email = readContactEmailOf(parsed);
25812
+ return {
25813
+ installId: parsed.installId,
25814
+ installSecret: parsed.installSecret,
25815
+ ...email ? { contactEmail: email } : {}
25816
+ };
25817
+ }
25818
+ const identity = {
25819
+ // 服务端校验 installId 长度为 8..36、只允许字母数字和连字符;uuid 正好符合
25820
+ installId: randomUUID5(),
25821
+ // 服务端校验 installSecret 为 32..64 位十六进制
25822
+ installSecret: randomBytes2(32).toString("hex")
25823
+ };
25824
+ mkdirSync6(stateDir, { recursive: true });
25825
+ writeFileSync3(file2, JSON.stringify(identity, null, 2) + "\n", { mode: 384 });
25826
+ try {
25827
+ chmodSync(file2, 384);
25828
+ } catch {
25829
+ }
25830
+ return identity;
25831
+ }
25832
+ function readInstallIdentityDetailed(stateDir) {
25833
+ const file2 = join14(stateDir, IDENTITY_FILE);
25834
+ if (!existsSync9(file2)) return { ok: false, reason: "missing" };
25835
+ let text;
25836
+ try {
25837
+ text = readFileSync8(file2, "utf8");
25838
+ } catch (e) {
25839
+ return { ok: false, reason: "corrupt", detail: `\u5B58\u5728\u4F46\u8BFB\u4E0D\u4E86\uFF08${e?.message ?? e}\uFF09` };
25840
+ }
25841
+ let parsed;
25842
+ try {
25843
+ parsed = JSON.parse(text);
25844
+ } catch (e) {
25845
+ return { ok: false, reason: "corrupt", detail: `\u4E0D\u662F\u5408\u6CD5 JSON\uFF08${e?.message ?? e}\uFF09` };
25846
+ }
25847
+ if (typeof parsed?.installId !== "string" || typeof parsed?.installSecret !== "string") {
25848
+ return { ok: false, reason: "corrupt", detail: "\u7F3A installId / installSecret \u5B57\u6BB5" };
25849
+ }
25850
+ const email = readContactEmailOf(parsed);
25851
+ return {
25852
+ ok: true,
25853
+ identity: {
25854
+ installId: parsed.installId,
25855
+ installSecret: parsed.installSecret,
25856
+ ...email ? { contactEmail: email } : {}
25857
+ }
25858
+ };
25859
+ }
25860
+
25861
+ // src/free-tier-apply.ts
25862
+ function isFreeTierConfig(cfg) {
25863
+ const hasProvider = !!cfg?.models?.providers?.[FREE_TIER_PROVIDER_ID];
25864
+ const primary = String(cfg?.agents?.defaults?.model?.primary || "");
25865
+ return hasProvider && primary.startsWith(`${FREE_TIER_PROVIDER_ID}/`);
25866
+ }
25867
+
25868
+ // src/startup/free-tier-voice-fixup.ts
25869
+ function needsFreeTierVoiceFixup(cfg) {
25870
+ if (!isFreeTierConfig(cfg)) return false;
25871
+ return cfg?.tools?.my_voice === void 0;
25872
+ }
25873
+ async function applyFreeTierVoiceFixup(io) {
25874
+ const cfg = io.all();
25875
+ if (!needsFreeTierVoiceFixup(cfg)) return false;
25876
+ const persisted = await io.set("tools.my_voice", freeTierVoiceConfig());
25877
+ if (persisted === false) {
25878
+ console.error("[startup] \u514D\u8D39\u6863\u8865\u9F50 tools.my_voice **\u672A\u843D\u76D8**\uFF08\u672C\u6B21\u8FD0\u884C\u5185\u5B58\u91CC\u5DF2\u751F\u6548\uFF0C\u914D\u7F6E\u6587\u4EF6\u4ECD\u662F\u65E7\u7684\u2014\u2014\u6258\u76D8/\u4E0B\u6B21\u542F\u52A8\u770B\u5230\u7684\u8FD8\u662F edge-tts\uFF09\u3002\u4E0A\u9762 [liveConfig] \u90A3\u884C\u662F\u539F\u56E0\u3002");
25879
+ return true;
25880
+ }
25881
+ console.log("[startup] \u514D\u8D39\u6863\u8865\u9F50 tools.my_voice \u2192 7yi\uFF08\u5347\u7EA7\u524D\u88C5\u7684\u673A\u5668\u8FD9\u5757\u4ECE\u672A\u88AB\u5199\u8FC7\uFF0C\u8BED\u97F3\u6761\u6B64\u524D\u843D\u5230 edge-tts\uFF1B\u7528\u6237\u81EA\u5DF1\u914D\u8FC7\u7684\u4E0D\u52A8\uFF09");
25882
+ return true;
25883
+ }
25884
+
25761
25885
  // src/startup/hooks-boot.ts
25762
25886
  init_live();
25763
25887
  import * as fs23 from "node:fs";
@@ -26811,7 +26935,7 @@ ${manifest}`
26811
26935
  // src/memory/memdir/findRelevantMemoriesVector.ts
26812
26936
  init_well_formed();
26813
26937
  import { statSync as statSync3 } from "node:fs";
26814
- import { join as join19, resolve as resolve5, sep as sep4 } from "node:path";
26938
+ import { join as join20, resolve as resolve5, sep as sep4 } from "node:path";
26815
26939
  import { createRequire as createRequire2 } from "node:module";
26816
26940
  var require2 = createRequire2(import.meta.url);
26817
26941
  var DEFAULT_TOP_K = 3;
@@ -26964,7 +27088,7 @@ async function findRelevantMemoriesVector(query, memoryDir, alreadySurfaced = /*
26964
27088
  }
26965
27089
  const scored = [];
26966
27090
  for (const row of rows) {
26967
- const absPath = join19(memoryDir, row.file_path.replace(/\//g, sep4));
27091
+ const absPath = join20(memoryDir, row.file_path.replace(/\//g, sep4));
26968
27092
  if (alreadySurfaced.has(absPath) || alreadySurfaced.has(row.file_path)) continue;
26969
27093
  const emb = new Float32Array(row.embedding.buffer, row.embedding.byteOffset, row.embedding.byteLength / 4);
26970
27094
  const score = cosineSim(qVec, emb);
@@ -27177,27 +27301,27 @@ ${ep.episode || ep.summary}`,
27177
27301
 
27178
27302
  // src/handle-query.ts
27179
27303
  init_paths();
27180
- import { readFileSync as readFileSync26, existsSync as existsSync20, statSync as statSync5 } from "node:fs";
27181
- import { join as join36, resolve as resolve7 } from "node:path";
27304
+ import { readFileSync as readFileSync27, existsSync as existsSync21, statSync as statSync5 } from "node:fs";
27305
+ import { join as join37, resolve as resolve7 } from "node:path";
27182
27306
  import * as path21 from "node:path";
27183
27307
 
27184
27308
  // src/light-mode.ts
27185
27309
  init_live();
27186
- import { readFileSync as readFileSync12 } from "node:fs";
27310
+ import { readFileSync as readFileSync13 } from "node:fs";
27187
27311
 
27188
27312
  // src/config/persona-files.ts
27189
- import { existsSync as existsSync11 } from "node:fs";
27190
- import { join as join20 } from "node:path";
27313
+ import { existsSync as existsSync12 } from "node:fs";
27314
+ import { join as join21 } from "node:path";
27191
27315
  var LEGACY_RELATIVE = {
27192
27316
  "my-inner-voice.md": "prompts/my-inner-voice.md"
27193
27317
  };
27194
27318
  function resolvePersonaFile(workspace, persona, name) {
27195
27319
  if (persona) {
27196
- const scoped = join20(workspace, "personas", persona, name);
27197
- if (existsSync11(scoped)) return scoped;
27320
+ const scoped = join21(workspace, "personas", persona, name);
27321
+ if (existsSync12(scoped)) return scoped;
27198
27322
  }
27199
- const legacy = join20(workspace, LEGACY_RELATIVE[name] ?? name);
27200
- return existsSync11(legacy) ? legacy : null;
27323
+ const legacy = join21(workspace, LEGACY_RELATIVE[name] ?? name);
27324
+ return existsSync12(legacy) ? legacy : null;
27201
27325
  }
27202
27326
 
27203
27327
  // src/light-mode.ts
@@ -27238,7 +27362,7 @@ function buildLightStablePrompt(workspace, mode, opts) {
27238
27362
  const filePath = resolvePersonaFile(workspace, persona, f);
27239
27363
  if (!filePath) continue;
27240
27364
  try {
27241
- parts.push(readFileSync12(filePath, "utf-8").trim());
27365
+ parts.push(readFileSync13(filePath, "utf-8").trim());
27242
27366
  } catch {
27243
27367
  }
27244
27368
  }
@@ -27322,8 +27446,8 @@ function voiceFastView(history, opts = VOICE_FAST_DEFAULTS) {
27322
27446
 
27323
27447
  // src/sender-context.ts
27324
27448
  init_clock();
27325
- import { readFileSync as readFileSync13, existsSync as existsSync13 } from "node:fs";
27326
- import { join as join21 } from "node:path";
27449
+ import { readFileSync as readFileSync14, existsSync as existsSync14 } from "node:fs";
27450
+ import { join as join22 } from "node:path";
27327
27451
  var contactMap = null;
27328
27452
  var externalChanWhitelist = null;
27329
27453
  function loadContactMap(workspace) {
@@ -27331,10 +27455,10 @@ function loadContactMap(workspace) {
27331
27455
  contactMap = /* @__PURE__ */ new Map();
27332
27456
  externalChanWhitelist = /* @__PURE__ */ new Set();
27333
27457
  try {
27334
- const contactsPath = join21(workspace, "prompts", "contacts.md");
27335
- console.log(`[meta] Loading contacts from ${contactsPath}, exists=${existsSync13(contactsPath)}`);
27336
- if (existsSync13(contactsPath)) {
27337
- const text = readFileSync13(contactsPath, "utf-8");
27458
+ const contactsPath = join22(workspace, "prompts", "contacts.md");
27459
+ console.log(`[meta] Loading contacts from ${contactsPath}, exists=${existsSync14(contactsPath)}`);
27460
+ if (existsSync14(contactsPath)) {
27461
+ const text = readFileSync14(contactsPath, "utf-8");
27338
27462
  const lines = text.split("\n");
27339
27463
  for (const line of lines) {
27340
27464
  const m = line.match(/^\|\s*(.+?)\s*\|\s*([a-zA-Z0-9_@.]+)\s*\|/);
@@ -27423,12 +27547,12 @@ function resetSessionStartInjection(sessionId) {
27423
27547
  }
27424
27548
  var externalChanRulesCache = null;
27425
27549
  function loadExternalChanRules(workspace) {
27426
- const path61 = join36(workspace, "prompts", "external-chan-rules.md");
27550
+ const path61 = join37(workspace, "prompts", "external-chan-rules.md");
27427
27551
  if (externalChanRulesCache && externalChanRulesCache.path === path61) return externalChanRulesCache;
27428
27552
  let content = "";
27429
- if (existsSync20(path61)) {
27553
+ if (existsSync21(path61)) {
27430
27554
  try {
27431
- content = readFileSync26(path61, "utf-8").trim();
27555
+ content = readFileSync27(path61, "utf-8").trim();
27432
27556
  } catch (e) {
27433
27557
  console.warn(`[external-chan-rules] Failed to load: ${e}`);
27434
27558
  }
@@ -27599,7 +27723,7 @@ ${text}` : text });
27599
27723
  }
27600
27724
  if (source === "user") {
27601
27725
  try {
27602
- const wm = readFileSync26(join36(workspace, ".work-mode"), "utf-8").trim();
27726
+ const wm = readFileSync27(join37(workspace, ".work-mode"), "utf-8").trim();
27603
27727
  if (wm === "on" && chatMode !== "work") {
27604
27728
  chatMode = "work";
27605
27729
  console.log(`[mode] ${sessionId} /work on \u2192 \u5F3A\u5236 work`);
@@ -27842,7 +27966,7 @@ ${text}` : text });
27842
27966
  for (const memPath of newPaths) {
27843
27967
  try {
27844
27968
  const stat4 = statSync5(memPath);
27845
- const content = readFileSync26(memPath, "utf-8");
27969
+ const content = readFileSync27(memPath, "utf-8");
27846
27970
  const header = memoryHeader(memPath, stat4.mtimeMs);
27847
27971
  restoredMemories.push({ path: memPath, content, mtimeMs: stat4.mtimeMs, header });
27848
27972
  } catch {
@@ -27929,7 +28053,7 @@ ${text}` : text });
27929
28053
  const attachmentMemories = [];
27930
28054
  for (const mem of relevantMemories) {
27931
28055
  try {
27932
- const content = mem.content ?? readFileSync26(mem.path, "utf-8");
28056
+ const content = mem.content ?? readFileSync27(mem.path, "utf-8");
27933
28057
  const header = mem.header ?? memoryHeader(mem.path, mem.mtimeMs);
27934
28058
  attachmentMemories.push({ path: mem.path, content, mtimeMs: mem.mtimeMs, header });
27935
28059
  } catch {
@@ -28249,7 +28373,7 @@ stack: ${err.stack ?? "(none)"}`);
28249
28373
  }
28250
28374
  } catch (err) {
28251
28375
  try {
28252
- (await import("node:fs")).appendFileSync(join36(process.env.ENGINE7_STATE_DIR || path21.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
28376
+ (await import("node:fs")).appendFileSync(join37(process.env.ENGINE7_STATE_DIR || path21.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
28253
28377
  stack: ${err.stack ?? "(none)"}
28254
28378
  `);
28255
28379
  } catch {
@@ -34855,80 +34979,6 @@ ${inbound.content}` }, ...videoBlocks];
34855
34979
  // src/optional/reporting/reporter.ts
34856
34980
  init_live();
34857
34981
 
34858
- // src/provision-free.ts
34859
- import { randomBytes as randomBytes4, randomUUID as randomUUID6 } from "node:crypto";
34860
- import { chmodSync, existsSync as existsSync24, mkdirSync as mkdirSync15, readFileSync as readFileSync34, writeFileSync as writeFileSync12 } from "node:fs";
34861
- import { dirname as dirname12, join as join47 } from "node:path";
34862
- import { fileURLToPath as fileURLToPath7 } from "node:url";
34863
- var __filename = fileURLToPath7(import.meta.url);
34864
- var IDENTITY_FILE = "install-identity.json";
34865
- function readContactEmailOf(parsed) {
34866
- return typeof parsed?.contactEmail === "string" ? parsed.contactEmail.trim() : "";
34867
- }
34868
- function loadOrCreateInstallIdentity(stateDir) {
34869
- const file2 = join47(stateDir, IDENTITY_FILE);
34870
- if (existsSync24(file2)) {
34871
- let parsed;
34872
- try {
34873
- parsed = JSON.parse(readFileSync34(file2, "utf8"));
34874
- } catch (e) {
34875
- throw new Error(
34876
- `${IDENTITY_FILE} \u5B58\u5728\u4F46\u4E0D\u662F\u5408\u6CD5 JSON\uFF08${e.message}\uFF09\u2014\u2014\u5220\u6389\u5B83\u91CD\u8DD1\u4F1A\u9886\u4E00\u628A\u65B0\u4EE4\u724C\uFF0C\u65E7\u7684\u90A3\u628A\u53D6\u4E0D\u56DE\u6765`
34877
- );
34878
- }
34879
- if (typeof parsed?.installId !== "string" || typeof parsed?.installSecret !== "string") {
34880
- throw new Error(`${IDENTITY_FILE} \u7F3A installId / installSecret \u5B57\u6BB5`);
34881
- }
34882
- const email = readContactEmailOf(parsed);
34883
- return {
34884
- installId: parsed.installId,
34885
- installSecret: parsed.installSecret,
34886
- ...email ? { contactEmail: email } : {}
34887
- };
34888
- }
34889
- const identity = {
34890
- // 服务端校验 installId 长度为 8..36、只允许字母数字和连字符;uuid 正好符合
34891
- installId: randomUUID6(),
34892
- // 服务端校验 installSecret 为 32..64 位十六进制
34893
- installSecret: randomBytes4(32).toString("hex")
34894
- };
34895
- mkdirSync15(stateDir, { recursive: true });
34896
- writeFileSync12(file2, JSON.stringify(identity, null, 2) + "\n", { mode: 384 });
34897
- try {
34898
- chmodSync(file2, 384);
34899
- } catch {
34900
- }
34901
- return identity;
34902
- }
34903
- function readInstallIdentityDetailed(stateDir) {
34904
- const file2 = join47(stateDir, IDENTITY_FILE);
34905
- if (!existsSync24(file2)) return { ok: false, reason: "missing" };
34906
- let text;
34907
- try {
34908
- text = readFileSync34(file2, "utf8");
34909
- } catch (e) {
34910
- return { ok: false, reason: "corrupt", detail: `\u5B58\u5728\u4F46\u8BFB\u4E0D\u4E86\uFF08${e?.message ?? e}\uFF09` };
34911
- }
34912
- let parsed;
34913
- try {
34914
- parsed = JSON.parse(text);
34915
- } catch (e) {
34916
- return { ok: false, reason: "corrupt", detail: `\u4E0D\u662F\u5408\u6CD5 JSON\uFF08${e?.message ?? e}\uFF09` };
34917
- }
34918
- if (typeof parsed?.installId !== "string" || typeof parsed?.installSecret !== "string") {
34919
- return { ok: false, reason: "corrupt", detail: "\u7F3A installId / installSecret \u5B57\u6BB5" };
34920
- }
34921
- const email = readContactEmailOf(parsed);
34922
- return {
34923
- ok: true,
34924
- identity: {
34925
- installId: parsed.installId,
34926
- installSecret: parsed.installSecret,
34927
- ...email ? { contactEmail: email } : {}
34928
- }
34929
- };
34930
- }
34931
-
34932
34982
  // src/optional/reporting/state.ts
34933
34983
  import { existsSync as existsSync25, mkdirSync as mkdirSync16, readFileSync as readFileSync35, writeFileSync as writeFileSync13 } from "node:fs";
34934
34984
  import { join as join48 } from "node:path";
@@ -35796,6 +35846,21 @@ var FeishuAdapter = class _FeishuAdapter {
35796
35846
  }
35797
35847
  }
35798
35848
  }
35849
+ /**
35850
+ * 检查飞书 API 的**业务返回码**(1001)。
35851
+ *
35852
+ * SDK 只在 **HTTP 非 2xx** 时抛错;业务错误走的是 "HTTP 200 + code≠0" —— 不查码就等于把
35853
+ * "飞书拒了"读成"发出去了"。客户那台 mac 的语音条"日志 Voice sent!、人没收到"卡了一整天
35854
+ * 就是卡在这儿:**引擎从不看码,所以线上到底是发成功了还是被拒了,日志里一个字都没有**。
35855
+ * (1001 实测:同一套参数在我方租户 code:0 全绿,把时长/内容形状/chat_id 通道三项嫌疑逐条排除,
35856
+ * 嫌疑因此全部落到"客户租户返回了什么"上——而那个答案以前根本打印不出来。)
35857
+ */
35858
+ _assertApiOk(res, what) {
35859
+ const code = res?.code;
35860
+ if (typeof code === "number" && code !== 0) {
35861
+ throw new Error(`Feishu ${what} \u88AB\u62D2: code=${code} msg=${res?.msg ?? ""}\uFF08HTTP 2xx \u4E5F\u53EF\u80FD\u662F\u4E1A\u52A1\u9519\u8BEF\u2014\u2014\u8FD9\u6B63\u662F\u300C\u62A5\u6210\u529F\u5374\u6CA1\u5230\u300D\u90A3\u7C7B\uFF09`);
35862
+ }
35863
+ }
35799
35864
  /** 发送媒体附件(图片/文件) */
35800
35865
  async sendFile(target, message, attachment) {
35801
35866
  const fs60 = await import("node:fs");
@@ -35813,25 +35878,25 @@ var FeishuAdapter = class _FeishuAdapter {
35813
35878
  const imageKey = await this._uploadImage(fileBuffer, filename);
35814
35879
  if (message) {
35815
35880
  const postContent = this._buildImagePost(message, imageKey);
35816
- await this.client.im.message.create({
35881
+ this._assertApiOk(await this.client.im.message.create({
35817
35882
  params: { receive_id_type: receiveIdType },
35818
35883
  data: { receive_id: safeTarget, msg_type: "post", content: JSON.stringify(postContent) }
35819
- });
35884
+ }), "\u56FE\u7247\u6D88\u606F\u53D1\u9001");
35820
35885
  } else {
35821
- await this.client.im.message.create({
35886
+ this._assertApiOk(await this.client.im.message.create({
35822
35887
  params: { receive_id_type: receiveIdType },
35823
35888
  data: { receive_id: safeTarget, msg_type: "image", content: JSON.stringify({ image_key: imageKey }) }
35824
- });
35889
+ }), "\u56FE\u7247\u6D88\u606F\u53D1\u9001");
35825
35890
  }
35826
35891
  } else if (mimeType.startsWith("audio/")) {
35827
35892
  const isOpus = filename.endsWith(".opus") || filename.endsWith(".ogg") || mimeType === "audio/opus";
35828
35893
  if (!isOpus) {
35829
35894
  console.warn(`[feishu:sendFile] audio '${filename}' \u4E0D\u662Fopus\uFF0C\u964D\u7EA7\u4E3A\u6587\u4EF6\u6D88\u606F\uFF08\u975E\u8BED\u97F3\u6761\uFF09`);
35830
35895
  const fileKey = await this._uploadFile(fileBuffer, filename);
35831
- await this.client.im.message.create({
35896
+ this._assertApiOk(await this.client.im.message.create({
35832
35897
  params: { receive_id_type: receiveIdType },
35833
35898
  data: { receive_id: safeTarget, msg_type: "file", content: JSON.stringify({ file_key: fileKey }) }
35834
- });
35899
+ }), "\u6587\u4EF6\u6D88\u606F\u53D1\u9001\uFF08\u975E opus \u97F3\u9891\u964D\u7EA7\uFF09");
35835
35900
  } else {
35836
35901
  let durationMs = Math.round(fileBuffer.length / 3);
35837
35902
  try {
@@ -35844,17 +35909,17 @@ var FeishuAdapter = class _FeishuAdapter {
35844
35909
  } catch {
35845
35910
  }
35846
35911
  const audioKey = await this._uploadAudio(fileBuffer, filename.endsWith(".opus") ? filename : filename.replace(/\.[^.]+$/, ".opus"), durationMs);
35847
- await this.client.im.message.create({
35912
+ this._assertApiOk(await this.client.im.message.create({
35848
35913
  params: { receive_id_type: receiveIdType },
35849
35914
  data: { receive_id: safeTarget, msg_type: "audio", content: JSON.stringify({ file_key: audioKey }) }
35850
- });
35915
+ }), "\u8BED\u97F3\u6761\u53D1\u9001");
35851
35916
  }
35852
35917
  } else {
35853
35918
  const fileKey = await this._uploadFile(fileBuffer, filename);
35854
- await this.client.im.message.create({
35919
+ this._assertApiOk(await this.client.im.message.create({
35855
35920
  params: { receive_id_type: receiveIdType },
35856
35921
  data: { receive_id: safeTarget, msg_type: "file", content: JSON.stringify({ file_key: fileKey }) }
35857
- });
35922
+ }), "\u6587\u4EF6\u6D88\u606F\u53D1\u9001");
35858
35923
  }
35859
35924
  if (message && mimeType.startsWith("image/")) {
35860
35925
  } else if (message) {
@@ -41012,7 +41077,7 @@ var TTS_IMPL = {
41012
41077
  if (r.warning) console.warn(`[my-voice] ${r.warning}`);
41013
41078
  if (!r.voice) {
41014
41079
  throw new TtsConfigError(
41015
- "relay TTS \u7F3A\u97F3\u8272\uFF1Atools.my_voice.voice \u662F\u7A7A\u7684\uFF0C\u4E0A\u6E38\u4F1A\u62D2\u3002\u514D\u8D39\u6863\u88C5\u673A\u5E94\u5DF2\u7531 applyFreeTier \u586B\u597D\u9ED8\u8BA4\u97F3\u8272\u3002"
41080
+ "relay TTS \u7F3A\u97F3\u8272\uFF1Atools.my_voice.voice \u662F\u7A7A\u7684\uFF0C\u4E0A\u6E38\u4F1A\u62D2\u3002\u514D\u8D39\u6863\u88C5\u673A\u5E94\u5DF2\u81EA\u52A8\u586B\u597D\u9ED8\u8BA4\u97F3\u8272\uFF08\u65B0\u88C5\u673A generateConfig / \u8001\u88C5\u673A\u542F\u52A8\u8865\u9F50 / \u5207\u6362\u514D\u8D39\u6863 applyFreeTier \u4E09\u6761\u8DEF\uFF0C\u89C1 cli-init-config.ts \u7684 freeTierVoiceConfig\uFF09\u3002"
41016
41081
  );
41017
41082
  }
41018
41083
  try {
@@ -41235,7 +41300,7 @@ registry.register({
41235
41300
  description: "TTS engine. relay = 7yi \u4E2D\u8F6C\u7AD9\uFF08\u514D\u8D39\u6863\u9ED8\u8BA4\uFF09\uFF0Ccosyvoice = \u767E\u70BC API\uFF0Cgptsovits = \u672C\u5730\u514B\u9686\uFF0Cqwen3-3060 = \u672C\u5730 GGML\uFF0Cedge = \u515C\u5E95\u3002"
41236
41301
  },
41237
41302
  channel: { type: "string", enum: ["weixin", "feishu", "discord"], description: "Target channel. Default: current channel." },
41238
- to: { type: "string", description: "Recipient ID. \u5FAE\u4FE1\u683C\u5F0F o\u5F00\u5934@im.wechat\u7ED3\u5C3E\uFF0C\u98DE\u4E66\u683C\u5F0F ou_\u5F00\u5934 open_id\u3002\u4E0D\u786E\u5B9A\u5C31\u5148 read prompts/contacts.md \u67E5\u6536\u4EF6\u4EBA ID\u3002multaca \u4EFB\u52A1\u91CC\u4E0D\u9700\u8981\u586B to\u2014\u2014\u8BED\u97F3\u4F1A\u6302\u5230\u5F53\u524D issue \u8BC4\u8BBA\uFF0C\u586B issueId \u6307\u5B9A\u76EE\u6807 issue\u3002" },
41303
+ to: { type: "string", description: 'Recipient ID, ONLY when sending to someone else. \u5FAE\u4FE1\u683C\u5F0F o\u5F00\u5934@im.wechat\u7ED3\u5C3E\uFF0C\u98DE\u4E66\u683C\u5F0F ou_\u5F00\u5934 open_id\uFF1B\u53D1\u7ED9\u522B\u4EBA\u524D read prompts/contacts.md \u67E5\u6536\u4EF6\u4EBA ID\u3002**\u53D1\u7ED9\u5F53\u524D\u5BF9\u8BDD\u7684\u4EBA\uFF08"\u53D1\u7ED9\u6211/\u53D1\u6761\u8BED\u97F3"\uFF09\u4E0D\u8981\u586B to**\u2014\u2014\u7559\u7A7A\u5373\u53D1\u5F53\u524D\u4F1A\u8BDD\uFF0C\u8FD9\u662F\u9ED8\u8BA4\u4E5F\u662F\u66F4\u7A33\u7684\u8DEF\uFF08\u90E8\u5206\u79DF\u6237\u4F1A\u62D2"\u6309\u7528\u6237 ID \u76F4\u53D1"\uFF0C\u89C1 1001 \u6848\u4F8B\uFF09\u3002multaca \u4EFB\u52A1\u91CC\u4E0D\u9700\u8981\u586B to\u2014\u2014\u8BED\u97F3\u4F1A\u6302\u5230\u5F53\u524D issue \u8BC4\u8BBA\uFF0C\u586B issueId \u6307\u5B9A\u76EE\u6807 issue\u3002' },
41239
41304
  issueId: { type: "string", description: 'multaca headless \u4E13\u7528\uFF1A\u76EE\u6807 issue ID\uFF08\u4EFB\u52A1 prompt \u91CC\u7684 "Your assigned issue ID"\uFF09\u3002\u666E\u901A\u98DE\u4E66/\u5FAE\u4FE1\u573A\u666F\u4E0D\u8981\u586B\u3002' },
41240
41305
  caption: { type: "string", description: "Optional text to accompany the voice message." }
41241
41306
  },
@@ -41347,7 +41412,8 @@ registry.register({
41347
41412
  }
41348
41413
  return { content: `Voice sent! (${actualEngine}, ${sizeKB.toFixed(0)}KB, ${resolvedChannel})` };
41349
41414
  } catch (err) {
41350
- return { content: `Voice send failed: ${err.message}`, isError: true };
41415
+ const toHint = args.to ? '\u3002\u26A0\uFE0F \u8FD9\u6B21\u5E26\u7684\u662F to=\u6536\u4EF6\u4EBA ID\uFF1A\u82E5\u6536\u4EF6\u4EBA\u5C31\u662F**\u5F53\u524D\u5BF9\u8BDD\u7684\u4EBA**\uFF0C\u53BB\u6389 to \u91CD\u8BD5\u2014\u2014\u5F15\u64CE\u4F1A\u53D1\u7ED9\u5F53\u524D\u4F1A\u8BDD\uFF0C\u90E8\u5206\u79DF\u6237\u4F1A\u62D2"\u6309\u7528\u6237 ID \u76F4\u53D1"\uFF08\u98DE\u4E66 230101\uFF09' : "";
41416
+ return { content: `Voice send failed: ${err.message}${toHint}`, isError: true };
41351
41417
  }
41352
41418
  },
41353
41419
  isConcurrencySafe: () => false,
@@ -44886,6 +44952,7 @@ async function startEngine(config, opts) {
44886
44952
  applyFreeTierVideoFixup({ all: () => liveConfig.all(), set: (p, v) => {
44887
44953
  void liveConfig.set(p, v);
44888
44954
  } });
44955
+ await applyFreeTierVoiceFixup({ all: () => liveConfig.all(), set: (p, v) => liveConfig.set(p, v) });
44889
44956
  let provider;
44890
44957
  let visionProvider;
44891
44958
  let visionChainLabels;