@wu529778790/open-im 1.9.3-beta.10 → 1.9.3-beta.12

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.
@@ -8,13 +8,14 @@ export declare const PAGE_TEXTS: {
8
8
  readonly heroKicker: "Local AI bridge";
9
9
  readonly langButton: "中文";
10
10
  readonly darkModeToggle: "Toggle dark mode";
11
+ readonly headerToolbarAria: "Bridge: validate, save, start, stop";
11
12
  readonly controlCenter: "Control center";
12
13
  readonly sidebarNoteTitle: "Local workflow";
13
14
  readonly sidebarNoteBody: "Configure at least one platform, save the config, then start the bridge from Service.";
14
15
  readonly mode: "Flow";
15
16
  readonly dashboardTitle: "Dashboard";
16
17
  readonly dashboardSubtitle: "Platform health status";
17
- readonly dashboardSubtitleFull: "Platform status and setup progress";
18
+ readonly dashboardSubtitleFull: "Platform and service status";
18
19
  readonly quickActionsTitle: "Quick Actions";
19
20
  readonly serviceTitle: "Service Control";
20
21
  readonly serviceHint: "Validate, save, start, and stop the local bridge from one place.";
@@ -46,7 +47,7 @@ export declare const PAGE_TEXTS: {
46
47
  readonly openImConfigCardHint: "Full open-im configuration. Use Format, then Save. Invalid JSON is rejected.";
47
48
  readonly claudeSettingsCardHint: "Claude SDK environment (ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, ANTHROPIC_MODEL, etc.). Set API access here without shell exports.";
48
49
  readonly claudeJsonShortcutHint: "Edit ~/.claude/settings.json in the sidebar «Config files» section below.";
49
- readonly platformsHint: "Follow the setup checklist on Overview first. Disabled platforms still keep saved values.";
50
+ readonly platformsHint: "Disabled platforms keep their saved values.";
50
51
  readonly enabled: "Enabled";
51
52
  readonly readyState: "Ready";
52
53
  readonly setupRequired: "Setup required";
@@ -140,28 +141,10 @@ export declare const PAGE_TEXTS: {
140
141
  readonly saveBtn: "Save";
141
142
  readonly jsonValid: "Valid JSON";
142
143
  readonly jsonInvalid: "Invalid JSON: {error}";
143
- readonly wizardTitle: "First-time setup";
144
- readonly wizardStep1Title: "Connect an IM channel";
145
- readonly wizardStep1Desc: "Enable at least one platform below and fill every required field. Use Check config when available.";
146
- readonly wizardStep2Title: "Set the default AI tool";
147
- readonly wizardStep2Desc: "Claude SDK: edit ~/.claude/settings.json under sidebar Config files. Codex / CodeBuddy: set the CLI path in the AI section.";
148
- readonly wizardStep3Title: "Validate and save";
149
- readonly wizardStep3Desc: "Click Validate, then Save config. Fix any errors shown in the banner above.";
150
- readonly wizardStep4Title: "Start the bridge";
151
- readonly wizardStep4Desc: "Open Service and click Start bridge. If it exits, read ~/.open-im/logs.";
152
- readonly wizardStatusDone: "Done";
153
- readonly wizardStatusTodo: "To do";
154
- readonly wizardJumpPlatforms: "Open Platforms";
155
- readonly wizardJumpAi: "Open AI";
156
- readonly wizardJumpService: "Open Service";
157
144
  readonly validationNoPlatformEnabled: "Enable at least one IM platform and fill its required credentials before saving.";
158
145
  readonly validationPlatformIncomplete: "Platform \"{platform}\" is enabled but these required fields are empty: {fields}";
159
146
  readonly validationAiCodexNoCli: "Default AI is Codex but Codex CLI path is empty. Set it under AI Tooling or change the default tool.";
160
147
  readonly validationAiCodebuddyNoCli: "Default AI is CodeBuddy but CodeBuddy CLI path is empty. Set it under AI Tooling or change the default tool.";
161
- readonly onboardingTitle: "Welcome to open-im";
162
- readonly onboardingDismiss: "Got it";
163
- readonly onboardingReadme: "README (setup)";
164
- 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>";
165
148
  readonly tipTelegramToken: "From Telegram, open <a href=\"https://t.me/BotFather\" target=\"_blank\" rel=\"noopener\">@BotFather</a> → /newbot → copy the token.";
166
149
  readonly tipFeishuAppId: "Feishu Open Platform → your app → Credentials → App ID.";
167
150
  readonly tipFeishuSecret: "Same page → App Secret (click show / reset if needed).";
@@ -180,13 +163,14 @@ export declare const PAGE_TEXTS: {
180
163
  readonly heroKicker: "本地 AI 桥接";
181
164
  readonly langButton: "EN";
182
165
  readonly darkModeToggle: "切换暗黑模式";
166
+ readonly headerToolbarAria: "桥接:校验、保存、启动、停止";
183
167
  readonly controlCenter: "控制中心";
184
168
  readonly sidebarNoteTitle: "本地工作流";
185
169
  readonly sidebarNoteBody: "至少配置一个平台,保存配置,然后在服务控制区启动桥接。";
186
170
  readonly mode: "模式";
187
171
  readonly dashboardTitle: "概览";
188
172
  readonly dashboardSubtitle: "平台健康状态";
189
- readonly dashboardSubtitleFull: "平台状态与接入进度";
173
+ readonly dashboardSubtitleFull: "平台与服务状态";
190
174
  readonly quickActionsTitle: "快捷操作";
191
175
  readonly refreshHealth: "刷新健康状态";
192
176
  readonly viewConfig: "查看配置";
@@ -216,7 +200,7 @@ export declare const PAGE_TEXTS: {
216
200
  readonly openImConfigCardHint: "open-im 完整配置。先格式化再保存;JSON 不合法时无法写入。";
217
201
  readonly claudeSettingsCardHint: "Claude SDK 环境变量(ANTHROPIC_API_KEY、ANTHROPIC_BASE_URL、ANTHROPIC_MODEL 等)。在此配置 API,无需在终端 export。";
218
202
  readonly claudeJsonShortcutHint: "提示:请在左侧栏「配置文件」分区编辑 ~/.claude/settings.json。";
219
- readonly platformsHint: "建议先在概览页按引导步骤操作。禁用的平台仍保留已保存的值。";
203
+ readonly platformsHint: "禁用的平台仍保留已保存的值。";
220
204
  readonly enabled: "启用";
221
205
  readonly readyState: "已就绪";
222
206
  readonly setupRequired: "需要完成配置";
@@ -306,28 +290,10 @@ export declare const PAGE_TEXTS: {
306
290
  readonly saveBtn: "保存";
307
291
  readonly jsonValid: "JSON 有效";
308
292
  readonly jsonInvalid: "JSON 无效:{error}";
309
- readonly wizardTitle: "首次使用引导";
310
- readonly wizardStep1Title: "接入一个 IM 渠道";
311
- readonly wizardStep1Desc: "在下方启用至少一个平台,并填写所有必填项。有条件时用「校验配置」测试凭证。";
312
- readonly wizardStep2Title: "设置默认 AI 工具";
313
- readonly wizardStep2Desc: "Claude SDK:在左侧栏「配置文件」编辑 ~/.claude/settings.json。Codex / CodeBuddy:在 AI 区填 CLI 路径。";
314
- readonly wizardStep3Title: "校验并保存";
315
- readonly wizardStep3Desc: "先点「校验」,再点「保存配置」。按顶部提示修复错误。";
316
- readonly wizardStep4Title: "启动桥接";
317
- readonly wizardStep4Desc: "到「服务」区点「启动桥接」。若马上退出,查 ~/.open-im/logs 日志。";
318
- readonly wizardStatusDone: "已完成";
319
- readonly wizardStatusTodo: "待完成";
320
- readonly wizardJumpPlatforms: "打开平台配置";
321
- readonly wizardJumpAi: "打开 AI 配置";
322
- readonly wizardJumpService: "打开服务控制";
323
293
  readonly validationNoPlatformEnabled: "保存前请至少启用一个 IM 平台,并填完必填凭证。";
324
294
  readonly validationPlatformIncomplete: "平台「{platform}」已启用,但以下必填项为空:{fields}";
325
295
  readonly validationAiCodexNoCli: "默认 AI 为 Codex,但 Codex CLI 路径为空。请在 AI 区填写,或改默认工具。";
326
296
  readonly validationAiCodebuddyNoCli: "默认 AI 为 CodeBuddy,但 CodeBuddy CLI 路径为空。请在 AI 区填写,或改默认工具。";
327
- readonly onboardingTitle: "欢迎使用 open-im";
328
- readonly onboardingDismiss: "知道了";
329
- readonly onboardingReadme: "README(部署说明)";
330
- 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>";
331
297
  readonly tipTelegramToken: "在 Telegram 搜 <a href=\"https://t.me/BotFather\" target=\"_blank\" rel=\"noopener\">@BotFather</a>,发 /newbot 创建机器人后复制 Token。";
332
298
  readonly tipFeishuAppId: "飞书开放平台 → 应用 → 凭证与基础信息 → App ID。";
333
299
  readonly tipFeishuSecret: "同一页 App Secret(可重置后查看)。";
@@ -8,13 +8,14 @@ export const PAGE_TEXTS = {
8
8
  heroKicker: "Local AI bridge",
9
9
  langButton: "\u4e2d\u6587",
10
10
  darkModeToggle: "Toggle dark mode",
11
+ headerToolbarAria: "Bridge: validate, save, start, stop",
11
12
  controlCenter: "Control center",
12
13
  sidebarNoteTitle: "Local workflow",
13
14
  sidebarNoteBody: "Configure at least one platform, save the config, then start the bridge from Service.",
14
15
  mode: "Flow",
15
16
  dashboardTitle: "Dashboard",
16
17
  dashboardSubtitle: "Platform health status",
17
- dashboardSubtitleFull: "Platform status and setup progress",
18
+ dashboardSubtitleFull: "Platform and service status",
18
19
  quickActionsTitle: "Quick Actions",
19
20
  serviceTitle: "Service Control",
20
21
  serviceHint: "Validate, save, start, and stop the local bridge from one place.",
@@ -46,7 +47,7 @@ export const PAGE_TEXTS = {
46
47
  openImConfigCardHint: "Full open-im configuration. Use Format, then Save. Invalid JSON is rejected.",
47
48
  claudeSettingsCardHint: "Claude SDK environment (ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, ANTHROPIC_MODEL, etc.). Set API access here without shell exports.",
48
49
  claudeJsonShortcutHint: "Edit ~/.claude/settings.json in the sidebar «Config files» section below.",
49
- platformsHint: "Follow the setup checklist on Overview first. Disabled platforms still keep saved values.",
50
+ platformsHint: "Disabled platforms keep their saved values.",
50
51
  enabled: "Enabled",
51
52
  readyState: "Ready",
52
53
  setupRequired: "Setup required",
@@ -140,28 +141,10 @@ export const PAGE_TEXTS = {
140
141
  saveBtn: "Save",
141
142
  jsonValid: "Valid JSON",
142
143
  jsonInvalid: "Invalid JSON: {error}",
143
- wizardTitle: "First-time setup",
144
- wizardStep1Title: "Connect an IM channel",
145
- wizardStep1Desc: "Enable at least one platform below and fill every required field. Use Check config when available.",
146
- wizardStep2Title: "Set the default AI tool",
147
- wizardStep2Desc: "Claude SDK: edit ~/.claude/settings.json under sidebar Config files. Codex / CodeBuddy: set the CLI path in the AI section.",
148
- wizardStep3Title: "Validate and save",
149
- wizardStep3Desc: "Click Validate, then Save config. Fix any errors shown in the banner above.",
150
- wizardStep4Title: "Start the bridge",
151
- wizardStep4Desc: "Open Service and click Start bridge. If it exits, read ~/.open-im/logs.",
152
- wizardStatusDone: "Done",
153
- wizardStatusTodo: "To do",
154
- wizardJumpPlatforms: "Open Platforms",
155
- wizardJumpAi: "Open AI",
156
- wizardJumpService: "Open Service",
157
144
  validationNoPlatformEnabled: "Enable at least one IM platform and fill its required credentials before saving.",
158
145
  validationPlatformIncomplete: "Platform \"{platform}\" is enabled but these required fields are empty: {fields}",
159
146
  validationAiCodexNoCli: "Default AI is Codex but Codex CLI path is empty. Set it under AI Tooling or change the default tool.",
160
147
  validationAiCodebuddyNoCli: "Default AI is CodeBuddy but CodeBuddy CLI path is empty. Set it under AI Tooling or change the default tool.",
161
- onboardingTitle: "Welcome to open-im",
162
- onboardingDismiss: "Got it",
163
- onboardingReadme: "README (setup)",
164
- 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>",
165
148
  tipTelegramToken: 'From Telegram, open <a href="https://t.me/BotFather" target="_blank" rel="noopener">@BotFather</a> → /newbot → copy the token.',
166
149
  tipFeishuAppId: "Feishu Open Platform → your app → Credentials → App ID.",
167
150
  tipFeishuSecret: "Same page → App Secret (click show / reset if needed).",
@@ -180,13 +163,14 @@ export const PAGE_TEXTS = {
180
163
  heroKicker: "\u672c\u5730 AI \u6865\u63a5",
181
164
  langButton: "EN",
182
165
  darkModeToggle: "\u5207\u6362\u6697\u9ed1\u6a21\u5f0f",
166
+ headerToolbarAria: "\u6865\u63a5\uff1a\u6821\u9a8c\u3001\u4fdd\u5b58\u3001\u542f\u52a8\u3001\u505c\u6b62",
183
167
  controlCenter: "\u63a7\u5236\u4e2d\u5fc3",
184
168
  sidebarNoteTitle: "\u672c\u5730\u5de5\u4f5c\u6d41",
185
169
  sidebarNoteBody: "\u81f3\u5c11\u914d\u7f6e\u4e00\u4e2a\u5e73\u53f0\uff0c\u4fdd\u5b58\u914d\u7f6e\uff0c\u7136\u540e\u5728\u670d\u52a1\u63a7\u5236\u533a\u542f\u52a8\u6865\u63a5\u3002",
186
170
  mode: "\u6a21\u5f0f",
187
171
  dashboardTitle: "\u6982\u89c8",
188
172
  dashboardSubtitle: "\u5e73\u53f0\u5065\u5eb7\u72b6\u6001",
189
- dashboardSubtitleFull: "\u5e73\u53f0\u72b6\u6001\u4e0e\u63a5\u5165\u8fdb\u5ea6",
173
+ dashboardSubtitleFull: "\u5e73\u53f0\u4e0e\u670d\u52a1\u72b6\u6001",
190
174
  quickActionsTitle: "\u5feb\u6377\u64cd\u4f5c",
191
175
  refreshHealth: "\u5237\u65b0\u5065\u5eb7\u72b6\u6001",
192
176
  viewConfig: "\u67e5\u770b\u914d\u7f6e",
@@ -216,7 +200,7 @@ export const PAGE_TEXTS = {
216
200
  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",
217
201
  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",
218
202
  claudeJsonShortcutHint: "\u63d0\u793a\uff1a\u8bf7\u5728\u5de6\u4fa7\u680f\u300c\u914d\u7f6e\u6587\u4ef6\u300d\u5206\u533a\u7f16\u8f91 ~/.claude/settings.json\u3002",
219
- 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",
203
+ platformsHint: "\u7981\u7528\u7684\u5e73\u53f0\u4ecd\u4fdd\u7559\u5df2\u4fdd\u5b58\u7684\u503c\u3002",
220
204
  enabled: "\u542f\u7528",
221
205
  readyState: "\u5df2\u5c31\u7eea",
222
206
  setupRequired: "\u9700\u8981\u5b8c\u6210\u914d\u7f6e",
@@ -306,28 +290,10 @@ export const PAGE_TEXTS = {
306
290
  saveBtn: "\u4fdd\u5b58",
307
291
  jsonValid: "JSON \u6709\u6548",
308
292
  jsonInvalid: "JSON \u65e0\u6548\uff1a{error}",
309
- wizardTitle: "\u9996\u6b21\u4f7f\u7528\u5f15\u5bfc",
310
- wizardStep1Title: "\u63a5\u5165\u4e00\u4e2a IM \u6e20\u9053",
311
- 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",
312
- wizardStep2Title: "\u8bbe\u7f6e\u9ed8\u8ba4 AI \u5de5\u5177",
313
- 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",
314
- wizardStep3Title: "\u6821\u9a8c\u5e76\u4fdd\u5b58",
315
- 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",
316
- wizardStep4Title: "\u542f\u52a8\u6865\u63a5",
317
- 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",
318
- wizardStatusDone: "\u5df2\u5b8c\u6210",
319
- wizardStatusTodo: "\u5f85\u5b8c\u6210",
320
- wizardJumpPlatforms: "\u6253\u5f00\u5e73\u53f0\u914d\u7f6e",
321
- wizardJumpAi: "\u6253\u5f00 AI \u914d\u7f6e",
322
- wizardJumpService: "\u6253\u5f00\u670d\u52a1\u63a7\u5236",
323
293
  validationNoPlatformEnabled: "\u4fdd\u5b58\u524d\u8bf7\u81f3\u5c11\u542f\u7528\u4e00\u4e2a IM \u5e73\u53f0\uff0c\u5e76\u586b\u5b8c\u5fc5\u586b\u51ed\u8bc1\u3002",
324
294
  validationPlatformIncomplete: "\u5e73\u53f0\u300c{platform}\u300d\u5df2\u542f\u7528\uff0c\u4f46\u4ee5\u4e0b\u5fc5\u586b\u9879\u4e3a\u7a7a\uff1a{fields}",
325
295
  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",
326
296
  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",
327
- onboardingTitle: "\u6b22\u8fce\u4f7f\u7528 open-im",
328
- onboardingDismiss: "\u77e5\u9053\u4e86",
329
- onboardingReadme: "README\uff08\u90e8\u7f72\u8bf4\u660e\uff09",
330
- 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>",
331
297
  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',
332
298
  tipFeishuAppId: "\u98de\u4e66\u5f00\u653e\u5e73\u53f0 \u2192 \u5e94\u7528 \u2192 \u51ed\u8bc1\u4e0e\u57fa\u7840\u4fe1\u606f \u2192 App ID\u3002",
333
299
  tipFeishuSecret: "\u540c\u4e00\u9875 App Secret\uff08\u53ef\u91cd\u7f6e\u540e\u67e5\u770b\uff09\u3002",
@@ -10,8 +10,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
10
10
  const aiTools = ["claude", "codex", "codebuddy"];
11
11
  const STORAGE_KEY_LANG = "open-im-web-lang";
12
12
  const STORAGE_KEY_DARK_MODE = "open-im-web-dark-mode";
13
- const STORAGE_KEY_ONBOARDING = "open-im-dashboard-onboarding-v1";
14
- const STORAGE_KEY_SAVED_SESSION = "open-im-setup-saved-session";
15
13
  const POLLING_INTERVAL = 10000;
16
14
  const toolLabels = { claude: "Claude", codex: "Codex", codebuddy: "CodeBuddy" };
17
15
 
@@ -107,7 +105,17 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
107
105
 
108
106
  // Button state
109
107
  const setBusy = (busy) => {
110
- ["validateButton","saveButton","startButton","stopButton","langButton"].forEach((id) => {
108
+ [
109
+ "validateButton",
110
+ "saveButton",
111
+ "startButton",
112
+ "stopButton",
113
+ "headerValidateButton",
114
+ "headerSaveButton",
115
+ "headerStartButton",
116
+ "headerStopButton",
117
+ "langButton",
118
+ ].forEach((id) => {
111
119
  const node = el(id);
112
120
  if (node) node.disabled = busy;
113
121
  });
@@ -146,7 +154,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
146
154
  const LANGUAGE_UPDATES = {
147
155
  simpleText: [
148
156
  { id: "mainTitle", key: "dashboardTitle" },
149
- { id: "mainSubtitle", key: "dashboardSubtitleFull" },
150
157
  { id: "navOverviewText", key: "dashboardTitle" },
151
158
  { id: "navPlatformsText", key: "platformsTitle" },
152
159
  { id: "navConfigFilesText", key: "navConfigFiles" },
@@ -175,22 +182,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
175
182
  { id: "resetJsonButtonText", key: "resetJson" },
176
183
  { id: "saveClaudeSettingsBtnText", key: "saveBtn" },
177
184
  { id: "saveOpenImConfigBtnText", key: "saveBtn" },
178
- { id: "wizardTitle", key: "wizardTitle" },
179
- { id: "wizardStep1Title", key: "wizardStep1Title" },
180
- { id: "wizardStep1Desc", key: "wizardStep1Desc" },
181
- { id: "wizardStep2Title", key: "wizardStep2Title" },
182
- { id: "wizardStep2Desc", key: "wizardStep2Desc" },
183
- { id: "wizardStep3Title", key: "wizardStep3Title" },
184
- { id: "wizardStep3Desc", key: "wizardStep3Desc" },
185
- { id: "wizardStep4Title", key: "wizardStep4Title" },
186
- { id: "wizardStep4Desc", key: "wizardStep4Desc" },
187
- { id: "wizardJumpPlatforms", key: "wizardJumpPlatforms" },
188
- { id: "wizardJumpAi", key: "wizardJumpAi" },
189
- { id: "wizardJumpService", key: "wizardJumpService" },
190
- { id: "wizardJumpService2", key: "wizardJumpService" },
191
- { id: "onboardingTitle", key: "onboardingTitle" },
192
- { id: "onboardingDismiss", key: "onboardingDismiss" },
193
- { id: "onboardingReadme", key: "onboardingReadme" },
194
185
  ],
195
186
  platformLabels: {
196
187
  enabled: { suffix: "-label", key: "enabled" },
@@ -254,6 +245,10 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
254
245
  { id: "saveButton", key: "save" },
255
246
  { id: "startButton", key: "start" },
256
247
  { id: "stopButton", key: "stop" },
248
+ { id: "headerValidateButton", key: "validate" },
249
+ { id: "headerSaveButton", key: "save" },
250
+ { id: "headerStartButton", key: "start" },
251
+ { id: "headerStopButton", key: "stop" },
257
252
  ],
258
253
  testButtons: [
259
254
  { prefix: "test-", key: "test" },
@@ -314,9 +309,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
314
309
  if (tipEl) tipEl.innerHTML = t(tipKey);
315
310
  });
316
311
 
317
- const onboardBody = el("onboardingBody");
318
- if (onboardBody) onboardBody.innerHTML = t("onboardingBody");
319
-
320
312
  // AI labels
321
313
  LANGUAGE_UPDATES.aiLabels.forEach(({ id, key }) => {
322
314
  const label = el(id + "-label");
@@ -344,13 +336,8 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
344
336
  const darkModeToggle = el("darkModeToggle");
345
337
  if (darkModeToggle) darkModeToggle.setAttribute("aria-label", t("darkModeToggle"));
346
338
 
347
- const readmeLink = el("onboardingReadmeLink");
348
- if (readmeLink && readmeLink instanceof HTMLAnchorElement) {
349
- readmeLink.href = isZh
350
- ? "https://github.com/wu529778790/open-im/blob/main/README.zh-CN.md"
351
- : "https://github.com/wu529778790/open-im/blob/main/README.md";
352
- }
353
- updateSetupWizard();
339
+ const headerToolbar = el("headerToolbar");
340
+ if (headerToolbar) headerToolbar.setAttribute("aria-label", t("headerToolbarAria"));
354
341
  }
355
342
 
356
343
  // AI tool switcher
@@ -382,34 +369,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
382
369
  const liveSummary = el("liveSummary");
383
370
  if (liveSummary) liveSummary.textContent = summary;
384
371
  updateAiToolVisibility();
385
- updateSetupWizard();
386
- }
387
-
388
- function hasReadyPlatform() {
389
- return platformDefinitions.some((platform) => {
390
- if (!getChecked(platform.key + "-enabled")) return false;
391
- return platform.requiredFields.every((field) => getValue(platform.key + "-" + field).trim().length > 0);
392
- });
393
- }
394
-
395
- function aiStepComplete() {
396
- const cmd = getValue("ai-aiCommand");
397
- if (cmd === "codex") return getValue("ai-codexCliPath").trim().length > 0;
398
- if (cmd === "codebuddy") return getValue("ai-codebuddyCliPath").trim().length > 0;
399
- return true;
400
- }
401
-
402
- function updateSetupWizard() {
403
- const s1 = hasReadyPlatform();
404
- const s2 = aiStepComplete();
405
- const s3 = sessionStorage.getItem(STORAGE_KEY_SAVED_SESSION) === "1";
406
- const s4 = Boolean(lastHealthPayload && lastHealthPayload.serviceStatus && lastHealthPayload.serviceStatus.running);
407
- const done = [s1, s2, s3, s4];
408
- for (let i = 0; i < 4; i += 1) {
409
- const step = el("wizard-step-" + (i + 1));
410
- if (step) step.classList.toggle("wizard-step--done", done[i]);
411
- setText("wizardStep" + (i + 1) + "Status", done[i] ? t("wizardStatusDone") : t("wizardStatusTodo"));
412
- }
413
372
  }
414
373
 
415
374
  function collectClientValidationErrors() {
@@ -498,7 +457,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
498
457
  el("statServiceValue").textContent = serviceStatus.running ? t("serviceRunningShort") : t("serviceIdleShort");
499
458
 
500
459
  lastHealthPayload = data;
501
- updateSetupWizard();
502
460
 
503
461
  return data;
504
462
  } catch (error) {
@@ -784,26 +742,6 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
784
742
  el("navAiBtn").onclick = () => scrollToSection("aiSection", "navAiBtn");
785
743
  el("navServiceBtn").onclick = () => scrollToSection("serviceSection", "navServiceBtn");
786
744
 
787
- document.querySelectorAll(".wizard-jump").forEach((jumpBtn) => {
788
- jumpBtn.addEventListener("click", () => {
789
- const sec = jumpBtn.getAttribute("data-section");
790
- const nav = jumpBtn.getAttribute("data-nav");
791
- if (sec && nav) scrollToSection(sec, nav);
792
- });
793
- });
794
-
795
- const onboardBackdrop = el("onboardingBackdrop");
796
- const onboardDismiss = el("onboardingDismiss");
797
- if (onboardBackdrop && onboardDismiss) {
798
- if (!localStorage.getItem(STORAGE_KEY_ONBOARDING)) {
799
- onboardBackdrop.classList.remove("hidden");
800
- }
801
- onboardDismiss.onclick = () => {
802
- localStorage.setItem(STORAGE_KEY_ONBOARDING, "1");
803
- onboardBackdrop.classList.add("hidden");
804
- };
805
- }
806
-
807
745
  // Language toggle
808
746
  el("langButton").onclick = () => {
809
747
  currentLang = currentLang === "zh" ? "en" : "zh";
@@ -817,19 +755,25 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
817
755
  el("darkModeToggle").onclick = toggleDarkMode;
818
756
  updateDarkMode(); // Initialize dark mode on load
819
757
 
820
- // Service buttons
821
- el("validateButton").onclick = validate;
822
- el("saveButton").onclick = async () => {
758
+ // Service buttons (page footer + sticky header toolbar)
759
+ const onSaveClick = async () => {
823
760
  if (!validateClientSideOrAbort()) return;
824
761
  await saveClaudeSettings();
825
762
  await save();
826
763
  };
827
- el("startButton").onclick = async () => {
764
+ const onStartClick = async () => {
828
765
  if (!validateClientSideOrAbort()) return;
829
766
  await saveClaudeSettings();
830
767
  await startService();
831
768
  };
769
+ el("validateButton").onclick = validate;
770
+ el("headerValidateButton").onclick = validate;
771
+ el("saveButton").onclick = onSaveClick;
772
+ el("headerSaveButton").onclick = onSaveClick;
773
+ el("startButton").onclick = onStartClick;
774
+ el("headerStartButton").onclick = onStartClick;
832
775
  el("stopButton").onclick = stopService;
776
+ el("headerStopButton").onclick = stopService;
833
777
 
834
778
  // Platform test buttons
835
779
  platformKeys.forEach((platform) => {
@@ -863,9 +807,7 @@ export const PAGE_SCRIPT = String.raw ` const platformDefinitions = [
863
807
  await saveOpenImConfig();
864
808
  // Then save form data
865
809
  await request("/api/config/save?final=1", { method: "POST", body: JSON.stringify(payload()) });
866
- sessionStorage.setItem(STORAGE_KEY_SAVED_SESSION, "1");
867
810
  setMessage(t("saveOk"), "success");
868
- updateSetupWizard();
869
811
  } catch (error) {
870
812
  setMessage(error.message || String(error), "error");
871
813
  } finally {
@@ -209,12 +209,39 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
209
209
  }
210
210
 
211
211
  .main-header {
212
+ position: sticky;
213
+ top: 0;
214
+ z-index: 30;
212
215
  background: var(--bg-primary);
213
216
  border-bottom: 1px solid var(--border-subtle);
214
- padding: 16px 32px;
217
+ padding: 16px 32px 14px;
218
+ display: flex;
219
+ flex-direction: column;
220
+ align-items: stretch;
221
+ gap: 12px;
222
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
223
+ }
224
+ :root.dark .main-header {
225
+ box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06);
226
+ }
227
+ .main-header-top {
215
228
  display: flex;
216
229
  justify-content: space-between;
217
230
  align-items: center;
231
+ gap: 16px;
232
+ flex-wrap: wrap;
233
+ }
234
+ .main-header-toolbar {
235
+ display: flex;
236
+ flex-wrap: wrap;
237
+ gap: 8px;
238
+ align-items: center;
239
+ padding-top: 12px;
240
+ margin: 0 -2px;
241
+ border-top: 1px solid var(--border-subtle);
242
+ }
243
+ .main-header-toolbar .btn {
244
+ flex: 0 1 auto;
218
245
  }
219
246
 
220
247
  .main-title {
@@ -223,12 +250,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
223
250
  color: var(--text-primary);
224
251
  }
225
252
 
226
- .main-subtitle {
227
- font-size: 13px;
228
- color: var(--text-secondary);
229
- margin-top: 2px;
230
- }
231
-
232
253
  .header-actions {
233
254
  display: flex;
234
255
  gap: 12px;
@@ -356,88 +377,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
356
377
  line-height: 1;
357
378
  }
358
379
 
359
- /* Setup wizard (overview) */
360
- .setup-wizard-card {
361
- background: var(--bg-card);
362
- border: 1px solid var(--border-subtle);
363
- border-radius: var(--radius-lg);
364
- padding: 20px 24px;
365
- margin-bottom: 24px;
366
- box-shadow: var(--shadow-sm);
367
- }
368
- .setup-wizard-card h2 {
369
- margin: 0 0 16px;
370
- font-size: 16px;
371
- font-weight: 600;
372
- color: var(--text-primary);
373
- }
374
- .wizard-steps {
375
- display: grid;
376
- gap: 12px;
377
- }
378
- @media (min-width: 900px) {
379
- .wizard-steps {
380
- grid-template-columns: repeat(2, 1fr);
381
- }
382
- }
383
- .wizard-step {
384
- display: flex;
385
- gap: 14px;
386
- align-items: flex-start;
387
- padding: 14px 16px;
388
- border-radius: var(--radius-md);
389
- border: 1px solid var(--border-subtle);
390
- background: var(--bg-secondary);
391
- transition: border-color var(--transition-fast), background var(--transition-fast);
392
- }
393
- .wizard-step--done {
394
- border-color: var(--success-border);
395
- background: var(--success-bg);
396
- }
397
- .wizard-step-badge {
398
- flex-shrink: 0;
399
- width: 28px;
400
- height: 28px;
401
- border-radius: 999px;
402
- display: flex;
403
- align-items: center;
404
- justify-content: center;
405
- font-size: 13px;
406
- font-weight: 700;
407
- background: var(--bg-tertiary);
408
- color: var(--text-secondary);
409
- }
410
- .wizard-step--done .wizard-step-badge {
411
- background: var(--success-text);
412
- color: #fff;
413
- }
414
- .wizard-step-body {
415
- flex: 1;
416
- min-width: 0;
417
- }
418
- .wizard-step-title {
419
- font-weight: 600;
420
- font-size: 14px;
421
- color: var(--text-primary);
422
- margin-bottom: 4px;
423
- }
424
- .wizard-step-desc {
425
- font-size: 13px;
426
- color: var(--text-secondary);
427
- line-height: 1.5;
428
- margin-bottom: 8px;
429
- }
430
- .wizard-step-status {
431
- font-size: 11px;
432
- font-weight: 600;
433
- text-transform: uppercase;
434
- letter-spacing: 0.04em;
435
- margin-bottom: 6px;
436
- color: var(--text-tertiary);
437
- }
438
- .wizard-step--done .wizard-step-status {
439
- color: var(--success-text);
440
- }
441
380
  .field-inline-tip {
442
381
  font-size: 12px;
443
382
  color: var(--text-tertiary);
@@ -454,51 +393,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
454
393
  border-radius: var(--radius-xs);
455
394
  }
456
395
 
457
- /* First-visit onboarding */
458
- .onboarding-backdrop {
459
- position: fixed;
460
- inset: 0;
461
- background: rgba(15, 23, 42, 0.45);
462
- z-index: 100;
463
- display: flex;
464
- align-items: center;
465
- justify-content: center;
466
- padding: 24px;
467
- }
468
- .onboarding-backdrop.hidden {
469
- display: none;
470
- }
471
- .onboarding-card {
472
- background: var(--bg-card);
473
- color: var(--text-primary);
474
- border-radius: var(--radius-xl);
475
- max-width: 520px;
476
- width: 100%;
477
- padding: 28px 28px 24px;
478
- box-shadow: var(--shadow-lg);
479
- border: 1px solid var(--border-subtle);
480
- }
481
- .onboarding-card h2 {
482
- margin: 0 0 12px;
483
- font-size: 20px;
484
- font-weight: 700;
485
- }
486
- .onboarding-card .onboarding-body {
487
- font-size: 14px;
488
- color: var(--text-secondary);
489
- line-height: 1.55;
490
- }
491
- .onboarding-card .onboarding-body p {
492
- margin: 0 0 8px;
493
- }
494
- .onboarding-actions {
495
- display: flex;
496
- flex-wrap: wrap;
497
- gap: 10px;
498
- margin-top: 20px;
499
- align-items: center;
500
- }
501
-
502
396
  .config-files-stack {
503
397
  display: flex;
504
398
  flex-direction: column;
@@ -953,27 +847,34 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
953
847
  <!-- Main Content -->
954
848
  <main class="main">
955
849
  <header class="main-header">
956
- <div>
957
- <h1 class="main-title" id="mainTitle">Dashboard</h1>
958
- <p class="main-subtitle" id="mainSubtitle">Platform status and setup progress</p>
850
+ <div class="main-header-top">
851
+ <div>
852
+ <h1 class="main-title" id="mainTitle">Dashboard</h1>
853
+ </div>
854
+ <div class="header-actions">
855
+ <a href="https://github.com/wu529778790/open-im" target="_blank" class="btn btn-ghost btn-sm">
856
+ <svg style="width:16px;height:16px" viewBox="0 0 16 16" fill="currentColor">
857
+ <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
858
+ </svg>
859
+ <span id="footerGithubText">GitHub</span>
860
+ </a>
861
+ <button class="dark-mode-toggle" id="darkModeToggle" type="button" aria-label="Toggle dark mode">
862
+ <svg class="sun-icon" style="width:16px;height:16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
863
+ <circle cx="12" cy="12" r="5"/>
864
+ <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
865
+ </svg>
866
+ <svg class="moon-icon" style="width:16px;height:16px;display:none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
867
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
868
+ </svg>
869
+ </button>
870
+ <button class="lang-button" id="langButton">中文</button>
871
+ </div>
959
872
  </div>
960
- <div class="header-actions">
961
- <a href="https://github.com/wu529778790/open-im" target="_blank" class="btn btn-ghost btn-sm">
962
- <svg style="width:16px;height:16px" viewBox="0 0 16 16" fill="currentColor">
963
- <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
964
- </svg>
965
- <span id="footerGithubText">GitHub</span>
966
- </a>
967
- <button class="dark-mode-toggle" id="darkModeToggle" type="button" aria-label="Toggle dark mode">
968
- <svg class="sun-icon" style="width:16px;height:16px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
969
- <circle cx="12" cy="12" r="5"/>
970
- <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
971
- </svg>
972
- <svg class="moon-icon" style="width:16px;height:16px;display:none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
973
- <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
974
- </svg>
975
- </button>
976
- <button class="lang-button" id="langButton">中文</button>
873
+ <div class="main-header-toolbar" id="headerToolbar" role="toolbar" aria-label="Bridge controls">
874
+ <button type="button" id="headerValidateButton" class="btn btn-warning btn-sm">Validate</button>
875
+ <button type="button" id="headerSaveButton" class="btn btn-secondary btn-sm">Save config</button>
876
+ <button type="button" id="headerStartButton" class="btn btn-primary btn-sm">Start bridge</button>
877
+ <button type="button" id="headerStopButton" class="btn btn-danger btn-sm">Stop bridge</button>
977
878
  </div>
978
879
  </header>
979
880
 
@@ -1005,48 +906,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1005
906
  <div class="stat-value" id="statServiceValue">Idle</div>
1006
907
  </div>
1007
908
  </div>
1008
-
1009
- <div class="setup-wizard-card">
1010
- <h2 id="wizardTitle">First-time setup</h2>
1011
- <div class="wizard-steps" id="wizardSteps">
1012
- <div class="wizard-step" id="wizard-step-1">
1013
- <div class="wizard-step-badge">1</div>
1014
- <div class="wizard-step-body">
1015
- <div class="wizard-step-status" id="wizardStep1Status">To do</div>
1016
- <div class="wizard-step-title" id="wizardStep1Title">Connect an IM channel</div>
1017
- <div class="wizard-step-desc" id="wizardStep1Desc"></div>
1018
- <button type="button" class="btn btn-secondary btn-sm wizard-jump" data-section="configSection" data-nav="navPlatformsBtn" id="wizardJumpPlatforms">Open Platforms</button>
1019
- </div>
1020
- </div>
1021
- <div class="wizard-step" id="wizard-step-2">
1022
- <div class="wizard-step-badge">2</div>
1023
- <div class="wizard-step-body">
1024
- <div class="wizard-step-status" id="wizardStep2Status">To do</div>
1025
- <div class="wizard-step-title" id="wizardStep2Title">Set the default AI tool</div>
1026
- <div class="wizard-step-desc" id="wizardStep2Desc"></div>
1027
- <button type="button" class="btn btn-secondary btn-sm wizard-jump" data-section="aiSection" data-nav="navAiBtn" id="wizardJumpAi">Open AI</button>
1028
- </div>
1029
- </div>
1030
- <div class="wizard-step" id="wizard-step-3">
1031
- <div class="wizard-step-badge">3</div>
1032
- <div class="wizard-step-body">
1033
- <div class="wizard-step-status" id="wizardStep3Status">To do</div>
1034
- <div class="wizard-step-title" id="wizardStep3Title">Validate and save</div>
1035
- <div class="wizard-step-desc" id="wizardStep3Desc"></div>
1036
- <button type="button" class="btn btn-secondary btn-sm wizard-jump" data-section="serviceSection" data-nav="navServiceBtn" id="wizardJumpService">Open Service</button>
1037
- </div>
1038
- </div>
1039
- <div class="wizard-step" id="wizard-step-4">
1040
- <div class="wizard-step-badge">4</div>
1041
- <div class="wizard-step-body">
1042
- <div class="wizard-step-status" id="wizardStep4Status">To do</div>
1043
- <div class="wizard-step-title" id="wizardStep4Title">Start the bridge</div>
1044
- <div class="wizard-step-desc" id="wizardStep4Desc"></div>
1045
- <button type="button" class="btn btn-secondary btn-sm wizard-jump" data-section="serviceSection" data-nav="navServiceBtn" id="wizardJumpService2">Open Service</button>
1046
- </div>
1047
- </div>
1048
- </div>
1049
- </div>
1050
909
  </section>
1051
910
 
1052
911
  <!-- Platforms Section -->
@@ -1492,17 +1351,6 @@ export const PAGE_HTML_PREFIX = String.raw `<!doctype html>
1492
1351
  </div>
1493
1352
  </section>
1494
1353
 
1495
- <div id="onboardingBackdrop" class="onboarding-backdrop hidden" role="dialog" aria-modal="true" aria-labelledby="onboardingTitle">
1496
- <div class="onboarding-card">
1497
- <h2 id="onboardingTitle">Welcome</h2>
1498
- <div id="onboardingBody" class="onboarding-body"></div>
1499
- <div class="onboarding-actions">
1500
- <button type="button" class="btn btn-primary" id="onboardingDismiss">Got it</button>
1501
- <a href="https://github.com/wu529778790/open-im/blob/main/README.zh-CN.md" target="_blank" rel="noopener" class="btn btn-ghost" id="onboardingReadmeLink"><span id="onboardingReadme">README</span></a>
1502
- </div>
1503
- </div>
1504
- </div>
1505
-
1506
1354
  </div>
1507
1355
  </main>
1508
1356
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.9.3-beta.10",
3
+ "version": "1.9.3-beta.12",
4
4
  "description": "Multi-platform IM bridge for AI CLI tools (Claude, Codex, CodeBuddy)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",