@wu529778790/open-im 1.9.3-beta.11 → 1.9.3-beta.13

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.
@@ -212,7 +212,6 @@ export class ClaudeSDKAdapter {
212
212
  let pendingTempId; // 记录临时 ID,用于 abort 时清理
213
213
  let runSettled = false;
214
214
  let currentStream; // 用于 abort 时立即中断 stream
215
- let timeoutHandle;
216
215
  const permissionMode = options?.skipPermissions
217
216
  ? 'bypassPermissions'
218
217
  : options?.permissionMode === 'acceptEdits'
@@ -305,8 +304,6 @@ export class ClaudeSDKAdapter {
305
304
  log.info(`[V2] Result: subtype=${m.subtype}, num_turns=${m.num_turns}, sessionId=${actualSessionId ?? 'unknown'}`);
306
305
  // 检查会话错误
307
306
  if (!success) {
308
- if (timeoutHandle)
309
- clearTimeout(timeoutHandle);
310
307
  runSettled = true;
311
308
  const noConvErr = errs.find((e) => e.includes('No conversation found') || e.includes('session not found'));
312
309
  if (noConvErr) {
@@ -343,8 +340,6 @@ export class ClaudeSDKAdapter {
343
340
  result.result = accumulated;
344
341
  }
345
342
  runSettled = true;
346
- if (timeoutHandle)
347
- clearTimeout(timeoutHandle);
348
343
  callbacks.onComplete(result);
349
344
  return;
350
345
  }
@@ -353,8 +348,6 @@ export class ClaudeSDKAdapter {
353
348
  if (!streamClosed) {
354
349
  if (accumulated) {
355
350
  log.info('Stream ended without result message, using accumulated text');
356
- if (timeoutHandle)
357
- clearTimeout(timeoutHandle);
358
351
  runSettled = true;
359
352
  callbacks.onComplete({
360
353
  success: true,
@@ -369,8 +362,6 @@ export class ClaudeSDKAdapter {
369
362
  else {
370
363
  // 流结束但无 result 也无 accumulated:必须触发回调,否则 Promise 永远挂起
371
364
  log.warn('Stream ended with no result and no accumulated text, calling onError to prevent stuck state');
372
- if (timeoutHandle)
373
- clearTimeout(timeoutHandle);
374
365
  runSettled = true;
375
366
  callbacks.onError('AI 响应异常结束(无输出),请重试');
376
367
  }
@@ -393,8 +384,6 @@ export class ClaudeSDKAdapter {
393
384
  return;
394
385
  }
395
386
  runSettled = true;
396
- if (timeoutHandle)
397
- clearTimeout(timeoutHandle);
398
387
  const errorObj = err;
399
388
  const msg = errorObj.message || String(err);
400
389
  log.error(`Claude SDK V2 error: ${msg}`);
@@ -428,38 +417,15 @@ export class ClaudeSDKAdapter {
428
417
  runSession().catch((err) => {
429
418
  if (!runSettled) {
430
419
  runSettled = true;
431
- if (timeoutHandle)
432
- clearTimeout(timeoutHandle);
433
420
  const msg = err instanceof Error ? err.message : String(err);
434
421
  log.error(`Unhandled runSession error: ${msg}`);
435
422
  callbacks.onError(msg);
436
423
  }
437
424
  });
438
- // 强制执行超时
439
- if (options?.timeoutMs && options.timeoutMs > 0) {
440
- timeoutHandle = setTimeout(() => {
441
- if (!runSettled) {
442
- log.warn(`Session timed out after ${options.timeoutMs}ms, aborting`);
443
- abortController.abort();
444
- // 立即中断 stream,不等下一条消息
445
- if (currentStream) {
446
- try {
447
- currentStream.return?.();
448
- }
449
- catch { /* ignore */ }
450
- }
451
- runSettled = true;
452
- callbacks.onError(`AI 响应超时(${Math.round(options.timeoutMs / 1000)}s),请重试`);
453
- }
454
- }, options.timeoutMs);
455
- timeoutHandle.unref();
456
- }
457
425
  return {
458
426
  abort: () => {
459
427
  log.info('Aborting session run');
460
428
  abortController.abort();
461
- if (timeoutHandle)
462
- clearTimeout(timeoutHandle);
463
429
  // 立即中断 stream,不等下一条消息
464
430
  if (currentStream) {
465
431
  try {
@@ -40,7 +40,6 @@ export class CodeBuddyAdapter {
40
40
  }, {
41
41
  skipPermissions: options?.skipPermissions,
42
42
  permissionMode: options?.permissionMode,
43
- timeoutMs: options?.timeoutMs,
44
43
  model: options?.model,
45
44
  });
46
45
  }
@@ -12,7 +12,6 @@ export class CodexAdapter {
12
12
  const opts = {
13
13
  skipPermissions: options?.skipPermissions,
14
14
  permissionMode: options?.permissionMode,
15
- timeoutMs: options?.timeoutMs,
16
15
  model: options?.model,
17
16
  chatId: options?.chatId,
18
17
  hookPort: options?.hookPort,
@@ -25,7 +25,6 @@ export interface RunOptions {
25
25
  skipPermissions?: boolean;
26
26
  /** Claude --permission-mode: default | acceptEdits | plan(yolo 时用 skipPermissions) */
27
27
  permissionMode?: 'default' | 'acceptEdits' | 'plan';
28
- timeoutMs?: number;
29
28
  model?: string;
30
29
  chatId?: string;
31
30
  hookPort?: number;
@@ -19,7 +19,6 @@ export interface CodeBuddyRunCallbacks {
19
19
  export interface CodeBuddyRunOptions {
20
20
  skipPermissions?: boolean;
21
21
  permissionMode?: 'default' | 'acceptEdits' | 'plan';
22
- timeoutMs?: number;
23
22
  model?: string;
24
23
  }
25
24
  export interface CodeBuddyRunHandle {
@@ -3,18 +3,6 @@ import { accessSync, constants } from 'node:fs';
3
3
  import { isAbsolute, join } from 'node:path';
4
4
  import { createLogger } from '../logger.js';
5
5
  const log = createLogger('CodeBuddyCli');
6
- const MAX_TIMEOUT_MS = 2_147_483_647;
7
- const DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
8
- function getIdleTimeoutMs(totalTimeoutMs) {
9
- const raw = process.env.CODEBUDDY_IDLE_TIMEOUT_MS;
10
- const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;
11
- const configuredIdleTimeoutMs = Number.isFinite(parsed) && parsed > 0
12
- ? Math.min(parsed, MAX_TIMEOUT_MS)
13
- : DEFAULT_IDLE_TIMEOUT_MS;
14
- return totalTimeoutMs > 0
15
- ? Math.min(configuredIdleTimeoutMs, totalTimeoutMs)
16
- : configuredIdleTimeoutMs;
17
- }
18
6
  export function buildCodeBuddyArgs(prompt, sessionId, options) {
19
7
  const args = ['--print', '--output-format', 'stream-json'];
20
8
  if (options?.skipPermissions) {
@@ -203,50 +191,7 @@ export function runCodeBuddy(cliPath, prompt, sessionId, workDir, callbacks, opt
203
191
  let currentModel;
204
192
  const toolStats = {};
205
193
  const startTime = Date.now();
206
- const timeoutMs = options?.timeoutMs && options.timeoutMs > 0
207
- ? Math.min(options.timeoutMs, MAX_TIMEOUT_MS)
208
- : 0;
209
- const idleTimeoutMs = getIdleTimeoutMs(timeoutMs);
210
- let timeoutHandle = null;
211
- let idleTimeoutHandle = null;
212
194
  const stdoutState = { buffer: '' };
213
- const clearTimers = () => {
214
- if (timeoutHandle) {
215
- clearTimeout(timeoutHandle);
216
- timeoutHandle = null;
217
- }
218
- if (idleTimeoutHandle) {
219
- clearTimeout(idleTimeoutHandle);
220
- idleTimeoutHandle = null;
221
- }
222
- };
223
- const resetIdleTimeout = () => {
224
- if (idleTimeoutMs <= 0 || completed)
225
- return;
226
- if (idleTimeoutHandle)
227
- clearTimeout(idleTimeoutHandle);
228
- idleTimeoutHandle = setTimeout(() => {
229
- if (completed)
230
- return;
231
- completed = true;
232
- clearTimers();
233
- if (!child.killed)
234
- child.kill('SIGTERM');
235
- callbacks.onError(`CodeBuddy 执行长时间无输出,已自动终止(${idleTimeoutMs}ms)`);
236
- }, idleTimeoutMs);
237
- };
238
- if (timeoutMs > 0) {
239
- timeoutHandle = setTimeout(() => {
240
- if (completed)
241
- return;
242
- completed = true;
243
- clearTimers();
244
- if (!child.killed)
245
- child.kill('SIGTERM');
246
- callbacks.onError(`CodeBuddy 执行超时(${timeoutMs}ms),已终止`);
247
- }, timeoutMs);
248
- }
249
- resetIdleTimeout();
250
195
  const MAX_STDERR = 8 * 1024;
251
196
  let stderrText = '';
252
197
  const handleErrorText = (message) => {
@@ -299,7 +244,6 @@ export function runCodeBuddy(cliPath, prompt, sessionId, workDir, callbacks, opt
299
244
  if (completed)
300
245
  return;
301
246
  completed = true;
302
- clearTimers();
303
247
  const isError = payload.is_error === true;
304
248
  const resultText = typeof payload.result === 'string'
305
249
  ? payload.result
@@ -324,7 +268,6 @@ export function runCodeBuddy(cliPath, prompt, sessionId, workDir, callbacks, opt
324
268
  }
325
269
  };
326
270
  child.stdout?.on('data', (chunk) => {
327
- resetIdleTimeout();
328
271
  stdoutState.buffer += chunk.toString();
329
272
  const payloads = extractBufferedPayloads(stdoutState);
330
273
  for (const payload of payloads) {
@@ -337,14 +280,12 @@ export function runCodeBuddy(cliPath, prompt, sessionId, workDir, callbacks, opt
337
280
  }
338
281
  });
339
282
  child.stderr?.on('data', (chunk) => {
340
- resetIdleTimeout();
341
283
  stderrText += chunk.toString();
342
284
  if (stderrText.length > MAX_STDERR) {
343
285
  stderrText = stderrText.slice(-MAX_STDERR);
344
286
  }
345
287
  });
346
288
  child.on('close', (code) => {
347
- clearTimers();
348
289
  if (completed)
349
290
  return;
350
291
  if (stdoutState.buffer.trim()) {
@@ -377,7 +318,6 @@ export function runCodeBuddy(cliPath, prompt, sessionId, workDir, callbacks, opt
377
318
  });
378
319
  });
379
320
  child.on('error', (err) => {
380
- clearTimers();
381
321
  if (completed)
382
322
  return;
383
323
  completed = true;
@@ -386,7 +326,6 @@ export function runCodeBuddy(cliPath, prompt, sessionId, workDir, callbacks, opt
386
326
  return {
387
327
  abort: () => {
388
328
  completed = true;
389
- clearTimers();
390
329
  if (!child.killed)
391
330
  child.kill('SIGTERM');
392
331
  },
@@ -22,7 +22,6 @@ export interface CodexRunCallbacks {
22
22
  export interface CodexRunOptions {
23
23
  skipPermissions?: boolean;
24
24
  permissionMode?: 'default' | 'acceptEdits' | 'plan';
25
- timeoutMs?: number;
26
25
  model?: string;
27
26
  chatId?: string;
28
27
  hookPort?: number;
@@ -8,8 +8,6 @@ import { createInterface } from 'node:readline';
8
8
  import { createLogger } from '../logger.js';
9
9
  const log = createLogger('CodexCli');
10
10
  const windowsCodexLaunchCache = new Map();
11
- const MAX_TIMEOUT_MS = 2_147_483_647;
12
- const DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
13
11
  const SUPPORTED_IMAGE_EXTENSIONS = new Set([
14
12
  '.png',
15
13
  '.jpg',
@@ -21,16 +19,6 @@ const SUPPORTED_IMAGE_EXTENSIONS = new Set([
21
19
  '.tiff',
22
20
  '.avif',
23
21
  ]);
24
- function getIdleTimeoutMs(totalTimeoutMs) {
25
- const raw = process.env.CODEX_IDLE_TIMEOUT_MS;
26
- const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;
27
- const configuredIdleTimeoutMs = Number.isFinite(parsed) && parsed > 0
28
- ? Math.min(parsed, MAX_TIMEOUT_MS)
29
- : DEFAULT_IDLE_TIMEOUT_MS;
30
- return totalTimeoutMs > 0
31
- ? Math.min(configuredIdleTimeoutMs, totalTimeoutMs)
32
- : configuredIdleTimeoutMs;
33
- }
34
22
  function parseCodexEvent(line) {
35
23
  const trimmed = line.trim();
36
24
  if (!trimmed)
@@ -225,51 +213,7 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
225
213
  let completed = false;
226
214
  const toolStats = {};
227
215
  const startTime = Date.now();
228
- const timeoutMs = options?.timeoutMs && options.timeoutMs > 0
229
- ? Math.min(options.timeoutMs, MAX_TIMEOUT_MS)
230
- : 0;
231
- const idleTimeoutMs = getIdleTimeoutMs(timeoutMs);
232
- let timeoutHandle = null;
233
- let idleTimeoutHandle = null;
234
216
  const rl = createInterface({ input: child.stdout });
235
- const clearTimers = () => {
236
- if (timeoutHandle) {
237
- clearTimeout(timeoutHandle);
238
- timeoutHandle = null;
239
- }
240
- if (idleTimeoutHandle) {
241
- clearTimeout(idleTimeoutHandle);
242
- idleTimeoutHandle = null;
243
- }
244
- };
245
- const failAndTerminate = (message, logMessage) => {
246
- if (completed)
247
- return;
248
- completed = true;
249
- clearTimers();
250
- log.warn(logMessage);
251
- rl.close();
252
- if (!child.killed)
253
- child.kill('SIGTERM');
254
- callbacks.onError(message);
255
- };
256
- const resetIdleTimeout = () => {
257
- if (idleTimeoutMs <= 0 || completed)
258
- return;
259
- if (idleTimeoutHandle)
260
- clearTimeout(idleTimeoutHandle);
261
- idleTimeoutHandle = setTimeout(() => {
262
- failAndTerminate(`Codex 执行长时间无输出,已自动终止(${idleTimeoutMs}ms)`, `Codex CLI idle timeout after ${idleTimeoutMs}ms, killing pid=${child.pid}`);
263
- }, idleTimeoutMs);
264
- };
265
- if (timeoutMs > 0) {
266
- timeoutHandle = setTimeout(() => {
267
- if (!completed && !child.killed) {
268
- failAndTerminate(`执行超时(${timeoutMs}ms),已终止进程`, `Codex CLI timeout after ${timeoutMs}ms, killing pid=${child.pid}`);
269
- }
270
- }, timeoutMs);
271
- }
272
- resetIdleTimeout();
273
217
  const MAX_STDERR_HEAD = 4 * 1024;
274
218
  const MAX_STDERR_TAIL = 6 * 1024;
275
219
  let stderrHead = '';
@@ -277,7 +221,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
277
221
  let stderrTotal = 0;
278
222
  let stderrHeadFull = false;
279
223
  child.stderr?.on('data', (chunk) => {
280
- resetIdleTimeout();
281
224
  const text = chunk.toString();
282
225
  stderrTotal += text.length;
283
226
  if (!stderrHeadFull) {
@@ -295,7 +238,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
295
238
  log.debug(`[stderr] ${text.trimEnd()}`);
296
239
  });
297
240
  rl.on('line', (line) => {
298
- resetIdleTimeout();
299
241
  const event = parseCodexEvent(line);
300
242
  if (!event)
301
243
  return;
@@ -309,7 +251,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
309
251
  }
310
252
  if (type === 'turn.failed') {
311
253
  completed = true;
312
- clearTimers();
313
254
  const err = event.error;
314
255
  callbacks.onError(err?.message ?? 'Codex turn failed');
315
256
  return;
@@ -320,7 +261,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
320
261
  return;
321
262
  }
322
263
  completed = true;
323
- clearTimers();
324
264
  callbacks.onError(msg ?? 'Codex stream error');
325
265
  return;
326
266
  }
@@ -374,7 +314,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
374
314
  }
375
315
  if (type === 'turn.completed') {
376
316
  completed = true;
377
- clearTimers();
378
317
  callbacks.onComplete({
379
318
  success: true,
380
319
  result: accumulated,
@@ -392,7 +331,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
392
331
  const finalize = () => {
393
332
  if (!rlClosed || !childClosed)
394
333
  return;
395
- clearTimers();
396
334
  if (completed)
397
335
  return;
398
336
  if (exitCode !== null && exitCode !== 0) {
@@ -443,7 +381,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
443
381
  child.on('error', (err) => {
444
382
  const errorCode = err.code;
445
383
  log.error(`Codex CLI spawn error: ${err.message}, code=${errorCode}, path=${cliPath}`);
446
- clearTimers();
447
384
  if (!completed) {
448
385
  completed = true;
449
386
  callbacks.onError(`Failed to start Codex CLI: ${err.message}`);
@@ -454,7 +391,6 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
454
391
  return {
455
392
  abort: () => {
456
393
  completed = true;
457
- clearTimers();
458
394
  rl.close();
459
395
  if (!child.killed)
460
396
  child.kill('SIGTERM');
@@ -15,7 +15,7 @@ export declare const PAGE_TEXTS: {
15
15
  readonly mode: "Flow";
16
16
  readonly dashboardTitle: "Dashboard";
17
17
  readonly dashboardSubtitle: "Platform health status";
18
- readonly dashboardSubtitleFull: "Platform status and setup progress";
18
+ readonly dashboardSubtitleFull: "Platform and service status";
19
19
  readonly quickActionsTitle: "Quick Actions";
20
20
  readonly serviceTitle: "Service Control";
21
21
  readonly serviceHint: "Validate, save, start, and stop the local bridge from one place.";
@@ -47,7 +47,7 @@ export declare const PAGE_TEXTS: {
47
47
  readonly openImConfigCardHint: "Full open-im configuration. Use Format, then Save. Invalid JSON is rejected.";
48
48
  readonly claudeSettingsCardHint: "Claude SDK environment (ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, ANTHROPIC_MODEL, etc.). Set API access here without shell exports.";
49
49
  readonly claudeJsonShortcutHint: "Edit ~/.claude/settings.json in the sidebar «Config files» section below.";
50
- readonly platformsHint: "Follow the setup checklist on Overview first. Disabled platforms still keep saved values.";
50
+ readonly platformsHint: "Disabled platforms keep their saved values.";
51
51
  readonly enabled: "Enabled";
52
52
  readonly readyState: "Ready";
53
53
  readonly setupRequired: "Setup required";
@@ -101,14 +101,11 @@ export declare const PAGE_TEXTS: {
101
101
  readonly codexCli: "Codex CLI path";
102
102
  readonly codebuddyCli: "CodeBuddy CLI path";
103
103
  readonly codexProxy: "Codex proxy";
104
- readonly claudeTimeout: "Claude timeout (ms)";
105
104
  readonly claudeConfigPath: "Config file location";
106
105
  readonly claudeAuthToken: "ANTHROPIC_AUTH_TOKEN";
107
106
  readonly claudeBaseUrl: "ANTHROPIC_BASE_URL";
108
107
  readonly claudeModel: "ANTHROPIC_MODEL";
109
108
  readonly claudeProxy: "Proxy (optional)";
110
- readonly codexTimeout: "Codex timeout (ms)";
111
- readonly codebuddyTimeout: "CodeBuddy timeout (ms)";
112
109
  readonly hookPort: "Hook port";
113
110
  readonly logLevel: "Log level";
114
111
  readonly logLevelDefault: "default (app default)";
@@ -141,28 +138,10 @@ export declare const PAGE_TEXTS: {
141
138
  readonly saveBtn: "Save";
142
139
  readonly jsonValid: "Valid JSON";
143
140
  readonly jsonInvalid: "Invalid JSON: {error}";
144
- readonly wizardTitle: "First-time setup";
145
- readonly wizardStep1Title: "Connect an IM channel";
146
- readonly wizardStep1Desc: "Enable at least one platform below and fill every required field. Use Check config when available.";
147
- readonly wizardStep2Title: "Set the default AI tool";
148
- readonly wizardStep2Desc: "Claude SDK: edit ~/.claude/settings.json under sidebar Config files. Codex / CodeBuddy: set the CLI path in the AI section.";
149
- readonly wizardStep3Title: "Validate and save";
150
- readonly wizardStep3Desc: "Click Validate, then Save config. Fix any errors shown in the banner above.";
151
- readonly wizardStep4Title: "Start the bridge";
152
- readonly wizardStep4Desc: "Open Service and click Start bridge. If it exits, read ~/.open-im/logs.";
153
- readonly wizardStatusDone: "Done";
154
- readonly wizardStatusTodo: "To do";
155
- readonly wizardJumpPlatforms: "Open Platforms";
156
- readonly wizardJumpAi: "Open AI";
157
- readonly wizardJumpService: "Open Service";
158
141
  readonly validationNoPlatformEnabled: "Enable at least one IM platform and fill its required credentials before saving.";
159
142
  readonly validationPlatformIncomplete: "Platform \"{platform}\" is enabled but these required fields are empty: {fields}";
160
143
  readonly validationAiCodexNoCli: "Default AI is Codex but Codex CLI path is empty. Set it under AI Tooling or change the default tool.";
161
144
  readonly validationAiCodebuddyNoCli: "Default AI is CodeBuddy but CodeBuddy CLI path is empty. Set it under AI Tooling or change the default tool.";
162
- readonly onboardingTitle: "Welcome to open-im";
163
- readonly onboardingDismiss: "Got it";
164
- readonly onboardingReadme: "README (setup)";
165
- readonly onboardingBody: "<p><strong>open-im</strong> bridges Telegram, Feishu, QQ, WeWork, DingTalk, and WorkBuddy to Claude / Codex / CodeBuddy on your machine.</p><ol style=\"margin:12px 0 12px 18px;line-height:1.65\"><li>Pick <strong>one</strong> chat app in <strong>Platforms</strong> and paste credentials (see hints under each field).</li><li>Set the <strong>default AI</strong> under AI Tooling; for Claude SDK, put API keys in sidebar <strong>Config files</strong> → <strong>~/.claude/settings.json</strong>.</li><li>Edit <strong>~/.open-im/config.json</strong> in the same <strong>Config files</strong> section when you need raw JSON.</li><li>Use <strong>Validate</strong> then <strong>Save config</strong>, then <strong>Start bridge</strong> under Service.</li><li>CLI alternative: run <code style=\"background:var(--bg-tertiary);padding:2px 6px;border-radius:4px\">open-im init</code> in a terminal.</li></ol>";
166
145
  readonly tipTelegramToken: "From Telegram, open <a href=\"https://t.me/BotFather\" target=\"_blank\" rel=\"noopener\">@BotFather</a> → /newbot → copy the token.";
167
146
  readonly tipFeishuAppId: "Feishu Open Platform → your app → Credentials → App ID.";
168
147
  readonly tipFeishuSecret: "Same page → App Secret (click show / reset if needed).";
@@ -188,7 +167,7 @@ export declare const PAGE_TEXTS: {
188
167
  readonly mode: "模式";
189
168
  readonly dashboardTitle: "概览";
190
169
  readonly dashboardSubtitle: "平台健康状态";
191
- readonly dashboardSubtitleFull: "平台状态与接入进度";
170
+ readonly dashboardSubtitleFull: "平台与服务状态";
192
171
  readonly quickActionsTitle: "快捷操作";
193
172
  readonly refreshHealth: "刷新健康状态";
194
173
  readonly viewConfig: "查看配置";
@@ -218,7 +197,7 @@ export declare const PAGE_TEXTS: {
218
197
  readonly openImConfigCardHint: "open-im 完整配置。先格式化再保存;JSON 不合法时无法写入。";
219
198
  readonly claudeSettingsCardHint: "Claude SDK 环境变量(ANTHROPIC_API_KEY、ANTHROPIC_BASE_URL、ANTHROPIC_MODEL 等)。在此配置 API,无需在终端 export。";
220
199
  readonly claudeJsonShortcutHint: "提示:请在左侧栏「配置文件」分区编辑 ~/.claude/settings.json。";
221
- readonly platformsHint: "建议先在概览页按引导步骤操作。禁用的平台仍保留已保存的值。";
200
+ readonly platformsHint: "禁用的平台仍保留已保存的值。";
222
201
  readonly enabled: "启用";
223
202
  readonly readyState: "已就绪";
224
203
  readonly setupRequired: "需要完成配置";
@@ -271,11 +250,8 @@ export declare const PAGE_TEXTS: {
271
250
  readonly codexCli: "Codex CLI 路径";
272
251
  readonly codebuddyCli: "CodeBuddy CLI 路径";
273
252
  readonly codexProxy: "Codex 代理";
274
- readonly claudeTimeout: "Claude 超时(毫秒)";
275
253
  readonly claudeConfigPath: "配置文件位置";
276
254
  readonly claudeProxy: "代理(可选)";
277
- readonly codexTimeout: "Codex 超时(毫秒)";
278
- readonly codebuddyTimeout: "CodeBuddy 超时(毫秒)";
279
255
  readonly hookPort: "Hook 端口";
280
256
  readonly logLevel: "日志级别";
281
257
  readonly logLevelDefault: "default(程序默认)";
@@ -308,28 +284,10 @@ export declare const PAGE_TEXTS: {
308
284
  readonly saveBtn: "保存";
309
285
  readonly jsonValid: "JSON 有效";
310
286
  readonly jsonInvalid: "JSON 无效:{error}";
311
- readonly wizardTitle: "首次使用引导";
312
- readonly wizardStep1Title: "接入一个 IM 渠道";
313
- readonly wizardStep1Desc: "在下方启用至少一个平台,并填写所有必填项。有条件时用「校验配置」测试凭证。";
314
- readonly wizardStep2Title: "设置默认 AI 工具";
315
- readonly wizardStep2Desc: "Claude SDK:在左侧栏「配置文件」编辑 ~/.claude/settings.json。Codex / CodeBuddy:在 AI 区填 CLI 路径。";
316
- readonly wizardStep3Title: "校验并保存";
317
- readonly wizardStep3Desc: "先点「校验」,再点「保存配置」。按顶部提示修复错误。";
318
- readonly wizardStep4Title: "启动桥接";
319
- readonly wizardStep4Desc: "到「服务」区点「启动桥接」。若马上退出,查 ~/.open-im/logs 日志。";
320
- readonly wizardStatusDone: "已完成";
321
- readonly wizardStatusTodo: "待完成";
322
- readonly wizardJumpPlatforms: "打开平台配置";
323
- readonly wizardJumpAi: "打开 AI 配置";
324
- readonly wizardJumpService: "打开服务控制";
325
287
  readonly validationNoPlatformEnabled: "保存前请至少启用一个 IM 平台,并填完必填凭证。";
326
288
  readonly validationPlatformIncomplete: "平台「{platform}」已启用,但以下必填项为空:{fields}";
327
289
  readonly validationAiCodexNoCli: "默认 AI 为 Codex,但 Codex CLI 路径为空。请在 AI 区填写,或改默认工具。";
328
290
  readonly validationAiCodebuddyNoCli: "默认 AI 为 CodeBuddy,但 CodeBuddy CLI 路径为空。请在 AI 区填写,或改默认工具。";
329
- readonly onboardingTitle: "欢迎使用 open-im";
330
- readonly onboardingDismiss: "知道了";
331
- readonly onboardingReadme: "README(部署说明)";
332
- readonly onboardingBody: "<p><strong>open-im</strong> 在本机把 Telegram、飞书、QQ、企微、钉钉、WorkBuddy 等渠道连到 Claude / Codex / CodeBuddy。</p><ol style=\"margin:12px 0 12px 18px;line-height:1.65\"><li>在<strong>平台配置</strong>选一个聊天应用,按字段下方提示填凭证。</li><li>在<strong>AI 工具配置</strong>设默认 AI;用 Claude SDK 时在左侧<strong>配置文件</strong>分区编辑<strong>~/.claude/settings.json</strong>。</li><li>同一<strong>配置文件</strong>分区可编辑<strong>~/.open-im/config.json</strong>。</li><li>先<strong>校验</strong>再<strong>保存配置</strong>,然后到<strong>服务</strong>启动桥接。</li><li>也可在终端运行 <code style=\"background:var(--bg-tertiary);padding:2px 6px;border-radius:4px\">open-im init</code> 交互配置。</li></ol>";
333
291
  readonly tipTelegramToken: "在 Telegram 搜 <a href=\"https://t.me/BotFather\" target=\"_blank\" rel=\"noopener\">@BotFather</a>,发 /newbot 创建机器人后复制 Token。";
334
292
  readonly tipFeishuAppId: "飞书开放平台 → 应用 → 凭证与基础信息 → App ID。";
335
293
  readonly tipFeishuSecret: "同一页 App Secret(可重置后查看)。";
@@ -15,7 +15,7 @@ export const PAGE_TEXTS = {
15
15
  mode: "Flow",
16
16
  dashboardTitle: "Dashboard",
17
17
  dashboardSubtitle: "Platform health status",
18
- dashboardSubtitleFull: "Platform status and setup progress",
18
+ dashboardSubtitleFull: "Platform and service status",
19
19
  quickActionsTitle: "Quick Actions",
20
20
  serviceTitle: "Service Control",
21
21
  serviceHint: "Validate, save, start, and stop the local bridge from one place.",
@@ -47,7 +47,7 @@ export const PAGE_TEXTS = {
47
47
  openImConfigCardHint: "Full open-im configuration. Use Format, then Save. Invalid JSON is rejected.",
48
48
  claudeSettingsCardHint: "Claude SDK environment (ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, ANTHROPIC_MODEL, etc.). Set API access here without shell exports.",
49
49
  claudeJsonShortcutHint: "Edit ~/.claude/settings.json in the sidebar «Config files» section below.",
50
- platformsHint: "Follow the setup checklist on Overview first. Disabled platforms still keep saved values.",
50
+ platformsHint: "Disabled platforms keep their saved values.",
51
51
  enabled: "Enabled",
52
52
  readyState: "Ready",
53
53
  setupRequired: "Setup required",
@@ -101,14 +101,11 @@ export const PAGE_TEXTS = {
101
101
  codexCli: "Codex CLI path",
102
102
  codebuddyCli: "CodeBuddy CLI path",
103
103
  codexProxy: "Codex proxy",
104
- claudeTimeout: "Claude timeout (ms)",
105
104
  claudeConfigPath: "Config file location",
106
105
  claudeAuthToken: "ANTHROPIC_AUTH_TOKEN",
107
106
  claudeBaseUrl: "ANTHROPIC_BASE_URL",
108
107
  claudeModel: "ANTHROPIC_MODEL",
109
108
  claudeProxy: "Proxy (optional)",
110
- codexTimeout: "Codex timeout (ms)",
111
- codebuddyTimeout: "CodeBuddy timeout (ms)",
112
109
  hookPort: "Hook port",
113
110
  logLevel: "Log level",
114
111
  logLevelDefault: "default (app default)",
@@ -141,28 +138,10 @@ export const PAGE_TEXTS = {
141
138
  saveBtn: "Save",
142
139
  jsonValid: "Valid JSON",
143
140
  jsonInvalid: "Invalid JSON: {error}",
144
- wizardTitle: "First-time setup",
145
- wizardStep1Title: "Connect an IM channel",
146
- wizardStep1Desc: "Enable at least one platform below and fill every required field. Use Check config when available.",
147
- wizardStep2Title: "Set the default AI tool",
148
- wizardStep2Desc: "Claude SDK: edit ~/.claude/settings.json under sidebar Config files. Codex / CodeBuddy: set the CLI path in the AI section.",
149
- wizardStep3Title: "Validate and save",
150
- wizardStep3Desc: "Click Validate, then Save config. Fix any errors shown in the banner above.",
151
- wizardStep4Title: "Start the bridge",
152
- wizardStep4Desc: "Open Service and click Start bridge. If it exits, read ~/.open-im/logs.",
153
- wizardStatusDone: "Done",
154
- wizardStatusTodo: "To do",
155
- wizardJumpPlatforms: "Open Platforms",
156
- wizardJumpAi: "Open AI",
157
- wizardJumpService: "Open Service",
158
141
  validationNoPlatformEnabled: "Enable at least one IM platform and fill its required credentials before saving.",
159
142
  validationPlatformIncomplete: "Platform \"{platform}\" is enabled but these required fields are empty: {fields}",
160
143
  validationAiCodexNoCli: "Default AI is Codex but Codex CLI path is empty. Set it under AI Tooling or change the default tool.",
161
144
  validationAiCodebuddyNoCli: "Default AI is CodeBuddy but CodeBuddy CLI path is empty. Set it under AI Tooling or change the default tool.",
162
- onboardingTitle: "Welcome to open-im",
163
- onboardingDismiss: "Got it",
164
- onboardingReadme: "README (setup)",
165
- onboardingBody: "<p><strong>open-im</strong> bridges Telegram, Feishu, QQ, WeWork, DingTalk, and WorkBuddy to Claude / Codex / CodeBuddy on your machine.</p><ol style=\"margin:12px 0 12px 18px;line-height:1.65\"><li>Pick <strong>one</strong> chat app in <strong>Platforms</strong> and paste credentials (see hints under each field).</li><li>Set the <strong>default AI</strong> under AI Tooling; for Claude SDK, put API keys in sidebar <strong>Config files</strong> → <strong>~/.claude/settings.json</strong>.</li><li>Edit <strong>~/.open-im/config.json</strong> in the same <strong>Config files</strong> section when you need raw JSON.</li><li>Use <strong>Validate</strong> then <strong>Save config</strong>, then <strong>Start bridge</strong> under Service.</li><li>CLI alternative: run <code style=\"background:var(--bg-tertiary);padding:2px 6px;border-radius:4px\">open-im init</code> in a terminal.</li></ol>",
166
145
  tipTelegramToken: 'From Telegram, open <a href="https://t.me/BotFather" target="_blank" rel="noopener">@BotFather</a> → /newbot → copy the token.',
167
146
  tipFeishuAppId: "Feishu Open Platform → your app → Credentials → App ID.",
168
147
  tipFeishuSecret: "Same page → App Secret (click show / reset if needed).",
@@ -188,7 +167,7 @@ export const PAGE_TEXTS = {
188
167
  mode: "\u6a21\u5f0f",
189
168
  dashboardTitle: "\u6982\u89c8",
190
169
  dashboardSubtitle: "\u5e73\u53f0\u5065\u5eb7\u72b6\u6001",
191
- dashboardSubtitleFull: "\u5e73\u53f0\u72b6\u6001\u4e0e\u63a5\u5165\u8fdb\u5ea6",
170
+ dashboardSubtitleFull: "\u5e73\u53f0\u4e0e\u670d\u52a1\u72b6\u6001",
192
171
  quickActionsTitle: "\u5feb\u6377\u64cd\u4f5c",
193
172
  refreshHealth: "\u5237\u65b0\u5065\u5eb7\u72b6\u6001",
194
173
  viewConfig: "\u67e5\u770b\u914d\u7f6e",
@@ -218,7 +197,7 @@ export const PAGE_TEXTS = {
218
197
  openImConfigCardHint: "open-im \u5b8c\u6574\u914d\u7f6e\u3002\u5148\u683c\u5f0f\u5316\u518d\u4fdd\u5b58\uff1bJSON \u4e0d\u5408\u6cd5\u65f6\u65e0\u6cd5\u5199\u5165\u3002",
219
198
  claudeSettingsCardHint: "Claude SDK \u73af\u5883\u53d8\u91cf\uff08ANTHROPIC_API_KEY\u3001ANTHROPIC_BASE_URL\u3001ANTHROPIC_MODEL \u7b49\uff09\u3002\u5728\u6b64\u914d\u7f6e API\uff0c\u65e0\u9700\u5728\u7ec8\u7aef export\u3002",
220
199
  claudeJsonShortcutHint: "\u63d0\u793a\uff1a\u8bf7\u5728\u5de6\u4fa7\u680f\u300c\u914d\u7f6e\u6587\u4ef6\u300d\u5206\u533a\u7f16\u8f91 ~/.claude/settings.json\u3002",
221
- platformsHint: "\u5efa\u8bae\u5148\u5728\u6982\u89c8\u9875\u6309\u5f15\u5bfc\u6b65\u9aa4\u64cd\u4f5c\u3002\u7981\u7528\u7684\u5e73\u53f0\u4ecd\u4fdd\u7559\u5df2\u4fdd\u5b58\u7684\u503c\u3002",
200
+ platformsHint: "\u7981\u7528\u7684\u5e73\u53f0\u4ecd\u4fdd\u7559\u5df2\u4fdd\u5b58\u7684\u503c\u3002",
222
201
  enabled: "\u542f\u7528",
223
202
  readyState: "\u5df2\u5c31\u7eea",
224
203
  setupRequired: "\u9700\u8981\u5b8c\u6210\u914d\u7f6e",
@@ -271,11 +250,8 @@ export const PAGE_TEXTS = {
271
250
  codexCli: "Codex CLI \u8def\u5f84",
272
251
  codebuddyCli: "CodeBuddy CLI \u8def\u5f84",
273
252
  codexProxy: "Codex \u4ee3\u7406",
274
- claudeTimeout: "Claude \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
275
253
  claudeConfigPath: "\u914d\u7f6e\u6587\u4ef6\u4f4d\u7f6e",
276
254
  claudeProxy: "\u4ee3\u7406\uff08\u53ef\u9009\uff09",
277
- codexTimeout: "Codex \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
278
- codebuddyTimeout: "CodeBuddy \u8d85\u65f6\uff08\u6beb\u79d2\uff09",
279
255
  hookPort: "Hook \u7aef\u53e3",
280
256
  logLevel: "\u65e5\u5fd7\u7ea7\u522b",
281
257
  logLevelDefault: "default\uff08\u7a0b\u5e8f\u9ed8\u8ba4\uff09",
@@ -308,28 +284,10 @@ export const PAGE_TEXTS = {
308
284
  saveBtn: "\u4fdd\u5b58",
309
285
  jsonValid: "JSON \u6709\u6548",
310
286
  jsonInvalid: "JSON \u65e0\u6548\uff1a{error}",
311
- wizardTitle: "\u9996\u6b21\u4f7f\u7528\u5f15\u5bfc",
312
- wizardStep1Title: "\u63a5\u5165\u4e00\u4e2a IM \u6e20\u9053",
313
- wizardStep1Desc: "\u5728\u4e0b\u65b9\u542f\u7528\u81f3\u5c11\u4e00\u4e2a\u5e73\u53f0\uff0c\u5e76\u586b\u5199\u6240\u6709\u5fc5\u586b\u9879\u3002\u6709\u6761\u4ef6\u65f6\u7528\u300c\u6821\u9a8c\u914d\u7f6e\u300d\u6d4b\u8bd5\u51ed\u8bc1\u3002",
314
- wizardStep2Title: "\u8bbe\u7f6e\u9ed8\u8ba4 AI \u5de5\u5177",
315
- wizardStep2Desc: "Claude SDK\uff1a\u5728\u5de6\u4fa7\u680f\u300c\u914d\u7f6e\u6587\u4ef6\u300d\u7f16\u8f91 ~/.claude/settings.json\u3002Codex / CodeBuddy\uff1a\u5728 AI \u533a\u586b CLI \u8def\u5f84\u3002",
316
- wizardStep3Title: "\u6821\u9a8c\u5e76\u4fdd\u5b58",
317
- wizardStep3Desc: "\u5148\u70b9\u300c\u6821\u9a8c\u300d\uff0c\u518d\u70b9\u300c\u4fdd\u5b58\u914d\u7f6e\u300d\u3002\u6309\u9876\u90e8\u63d0\u793a\u4fee\u590d\u9519\u8bef\u3002",
318
- wizardStep4Title: "\u542f\u52a8\u6865\u63a5",
319
- wizardStep4Desc: "\u5230\u300c\u670d\u52a1\u300d\u533a\u70b9\u300c\u542f\u52a8\u6865\u63a5\u300d\u3002\u82e5\u9a6c\u4e0a\u9000\u51fa\uff0c\u67e5 ~/.open-im/logs \u65e5\u5fd7\u3002",
320
- wizardStatusDone: "\u5df2\u5b8c\u6210",
321
- wizardStatusTodo: "\u5f85\u5b8c\u6210",
322
- wizardJumpPlatforms: "\u6253\u5f00\u5e73\u53f0\u914d\u7f6e",
323
- wizardJumpAi: "\u6253\u5f00 AI \u914d\u7f6e",
324
- wizardJumpService: "\u6253\u5f00\u670d\u52a1\u63a7\u5236",
325
287
  validationNoPlatformEnabled: "\u4fdd\u5b58\u524d\u8bf7\u81f3\u5c11\u542f\u7528\u4e00\u4e2a IM \u5e73\u53f0\uff0c\u5e76\u586b\u5b8c\u5fc5\u586b\u51ed\u8bc1\u3002",
326
288
  validationPlatformIncomplete: "\u5e73\u53f0\u300c{platform}\u300d\u5df2\u542f\u7528\uff0c\u4f46\u4ee5\u4e0b\u5fc5\u586b\u9879\u4e3a\u7a7a\uff1a{fields}",
327
289
  validationAiCodexNoCli: "\u9ed8\u8ba4 AI \u4e3a Codex\uff0c\u4f46 Codex CLI \u8def\u5f84\u4e3a\u7a7a\u3002\u8bf7\u5728 AI \u533a\u586b\u5199\uff0c\u6216\u6539\u9ed8\u8ba4\u5de5\u5177\u3002",
328
290
  validationAiCodebuddyNoCli: "\u9ed8\u8ba4 AI \u4e3a CodeBuddy\uff0c\u4f46 CodeBuddy CLI \u8def\u5f84\u4e3a\u7a7a\u3002\u8bf7\u5728 AI \u533a\u586b\u5199\uff0c\u6216\u6539\u9ed8\u8ba4\u5de5\u5177\u3002",
329
- onboardingTitle: "\u6b22\u8fce\u4f7f\u7528 open-im",
330
- onboardingDismiss: "\u77e5\u9053\u4e86",
331
- onboardingReadme: "README\uff08\u90e8\u7f72\u8bf4\u660e\uff09",
332
- onboardingBody: "<p><strong>open-im</strong> \u5728\u672c\u673a\u628a Telegram\u3001\u98de\u4e66\u3001QQ\u3001\u4f01\u5fae\u3001\u9489\u9489\u3001WorkBuddy \u7b49\u6e20\u9053\u8fde\u5230 Claude / Codex / CodeBuddy\u3002</p><ol style=\"margin:12px 0 12px 18px;line-height:1.65\"><li>\u5728<strong>\u5e73\u53f0\u914d\u7f6e</strong>\u9009\u4e00\u4e2a\u804a\u5929\u5e94\u7528\uff0c\u6309\u5b57\u6bb5\u4e0b\u65b9\u63d0\u793a\u586b\u51ed\u8bc1\u3002</li><li>\u5728<strong>AI \u5de5\u5177\u914d\u7f6e</strong>\u8bbe\u9ed8\u8ba4 AI\uff1b\u7528 Claude SDK \u65f6\u5728\u5de6\u4fa7<strong>\u914d\u7f6e\u6587\u4ef6</strong>\u5206\u533a\u7f16\u8f91<strong>~/.claude/settings.json</strong>\u3002</li><li>\u540c\u4e00<strong>\u914d\u7f6e\u6587\u4ef6</strong>\u5206\u533a\u53ef\u7f16\u8f91<strong>~/.open-im/config.json</strong>\u3002</li><li>\u5148<strong>\u6821\u9a8c</strong>\u518d<strong>\u4fdd\u5b58\u914d\u7f6e</strong>\uff0c\u7136\u540e\u5230<strong>\u670d\u52a1</strong>\u542f\u52a8\u6865\u63a5\u3002</li><li>\u4e5f\u53ef\u5728\u7ec8\u7aef\u8fd0\u884c <code style=\"background:var(--bg-tertiary);padding:2px 6px;border-radius:4px\">open-im init</code> \u4ea4\u4e92\u914d\u7f6e\u3002</li></ol>",
333
291
  tipTelegramToken: '\u5728 Telegram \u641c <a href="https://t.me/BotFather" target="_blank" rel="noopener">@BotFather</a>\uff0c\u53d1 /newbot \u521b\u5efa\u673a\u5668\u4eba\u540e\u590d\u5236 Token\u3002',
334
292
  tipFeishuAppId: "\u98de\u4e66\u5f00\u653e\u5e73\u53f0 \u2192 \u5e94\u7528 \u2192 \u51ed\u8bc1\u4e0e\u57fa\u7840\u4fe1\u606f \u2192 App ID\u3002",
335
293
  tipFeishuSecret: "\u540c\u4e00\u9875 App Secret\uff08\u53ef\u91cd\u7f6e\u540e\u67e5\u770b\uff09\u3002",