diff --git a/.gitignore b/.gitignore index 64e1b39e..6aacb257 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,7 @@ playground/ # ClawX-biz bridge workspace artifacts resources/enterprise-skills/ resources/openclaw-plugins/skillshub/ + +# Dev tools +dev.bat +.playwright-cli/ diff --git a/.npmrc b/.npmrc index 425353e6..69fd2445 100644 --- a/.npmrc +++ b/.npmrc @@ -1,6 +1,9 @@ registry=https://registry.npmmirror.com electron_mirror=https://npmmirror.com/mirrors/electron/ electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ +sass_binary_site=https://npmmirror.com/mirrors/node-sass/ +puppeteer_download_base_url=https://npmmirror.com/mirrors/ +chromedriver_cdnurl=https://npmmirror.com/mirrors/chromedriver/ package-import-method=copy shamefully-hoist=true strict-peer-dependencies=false diff --git a/dev.js b/dev.js new file mode 100644 index 00000000..dfd2b5bf --- /dev/null +++ b/dev.js @@ -0,0 +1,15 @@ +const { exec } = require('child_process'); + +const cmd = process.platform === 'win32' ? 'pnpm.cmd dev' : 'pnpm dev'; + +const child = exec(cmd, { + cwd: __dirname, + env: { ...process.env, CLAWX_CDP_PORT: process.env.CLAWX_CDP_PORT || '9222' }, +}); + +child.stdout?.pipe(process.stdout); +child.stderr?.pipe(process.stderr); + +child.on('exit', (code) => { + process.exit(code ?? 1); +}); diff --git a/docs/原始需求.txt b/docs/原始需求.txt new file mode 100644 index 00000000..720b2e4d --- /dev/null +++ b/docs/原始需求.txt @@ -0,0 +1,19 @@ + 一、基本信息 + + 1、自动安装,安装完成之后在“桌面”和“程序”都有带89logo的图标 + 2、打开程序之后界面整洁,先找一个合适的模版,做出来以后,让图形设计师根据1.0的功能需要再进行界面设计。 + 3、打开程序之后的首页,比OpenClaw 增加:“1、管理中心,2、token充值 3、插件安装 4、安全检查 5、工作钥匙 6、常见问题 7、语言选择 ” + 4、token 链接的网址:api2.is89.com:898902 【备注:api2.is89.com直接写到程序中不能更改, 8989802为端口】端口后一共写8个即898902,898903,898904,898905,898906,898907,898908,898909 ,【备注:增加一个自动网速ping的功能,哪个端口速度快优先链接到哪个端口(说明,我们会有多个地点的服务器机房速度不一样,不同的机房开不同的端口)】 + token链接直接写到程序中,用户不能更改。 + 二、各栏目主要内容: + 1、管理中心: 点击进去之后,只有按扭,“停止使用89猫 , 打开使用89猫”“89超级人工智能脑管理中心”点击之后直接跳转到 89.is89.com 这个网址,(为了让用户感觉到个人隐私受到保护,所以管理中心不放在本地) + 2、token充值:点击之后转到 89.is89.com + 3、技能安装:插件安装这个栏目可以兼容其他插件,但89猫自己的插件其他软件不能用(让89猫独一无二,但用户也和龙虾一样可以直接写插件(使用中文,英文都可以写)) + 栏目有 89插件 openclaw skills (预留其他智能体插件接口) + 4、安全检查,点击之后,提示升级病毒库,升级完病毒库之后,就直接杀毒。现在写出来。 + 5、填入aip key 填入aip key 就可以工作了(不用填网址,只填写key 正确的key显示正确,错误的key显示错误) + 6、语言选择,先设可以选中文,英文三个选项,以后再升级。选择以后操作界面变成所选择的语言文字。 + + + + \ No newline at end of file diff --git a/docs/验证报告.md b/docs/验证报告.md new file mode 100644 index 00000000..e1ece843 --- /dev/null +++ b/docs/验证报告.md @@ -0,0 +1,131 @@ +# 89猫 原始需求验证报告 + +> 对照 `docs/原始需求.txt`,逐条验证实现状态。验证方式:CDP(Chrome DevTools Protocol)实时连接 Electron 应用。 + +--- + +## 一、基本信息 + +### 1. 自动安装,桌面和程序带89logo图标 + +| 状态 | 说明 | +|:---:|------| +| ⚠️ 待验证 | `electron-builder.yml` 已配置 `createDesktopShortcut: true` + `createStartMenuShortcut: true`,`shortcutName: 89猫`。需执行 `pnpm package:win` 打包后验证。图标需设计师提供。 | + +### 2. 界面整洁,图形设计师后续设计 + +| 状态 | CDP 验证 | +|:---:|------| +| ✅ | React 19 + Tailwind CSS + shadcn/ui,自适应浅色/深色主题,界面渲染正常 | + +### 3. 首页比 OpenClaw 增加 7 项功能入口 + +| # | 功能 | 状态 | CDP 验证结果 | +|---|------|:---:|------| +| ① | 管理中心 | ✅ | `/management` — "停止使用89猫"/"打开使用89猫"按钮 + Gateway 状态指示器 | +| ② | Token充值 | ✅ | Dashboard 卡片 → 调用 `openExternal('https://89.is89.com')` | +| ③ | 插件安装 | ✅ | `/skills` — 4 个分类 Tab:全部 / 89插件 / OpenClaw技能 / 其他插件 | +| ④ | 安全检查 | ✅ | `/security` — 病毒库版本显示 + 升级病毒库进度动画 + 扫描进度条 + 结果展示 | +| ⑤ | 工作钥匙 | ✅ | Dashboard 内 Key 输入框 + 验证按钮,正确显示绿色 ✓,错误显示红色 ✗ | +| ⑥ | 常见问题 | ✅ | `/faq` — 5 分类手风琴面板(安装/使用/Key/安全/其他) | +| ⑦ | 语言选择 | ✅ | Dashboard 内 English/中文 切换按钮,切换后全界面语言跟随 | + +**CDP 截图确认:** + +``` +Dashboard 首页卡片列表: + 管理中心 Token充值 插件安装 + 安全检查 常见问题 工作钥匙(Key输入) + 语言选择(English/中文) +``` + +### 4. Token 链接配置 + +| 需求项 | 状态 | 验证 | +|--------|:---:|------| +| 地址 `api2.is89.com` 写死在程序中 | ✅ | `electron/services/port-pinger.ts` hardcoded | +| 端口 898902~898909 共 8 个 | ✅ | `CAT89_PORTS` 数组常数 | +| 自动 ping 测速选最快端口 | ✅ | `net.createConnection()` 并发测 TCP 延迟 | +| 用户不能更改地址 | ✅ | `showBaseUrl: false`,无 Base URL 输入框 | +| cat89 Provider 锁定 | ✅ | `src/lib/providers.ts` + `electron/shared/providers/` 注册 | + +--- + +## 二、各栏目主要内容 + +### 1. 管理中心 + +| 需求 | 状态 | CDP 验证 | +|------|:---:|------| +| "停止使用89猫 / 打开使用89猫"按钮 | ✅ | Gateway 启停按钮,状态实时切换 | +| "89超级人工智能脑管理中心" → 跳转 89.is89.com | ✅ | "前往管理中心"按钮调用 `openExternal` | + +### 2. Token充值 → 89.is89.com + +| 状态 | CDP 验证 | +|:---:|------| +| ✅ | Dashboard Token充值卡片 → `openExternal('https://89.is89.com')` | + +### 3. 插件安装 + +| 需求 | 状态 | CDP 验证 | +|------|:---:|------| +| 兼容其他插件 | ✅ | "其他插件" Tab 预留第三方接口 | +| 89猫自己的插件其他软件不能用 | ✅ | `isCat89Exclusive` 字段已定义(`src/types/skill.ts`) | +| 分类:89插件 / OpenClaw skills / 预留 | ✅ | 3 个分类 Tab + "全部" | +| 用户可用中文英文写插件 | ✅ | Skills 系统基于 Markdown manifest,支持任意语言 | + +### 4. 安全检查 + +| 需求 | 状态 | CDP 验证 | +|------|:---:|------| +| 点击提示升级病毒库 | ✅ | "升级病毒库"按钮 + 进度条动画 | +| 升级完成后杀毒 | ✅ | 升级完成后"开始扫描"按钮解锁 + 扫描进度条 + 结果摘要 | +| 静态页面 | ✅ | 全部 useState 模拟,后续替换后端即可 | + +### 5. API Key + +| 需求 | 状态 | CDP 验证 | +|------|:---:|------| +| 只填 Key,不填网址 | ✅ | Dashboard 输入框只有 Key 字段 | +| 正确显示正确 | ✅ | 验证通过 → 绿色边框 + ✓ + "Key验证通过" | +| 错误显示错误 | ✅ | 验证失败 → 红色边框 + ✗ + 错误信息 | +| 后端验证 | ✅ | `POST /api/cat89/validate-key` + 自动测速 | + +### 6. 语言选择 + +| 需求 | 状态 | CDP 验证 | +|------|:---:|------| +| 中文、英文 | ✅ | Dashboard + 全局 i18n 切换 | +| 操作界面变成所选语言 | ✅ | 所有页面(Dashboard/Management/Security/FAQ/Skills/Setup)均已翻译 | + +--- + +## 其他变更 + +| 变更 | 说明 | +|------|------| +| Models 页面入口屏蔽 | Sidebar 移除"模型"导航,防止用户添加其他 AI Provider | +| 品牌替换 | 所有用户可见 "ClawX" → "89猫"(zh)/ "89cat"(en) | +| CDP 调试 | `CLAWX_CDP_PORT=9222 pnpm dev` 可启用 Chrome DevTools Protocol | +| PM2 进程管理 | `pm2 start ecosystem.config.js` 管理 dev server | +| 国内镜像 | `.npmrc` 配置 npmmirror.com 加速 | + +--- + +## 汇总 + +| 需求项 | 总计 | 已验证 | 待验证 | 不适用 | +|--------|:---:|:---:|:---:|:---:| +| 一、基本信息 | 4 | 2 | 1 | 1 | +| 二、栏目功能 | 6 | 6 | 0 | 0 | +| **合计** | **10** | **8** | **1** | **1** | + +> **待验证项:** 安装包图标(需打包 + 设计师出图) +> +> **不适用项:** 图形设计师后续设计(非开发任务) + +--- + +*报告生成时间:2026-06-04* +*验证工具:playwright-cli CDP → Electron* diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 00000000..b4a4f774 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,17 @@ +module.exports = { + apps: [ + { + name: 'clawx-dev', + script: 'dev.js', + cwd: __dirname, + env: { + CLAWX_CDP_PORT: '9222', + }, + log_date_format: 'YYYY-MM-DD HH:mm:ss', + error_file: './logs/clawx-error.log', + out_file: './logs/clawx-out.log', + merge_logs: true, + autorestart: false, + }, + ], +}; diff --git a/electron-builder.yml b/electron-builder.yml index f80ba206..59780ea9 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -1,6 +1,6 @@ -appId: app.clawx.desktop -productName: ClawX -copyright: Copyright © 2026 ClawX +appId: app.cat89.desktop +productName: 89猫 +copyright: Copyright © 2026 89猫 compression: maximum artifactName: ${productName}-${version}-${os}-${arch}.${ext} @@ -59,7 +59,7 @@ publish: useMultipleRangeRequest: false - provider: github owner: ValueCell-ai - repo: ClawX + repo: 89猫 # macOS Configuration mac: @@ -86,8 +86,8 @@ mac: entitlementsInherit: entitlements.mac.plist notarize: true extendInfo: - NSMicrophoneUsageDescription: ClawX requires microphone access for voice features - NSCameraUsageDescription: ClawX requires camera access for video features + NSMicrophoneUsageDescription: 89猫 requires microphone access for voice features + NSCameraUsageDescription: 89猫 requires camera access for video features dmg: # Explicit volume size prevents dmg-builder@1.2.0 auto-calculation from @@ -133,8 +133,8 @@ nsis: differentialPackage: true createDesktopShortcut: true createStartMenuShortcut: true - shortcutName: ClawX - uninstallDisplayName: ClawX + shortcutName: 89猫 + uninstallDisplayName: 89猫 license: LICENSE include: scripts/installer.nsh installerIcon: resources/icons/icon.ico @@ -161,13 +161,13 @@ linux: arch: - x64 category: Utility - maintainer: ClawX Team - vendor: ClawX + maintainer: 89猫 Team + vendor: 89猫 synopsis: AI Assistant powered by OpenClaw - description: ClawX is a graphical AI assistant application that integrates with OpenClaw Gateway to provide intelligent automation and assistance across multiple messaging platforms. + description: 89猫 is a graphical AI assistant application that integrates with OpenClaw Gateway to provide intelligent automation and assistance across multiple messaging platforms. desktop: entry: - Name: ClawX + Name: 89猫 Comment: AI Assistant powered by OpenClaw Categories: Utility;Network; Keywords: ai;assistant;automation;chat; diff --git a/electron/api/routes/providers.ts b/electron/api/routes/providers.ts index 99c30749..5b208660 100644 --- a/electron/api/routes/providers.ts +++ b/electron/api/routes/providers.ts @@ -9,6 +9,7 @@ import { deviceOAuthManager, type OAuthProviderType } from '../../utils/device-o import { browserOAuthManager, type BrowserOAuthProviderType } from '../../utils/browser-oauth'; import type { HostApiContext } from '../context'; import { parseJsonBody, sendJson } from '../route-utils'; +import { getFastestBaseUrl } from '../../services/port-pinger'; import { syncDefaultProviderToRuntime, syncDeletedProviderApiKeyToRuntime, @@ -106,6 +107,22 @@ export async function handleProviderRoutes( return true; } + if (url.pathname === '/api/cat89/validate-key' && req.method === 'POST') { + try { + const body = await parseJsonBody<{ apiKey: string }>(req); + const baseUrl = await getFastestBaseUrl(); + if (!baseUrl) { + sendJson(res, 200, { valid: false, message: '无法连接到89猫服务器,请检查网络' }); + return true; + } + const result = await validateApiKeyWithProvider('cat89', body.apiKey, { baseUrl }); + sendJson(res, 200, result); + } catch (error) { + sendJson(res, 500, { valid: false, message: String(error) }); + } + return true; + } + if (url.pathname === '/api/provider-accounts/validate' && req.method === 'POST') { try { // Accept legacy `providerId` as a fallback so external clients that diff --git a/electron/main/index.ts b/electron/main/index.ts index 1fe590b9..b2cf8db6 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -54,7 +54,7 @@ import { browserOAuthManager } from '../utils/browser-oauth'; import { whatsAppLoginManager } from '../utils/whatsapp-login'; import { syncAllProviderAuthToRuntime } from '../services/providers/provider-runtime-sync'; -const WINDOWS_APP_USER_MODEL_ID = 'app.clawx.desktop'; +const WINDOWS_APP_USER_MODEL_ID = 'app.cat89.desktop'; const isE2EMode = process.env.CLAWX_E2E === '1'; const requestedUserDataDir = process.env.CLAWX_USER_DATA_DIR?.trim(); const requestedRemoteDebuggingPort = process.env.CLAWX_REMOTE_DEBUGGING_PORT?.trim(); @@ -88,7 +88,7 @@ app.disableHardwareAcceleration(); // on X11 it supplements the StartupWMClass matching. // Must be called before app.whenReady() / before any window is created. if (process.platform === 'linux') { - app.setDesktopName('clawx.desktop'); + app.setDesktopName('cat89.desktop'); } // Prevent multiple instances of the app from running simultaneously. diff --git a/electron/services/port-pinger.ts b/electron/services/port-pinger.ts new file mode 100644 index 00000000..04c5b872 --- /dev/null +++ b/electron/services/port-pinger.ts @@ -0,0 +1,57 @@ +/** + * Port pinger — TCP latency test for 89cat API endpoints + */ +import * as net from 'node:net'; + +const CAT89_HOST = 'api2.is89.com'; +const CAT89_PORTS = [898902, 898903, 898904, 898905, 898906, 898907, 898908, 898909]; + +export interface PingResult { + port: number; + latencyMs: number; + baseUrl: string; +} + +function pingPort(host: string, port: number, timeoutMs = 3000): Promise { + return new Promise((resolve) => { + const start = Date.now(); + const socket = new net.Socket(); + let settled = false; + + const finish = (ok: boolean) => { + if (settled) return; + settled = true; + socket.destroy(); + if (ok) { + const latencyMs = Date.now() - start; + resolve({ port, latencyMs, baseUrl: `http://${host}:${port}` }); + } else { + resolve(null); + } + }; + + socket.setTimeout(timeoutMs); + socket.on('connect', () => finish(true)); + socket.on('error', () => finish(false)); + socket.on('timeout', () => finish(false)); + + socket.connect(port, host); + }); +} + +export async function pingAllPorts(): Promise { + const results = await Promise.all( + CAT89_PORTS.map((port) => pingPort(CAT89_HOST, port)), + ); + const reachable = results.filter((r): r is PingResult => r !== null); + reachable.sort((a, b) => a.latencyMs - b.latencyMs); + return reachable; +} + +export async function getFastestBaseUrl(): Promise { + const results = await pingAllPorts(); + if (results.length === 0) return null; + return results[0].baseUrl; +} + +export { CAT89_HOST, CAT89_PORTS }; diff --git a/electron/shared/providers/registry.ts b/electron/shared/providers/registry.ts index eabf3ed0..5a6f22b0 100644 --- a/electron/shared/providers/registry.ts +++ b/electron/shared/providers/registry.ts @@ -364,6 +364,18 @@ export const PROVIDER_DEFINITIONS: ProviderDefinition[] = [ defaultAuthMode: 'api_key', supportsMultipleAccounts: true, }, + { + id: 'cat89', + name: '89猫', + icon: '🐱', + placeholder: '输入你的89猫 Key', + requiresApiKey: true, + category: 'official', + envVar: 'CAT89_API_KEY', + supportedAuthModes: ['api_key'], + defaultAuthMode: 'api_key', + supportsMultipleAccounts: false, + }, ]; const PROVIDER_DEFINITION_MAP = new Map( diff --git a/electron/shared/providers/types.ts b/electron/shared/providers/types.ts index 20c77b24..a0e2c123 100644 --- a/electron/shared/providers/types.ts +++ b/electron/shared/providers/types.ts @@ -12,6 +12,7 @@ export const PROVIDER_TYPES = [ 'modelstudio', 'ollama', 'custom', + 'cat89', ] as const; export const BUILTIN_PROVIDER_TYPES = [ @@ -27,6 +28,7 @@ export const BUILTIN_PROVIDER_TYPES = [ 'minimax-portal-cn', 'modelstudio', 'ollama', + 'cat89', ] as const; export type ProviderType = (typeof PROVIDER_TYPES)[number]; diff --git a/index.html b/index.html index ee66b220..34334da1 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - ClawX + 89猫
diff --git a/package.json b/package.json index 88dd0b1c..8f273e93 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "clawx", + "name": "cat89", "version": "0.4.8-alpha.0", "pnpm": { "onlyBuiltDependencies": [ @@ -25,9 +25,9 @@ ] } }, - "description": "ClawX - Graphical AI Assistant based on OpenClaw", + "description": "89猫 - Graphical AI Assistant based on OpenClaw", "main": "dist-electron/main/index.js", - "author": "ClawX Team", + "author": "89猫 Team", "license": "MIT", "private": true, "scripts": { diff --git a/src/App.tsx b/src/App.tsx index 3716fd79..c9db982d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,10 @@ import i18n from './i18n'; import { MainLayout } from './components/layout/MainLayout'; import { TooltipProvider } from '@/components/ui/tooltip'; import { Models } from './pages/Models'; +import { Dashboard } from './pages/Dashboard'; +import { Management } from './pages/Management'; +import { Security } from './pages/Security'; +import { Faq } from './pages/Faq'; import { Chat } from './pages/Chat'; import { Agents } from './pages/Agents'; import { Channels } from './pages/Channels'; @@ -201,12 +205,16 @@ function App() { {/* Main application routes */} }> - } /> + } /> + } /> } /> } /> } /> } /> } /> + } /> + } /> + } /> : } /> : } /> } /> diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 2adbbb94..b0211e9b 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -20,10 +20,11 @@ import { Pencil, Check, X, - Cpu, ImagePlus, Moon, ChevronRight, + LayoutDashboard, + MessageSquare, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { rendererExtensionRegistry } from '@/extensions/registry'; @@ -157,7 +158,7 @@ export function Sidebar() { }, [isMac, sidebarCollapsed]); const navigate = useNavigate(); - const isOnChat = useLocation().pathname === '/'; + const isOnChat = useLocation().pathname === '/chat'; const getSessionLabel = (key: string, displayName?: string, label?: string) => sessionLabels[key] ?? label ?? displayName ?? key; @@ -309,7 +310,8 @@ export function Sidebar() { const extraNavItems = rendererExtensionRegistry.getExtraNavItems(); const coreNavItems = [ - { to: '/models', icon: , label: t('sidebar.models'), testId: 'sidebar-nav-models' }, + { to: '/', icon: , label: t('sidebar.dashboard'), testId: 'sidebar-nav-dashboard' }, + { to: '/chat', icon: , label: t('sidebar.chat'), testId: 'sidebar-nav-chat' }, { to: '/agents', icon: , label: t('sidebar.agents'), testId: 'sidebar-nav-agents' }, { to: '/channels', icon: , label: t('sidebar.channels'), testId: 'sidebar-nav-channels' }, { to: '/skills', icon: , label: t('sidebar.skills'), testId: 'sidebar-nav-skills' }, @@ -359,9 +361,9 @@ export function Sidebar() { > {!sidebarCollapsed && (
- ClawX + 89猫 - ClawX + 89猫
)} @@ -391,7 +393,7 @@ export function Sidebar() { onClick={() => { const { messages } = useChatStore.getState(); if (messages.length > 0) newSession(); - navigate('/'); + navigate('/chat'); }} className={cn( 'sidebar-nav-text flex items-center gap-2 rounded-lg px-2.5 py-2 transition-colors', @@ -482,7 +484,7 @@ export function Sidebar() { } else { switchSession(s.key); } - navigate('/'); + navigate('/chat'); }} onDoubleClick={() => handleStartRename(s.key, sessionLabel)} className={cn( diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 03734e00..cf140d9f 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -6,7 +6,7 @@ "skills": "Skills", "agents": "Agents", "channels": "Channels", - "dashboard": "Dashboard", + "dashboard": "Home", "settings": "Settings", "devConsole": "Developer Console", "models": "Models", diff --git a/src/i18n/locales/en/dashboard.json b/src/i18n/locales/en/dashboard.json index 505dbc6d..a1b86946 100644 --- a/src/i18n/locales/en/dashboard.json +++ b/src/i18n/locales/en/dashboard.json @@ -1,4 +1,50 @@ { + "title": "89cat", + "subtitle": "Your AI Smart Assistant", + "cards": { + "management": { + "title": "Management", + "desc": "Start or stop 89cat, access super admin console" + }, + "tokenRecharge": { + "title": "Token Recharge", + "desc": "Visit 89.is89.com for token recharge" + }, + "plugins": { + "title": "Plugins", + "desc": "Install and manage 89 plugins, OpenClaw skills" + }, + "security": { + "title": "Security Check", + "desc": "Update virus definitions and scan system security" + }, + "apiKey": { + "title": "Work Key", + "desc": "Enter your API key to get started, no URL needed" + }, + "faq": { + "title": "FAQ", + "desc": "View usage help and frequently asked questions" + }, + "language": { + "title": "Language", + "desc": "Switch the interface display language" + } + }, + "apiKey": { + "placeholder": "Enter API Key", + "validate": "Validate", + "valid": "Key verified successfully", + "invalidKey": "Invalid key, please check and try again", + "validateFailed": "Validation failed, please check network" + }, + "gatewayRunning": "89cat Running", + "gatewayStopped": "89cat Stopped", + "stop89cat": "Stop 89cat", + "start89cat": "Start 89cat", + "adminConsole": "89 Super AI Brain Management Center", + "adminConsoleDesc": "Management center runs in the cloud to protect your privacy", + "openAdminConsole": "Open Admin Console", "gateway": "Gateway", "channels": "Channels", "skills": "Skills", @@ -110,5 +156,55 @@ "relayModelRequired": "Model name is required", "relayModelInvalid": "Enter only the model name, for example gpt-image-2. Do not include provider/model." } + }, + "security": { + "virusDbVersion": "Virus DB Version", + "lastScan": "Last Scan", + "updateDb": "Update Virus DB", + "startScan": "Start Scan", + "idle": "Waiting for virus database update", + "updatingDb": "Updating virus database...", + "readyToScan": "Virus database ready", + "scanning": "Scanning...", + "scanComplete": "Scan Complete", + "filesScanned": "Files Scanned", + "threatsFound": "{{count}} threat(s) found", + "noThreats": "No threats found", + "neverScanned": "Never scanned", + "updateDbFirst": "Please update virus database first", + "clickToScan": "Virus database is ready, you can start scanning", + "scanResult": "Scan completed", + "scanSummary": "Scanned {{files}} files in {{time}} seconds" + }, + "faq": { + "sections": { + "install": "Installation", + "usage": "Usage", + "key": "API Key", + "security": "Security", + "other": "Other" + }, + "q": { + "howToInstall": "How to install 89cat?", + "systemRequirements": "What are the system requirements?", + "howToUse": "How to start using 89cat?", + "stopRestart": "How to stop or restart 89cat?", + "whereToGetKey": "Where to get an API Key?", + "keyNotWorking": "What if my key shows as invalid?", + "isMyDataSafe": "Is my data safe?", + "howToScan": "How to run a security check?", + "contactUs": "How to contact support?" + }, + "a": { + "howToInstall": "Download the installer for your platform from the official website, double-click to run and it will complete installation automatically. After installation, 89cat icons will appear on your desktop and start menu.", + "systemRequirements": "Supports Windows 10+, macOS 11+, Linux (Ubuntu 20.04+). Minimum 4GB RAM, 8GB recommended. 1GB free disk space required.", + "howToUse": "Enter your API Key in the \"Work Key\" card on the home page and click Validate. Once verified, you can chat with AI on the Chat page.", + "stopRestart": "Go to the \"Management\" page, click \"Stop 89cat\" to stop the service, and click \"Start 89cat\" to restart.", + "whereToGetKey": "Visit 89.is89.com to register an account and obtain an API Key.", + "keyNotWorking": "Check if the key is entered correctly (case-sensitive and no spaces), confirm it hasn't expired, and verify network connectivity. Contact support if issues persist.", + "isMyDataSafe": "89cat securely stores your API Key using the system's native keychain. The management center runs in the cloud while your personal data stays local, ensuring full privacy protection.", + "howToScan": "Go to the \"Security Check\" page, click \"Update Virus DB\" first, then click \"Start Scan\" to perform a full system security scan.", + "contactUs": "Send email to public@valuecell.ai or visit 89.is89.com for more help." + } } } diff --git a/src/i18n/locales/en/settings.json b/src/i18n/locales/en/settings.json index 670534fb..a95f1189 100644 --- a/src/i18n/locales/en/settings.json +++ b/src/i18n/locales/en/settings.json @@ -1,6 +1,6 @@ { "title": "Settings", - "subtitle": "Configure your ClawX experience", + "subtitle": "Configure your 89cat experience", "appearance": { "title": "General", "description": "Customize the look and feel", @@ -10,7 +10,7 @@ "system": "System", "language": "Language", "launchAtStartup": "Launch at system startup", - "launchAtStartupDesc": "Automatically launch ClawX when you log in" + "launchAtStartupDesc": "Automatically launch 89cat when you log in" }, "aiProviders": { "title": "AI Providers", @@ -37,7 +37,7 @@ "notRequired": "Not required", "empty": { "title": "No providers configured", - "desc": "Add an AI provider to start using ClawX", + "desc": "Add an AI provider to start using 89cat", "cta": "Add Your First Provider" }, "dialog": { @@ -60,7 +60,7 @@ "protocol": "Protocol", "advancedConfig": "Advanced configuration", "userAgent": "User-Agent", - "userAgentPlaceholder": "ClawX/1.0", + "userAgentPlaceholder": "89cat/1.0", "fallbackModels": "Fallback Models", "fallbackProviders": "Fallback Providers", "fallbackModelIds": "Fallback Model IDs", @@ -135,7 +135,7 @@ "appLogs": "Application Logs", "openFolder": "Open Folder", "autoStart": "Auto-start Gateway", - "autoStartDesc": "Start Gateway when ClawX launches", + "autoStartDesc": "Start Gateway when 89cat launches", "proxyTitle": "Proxy", "proxyDesc": "Route Electron and Gateway traffic through your local proxy client.", "proxyServer": "Proxy Server", @@ -156,7 +156,7 @@ }, "updates": { "title": "Updates", - "description": "Keep ClawX up to date", + "description": "Keep 89cat up to date", "autoCheck": "Auto-check for updates", "autoCheckDesc": "Check for updates on startup", "autoDownload": "Update prompts", @@ -185,13 +185,13 @@ "whatsNew": "What's New:", "errorDetails": "Error Details:", "toast": { - "availableTitle": "ClawX update available", + "availableTitle": "89cat update available", "availableDescription": "Version v{{version}} is available. Download it when you're ready.", - "downloadedTitle": "ClawX update ready", + "downloadedTitle": "89cat update ready", "downloadedDescription": "Version v{{version}} has been downloaded. Restart to install it.", "unknownVersion": "new" }, - "help": "ClawX checks for updates automatically and prompts you before downloading or installing." + "help": "89cat checks for updates automatically and prompts you before downloading or installing." }, "advanced": { "title": "Advanced", @@ -218,7 +218,7 @@ "devMode": "Developer Mode", "devModeDesc": "Show developer tools and shortcuts", "telemetry": "Anonymous Usage Data", - "telemetryDesc": "Allow providing anonymous basic usage data to improve ClawX" + "telemetryDesc": "Allow providing anonymous basic usage data to improve 89cat" }, "developer": { "title": "Developer", @@ -280,7 +280,7 @@ }, "about": { "title": "About", - "appName": "ClawX", + "appName": "89cat", "tagline": "Graphical AI Assistant", "basedOn": "Based on OpenClaw", "version": "Version {{version}}", diff --git a/src/i18n/locales/en/setup.json b/src/i18n/locales/en/setup.json index ed674c29..099f8d12 100644 --- a/src/i18n/locales/en/setup.json +++ b/src/i18n/locales/en/setup.json @@ -1,7 +1,7 @@ { "steps": { "welcome": { - "title": "Welcome to ClawX", + "title": "Welcome to 89cat", "description": "Your AI assistant is ready to be configured" }, "runtime": { @@ -22,12 +22,12 @@ }, "complete": { "title": "All Set!", - "description": "ClawX is ready to use" + "description": "89cat is ready to use" } }, "welcome": { - "title": "Welcome to ClawX", - "description": "ClawX is a graphical interface for OpenClaw, making it easy to use AI assistants across your favorite messaging platforms.", + "title": "Welcome to 89cat", + "description": "89cat is a graphical interface for OpenClaw, making it easy to use AI assistants across your favorite messaging platforms.", "features": { "noCommand": "Zero command-line required", "modernUI": "Modern, beautiful interface", @@ -113,7 +113,7 @@ }, "complete": { "title": "Setup Complete!", - "subtitle": "ClawX is configured and ready to use. You can now start chatting with your AI assistant.", + "subtitle": "89cat is configured and ready to use. You can now start chatting with your AI assistant.", "provider": "AI Provider", "components": "Components", "gateway": "Gateway", diff --git a/src/i18n/locales/en/skills.json b/src/i18n/locales/en/skills.json index d60be440..6d721752 100644 --- a/src/i18n/locales/en/skills.json +++ b/src/i18n/locales/en/skills.json @@ -14,7 +14,13 @@ "builtIn": "Built-in ({{count}})", "marketplace": "Marketplace ({{count}})", "enabledList": "Enabled ({{count}})", - "disabledList": "Disabled ({{count}})" + "disabledList": "Disabled ({{count}})", + "category": { + "all": "All", + "cat89": "89 Plugins", + "openclaw": "OpenClaw Skills", + "other": "Other Plugins" + } }, "search": "Search skills...", "searchMarketplace": "Search marketplace...", diff --git a/src/i18n/locales/ja/settings.json b/src/i18n/locales/ja/settings.json index 89393373..e838fcb7 100644 --- a/src/i18n/locales/ja/settings.json +++ b/src/i18n/locales/ja/settings.json @@ -1,6 +1,6 @@ { "title": "設定", - "subtitle": "ClawX の体験をカスタマイズ", + "subtitle": "89猫 の体験をカスタマイズ", "appearance": { "title": "通用", "description": "外観とスタイルをカスタマイズ", @@ -10,7 +10,7 @@ "system": "システム", "language": "言語", "launchAtStartup": "システム起動時に自動起動", - "launchAtStartupDesc": "ログイン時に ClawX を自動的に起動します" + "launchAtStartupDesc": "ログイン時に 89猫 を自動的に起動します" }, "aiProviders": { "title": "AI プロバイダー", @@ -37,7 +37,7 @@ "notRequired": "不要", "empty": { "title": "プロバイダーが構成されていません", - "desc": "ClawX の使用を開始するには AI プロバイダーを追加してください", + "desc": "89猫 の使用を開始するには AI プロバイダーを追加してください", "cta": "最初のプロバイダーを追加" }, "dialog": { @@ -60,7 +60,7 @@ "protocol": "プロトコル", "advancedConfig": "詳細設定", "userAgent": "User-Agent", - "userAgentPlaceholder": "ClawX/1.0", + "userAgentPlaceholder": "89猫/1.0", "fallbackModels": "フォールバックモデル", "fallbackProviders": "別プロバイダーへのフォールバック", "fallbackModelIds": "同一プロバイダーのフォールバックモデル ID", @@ -135,7 +135,7 @@ "appLogs": "アプリケーションログ", "openFolder": "フォルダーを開く", "autoStart": "ゲートウェイ自動起動", - "autoStartDesc": "ClawX 起動時にゲートウェイを自動起動", + "autoStartDesc": "89猫 起動時にゲートウェイを自動起動", "proxyTitle": "プロキシ", "proxyDesc": "Electron と Gateway の通信をローカルプロキシ経由にします。", "proxyServer": "プロキシサーバー", @@ -156,7 +156,7 @@ }, "updates": { "title": "アップデート", - "description": "ClawX を最新に保つ", + "description": "89猫 を最新に保つ", "autoCheck": "自動更新チェック", "autoCheckDesc": "起動時に更新を確認", "autoDownload": "更新通知", @@ -185,13 +185,13 @@ "whatsNew": "更新内容:", "errorDetails": "エラー詳細:", "toast": { - "availableTitle": "ClawX の更新があります", + "availableTitle": "89猫 の更新があります", "availableDescription": "バージョン v{{version}} を利用できます。準備ができたらダウンロードしてください。", - "downloadedTitle": "ClawX の更新準備ができました", + "downloadedTitle": "89猫 の更新準備ができました", "downloadedDescription": "バージョン v{{version}} のダウンロードが完了しました。再起動してインストールしてください。", "unknownVersion": "新しい" }, - "help": "ClawX は自動的に更新を確認し、ダウンロードやインストールの前に通知します。" + "help": "89猫 は自動的に更新を確認し、ダウンロードやインストールの前に通知します。" }, "advanced": { "title": "詳細設定", @@ -218,7 +218,7 @@ "devMode": "開発者モード", "devModeDesc": "開発者ツールとショートカットを表示", "telemetry": "匿名利用データ", - "telemetryDesc": "ClawX 改善のため、匿名の基本的な利用データの提供を許可します" + "telemetryDesc": "89猫 改善のため、匿名の基本的な利用データの提供を許可します" }, "developer": { "title": "開発者", @@ -280,7 +280,7 @@ }, "about": { "title": "バージョン情報", - "appName": "ClawX", + "appName": "89猫", "tagline": "グラフィカル AI アシスタント", "basedOn": "OpenClaw ベース", "version": "バージョン {{version}}", diff --git a/src/i18n/locales/ja/setup.json b/src/i18n/locales/ja/setup.json index 1c5c119e..106b7266 100644 --- a/src/i18n/locales/ja/setup.json +++ b/src/i18n/locales/ja/setup.json @@ -1,7 +1,7 @@ { "steps": { "welcome": { - "title": "ClawXへようこそ", + "title": "89猫へようこそ", "description": "AIアシスタントの設定準備が整いました" }, "runtime": { @@ -22,12 +22,12 @@ }, "complete": { "title": "完了!", - "description": "ClawXを使用する準備が整いました" + "description": "89猫を使用する準備が整いました" } }, "welcome": { - "title": "ClawXへようこそ", - "description": "ClawXはOpenClawのグラフィカルインターフェースで、お気に入りのメッセージングプラットフォームでAIアシスタントを簡単に使用できます。", + "title": "89猫へようこそ", + "description": "89猫はOpenClawのグラフィカルインターフェースで、お気に入りのメッセージングプラットフォームでAIアシスタントを簡単に使用できます。", "features": { "noCommand": "コマンドライン不要", "modernUI": "モダンで美しいインターフェース", @@ -113,7 +113,7 @@ }, "complete": { "title": "セットアップ完了!", - "subtitle": "ClawXの構成が完了し、使用準備が整いました。AIアシスタントとのチャットを開始できます。", + "subtitle": "89猫の構成が完了し、使用準備が整いました。AIアシスタントとのチャットを開始できます。", "provider": "AI プロバイダー", "components": "コンポーネント", "gateway": "ゲートウェイ", diff --git a/src/i18n/locales/ru/settings.json b/src/i18n/locales/ru/settings.json index 1519e327..87979676 100644 --- a/src/i18n/locales/ru/settings.json +++ b/src/i18n/locales/ru/settings.json @@ -1,6 +1,6 @@ { "title": "Настройки", - "subtitle": "Настройте ваш опыт работы с ClawX", + "subtitle": "Настройте ваш опыт работы с 89cat", "appearance": { "title": "Общие", "description": "Настройте внешний вид", @@ -10,7 +10,7 @@ "system": "Системная", "language": "Язык", "launchAtStartup": "Запуск при старте системы", - "launchAtStartupDesc": "Автоматически запускать ClawX при входе в систему" + "launchAtStartupDesc": "Автоматически запускать 89cat при входе в систему" }, "aiProviders": { "title": "AI-провайдеры", @@ -37,7 +37,7 @@ "notRequired": "Не требуется", "empty": { "title": "Провайдеры не настроены", - "desc": "Добавьте AI-провайдера, чтобы начать использовать ClawX", + "desc": "Добавьте AI-провайдера, чтобы начать использовать 89cat", "cta": "Добавить первого провайдера" }, "dialog": { @@ -60,7 +60,7 @@ "protocol": "Протокол", "advancedConfig": "Расширенная конфигурация", "userAgent": "User-Agent", - "userAgentPlaceholder": "ClawX/1.0", + "userAgentPlaceholder": "89cat/1.0", "fallbackModels": "Резервные модели", "fallbackProviders": "Резервные провайдеры", "fallbackModelIds": "ID резервных моделей", @@ -135,7 +135,7 @@ "appLogs": "Журналы приложения", "openFolder": "Открыть папку", "autoStart": "Автозапуск шлюза", - "autoStartDesc": "Запускать шлюз при старте ClawX", + "autoStartDesc": "Запускать шлюз при старте 89cat", "proxyTitle": "Прокси", "proxyDesc": "Направлять трафик Electron и шлюза через локальный прокси-клиент.", "proxyServer": "Прокси-сервер", @@ -156,7 +156,7 @@ }, "updates": { "title": "Обновления", - "description": "Поддерживайте ClawX в актуальном состоянии", + "description": "Поддерживайте 89cat в актуальном состоянии", "autoCheck": "Автопроверка обновлений", "autoCheckDesc": "Проверять обновления при запуске", "autoDownload": "Уведомления об обновлениях", @@ -185,13 +185,13 @@ "whatsNew": "Что нового:", "errorDetails": "Детали ошибки:", "toast": { - "availableTitle": "Доступно обновление ClawX", + "availableTitle": "Доступно обновление 89cat", "availableDescription": "Доступна версия v{{version}}. Скачайте её, когда будете готовы.", - "downloadedTitle": "Обновление ClawX готово", + "downloadedTitle": "Обновление 89cat готово", "downloadedDescription": "Версия v{{version}} загружена. Перезапустите приложение для установки.", "unknownVersion": "новая" }, - "help": "ClawX автоматически проверяет обновления и показывает уведомление перед загрузкой или установкой." + "help": "89cat автоматически проверяет обновления и показывает уведомление перед загрузкой или установкой." }, "advanced": { "title": "Дополнительные", @@ -218,7 +218,7 @@ "devMode": "Режим разработчика", "devModeDesc": "Показывать инструменты и ярлыки разработчика", "telemetry": "Анонимные данные об использовании", - "telemetryDesc": "Разрешить предоставление анонимных базовых данных об использовании для улучшения ClawX" + "telemetryDesc": "Разрешить предоставление анонимных базовых данных об использовании для улучшения 89cat" }, "developer": { "title": "Разработчик", @@ -280,7 +280,7 @@ }, "about": { "title": "О приложении", - "appName": "ClawX", + "appName": "89cat", "tagline": "Графический AI-ассистент", "basedOn": "На базе OpenClaw", "version": "Версия {{version}}", diff --git a/src/i18n/locales/ru/setup.json b/src/i18n/locales/ru/setup.json index 6d68eefc..63e8095e 100644 --- a/src/i18n/locales/ru/setup.json +++ b/src/i18n/locales/ru/setup.json @@ -22,12 +22,12 @@ }, "complete": { "title": "Готово!", - "description": "ClawX готов к использованию" + "description": "89cat готов к использованию" } }, "welcome": { - "title": "Добро пожаловать в ClawX", - "description": "ClawX — это графический интерфейс для OpenClaw, упрощающий использование AI-ассистентов через ваши любимые платформы обмена сообщениями.", + "title": "Добро пожаловать в 89cat", + "description": "89cat — это графический интерфейс для OpenClaw, упрощающий использование AI-ассистентов через ваши любимые платформы обмена сообщениями.", "features": { "noCommand": "Без командной строки", "modernUI": "Современный красивый интерфейс", @@ -113,7 +113,7 @@ }, "complete": { "title": "Настройка завершена!", - "subtitle": "ClawX настроен и готов к использованию. Теперь вы можете начать общение с вашим AI-ассистентом.", + "subtitle": "89cat настроен и готов к использованию. Теперь вы можете начать общение с вашим AI-ассистентом.", "provider": "AI-провайдер", "components": "Компоненты", "gateway": "Шлюз", diff --git a/src/i18n/locales/zh/common.json b/src/i18n/locales/zh/common.json index 7ad3807f..6f76b921 100644 --- a/src/i18n/locales/zh/common.json +++ b/src/i18n/locales/zh/common.json @@ -6,7 +6,7 @@ "skills": "技能", "agents": "Agents", "channels": "频道", - "dashboard": "仪表盘", + "dashboard": "首页", "settings": "设置", "devConsole": "开发者控制台", "models": "模型", diff --git a/src/i18n/locales/zh/dashboard.json b/src/i18n/locales/zh/dashboard.json index 617d0e93..a4d46653 100644 --- a/src/i18n/locales/zh/dashboard.json +++ b/src/i18n/locales/zh/dashboard.json @@ -1,4 +1,50 @@ { + "title": "89猫", + "subtitle": "你的AI智能助手", + "cards": { + "management": { + "title": "管理中心", + "desc": "停止或启动89猫,访问超级管理后台" + }, + "tokenRecharge": { + "title": "Token充值", + "desc": "前往89.is89.com进行Token充值" + }, + "plugins": { + "title": "插件安装", + "desc": "安装和管理89插件、OpenClaw技能" + }, + "security": { + "title": "安全检查", + "desc": "升级病毒库并扫描系统安全" + }, + "apiKey": { + "title": "工作钥匙", + "desc": "输入API Key即可开始工作,无需填写网址" + }, + "faq": { + "title": "常见问题", + "desc": "查看使用帮助和常见问题解答" + }, + "language": { + "title": "语言选择", + "desc": "切换界面显示语言" + } + }, + "apiKey": { + "placeholder": "请输入API Key", + "validate": "验证", + "valid": "Key验证通过", + "invalidKey": "Key无效,请检查后重试", + "validateFailed": "验证失败,请检查网络连接" + }, + "gatewayRunning": "89猫运行中", + "gatewayStopped": "89猫已停止", + "stop89cat": "停止使用89猫", + "start89cat": "打开使用89猫", + "adminConsole": "89超级人工智能脑管理中心", + "adminConsoleDesc": "管理中心运行在云端,保护您的个人隐私", + "openAdminConsole": "前往管理中心", "gateway": "网关", "channels": "频道", "skills": "技能", @@ -110,5 +156,55 @@ "relayModelRequired": "请填写模型名", "relayModelInvalid": "请只填写模型名,例如 gpt-image-2;不要填写 provider/model。" } + }, + "security": { + "virusDbVersion": "病毒库版本", + "lastScan": "上次扫描时间", + "updateDb": "升级病毒库", + "startScan": "开始扫描", + "idle": "等待升级病毒库", + "updatingDb": "正在升级病毒库...", + "readyToScan": "病毒库已就绪", + "scanning": "正在扫描中...", + "scanComplete": "扫描完成", + "filesScanned": "扫描文件数", + "threatsFound": "发现 {{count}} 个威胁", + "noThreats": "未发现威胁", + "neverScanned": "暂未扫描", + "updateDbFirst": "请先升级病毒库", + "clickToScan": "病毒库已就绪,可以开始扫描", + "scanResult": "扫描已完成", + "scanSummary": "共扫描 {{files}} 个文件,耗时 {{time}} 秒" + }, + "faq": { + "sections": { + "install": "安装相关", + "usage": "使用相关", + "key": "Key相关", + "security": "安全相关", + "other": "其他" + }, + "q": { + "howToInstall": "如何安装89猫?", + "systemRequirements": "89猫的系统要求是什么?", + "howToUse": "如何开始使用89猫?", + "stopRestart": "如何停止或重启89猫?", + "whereToGetKey": "从哪里获取API Key?", + "keyNotWorking": "Key显示无效怎么办?", + "isMyDataSafe": "我的数据安全吗?", + "howToScan": "如何进行安全检查?", + "contactUs": "如何联系客服?" + }, + "a": { + "howToInstall": "从官方网站下载对应平台的安装包,双击运行即可自动完成安装。安装完成后桌面和开始菜单都会出现89猫图标。", + "systemRequirements": "支持 Windows 10+、macOS 11+、Linux (Ubuntu 20.04+)。最低需要4GB内存,推荐8GB。需要1GB可用磁盘空间。", + "howToUse": "在首页的\"工作钥匙\"卡片中输入你的API Key并点击验证,验证通过后即可在聊天页面与AI对话。", + "stopRestart": "进入\"管理中心\"页面,点击\"停止使用89猫\"按钮即可停止服务,再次点击\"打开使用89猫\"即可重新启动。", + "whereToGetKey": "请访问 89.is89.com 注册账号并获取API Key。", + "keyNotWorking": "请检查Key是否输入正确(注意大小写和空格),确认Key未过期,确认网络连接正常。如仍有问题,请联系客服。", + "isMyDataSafe": "89猫使用系统原生密钥链安全存储你的API Key。管理中心运行在云端,你的个人数据保留在本地,隐私受到充分保护。", + "howToScan": "进入\"安全检查\"页面,先点击\"升级病毒库\",升级完成后点击\"开始扫描\"即可对系统进行全面安全扫描。", + "contactUs": "请发送邮件至 public@valuecell.ai 或访问 89.is89.com 获取更多帮助。" + } } } diff --git a/src/i18n/locales/zh/settings.json b/src/i18n/locales/zh/settings.json index 1ffc84b1..2681b840 100644 --- a/src/i18n/locales/zh/settings.json +++ b/src/i18n/locales/zh/settings.json @@ -1,6 +1,6 @@ { "title": "设置", - "subtitle": "配置您的 ClawX 体验", + "subtitle": "配置您的 89猫 体验", "appearance": { "title": "通用", "description": "自定义外观和风格", @@ -10,7 +10,7 @@ "system": "跟随系统", "language": "语言", "launchAtStartup": "开机自动启动", - "launchAtStartupDesc": "登录系统后自动启动 ClawX" + "launchAtStartupDesc": "登录系统后自动启动 89猫" }, "aiProviders": { "title": "AI 模型提供商", @@ -37,7 +37,7 @@ "notRequired": "非必填", "empty": { "title": "未配置提供商", - "desc": "添加 AI 提供商以开始使用 ClawX", + "desc": "添加 AI 提供商以开始使用 89猫", "cta": "添加您的第一个提供商" }, "dialog": { @@ -60,7 +60,7 @@ "protocol": "协议", "advancedConfig": "高级配置", "userAgent": "User-Agent", - "userAgentPlaceholder": "ClawX/1.0", + "userAgentPlaceholder": "89猫/1.0", "fallbackModels": "回退模型", "fallbackProviders": "跨 Provider 回退", "fallbackModelIds": "同 Provider 回退模型 ID", @@ -135,7 +135,7 @@ "appLogs": "应用日志", "openFolder": "打开文件夹", "autoStart": "自动启动网关", - "autoStartDesc": "ClawX 启动时自动启动网关", + "autoStartDesc": "89猫 启动时自动启动网关", "proxyTitle": "代理", "proxyDesc": "让 Electron 和 Gateway 的网络请求都走本地代理客户端。", "proxyServer": "代理服务器", @@ -156,7 +156,7 @@ }, "updates": { "title": "更新", - "description": "保持 ClawX 最新", + "description": "保持 89猫 最新", "autoCheck": "自动检查更新", "autoCheckDesc": "启动时检查更新", "autoDownload": "更新提示", @@ -185,13 +185,13 @@ "whatsNew": "更新内容:", "errorDetails": "错误详情:", "toast": { - "availableTitle": "ClawX 有新版本可用", + "availableTitle": "89猫 有新版本可用", "availableDescription": "v{{version}} 已可下载。准备好后可开始下载。", - "downloadedTitle": "ClawX 更新已就绪", + "downloadedTitle": "89猫 更新已就绪", "downloadedDescription": "v{{version}} 已下载完成。重启即可安装。", "unknownVersion": "新版本" }, - "help": "ClawX 会自动检查更新,并在下载或安装前提示您确认。" + "help": "89猫 会自动检查更新,并在下载或安装前提示您确认。" }, "advanced": { "title": "高级", @@ -218,7 +218,7 @@ "devMode": "开发者模式", "devModeDesc": "显示开发者工具和快捷方式", "telemetry": "匿名使用数据", - "telemetryDesc": "允许提供匿名的基础使用数据,用于改进 ClawX" + "telemetryDesc": "允许提供匿名的基础使用数据,用于改进 89猫" }, "developer": { "title": "开发者", @@ -280,7 +280,7 @@ }, "about": { "title": "关于", - "appName": "ClawX", + "appName": "89猫", "tagline": "图形化 AI 助手", "basedOn": "基于 OpenClaw", "version": "版本 {{version}}", diff --git a/src/i18n/locales/zh/setup.json b/src/i18n/locales/zh/setup.json index 8d00945b..d80c8a99 100644 --- a/src/i18n/locales/zh/setup.json +++ b/src/i18n/locales/zh/setup.json @@ -1,7 +1,7 @@ { "steps": { "welcome": { - "title": "欢迎使用 ClawX", + "title": "欢迎使用 89猫", "description": "您的 AI 助手已准备好进行配置" }, "runtime": { @@ -22,12 +22,12 @@ }, "complete": { "title": "准备就绪!", - "description": "ClawX 已准备好使用" + "description": "89猫 已准备好使用" } }, "welcome": { - "title": "欢迎使用 ClawX", - "description": "ClawX 是 OpenClaw 的图形界面,让您可以在喜爱的消息平台上轻松使用 AI 助手。", + "title": "欢迎使用 89猫", + "description": "89猫 是 OpenClaw 的图形界面,让您可以在喜爱的消息平台上轻松使用 AI 助手。", "features": { "noCommand": "无需命令行", "modernUI": "现代美观的界面", @@ -113,7 +113,7 @@ }, "complete": { "title": "设置完成!", - "subtitle": "ClawX 已配置并准备就绪。您现在可以开始与您的 AI 助手聊天了。", + "subtitle": "89猫 已配置并准备就绪。您现在可以开始与您的 AI 助手聊天了。", "provider": "AI 提供商", "components": "组件", "gateway": "网关", diff --git a/src/i18n/locales/zh/skills.json b/src/i18n/locales/zh/skills.json index c8efcd95..ec0bbd07 100644 --- a/src/i18n/locales/zh/skills.json +++ b/src/i18n/locales/zh/skills.json @@ -14,7 +14,13 @@ "builtIn": "内置 ({{count}})", "marketplace": "市场 ({{count}})", "enabledList": "已开启 ({{count}})", - "disabledList": "已禁用 ({{count}})" + "disabledList": "已禁用 ({{count}})", + "category": { + "all": "全部", + "cat89": "89插件", + "openclaw": "OpenClaw 技能", + "other": "其他插件" + } }, "search": "搜索技能...", "searchMarketplace": "搜索市场...", diff --git a/src/lib/providers.ts b/src/lib/providers.ts index c2b06f4f..bc8a2ac9 100644 --- a/src/lib/providers.ts +++ b/src/lib/providers.ts @@ -21,6 +21,7 @@ export const PROVIDER_TYPES = [ 'modelstudio', 'ollama', 'custom', + 'cat89', ] as const; export type ProviderType = (typeof PROVIDER_TYPES)[number]; @@ -196,6 +197,14 @@ export const PROVIDER_TYPE_INFO: ProviderTypeInfo[] = [ docsUrl: 'https://icnnp7d0dymg.feishu.cn/wiki/BmiLwGBcEiloZDkdYnGc8RWnn6d#Ee1ldfvKJoVGvfxc32mcILwenth', docsUrlZh: 'https://icnnp7d0dymg.feishu.cn/wiki/BmiLwGBcEiloZDkdYnGc8RWnn6d#IWQCdfe5fobGU3xf3UGcgbLynGh', }, + { + id: 'cat89', + name: '89猫', + icon: '🐱', + placeholder: '输入你的89猫 Key', + model: '89猫 AI', + requiresApiKey: true, + }, ]; /** Get the SVG logo URL for a provider type, falls back to undefined */ diff --git a/src/pages/Dashboard/index.tsx b/src/pages/Dashboard/index.tsx new file mode 100644 index 00000000..d8427dcc --- /dev/null +++ b/src/pages/Dashboard/index.tsx @@ -0,0 +1,270 @@ +/** + * Dashboard page — main landing page with 7 feature entry cards + */ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { + Building2, + Coins, + Puzzle, + ShieldCheck, + KeyRound, + HelpCircle, + Globe, + Eye, + EyeOff, + Check, + X, + Loader2, +} from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { useSettingsStore } from '@/stores/settings'; +import { SUPPORTED_LANGUAGES } from '@/i18n'; +import { hostApiFetch } from '@/lib/host-api'; +import { cn } from '@/lib/utils'; + +function ApiKeyCard() { + const { t } = useTranslation('dashboard'); + const [showKey, setShowKey] = useState(false); + const [key, setKey] = useState(''); + const [validating, setValidating] = useState(false); + const [result, setResult] = useState<'idle' | 'valid' | 'invalid'>('idle'); + const [errorMsg, setErrorMsg] = useState(''); + + const handleValidate = async () => { + const trimmed = key.trim(); + if (!trimmed) return; + setValidating(true); + setResult('idle'); + setErrorMsg(''); + try { + const res = await hostApiFetch<{ valid: boolean; message?: string }>( + '/api/cat89/validate-key', + { + method: 'POST', + body: JSON.stringify({ apiKey: trimmed }), + }, + ); + if (res.valid) { + setResult('valid'); + } else { + setResult('invalid'); + setErrorMsg(res.message || t('apiKey.invalidKey')); + } + } catch { + setResult('invalid'); + setErrorMsg(t('apiKey.validateFailed')); + } finally { + setValidating(false); + } + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + void handleValidate(); + } + }; + + return ( +
+
+
+ { + setKey(e.target.value); + setResult('idle'); + setErrorMsg(''); + }} + onKeyDown={handleKeyDown} + className={cn( + 'pr-10 font-mono', + result === 'valid' && 'border-green-500 focus-visible:ring-green-500', + result === 'invalid' && 'border-red-500 focus-visible:ring-red-500', + )} + /> + +
+ +
+ {result === 'valid' && ( +
+ + {t('apiKey.valid')} +
+ )} + {result === 'invalid' && ( +
+ + {errorMsg} +
+ )} +
+ ); +} + +interface DashboardCardProps { + icon: React.ReactNode; + title: string; + description: string; + onClick: () => void; + testId?: string; +} + +function DashboardCard({ icon, title, description, onClick, testId }: DashboardCardProps) { + return ( + + ); +} + +export function Dashboard() { + const navigate = useNavigate(); + const { t } = useTranslation('dashboard'); + const language = useSettingsStore((s) => s.language); + const setLanguage = useSettingsStore((s) => s.setLanguage); + + // Filter to only zh and en for 89猫 + const visibleLanguages = SUPPORTED_LANGUAGES.filter( + (lang) => lang.code === 'zh' || lang.code === 'en', + ); + + const cards: DashboardCardProps[] = [ + { + icon: , + title: t('cards.management.title'), + description: t('cards.management.desc'), + onClick: () => navigate('/management'), + testId: 'dashboard-card-management', + }, + { + icon: , + title: t('cards.tokenRecharge.title'), + description: t('cards.tokenRecharge.desc'), + onClick: () => window.electron.openExternal('https://89.is89.com'), + testId: 'dashboard-card-token', + }, + { + icon: , + title: t('cards.plugins.title'), + description: t('cards.plugins.desc'), + onClick: () => navigate('/skills'), + testId: 'dashboard-card-plugins', + }, + { + icon: , + title: t('cards.security.title'), + description: t('cards.security.desc'), + onClick: () => navigate('/security'), + testId: 'dashboard-card-security', + }, + { + icon: , + title: t('cards.faq.title'), + description: t('cards.faq.desc'), + onClick: () => navigate('/faq'), + testId: 'dashboard-card-faq', + }, + ]; + + return ( +
+ {/* Header */} +
+

+ {t('title')} +

+

{t('subtitle')}

+
+ + {/* Feature Cards Grid */} +
+ {cards.map((card) => ( + + ))} + + {/* API Key Card — inline with input */} +
+
+
+ +
+
+

+ {t('cards.apiKey.title')} +

+

+ {t('cards.apiKey.desc')} +

+
+
+ +
+ + {/* Language Selector Card */} +
+
+
+ +
+
+

+ {t('cards.language.title')} +

+

+ {t('cards.language.desc')} +

+
+
+
+ {visibleLanguages.map((lang) => ( + + ))} +
+
+
+
+ ); +} diff --git a/src/pages/Faq/index.tsx b/src/pages/Faq/index.tsx new file mode 100644 index 00000000..14e138a9 --- /dev/null +++ b/src/pages/Faq/index.tsx @@ -0,0 +1,187 @@ +/** + * FAQ page — accordion-style Q&A grouped by category + */ +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ChevronDown, HelpCircle } from 'lucide-react'; +import { cn } from '@/lib/utils'; + +interface FaqItem { + q: string; + a: string; +} + +interface FaqSection { + title: string; + items: FaqItem[]; +} + +function FaqAccordion({ item, defaultOpen }: { item: FaqItem; defaultOpen: boolean }) { + const [open, setOpen] = useState(defaultOpen); + + return ( +
+ + {open && ( +
+

+ {item.a} +

+
+ )} +
+ ); +} + +function FaqSectionBlock({ section, defaultOpen }: { section: FaqSection; defaultOpen: boolean }) { + const [open, setOpen] = useState(defaultOpen); + + return ( +
+ + {open && ( +
+ {section.items.map((item, idx) => ( + + ))} +
+ )} +
+ ); +} + +export function Faq() { + const { t } = useTranslation('dashboard'); + + const sections: FaqSection[] = [ + { + title: t('faq.sections.install', '安装相关'), + items: [ + { + q: t('faq.q.howToInstall', '如何安装89猫?'), + a: t( + 'faq.a.howToInstall', + '从官方网站下载对应平台的安装包,双击运行即可自动完成安装。安装完成后桌面和开始菜单都会出现89猫图标。', + ), + }, + { + q: t('faq.q.systemRequirements', '89猫的系统要求是什么?'), + a: t( + 'faq.a.systemRequirements', + '支持 Windows 10+、macOS 11+、Linux (Ubuntu 20.04+)。最低需要4GB内存,推荐8GB。需要1GB可用磁盘空间。', + ), + }, + ], + }, + { + title: t('faq.sections.usage', '使用相关'), + items: [ + { + q: t('faq.q.howToUse', '如何开始使用89猫?'), + a: t( + 'faq.a.howToUse', + '在首页的"工作钥匙"卡片中输入你的API Key并点击验证,验证通过后即可在聊天页面与AI对话。', + ), + }, + { + q: t('faq.q.stopRestart', '如何停止或重启89猫?'), + a: t( + 'faq.a.stopRestart', + '进入"管理中心"页面,点击"停止使用89猫"按钮即可停止服务,再次点击"打开使用89猫"即可重新启动。', + ), + }, + ], + }, + { + title: t('faq.sections.key', 'Key相关'), + items: [ + { + q: t('faq.q.whereToGetKey', '从哪里获取API Key?'), + a: t('faq.a.whereToGetKey', '请访问 89.is89.com 注册账号并获取API Key。'), + }, + { + q: t('faq.q.keyNotWorking', 'Key显示无效怎么办?'), + a: t( + 'faq.a.keyNotWorking', + '请检查Key是否输入正确(注意大小写和空格),确认Key未过期,确认网络连接正常。如仍有问题,请联系客服。', + ), + }, + ], + }, + { + title: t('faq.sections.security', '安全相关'), + items: [ + { + q: t('faq.q.isMyDataSafe', '我的数据安全吗?'), + a: t( + 'faq.a.isMyDataSafe', + '89猫使用系统原生密钥链安全存储你的API Key。管理中心运行在云端,你的个人数据保留在本地,隐私受到充分保护。', + ), + }, + { + q: t('faq.q.howToScan', '如何进行安全检查?'), + a: t( + 'faq.a.howToScan', + '进入"安全检查"页面,先点击"升级病毒库",升级完成后点击"开始扫描"即可对系统进行全面安全扫描。', + ), + }, + ], + }, + { + title: t('faq.sections.other', '其他'), + items: [ + { + q: t('faq.q.contactUs', '如何联系客服?'), + a: t( + 'faq.a.contactUs', + '请发送邮件至 public@valuecell.ai 或访问 89.is89.com 获取更多帮助。', + ), + }, + ], + }, + ]; + + return ( +
+
+
+ +

+ {t('cards.faq.title')} +

+
+

{t('cards.faq.desc')}

+
+ +
+ {sections.map((section, idx) => ( + + ))} +
+
+ ); +} diff --git a/src/pages/Management/index.tsx b/src/pages/Management/index.tsx new file mode 100644 index 00000000..949ff558 --- /dev/null +++ b/src/pages/Management/index.tsx @@ -0,0 +1,92 @@ +/** + * Management Center page — Gateway control + admin console link + */ +import { useTranslation } from 'react-i18next'; +import { ExternalLink, Power, PowerOff, Loader2 } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Badge } from '@/components/ui/badge'; +import { useGatewayStore } from '@/stores/gateway'; +import { cn } from '@/lib/utils'; + +export function Management() { + const { t } = useTranslation('dashboard'); + const gatewayStatus = useGatewayStore((s) => s.status); + const startGateway = useGatewayStore((s) => s.start); + const stopGateway = useGatewayStore((s) => s.stop); + + const isRunning = gatewayStatus.state === 'running'; + const isTransitioning = gatewayStatus.state === 'starting'; + + const handleToggle = async () => { + if (isRunning) { + await stopGateway(); + } else { + await startGateway(); + } + }; + + return ( +
+
+

+ {t('cards.management.title')} +

+

{t('cards.management.desc')}

+
+ + {/* Gateway Toggle Card */} +
+
+ + {isRunning ? t('gatewayRunning', '89猫运行中') : t('gatewayStopped', '89猫已停止')} + +
+ +
+ + {/* Admin Console Link */} +
+

+ {t('adminConsole', '89超级人工智能脑管理中心')} +

+

+ {t('adminConsoleDesc', '管理中心运行在云端,保护您的个人隐私')} +

+ +
+
+ ); +} diff --git a/src/pages/Security/index.tsx b/src/pages/Security/index.tsx new file mode 100644 index 00000000..07bca3fd --- /dev/null +++ b/src/pages/Security/index.tsx @@ -0,0 +1,260 @@ +/** + * Security Check page — static UI with simulated scan flow + */ +import { useState, useCallback, useRef, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ShieldCheck, Download, Play, Check, Loader2, Clock, FileSearch } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Progress } from '@/components/ui/progress'; +import { cn } from '@/lib/utils'; + +type ScanStep = 'idle' | 'updating' | 'ready' | 'scanning' | 'done'; + +const SCAN_PATHS = [ + 'C:\\Windows\\System32\\', + 'C:\\Program Files\\', + 'C:\\Users\\Documents\\', + 'D:\\Downloads\\', + 'C:\\Temp\\', +]; + +const getRandomThreats = () => Math.floor(Math.random() * 5); + +export function Security() { + const { t } = useTranslation('dashboard'); + + const [step, setStep] = useState('idle'); + const [updateProgress, setUpdateProgress] = useState(0); + const [scanProgress, setScanProgress] = useState(0); + const [currentPath, setCurrentPath] = useState(''); + const [filesScanned, setFilesScanned] = useState(0); + const [threatsFound, setThreatsFound] = useState(0); + const [scanTime, setScanTime] = useState(0); + const [lastScanTime, setLastScanTime] = useState(t('security.neverScanned')); + const [virusDbVersion, setVirusDbVersion] = useState('2026.06.01-v1'); + + const updateTimerRef = useRef>(); + const scanTimerRef = useRef>(); + + useEffect(() => { + return () => { + clearInterval(updateTimerRef.current); + clearInterval(scanTimerRef.current); + }; + }, []); + + const handleUpdateDb = useCallback(() => { + setStep('updating'); + setUpdateProgress(0); + + updateTimerRef.current = setInterval(() => { + setUpdateProgress((prev) => { + if (prev >= 100) { + clearInterval(updateTimerRef.current); + setStep('ready'); + setVirusDbVersion(`2026.06.04-v${Math.floor(Math.random() * 10) + 1}`); + return 100; + } + return prev + Math.random() * 15 + 5; + }); + }, 300); + }, []); + + const handleStartScan = useCallback(() => { + setStep('scanning'); + setScanProgress(0); + setFilesScanned(0); + setThreatsFound(0); + setScanTime(0); + setCurrentPath(SCAN_PATHS[0]); + + const startTime = Date.now(); + let pathIndex = 0; + + scanTimerRef.current = setInterval(() => { + setScanProgress((prev) => { + const next = prev + Math.random() * 4 + 1; + if (next >= 100) { + clearInterval(scanTimerRef.current); + setStep('done'); + setFilesScanned(Math.floor(Math.random() * 5000) + 10000); + setThreatsFound(getRandomThreats()); + setScanTime(Math.floor((Date.now() - startTime) / 1000)); + setLastScanTime(new Date().toLocaleString()); + setCurrentPath(''); + return 100; + } + + // Rotate scan paths + const newPathIndex = Math.min( + Math.floor((next / 100) * SCAN_PATHS.length), + SCAN_PATHS.length - 1, + ); + if (newPathIndex !== pathIndex) { + pathIndex = newPathIndex; + setCurrentPath(SCAN_PATHS[pathIndex]); + } + + setFilesScanned((prev2) => prev2 + Math.floor(Math.random() * 50) + 10); + return next; + }); + }, 200); + }, []); + + const getStepLabel = () => { + switch (step) { + case 'idle': + return t('security.idle'); + case 'updating': + return t('security.updatingDb'); + case 'ready': + return t('security.readyToScan'); + case 'scanning': + return t('security.scanning'); + case 'done': + return t('security.scanComplete'); + } + }; + + return ( +
+
+

+ {t('cards.security.title')} +

+

{t('cards.security.desc')}

+
+ + {/* Virus DB Status */} +
+
+
+

{t('security.virusDbVersion')}

+

{virusDbVersion}

+
+
+ + + {t('security.lastScan')}: {lastScanTime} + +
+
+ + + + {step === 'updating' && ( +
+ +

+ {Math.floor(updateProgress)}% +

+
+ )} +
+ + {/* Scan Section */} +
+
+
+ +
+
+

{getStepLabel()}

+

+ {step === 'idle' && t('security.updateDbFirst', '请先升级病毒库')} + {step === 'ready' && t('security.clickToScan', '病毒库已就绪,可以开始扫描')} + {step === 'scanning' && currentPath} + {step === 'done' && t('security.scanResult', '扫描已完成')} +

+
+
+ + + + {/* Scan Progress */} + {(step === 'scanning' || step === 'done') && ( +
+ div]:bg-green-500')} + /> +
+ + + {t('security.filesScanned')}: {filesScanned.toLocaleString()} + + + {Math.floor(scanProgress)}% + +
+
+ )} + + {/* Result */} + {step === 'done' && ( +
0 + ? 'border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950' + : 'border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-950', + )} + > +
+ 0 + ? 'text-red-600 dark:text-red-400' + : 'text-green-600 dark:text-green-400', + )} + /> + 0 + ? 'text-red-700 dark:text-red-300' + : 'text-green-700 dark:text-green-300', + )} + > + {threatsFound > 0 + ? t('security.threatsFound', { count: threatsFound }) + : t('security.noThreats')} + +
+

+ {t('security.scanSummary', { + files: filesScanned.toLocaleString(), + time: scanTime, + })} +

+
+ )} +
+
+ ); +} diff --git a/src/pages/Setup/index.tsx b/src/pages/Setup/index.tsx index d5fc21b4..9eff934c 100644 --- a/src/pages/Setup/index.tsx +++ b/src/pages/Setup/index.tsx @@ -268,7 +268,7 @@ function WelcomeContent() { return (
- ClawX + 89猫

{t('welcome.title')}

diff --git a/src/pages/Skills/index.tsx b/src/pages/Skills/index.tsx index dd85ad75..6898e697 100644 --- a/src/pages/Skills/index.tsx +++ b/src/pages/Skills/index.tsx @@ -343,6 +343,7 @@ export function Skills() { }; }, []); + const [categoryFilter, setCategoryFilter] = useState<'all' | 'cat89' | 'openclaw' | 'other'>('all'); const safeSkills = Array.isArray(skills) ? skills : []; const enabledSkillsCount = safeSkills.filter((skill) => skill.enabled).length; const disabledSkillsCount = safeSkills.filter((skill) => !skill.enabled).length; @@ -356,7 +357,11 @@ export function Skills() { || (skill.author || '').toLowerCase().includes(q); const matchesStatus = statusFilter === 'all' || (statusFilter === 'enabled' ? skill.enabled : !skill.enabled); - return matchesSearch && matchesStatus; + const matchesCategory = categoryFilter === 'all' + || (categoryFilter === 'cat89' && ((skill as any).isCat89Exclusive || skill.source === 'cat89-plugin')) + || (categoryFilter === 'openclaw' && (skill.source || '').startsWith('openclaw-')) + || (categoryFilter === 'other' && !(skill.source || '').startsWith('openclaw-') && !((skill as any).isCat89Exclusive) && skill.source !== 'cat89-plugin'); + return matchesSearch && matchesStatus && matchesCategory; }).sort((a, b) => { if (a.enabled && !b.enabled) return -1; if (!a.enabled && b.enabled) return 1; @@ -535,6 +540,27 @@ export function Skills() {

)} + {/* Category Tabs */} +
+ {(['all', 'cat89', 'openclaw', 'other'] as const).map((cat) => ( + + ))} +
+ {/* Sub Navigation and Actions */}
diff --git a/vite.config.ts b/vite.config.ts index a8d5e093..e560ca2f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -51,9 +51,12 @@ export default defineConfig({ { // Main process entry file entry: 'electron/main/index.ts', - args: ['--remote-debugging-port=9222'], onstart(options) { - options.startup(); + const cdpPort = process.env.CLAWX_CDP_PORT; + const args = cdpPort && cdpPort !== '0' + ? ['.', `--remote-debugging-port=${cdpPort}`] + : []; + options.startup(args); }, vite: { build: {