@wu529778790/open-im 1.11.1-beta.14 → 1.11.1-beta.16

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.
@@ -15,6 +15,17 @@ import { createLogger } from '../logger.js';
15
15
  import { refreshClaudeEnvToProcess } from '../config/file-io.js';
16
16
  import { toReplyPlainText } from '../shared/utils.js';
17
17
  const log = createLogger('ClaudeSDK');
18
+ /**
19
+ * 注入交互式上下文指令,让 Claude 认为这是交互式终端会话。
20
+ * 解决 query() 非交互环境下 Claude 跳过用户选择、直接自主决策的问题。
21
+ */
22
+ const INTERACTIVE_CONTEXT = `[SYSTEM: You are in an interactive chat session via instant messenger. The user CAN and WILL respond to your messages — treat this like an interactive terminal session. Rules:
23
+ 1. When you need to make a decision involving user preference (choosing an approach, selecting between options, deciding what to do next), ALWAYS present clearly numbered options and WAIT for the user's response.
24
+ 2. Do NOT proceed autonomously when user input would be valuable.
25
+ 3. Only proceed autonomously for obvious single-path tasks (e.g. reading a file, running a simple command).
26
+ 4. When presenting options, format them as a numbered list and end with a question.
27
+ ]
28
+ `;
18
29
  function loadUserPluginSettings() {
19
30
  try {
20
31
  const settingsPath = join(homedir(), '.claude', 'settings.json');
@@ -386,7 +397,7 @@ export class ClaudeSDKAdapter {
386
397
  }
387
398
  }
388
399
  const q = query({
389
- prompt,
400
+ prompt: INTERACTIVE_CONTEXT + prompt,
390
401
  options: {
391
402
  cwd: workDir,
392
403
  model: resolvedModel,
@@ -161,8 +161,8 @@ export declare const PAGE_TEXTS: {
161
161
  readonly tipQqSecret: "Same console → App Secret.";
162
162
  readonly tipWeworkCorp: "WeCom admin → app → view Corp ID (or smart-bot Bot ID) and Secret.";
163
163
  readonly tipDingtalkClient: "<a href=\"https://open-dev.dingtalk.com\" target=\"_blank\" rel=\"noopener\">DingTalk Open Platform</a> → internal app → App Key & App Secret.";
164
- readonly tipWorkbuddyToken: "Use terminal <code>open-im init</code> for WorkBuddy OAuth, or paste tokens from CodeBuddy login.";
165
- readonly tipClawbotApiToken: "Run <code>open-im init</code> and select ClawBot to scan QR code, or paste token from ClawBot iLink login.";
164
+ readonly tipWorkbuddyToken: "Go to Settings AI Tooling or use the Setup Wizard to configure WorkBuddy OAuth. You can also paste tokens from CodeBuddy login.";
165
+ readonly tipClawbotApiToken: "Use the \"Scan QR Login\" button in the platform card, or paste token from ClawBot iLink login.";
166
166
  readonly navSetupWizard: "Setup Wizard";
167
167
  readonly wizardStepLabel_welcome: "Welcome";
168
168
  readonly wizardStepLabel_ai: "AI Backend";
@@ -194,6 +194,21 @@ export declare const PAGE_TEXTS: {
194
194
  readonly wizardWorking: "Working...";
195
195
  readonly wizardSaving: "Saving configuration...";
196
196
  readonly wizardStarting: "Starting bridge...";
197
+ readonly wizardStepLabel_claudeApi: "Claude API";
198
+ readonly wizardStepClaudeApi: "Set up your Claude API access";
199
+ readonly wizardClaudeApiTitle: "Claude API Setup";
200
+ readonly wizardClaudeApiDesc: "Choose how to authenticate with Claude. This is required for the AI assistant to work.";
201
+ readonly wizardApiTypeLabel: "API Type";
202
+ readonly wizardApiOfficial: "Official Anthropic API";
203
+ readonly wizardApiOfficialDesc: "Use your Anthropic API key or auth token";
204
+ readonly wizardApiThirdparty: "Third-party Model";
205
+ readonly wizardApiThirdpartyDesc: "Use a compatible third-party API endpoint";
206
+ readonly wizardApiSkip: "Already configured";
207
+ readonly wizardApiSkipDesc: "Skip if you've already set up API access";
208
+ readonly wizardAuthTypeLabel: "Authentication";
209
+ readonly wizardAuthApiKey: "API Key";
210
+ readonly wizardAuthToken: "Auth Token";
211
+ readonly wizardLoading: "Loading...";
197
212
  };
198
213
  readonly zh: {
199
214
  readonly pageTitle: "open-im 本地控制台";
@@ -354,8 +369,8 @@ export declare const PAGE_TEXTS: {
354
369
  readonly tipQqSecret: "同一处获取 App Secret。";
355
370
  readonly tipWeworkCorp: "企业微信管理后台 → 应用 → 查省 Corp ID / 智能机器人 Bot ID 与 Secret。";
356
371
  readonly tipDingtalkClient: "<a href=\"https://open-dev.dingtalk.com\" target=\"_blank\" rel=\"noopener\">钉钉开放平台</a> → 企业内部应用 → AppKey / AppSecret。";
357
- readonly tipWorkbuddyToken: "建议在终端运行 <code>open-im init</code> 完成 WorkBuddy 授权;或粘贴 CodeBuddy 登录后的 Token。";
358
- readonly tipClawbotApiToken: "在终端运行 <code>open-im init</code> 选择 ClawBot 扫码登录,或从 ClawBot iLink 登录后复制 Token。";
372
+ readonly tipWorkbuddyToken: "前往“AI 工具配置”或使用设置向导配置 WorkBuddy OAuth;或粘贴 CodeBuddy 登录后的 Token。";
373
+ readonly tipClawbotApiToken: "使用平台卡片中的“扫码登录”按钮,或从 ClawBot iLink 登录后复制 Token。";
359
374
  readonly navSetupWizard: "设置向导";
360
375
  readonly wizardStepLabel_welcome: "欢迎";
361
376
  readonly wizardStepLabel_ai: "AI 后端";
@@ -387,5 +402,20 @@ export declare const PAGE_TEXTS: {
387
402
  readonly wizardWorking: "处理中...";
388
403
  readonly wizardSaving: "正在保存配置...";
389
404
  readonly wizardStarting: "正在启动桥接...";
405
+ readonly wizardStepLabel_claudeApi: "Claude API";
406
+ readonly wizardStepClaudeApi: "配置 Claude API 访问";
407
+ readonly wizardClaudeApiTitle: "Claude API 配置";
408
+ readonly wizardClaudeApiDesc: "选择 Claude 的认证方式,这是 AI 助手工作的必要配置。";
409
+ readonly wizardApiTypeLabel: "API 类型";
410
+ readonly wizardApiOfficial: "官方 Anthropic API";
411
+ readonly wizardApiOfficialDesc: "使用 Anthropic API Key 或 Auth Token";
412
+ readonly wizardApiThirdparty: "第三方模型";
413
+ readonly wizardApiThirdpartyDesc: "使用兼容的第三方 API 端点";
414
+ readonly wizardApiSkip: "已配置";
415
+ readonly wizardApiSkipDesc: "如果已配置 API 访问,可跳过此步";
416
+ readonly wizardAuthTypeLabel: "认证方式";
417
+ readonly wizardAuthApiKey: "API Key";
418
+ readonly wizardAuthToken: "Auth Token";
419
+ readonly wizardLoading: "加载中...";
390
420
  };
391
421
  };
@@ -161,8 +161,8 @@ export const PAGE_TEXTS = {
161
161
  tipQqSecret: "Same console → App Secret.",
162
162
  tipWeworkCorp: "WeCom admin → app → view Corp ID (or smart-bot Bot ID) and Secret.",
163
163
  tipDingtalkClient: '<a href="https://open-dev.dingtalk.com" target="_blank" rel="noopener">DingTalk Open Platform</a> → internal app → App Key & App Secret.',
164
- tipWorkbuddyToken: 'Use terminal <code>open-im init</code> for WorkBuddy OAuth, or paste tokens from CodeBuddy login.',
165
- tipClawbotApiToken: 'Run <code>open-im init</code> and select ClawBot to scan QR code, or paste token from ClawBot iLink login.',
164
+ tipWorkbuddyToken: 'Go to Settings AI Tooling or use the Setup Wizard to configure WorkBuddy OAuth. You can also paste tokens from CodeBuddy login.',
165
+ tipClawbotApiToken: 'Use the "Scan QR Login" button in the platform card, or paste token from ClawBot iLink login.',
166
166
  /* ---- Setup Wizard ---- */
167
167
  navSetupWizard: "Setup Wizard",
168
168
  wizardStepLabel_welcome: "Welcome",
@@ -195,6 +195,21 @@ export const PAGE_TEXTS = {
195
195
  wizardWorking: "Working...",
196
196
  wizardSaving: "Saving configuration...",
197
197
  wizardStarting: "Starting bridge...",
198
+ wizardStepLabel_claudeApi: "Claude API",
199
+ wizardStepClaudeApi: "Set up your Claude API access",
200
+ wizardClaudeApiTitle: "Claude API Setup",
201
+ wizardClaudeApiDesc: "Choose how to authenticate with Claude. This is required for the AI assistant to work.",
202
+ wizardApiTypeLabel: "API Type",
203
+ wizardApiOfficial: "Official Anthropic API",
204
+ wizardApiOfficialDesc: "Use your Anthropic API key or auth token",
205
+ wizardApiThirdparty: "Third-party Model",
206
+ wizardApiThirdpartyDesc: "Use a compatible third-party API endpoint",
207
+ wizardApiSkip: "Already configured",
208
+ wizardApiSkipDesc: "Skip if you've already set up API access",
209
+ wizardAuthTypeLabel: "Authentication",
210
+ wizardAuthApiKey: "API Key",
211
+ wizardAuthToken: "Auth Token",
212
+ wizardLoading: "Loading...",
198
213
  },
199
214
  zh: {
200
215
  pageTitle: "open-im \u672c\u5730\u63a7\u5236\u53f0",
@@ -355,8 +370,8 @@ export const PAGE_TEXTS = {
355
370
  tipQqSecret: "\u540c\u4e00\u5904\u83b7\u53d6 App Secret\u3002",
356
371
  tipWeworkCorp: "\u4f01\u4e1a\u5fae\u4fe1\u7ba1\u7406\u540e\u53f0 \u2192 \u5e94\u7528 \u2192 \u67e5\u7701 Corp ID / \u667a\u80fd\u673a\u5668\u4eba Bot ID \u4e0e Secret\u3002",
357
372
  tipDingtalkClient: '<a href="https://open-dev.dingtalk.com" target="_blank" rel="noopener">\u9489\u9489\u5f00\u653e\u5e73\u53f0</a> \u2192 \u4f01\u4e1a\u5185\u90e8\u5e94\u7528 \u2192 AppKey / AppSecret\u3002',
358
- tipWorkbuddyToken: "\u5efa\u8bae\u5728\u7ec8\u7aef\u8fd0\u884c <code>open-im init</code> \u5b8c\u6210 WorkBuddy \u6388\u6743\uff1b\u6216\u7c98\u8d34 CodeBuddy \u767b\u5f55\u540e\u7684 Token\u3002",
359
- tipClawbotApiToken: '\u5728\u7ec8\u7aef\u8fd0\u884c <code>open-im init</code> \u9009\u62e9 ClawBot \u626b\u7801\u767b\u5f55\uff0c\u6216\u4ece ClawBot iLink \u767b\u5f55\u540e\u590d\u5236 Token\u3002',
373
+ tipWorkbuddyToken: "\u524d\u5f80\u201cAI \u5de5\u5177\u914d\u7f6e\u201d\u6216\u4f7f\u7528\u8bbe\u7f6e\u5411\u5bfc\u914d\u7f6e WorkBuddy OAuth\uff1b\u6216\u7c98\u8d34 CodeBuddy \u767b\u5f55\u540e\u7684 Token\u3002",
374
+ tipClawbotApiToken: '\u4f7f\u7528\u5e73\u53f0\u5361\u7247\u4e2d\u7684\u201c\u626b\u7801\u767b\u5f55\u201d\u6309\u94ae\uff0c\u6216\u4ece ClawBot iLink \u767b\u5f55\u540e\u590d\u5236 Token\u3002',
360
375
  /* ---- Setup Wizard ---- */
361
376
  navSetupWizard: "\u8bbe\u7f6e\u5411\u5bfc",
362
377
  wizardStepLabel_welcome: "\u6b22\u8fce",
@@ -389,5 +404,20 @@ export const PAGE_TEXTS = {
389
404
  wizardWorking: "\u5904\u7406\u4e2d...",
390
405
  wizardSaving: "\u6b63\u5728\u4fdd\u5b58\u914d\u7f6e...",
391
406
  wizardStarting: "\u6b63\u5728\u542f\u52a8\u6865\u63a5...",
407
+ wizardStepLabel_claudeApi: "Claude API",
408
+ wizardStepClaudeApi: "\u914d\u7f6e Claude API \u8bbf\u95ee",
409
+ wizardClaudeApiTitle: "Claude API \u914d\u7f6e",
410
+ wizardClaudeApiDesc: "\u9009\u62e9 Claude \u7684\u8ba4\u8bc1\u65b9\u5f0f\uff0c\u8fd9\u662f AI \u52a9\u624b\u5de5\u4f5c\u7684\u5fc5\u8981\u914d\u7f6e\u3002",
411
+ wizardApiTypeLabel: "API \u7c7b\u578b",
412
+ wizardApiOfficial: "\u5b98\u65b9 Anthropic API",
413
+ wizardApiOfficialDesc: "\u4f7f\u7528 Anthropic API Key \u6216 Auth Token",
414
+ wizardApiThirdparty: "\u7b2c\u4e09\u65b9\u6a21\u578b",
415
+ wizardApiThirdpartyDesc: "\u4f7f\u7528\u517c\u5bb9\u7684\u7b2c\u4e09\u65b9 API \u7aef\u70b9",
416
+ wizardApiSkip: "\u5df2\u914d\u7f6e",
417
+ wizardApiSkipDesc: "\u5982\u679c\u5df2\u914d\u7f6e API \u8bbf\u95ee\uff0c\u53ef\u8df3\u8fc7\u6b64\u6b65",
418
+ wizardAuthTypeLabel: "\u8ba4\u8bc1\u65b9\u5f0f",
419
+ wizardAuthApiKey: "API Key",
420
+ wizardAuthToken: "Auth Token",
421
+ wizardLoading: "\u52a0\u8f7d\u4e2d...",
392
422
  }
393
423
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.11.1-beta.14",
3
+ "version": "1.11.1-beta.16",
4
4
  "description": "Your AI coding assistant, in every chat app. Multi-platform IM bridge for Claude Code, Codex, and CodeBuddy.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1 @@
1
+ :root{--c-bg: #f4f5f7;--c-surface: #ffffff;--c-surface-alt: #f9fafb;--c-border: #e4e7ec;--c-border-foc: #c0c7d1;--c-text: #101828;--c-text-2: #475467;--c-text-3: #98a2b3;--c-accent: #2970ff;--c-accent-h: #155eef;--c-accent-bg: #eff4ff;--c-accent-bdr: #b2ddff;--c-ok: #12b76a;--c-ok-bg: #ecfdf3;--c-ok-bdr: #a6f4c5;--c-warn: #f79009;--c-warn-bg: #fffaeb;--c-warn-bdr: #fedf89;--c-err: #f04438;--c-err-bg: #fef3f2;--c-err-bdr: #fecdca;--c-sb-bg: #101828;--c-sb-text: #98a2b3;--c-sb-text-a: #f4f5f7;--c-sb-hover: rgba(255,255,255,.06);--c-sb-active: rgba(255,255,255,.1);--shadow-xs: 0 1px 2px rgba(16,24,40,.05);--shadow-s: 0 1px 3px rgba(16,24,40,.1), 0 1px 2px rgba(16,24,40,.06);--shadow-m: 0 4px 8px -2px rgba(16,24,40,.1), 0 2px 4px -2px rgba(16,24,40,.06);--shadow-l: 0 12px 16px -4px rgba(16,24,40,.08), 0 4px 6px -2px rgba(16,24,40,.03);--r-s: 6px;--r-m: 8px;--r-l: 12px;--r-xl: 16px;--font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--mono: "SF Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;--fast: .12s ease;--norm: .2s ease;--sidebar-w: 240px;--header-h: 56px}:root.dark{--c-bg: #0c0d0f;--c-surface: #16171a;--c-surface-alt: #1c1d21;--c-border: #2a2b30;--c-border-foc: #3e4047;--c-text: #f0f1f4;--c-text-2: #98a2b3;--c-text-3: #5d6573;--c-accent: #528bff;--c-accent-h: #79a6ff;--c-accent-bg: rgba(42,114,255,.12);--c-accent-bdr: rgba(42,114,255,.24);--c-ok-bg: rgba(18,183,108,.1);--c-ok-bdr: rgba(18,183,108,.2);--c-warn-bg: rgba(247,144,9,.1);--c-warn-bdr: rgba(247,144,9,.2);--c-err-bg: rgba(240,68,56,.1);--c-err-bdr: rgba(240,68,56,.2);--c-sb-bg: #08090b;--c-sb-hover: rgba(255,255,255,.04);--c-sb-active: rgba(255,255,255,.08)}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}body{font-family:var(--font);font-size:14px;line-height:1.5;color:var(--c-text);background:var(--c-bg);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.app{display:flex;min-height:100vh}.main{flex:1;margin-left:var(--sidebar-w);display:flex;flex-direction:column;min-height:100vh;transition:margin-left var(--norm)}.content{flex:1;padding:32px 40px 64px;max-width:960px;width:100%;margin:0 auto}.sidebar{position:fixed;top:0;left:0;bottom:0;width:var(--sidebar-w);background:var(--c-sb-bg);color:var(--c-sb-text);display:flex;flex-direction:column;z-index:20;border-right:1px solid rgba(255,255,255,.06);overflow:hidden}.sidebar-header{padding:20px 16px 16px;display:flex;align-items:center;gap:10px}.sidebar-logo{width:32px;height:32px;border-radius:var(--r-m);background:var(--c-accent);display:flex;align-items:center;justify-content:center;flex-shrink:0}.sidebar-logo svg{width:18px;height:18px;color:#fff}.sidebar-brand{font-size:15px;font-weight:700;color:var(--c-sb-text-a);letter-spacing:-.01em;white-space:nowrap;overflow:hidden}.sidebar-nav{flex:1;padding:4px 8px;display:flex;flex-direction:column;gap:2px;overflow-y:auto}.sidebar-section-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--c-text-3);padding:16px 12px 6px}.nav-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:var(--r-m);color:var(--c-sb-text);font-size:13px;font-weight:500;cursor:pointer;border:none;background:transparent;width:100%;text-align:left;transition:background var(--fast),color var(--fast);white-space:nowrap;overflow:hidden}.nav-item:hover{background:var(--c-sb-hover);color:var(--c-sb-text-a)}.nav-item.active{background:var(--c-sb-active);color:var(--c-sb-text-a)}.nav-item svg{width:18px;height:18px;flex-shrink:0;opacity:.7}.nav-item.active svg,.nav-item:hover svg{opacity:1}.header{position:sticky;top:0;z-index:15;background:var(--c-surface);border-bottom:1px solid var(--c-border);padding:0 40px;height:var(--header-h);display:flex;align-items:center;justify-content:space-between;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-title{font-size:15px;font-weight:600;color:var(--c-text)}.header-actions{display:flex;align-items:center;gap:8px}.header-divider{height:1px;background:var(--c-border);margin:0}.header-toolbar{background:var(--c-surface-alt);border-bottom:1px solid var(--c-border);padding:10px 40px;display:flex;gap:8px;flex-wrap:wrap;align-items:center}.header-toolbar-spacer{flex:1}.header-toolbar-status{font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px;color:var(--c-text-2)}.header-toolbar-status .dot{width:6px;height:6px;border-radius:50%;display:inline-block}.header-toolbar-status .dot.running{background:var(--c-ok)}.header-toolbar-status .dot.idle{background:var(--c-text-3)}.stats-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:32px}.stat-card{background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--r-l);padding:20px}.stat-label{font-size:12px;font-weight:500;color:var(--c-text-3);text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px}.stat-value{font-size:28px;font-weight:700;color:var(--c-text);line-height:1}.stat-meta{font-size:12px;color:var(--c-text-3);margin-top:4px}.section{margin-bottom:40px}.section-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:20px;flex-wrap:wrap;gap:8px}.section-title{font-size:16px;font-weight:600;color:var(--c-text)}.section-desc{font-size:13px;color:var(--c-text-3)}.card{background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--r-l);overflow:hidden}.card-head{padding:16px 20px;border-bottom:1px solid var(--c-border);display:flex;justify-content:space-between;align-items:center;gap:12px}.card-title{font-size:14px;font-weight:600;color:var(--c-text)}.card-body{padding:20px}.card-foot{padding:12px 20px;border-top:1px solid var(--c-border);background:var(--c-surface-alt)}.platform-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.platform-card{background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--r-l);overflow:hidden;transition:border-color var(--fast),box-shadow var(--fast)}.platform-card:hover{box-shadow:var(--shadow-s)}.platform-card.disabled{opacity:.55}.platform-card-head{padding:14px 20px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--c-border);gap:12px}.platform-card-name{font-size:14px;font-weight:600;color:var(--c-text);display:flex;align-items:center;gap:8px}.platform-card-chevron{font-size:12px;color:var(--c-text-3);margin-left:4px;transition:transform var(--fast)}.platform-card-name .dot{width:6px;height:6px;border-radius:50%;background:var(--c-text-3)}.platform-card.enabled .platform-card-name .dot{background:var(--c-ok)}.platform-card-body{padding:16px 20px 20px}.platform-card-hint{font-size:12px;color:var(--c-text-3);line-height:1.5;margin-bottom:16px}.platform-card-help{margin-top:16px;padding:10px 14px;background:var(--c-surface-alt);border-radius:var(--r-m);font-size:12px;color:var(--c-text-2);line-height:1.6}.platform-card-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:16px}.ai-grid{display:grid;grid-template-columns:280px 1fr;gap:16px}.config-stack{display:flex;flex-direction:column;gap:16px}.config-card .card-title{font-family:var(--mono);font-size:13px}.config-card textarea{width:100%}.config-card-toolbar{display:flex;justify-content:flex-end;gap:6px;margin-bottom:8px}.form-group{margin-bottom:14px}.form-group:last-child{margin-bottom:0}.form-label{display:block;font-size:12px;font-weight:500;color:var(--c-text-2);margin-bottom:5px}.form-input,.form-select,.form-textarea{width:100%;padding:8px 10px;font-family:inherit;font-size:13px;color:var(--c-text);background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--r-s);transition:border-color var(--fast),box-shadow var(--fast);outline:none}.form-input:focus,.form-select:focus,.form-textarea:focus{border-color:var(--c-accent);box-shadow:0 0 0 3px var(--c-accent-bg)}.form-input.mono,.form-textarea.mono{font-family:var(--mono);font-size:12px}.form-textarea{min-height:80px;resize:vertical}.form-hint{font-size:11px;color:var(--c-text-3);margin-top:4px;line-height:1.4}.form-hint a{color:var(--c-accent)}.form-hint code{font-family:var(--mono);font-size:10px;padding:1px 4px;background:var(--c-surface-alt);border-radius:3px}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:7px 14px;font-family:inherit;font-size:13px;font-weight:500;border-radius:var(--r-s);border:1px solid transparent;cursor:pointer;text-decoration:none;transition:all var(--fast);white-space:nowrap}.btn:disabled{opacity:.5;cursor:not-allowed}.btn-p{background:var(--c-accent);color:#fff}.btn-p:hover:not(:disabled){background:var(--c-accent-h)}.btn-s{background:var(--c-surface);color:var(--c-text);border-color:var(--c-border)}.btn-s:hover:not(:disabled){background:var(--c-surface-alt);border-color:var(--c-border-foc)}.btn-g{background:transparent;color:var(--c-text-2)}.btn-g:hover:not(:disabled){background:var(--c-surface-alt);color:var(--c-text)}.btn-d{background:var(--c-err-bg);color:var(--c-err);border-color:var(--c-err-bdr)}.btn-d:hover:not(:disabled){background:var(--c-err);color:#fff}.btn-w{background:var(--c-warn-bg);color:var(--c-warn);border-color:var(--c-warn-bdr)}.btn-w:hover:not(:disabled){background:var(--c-warn);color:#fff}.btn-sm{padding:5px 10px;font-size:12px}.btn-lg{padding:10px 20px;font-size:14px}.toggle{display:inline-flex;align-items:center;gap:8px;cursor:pointer;flex-shrink:0}.toggle-input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.toggle-track{position:relative;width:36px;height:20px;background:var(--c-border-foc);border-radius:999px;transition:background var(--fast);flex-shrink:0}.toggle-track:after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;background:#fff;border-radius:50%;transition:transform var(--fast);box-shadow:var(--shadow-xs)}.toggle-input:checked+.toggle-track{background:var(--c-accent)}.toggle-input:checked+.toggle-track:after{transform:translate(16px)}.tabs{display:inline-flex;gap:2px;padding:3px;background:var(--c-surface-alt);border:1px solid var(--c-border);border-radius:var(--r-m)}.tab{padding:6px 12px;font-size:12px;font-weight:500;color:var(--c-text-2);background:transparent;border:none;border-radius:var(--r-s);cursor:pointer;transition:all var(--fast)}.tab:hover{color:var(--c-text)}.tab.active{background:var(--c-surface);color:var(--c-text);box-shadow:var(--shadow-xs)}.msg{padding:10px 14px;border-radius:var(--r-m);font-size:13px;line-height:1.5}.msg-ok{background:var(--c-ok-bg);color:var(--c-ok)}.msg-err{background:var(--c-err-bg);color:var(--c-err)}.msg-w{background:var(--c-warn-bg);color:var(--c-warn)}.badge{display:inline-flex;align-items:center;padding:2px 8px;font-size:11px;font-weight:500;border-radius:999px}.badge-ok{background:var(--c-ok-bg);color:var(--c-ok)}.badge-err{background:var(--c-err-bg);color:var(--c-err)}.badge-w{background:var(--c-warn-bg);color:var(--c-warn)}.badge-info{background:var(--c-accent-bg);color:var(--c-accent)}.field-tip{font-size:11px;color:var(--c-text-3);line-height:1.45;margin-top:5px}.field-tip a{color:var(--c-accent)}.field-tip code{font-family:var(--mono);font-size:10px;padding:1px 4px;background:var(--c-surface-alt);border-radius:3px}.flash{margin-bottom:20px}.mt-4{margin-top:16px}.mt-6{margin-top:24px}.gap-2{gap:8px}.gap-3{gap:12px}.text-center{text-align:center}.mono{font-family:var(--mono)}.hidden{display:none!important}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.wizard-wrap{display:flex;justify-content:center;padding-top:16px}.wizard{width:100%;max-width:580px;background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--r-xl);box-shadow:var(--shadow-m);overflow:hidden}.wizard-bar{height:3px;background:var(--c-border)}.wizard-bar-fill{height:100%;background:var(--c-accent);transition:width .4s cubic-bezier(.4,0,.2,1)}.wizard-steps{display:flex;padding:20px 24px 0;gap:0}.wizard-step-ind{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;position:relative}.wizard-step-ind+.wizard-step-ind:before{content:"";position:absolute;top:12px;right:calc(50% + 16px);width:calc(100% - 32px);height:1px;background:var(--c-border)}.wizard-step-ind.done+.wizard-step-ind:before{background:var(--c-accent)}.wizard-step-dot{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;background:var(--c-surface-alt);color:var(--c-text-3);border:2px solid var(--c-border);position:relative;z-index:1;transition:all var(--norm)}.wizard-step-ind.active .wizard-step-dot{background:var(--c-accent);color:#fff;border-color:var(--c-accent)}.wizard-step-ind.done .wizard-step-dot{background:var(--c-ok);color:#fff;border-color:var(--c-ok)}.wizard-step-label{font-size:11px;font-weight:500;color:var(--c-text-3);white-space:nowrap}.wizard-step-ind.active .wizard-step-label{color:var(--c-accent);font-weight:600}.wizard-step-ind.done .wizard-step-label{color:var(--c-ok)}.wizard-body{padding:28px 32px;min-height:260px}.wizard-icon{font-size:36px;margin-bottom:12px}.wizard-title{font-size:18px;font-weight:700;color:var(--c-text);margin-bottom:6px;letter-spacing:-.01em}.wizard-desc{font-size:13px;color:var(--c-text-2);line-height:1.6;margin-bottom:24px}.wizard-checklist{display:flex;flex-direction:column;gap:10px}.wizard-check{display:flex;align-items:center;gap:10px;font-size:13px;color:var(--c-text)}.wizard-check-num{width:24px;height:24px;border-radius:50%;background:var(--c-accent-bg);color:var(--c-accent);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;flex-shrink:0}.wizard-chips{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}.wizard-chip{display:flex;flex-direction:column;gap:4px;padding:14px;background:var(--c-surface);border:2px solid var(--c-border);border-radius:var(--r-l);cursor:pointer;text-align:left;transition:all var(--fast);color:var(--c-text);font-family:inherit;font-size:inherit}.wizard-chip:hover{border-color:var(--c-accent-bdr)}.wizard-chip.on{border-color:var(--c-accent);background:var(--c-accent-bg)}.wizard-chip-name{font-weight:600;font-size:13px}.wizard-chip-hint{font-size:11px;color:var(--c-text-3);line-height:1.3}.wizard-cred{background:var(--c-surface-alt);border:1px solid var(--c-border);border-radius:var(--r-l);padding:20px;margin-bottom:14px}.wizard-cred:last-child{margin-bottom:0}.wizard-cred-name{font-size:14px;font-weight:600;margin-bottom:14px;color:var(--c-text)}.wizard-review-block{margin-bottom:20px}.wizard-review-head{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--c-text-3);margin-bottom:10px}.wizard-kv{display:flex;justify-content:space-between;align-items:center;padding:7px 0;border-bottom:1px solid var(--c-border);font-size:12px}.wizard-kv span{color:var(--c-text-2)}.wizard-kv code{font-family:var(--mono);font-size:11px;color:var(--c-text);background:var(--c-surface-alt);padding:2px 6px;border-radius:4px}.wizard-platforms{display:flex;flex-wrap:wrap;gap:6px}.wizard-platform-pill{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:var(--c-surface-alt);border-radius:999px;font-size:12px;font-weight:500}.wizard-platform-pill .cmd{font-size:10px;padding:1px 6px;border-radius:999px;background:var(--c-accent-bg);color:var(--c-accent);font-weight:500}.wizard-done{text-align:center;padding:20px 0}.wizard-pulse{animation:wiz-pulse 1.2s ease-in-out infinite}@keyframes wiz-pulse{0%,to{opacity:1}50%{opacity:.4}}.wizard-radio-group{display:flex;flex-direction:column;gap:8px}.wizard-radio{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border:2px solid var(--c-border);border-radius:var(--r-m);cursor:pointer;transition:all var(--fast)}.wizard-radio:hover{border-color:var(--c-accent-bdr)}.wizard-radio.on{border-color:var(--c-accent);background:var(--c-accent-bg)}.wizard-radio input[type=radio]{margin-top:2px;accent-color:var(--c-accent)}.wizard-radio-body{display:flex;flex-direction:column;gap:2px}.wizard-radio-label{font-size:13px;font-weight:600;color:var(--c-text)}.wizard-radio-desc{font-size:12px;color:var(--c-text-3)}.wizard-nav{display:flex;align-items:center;padding:16px 32px 24px;gap:10px}.wizard-nav-spacer{flex:1}.conn{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:32px}.conn-card{width:100%;max-width:420px;background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--r-xl);box-shadow:var(--shadow-l);padding:32px}.conn-logo{width:40px;height:40px;border-radius:var(--r-m);background:var(--c-accent);display:flex;align-items:center;justify-content:center;margin-bottom:20px}.conn-logo svg{width:22px;height:22px;color:#fff}.conn-title{font-size:18px;font-weight:700;color:var(--c-text);margin-bottom:6px}.conn-desc{font-size:13px;color:var(--c-text-2);margin-bottom:24px;line-height:1.5}.conn-row{display:flex;gap:8px}.conn-input{flex:1;padding:8px 10px;font-family:var(--mono);font-size:13px;color:var(--c-text);background:var(--c-surface-alt);border:1px solid var(--c-border);border-radius:var(--r-s);outline:none;transition:border-color var(--fast)}.conn-input:focus{border-color:var(--c-accent);box-shadow:0 0 0 3px var(--c-accent-bg)}.conn-status{font-size:12px;margin-top:10px;color:var(--c-text-3)}.conn-status.ok{color:var(--c-ok)}.conn-status.err{color:var(--c-err)}.lang-btn{padding:4px 10px;font-size:12px;font-weight:500;border-radius:var(--r-s);border:1px solid var(--c-border);background:var(--c-surface);color:var(--c-text-2);cursor:pointer;transition:all var(--fast)}.lang-btn:hover{border-color:var(--c-border-foc);color:var(--c-text)}.dark-btn{padding:4px 8px;border-radius:var(--r-s);border:1px solid var(--c-border);background:var(--c-surface);color:var(--c-text-2);cursor:pointer;font-size:14px;line-height:1;transition:all var(--fast);display:inline-flex;align-items:center;justify-content:center}.dark-btn:hover{border-color:var(--c-border-foc);color:var(--c-text)}@media(max-width:1024px){.ai-grid,.stats-grid{grid-template-columns:1fr}}@media(max-width:768px){.sidebar{display:none}.main{margin-left:0}.content{padding:20px 16px 40px}.header{padding:0 16px}.header-toolbar{padding:10px 16px}.platform-grid{grid-template-columns:1fr}.wizard-chips{grid-template-columns:1fr 1fr}}