engine7 7.1.43 → 7.1.45

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
@@ -138,6 +138,32 @@ var init_feishu_quick_register = __esm({
138
138
  }
139
139
  });
140
140
 
141
+ // src/qr-render.ts
142
+ var qr_render_exports = {};
143
+ __export(qr_render_exports, {
144
+ renderQrTerminal: () => renderQrTerminal
145
+ });
146
+ import { createRequire } from "node:module";
147
+ async function renderQrTerminal(url, options) {
148
+ return new Promise((resolve2, reject) => {
149
+ try {
150
+ const qt = require2("qrcode-terminal");
151
+ qt.generate(url, { small: options?.small ?? true }, (output) => {
152
+ resolve2(output);
153
+ });
154
+ } catch (err) {
155
+ reject(err);
156
+ }
157
+ });
158
+ }
159
+ var require2;
160
+ var init_qr_render = __esm({
161
+ "src/qr-render.ts"() {
162
+ "use strict";
163
+ require2 = createRequire(import.meta.url);
164
+ }
165
+ });
166
+
141
167
  // src/channels/wechat.ts
142
168
  var wechat_exports = {};
143
169
  __export(wechat_exports, {
@@ -425,20 +451,35 @@ async function wechatQrLogin(options) {
425
451
  console.error("[wechat] QR response missing qrcode field");
426
452
  return null;
427
453
  }
454
+ let pollQrValue = qrcodeValue;
428
455
  const qrScanData = qrcodeUrl || qrcodeValue;
429
- console.log("\n========== \u5FAE\u4FE1\u626B\u7801\u767B\u5F55 ==========");
430
- if (qrcodeUrl) {
431
- console.log(`\u626B\u7801\u94FE\u63A5: ${qrcodeUrl}`);
456
+ try {
457
+ const { renderQrTerminal: renderQrTerminal2 } = await Promise.resolve().then(() => (init_qr_render(), qr_render_exports));
458
+ const qrBlock = await renderQrTerminal2(qrScanData);
459
+ console.log("\n========== \u5FAE\u4FE1\u626B\u7801\u767B\u5F55 ==========");
460
+ if (qrcodeUrl) {
461
+ console.log(`\u626B\u7801\u94FE\u63A5: ${qrcodeUrl}`);
462
+ }
463
+ if (qrBlock) {
464
+ console.log("\u8BF7\u7528\u5FAE\u4FE1\u626B\u63CF\u4EE5\u4E0B\u4E8C\u7EF4\u7801:");
465
+ console.log(qrBlock);
466
+ } else {
467
+ console.log("\u4E8C\u7EF4\u7801\u6E32\u67D3\u5931\u8D25\uFF0C\u8BF7\u7528\u5FAE\u4FE1\u300C\u626B\u4E00\u626B\u300D\u6253\u5F00\u4E0A\u9762\u7684\u94FE\u63A5:");
468
+ }
469
+ console.log("===================================\n");
470
+ } catch {
471
+ console.log("\n========== \u5FAE\u4FE1\u626B\u7801\u767B\u5F55 ==========");
472
+ if (qrcodeUrl) console.log(`\u626B\u7801\u94FE\u63A5: ${qrcodeUrl}`);
473
+ console.log("\u8BF7\u7528\u5FAE\u4FE1\u626B\u63CF\u4E8C\u7EF4\u7801\uFF08\u6216\u6253\u5F00\u4E0A\u9762\u7684\u94FE\u63A5\uFF09:");
474
+ console.log("===================================\n");
432
475
  }
433
- console.log("\u8BF7\u7528\u5FAE\u4FE1\u626B\u63CF\u4E8C\u7EF4\u7801\uFF08\u6216\u6253\u5F00\u4E0A\u9762\u7684\u94FE\u63A5\uFF09:");
434
- console.log("===================================\n");
435
476
  const deadline = Date.now() + timeoutSeconds * 1e3;
436
477
  let currentBaseUrl = ILINK_BASE_URL;
437
478
  let refreshCount = 0;
438
479
  while (Date.now() < deadline) {
439
480
  let statusResp;
440
481
  try {
441
- statusResp = await apiGet(currentBaseUrl, `${EP_GET_QR_STATUS}?qrcode=${qrcodeValue}`, "", QR_TIMEOUT_MS);
482
+ statusResp = await apiGet(currentBaseUrl, `${EP_GET_QR_STATUS}?qrcode=${pollQrValue}`, "", QR_TIMEOUT_MS);
442
483
  } catch {
443
484
  await sleep2(1e3);
444
485
  continue;
@@ -463,7 +504,17 @@ async function wechatQrLogin(options) {
463
504
  qrResp = await apiGet(ILINK_BASE_URL, `${EP_GET_BOT_QR}?bot_type=${botType}`, "", QR_TIMEOUT_MS);
464
505
  const newQrValue = String(qrResp?.qrcode || "");
465
506
  const newQrUrl = String(qrResp?.qrcode_img_content || "");
466
- if (newQrUrl) console.log(`\u65B0\u626B\u7801\u94FE\u63A5: ${newQrUrl}`);
507
+ if (!newQrValue) throw new Error("refresh response missing qrcode");
508
+ pollQrValue = newQrValue;
509
+ console.log("\u65B0\u626B\u7801\u94FE\u63A5:" + (newQrUrl ? ` ${newQrUrl}` : " (\u89C1\u4E0A\u65B9\u4E8C\u7EF4\u7801\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u626B)"));
510
+ if (newQrUrl) {
511
+ try {
512
+ const { renderQrTerminal: renderQrTerminal2 } = await Promise.resolve().then(() => (init_qr_render(), qr_render_exports));
513
+ const qrBlock = await renderQrTerminal2(newQrUrl);
514
+ if (qrBlock) console.log(qrBlock);
515
+ } catch {
516
+ }
517
+ }
467
518
  } catch (err) {
468
519
  console.error(`[wechat] QR refresh failed: ${err.message}`);
469
520
  return null;
@@ -484,15 +535,6 @@ async function wechatQrLogin(options) {
484
535
  \u2705 \u5FAE\u4FE1\u767B\u5F55\u6210\u529F!`);
485
536
  console.log(` accountId: ${accountId}`);
486
537
  console.log(` \u51ED\u8BC1\u5DF2\u4FDD\u5B58: ${credFile}`);
487
- console.log(`
488
- \u8BF7\u5C06\u4EE5\u4E0B\u914D\u7F6E\u6DFB\u52A0\u5230 xiaoke.json:`);
489
- console.log(JSON.stringify({
490
- wechat: {
491
- token,
492
- accountId,
493
- baseUrl: baseUrl !== ILINK_BASE_URL ? baseUrl : void 0
494
- }
495
- }, null, 2));
496
538
  return { accountId, token, baseUrl, userId };
497
539
  }
498
540
  await sleep2(1e3);
@@ -1083,32 +1125,6 @@ var init_wechat = __esm({
1083
1125
  }
1084
1126
  });
1085
1127
 
1086
- // src/qr-render.ts
1087
- var qr_render_exports = {};
1088
- __export(qr_render_exports, {
1089
- renderQrTerminal: () => renderQrTerminal
1090
- });
1091
- import { createRequire } from "node:module";
1092
- async function renderQrTerminal(url, options) {
1093
- return new Promise((resolve2, reject) => {
1094
- try {
1095
- const qt = require2("qrcode-terminal");
1096
- qt.generate(url, { small: options?.small ?? true }, (output) => {
1097
- resolve2(output);
1098
- });
1099
- } catch (err) {
1100
- reject(err);
1101
- }
1102
- });
1103
- }
1104
- var require2;
1105
- var init_qr_render = __esm({
1106
- "src/qr-render.ts"() {
1107
- "use strict";
1108
- require2 = createRequire(import.meta.url);
1109
- }
1110
- });
1111
-
1112
1128
  // src/cli-travel.ts
1113
1129
  var cli_travel_exports = {};
1114
1130
  __export(cli_travel_exports, {
@@ -1841,6 +1857,8 @@ function getDefaultValues(stateDir) {
1841
1857
  wechatEnabled: false,
1842
1858
  wechatToken: "",
1843
1859
  wechatAccountId: "",
1860
+ customBaseUrl: "",
1861
+ customModelId: "",
1844
1862
  tavilyKey: "",
1845
1863
  apiPort: 16990
1846
1864
  };
@@ -1849,42 +1867,56 @@ async function interactiveConfig(rl, defaults) {
1849
1867
  const v = { ...defaults };
1850
1868
  console.log("\n=== \u7B2C\u4E00\u6B65\uFF1A\u5FC5\u586B\u914D\u7F6E ===\n");
1851
1869
  v.agentName = await ask(rl, "Agent \u540D\u79F0", defaults.agentName);
1852
- const providers = ["dashscope (\u901A\u4E49\u5343\u95EE)", "minimax (MiniMax)", "zhipu (\u667A\u8C31)", "deepseek (DeepSeek)"];
1870
+ const providers = ["dashscope (\u901A\u4E49\u5343\u95EE)", "minimax (MiniMax)", "zhipu (\u667A\u8C31)", "deepseek (DeepSeek)", "custom (\u81EA\u5B9A\u4E49/\u5176\u4ED6 Anthropic \u517C\u5BB9\u7AEF\u70B9)"];
1853
1871
  const providerMap = {
1854
1872
  "dashscope (\u901A\u4E49\u5343\u95EE)": "dashscope",
1855
1873
  "minimax (MiniMax)": "minimax",
1856
1874
  "zhipu (\u667A\u8C31)": "zhipu",
1857
- "deepseek (DeepSeek)": "deepseek"
1875
+ "deepseek (DeepSeek)": "deepseek",
1876
+ "custom (\u81EA\u5B9A\u4E49/\u5176\u4ED6 Anthropic \u517C\u5BB9\u7AEF\u70B9)": "custom"
1858
1877
  };
1859
1878
  const chosenProvider = await askChoice(rl, "\u4E3B\u6A21\u578B Provider:", providers, 0);
1860
1879
  v.primaryProvider = providerMap[chosenProvider] || "dashscope";
1861
1880
  v.zhipuPlan = "";
1862
1881
  if (v.primaryProvider === "zhipu") {
1863
- const planOptions = ["coding-plan (GLM Coding \u8BA2\u9605)", "token-plan (\u666E\u901A\u6309\u91CF/TokenPlan)"];
1882
+ const planOptions = ["coding-plan (GLM Coding \u8BA2\u9605\uFF0C\u5305\u6708)", "api-pay (API \u6309\u91CF\u4ED8\u8D39)"];
1864
1883
  const chosenPlan = await askChoice(rl, "\u667A\u8C31\u8BA2\u9605\u7C7B\u578B:", planOptions, 0);
1865
1884
  v.zhipuPlan = chosenPlan.startsWith("coding") ? "coding" : "token";
1866
1885
  }
1886
+ v.customBaseUrl = "";
1887
+ v.customModelId = "";
1888
+ if (v.primaryProvider === "custom") {
1889
+ v.primaryProvider = await ask(rl, "Provider ID\uFF08\u5C0F\u5199\u5B57\u6BCD\uFF0C\u5982 kimi / moonshot / openrouter\uFF09", "custom");
1890
+ v.customBaseUrl = await ask(rl, "Anthropic \u517C\u5BB9 baseUrl\uFF08\u5982 https://api.moonshot.cn/anthropic\uFF09");
1891
+ const cm = await ask(rl, "\u6A21\u578B ID\uFF08\u5982 kimi-k2-turbo-preview\uFF09");
1892
+ v.customModelId = cm;
1893
+ }
1867
1894
  const keyMap = {
1868
1895
  dashscope: "DashScope API Key",
1869
1896
  minimax: "MiniMax API Key",
1870
1897
  zhipu: "\u667A\u8C31 API Key",
1871
1898
  deepseek: "DeepSeek API Key"
1872
1899
  };
1873
- v.primaryApiKey = await ask(rl, keyMap[v.primaryProvider] || "API Key");
1900
+ v.primaryApiKey = await ask(rl, keyMap[v.primaryProvider] || v.primaryProvider + " API Key");
1901
+ if (v.customModelId) {
1902
+ v.primaryModel = v.primaryProvider + "/" + v.customModelId;
1903
+ }
1874
1904
  const modelMap = {
1875
1905
  dashscope: ["dashscope/qwen3.7-max", "dashscope/qwen3.7-plus"],
1876
1906
  minimax: ["minimax/MiniMax-M3", "minimax/MiniMax-M2.7"],
1877
- zhipu: ["zhipu/glm-5.1", "zhipu/glm-5v-turbo"],
1907
+ zhipu: ["zhipu/glm-5.3", "zhipu/glm-5v-turbo"],
1878
1908
  deepseek: ["deepseek/deepseek-v4-pro", "deepseek/deepseek-v4-flash"]
1879
1909
  };
1880
- const models = modelMap[v.primaryProvider] || ["dashscope/qwen3.7-max"];
1881
- v.primaryModel = await askChoice(rl, "\u4E3B\u6A21\u578B:", models, 0);
1910
+ if (!v.customModelId) {
1911
+ const models = modelMap[v.primaryProvider] || ["dashscope/qwen3.7-max"];
1912
+ v.primaryModel = await askChoice(rl, "\u4E3B\u6A21\u578B:", models, 0);
1913
+ }
1882
1914
  const visionCapableMap = {
1883
1915
  "dashscope/qwen3.7-max": true,
1884
1916
  "dashscope/qwen3.7-plus": true,
1885
1917
  "minimax/MiniMax-M3": true,
1886
1918
  "zhipu/glm-5v-turbo": true,
1887
- "zhipu/glm-5.1": false,
1919
+ "zhipu/glm-5.3": false,
1888
1920
  "deepseek/deepseek-v4-pro": false,
1889
1921
  "deepseek/deepseek-v4-flash": false
1890
1922
  };
@@ -2107,8 +2139,8 @@ function generateConfig(v) {
2107
2139
  baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
2108
2140
  api: "openai-completions",
2109
2141
  models: [
2110
- { id: "glm-5.1", name: "GLM-5.1", reasoning: true, input: ["text"], contextWindow: 204800, maxTokens: 131072 },
2111
- { id: "glm-5v-turbo", name: "GLM-5V-Turbo", reasoning: true, input: ["text", "image"], contextWindow: 2e5, maxTokens: 128e3 }
2142
+ { id: "glm-5.3", name: "GLM-5.3 (\u6700\u65B0\u4E3B\u529B)", reasoning: true, input: ["text"], contextWindow: 1e6, maxTokens: 128e3 },
2143
+ { id: "glm-5v-turbo", name: "GLM-5V-Turbo (\u89C6\u89C9)", reasoning: true, input: ["text", "image"], contextWindow: 2e5, maxTokens: 128e3 }
2112
2144
  ]
2113
2145
  },
2114
2146
  deepseek: {
@@ -2121,6 +2153,16 @@ function generateConfig(v) {
2121
2153
  ]
2122
2154
  }
2123
2155
  };
2156
+ if (!providerDefs[v.primaryProvider] && v.customModelId) {
2157
+ config.models.providers[v.primaryProvider] = {
2158
+ baseUrl: (v.customBaseUrl || "").trim(),
2159
+ api: "anthropic",
2160
+ apiKey: v.primaryApiKey.trim(),
2161
+ models: [
2162
+ { id: v.customModelId, name: v.customModelId, reasoning: false, input: ["text"], contextWindow: 2e5, maxTokens: 8192 }
2163
+ ]
2164
+ };
2165
+ }
2124
2166
  if (providerDefs[v.primaryProvider]) {
2125
2167
  const def = { ...providerDefs[v.primaryProvider] };
2126
2168
  if (v.primaryProvider === "zhipu" && v.zhipuPlan === "token") {
@@ -2128,7 +2170,8 @@ function generateConfig(v) {
2128
2170
  }
2129
2171
  config.models.providers[v.primaryProvider] = {
2130
2172
  ...def,
2131
- apiKey: v.primaryApiKey
2173
+ apiKey: v.primaryApiKey.trim(),
2174
+ ...def.baseUrl ? { baseUrl: def.baseUrl.trim() } : {}
2132
2175
  };
2133
2176
  }
2134
2177
  return config;
@@ -2298,8 +2341,8 @@ async function main() {
2298
2341
  let stateDir = "";
2299
2342
  let configName = "";
2300
2343
  for (let i = 1; i < args.length; i++) {
2301
- if (args[i] === "--state-dir" && args[i + 1]) stateDir = args[++i];
2302
- else if (args[i] === "--config" && args[i + 1]) configName = args[++i];
2344
+ if (args[i] === "--state-dir" && args[i + 1]) stateDir = args[++i].trim();
2345
+ else if (args[i] === "--config" && args[i + 1]) configName = args[++i].trim();
2303
2346
  }
2304
2347
  if (!stateDir) stateDir = path3.resolve(process.cwd());
2305
2348
  if (!target && !isLegacyAddchannel) {
@@ -2226,9 +2226,19 @@ var init_compact2 = __esm({
2226
2226
  // src/config/live.ts
2227
2227
  var live_exports = {};
2228
2228
  __export(live_exports, {
2229
- liveConfig: () => liveConfig
2229
+ consumeSelfWrite: () => consumeSelfWrite,
2230
+ liveConfig: () => liveConfig,
2231
+ markSelfWrite: () => markSelfWrite
2230
2232
  });
2231
- var LiveConfigClass, liveConfig;
2233
+ function markSelfWrite() {
2234
+ selfWrite.pending = true;
2235
+ }
2236
+ function consumeSelfWrite() {
2237
+ const was = selfWrite.pending;
2238
+ selfWrite.pending = false;
2239
+ return was;
2240
+ }
2241
+ var LiveConfigClass, liveConfig, selfWrite;
2232
2242
  var init_live = __esm({
2233
2243
  "src/config/live.ts"() {
2234
2244
  "use strict";
@@ -2289,6 +2299,7 @@ var init_live = __esm({
2289
2299
  o[keys[keys.length - 1]] = val;
2290
2300
  fs48.writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
2291
2301
  console.log(`[liveConfig] persisted ${dotPath} = ${JSON.stringify(val)} to ${cfgPath}`);
2302
+ markSelfWrite();
2292
2303
  } catch (e) {
2293
2304
  console.warn(`[liveConfig] persist failed (${dotPath}): ${e.message}`);
2294
2305
  }
@@ -2299,6 +2310,7 @@ var init_live = __esm({
2299
2310
  }
2300
2311
  };
2301
2312
  liveConfig = new LiveConfigClass();
2313
+ selfWrite = { pending: false };
2302
2314
  }
2303
2315
  });
2304
2316
 
@@ -31890,6 +31902,7 @@ function createMemorySideProvider(sideConfig, mainProvider, providers) {
31890
31902
  console.log(`[memory] Side provider: ${sideConfig.provider}/${sideConfig.model} (thinking=${sideConfig.thinking || "default"})`);
31891
31903
  return { provider: sideProvider, model: sideConfig.model, disableThinking };
31892
31904
  }
31905
+ var lastLoadedConfigRaw = null;
31893
31906
  async function doReloadConfig(config, deps, provider) {
31894
31907
  try {
31895
31908
  const savedConfigPath = config._configFilePath;
@@ -31904,7 +31917,17 @@ async function doReloadConfig(config, deps, provider) {
31904
31917
  reloadConfigPath = altPath;
31905
31918
  }
31906
31919
  }
31920
+ let configRaw = "";
31921
+ try {
31922
+ configRaw = fs47.readFileSync(reloadConfigPath, "utf-8");
31923
+ } catch {
31924
+ }
31925
+ if (lastLoadedConfigRaw !== null && configRaw.trim() === lastLoadedConfigRaw) {
31926
+ console.log(`[reload] config content unchanged, skipping reload`);
31927
+ return { ok: true, changes: ["unchanged (skipped)"] };
31928
+ }
31907
31929
  const newConfig = loadConfig(reloadConfigPath);
31930
+ lastLoadedConfigRaw = configRaw.trim();
31908
31931
  const changes = [];
31909
31932
  const oldProviderKey = JSON.stringify({
31910
31933
  providers: config.providers,
@@ -32055,9 +32078,22 @@ function startConfigWatcher(config, deps, provider) {
32055
32078
  return null;
32056
32079
  }
32057
32080
  let debounceTimer = null;
32081
+ try {
32082
+ lastLoadedConfigRaw = fs47.readFileSync(configPath, "utf-8").trim();
32083
+ } catch {
32084
+ }
32058
32085
  const watcher = fs47.watch(configPath, { persistent: true }, (eventType) => {
32059
32086
  if (debounceTimer) clearTimeout(debounceTimer);
32060
32087
  debounceTimer = setTimeout(async () => {
32088
+ if (consumeSelfWrite()) {
32089
+ console.log(`[config-watch] self-write (liveConfig.set, memory already synced), skipping reload`);
32090
+ try {
32091
+ fs47.appendFileSync(path49.join(config.stateDir, "logs", "engine-config-watch.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] SELF-WRITE SKIP (liveConfig.set, memory synced)
32092
+ `);
32093
+ } catch {
32094
+ }
32095
+ return;
32096
+ }
32061
32097
  console.log(`[config-watch] file changed (${eventType}), reloading...`);
32062
32098
  try {
32063
32099
  fs47.appendFileSync(path49.join(config.stateDir, "logs", "engine-config-watch.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] CHANGE eventType=${eventType}, calling doReloadConfig
package/dist/main.mjs CHANGED
@@ -34,9 +34,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
34
34
  // src/config/live.ts
35
35
  var live_exports = {};
36
36
  __export(live_exports, {
37
- liveConfig: () => liveConfig
37
+ consumeSelfWrite: () => consumeSelfWrite,
38
+ liveConfig: () => liveConfig,
39
+ markSelfWrite: () => markSelfWrite
38
40
  });
39
- var LiveConfigClass, liveConfig;
41
+ function markSelfWrite() {
42
+ selfWrite.pending = true;
43
+ }
44
+ function consumeSelfWrite() {
45
+ const was = selfWrite.pending;
46
+ selfWrite.pending = false;
47
+ return was;
48
+ }
49
+ var LiveConfigClass, liveConfig, selfWrite;
40
50
  var init_live = __esm({
41
51
  "src/config/live.ts"() {
42
52
  "use strict";
@@ -97,6 +107,7 @@ var init_live = __esm({
97
107
  o[keys[keys.length - 1]] = val;
98
108
  fs48.writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
99
109
  console.log(`[liveConfig] persisted ${dotPath} = ${JSON.stringify(val)} to ${cfgPath}`);
110
+ markSelfWrite();
100
111
  } catch (e) {
101
112
  console.warn(`[liveConfig] persist failed (${dotPath}): ${e.message}`);
102
113
  }
@@ -107,6 +118,7 @@ var init_live = __esm({
107
118
  }
108
119
  };
109
120
  liveConfig = new LiveConfigClass();
121
+ selfWrite = { pending: false };
110
122
  }
111
123
  });
112
124
 
@@ -31974,6 +31986,7 @@ function createMemorySideProvider(sideConfig, mainProvider, providers) {
31974
31986
  console.log(`[memory] Side provider: ${sideConfig.provider}/${sideConfig.model} (thinking=${sideConfig.thinking || "default"})`);
31975
31987
  return { provider: sideProvider, model: sideConfig.model, disableThinking };
31976
31988
  }
31989
+ var lastLoadedConfigRaw = null;
31977
31990
  async function doReloadConfig(config2, deps, provider) {
31978
31991
  try {
31979
31992
  const savedConfigPath = config2._configFilePath;
@@ -31988,7 +32001,17 @@ async function doReloadConfig(config2, deps, provider) {
31988
32001
  reloadConfigPath = altPath;
31989
32002
  }
31990
32003
  }
32004
+ let configRaw = "";
32005
+ try {
32006
+ configRaw = fs47.readFileSync(reloadConfigPath, "utf-8");
32007
+ } catch {
32008
+ }
32009
+ if (lastLoadedConfigRaw !== null && configRaw.trim() === lastLoadedConfigRaw) {
32010
+ console.log(`[reload] config content unchanged, skipping reload`);
32011
+ return { ok: true, changes: ["unchanged (skipped)"] };
32012
+ }
31991
32013
  const newConfig = loadConfig(reloadConfigPath);
32014
+ lastLoadedConfigRaw = configRaw.trim();
31992
32015
  const changes = [];
31993
32016
  const oldProviderKey = JSON.stringify({
31994
32017
  providers: config2.providers,
@@ -32139,9 +32162,22 @@ function startConfigWatcher(config2, deps, provider) {
32139
32162
  return null;
32140
32163
  }
32141
32164
  let debounceTimer = null;
32165
+ try {
32166
+ lastLoadedConfigRaw = fs47.readFileSync(configPath2, "utf-8").trim();
32167
+ } catch {
32168
+ }
32142
32169
  const watcher = fs47.watch(configPath2, { persistent: true }, (eventType) => {
32143
32170
  if (debounceTimer) clearTimeout(debounceTimer);
32144
32171
  debounceTimer = setTimeout(async () => {
32172
+ if (consumeSelfWrite()) {
32173
+ console.log(`[config-watch] self-write (liveConfig.set, memory already synced), skipping reload`);
32174
+ try {
32175
+ fs47.appendFileSync(path49.join(config2.stateDir, "logs", "engine-config-watch.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] SELF-WRITE SKIP (liveConfig.set, memory synced)
32176
+ `);
32177
+ } catch {
32178
+ }
32179
+ return;
32180
+ }
32145
32181
  console.log(`[config-watch] file changed (${eventType}), reloading...`);
32146
32182
  try {
32147
32183
  fs47.appendFileSync(path49.join(config2.stateDir, "logs", "engine-config-watch.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] CHANGE eventType=${eventType}, calling doReloadConfig
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "engine7",
3
- "version": "7.1.43",
3
+ "version": "7.1.45",
4
4
  "type": "module",
5
5
  "description": "Engine 7 — 给助手一个家 / A home for your AI assistant",
6
6
  "main": "dist/main.mjs",