@wu529778790/open-im 1.11.8-beta.0 → 1.11.8-beta.2

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.
@@ -6,6 +6,7 @@ import { createRequire } from "node:module";
6
6
  import { createInterface } from "node:readline/promises";
7
7
  import { stdin as input, stdout as output } from "node:process";
8
8
  import { createLogger } from "./logger.js";
9
+ import { UPDATE_CHECK_TIMEOUT_MS } from "./constants.js";
9
10
  const log = createLogger("CheckUpdate");
10
11
  const require = createRequire(import.meta.url);
11
12
  const { version: CURRENT_VERSION } = require("../package.json");
@@ -15,7 +16,7 @@ const REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PKG_NAME)}
15
16
  async function fetchLatestVersion() {
16
17
  try {
17
18
  const res = await fetch(`${REGISTRY_URL}?fields=dist-tags`, {
18
- signal: AbortSignal.timeout(5000),
19
+ signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS),
19
20
  });
20
21
  if (!res.ok)
21
22
  return null;
@@ -4,7 +4,7 @@ import { join, dirname } from 'node:path';
4
4
  import { homedir } from 'node:os';
5
5
  import { createRequire } from 'node:module';
6
6
  import { createLogger } from '../logger.js';
7
- import { APP_HOME } from '../constants.js';
7
+ import { APP_HOME, CLI_VERSION_CHECK_TIMEOUT_MS } from "../constants.js";
8
8
  const log = createLogger('config');
9
9
  export const CONFIG_PATH = join(APP_HOME, 'config.json');
10
10
  export const CODEX_AUTH_PATHS = [
@@ -327,7 +327,7 @@ export function getClaudeSdkRuntimeIssue() {
327
327
  ...process.env,
328
328
  CLAUDE_CODE_ENTRYPOINT: process.env.CLAUDE_CODE_ENTRYPOINT || 'sdk-ts',
329
329
  },
330
- timeout: 5000,
330
+ timeout: CLI_VERSION_CHECK_TIMEOUT_MS,
331
331
  windowsHide: process.platform === 'win32',
332
332
  });
333
333
  }
@@ -5,14 +5,14 @@ import { randomBytes } from "node:crypto";
5
5
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
6
6
  import { join, dirname } from "node:path";
7
7
  import { DWClient } from "dingtalk-stream";
8
- import { WEB_CONFIG_PORT, getPublicWebDashboardUrl } from "./constants.js";
8
+ import { WEB_CONFIG_PORT, getPublicWebDashboardUrl, PLATFORM_TEST_TIMEOUT_MS } from "./constants.js";
9
9
  import { CONFIG_PATH, getClaudeConfigHome, loadClaudeSettingsEnv, saveClaudeSettingsEnv, loadConfig, loadFileConfig, saveFileConfig, normalizeAiCommand, CODEX_AUTH_PATHS, } from "./config.js";
10
10
  import { getWebDistDir, tryServeDashboardStatic } from "./config-web-static.js";
11
11
  import { getServiceStatus, startBackgroundService, stopBackgroundService } from "./service-control.js";
12
12
  import { initWeWork, stopWeWork } from "./wework/client.js";
13
13
  import { createLogger } from "./logger.js";
14
14
  const log = createLogger("ConfigWeb");
15
- const TEST_TIMEOUT_MS = 10000;
15
+ // 已移至 constants.ts;
16
16
  function getClaudeSettingsPath() {
17
17
  const home = getClaudeConfigHome();
18
18
  const baseDir = join(home, ".claude");
@@ -514,7 +514,7 @@ async function probeTelegram(config) {
514
514
  if (!botToken)
515
515
  throw new Error("Telegram bot token is required.");
516
516
  const response = await fetch(`https://api.telegram.org/bot${botToken}/getMe`, {
517
- signal: AbortSignal.timeout(TEST_TIMEOUT_MS),
517
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
518
518
  });
519
519
  const body = await readJsonResponse(response);
520
520
  if (!response.ok || body.ok !== true) {
@@ -533,7 +533,7 @@ async function probeFeishu(config) {
533
533
  method: "POST",
534
534
  headers: { "content-type": "application/json" },
535
535
  body: JSON.stringify({ app_id: appId, app_secret: appSecret }),
536
- signal: AbortSignal.timeout(TEST_TIMEOUT_MS),
536
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
537
537
  });
538
538
  const body = await readJsonResponse(response);
539
539
  if (!response.ok || body.code !== 0) {
@@ -550,7 +550,7 @@ async function probeQQ(config) {
550
550
  method: "POST",
551
551
  headers: { "content-type": "application/json" },
552
552
  body: JSON.stringify({ appId, clientSecret: secret }),
553
- signal: AbortSignal.timeout(TEST_TIMEOUT_MS),
553
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
554
554
  });
555
555
  const body = await readJsonResponse(response);
556
556
  if (!response.ok || typeof body.access_token !== "string" || body.access_token.length === 0) {
@@ -584,7 +584,7 @@ async function probeDingTalk(config) {
584
584
  });
585
585
  const token = await Promise.race([
586
586
  client.getAccessToken(),
587
- new Promise((_, reject) => setTimeout(() => reject(new Error("DingTalk access token request timed out.")), TEST_TIMEOUT_MS)),
587
+ new Promise((_, reject) => setTimeout(() => reject(new Error("DingTalk access token request timed out.")), PLATFORM_TEST_TIMEOUT_MS)),
588
588
  ]);
589
589
  if (typeof token !== "string" || token.length === 0) {
590
590
  throw new Error("DingTalk did not return an access token.");
@@ -612,7 +612,7 @@ async function probeWorkBuddy(config) {
612
612
  workspaceName: "OpenIM Test Workspace",
613
613
  localAgentType: "ide",
614
614
  }),
615
- signal: AbortSignal.timeout(TEST_TIMEOUT_MS),
615
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
616
616
  });
617
617
  if (!response.ok) {
618
618
  const body = await response.text();
@@ -634,7 +634,7 @@ async function probeClawBot(config) {
634
634
  'iLink-App-ClientVersion': '131588',
635
635
  'X-WECHAT-UIN': randomUUID(),
636
636
  },
637
- signal: AbortSignal.timeout(TEST_TIMEOUT_MS),
637
+ signal: AbortSignal.timeout(PLATFORM_TEST_TIMEOUT_MS),
638
638
  });
639
639
  const body = await readJsonResponse(response);
640
640
  const ok = body.ok === true || body.ret === 0 || body.ret === '0';
@@ -1,36 +1,75 @@
1
1
  export declare const APP_HOME: string;
2
+ export declare const IMAGE_DIR: string;
2
3
  /** 优雅关闭 HTTP 端口(stop 命令通过此端口触发 shutdown) */
3
4
  export declare const SHUTDOWN_PORT = 39281;
4
- /** 本地 Web 配置 API 固定端口(完整 UI 由 web/dist 随包提供,见 getPublicWebDashboardUrl) */
5
+ /** 本地 Web 配置 API 固定端口 */
5
6
  export declare const WEB_CONFIG_PORT = 39282;
6
- /** 本机仪表盘默认 URL(与内置 SPA 同源;可通过 OPEN_IM_PUBLIC_WEB_URL 覆盖为自定义地址) */
7
7
  export declare function getDefaultLocalDashboardUrl(): string;
8
8
  export declare function getPublicWebDashboardUrl(): string;
9
- export declare const IMAGE_DIR: string;
10
- /**
11
- * Co-authored-by 使用的固定提交者地址(开箱即用,形如 GitHub noreply)。
12
- * 若希望贡献图关联到具体用户,请将该地址加入对应 GitHub 账号的已验证联系方式,或 fork 后自行修改常量。
13
- */
14
- export declare const DEFAULT_OPEN_IM_COAUTHOR_ADDR = "529778790@qq.com";
15
- export declare const TERMINAL_ONLY_COMMANDS: Set<string>;
16
- /** CardKit 流式更新节流:80ms(约 12 次/秒,cardElement.content 专为打字机设计,支持更高频率) */
9
+ /** 服务启动就绪超时 */
10
+ export declare const SERVICE_READY_TIMEOUT_MS = 8000;
11
+ /** 服务健康检查超时 */
12
+ export declare const HEALTH_CHECK_TIMEOUT_MS = 3000;
13
+ /** 平台凭证测试超时 */
14
+ export declare const PLATFORM_TEST_TIMEOUT_MS = 10000;
15
+ /** 版本检查超时 */
16
+ export declare const UPDATE_CHECK_TIMEOUT_MS = 5000;
17
+ /** 媒体下载超时(Telegram/飞书/企业微信) */
18
+ export declare const MEDIA_DOWNLOAD_TIMEOUT_MS = 60000;
19
+ /** 优雅关闭强制退出超时 */
20
+ export declare const SHUTDOWN_FORCE_EXIT_MS = 10000;
21
+ /** ClawBot 长轮询单次请求超时 */
22
+ export declare const CLAWBOT_POLL_REQUEST_TIMEOUT_MS: number;
23
+ /** ClawBot watchdog 检查间隔 */
24
+ export declare const CLAWBOT_WATCHDOG_INTERVAL_MS = 60000;
25
+ /** ClawBot 判定连接死亡的静默时间 */
26
+ export declare const CLAWBOT_WATCHDOG_STALE_MS: number;
27
+ /** 企业微信任务安全超时 */
28
+ export declare const WEWORK_TASK_SAFETY_TIMEOUT_MS: number;
29
+ /** DingTalk webhook 请求超时 */
30
+ export declare const DINGTALK_WEBHOOK_TIMEOUT_MS = 30000;
31
+ /** DingTalk API 请求超时 */
32
+ export declare const DINGTALK_API_TIMEOUT_MS = 30000;
33
+ /** CLI 子进程版本检测超时 */
34
+ export declare const CLI_VERSION_CHECK_TIMEOUT_MS = 5000;
35
+ /** 企业微信最大重连尝试次数 */
36
+ export declare const WEWORK_MAX_RECONNECT_ATTEMPTS = 3;
37
+ /** 企业微信重连延迟 */
38
+ export declare const WEWORK_RECONNECT_DELAY_MS = 1500;
39
+ /** 企业微信最大重连尝试(总) */
40
+ export declare const WEWORK_MAX_RECONNECT_TOTAL = 5;
41
+ /** DingTalk 429 限流重试延迟 */
42
+ export declare const DINGTALK_RATE_LIMIT_RETRY_MS = 60000;
43
+ /** DingTalk 消息发送重试次数 */
44
+ export declare const DINGTALK_SEND_RETRIES = 1;
45
+ /** DingTalk 消息发送重试延迟 */
46
+ export declare const DINGTALK_SEND_RETRY_DELAY_MS = 300;
47
+ /** ClawBot 重连延迟阶梯 */
48
+ export declare const CLAWBOT_RECONNECT_DELAYS_MS: number[];
49
+ /** ClawBot 最大重连尝试 */
50
+ export declare const CLAWBOT_MAX_RECONNECT_ATTEMPTS = 5;
51
+ /** CardKit 流式更新节流:80ms */
17
52
  export declare const CARDKIT_THROTTLE_MS = 80;
18
- /** Telegram 编辑消息节流:200ms(open-im 默认值) */
53
+ /** Telegram 编辑消息节流 */
19
54
  export declare const TELEGRAM_THROTTLE_MS = 200;
20
- /** WorkBuddy 流式更新节流:1000ms(Centrifuge 协议建议值) */
21
- export declare const WORKBUDDY_THROTTLE_MS = 1000;
55
+ /** 企业微信流式更新节流 */
22
56
  export declare const WEWORK_THROTTLE_MS = 500;
57
+ /** WorkBuddy 流式更新节流 */
58
+ export declare const WORKBUDDY_THROTTLE_MS = 1000;
59
+ /** ClawBot 流式更新节流 */
60
+ export declare const CLAWBOT_THROTTLE_MS = 1000;
61
+ /** 企业微信流式发送间隔 */
62
+ export declare const WEWORK_STREAM_SEND_INTERVAL_MS = 900;
63
+ /** 企业微信流式清理间隔 */
64
+ export declare const WEWORK_STREAM_CLEANUP_INTERVAL_MS: number;
23
65
  export declare const MAX_TELEGRAM_MESSAGE_LENGTH = 4000;
24
66
  export declare const MAX_FEISHU_MESSAGE_LENGTH = 4000;
25
- /** CardKit 流式内容最大长度(卡片上限约 30KB,留余量) */
26
67
  export declare const MAX_STREAMING_CONTENT_LENGTH = 25000;
27
68
  export declare const MAX_WEWORK_MESSAGE_LENGTH = 2048;
28
69
  export declare const MAX_DINGTALK_MESSAGE_LENGTH = 2048;
29
- /** WeChat KF (微信客服) 单条消息最大字符数 */
30
70
  export declare const MAX_WORKBUDDY_MESSAGE_LENGTH = 2000;
31
- /** ClawBot 流式更新节流 */
32
- export declare const CLAWBOT_THROTTLE_MS = 1000;
33
- /** ClawBot 单条消息最大字符数 */
34
71
  export declare const MAX_CLAWBOT_MESSAGE_LENGTH = 2000;
35
72
  /** ClawBot 长轮询间隔 */
36
73
  export declare const CLAWBOT_POLL_INTERVAL_MS = 3000;
74
+ export declare const DEFAULT_OPEN_IM_COAUTHOR_ADDR = "529778790@qq.com";
75
+ export declare const TERMINAL_ONLY_COMMANDS: Set<string>;
package/dist/constants.js CHANGED
@@ -1,15 +1,17 @@
1
1
  import { join } from "node:path";
2
2
  import { homedir, tmpdir } from "node:os";
3
+ // ─── 路径 ───
3
4
  export const APP_HOME = join(homedir(), ".open-im");
5
+ export const IMAGE_DIR = join(tmpdir(), "open-im-images");
6
+ // ─── 端口 ───
4
7
  /** 优雅关闭 HTTP 端口(stop 命令通过此端口触发 shutdown) */
5
8
  export const SHUTDOWN_PORT = 39281;
6
- /** 本地 Web 配置 API 固定端口(完整 UI 由 web/dist 随包提供,见 getPublicWebDashboardUrl) */
9
+ /** 本地 Web 配置 API 固定端口 */
7
10
  export const WEB_CONFIG_PORT = 39282;
8
11
  function resolveWebConfigPort() {
9
12
  const p = process.env.OPEN_IM_WEB_PORT ? parseInt(process.env.OPEN_IM_WEB_PORT, 10) : NaN;
10
13
  return Number.isFinite(p) && p > 0 ? p : WEB_CONFIG_PORT;
11
14
  }
12
- /** 本机仪表盘默认 URL(与内置 SPA 同源;可通过 OPEN_IM_PUBLIC_WEB_URL 覆盖为自定义地址) */
13
15
  export function getDefaultLocalDashboardUrl() {
14
16
  return `http://127.0.0.1:${resolveWebConfigPort()}`;
15
17
  }
@@ -18,12 +20,79 @@ export function getPublicWebDashboardUrl() {
18
20
  const raw = fromEnv || getDefaultLocalDashboardUrl();
19
21
  return raw.replace(/\/$/, "");
20
22
  }
21
- export const IMAGE_DIR = join(tmpdir(), "open-im-images");
22
- /**
23
- * Co-authored-by 使用的固定提交者地址(开箱即用,形如 GitHub noreply)。
24
- * 若希望贡献图关联到具体用户,请将该地址加入对应 GitHub 账号的已验证联系方式,或 fork 后自行修改常量。
25
- */
23
+ // ─── 超时(毫秒) ───
24
+ /** 服务启动就绪超时 */
25
+ export const SERVICE_READY_TIMEOUT_MS = 8_000;
26
+ /** 服务健康检查超时 */
27
+ export const HEALTH_CHECK_TIMEOUT_MS = 3_000;
28
+ /** 平台凭证测试超时 */
29
+ export const PLATFORM_TEST_TIMEOUT_MS = 10_000;
30
+ /** 版本检查超时 */
31
+ export const UPDATE_CHECK_TIMEOUT_MS = 5_000;
32
+ /** 媒体下载超时(Telegram/飞书/企业微信) */
33
+ export const MEDIA_DOWNLOAD_TIMEOUT_MS = 60_000;
34
+ /** 优雅关闭强制退出超时 */
35
+ export const SHUTDOWN_FORCE_EXIT_MS = 10_000;
36
+ /** ClawBot 长轮询单次请求超时 */
37
+ export const CLAWBOT_POLL_REQUEST_TIMEOUT_MS = 3 * 60 * 1000;
38
+ /** ClawBot watchdog 检查间隔 */
39
+ export const CLAWBOT_WATCHDOG_INTERVAL_MS = 60_000;
40
+ /** ClawBot 判定连接死亡的静默时间 */
41
+ export const CLAWBOT_WATCHDOG_STALE_MS = 5 * 60 * 1000;
42
+ /** 企业微信任务安全超时 */
43
+ export const WEWORK_TASK_SAFETY_TIMEOUT_MS = 4.5 * 60 * 1000;
44
+ /** DingTalk webhook 请求超时 */
45
+ export const DINGTALK_WEBHOOK_TIMEOUT_MS = 30_000;
46
+ /** DingTalk API 请求超时 */
47
+ export const DINGTALK_API_TIMEOUT_MS = 30_000;
48
+ /** CLI 子进程版本检测超时 */
49
+ export const CLI_VERSION_CHECK_TIMEOUT_MS = 5_000;
50
+ // ─── 重试与重连 ───
51
+ /** 企业微信最大重连尝试次数 */
52
+ export const WEWORK_MAX_RECONNECT_ATTEMPTS = 3;
53
+ /** 企业微信重连延迟 */
54
+ export const WEWORK_RECONNECT_DELAY_MS = 1_500;
55
+ /** 企业微信最大重连尝试(总) */
56
+ export const WEWORK_MAX_RECONNECT_TOTAL = 5;
57
+ /** DingTalk 429 限流重试延迟 */
58
+ export const DINGTALK_RATE_LIMIT_RETRY_MS = 60_000;
59
+ /** DingTalk 消息发送重试次数 */
60
+ export const DINGTALK_SEND_RETRIES = 1;
61
+ /** DingTalk 消息发送重试延迟 */
62
+ export const DINGTALK_SEND_RETRY_DELAY_MS = 300;
63
+ /** ClawBot 重连延迟阶梯 */
64
+ export const CLAWBOT_RECONNECT_DELAYS_MS = [3_000, 5_000, 10_000, 20_000, 30_000];
65
+ /** ClawBot 最大重连尝试 */
66
+ export const CLAWBOT_MAX_RECONNECT_ATTEMPTS = 5;
67
+ // ─── 流式与节流 ───
68
+ /** CardKit 流式更新节流:80ms */
69
+ export const CARDKIT_THROTTLE_MS = 80;
70
+ /** Telegram 编辑消息节流 */
71
+ export const TELEGRAM_THROTTLE_MS = 200;
72
+ /** 企业微信流式更新节流 */
73
+ export const WEWORK_THROTTLE_MS = 500;
74
+ /** WorkBuddy 流式更新节流 */
75
+ export const WORKBUDDY_THROTTLE_MS = 1000;
76
+ /** ClawBot 流式更新节流 */
77
+ export const CLAWBOT_THROTTLE_MS = 1000;
78
+ /** 企业微信流式发送间隔 */
79
+ export const WEWORK_STREAM_SEND_INTERVAL_MS = 900;
80
+ /** 企业微信流式清理间隔 */
81
+ export const WEWORK_STREAM_CLEANUP_INTERVAL_MS = 5 * 60 * 1000;
82
+ // ─── 消息长度限制 ───
83
+ export const MAX_TELEGRAM_MESSAGE_LENGTH = 4000;
84
+ export const MAX_FEISHU_MESSAGE_LENGTH = 4000;
85
+ export const MAX_STREAMING_CONTENT_LENGTH = 25000;
86
+ export const MAX_WEWORK_MESSAGE_LENGTH = 2048;
87
+ export const MAX_DINGTALK_MESSAGE_LENGTH = 2048;
88
+ export const MAX_WORKBUDDY_MESSAGE_LENGTH = 2000;
89
+ export const MAX_CLAWBOT_MESSAGE_LENGTH = 2000;
90
+ // ─── 轮询间隔 ───
91
+ /** ClawBot 长轮询间隔 */
92
+ export const CLAWBOT_POLL_INTERVAL_MS = 3000;
93
+ // ─── Git 共同作者 ───
26
94
  export const DEFAULT_OPEN_IM_COAUTHOR_ADDR = "529778790@qq.com";
95
+ // ─── 终端独占命令 ───
27
96
  export const TERMINAL_ONLY_COMMANDS = new Set([
28
97
  "/rewind",
29
98
  "/copy",
@@ -42,24 +111,3 @@ export const TERMINAL_ONLY_COMMANDS = new Set([
42
111
  "/teleport",
43
112
  "/add-dir",
44
113
  ]);
45
- /** CardKit 流式更新节流:80ms(约 12 次/秒,cardElement.content 专为打字机设计,支持更高频率) */
46
- export const CARDKIT_THROTTLE_MS = 80;
47
- /** Telegram 编辑消息节流:200ms(open-im 默认值) */
48
- export const TELEGRAM_THROTTLE_MS = 200;
49
- /** WorkBuddy 流式更新节流:1000ms(Centrifuge 协议建议值) */
50
- export const WORKBUDDY_THROTTLE_MS = 1000;
51
- export const WEWORK_THROTTLE_MS = 500;
52
- export const MAX_TELEGRAM_MESSAGE_LENGTH = 4000;
53
- export const MAX_FEISHU_MESSAGE_LENGTH = 4000;
54
- /** CardKit 流式内容最大长度(卡片上限约 30KB,留余量) */
55
- export const MAX_STREAMING_CONTENT_LENGTH = 25000;
56
- export const MAX_WEWORK_MESSAGE_LENGTH = 2048;
57
- export const MAX_DINGTALK_MESSAGE_LENGTH = 2048;
58
- /** WeChat KF (微信客服) 单条消息最大字符数 */
59
- export const MAX_WORKBUDDY_MESSAGE_LENGTH = 2000;
60
- /** ClawBot 流式更新节流 */
61
- export const CLAWBOT_THROTTLE_MS = 1000;
62
- /** ClawBot 单条消息最大字符数 */
63
- export const MAX_CLAWBOT_MESSAGE_LENGTH = 2000;
64
- /** ClawBot 长轮询间隔 */
65
- export const CLAWBOT_POLL_INTERVAL_MS = 3000;
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ import { SessionManager } from "./session/session-manager.js";
33
33
  import { loadActiveChats, getActiveChatId, flushActiveChats, } from "./shared/active-chats.js";
34
34
  import { destroyAllLiveChildren } from "./shared/process-kill.js";
35
35
  import { initLogger, createLogger, closeLogger, } from "./logger.js";
36
- import { APP_HOME, SHUTDOWN_PORT } from "./constants.js";
36
+ import { APP_HOME, SHUTDOWN_PORT, SHUTDOWN_FORCE_EXIT_MS } from "./constants.js";
37
37
  import { createRequire } from "node:module";
38
38
  import { escapePathForMarkdown, getAIToolDisplayName } from "./shared/utils.js";
39
39
  import { applyOpenImGitCoauthorToProcessEnv } from "./shared/git-coauthor.js";
@@ -393,12 +393,12 @@ export async function main() {
393
393
  };
394
394
  process.on("SIGINT", () => {
395
395
  // 优雅关闭超时:10 秒后强制退出
396
- const forceExit = setTimeout(() => { log.warn('Shutdown timeout, forcing exit'); process.exit(1); }, 10_000);
396
+ const forceExit = setTimeout(() => { log.warn('Shutdown timeout, forcing exit'); process.exit(1); }, SHUTDOWN_FORCE_EXIT_MS);
397
397
  forceExit.unref();
398
398
  shutdown().catch(() => process.exit(1));
399
399
  });
400
400
  process.on("SIGTERM", () => {
401
- const forceExit = setTimeout(() => { log.warn('Shutdown timeout, forcing exit'); process.exit(1); }, 10_000);
401
+ const forceExit = setTimeout(() => { log.warn('Shutdown timeout, forcing exit'); process.exit(1); }, SHUTDOWN_FORCE_EXIT_MS);
402
402
  forceExit.unref();
403
403
  shutdown().catch(() => process.exit(1));
404
404
  });
@@ -2,7 +2,7 @@ import { execFileSync, spawn } from "node:child_process";
2
2
  import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
3
3
  import { dirname, extname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { APP_HOME, SHUTDOWN_PORT } from "./constants.js";
5
+ import { APP_HOME, SHUTDOWN_PORT, SERVICE_READY_TIMEOUT_MS, HEALTH_CHECK_TIMEOUT_MS } from "./constants.js";
6
6
  import { resolveNodeExecutable } from "./node-exec.js";
7
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
8
  const PID_FILE = join(APP_HOME, "open-im-worker.pid");
@@ -106,7 +106,7 @@ export function startBackgroundService(cwd) {
106
106
  writePid(child.pid);
107
107
  return { pid: child.pid };
108
108
  }
109
- export async function waitForBackgroundServiceReady(timeoutMs = 8000, pollIntervalMs = 100) {
109
+ export async function waitForBackgroundServiceReady(timeoutMs = SERVICE_READY_TIMEOUT_MS, pollIntervalMs = 100) {
110
110
  const startedAt = Date.now();
111
111
  while (Date.now() - startedAt < timeoutMs) {
112
112
  const status = getServiceStatus();
@@ -133,7 +133,7 @@ export async function stopBackgroundService() {
133
133
  : SHUTDOWN_PORT;
134
134
  try {
135
135
  const response = await fetch(`http://127.0.0.1:${port}/shutdown`, {
136
- signal: AbortSignal.timeout(3000),
136
+ signal: AbortSignal.timeout(HEALTH_CHECK_TIMEOUT_MS),
137
137
  });
138
138
  if (response.ok) {
139
139
  for (let index = 0; index < 50; index += 1) {
@@ -135,7 +135,8 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
135
135
  clearTimeout(pendingUpdate);
136
136
  pendingUpdate = null;
137
137
  }
138
- const toolNote = toolLines.length > 0 ? toolLines.slice(-3).join('\n') : undefined;
138
+ // 只在 force=true(工具调用)时传 toolNote,普通文本更新不传
139
+ const toolNote = force && toolLines.length > 0 ? toolLines.slice(-3).join('\n') : undefined;
139
140
  platformAdapter.streamUpdate(content, toolNote);
140
141
  }
141
142
  else if (!pendingUpdate) {
@@ -143,8 +144,7 @@ export function runAITask(deps, ctx, prompt, toolAdapter, platformAdapter) {
143
144
  pendingUpdate = null;
144
145
  lastUpdateTime = Date.now();
145
146
  lastSentContentLength = taskState.latestContent.length;
146
- const toolNote = toolLines.length > 0 ? toolLines.slice(-3).join('\n') : undefined;
147
- platformAdapter.streamUpdate(taskState.latestContent, toolNote);
147
+ platformAdapter.streamUpdate(taskState.latestContent, undefined);
148
148
  }, platformAdapter.throttleMs - elapsed);
149
149
  }
150
150
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.11.8-beta.0",
3
+ "version": "1.11.8-beta.2",
4
4
  "description": "Your AI coding assistant, in every chat app. Multi-platform IM bridge for Claude Code, Codex, and CodeBuddy.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",