@keyou007/agent-bot 0.1.3 → 0.1.4

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.
Files changed (56) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +3 -1
  3. package/README.zh.md +3 -1
  4. package/dist/cli/FeishuAppConfiguration.js +10 -10
  5. package/dist/cli/FeishuAppConfiguration.js.map +1 -1
  6. package/dist/cli/FeishuAppRegistration.js +9 -9
  7. package/dist/cli/FeishuAppRegistration.js.map +1 -1
  8. package/dist/cli/Initializer.js +4 -4
  9. package/dist/cli/Initializer.js.map +1 -1
  10. package/dist/cli/LocalControlClient.js +2 -2
  11. package/dist/cli/LocalControlClient.js.map +1 -1
  12. package/dist/cli/LocalControlServer.js +1 -1
  13. package/dist/cli/LocalControlServer.js.map +1 -1
  14. package/dist/cli/ServerStarter.js +3 -3
  15. package/dist/cli/ServerStarter.js.map +1 -1
  16. package/dist/cli/SkillRegistry.js +4 -4
  17. package/dist/cli/SkillRegistry.js.map +1 -1
  18. package/dist/cli/help.js +2 -57
  19. package/dist/cli/help.js.map +1 -1
  20. package/dist/cli/packageVersion.js +1 -1
  21. package/dist/cli/packageVersion.js.map +1 -1
  22. package/dist/cli/profile.js +3 -3
  23. package/dist/cli/profile.js.map +1 -1
  24. package/dist/cli/serverStatus.js +37 -0
  25. package/dist/cli/serverStatus.js.map +1 -0
  26. package/dist/cli/taskChatRoute.js +2 -2
  27. package/dist/cli/taskChatRoute.js.map +1 -1
  28. package/dist/cli.js +112 -116
  29. package/dist/cli.js.map +1 -1
  30. package/dist/feishu/transport.js +1 -1
  31. package/dist/feishu/transport.js.map +1 -1
  32. package/dist/index.js +5 -4
  33. package/dist/index.js.map +1 -1
  34. package/dist/proxy/ProxySessionController.js +10 -10
  35. package/dist/proxy/ProxySessionController.js.map +1 -1
  36. package/docs/technical-reference.md +2 -0
  37. package/docs/technical-reference.zh.md +2 -0
  38. package/npm-shrinkwrap.json +2 -2
  39. package/package.json +1 -1
  40. package/skills/agent-bot/SKILL.md +1 -1
  41. package/src/cli/FeishuAppConfiguration.ts +10 -10
  42. package/src/cli/FeishuAppRegistration.ts +9 -9
  43. package/src/cli/Initializer.ts +4 -4
  44. package/src/cli/LocalControlClient.ts +2 -2
  45. package/src/cli/LocalControlServer.ts +1 -1
  46. package/src/cli/ServerStarter.ts +3 -3
  47. package/src/cli/SkillRegistry.ts +4 -4
  48. package/src/cli/help.ts +2 -66
  49. package/src/cli/packageVersion.ts +1 -1
  50. package/src/cli/profile.ts +3 -3
  51. package/src/cli/serverStatus.ts +39 -0
  52. package/src/cli/taskChatRoute.ts +2 -2
  53. package/src/cli.ts +113 -119
  54. package/src/feishu/transport.ts +1 -1
  55. package/src/index.ts +5 -4
  56. package/src/proxy/ProxySessionController.ts +10 -10
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@keyou007/agent-bot",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@keyou007/agent-bot",
9
- "version": "0.1.3",
9
+ "version": "0.1.4",
10
10
  "license": "GPL-3.0-only",
11
11
  "dependencies": {
12
12
  "@agentclientprotocol/sdk": "1.2.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keyou007/agent-bot",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "description": "Using Codex in Lark/Feishu feels just like using native Codex.",
6
6
  "license": "GPL-3.0-only",
@@ -74,7 +74,7 @@ agent-bot server status
74
74
  agent-bot task list
75
75
  ```
76
76
 
77
- `agent-bot --help` uses Chinese when the system locale is Chinese and English otherwise.
77
+ All Agent Bot CLI interface text is English regardless of system locale. `agent-bot server status` also reports the running profile's Lark App ID; with `--json`, read it from `feishuAppId`.
78
78
 
79
79
  Add `--json` to status and list commands when machine-readable output helps. If `agent-bot` is unavailable, report that the CLI is not installed or linked instead of guessing process state.
80
80
 
@@ -178,8 +178,8 @@ export async function ensureFeishuAppConfiguration(
178
178
  }
179
179
  }
180
180
 
181
- const detail = lastError instanceof Error ? ` 最后一次检查失败:${lastError.message}` : "";
182
- throw new Error(`等待飞书核心权限和消息事件配置生效超时,请重新运行 agent-bot init。${detail}`);
181
+ const detail = lastError instanceof Error ? ` Last check failed: ${lastError.message}` : "";
182
+ throw new Error(`Timed out waiting for the core Lark scopes and message event. Run agent-bot init again.${detail}`);
183
183
  }
184
184
 
185
185
  async function requestMissingFeishuConfiguration(
@@ -248,14 +248,14 @@ async function readFeishuAppConfiguration(
248
248
  `${FEISHU_OPEN_BASE_URL}${APPLICATION_PATH_PREFIX}/${appId}?lang=zh_cn`,
249
249
  { headers },
250
250
  signal,
251
- "查询飞书应用配置",
251
+ "Read Lark app configuration",
252
252
  ),
253
253
  fetchJson(
254
254
  fetchImpl,
255
255
  `${FEISHU_OPEN_BASE_URL}${APPLICATION_PATH_PREFIX}/${appId}/app_versions?lang=zh_cn&page_size=2`,
256
256
  { headers },
257
257
  signal,
258
- "查询飞书应用版本",
258
+ "Read Lark app versions",
259
259
  ),
260
260
  ]);
261
261
 
@@ -303,10 +303,10 @@ async function getTenantAccessToken(
303
303
  }),
304
304
  },
305
305
  signal,
306
- "获取飞书 tenant_access_token",
306
+ "Get the Lark tenant_access_token",
307
307
  );
308
308
  const token = readString(payload, "tenant_access_token");
309
- if (!token) throw new Error("飞书 tenant_access_token 响应缺少访问凭证。");
309
+ if (!token) throw new Error("The Lark tenant_access_token response is missing the access token.");
310
310
  return token;
311
311
  }
312
312
 
@@ -327,12 +327,12 @@ async function fetchJson(
327
327
  const response = await fetchImpl(url, { ...init, signal: controller.signal });
328
328
  const payload = (await response.json().catch(() => undefined)) as unknown;
329
329
  if (!isJsonObject(payload)) {
330
- throw new Error(`${operation}返回了无法解析的响应(HTTP ${response.status})。`);
330
+ throw new Error(`${operation} returned an invalid response (HTTP ${response.status}).`);
331
331
  }
332
332
  const code = readNumber(payload, "code");
333
333
  if (!response.ok || code !== 0) {
334
334
  throw new FeishuConfigurationApiError(
335
- `${operation}失败:${readString(payload, "msg") || response.statusText || `HTTP ${response.status}`}`,
335
+ `${operation} failed: ${readString(payload, "msg") || response.statusText || `HTTP ${response.status}`}`,
336
336
  code,
337
337
  response.status,
338
338
  );
@@ -340,7 +340,7 @@ async function fetchJson(
340
340
  return payload;
341
341
  } catch (error) {
342
342
  if (parentSignal?.aborted) throw abortError(parentSignal);
343
- if (controller.signal.aborted) throw new Error(`${operation}请求超时。`);
343
+ if (controller.signal.aborted) throw new Error(`${operation} timed out.`);
344
344
  throw error;
345
345
  } finally {
346
346
  clearTimeout(timeout);
@@ -442,7 +442,7 @@ function positiveInteger(value: number | undefined): number | undefined {
442
442
  }
443
443
 
444
444
  function abortError(signal: AbortSignal): Error {
445
- return signal.reason instanceof Error ? signal.reason : new Error("飞书应用配置已取消。");
445
+ return signal.reason instanceof Error ? signal.reason : new Error("Lark app configuration was cancelled.");
446
446
  }
447
447
 
448
448
  function delay(milliseconds: number): Promise<void> {
@@ -41,12 +41,12 @@ export async function registerFeishuApp(options: FeishuAppRegistrationOptions =
41
41
  },
42
42
  options.signal,
43
43
  );
44
- throwRegistrationError(begin, "无法发起飞书应用创建");
44
+ throwRegistrationError(begin, "Could not start Lark app creation");
45
45
 
46
46
  const deviceCode = readString(begin, "device_code");
47
47
  const userCode = readString(begin, "user_code");
48
48
  if (!deviceCode || !userCode) {
49
- throw new Error("飞书应用创建响应缺少 device_code 或 user_code。");
49
+ throw new Error("The Lark app creation response is missing device_code or user_code.");
50
50
  }
51
51
 
52
52
  const expiresIn =
@@ -113,16 +113,16 @@ export async function registerFeishuApp(options: FeishuAppRegistrationOptions =
113
113
  intervalSeconds = Math.min(intervalSeconds + 5, MAX_POLL_INTERVAL_SECONDS);
114
114
  continue;
115
115
  case "access_denied":
116
- throw new Error("你已取消飞书应用创建。");
116
+ throw new Error("Lark app creation was cancelled.");
117
117
  case "expired_token":
118
118
  case "invalid_grant":
119
- throw new Error("飞书应用创建链接已过期,请重新运行 agent-bot init。");
119
+ throw new Error("The Lark app creation link expired. Run agent-bot init again.");
120
120
  default:
121
- throwRegistrationError(payload, "飞书应用创建失败");
121
+ throwRegistrationError(payload, "Lark app creation failed");
122
122
  }
123
123
  }
124
124
 
125
- throw new Error("等待飞书应用创建超时,请重新运行 agent-bot init。");
125
+ throw new Error("Timed out waiting for Lark app creation. Run agent-bot init again.");
126
126
  }
127
127
 
128
128
  function buildVerificationUrl(userCode: string): string {
@@ -152,7 +152,7 @@ async function postRegistration(
152
152
  });
153
153
  const payload = (await response.json().catch(() => undefined)) as unknown;
154
154
  if (!isRecord(payload)) {
155
- throw new Error(`飞书应用注册接口返回了无法解析的响应(HTTP ${response.status})。`);
155
+ throw new Error(`The Lark app registration endpoint returned an invalid response (HTTP ${response.status}).`);
156
156
  }
157
157
  return payload;
158
158
  } finally {
@@ -165,7 +165,7 @@ function throwRegistrationError(payload: RegistrationPayload, prefix: string): v
165
165
  const code = readString(payload, "error");
166
166
  if (!code) return;
167
167
  const description = readString(payload, "error_description") || code;
168
- throw new Error(`${prefix}:${description}`);
168
+ throw new Error(`${prefix}: ${description}`);
169
169
  }
170
170
 
171
171
  function readString(value: RegistrationPayload, key: string): string {
@@ -189,7 +189,7 @@ function isRecord(value: unknown): value is RegistrationPayload {
189
189
  }
190
190
 
191
191
  function abortError(signal: AbortSignal): Error {
192
- return signal.reason instanceof Error ? signal.reason : new Error("飞书应用创建已取消。");
192
+ return signal.reason instanceof Error ? signal.reason : new Error("Lark app creation was cancelled.");
193
193
  }
194
194
 
195
195
  function delay(milliseconds: number): Promise<void> {
@@ -122,7 +122,7 @@ export function writeFeishuCredentials(envPath: string, credentials: FeishuCrede
122
122
  || persisted.appSecret !== credentials.appSecret
123
123
  || persisted.userOpenId !== credentials.userOpenId
124
124
  ) {
125
- throw new Error("飞书凭据写入后校验失败。");
125
+ throw new Error("Lark credential verification failed after writing the environment file.");
126
126
  }
127
127
  } finally {
128
128
  if (temporaryFile !== undefined) fs.closeSync(temporaryFile);
@@ -169,13 +169,13 @@ export function acquireInitializationLock(lockDirectory: string): Initialization
169
169
  if (created) fs.rmSync(lockPath, { force: true });
170
170
  if (!isFileExistsError(error)) throw error;
171
171
  if (!isStaleInitializationLock(lockPath)) {
172
- throw new Error(`另一个 agent-bot init 正在运行(锁文件:${lockPath})。`);
172
+ throw new Error(`Another agent-bot init process is running (lock file: ${lockPath}).`);
173
173
  }
174
174
  fs.rmSync(lockPath, { force: true });
175
175
  }
176
176
  }
177
177
 
178
- throw new Error(`无法获取初始化锁:${lockPath}`);
178
+ throw new Error(`Could not acquire the initialization lock: ${lockPath}`);
179
179
  }
180
180
 
181
181
  export function cleanupFeishuCredentialTemporaryFiles(envPath: string): number {
@@ -234,7 +234,7 @@ function upsertDotEnvValue(contents: string, key: string, value: string): string
234
234
 
235
235
  function assertDotEnvValue(key: string, value: string): void {
236
236
  if (!value.trim() || /[\r\n]/.test(value)) {
237
- throw new Error(`${key} 不是有效的单行环境变量值。`);
237
+ throw new Error(`${key} is not a valid single-line environment variable value.`);
238
238
  }
239
239
  }
240
240
 
@@ -17,7 +17,7 @@ export async function sendControlRequest(
17
17
  socket.destroy();
18
18
  operation();
19
19
  };
20
- const timer = setTimeout(() => finish(() => reject(new Error("连接 Agent Bot 控制端点超时。"))), timeoutMs);
20
+ const timer = setTimeout(() => finish(() => reject(new Error("Timed out connecting to the Agent Bot control endpoint."))), timeoutMs);
21
21
  socket.setEncoding("utf8");
22
22
  socket.once("connect", () => socket.write(`${JSON.stringify(request)}\n`));
23
23
  socket.on("data", (chunk: string) => {
@@ -33,7 +33,7 @@ export async function sendControlRequest(
33
33
  });
34
34
  socket.once("error", (error) => finish(() => reject(error)));
35
35
  socket.once("end", () => {
36
- if (!settled) finish(() => reject(new Error("Agent Bot 控制端点未返回结果。")));
36
+ if (!settled) finish(() => reject(new Error("The Agent Bot control endpoint returned no response.")));
37
37
  });
38
38
  });
39
39
  }
@@ -61,7 +61,7 @@ export class LocalControlServer {
61
61
  function parseRequest(line: string): ControlRequest {
62
62
  const value = JSON.parse(line) as unknown;
63
63
  if (!value || typeof value !== "object" || !("action" in value) || typeof value.action !== "string") {
64
- throw new Error("无效的本地控制请求。");
64
+ throw new Error("Invalid local control request.");
65
65
  }
66
66
  return value as ControlRequest;
67
67
  }
@@ -56,7 +56,7 @@ export async function startServer(
56
56
  if (await dependencies.isReachable(endpoint)) {
57
57
  const running = await dependencies.waitUntilRunning(endpoint, SERVER_START_TIMEOUT_MS);
58
58
  if (!running) {
59
- throw new Error("agent-bot server 已启动,但未能连接飞书机器人。请检查日志。");
59
+ throw new Error("The Agent Bot server started but could not connect to Lark. Check the logs.");
60
60
  }
61
61
  return { status: "started" };
62
62
  }
@@ -64,7 +64,7 @@ export async function startServer(
64
64
  dependencies.spawnSupervisor(config);
65
65
  const running = await dependencies.waitUntilRunning(endpoint, SERVER_START_TIMEOUT_MS);
66
66
  if (!running) {
67
- throw new Error("已启动 Supervisor,但 server 未在 45 秒内连接飞书机器人。请检查日志。");
67
+ throw new Error("The Supervisor started, but the server did not connect to Lark within 45 seconds. Check the logs.");
68
68
  }
69
69
  return { status: "started" };
70
70
  }
@@ -85,7 +85,7 @@ const defaultDependencies: ServerStarterDependencies = {
85
85
  detached: true,
86
86
  windowsHide: true,
87
87
  stdio: "ignore",
88
- env: { ...process.env, AGENT_BOT_RESTART_REASON: "通过 agent-bot CLI 启动" },
88
+ env: { ...process.env, AGENT_BOT_RESTART_REASON: "通过 Agent Bot CLI 启动" },
89
89
  });
90
90
  child.unref();
91
91
  },
@@ -65,7 +65,7 @@ export class SkillRegistry {
65
65
  this.assertValidSource();
66
66
  const existing = fs.existsSync(this.targetPath);
67
67
  if (existing && this.readMarker()?.managedBy !== "agent-bot") {
68
- throw new Error(`目标目录已存在且不由 Agent Bot 管理:${this.targetPath}`);
68
+ throw new Error(`The target directory exists and is not managed by Agent Bot: ${this.targetPath}`);
69
69
  }
70
70
 
71
71
  const before = existing ? this.status() : undefined;
@@ -93,7 +93,7 @@ export class SkillRegistry {
93
93
  uninstall(): boolean {
94
94
  if (!fs.existsSync(this.targetPath)) return false;
95
95
  if (this.readMarker()?.managedBy !== "agent-bot") {
96
- throw new Error(`拒绝删除不由 Agent Bot 管理的目录:${this.targetPath}`);
96
+ throw new Error(`Refusing to remove a directory that is not managed by Agent Bot: ${this.targetPath}`);
97
97
  }
98
98
  this.removeManagedTarget();
99
99
  return true;
@@ -101,13 +101,13 @@ export class SkillRegistry {
101
101
 
102
102
  private assertValidSource(): void {
103
103
  if (!fs.existsSync(path.join(this.sourcePath, "SKILL.md"))) {
104
- throw new Error(`找不到内置 Agent Bot Skill:${this.sourcePath}`);
104
+ throw new Error(`The built-in Agent Bot Skill was not found: ${this.sourcePath}`);
105
105
  }
106
106
  }
107
107
 
108
108
  private assertSafeTarget(): void {
109
109
  if (path.dirname(this.targetPath) !== this.skillsRoot || path.basename(this.targetPath) !== SKILL_NAME) {
110
- throw new Error(`不安全的 Skill 目标路径:${this.targetPath}`);
110
+ throw new Error(`Unsafe Skill target path: ${this.targetPath}`);
111
111
  }
112
112
  }
113
113
 
package/src/cli/help.ts CHANGED
@@ -1,63 +1,4 @@
1
- export type CliLanguage = "en" | "zh";
2
-
3
- export function resolveCliLanguage(
4
- env: NodeJS.ProcessEnv = process.env,
5
- systemLocale = Intl.DateTimeFormat().resolvedOptions().locale,
6
- ): CliLanguage {
7
- const configuredLocale = [
8
- env.LC_ALL,
9
- env.LC_MESSAGES,
10
- env.LANGUAGE,
11
- env.LANG,
12
- ].find((value) => value?.trim());
13
- return isChineseLocale(configuredLocale ?? systemLocale) ? "zh" : "en";
14
- }
15
-
16
- export function renderCliHelp(version: string, language = resolveCliLanguage()): string {
17
- return language === "zh" ? renderChineseHelp(version) : renderEnglishHelp(version);
18
- }
19
-
20
- function renderChineseHelp(version: string): string {
21
- return `Agent Bot ${version}
22
- 通过飞书/Lark 使用本机 Codex 与 ACP Agent。
23
-
24
- 用法:
25
- agent-bot [选项] <命令>
26
-
27
- 常用命令:
28
- init 初始化配置和飞书应用,并启动服务
29
- console 打开本地 Console
30
- server start 在后台启动 Agent Bot
31
- server status 查看服务和安全重启状态
32
- server restart 安排安全重启
33
- server stop 停止 Agent Bot
34
- task list 列出任务
35
- task status <task> 查看任务状态
36
- task chat <task> 查看任务绑定的飞书会话
37
- task prompt <task> <prompt> 向指定任务发送 Prompt
38
- task stop <task> 停止指定任务
39
- task title <task> <title> 修改任务标题
40
- skills status 查看内置 Skill 状态
41
- skills install 安装内置 Skill
42
-
43
- 选项:
44
- --profile <directory> 使用指定目录中的独立 Profile
45
- --config <path> 使用指定配置文件
46
- --json 在支持的命令中输出 JSON
47
- -h, --help 显示帮助
48
- -v, --version 显示版本
49
-
50
- 示例:
51
- agent-bot init
52
- agent-bot --profile ~/.agent-bot-rescue init
53
- agent-bot server start
54
- agent-bot server status
55
- agent-bot task list
56
- agent-bot server restart --reason "升级 Agent Bot"
57
- `;
58
- }
59
-
60
- function renderEnglishHelp(version: string): string {
1
+ export function renderCliHelp(version: string): string {
61
2
  return `Agent Bot ${version}
62
3
  Use local Codex and ACP agents from Lark/Feishu.
63
4
 
@@ -68,7 +9,7 @@ Common commands:
68
9
  init Initialize the Lark app and start the service
69
10
  console Open the local console
70
11
  server start Start Agent Bot in the background
71
- server status Show server and safe-restart status
12
+ server status Show the server, Lark App ID, and safe-restart status
72
13
  server restart Schedule a safe restart
73
14
  server stop Stop Agent Bot
74
15
  task list List tasks
@@ -96,8 +37,3 @@ Examples:
96
37
  agent-bot server restart --reason "Update Agent Bot"
97
38
  `;
98
39
  }
99
-
100
- function isChineseLocale(value: string): boolean {
101
- const locale = value.trim().split(":")[0]?.split(/[.@]/)[0]?.replaceAll("_", "-").toLowerCase();
102
- return locale === "zh" || Boolean(locale?.startsWith("zh-"));
103
- }
@@ -8,7 +8,7 @@ export function readPackageVersion(
8
8
  fs.readFileSync(fileURLToPath(packageJsonUrl), "utf8"),
9
9
  ) as { version?: unknown };
10
10
  if (typeof metadata.version !== "string" || !metadata.version.trim()) {
11
- throw new Error("package.json 中缺少有效的 version。");
11
+ throw new Error("package.json does not contain a valid version.");
12
12
  }
13
13
  return metadata.version;
14
14
  }
@@ -22,7 +22,7 @@ export function parseGlobalOptions(input: string[]): ParsedGlobalOptions {
22
22
  const configPath = removeOption(args, "--config");
23
23
  const profilePath = removeOption(args, "--profile");
24
24
  if (configPath && profilePath) {
25
- throw new Error("--profile 和 --config 不能同时使用。Profile 固定使用其目录下的 config.yaml。");
25
+ throw new Error("--profile and --config cannot be used together. A profile always uses config.yaml in its directory.");
26
26
  }
27
27
  return {
28
28
  args,
@@ -49,11 +49,11 @@ export function applyExplicitProfile(
49
49
 
50
50
  function removeOption(args: string[], option: string): string | undefined {
51
51
  const indexes = args.flatMap((value, index) => value === option ? [index] : []);
52
- if (indexes.length > 1) throw new Error(`${option} 只能指定一次。`);
52
+ if (indexes.length > 1) throw new Error(`${option} can only be specified once.`);
53
53
  const index = indexes[0];
54
54
  if (index === undefined) return undefined;
55
55
  const value = args[index + 1];
56
- if (!value || value.startsWith("--")) throw new Error(`${option} 需要目录或文件路径。`);
56
+ if (!value || value.startsWith("--")) throw new Error(`${option} requires a directory or file path.`);
57
57
  args.splice(index, 2);
58
58
  return value;
59
59
  }
@@ -0,0 +1,39 @@
1
+ export function withConfiguredFeishuAppId(
2
+ data: unknown,
3
+ configuredFeishuAppId?: string,
4
+ ): Record<string, unknown> {
5
+ const value = data && typeof data === "object"
6
+ ? data as Record<string, unknown>
7
+ : {};
8
+ if (Object.hasOwn(value, "feishuAppId")) return value;
9
+ return {
10
+ ...value,
11
+ feishuAppId: configuredFeishuAppId ?? null,
12
+ };
13
+ }
14
+
15
+ export function formatServerStatus(data: unknown): string {
16
+ const value = data && typeof data === "object" ? data as Record<string, unknown> : {};
17
+ const activity = value.activity && typeof value.activity === "object"
18
+ ? value.activity as Record<string, unknown>
19
+ : {};
20
+ const state = value.running === false
21
+ ? "not running"
22
+ : value.ready === false
23
+ ? "starting (connecting to Lark)"
24
+ : "running";
25
+ const safeRestart = value.safeRestartScheduled
26
+ ? `pending (${String(value.safeRestartReason ?? "no reason provided")})`
27
+ : "not scheduled";
28
+ return [
29
+ `Agent Bot server: ${state}`,
30
+ `Lark App ID: ${value.feishuAppId ?? "not configured"}`,
31
+ `PID: ${value.pid ?? "-"}`,
32
+ `Started at: ${value.startedAt ?? "-"}`,
33
+ `Supervisor: ${value.supervised ? "enabled" : "disabled"}`,
34
+ `Running tasks: ${activity.runningSessions ?? 0}`,
35
+ `Pending final deliveries: ${activity.pendingFinalDeliveries ?? 0}`,
36
+ `Safe restart: ${safeRestart}`,
37
+ "",
38
+ ].join("\n");
39
+ }
@@ -15,10 +15,10 @@ export function taskChatRoute(session: SessionRecord): TaskChatRoute {
15
15
  const contextKey = session.contextKey;
16
16
  const baseContextKey = baseChatContextKey(contextKey);
17
17
  if (!baseContextKey.startsWith(CHAT_CONTEXT_PREFIX)) {
18
- throw new Error(`任务没有绑定飞书会话:${session.remoteSessionId ?? session.acpSessionId ?? session.localSessionId}`);
18
+ throw new Error(`The task is not bound to a Lark chat: ${session.remoteSessionId ?? session.acpSessionId ?? session.localSessionId}`);
19
19
  }
20
20
  const chatId = baseContextKey.slice(CHAT_CONTEXT_PREFIX.length);
21
- if (!chatId) throw new Error(`任务的飞书会话 ID 无效:${contextKey}`);
21
+ if (!chatId) throw new Error(`The task has an invalid Lark chat ID: ${contextKey}`);
22
22
  const threadId = isThreadContextKey(contextKey)
23
23
  ? contextKey.slice(contextKey.indexOf(THREAD_CONTEXT_MARKER) + THREAD_CONTEXT_MARKER.length)
24
24
  : undefined;